From ddf058b4cfa564d922a167a06ca005356eb1ca91 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 3 Sep 2019 09:37:08 -0600 Subject: [PATCH 001/377] Added some comments --- modules/hydrodyn/src/Morison.txt | 430 +++++++++++++++---------------- 1 file changed, 215 insertions(+), 215 deletions(-) diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 28caed10a..27fb926eb 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -15,204 +15,204 @@ include Registry_NWTC_Library.txt # # -param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "" - -typedef Morison/Morison Morison_JointType INTEGER JointID - - - "" - -typedef ^ ^ ReKi JointPos {3} - - "" - -typedef ^ ^ INTEGER JointAxID - - - "" - -typedef ^ ^ INTEGER JointAxIDIndx - - - "" - -typedef ^ ^ INTEGER JointOvrlp - - - "" - -typedef ^ ^ INTEGER NConnections - - - "" - -typedef ^ ^ INTEGER ConnectionList {10} - - "" - -typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "" - -typedef ^ ^ ReKi PropD - - - "" - -typedef ^ ^ ReKi PropThck - - - "" - -typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "" - -typedef ^ ^ INTEGER FillMList {:} - - "" - -typedef ^ ^ ReKi FillFSLoc - - - "" - -typedef ^ ^ CHARACTER(80) FillDensChr - - - "" - -typedef ^ ^ ReKi FillDens - - - "" - -typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "" - -typedef ^ ^ ReKi DpthCd - - - "" - -typedef ^ ^ ReKi DpthCdMG - - - "" - -typedef ^ ^ ReKi DpthCa - - - "" - -typedef ^ ^ ReKi DpthCaMG - - - "" - -typedef ^ ^ ReKi DpthCp - - - "" - -typedef ^ ^ ReKi DpthCpMG - - - "" - -typedef ^ ^ ReKi DpthAxCa - - - "" - -typedef ^ ^ ReKi DpthAxCaMG - - - "" - -typedef ^ ^ ReKi DpthAxCp - - - "" - -typedef ^ ^ ReKi DpthAxCpMG - - - "" - -typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "" - -typedef ^ ^ ReKi AxCd - - - "" - -typedef ^ ^ ReKi AxCa - - - "" - -typedef ^ ^ ReKi AxCp - - - "" - -typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "" - -typedef ^ ^ INTEGER MJointID1 - - - "" - -typedef ^ ^ INTEGER MJointID2 - - - "" - -typedef ^ ^ INTEGER MJointID1Indx - - - "" - -typedef ^ ^ INTEGER MJointID2Indx - - - "" - -typedef ^ ^ INTEGER MPropSetID1 - - - "" - -typedef ^ ^ INTEGER MPropSetID2 - - - "" - -typedef ^ ^ INTEGER MPropSetID1Indx - - - "" - -typedef ^ ^ INTEGER MPropSetID2Indx - - - "" - -typedef ^ ^ ReKi MDivSize - - - "" - -typedef ^ ^ INTEGER MCoefMod - - - "" - -typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "" - -typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "" - -typedef ^ ^ LOGICAL PropPot - - - "" - -#typedef ^ ^ INTEGER MGSplitState - - - "" - -#typedef ^ ^ INTEGER WtrSplitState - - - "" - -typedef ^ ^ INTEGER NumSplits - - - "" - -typedef ^ ^ ReKi Splits {5} - - "" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "" - -typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "" - -typedef ^ ^ INTEGER JointIndx - - - "" - -typedef ^ ^ ReKi JointPos {3} - - "" - +param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "Total number of possible Morison module output channels" - +typedef Morison/Morison Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - +typedef ^ ^ ReKi JointPos {3} - - "Undisplaced location of the joint in the platform coordinate system" m +typedef ^ ^ INTEGER JointAxID - - - "Axial ID (found in the user-supplied Axial Coefficients Table) for this joint: used to determine axial coefs" - +typedef ^ ^ INTEGER JointAxIDIndx - - - "The index into the Axial Coefs arrays corresponding to the above Axial ID" - +typedef ^ ^ INTEGER JointOvrlp - - - "Joint overlap code [Unused" - +typedef ^ ^ INTEGER NConnections - - - "Number of members connecting to this joint" - +typedef ^ ^ INTEGER ConnectionList {10} - - "List of Members connected to this joint. The member index is what is stored, not the Member ID" - +typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - +typedef ^ ^ ReKi PropD - - - "Diameter" m +typedef ^ ^ ReKi PropThck - - - "Wall thickness" m +typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - +typedef ^ ^ INTEGER FillMList {:} - - "List of Member IDs for the members in this fill group" - +typedef ^ ^ ReKi FillFSLoc - - - "The free-surface location (in Z) for this fill group" m +typedef ^ ^ CHARACTER(80) FillDensChr - - - "String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens]" kg/m^3 +typedef ^ ^ ReKi FillDens - - - "Numerical fill density" kg/m^3 +typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m +typedef ^ ^ ReKi DpthCd - - - "Depth-based drag coef" - +typedef ^ ^ ReKi DpthCdMG - - - "Depth-based drag coef for marine growth" - +typedef ^ ^ ReKi DpthCa - - - "Depth-based Ca" - +typedef ^ ^ ReKi DpthCaMG - - - "Depth-based Ca for marine growth" - +typedef ^ ^ ReKi DpthCp - - - "Depth-based Cp" - +typedef ^ ^ ReKi DpthCpMG - - - "Depth-based Cp for marine growth" - +typedef ^ ^ ReKi DpthAxCa - - - "Depth-based Axial Ca" - +typedef ^ ^ ReKi DpthAxCaMG - - - "Depth-based Axial Ca for marine growth" - +typedef ^ ^ ReKi DpthAxCp - - - "Depth-based Axial Cp" - +typedef ^ ^ ReKi DpthAxCpMG - - - "Depth-based Axial Cp for marine growth" - +typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - +typedef ^ ^ ReKi AxCd - - - "Axial Cd" - +typedef ^ ^ ReKi AxCa - - - "Axial Ca" - +typedef ^ ^ ReKi AxCp - - - "Axial Cp" - +typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "User-supplied integer ID for this member" - +typedef ^ ^ INTEGER MJointID1 - - - "Joint ID for start of member" - +typedef ^ ^ INTEGER MJointID2 - - - "Joint ID for end of member" - +typedef ^ ^ INTEGER MJointID1Indx - - - "Index into the joint table for the start of this member" - +typedef ^ ^ INTEGER MJointID2Indx - - - "Index into the joint table for the end of this member" - +typedef ^ ^ INTEGER MPropSetID1 - - - "Property set ID for the start of this member" - +typedef ^ ^ INTEGER MPropSetID2 - - - "Property set ID for the end of this member" - +typedef ^ ^ INTEGER MPropSetID1Indx - - - "Index into the Property table for the start of this member" - +typedef ^ ^ INTEGER MPropSetID2Indx - - - "Index into the Property table for the end of this member" - +typedef ^ ^ ReKi MDivSize - - - "User-specified desired member discretization size for the final element" m +typedef ^ ^ INTEGER MCoefMod - - - "Which coef. model is being used for this member [1=simple, 2=depth-based, 3=member-based]" - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "Index into the appropriate coefs table for this member's properties" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "Index into the filled group table if this is a filled member" - +typedef ^ ^ LOGICAL PropPot - - - "Flag T/F for whether the member is modeled with potential flow theory" - +#typedef ^ ^ INTEGER MGSplitState - - - "No longer used" - +#typedef ^ ^ INTEGER WtrSplitState - - - "No longer used" - +typedef ^ ^ INTEGER NumSplits - - - "How many splits are needs beyond the user-specified geometry" - +typedef ^ ^ ReKi Splits {5} - - "Number of times a user member is subdivided by the software" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from local to global coordinates" - +typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - +typedef ^ ^ INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - +typedef ^ ^ ReKi JointPos {3} - - "Position of the node in global coordinates" m typedef ^ ^ INTEGER JointOvrlp - - - "" - typedef ^ ^ INTEGER JointAxIDIndx - - - "" - -typedef ^ ^ INTEGER NConnections - - - "" - -typedef ^ ^ INTEGER ConnectionList {10} - - "" - -typedef ^ ^ INTEGER NConnectPreSplit - - - "" - -typedef ^ ^ ReKi Cd - - - "" - -typedef ^ ^ ReKi CdMG - - - "" - -typedef ^ ^ ReKi Ca - - - "" - -typedef ^ ^ ReKi CaMG - - - "" - -typedef ^ ^ ReKi Cp - - - "" - -typedef ^ ^ ReKi CpMG - - - "" - -typedef ^ ^ ReKi JAxCd - - - "" - -typedef ^ ^ ReKi JAxCa - - - "" - -typedef ^ ^ ReKi JAxCp - - - "" - -typedef ^ ^ ReKi AxCa - - - "" - -typedef ^ ^ ReKi AxCp - - - "" - -typedef ^ ^ ReKi AxCaMG - - - "" - -typedef ^ ^ ReKi AxCpMG - - - "" - -typedef ^ ^ ReKi R - - - "" - -typedef ^ ^ ReKi t - - - "" - -typedef ^ ^ ReKi tMG - - - "" - -typedef ^ ^ ReKi dRdz - - - "" - -typedef ^ ^ ReKi MGdensity - - - "" - -typedef ^ ^ ReKi FillFSLoc - - - "" - -typedef ^ ^ LOGICAL FillFlag - - - "" - -typedef ^ ^ ReKi FillDensity - - - "" - -typedef ^ ^ INTEGER InpMbrIndx - - - "" - -typedef ^ ^ ReKi InpMbrDist - - - "" - -typedef ^ ^ LOGICAL PropPot - - - "" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "" - -typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "" - -typedef ^ ^ INTEGER Node2Indx - - - "" - -typedef ^ ^ ReKi R1 - - - "" - -typedef ^ ^ ReKi t1 - - - "" - -typedef ^ ^ ReKi R2 - - - "" - -typedef ^ ^ ReKi t2 - - - "" - -typedef ^ ^ ReKi Cd1 - - - "" - -typedef ^ ^ ReKi CdMG1 - - - "" - -typedef ^ ^ ReKi Ca1 - - - "" - -typedef ^ ^ ReKi CaMG1 - - - "" - -typedef ^ ^ ReKi Cp1 - - - "" - -typedef ^ ^ ReKi CpMG1 - - - "" - -typedef ^ ^ ReKi AxCa1 - - - "" - -typedef ^ ^ ReKi AxCaMG1 - - - "" - -typedef ^ ^ ReKi AxCp1 - - - "" - -typedef ^ ^ ReKi AxCpMG1 - - - "" - -typedef ^ ^ ReKi Cd2 - - - "" - -typedef ^ ^ ReKi CdMG2 - - - "" - -typedef ^ ^ ReKi Ca2 - - - "" - -typedef ^ ^ ReKi CaMG2 - - - "" - -typedef ^ ^ ReKi Cp2 - - - "" - -typedef ^ ^ ReKi CpMG2 - - - "" - -typedef ^ ^ ReKi AxCa2 - - - "" - -typedef ^ ^ ReKi AxCaMG2 - - - "" - -typedef ^ ^ ReKi AxCp2 - - - "" - -typedef ^ ^ ReKi AxCpMG2 - - - "" - -typedef ^ ^ ReKi InpMbrDist1 - - - "" - -typedef ^ ^ ReKi InpMbrDist2 - - - "" - -typedef ^ ^ ReKi InpMbrLen - - - "" - -typedef ^ ^ INTEGER InpMbrIndx - - - "" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "" - -#typedef ^ ^ INTEGER MGSplitState - - - "" - -#typedef ^ ^ INTEGER WtrSplitState - - - "" - -typedef ^ ^ INTEGER NumSplits - - - "" - -typedef ^ ^ ReKi Splits {5} - - "" - -typedef ^ ^ ReKi MGvolume - - - "" - -typedef ^ ^ ReKi MDivSize - - - "" - -typedef ^ ^ INTEGER MCoefMod - - - "" - -typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "" - -typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "" - -typedef ^ ^ ReKi FillFSLoc - - - "" - -typedef ^ ^ ReKi FillDens - - - "" - -typedef ^ ^ ReKi F_Bouy {6} - - "" - -typedef ^ ^ ReKi F_DP {6} - - "" - -typedef ^ ^ LOGICAL PropPot - - - "" - -typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "" - -typedef ^ ^ ReKi MemberCd1 - - - "" - -typedef ^ ^ ReKi MemberCd2 - - - "" - -typedef ^ ^ ReKi MemberCdMG1 - - - "" - -typedef ^ ^ ReKi MemberCdMG2 - - - "" - -typedef ^ ^ ReKi MemberCa1 - - - "" - -typedef ^ ^ ReKi MemberCa2 - - - "" - -typedef ^ ^ ReKi MemberCaMG1 - - - "" - -typedef ^ ^ ReKi MemberCaMG2 - - - "" - -typedef ^ ^ ReKi MemberCp1 - - - "" - -typedef ^ ^ ReKi MemberCp2 - - - "" - -typedef ^ ^ ReKi MemberCpMG1 - - - "" - -typedef ^ ^ ReKi MemberCpMG2 - - - "" - -typedef ^ ^ ReKi MemberAxCa1 - - - "" - -typedef ^ ^ ReKi MemberAxCa2 - - - "" - -typedef ^ ^ ReKi MemberAxCaMG1 - - - "" - -typedef ^ ^ ReKi MemberAxCaMG2 - - - "" - -typedef ^ ^ ReKi MemberAxCp1 - - - "" - -typedef ^ ^ ReKi MemberAxCp2 - - - "" - -typedef ^ ^ ReKi MemberAxCpMG1 - - - "" - -typedef ^ ^ ReKi MemberAxCpMG2 - - - "" - -typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "" - -typedef ^ ^ ReKi MGThck - - - "" - -typedef ^ ^ ReKi MGDens - - - "" - -typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "" - -typedef ^ ^ INTEGER NOutLoc - - - "" - -typedef ^ ^ ReKi NodeLocs {:} - - "" - -typedef ^ ^ INTEGER MemberIDIndx - - - "" - -typedef ^ ^ INTEGER Marker1 {:} - - "" - -typedef ^ ^ INTEGER Marker2 {:} - - "" - -typedef ^ ^ ReKi s {:} - - "" - -typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "" - -typedef ^ ^ INTEGER JointIDIndx - - - "" - -typedef ^ ^ INTEGER NumMarkers - - - "" - -typedef ^ ^ INTEGER Markers {10} - - "" - +typedef ^ ^ INTEGER NConnections - - - "Number of elements connecting to this node" - +typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the elements connected to this node" - +typedef ^ ^ INTEGER NConnectPreSplit - - - "In code, but unused: should be removed" - +typedef ^ ^ ReKi Cd - - - "Nodal Cd" - +typedef ^ ^ ReKi CdMG - - - "Nodal Cd with marine growth" - +typedef ^ ^ ReKi Ca - - - "Nodal Ca" - +typedef ^ ^ ReKi CaMG - - - "Nodal Ca with marine growth" - +typedef ^ ^ ReKi Cp - - - "Nodal Cp" - +typedef ^ ^ ReKi CpMG - - - "Nodal Cp with marine growth" - +typedef ^ ^ ReKi JAxCd - - - "Nodal lumped (joint) axial Cd" - +typedef ^ ^ ReKi JAxCa - - - "Nodal lumped (joint) axial Cp" - +typedef ^ ^ ReKi JAxCp - - - "Nodal lumped (joint) axial Ca" - +typedef ^ ^ ReKi AxCa - - - "Nodal axial Ca" - +typedef ^ ^ ReKi AxCp - - - "Nodal axial Cp" - +typedef ^ ^ ReKi AxCaMG - - - "Nodal axial Ca with marine growth" - +typedef ^ ^ ReKi AxCpMG - - - "Nodal axial Cp with marine growth" - +typedef ^ ^ ReKi R - - - "Nodal radius (of member at node location)" m +typedef ^ ^ ReKi t - - - "Nodal thickness (of member at node location)" m +typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth (of member at node location)" m +typedef ^ ^ ReKi dRdz - - - "Nodal rate of change in member radius with respect to member axial direction" +typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 +typedef ^ ^ ReKi FillFSLoc - - - "Nodal fill free surface location (of connected chamber to this node)" m +typedef ^ ^ LOGICAL FillFlag - - - "Is this node filled? T/F" - +typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 +typedef ^ ^ INTEGER InpMbrIndx - - - "Index of member this node is connected to (from the user-specified member list in the input file)" - +typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - +typedef ^ ^ LOGICAL PropPot - - - "Is this node modeled with potential flow theory? T/F" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from node local to global coordinates" - +typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "Index of member's node 1 in the master node list" - +typedef ^ ^ INTEGER Node2Indx - - - "Index of member's node 2 in the master node list" - +typedef ^ ^ ReKi R1 - - - "Radius of node 1" m +typedef ^ ^ ReKi t1 - - - "Member thickness at node 1" m +typedef ^ ^ ReKi R2 - - - "Radius of node 2" m +typedef ^ ^ ReKi t2 - - - "Member thickness at node 2" m +typedef ^ ^ ReKi Cd1 - - - "Member Cd at node 1" - +typedef ^ ^ ReKi CdMG1 - - - "Member Cd at node 1 with marine growth" - +typedef ^ ^ ReKi Ca1 - - - "Member Ca at node 1" - +typedef ^ ^ ReKi CaMG1 - - - "Member Ca at node 1 with marine growth" - +typedef ^ ^ ReKi Cp1 - - - "Member Cp at node 1" - +typedef ^ ^ ReKi CpMG1 - - - "Member Cp at node 1 with marine growth" - +typedef ^ ^ ReKi AxCa1 - - - "Member axial Ca at node 1" - +typedef ^ ^ ReKi AxCaMG1 - - - "Member axial Ca at node 1 with marine growth" - +typedef ^ ^ ReKi AxCp1 - - - "Member axial Cp at node 1" - +typedef ^ ^ ReKi AxCpMG1 - - - "Member axial Cp at node 1 with marine growth" - +typedef ^ ^ ReKi Cd2 - - - "Member Cd at node 2" - +typedef ^ ^ ReKi CdMG2 - - - "Member Cd at node 2 with marine growth" - +typedef ^ ^ ReKi Ca2 - - - "Member Ca at node 2" - +typedef ^ ^ ReKi CaMG2 - - - "Member Ca at node 2 with marine growth" - +typedef ^ ^ ReKi Cp2 - - - "Member Cp at node 2" - +typedef ^ ^ ReKi CpMG2 - - - "Member Cp at node 2 with marine growth" - +typedef ^ ^ ReKi AxCa2 - - - "Member axial Ca at node 2" - +typedef ^ ^ ReKi AxCaMG2 - - - "Member axial Ca at node 2 with marine growth" - +typedef ^ ^ ReKi AxCp2 - - - "Member axial Cp at node 2" - +typedef ^ ^ ReKi AxCpMG2 - - - "Member axial Cp at node 2 with marine growth" - +typedef ^ ^ ReKi InpMbrDist1 - - - "Normalized distance of node 1 from the user-specified corresponding member in the input file" - +typedef ^ ^ ReKi InpMbrDist2 - - - "Normalized distance of node 2 from the user-specified corresponding member in the input file" - +typedef ^ ^ ReKi InpMbrLen - - - "Length of the user-specified member this is a part of" - +typedef ^ ^ INTEGER InpMbrIndx - - - "Index of the user-specified member this is a part of" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from member local to global coordinates" - +#typedef ^ ^ INTEGER MGSplitState - - - "Unused" - +#typedef ^ ^ INTEGER WtrSplitState - - - "Unused" - +typedef ^ ^ INTEGER NumSplits - - - "How many splits need to be created in the member/element" - +typedef ^ ^ ReKi Splits {5} - - "Locations of the splits in the Z coordinate" m +typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 +typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m +typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - +typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m +typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 +typedef ^ ^ ReKi F_Bouy {6} - - "Unused" - +typedef ^ ^ ReKi F_DP {6} - - "Unused" - +typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - +typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - +typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m +typedef ^ ^ ReKi MGThck - - - "Marine growth thickness" m +typedef ^ ^ ReKi MGDens - - - "Marine growth density" kg/m^3 +typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "Member ID for requested output" - +typedef ^ ^ INTEGER NOutLoc - - - "The number of requested output locations" - +typedef ^ ^ ReKi NodeLocs {:} - - "Normalized locations along user-specified member for the outputs" - +typedef ^ ^ INTEGER MemberIDIndx - - - "Index for member in the master list" - +typedef ^ ^ INTEGER Marker1 {:} - - "Index of node in DistribMesh for the start of the member" - +typedef ^ ^ INTEGER Marker2 {:} - - "Index of node in DistribMesh for the end of the member" - +typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - +typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - +typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - +typedef ^ ^ INTEGER NumMarkers - - - "Number of lumped mesh nodes which are co-located at the requested Joint" - +typedef ^ ^ INTEGER Markers {10} - - "Index of all nodes in lumped mesh which are co-located at the requested Joint" - # ..... Initialization data ....................................................................................................... # Define inputs that the initialization routine may need here: # e.g., the name of the input file, the file root name,etc. # -typedef Morison/Morison InitInputType ReKi Gravity - - - "" - -typedef ^ ^ ReKi WtrDens - - - "" - -typedef ^ ^ ReKi WtrDpth - - - "" - -typedef ^ ^ ReKi MSL2SWL - - - "" - -typedef ^ ^ INTEGER NJoints - - - "" - -typedef ^ ^ INTEGER NNodes - - - "" - -typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "" - -typedef ^ ^ Morison_JointType InpJoints {:} - - "" - -typedef ^ ^ Morison_NodeType Nodes {:} - - "" - -typedef ^ ^ INTEGER NElements - - - "" - -typedef ^ ^ Morison_MemberType Elements {:} - - "" - -typedef ^ ^ INTEGER NAxCoefs - - - "" - -typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "" - -typedef ^ ^ INTEGER NPropSets - - - "" - -typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "" - -typedef ^ ^ ReKi SimplCd - - - "" - -typedef ^ ^ ReKi SimplCdMG - - - "" - -typedef ^ ^ ReKi SimplCa - - - "" - -typedef ^ ^ ReKi SimplCaMG - - - "" - -typedef ^ ^ ReKi SimplCp - - - "" - -typedef ^ ^ ReKi SimplCpMG - - - "" - -typedef ^ ^ ReKi SimplAxCa - - - "" - -typedef ^ ^ ReKi SimplAxCaMG - - - "" - -typedef ^ ^ ReKi SimplAxCp - - - "" - -typedef ^ ^ ReKi SimplAxCpMG - - - "" - -typedef ^ ^ INTEGER NCoefDpth - - - "" - +typedef Morison/Morison InitInputType ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 +typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 +typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m +typedef ^ ^ ReKi MSL2SWL - - - "Mean Sea Level to Still Water Level offset" m +typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - +typedef ^ ^ INTEGER NNodes - - - "Total number of nodes in the final software model" - +typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "Unused: For super member calculations" - +typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - +typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - +typedef ^ ^ INTEGER NElements - - - "Number of elements in the discretized model" - +typedef ^ ^ Morison_MemberType Elements {:} - - "Array of elements which were derived from the user-specified members" - +typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - +typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - +typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - +typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "List of Member property sets" - +typedef ^ ^ ReKi SimplCd - - - "Simple model drag coef" - +typedef ^ ^ ReKi SimplCdMG - - - "Simple model drag coef for marine growth" - +typedef ^ ^ ReKi SimplCa - - - "Simple model Ca" - +typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for marine growth" - +typedef ^ ^ ReKi SimplCp - - - "Simple model Cp" - +typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for marine growth" - +typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca" - +typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for marine growth" - +typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp" - +typedef ^ ^ ReKi SimplAxCpMG - - - "Simple model Axial Cp for marine growth" - +typedef ^ ^ INTEGER NCoefDpth - - - "" - typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - typedef ^ ^ INTEGER NCoefMembers - - - "" - typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - -typedef ^ ^ INTEGER NMembers - - - "" - -typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "" - +typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - +typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "Array of user-specified members" - typedef ^ ^ INTEGER NFillGroups - - - "" - typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - typedef ^ ^ INTEGER NMGDepths - - - "" - @@ -241,11 +241,11 @@ typedef ^ ^ INTEGER # # Define outputs from the initialization routine here: # -typedef ^ InitOutputType MeshType DistribMesh - - - "" - -typedef ^ ^ MeshType LumpedMesh - - - "" - +typedef ^ InitOutputType MeshType DistribMesh - - - "Unused?" - +typedef ^ ^ MeshType LumpedMesh - - - "Unused?" - typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) -typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "" - -typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "" - +typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - +typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "User-requested Output channel units" - # # # ..... States .................................................................................................................... @@ -256,7 +256,7 @@ typedef ^ ContinuousStateType SiKi # # Define discrete (nondifferentiable) states here: # -typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - # # # Define constraint states here: @@ -270,25 +270,25 @@ typedef ^ OtherStateType IntKi # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi D_F_D {:}{:} - - "Distributed viscous drag loads" - -typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads" - -typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads" - -#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Distributed dynamic pressure loads" - -typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads" - -typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads" - -typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads" - -typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid" - -typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node" - -typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node" - -typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node" - +typedef ^ MiscVarType ReKi D_F_D {:}{:} - - "Distributed viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - +typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_B was computed)" - +#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Unused: Distributed dynamic pressure loads" - +typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi L_F_B {:}{:} - - "" - -typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads" - -typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads" - -typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads" - -typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads" - -typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node" - -typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node" - -typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node" - +typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - # ..... Parameters ................................................................................................................ @@ -296,10 +296,10 @@ typedef ^ ^ INTEGER # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: # typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) -typedef ^ ^ ReKi WtrDens - - - "" - +typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 typedef ^ ^ INTEGER NNodes - - - "" - typedef ^ ^ Morison_NodeType Nodes {:} - - "" - -typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "" - +typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - typedef ^ ^ ReKi D_dragConst {:} - - "" - typedef ^ ^ ReKi L_An {:}{:} - - "" - @@ -317,7 +317,7 @@ typedef ^ ^ INTEGER typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - -typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "Times for which the wave kinematics are pre-computed" s typedef ^ ^ INTEGER elementWaterState {:}{:} - - "State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2]" - typedef ^ ^ INTEGER elementFillState {:} - - "State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2]" - typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - From b1241713a09e398dccf44908af1af9b97428884b Mon Sep 17 00:00:00 2001 From: Hall Date: Tue, 17 Sep 2019 12:09:55 -0600 Subject: [PATCH 002/377] Matt's initial comments and notes in Morison.f90, mostly for his own sake. I made these months ago and just copied the source over to the file in this new repo. Small possibility there base versions had differences so I introduced small changes to uncommented code through this commit, but shouldn't be an issue considering many changes are in the works for Morison. --- modules/hydrodyn/src/Morison.f90 | 148 +++++++++++++++---------------- 1 file changed, 71 insertions(+), 77 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 18d0c9a53..ad326f363 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -351,22 +351,23 @@ FUNCTION InterpWrappedStpLogical( XValIn, XAry, YAry, Ind, AryLen ) END FUNCTION InterpWrappedStpLogical ! ( XVal, XAry, YAry, Ind, AryLen ) SUBROUTINE DistrBuoyancy( densWater, R, tMG, dRdz, Z, C, g, F_B ) + ! This calculates the distributed buoyancy forces and moments on a given node REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( IN ) :: dRdz - REAL(ReKi), INTENT ( IN ) :: Z + REAL(ReKi), INTENT ( IN ) :: R ! Radius of node [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: dRdz ! Rate of change in radius with length at node [-] + REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of node [m] (not currently used) REAL(ReKi), INTENT ( IN ) :: C(3,3) REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_B(6) + REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Distributed force and moment vector [N/m and N-m/m] REAL(DbKi) :: Reff,ReffSq,ReffCub,f1,f2,f3 REAL(DbKi) :: CC(3,3) CC = REAL(C,DbKi) - Reff = REAL(R + tMG,DbKi) + Reff = REAL(R + tMG,DbKi) ! Effective radius after adding marine growth @@ -582,27 +583,28 @@ SUBROUTINE DistrFloodedBuoyancy( densFluid, Z_f, R, t, dRdz, Z, C, g, F_B ) END SUBROUTINE DistrFloodedBuoyancy SUBROUTINE DistrAddedMass( densWater, Ca, AxCa, C, R, tMG, dRdZ, AM_M) + ! This calculates the distributed hydrodynamic added mass matrix for a given node. REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: Ca - REAL(ReKi), INTENT ( IN ) :: AxCa - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( IN ) :: dRdZ - REAL(ReKi), INTENT ( OUT ) :: AM_M(3,3) + REAL(ReKi), INTENT ( IN ) :: Ca ! Transverse added mass coefficient + REAL(ReKi), INTENT ( IN ) :: AxCa ! Axial added mass coefficient (applied to tapered portions) + REAL(ReKi), INTENT ( IN ) :: C(3,3) + REAL(ReKi), INTENT ( IN ) :: R ! Radius at node [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: dRdZ ! Rate of change in radius with length at node [-] + REAL(ReKi), INTENT ( OUT ) :: AM_M(3,3) ! Distributed added mass matrix to be calculated [kg/m] REAL(ReKi) :: f,f2 - f = Ca*densWater*Pi*(R+tMG)*(R+tMG) - f2 = AxCa*2.0*densWater*Pi*abs(dRdZ)*(R+tMG)*(R+tMG) + f = Ca*densWater*Pi*(R+tMG)*(R+tMG) ! Transverse added mass scaler, applied to I - k*k^T + f2 = AxCa*2.0*densWater*Pi*abs(dRdZ)*(R+tMG)*(R+tMG) ! Axial added mass scaler, applied to k k^T !AM_M = 0.0 - AM_M(1,1) = f*( C(2,3)*C(2,3) + C(3,3)*C(3,3) ) -f2*C(1,3)*C(1,3) + AM_M(1,1) = f*( C(2,3)*C(2,3) + C(3,3)*C(3,3) ) -f2*C(1,3)*C(1,3) !<----@mhall: why is the f2 term being subtracted rather than added? AM_M(1,2) = f*( -C(1,3)*C(2,3) ) -f2*C(1,3)*C(2,3) AM_M(1,3) = f*( -C(1,3)*C(3,3) ) -f2*C(1,3)*C(3,3) AM_M(2,1) = f*( -C(1,3)*C(2,3) ) -f2*C(2,3)*C(1,3) - AM_M(2,2) = f*( C(1,3)*C(1,3) + C(3,3)*C(3,3) ) -f2*C(2,3)*C(2,3) + AM_M(2,2) = f*( C(1,3)*C(1,3) + C(3,3)*C(3,3) ) -f2*C(2,3)*C(2,3) !<----@mhall: would it be cleaner to just use the k unit vector? (also, diagonal terms can be shortened (1-k*kT)) AM_M(2,3) = f*( -C(2,3)*C(3,3) ) -f2*C(2,3)*C(3,3) AM_M(3,1) = f*( -C(1,3)*C(3,3) ) -f2*C(3,3)*C(1,3) @@ -701,15 +703,17 @@ END SUBROUTINE LumpDynPressure SUBROUTINE LumpBuoyancy( sgn, densWater, R, tMG, Z, C, g, F_B ) + ! This calculates lumped buoyancy forces/moments on a member end. - REAL(ReKi), INTENT ( IN ) :: sgn + REAL(ReKi), INTENT ( IN ) :: sgn ! @mhall: this indicates if this is the start or end node so that direction is correct? REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( IN ) :: Z + REAL(ReKi), INTENT ( IN ) :: R ! Radius of end [m] + REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] + REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of end [m] + REAL(ReKi), INTENT ( IN ) :: C(3,3) REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_B(6) + REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Lumped force and moment vector [N and N-m] REAL(DbKi) :: f, f1, f2, f3, Reff, Rsq,R_4 @@ -845,11 +849,12 @@ SUBROUTINE GetMaxSimQuantities( numMGDepths, MGTop, MGBottom, MSL2SWL, Zseabed, ! For this member, determine possible split conditions due to crossing through: ! MSL, seabed, marine growth boundaries, filled free surface location. ! - + + ! Start with no splits. nSplits = 0 possibleSplits = -9999999.0 ! Initialize possibleSplit values to a number that never appears in the geometry. - ! Is the member filled? + ! If the member is filled, add a possible split location at the global Z location of the filled free surface. IF ( members(I)%MmbrFilledIDIndx /= -1 ) THEN nSplits = 1 ! The free surface is specified relative to the MSL. @@ -857,16 +862,13 @@ SUBROUTINE GetMaxSimQuantities( numMGDepths, MGTop, MGBottom, MSL2SWL, Zseabed, END IF - ! Check if MSL is equal to Zfs, if it is, then don't add MSL2SWL as an additional possible split, otherwise do add it. - - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MSL2SWL )) THEN + ! If the filled fluid hasn't already caused a split in the member at the still water line, then add a possible split there (at the water free surface, MSL2SWL). + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MSL2SWL )) THEN nSplits = nSplits + 1 possibleSplits(nSplits) = MSL2SWL - END IF - + END IF - ! Is there a marine growth region? - + ! If there are one more depth-defined marine growth regions, add a possible split at each boundary if one doesn't already exist. IF ( numMGDepths > 0 ) THEN ! Recursively check to see if this @@ -881,15 +883,15 @@ SUBROUTINE GetMaxSimQuantities( numMGDepths, MGTop, MGBottom, MSL2SWL, Zseabed, END IF - ! Check if seabed is equal to other possibleSplits - - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, Zseabed) ) THEN + ! Add a possible split a the seabed if there isn't already one there. + ! Check if seabed is equal to other possibleSplits + IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, Zseabed) ) THEN nSplits = nSplits + 1 possibleSplits(nSplits) = Zseabed - END IF + END IF - ! Now determine which possible splits this member actually crosses + ! Now determine which possible splits this member actually crosses and record them in the member's data structure. DO J=1,nSplits @@ -1580,12 +1582,13 @@ END SUBROUTINE WriteSummaryFile !==================================================================================================== SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, numElements, node1, node2, originalElement, newNode, newElement, ErrStat, ErrMsg ) + !@mhall: This splits an element at a given global x, y, or z location? - INTEGER, INTENT ( IN ) :: axis - REAL(ReKi), INTENT ( IN ) :: boundary + INTEGER, INTENT ( IN ) :: axis !@mhall: which axis to work with in calculating positions along element (global x,y, or z)? + REAL(ReKi), INTENT ( IN ) :: boundary !@mhall: [axis] coordinate of boundary? INTEGER, INTENT ( IN ) :: iCurrentElement INTEGER, INTENT ( INOUT ) :: numNodes - TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 + TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 !@mhall: element end nodes? INTEGER, INTENT ( INOUT ) :: numElements TYPE(Morison_MemberType), INTENT ( INOUT ) :: originalElement TYPE(Morison_NodeType), INTENT ( OUT ) :: newNode @@ -1607,11 +1610,15 @@ SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, n ! find normalized distance from 1nd node to the boundary CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) newNode = node1 ! copy all base node properties + + newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] + + !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates DO I=axis,axis+1 J = MOD(I,3) + 1 newNode%JointPos(J) = node1%JointPos(J)*(1-s) + node2%JointPos(J)*s END DO - newNode%JointPos(axis) = boundary + newNode%R_LToG = node1%R_LToG ! Create the new node information. ! Note that the caller will determine if this is an interior node (subdivide) or an endnode (split due to MG, MSL, seabed, filled free surface) @@ -1728,7 +1735,8 @@ END SUBROUTINE SplitElementOnZBoundary !END SUBROUTINE SplitElementsForMG SUBROUTINE SplitElements(numNodes, nodes, numElements, elements, ErrStat, ErrMsg) - + ! This splits all of the Morison elements according to already defined split locations, + ! adding resuling new nodes and elements to the respective master arrays. INTEGER, INTENT ( INOUT ) :: numNodes TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) @@ -1883,7 +1891,9 @@ END SUBROUTINE SplitElements !END SUBROUTINE SplitElementsForWtr !==================================================================================================== SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, ErrMsg ) - + ! This subdivides all of the (already-split) Morison elements according to each element's maximum desired + ! element length (MDivSize), adding resuling new nodes and elements to the respective master arrays. + INTEGER, INTENT ( INOUT ) :: numNodes TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) INTEGER, INTENT ( INOUT ) :: numElements @@ -1896,7 +1906,7 @@ SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, Er INTEGER :: numDiv REAL(ReKi) :: divSize(3) INTEGER :: I, J, K - REAL(ReKi) :: memLen + REAL(ReKi) :: memLen ! Length of member [m] INTEGER :: origNumElements INTEGER :: node1Indx, node2Indx, elementIndx, axis REAL(ReKi) :: start, Loc @@ -1924,12 +1934,14 @@ SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, Er elementIndx = I - CALL GetDistance(node1%JointPos, node2%JointPos, memLen) + CALL GetDistance(node1%JointPos, node2%JointPos, memLen) ! Calculate member length. ! If the requested division size is less then the member length, we will subdivide the member IF ( element%MDivSize < memLen ) THEN + + ! Ensure a safe choice of x/y/z axis to use for splitting. IF ( .NOT. ( EqualRealNos( node2%JointPos(3) , node1%JointPos(3) ) ) ) THEN axis = 3 ELSE IF ( .NOT. ( EqualRealNos( node2%JointPos(2) , node1%JointPos(2) ) ) ) THEN @@ -2141,6 +2153,8 @@ SUBROUTINE SetSplitNodeProperties( numNodes, nodes, numElements, elements, ErrSt nodes(element%Node1Indx)%MGdensity = 0.0 nodes(element%Node2Indx)%MGdensity = 0.0 END IF + + !@mhall: if this node is Node 1 of the element in question... ? IF ( element%Node1Indx == I ) THEN IF ( nodes(I)%tMG > 0 ) THEN @@ -2160,6 +2174,8 @@ SUBROUTINE SetSplitNodeProperties( numNodes, nodes, numElements, elements, ErrSt nodes(I)%R = element%R1 nodes(I)%t = element%t1 nodes(I)%InpMbrDist = element%InpMbrDist1 + + !@mhall: otherwise this must be Node 2 of the element in question? ELSE IF ( nodes(I)%tMG > 0 ) THEN @@ -3484,11 +3500,11 @@ SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWav END IF D_dragConst = 0.0 - ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads + ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads <---@mhall: what does "create all loads" mean? ! For the buoyancy loads, loop over the elements and then apply one half of the resulting value ! to each of the interior element nodes but the full value to an end node. This means that an internal member node will receive 1/2 of its ! load from element A and 1/2 from element B. If it is the end of a member it will simply receive - ! the element A load. + ! the element A load. count = 1 @@ -3534,7 +3550,7 @@ SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWav ! IF ( nodes(I)%JointPos(3) <= MSL2SWL .AND. nodes(I)%JointPos(3) >= z0 ) THEN - + CALL DistrAddedMass( densWater, nodes(I)%Ca, nodes(I)%AxCa, nodes(I)%R_LToG, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdZ, D_AM_M(:,:,count) ) ! IF ( secondNodeWaterState == 0 ) THEN ! Element is in the water @@ -3581,7 +3597,7 @@ SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWav END IF ! IF ( .NOT. nodes(I)%PropPot ) - ! This is always computed, but may be zereod out for any given timestep during the CalcOutput work + ! This is always computed, but may be zereod out for any given timestep during the CalcOutput work <---@mhall: what is this? CALL DistrDragConst( densWater, nodes(I)%Cd, nodes(I)%R, nodes(I)%tMG, D_dragConst(count) ) IF ( nodes(I)%FillFlag ) THEN @@ -3648,6 +3664,7 @@ SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWav Morison_Rad(count) = nodes(I)%R ! set this for FAST visualization + !@mhall: what is happening in these lines? distribToNodeIndx(count) = I nodeToDistribIndx(I) = count count = count + 1 @@ -3777,7 +3794,7 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! Local variables - INTEGER :: I , J! j1, j2, tempINT ! generic integer for counting + INTEGER :: I !, J, j1, j2, tempINT ! generic integer for counting ! TYPE(Morison_JointType) :: joint1, joint2 ! Real(ReKi) :: z1 ! Real(ReKi) :: z2 @@ -3902,22 +3919,7 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) prop2Indx = temp InitInp%Elements(I)%InpMbrDist1 = 1.0 InitInp%Elements(I)%InpMbrDist2 = 0.0 - ! --- Swap member coeffs if needed. - ! Fine in this loop since there is a unique CoefMember per Member (otherwise we could swap them several times). - J = InitInp%InpMembers(I)%MmbrCoefIDIndx ! Index in CoefMembers table - IF (J>0) THEN - ! NOTE: SWAP defined at the end of the current subroutine - CALL SWAP(InitInp%CoefMembers(J)%MemberCd1 , InitInp%CoefMembers(J)%MemberCd2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCa1 , InitInp%CoefMembers(J)%MemberCa2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCp1 , InitInp%CoefMembers(J)%MemberCp2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCa1 , InitInp%CoefMembers(J)%MemberAxCa2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCp1 , InitInp%CoefMembers(J)%MemberAxCp2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCdMG1 , InitInp%CoefMembers(J)%MemberCdMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCaMG1 , InitInp%CoefMembers(J)%MemberCaMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCpMG1 , InitInp%CoefMembers(J)%MemberCpMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCaMG1, InitInp%CoefMembers(J)%MemberAxCaMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCpMG1, InitInp%CoefMembers(J)%MemberAxCpMG2) - END IF + END IF propSet = InitInp%MPropSets(prop1Indx) @@ -3964,7 +3966,7 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) CALL SetElementFillProps( InitInp%NFillGroups, InitInp%FilledGroups, InitInp%NElements, InitInp%Elements ) - ! Split elements + ! Split the elements at certain depths according to still water line, internal filled free surface, marine growth transition depths, seabed dpeth, etc. as applicable. CALL SplitElements(InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) ! Split element due to MSL2SWL location and seabed location @@ -4042,14 +4044,7 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! p%NMorisonElements = 0 END IF - CONTAINS - SUBROUTINE SWAP(x1,x2) - Real(Reki),intent(inout) :: x1,x2 - Real(Reki) :: tmp - tmp = x1 - x1 = x2 - x2 = tmp - END SUBROUTINE SWAP + END SUBROUTINE Morison_ProcessMorisonGeometry !---------------------------------------------------------------------------------------------------------------------------------- @@ -4189,7 +4184,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In InitOut%Morison_Rad, ErrStat, ErrMsg ) - + !@mhall: forces should become variables rather than parameters <<<< IF ( ErrStat > ErrID_None ) RETURN @@ -4580,8 +4575,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, qdotdot2(1) = elementWaterState *u%DistribMesh%TranslationAcc(1,J) qdotdot2(2) = elementWaterState *u%DistribMesh%TranslationAcc(2,J) qdotdot2(3) = elementWaterState *u%DistribMesh%TranslationAcc(3,J) - ! calculated the added mass forces (moments are zero) - m%D_F_AM_M(1:3,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? + m%D_F_AM_M(:,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? DO I=1,6 IF (I < 4 ) THEN From b0e967baec46cd3b9bf549a60dc67a047e520c15 Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Tue, 17 Sep 2019 12:53:45 -0600 Subject: [PATCH 003/377] A couple corrections to undo code changes caused by my last commit (due to updates in Morison.f90 since I made my comments). --- modules/hydrodyn/src/Morison.f90 | 38 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index ad326f363..75553bbc0 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1611,14 +1611,14 @@ SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, n CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) newNode = node1 ! copy all base node properties - newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] - !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates DO I=axis,axis+1 J = MOD(I,3) + 1 newNode%JointPos(J) = node1%JointPos(J)*(1-s) + node2%JointPos(J)*s END DO + newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] + newNode%R_LToG = node1%R_LToG ! Create the new node information. ! Note that the caller will determine if this is an interior node (subdivide) or an endnode (split due to MG, MSL, seabed, filled free surface) @@ -3794,7 +3794,7 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! Local variables - INTEGER :: I !, J, j1, j2, tempINT ! generic integer for counting + INTEGER :: I, J !, j1, j2, tempINT ! generic integer for counting ! TYPE(Morison_JointType) :: joint1, joint2 ! Real(ReKi) :: z1 ! Real(ReKi) :: z2 @@ -3920,6 +3920,24 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) InitInp%Elements(I)%InpMbrDist1 = 1.0 InitInp%Elements(I)%InpMbrDist2 = 0.0 + ! --- Swap member coeffs if needed. + + ! Fine in this loop since there is a unique CoefMember per Member (otherwise we could swap them several times). + J = InitInp%InpMembers(I)%MmbrCoefIDIndx ! Index in CoefMembers table + IF (J>0) THEN + ! NOTE: SWAP defined at the end of the current subroutine + CALL SWAP(InitInp%CoefMembers(J)%MemberCd1 , InitInp%CoefMembers(J)%MemberCd2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCa1 , InitInp%CoefMembers(J)%MemberCa2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCp1 , InitInp%CoefMembers(J)%MemberCp2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCa1 , InitInp%CoefMembers(J)%MemberAxCa2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCp1 , InitInp%CoefMembers(J)%MemberAxCp2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCdMG1 , InitInp%CoefMembers(J)%MemberCdMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCaMG1 , InitInp%CoefMembers(J)%MemberCaMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberCpMG1 , InitInp%CoefMembers(J)%MemberCpMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCaMG1, InitInp%CoefMembers(J)%MemberAxCaMG2) + CALL SWAP(InitInp%CoefMembers(J)%MemberAxCpMG1, InitInp%CoefMembers(J)%MemberAxCpMG2) + END IF + END IF propSet = InitInp%MPropSets(prop1Indx) @@ -4044,7 +4062,15 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! p%NMorisonElements = 0 END IF - + CONTAINS + + SUBROUTINE SWAP(x1,x2) + Real(Reki),intent(inout) :: x1,x2 + Real(Reki) :: tmp + tmp = x1 + x1 = x2 + x2 = tmp + END SUBROUTINE SWAP END SUBROUTINE Morison_ProcessMorisonGeometry !---------------------------------------------------------------------------------------------------------------------------------- @@ -4575,7 +4601,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, qdotdot2(1) = elementWaterState *u%DistribMesh%TranslationAcc(1,J) qdotdot2(2) = elementWaterState *u%DistribMesh%TranslationAcc(2,J) qdotdot2(3) = elementWaterState *u%DistribMesh%TranslationAcc(3,J) - m%D_F_AM_M(:,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? + + ! calculated the added mass forces (moments are zero) + m%D_F_AM_M(1:3,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? DO I=1,6 IF (I < 4 ) THEN From 3a02d97424f2a45ec4230e6a7e69db10d13d872a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 25 Sep 2019 14:22:58 -0600 Subject: [PATCH 004/377] Initial Draft of WAMIT multi-body (with build errors) Result of a merge, need to fix some merge artifacts --- modules/hydrodyn/src/Conv_Radiation.f90 | 134 +-- modules/hydrodyn/src/Conv_Radiation.txt | 10 +- modules/hydrodyn/src/HydroDyn.f90 | 659 ++++++----- modules/hydrodyn/src/HydroDyn.txt | 72 +- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 99 +- modules/hydrodyn/src/HydroDyn_Input.f90 | 267 +++-- modules/hydrodyn/src/HydroDyn_Output.f90 | 1022 +++++++++++++++--- modules/hydrodyn/src/WAMIT.f90 | 491 +++++---- modules/hydrodyn/src/WAMIT.txt | 41 +- modules/hydrodyn/src/WAMIT2.f90 | 12 +- modules/hydrodyn/src/WAMIT_Output.f90 | 80 +- reg_tests/r-test | 2 +- vs-build/HydroDyn/HydroDynDriver.vfproj | 9 +- 13 files changed, 1934 insertions(+), 964 deletions(-) diff --git a/modules/hydrodyn/src/Conv_Radiation.f90 b/modules/hydrodyn/src/Conv_Radiation.f90 index 54040d15a..c510bacf2 100644 --- a/modules/hydrodyn/src/Conv_Radiation.f90 +++ b/modules/hydrodyn/src/Conv_Radiation.f90 @@ -55,23 +55,7 @@ MODULE Conv_Radiation CONTAINS -SUBROUTINE ShiftValuesLeft(XDHistory, NSteps) -! This routine shifts every entry in XDHistory such that XDHistory(K+1,I) is now stored in XDHistory(K,I) -! - REAL(ReKi), INTENT(INOUT) :: XDHistory (:,:) ! The time history of the 3 components of the translational velocity (in m/s) of the WAMIT reference and the 3 components of the rotational (angular) velocity (in rad/s) of the platform relative to the inertial frame - INTEGER(IntKi), INTENT(IN ) :: NSteps ! Number of elements in the array - - INTEGER(IntKi) :: I -! INTEGER(IntKi) :: J - INTEGER(IntKi) :: K - - DO K = 0,NSteps-2 - DO I = 1,6 ! Loop through all DOFs - XDHistory(K,I) = XDHistory(K+1,I) - END DO - END DO - -END SUBROUTINE ShiftValuesLeft + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. @@ -119,6 +103,9 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using + ! Error handling + CHARACTER(1024) :: ErrMsg2 ! Temporary error message for calls + INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls ! Initialize ErrStat @@ -139,7 +126,7 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, ! RdtnOmegaMax, Abort because RdtnDT must be reduced in order to have ! sufficient accuracy in the computation of the radiation impulse response ! functions: - + p%NBody = InitInp%NBody p%RdtnDT = InitInp%RdtnDT RdtnOmegaMax = Pi / InitInp%RdtnDT @@ -151,8 +138,8 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, RETURN END IF - - + call AllocAry( u%Velocity, 6*p%NBody, "u%Velocity" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Conv_Rdtn_Init' ) + call AllocAry( y%F_Rdtn , 6*p%NBody, "y%F_Rdtn" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Conv_Rdtn_Init' ) u%Velocity = 0.0 !this is an initial guess; @@ -190,14 +177,14 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, RETURN END IF - ALLOCATE ( p%RdtnKrnl (0:p%NStepRdtn-1,6,6) , STAT=ErrStat ) + ALLOCATE ( p%RdtnKrnl (0:p%NStepRdtn-1,6*p%NBody,6*p%NBody) , STAT=ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating memory for the RdtnKrnl array.' ErrStat = ErrID_Fatal RETURN END IF - ALLOCATE ( xd%XDHistory(0:p%NStepRdtn ,6 ) , STAT=ErrStat ) ! In the numerical convolution we must have NStepRdtn1 elements within the XDHistory array, which is one more than the NStepRdtn elements that are in the RdtnKrnl array + ALLOCATE ( xd%XDHistory(0:p%NStepRdtn ,6*p%NBody ) , STAT=ErrStat ) ! In the numerical convolution we must have NStepRdtn1 elements within the XDHistory array, which is one more than the NStepRdtn elements that are in the RdtnKrnl array IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating memory for the XDHistory array.' ErrStat = ErrID_Fatal @@ -206,7 +193,7 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, ! Initialize all elements of the xd%XDHistory array with the intial values of u%Velocity DO K = 0,p%NStepRdtn-1 - DO J = 1,6 ! Loop through all DOFs + DO J = 1,6*p%NBody ! Loop through all DOFs xd%XDHistory(K,J) = u%Velocity(J) END DO END DO @@ -243,13 +230,13 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, ! Compute the upper-triangular portion (diagonal and above) of the sine ! transform of the wave radiation kernel: - Indx = 0 - DO J = 1,6 ! Loop through all rows of RdtnKrnl - DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal - Indx = Indx + 1 + ! Indx = 0 + DO J = 1,6*p%NBody ! Loop through all rows of RdtnKrnl + DO K = 1,6*p%NBody ! Loop through all columns of RdtnKrnl above and including the diagonal + !Indx = Indx + 1 p%RdtnKrnl(I,J,K) = Krnl_Fact*Omega*( InterpStp( Omega, InitInp%HdroFreq(:), & - InitInp%HdroAddMs(: ,Indx), LastInd, InitInp%NInpFreq ) & - - InitInp%HdroAddMs(InitInp%NInpFreq,Indx) ) + InitInp%HdroAddMs(: ,J,K), LastInd, InitInp%NInpFreq ) & + - InitInp%HdroAddMs(InitInp%NInpFreq,J,K) ) END DO ! K - All columns of RdtnKrnl above and including the diagonal END DO ! J - All rows of RdtnKrnl @@ -269,16 +256,11 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, RETURN END IF - DO J = 1,6 ! Loop through all rows of RdtnKrnl - DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + DO J = 1,6*p%NBody ! Loop through all rows of RdtnKrnl + DO K = 1,6*p%NBody ! Loop through all columns of RdtnKrnl above and including the diagonal CALL ApplySINT( p%RdtnKrnl(:,J,K), FFT_Data, ErrStat ) IF ( ErrStat /= ErrID_None ) RETURN END DO ! K - All columns of RdtnKrnl above and including the diagonal - DO K = J+1,6 ! Loop through all rows of RdtnKrnl below the diagonal - DO I = 0,p%NStepRdtn-1 ! Loop through all frequency components (including zero) of the sine transform - p%RdtnKrnl(I,K,J) = p%RdtnKrnl(I,J,K) - END DO ! I - All frequency components (including zero) of the sine transform - END DO ! K - All rows of RdtnKrnl below the diagonal END DO ! J - All rows of RdtnKrnl CALL ExitSINT(FFT_Data, ErrStat) @@ -320,11 +302,11 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, ! Compute the upper-triangular portion (diagonal and above) of the cosine ! transform of the wave radiation kernel: - Indx = 0 - DO J = 1,6 ! Loop through all rows of RdtnKrnl - DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal - Indx = Indx + 1 - p%RdtnKrnl(I,J,K) = Krnl_Fact*InterpStp ( Omega, InitInp%HdroFreq(:), InitInp%HdroDmpng(:,Indx), LastInd, InitInp%NInpFreq ) + !Indx = 0 + DO J = 1,6*p%NBody ! Loop through all rows of RdtnKrnl + DO K = 1,6*p%NBody ! Loop through all columns of RdtnKrnl above and including the diagonal + !Indx = Indx + 1 + p%RdtnKrnl(I,J,K) = Krnl_Fact*InterpStp ( Omega, InitInp%HdroFreq(:), InitInp%HdroDmpng(:,J,K), LastInd, InitInp%NInpFreq ) END DO ! K - All columns of RdtnKrnl above and including the diagonal END DO ! J - All rows of RdtnKrnl @@ -343,8 +325,8 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, RETURN END IF - DO J = 1,6 ! Loop through all rows of RdtnKrnl - DO K = J,6 ! Loop through all columns of RdtnKrnl above and including the diagonal + DO J = 1,6*p%NBody ! Loop through all rows of RdtnKrnl + DO K = 1,6*p%NBody ! Loop through all columns of RdtnKrnl above and including the diagonal CALL ApplyCOST( p%RdtnKrnl(:,J,K), FFT_Data, ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = 'Error applying Cosine Transform' @@ -352,11 +334,6 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, RETURN END IF END DO ! K - All columns of RdtnKrnl above and including the diagonal - DO K = J+1,6 ! Loop through all rows of RdtnKrnl below the diagonal - DO I = 0,p%NStepRdtn-1 ! Loop through all radiation time steps - p%RdtnKrnl(I,K,J) = p%RdtnKrnl(I,J,K) - END DO ! I - All radiation time steps - END DO ! K - All rows of RdtnKrnl below the diagonal END DO ! J - All rows of RdtnKrnl CALL ExitCOST(FFT_Data, ErrStat) @@ -388,10 +365,8 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, !END IF - IF ( ALLOCATED( RdtnTime ) ) DEALLOCATE( RdtnTime ) + IF ( ALLOCATED( RdtnTime ) ) DEALLOCATE( RdtnTime ) - - ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which ! this module must be called here: @@ -550,7 +525,7 @@ SUBROUTINE Conv_Rdtn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! REAL(ReKi) :: F_Rdtn (6) - REAL(ReKi) :: F_RdtnDT (6) ! The portion of the total load contribution from wave radiation damping associated with the convolution integral proportional to ( RdtnDT - RdtnRmndr ) (N, N-m) + REAL(ReKi) :: F_RdtnDT (6*p%NBody) ! The portion of the total load contribution from wave radiation damping associated with the convolution integral proportional to ( RdtnDT - RdtnRmndr ) (N, N-m) INTEGER :: I ! Generic index INTEGER :: J ! Generic index @@ -568,12 +543,12 @@ SUBROUTINE Conv_Rdtn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat MaxInd = MIN(p%NStepRdtn-1,OtherState%IndRdtn) ! Note: xd%IndRdtn index is from the previous time-step since this state was for the previous time-step - DO I = 1,6 ! Loop through all wave radiation damping forces and moments + DO I = 1,6*p%NBody ! Loop through all wave radiation damping forces and moments F_RdtnDT (I) = 0.0 ! F_RdtnRmndr(I) = 0.0 - DO J = 1,6 ! Loop through all platform DOFs + DO J = 1,6*p%NBody ! Loop through all platform DOFs DO K = 0, MaxInd ! Loop through all NStepRdtn time steps in the radiation Kernel (less than NStepRdtn time steps are used when ZTime < RdtnTmax) F_RdtnDT(I) = F_RdtnDT(I) - p%RdtnKrnl(MaxInd-K,I,J)*xd%XDHistory(K,J) @@ -689,64 +664,21 @@ SUBROUTINE Conv_Rdtn_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, Er !BJJ: this needs a better check so that it is ALWAYS done (MATLAB/Simulink could possibly avoid this step by starting at Time>0, OR there may be some numerical issues where this is NOT EXACTLY zero) IF ( OtherState%IndRdtn < (p%NStepRdtn) ) THEN - DO J = 1,6 ! Loop through all platform DOFs + DO J = 1,6*p%NBody ! Loop through all platform DOFs xd%XDHistory(OtherState%IndRdtn,J) = u%Velocity(J) ! XDHistory was allocated as a zero-based array! END DO ! J - All platform DOFs ELSE - !CALL ShiftValuesLeft( xd%XDHistory, p%NStepRdtn ) ! This is NOT to be used GJH + ! Shift the stored history by one index DO K = 0,p%NStepRdtn-2 - DO J = 1,6 ! Loop through all DOFs + DO J = 1,6*p%NBody ! Loop through all DOFs xd%XDHistory(K,J) = xd%XDHistory(K+1,J) END DO END DO - DO J = 1,6 ! Loop through all platform DOFs + DO J = 1,6*p%NBody ! Loop through all platform DOFs xd%XDHistory(p%NStepRdtn-1,J) = u%Velocity(J) ! Set the last array element to the current velocity END DO ! J - All platform DOFs END IF - - ! IF ( Time == 0.0_DbKi ) THEN ! (1) .TRUE. if we are on the initialization pass where Time = 0.0 (and IndRdtn = 0) - ! - ! DO J = 1,6 ! Loop through all platform DOFs - ! xd%XDHistory(xd%IndRdtn,J) = u%Velocity(J) - ! END DO ! J - All platform DOFs - ! - ! xd%LastIndRdtn = xd%IndRdtn ! Save the value of IndRdtn for the next call to this routine (in this case IndRdtn = 0) - ! - ! ELSEIF ( xd%IndRdtn > xd%LastIndRdtn ) THEN ! (2) .TRUE. if we have increased in time by at least RdtnDT - ! - ! DO J = 1,6 ! Loop through all platform DOFs - ! - ! IncrmntUD = ( p%RdtnDT/( Time - ( xd%LastIndRdtn*p%RdtnDT ) ) ) * & - ! ( u%Velocity(J) - xd%XDHistory(MOD(xd%LastIndRdtn ,p%NStepRdtn1),J) ) - ! - ! DO K = xd%LastIndRdtn +1,xd%IndRdtn ! Loop through all radiation time steps where the time history of UD has yet to be stored - ! xd%XDHistory(MOD(K,p%NStepRdtn1),J) = xd%XDHistory(MOD(xd%LastIndRdtn ,p%NStepRdtn1),J) & - ! + ( K - xd%LastIndRdtn )*IncrmntUD - ! END DO ! K - All radiation time steps where the time history of UD has yet to be stored - ! - ! END DO ! J - All platform DOFs - ! - ! xd%LastIndRdtn2 = xd%LastIndRdtn ! Save the value of LastIndRdtn for the next call to this routine - ! xd%LastIndRdtn = xd%IndRdtn ! Save the value of IndRdtn for the next call to this routine - ! xd%LastTime = Time ! Save the value of Time associated with LastIndRdtn for the next call to this routine - ! - !!BJJ: this needs a better check in case there may be some numerical issues where this is NOT EXACTLY the same... - ! ELSEIF ( Time == xd%LastTime ) THEN ! (3). .TRUE. if the time has not changed since the last time we have increased in time by at least RdtnDt (i.e., on a call to the corrector) - ! - ! DO J = 1,6 ! Loop through all platform DOFs - ! - ! IncrmntUD = ( p%RdtnDT/( Time - ( xd%LastIndRdtn2*p%RdtnDT ) ) ) * & - ! ( u%Velocity(J) - xd%XDHistory(MOD(xd%LastIndRdtn2,p%NStepRdtn1),J) ) - ! - ! DO K = xd%LastIndRdtn2+1,xd%IndRdtn ! Loop through all radiation time steps where the time history of UD should be updated - ! xd%XDHistory(MOD(K,p%NStepRdtn1),J) = xd%XDHistory(MOD(xd%LastIndRdtn2,p%NStepRdtn1),J) & - ! + ( K - xd%LastIndRdtn2 )*IncrmntUD - ! END DO ! K - All radiation time steps where the time history of UD should be updated - ! - ! END DO ! J - All platform DOFs - ! - ! END IF END SUBROUTINE Conv_Rdtn_UpdateDiscState !---------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/hydrodyn/src/Conv_Radiation.txt b/modules/hydrodyn/src/Conv_Radiation.txt index 82a4f09dc..e421042b5 100644 --- a/modules/hydrodyn/src/Conv_Radiation.txt +++ b/modules/hydrodyn/src/Conv_Radiation.txt @@ -20,11 +20,12 @@ include Registry_NWTC_Library.txt # typedef Conv_Radiation/Conv_Rdtn InitInputType DbKi RdtnDT - - - "" - typedef ^ ^ CHARACTER(80) RdtnDTChr +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - typedef ^ ^ ReKi HighFreq - - - "" - typedef ^ ^ CHARACTER(1024) WAMITFile - - - "" - -typedef ^ ^ SiKi HdroAddMs {:}{:} - - "" - +typedef ^ ^ SiKi HdroAddMs {:}{:}{:} - - "" - typedef ^ ^ SiKi HdroFreq {:} - - "" - -typedef ^ ^ SiKi HdroDmpng {:}{:} - - "" - +typedef ^ ^ SiKi HdroDmpng {:}{:}{:} - - "" - typedef ^ ^ INTEGER NInpFreq - - - "" - typedef ^ ^ DbKi RdtnTMax - - - "" - typedef ^ ^ INTEGER UnSum - - - "" - @@ -67,6 +68,7 @@ typedef ^ MiscVarType INTEGER # typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" seconds typedef ^ ^ DbKi RdtnDT - - - "" - +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - typedef ^ ^ SiKi RdtnKrnl {:}{:}{:} - - "" - typedef ^ ^ INTEGER NStepRdtn - - - "" - typedef ^ ^ INTEGER NStepRdtn1 - - - "" - @@ -77,11 +79,11 @@ typedef ^ ^ INTEGER # #typedef^ InputType MeshType MeshedInput - - - "Meshed input data" - # Define inputs that are not on this mesh here: -typedef ^ InputType ReKi Velocity {6} - - "" - +typedef ^ InputType ReKi Velocity {:} - - "" - # # # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: #typedef^ OutputType MeshType MeshedOutput - - - "Meshed output data" - # Define outputs that are not on this mesh here: -typedef ^ OutputType ReKi F_Rdtn {6} - - "" - +typedef ^ OutputType ReKi F_Rdtn {:} - - "" - diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 748b99024..3be34ca97 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -255,7 +255,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! LOGICAL :: hasWAMITOuts ! Are there any WAMIT-related outputs ! LOGICAL :: hasMorisonOuts ! Are there any Morison-related outputs ! INTEGER :: numHydroOuts ! total number of WAMIT and Morison outputs - INTEGER :: I, J ! Generic counters + INTEGER :: I, J, iBody ! Generic counters REAL(SiKi) :: WaveNmbr ! Wavenumber of the current frequency component (1/meter) ! These are dummy variables to satisfy the framework, but are not used @@ -296,6 +296,9 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I Real(ReKi) :: dftreal Real(ReKi) :: dftimag + ! WAMIT Mesh + real(R8Ki) :: theta(3), orientation(3,3) + ! Wave Stretching Data REAL(SiKi), ALLOCATABLE :: tmpWaveKinzi(: ) INTEGER :: tmpNWaveElev @@ -352,7 +355,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I - IF ( InitInp%UseInputFile ) THEN + IF ( InitLocal%UseInputFile ) THEN ! Parse all HydroDyn-related input files and populate the *_InitInputType derived types @@ -844,66 +847,147 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Is there a WAMIT body? IF ( InitLocal%PotMod == 1 ) THEN + p%nWAMITObj = InitLocal%nWAMITObj ! All the data for the various WAMIT bodies are stored in a single WAMIT file + p%vecMultiplier = InitLocal%vecMultiplier ! Multiply all vectors and matrices row/column lengths by NBody + InitLocal%WAMIT%NBodyMod = InitLocal%NBodyMod + p%NBody = InitLocal%NBody + p%NBodyMod = InitLocal%NBodyMod - ! Copy Waves initialization output into the initialization input type for the WAMIT module - - InitLocal%WAMIT%RhoXg = Waves_InitOut%RhoXg - InitLocal%WAMIT%NStepWave = Waves_InitOut%NStepWave - InitLocal%WAMIT%NStepWave2 = Waves_InitOut%NStepWave2 - InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin - InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax - InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega - - - ! Init inputs for the SS_Excitation model (set this just in case it will be used) - InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir - CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) + call AllocAry( m%F_PtfmAdd, 6*InitLocal%NBody, "m%F_PtfmAdd", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( m%F_Waves , 6*InitLocal%NBody, "m%F_Waves" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! Temporarily move arrays to init input for WAMIT (save some space) - CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) - CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT%WaveElevC0) - CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT%WaveDirArr) + ! Determine how many WAMIT modules we need based on NBody and NBodyMod + if (p%NBodyMod == 1) then + InitLocal%WAMIT%NBody = InitLocal%NBody ! The WAMIT object will contain all NBody WAMIT bodies - !----------------------------------------- - ! Initialize the WAMIT Calculations - !----------------------------------------- - - CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, & - y%WAMIT, m%WAMIT, Interval, InitOut%WAMIT, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - + ! Allocate WAMIT InitInp arrays based on NBodyMod and copy the inputfile data into the WAMIT init data (entire arrays' worth for NBodyMod=1 + call AllocAry( InitLocal%WAMIT%PtfmVol0 , InitLocal%NBody, "PtfmVol0" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefxt , InitLocal%NBody, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefyt , InitLocal%NBody, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefzt , InitLocal%NBody, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefztRot, InitLocal%NBody, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmCOBxt , InitLocal%NBody, "PtfmCOBxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmCOByt , InitLocal%NBody, "PtfmCOByt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + allocate( p%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array p%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( x%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array x%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( xd%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array xd%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( OtherState%WAMIT(1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( y%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( m%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( InitOut%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT.', ErrStat, ErrMsg, RoutineName ) + + InitLocal%WAMIT%PtfmVol0 = InitLocal%PtfmVol0 + InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN(1) + InitLocal%WAMIT%PtfmRefxt = InitLocal%PtfmRefxt + InitLocal%WAMIT%PtfmRefyt = InitLocal%PtfmRefyt + InitLocal%WAMIT%PtfmRefzt = InitLocal%PtfmRefzt + InitLocal%WAMIT%PtfmRefztRot = InitLocal%PtfmRefztRot + InitLocal%WAMIT%PtfmCOBxt = InitLocal%PtfmCOBxt + InitLocal%WAMIT%PtfmCOByt = InitLocal%PtfmCOByt + else + InitLocal%WAMIT%NBody = 1 ! Each WAMIT object will only contain one of the NBody WAMIT bodies + + ! Allocate WAMIT InitInp arrays based on NBodyMod and copy the inputfile data into the 1st WAMIT body init data for NBodyMod > 1 + call AllocAry( InitLocal%WAMIT%PtfmVol0 , 1, "PtfmVol0" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefxt , 1, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefyt , 1, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefzt , 1, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefztRot, 1, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmCOBxt , 1, "PtfmCOBxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmCOByt , 1, "PtfmCOByt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + allocate( p%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array p%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( x%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array x%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( xd%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array xd%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( OtherState%WAMIT(InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( y%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( m%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( InitOut%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT.', ErrStat, ErrMsg, RoutineName ) + InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (1) + InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (1) + InitLocal%WAMIT%PtfmRefxt (1) = InitLocal%PtfmRefxt (1) + InitLocal%WAMIT%PtfmRefyt (1) = InitLocal%PtfmRefyt (1) + InitLocal%WAMIT%PtfmRefzt (1) = InitLocal%PtfmRefzt (1) + InitLocal%WAMIT%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(1) + InitLocal%WAMIT%PtfmCOBxt (1) = InitLocal%PtfmCOBxt (1) + InitLocal%WAMIT%PtfmCOByt (1) = InitLocal%PtfmCOByt (1) + + end if - ! Generate Summary file information for WAMIT module - ! Compute the load contribution from hydrostatics: - IF ( InitLocal%UnSum > 0 ) THEN + + ! Copy Waves initialization output into the initialization input type for the WAMIT module + + InitLocal%WAMIT%RhoXg = Waves_InitOut%RhoXg + InitLocal%WAMIT%NStepWave = Waves_InitOut%NStepWave + InitLocal%WAMIT%NStepWave2 = Waves_InitOut%NStepWave2 + InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin + InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax + InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega - WRITE( InitLocal%UnSum, '(A11)') 'WAMIT Model' - WRITE( InitLocal%UnSum, '(A11)') '-----------' - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', p%WAMIT%PtfmVol0 - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', p%WAMIT%PtfmCOBxt - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', p%WAMIT%PtfmCOByt - WRITE( InitLocal%UnSum, '(/)' ) - WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' - WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,p%WAMIT%RhoXg*p%WAMIT%PtfmVol0,p%WAMIT%RhoXg*p%WAMIT%PtfmVol0*p%WAMIT%PtfmCOByt, -p%WAMIT%RhoXg*p%WAMIT%PtfmVol0*p%WAMIT%PtfmCOBxt, 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point - - END IF + + ! Temporarily move arrays to init input for WAMIT (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT%WaveDirArr) + + CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), & + y%WAMIT(1), m%WAMIT(1), Interval, InitOut%WAMIT(1), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! For NBodyMod > 1 and NBody > 1, set the body info and init the WAMIT body + do i = 2, p%nWAMITObj + !----------------------------------------- + ! Initialize the WAMIT Calculations + !----------------------------------------- + InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (i) + InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (i) + InitLocal%WAMIT%PtfmRefxt (1) = InitLocal%PtfmRefxt (i) + InitLocal%WAMIT%PtfmRefyt (1) = InitLocal%PtfmRefyt (i) + InitLocal%WAMIT%PtfmRefzt (1) = InitLocal%PtfmRefzt (i) + InitLocal%WAMIT%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(i) + InitLocal%WAMIT%PtfmCOBxt (1) = InitLocal%PtfmCOBxt (i) + InitLocal%WAMIT%PtfmCOByt (1) = InitLocal%PtfmCOByt (i) + + CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT(i), x%WAMIT(i), xd%WAMIT(i), z%WAMIT, OtherState%WAMIT(i), & + y%WAMIT(i), m%WAMIT(i), Interval, InitOut%WAMIT(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + end do + + ! Generate Summary file information for WAMIT module + ! Compute the load contribution from hydrostatics: + IF ( InitLocal%UnSum > 0 ) THEN + do iBody = 1, InitLocal%NBody + WRITE( InitLocal%UnSum, '(A18,I5)') 'WAMIT Model - Body',iBody + WRITE( InitLocal%UnSum, '(A18)') '------------------' + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', InitLocal%PtfmVol0(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', InitLocal%PtfmCOBxt(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', InitLocal%PtfmCOByt(iBody) + WRITE( InitLocal%UnSum, '(/)' ) + WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody),InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOByt(iBody), -InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOBxt(iBody), 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point + end do + END IF - ! Verify that WAMIT_Init() did not request a different Interval! + ! Verify that WAMIT_Init() did not request a different Interval! - IF ( p%DT /= Interval ) THEN - CALL SetErrStat(ErrID_Fatal,'WAMIT Module attempted to change timestep interval, but this is not allowed. WAMIT Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) - CALL CleanUp() - RETURN - END IF - + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'WAMIT Module attempted to change timestep interval, but this is not allowed. WAMIT Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF + + ! move arrays back CALL MOVE_ALLOC(InitLocal%WAMIT%WaveTime, p%WaveTime ) CALL MOVE_ALLOC(InitLocal%WAMIT%WaveElevC0, Waves_InitOut%WaveElevC0) @@ -1142,7 +1226,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! TODO: 1/29/2016 GJH ! This is where we need to perform Wave Stretching, now that the wave kinematics have been combined. ! We will call a new subroutine to perform this work. - ! As an input, this code need the kinematics at the (X,Y,0) location which in a Z-line above/below all the nodes where kinematics are computed. + ! As an input, this code needs the kinematics at the (X,Y,0) location which in a Z-line above/below all the nodes where kinematics are computed. ! This code will alter the kinematics for stretching AND alter the nodeInWater array based on the combined wave elevation information IF (InitLocal%Waves%WaveStMod > 0 ) THEN call WvStretch_Init( InitLocal%Waves%WaveStMod, InitLocal%Waves%WtrDpth, InitLocal%Morison%NStepWave, InitLocal%Morison%NNodes, & @@ -1275,9 +1359,9 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' (-) ' , ' (s) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)' ! Write the data - DO I = 0,p%WAMIT%Conv_Rdtn%NStepRdtn-1 + DO I = 0,p%WAMIT(1)%Conv_Rdtn%NStepRdtn-1 - WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%WAMIT%Conv_Rdtn%RdtnDT, p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,1), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,2), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,1,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,2), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,2,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,3), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,3,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,4), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,4,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,5,5), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,5,6), p%WAMIT%Conv_Rdtn%RdtnKrnl(I,6,6) + WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%WAMIT(1)%Conv_Rdtn%RdtnDT, p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,1), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,2), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,2), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,5,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,5,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,6,6) END DO END IF @@ -1307,84 +1391,93 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Define system output initializations (set up mesh) here: + ! Create the input and output meshes associated with lumped load at the WAMIT reference point (WRP) - - CALL MeshCreate( BlankMesh = u%Mesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = 1 & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE.) - ! Create the node on the mesh + + CALL MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NBody & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + ! Create the node on the mesh - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + do iBody = 1, p%NBody + + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) + orientation = EulerConstruct(theta) - CALL MeshPositionNode (u%Mesh & - , 1 & - , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & - , ErrStat2 & - , ErrMsg2 ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - - ! Create the mesh element - CALL MeshConstructElement ( u%Mesh & - , ELEMENT_POINT & - , ErrStat2 & - , ErrMsg2 & - , 1 & - ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + ! Create the node on the mesh + CALL MeshPositionNode (u%Mesh & + , iBody & + , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & + , ErrStat2 & + , ErrMsg2 & + , orientation ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , iBody & + ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - CALL MeshCommit ( u%Mesh & - , ErrStat2 & - , ErrMsg2 ) + end do + + CALL MeshCommit ( u%Mesh & + , ErrStat2 & + , ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - CALL MeshCopy ( SrcMesh = u%Mesh & - ,DestMesh = y%Mesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%Mesh') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - u%Mesh%RemapFlag = .TRUE. - y%Mesh%RemapFlag = .TRUE. + CALL MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%Mesh') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + !TODO: Deal with AllHdroOrigin CALL MeshCopy ( SrcMesh = y%Mesh & ,DestMesh = y%AllHdroOrigin & ,CtrlCode = MESH_NEWCOPY & @@ -1402,7 +1495,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I y%AllHdroOrigin%RemapFlag = .TRUE. ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = u%Mesh & + CALL MeshCopy ( SrcMesh = u%Mesh & , DestMesh = m%AllHdroOrigin_position & , CtrlCode = MESH_NEWCOPY & , IOS = COMPONENT_INPUT & @@ -1435,7 +1528,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL CleanUp() RETURN END IF - +! TODO: Deal with Mesh ! Create some mesh mapping data CALL MeshCopy ( SrcMesh = y%Mesh & ,DestMesh = m%y_mapped & @@ -1462,16 +1555,14 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I RETURN END IF - ! Define initialization-routine output here: - InitOut%Ver = HydroDyn_ProgDesc - ! These three come directly from processing the inputs, and so will exist even if not using Morison elements: - InitOut%WtrDens = InitLocal%Morison%WtrDens - InitOut%WtrDpth = InitLocal%Morison%WtrDpth - InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL - - p%WtrDpth = InitOut%WtrDpth - - IF ( InitInp%hasIce ) THEN + ! Define initialization-routine output here: + InitOut%Ver = HydroDyn_ProgDesc + ! These three come directly from processing the inputs, and so will exist even if not using Morison elements: + InitOut%WtrDens = InitLocal%Morison%WtrDens + InitOut%WtrDpth = InitLocal%Morison%WtrDpth + InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL + + IF ( InitLocal%hasIce ) THEN IF ((InitLocal%Waves%WaveMod /= 0) .OR. (InitLocal%Current%CurrMod /= 0) ) THEN CALL SetErrStat(ErrID_Fatal,'Waves and Current must be turned off in HydroDyn when ice loading is computed. Set WaveMod=0 and CurrMod=0.',ErrStat,ErrMsg,RoutineName) END IF @@ -1618,7 +1709,7 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I ! Generic loop counter + INTEGER :: I, iWAMIT, iBody ! Generic loop counters TYPE(HydroDyn_ContinuousStateType) :: dxdt ! Continuous state derivatives at t TYPE(HydroDyn_DiscreteStateType) :: xd_t ! Discrete states at t (copy) TYPE(HydroDyn_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z) @@ -1661,39 +1752,66 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt !FIXME: Error handling appears to be broken here IF ( p%PotMod == 1 ) THEN + ALLOCATE( Inputs_WAMIT(nTime), STAT = ErrStat2 ) IF (ErrStat2 /=0) THEN CALL SetErrStat( ErrID_Fatal, 'Failed to allocate array Inputs_WAMIT.', ErrStat, ErrMsg, RoutineName ) RETURN END IF + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + ! For this NBodyMod or NBody=1, there is only one WAMIT object, so copy the necessary inputs and then call WAMIT_UpdateStates + do I=1,nTime + ! Copy the inputs from the HD mesh into the WAMIT mesh + call MeshCopy( Inputs(I)%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do - ! Loop over number of inputs and copy them into an array of WAMIT inputs + if (ErrStat < AbortErrLev) then ! if there was an error copying the input meshes, we'll skip this step and then cleanup the temporary input meshes + ! Update the WAMIT module states - DO I=1,nTime - - ! Copy the inputs from the HD mesh into the WAMIT mesh - CALL MeshCopy( Inputs(I)%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call WAMIT_UpdateStates( t, n, Inputs_WAMIT, InputTimes, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), m%WAMIT(1), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + end if - END DO - + else - IF (ErrStat < AbortErrLev) THEN ! if there was an error copying the input meshes, we'll skip this step and then cleanup the temporary input meshes - ! Update the WAMIT module states - - CALL WAMIT_UpdateStates( t, n, Inputs_WAMIT, InputTimes, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - END IF - + ! We have multiple WAMIT objects + + + do I=1,nTime + ! We need to create to valid mesh data structures in our Inputs_WAMIT(I)%Mesh using the miscvar version as a template, but the actually data will be generated below + call MeshCopy( m%u_WAMIT%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do + + ! Loop over number of inputs and copy them into an array of WAMIT inputs + do iWAMIT = 1, p%nWAMITObj + + do I=1,nTime + ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + Inputs_WAMIT(I)%Mesh%TranslationDisp(:,1) = Inputs(I)%Mesh%TranslationDisp(:,iWAMIT) + Inputs_WAMIT(I)%Mesh%Orientation (:,:,1)= Inputs(I)%Mesh%Orientation (:,:,iWAMIT) + Inputs_WAMIT(I)%Mesh%TranslationVel (:,1) = Inputs(I)%Mesh%TranslationVel (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%RotationVel (:,1) = Inputs(I)%Mesh%RotationVel (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%TranslationAcc (:,1) = Inputs(I)%Mesh%TranslationAcc (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%RotationAcc (:,1) = Inputs(I)%Mesh%RotationAcc (:,iWAMIT) + end do + + ! UpdateStates for the iWAMIT-th body + call WAMIT_UpdateStates( t, n, Inputs_WAMIT, InputTimes, p%WAMIT(iWAMIT), x%WAMIT(iWAMIT), xd%WAMIT(iWAMIT), z%WAMIT, OtherState%WAMIT(iWAMIT), m%WAMIT(iWAMIT), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (ErrStat > AbortErrLev) exit + + end do + + end if + ! deallocate temporary inputs - DO I=1,nTime - CALL WAMIT_DestroyInput( Inputs_WAMIT(I), ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - END DO + do I=1,nTime + call WAMIT_DestroyInput( Inputs_WAMIT(I), ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end do - DEALLOCATE(Inputs_WAMIT) + deallocate(Inputs_WAMIT) #ifdef USE_FIT ELSE IF ( p%PotMod == 2 ) THEN ! FIT @@ -1774,10 +1892,10 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, REAL(ReKi) :: WaveElev (p%NWaveElev) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi) :: WaveElev1(p%NWaveElev) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) - REAL(ReKi) :: q(6), qdot(6), qdotsq(6), qdotdot(6) + REAL(ReKi) :: q(6*p%NBody), qdot(6*p%NBody), qdotsq(6*p%NBody), qdotdot(6*p%NBody) REAL(ReKi) :: rotdisp(3) ! small angle rotational displacements REAL(ReKi) :: AllOuts(MaxHDOutputs) - + integer(IntKi) :: iBody, indxStart, indxEnd, iWAMIT ! Counters ! Initialize ErrStat @@ -1804,50 +1922,91 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) END IF -!FIXME: Error handling appears to be broken here. - - ! Determine the rotational angles from the direction-cosine matrix - rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - q = reshape((/REAL(u%Mesh%TranslationDisp(:,1),ReKi),rotdisp(:)/),(/6/)) - qdot = reshape((/u%Mesh%TranslationVel(:,1),u%Mesh%RotationVel(:,1)/),(/6/)) - qdotsq = abs(qdot)*qdot - qdotdot = reshape((/u%Mesh%TranslationAcc(:,1),u%Mesh%RotationAcc(:,1)/),(/6/)) - - - ! Compute the load contirbution from user-supplied added stiffness and damping + if ( p%PotMod == 1 ) then + !TODO: Check that we have valid Mesh data? + do iBody = 1, p%NBody + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,iBody), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + q (indxStart:indxEnd) = reshape((/real(u%Mesh%TranslationDisp(:,iBody),ReKi),rotdisp(:)/),(/6/)) + qdot (indxStart:indxEnd) = reshape((/u%Mesh%TranslationVel(:,iBody),u%Mesh%RotationVel(:,iBody)/),(/6/)) + qdotsq (indxStart:indxEnd) = abs(qdot(indxStart:indxEnd))*qdot(indxStart:indxEnd) + qdotdot(indxStart:indxEnd) = reshape((/u%Mesh%TranslationAcc(:,iBody),u%Mesh%RotationAcc(:,iBody)/),(/6/)) + end do + !FIXME: Error handling appears to be broken here. + if ( p%NBodyMod == 1 ) then + + ! Compute the load contirbution from user-supplied added stiffness and damping + m%F_PtfmAdd = p%AddF0(:,1) - matmul(p%AddCLin(:,:,1), q) - matmul(p%AddBLin(:,:,1), qdot) - matmul(p%AddBQuad(:,:,1), qdotsq) + do iBody = 1, p%NBody + indxStart = (iBody-1)*6+1 + ! Attach to the output point mesh + y%Mesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) + y%Mesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) + end do - m%F_PtfmAdd = p%AddF0 - matmul(p%AddCLin, q) - matmul(p%AddBLin, qdot) - matmul(p%AddBQuad, qdotsq) - - ! Attach to the output point mesh - y%Mesh%Force (:,1) = m%F_PtfmAdd(1:3) - y%Mesh%Moment(:,1) = m%F_PtfmAdd(4:6) + else + do iBody = 1, p%NBody + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + + m%F_PtfmAdd(indxStart:indxEnd) = p%AddF0(:,1) - matmul(p%AddCLin(:,:,iBody), q(indxStart:indxEnd)) - matmul(p%AddBLin(:,:,iBody), qdot(indxStart:indxEnd)) - matmul(p%AddBQuad(:,:,iBody), qdotsq(indxStart:indxEnd)) - IF ( p%PotMod == 1 ) THEN - IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh - - ! Copy the inputs from the HD mesh into the WAMIT mesh - CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL WAMIT_CalcOutput( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, & - z%WAMIT, OtherState%WAMIT, y%WAMIT, m%WAMIT, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - - ! Add WAMIT forces to the HydroDyn output mesh - y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%WAMIT%Mesh%Force (:,1) - y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%WAMIT%Mesh%Moment(:,1) + ! Attach to the output point mesh + y%Mesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) + y%Mesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) + end do - - ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order - m%F_Waves = m%WAMIT%F_Waves1 - + end if + + m%F_Waves = 0.0_ReKi + + if ( m%u_WAMIT%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh + + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + ! Copy the inputs from the HD mesh into the WAMIT mesh + call MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + if ( ErrStat >= AbortErrLev ) return + + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), & + z%WAMIT, OtherState%WAMIT(1), y%WAMIT(1), m%WAMIT(1), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + do iBody=1,p%NBody + y%Mesh%Force (:,iBody) = y%Mesh%Force (:,iBody) + y%WAMIT(1)%Mesh%Force (:,iBody) + y%Mesh%Moment(:,iBody) = y%Mesh%Moment(:,iBody) + y%WAMIT(1)%Mesh%Moment(:,iBody) + + end do + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + m%F_Waves = m%F_Waves + m%WAMIT(1)%F_Waves1 + else + do iBody=1,p%NBody + + ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + m%u_WAMIT%Mesh%TranslationDisp(:,1) = u%Mesh%TranslationDisp(:,iBody) + m%u_WAMIT%Mesh%Orientation (:,:,1)= u%Mesh%Orientation (:,:,iBody) + m%u_WAMIT%Mesh%TranslationVel (:,1) = u%Mesh%TranslationVel (:,iBody) + m%u_WAMIT%Mesh%RotationVel (:,1) = u%Mesh%RotationVel (:,iBody) + m%u_WAMIT%Mesh%TranslationAcc (:,1) = u%Mesh%TranslationAcc (:,iBody) + m%u_WAMIT%Mesh%RotationAcc (:,1) = u%Mesh%RotationAcc (:,iBody) + + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT, p%WAMIT(iBody), x%WAMIT(iBody), xd%WAMIT(iBody), & + z%WAMIT, OtherState%WAMIT(iBody), y%WAMIT(iBody), m%WAMIT(iBody), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + y%Mesh%Force (:,iBody) = y%Mesh%Force (:,iBody) + y%WAMIT(iBody)%Mesh%Force (:,1) + y%Mesh%Moment(:,iBody) = y%Mesh%Moment(:,iBody) + y%WAMIT(iBody)%Mesh%Moment(:,1) + + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + m%F_Waves(indxStart:indxEnd) = m%F_Waves(indxStart:indxEnd) + m%WAMIT(iBody)%F_Waves1 + end do + end if + end if - END IF - #ifdef USE_FIT ELSE IF ( p%PotMod ==2 ) THEN !FIT Inputs_FIT%roll = rotdisp(1) @@ -1873,7 +2032,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, IF ( ErrStat >= AbortErrLev ) RETURN - CALL WAMIT2_CalcOutput( Time, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, & + CALL WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, & z%WAMIT2, OtherState%WAMIT2, y%WAMIT2, m%WAMIT2, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) @@ -1923,7 +2082,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Map calculated results into the AllOuts Array - CALL HDOut_MapOutputs( Time, y, p%NWaveElev, WaveElev, WaveElev1, m%F_PtfmAdd, m%F_Waves, m%F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat2, ErrMsg2 ) + CALL HDOut_MapOutputs( Time, p, y, m%WAMIT, p%NWaveElev, WaveElev, WaveElev1, m%F_PtfmAdd, m%F_Waves, m%F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) DO I = 1,p%NumOuts @@ -1936,13 +2095,6 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, J = p%NumOuts + 1 - IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN - DO I=1, p%WAMIT%NumOuts - y%WriteOutput(J) = y%WAMIT%WriteOutput(I) - J = J + 1 - END DO - END IF - IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN DO I=1, p%Waves2%NumOuts y%WriteOutput(J) = y%Waves2%WriteOutput(I) @@ -1986,7 +2138,7 @@ SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxd TYPE(HydroDyn_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at Time INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - + integer(IntKi) :: iWAMIT ! loop counter CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_CalcContStateDeriv' ! Initialize ErrStat @@ -1996,58 +2148,41 @@ SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxd ! Compute the first time derivatives of the continuous states here: - - IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh - + if ( .not. m%u_WAMIT%Mesh%Committed ) return ! Make sure we are using WAMIT / there is a valid mesh + + + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then ! Copy the inputs from the HD mesh into the WAMIT mesh - CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN + call MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) + if ( ErrStat >= AbortErrLev ) return - CALL WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, dxdt%WAMIT, ErrStat, ErrMsg ) - - END IF + call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), m%WAMIT(1), dxdt%WAMIT(1), ErrStat, ErrMsg ) + else + + ! We have multiple WAMIT objects + + ! Loop over number of inputs and copy them into an array of WAMIT inputs + do iWAMIT = 1, p%nWAMITObj + + ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + m%u_WAMIT%Mesh%TranslationDisp(:,1) = u%Mesh%TranslationDisp(:,iWAMIT) + m%u_WAMIT%Mesh%Orientation (:,:,1)= u%Mesh%Orientation (:,:,iWAMIT) + m%u_WAMIT%Mesh%TranslationVel (:,1) = u%Mesh%TranslationVel (:,iWAMIT) + m%u_WAMIT%Mesh%RotationVel (:,1) = u%Mesh%RotationVel (:,iWAMIT) + m%u_WAMIT%Mesh%TranslationAcc (:,1) = u%Mesh%TranslationAcc (:,iWAMIT) + m%u_WAMIT%Mesh%RotationAcc (:,1) = u%Mesh%RotationAcc (:,iWAMIT) + + ! UpdateStates for the iWAMIT-th body + call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT(iWAMIT), x%WAMIT(iWAMIT), xd%WAMIT(iWAMIT), z%WAMIT, OtherState%WAMIT(iWAMIT), m%WAMIT(iWAMIT), dxdt%WAMIT(iWAMIT), ErrStat, ErrMsg ) + if (ErrStat > AbortErrLev) exit + + end do + + end if END SUBROUTINE HydroDyn_CalcContStateDeriv -!---------------------------------------------------------------------------------------------------------------------------------- -! Tight coupling routine for updating discrete states. Note that the WAMIT_UpdateDiscState violates the framework by having OtherStates -! be intent in/out. If/when this is fixed we can uncomment this routine. -!SUBROUTINE HydroDyn_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -! -! REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds -! INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval -! TYPE(HydroDyn_InputType), INTENT(IN ) :: u !< Inputs at Time -! TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters -! TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time -! TYPE(HydroDyn_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; -! !! Output: Discrete states at Time + Interval -! TYPE(HydroDyn_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time -! TYPE(HydroDyn_OtherStateType), INTENT(IN ) :: OtherState !< Other/optimization states -! TYPE(HydroDyn_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables -! INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation -! CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None -! -! -! ! Initialize ErrStat -! -! ErrStat = ErrID_None -! ErrMsg = "" -! -! -! ! Update discrete states -! -! IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh -! -! ! Copy the inputs from the HD mesh into the WAMIT mesh -! CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) -! IF ( ErrStat >= AbortErrLev ) RETURN -! -! CALL WAMIT_UpdateDiscState( Time, n, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, ErrStat, ErrMsg ) -! IF ( ErrStat >= AbortErrLev ) RETURN -! END IF -! -!END SUBROUTINE HydroDyn_UpdateDiscState !---------------------------------------------------------------------------------------------------------------------------------- @@ -2073,18 +2208,10 @@ SUBROUTINE HydroDyn_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m ErrStat = ErrID_None ErrMsg = "" - + ! Nothing to do here since none of the sub-modules have contraint states + z_residual = z + ! Solve for the constraint states here: - - IF ( m%u_WAMIT%Mesh%Committed ) THEN ! Make sure we are using WAMIT / there is a valid mesh - - ! Copy the inputs from the HD mesh into the WAMIT mesh - CALL MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - call WAMIT_CalcConstrStateResidual( Time, m%u_WAMIT, p%WAMIT, x%WAMIT, xd%WAMIT, z%WAMIT, OtherState%WAMIT, m%WAMIT, z_residual%WAMIT, ErrStat, ErrMsg ) - - END IF END SUBROUTINE HydroDyn_CalcConstrStateResidual diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 6736faf36..66c306943 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -23,7 +23,7 @@ usefrom WAMIT.txt usefrom WAMIT2.txt usefrom Morison.txt #usefrom FIT.txt -param HydroDyn/HydroDyn unused INTEGER MaxHDOutputs - 54 - "The maximum number of output channels supported by this module" - +param HydroDyn/HydroDyn unused INTEGER MaxHDOutputs - 456 - "The maximum number of output channels supported by this module" - typedef HydroDyn/HydroDyn InitInputType CHARACTER(1024) InputFile - - - "Supplied by Driver: full path and filename for the HydroDyn module" - typedef ^ ^ LOGICAL UseInputFile - - - "Supplied by Driver: .TRUE. if using a input file, .FALSE. if all inputs are being passed in by the caller" - typedef ^ ^ CHARACTER(1024) OutRootName - - - "Supplied by Driver: The name of the root file (without extension) including the full path" - @@ -47,14 +47,27 @@ typedef ^ ^ CHARACTER(8 typedef ^ ^ LOGICAL PtfmPF - - - "Optionally Supplied by Driver: Platform pitch tilt rotation force (flag)" - typedef ^ ^ CHARACTER(80) PtfmYFChr - - - "Platform yaw rotation force (flag) or DEFAULT" - typedef ^ ^ LOGICAL PtfmYF - - - "Optionally Supplied by Driver: Platform yaw rotation force (flag)" - -typedef ^ ^ ReKi AddF0 {6} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - -typedef ^ ^ ReKi AddCLin {6}{6} - - "Additional stiffness matrix" - -typedef ^ ^ ReKi AddBLin {6}{6} - - "Additional linear damping matrix" - -typedef ^ ^ ReKi AddBQuad {6}{6} - - "Additional quadratic damping (drag) matrix" - +typedef ^ ^ ReKi AddF0 {:}{:} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - +typedef ^ ^ ReKi AddCLin {:}{:}{:} - - "Additional stiffness matrix" - +typedef ^ ^ ReKi AddBLin {:}{:}{:} - - "Additional linear damping matrix" - +typedef ^ ^ ReKi AddBQuad {:}{:}{:} - - "Additional quadratic damping (drag) matrix" - typedef ^ ^ Waves_InitInputType Waves - - - "Initialization data for Waves module" - typedef ^ ^ Waves2_InitInputType Waves2 - - - "Initialization data for Waves module" - typedef ^ ^ Current_InitInputType Current - - - "Initialization data for Current module" - -typedef ^ ^ CHARACTER(1024) PotFile - - - "The name of the root potential flow file (without extension for WAMIT, complete name for FIT)" - +typedef ^ ^ CHARACTER(1024) PotFile {:} - - "The name of the root potential flow file (without extension for WAMIT, complete name for FIT)" - +typedef ^ ^ INTEGER nWAMITObj - - - "number of WAMIT input files. If NBodyMod = 1 then nPotFiles will be 1 even if NBody > 1" - +typedef ^ ^ INTEGER vecMultiplier - - - "multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1" - +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ ReKi PtfmVol0 {:} - - "" - +typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - +typedef ^ ^ ReKi WAMITULEN {:} - - "" - +typedef ^ ^ ReKi PtfmRefxt {:} - - "The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefyt {:} - - "The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefzt {:} - - "The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians +typedef ^ ^ ReKi PtfmCOBxt {:} - - "" - +typedef ^ ^ ReKi PtfmCOByt {:} - - "" - typedef ^ ^ WAMIT_InitInputType WAMIT - - - "Initialization data for WAMIT module" - typedef ^ ^ WAMIT2_InitInputType WAMIT2 - - - "Initialization data for WAMIT2 module" - typedef ^ ^ Morison_InitInputType Morison - - - "Initialization data for Morison module" - @@ -65,7 +78,7 @@ typedef ^ ^ CHARACTER(1 typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files]" - typedef ^ ^ LOGICAL OutAll - - - "Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F]" - typedef ^ ^ INTEGER NumOuts - - - "The number of outputs for this module as requested in the input file" - -typedef ^ ^ CHARACTER(10) OutList {54} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - +typedef ^ ^ CHARACTER(10) OutList {:} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - typedef ^ ^ LOGICAL HDSum - - - "Generate a HydroDyn summary file [T/F]" - typedef ^ ^ INTEGER UnSum - - - "File unit for the HydroDyn summary file [-1 = no summary file]" - typedef ^ ^ CHARACTER(20) OutFmt - - - "Output format for numerical results" - @@ -74,9 +87,9 @@ typedef ^ ^ CHARACTER(2 # # Define outputs from the initialization routine here: # -typedef ^ InitOutputType WAMIT_InitOutputType WAMIT - - - "Initialization output from the WAMIT module" - -typedef ^ ^ WAMIT2_InitOutputType WAMIT2 - - - "Initialization output from the WAMIT2 module" - -typedef ^ ^ Waves2_InitOutputType Waves2 - - - "Initialization output from the Waves2 module" - +typedef ^ InitOutputType WAMIT_InitOutputType WAMIT {:} - - "Initialization output from the WAMIT module" - +typedef ^ InitOutputType WAMIT2_InitOutputType WAMIT2 - - - "Initialization output from the WAMIT2 module" - +typedef ^ InitOutputType Waves2_InitOutputType Waves2 - - - "Initialization output from the Waves2 module" - typedef ^ ^ Morison_InitOutputType Morison - - - "Initialization output from the Morison module" - typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "The is the list of all HD-related output channel header strings (includes all sub-module channels)" - typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "The is the list of all HD-related output channel unit strings (includes all sub-module channels)" - @@ -102,7 +115,7 @@ typedef ^ HD_ModuleMapType MeshMapType # ..... States .................................................................................................................... # Define continuous (differentiable) states here: # -typedef ^ ContinuousStateType WAMIT_ContinuousStateType WAMIT - - - "continuous states from the wamit module" - +typedef ^ ContinuousStateType WAMIT_ContinuousStateType WAMIT {:} - - "continuous states from the wamit module" - typedef ^ ContinuousStateType WAMIT2_ContinuousStateType WAMIT2 - - - "continuous states from the wamit2 module" - typedef ^ ContinuousStateType Waves2_ContinuousStateType Waves2 - - - "continuous states from the waves2 module" - typedef ^ ContinuousStateType Morison_ContinuousStateType Morison - - - "continuous states from the Morison module" - @@ -110,7 +123,7 @@ typedef ^ ContinuousStateType Morison_Con # # Define discrete (nondifferentiable) states here: # -typedef ^ DiscreteStateType WAMIT_DiscreteStateType WAMIT - - - "discrete states from the wamit module" - +typedef ^ DiscreteStateType WAMIT_DiscreteStateType WAMIT {:} - - "discrete states from the wamit module" - typedef ^ DiscreteStateType WAMIT2_DiscreteStateType WAMIT2 - - - "discrete states from the wamit2 module" - #typedef ^ DiscreteStateType FIT_DiscreteStateType FIT - - - "discrete states from the FIT module" - typedef ^ DiscreteStateType Waves2_DiscreteStateType Waves2 - - - "discrete states from the waves2 module" - @@ -119,7 +132,7 @@ typedef ^ DiscreteStateType Morison_Dis # # Define constraint states here: # -typedef ^ ConstraintStateType WAMIT_ConstraintStateType WAMIT - - - "constraint states from WAMIT (may be empty)" - +typedef ^ ConstraintStateType WAMIT_ConstraintStateType WAMIT - - - "constraint states from WAMIT (may be empty)" - typedef ^ ConstraintStateType WAMIT2_ConstraintStateType WAMIT2 - - - "constraint states from WAMIT2 (may be empty)" - typedef ^ ConstraintStateType Waves2_ConstraintStateType Waves2 - - - "constraint states from the waves2 module" - typedef ^ ConstraintStateType Morison_ConstraintStateType Morison - - - "constraint states from the Morison module" - @@ -127,7 +140,7 @@ typedef ^ ConstraintStateType Morison_Con # # Define any other states here: # -typedef ^ OtherStateType WAMIT_OtherStateType WAMIT - - - "OtherState information from the WAMIT module" - +typedef ^ OtherStateType WAMIT_OtherStateType WAMIT {:} - - "OtherState information from the WAMIT module" - typedef ^ OtherStateType WAMIT2_OtherStateType WAMIT2 - - - "OtherState information from the WAMIT2 module" - #typedef ^ OtherStateType FIT_OtherStateType FIT - - - "OtherState information from the FIT module" - typedef ^ OtherStateType Waves2_OtherStateType Waves2 - - - "OtherState information from the Waves2 module" - @@ -144,14 +157,14 @@ typedef ^ ^ HD_ModuleMa typedef ^ ^ INTEGER Decimate - - - "The output decimation counter" - typedef ^ ^ DbKi LastOutTime - - - "Last time step which was written to the output file (sec)" - typedef ^ ^ INTEGER LastIndWave - - - "The last index used in the wave kinematics arrays, used to optimize interpolation" - -typedef ^ ^ ReKi F_PtfmAdd {6} - - "The total forces and moments due to additional pre-load, stiffness, and damping" - +typedef ^ ^ ReKi F_PtfmAdd {:} - - "The total forces and moments due to additional pre-load, stiffness, and damping" - typedef ^ ^ ReKi F_Hydro {6} - - "The total hydrodynamic forces and moments integrated about the WAMIT reference point" - -typedef ^ ^ ReKi F_Waves {6} - - "The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules)" - -typedef ^ ^ WAMIT_MiscVarType WAMIT - - - "misc var information from the WAMIT module" - +typedef ^ ^ ReKi F_Waves {:} - - "The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules)" - +typedef ^ ^ WAMIT_MiscVarType WAMIT {:} - - "misc var information from the WAMIT module" - typedef ^ ^ WAMIT2_MiscVarType WAMIT2 - - - "misc var information from the WAMIT2 module" - typedef ^ ^ Waves2_MiscVarType Waves2 - - - "misc var information from the Waves2 module" - typedef ^ ^ Morison_MiscVarType Morison - - - "misc var information from the Morison module" - -typedef ^ ^ WAMIT_InputType u_WAMIT - - - "WAMIT module inputs" - +typedef ^ ^ WAMIT_InputType u_WAMIT - - - "WAMIT module inputs" - typedef ^ ^ WAMIT2_InputType u_WAMIT2 - - - "WAMIT2 module inputs" - typedef ^ ^ Waves2_InputType u_Waves2 - - - "Waves2 module inputs" - typedef ^ ^ Logical IgnoreMod - - - "whether to ignore the modulo in ED outputs (necessary for linearization perturbations)" - @@ -159,22 +172,25 @@ typedef ^ ^ Logical # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: # -typedef ^ ParameterType WAMIT_ParameterType WAMIT - - - "Parameter data for the WAMIT module" - -typedef ^ ParameterType WAMIT2_ParameterType WAMIT2 - - - "Parameter data for the WAMIT2 module" - +typedef ^ ParameterType INTEGER nWAMITObj - - - "number of WAMIT input files and matrices. If NBodyMod = 1 then nPotFiles will be 1 even if NBody > 1" - +typedef ^ ^ INTEGER vecMultiplier - - - "multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1" - +typedef ^ ^ WAMIT_ParameterType WAMIT {:} - - "Parameter data for the WAMIT module" - +typedef ^ ^ WAMIT2_ParameterType WAMIT2 - - - "Parameter data for the WAMIT2 module" - #typedef ^ ^ FIT_ParameterType FIT - - - "Parameter data for the FIT module" - -typedef ^ ParameterType Waves2_ParameterType Waves2 - - - "Parameter data for the Waves2 module" - +typedef ^ ^ Waves2_ParameterType Waves2 - - - "Parameter data for the Waves2 module" - typedef ^ ^ Morison_ParameterType Morison - - - "Parameter data for the Morison module" - typedef ^ ^ INTEGER PotMod - - - "1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model" - +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - typedef ^ ^ SiKi WaveTime {:} - - "Array of time samples, (sec)" - typedef ^ ^ INTEGER NStepWave - - - "Number of data points in the wave kinematics arrays" - typedef ^ ^ INTEGER NWaveElev - - - "Number of wave elevation outputs" - typedef ^ ^ SiKi WaveElev {:}{:} - - "Total wave elevation" - typedef ^ ^ SiKi WaveElev1 {:}{:} - - "First order wave elevation" - -typedef ^ ^ ReKi WtrDpth - - - "Water depth" (m) -typedef ^ ^ ReKi AddF0 {6} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - -typedef ^ ^ ReKi AddCLin {6}{6} - - "Additional stiffness matrix" - -typedef ^ ^ ReKi AddBLin {6}{6} - - "Additional linear damping matrix" - -typedef ^ ^ ReKi AddBQuad {6}{6} - - "Additional quadratic damping (drag) matrix" - +typedef ^ ^ ReKi AddF0 {:}{:} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - +typedef ^ ^ ReKi AddCLin {:}{:}{:} - - "Additional stiffness matrix" - +typedef ^ ^ ReKi AddBLin {:}{:}{:} - - "Additional linear damping matrix" - +typedef ^ ^ ReKi AddBQuad {:}{:}{:} - - "Additional quadratic damping (drag) matrix" - typedef ^ ^ DbKi DT - - - "Time step in seconds for integration of continuous states (if a fixed-step integrator is used) and update of discrete states" - typedef ^ ^ OutParmType OutParam {:} - - "" - typedef ^ ^ INTEGER NumOuts - - - "Number of HydroDyn module-level outputs (not the total number including sub-modules" - @@ -200,10 +216,10 @@ typedef ^ InputType MeshType # # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: -typedef ^ OutputType WAMIT_OutputType WAMIT - - - "WAMIT module outputs" - +typedef ^ OutputType WAMIT_OutputType WAMIT {:} - - "WAMIT module outputs" - typedef ^ OutputType WAMIT2_OutputType WAMIT2 - - - "WAMIT2 module outputs" - typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - -typedef ^ OutputType MeshType Mesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - +typedef ^ OutputType MeshType Mesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index bcb8b6e5a..bffe4d1ed 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -101,9 +101,9 @@ PROGRAM HydroDynDriver INTEGER(IntKi) :: I ! Generic loop counter INTEGER(IntKi) :: J ! Generic loop counter INTEGER(IntKi) :: n ! Loop counter (for time step) - INTEGER(IntKi) :: ErrStat ! Status of error message - CHARACTER(1024) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). + INTEGER(IntKi) :: ErrStat,ErrStat2 ! Status of error message + CHARACTER(1024) :: ErrMsg,ErrMsg2 ! Error message if ErrStat /= ErrID_None + REAL(R8Ki) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. TYPE(HD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program @@ -118,6 +118,9 @@ PROGRAM HydroDynDriver real(DbKi) :: SttsTime ! Amount of time between screen status messages (sec) integer :: n_SttsTime ! Number of time steps between screen status messages (-) + type(MeshType) :: RefPtMesh ! 1-node Point mesh located at (0,0,0) in global system where all WAMIT-related driver inputs are set + type(MeshMapType) :: HD_Ref_2_WB_P ! Mesh mapping between Reference pt mesh and WAMIT body(ies) mesh + real(R8Ki) :: theta(3) ! mesh creation helper data ! For testing LOGICAL :: DoTight = .FALSE. @@ -198,9 +201,6 @@ PROGRAM HydroDynDriver !BJJ: added this for IceFloe/IceDyn InitInData%hasIce = .FALSE. - - - !------------------------------------------------------------------------------------- @@ -325,25 +325,96 @@ PROGRAM HydroDynDriver CALL HydroDyn_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) - ! Set any steady-state inputs, once before the time-stepping loop + IF ( u(1)%Mesh%Initialized ) THEN + + ! Create a motions mesh a (0,0,0) where all kinematics are specified + call MeshCreate( BlankMesh = RefPtMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + theta = (/ 0.0_R8Ki, 0.0_R8Ki, 0.0_R8Ki /) + dcm = EulerConstruct(theta) + + + ! Create the node on the mesh + + CALL MeshPositionNode (RefPtMesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat2 & + , ErrMsg2 & + , dcm ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + + ! Create the mesh element + CALL MeshConstructElement ( RefPtMesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + CALL MeshCommit ( RefPtMesh & + , ErrStat2 & + , ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + RefPtMesh%RemapFlag = .TRUE. + + ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] + + CALL MeshMapCreate( RefPtMesh, u(1)%Mesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + ! Set any steady-state inputs, once before the time-stepping loop IF ( drvrInitInp%WAMITInputsMod /= 2 ) THEN - u(1)%Mesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) + RefPtMesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) ! Compute direction cosine matrix from the rotation angles CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uWAMITInSteady(4), ReKi), REAL(drvrInitInp%uWAMITInSteady(5), ReKi), REAL(drvrInitInp%uWAMITInSteady(6), ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%Mesh%Orientation(:,:,1) = dcm - - u(1)%Mesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) - u(1)%Mesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) - u(1)%Mesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) - u(1)%Mesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) + RefPtMesh%Orientation(:,:,1) = dcm + + RefPtMesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) + RefPtMesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) + RefPtMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) + RefPtMesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) + ! Map kinematics to the WAMIT mesh with 1 to NBody nodes + CALL Transfer_Point_to_Point( RefPtMesh, u(1)%Mesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if END IF END IF diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 556c851e8..ac371b6cf 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -26,7 +26,6 @@ MODULE HydroDyn_Input USE HydroDyn_Output USE Waves USE Morison - USE WAMIT_Output USE WAMIT2_Output USE Waves2_Output USE Morison_Output @@ -200,26 +199,17 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! Local variables - INTEGER :: I ! generic integer for counting -! INTEGER :: J ! generic integer for counting + INTEGER :: I, j ! generic integer for counting CHARACTER( 2) :: strI ! string version of the loop counter - INTEGER :: UnIn ! Unit number for the input file -! LOGICAL :: EchoStore ! Stored version of NWTC_Library Echo variable -! INTEGER :: UnEchoStore ! Stored unit name for another module's echo file INTEGER :: UnEchoLocal ! The local unit number for this module's echo file CHARACTER(1024) :: EchoFile ! Name of HydroDyn echo file CHARACTER(1024) :: Line ! String to temporarially hold value of read line -! CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name -! CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement CHARACTER(1024) :: FileName ! Name of HydroDyn input file CHARACTER( 35) :: Frmt ! Output format for logical parameters. (matches NWTC Subroutine Library format) -! INTEGER :: JointID ! Temporary storage of JointID read from HydroDyn input file -! INTEGER :: PropSetID ! Temporary storage of PropSetID read from HydroDyn input file -! INTEGER :: MemberID ! Temporary storage of MemberID read from HydroDyn input file INTEGER, ALLOCATABLE :: tmpArray(:) ! Temporary array storage of the joint output list - - + real(ReKi), ALLOCATABLE :: tmpVec1(:), tmpVec2(:) ! Temporary arrays for WAMIT data + integer(IntKi) :: startIndx, endIndx ! indices into working arrays INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -820,30 +810,115 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) RETURN END IF + ! NBody - Number of WAMIT bodies to be used (-) [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data + ! contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there + ! are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] - ! PotFile - Root name of Potential flow data files (Could be WAMIT files or the FIT input file) + CALL ReadVar ( UnIn, FileName, InitInp%NBody, 'NBody', 'Number of WAMIT bodies', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! NBodyMod - Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, + ! 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms + ! between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] - CALL ReadVar ( UnIn, FileName, InitInp%PotFile, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL ReadVar ( UnIn, FileName, InitInp%NBodyMod, 'NBodyMod', 'Body coupling model', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() RETURN END IF + ! PotFile - Root name of Potential flow data files (Could be WAMIT files or the FIT input file) + + ! allocate space for the WAMIT-related data arrays: + InitInp%nWAMITObj = InitInp%NBody + InitInp%vecMultiplier = 1 + + if ( InitInp%NBodyMod == 1 ) then + InitInp%nWAMITObj = 1 ! Special case where all data in a single WAMIT input file as opposed to InitInp%NBody number of separate input files. + InitInp%vecMultiplier = InitInp%NBody + end if + + CALL AllocAry( InitInp%PotFile , InitInp%nWAMITObj, 'PotFile' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%WAMITULEN, InitInp%nWAMITObj, 'WAMITULEN' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmRefxt, InitInp%NBody, 'PtfmRefxt' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmRefyt, InitInp%NBody, 'PtfmRefyt' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmRefzt, InitInp%NBody, 'PtfmRefzt' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmRefztRot, InitInp%NBody, 'PtfmRefztRot' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmVol0 , InitInp%NBody, 'PtfmVol0' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmCOBxt, InitInp%NBody, 'PtfmCOBxt' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%PtfmCOByt, InitInp%NBody, 'PtfmCOByt' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + CALL ReadAry ( UnIn, FileName, InitInp%PotFile, InitInp%nWAMITObj, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF ! WAMITULEN - WAMIT characteristic body length scale - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%WAMITULEN, 'WAMITULEN', 'WAMIT characteristic body length scale', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL ReadAry ( UnIn, FileName, InitInp%WAMITULEN, InitInp%nWAMITObj, 'WAMITULEN', 'WAMIT characteristic body length scale', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() RETURN END IF + ! PtfmRefxt - The xt offset of the body reference point(s) from (0,0,0) (meters) + CALL ReadAry ( UnIn, FileName, InitInp%PtfmRefxt, InitInp%NBody, 'PtfmRefxt', & + 'xt offset of the body reference point(s) from (0,0,0)', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! PtfmRefyt - The yt offset of the body reference point(s) from (0,0,0) (meters) + + CALL ReadAry ( UnIn, FileName, InitInp%PtfmRefyt, InitInp%NBody, 'PtfmRefyt', & + 'yt offset of the body reference point(s) from (0,0,0)', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! PtfmRefzt - The zt offset of the body reference point(s) from (0,0,0) (meters) + + CALL ReadAry ( UnIn, FileName, InitInp%PtfmRefzt, InitInp%NBody, 'PtfmRefzt', & + 'zt offset of the body reference point(s) from (0,0,0)', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! PtfmRefztRot - The rotation about zt of the body reference frame(s) from xt/yt (deg) + + CALL ReadAry ( UnIn, FileName, InitInp%PtfmRefztRot, InitInp%NBody, 'PtfmRefzt', & + 'The rotation about zt of the body reference frame(s) from xt/yt', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + InitInp%PtfmRefztRot = InitInp%PtfmRefztRot*D2R_D ! Convert to radians + ! PtfmVol0 - Displaced volume of water when the platform is in its undisplaced position - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmVol0, 'PtfmVol0', & + CALL ReadAry ( UnIn, FileName, InitInp%PtfmVol0, InitInp%NBody, 'PtfmVol0', & 'Displaced volume of water when the platform is in its undisplaced position', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN @@ -854,7 +929,7 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! PtfmCOBxt - The xt offset of the center of buoyancy (COB) from the WAMIT reference point - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmCOBxt, 'PtfmCOBxt', & + CALL ReadAry ( UnIn, FileName, InitInp%PtfmCOBxt, InitInp%NBody, 'PtfmCOBxt', & 'xt offset of the center of buoyancy (COB) from the WAMIT reference point', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN @@ -865,7 +940,7 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! PtfmCOByt - The yt offset of the center of buoyancy (COB) from the WAMIT reference point - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%PtfmCOByt, 'PtfmCOByt', & + CALL ReadAry ( UnIn, FileName, InitInp%PtfmCOByt, InitInp%NBody, 'PtfmCOByt', & 'yt offset of the center of buoyancy (COB) from the WAMIT reference point', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN @@ -1091,9 +1166,15 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) !------------------------------------------------------------------------------------------------- ! Floating Platform Additional Stiffness and Damping Section !------------------------------------------------------------------------------------------------- + + CALL AllocAry( InitInp%AddF0, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddF0' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%AddCLin, InitInp%vecMultiplier*6, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddCLin' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%AddBLin, InitInp%vecMultiplier*6, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddBLin' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( InitInp%AddBQuad, InitInp%vecMultiplier*6, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddBQuad' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( tmpVec1, InitInp%nWAMITObj, 'tmpVec1', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL AllocAry( tmpVec2, 6*InitInp%NBody, 'tmpVec2', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - - ! Header + ! Header CALL ReadCom( UnIn, FileName, 'Additional stiffness and damping header', ErrStat2, ErrMsg2, UnEchoLocal ) @@ -1105,38 +1186,46 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! AddF0 - Additional preload - - CALL ReadAry ( UnIn, FileName, InitInp%AddF0, 6, 'AddF0', & - ' Additional preload vector', ErrStat2, ErrMsg2, UnEchoLocal ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - + do i = 1,6*InitInp%vecMultiplier + CALL ReadAry ( UnIn, FileName, tmpVec1, InitInp%nWAMITObj, 'AddF0', & + ' Additional preload vector', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + do j = 1, InitInp%nWAMITObj + InitInp%AddF0(i,j) = tmpVec1(j) + end do + end do ! AddCLin - DO I=1,6 + do i=1,6*InitInp%vecMultiplier - WRITE(strI,'(I1)') I - CALL ReadAry ( UnIn, FileName, InitInp%AddCLin(I,:), 6, 'AddCLin', & + write(strI,'(I1)') i + call ReadAry ( UnIn, FileName, tmpVec2, 6*InitInp%NBody, 'AddCLin', & ' Row '//strI//' of the additional linear stiffness matrix', ErrStat2, ErrMsg2, UnEchoLocal ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - END DO + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + if (ErrStat >= AbortErrLev) then + call CleanUp() + return + end if + do j = 1, InitInp%nWAMITObj + startIndx = 6*InitInp%vecMultiplier*(j-1) + 1 + endIndx = startIndx + 6*InitInp%vecMultiplier - 1 + InitInp%AddCLin(I,:,j) = tmpVec2(startIndx:endIndx) + end do + end do ! AddBLin - DO I=1,6 + DO I=1,6*InitInp%vecMultiplier WRITE(strI,'(I1)') I - CALL ReadAry ( UnIn, FileName, InitInp%AddBLin(I,:), 6, 'AddBLin', & + CALL ReadAry ( UnIn, FileName, tmpVec2, 6*InitInp%NBody, 'AddBLin', & ' Row '//strI//' of the additional linear damping matrix', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) @@ -1144,15 +1233,20 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) CALL CleanUp() RETURN END IF + do j = 1, InitInp%nWAMITObj + startIndx = 6*InitInp%vecMultiplier*(j-1) + 1 + endIndx = startIndx + 6*InitInp%vecMultiplier - 1 + InitInp%AddBLin(I,:,j) = tmpVec2(startIndx:endIndx) + end do END DO ! AddBQuad - DO I=1,6 + DO I=1,6*InitInp%vecMultiplier WRITE(strI,'(I1)') I - CALL ReadAry ( UnIn, FileName, InitInp%AddBQuad(I,:), 6, 'AddBQuad', & + CALL ReadAry ( UnIn, FileName, tmpVec2, 6*InitInp%NBody, 'AddBQuad', & ' Row '//strI//' of the additional quadratic damping matrix', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) @@ -1160,6 +1254,11 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) CALL CleanUp() RETURN END IF + do j = 1, InitInp%nWAMITObj + startIndx = 6*InitInp%vecMultiplier*(j-1) + 1 + endIndx = startIndx + 6*InitInp%vecMultiplier - 1 + InitInp%AddBQuad(I,:,j) = tmpVec2(startIndx:endIndx) + end do END DO @@ -2936,24 +3035,28 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! PotFile - Root name of potential flow files IF ( InitInp%PotMod > 0 ) THEN - IF ( LEN_TRIM( InitInp%PotFile ) == 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'PotFile must not be an empty string.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF + do i = 1,InitInp%nWAMITObj + IF ( LEN_TRIM( InitInp%PotFile(i) ) == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'PotFile must not be an empty string.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF - ! if this is a relative path, let's make it relative to the location of the main input file - ! tell the WAMIT and WAMIT2 modules what the filename is + ! if this is a relative path, let's make it relative to the location of the main input file + ! tell the WAMIT and WAMIT2 modules what the filename is - IF ( PathIsRelative( InitInp%PotFile ) ) THEN - CALL GetPath( TRIM(InitInp%InputFile), TmpPath ) - InitInp%PotFile = TRIM(TmpPath)//TRIM(InitInp%PotFile) - END IF - InitInp%WAMIT%WAMITFile = InitInp%PotFile - InitInp%WAMIT2%WAMITFile = InitInp%PotFile + IF ( PathIsRelative( InitInp%PotFile(i) ) ) THEN + CALL GetPath( TRIM(InitInp%InputFile), TmpPath ) + InitInp%PotFile(i) = TRIM(TmpPath)//TRIM(InitInp%PotFile(i)) + END IF + end do + + !TODO: Move this to where the WAMIT modules are initialized + InitInp%WAMIT%WAMITFile = InitInp%PotFile(1) + InitInp%WAMIT2%WAMITFile = InitInp%PotFile(1) ! Set the flag for multidirectional waves for WAMIT2 module. It needs to know since the Newman approximation ! can only use uni-directional waves. - InitInp%WAMIT2%WaveMultiDir = InitInp%Waves%WaveMultiDir + InitInp%WAMIT2%WaveMultiDir = InitInp%Waves%WaveMultiDir ELSE InitInp%PotFile = "" @@ -2967,15 +3070,17 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! WAMITULEN - WAMIT characteristic body length scale IF ( InitInp%PotMod == 1 ) THEN - - InitInp%WAMIT2%WAMITULEN = InitInp%WAMIT%WAMITULEN ! Copy to the WAMIT2 module info - IF ( InitInp%WAMIT%WAMITULEN < 0.0 ) THEN - CALL SetErrStat( ErrID_Fatal,'WAMITULEN must be positive.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF +!TODO: Deal with WAMIT2 and check each WAMITULEN not just the first + InitInp%WAMIT2%WAMITULEN = InitInp%WAMITULEN(1) ! Copy to the WAMIT2 module info + do i = 1,InitInp%nWAMITObj + IF ( InitInp%WAMITULEN(1) < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'WAMITULEN must be positive.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + end do ELSE - InitInp%WAMIT%WAMITULEN = 1.0 + InitInp%WAMITULEN = 1.0 InitInp%WAMIT2%WAMITULEN = 1.0 END IF @@ -2984,15 +3089,15 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! PtfmVol0 - Displaced volume of water when the platform is in its undisplaced position IF ( InitInp%PotMod == 1 ) THEN - - IF ( InitInp%WAMIT%PtfmVol0 < 0.0 ) THEN - CALL SetErrStat( ErrID_Fatal,'PtfmVol0 must not be negative.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - + do i = 1,InitInp%nWAMITObj + IF ( InitInp%PtfmVol0(i) < 0.0 ) THEN + CALL SetErrStat( ErrID_Fatal,'PtfmVol0 must not be negative.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + end do ELSE - InitInp%WAMIT%PtfmVol0 = 0.0 + InitInp%PtfmVol0 = 0.0 END IF @@ -4116,31 +4221,25 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF foundMask = .FALSE. ! Extract Waves2 list - InitInp%Waves2%NumOuts = GetWaves2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Waves2%OutList, foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + InitInp%Waves2%NumOuts = GetWaves2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Waves2%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! Extract WAMIT list - InitInp%WAMIT%NumOuts = GetWAMITChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT%OutList, foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! Extract WAMIT2 list - InitInp%WAMIT2%NumOuts = GetWAMIT2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT2%OutList, foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + InitInp%WAMIT2%NumOuts = GetWAMIT2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT2%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! Extract Morison list !foundMask = .FALSE. - InitInp%Morison%NumOuts = GetMorisonChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Morison%OutList, foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + InitInp%Morison%NumOuts = GetMorisonChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Morison%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! Attach remaining items to the HydroDyn list !foundMask = .FALSE. - InitInp%NumOuts = HDOut_GetChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%OutList , foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL PrintBadChannelWarning(InitInp%NUserOutputs, InitInp%UserOutputs , foundMask, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call Allocary(InitInp%OutList, InitInp%NUserOutputs, "InitInp%OutList", ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + InitInp%NumOuts = HDOut_GetChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%OutList , foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL PrintBadChannelWarning(InitInp%NUserOutputs, InitInp%UserOutputs , foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev ) RETURN DEALLOCATE(foundMask) + END IF ! Now that we have the sub-lists organized, lets do some additional validation. diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index 8df4c6ada..4d2613909 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -29,155 +29,781 @@ MODULE HydroDyn_Output PRIVATE +! =================================================================================================== +! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" +! using the parameters listed in the "HydroDynOutListParameters.xlsx" Excel file. Any changes to these +! lines should be modified in the Matlab script and/or Excel worksheet as necessary. +! =================================================================================================== +! This code was generated by Write_ChckOutLst.m at 22-Sep-2019 15:01:11. - ! Parameters related to output length (number of characters allowed in the output data headers): + + ! Parameters related to output length (number of characters allowed in the output data headers): INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + ! Time: - INTEGER(IntKi), PARAMETER :: Time = 0 - - - ! Category: - - INTEGER(IntKi), PARAMETER :: AddFxi = 1 - INTEGER(IntKi), PARAMETER :: AddFyi = 2 - INTEGER(IntKi), PARAMETER :: AddFzi = 3 - INTEGER(IntKi), PARAMETER :: AddMxi = 4 - INTEGER(IntKi), PARAMETER :: AddMyi = 5 - INTEGER(IntKi), PARAMETER :: AddMzi = 6 - - - ! Category: - - INTEGER(IntKi), PARAMETER :: HydroFxi = 7 - INTEGER(IntKi), PARAMETER :: HydroFyi = 8 - INTEGER(IntKi), PARAMETER :: HydroFzi = 9 - INTEGER(IntKi), PARAMETER :: HydroMxi = 10 - INTEGER(IntKi), PARAMETER :: HydroMyi = 11 - INTEGER(IntKi), PARAMETER :: HydroMzi = 12 - - - ! Category: - - INTEGER(IntKi), PARAMETER :: Wave1Elev = 13 - INTEGER(IntKi), PARAMETER :: Wave1Elv1 = 14 - INTEGER(IntKi), PARAMETER :: Wave2Elev = 15 - INTEGER(IntKi), PARAMETER :: Wave2Elv1 = 16 - INTEGER(IntKi), PARAMETER :: Wave3Elev = 17 - INTEGER(IntKi), PARAMETER :: Wave3Elv1 = 18 - INTEGER(IntKi), PARAMETER :: Wave4Elev = 19 - INTEGER(IntKi), PARAMETER :: Wave4Elv1 = 20 - INTEGER(IntKi), PARAMETER :: Wave5Elev = 21 - INTEGER(IntKi), PARAMETER :: Wave5Elv1 = 22 - INTEGER(IntKi), PARAMETER :: Wave6Elev = 23 - INTEGER(IntKi), PARAMETER :: Wave6Elv1 = 24 - INTEGER(IntKi), PARAMETER :: Wave7Elev = 25 - INTEGER(IntKi), PARAMETER :: Wave7Elv1 = 26 - INTEGER(IntKi), PARAMETER :: Wave8Elev = 27 - INTEGER(IntKi), PARAMETER :: Wave8Elv1 = 28 - INTEGER(IntKi), PARAMETER :: Wave9Elev = 29 - INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 30 - - - ! Category: - - INTEGER(IntKi), PARAMETER :: WavesFxi = 31 - INTEGER(IntKi), PARAMETER :: WavesFyi = 32 - INTEGER(IntKi), PARAMETER :: WavesFzi = 33 - INTEGER(IntKi), PARAMETER :: WavesMxi = 34 - INTEGER(IntKi), PARAMETER :: WavesMyi = 35 - INTEGER(IntKi), PARAMETER :: WavesMzi = 36 - - - ! Category: - - INTEGER(IntKi), PARAMETER :: WRPSurge = 37 - INTEGER(IntKi), PARAMETER :: WRPSway = 38 - INTEGER(IntKi), PARAMETER :: WRPHeave = 39 - INTEGER(IntKi), PARAMETER :: WRPRoll = 40 - INTEGER(IntKi), PARAMETER :: WRPPitch = 41 - INTEGER(IntKi), PARAMETER :: WRPYaw = 42 - INTEGER(IntKi), PARAMETER :: WRPTVxi = 43 - INTEGER(IntKi), PARAMETER :: WRPTVyi = 44 - INTEGER(IntKi), PARAMETER :: WRPTVzi = 45 - INTEGER(IntKi), PARAMETER :: WRPRVxi = 46 - INTEGER(IntKi), PARAMETER :: WRPRVyi = 47 - INTEGER(IntKi), PARAMETER :: WRPRVzi = 48 - INTEGER(IntKi), PARAMETER :: WRPTAxi = 49 - INTEGER(IntKi), PARAMETER :: WRPTAyi = 50 - INTEGER(IntKi), PARAMETER :: WRPTAzi = 51 - INTEGER(IntKi), PARAMETER :: WRPRAxi = 52 - INTEGER(IntKi), PARAMETER :: WRPRAyi = 53 - INTEGER(IntKi), PARAMETER :: WRPRAzi = 54 - - !End of code generated by Matlab script + INTEGER(IntKi), PARAMETER :: Time = 0 + + + ! Integrated Hydrodynamic Loads at (0,0,0): + + INTEGER(IntKi), PARAMETER :: HydroFxi = 1 + INTEGER(IntKi), PARAMETER :: HydroFyi = 2 + INTEGER(IntKi), PARAMETER :: HydroFzi = 3 + INTEGER(IntKi), PARAMETER :: HydroMxi = 4 + INTEGER(IntKi), PARAMETER :: HydroMyi = 5 + INTEGER(IntKi), PARAMETER :: HydroMzi = 6 + + + ! WAMIT Body Kinematics: + + INTEGER(IntKi), PARAMETER :: B1Surge = 7 + INTEGER(IntKi), PARAMETER :: B1Sway = 8 + INTEGER(IntKi), PARAMETER :: B1Heave = 9 + INTEGER(IntKi), PARAMETER :: B1Roll = 10 + INTEGER(IntKi), PARAMETER :: B1Pitch = 11 + INTEGER(IntKi), PARAMETER :: B1Yaw = 12 + INTEGER(IntKi), PARAMETER :: B1TVxi = 13 + INTEGER(IntKi), PARAMETER :: B1TVyi = 14 + INTEGER(IntKi), PARAMETER :: B1TVzi = 15 + INTEGER(IntKi), PARAMETER :: B1RVxi = 16 + INTEGER(IntKi), PARAMETER :: B1RVyi = 17 + INTEGER(IntKi), PARAMETER :: B1RVzi = 18 + INTEGER(IntKi), PARAMETER :: B1TAxi = 19 + INTEGER(IntKi), PARAMETER :: B1TAyi = 20 + INTEGER(IntKi), PARAMETER :: B1TAzi = 21 + INTEGER(IntKi), PARAMETER :: B1RAxi = 22 + INTEGER(IntKi), PARAMETER :: B1RAyi = 23 + INTEGER(IntKi), PARAMETER :: B1RAzi = 24 + INTEGER(IntKi), PARAMETER :: B2Surge = 25 + INTEGER(IntKi), PARAMETER :: B2Sway = 26 + INTEGER(IntKi), PARAMETER :: B2Heave = 27 + INTEGER(IntKi), PARAMETER :: B2Roll = 28 + INTEGER(IntKi), PARAMETER :: B2Pitch = 29 + INTEGER(IntKi), PARAMETER :: B2Yaw = 30 + INTEGER(IntKi), PARAMETER :: B2TVxi = 31 + INTEGER(IntKi), PARAMETER :: B2TVyi = 32 + INTEGER(IntKi), PARAMETER :: B2TVzi = 33 + INTEGER(IntKi), PARAMETER :: B2RVxi = 34 + INTEGER(IntKi), PARAMETER :: B2RVyi = 35 + INTEGER(IntKi), PARAMETER :: B2RVzi = 36 + INTEGER(IntKi), PARAMETER :: B2TAxi = 37 + INTEGER(IntKi), PARAMETER :: B2TAyi = 38 + INTEGER(IntKi), PARAMETER :: B2TAzi = 39 + INTEGER(IntKi), PARAMETER :: B2RAxi = 40 + INTEGER(IntKi), PARAMETER :: B2RAyi = 41 + INTEGER(IntKi), PARAMETER :: B2RAzi = 42 + INTEGER(IntKi), PARAMETER :: B3Surge = 43 + INTEGER(IntKi), PARAMETER :: B3Sway = 44 + INTEGER(IntKi), PARAMETER :: B3Heave = 45 + INTEGER(IntKi), PARAMETER :: B3Roll = 46 + INTEGER(IntKi), PARAMETER :: B3Pitch = 47 + INTEGER(IntKi), PARAMETER :: B3Yaw = 48 + INTEGER(IntKi), PARAMETER :: B3TVxi = 49 + INTEGER(IntKi), PARAMETER :: B3TVyi = 50 + INTEGER(IntKi), PARAMETER :: B3TVzi = 51 + INTEGER(IntKi), PARAMETER :: B3RVxi = 52 + INTEGER(IntKi), PARAMETER :: B3RVyi = 53 + INTEGER(IntKi), PARAMETER :: B3RVzi = 54 + INTEGER(IntKi), PARAMETER :: B3TAxi = 55 + INTEGER(IntKi), PARAMETER :: B3TAyi = 56 + INTEGER(IntKi), PARAMETER :: B3TAzi = 57 + INTEGER(IntKi), PARAMETER :: B3RAxi = 58 + INTEGER(IntKi), PARAMETER :: B3RAyi = 59 + INTEGER(IntKi), PARAMETER :: B3RAzi = 60 + INTEGER(IntKi), PARAMETER :: B4Surge = 61 + INTEGER(IntKi), PARAMETER :: B4Sway = 62 + INTEGER(IntKi), PARAMETER :: B4Heave = 63 + INTEGER(IntKi), PARAMETER :: B4Roll = 64 + INTEGER(IntKi), PARAMETER :: B4Pitch = 65 + INTEGER(IntKi), PARAMETER :: B4Yaw = 66 + INTEGER(IntKi), PARAMETER :: B4TVxi = 67 + INTEGER(IntKi), PARAMETER :: B4TVyi = 68 + INTEGER(IntKi), PARAMETER :: B4TVzi = 69 + INTEGER(IntKi), PARAMETER :: B4RVxi = 70 + INTEGER(IntKi), PARAMETER :: B4RVyi = 71 + INTEGER(IntKi), PARAMETER :: B4RVzi = 72 + INTEGER(IntKi), PARAMETER :: B4TAxi = 73 + INTEGER(IntKi), PARAMETER :: B4TAyi = 74 + INTEGER(IntKi), PARAMETER :: B4TAzi = 75 + INTEGER(IntKi), PARAMETER :: B4RAxi = 76 + INTEGER(IntKi), PARAMETER :: B4RAyi = 77 + INTEGER(IntKi), PARAMETER :: B4RAzi = 78 + INTEGER(IntKi), PARAMETER :: B5Surge = 79 + INTEGER(IntKi), PARAMETER :: B5Sway = 80 + INTEGER(IntKi), PARAMETER :: B5Heave = 81 + INTEGER(IntKi), PARAMETER :: B5Roll = 82 + INTEGER(IntKi), PARAMETER :: B5Pitch = 83 + INTEGER(IntKi), PARAMETER :: B5Yaw = 84 + INTEGER(IntKi), PARAMETER :: B5TVxi = 85 + INTEGER(IntKi), PARAMETER :: B5TVyi = 86 + INTEGER(IntKi), PARAMETER :: B5TVzi = 87 + INTEGER(IntKi), PARAMETER :: B5RVxi = 88 + INTEGER(IntKi), PARAMETER :: B5RVyi = 89 + INTEGER(IntKi), PARAMETER :: B5RVzi = 90 + INTEGER(IntKi), PARAMETER :: B5TAxi = 91 + INTEGER(IntKi), PARAMETER :: B5TAyi = 92 + INTEGER(IntKi), PARAMETER :: B5TAzi = 93 + INTEGER(IntKi), PARAMETER :: B5RAxi = 94 + INTEGER(IntKi), PARAMETER :: B5RAyi = 95 + INTEGER(IntKi), PARAMETER :: B5RAzi = 96 + INTEGER(IntKi), PARAMETER :: B6Surge = 97 + INTEGER(IntKi), PARAMETER :: B6Sway = 98 + INTEGER(IntKi), PARAMETER :: B6Heave = 99 + INTEGER(IntKi), PARAMETER :: B6Roll = 100 + INTEGER(IntKi), PARAMETER :: B6Pitch = 101 + INTEGER(IntKi), PARAMETER :: B6Yaw = 102 + INTEGER(IntKi), PARAMETER :: B6TVxi = 103 + INTEGER(IntKi), PARAMETER :: B6TVyi = 104 + INTEGER(IntKi), PARAMETER :: B6TVzi = 105 + INTEGER(IntKi), PARAMETER :: B6RVxi = 106 + INTEGER(IntKi), PARAMETER :: B6RVyi = 107 + INTEGER(IntKi), PARAMETER :: B6RVzi = 108 + INTEGER(IntKi), PARAMETER :: B6TAxi = 109 + INTEGER(IntKi), PARAMETER :: B6TAyi = 110 + INTEGER(IntKi), PARAMETER :: B6TAzi = 111 + INTEGER(IntKi), PARAMETER :: B6RAxi = 112 + INTEGER(IntKi), PARAMETER :: B6RAyi = 113 + INTEGER(IntKi), PARAMETER :: B6RAzi = 114 + INTEGER(IntKi), PARAMETER :: B7Surge = 115 + INTEGER(IntKi), PARAMETER :: B7Sway = 116 + INTEGER(IntKi), PARAMETER :: B7Heave = 117 + INTEGER(IntKi), PARAMETER :: B7Roll = 118 + INTEGER(IntKi), PARAMETER :: B7Pitch = 119 + INTEGER(IntKi), PARAMETER :: B7Yaw = 120 + INTEGER(IntKi), PARAMETER :: B7TVxi = 121 + INTEGER(IntKi), PARAMETER :: B7TVyi = 122 + INTEGER(IntKi), PARAMETER :: B7TVzi = 123 + INTEGER(IntKi), PARAMETER :: B7RVxi = 124 + INTEGER(IntKi), PARAMETER :: B7RVyi = 125 + INTEGER(IntKi), PARAMETER :: B7RVzi = 126 + INTEGER(IntKi), PARAMETER :: B7TAxi = 127 + INTEGER(IntKi), PARAMETER :: B7TAyi = 128 + INTEGER(IntKi), PARAMETER :: B7TAzi = 129 + INTEGER(IntKi), PARAMETER :: B7RAxi = 130 + INTEGER(IntKi), PARAMETER :: B7RAyi = 131 + INTEGER(IntKi), PARAMETER :: B7RAzi = 132 + INTEGER(IntKi), PARAMETER :: B8Surge = 133 + INTEGER(IntKi), PARAMETER :: B8Sway = 134 + INTEGER(IntKi), PARAMETER :: B8Heave = 135 + INTEGER(IntKi), PARAMETER :: B8Roll = 136 + INTEGER(IntKi), PARAMETER :: B8Pitch = 137 + INTEGER(IntKi), PARAMETER :: B8Yaw = 138 + INTEGER(IntKi), PARAMETER :: B8TVxi = 139 + INTEGER(IntKi), PARAMETER :: B8TVyi = 140 + INTEGER(IntKi), PARAMETER :: B8TVzi = 141 + INTEGER(IntKi), PARAMETER :: B8RVxi = 142 + INTEGER(IntKi), PARAMETER :: B8RVyi = 143 + INTEGER(IntKi), PARAMETER :: B8RVzi = 144 + INTEGER(IntKi), PARAMETER :: B8TAxi = 145 + INTEGER(IntKi), PARAMETER :: B8TAyi = 146 + INTEGER(IntKi), PARAMETER :: B8TAzi = 147 + INTEGER(IntKi), PARAMETER :: B8RAxi = 148 + INTEGER(IntKi), PARAMETER :: B8RAyi = 149 + INTEGER(IntKi), PARAMETER :: B8RAzi = 150 + INTEGER(IntKi), PARAMETER :: B9Surge = 151 + INTEGER(IntKi), PARAMETER :: B9Sway = 152 + INTEGER(IntKi), PARAMETER :: B9Heave = 153 + INTEGER(IntKi), PARAMETER :: B9Roll = 154 + INTEGER(IntKi), PARAMETER :: B9Pitch = 155 + INTEGER(IntKi), PARAMETER :: B9Yaw = 156 + INTEGER(IntKi), PARAMETER :: B9TVxi = 157 + INTEGER(IntKi), PARAMETER :: B9TVyi = 158 + INTEGER(IntKi), PARAMETER :: B9TVzi = 159 + INTEGER(IntKi), PARAMETER :: B9RVxi = 160 + INTEGER(IntKi), PARAMETER :: B9RVyi = 161 + INTEGER(IntKi), PARAMETER :: B9RVzi = 162 + INTEGER(IntKi), PARAMETER :: B9TAxi = 163 + INTEGER(IntKi), PARAMETER :: B9TAyi = 164 + INTEGER(IntKi), PARAMETER :: B9TAzi = 165 + INTEGER(IntKi), PARAMETER :: B9RAxi = 166 + INTEGER(IntKi), PARAMETER :: B9RAyi = 167 + INTEGER(IntKi), PARAMETER :: B9RAzi = 168 + + + ! WAMIT Body Forces: + + INTEGER(IntKi), PARAMETER :: B1AddFxi = 169 + INTEGER(IntKi), PARAMETER :: B1AddFyi = 170 + INTEGER(IntKi), PARAMETER :: B1AddFzi = 171 + INTEGER(IntKi), PARAMETER :: B1AddMxi = 172 + INTEGER(IntKi), PARAMETER :: B1AddMyi = 173 + INTEGER(IntKi), PARAMETER :: B1AddMzi = 174 + INTEGER(IntKi), PARAMETER :: B1WvsF1xi = 175 + INTEGER(IntKi), PARAMETER :: B1WvsF1yi = 176 + INTEGER(IntKi), PARAMETER :: B1WvsF1zi = 177 + INTEGER(IntKi), PARAMETER :: B1WvsM1xi = 178 + INTEGER(IntKi), PARAMETER :: B1WvsM1yi = 179 + INTEGER(IntKi), PARAMETER :: B1WvsM1zi = 180 + INTEGER(IntKi), PARAMETER :: B1WvsFxi = 181 + INTEGER(IntKi), PARAMETER :: B1WvsFyi = 182 + INTEGER(IntKi), PARAMETER :: B1WvsFzi = 183 + INTEGER(IntKi), PARAMETER :: B1WvsMxi = 184 + INTEGER(IntKi), PARAMETER :: B1WvsMyi = 185 + INTEGER(IntKi), PARAMETER :: B1WvsMzi = 186 + INTEGER(IntKi), PARAMETER :: B1HdSFxi = 187 + INTEGER(IntKi), PARAMETER :: B1HdSFyi = 188 + INTEGER(IntKi), PARAMETER :: B1HdSFzi = 189 + INTEGER(IntKi), PARAMETER :: B1HdSMxi = 190 + INTEGER(IntKi), PARAMETER :: B1HdSMyi = 191 + INTEGER(IntKi), PARAMETER :: B1HdSMzi = 192 + INTEGER(IntKi), PARAMETER :: B1RdtFxi = 193 + INTEGER(IntKi), PARAMETER :: B1RdtFyi = 194 + INTEGER(IntKi), PARAMETER :: B1RdtFzi = 195 + INTEGER(IntKi), PARAMETER :: B1RdtMxi = 196 + INTEGER(IntKi), PARAMETER :: B1RdtMyi = 197 + INTEGER(IntKi), PARAMETER :: B1RdtMzi = 198 + INTEGER(IntKi), PARAMETER :: B2AddFxi = 199 + INTEGER(IntKi), PARAMETER :: B2AddFyi = 200 + INTEGER(IntKi), PARAMETER :: B2AddFzi = 201 + INTEGER(IntKi), PARAMETER :: B2AddMxi = 202 + INTEGER(IntKi), PARAMETER :: B2AddMyi = 203 + INTEGER(IntKi), PARAMETER :: B2AddMzi = 204 + INTEGER(IntKi), PARAMETER :: B2WvsF1xi = 205 + INTEGER(IntKi), PARAMETER :: B2WvsF1yi = 206 + INTEGER(IntKi), PARAMETER :: B2WvsF1zi = 207 + INTEGER(IntKi), PARAMETER :: B2WvsM1xi = 208 + INTEGER(IntKi), PARAMETER :: B2WvsM1yi = 209 + INTEGER(IntKi), PARAMETER :: B2WvsM1zi = 210 + INTEGER(IntKi), PARAMETER :: B2WvsFxi = 211 + INTEGER(IntKi), PARAMETER :: B2WvsFyi = 212 + INTEGER(IntKi), PARAMETER :: B2WvsFzi = 213 + INTEGER(IntKi), PARAMETER :: B2WvsMxi = 214 + INTEGER(IntKi), PARAMETER :: B2WvsMyi = 215 + INTEGER(IntKi), PARAMETER :: B2WvsMzi = 216 + INTEGER(IntKi), PARAMETER :: B2HdSFxi = 217 + INTEGER(IntKi), PARAMETER :: B2HdSFyi = 218 + INTEGER(IntKi), PARAMETER :: B2HdSFzi = 219 + INTEGER(IntKi), PARAMETER :: B2HdSMxi = 220 + INTEGER(IntKi), PARAMETER :: B2HdSMyi = 221 + INTEGER(IntKi), PARAMETER :: B2HdSMzi = 222 + INTEGER(IntKi), PARAMETER :: B2RdtFxi = 223 + INTEGER(IntKi), PARAMETER :: B2RdtFyi = 224 + INTEGER(IntKi), PARAMETER :: B2RdtFzi = 225 + INTEGER(IntKi), PARAMETER :: B2RdtMxi = 226 + INTEGER(IntKi), PARAMETER :: B2RdtMyi = 227 + INTEGER(IntKi), PARAMETER :: B2RdtMzi = 228 + INTEGER(IntKi), PARAMETER :: B3AddFxi = 229 + INTEGER(IntKi), PARAMETER :: B3AddFyi = 230 + INTEGER(IntKi), PARAMETER :: B3AddFzi = 231 + INTEGER(IntKi), PARAMETER :: B3AddMxi = 232 + INTEGER(IntKi), PARAMETER :: B3AddMyi = 233 + INTEGER(IntKi), PARAMETER :: B3AddMzi = 234 + INTEGER(IntKi), PARAMETER :: B3WvsF1xi = 235 + INTEGER(IntKi), PARAMETER :: B3WvsF1yi = 236 + INTEGER(IntKi), PARAMETER :: B3WvsF1zi = 237 + INTEGER(IntKi), PARAMETER :: B3WvsM1xi = 238 + INTEGER(IntKi), PARAMETER :: B3WvsM1yi = 239 + INTEGER(IntKi), PARAMETER :: B3WvsM1zi = 240 + INTEGER(IntKi), PARAMETER :: B3WvsFxi = 241 + INTEGER(IntKi), PARAMETER :: B3WvsFyi = 242 + INTEGER(IntKi), PARAMETER :: B3WvsFzi = 243 + INTEGER(IntKi), PARAMETER :: B3WvsMxi = 244 + INTEGER(IntKi), PARAMETER :: B3WvsMyi = 245 + INTEGER(IntKi), PARAMETER :: B3WvsMzi = 246 + INTEGER(IntKi), PARAMETER :: B3HdSFxi = 247 + INTEGER(IntKi), PARAMETER :: B3HdSFyi = 248 + INTEGER(IntKi), PARAMETER :: B3HdSFzi = 249 + INTEGER(IntKi), PARAMETER :: B3HdSMxi = 250 + INTEGER(IntKi), PARAMETER :: B3HdSMyi = 251 + INTEGER(IntKi), PARAMETER :: B3HdSMzi = 252 + INTEGER(IntKi), PARAMETER :: B3RdtFxi = 253 + INTEGER(IntKi), PARAMETER :: B3RdtFyi = 254 + INTEGER(IntKi), PARAMETER :: B3RdtFzi = 255 + INTEGER(IntKi), PARAMETER :: B3RdtMxi = 256 + INTEGER(IntKi), PARAMETER :: B3RdtMyi = 257 + INTEGER(IntKi), PARAMETER :: B3RdtMzi = 258 + INTEGER(IntKi), PARAMETER :: B4AddFxi = 259 + INTEGER(IntKi), PARAMETER :: B4AddFyi = 260 + INTEGER(IntKi), PARAMETER :: B4AddFzi = 261 + INTEGER(IntKi), PARAMETER :: B4AddMxi = 262 + INTEGER(IntKi), PARAMETER :: B4AddMyi = 263 + INTEGER(IntKi), PARAMETER :: B4AddMzi = 264 + INTEGER(IntKi), PARAMETER :: B4WvsF1xi = 265 + INTEGER(IntKi), PARAMETER :: B4WvsF1yi = 266 + INTEGER(IntKi), PARAMETER :: B4WvsF1zi = 267 + INTEGER(IntKi), PARAMETER :: B4WvsM1xi = 268 + INTEGER(IntKi), PARAMETER :: B4WvsM1yi = 269 + INTEGER(IntKi), PARAMETER :: B4WvsM1zi = 270 + INTEGER(IntKi), PARAMETER :: B4WvsFxi = 271 + INTEGER(IntKi), PARAMETER :: B4WvsFyi = 272 + INTEGER(IntKi), PARAMETER :: B4WvsFzi = 273 + INTEGER(IntKi), PARAMETER :: B4WvsMxi = 274 + INTEGER(IntKi), PARAMETER :: B4WvsMyi = 275 + INTEGER(IntKi), PARAMETER :: B4WvsMzi = 276 + INTEGER(IntKi), PARAMETER :: B4HdSFxi = 277 + INTEGER(IntKi), PARAMETER :: B4HdSFyi = 278 + INTEGER(IntKi), PARAMETER :: B4HdSFzi = 279 + INTEGER(IntKi), PARAMETER :: B4HdSMxi = 280 + INTEGER(IntKi), PARAMETER :: B4HdSMyi = 281 + INTEGER(IntKi), PARAMETER :: B4HdSMzi = 282 + INTEGER(IntKi), PARAMETER :: B4RdtFxi = 283 + INTEGER(IntKi), PARAMETER :: B4RdtFyi = 284 + INTEGER(IntKi), PARAMETER :: B4RdtFzi = 285 + INTEGER(IntKi), PARAMETER :: B4RdtMxi = 286 + INTEGER(IntKi), PARAMETER :: B4RdtMyi = 287 + INTEGER(IntKi), PARAMETER :: B4RdtMzi = 288 + INTEGER(IntKi), PARAMETER :: B5AddFxi = 289 + INTEGER(IntKi), PARAMETER :: B5AddFyi = 290 + INTEGER(IntKi), PARAMETER :: B5AddFzi = 291 + INTEGER(IntKi), PARAMETER :: B5AddMxi = 292 + INTEGER(IntKi), PARAMETER :: B5AddMyi = 293 + INTEGER(IntKi), PARAMETER :: B5AddMzi = 294 + INTEGER(IntKi), PARAMETER :: B5WvsF1xi = 295 + INTEGER(IntKi), PARAMETER :: B5WvsF1yi = 296 + INTEGER(IntKi), PARAMETER :: B5WvsF1zi = 297 + INTEGER(IntKi), PARAMETER :: B5WvsM1xi = 298 + INTEGER(IntKi), PARAMETER :: B5WvsM1yi = 299 + INTEGER(IntKi), PARAMETER :: B5WvsM1zi = 300 + INTEGER(IntKi), PARAMETER :: B5WvsFxi = 301 + INTEGER(IntKi), PARAMETER :: B5WvsFyi = 302 + INTEGER(IntKi), PARAMETER :: B5WvsFzi = 303 + INTEGER(IntKi), PARAMETER :: B5WvsMxi = 304 + INTEGER(IntKi), PARAMETER :: B5WvsMyi = 305 + INTEGER(IntKi), PARAMETER :: B5WvsMzi = 306 + INTEGER(IntKi), PARAMETER :: B5HdSFxi = 307 + INTEGER(IntKi), PARAMETER :: B5HdSFyi = 308 + INTEGER(IntKi), PARAMETER :: B5HdSFzi = 309 + INTEGER(IntKi), PARAMETER :: B5HdSMxi = 310 + INTEGER(IntKi), PARAMETER :: B5HdSMyi = 311 + INTEGER(IntKi), PARAMETER :: B5HdSMzi = 312 + INTEGER(IntKi), PARAMETER :: B5RdtFxi = 313 + INTEGER(IntKi), PARAMETER :: B5RdtFyi = 314 + INTEGER(IntKi), PARAMETER :: B5RdtFzi = 315 + INTEGER(IntKi), PARAMETER :: B5RdtMxi = 316 + INTEGER(IntKi), PARAMETER :: B5RdtMyi = 317 + INTEGER(IntKi), PARAMETER :: B5RdtMzi = 318 + INTEGER(IntKi), PARAMETER :: B6AddFxi = 319 + INTEGER(IntKi), PARAMETER :: B6AddFyi = 320 + INTEGER(IntKi), PARAMETER :: B6AddFzi = 321 + INTEGER(IntKi), PARAMETER :: B6AddMxi = 322 + INTEGER(IntKi), PARAMETER :: B6AddMyi = 323 + INTEGER(IntKi), PARAMETER :: B6AddMzi = 324 + INTEGER(IntKi), PARAMETER :: B6WvsF1xi = 325 + INTEGER(IntKi), PARAMETER :: B6WvsF1yi = 326 + INTEGER(IntKi), PARAMETER :: B6WvsF1zi = 327 + INTEGER(IntKi), PARAMETER :: B6WvsM1xi = 328 + INTEGER(IntKi), PARAMETER :: B6WvsM1yi = 329 + INTEGER(IntKi), PARAMETER :: B6WvsM1zi = 330 + INTEGER(IntKi), PARAMETER :: B6WvsFxi = 331 + INTEGER(IntKi), PARAMETER :: B6WvsFyi = 332 + INTEGER(IntKi), PARAMETER :: B6WvsFzi = 333 + INTEGER(IntKi), PARAMETER :: B6WvsMxi = 334 + INTEGER(IntKi), PARAMETER :: B6WvsMyi = 335 + INTEGER(IntKi), PARAMETER :: B6WvsMzi = 336 + INTEGER(IntKi), PARAMETER :: B6HdSFxi = 337 + INTEGER(IntKi), PARAMETER :: B6HdSFyi = 338 + INTEGER(IntKi), PARAMETER :: B6HdSFzi = 339 + INTEGER(IntKi), PARAMETER :: B6HdSMxi = 340 + INTEGER(IntKi), PARAMETER :: B6HdSMyi = 341 + INTEGER(IntKi), PARAMETER :: B6HdSMzi = 342 + INTEGER(IntKi), PARAMETER :: B6RdtFxi = 343 + INTEGER(IntKi), PARAMETER :: B6RdtFyi = 344 + INTEGER(IntKi), PARAMETER :: B6RdtFzi = 345 + INTEGER(IntKi), PARAMETER :: B6RdtMxi = 346 + INTEGER(IntKi), PARAMETER :: B6RdtMyi = 347 + INTEGER(IntKi), PARAMETER :: B6RdtMzi = 348 + INTEGER(IntKi), PARAMETER :: B7AddFxi = 349 + INTEGER(IntKi), PARAMETER :: B7AddFyi = 350 + INTEGER(IntKi), PARAMETER :: B7AddFzi = 351 + INTEGER(IntKi), PARAMETER :: B7AddMxi = 352 + INTEGER(IntKi), PARAMETER :: B7AddMyi = 353 + INTEGER(IntKi), PARAMETER :: B7AddMzi = 354 + INTEGER(IntKi), PARAMETER :: B7WvsF1xi = 355 + INTEGER(IntKi), PARAMETER :: B7WvsF1yi = 356 + INTEGER(IntKi), PARAMETER :: B7WvsF1zi = 357 + INTEGER(IntKi), PARAMETER :: B7WvsM1xi = 358 + INTEGER(IntKi), PARAMETER :: B7WvsM1yi = 359 + INTEGER(IntKi), PARAMETER :: B7WvsM1zi = 360 + INTEGER(IntKi), PARAMETER :: B7WvsFxi = 361 + INTEGER(IntKi), PARAMETER :: B7WvsFyi = 362 + INTEGER(IntKi), PARAMETER :: B7WvsFzi = 363 + INTEGER(IntKi), PARAMETER :: B7WvsMxi = 364 + INTEGER(IntKi), PARAMETER :: B7WvsMyi = 365 + INTEGER(IntKi), PARAMETER :: B7WvsMzi = 366 + INTEGER(IntKi), PARAMETER :: B7HdSFxi = 367 + INTEGER(IntKi), PARAMETER :: B7HdSFyi = 368 + INTEGER(IntKi), PARAMETER :: B7HdSFzi = 369 + INTEGER(IntKi), PARAMETER :: B7HdSMxi = 370 + INTEGER(IntKi), PARAMETER :: B7HdSMyi = 371 + INTEGER(IntKi), PARAMETER :: B7HdSMzi = 372 + INTEGER(IntKi), PARAMETER :: B7RdtFxi = 373 + INTEGER(IntKi), PARAMETER :: B7RdtFyi = 374 + INTEGER(IntKi), PARAMETER :: B7RdtFzi = 375 + INTEGER(IntKi), PARAMETER :: B7RdtMxi = 376 + INTEGER(IntKi), PARAMETER :: B7RdtMyi = 377 + INTEGER(IntKi), PARAMETER :: B7RdtMzi = 378 + INTEGER(IntKi), PARAMETER :: B8AddFxi = 379 + INTEGER(IntKi), PARAMETER :: B8AddFyi = 380 + INTEGER(IntKi), PARAMETER :: B8AddFzi = 381 + INTEGER(IntKi), PARAMETER :: B8AddMxi = 382 + INTEGER(IntKi), PARAMETER :: B8AddMyi = 383 + INTEGER(IntKi), PARAMETER :: B8AddMzi = 384 + INTEGER(IntKi), PARAMETER :: B8WvsF1xi = 385 + INTEGER(IntKi), PARAMETER :: B8WvsF1yi = 386 + INTEGER(IntKi), PARAMETER :: B8WvsF1zi = 387 + INTEGER(IntKi), PARAMETER :: B8WvsM1xi = 388 + INTEGER(IntKi), PARAMETER :: B8WvsM1yi = 389 + INTEGER(IntKi), PARAMETER :: B8WvsM1zi = 390 + INTEGER(IntKi), PARAMETER :: B8WvsFxi = 391 + INTEGER(IntKi), PARAMETER :: B8WvsFyi = 392 + INTEGER(IntKi), PARAMETER :: B8WvsFzi = 393 + INTEGER(IntKi), PARAMETER :: B8WvsMxi = 394 + INTEGER(IntKi), PARAMETER :: B8WvsMyi = 395 + INTEGER(IntKi), PARAMETER :: B8WvsMzi = 396 + INTEGER(IntKi), PARAMETER :: B8HdSFxi = 397 + INTEGER(IntKi), PARAMETER :: B8HdSFyi = 398 + INTEGER(IntKi), PARAMETER :: B8HdSFzi = 399 + INTEGER(IntKi), PARAMETER :: B8HdSMxi = 400 + INTEGER(IntKi), PARAMETER :: B8HdSMyi = 401 + INTEGER(IntKi), PARAMETER :: B8HdSMzi = 402 + INTEGER(IntKi), PARAMETER :: B8RdtFxi = 403 + INTEGER(IntKi), PARAMETER :: B8RdtFyi = 404 + INTEGER(IntKi), PARAMETER :: B8RdtFzi = 405 + INTEGER(IntKi), PARAMETER :: B8RdtMxi = 406 + INTEGER(IntKi), PARAMETER :: B8RdtMyi = 407 + INTEGER(IntKi), PARAMETER :: B8RdtMzi = 408 + INTEGER(IntKi), PARAMETER :: B9AddFxi = 409 + INTEGER(IntKi), PARAMETER :: B9AddFyi = 410 + INTEGER(IntKi), PARAMETER :: B9AddFzi = 411 + INTEGER(IntKi), PARAMETER :: B9AddMxi = 412 + INTEGER(IntKi), PARAMETER :: B9AddMyi = 413 + INTEGER(IntKi), PARAMETER :: B9AddMzi = 414 + INTEGER(IntKi), PARAMETER :: B9WvsF1xi = 415 + INTEGER(IntKi), PARAMETER :: B9WvsF1yi = 416 + INTEGER(IntKi), PARAMETER :: B9WvsF1zi = 417 + INTEGER(IntKi), PARAMETER :: B9WvsM1xi = 418 + INTEGER(IntKi), PARAMETER :: B9WvsM1yi = 419 + INTEGER(IntKi), PARAMETER :: B9WvsM1zi = 420 + INTEGER(IntKi), PARAMETER :: B9WvsFxi = 421 + INTEGER(IntKi), PARAMETER :: B9WvsFyi = 422 + INTEGER(IntKi), PARAMETER :: B9WvsFzi = 423 + INTEGER(IntKi), PARAMETER :: B9WvsMxi = 424 + INTEGER(IntKi), PARAMETER :: B9WvsMyi = 425 + INTEGER(IntKi), PARAMETER :: B9WvsMzi = 426 + INTEGER(IntKi), PARAMETER :: B9HdSFxi = 427 + INTEGER(IntKi), PARAMETER :: B9HdSFyi = 428 + INTEGER(IntKi), PARAMETER :: B9HdSFzi = 429 + INTEGER(IntKi), PARAMETER :: B9HdSMxi = 430 + INTEGER(IntKi), PARAMETER :: B9HdSMyi = 431 + INTEGER(IntKi), PARAMETER :: B9HdSMzi = 432 + INTEGER(IntKi), PARAMETER :: B9RdtFxi = 433 + INTEGER(IntKi), PARAMETER :: B9RdtFyi = 434 + INTEGER(IntKi), PARAMETER :: B9RdtFzi = 435 + INTEGER(IntKi), PARAMETER :: B9RdtMxi = 436 + INTEGER(IntKi), PARAMETER :: B9RdtMyi = 437 + INTEGER(IntKi), PARAMETER :: B9RdtMzi = 438 + + + ! Wave Elevations: + + INTEGER(IntKi), PARAMETER :: Wave1Elev = 439 + INTEGER(IntKi), PARAMETER :: Wave2Elev = 440 + INTEGER(IntKi), PARAMETER :: Wave3Elev = 441 + INTEGER(IntKi), PARAMETER :: Wave4Elev = 442 + INTEGER(IntKi), PARAMETER :: Wave5Elev = 443 + INTEGER(IntKi), PARAMETER :: Wave6Elev = 444 + INTEGER(IntKi), PARAMETER :: Wave7Elev = 445 + INTEGER(IntKi), PARAMETER :: Wave8Elev = 446 + INTEGER(IntKi), PARAMETER :: Wave9Elev = 447 + INTEGER(IntKi), PARAMETER :: Wave1Elv1 = 448 + INTEGER(IntKi), PARAMETER :: Wave2Elv1 = 449 + INTEGER(IntKi), PARAMETER :: Wave3Elv1 = 450 + INTEGER(IntKi), PARAMETER :: Wave4Elv1 = 451 + INTEGER(IntKi), PARAMETER :: Wave5Elv1 = 452 + INTEGER(IntKi), PARAMETER :: Wave6Elv1 = 453 + INTEGER(IntKi), PARAMETER :: Wave7Elv1 = 454 + INTEGER(IntKi), PARAMETER :: Wave8Elv1 = 455 + INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 456 + + + +!End of code generated by Matlab script +! =================================================================================================== + + + + REAL(ReKi) :: AllOuts(MaxHDOutputs) ! Array of all possible outputs + INTEGER, PARAMETER :: FHydro(6) = (/HydroFxi,HydroFyi,HydroFzi,HydroMxi,HydroMyi,HydroMzi/) - INTEGER, PARAMETER :: FAdd(6) = (/AddFxi,AddFyi,AddFzi,AddMxi,AddMyi,AddMzi/) - INTEGER, PARAMETER :: FWavesTot(6) = (/WavesFxi,WavesFyi,WavesFzi,WavesMxi,WavesMyi,WavesMzi/) - INTEGER, PARAMETER :: WRPMotions(6) = (/WRPSurge,WRPSway,WRPHeave,WRPRoll,WRPPitch,WRPYaw/) - INTEGER, PARAMETER :: WRPVel(6) = (/WRPTVxi,WRPTVyi,WRPTVzi,WRPRVxi,WRPRVyi,WRPRVzi/) - INTEGER, PARAMETER :: WRPAcc(6) = (/WRPTAxi,WRPTAyi,WRPTAzi,WRPRAxi,WRPRAyi,WRPRAzi/) + + INTEGER, PARAMETER :: FAdd(6,9) = transpose(reshape((/B1AddFxi,B2AddFxi,B3AddFxi,B4AddFxi,B5AddFxi,B6AddFxi,B7AddFxi,B8AddFxi,B9AddFxi, & + B1AddFyi,B2AddFyi,B3AddFyi,B4AddFyi,B5AddFyi,B6AddFyi,B7AddFyi,B8AddFyi,B9AddFyi, & + B1AddFzi,B2AddFzi,B3AddFzi,B4AddFzi,B5AddFzi,B6AddFzi,B7AddFzi,B8AddFzi,B9AddFzi, & + B1AddMxi,B2AddMxi,B3AddMxi,B4AddMxi,B5AddMxi,B6AddMxi,B7AddMxi,B8AddMxi,B9AddMxi, & + B1AddMyi,B2AddMyi,B3AddMyi,B4AddMyi,B5AddMyi,B6AddMyi,B7AddMyi,B8AddMyi,B9AddMyi, & + B1AddMzi,B2AddMzi,B3AddMzi,B4AddMzi,B5AddMzi,B6AddMzi,B7AddMzi,B8AddMzi,B9AddMzi/), & + (/9,6/))) + INTEGER, PARAMETER :: FWaves1(6,9) = transpose(reshape((/B1WvsF1xi,B2WvsF1xi,B3WvsF1xi,B4WvsF1xi,B5WvsF1xi,B6WvsF1xi,B7WvsF1xi,B8WvsF1xi,B9WvsF1xi, & + B1WvsF1yi,B2WvsF1yi,B3WvsF1yi,B4WvsF1yi,B5WvsF1yi,B6WvsF1yi,B7WvsF1yi,B8WvsF1yi,B9WvsF1yi, & + B1WvsF1zi,B2WvsF1zi,B3WvsF1zi,B4WvsF1zi,B5WvsF1zi,B6WvsF1zi,B7WvsF1zi,B8WvsF1zi,B9WvsF1zi, & + B1WvsM1xi,B2WvsM1xi,B3WvsM1xi,B4WvsM1xi,B5WvsM1xi,B6WvsM1xi,B7WvsM1xi,B8WvsM1xi,B9WvsM1xi, & + B1WvsM1yi,B2WvsM1yi,B3WvsM1yi,B4WvsM1yi,B5WvsM1yi,B6WvsM1yi,B7WvsM1yi,B8WvsM1yi,B9WvsM1yi, & + B1WvsM1zi,B2WvsM1zi,B3WvsM1zi,B4WvsM1zi,B5WvsM1zi,B6WvsM1zi,B7WvsM1zi,B8WvsM1zi,B9WvsM1zi/), & + (/9,6/))) + INTEGER, PARAMETER :: FWavesTot(6,9)= transpose(reshape((/B1WvsFxi,B2WvsFxi,B3WvsFxi,B4WvsFxi,B5WvsFxi,B6WvsFxi,B7WvsFxi,B8WvsFxi,B9WvsFxi, & + B1WvsFyi,B2WvsFyi,B3WvsFyi,B4WvsFyi,B5WvsFyi,B6WvsFyi,B7WvsFyi,B8WvsFyi,B9WvsFyi, & + B1WvsFzi,B2WvsFzi,B3WvsFzi,B4WvsFzi,B5WvsFzi,B6WvsFzi,B7WvsFzi,B8WvsFzi,B9WvsFzi, & + B1WvsMxi,B2WvsMxi,B3WvsMxi,B4WvsMxi,B5WvsMxi,B6WvsMxi,B7WvsMxi,B8WvsMxi,B9WvsMxi, & + B1WvsMyi,B2WvsMyi,B3WvsMyi,B4WvsMyi,B5WvsMyi,B6WvsMyi,B7WvsMyi,B8WvsMyi,B9WvsMyi, & + B1WvsMzi,B2WvsMzi,B3WvsMzi,B4WvsMzi,B5WvsMzi,B6WvsMzi,B7WvsMzi,B8WvsMzi,B9WvsMzi/), & + (/9,6/))) + INTEGER, PARAMETER :: FHdrSttc(6,9) = transpose(reshape((/B1HdSFxi,B2HdSFxi,B3HdSFxi,B4HdSFxi,B5HdSFxi,B6HdSFxi,B7HdSFxi,B8HdSFxi,B9HdSFxi, & + B1HdSFyi,B2HdSFyi,B3HdSFyi,B4HdSFyi,B5HdSFyi,B6HdSFyi,B7HdSFyi,B8HdSFyi,B9HdSFyi, & + B1HdSFzi,B2HdSFzi,B3HdSFzi,B4HdSFzi,B5HdSFzi,B6HdSFzi,B7HdSFzi,B8HdSFzi,B9HdSFzi, & + B1HdSMxi,B2HdSMxi,B3HdSMxi,B4HdSMxi,B5HdSMxi,B6HdSMxi,B7HdSMxi,B8HdSMxi,B9HdSMxi, & + B1HdSMyi,B2HdSMyi,B3HdSMyi,B4HdSMyi,B5HdSMyi,B6HdSMyi,B7HdSMyi,B8HdSMyi,B9HdSMyi, & + B1HdSMzi,B2HdSMzi,B3HdSMzi,B4HdSMzi,B5HdSMzi,B6HdSMzi,B7HdSMzi,B8HdSMzi,B9HdSMzi/), & + (/9,6/))) + INTEGER, PARAMETER :: FRdtn(6,9) = transpose(reshape((/B1RdtFxi,B2RdtFxi,B3RdtFxi,B4RdtFxi,B5RdtFxi,B6RdtFxi,B7RdtFxi,B8RdtFxi,B9RdtFxi, & + B1RdtFyi,B2RdtFyi,B3RdtFyi,B4RdtFyi,B5RdtFyi,B6RdtFyi,B7RdtFyi,B8RdtFyi,B9RdtFyi, & + B1RdtFzi,B2RdtFzi,B3RdtFzi,B4RdtFzi,B5RdtFzi,B6RdtFzi,B7RdtFzi,B8RdtFzi,B9RdtFzi, & + B1RdtMxi,B2RdtMxi,B3RdtMxi,B4RdtMxi,B5RdtMxi,B6RdtMxi,B7RdtMxi,B8RdtMxi,B9RdtMxi, & + B1RdtMyi,B2RdtMyi,B3RdtMyi,B4RdtMyi,B5RdtMyi,B6RdtMyi,B7RdtMyi,B8RdtMyi,B9RdtMyi, & + B1RdtMzi,B2RdtMzi,B3RdtMzi,B4RdtMzi,B5RdtMzi,B6RdtMzi,B7RdtMzi,B8RdtMzi,B9RdtMzi/), & + (/9,6/))) + + INTEGER, PARAMETER :: WBMotions(6,9) = transpose(reshape((/B1Surge,B2Surge,B3Surge,B4Surge,B5Surge,B6Surge,B7Surge,B8Surge,B9Surge, & + B1Sway ,B2Sway ,B3Sway ,B4Sway ,B5Sway ,B6Sway ,B7Sway ,B8Sway ,B9Sway , & + B1Heave,B2Heave,B3Heave,B4Heave,B5Heave,B6Heave,B7Heave,B8Heave,B9Heave, & + B1Roll ,B2Roll ,B3Roll ,B4Roll ,B5Roll ,B6Roll ,B7Roll ,B8Roll ,B9Roll , & + B1Pitch,B2Pitch,B3Pitch,B4Pitch,B5Pitch,B6Pitch,B7Pitch,B8Pitch,B9Pitch, & + B1Yaw ,B2Yaw ,B3Yaw ,B4Yaw ,B5Yaw ,B6Yaw ,B7Yaw ,B8Yaw ,B9Yaw /), & + (/9,6/))) + + INTEGER, PARAMETER :: WBVel(6,9) = transpose(reshape((/B1TVxi,B2TVxi,B3TVxi,B4TVxi,B5TVxi,B6TVxi,B7TVxi,B8TVxi,B9TVxi, & + B1TVyi,B2TVyi,B3TVyi,B4TVyi,B5TVyi,B6TVyi,B7TVyi,B8TVyi,B9TVyi, & + B1TVzi,B2TVzi,B3TVzi,B4TVzi,B5TVzi,B6TVzi,B7TVzi,B8TVzi,B9TVzi, & + B1RVxi,B2RVxi,B3RVxi,B4RVxi,B5RVxi,B6RVxi,B7RVxi,B8RVxi,B9RVxi, & + B1RVyi,B2RVyi,B3RVyi,B4RVyi,B5RVyi,B6RVyi,B7RVyi,B8RVyi,B9RVyi, & + B1RVzi,B2RVzi,B3RVzi,B4RVzi,B5RVzi,B6RVzi,B7RVzi,B8RVzi,B9RVzi/), & + (/9,6/))) + + INTEGER, PARAMETER :: WBAcc(6,9) = transpose(reshape((/B1TAxi,B2TAxi,B3TAxi,B4TAxi,B5TAxi,B6TAxi,B7TAxi,B8TAxi,B9TAxi, & + B1TAyi,B2TAyi,B3TAyi,B4TAyi,B5TAyi,B6TAyi,B7TAyi,B8TAyi,B9TAyi, & + B1TAzi,B2TAzi,B3TAzi,B4TAzi,B5TAzi,B6TAzi,B7TAzi,B8TAzi,B9TAzi, & + B1RAxi,B2RAxi,B3RAxi,B4RAxi,B5RAxi,B6RAxi,B7RAxi,B8RAxi,B9RAxi, & + B1RAyi,B2RAyi,B3RAyi,B4RAyi,B5RAyi,B6RAyi,B7RAyi,B8RAyi,B9RAyi, & + B1RAzi,B2RAzi,B3RAzi,B4RAzi,B5RAzi,B6RAzi,B7RAzi,B8RAzi,B9RAzi/), & + (/9,6/))) + INTEGER, PARAMETER :: WaveElevi(9) = (/Wave1Elev,Wave2Elev,Wave3Elev,Wave4Elev,Wave5Elev,Wave6Elev,Wave7Elev,Wave8Elev,Wave9Elev/) INTEGER, PARAMETER :: WaveElevi1(9) = (/Wave1Elv1,Wave2Elv1,Wave3Elv1,Wave4Elv1,Wave5Elv1,Wave6Elv1,Wave7Elv1,Wave8Elv1,Wave9Elv1/) - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(54) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "ADDFXI ","ADDFYI ","ADDFZI ","ADDMXI ","ADDMYI ","ADDMZI ", & - "HYDROFXI ","HYDROFYI ","HYDROFZI ","HYDROMXI ","HYDROMYI ","HYDROMZI ", & - "WAVE1ELEV","WAVE1ELV1", & - "WAVE2ELEV","WAVE2ELV1", & - "WAVE3ELEV","WAVE3ELV1", & - "WAVE4ELEV","WAVE4ELV1", & - "WAVE5ELEV","WAVE5ELV1", & - "WAVE6ELEV","WAVE6ELV1", & - "WAVE7ELEV","WAVE7ELV1", & - "WAVE8ELEV","WAVE8ELV1", & - "WAVE9ELEV","WAVE9ELV1", & - "WAVESFXI ","WAVESFYI ","WAVESFZI ","WAVESMXI ","WAVESMYI ","WAVESMZI ", & - "WRPHEAVE ","WRPPITCH ","WRPRAXI ","WRPRAYI ","WRPRAZI ","WRPROLL ", & - "WRPRVXI ","WRPRVYI ","WRPRVZI ","WRPSURGE ","WRPSWAY ","WRPTAXI ", & - "WRPTAYI ","WRPTAZI ","WRPTVXI ","WRPTVYI ","WRPTVZI ","WRPYAW "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(54) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - AddFxi , AddFyi , AddFzi , AddMxi , AddMyi , AddMzi , & - HydroFxi , HydroFyi , HydroFzi , HydroMxi , HydroMyi , HydroMzi , & - Wave1Elev , Wave1Elv1 , & - Wave2Elev , Wave2Elv1 , & - Wave3Elev , Wave3Elv1 , & - Wave4Elev , Wave4Elv1 , & - Wave5Elev , Wave5Elv1 , & - Wave6Elev , Wave6Elv1 , & - Wave7Elev , Wave7Elv1 , & - Wave8Elev , Wave8Elv1 , & - Wave9Elev , Wave9Elv1 , & - WavesFxi , WavesFyi , WavesFzi , WavesMxi , WavesMyi , WavesMzi , & - WRPHeave , WRPPitch , WRPRAxi , WRPRAyi , WRPRAzi , WRPRoll , & - WRPRVxi , WRPRVyi , WRPRVzi , WRPSurge , WRPSway , WRPTAxi , & - WRPTAyi , WRPTAzi , WRPTVxi , WRPTVyi , WRPTVzi , WRPYaw /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(54) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(rad) "/) - - - REAL(ReKi) :: AllOuts(MaxHDOutputs) ! Array of all possible outputs - + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(456) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "B1ADDFXI ","B1ADDFYI ","B1ADDFZI ","B1ADDMXI ","B1ADDMYI ","B1ADDMZI ","B1HDSFXI ", & + "B1HDSFYI ","B1HDSFZI ","B1HDSMXI ","B1HDSMYI ","B1HDSMZI ","B1HEAVE ","B1PITCH ", & + "B1RAXI ","B1RAYI ","B1RAZI ","B1RDTFXI ","B1RDTFYI ","B1RDTFZI ","B1RDTMXI ", & + "B1RDTMYI ","B1RDTMZI ","B1ROLL ","B1RVXI ","B1RVYI ","B1RVZI ","B1SURGE ", & + "B1SWAY ","B1TAXI ","B1TAYI ","B1TAZI ","B1TVXI ","B1TVYI ","B1TVZI ", & + "B1WVSF1XI","B1WVSF1YI","B1WVSF1ZI","B1WVSFXI ","B1WVSFYI ","B1WVSFZI ","B1WVSM1XI", & + "B1WVSM1YI","B1WVSM1ZI","B1WVSMXI ","B1WVSMYI ","B1WVSMZI ","B1YAW ","B2ADDFXI ", & + "B2ADDFYI ","B2ADDFZI ","B2ADDMXI ","B2ADDMYI ","B2ADDMZI ","B2HDSFXI ","B2HDSFYI ", & + "B2HDSFZI ","B2HDSMXI ","B2HDSMYI ","B2HDSMZI ","B2HEAVE ","B2PITCH ","B2RAXI ", & + "B2RAYI ","B2RAZI ","B2RDTFXI ","B2RDTFYI ","B2RDTFZI ","B2RDTMXI ","B2RDTMYI ", & + "B2RDTMZI ","B2ROLL ","B2RVXI ","B2RVYI ","B2RVZI ","B2SURGE ","B2SWAY ", & + "B2TAXI ","B2TAYI ","B2TAZI ","B2TVXI ","B2TVYI ","B2TVZI ","B2WVSF1XI", & + "B2WVSF1YI","B2WVSF1ZI","B2WVSFXI ","B2WVSFYI ","B2WVSFZI ","B2WVSM1XI","B2WVSM1YI", & + "B2WVSM1ZI","B2WVSMXI ","B2WVSMYI ","B2WVSMZI ","B2YAW ","B3ADDFXI ","B3ADDFYI ", & + "B3ADDFZI ","B3ADDMXI ","B3ADDMYI ","B3ADDMZI ","B3HDSFXI ","B3HDSFYI ","B3HDSFZI ", & + "B3HDSMXI ","B3HDSMYI ","B3HDSMZI ","B3HEAVE ","B3PITCH ","B3RAXI ","B3RAYI ", & + "B3RAZI ","B3RDTFXI ","B3RDTFYI ","B3RDTFZI ","B3RDTMXI ","B3RDTMYI ","B3RDTMZI ", & + "B3ROLL ","B3RVXI ","B3RVYI ","B3RVZI ","B3SURGE ","B3SWAY ","B3TAXI ", & + "B3TAYI ","B3TAZI ","B3TVXI ","B3TVYI ","B3TVZI ","B3WVSF1XI","B3WVSF1YI", & + "B3WVSF1ZI","B3WVSFXI ","B3WVSFYI ","B3WVSFZI ","B3WVSM1XI","B3WVSM1YI","B3WVSM1ZI", & + "B3WVSMXI ","B3WVSMYI ","B3WVSMZI ","B3YAW ","B4ADDFXI ","B4ADDFYI ","B4ADDFZI ", & + "B4ADDMXI ","B4ADDMYI ","B4ADDMZI ","B4HDSFXI ","B4HDSFYI ","B4HDSFZI ","B4HDSMXI ", & + "B4HDSMYI ","B4HDSMZI ","B4HEAVE ","B4PITCH ","B4RAXI ","B4RAYI ","B4RAZI ", & + "B4RDTFXI ","B4RDTFYI ","B4RDTFZI ","B4RDTMXI ","B4RDTMYI ","B4RDTMZI ","B4ROLL ", & + "B4RVXI ","B4RVYI ","B4RVZI ","B4SURGE ","B4SWAY ","B4TAXI ","B4TAYI ", & + "B4TAZI ","B4TVXI ","B4TVYI ","B4TVZI ","B4WVSF1XI","B4WVSF1YI","B4WVSF1ZI", & + "B4WVSFXI ","B4WVSFYI ","B4WVSFZI ","B4WVSM1XI","B4WVSM1YI","B4WVSM1ZI","B4WVSMXI ", & + "B4WVSMYI ","B4WVSMZI ","B4YAW ","B5ADDFXI ","B5ADDFYI ","B5ADDFZI ","B5ADDMXI ", & + "B5ADDMYI ","B5ADDMZI ","B5HDSFXI ","B5HDSFYI ","B5HDSFZI ","B5HDSMXI ","B5HDSMYI ", & + "B5HDSMZI ","B5HEAVE ","B5PITCH ","B5RAXI ","B5RAYI ","B5RAZI ","B5RDTFXI ", & + "B5RDTFYI ","B5RDTFZI ","B5RDTMXI ","B5RDTMYI ","B5RDTMZI ","B5ROLL ","B5RVXI ", & + "B5RVYI ","B5RVZI ","B5SURGE ","B5SWAY ","B5TAXI ","B5TAYI ","B5TAZI ", & + "B5TVXI ","B5TVYI ","B5TVZI ","B5WVSF1XI","B5WVSF1YI","B5WVSF1ZI","B5WVSFXI ", & + "B5WVSFYI ","B5WVSFZI ","B5WVSM1XI","B5WVSM1YI","B5WVSM1ZI","B5WVSMXI ","B5WVSMYI ", & + "B5WVSMZI ","B5YAW ","B6ADDFXI ","B6ADDFYI ","B6ADDFZI ","B6ADDMXI ","B6ADDMYI ", & + "B6ADDMZI ","B6HDSFXI ","B6HDSFYI ","B6HDSFZI ","B6HDSMXI ","B6HDSMYI ","B6HDSMZI ", & + "B6HEAVE ","B6PITCH ","B6RAXI ","B6RAYI ","B6RAZI ","B6RDTFXI ","B6RDTFYI ", & + "B6RDTFZI ","B6RDTMXI ","B6RDTMYI ","B6RDTMZI ","B6ROLL ","B6RVXI ","B6RVYI ", & + "B6RVZI ","B6SURGE ","B6SWAY ","B6TAXI ","B6TAYI ","B6TAZI ","B6TVXI ", & + "B6TVYI ","B6TVZI ","B6WVSF1XI","B6WVSF1YI","B6WVSF1ZI","B6WVSFXI ","B6WVSFYI ", & + "B6WVSFZI ","B6WVSM1XI","B6WVSM1YI","B6WVSM1ZI","B6WVSMXI ","B6WVSMYI ","B6WVSMZI ", & + "B6YAW ","B7ADDFXI ","B7ADDFYI ","B7ADDFZI ","B7ADDMXI ","B7ADDMYI ","B7ADDMZI ", & + "B7HDSFXI ","B7HDSFYI ","B7HDSFZI ","B7HDSMXI ","B7HDSMYI ","B7HDSMZI ","B7HEAVE ", & + "B7PITCH ","B7RAXI ","B7RAYI ","B7RAZI ","B7RDTFXI ","B7RDTFYI ","B7RDTFZI ", & + "B7RDTMXI ","B7RDTMYI ","B7RDTMZI ","B7ROLL ","B7RVXI ","B7RVYI ","B7RVZI ", & + "B7SURGE ","B7SWAY ","B7TAXI ","B7TAYI ","B7TAZI ","B7TVXI ","B7TVYI ", & + "B7TVZI ","B7WVSF1XI","B7WVSF1YI","B7WVSF1ZI","B7WVSFXI ","B7WVSFYI ","B7WVSFZI ", & + "B7WVSM1XI","B7WVSM1YI","B7WVSM1ZI","B7WVSMXI ","B7WVSMYI ","B7WVSMZI ","B7YAW ", & + "B8ADDFXI ","B8ADDFYI ","B8ADDFZI ","B8ADDMXI ","B8ADDMYI ","B8ADDMZI ","B8HDSFXI ", & + "B8HDSFYI ","B8HDSFZI ","B8HDSMXI ","B8HDSMYI ","B8HDSMZI ","B8HEAVE ","B8PITCH ", & + "B8RAXI ","B8RAYI ","B8RAZI ","B8RDTFXI ","B8RDTFYI ","B8RDTFZI ","B8RDTMXI ", & + "B8RDTMYI ","B8RDTMZI ","B8ROLL ","B8RVXI ","B8RVYI ","B8RVZI ","B8SURGE ", & + "B8SWAY ","B8TAXI ","B8TAYI ","B8TAZI ","B8TVXI ","B8TVYI ","B8TVZI ", & + "B8WVSF1XI","B8WVSF1YI","B8WVSF1ZI","B8WVSFXI ","B8WVSFYI ","B8WVSFZI ","B8WVSM1XI", & + "B8WVSM1YI","B8WVSM1ZI","B8WVSMXI ","B8WVSMYI ","B8WVSMZI ","B8YAW ","B9ADDFXI ", & + "B9ADDFYI ","B9ADDFZI ","B9ADDMXI ","B9ADDMYI ","B9ADDMZI ","B9HDSFXI ","B9HDSFYI ", & + "B9HDSFZI ","B9HDSMXI ","B9HDSMYI ","B9HDSMZI ","B9HEAVE ","B9PITCH ","B9RAXI ", & + "B9RAYI ","B9RAZI ","B9RDTFXI ","B9RDTFYI ","B9RDTFZI ","B9RDTMXI ","B9RDTMYI ", & + "B9RDTMZI ","B9ROLL ","B9RVXI ","B9RVYI ","B9RVZI ","B9SURGE ","B9SWAY ", & + "B9TAXI ","B9TAYI ","B9TAZI ","B9TVXI ","B9TVYI ","B9TVZI ","B9WVSF1XI", & + "B9WVSF1YI","B9WVSF1ZI","B9WVSFXI ","B9WVSFYI ","B9WVSFZI ","B9WVSM1XI","B9WVSM1YI", & + "B9WVSM1ZI","B9WVSMXI ","B9WVSMYI ","B9WVSMZI ","B9YAW ","HYDROFXI ","HYDROFYI ", & + "HYDROFZI ","HYDROMXI ","HYDROMYI ","HYDROMZI ","WAVE1ELEV","WAVE1ELV1","WAVE2ELEV", & + "WAVE2ELV1","WAVE3ELEV","WAVE3ELV1","WAVE4ELEV","WAVE4ELV1","WAVE5ELEV","WAVE5ELV1", & + "WAVE6ELEV","WAVE6ELV1","WAVE7ELEV","WAVE7ELV1","WAVE8ELEV","WAVE8ELV1","WAVE9ELEV", & + "WAVE9ELV1"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(456) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + B1AddFxi , B1AddFyi , B1AddFzi , B1AddMxi , B1AddMyi , B1AddMzi , B1HdSFxi , & + B1HdSFyi , B1HdSFzi , B1HdSMxi , B1HdSMyi , B1HdSMzi , B1Heave , B1Pitch , & + B1RAxi , B1RAyi , B1RAzi , B1RdtFxi , B1RdtFyi , B1RdtFzi , B1RdtMxi , & + B1RdtMyi , B1RdtMzi , B1Roll , B1RVxi , B1RVyi , B1RVzi , B1Surge , & + B1Sway , B1TAxi , B1TAyi , B1TAzi , B1TVxi , B1TVyi , B1TVzi , & + B1WvsF1xi , B1WvsF1yi , B1WvsF1zi , B1WvsFxi , B1WvsFyi , B1WvsFzi , B1WvsM1xi , & + B1WvsM1yi , B1WvsM1zi , B1WvsMxi , B1WvsMyi , B1WvsMzi , B1Yaw , B2AddFxi , & + B2AddFyi , B2AddFzi , B2AddMxi , B2AddMyi , B2AddMzi , B2HdSFxi , B2HdSFyi , & + B2HdSFzi , B2HdSMxi , B2HdSMyi , B2HdSMzi , B2Heave , B2Pitch , B2RAxi , & + B2RAyi , B2RAzi , B2RdtFxi , B2RdtFyi , B2RdtFzi , B2RdtMxi , B2RdtMyi , & + B2RdtMzi , B2Roll , B2RVxi , B2RVyi , B2RVzi , B2Surge , B2Sway , & + B2TAxi , B2TAyi , B2TAzi , B2TVxi , B2TVyi , B2TVzi , B2WvsF1xi , & + B2WvsF1yi , B2WvsF1zi , B2WvsFxi , B2WvsFyi , B2WvsFzi , B2WvsM1xi , B2WvsM1yi , & + B2WvsM1zi , B2WvsMxi , B2WvsMyi , B2WvsMzi , B2Yaw , B3AddFxi , B3AddFyi , & + B3AddFzi , B3AddMxi , B3AddMyi , B3AddMzi , B3HdSFxi , B3HdSFyi , B3HdSFzi , & + B3HdSMxi , B3HdSMyi , B3HdSMzi , B3Heave , B3Pitch , B3RAxi , B3RAyi , & + B3RAzi , B3RdtFxi , B3RdtFyi , B3RdtFzi , B3RdtMxi , B3RdtMyi , B3RdtMzi , & + B3Roll , B3RVxi , B3RVyi , B3RVzi , B3Surge , B3Sway , B3TAxi , & + B3TAyi , B3TAzi , B3TVxi , B3TVyi , B3TVzi , B3WvsF1xi , B3WvsF1yi , & + B3WvsF1zi , B3WvsFxi , B3WvsFyi , B3WvsFzi , B3WvsM1xi , B3WvsM1yi , B3WvsM1zi , & + B3WvsMxi , B3WvsMyi , B3WvsMzi , B3Yaw , B4AddFxi , B4AddFyi , B4AddFzi , & + B4AddMxi , B4AddMyi , B4AddMzi , B4HdSFxi , B4HdSFyi , B4HdSFzi , B4HdSMxi , & + B4HdSMyi , B4HdSMzi , B4Heave , B4Pitch , B4RAxi , B4RAyi , B4RAzi , & + B4RdtFxi , B4RdtFyi , B4RdtFzi , B4RdtMxi , B4RdtMyi , B4RdtMzi , B4Roll , & + B4RVxi , B4RVyi , B4RVzi , B4Surge , B4Sway , B4TAxi , B4TAyi , & + B4TAzi , B4TVxi , B4TVyi , B4TVzi , B4WvsF1xi , B4WvsF1yi , B4WvsF1zi , & + B4WvsFxi , B4WvsFyi , B4WvsFzi , B4WvsM1xi , B4WvsM1yi , B4WvsM1zi , B4WvsMxi , & + B4WvsMyi , B4WvsMzi , B4Yaw , B5AddFxi , B5AddFyi , B5AddFzi , B5AddMxi , & + B5AddMyi , B5AddMzi , B5HdSFxi , B5HdSFyi , B5HdSFzi , B5HdSMxi , B5HdSMyi , & + B5HdSMzi , B5Heave , B5Pitch , B5RAxi , B5RAyi , B5RAzi , B5RdtFxi , & + B5RdtFyi , B5RdtFzi , B5RdtMxi , B5RdtMyi , B5RdtMzi , B5Roll , B5RVxi , & + B5RVyi , B5RVzi , B5Surge , B5Sway , B5TAxi , B5TAyi , B5TAzi , & + B5TVxi , B5TVyi , B5TVzi , B5WvsF1xi , B5WvsF1yi , B5WvsF1zi , B5WvsFxi , & + B5WvsFyi , B5WvsFzi , B5WvsM1xi , B5WvsM1yi , B5WvsM1zi , B5WvsMxi , B5WvsMyi , & + B5WvsMzi , B5Yaw , B6AddFxi , B6AddFyi , B6AddFzi , B6AddMxi , B6AddMyi , & + B6AddMzi , B6HdSFxi , B6HdSFyi , B6HdSFzi , B6HdSMxi , B6HdSMyi , B6HdSMzi , & + B6Heave , B6Pitch , B6RAxi , B6RAyi , B6RAzi , B6RdtFxi , B6RdtFyi , & + B6RdtFzi , B6RdtMxi , B6RdtMyi , B6RdtMzi , B6Roll , B6RVxi , B6RVyi , & + B6RVzi , B6Surge , B6Sway , B6TAxi , B6TAyi , B6TAzi , B6TVxi , & + B6TVyi , B6TVzi , B6WvsF1xi , B6WvsF1yi , B6WvsF1zi , B6WvsFxi , B6WvsFyi , & + B6WvsFzi , B6WvsM1xi , B6WvsM1yi , B6WvsM1zi , B6WvsMxi , B6WvsMyi , B6WvsMzi , & + B6Yaw , B7AddFxi , B7AddFyi , B7AddFzi , B7AddMxi , B7AddMyi , B7AddMzi , & + B7HdSFxi , B7HdSFyi , B7HdSFzi , B7HdSMxi , B7HdSMyi , B7HdSMzi , B7Heave , & + B7Pitch , B7RAxi , B7RAyi , B7RAzi , B7RdtFxi , B7RdtFyi , B7RdtFzi , & + B7RdtMxi , B7RdtMyi , B7RdtMzi , B7Roll , B7RVxi , B7RVyi , B7RVzi , & + B7Surge , B7Sway , B7TAxi , B7TAyi , B7TAzi , B7TVxi , B7TVyi , & + B7TVzi , B7WvsF1xi , B7WvsF1yi , B7WvsF1zi , B7WvsFxi , B7WvsFyi , B7WvsFzi , & + B7WvsM1xi , B7WvsM1yi , B7WvsM1zi , B7WvsMxi , B7WvsMyi , B7WvsMzi , B7Yaw , & + B8AddFxi , B8AddFyi , B8AddFzi , B8AddMxi , B8AddMyi , B8AddMzi , B8HdSFxi , & + B8HdSFyi , B8HdSFzi , B8HdSMxi , B8HdSMyi , B8HdSMzi , B8Heave , B8Pitch , & + B8RAxi , B8RAyi , B8RAzi , B8RdtFxi , B8RdtFyi , B8RdtFzi , B8RdtMxi , & + B8RdtMyi , B8RdtMzi , B8Roll , B8RVxi , B8RVyi , B8RVzi , B8Surge , & + B8Sway , B8TAxi , B8TAyi , B8TAzi , B8TVxi , B8TVyi , B8TVzi , & + B8WvsF1xi , B8WvsF1yi , B8WvsF1zi , B8WvsFxi , B8WvsFyi , B8WvsFzi , B8WvsM1xi , & + B8WvsM1yi , B8WvsM1zi , B8WvsMxi , B8WvsMyi , B8WvsMzi , B8Yaw , B9AddFxi , & + B9AddFyi , B9AddFzi , B9AddMxi , B9AddMyi , B9AddMzi , B9HdSFxi , B9HdSFyi , & + B9HdSFzi , B9HdSMxi , B9HdSMyi , B9HdSMzi , B9Heave , B9Pitch , B9RAxi , & + B9RAyi , B9RAzi , B9RdtFxi , B9RdtFyi , B9RdtFzi , B9RdtMxi , B9RdtMyi , & + B9RdtMzi , B9Roll , B9RVxi , B9RVyi , B9RVzi , B9Surge , B9Sway , & + B9TAxi , B9TAyi , B9TAzi , B9TVxi , B9TVyi , B9TVzi , B9WvsF1xi , & + B9WvsF1yi , B9WvsF1zi , B9WvsFxi , B9WvsFyi , B9WvsFzi , B9WvsM1xi , B9WvsM1yi , & + B9WvsM1zi , B9WvsMxi , B9WvsMyi , B9WvsMzi , B9Yaw , HydroFxi , HydroFyi , & + HydroFzi , HydroMxi , HydroMyi , HydroMzi , Wave1Elev , Wave1Elv1 , Wave2Elev , & + Wave2Elv1 , Wave3Elev , Wave3Elv1 , Wave4Elev , Wave4Elv1 , Wave5Elev , Wave5Elv1 , & + Wave6Elev , Wave6Elv1 , Wave7Elev , Wave7Elv1 , Wave8Elev , Wave8Elv1 , Wave9Elev , & + Wave9Elv1 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(456) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & + "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & + "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ", & + "(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ", & + "(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(rad) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ", & + "(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ", & + "(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & + "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) "/) + + ! ..... Public Subroutines ................................................................................................... PUBLIC :: HDOut_CloseSum @@ -190,7 +816,9 @@ MODULE HydroDyn_Output PUBLIC :: HDOUT_Init PUBLIC :: HDOut_WriteWvKinFiles -CONTAINS + CONTAINS + + !==================================================================================================== SUBROUTINE HDOut_CloseSum( UnSum, ErrStat, ErrMsg ) @@ -393,41 +1021,74 @@ SUBROUTINE HDOut_WriteWvKinFiles( Rootname, HD_Prog, NStepWave, NNodes, NWaveEle END SUBROUTINE HDOut_WriteWvKinFiles !==================================================================================================== -SUBROUTINE HDOut_MapOutputs( CurrentTime, y, NWaveElev, WaveElev, WaveElev1, F_Add, F_Waves, F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat, ErrMsg ) +SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, WaveElev1, F_Add, F_Waves, F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat, ErrMsg ) ! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput ! This is called by HydroDyn_CalcOutput() at each time step. !---------------------------------------------------------------------------------------------------- REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds + TYPE(HydroDyn_ParameterType), INTENT( IN ) :: p ! HydroDyn's parameter data TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! HydroDyn's output data + type(WAMIT_MiscVarType), intent( in ) :: m_WAMIT(:) ! WAMIT object's MiscVar data INTEGER, INTENT( IN ) :: NWaveElev ! Number of wave elevation locations to output REAL(ReKi), INTENT( IN ) :: WaveElev(:) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi), INTENT( IN ) :: WaveElev1(:) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) - REAL(ReKi), INTENT( IN ) :: F_Add(6) - REAL(ReKi), INTENT( IN ) :: F_Waves(6) - REAL(ReKi), INTENT( IN ) :: F_Hydro(6) - REAL(ReKi), INTENT( IN ) :: q(6) ! WRP translations and rotations - REAL(ReKi), INTENT( IN ) :: qdot(6) ! WRP translational and rotational velocities - REAL(ReKi), INTENT( IN ) :: qdotdot(6) ! WRP translational and rotational accelerations + REAL(ReKi), INTENT( IN ) :: F_Add(:) + REAL(ReKi), INTENT( IN ) :: F_Waves(:) + REAL(ReKi), INTENT( IN ) :: F_Hydro(:) ! All hydrodynamic loads integrated at (0,0,0) in the global coordinate system + REAL(ReKi), INTENT( IN ) :: q(:) ! WAMIT body translations and rotations + REAL(ReKi), INTENT( IN ) :: qdot(:) ! WAMIT body translational and rotational velocities + REAL(ReKi), INTENT( IN ) :: qdotdot(:) ! WAMIT body translational and rotational accelerations REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxHDOutputs) INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - INTEGER :: I + INTEGER :: I, iBody, startIndx, endIndx ErrStat = ErrID_None ErrMsg = "" - ! TODO: use y%mesh for the forces instead of individual parameters - - !AllOuts(Time) = REAL(CurrentTime,ReKi) - AllOuts(FAdd) = F_Add - AllOuts(FWavesTot) = F_Waves - AllOuts(FHydro) = F_Hydro - AllOuts(WRPMotions) = q - AllOuts(WRPVel) = qdot - AllOuts(WRPAcc) = qdotdot + + ! Need to use individual components of force for output reporting, the y%mesh data has total forces from all contributions + if ( p%potMod == 1 ) then + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + do iBody = 1,p%NBody + startIndx = 6*(iBody-1) + 1 + endIndx = startIndx + 5 + AllOuts(FWaves1 (:,iBody)) = m_WAMIT(1)%F_Waves1(startIndx:endIndx) + AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(1)%F_HS(startIndx:endIndx) + AllOuts(FRdtn (:,iBody)) = m_WAMIT(1)%F_Rdtn(startIndx:endIndx) + m_WAMIT(1)%F_PtfmAM(startIndx:endIndx) + ! AllOuts(FWaves2 (iBody)) = F_Waves2(startIndx:endIndx) ! These are reported by the WAMIT2 module + AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) + AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) + AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) + AllOuts(WBVel (:,iBody)) = qdot(startIndx:endIndx) + AllOuts(WBAcc (:,iBody)) = qdotdot(startIndx:endIndx) + end do + else + + ! This happens when NBodyMod > 1, in which case, each WAMIT object is for a single body, but there may be multiple bodies in the HydroDyn model, + ! so we need to use BodyID to determine the index into the complete HydroDyn list of WAMIT bodies + + do iBody = 1,p%NBody + startIndx = 6*(iBody-1) + 1 + endIndx = startIndx + 5 + AllOuts(FWaves1 (:,iBody)) = m_WAMIT(iBody)%F_Waves1 + AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(iBody)%F_HS + AllOuts(FRdtn (:,iBody)) = m_WAMIT(iBody)%F_Rdtn + m_WAMIT(iBody)%F_PtfmAM + !AllOuts(FWaves2 (:,iBody)) = F_Waves2 + AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) + AllOuts(FWavesTot(:,iBody)) = F_Waves + AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) + AllOuts(WBVel (:,iBody)) = qdot(startIndx:endIndx) + AllOuts(WBAcc (:,iBody)) = qdotdot(startIndx:endIndx) + end do + end if + end if + + + AllOuts(FHydro ) = F_Hydro DO I=1,NWaveElev AllOuts(WaveElevi(I)) = WaveElev(I) @@ -461,7 +1122,7 @@ SUBROUTINE HDOut_WriteOutputs( Time, y, p, Decimate, ErrStat, ErrMsg ) ! Initialize ErrStat and determine if it makes any sense to write output !TODO: We should not have this check here, once per timestep! This should be resolved during initialization. GJH 7/7/2014 - IF ( ( (.NOT. ALLOCATED( p%OutParam )) .AND. (.NOT. ALLOCATED( p%WAMIT%OutParam ) ) .AND. (.NOT. ALLOCATED( p%WAMIT2%OutParam ) )& + IF ( ( (.NOT. ALLOCATED( p%OutParam )) .AND. (.NOT. ALLOCATED( p%WAMIT(1)%OutParam ) ) .AND. (.NOT. ALLOCATED( p%WAMIT2%OutParam ) )& .AND. (.NOT. ALLOCATED( p%Waves2%OutParam ) ) .AND. ( .NOT. ALLOCATED( p%Morison%OutParam ) ) ) ) THEN ErrStat = ErrID_Warn ErrMsg = ' Cannot write output to file because there are not a valid output list.' @@ -546,6 +1207,7 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E ! Local variables INTEGER :: I ! Generic loop counter INTEGER :: J ! Generic loop counter + INTEGER :: iWAMIT ! loop counter over WAMIT objects ! INTEGER :: Indx ! Counts the current index into the WaveKinNd array ! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. ! CHARACTER(200) :: Frmt ! a string to hold a format statement @@ -616,7 +1278,7 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E ! Aggregate the sub-module initialization outputs for the glue code !IF ( p%OutSwtch == 2 .OR. p%OutSwtch == 3 ) THEN - hasWAMITOuts = .FALSE. + !hasWAMITOuts = .FALSE. hasWAMIT2Outs = .FALSE. hasWaves2Outs = .FALSE. hasMorisonOuts = .FALSE. @@ -625,10 +1287,10 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E m%Decimate = 0 p%OutDec = 1 !TODO: Remove this once the parameter has been added to the HD input file GJH 7/8/2014 - IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN - hasWAMITOuts = .TRUE. - p%NumTotalOuts = p%NumTotalOuts + p%WAMIT%NumOuts - END IF + !IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN + ! hasWAMITOuts = .TRUE. + ! p%NumTotalOuts = p%NumTotalOuts + p%WAMIT(1)%NumOuts * p%nWAMITObj + !END IF IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN hasWAMIT2Outs = .TRUE. p%NumTotalOuts = p%NumTotalOuts + p%WAMIT2%NumOuts @@ -678,13 +1340,15 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E J = p%NumOuts + 1 - IF ( hasWAMITOuts ) THEN - DO I=1, p%WAMIT%NumOuts - InitOut%WriteOutputHdr(J) = InitOut%WAMIT%WriteOutputHdr(I) - InitOut%WriteOutputUnt(J) = InitOut%WAMIT%WriteOutputUnt(I) - J = J + 1 - END DO - END IF + !IF ( hasWAMITOuts ) THEN + ! do iWAMIT = 1, p%nWAMITObj + ! DO I=1, p%WAMIT(iWAMIT)%NumOuts + ! InitOut%WriteOutputHdr(J) = InitOut%WAMIT(iWAMIT)%WriteOutputHdr(I) + ! InitOut%WriteOutputUnt(J) = InitOut%WAMIT(iWAMIT)%WriteOutputUnt(I) + ! J = J + 1 + ! END DO + ! end do + !END IF IF ( hasWaves2Outs ) THEN DO I=1, p%Waves2%NumOuts @@ -742,7 +1406,7 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta ! Local variables INTEGER :: I ! Generic loop counter -! INTEGER :: J ! Generic loop counter + INTEGER :: iWAMIT ! loop counter for WAMIT Objects ! INTEGER :: Indx ! Counts the current index into the WaveKinNd array CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. CHARACTER(200) :: Frmt ! a string to hold a format statement @@ -760,7 +1424,7 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta !------------------------------------------------------------------------------------------------- p%UnOutFile = -1 IF ( (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) .OR. & - (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0 ) .OR. & + (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0 ) .OR. & (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0 ) .OR. & (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0 ) .OR. & (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0 ) ) THEN ! Output has been requested so let's open an output file @@ -787,9 +1451,11 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT%WriteOutputHdr(I) ), I=1,p%WAMIT%NumOuts ) + IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN + do iWAMIT = 1, p%nWAMITObj + Frmt = '('//TRIM(Int2LStr(p%WAMIT(iWAMIT)%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT(iWAMIT)%WriteOutputHdr(I) ), I=1,p%WAMIT(iWAMIT)%NumOuts ) + end do END IF IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN @@ -822,9 +1488,11 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT%WriteOutputUnt(I) ), I=1,p%WAMIT%NumOuts ) + IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN + do iWAMIT = 1, p%nWAMITObj + Frmt = '('//TRIM(Int2LStr(p%WAMIT(iWAMIT)%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT(iWAMIT)%WriteOutputUnt(I) ), I=1,p%WAMIT(iWAMIT)%NumOuts ) + end do END IF IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN @@ -863,7 +1531,7 @@ FUNCTION HDOut_GetChannels ( NUserOutputs, UserOutputs, OutList, foundMask, !---------------------------------------------------------------------------------------------------- INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels CHARACTER(10), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. - CHARACTER(10), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. + CHARACTER(10), INTENT( INOUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -933,8 +1601,7 @@ FUNCTION HDOut_GetChannels ( NUserOutputs, UserOutputs, OutList, foundMask, IF ( HDOut_GetChannels > 0 ) THEN count = 1 - ! Test that num channels does not exceed max possible channels due to size of OutList - !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN ErrMsg = ' Error allocating memory for the OutList array in the GetHydroDynChannels function.' ErrStat = ErrID_Fatal @@ -943,6 +1610,7 @@ FUNCTION HDOut_GetChannels ( NUserOutputs, UserOutputs, OutList, foundMask, DO I = 1,NUserOutputs IF ( newFoundMask(I) ) THEN + OutList(count) = UserOutputs(I) count = count + 1 END IF diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index ac035b3c0..a31162074 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -23,7 +23,6 @@ MODULE WAMIT USE Waves USE WAMIT_Types - USE WAMIT_Output USE WAMIT_Interp USE NWTC_Library ! USE Waves_Types @@ -102,8 +101,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init COMPLEX(SiKi), ALLOCATABLE :: HdroExctn (:,:,:) ! Frequency- and direction-dependent complex hydrodynamic wave excitation force per unit wave amplitude vector (kg/s^2, kg-m/s^2) COMPLEX(SiKi), ALLOCATABLE :: WaveExctnC(:,:) ! Discrete Fourier transform of the instantaneous value of the total excitation force on the support platfrom from incident waves (N, N-m) REAL(ReKi) :: DffrctDim (6) ! Matrix used to redimensionalize WAMIT hydrodynamic wave excitation force output (kg/s^2, kg-m/s^2 ) - REAL(SiKi), ALLOCATABLE :: HdroAddMs (:,:) ! The upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic added mass matrix from the radiation problem (kg , kg-m , kg-m^2 ) - REAL(SiKi), ALLOCATABLE :: HdroDmpng (:,:) ! The upper-triangular portion (diagonal and above) of the frequency-dependent hydrodynamic damping matrix from the radiation problem (kg/s, kg-m/s, kg-m^2/s) + REAL(SiKi), ALLOCATABLE :: HdroAddMs (:,:,:) ! The frequency-dependent hydrodynamic added mass matrix from the radiation problem (kg , kg-m , kg-m^2 ) + REAL(SiKi), ALLOCATABLE :: HdroDmpng (:,:,:) ! The frequency-dependent hydrodynamic damping matrix from the radiation problem (kg/s, kg-m/s, kg-m^2/s) REAL(SiKi), ALLOCATABLE :: HdroFreq (:) ! Frequency components inherent in the hydrodynamic added mass matrix, hydrodynamic daming matrix, and complex wave excitation force per unit wave amplitude vector (rad/s) REAL(SiKi), ALLOCATABLE :: HdroWvDir (:) ! Incident wave propagation heading direction components inherent in the complex wave excitation force per unit wave amplitude vector (degrees) REAL(ReKi) :: HighFreq ! The highest frequency component in the WAMIT file, not counting infinity. @@ -148,7 +147,10 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CHARACTER(1024) :: Line ! String to temporarily hold the value of a line within a WAMIT output file. TYPE(FFT_DataType) :: FFT_Data ! the instance of the FFT module we're using - + integer(IntKi) :: iSub, jSub ! indices into the 6x6 sub-matrices used to redimensionalize the WAMIT data (Needed because NBodyMod=1 could have WAMIT matrices which are 6N x 6N) + integer(IntKi) :: iBody ! WAMIT body index + real(R8Ki) :: orientation(3,3) ! Initial orientation of the WAMIT body + real(R8Ki) :: theta(3) ! Euler angle rotations of the WAMIT body ! Error handling CHARACTER(1024) :: ErrMsg2 ! Temporary error message for calls INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls @@ -179,77 +181,56 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Copy Output Init data from Waves Module Init call - p%RhoXg = InitInp%RhoXg p%NStepWave = InitInp%NStepWave p%NumOuts = InitInp%NumOuts p%ExctnMod = InitInp%ExctnMod - - ! For now, we are forcing WAMIT to use the glue-code time-step. If the Convolution-based radiation module was requesting a different timestep (RdtnDT) - ! Then HydroDyn will have already thrown an error. - - p%DT = Interval - - !IF ( InitInp%HasWAMIT ) THEN - ! p%NumOuts = InitInp%NumOuts - !ELSE - ! p%NumOuts = 0 ! Need to set this so the when a call uses generic output writing code, there will be no WAMIT outputs - ! - ! RETURN ! We don't need to do any further initialization work because we are not using WAMIT - - ! Need to allocate and copy data and then destroy the original ??? - ALLOCATE ( p%WaveTime (0:p%NStepWave ) , STAT=ErrStat2 ) - IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') - CALL Cleanup() - RETURN - END IF - p%WaveTime = InitInp%WaveTime - - ! Copy Input Init data into parameters - - p%PtfmVol0 = InitInp%PtfmVol0 - p%PtfmCOBxt = InitInp%PtfmCOBxt - p%PtfmCOByt = InitInp%PtfmCOByt - - - - - - - - - - - - - - - - - + p%NBodyMod = InitInp%NBodyMod + p%NBody = InitInp%NBody + + ! This module's implementation requires that if NBodyMod = 2 or 3, then there is one instance of a WAMIT module for each body, therefore, HydroDyn may have NBody > 1, but this WAMIT module will have NBody = 1 + if ( (p%NBodyMod > 1) .and. (p%NBody > 1) ) then + CALL SetErrStat( ErrID_Fatal, "DEVELOPER ERROR: If NBodyMod = 2 or 3, then NBody for the a WAMIT object must be equal to 1", ErrStat, ErrMsg, 'WAMIT_Init') + return + end if + + ! Allocate misc var and parameter vectors/matrices + call AllocAry( p%F_HS_Moment_Offset, 3, p%NBody, 'p%F_HS_Moment_Offset', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( m%F_HS , 6*p%NBody, 'm%F_HS' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( m%F_Waves1 , 6*p%NBody, 'm%F_Waves1' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( m%F_Rdtn , 6*p%NBody, 'm%F_Rdtn' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( m%F_PtfmAM , 6*p%NBody, 'm%F_PtfmAM' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( p%HdroAdMsI, 6*p%NBody,6*p%NBody, 'p%HdroAdMsI' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( p%HdroSttc , 6*p%NBody,6*p%NBody, 'p%HdroSttc' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + + + do iBody = 1, p%NBody + p%F_HS_Moment_Offset(1,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody) ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position + p%F_HS_Moment_Offset(2,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOByt(iBody) - InitInp%PtfmRefyt(iBody) ) ! and the moment about X due to the COB being offset from the local WAMIT reference point + p%F_HS_Moment_Offset(3,iBody) = -InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOBxt(iBody) - InitInp%PtfmRefxt(iBody) ) ! and the moment about Y due to the COB being offset from the localWAMIT reference point + end do ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Reading in WAMIT output with root name "'//TRIM(InitInp%WAMITFile)//'".' ) - +!TODO: Augment this for NBodyMod = 1 ! Let's set up the matrices used to redimensionalize the hydrodynamic data ! from WAMIT; all these matrices are symmetric and need to be used with ! element-by-element multiplication, instead of matrix-by-matrix ! multiplication: - SttcDim(1,1) = p%RhoXg *InitInp%WAMITULEN**2 ! Force-translation - SttcDim(1,4) = p%RhoXg *InitInp%WAMITULEN**3 ! Force-rotation/Moment-translation - Hydrostatic restoring - SttcDim(4,4) = p%RhoXg *InitInp%WAMITULEN**4 ! Moment-rotation + SttcDim(1,1) = InitInp%RhoXg *InitInp%WAMITULEN**2 ! Force-translation + SttcDim(1,4) = InitInp%RhoXg *InitInp%WAMITULEN**3 ! Force-rotation/Moment-translation - Hydrostatic restoring + SttcDim(4,4) = InitInp%RhoXg *InitInp%WAMITULEN**4 ! Moment-rotation RdtnDim(1,1) = InitInp%WtrDens*InitInp%WAMITULEN**3 ! Force-translation RdtnDim(1,4) = InitInp%WtrDens*InitInp%WAMITULEN**4 ! Force-rotation/Moment-translation - Hydrodynamic added mass and damping RdtnDim(4,4) = InitInp%WtrDens*InitInp%WAMITULEN**5 ! Moment-rotation - DffrctDim(1) = p%RhoXg *InitInp%WAMITULEN**2 ! Force-translation - Hydrodynamic wave excitation force - DffrctDim(4) = p%RhoXg *InitInp%WAMITULEN**3 ! Moment-rotation + DffrctDim(1) = InitInp%RhoXg *InitInp%WAMITULEN**2 ! Force-translation - Hydrodynamic wave excitation force + DffrctDim(4) = InitInp%RhoXg *InitInp%WAMITULEN**3 ! Moment-rotation DO I = 1,3 ! Loop through all force-translation elements (rows) @@ -317,10 +298,15 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init READ (UnWh,*,IOSTAT=Sttus) I, J, TmpData1 ! Read in the row index, column index, and nondimensional data from the WAMIT file IF ( Sttus == 0 ) THEN ! .TRUE. when data is read in successfully -!bjj: TODO verify that I and J are valid values - p%HdroSttc (I,J) = TmpData1*SttcDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array - ELSE ! We must have reached the end of the file, so stop reading in data + ! In case NBodyMod = 1, we now have WAMIT matrices which are potentially larger than 6x6, so we need to determine how the SttcDim multiplier matrix (a 6x6) + ! should be applied to the larger WAMIT matrix. + + iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix + jSub = mod(J-1,6)+1 + p%HdroSttc (I,J) = TmpData1*SttcDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array + + ELSE ! We must have reached the end of the file, so stop reading in data EXIT @@ -386,8 +372,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CALL AllocAry( WAMITPer, NInpFreq, 'WAMITPer', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') CALL AllocAry( SortFreqInd, NInpFreq, 'SortFreqInd', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') CALL AllocAry( HdroFreq, NInpFreq, 'HdroFreq', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - CALL AllocAry( HdroAddMs, NInpFreq, 21,'HdroAddMs', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - CALL AllocAry( HdroDmpng, NInpFreq, 21,'HdroDmpng', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroAddMs, NInpFreq, 6*p%NBody, 6*p%NBody, 'HdroAddMs', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + CALL AllocAry( HdroDmpng, NInpFreq, 6*p%NBody, 6*p%NBody, 'HdroDmpng', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -463,8 +449,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init PrvPer = 0.0 ! Initialize to a don't care FirstPass = .TRUE. ! Initialize to .TRUE. for the first pass - HdroAddMs(:,:) = 0.0 ! Initialize to zero - HdroDmpng(:,:) = 0.0 ! Initialize to zero + HdroAddMs = 0.0 ! Initialize to zero + HdroDmpng = 0.0 ! Initialize to zero DO ! Loop through all rows in the file @@ -506,28 +492,32 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init !bjj: verify that I and J are valid indices for RdtnDim - IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal - Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + ! IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal + ! Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix + jSub = mod(J-1,6)+1 - HdroAddMs(SortFreqInd(K),Indx) = TmpData1*RdtnDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array - END IF + HdroAddMs(SortFreqInd(K),I,J) = TmpData1*RdtnDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array + ! END IF ELSE ! We must have a positive, non-infinite frequency. - READ (Line,*,IOSTAT=Sttus) TmpPer, I, J, TmpData1, TmpData2 ! Read in the period, row index, column index, and nondimensional data from the WAMIT file + READ (Line,*,IOSTAT=Sttus) TmpPer, I, J, TmpData1, TmpData2 ! Read in the period, row index, column index, and nondimensional data from the WAMIT file IF ( Sttus /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, "Error reading line from WAMIT file", ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() RETURN END IF -!bjj: verify that I and J are valid indices for RdtnDim + - IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal - Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + !IF ( J >= I ) THEN ! .TRUE. if we are on or above the diagonal + ! Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). + iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix + jSub = mod(J-1,6)+1 - HdroAddMs(SortFreqInd(K),Indx) = TmpData1*RdtnDim(I,J) ! Redimensionalize the data and place it at the appropriate location within the array - HdroDmpng(SortFreqInd(K),Indx) = TmpData2*RdtnDim(I,J)*HdroFreq(SortFreqInd(K)) ! Redimensionalize the data and place it at the appropriate location within the array - END IF + HdroAddMs(SortFreqInd(K),I,J) = TmpData1*RdtnDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array + HdroDmpng(SortFreqInd(K),I,J) = TmpData2*RdtnDim(iSub,jSub)*HdroFreq(SortFreqInd(K)) ! Redimensionalize the data and place it at the appropriate location within the array + ! END IF END IF @@ -623,7 +613,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF - ALLOCATE ( HdroExctn (NInpFreq,NInpWvDir,6) , STAT=ErrStat2 ) ! complex so we don't have a reoutine + ALLOCATE ( HdroExctn (NInpFreq,NInpWvDir,6*p%NBody) , STAT=ErrStat2 ) ! complex so we don't have a built in subroutine IF ( ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating space for HdroExctn array', ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() @@ -783,8 +773,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END IF - - HdroExctn(SortFreqInd(K),SortWvDirInd(J),I) = CMPLX( TmpRe, TmpIm )*DffrctDim(I) ! Redimensionalize the data and place it at the appropriate location within the array + iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix + HdroExctn(SortFreqInd(K),SortWvDirInd(J),I) = CMPLX( TmpRe, TmpIm )*DffrctDim(iSub) ! Redimensionalize the data and place it at the appropriate location within the array ELSE ! We must have reached the end of the file, so stop reading in data @@ -850,16 +840,16 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Set the infinite-frequency limit of the frequency-dependent hydrodynamic ! added mass matrix, HdroAdMsI, based on the highest frequency available: - - Indx = 0 - DO J = 1,6 ! Loop through all rows of HdroAdMsI - DO K = J,6 ! Loop through all columns of HdroAdMsI above and including the diagonal - Indx = Indx + 1 - p%HdroAdMsI(J,K) = HdroAddMs(NInpFreq,Indx) +!TODO: Is this index order correct for computational speed? GJH 9/5/19 + !Indx = 0 + DO J = 1,6*p%NBody ! Loop through all rows of HdroAdMsI + DO K = 1,6*p%NBody ! Loop through all columns of HdroAdMsI above and including the diagonal + ! Indx = Indx + 1 + p%HdroAdMsI(J,K) = HdroAddMs(NInpFreq,J,K) END DO ! K - All columns of HdroAdMsI above and including the diagonal - DO K = J+1,6 ! Loop through all rows of HdroAdMsI below the diagonal - p%HdroAdMsI(K,J) = p%HdroAdMsI(J,K) - END DO ! K - All rows of HdroAdMsI below the diagonal + ! DO K = J+1,6 ! Loop through all rows of HdroAdMsI below the diagonal + ! p%HdroAdMsI(K,J) = p%HdroAdMsI(J,K) + ! END DO ! K - All rows of HdroAdMsI below the diagonal END DO ! J - All rows of HdroAdMsI @@ -882,7 +872,18 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF - p%WaveExctn = 0.0 + + + ! Initialize everything to zero: + + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + + p%WaveExctn = 0.0 else if ( p%ExctnMod == 2 ) then Interval_Sub = InitInp%Conv_Rdtn%RdtnDT @@ -950,9 +951,19 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END IF + ALLOCATE ( WaveExctnC(0:InitInp%NStepWave2 ,6*p%NBody) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctnC array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF - ! Compute the positive-frequency components (including zero) of the discrete - ! Fourier transform of the wave excitation force: + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF DO I = 0,InitInp%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transform @@ -976,7 +987,23 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END DO ! J - All wave excitation forces and moments - END DO ! I - The positive frequency components (including zero) of the discrete Fourier transform + ! Compute the discrete Fourier transform of the instantaneous value of the + ! total excitation force on the support platfrom from incident waves: + + DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments + TmpCoord(1) = Omega + TmpCoord(2) = InitInp%WaveDirArr(I) + CALL WAMIT_Interp2D_Cplx( TmpCoord, HdroExctn(:,:,J), HdroFreq, HdroWvDir, LastInd2, WaveExctnC(I,J), ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + WaveExctnC(I,J) = WaveExctnC(I,J) * CMPLX(InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I)) + END DO ! J - All wave excitation forces and moments + + + END DO ! I - The positive frequency components (including zero) of the discrete Fourier transform @@ -1021,13 +1048,13 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF - DO J = 1,6 ! Loop through all wave excitation forces and moments - CALL ApplyFFT_cx ( p%WaveExctn(0:InitInp%NStepWave-1,J), WaveExctnC(:,J), FFT_Data, ErrStat2 ) - CALL SetErrStat( ErrStat2, ' An error occured while applying an FFT to WaveExctnC.', ErrStat, ErrMsg, 'WAMIT_Init') - IF ( ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - END IF + DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments + CALL ApplyFFT_cx ( p%WaveExctn(0:InitInp%NStepWave-1,J), WaveExctnC(:,J), FFT_Data, ErrStat2 ) + CALL SetErrStat( ErrStat2, ' An error occured while applying an FFT to WaveExctnC.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF ! Append first datpoint as the last as aid for repeated wave data p%WaveExctn(InitInp%NStepWave,J) = p%WaveExctn(0,J) @@ -1093,7 +1120,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CALL MOVE_ALLOC( HdroFreq, Conv_Rdtn_InitInp%HdroFreq ) CALL MOVE_ALLOC( HdroAddMs, Conv_Rdtn_InitInp%HdroAddMs ) CALL MOVE_ALLOC( HdroDmpng, Conv_Rdtn_InitInp%HdroDmpng ) - + Conv_Rdtn_InitInp%NBody = InitInp%NBody Conv_Rdtn_InitInp%RdtnTMax = InitInp%RdtnTMax Conv_Rdtn_InitInp%RdtnDT = InitInp%Conv_Rdtn%RdtnDT Conv_Rdtn_InitInp%HighFreq = HighFreq @@ -1150,54 +1177,62 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init - ! Define system output initializations (set up mesh) here: - + ! Define system output initializations (set up meshes) here: + ! Create the input and output meshes associated with lumped loads + - CALL MeshCreate( BlankMesh = u%Mesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = 1 & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE.) + + call MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NBody & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - ! Create the node on the mesh - + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + do iBody = 1, p%NBody + + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(iBody)/) + orientation = EulerConstruct(theta) - CALL MeshPositionNode (u%Mesh & - , 1 & - , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & - , ErrStat2 & - , ErrMsg2 ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + ! Create the node on the mesh + + CALL MeshPositionNode (u%Mesh & + , iBody & + , (/InitInp%PtfmRefxt(iBody), InitInp%PtfmRefyt(iBody), InitInp%PtfmRefzt(iBody)/) & + , ErrStat2 & + , ErrMsg2 & + , orientation ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - ! Create the mesh element - CALL MeshConstructElement ( u%Mesh & - , ELEMENT_POINT & - , ErrStat2 & - , ErrMsg2 & - , 1 & - ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , iBody & + ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + end do CALL MeshCommit ( u%Mesh & - , ErrStat2 & - , ErrMsg2 ) + , ErrStat2 & + , ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -1221,18 +1256,12 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END IF - u%Mesh%RemapFlag = .TRUE. - y%Mesh%RemapFlag = .TRUE. - + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + + ! Define initialization-routine output here: - ! Initialize the outputs - CALL WMTOUT_Init( InitInp, y, p, InitOut, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF @@ -1364,6 +1393,10 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState INTEGER :: I ! Generic loop counter INTEGER :: nTime ! Number of inputs + integer(IntKi) :: iBody ! WAMIT body index + + integer(IntKi) :: indxStart, indxEnd ! Starting and ending indices for the iBody_th sub vector in an NBody long vector + ! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (secondary error) ! CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None @@ -1400,7 +1433,16 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState END IF DO I=1,nTime - Conv_Rdtn_u(I)%Velocity = (/Inputs(I)%Mesh%TranslationVel(:,1), Inputs(I)%Mesh%RotationVel(:,1)/) + ALLOCATE( Conv_Rdtn_u(I)%Velocity(size(m%Conv_Rdtn_u%Velocity)), STAT = ErrStat ) + IF (ErrStat /=0) THEN + ErrMsg = ' Failed to allocate array Conv_Rdtn_u(I)%Velocity.' + RETURN + END IF + do iBody=1,p%NBody + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + Conv_Rdtn_u(I)%Velocity(indxStart:indxEnd) = (/Inputs(I)%Mesh%TranslationVel(:,iBody), Inputs(I)%Mesh%RotationVel(:,iBody)/) + end do END DO CALL Conv_Rdtn_UpdateStates( t, n, Conv_Rdtn_u, InputTimes, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, & @@ -1419,9 +1461,12 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState END IF DO I=1,nTime - SS_Rdtn_u(I)%dq(1:3) = Inputs(I)%Mesh%TranslationVel(:,1) - SS_Rdtn_u(I)%dq(4:6) = Inputs(I)%Mesh%RotationVel(:,1) - !SS_Rdtn_u(I)%dq = reshape((/Inputs(I)%Mesh%TranslationVel(:,1), Inputs(I)%Mesh%RotationVel(:,1)/), (/6,1/)) !reshape(u%Velocity, (/6,1/)) ! dq is a 6x1 matrix + do iBody=1,p%NBody + indxStart = (iBody-1)*6+1 + SS_Rdtn_u(I)%dq(indxStart:indxStart+2) = Inputs(I)%Mesh%TranslationVel(:,iBody) + SS_Rdtn_u(I)%dq(indxStart+3:indxStart+5) = Inputs(I)%Mesh%RotationVel(:,iBody) + !SS_Rdtn_u(I)%dq = reshape((/Inputs(I)%Mesh%TranslationVel(:,1), Inputs(I)%Mesh%RotationVel(:,1)/), (/6,1/)) !reshape(u%Velocity, (/6,1/)) ! dq is a 6x1 matrix + end do END DO CALL SS_Rad_UpdateStates( t, n, SS_Rdtn_u, InputTimes, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, ErrStat, ErrMsg ) @@ -1449,10 +1494,11 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState END SUBROUTINE WAMIT_UpdateStates !---------------------------------------------------------------------------------------------------------------------------------- !> Routine for computing outputs, used in both loose and tight coupling. -SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +SUBROUTINE WAMIT_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + real(SiKi), intent(in ) :: WaveTime(:) !< Array of wave kinematic time samples, (sec) TYPE(WAMIT_InputType), INTENT(IN ) :: u !< Inputs at Time TYPE(WAMIT_ParameterType), INTENT(IN ) :: p !< Parameters TYPE(WAMIT_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time @@ -1474,9 +1520,11 @@ SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, Er INTEGER(IntKi) :: I ! Generic index INTEGER(IntKi) :: J ! Generic index ! INTEGER(IntKi) :: K ! Generic index - REAL(ReKi) :: q(6), qdot(6), qdotdot(6) + REAL(ReKi) :: q(6*p%NBody), qdot(6*p%NBody), qdotdot(6*p%NBody) ! kinematics for all WAMIT bodies REAL(ReKi) :: rotdisp(3) ! small angle rotational displacements - REAL(ReKi) :: AllOuts(MaxWAMITOutputs) + REAL(ReKi) :: AllOuts(MaxWAMITOutputs) + integer(IntKi) :: iBody ! Counter for WAMIT bodies. If NBodyMod > 1 then NBody = 1, and hence iBody = 1 + integer(IntKi) :: indxStart, indxEnd ! Starting and ending indices for the iBody_th sub vector in an NBody long vector ! Initialize ErrStat @@ -1503,11 +1551,10 @@ SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, Er RETURN END IF - DO I = 1,6 ! Loop through all wave excitation forces and moments - m%F_Waves1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveExctn(:,I), & - m%LastIndWave, p%NStepWave + 1 ) - END DO ! I - All wave excitation forces and moments - + DO I = 1,6*p%NBody ! Loop through all wave excitation forces and moments + m%F_Waves1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + END DO ! I - All wave excitation forces and moments else if ( p%ExctnMod == 2 ) then call SS_Exc_CalcOutput( Time, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, & @@ -1517,42 +1564,29 @@ SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, Er end if - + do iBody = 1, p%NBody - ! Determine the rotational angles from the direction-cosine matrix - rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,1), ErrStat, ErrMsg ) - - q = reshape((/real(u%Mesh%TranslationDisp(:,1),ReKi),rotdisp(:)/),(/6/)) - qdot = reshape((/u%Mesh%TranslationVel(:,1),u%Mesh%RotationVel(:,1)/),(/6/)) - qdotdot = reshape((/u%Mesh%TranslationAcc(:,1),u%Mesh%RotationAcc(:,1)/),(/6/)) - - - ! Compute the load contirbution from user-supplied added stiffness and damping - ! This is being done by the HydroDyn Module now. GJH 1/6/14 - m%F_PtfmAdd = 0.0 ! p%AddF0 - matmul(p%AddCLin, q) - matmul(p%AddBLin, qdot) - matmul(p%AddBQuad, qdotsq) - - - - + ! Determine the rotational angles from the direction-cosine matrix + rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,iBody), ErrStat, ErrMsg ) + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + q (indxStart:indxEnd) = reshape((/real(u%Mesh%TranslationDisp(:,iBody),ReKi),rotdisp(:)/),(/6/)) + qdot (indxStart:indxEnd) = reshape((/u%Mesh%TranslationVel(:,iBody),u%Mesh%RotationVel(:,iBody)/),(/6/)) + qdotdot(indxStart:indxEnd) = reshape((/u%Mesh%TranslationAcc(:,iBody),u%Mesh%RotationAcc(:,iBody)/),(/6/)) + + end do ! Compute the load contribution from hydrostatics: - m%F_HS(:) = 0.0 ! Initialize to zero... - m%F_HS(3) = p%RhoXg*p%PtfmVol0 ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position - m%F_HS(4) = p%RhoXg*p%PtfmVol0*p%PtfmCOByt ! and the moment about X due to the COB being offset from the WAMIT reference point - m%F_HS(5) = -p%RhoXg*p%PtfmVol0*p%PtfmCOBxt ! and the moment about Y due to the COB being offset from the WAMIT reference point + m%F_HS = -matmul(p%HdroSttc,q) - DO I = 1,6 ! Loop through all hydrostatic forces and moments - DO J = 1,6 ! Loop through all platform DOFs - m%F_HS(I) = m%F_HS(I) - p%HdroSttc(I,J)*q(J) - END DO ! J - platform DOFs - - END DO ! I - All hydrostatic forces and moments + do iBody = 1, p%NBody + indxStart = (iBody-1)*6+3 + indxEnd = indxStart+2 + m%F_HS(indxStart:indxEnd) = m%F_HS(indxStart:indxEnd) + p%F_HS_Moment_Offset(:,iBody) ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position + end do - - - - + ! If necessary, compute the load contribution from wave radiation damping ! (i.e., the radiation problem): @@ -1591,30 +1625,34 @@ SUBROUTINE WAMIT_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, Er ! Compute outputs here: - DO I=1,3 - y%Mesh%Force(I,1) = m%F_PtfmAM(I) + m%F_Rdtn(I) + m%F_Waves1(I) + m%F_HS(I) + m%F_PtfmAdd(I) - END DO - DO I=1,3 - y%Mesh%Moment(I,1) = m%F_PtfmAM(I+3) + m%F_Rdtn(I+3) + m%F_Waves1(I+3) + m%F_HS(I+3) + m%F_PtfmAdd(I+3) - END DO - - - - - - - - ! Map calculated results into the AllOuts Array - CALL WMTOut_MapOutputs(Time, y, m%F_Waves1, m%F_HS, m%F_Rdtn, m%F_PtfmAM, AllOuts, ErrStat, ErrMsg) - - - ! Put the output data in the OutData array - - DO I = 1,p%NumOuts - - y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) - - END DO + do iBody = 1, p%NBody + indxStart = (iBody-1)*6 + + DO I=1,3 + y%Mesh%Force(I,iBody) = m%F_PtfmAM(indxStart+I) + m%F_Rdtn(indxStart+I) + m%F_Waves1(indxStart+I) + m%F_HS(indxStart+I) + END DO + DO I=1,3 + y%Mesh%Moment(I,iBody) = m%F_PtfmAM(indxStart+I+3) + m%F_Rdtn(indxStart+I+3) + m%F_Waves1(indxStart+I+3) + m%F_HS(indxStart+I+3) + END DO + end do + + + ! Output channels will be dealt with by the HydroDyn module + + !TODO: Clean this up + ! + ! + ! ! Map calculated results into the AllOuts Array + !CALL WMTOut_MapOutputs(Time, p%NBody, p%BodyID, y, m%F_Waves1, m%F_HS, m%F_Rdtn, m%F_PtfmAM, AllOuts, ErrStat, ErrMsg) + ! + ! + ! ! Put the output data in the OutData array + ! + !DO I = 1,p%NumOuts + ! + ! y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + ! + !END DO END SUBROUTINE WAMIT_CalcOutput @@ -1635,23 +1673,26 @@ SUBROUTINE WAMIT_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - + integer(IntKi) :: iBody ! WAMIT body index + integer(IntKi) :: indxStart ! Starting and ending indices for the iBody_th sub vector in an NBody long vector + ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - ! Compute the first time derivatives of the continuous states here: - m%SS_Rdtn_u%dq(1:3) = u%Mesh%TranslationVel(:,1) - m%SS_Rdtn_u%dq(4:6) = u%Mesh%RotationVel(:,1) - - CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) - + ! Compute the first time derivatives of the continuous states here: + do iBody = 1, p%NBody + indxStart = (iBody-1)*6+1 + m%SS_Rdtn_u%dq(indxStart:indxStart+2) = u%Mesh%TranslationVel(:,iBody) + m%SS_Rdtn_u%dq(indxStart+3:indxStart+5) = u%Mesh%RotationVel(:,iBody) + end do + CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) + ! NOTE: The input below (0.0) will only work as part of a linearization Get_OP call! If this routine (WAMIT_CalcContStateDeriv) is called in another context, then the following ! input needs to be implemented generically. CALL SS_Exc_CalcContStateDeriv( Time, 0.0_SiKi, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, m%SS_Exctn, dxdt%SS_Exctn, ErrStat, ErrMsg ) - END SUBROUTINE WAMIT_CalcContStateDeriv !---------------------------------------------------------------------------------------------------------------------------------- @@ -1672,7 +1713,9 @@ SUBROUTINE WAMIT_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrSta INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - + integer(IntKi) :: iBody ! WAMIT body index + integer(IntKi) :: indxStart, indxEnd ! Starting and ending indices for the iBody_th sub vector in an NBody long vector + ! Initialize ErrStat ErrStat = ErrID_None @@ -1681,9 +1724,11 @@ SUBROUTINE WAMIT_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, ErrSta ! Update discrete states here: IF ( p%RdtnMod == 1 ) THEN ! .TRUE. when we will be modeling wave radiation damping. - - m%Conv_Rdtn_u%Velocity = (/u%Mesh%TranslationVel(:,1), u%Mesh%RotationVel(:,1)/) - + do iBody=1,p%NBody + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + m%Conv_Rdtn_u%Velocity(indxStart:indxEnd) = (/u%Mesh%TranslationVel(:,iBody), u%Mesh%RotationVel(:,iBody)/) + end do CALL Conv_Rdtn_UpdateDiscState( Time, n, m%Conv_Rdtn_u, p%Conv_Rdtn, x%Conv_Rdtn, xd%Conv_Rdtn, z%Conv_Rdtn, & OtherState%Conv_Rdtn, m%Conv_Rdtn, ErrStat, ErrMsg ) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index 97e395069..63ee7c34e 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -17,12 +17,18 @@ usefrom Conv_Radiation.txt usefrom SS_Radiation.txt usefrom SS_Excitation.txt usefrom Waves.txt -param WAMIT/WAMIT unused INTEGER MaxWAMITOutputs - 18 - "" - -typedef WAMIT/WAMIT InitInputType ReKi PtfmVol0 - - - "" - +param WAMIT/WAMIT unused INTEGER MaxWAMITOutputs - 18 - "" - +typedef ^ InitInputType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ ReKi PtfmVol0 {:} - - "" - typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - typedef ^ ^ ReKi WAMITULEN - - - "" - -typedef ^ ^ ReKi PtfmCOBxt - - - "" - -typedef ^ ^ ReKi PtfmCOByt - - - "" - +typedef ^ ^ ReKi PtfmRefxt {:} - - "The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefyt {:} - - "The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefzt {:} - - "The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians +typedef ^ ^ ReKi PtfmCOBxt {:} - - "" - +typedef ^ ^ ReKi PtfmCOByt {:} - - "" - typedef ^ ^ INTEGER RdtnMod - - - "" - typedef ^ ^ INTEGER ExctnMod - - - "" - typedef ^ ^ DbKi RdtnTMax - - - "" - @@ -88,11 +94,10 @@ typedef ^ ^ Conv_Rdtn_O # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. typedef ^ MiscVarType INTEGER LastIndWave - - - "" - -typedef ^ ^ ReKi F_HS {6} - - "local variable in CalcOutput:Total load contribution from hydrostatics, including the effects of waterplane area and the center of buoyancy" "(N, N-m)" -typedef ^ ^ ReKi F_Waves1 {6} - - "local variable in CalcOutput:Total load contribution from incident waves (i.e., the diffraction problem)" "(N, N-m)" -typedef ^ ^ ReKi F_Rdtn {6} - - "local variable in CalcOutput:Total load contribution from wave radiation damping (i.e., the diffraction problem)" "(N, N-m)" -typedef ^ ^ ReKi F_PtfmAdd {6} - - "local variable in CalcOutput:set to zero because this is calculated in HydroDyn now" - -typedef ^ ^ ReKi F_PtfmAM {6} - - "local variable in CalcOutput:" - +typedef ^ ^ ReKi F_HS {:} - - "local variable in CalcOutput:Total load contribution from hydrostatics, including the effects of waterplane area and the center of buoyancy" "(N, N-m)" +typedef ^ ^ ReKi F_Waves1 {:} - - "local variable in CalcOutput:Total load contribution from incident waves (i.e., the diffraction problem)" "(N, N-m)" +typedef ^ ^ ReKi F_Rdtn {:} - - "local variable in CalcOutput:Total load contribution from wave radiation damping (i.e., the diffraction problem)" "(N, N-m)" +typedef ^ ^ ReKi F_PtfmAM {:} - - "local variable in CalcOutput:" - typedef ^ ^ SS_Rad_MiscVarType SS_Rdtn - - - "" - typedef ^ ^ SS_Rad_InputType SS_Rdtn_u - - - "" - typedef ^ ^ SS_Rad_OutputType SS_Rdtn_y - - - "" - @@ -107,16 +112,14 @@ typedef ^ ^ Conv_Rdtn_O # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: # -typedef ^ ParameterType ReKi HdroAdMsI {6}{6} - - "" (sec) -typedef ^ ^ ReKi HdroSttc {6}{6} - - "" - -typedef ^ ^ ReKi PtfmVol0 - - - "" - -typedef ^ ^ ReKi PtfmCOBxt - - - "" - -typedef ^ ^ ReKi PtfmCOByt - - - "" - +typedef ^ ParameterType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ ReKi F_HS_Moment_Offset {:}{:} - - "The offset moment due to the COB being offset from the WAMIT body's local location {matrix 3xNBody}" N-m +typedef ^ ^ ReKi HdroAdMsI {:}{:} - - "" (sec) +typedef ^ ^ ReKi HdroSttc {:}{:} - - "" - typedef ^ ^ INTEGER RdtnMod - - - "" - typedef ^ ^ INTEGER ExctnMod - - - "" - typedef ^ ^ SiKi WaveExctn {:}{:} - - "" - -typedef ^ ^ ReKi RhoXg - - - "" - -typedef ^ ^ SiKi WaveTime {:} - - "" - typedef ^ ^ INTEGER NStepWave - - - "" - typedef ^ ^ Conv_Rdtn_ParameterType Conv_Rdtn - - - "" - typedef ^ ^ SS_Rad_ParameterType SS_Rdtn - - - "" - @@ -140,10 +143,10 @@ typedef ^ ^ INTEGER # ..... Inputs .................................................................................................................... # Define inputs that are contained on the mesh here: # -typedef ^ InputType MeshType Mesh - - - "Displacements at the WAMIT reference point in the inertial frame" - +typedef ^ InputType MeshType Mesh - - - "Displacements at the WAMIT reference point in the inertial frame" - # # # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: -typedef ^ OutputType MeshType Mesh - - - "Loads at the WAMIT reference point in the inertial frame" - -typedef ^ ^ ReKi WriteOutput {:} - - "" - +typedef ^ OutputType MeshType Mesh - - - "Loads at the WAMIT reference point in the inertial frame" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 05c45bde5..393bf0f1c 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -3025,13 +3025,6 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff p%DT = Interval ! Timestep from calling program - ! Allocate array for the WaveTime information -- array of times to generate output for. NOTE: can't use MOVE_ALLOC since InitInp is intent in. - CALL AllocAry( p%WaveTime, SIZE(InitInp%WaveTime,1), 'array to hold WaveTime', ErrStatTmp, ErrMsgTmp ) - IF ( ErrStatTmp /= ErrID_None ) THEN - CALL SetErrStat( ErrID_Fatal, ErrMsgTmp, ErrStat, ErrMsg, 'CheckInitInput') - RETURN - ENDIF - p%WaveTime = InitInp%WaveTime @@ -5414,10 +5407,11 @@ END SUBROUTINE WAMIT2_UpdateStates !---------------------------------------------------------------------------------------------------------------------------------- !> Routine for computing outputs, used in both loose and tight coupling. -SUBROUTINE WAMIT2_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +SUBROUTINE WAMIT2_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + real(SiKi), intent(in ) :: WaveTime(:) !< Array of wave kinematic time samples, (sec) TYPE(WAMIT2_InputType), INTENT(IN ) :: u !< Inputs at Time TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters TYPE(WAMIT2_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time @@ -5459,7 +5453,7 @@ SUBROUTINE WAMIT2_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, E ! Compute the 2nd order load contribution from incident waves: DO I = 1,6 ! Loop through all wave excitation forces and moments - m%F_Waves2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveExctn2(:,I), & + m%F_Waves2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn2(:,I), & m%LastIndWave, p%NStepWave + 1 ) END DO ! I - All wave excitation forces and moments diff --git a/modules/hydrodyn/src/WAMIT_Output.f90 b/modules/hydrodyn/src/WAMIT_Output.f90 index 30d0fa16c..1d5480ed3 100644 --- a/modules/hydrodyn/src/WAMIT_Output.f90 +++ b/modules/hydrodyn/src/WAMIT_Output.f90 @@ -102,39 +102,53 @@ MODULE WAMIT_Output -!==================================================================================================== -SUBROUTINE WMTOUT_MapOutputs( CurrentTime, y, F_Waves1, F_HS, F_Rdtn, F_PtfmAM, AllOuts, ErrStat, ErrMsg ) -! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput -! This is called by WAMIT_CalcOutput() at each time step. -!---------------------------------------------------------------------------------------------------- - REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds - TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data - REAL(ReKi), INTENT( IN ) :: F_Waves1(6) - REAL(ReKi), INTENT( IN ) :: F_HS(6) - REAL(ReKi), INTENT( IN ) :: F_Rdtn(6) - REAL(ReKi), INTENT( IN ) :: F_PtfmAM(6) - REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMITOutputs) - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - -! INTEGER :: I - - ErrStat = ErrID_None - ErrMsg = "" - - - ! TODO: use y%mesh for the forces instead of individual parameters - - !AllOuts(Time) = REAL(CurrentTime,ReKi) - AllOuts(FWaves1) = F_Waves1 - AllOuts(FHdrSttc) = F_HS - AllOuts(FRdtn) = F_Rdtn + F_PtfmAM - - - - - -END SUBROUTINE WMTOUT_MapOutputs +!!==================================================================================================== +!SUBROUTINE WMTOUT_MapOutputs( CurrentTime, NBody, BodyID, y, F_Waves1, F_HS, F_Rdtn, F_PtfmAM, AllOuts, ErrStat, ErrMsg ) +!! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput +!! This is called by WAMIT_CalcOutput() at each time step. +!!---------------------------------------------------------------------------------------------------- +! REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds +! integer(IntKi), intent( in ) :: NBody ! If NBody > 1 then BodyID is ignored. If NBody = 1 then BodyID is used and force arrays are 6 elements long otherwise they are 6*NBody long +! integer(IntKi), intent( in ) :: BodyID ! The body index for this WAMIT object within the HydroDyn context when NBodyMod > 1, if NBody> 1 then BodyID is ignored +! TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data +! REAL(ReKi), INTENT( IN ) :: F_Waves1(:) +! REAL(ReKi), INTENT( IN ) :: F_HS(:) +! REAL(ReKi), INTENT( IN ) :: F_Rdtn(:) +! REAL(ReKi), INTENT( IN ) :: F_PtfmAM(:) +! REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMITOutputs) +! INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation +! CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! +! integer(IntKi) :: iBody, startIndx, endIndx ! indices +! +! ErrStat = ErrID_None +! ErrMsg = "" +! +! +! ! Need to use individual components of force for output reporting, the y%mesh data has total forces from all contributions +! +! if ( NBody == 1 ) then +! +! ! This happens when NBodyMod > 1, in which case, each WAMIT object is for a single body, but there may be multiple bodies in the HydroDyn model, +! ! so we need to use BodyID to determine the index into the complete HydroDyn list of WAMIT bodies +! +! AllOuts(FWaves (BodyID)) = F_Waves1 +! AllOuts(FHdrSttc(BodyID)) = F_HS +! AllOuts(FRdtn (BodyID)) = F_Rdtn + F_PtfmAM +! +! else +! ! The only happens if NBodyMod = 1, and all HydroDyn WAMIT bodies are represented in this single WAMIT object +! do iBody = 1,NBody +! startIndx = 6*(iBody-1) + 1 +! endIndx = startIndx + 5 +! AllOuts(FWaves (iBody)) = F_Waves1(startIndx:endIndx) +! AllOuts(FHdrSttc(iBody)) = F_HS(startIndx:endIndx) +! AllOuts(FRdtn (iBody)) = F_Rdtn(startIndx:endIndx) + F_PtfmAM(startIndx:endIndx) +! end do +! +! end if +! +!END SUBROUTINE WMTOUT_MapOutputs !==================================================================================================== diff --git a/reg_tests/r-test b/reg_tests/r-test index 8db70cc4e..3cebe503e 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 8db70cc4eec2465e0fb4f79fd8c8a872b0ac286b +Subproject commit 3cebe503ebabc3fec64f396ded592e2df458e9b5 diff --git a/vs-build/HydroDyn/HydroDynDriver.vfproj b/vs-build/HydroDyn/HydroDynDriver.vfproj index 8447d96ad..a10a909e3 100644 --- a/vs-build/HydroDyn/HydroDynDriver.vfproj +++ b/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -6,7 +6,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -147,7 +147,6 @@ - From 0d17c125e6cca42a5144cfca2aade0729e7991c2 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 26 Sep 2019 06:59:01 -0600 Subject: [PATCH 005/377] -Fixed bugs related to switching of p%WAMIT from scalar to array -Added back p%WtrDpth because it is needed for linearization -Added back some initialization input data needed for SS_Excitation model --- modules/hydrodyn/src/HydroDyn.f90 | 80 +++++++++++++++++-------------- modules/hydrodyn/src/HydroDyn.txt | 1 + 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 3be34ca97..70fa6acdd 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -922,7 +922,12 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega - + +!<==============TODO Check if this code block is needed ===================== + ! Init inputs for the SS_Excitation model (set this just in case it will be used) + InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir + CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) +!<==============TODO Check if this code block is needed ===================== ! Temporarily move arrays to init input for WAMIT (save some space) CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) @@ -1561,7 +1566,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitOut%WtrDens = InitLocal%Morison%WtrDens InitOut%WtrDpth = InitLocal%Morison%WtrDpth InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL - + p%WtrDpth = InitOut%WtrDpth + IF ( InitLocal%hasIce ) THEN IF ((InitLocal%Waves%WaveMod /= 0) .OR. (InitLocal%Current%CurrMod /= 0) ) THEN CALL SetErrStat(ErrID_Fatal,'Waves and Current must be turned off in HydroDyn when ice loading is computed. Set WaveMod=0 and CurrMod=0.',ErrStat,ErrMsg,RoutineName) @@ -2359,7 +2365,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM m%IgnoreMod = .true. ! to compute perturbations, we need to ignore the modulo function ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid - NN = p%WAMIT%SS_Rdtn%N + p%WAMIT%SS_Exctn%N + NN = p%WAMIT(1)%SS_Rdtn%N + p%WAMIT(1)%SS_Exctn%N ! make a copy of the inputs to perturb call HydroDyn_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2455,16 +2461,16 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM dXdu = 0.0_R8Ki - do i = 1,p%WAMIT%SS_Exctn%N - dXdu(offsetI+i,size(p%Jac_u_indx,1)+1) = p%WAMIT%SS_Exctn%B(i) + do i = 1,p%WAMIT(1)%SS_Exctn%N + dXdu(offsetI+i,size(p%Jac_u_indx,1)+1) = p%WAMIT(1)%SS_Exctn%B(i) end do - offsetI = NN - p%WAMIT%SS_Rdtn%N + offsetI = NN - p%WAMIT(1)%SS_Rdtn%N offsetJ = size(p%Jac_u_indx,1)+1 - 13 do j = 1, 6 - do i = 1,p%WAMIT%SS_Rdtn%N - dXdu(offsetI+i,offsetJ+j) = p%WAMIT%SS_Rdtn%B(i,j) + do i = 1,p%WAMIT(1)%SS_Rdtn%N + dXdu(offsetI+i,offsetJ+j) = p%WAMIT(1)%SS_Rdtn%B(i,j) end do end do @@ -2547,7 +2553,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: - NN = p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N + NN = p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N ! make a copy of the continuous states to perturb call HydroDyn_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2633,17 +2639,17 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, dXdx = 0.0_R8Ki ! Analytical Jacobians from State-space models - if ( p%WAMIT%SS_Exctn%N > 0 ) then - do j=1,p%WAMIT%SS_Exctn%N - do i=1,p%WAMIT%SS_Exctn%N ! Loop through all active (enabled) DOFs - dXdx(i, j) = p%WAMIT%SS_Exctn%A(i,j) + if ( p%WAMIT(1)%SS_Exctn%N > 0 ) then + do j=1,p%WAMIT(1)%SS_Exctn%N + do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all active (enabled) DOFs + dXdx(i, j) = p%WAMIT(1)%SS_Exctn%A(i,j) end do end do end if - if ( p%WAMIT%SS_Rdtn%N > 0 ) then - do j=1,p%WAMIT%SS_Rdtn%N - do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all active (enabled) DOFs - dXdx(i+p%WAMIT%SS_Exctn%N, j+p%WAMIT%SS_Exctn%N) = p%WAMIT%SS_Rdtn%A(i,j) + if ( p%WAMIT(1)%SS_Rdtn%N > 0 ) then + do j=1,p%WAMIT(1)%SS_Rdtn%N + do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all active (enabled) DOFs + dXdx(i+p%WAMIT(1)%SS_Exctn%N, j+p%WAMIT(1)%SS_Exctn%N) = p%WAMIT(1)%SS_Rdtn%A(i,j) end do end do end if @@ -2909,7 +2915,7 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" indx = 1 - NN = p%WAMIT%SS_Rdtn%N + p%WAMIT%SS_Exctn%N + NN = p%WAMIT(1)%SS_Rdtn%N + p%WAMIT(1)%SS_Exctn%N if ( NN == 0 ) return ! allocate space for the row/column names and for perturbation sizes call allocAry(p%dx, NN, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2922,12 +2928,12 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) ! set perturbation sizes: p%dx - do i = 1, p%WAMIT%SS_Exctn%N + do i = 1, p%WAMIT(1)%SS_Exctn%N p%dx(i) = 20000.0_R8Ki * D2R_D end do - do i = 1, p%WAMIT%SS_Rdtn%N - p%dx(i+p%WAMIT%SS_Exctn%N) = 2.0_R8Ki * D2R_D + do i = 1, p%WAMIT(1)%SS_Rdtn%N + p%dx(i+p%WAMIT(1)%SS_Exctn%N) = 2.0_R8Ki * D2R_D end do modLabels = (/'Exctn ','Rdtn '/) @@ -2940,9 +2946,9 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) do j = 1, 6 if (k == 1) then - spdof = p%WAMIT%SS_Exctn%spdof(j) + spdof = p%WAMIT(1)%SS_Exctn%spdof(j) else - spdof = p%WAMIT%SS_Rdtn%spdof(j) + spdof = p%WAMIT(1)%SS_Rdtn%spdof(j) end if do i = 1,spdof @@ -3277,12 +3283,12 @@ SUBROUTINE HD_Perturb_x( p, n, perturb_sign, x, dx ) dx = p%dx(n) - if (n > p%WAMIT%SS_Exctn%N) then - indx = n - p%WAMIT%SS_Exctn%N - x%WAMIT%SS_Rdtn%x( indx ) = x%WAMIT%SS_Rdtn%x( indx ) + dx * perturb_sign + if (n > p%WAMIT(1)%SS_Exctn%N) then + indx = n - p%WAMIT(1)%SS_Exctn%N + x%WAMIT(1)%SS_Rdtn%x( indx ) = x%WAMIT(1)%SS_Rdtn%x( indx ) + dx * perturb_sign else indx = n - x%WAMIT%SS_Exctn%x( indx ) = x%WAMIT%SS_Exctn%x( indx ) + dx * perturb_sign + x%WAMIT(1)%SS_Exctn%x( indx ) = x%WAMIT(1)%SS_Exctn%x( indx ) + dx * perturb_sign end if END SUBROUTINE HD_Perturb_x @@ -3439,16 +3445,16 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, IF ( PRESENT( x_op ) ) THEN if (.not. allocated(x_op)) then - call AllocAry(x_op, p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N,'x_op',ErrStat2,ErrMsg2) + call AllocAry(x_op, p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N,'x_op',ErrStat2,ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) return end if - do i=1,p%WAMIT%SS_Exctn%N ! Loop through all DOFs - x_op(i) = x%WAMIT%SS_Exctn%x(i) + do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all DOFs + x_op(i) = x%WAMIT(1)%SS_Exctn%x(i) end do - do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all DOFs - x_op(i+p%WAMIT%SS_Exctn%N) = x%WAMIT%SS_Rdtn%x(i) + do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all DOFs + x_op(i+p%WAMIT(1)%SS_Exctn%N) = x%WAMIT(1)%SS_Rdtn%x(i) end do END IF @@ -3457,7 +3463,7 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, IF ( PRESENT( dx_op ) ) THEN if (.not. allocated(dx_op)) then - call AllocAry(dx_op, p%WAMIT%SS_Exctn%N+p%WAMIT%SS_Rdtn%N,'dx_op',ErrStat2,ErrMsg2) + call AllocAry(dx_op, p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N,'dx_op',ErrStat2,ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) return end if @@ -3469,11 +3475,11 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, return end if - do i=1,p%WAMIT%SS_Exctn%N ! Loop through all DOFs - dx_op(i) = dx%WAMIT%SS_Exctn%x(i) + do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all DOFs + dx_op(i) = dx%WAMIT(1)%SS_Exctn%x(i) end do - do i=1,p%WAMIT%SS_Rdtn%N ! Loop through all DOFs - dx_op(i+p%WAMIT%SS_Exctn%N) = dx%WAMIT%SS_Rdtn%x(i) + do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all DOFs + dx_op(i+p%WAMIT(1)%SS_Exctn%N) = dx%WAMIT(1)%SS_Rdtn%x(i) end do call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 66c306943..fe020501f 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -187,6 +187,7 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER NWaveElev - - - "Number of wave elevation outputs" - typedef ^ ^ SiKi WaveElev {:}{:} - - "Total wave elevation" - typedef ^ ^ SiKi WaveElev1 {:}{:} - - "First order wave elevation" - +typedef ^ ^ ReKi WtrDpth - - - "Water depth" (m) typedef ^ ^ ReKi AddF0 {:}{:} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - typedef ^ ^ ReKi AddCLin {:}{:}{:} - - "Additional stiffness matrix" - typedef ^ ^ ReKi AddBLin {:}{:}{:} - - "Additional linear damping matrix" - From 6bb18369d09f44ef5a0ff49623509d42b0b64f5f Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 26 Sep 2019 07:10:35 -0600 Subject: [PATCH 006/377] Merge cleanup cleanup of some merged code --- modules/hydrodyn/src/WAMIT.f90 | 79 ++++++++++------------------------ modules/hydrodyn/src/WAMIT.txt | 4 +- 2 files changed, 24 insertions(+), 59 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index a31162074..ce64ada63 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -863,27 +863,17 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init SELECT CASE ( InitInp%WaveMod ) ! Which incident wave kinematics model are we using? CASE ( 0 ) if ( p%ExctnMod == 1 ) then - ! Initialize everything to zero: - ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6) , STAT=ErrStat2 ) + ! Initialize everything to zero: + + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() RETURN END IF - - - ! Initialize everything to zero: - - ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) - IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') - CALL Cleanup() - RETURN - END IF - - p%WaveExctn = 0.0 + p%WaveExctn = 0.0 else if ( p%ExctnMod == 2 ) then Interval_Sub = InitInp%Conv_Rdtn%RdtnDT @@ -936,14 +926,14 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! ALLOCATE the arrays: - ALLOCATE ( WaveExctnC(0:InitInp%NStepWave2 ,6) , STAT=ErrStat2 ) + ALLOCATE ( WaveExctnC(0:InitInp%NStepWave2 ,6*p%NBody) , STAT=ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctnC array.', ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() RETURN END IF - ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6) , STAT=ErrStat2 ) + ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() @@ -951,30 +941,21 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END IF - ALLOCATE ( WaveExctnC(0:InitInp%NStepWave2 ,6*p%NBody) , STAT=ErrStat2 ) - IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctnC array.', ErrStat, ErrMsg, 'WAMIT_Init') - CALL Cleanup() - RETURN - END IF - ALLOCATE ( p%WaveExctn (0:InitInp%NStepWave,6*p%NBody) , STAT=ErrStat2 ) - IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the WaveExctn array.', ErrStat, ErrMsg, 'WAMIT_Init') - CALL Cleanup() - RETURN - END IF + ! Compute the positive-frequency components (including zero) of the discrete + ! Fourier transform of the wave excitation force: DO I = 0,InitInp%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transform ! Compute the frequency of this component: Omega = I*InitInp%WaveDOmega + ! Compute the discrete Fourier transform of the instantaneous value of the ! total excitation force on the support platfrom from incident waves: - DO J = 1,6 ! Loop through all wave excitation forces and moments + DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments TmpCoord(1) = Omega TmpCoord(2) = InitInp%WaveDirArr(I) CALL WAMIT_Interp2D_Cplx( TmpCoord, HdroExctn(:,:,J), HdroFreq, HdroWvDir, LastInd2, WaveExctnC(I,J), ErrStat2, ErrMsg2 ) @@ -987,23 +968,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init END DO ! J - All wave excitation forces and moments - ! Compute the discrete Fourier transform of the instantaneous value of the - ! total excitation force on the support platfrom from incident waves: - - DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments - TmpCoord(1) = Omega - TmpCoord(2) = InitInp%WaveDirArr(I) - CALL WAMIT_Interp2D_Cplx( TmpCoord, HdroExctn(:,:,J), HdroFreq, HdroWvDir, LastInd2, WaveExctnC(I,J), ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - WaveExctnC(I,J) = WaveExctnC(I,J) * CMPLX(InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I)) - END DO ! J - All wave excitation forces and moments - - - END DO ! I - The positive frequency components (including zero) of the discrete Fourier transform + END DO ! I - The positive frequency components (including zero) of the discrete Fourier transform @@ -1048,13 +1013,13 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF - DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments - CALL ApplyFFT_cx ( p%WaveExctn(0:InitInp%NStepWave-1,J), WaveExctnC(:,J), FFT_Data, ErrStat2 ) - CALL SetErrStat( ErrStat2, ' An error occured while applying an FFT to WaveExctnC.', ErrStat, ErrMsg, 'WAMIT_Init') - IF ( ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - END IF + DO J = 1,6*p%NBody ! Loop through all wave excitation forces and moments + CALL ApplyFFT_cx ( p%WaveExctn(0:InitInp%NStepWave-1,J), WaveExctnC(:,J), FFT_Data, ErrStat2 ) + CALL SetErrStat( ErrStat2, ' An error occured while applying an FFT to WaveExctnC.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF ! Append first datpoint as the last as aid for repeated wave data p%WaveExctn(InitInp%NStepWave,J) = p%WaveExctn(0,J) @@ -1551,10 +1516,10 @@ SUBROUTINE WAMIT_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, E RETURN END IF - DO I = 1,6*p%NBody ! Loop through all wave excitation forces and moments - m%F_Waves1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn(:,I), & - m%LastIndWave, p%NStepWave + 1 ) - END DO ! I - All wave excitation forces and moments + DO I = 1,6*p%NBody ! Loop through all wave excitation forces and moments + m%F_Waves1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + END DO ! I - All wave excitation forces and moments else if ( p%ExctnMod == 2 ) then call SS_Exc_CalcOutput( Time, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, & diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index 63ee7c34e..d0a7c2f66 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -118,7 +118,7 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi HdroAdMsI {:}{:} - - "" (sec) typedef ^ ^ ReKi HdroSttc {:}{:} - - "" - typedef ^ ^ INTEGER RdtnMod - - - "" - -typedef ^ ^ INTEGER ExctnMod - - - "" - +typedef ^ ^ INTEGER ExctnMod - - - "" - typedef ^ ^ SiKi WaveExctn {:}{:} - - "" - typedef ^ ^ INTEGER NStepWave - - - "" - typedef ^ ^ Conv_Rdtn_ParameterType Conv_Rdtn - - - "" - @@ -133,7 +133,7 @@ typedef ^ ^ LOGICAL typedef ^ ^ LOGICAL PtfmYF - - - "" - typedef ^ ^ OutParmType OutParam {:} - - "" - typedef ^ ^ INTEGER NumOuts - - - "" - -typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - typedef ^ ^ CHARACTER(20) OutFmt - - - "" - typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - typedef ^ ^ CHARACTER(10) Delim - - - "" - From ff6140654102f1efe246fa0c89b5d61f81aa1d00 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 26 Sep 2019 07:12:09 -0600 Subject: [PATCH 007/377] Reordered Input file parsing Added back ExctnMod and reordered some values per Jason's request --- modules/hydrodyn/src/HydroDyn_Input.f90 | 93 +++++++++++++------------ 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index ac371b6cf..dc0107871 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -810,6 +810,53 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) RETURN END IF + ! ExctnMod - Wave Excitation model {0: None, 1: DFT, 2: state-space} (switch) + ! [STATE-SPACE REQUIRES *.ssexctn INPUT FILE] + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%ExctnMod, 'ExctnMod', & + 'Wave Excitation model', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + ! RdtnMod - Radiation memory-effect model {1: convolution, 2: state-space} (switch) + ! [STATE-SPACE REQUIRES *.ss INPUT FILE] + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnMod, 'RdtnMod', & + 'Radiation memory-effect model', ErrStat2, ErrMsg2, UnEchoLocal ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! RdtnTMax - Analysis time for wave radiation kernel calculations + ! NOTE: Use RdtnTMax = 0.0 to eliminate wave radiation damping + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnTMax, 'RdtnTMax', & + 'Analysis time for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + + + ! RdtnDT - Time step for wave radiation kernel calculations + + + CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%Conv_Rdtn%RdtnDTChr, 'RdtnDT', 'Time step for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF + ! NBody - Number of WAMIT bodies to be used (-) [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data ! contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there ! are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] @@ -948,52 +995,6 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) RETURN END IF - ! ExctnMod - Wave Excitation model {0: None, 1: DFT, 2: state-space} (switch) - ! [STATE-SPACE REQUIRES *.ssexctn INPUT FILE] - - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%ExctnMod, 'ExctnMod', & - 'Wave Excitation model', ErrStat2, ErrMsg2, UnEchoLocal ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - ! RdtnMod - Radiation memory-effect model {1: convolution, 2: state-space} (switch) - ! [STATE-SPACE REQUIRES *.ss INPUT FILE] - - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnMod, 'RdtnMod', & - 'Radiation memory-effect model', ErrStat2, ErrMsg2, UnEchoLocal ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - - ! RdtnTMax - Analysis time for wave radiation kernel calculations - ! NOTE: Use RdtnTMax = 0.0 to eliminate wave radiation damping - - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%RdtnTMax, 'RdtnTMax', & - 'Analysis time for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - - ! RdtnDT - Time step for wave radiation kernel calculations - - - CALL ReadVar ( UnIn, FileName, InitInp%WAMIT%Conv_Rdtn%RdtnDTChr, 'RdtnDT', 'Time step for wave radiation kernel calculations', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF !bjj: should we add this? From bee7284c2671ddb491e3ea1b8dba29f8fd96b334 Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Tue, 1 Oct 2019 17:50:50 -0600 Subject: [PATCH 008/377] Minor comment edits --- modules/hydrodyn/src/Morison.f90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 75553bbc0..051fd081d 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -528,7 +528,8 @@ SUBROUTINE DistrMGLoads(MGdens, g, R, tMG, F_MG ) END SUBROUTINE DistrMGLoads -SUBROUTINE DistrDragConst( densWater, Cd, R, tMG, DragConst ) +SUBROUTINE DistrDragConst( densWater, Cd, R, tMG, DragConst ) !@mhall: is there any reason to have this function? + ! It's only called once and it's a simple multiplication. ! This is used to minimize the computations which occur at each timestep @@ -1005,8 +1006,8 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen TYPE(MeshType), INTENT ( INOUT ) :: outDistribMesh REAL(ReKi), INTENT ( IN ) :: L_F_B(:,:) ! Lumped buoyancy force associated with the member REAL(ReKi), INTENT ( IN ) :: L_F_BF(:,:) ! Lumped buoyancy force associated flooded/filled fluid within the member - REAL(ReKi), INTENT ( IN ) :: D_F_B(:,:) ! Lumped buoyancy force associated with the member - REAL(ReKi), INTENT ( IN ) :: D_F_BF(:,:) ! Lumped buoyancy force associated flooded/filled fluid within the member + REAL(ReKi), INTENT ( IN ) :: D_F_B(:,:) ! Distributed buoyancy force associated with the member + REAL(ReKi), INTENT ( IN ) :: D_F_BF(:,:) ! Distributed buoyancy force associated flooded/filled fluid within the member REAL(ReKi), INTENT ( IN ) :: D_F_MG(:,:) REAL(ReKi), INTENT ( IN ) :: g ! gravity !INTEGER, INTENT ( IN ) :: numDistribMarkers @@ -4609,7 +4610,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, IF (I < 4 ) THEN ! We are now combining the dynamic pressure term into the inertia term m%D_F_AM_MG(I,J) = -p%D_AM_MG(J)*u%DistribMesh%TranslationAcc(I,J) - m%D_F_AM_F(:,J) = -p%D_AM_F(J)*u%DistribMesh%TranslationAcc(I,J) + m%D_F_AM_F(:,J) = -p%D_AM_F(J)*u%DistribMesh%TranslationAcc(I,J) !@mhall: should D_F_AM_F(:,J) be D_F_AM_F(I,J) ? m%D_F_AM(I,J) = m%D_F_AM_M(I,J) + m%D_F_AM_MG(I,J) + m%D_F_AM_F(I,J) m%D_F_D(I,J) = elementWaterState * vmag*v(I) * p%D_dragConst(J) m%D_F_B(I,J) = elementWaterState * p%D_F_B(I,J) From 56e2db613298a8ffbb8016196535f2331d1624bf Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 7 Oct 2019 13:15:05 -0600 Subject: [PATCH 009/377] Added InitInputs to support calculation of Wave Number --- modules/hydrodyn/src/WAMIT.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index d0a7c2f66..c7d732bd1 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -18,8 +18,10 @@ usefrom SS_Radiation.txt usefrom SS_Excitation.txt usefrom Waves.txt param WAMIT/WAMIT unused INTEGER MaxWAMITOutputs - 18 - "" - -typedef ^ InitInputType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - -typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ InitInputType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ ReKi Gravity - - - "Supplied by Driver: Gravitational acceleration" "(m/s^2)" +typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m typedef ^ ^ ReKi PtfmVol0 {:} - - "" - typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - typedef ^ ^ ReKi WAMITULEN - - - "" - From e4a137e93ac9a336228df05094b43f2234485271 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 7 Oct 2019 13:18:07 -0600 Subject: [PATCH 010/377] Code review bug fixes and Wave Excitation force corrections --- modules/hydrodyn/src/HydroDyn.f90 | 22 +++--- modules/hydrodyn/src/HydroDyn.txt | 2 +- modules/hydrodyn/src/HydroDyn_Input.f90 | 55 ++++++--------- modules/hydrodyn/src/WAMIT.f90 | 94 ++++++++++++++++++------- 4 files changed, 100 insertions(+), 73 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 70fa6acdd..cf64d31b5 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -850,6 +850,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I p%nWAMITObj = InitLocal%nWAMITObj ! All the data for the various WAMIT bodies are stored in a single WAMIT file p%vecMultiplier = InitLocal%vecMultiplier ! Multiply all vectors and matrices row/column lengths by NBody InitLocal%WAMIT%NBodyMod = InitLocal%NBodyMod + InitLocal%WAMIT%Gravity = InitLocal%Gravity + InitLocal%WAMIT%WtrDpth = InitLocal%Morison%WtrDpth ! The data in InitLocal%Morison%WtrDpth was directly placed there when we parsed the HydroDyn input file p%NBody = InitLocal%NBody p%NBodyMod = InitLocal%NBodyMod @@ -970,16 +972,16 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Compute the load contribution from hydrostatics: IF ( InitLocal%UnSum > 0 ) THEN do iBody = 1, InitLocal%NBody - WRITE( InitLocal%UnSum, '(A18,I5)') 'WAMIT Model - Body',iBody - WRITE( InitLocal%UnSum, '(A18)') '------------------' - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', InitLocal%PtfmVol0(iBody) - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', InitLocal%PtfmCOBxt(iBody) - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', InitLocal%PtfmCOByt(iBody) - WRITE( InitLocal%UnSum, '(/)' ) - WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' - WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody),InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOByt(iBody), -InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOBxt(iBody), 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point + WRITE( InitLocal%UnSum, '(A18,I5)') 'WAMIT Model - Body',iBody + WRITE( InitLocal%UnSum, '(A18)') '------------------' + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', InitLocal%PtfmVol0(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', InitLocal%PtfmCOBxt(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', InitLocal%PtfmCOByt(iBody) + WRITE( InitLocal%UnSum, '(/)' ) + WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody),InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOByt(iBody), -InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOBxt(iBody), 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point end do END IF diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index fe020501f..e5fc2af70 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -158,7 +158,7 @@ typedef ^ ^ INTEGER typedef ^ ^ DbKi LastOutTime - - - "Last time step which was written to the output file (sec)" - typedef ^ ^ INTEGER LastIndWave - - - "The last index used in the wave kinematics arrays, used to optimize interpolation" - typedef ^ ^ ReKi F_PtfmAdd {:} - - "The total forces and moments due to additional pre-load, stiffness, and damping" - -typedef ^ ^ ReKi F_Hydro {6} - - "The total hydrodynamic forces and moments integrated about the WAMIT reference point" - +typedef ^ ^ ReKi F_Hydro {6} - - "The total hydrodynamic forces and moments integrated about the (0,0,0) platform reference point" - typedef ^ ^ ReKi F_Waves {:} - - "The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules)" - typedef ^ ^ WAMIT_MiscVarType WAMIT {:} - - "misc var information from the WAMIT module" - typedef ^ ^ WAMIT2_MiscVarType WAMIT2 - - - "misc var information from the WAMIT2 module" - diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index dc0107871..282a829b7 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -882,12 +882,13 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! PotFile - Root name of Potential flow data files (Could be WAMIT files or the FIT input file) ! allocate space for the WAMIT-related data arrays: - InitInp%nWAMITObj = InitInp%NBody - InitInp%vecMultiplier = 1 if ( InitInp%NBodyMod == 1 ) then InitInp%nWAMITObj = 1 ! Special case where all data in a single WAMIT input file as opposed to InitInp%NBody number of separate input files. InitInp%vecMultiplier = InitInp%NBody + else + InitInp%nWAMITObj = InitInp%NBody + InitInp%vecMultiplier = 1 end if CALL AllocAry( InitInp%PotFile , InitInp%nWAMITObj, 'PotFile' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) @@ -1167,7 +1168,8 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) !------------------------------------------------------------------------------------------------- ! Floating Platform Additional Stiffness and Damping Section !------------------------------------------------------------------------------------------------- - + ! If NBodyMod = 1 then vecMultiplier = NBody and nWAMITObj = 1 + ! Else vecMultiplier = 1 and nWAMITObj = NBody CALL AllocAry( InitInp%AddF0, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddF0' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL AllocAry( InitInp%AddCLin, InitInp%vecMultiplier*6, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddCLin' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL AllocAry( InitInp%AddBLin, InitInp%vecMultiplier*6, InitInp%vecMultiplier*6, InitInp%nWAMITObj, 'InitInp%AddBLin' , ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) @@ -1216,7 +1218,7 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) do j = 1, InitInp%nWAMITObj startIndx = 6*InitInp%vecMultiplier*(j-1) + 1 endIndx = startIndx + 6*InitInp%vecMultiplier - 1 - InitInp%AddCLin(I,:,j) = tmpVec2(startIndx:endIndx) + InitInp%AddCLin(i,:,j) = tmpVec2(startIndx:endIndx) end do end do @@ -2308,9 +2310,7 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! OutList - list of requested parameters to output to a file - !CALL ReadOutputList ( UnIn, FileName, InitInp%WAMIT%OutList, InitInp%WAMIT%NumOuts, & - ! 'OutList', 'List of floating platform outputs requested', ErrStat2, ErrMsg2, UnEchoLocal ) - ALLOCATE( InitInp%UserOutputs(2778), Stat=ErrStat2) !todo: bjj: what is this 2778? + ALLOCATE( InitInp%UserOutputs(4526), Stat=ErrStat2) ! Total possible number of output channels: Waves2 = 18 + SS_Excitation = 7 + SS_Radiation = 7 + WAMIT2 = 6 + Morison= 4032 + HydroDyn=456 = 4526 IF (ErrStat2 /= 0) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating UserOutputs.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL CleanUp() @@ -2326,32 +2326,6 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) RETURN END IF - ! - ! - !!------------------------------------------------------------------------------------------------- - !! Data section for MESH-BASED OUTPUTS - !!------------------------------------------------------------------------------------------------- - ! - ! ! Header - ! - !CALL ReadCom( UnIn, FileName, 'Mesh-based Outputs header', ErrStat2, ErrMsg2, UnEchoLocal ) - ! - ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - ! IF (ErrStat >= AbortErrLev) THEN - ! CALL CleanUp() - ! RETURN - ! END IF - ! - ! ! OutList - list of requested parameters to output to a file - ! - !CALL ReadOutputList ( UnIn, FileName, InitInp%Morison%OutList, InitInp%Morison%NumOuts, & - ! 'OutList', 'List of mesh-based outputs requested', ErrStat2, ErrMsg2, UnEchoLocal ) - ! - !CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - !IF (ErrStat >= AbortErrLev) THEN - ! CALL CleanUp() - ! RETURN - !END IF !------------------------------------------------------------------------------------------------- ! This is the end of the input file @@ -3074,7 +3048,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) !TODO: Deal with WAMIT2 and check each WAMITULEN not just the first InitInp%WAMIT2%WAMITULEN = InitInp%WAMITULEN(1) ! Copy to the WAMIT2 module info do i = 1,InitInp%nWAMITObj - IF ( InitInp%WAMITULEN(1) < 0.0 ) THEN + IF ( InitInp%WAMITULEN(i) < 0.0 ) THEN CALL SetErrStat( ErrID_Fatal,'WAMITULEN must be positive.',ErrStat,ErrMsg,RoutineName) RETURN END IF @@ -3102,6 +3076,17 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF + ! PtfmRefzt - The zt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] + ! NOTE: only used when PotMod=1. If NBodyMod=2,PtfmRefzt=0.0 + + IF ( InitInp%PotMod == 1 .and. InitInp%NBodyMod == 2) THEN + do i = 1,InitInp%NBody + IF ( .not. EqualRealNos( InitInp%PtfmRefzt(i), 0.0_ReKi ) THEN + CALL SetErrStat( ErrID_Fatal,'PtfmRefzt must be 0.0 for all WAMIT bodies when NBodyMod=2.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + end do + END IF ! RdtnTMax - Analysis time for wave radiation kernel calculations ! NOTE: Use RdtnTMax = 0.0 to eliminate wave radiation damping @@ -3245,7 +3230,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) !------------------------------------------------------------------------------------------------- ! Second order Forces due to Waves section (WAMIT2 Module) !------------------------------------------------------------------------------------------------- - +!TODO: Add check on NBody > 1 and MnDrift and NewmanApp cannot equal 8 ! Check that we only specified one of MnDrift, NewmanApp, or DiffQTF ! (compared pairwise -- if any two are both true, we have a problem) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index ce64ada63..77086b277 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -151,6 +151,10 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init integer(IntKi) :: iBody ! WAMIT body index real(R8Ki) :: orientation(3,3) ! Initial orientation of the WAMIT body real(R8Ki) :: theta(3) ! Euler angle rotations of the WAMIT body + real(ReKi) :: WaveNmbr ! Frequency-dependent wave number + COMPLEX(SiKi) :: Fxy ! Phase correction term for Wave excitation forces + real(ReKi) :: tmpAngle ! Frequency and heading and platform offset dependent phase shift angle for Euler's Equation e^(-j*tmpAngle) + COMPLEX(SiKi), ALLOCATABLE :: HdroExctn_Local (:,:,:) ! Temporary Frequency- and direction-dependent complex hydrodynamic wave excitation force per unit wave amplitude vector (kg/s^2, kg-m/s^2) ! Error handling CHARACTER(1024) :: ErrMsg2 ! Temporary error message for calls INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls @@ -185,7 +189,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init p%NumOuts = InitInp%NumOuts p%ExctnMod = InitInp%ExctnMod p%NBodyMod = InitInp%NBodyMod - p%NBody = InitInp%NBody + p%NBody = InitInp%NBody ! In the context of this WAMIT object NBody is 1 if NBodyMod > 1 [there are NBody different WAMIT objects in this case] ! This module's implementation requires that if NBodyMod = 2 or 3, then there is one instance of a WAMIT module for each body, therefore, HydroDyn may have NBody > 1, but this WAMIT module will have NBody = 1 if ( (p%NBodyMod > 1) .and. (p%NBody > 1) ) then @@ -194,7 +198,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init end if ! Allocate misc var and parameter vectors/matrices - call AllocAry( p%F_HS_Moment_Offset, 3, p%NBody, 'p%F_HS_Moment_Offset', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call AllocAry( p%F_HS_Moment_Offset, 6, p%NBody, 'p%F_HS_Moment_Offset', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') call AllocAry( m%F_HS , 6*p%NBody, 'm%F_HS' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') call AllocAry( m%F_Waves1 , 6*p%NBody, 'm%F_Waves1' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') call AllocAry( m%F_Rdtn , 6*p%NBody, 'm%F_Rdtn' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') @@ -204,9 +208,12 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init do iBody = 1, p%NBody - p%F_HS_Moment_Offset(1,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody) ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position - p%F_HS_Moment_Offset(2,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOByt(iBody) - InitInp%PtfmRefyt(iBody) ) ! and the moment about X due to the COB being offset from the local WAMIT reference point - p%F_HS_Moment_Offset(3,iBody) = -InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOBxt(iBody) - InitInp%PtfmRefxt(iBody) ) ! and the moment about Y due to the COB being offset from the localWAMIT reference point + p%F_HS_Moment_Offset(1,iBody) = 0.0_ReKi + p%F_HS_Moment_Offset(2,iBody) = 0.0_ReKi + p%F_HS_Moment_Offset(3,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody) ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position + p%F_HS_Moment_Offset(4,iBody) = InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOByt(iBody) - InitInp%PtfmRefyt(iBody) ) ! and the moment about X due to the COB being offset from the local WAMIT reference point + p%F_HS_Moment_Offset(5,iBody) = -InitInp%RhoXg*InitInp%PtfmVol0(iBody)*( InitInp%PtfmCOBxt(iBody) - InitInp%PtfmRefxt(iBody) ) ! and the moment about Y due to the COB being offset from the localWAMIT reference point + p%F_HS_Moment_Offset(6,iBody) = 0.0_ReKi end do @@ -214,8 +221,6 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CALL WrScr ( ' Reading in WAMIT output with root name "'//TRIM(InitInp%WAMITFile)//'".' ) -!TODO: Augment this for NBodyMod = 1 - ! Let's set up the matrices used to redimensionalize the hydrodynamic data ! from WAMIT; all these matrices are symmetric and need to be used with ! element-by-element multiplication, instead of matrix-by-matrix @@ -304,6 +309,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix jSub = mod(J-1,6)+1 +!TODO need to transform this when PtfmRefztRot is nonzero per plan p%HdroSttc (I,J) = TmpData1*SttcDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array ELSE ! We must have reached the end of the file, so stop reading in data @@ -514,7 +520,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix jSub = mod(J-1,6)+1 - +!TODO need to transform these when PtfmRefztRot is nonzero per plan HdroAddMs(SortFreqInd(K),I,J) = TmpData1*RdtnDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array HdroDmpng(SortFreqInd(K),I,J) = TmpData2*RdtnDim(iSub,jSub)*HdroFreq(SortFreqInd(K)) ! Redimensionalize the data and place it at the appropriate location within the array ! END IF @@ -940,8 +946,57 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF + !==================================== + ! Transform the wave excitation coefs + !==================================== + + + if ( p%NBodyMod == 2 ) then + + ! Since NBodyMod = 2, then NBody = 1 for this WAMIT object (this requirement is encoded at the HydroDyn module level) + + allocate ( HdroExctn_Local(NInpFreq, NInpWvDir, 6), STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the HdroExctn_Local array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF - + do K = 1,6 ! Loop through all wave excitation forces and moments + do J = 1, NInpWvDir + TmpCoord(2) = HdroWvDir(J) - InitInp%PtfmRefztRot(1)*R2D ! apply locale Z rotation to heading angle (degrees) + do I = 1, NInpFreq + TmpCoord(1) = HdroFreq(I) + ! Iterpolate to find new coef + call WAMIT_Interp2D_Cplx( TmpCoord, HdroExctn(:,:,K), HdroFreq, HdroWvDir, LastInd2, HdroExctn_Local(I,J,K), ErrStat2, ErrMsg2 ) + end do + end do + end do + + ! Now apply rotation and phase shift + + do J = 1, NInpWvDir + do I = 1, NInpFreq + + ! Fxy = exp(-j * k(w) * ( X*cos(Beta(w)) + Y*sin(Beta(w)) ) + WaveNmbr = WaveNumber ( HdroFreq(I), InitInp%Gravity, InitInp%WtrDpth ) + tmpAngle = WaveNmbr * ( InitInp%PtfmRefxt(1)*cos(HdroWvDir(J)*D2R) + InitInp%PtfmRefyt(1)*sin(HdroWvDir(J)*D2R) ) + TmpRe = cos(tmpAngle) + TmpIm = -sin(tmpAngle) + Fxy = CMPLX( TmpRe, TmpIm ) + + HdroExctn(I,J,1) = Fxy*( HdroExctn_Local(I,J,1)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn_Local(I,J,2)*sin(InitInp%PtfmRefztRot(1)) ) + HdroExctn(I,J,2) = Fxy*( HdroExctn_Local(I,J,1)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn_Local(I,J,2)*cos(InitInp%PtfmRefztRot(1)) ) + HdroExctn(I,J,3) = Fxy*( HdroExctn_Local(I,J,3) ) + HdroExctn(I,J,4) = Fxy*( HdroExctn_Local(I,J,4)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn_Local(I,J,5)*sin(InitInp%PtfmRefztRot(1)) ) + HdroExctn(I,J,5) = Fxy*( HdroExctn_Local(I,J,4)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn_Local(I,J,5)*cos(InitInp%PtfmRefztRot(1)) ) + HdroExctn(I,J,6) = Fxy*( HdroExctn_Local(I,J,6) ) + + end do + end do + deallocate(HdroExctn_Local) + end if + ! Compute the positive-frequency components (including zero) of the discrete ! Fourier transform of the wave excitation force: @@ -1546,8 +1601,8 @@ SUBROUTINE WAMIT_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, E m%F_HS = -matmul(p%HdroSttc,q) do iBody = 1, p%NBody - indxStart = (iBody-1)*6+3 - indxEnd = indxStart+2 + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 m%F_HS(indxStart:indxEnd) = m%F_HS(indxStart:indxEnd) + p%F_HS_Moment_Offset(:,iBody) ! except for the hydrostatic buoyancy force from Archimede's Principle when the support platform is in its undisplaced position end do @@ -1603,22 +1658,7 @@ SUBROUTINE WAMIT_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, E ! Output channels will be dealt with by the HydroDyn module - - !TODO: Clean this up - ! - ! - ! ! Map calculated results into the AllOuts Array - !CALL WMTOut_MapOutputs(Time, p%NBody, p%BodyID, y, m%F_Waves1, m%F_HS, m%F_Rdtn, m%F_PtfmAM, AllOuts, ErrStat, ErrMsg) - ! - ! - ! ! Put the output data in the OutData array - ! - !DO I = 1,p%NumOuts - ! - ! y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) - ! - !END DO - + END SUBROUTINE WAMIT_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- From 4d0cdc6696c61194fc0b0af52583d45fb1ca5927 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:22:06 -0600 Subject: [PATCH 011/377] Fixed some project properties Build for x64 was not running the registry --- vs-build/HydroDyn/HydroDynDriver.vfproj | 38 ++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/vs-build/HydroDyn/HydroDynDriver.vfproj b/vs-build/HydroDyn/HydroDynDriver.vfproj index a10a909e3..9c1315b49 100644 --- a/vs-build/HydroDyn/HydroDynDriver.vfproj +++ b/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -25,7 +25,7 @@ - + @@ -53,7 +53,11 @@ + + + + @@ -62,6 +66,10 @@ + + + + @@ -70,6 +78,10 @@ + + + + @@ -78,6 +90,10 @@ + + + + @@ -96,6 +112,10 @@ + + + + @@ -104,11 +124,19 @@ + + + + + + + + @@ -120,11 +148,19 @@ + + + + + + + + From ff798e09fc5e41b72cd8ece942ae33d7a4b4339b Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:23:55 -0600 Subject: [PATCH 012/377] Added code to transform WAMIT matrices based on Heading Direction --- modules/hydrodyn/src/WAMIT.f90 | 80 +++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 77086b277..1308ca108 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -55,6 +55,42 @@ MODULE WAMIT CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transforms WAMIT input file data from a local (heading-angle, based) coordinate system to the global system. + subroutine TransformWAMITMatrices( NBody, RotZ, M ) +!.................................................................................................................................. + integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) + real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) + real(SiKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + + integer(IntKi) :: i,j,ii,jj,iSub,jSub + real(R8Ki) :: Rj(3,3) + real(R8Ki) :: Ri(3,3) + + do j = 1, NBody + Rj(1,:) = (/ cos(RotZ(j)), sin(RotZ(j)), 0.0_R8Ki/) + Rj(2,:) = (/-sin(RotZ(j)), cos(RotZ(j)), 0.0_R8Ki/) + Rj(3,:) = (/ 0.0_R8Ki , 0.0_R8Ki , 1.0_R8Ki/) + do i = 1, NBody + if ( (.not. EqualRealNos(RotZ(i), 0.0_R8Ki)) .or. (.not. EqualRealNos(RotZ(j), 0.0_R8Ki)) ) then + Ri(1,:) = (/ cos(RotZ(i)), sin(RotZ(i)), 0.0_R8Ki/) + Ri(2,:) = (/-sin(RotZ(i)), cos(RotZ(i)), 0.0_R8Ki/) + Ri(3,:) = (/ 0.0_R8Ki , 0.0_R8Ki , 1.0_R8Ki/) + do jj = 1,2 + jSub = (j-1)*6 + (jj-1)*3 + 1 + do ii = 1,2 + iSub = (i-1)*6 + (ii-1)*3 + 1 + M(iSub:iSub+2,jSub:jSub+2) = matmul( transpose(Ri), matmul( M(iSub:iSub+2,jSub:jSub+2), Rj ) ) + end do + end do + end if + end do + + end do + end subroutine TransformWAMITMatrices + + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -309,7 +345,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix jSub = mod(J-1,6)+1 -!TODO need to transform this when PtfmRefztRot is nonzero per plan + p%HdroSttc (I,J) = TmpData1*SttcDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array ELSE ! We must have reached the end of the file, so stop reading in data @@ -323,7 +359,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CLOSE ( UnWh ) ! Close file. - + ! need to transform p%HdroSttc when PtfmRefztRot is nonzero per plan + call TransformWAMITMatrices( p%NBody, InitInp%PtfmRefztRot, p%HdroSttc ) ! Linear, frequency-dependent hydrodynamic added mass and damping from the ! radiation problem: @@ -542,8 +579,13 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CLOSE ( UnW1 ) ! Close file. - - + ! need to transform HdroAddMs and HdroDmpng when PtfmRefztRot is nonzero per plan + do I = 1, NInpFreq + call TransformWAMITMatrices( p%NBody, InitInp%PtfmRefztRot, HdroAddMs(I,:,:) ) + call TransformWAMITMatrices( p%NBody, InitInp%PtfmRefztRot, HdroDmpng(I,:,:) ) + end do + + ! Linear, frequency- and direction-dependent complex hydrodynamic wave ! excitation force per unit wave amplitude vector from the diffraction ! problem: @@ -1221,7 +1263,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init CALL Cleanup() RETURN END IF - + do iBody = 1, p%NBody theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(iBody)/) @@ -1238,7 +1280,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init , orientation ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - + ! Create the mesh element CALL MeshConstructElement ( u%Mesh & @@ -1248,6 +1290,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init , iBody & ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + end do CALL MeshCommit ( u%Mesh & @@ -1259,23 +1302,20 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init RETURN END IF - - CALL MeshCopy ( SrcMesh = u%Mesh & - ,DestMesh = y%Mesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') + call MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() RETURN - END IF - - + END IF u%Mesh%RemapFlag = .TRUE. y%Mesh%RemapFlag = .TRUE. From b31c2fdfaefe5b3ba1d9ed5a0bdb9fbf312de2cd Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:53:05 -0600 Subject: [PATCH 013/377] Fixed bug with estranged sibling meshes and renamed WAMIT mesh changed HD-level WAMIT-related mesh from %Mesh to %WAMITMesh Fixed bug where I created estranged sibling meshes because I was only using a single u_WAMIT instead of an array in HD. --- modules/hydrodyn/src/HydroDyn.f90 | 370 ++++++++++--------- modules/hydrodyn/src/HydroDyn.txt | 6 +- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 20 +- 3 files changed, 199 insertions(+), 197 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index cf64d31b5..1cfde3507 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -876,6 +876,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I allocate( OtherState%WAMIT(1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( y%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( m%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( m%u_WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%u_WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( InitOut%WAMIT( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT.', ErrStat, ErrMsg, RoutineName ) InitLocal%WAMIT%PtfmVol0 = InitLocal%PtfmVol0 @@ -903,6 +904,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I allocate( OtherState%WAMIT(InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( y%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( m%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT.', ErrStat, ErrMsg, RoutineName ) + allocate( m%u_WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%u_WAMIT.', ErrStat, ErrMsg, RoutineName ) allocate( InitOut%WAMIT( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT.', ErrStat, ErrMsg, RoutineName ) InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (1) InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (1) @@ -915,84 +917,88 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I end if - - ! Copy Waves initialization output into the initialization input type for the WAMIT module + if ( ErrStat >= AbortErrLev ) then + call CleanUp() + return + end if + + ! Copy Waves initialization output into the initialization input type for the WAMIT module - InitLocal%WAMIT%RhoXg = Waves_InitOut%RhoXg - InitLocal%WAMIT%NStepWave = Waves_InitOut%NStepWave - InitLocal%WAMIT%NStepWave2 = Waves_InitOut%NStepWave2 - InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin - InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax - InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega + InitLocal%WAMIT%RhoXg = Waves_InitOut%RhoXg + InitLocal%WAMIT%NStepWave = Waves_InitOut%NStepWave + InitLocal%WAMIT%NStepWave2 = Waves_InitOut%NStepWave2 + InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin + InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax + InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega !<==============TODO Check if this code block is needed ===================== ! Init inputs for the SS_Excitation model (set this just in case it will be used) - InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir - CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) + InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir + CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) !<==============TODO Check if this code block is needed ===================== - ! Temporarily move arrays to init input for WAMIT (save some space) - CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) - CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT%WaveElevC0) - CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT%WaveDirArr) + ! Temporarily move arrays to init input for WAMIT (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT%WaveDirArr) - CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), & - y%WAMIT(1), m%WAMIT(1), Interval, InitOut%WAMIT(1), ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT(1), p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), & + y%WAMIT(1), m%WAMIT(1), Interval, InitOut%WAMIT(1), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF ! For NBodyMod > 1 and NBody > 1, set the body info and init the WAMIT body - do i = 2, p%nWAMITObj - !----------------------------------------- - ! Initialize the WAMIT Calculations - !----------------------------------------- - InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (i) - InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (i) - InitLocal%WAMIT%PtfmRefxt (1) = InitLocal%PtfmRefxt (i) - InitLocal%WAMIT%PtfmRefyt (1) = InitLocal%PtfmRefyt (i) - InitLocal%WAMIT%PtfmRefzt (1) = InitLocal%PtfmRefzt (i) - InitLocal%WAMIT%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(i) - InitLocal%WAMIT%PtfmCOBxt (1) = InitLocal%PtfmCOBxt (i) - InitLocal%WAMIT%PtfmCOByt (1) = InitLocal%PtfmCOByt (i) + do i = 2, p%nWAMITObj + !----------------------------------------- + ! Initialize the WAMIT Calculations + !----------------------------------------- + InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (i) + InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (i) + InitLocal%WAMIT%PtfmRefxt (1) = InitLocal%PtfmRefxt (i) + InitLocal%WAMIT%PtfmRefyt (1) = InitLocal%PtfmRefyt (i) + InitLocal%WAMIT%PtfmRefzt (1) = InitLocal%PtfmRefzt (i) + InitLocal%WAMIT%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(i) + InitLocal%WAMIT%PtfmCOBxt (1) = InitLocal%PtfmCOBxt (i) + InitLocal%WAMIT%PtfmCOByt (1) = InitLocal%PtfmCOByt (i) - CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT, p%WAMIT(i), x%WAMIT(i), xd%WAMIT(i), z%WAMIT, OtherState%WAMIT(i), & - y%WAMIT(i), m%WAMIT(i), Interval, InitOut%WAMIT(i), ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - end do + CALL WAMIT_Init(InitLocal%WAMIT, m%u_WAMIT(i), p%WAMIT(i), x%WAMIT(i), xd%WAMIT(i), z%WAMIT, OtherState%WAMIT(i), & + y%WAMIT(i), m%WAMIT(i), Interval, InitOut%WAMIT(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + end do ! Generate Summary file information for WAMIT module ! Compute the load contribution from hydrostatics: - IF ( InitLocal%UnSum > 0 ) THEN - do iBody = 1, InitLocal%NBody - WRITE( InitLocal%UnSum, '(A18,I5)') 'WAMIT Model - Body',iBody - WRITE( InitLocal%UnSum, '(A18)') '------------------' - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', InitLocal%PtfmVol0(iBody) - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', InitLocal%PtfmCOBxt(iBody) - WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', InitLocal%PtfmCOByt(iBody) - WRITE( InitLocal%UnSum, '(/)' ) - WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' - WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' - WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody),InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOByt(iBody), -InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOBxt(iBody), 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point - end do - END IF + IF ( InitLocal%UnSum > 0 ) THEN + do iBody = 1, InitLocal%NBody + WRITE( InitLocal%UnSum, '(A18,I5)') 'WAMIT Model - Body',iBody + WRITE( InitLocal%UnSum, '(A18)') '------------------' + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Displaced volume (m^3) :', InitLocal%PtfmVol0(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'X-offset of the center of buoyancy (m) :', InitLocal%PtfmCOBxt(iBody) + WRITE( InitLocal%UnSum, '(A42,2X,ES15.6)') 'Y-offset of the center of buoyancy (m) :', InitLocal%PtfmCOByt(iBody) + WRITE( InitLocal%UnSum, '(/)' ) + WRITE( InitLocal%UnSum, '(A81)' ) 'Buoyancy loads from members modelled with WAMIT, summed about ( 0.0, 0.0, 0.0 )' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( InitLocal%UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( InitLocal%UnSum, '(A18,6(2X,ES20.6))') ' External: ',0.0,0.0,InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody),InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOByt(iBody), -InitLocal%WAMIT%RhoXg*InitLocal%PtfmVol0(iBody)*InitLocal%PtfmCOBxt(iBody), 0.0 ! and the moment about Y due to the COB being offset from the WAMIT reference point + end do + END IF - ! Verify that WAMIT_Init() did not request a different Interval! + ! Verify that WAMIT_Init() did not request a different Interval! - IF ( p%DT /= Interval ) THEN - CALL SetErrStat(ErrID_Fatal,'WAMIT Module attempted to change timestep interval, but this is not allowed. WAMIT Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) - CALL CleanUp() - RETURN - END IF + IF ( p%DT /= Interval ) THEN + CALL SetErrStat(ErrID_Fatal,'WAMIT Module attempted to change timestep interval, but this is not allowed. WAMIT Module must use the HydroDyn Interval.',ErrStat,ErrMsg,RoutineName) + CALL CleanUp() + RETURN + END IF ! move arrays back @@ -1402,7 +1408,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Create the input and output meshes associated with lumped load at the WAMIT reference point (WRP) - CALL MeshCreate( BlankMesh = u%Mesh & + CALL MeshCreate( BlankMesh = u%WAMITMesh & ,IOS = COMPONENT_INPUT & ,Nnodes = p%NBody & ,ErrStat = ErrStat2 & @@ -1427,7 +1433,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I orientation = EulerConstruct(theta) ! Create the node on the mesh - CALL MeshPositionNode (u%Mesh & + CALL MeshPositionNode (u%WAMITMesh & , iBody & , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & , ErrStat2 & @@ -1441,7 +1447,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I END IF ! Create the mesh element - CALL MeshConstructElement ( u%Mesh & + CALL MeshConstructElement ( u%WAMITMesh & , ELEMENT_POINT & , ErrStat2 & , ErrMsg2 & @@ -1455,7 +1461,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I end do - CALL MeshCommit ( u%Mesh & + CALL MeshCommit ( u%WAMITMesh & , ErrStat2 & , ErrMsg2 ) @@ -1467,8 +1473,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I - CALL MeshCopy ( SrcMesh = u%Mesh & - ,DestMesh = y%Mesh & + CALL MeshCopy ( SrcMesh = u%WAMITMesh & + ,DestMesh = y%WAMITMesh & ,CtrlCode = MESH_SIBLING & ,IOS = COMPONENT_OUTPUT & ,ErrStat = ErrStat2 & @@ -1476,16 +1482,16 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ,Force = .TRUE. & ,Moment = .TRUE. ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%Mesh') + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() RETURN END IF - u%Mesh%RemapFlag = .TRUE. - y%Mesh%RemapFlag = .TRUE. + u%WAMITMesh%RemapFlag = .TRUE. + y%WAMITMesh%RemapFlag = .TRUE. !TODO: Deal with AllHdroOrigin - CALL MeshCopy ( SrcMesh = y%Mesh & + CALL MeshCopy ( SrcMesh = y%WAMITMesh & ,DestMesh = y%AllHdroOrigin & ,CtrlCode = MESH_NEWCOPY & ,IOS = COMPONENT_OUTPUT & @@ -1502,7 +1508,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I y%AllHdroOrigin%RemapFlag = .TRUE. ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = u%Mesh & + CALL MeshCopy ( SrcMesh = u%WAMITMesh & , DestMesh = m%AllHdroOrigin_position & , CtrlCode = MESH_NEWCOPY & , IOS = COMPONENT_INPUT & @@ -1537,7 +1543,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I END IF ! TODO: Deal with Mesh ! Create some mesh mapping data - CALL MeshCopy ( SrcMesh = y%Mesh & + CALL MeshCopy ( SrcMesh = y%WAMITMesh & ,DestMesh = m%y_mapped & ,CtrlCode = MESH_NEWCOPY & ,IOS = COMPONENT_OUTPUT & @@ -1549,7 +1555,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) m%y_mapped%RemapFlag = .TRUE. - CALL MeshMapCreate( y%Mesh, m%y_mapped, m%HD_MeshMap%HD_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL MeshMapCreate( y%WAMITMesh, m%y_mapped, m%HD_MeshMap%HD_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF ( y%Morison%LumpedMesh%Committed ) THEN CALL MeshMapCreate( y%Morison%LumpedMesh, m%y_mapped, m%HD_MeshMap%M_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ENDIF @@ -1771,7 +1777,7 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt ! For this NBodyMod or NBody=1, there is only one WAMIT object, so copy the necessary inputs and then call WAMIT_UpdateStates do I=1,nTime ! Copy the inputs from the HD mesh into the WAMIT mesh - call MeshCopy( Inputs(I)%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call MeshCopy( Inputs(I)%WAMITMesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) end do if (ErrStat < AbortErrLev) then ! if there was an error copying the input meshes, we'll skip this step and then cleanup the temporary input meshes @@ -1785,24 +1791,20 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt else ! We have multiple WAMIT objects - - - do I=1,nTime - ! We need to create to valid mesh data structures in our Inputs_WAMIT(I)%Mesh using the miscvar version as a template, but the actually data will be generated below - call MeshCopy( m%u_WAMIT%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - end do - + ! Loop over number of inputs and copy them into an array of WAMIT inputs do iWAMIT = 1, p%nWAMITObj do I=1,nTime - ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh - Inputs_WAMIT(I)%Mesh%TranslationDisp(:,1) = Inputs(I)%Mesh%TranslationDisp(:,iWAMIT) - Inputs_WAMIT(I)%Mesh%Orientation (:,:,1)= Inputs(I)%Mesh%Orientation (:,:,iWAMIT) - Inputs_WAMIT(I)%Mesh%TranslationVel (:,1) = Inputs(I)%Mesh%TranslationVel (:,iWAMIT) - Inputs_WAMIT(I)%Mesh%RotationVel (:,1) = Inputs(I)%Mesh%RotationVel (:,iWAMIT) - Inputs_WAMIT(I)%Mesh%TranslationAcc (:,1) = Inputs(I)%Mesh%TranslationAcc (:,iWAMIT) - Inputs_WAMIT(I)%Mesh%RotationAcc (:,1) = Inputs(I)%Mesh%RotationAcc (:,iWAMIT) + ! We need to create to valid mesh data structures in our Inputs_WAMIT(I)%Mesh using the miscvar version as a template, but the actually data will be generated below + call MeshCopy( m%u_WAMIT(iWAMIT)%Mesh, Inputs_WAMIT(I)%Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! We need to copy the iWAMIT-th node data from the Inputs(I)%WAMITMesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + Inputs_WAMIT(I)%Mesh%TranslationDisp(:,1) = Inputs(I)%WAMITMesh%TranslationDisp(:,iWAMIT) + Inputs_WAMIT(I)%Mesh%Orientation (:,:,1)= Inputs(I)%WAMITMesh%Orientation (:,:,iWAMIT) + Inputs_WAMIT(I)%Mesh%TranslationVel (:,1) = Inputs(I)%WAMITMesh%TranslationVel (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%RotationVel (:,1) = Inputs(I)%WAMITMesh%RotationVel (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%TranslationAcc (:,1) = Inputs(I)%WAMITMesh%TranslationAcc (:,iWAMIT) + Inputs_WAMIT(I)%Mesh%RotationAcc (:,1) = Inputs(I)%WAMITMesh%RotationAcc (:,iWAMIT) end do ! UpdateStates for the iWAMIT-th body @@ -1838,13 +1840,13 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt ! Copy the inputs from the HD mesh into the FIT input variables ! Determine the rotational angles from the direction-cosine matrix - rotdisp = GetSmllRotAngs ( Inputs(I)%Mesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) + rotdisp = GetSmllRotAngs ( Inputs(I)%WAMITMesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) Inputs_FIT(I)%roll = rotdisp(1) Inputs_FIT(I)%pitch = rotdisp(2) Inputs_FIT(I)%yaw = rotdisp(3) - Inputs_FIT(I)%si_t(:) = Inputs(I)%Mesh%TranslationDisp(:,1) - Inputs_FIT(I)%vel_t(:) = Inputs(I)%Mesh%TranslationVel (:,1) + Inputs_FIT(I)%si_t(:) = Inputs(I)%WAMITMesh%TranslationDisp(:,1) + Inputs_FIT(I)%vel_t(:) = Inputs(I)%WAMITMesh%TranslationVel (:,1) END DO @@ -1875,7 +1877,7 @@ END SUBROUTINE HydroDyn_UpdateStates SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds - TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at Time (note that this is intent out because we're copying the u%mesh into m%u_wamit%mesh) + TYPE(HydroDyn_InputType), INTENT(INOUT) :: u !< Inputs at Time (note that this is intent out because we're copying the u%WAMITMesh into m%u_wamit%mesh) TYPE(HydroDyn_ParameterType), INTENT(IN ) :: p !< Parameters TYPE(HydroDyn_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time TYPE(HydroDyn_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time @@ -1935,14 +1937,14 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, !TODO: Check that we have valid Mesh data? do iBody = 1, p%NBody ! Determine the rotational angles from the direction-cosine matrix - rotdisp = GetSmllRotAngs ( u%Mesh%Orientation(:,:,iBody), ErrStat2, ErrMsg2 ) + rotdisp = GetSmllRotAngs ( u%WAMITMesh%Orientation(:,:,iBody), ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) indxStart = (iBody-1)*6+1 indxEnd = indxStart+5 - q (indxStart:indxEnd) = reshape((/real(u%Mesh%TranslationDisp(:,iBody),ReKi),rotdisp(:)/),(/6/)) - qdot (indxStart:indxEnd) = reshape((/u%Mesh%TranslationVel(:,iBody),u%Mesh%RotationVel(:,iBody)/),(/6/)) + q (indxStart:indxEnd) = reshape((/real(u%WAMITMesh%TranslationDisp(:,iBody),ReKi),rotdisp(:)/),(/6/)) + qdot (indxStart:indxEnd) = reshape((/u%WAMITMesh%TranslationVel(:,iBody),u%WAMITMesh%RotationVel(:,iBody)/),(/6/)) qdotsq (indxStart:indxEnd) = abs(qdot(indxStart:indxEnd))*qdot(indxStart:indxEnd) - qdotdot(indxStart:indxEnd) = reshape((/u%Mesh%TranslationAcc(:,iBody),u%Mesh%RotationAcc(:,iBody)/),(/6/)) + qdotdot(indxStart:indxEnd) = reshape((/u%WAMITMesh%TranslationAcc(:,iBody),u%WAMITMesh%RotationAcc(:,iBody)/),(/6/)) end do !FIXME: Error handling appears to be broken here. if ( p%NBodyMod == 1 ) then @@ -1952,8 +1954,8 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, do iBody = 1, p%NBody indxStart = (iBody-1)*6+1 ! Attach to the output point mesh - y%Mesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) - y%Mesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) + y%WAMITMesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) + y%WAMITMesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) end do else @@ -1964,28 +1966,28 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, m%F_PtfmAdd(indxStart:indxEnd) = p%AddF0(:,1) - matmul(p%AddCLin(:,:,iBody), q(indxStart:indxEnd)) - matmul(p%AddBLin(:,:,iBody), qdot(indxStart:indxEnd)) - matmul(p%AddBQuad(:,:,iBody), qdotsq(indxStart:indxEnd)) ! Attach to the output point mesh - y%Mesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) - y%Mesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) + y%WAMITMesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) + y%WAMITMesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) end do end if m%F_Waves = 0.0_ReKi - if ( m%u_WAMIT%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh + if ( m%u_WAMIT(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then ! Copy the inputs from the HD mesh into the WAMIT mesh - call MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call MeshCopy( u%WAMITMesh, m%u_WAMIT(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) if ( ErrStat >= AbortErrLev ) return - call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), & + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(1), p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), & z%WAMIT, OtherState%WAMIT(1), y%WAMIT(1), m%WAMIT(1), ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) do iBody=1,p%NBody - y%Mesh%Force (:,iBody) = y%Mesh%Force (:,iBody) + y%WAMIT(1)%Mesh%Force (:,iBody) - y%Mesh%Moment(:,iBody) = y%Mesh%Moment(:,iBody) + y%WAMIT(1)%Mesh%Moment(:,iBody) + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(1)%Mesh%Force (:,iBody) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(1)%Mesh%Moment(:,iBody) end do ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order @@ -1993,19 +1995,19 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, else do iBody=1,p%NBody - ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh - m%u_WAMIT%Mesh%TranslationDisp(:,1) = u%Mesh%TranslationDisp(:,iBody) - m%u_WAMIT%Mesh%Orientation (:,:,1)= u%Mesh%Orientation (:,:,iBody) - m%u_WAMIT%Mesh%TranslationVel (:,1) = u%Mesh%TranslationVel (:,iBody) - m%u_WAMIT%Mesh%RotationVel (:,1) = u%Mesh%RotationVel (:,iBody) - m%u_WAMIT%Mesh%TranslationAcc (:,1) = u%Mesh%TranslationAcc (:,iBody) - m%u_WAMIT%Mesh%RotationAcc (:,1) = u%Mesh%RotationAcc (:,iBody) + ! We need to copy the iWAMIT-th node data from the Inputs(I)%WAMITMesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + m%u_WAMIT(iBody)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iBody) + m%u_WAMIT(iBody)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iBody) + m%u_WAMIT(iBody)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iBody) + m%u_WAMIT(iBody)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iBody) + m%u_WAMIT(iBody)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iBody) + m%u_WAMIT(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) - call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT, p%WAMIT(iBody), x%WAMIT(iBody), xd%WAMIT(iBody), & + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(iBody), p%WAMIT(iBody), x%WAMIT(iBody), xd%WAMIT(iBody), & z%WAMIT, OtherState%WAMIT(iBody), y%WAMIT(iBody), m%WAMIT(iBody), ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - y%Mesh%Force (:,iBody) = y%Mesh%Force (:,iBody) + y%WAMIT(iBody)%Mesh%Force (:,1) - y%Mesh%Moment(:,iBody) = y%Mesh%Moment(:,iBody) + y%WAMIT(iBody)%Mesh%Moment(:,1) + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(iBody)%Mesh%Force (:,1) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(iBody)%Mesh%Moment(:,1) ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order indxStart = (iBody-1)*6+1 @@ -2020,13 +2022,13 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, Inputs_FIT%roll = rotdisp(1) Inputs_FIT%pitch = rotdisp(2) Inputs_FIT%yaw = rotdisp(3) - Inputs_FIT%si_t(:) = u%Mesh%TranslationDisp(:,1) - Inputs_FIT%vel_t(:) = u%Mesh%TranslationVel (:,1) + Inputs_FIT%si_t(:) = u%WAMITMesh%TranslationDisp(:,1) + Inputs_FIT%vel_t(:) = u%WAMITMesh%TranslationVel (:,1) CALL FIT_CalcOutput( Time, Inputs_FIT, p%FIT, FIT_x, xd%FIT, FIT_z, OtherState%FIT, y%FIT, ErrStat2, ErrMsg2 ) ! Add FIT forces to the HydroDyn output mesh - y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%FIT%F(:) - y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%FIT%M(:) + y%WAMITMesh%Force (:,1) = y%WAMITMesh%Force (:,1) + y%FIT%F(:) + y%WAMITMesh%Moment(:,1) = y%WAMITMesh%Moment(:,1) + y%FIT%M(:) #endif END IF @@ -2035,7 +2037,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, IF ( m%u_WAMIT2%Mesh%Committed ) THEN ! Make sure we are using WAMIT2 / there is a valid mesh ! Copy the inputs from the HD mesh into the WAMIT2 mesh - CALL MeshCopy( u%Mesh, m%u_WAMIT2%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL MeshCopy( u%WAMITMesh, m%u_WAMIT2%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -2045,8 +2047,8 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) ! Add WAMIT2 forces to the HydroDyn output mesh - y%Mesh%Force (:,1) = y%Mesh%Force (:,1) + y%WAMIT2%Mesh%Force (:,1) - y%Mesh%Moment(:,1) = y%Mesh%Moment(:,1) + y%WAMIT2%Mesh%Moment(:,1) + y%WAMITMesh%Force (:,1) = y%WAMITMesh%Force (:,1) + y%WAMIT2%Mesh%Force (:,1) + y%WAMITMesh%Moment(:,1) = y%WAMITMesh%Moment(:,1) + y%WAMIT2%Mesh%Moment(:,1) ! Add the second order WAMIT forces to the first order WAMIT forces for the total (this is just to make the mesh match this misc var) m%F_Waves = m%F_Waves + m%WAMIT2%F_Waves2 @@ -2156,15 +2158,15 @@ SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxd ! Compute the first time derivatives of the continuous states here: - if ( .not. m%u_WAMIT%Mesh%Committed ) return ! Make sure we are using WAMIT / there is a valid mesh + if ( .not. m%u_WAMIT(1)%Mesh%Committed ) return ! Make sure we are using WAMIT / there is a valid mesh if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then ! Copy the inputs from the HD mesh into the WAMIT mesh - call MeshCopy( u%Mesh, m%u_WAMIT%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) + call MeshCopy( u%WAMITMesh, m%u_WAMIT(1)%Mesh, MESH_UPDATECOPY, ErrStat, ErrMsg ) if ( ErrStat >= AbortErrLev ) return - call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), m%WAMIT(1), dxdt%WAMIT(1), ErrStat, ErrMsg ) + call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT(1), p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), z%WAMIT, OtherState%WAMIT(1), m%WAMIT(1), dxdt%WAMIT(1), ErrStat, ErrMsg ) else ! We have multiple WAMIT objects @@ -2172,16 +2174,16 @@ SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxd ! Loop over number of inputs and copy them into an array of WAMIT inputs do iWAMIT = 1, p%nWAMITObj - ! We need to copy the iWAMIT-th node data from the Inputs(I)%Mesh onto the 1st node of the Inputs_WAMIT(I)%Mesh - m%u_WAMIT%Mesh%TranslationDisp(:,1) = u%Mesh%TranslationDisp(:,iWAMIT) - m%u_WAMIT%Mesh%Orientation (:,:,1)= u%Mesh%Orientation (:,:,iWAMIT) - m%u_WAMIT%Mesh%TranslationVel (:,1) = u%Mesh%TranslationVel (:,iWAMIT) - m%u_WAMIT%Mesh%RotationVel (:,1) = u%Mesh%RotationVel (:,iWAMIT) - m%u_WAMIT%Mesh%TranslationAcc (:,1) = u%Mesh%TranslationAcc (:,iWAMIT) - m%u_WAMIT%Mesh%RotationAcc (:,1) = u%Mesh%RotationAcc (:,iWAMIT) - + ! We need to copy the iWAMIT-th node data from the Inputs(I)%WAMITMesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + m%u_WAMIT(iWAMIT)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iWAMIT) + m%u_WAMIT(iWAMIT)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iWAMIT) + m%u_WAMIT(iWAMIT)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iWAMIT) + m%u_WAMIT(iWAMIT)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iWAMIT) + m%u_WAMIT(iWAMIT)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iWAMIT) + m%u_WAMIT(iWAMIT)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iWAMIT) + ! UpdateStates for the iWAMIT-th body - call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT, p%WAMIT(iWAMIT), x%WAMIT(iWAMIT), xd%WAMIT(iWAMIT), z%WAMIT, OtherState%WAMIT(iWAMIT), m%WAMIT(iWAMIT), dxdt%WAMIT(iWAMIT), ErrStat, ErrMsg ) + call WAMIT_CalcContStateDeriv( Time, m%u_WAMIT(iWAMIT), p%WAMIT(iWAMIT), x%WAMIT(iWAMIT), xd%WAMIT(iWAMIT), z%WAMIT, OtherState%WAMIT(iWAMIT), m%WAMIT(iWAMIT), dxdt%WAMIT(iWAMIT), ErrStat, ErrMsg ) if (ErrStat > AbortErrLev) exit end do @@ -2246,12 +2248,12 @@ FUNCTION CalcLoadsAtWRP( y, u, y_mapped, AllHdroOrigin_position, MrsnLumpedMesh_ y%AllHdroOrigin%Force = 0.0 y%AllHdroOrigin%Moment= 0.0 - IF ( y%Mesh%Committed ) THEN + IF ( y%WAMITMesh%Committed ) THEN ! Just transfer the loads because the meshes are at the same location (0,0,0) - y%AllHdroOrigin%Force = y%Mesh%Force - y%AllHdroOrigin%Moment = y%Mesh%Moment + y%AllHdroOrigin%Force = y%WAMITMesh%Force + y%AllHdroOrigin%Moment = y%WAMITMesh%Moment END IF @@ -2856,7 +2858,7 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) p%Jac_ny = p%Jac_ny + y%Morison%LumpedMesh%NNodes * 6 ! 3 Force, Moment, at each node on the lumped loads mesh end if - p%Jac_ny = p%Jac_ny + y%Mesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point + p%Jac_ny = p%Jac_ny + y%WAMITMesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point p%Jac_ny = p%Jac_ny + y%AllHdroOrigin%NNodes * 6 ! 3 Force, Moment, of all HD loads integrated to the origin (0,0,0) p%Jac_ny = p%Jac_ny + p%NumTotalOuts ! WriteOutput values @@ -2882,7 +2884,7 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) index_last = index_next - call PackLoadMesh_Names(y%Mesh, 'PlatformRefPtLoads', InitOut%LinNames_y, index_next) + call PackLoadMesh_Names(y%WAMITMesh, 'PlatformRefPtLoads', InitOut%LinNames_y, index_next) index_last = index_next call PackLoadMesh_Names(y%AllHdroOrigin, 'AllHdroOrigin', InitOut%LinNames_y, index_next) @@ -3004,7 +3006,7 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) nu = nu + u%Morison%LumpedMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node end if - nu = nu + u%Mesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + nu = nu + u%WAMITMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node ! DO NOT Add the extended input WaveElev0 when computing the size of p%Jac_u_indx @@ -3069,15 +3071,15 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) meshFieldCount = meshFieldCount + 6 end if - !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 or 1; - !Module/Mesh/Field: u%Mesh%Orientation = 14 or 2; - !Module/Mesh/Field: u%Mesh%TranslationVel = 15 or 3; - !Module/Mesh/Field: u%Mesh%RotationVel = 16 or 4; - !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 or 5; - !Module/Mesh/Field: u%Mesh%RotationAcc = 18 or 6; + !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 or 1; + !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 or 2; + !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 or 3; + !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 or 4; + !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 or 5; + !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 or 6; do i_meshField = 1,6 - do i=1,u%Mesh%NNodes + do i=1,u%WAMITMesh%NNodes do j=1,3 p%Jac_u_indx(index,1) = meshFieldCount + i_meshField p%Jac_u_indx(index,2) = j !index: j @@ -3124,12 +3126,12 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) end if - p%du(index + 1) = perturb_t ! u%Mesh%TranslationDisp - p%du(index + 2) = perturb ! u%Mesh%Orientation - p%du(index + 3) = perturb_t ! u%Mesh%TranslationVel - p%du(index + 4) = perturb ! u%Mesh%RotationVel - p%du(index + 5) = perturb_t ! u%Mesh%TranslationAcc - p%du(index + 6) = perturb ! u%Mesh%RotationAcc + p%du(index + 1) = perturb_t ! u%WAMITMesh%TranslationDisp + p%du(index + 2) = perturb ! u%WAMITMesh%Orientation + p%du(index + 3) = perturb_t ! u%WAMITMesh%TranslationVel + p%du(index + 4) = perturb ! u%WAMITMesh%RotationVel + p%du(index + 5) = perturb_t ! u%WAMITMesh%TranslationAcc + p%du(index + 6) = perturb ! u%WAMITMesh%RotationAcc index = index + 6 @@ -3174,7 +3176,7 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) FieldMask(MASKID_ROTATIONVel) = .true. FieldMask(MASKID_TRANSLATIONACC) = .true. FieldMask(MASKID_ROTATIONACC) = .true. - call PackMotionMesh_Names(u%Mesh, 'Platform-RefPt', InitOut%LinNames_u, index, FieldMask=FieldMask) + call PackMotionMesh_Names(u%WAMITMesh, 'Platform-RefPt', InitOut%LinNames_u, index, FieldMask=FieldMask) InitOut%LinNames_u(index) = 'Extended input: wave elevation at platform ref point, m' @@ -3233,35 +3235,35 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) CASE (12) !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12 u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) = u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) + du * perturb_sign - CASE (13) !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 - u%Mesh%TranslationDisp (fieldIndx,node) = u%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE (14) !Module/Mesh/Field: u%Mesh%Orientation = 14 - CALL PerturbOrientationMatrix( u%Mesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE (15) !Module/Mesh/Field: u%Mesh%TranslationVel = 15 - u%Mesh%TranslationVel( fieldIndx,node) = u%Mesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (16) !Module/Mesh/Field: u%Mesh%RotationVel = 16 - u%Mesh%RotationVel (fieldIndx,node) = u%Mesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (17) !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 - u%Mesh%TranslationAcc( fieldIndx,node) = u%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (18) !Module/Mesh/Field: u%Mesh%RotationAcc = 18 - u%Mesh%RotationAcc(fieldIndx,node) = u%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign + CASE (13) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 + u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE (14) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 + CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (15) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 + u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (16) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (17) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 + u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (18) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 + u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign END SELECT else SELECT CASE( p%Jac_u_indx(n,1) ) - CASE (1) !Module/Mesh/Field: u%Mesh%TranslationDisp = 13 - u%Mesh%TranslationDisp (fieldIndx,node) = u%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE (2) !Module/Mesh/Field: u%Mesh%Orientation = 14 - CALL PerturbOrientationMatrix( u%Mesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE (3) !Module/Mesh/Field: u%Mesh%TranslationVel = 15 - u%Mesh%TranslationVel( fieldIndx,node) = u%Mesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (4) !Module/Mesh/Field: u%Mesh%RotationVel = 16 - u%Mesh%RotationVel (fieldIndx,node) = u%Mesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (5) !Module/Mesh/Field: u%Mesh%TranslationAcc = 17 - u%Mesh%TranslationAcc( fieldIndx,node) = u%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (6) !Module/Mesh/Field: u%Mesh%RotationAcc = 18 - u%Mesh%RotationAcc(fieldIndx,node) = u%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign + CASE (1) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 + u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE (2) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 + CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (3) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 + u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (4) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (5) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 + u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (6) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 + u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign END SELECT end if @@ -3321,7 +3323,7 @@ SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) call PackLoadMesh_dY(y_p%Morison%LumpedMesh , y_m%Morison%LumpedMesh , dY, indx_first) end if - call PackLoadMesh_dY(y_p%Mesh, y_m%Mesh, dY, indx_first) + call PackLoadMesh_dY(y_p%WAMITMesh, y_m%WAMITMesh, dY, indx_first) call PackLoadMesh_dY(y_p%AllHdroOrigin, y_m%AllHdroOrigin, dY, indx_first) do k=1,p%NumTotalOuts @@ -3383,10 +3385,10 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, if ( u%Morison%DistribMesh%Committed ) then nu = nu + u%Morison%DistribMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + u%Morison%LumpedMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node - + u%Mesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node nu = nu + 1 ! Extended input else - nu = nu + u%Mesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + nu = nu + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node nu = nu + 1 ! Extended input end if @@ -3410,7 +3412,7 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, call PackMotionMesh(u%Morison%LumpedMesh , u_op, index, FieldMask=Mask) end if - call PackMotionMesh(u%Mesh, u_op, index, FieldMask=Mask) + call PackMotionMesh(u%WAMITMesh, u_op, index, FieldMask=Mask) ! extended input: u_op(index) = 0.0_R8Ki !u%WaveElev0 @@ -3433,7 +3435,7 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, call PackLoadMesh(y%Morison%LumpedMesh , y_op, index) end if - call PackLoadMesh(y%Mesh, y_op, index) + call PackLoadMesh(y%WAMITMesh, y_op, index) call PackLoadMesh(y%AllHdroOrigin, y_op, index) index = index - 1 diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index e5fc2af70..1328ccc5b 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -164,7 +164,7 @@ typedef ^ ^ WAMIT_MiscV typedef ^ ^ WAMIT2_MiscVarType WAMIT2 - - - "misc var information from the WAMIT2 module" - typedef ^ ^ Waves2_MiscVarType Waves2 - - - "misc var information from the Waves2 module" - typedef ^ ^ Morison_MiscVarType Morison - - - "misc var information from the Morison module" - -typedef ^ ^ WAMIT_InputType u_WAMIT - - - "WAMIT module inputs" - +typedef ^ ^ WAMIT_InputType u_WAMIT {:} - - "WAMIT module inputs" - typedef ^ ^ WAMIT2_InputType u_WAMIT2 - - - "WAMIT2 module inputs" - typedef ^ ^ Waves2_InputType u_Waves2 - - - "Waves2 module inputs" - typedef ^ ^ Logical IgnoreMod - - - "whether to ignore the modulo in ED outputs (necessary for linearization perturbations)" - @@ -212,7 +212,7 @@ typedef ^ ^ Integer # Define inputs that are contained on the mesh here: # typedef ^ InputType Morison_InputType Morison - - - "Morison module inputs" - -typedef ^ InputType MeshType Mesh - - - "Displacements at the WAMIT reference point in the inertial frame" - +typedef ^ InputType MeshType WAMITMesh - - - "Displacements at the WAMIT reference point in the inertial frame" - # # # ..... Outputs ................................................................................................................... @@ -221,6 +221,6 @@ typedef ^ OutputType WAMIT_Output typedef ^ OutputType WAMIT2_OutputType WAMIT2 - - - "WAMIT2 module outputs" - typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - -typedef ^ OutputType MeshType Mesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - +typedef ^ OutputType MeshType WAMITMesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index bffe4d1ed..944ad72e5 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -327,7 +327,7 @@ PROGRAM HydroDynDriver - IF ( u(1)%Mesh%Initialized ) THEN + IF ( u(1)%WAMITMesh%Initialized ) THEN ! Create a motions mesh a (0,0,0) where all kinematics are specified call MeshCreate( BlankMesh = RefPtMesh & @@ -386,7 +386,7 @@ PROGRAM HydroDynDriver ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] - CALL MeshMapCreate( RefPtMesh, u(1)%Mesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + CALL MeshMapCreate( RefPtMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() @@ -410,7 +410,7 @@ PROGRAM HydroDynDriver RefPtMesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) ! Map kinematics to the WAMIT mesh with 1 to NBody nodes - CALL Transfer_Point_to_Point( RefPtMesh, u(1)%Mesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + CALL Transfer_Point_to_Point( RefPtMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() @@ -478,12 +478,12 @@ PROGRAM HydroDynDriver ! Modify u (likely from the outputs of another module or a set of test conditions) here: - IF ( u(1)%Mesh%Initialized ) THEN + IF ( u(1)%WAMITMesh%Initialized ) THEN IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN - u(1)%Mesh%TranslationDisp(:,1) = WAMITin(n,2:4) + u(1)%WAMITMesh%TranslationDisp(:,1) = WAMITin(n,2:4) ! Compute direction cosine matrix from the rotation angles @@ -493,13 +493,13 @@ PROGRAM HydroDynDriver IF ( abs(WAMITin(n,7)) > maxAngle ) maxAngle = abs(WAMITin(n,7)) CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%Mesh%Orientation(:,:,1) = dcm + u(1)%WAMITMesh%Orientation(:,:,1) = dcm - u(1)%Mesh%TranslationVel(:,1) = WAMITin(n,8:10) - u(1)%Mesh%RotationVel(:,1) = WAMITin(n,11:13) - u(1)%Mesh%TranslationAcc(:,1) = WAMITin(n,14:16) - u(1)%Mesh%RotationAcc(:,1) = WAMITin(n,17:19) + u(1)%WAMITMesh%TranslationVel(:,1) = WAMITin(n,8:10) + u(1)%WAMITMesh%RotationVel(:,1) = WAMITin(n,11:13) + u(1)%WAMITMesh%TranslationAcc(:,1) = WAMITin(n,14:16) + u(1)%WAMITMesh%RotationAcc(:,1) = WAMITin(n,17:19) END IF From e82f3f8f30caf6646c9fd6dce8aa94330812838c Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:54:21 -0600 Subject: [PATCH 014/377] Removed output handling code --- modules/hydrodyn/src/HydroDyn_Output.f90 | 97 +----------------------- 1 file changed, 4 insertions(+), 93 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index 4d2613909..ba99eae9f 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -1152,27 +1152,6 @@ SUBROUTINE HDOut_WriteOutputs( Time, y, p, Decimate, ErrStat, ErrMsg ) Frmt = '('//TRIM(Int2LStr(p%NumTotalOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WriteOutput(I) , I=1,p%NumTotalOuts ) END IF - - ! ! HydroDyn Outputs - !IF (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0) THEN - !!IF (p%DoOutput) THEN - ! Frmt = '('//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WriteOutput(I) , I=1,p%NumOuts ) - !END IF - ! - ! ! WAMIT Outputs - !IF (ALLOCATED( p%WAMIT%OutParam ) .AND. p%WAMIT%NumOuts > 0) THEN - !!IF (p%WAMIT%DoOutput) THEN - ! Frmt = '('//TRIM(Int2LStr(p%WAMIT%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%WAMIT%WriteOutput(I) , I=1,p%WAMIT%NumOuts ) - !END IF - ! - ! ! Morison Outputs - !IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN - !!IF (p%Morison%DoOutput) THEN - ! Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - ! WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, y%Morison%WriteOutput(I), I=1,p%Morison%NumOuts ) - !END IF WRITE (p%UnOutFile,'()', IOSTAT=ErrStat) ! write the line return @@ -1238,47 +1217,9 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E CALL HDOUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) IF ( ErrStat /= 0 ) RETURN - - - !IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file - ! - ! ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for WriteOutput array.' - ! ErrStat = ErrID_Fatal - ! RETURN - ! END IF - ! y%WriteOutput = 0.0_ReKi - ! - ! ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ! ErrStat = ErrID_Fatal - ! RETURN - ! END IF - ! - ! ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ! ErrStat = ErrID_Fatal - ! RETURN - ! END IF - ! - ! DO I = 1,p%NumOuts - ! - ! InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - ! InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) - ! - ! END DO - ! - ! END IF ! there are any requested outputs - - ! Aggregate the sub-module initialization outputs for the glue code - !IF ( p%OutSwtch == 2 .OR. p%OutSwtch == 3 ) THEN - - !hasWAMITOuts = .FALSE. + hasWAMIT2Outs = .FALSE. hasWaves2Outs = .FALSE. hasMorisonOuts = .FALSE. @@ -1286,11 +1227,7 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E m%LastOutTime = 0.0_DbKi m%Decimate = 0 p%OutDec = 1 !TODO: Remove this once the parameter has been added to the HD input file GJH 7/8/2014 - - !IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN - ! hasWAMITOuts = .TRUE. - ! p%NumTotalOuts = p%NumTotalOuts + p%WAMIT(1)%NumOuts * p%nWAMITObj - !END IF + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN hasWAMIT2Outs = .TRUE. p%NumTotalOuts = p%NumTotalOuts + p%WAMIT2%NumOuts @@ -1340,16 +1277,6 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E J = p%NumOuts + 1 - !IF ( hasWAMITOuts ) THEN - ! do iWAMIT = 1, p%nWAMITObj - ! DO I=1, p%WAMIT(iWAMIT)%NumOuts - ! InitOut%WriteOutputHdr(J) = InitOut%WAMIT(iWAMIT)%WriteOutputHdr(I) - ! InitOut%WriteOutputUnt(J) = InitOut%WAMIT(iWAMIT)%WriteOutputUnt(I) - ! J = J + 1 - ! END DO - ! end do - !END IF - IF ( hasWaves2Outs ) THEN DO I=1, p%Waves2%NumOuts InitOut%WriteOutputHdr(J) = InitOut%Waves2%WriteOutputHdr(I) @@ -1373,9 +1300,7 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E J = J + 1 END DO END IF - - !END IF - + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN CALL HDOut_OpenOutput( HydroDyn_ProgDesc, InitInp%OutRootName, p, InitOut, ErrStat, ErrMsg ) IF (ErrStat >= AbortErrLev ) RETURN @@ -1451,13 +1376,6 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN - do iWAMIT = 1, p%nWAMITObj - Frmt = '('//TRIM(Int2LStr(p%WAMIT(iWAMIT)%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT(iWAMIT)%WriteOutputHdr(I) ), I=1,p%WAMIT(iWAMIT)%NumOuts ) - end do - END IF - IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputHdr(I) ), I=1,p%WAMIT2%NumOuts ) @@ -1487,14 +1405,7 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta Frmt = '('//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) END IF - - IF (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0) THEN - do iWAMIT = 1, p%nWAMITObj - Frmt = '('//TRIM(Int2LStr(p%WAMIT(iWAMIT)%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT(iWAMIT)%WriteOutputUnt(I) ), I=1,p%WAMIT(iWAMIT)%NumOuts ) - end do - END IF - + IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputUnt(I) ), I=1,p%WAMIT2%NumOuts ) From 149560eff6e8fc5a23b2b6c5fb13efa596649988 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:55:15 -0600 Subject: [PATCH 015/377] Added error check for MnDrift and NewmanApp when NBody>1 --- modules/hydrodyn/src/HydroDyn_Input.f90 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 282a829b7..1fe5bfd55 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -3081,7 +3081,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) IF ( InitInp%PotMod == 1 .and. InitInp%NBodyMod == 2) THEN do i = 1,InitInp%NBody - IF ( .not. EqualRealNos( InitInp%PtfmRefzt(i), 0.0_ReKi ) THEN + IF ( .not. EqualRealNos( InitInp%PtfmRefzt(i), 0.0_ReKi ) )THEN CALL SetErrStat( ErrID_Fatal,'PtfmRefzt must be 0.0 for all WAMIT bodies when NBodyMod=2.',ErrStat,ErrMsg,RoutineName) RETURN END IF @@ -3226,11 +3226,9 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%WAMIT2%PtfmYF2 = InitInp%PtfmYF - !------------------------------------------------------------------------------------------------- ! Second order Forces due to Waves section (WAMIT2 Module) !------------------------------------------------------------------------------------------------- -!TODO: Add check on NBody > 1 and MnDrift and NewmanApp cannot equal 8 ! Check that we only specified one of MnDrift, NewmanApp, or DiffQTF ! (compared pairwise -- if any two are both true, we have a problem) @@ -3241,7 +3239,16 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) RETURN END IF + if ( InitInp%NBody > 1 .and. InitInp%WAMIT2%MnDrift == 8 ) then + call SetErrStat( ErrID_Fatal,'MnDrift cannot equal 8 when NBody > 1.',ErrStat,ErrMsg,RoutineName) + return + end if + if ( InitInp%NBody > 1 .and. InitInp%WAMIT2%NewmanApp == 8 ) then + call SetErrStat( ErrID_Fatal,'NewmanApp cannot equal 8 when NBody > 1.',ErrStat,ErrMsg,RoutineName) + return + end if + ! Check MnDrift and set the flag indicating WAMIT2 should perform the mean drift calculation. ! Also make sure we have a valid input value for the file extension From 861efc04c426a51b7b2b29331acbc5d49f432809 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Oct 2019 15:56:59 -0600 Subject: [PATCH 016/377] Added check on NCoefDpth to prevent accessing unallocated array --- modules/hydrodyn/src/Morison.f90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 051fd081d..7c2efa974 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1941,7 +1941,7 @@ SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, Er ! If the requested division size is less then the member length, we will subdivide the member IF ( element%MDivSize < memLen ) THEN - + ! Ensure a safe choice of x/y/z axis to use for splitting. IF ( .NOT. ( EqualRealNos( node2%JointPos(3) , node1%JointPos(3) ) ) ) THEN axis = 3 @@ -2071,6 +2071,8 @@ SUBROUTINE SetDepthBasedCoefs( z, NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, indx1 = 1 indx2 = 1 + if (NCoefDpth == 0) return + DO I = 1, NCoefDpth IF ( CoefDpths(I)%Dpth <= z .AND. .NOT. foundLess ) THEN indx1 = I From ef1350268bc7d985e3fc33962d900a876d187531 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 18 Oct 2019 14:06:15 -0600 Subject: [PATCH 017/377] Fixes bugs with cmake files which were created in prev. merge --- modules/hydrodyn/CMakeLists.txt | 2 +- modules/map/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/hydrodyn/CMakeLists.txt b/modules/hydrodyn/CMakeLists.txt index ad2ce522b..7f1d6857b 100644 --- a/modules/hydrodyn/CMakeLists.txt +++ b/modules/hydrodyn/CMakeLists.txt @@ -20,12 +20,12 @@ if (GENERATE_TYPES) generate_f90_types(src/HydroDyn.txt ${CMAKE_CURRENT_LIST_DIR}/src/HydroDyn_Types.f90) generate_f90_types(src/Morison.txt ${CMAKE_CURRENT_LIST_DIR}/src/Morison_Types.f90) generate_f90_types(src/SS_Radiation.txt ${CMAKE_CURRENT_LIST_DIR}/src/SS_Radiation_Types.f90) + generate_f90_types(src/SS_Excitation.txt ${CMAKE_CURRENT_LIST_DIR}/src/SS_Excitation_Types.f90) generate_f90_types(src/WAMIT.txt ${CMAKE_CURRENT_LIST_DIR}/src/WAMIT_Types.f90) generate_f90_types(src/WAMIT2.txt ${CMAKE_CURRENT_LIST_DIR}/src/WAMIT2_Types.f90) generate_f90_types(src/Waves.txt ${CMAKE_CURRENT_LIST_DIR}/src/Waves_Types.f90) generate_f90_types(src/Waves2.txt ${CMAKE_CURRENT_LIST_DIR}/src/Waves2_Types.f90) endif() -generate_f90_types(src/SS_Excitation.txt SS_Excitation_Types.f90) set(HYDRODYN_SOURCES src/Conv_Radiation.f90 diff --git a/modules/map/CMakeLists.txt b/modules/map/CMakeLists.txt index b78002235..326bce1f3 100644 --- a/modules/map/CMakeLists.txt +++ b/modules/map/CMakeLists.txt @@ -21,6 +21,7 @@ endif() if (GENERATE_TYPES) generate_f90_types(src/MAP_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -ccode) + generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -noextrap) endif() file(GLOB MAP_CLIB_SOURCES src/*.c src/*.cc src/*/*.c src/*/*.cc) @@ -38,6 +39,7 @@ target_link_libraries(mapcpplib nwtclibs) add_library(maplib src/map.f90 src/MAP_Types.f90 + src/MAP_Fortran_Types.f90 ) target_link_libraries(maplib mapcpplib) From 069cd236b45c3994d4d9331a4987daebe4979d7c Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 18 Oct 2019 14:06:59 -0600 Subject: [PATCH 018/377] Gluecode now references WAMITMesh instead of Mesh --- modules/openfast-library/src/FAST_Lin.f90 | 14 ++-- .../openfast-library/src/FAST_Registry.txt | 2 +- modules/openfast-library/src/FAST_Solver.f90 | 68 +++++++++---------- modules/openfast-library/src/FAST_Subs.f90 | 10 +-- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 29bbffda7..428c4fe6b 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -1761,7 +1761,7 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, ! we're mapping loads, so we also need the sibling meshes' displacements: HD_Start = Indx_u_HD_PlatformRef_Start(HD%Input(1), y_FAST) - call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) ! HD is source in the mapping, so we want M_{uSm} @@ -2603,18 +2603,18 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd ! y_ED%PlatformPtMesh and u_HD%Mesh !=================================================== - call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) HD_Start_td = HD_Start_tr + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 field ( TranslationalAcc and RotationAcc) - HD_Start_tr = HD_Start_td + u_HD%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + HD_Start_tr = HD_Start_td + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field ! translational velocity: if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%tv_uD )) then call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) end if ! translational acceleration: - HD_Start_tr = HD_Start_tr + u_HD%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + HD_Start_tr = HD_Start_tr + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%ta_uD )) then call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) @@ -2686,7 +2686,7 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd !................................... ! Lumped Platform Reference Pt Mesh !................................... - IF (u_HD%Mesh%Committed) THEN + IF (u_HD%WAMITMesh%Committed) THEN !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices !!! ! while forming dUdy, too. @@ -2695,7 +2695,7 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd HD_Start = Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy, .false.) + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy, .false.) END IF @@ -3755,7 +3755,7 @@ FUNCTION Indx_y_HD_AllHdro_Start(y_HD, y_FAST) RESULT(HD_Start) !< starting index of this mesh in HydroDyn Outputs HD_Start = Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) - if (y_HD%Mesh%committed) HD_Start = HD_Start + y_HD%Mesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + if (y_HD%WAMITMesh%committed) HD_Start = HD_Start + y_HD%WAMITMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components END FUNCTION Indx_y_HD_AllHdro_Start END MODULE FAST_Linear diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index 40d766bed..2bc3c92cc 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -408,7 +408,7 @@ typedef FAST FAST_ModuleMapType MeshMapType BD_P_2_ED_P {:} - - "Map BeamDyn Rea typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P_Hub {:} - - "ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator" # ED <-> HD typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_W_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point" -typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point (from either y%Mesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh" +typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point (from either y%WAMITMesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh" typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point" typedef ^ FAST_ModuleMapType MeshMapType HD_M_P_2_ED_P - - - "Map HydroDyn Morison Point to ElastoDyn PlatformPtMesh" typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_L - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Line2" diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index adfbecf12..d0f8458cf 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -922,14 +922,14 @@ SUBROUTINE Transfer_ED_to_HD( y_ED, u_HD, MeshMapData, ErrStat, ErrMsg ) !bjj: We do this without all the extra meshcopy/destroy calls with u_mapped because these inputs are only from one mesh - IF ( u_HD%Mesh%Committed ) THEN + IF ( u_HD%WAMITMesh%Committed ) THEN ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, ! hydrodynamic added mass - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_ED_to_HD (u_HD%Mesh)' ) + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_ED_to_HD (u_HD%WAMITMesh)' ) END IF !WAMIT @@ -1992,7 +1992,7 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & END DO CALL Create_FullOpt1_UVector(u, u_ED%PlatformPtMesh, u_SD%TPMesh, u_SD%LMesh, u_HD%Morison%LumpedMesh, & - u_HD%Morison%DistribMesh, u_HD%Mesh, u_ED%HubPtLoad, MeshMapData%u_BD_RootMotion, u_Orca%PtfmMesh, & + u_HD%Morison%DistribMesh, u_HD%WAMITMesh, u_ED%HubPtLoad, MeshMapData%u_BD_RootMotion, u_Orca%PtfmMesh, & u_ExtPtfm%PtfmMesh, p_FAST ) K = 0 @@ -2326,12 +2326,12 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO - DO TmpIndx=1,u_HD%Mesh%NNodes + DO TmpIndx=1,u_HD%WAMITMesh%NNodes CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO - DO TmpIndx=1,u_HD%Mesh%NNodes + DO TmpIndx=1,u_HD%WAMITMesh%NNodes CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) @@ -2453,8 +2453,8 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & MeshMapData%u_HD_M_DistribMesh%TranslationAcc = u_HD%Morison%DistribMesh%TranslationAcc ENDIF IF (MeshMapData%u_HD_Mesh%Committed) THEN - MeshMapData%u_HD_Mesh%RotationAcc = u_HD%Mesh%RotationAcc - MeshMapData%u_HD_Mesh%TranslationAcc = u_HD%Mesh%TranslationAcc + MeshMapData%u_HD_Mesh%RotationAcc = u_HD%WAMITMesh%RotationAcc + MeshMapData%u_HD_Mesh%TranslationAcc = u_HD%WAMITMesh%TranslationAcc ENDIF ! transfer the output data to inputs @@ -2467,7 +2467,7 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & ! Map ED outputs to HD inputs (keeping the accelerations we just calculated): - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSE @@ -2488,8 +2488,8 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & u_HD%Morison%DistribMesh%TranslationAcc = MeshMapData%u_HD_M_DistribMesh%TranslationAcc ENDIF IF (MeshMapData%u_HD_Mesh%Committed) THEN - u_HD%Mesh%RotationAcc = MeshMapData%u_HD_Mesh%RotationAcc - u_HD%Mesh%TranslationAcc = MeshMapData%u_HD_Mesh%TranslationAcc + u_HD%WAMITMesh%RotationAcc = MeshMapData%u_HD_Mesh%RotationAcc + u_HD%WAMITMesh%TranslationAcc = MeshMapData%u_HD_Mesh%TranslationAcc ENDIF !...... @@ -2736,10 +2736,10 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) ! WAMIT loads from HD get added to this load: - IF ( y_HD2%Mesh%Committed ) THEN + IF ( y_HD2%WAMITMesh%Committed ) THEN ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%Mesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh ) !u_SD contains the orientations needed for moment calculations + CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh ) !u_SD contains the orientations needed for moment calculations CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force @@ -3147,7 +3147,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP !(Mesh) do i=1,HD_WAMIT_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 13 !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 + MeshMapData%Jac_u_indx(index,1) = 13 !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3156,7 +3156,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,HD_WAMIT_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 14 !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 + MeshMapData%Jac_u_indx(index,1) = 14 !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3477,10 +3477,10 @@ SUBROUTINE Add_FullOpt1_u_delta( p_FAST, Jac_u_indx, u_delta, u_ED, u_SD, u_HD, u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) + u_delta(n) CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (13) !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 - u_HD%Mesh%TranslationAcc( fieldIndx,node) = u_HD%Mesh%TranslationAcc( fieldIndx,node) + u_delta(n) - CASE (14) !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 - u_HD%Mesh%RotationAcc( fieldIndx,node) = u_HD%Mesh%RotationAcc( fieldIndx,node) + u_delta(n) + CASE (13) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 + u_HD%WAMITMesh%TranslationAcc( fieldIndx,node) = u_HD%WAMITMesh%TranslationAcc( fieldIndx,node) + u_delta(n) + CASE (14) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 + u_HD%WAMITMesh%RotationAcc( fieldIndx,node) = u_HD%WAMITMesh%RotationAcc( fieldIndx,node) + u_delta(n) CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) @@ -3576,12 +3576,12 @@ SUBROUTINE Perturb_u_FullOpt1( p_FAST, Jac_u_indx, n, u_perturb, u_ED_perturb, u CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 perturb = GetPerturb( u_HD_perturb%Morison%DistribMesh%RotationAcc(fieldIndx , node) ) u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) + perturb - CASE (13) !Module/Mesh/Field: u_HD%Mesh%TranslationAcc = 13 - perturb = GetPerturb( u_HD_perturb%Mesh%TranslationAcc(fieldIndx , node) ) - u_HD_perturb%Mesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Mesh%TranslationAcc(fieldIndx,node) + perturb - CASE (14) !Module/Mesh/Field: u_HD%Mesh%RotationAcc = 14 - perturb = GetPerturb( u_HD_perturb%Mesh%RotationAcc(fieldIndx , node) ) - u_HD_perturb%Mesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Mesh%RotationAcc( fieldIndx,node) + perturb + CASE (13) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 + perturb = GetPerturb( u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx , node) ) + u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx,node) + perturb + CASE (14) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 + perturb = GetPerturb( u_HD_perturb%WAMITMesh%RotationAcc(fieldIndx , node) ) + u_HD_perturb%WAMITMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%WAMITMesh%RotationAcc( fieldIndx,node) + perturb CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) @@ -3735,9 +3735,9 @@ SUBROUTINE ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp ! HydroDyn IF ( p_FAST%CompHydro == Module_HD ) THEN - IF (HD%Input(1)%Mesh%Committed) THEN - HD%Input(1)%Mesh%RemapFlag = .FALSE. - HD%y%Mesh%RemapFlag = .FALSE. + IF (HD%Input(1)%WAMITMesh%Committed) THEN + HD%Input(1)%WAMITMesh%RemapFlag = .FALSE. + HD%y%WAMITMesh%RemapFlag = .FALSE. HD%y%AllHdroOrigin%RemapFlag = .FALSE. END IF IF (HD%Input(1)%Morison%LumpedMesh%Committed) THEN @@ -4063,7 +4063,7 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M ! HydroDyn WAMIT point mesh to/from ElastoDyn point mesh CALL MeshMapCreate( HD%y%AllHdroOrigin, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) END IF @@ -4083,12 +4083,12 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M ELSE ! these get mapped to ElastoDyn AND SubDyn (in ED_SD_HD coupling) ! offshore fixed ! HydroDyn WAMIT mesh to ElastoDyn point mesh - IF ( HD%y%Mesh%Committed ) THEN + IF ( HD%y%WAMITMesh%Committed ) THEN ! HydroDyn WAMIT point mesh to ElastoDyn point mesh ! meshes for fixed-bottom - CALL MeshMapCreate( HD%y%Mesh, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( HD%y%WAMITMesh, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) END IF @@ -4247,7 +4247,7 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M !IF ( p_FAST%TurbineType == Type_Offshore_Fixed ) THEN ! p_FAST%CompSub == Module_SD .AND. p_FAST%CompHydro == Module_HD IF ( p_FAST%CompSub /= Module_None .OR. (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) .or. p_FAST%CompMooring == Module_Orca) THEN !.OR. p_FAST%CompHydro == Module_HD ) THEN CALL Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED%Input(1)%PlatformPtMesh, SD%Input(1)%TPMesh, SD%Input(1)%LMesh, & - HD%Input(1)%Morison%LumpedMesh, HD%Input(1)%Morison%DistribMesh, HD%Input(1)%Mesh, & + HD%Input(1)%Morison%LumpedMesh, HD%Input(1)%Morison%DistribMesh, HD%Input(1)%WAMITMesh, & ED%Input(1)%HubPtLoad, BD%Input(1,:), Orca%Input(1)%PtfmMesh, ExtPtfm%Input(1)%PtfmMesh, ErrStat2, ErrMsg2) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN @@ -4329,7 +4329,7 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M IF ( p_FAST%CompHydro == Module_HD ) THEN - CALL MeshCopy ( HD%Input(1)%Mesh, MeshMapData%u_HD_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL MeshCopy ( HD%Input(1)%WAMITMesh, MeshMapData%u_HD_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_Mesh' ) CALL MeshCopy ( HD%Input(1)%Morison%LumpedMesh, MeshMapData%u_HD_M_LumpedMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 343e65218..ed3b040e6 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -5166,10 +5166,10 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD14, AD, IfW, O !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%OutFileRoot)//'.HD_MorisonDistrib_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) outputFields = .false. else - call MeshWrVTK(p_FAST%TurbinePos, HD%y%Mesh, trim(VTK_path)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WAMITMesh, trim(VTK_path)//'.HD_WAMITMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) outputFields = p_FAST%VTK_fields end if call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%LumpedMesh, trim(VTK_path)//'.HD_MorisonLumped', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%Morison%LumpedMesh ) @@ -5329,7 +5329,7 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD14, AD, IfW, IF ( p_FAST%CompHydro == Module_HD ) THEN if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) outputFields = .false. else OutputFields = p_FAST%VTK_fields @@ -5688,7 +5688,7 @@ SUBROUTINE WriteInputMeshesToFile(u_ED, u_AD, u_SD, u_HD, u_MAP, u_BD, FileName, CALL MeshWrBin( unOut, u_SD%LMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) ! Add how many BD blade meshes there are: NumBl = SIZE(u_BD,1) ! Note that NumBl is B4Ki @@ -5771,7 +5771,7 @@ SUBROUTINE WriteMotionMeshesToFile(time, y_ED, u_SD, y_SD, u_HD, u_MAP, y_BD, u_ CALL MeshWrBin( unOut, y_SD%y2Mesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Mesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) DO K_local = 1,SIZE(y_BD,1) CALL MeshWrBin( unOut, u_BD(K_local)%RootMotion, ErrStat, ErrMsg ) From 6a86c55d0a3b8558c72f681cfe2d74390fa7a060 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 22 Oct 2019 10:30:19 -0600 Subject: [PATCH 019/377] Fixed bug with integrating HD loads to PRP --- modules/hydrodyn/src/HydroDyn.f90 | 400 ++++++++++++------------ modules/hydrodyn/src/HydroDyn.txt | 11 +- modules/hydrodyn/src/HydroDyn_Types.f90 | 264 ++++++++-------- 3 files changed, 341 insertions(+), 334 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 1cfde3507..d29d3edcc 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1403,125 +1403,164 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I END IF ! Define system output initializations (set up mesh) here: - - - - ! Create the input and output meshes associated with lumped load at the WAMIT reference point (WRP) + + ! Create the input mesh associated with kinematics of the various WAMIT bodies - CALL MeshCreate( BlankMesh = u%WAMITMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = p%NBody & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE.) - ! Create the node on the mesh + CALL MeshCreate( BlankMesh = u%WAMITMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NBody & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE.) + ! Create the node on the mesh - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - do iBody = 1, p%NBody + do iBody = 1, p%NBody - theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) - orientation = EulerConstruct(theta) + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) + orientation = EulerConstruct(theta) - ! Create the node on the mesh - CALL MeshPositionNode (u%WAMITMesh & - , iBody & - , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & - , ErrStat2 & - , ErrMsg2 & - , orientation ) + ! Create the node on the mesh + CALL MeshPositionNode (u%WAMITMesh & + , iBody & + , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & + , ErrStat2 & + , ErrMsg2 & + , orientation ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - ! Create the mesh element - CALL MeshConstructElement ( u%WAMITMesh & - , ELEMENT_POINT & - , ErrStat2 & - , ErrMsg2 & - , iBody & - ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Create the mesh element + CALL MeshConstructElement ( u%WAMITMesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , iBody & + ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - end do + end do - CALL MeshCommit ( u%WAMITMesh & - , ErrStat2 & - , ErrMsg2 ) + CALL MeshCommit ( u%WAMITMesh & + , ErrStat2 & + , ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - - CALL MeshCopy ( SrcMesh = u%WAMITMesh & - ,DestMesh = y%WAMITMesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - u%WAMITMesh%RemapFlag = .TRUE. - y%WAMITMesh%RemapFlag = .TRUE. - - !TODO: Deal with AllHdroOrigin - CALL MeshCopy ( SrcMesh = y%WAMITMesh & - ,DestMesh = y%AllHdroOrigin & - ,CtrlCode = MESH_NEWCOPY & + ! Output mesh for loads at each WAMIT body + + CALL MeshCopy ( SrcMesh = u%WAMITMesh & + ,DestMesh = y%WAMITMesh & + ,CtrlCode = MESH_SIBLING & ,IOS = COMPONENT_OUTPUT & ,ErrStat = ErrStat2 & ,ErrMess = ErrMsg2 & ,Force = .TRUE. & ,Moment = .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + u%WAMITMesh%RemapFlag = .TRUE. + y%WAMITMesh%RemapFlag = .TRUE. + + ! Create helper mesh to map all Hydrodynamics loads to the platform reference point to (0,0,0) + CALL MeshCreate ( BlankMesh = m%AllHdroOrigin & + ,IOS = COMPONENT_OUTPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%AllHdroOrigin') IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() RETURN END IF - y%AllHdroOrigin%RemapFlag = .TRUE. + ! Create the node on the mesh + CALL MeshPositionNode (m%AllHdroOrigin & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! Create the mesh element + CALL MeshConstructElement ( m%AllHdroOrigin & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 & + ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + CALL MeshCommit ( m%AllHdroOrigin & + , ErrStat2 & + , ErrMsg2 ) + + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + m%AllHdroOrigin%RemapFlag = .TRUE. ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = u%WAMITMesh & - , DestMesh = m%AllHdroOrigin_position & - , CtrlCode = MESH_NEWCOPY & - , IOS = COMPONENT_INPUT & - , TranslationDisp = .TRUE. & - , ErrStat = ErrStat2 & - , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. + CALL MeshCopy ( SrcMesh = m%AllHdroOrigin & + , DestMesh = m%AllHdroOrigin_Position & + , CtrlCode = MESH_SIBLING & + , IOS = COMPONENT_INPUT & + , TranslationDisp = .TRUE. & + , Orientation = .TRUE. & + , TranslationVel = .TRUE. & + , RotationVel = .TRUE. & + , TranslationAcc = .TRUE. & + , RotationAcc = .TRUE. & + , ErrStat = ErrStat2 & + , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() RETURN END IF - m%AllHdroOrigin_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + m%AllHdroOrigin_Position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. ! Create the Output file if requested @@ -1534,47 +1573,37 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I p%OutSFmt = InitLocal%OutSFmt p%NumOuts = InitLocal%NumOuts - CALL HDOUT_Init( HydroDyn_ProgDesc, InitLocal, y, p, m, InitOut, ErrStat2, ErrMsg2 ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL HDOUT_Init( HydroDyn_ProgDesc, InitLocal, y, p, m, InitOut, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() RETURN END IF -! TODO: Deal with Mesh - ! Create some mesh mapping data - CALL MeshCopy ( SrcMesh = y%WAMITMesh & - ,DestMesh = m%y_mapped & - ,CtrlCode = MESH_NEWCOPY & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - m%y_mapped%RemapFlag = .TRUE. - - CALL MeshMapCreate( y%WAMITMesh, m%y_mapped, m%HD_MeshMap%HD_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + if ( u%WAMITMesh%Committed ) then + call MeshMapCreate( u%WAMITMesh, m%AllHdroOrigin_Position, m%HD_MeshMap%uW_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + if ( y%WAMITMesh%Committed ) then + call MeshMapCreate( y%WAMITMesh, m%AllHdroOrigin, m%HD_MeshMap%W_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if IF ( y%Morison%LumpedMesh%Committed ) THEN - CALL MeshMapCreate( y%Morison%LumpedMesh, m%y_mapped, m%HD_MeshMap%M_P_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL MeshMapCreate( y%Morison%LumpedMesh, m%AllHdroOrigin, m%HD_MeshMap%M_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ENDIF IF ( y%Morison%DistribMesh%Committed ) THEN - CALL MeshMapCreate( y%Morison%DistribMesh, m%y_mapped, m%HD_MeshMap%M_L_2_WRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL MeshMapCreate( y%Morison%DistribMesh, m%AllHdroOrigin, m%HD_MeshMap%M_L_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ENDIF - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - ! Define initialization-routine output here: - InitOut%Ver = HydroDyn_ProgDesc - ! These three come directly from processing the inputs, and so will exist even if not using Morison elements: - InitOut%WtrDens = InitLocal%Morison%WtrDens - InitOut%WtrDpth = InitLocal%Morison%WtrDpth - InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL - p%WtrDpth = InitOut%WtrDpth + ! Define initialization-routine output here: + InitOut%Ver = HydroDyn_ProgDesc + ! These three come directly from processing the inputs, and so will exist even if not using Morison elements: + InitOut%WtrDens = InitLocal%Morison%WtrDens + InitOut%WtrDpth = InitLocal%Morison%WtrDpth + InitOut%MSL2SWL = InitLocal%Morison%MSL2SWL + p%WtrDpth = InitOut%WtrDpth IF ( InitLocal%hasIce ) THEN IF ((InitLocal%Waves%WaveMod /= 0) .OR. (InitLocal%Current%CurrMod /= 0) ) THEN @@ -2064,8 +2093,8 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, END IF - ! Integrate all the mesh loads onto the WAMIT reference Point (WRP) at (0,0,0) - m%F_Hydro = CalcLoadsAtWRP( y, u, m%y_mapped, m%AllHdroOrigin_position, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) + ! Integrate all the mesh loads onto the platfrom reference Point (PRP) at (0,0,0) + m%F_Hydro = CalcLoadsAtWRP( y, u, m%AllHdroOrigin, m%AllHdroOrigin_Position, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) @@ -2228,92 +2257,69 @@ END SUBROUTINE HydroDyn_CalcConstrStateResidual !---------------------------------------------------------------------------------------------------------------------------------- -FUNCTION CalcLoadsAtWRP( y, u, y_mapped, AllHdroOrigin_position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) - - TYPE(HydroDyn_OutputType), INTENT(INOUT) :: y ! Hydrodyn outputs - TYPE(HydroDyn_InputType), INTENT(IN ) :: u ! Hydrodyn inputs - TYPE(MeshType), INTENT(INOUT) :: y_mapped ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call - TYPE(MeshType), INTENT(IN ) :: AllHdroOrigin_position ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call - TYPE(MeshType), INTENT(IN ) :: MrsnLumpedMesh_Postion ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call - TYPE(MeshType), INTENT(IN ) :: MrsnDistribMesh_Position ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call - TYPE(HD_ModuleMapType), INTENT(INOUT) :: MeshMapData ! Map data structures - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: CalcLoadsAtWRP(6) +function CalcLoadsAtWRP( y, u, AllHdroOrigin, AllHdroOrigin_Position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) + + type(HydroDyn_OutputType), intent(inout) :: y ! Hydrodyn outputs + type(HydroDyn_InputType), intent(in ) :: u ! Hydrodyn inputs + type(MeshType), intent(inout) :: AllHdroOrigin ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call + type(MeshType), intent(inout) :: AllHdroOrigin_Position ! These are the kinematics associated the PRP at (0,0,0). We pass it in to avoid allocating it at each call + type(MeshType), intent(in ) :: MrsnLumpedMesh_Postion ! These are the kinematics associated with the Morison lumped loads mesh. We pass it in to avoid allocating it at each call + type(MeshType), intent(in ) :: MrsnDistribMesh_Position ! These are the kinematics associated with the Morison distributed loads mesh. We pass it in to avoid allocating it at each call + type(HD_ModuleMapType), intent(inout) :: MeshMapData ! Mesh mapping data structures + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(ReKi) :: CalcLoadsAtWRP(6) ! local variables - INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 ! temporary Error status of the operation + character(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None - y%AllHdroOrigin%Force = 0.0 - y%AllHdroOrigin%Moment= 0.0 + CalcLoadsAtWRP = 0.0_ReKi - IF ( y%WAMITMesh%Committed ) THEN + if ( u%WAMITMesh%Committed ) then + ! Just transfer the loads because the meshes are at the same location (0,0,0) + call Transfer_Point_to_Point( u%WAMITMesh, AllHdroOrigin_Position, MeshMapData%uW_P_2_PRP_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') + if (ErrStat >= AbortErrLev) return + end if + + if ( y%WAMITMesh%Committed ) then ! Just transfer the loads because the meshes are at the same location (0,0,0) + call Transfer_Point_to_Point( y%WAMITMesh, AllHdroOrigin, MeshMapData%W_P_2_PRP_P, ErrStat2, ErrMsg2, u%WAMITMesh, AllHdroOrigin_Position ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') + if (ErrStat >= AbortErrLev) return + + CalcLoadsAtWRP(1:3) = CalcLoadsAtWRP(1:3) + AllHdroOrigin%Force(:,1) + CalcLoadsAtWRP(4:6) = CalcLoadsAtWRP(4:6) + AllHdroOrigin%Moment(:,1) - y%AllHdroOrigin%Force = y%WAMITMesh%Force - y%AllHdroOrigin%Moment = y%WAMITMesh%Moment - - END IF + end if - IF ( y%Morison%LumpedMesh%Committed ) THEN + if ( y%Morison%LumpedMesh%Committed ) then ! This is viscous drag associate with the WAMIT body and/or filled/flooded forces of the WAMIT body - CALL Transfer_Point_to_Point( y%Morison%LumpedMesh, y_mapped, MeshMapData%M_P_2_WRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, AllHdroOrigin_position ) - CALL CheckError( ErrStat2, ErrMsg2 ) - IF (ErrStat >= AbortErrLev) RETURN + call Transfer_Point_to_Point( y%Morison%LumpedMesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, AllHdroOrigin_Position ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') + if (ErrStat >= AbortErrLev) return - y%AllHdroOrigin%Force = y%AllHdroOrigin%Force + y_mapped%Force - y%AllHdroOrigin%Moment = y%AllHdroOrigin%Moment + y_mapped%Moment + CalcLoadsAtWRP(1:3) = CalcLoadsAtWRP(1:3) + AllHdroOrigin%Force(:,1) + CalcLoadsAtWRP(4:6) = CalcLoadsAtWRP(4:6) + AllHdroOrigin%Moment(:,1) - END IF + end if - IF ( y%Morison%DistribMesh%Committed ) THEN + if ( y%Morison%DistribMesh%Committed ) then - CALL Transfer_Line2_to_Point( y%Morison%DistribMesh, y_mapped, MeshMapData%M_L_2_WRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, AllHdroOrigin_position ) - CALL CheckError( ErrStat2, ErrMsg2 ) - IF (ErrStat >= AbortErrLev) RETURN + call Transfer_Line2_to_Point( y%Morison%DistribMesh, AllHdroOrigin, MeshMapData%M_L_2_PRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, AllHdroOrigin_Position ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') + if (ErrStat >= AbortErrLev) return - y%AllHdroOrigin%Force = y%AllHdroOrigin%Force + y_mapped%Force - y%AllHdroOrigin%Moment = y%AllHdroOrigin%Moment + y_mapped%Moment + CalcLoadsAtWRP(1:3) = CalcLoadsAtWRP(1:3) + AllHdroOrigin%Force(:,1) + CalcLoadsAtWRP(4:6) = CalcLoadsAtWRP(4:6) + AllHdroOrigin%Moment(:,1) - END IF + end if - CalcLoadsAtWRP(1:3) = y%AllHdroOrigin%Force(:,1) - CalcLoadsAtWRP(4:6) = y%AllHdroOrigin%Moment(:,1) - -CONTAINS - !............................................................................................................................... - SUBROUTINE CheckError(ErrID,Msg) - ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev - !............................................................................................................................... - - ! Passed arguments - INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) - CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) - - INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) - CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) - - !............................................................................................................................ - ! Set error status/message; - !............................................................................................................................ - - IF ( ErrID /= ErrID_None ) THEN - - IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine - ErrMsg = TRIM(ErrMsg)//' CalcLoadsAtWRP:'//TRIM(Msg) - ErrStat = MAX(ErrStat, ErrID) - - !......................................................................................................................... - ! Clean up if we're going to return on error: close files, deallocate local arrays - !......................................................................................................................... - END IF - - END SUBROUTINE CheckError -END FUNCTION CalcLoadsAtWRP +end function CalcLoadsAtWRP !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ###### The following four routines are Jacobian routines for linearization capabilities ####### @@ -2859,7 +2865,8 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) end if p%Jac_ny = p%Jac_ny + y%WAMITMesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point - p%Jac_ny = p%Jac_ny + y%AllHdroOrigin%NNodes * 6 ! 3 Force, Moment, of all HD loads integrated to the origin (0,0,0) +!TODO: With NBody WAMIT rework need to see if removing this causes issues + ! p%Jac_ny = p%Jac_ny + y%AllHdroOrigin%NNodes * 6 ! 3 Force, Moment, of all HD loads integrated to the origin (0,0,0) p%Jac_ny = p%Jac_ny + p%NumTotalOuts ! WriteOutput values @@ -2886,8 +2893,9 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) index_last = index_next call PackLoadMesh_Names(y%WAMITMesh, 'PlatformRefPtLoads', InitOut%LinNames_y, index_next) - index_last = index_next - call PackLoadMesh_Names(y%AllHdroOrigin, 'AllHdroOrigin', InitOut%LinNames_y, index_next) +!TODO: With NBody WAMIT rework need to see if removing this causes issues + ! index_last = index_next + ! call PackLoadMesh_Names(y%AllHdroOrigin, 'AllHdroOrigin', InitOut%LinNames_y, index_next) index_last = index_next @@ -3324,7 +3332,8 @@ SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) end if call PackLoadMesh_dY(y_p%WAMITMesh, y_m%WAMITMesh, dY, indx_first) - call PackLoadMesh_dY(y_p%AllHdroOrigin, y_m%AllHdroOrigin, dY, indx_first) +!TODO: With NBody WAMIT rework need to see if removing this causes issues + !call PackLoadMesh_dY(y_p%AllHdroOrigin, y_m%AllHdroOrigin, dY, indx_first) do k=1,p%NumTotalOuts dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) @@ -3436,7 +3445,8 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, end if call PackLoadMesh(y%WAMITMesh, y_op, index) - call PackLoadMesh(y%AllHdroOrigin, y_op, index) +!TODO: With NBody WAMIT rework need to see if removing this causes issues +! call PackLoadMesh(y%AllHdroOrigin, y_op, index) index = index - 1 do i=1,p%NumTotalOuts diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 1328ccc5b..f7a0b345d 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -106,9 +106,10 @@ typedef ^ ^ LOGICAL # ..... HD_ModuleMapType .................................................................................................................... -typedef ^ HD_ModuleMapType MeshMapType HD_P_2_WRP_P -typedef ^ HD_ModuleMapType MeshMapType M_P_2_WRP_P -typedef ^ HD_ModuleMapType MeshMapType M_L_2_WRP_P +typedef ^ HD_ModuleMapType MeshMapType uW_P_2_PRP_P - - - "Mesh mapping data: WAMIT body kinematics to PRP node at (0,0,0)" - +typedef ^ HD_ModuleMapType MeshMapType W_P_2_PRP_P - - - "Mesh mapping data: WAMIT loads to PRP node at (0,0,0)" - +typedef ^ HD_ModuleMapType MeshMapType M_P_2_PRP_P - - - "Mesh mapping data: lumped Morison loads to PRP node at (0,0,0)" - +typedef ^ HD_ModuleMapType MeshMapType M_L_2_PRP_P - - - "Mesh mapping data: distributed Morison loads to PRP node at (0,0,0)" - # # @@ -149,7 +150,7 @@ typedef ^ ^ Morison_Oth # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType MeshType y_mapped - - - "An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ MiscVarType MeshType AllHdroOrigin - - - "An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ MeshType AllHdroOrigin_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ MeshType MrsnLumpedMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ MeshType MrsnDistribMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - @@ -222,5 +223,5 @@ typedef ^ OutputType WAMIT2_Outpu typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - typedef ^ OutputType MeshType WAMITMesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - -typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - +#typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 309384bc7..ef56e7b87 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -128,9 +128,10 @@ MODULE HydroDyn_Types ! ======================= ! ========= HD_ModuleMapType ======= TYPE, PUBLIC :: HD_ModuleMapType - TYPE(MeshMapType) :: HD_P_2_WRP_P - TYPE(MeshMapType) :: M_P_2_WRP_P - TYPE(MeshMapType) :: M_L_2_WRP_P + TYPE(MeshMapType) :: uW_P_2_PRP_P !< Mesh mapping data: WAMIT body kinematics to PRP node at (0,0,0) [-] + TYPE(MeshMapType) :: W_P_2_PRP_P !< Mesh mapping data: WAMIT loads to PRP node at (0,0,0) [-] + TYPE(MeshMapType) :: M_P_2_PRP_P !< Mesh mapping data: lumped Morison loads to PRP node at (0,0,0) [-] + TYPE(MeshMapType) :: M_L_2_PRP_P !< Mesh mapping data: distributed Morison loads to PRP node at (0,0,0) [-] END TYPE HD_ModuleMapType ! ======================= ! ========= HydroDyn_ContinuousStateType ======= @@ -167,7 +168,7 @@ MODULE HydroDyn_Types ! ======================= ! ========= HydroDyn_MiscVarType ======= TYPE, PUBLIC :: HydroDyn_MiscVarType - TYPE(MeshType) :: y_mapped !< An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(MeshType) :: AllHdroOrigin !< An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(MeshType) :: AllHdroOrigin_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(MeshType) :: MrsnLumpedMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(MeshType) :: MrsnDistribMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] @@ -238,7 +239,6 @@ MODULE HydroDyn_Types TYPE(Waves2_OutputType) :: Waves2 !< Waves2 module outputs [-] TYPE(Morison_OutputType) :: Morison !< Morison module outputs [-] TYPE(MeshType) :: WAMITMesh !< Point Loads at the WAMIT reference point in the inertial frame [-] - TYPE(MeshType) :: AllHdroOrigin !< All HD-related loads integrated to the origin, (0,0,0) in the inertial frame [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] END TYPE HydroDyn_OutputType ! ======================= @@ -3311,13 +3311,16 @@ SUBROUTINE HydroDyn_CopyHD_ModuleMapType( SrcHD_ModuleMapTypeData, DstHD_ModuleM ! ErrStat = ErrID_None ErrMsg = "" - CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%HD_P_2_WRP_P, DstHD_ModuleMapTypeData%HD_P_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%uW_P_2_PRP_P, DstHD_ModuleMapTypeData%uW_P_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_P_2_WRP_P, DstHD_ModuleMapTypeData%M_P_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%W_P_2_PRP_P, DstHD_ModuleMapTypeData%W_P_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_L_2_WRP_P, DstHD_ModuleMapTypeData%M_L_2_WRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_P_2_PRP_P, DstHD_ModuleMapTypeData%M_P_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_L_2_PRP_P, DstHD_ModuleMapTypeData%M_L_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE HydroDyn_CopyHD_ModuleMapType @@ -3331,9 +3334,10 @@ SUBROUTINE HydroDyn_DestroyHD_ModuleMapType( HD_ModuleMapTypeData, ErrStat, ErrM ! ErrStat = ErrID_None ErrMsg = "" - CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%HD_P_2_WRP_P, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_P_2_WRP_P, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_L_2_WRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%uW_P_2_PRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%W_P_2_PRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_P_2_PRP_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_L_2_PRP_P, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyHD_ModuleMapType SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -3372,54 +3376,71 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Db_BufSz = 0 Int_BufSz = 0 ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! HD_P_2_WRP_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_P_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_P_2_WRP_P + Int_BufSz = Int_BufSz + 3 ! uW_P_2_PRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%uW_P_2_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! uW_P_2_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! uW_P_2_PRP_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! uW_P_2_PRP_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! uW_P_2_PRP_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! W_P_2_PRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%W_P_2_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! W_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! HD_P_2_WRP_P + IF(ALLOCATED(Re_Buf)) THEN ! W_P_2_PRP_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! HD_P_2_WRP_P + IF(ALLOCATED(Db_Buf)) THEN ! W_P_2_PRP_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! HD_P_2_WRP_P + IF(ALLOCATED(Int_Buf)) THEN ! W_P_2_PRP_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! M_P_2_WRP_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_P_2_WRP_P + Int_BufSz = Int_BufSz + 3 ! M_P_2_PRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! M_P_2_WRP_P + IF(ALLOCATED(Re_Buf)) THEN ! M_P_2_PRP_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! M_P_2_WRP_P + IF(ALLOCATED(Db_Buf)) THEN ! M_P_2_PRP_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! M_P_2_WRP_P + IF(ALLOCATED(Int_Buf)) THEN ! M_P_2_PRP_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! M_L_2_WRP_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_WRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_L_2_WRP_P + Int_BufSz = Int_BufSz + 3 ! M_L_2_PRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_L_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! M_L_2_WRP_P + IF(ALLOCATED(Re_Buf)) THEN ! M_L_2_PRP_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! M_L_2_WRP_P + IF(ALLOCATED(Db_Buf)) THEN ! M_L_2_PRP_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! M_L_2_WRP_P + IF(ALLOCATED(Int_Buf)) THEN ! M_L_2_PRP_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -3450,7 +3471,35 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Db_Xferred = 1 Int_Xferred = 1 - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_P_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_P_2_WRP_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%uW_P_2_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! uW_P_2_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%W_P_2_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! W_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3478,7 +3527,7 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_P_2_WRP_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_P_2_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3506,7 +3555,7 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_WRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_L_2_WRP_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_L_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3601,7 +3650,47 @@ SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_P_2_WRP_P, ErrStat2, ErrMsg2 ) ! HD_P_2_WRP_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%uW_P_2_PRP_P, ErrStat2, ErrMsg2 ) ! uW_P_2_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%W_P_2_PRP_P, ErrStat2, ErrMsg2 ) ! W_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3641,7 +3730,7 @@ SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_P_2_WRP_P, ErrStat2, ErrMsg2 ) ! M_P_2_WRP_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_P_2_PRP_P, ErrStat2, ErrMsg2 ) ! M_P_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3681,7 +3770,7 @@ SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_L_2_WRP_P, ErrStat2, ErrMsg2 ) ! M_L_2_WRP_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_L_2_PRP_P, ErrStat2, ErrMsg2 ) ! M_L_2_PRP_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5798,7 +5887,7 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshCopy( SrcMiscData%y_mapped, DstMiscData%y_mapped, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcMiscData%AllHdroOrigin, DstMiscData%AllHdroOrigin, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL MeshCopy( SrcMiscData%AllHdroOrigin_position, DstMiscData%AllHdroOrigin_position, CtrlCode, ErrStat2, ErrMsg2 ) @@ -5900,7 +5989,7 @@ SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshDestroy( MiscData%y_mapped, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%AllHdroOrigin, ErrStat, ErrMsg ) CALL MeshDestroy( MiscData%AllHdroOrigin_position, ErrStat, ErrMsg ) CALL MeshDestroy( MiscData%MrsnLumpedMesh_position, ErrStat, ErrMsg ) CALL MeshDestroy( MiscData%MrsnDistribMesh_position, ErrStat, ErrMsg ) @@ -5966,20 +6055,20 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_BufSz = 0 Int_BufSz = 0 ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! y_mapped: size of buffers for each call to pack subtype - CALL MeshPack( InData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! y_mapped + Int_BufSz = Int_BufSz + 3 ! AllHdroOrigin: size of buffers for each call to pack subtype + CALL MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! AllHdroOrigin CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! y_mapped + IF(ALLOCATED(Re_Buf)) THEN ! AllHdroOrigin Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! y_mapped + IF(ALLOCATED(Db_Buf)) THEN ! AllHdroOrigin Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! y_mapped + IF(ALLOCATED(Int_Buf)) THEN ! AllHdroOrigin Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -6224,7 +6313,7 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! y_mapped + CALL MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! AllHdroOrigin CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6690,7 +6779,7 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%y_mapped, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! y_mapped + CALL MeshUnpack( OutData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! AllHdroOrigin CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9026,9 +9115,6 @@ SUBROUTINE HydroDyn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, CALL MeshCopy( SrcOutputData%WAMITMesh, DstOutputData%WAMITMesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcOutputData%AllHdroOrigin, DstOutputData%AllHdroOrigin, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN i1_l = LBOUND(SrcOutputData%WriteOutput,1) i1_u = UBOUND(SrcOutputData%WriteOutput,1) @@ -9062,7 +9148,6 @@ SUBROUTINE HydroDyn_DestroyOutput( OutputData, ErrStat, ErrMsg ) CALL Waves2_DestroyOutput( OutputData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyOutput( OutputData%Morison, ErrStat, ErrMsg ) CALL MeshDestroy( OutputData%WAMITMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( OutputData%AllHdroOrigin, ErrStat, ErrMsg ) IF (ALLOCATED(OutputData%WriteOutput)) THEN DEALLOCATE(OutputData%WriteOutput) ENDIF @@ -9195,23 +9280,6 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! AllHdroOrigin: size of buffers for each call to pack subtype - CALL MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! AllHdroOrigin - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! AllHdroOrigin - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! AllHdroOrigin - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! AllHdroOrigin - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no IF ( ALLOCATED(InData%WriteOutput) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension @@ -9397,34 +9465,6 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL MeshPack( InData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! AllHdroOrigin - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9689,46 +9729,6 @@ SUBROUTINE HydroDyn_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%AllHdroOrigin, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! AllHdroOrigin - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10015,8 +10015,6 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, E CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp1(y1%WAMITMesh, y2%WAMITMesh, tin, y_out%WAMITMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp1(y1%AllHdroOrigin, y2%AllHdroOrigin, tin, y_out%AllHdroOrigin, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) @@ -10094,8 +10092,6 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSta CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp2(y1%WAMITMesh, y2%WAMITMesh, y3%WAMITMesh, tin, y_out%WAMITMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp2(y1%AllHdroOrigin, y2%AllHdroOrigin, y3%AllHdroOrigin, tin, y_out%AllHdroOrigin, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) From 57388e9a49a4b277a9e2964b7f00600ddc5bb91a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 24 Oct 2019 09:07:24 -0600 Subject: [PATCH 020/377] Fixed indexing bug on F_Waves outputs --- modules/hydrodyn/src/HydroDyn_Output.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index ba99eae9f..d5858add0 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -1079,7 +1079,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, Wa AllOuts(FRdtn (:,iBody)) = m_WAMIT(iBody)%F_Rdtn + m_WAMIT(iBody)%F_PtfmAM !AllOuts(FWaves2 (:,iBody)) = F_Waves2 AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) - AllOuts(FWavesTot(:,iBody)) = F_Waves + AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) AllOuts(WBVel (:,iBody)) = qdot(startIndx:endIndx) AllOuts(WBAcc (:,iBody)) = qdotdot(startIndx:endIndx) From 3e283c0055a8ec207eeea47ce442a67a0d043f22 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 23 Oct 2019 18:27:06 -0600 Subject: [PATCH 021/377] FlexSub: starting clean up --- modules/subdyn/src/SD_FEM.f90 | 835 ++++++++++++++-------------------- 1 file changed, 341 insertions(+), 494 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index db0b155e9..aeca6df92 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -19,11 +19,10 @@ MODULE SD_FEM USE NWTC_Library USE SubDyn_Types - IMPLICIT NONE - - INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors - + + INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors + INTEGER(IntKi), PARAMETER :: MaxMemjnt = 10 ! Maximum number of members at one joint INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) @@ -40,50 +39,37 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsCol,XPropSetsCol,COSMsCol,CMassCol) - CONTAINS + +CONTAINS +!> Maps nodes to elements +!! allocate NodesConnE and NodesConnN SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) - -!This Subroutine maps nodes to elements -! allocate for NodesConnE and NodesConnN - USE qsort_c_module - IMPLICIT NONE - - TYPE(SD_InitType), INTENT( INOUT ) ::Init - TYPE(SD_ParameterType), INTENT( IN ) ::p - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - !local variable + USE qsort_c_module ,only: QsortC + TYPE(SD_InitType), INTENT( INOUT ) :: Init + TYPE(SD_ParameterType), INTENT( IN ) :: p + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements INTEGER(IntKi) :: I,J,K !counter - ! bjj: shouldn't there be a check that there AREN'T actually more members at one joint than MaxMemJnt? - ALLOCATE(Init%NodesConnE(Init%NNode, MaxMemJnt+1), STAT=ErrStat) !the row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating NodesConnE matrix' - ErrStat = ErrID_Fatal - RETURN - ENDIF + ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) + CALL AllocAry(Init%NodesConnE, Init%NNode, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnN, Init%NNode, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; Init%NodesConnE = 0 - - ALLOCATE(Init%NodesConnN(Init%NNode, MaxMemJnt+2), STAT=ErrStat) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating NodesConnN matrix' - ErrStat = ErrID_Fatal - RETURN - ENDIF Init%NodesConnN = 0 -! ! find the node connectivity, nodes/elements that connect to a common node - + ! find the node connectivity, nodes/elements that connect to a common node DO I = 1, Init%NNode Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array - k = 0 DO J = 1, Init%NElem !This should be vectorized IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element k = k + 1 + if (k > MaxMemJnt+1) then + CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); + endif Init%NodesConnE(I, k + 1) = p%Elems(J, 1) Init%NodesConnN(I, k + 1) = p%Elems(J, 3) IF ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element @@ -102,15 +88,13 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) END SUBROUTINE NodeCon -!---------------------------------------------------------------------------- !---------------------------------------------------------------------------- SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) ::Init TYPE(SD_ParameterType), INTENT(INOUT) ::p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable + ! local variable INTEGER :: I, J, n, Node, Node1, Node2, Prop, Prop1, Prop2 INTEGER :: OldJointIndex(Init%NJoints) INTEGER :: NNE ! number of nodes per element @@ -122,22 +106,17 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) LOGICAL :: found, CreateNewProp INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 - - ErrStat = ErrID_None ErrMsg = "" - !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ! number of nodes per element IF( ( Init%FEMMod .GE. 0 ) .and. (Init%FEMMod .LE. 3) ) THEN NNE = 2 ELSE - CALL SetErrStat(ErrID_Fatal, 'FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.',ErrStat,ErrMsg,'SD_Discrt') + CALL Abort('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') RETURN ENDIF - Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers ! Calculate total number of nodes according to divisions Init%NElem = p%NMembers*Init%NDiv ! Total number of element MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) @@ -149,7 +128,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! check the number of interior modes IF ( p%Nmodes .GT. 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN - CALL SetErrStat(ErrID_Fatal, ' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) )),ErrStat,ErrMsg,'SD_Discrt') + CALL Abort(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) RETURN ENDIF @@ -163,7 +142,6 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') CALL AllocAry(TempProps, MaxNProp, PropSetsCol,'TempProps', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp_Discrt() @@ -186,12 +164,10 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) p%Elems(I, 1) = I ! element/member number (not MemberID) !bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. - - ! loop through the JointIDs for this member and find the corresponding indices into the Joints array + ! loop through the JointIDs for this member and find the corresponding indices into the Joints array DO n = 2,3 ! Members column for JointIDs for nodes 1 and 2 Node = Init%Members(I, n) ! n=2 or 3 - - ! ...... search for index of joint whose JointID matches Node ...... + ! ...... search for index of joint whose JointID matches Node ...... J = 1 found = .false. DO WHILE ( .NOT. found .AND. J <= Init%NJoints ) @@ -201,29 +177,19 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) END IF J = J + 1 END DO - IF ( .NOT. found) THEN - CALL SetErrStat(ErrID_Fatal,' Member '//TRIM(Num2LStr(I))//' has JointID'//TRIM(Num2LStr(n-1))//' = '//& - TRIM(Num2LStr(Node))//' which is not in the node list !', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() + CALL Abort(' Member '//TRIM(Num2LStr(I))//' has JointID'//TRIM(Num2LStr(n-1))//' = '// TRIM(Num2LStr(Node))//' which is not in the node list !') RETURN END IF - END DO ! loop through nodes/joints - - ! loop through the PropSetIDs for this member and find the corresponding indices into the Joints array - + ! loop through the PropSetIDs for this member and find the corresponding indices into the Joints array ! we're setting these two values: - !p%Elems(I, 4) = property set for node 1 (note this sets the YoungE, ShearG, and MatDens columns for the ENTIRE element) - !p%Elems(I, 5) = property set for node 2 (note this should be used only for the XsecD and XsecT properties in the element [for a linear distribution from node 1 to node 2 of D and T]) - + ! p%Elems(I, 4) = property set for node 1 (note this sets the YoungE, ShearG, and MatDens columns for the ENTIRE element) + ! p%Elems(I, 5) = property set for node 2 (note this should be used only for the XsecD and XsecT properties in the element [for a linear distribution from node 1 to node 2 of D and T]) DO n=4,5 ! Member column for MPropSetID1 and MPropSetID2 - - Prop = Init%Members(I, n) ! n=4 or 5 - - ! ...... search for index of property set whose PropSetID matches Prop ...... + ! ...... search for index of property set whose PropSetID matches Prop ...... J = 1 found = .false. DO WHILE ( .NOT. found .AND. J <= Init%NPropSets ) @@ -233,16 +199,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) END IF J = J + 1 END DO - IF ( .NOT. found) THEN - CALL SetErrStat(ErrID_Fatal,' Member '//TRIM(Num2LStr(I))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//& - TRIM(Num2LStr(Prop))//' which is not in the Member X-Section Property data!', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() + CALL Abort(' Member '//TRIM(Num2LStr(I))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the Member X-Section Property data!') RETURN END IF - END DO ! loop through property ids - END DO ! loop through members ! Initialize TempMembers @@ -252,18 +213,14 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) TempProps = 0 TempProps(1:Init%NPropSets, :) = Init%PropSets - ! Initialize boundary constraint vector ! Change the node number - - - !Allocate array that will be p%Reacts renumbered and ordered so that ID does not play a role, just ordinal position number will count -RRD + ! Allocate array that will be p%Reacts renumbered and ordered so that ID does not play a role, just ordinal position number will count -RRD Init%BCs = 0 - TempReacts=0 !INitialize -RRD + TempReacts=0 DO I = 1, p%NReact Node1 = p%Reacts(I, 1); !NODE ID TempReacts(I,2:ReactCol)=p%Reacts(I, 2:ReactCol) !Assign all the appropriate fixity to the new Reacts array -RRD - found = .false. DO J = 1, Init%NJoints IF ( Node1 == NINT(Init%Joints(J, 1)) ) THEN @@ -273,25 +230,19 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) EXIT !Exit J loop if node found -RRD ENDIF ENDDO - IF (.not. found) THEN - CALL SetErrStat(ErrID_Fatal,' React has node not in the node list !', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() + CALL Abort(' React has node not in the node list !') RETURN ENDIF - - DO J = 1, 6 Init%BCs( (I-1)*6+J, 1) = (Node2-1)*6+J; Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); ENDDO - ENDDO p%Reacts=TempReacts !UPDATED REACTS ! Initialize interface constraint vector ! Change the node number - Init%IntFc = 0 DO I = 1, Init%NInterf Node1 = Init%Interf(I, 1); @@ -302,13 +253,10 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) found = .true. ENDIF ENDDO - IF (.not. found) THEN - CALL SetErrStat(ErrID_Fatal,' Interf has node not in the node list !', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() + CALL Abort(' Interf has node not in the node list !') RETURN ENDIF - DO J = 1, 6 Init%IntFc( (I-1)*6+J, 1) = (Node2-1)*6+J; Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); @@ -325,160 +273,151 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDDO ENDDO -! discretize structure according to NDiv - -knode = Init%NJoints -kelem = 0 -kprop = Init%NPropSets -Init%MemberNodes = 0 + ! discretize structure according to NDiv + knode = Init%NJoints + kelem = 0 + kprop = Init%NPropSets + Init%MemberNodes = 0 + + IF (Init%NDiv .GT. 1) THEN + DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information + ! create new node + Node1 = TempMembers(I, 2) + Node2 = TempMembers(I, 3) + + IF ( Node1==Node2 ) THEN + CALL Abort(' Same starting and ending node in the member.') + RETURN + ENDIF + + Prop1 = TempMembers(I, 4) + Prop2 = TempMembers(I, 5) + + Init%MemberNodes(I, 1) = Node1 + Init%MemberNodes(I, Init%NDiv+1) = Node2 + + IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN + + CALL Abort(' Material E,G and rho in a member must be the same') + RETURN + ENDIF + x1 = Init%Nodes(Node1, 2) + y1 = Init%Nodes(Node1, 3) + z1 = Init%Nodes(Node1, 4) -IF (Init%NDiv .GT. 1) THEN - DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information - ! create new node - Node1 = TempMembers(I, 2) - Node2 = TempMembers(I, 3) - - IF ( Node1==Node2 ) THEN - CALL SetErrStat(ErrID_Fatal,' Same starting and ending node in the member.', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() - RETURN - ENDIF - - - - Prop1 = TempMembers(I, 4) - Prop2 = TempMembers(I, 5) - - Init%MemberNodes(I, 1) = Node1 - Init%MemberNodes(I, Init%NDiv+1) = Node2 - - IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN - - CALL SetErrStat(ErrID_Fatal,' Material E,G and rho in a member must be the same', ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() - RETURN - ENDIF + x2 = Init%Nodes(Node2, 2) + y2 = Init%Nodes(Node2, 3) + z2 = Init%Nodes(Node2, 4) + + dx = ( x2 - x1 )/Init%NDiv + dy = ( y2 - y1 )/Init%NDiv + dz = ( z2 - z1 )/Init%NDiv + + d1 = TempProps(Prop1, 5) + t1 = TempProps(Prop1, 6) - x1 = Init%Nodes(Node1, 2) - y1 = Init%Nodes(Node1, 3) - z1 = Init%Nodes(Node1, 4) + d2 = TempProps(Prop2, 5) + t2 = TempProps(Prop2, 6) + + dd = ( d2 - d1 )/Init%NDiv + dt = ( t2 - t1 )/Init%NDiv + + ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node + CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) + + ! node connect to Node1 + knode = knode + 1 + Init%MemberNodes(I, 2) = knode + CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) + + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, Prop1, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, Prop1, Prop1, p) + nprop = Prop1 + ENDIF + + ! interior nodes + DO J = 2, (Init%NDiv-1) + knode = knode + 1 + Init%MemberNodes(I, J+1) = knode + + CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3),& + Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, & + TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, nprop, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, nprop, nprop, p) + + ENDIF + ENDDO + + ! the element connect to Node2 + kelem = kelem + 1 + CALL SetNewElem(kelem, knode, Node2, nprop, Prop2, p) - x2 = Init%Nodes(Node2, 2) - y2 = Init%Nodes(Node2, 3) - z2 = Init%Nodes(Node2, 4) - - dx = ( x2 - x1 )/Init%NDiv - dy = ( y2 - y1 )/Init%NDiv - dz = ( z2 - z1 )/Init%NDiv - - d1 = TempProps(Prop1, 5) - t1 = TempProps(Prop1, 6) + ENDDO ! loop over all members - d2 = TempProps(Prop2, 5) - t2 = TempProps(Prop2, 6) - - dd = ( d2 - d1 )/Init%NDiv - dt = ( t2 - t1 )/Init%NDiv - - ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node - CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. & - EqualRealNos( dt , 0.0_ReKi ) ) - - ! node connect to Node1 - knode = knode + 1 - Init%MemberNodes(I, 2) = knode - CALL GetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) - - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - - kprop = kprop + 1 - CALL GetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3),& - TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) - kelem = kelem + 1 - CALL GetNewElem(kelem, Node1, knode, Prop1, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL GetNewElem(kelem, Node1, knode, Prop1, Prop1, p) - nprop = Prop1 - ENDIF - - ! interior nodes - - DO J = 2, (Init%NDiv-1) - knode = knode + 1 - Init%MemberNodes(I, J+1) = knode + ELSE ! NDiv = 1 - CALL GetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - - kprop = kprop + 1 - CALL GetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3),& - Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, & - TempProps) - kelem = kelem + 1 - CALL GetNewElem(kelem, knode-1, knode, nprop, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL GetNewElem(kelem, knode-1, knode, nprop, nprop, p) - - ENDIF - ENDDO - - ! the element connect to Node2 - kelem = kelem + 1 - CALL GetNewElem(kelem, knode, Node2, nprop, Prop2, p) - - ENDDO ! loop over all members + Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) -ELSE ! NDiv = 1 + ENDIF ! if NDiv is greater than 1 - Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) + ! set the props in Init + Init%NProp = kprop + CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%Props', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + IF (ErrStat >= AbortErrLev ) THEN + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat,ErrMsg,'SD_Discrt'); + CALL CleanUp_Discrt() + RETURN + ENDIF + !Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps + Init%Props = TempProps(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 -ENDIF ! if NDiv is greater than 1 + CALL CleanUp_Discrt() -! set the props in Init -Init%NProp = kprop -CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%Props', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - IF (ErrStat >= AbortErrLev ) THEN - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat,ErrMsg,'SD_Discrt'); +CONTAINS + SUBROUTINE Abort(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); CALL CleanUp_Discrt() - RETURN -ENDIF -!Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps -Init%Props = TempProps(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + END SUBROUTINE Abort -CALL CleanUp_Discrt() - -RETURN -CONTAINS -!................ SUBROUTINE CleanUp_Discrt() - -! deallocate temp matrices -IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) -IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) -IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) - + ! deallocate temp matrices + IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) + IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) + IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) END SUBROUTINE CleanUp_Discrt END SUBROUTINE SD_Discrt -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ -SUBROUTINE GetNewNode(k, x, y, z, Init) +!------------------------------------------------------------------------------------------------------ +!> Set properties of node k +SUBROUTINE SetNewNode(k, x, y, z, Init) TYPE(SD_InitType), INTENT(INOUT) :: Init - INTEGER, INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: x, y, z @@ -487,19 +426,17 @@ SUBROUTINE GetNewNode(k, x, y, z, Init) Init%Nodes(k, 3) = y Init%Nodes(k, 4) = z +END SUBROUTINE SetNewNode -END SUBROUTINE GetNewNode -!------------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------------ -SUBROUTINE GetNewElem(k, n1, n2, p1, p2, p) - +!> Set properties of element k +SUBROUTINE SetNewElem(k, n1, n2, p1, p2, p) INTEGER, INTENT(IN ) :: k INTEGER, INTENT(IN ) :: n1 INTEGER, INTENT(IN ) :: n2 INTEGER, INTENT(IN ) :: p1 INTEGER, INTENT(IN ) :: p2 TYPE(SD_ParameterType), INTENT(INOUT) :: p - p%Elems(k, 1) = k p%Elems(k, 2) = n1 @@ -507,12 +444,11 @@ SUBROUTINE GetNewElem(k, n1, n2, p1, p2, p) p%Elems(k, 4) = p1 p%Elems(k, 5) = p2 -END SUBROUTINE GetNewElem -!------------------------------------------------------------------------------------------------------ +END SUBROUTINE SetNewElem + !------------------------------------------------------------------------------------------------------ -SUBROUTINE GetNewProp(k, E, G, rho, d, t, TempProps) -!RRD-modifying this routine: This routine intends to calculate new member properties in case NDIV>1 ; 1/23/14 - +!> Set material properties of element k +SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) INTEGER , INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: E, G, rho, d, t REAL(ReKi), INTENT(INOUT):: TempProps(:, :) @@ -524,22 +460,20 @@ SUBROUTINE GetNewProp(k, E, G, rho, d, t, TempProps) TempProps(k, 5) = d TempProps(k, 6) = t -END SUBROUTINE GetNewProp -!------------------------------------------------------------------------------------------------------ +END SUBROUTINE SetNewProp + !------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) - - TYPE(SD_InitType), INTENT(INOUT) ::Init - TYPE(SD_ParameterType), INTENT(INOUT) ::p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables INTEGER :: I, J, K, Jn, Kn - - INTEGER :: NNE ! number of nodes in one element + INTEGER, PARAMETER :: NNE=2 ! number of nodes in one element, fixed to 2 INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes - REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section REAL(ReKi) :: x1, y1, z1, x2, y2, z2 ! coordinates of the nodes REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices @@ -547,55 +481,46 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector - INTEGER, ALLOCATABLE :: nn(:) ! node number in element + INTEGER, DIMENSION(NNE) :: nn ! node number in element INTEGER :: r - - INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 - - ! for current application - IF ( (Init%FEMMod .LE. 3) .and. (Init%FEMMod .GE. 0)) THEN - NNE = 2 - ELSE - ErrStat = ErrID_Fatal - ErrMsg = 'Invalid FEMMod in AssembleKM' - RETURN - ENDIF + ! for current application + if (Init%FEMMod == 2) THEN ! tapered Euler-Bernoulli + CALL Abort ('FEMMod = 2 is not implemented.') + return + elseif (Init%FEMMod == 4) THEN ! tapered Timoshenko + CALL Abort ('FEMMod = 2 is not implemented.') + return + elseif ((Init%FEMMod == 1) .or. (Init%FEMMod == 3)) THEN ! + ! 1: uniform Euler-Bernouli, 3: uniform Timoshenko + else + CALL Abort('FEMMod is not valid. Please choose from 1, 2, 3, and 4. ') + return + endif ! total degrees of freedom of the system Init%TDOF = 6*Init%NNode - ! Assemble system stiffness and mass matrices with gravity force vector - ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat ( ErrID_Fatal, 'Error allocating p%ElemProps', ErrStat, ErrMsg, 'AssembleKM' ) - CALL CleanUp_AssembleKM() - RETURN + IF (ErrStat2 /= 0) THEN + CALL Abort('Error allocating p%ElemProps') + return ENDIF - CALL AllocAry( Ke, NNE*6, NNE*6 , 'Ke', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! element stiffness matrix - CALL AllocAry( Me, NNE*6, NNE*6 , 'Me', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! element mass matrix - CALL AllocAry( FGe, NNE*6, 'FGe', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! element gravity force vector - CALL AllocAry( nn, NNE, 'nn', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! node number in element array - - CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! system stiffness matrix - CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! system mass matrix - CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) ! system gravity force vector - - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp_AssembleKM() - RETURN - ENDIF - - Init%K = 0.0_ReKi - Init%M = 0.0_ReKi + CALL AllocAry( Ke, NNE*6, NNE*6 , 'Ke', ErrStat2, ErrMsg2); if(Failed()) return; ! element stiffness matrix + CALL AllocAry( Me, NNE*6, NNE*6 , 'Me', ErrStat2, ErrMsg2); if(Failed()) return; ! element mass matrix + CALL AllocAry( FGe, NNE*6, 'FGe', ErrStat2, ErrMsg2); if(Failed()) return; ! element gravity force vector + CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + Init%K = 0.0_ReKi + Init%M = 0.0_ReKi Init%FG = 0.0_ReKi - ! loop over all elements + ! loop over all elements DO I = 1, Init%NElem DO J = 1, NNE @@ -608,7 +533,6 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) P1 = p%Elems(I, NNE + 2) P2 = p%Elems(I, NNE + 3) - E = Init%Props(P1, 2) G = Init%Props(P1, 3) rho = Init%Props(P1, 4) @@ -625,166 +549,119 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) y2 = Init%Nodes(N2, 3) z2 = Init%Nodes(N2, 4) - CALL GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat2, ErrMsg2) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp_AssembleKM() - RETURN - END IF - - -!BJJ: TODO: for efficiency, this if check should be OUTSIDE the DO loop. - ! 1: uniform Euler-Bernouli - ! 3: uniform Timoshenko - IF ( (Init%FEMMod == 1).OR.(Init%FEMMod == 3)) THEN ! uniform element - r1 = 0.25*(D1 + D2) - t = 0.5*(t1+t2) - - IF ( EqualRealNos(t, 0.0_ReKi) ) THEN - r2 = 0 - ELSE - r2 = r1 - t - ENDIF - - A = Pi_D*(r1*r1-r2*r2) - Ixx = 0.25*Pi_D*(r1**4-r2**4) - Iyy = Ixx - Jzz = 2.0*Ixx - - IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli - Shear = .false. - kappa = 0 - ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko - Shear = .true. - ! kappa = 0.53 - - ! equation 13 (Steinboeck et al) in SubDyn Theory Manual - nu = E / (2.0_ReKi*G) - 1.0_ReKi - D_outer = 2.0_ReKi * r1 ! average (outer) diameter - D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter - ratioSq = ( D_inner / D_outer)**2 - kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & - / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) - - ENDIF - - p%ElemProps(i)%Area = A - p%ElemProps(i)%Length = L - p%ElemProps(i)%Ixx = Ixx - p%ElemProps(i)%Iyy = Iyy - p%ElemProps(i)%Jzz = Jzz - p%ElemProps(i)%Shear = Shear - p%ElemProps(i)%kappa = kappa - p%ElemProps(i)%YoungE = E - p%ElemProps(i)%ShearG = G - p%ElemProps(i)%Rho = rho - p%ElemProps(i)%DirCos = DirCos - - - CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) - CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) - CALL ElemG(A, L, rho, DirCos, FGe, Init%g) - - ELSEIF (Init%FEMMod == 2) THEN ! tapered Euler-Bernoulli - CALL SetErrStat ( ErrID_Fatal, 'FEMMod = 2 is not implemented.', ErrStat, ErrMsg, 'AssembleKM' ) - CALL CleanUp_AssembleKM() - RETURN - - ELSEIF (Init%FEMMod == 4) THEN ! tapered Timoshenko - CALL SetErrStat ( ErrID_Fatal, 'FEMMod = 4 is not implemented.', ErrStat, ErrMsg, 'AssembleKM' ) - CALL CleanUp_AssembleKM() - RETURN + CALL GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return + r1 = 0.25*(D1 + D2) + t = 0.5*(t1+t2) + + IF ( EqualRealNos(t, 0.0_ReKi) ) THEN + r2 = 0 ELSE - CALL SetErrStat ( ErrID_Fatal, 'FEMMod is not valid. Please choose from 1, 2, 3, and 4. ', ErrStat, ErrMsg, 'AssembleKM' ) - CALL CleanUp_AssembleKM() - RETURN - - ENDIF - - + r2 = r1 - t + ENDIF + + A = Pi_D*(r1*r1-r2*r2) + Ixx = 0.25*Pi_D*(r1**4-r2**4) + Iyy = Ixx + Jzz = 2.0*Ixx + + IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli + Shear = .false. + kappa = 0 + ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko + Shear = .true. + ! kappa = 0.53 + ! equation 13 (Steinboeck et al) in SubDyn Theory Manual + nu = E / (2.0_ReKi*G) - 1.0_ReKi + D_outer = 2.0_ReKi * r1 ! average (outer) diameter + D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter + ratioSq = ( D_inner / D_outer)**2 + kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & + / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) + ENDIF + + p%ElemProps(i)%Area = A + p%ElemProps(i)%Length = L + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%kappa = kappa + p%ElemProps(i)%YoungE = E + p%ElemProps(i)%ShearG = G + p%ElemProps(i)%Rho = rho + p%ElemProps(i)%DirCos = DirCos + + CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) + CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) + CALL ElemG(A, L, rho, DirCos, FGe, Init%g) ! assemble element matrices to global matrices - DO J = 1, NNE jn = nn(j) - - Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) & - + FGe( (J*6-5):(J*6) ) - + Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) ) DO K = 1, NNE kn = nn(k) - - Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) & - + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) - - Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) & - + Me( (J*6-5):(J*6), (K*6-5):(K*6) ) - - + Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) + Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Me( (J*6-5):(J*6), (K*6-5):(K*6) ) ENDDO !K - ENDDO !J - - ENDDO ! I end loop over elements - - ! add concentrated mass + ! add concentrated mass DO I = 1, Init%NCMass DO J = 1, 3 r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J Init%M(r, r) = Init%M(r, r) + Init%CMass(I, 2) - ENDDO DO J = 4, 6 r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J Init%M(r, r) = Init%M(r, r) + Init%CMass(I, J-1) ENDDO + ENDDO ! Loop on concentrated mass - ENDDO ! I concentrated mass - - ! add concentrated mass induced gravity force + ! add concentrated mass induced gravity force DO I = 1, Init%NCMass - - r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 - Init%FG(r) = Init%FG(r) - Init%CMass(I, 2)*Init%g - + r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 + Init%FG(r) = Init%FG(r) - Init%CMass(I, 2)*Init%g ENDDO ! I concentrated mass induced gravity CALL CleanUp_AssembleKM() - RETURN CONTAINS -!.............. + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM') + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup_AssembleKM() + END FUNCTION Failed + + SUBROUTINE Abort(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); + CALL CleanUp_AssembleKM() + END SUBROUTINE Abort + SUBROUTINE CleanUp_AssembleKM() -! deallocate temp matrices - IF (ALLOCATED(Ke)) DEALLOCATE(Ke) - IF (ALLOCATED(Me)) DEALLOCATE(Me) - IF (ALLOCATED(FGe)) DEALLOCATE(FGe) - IF (ALLOCATED(nn)) DEALLOCATE(nn) + IF(ALLOCATED(Ke )) DEALLOCATE(Ke ) + IF(ALLOCATED(Me )) DEALLOCATE(Me ) + IF(ALLOCATED(FGe)) DEALLOCATE(FGe) END SUBROUTINE CleanUp_AssembleKM END SUBROUTINE AssembleKM -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!------------------------------------------------------------------------------------------------------ +!> Computes directional cosine matrix DirCos +!! rrd: This should be from local to global +!! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix +!! in the FAST framework. It seems to be used consistantly in the code (i.e., the transpose +!! of this matrix is used later). SUBROUTINE GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat, ErrMsg) - !This should be from local to global -RRD - ! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix - ! in the FAST framework. It seems to be used consistantly in the code (i.e., the transpose - ! of this matrix is used later). - - REAL(ReKi) , INTENT(IN ) :: x1, y1, z1, x2, y2, z2 ! (x,y,z) positions of two nodes making up an element REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix REAL(ReKi) , INTENT( OUT) :: L ! length of element - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: Dx,Dy,Dz, Dxy ! distances between nodes -!real(reki) :: dxyz ErrMsg = "" ErrStat = ErrID_None @@ -826,27 +703,24 @@ SUBROUTINE GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat, ErrMsg) ENDIF END SUBROUTINE GetDirCos -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for classical beam elements +!! shear is true -- non-tapered Timoshenko beam +!! shear is false -- non-tapered Euler-Bernoulli beam SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) - ! element stiffness matrix for classical beam elements - ! shear is true -- non-tapered Timoshenko beam - ! shear is false -- non-tapered Euler-Bernoulli beam - - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - LOGICAL, INTENT( IN) :: Shear - - REAL(ReKi), INTENT(OUT) :: K(12, 12) !RRD: Ke and Me need to be modified if convention of dircos is not followed? - + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + LOGICAL , INTENT( IN) :: Shear + REAL(ReKi), INTENT(OUT) :: K(12, 12) + ! Local variables REAL(ReKi) :: Ax, Ay, Kx, Ky REAL(ReKi) :: DC(12, 12) Ax = kappa*A Ay = kappa*A - K = 0 + K(1:12,1:12) = 0 IF (Shear) THEN Kx = 12.0*E*Iyy / (G*Ax*L*L) @@ -904,33 +778,26 @@ SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) DC( 7: 9, 7: 9) = DirCos DC(10:12, 10:12) = DirCos - K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) + K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed - !write(*, *) K - TRANSPOSE(K) - END SUBROUTINE ElemK -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!------------------------------------------------------------------------------------------------------ +!> Element mass matrix for classical beam elements SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) - ! element mass matrix for classical beam elements + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT(OUT) :: M(12, 12) - - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - - REAL(ReKi) :: M(12, 12) - - REAL(ReKi) :: t, rx, ry, po - REAL(ReKi) :: DC(12, 12) + REAL(ReKi) :: t, rx, ry, po + REAL(ReKi) :: DC(12, 12) t = rho*A*L; rx = rho*Ixx; ry = rho*Iyy; po = rho*Jzz*L; - M = 0 - + M(1:12,1:12) = 0 M( 9, 9) = t/3.0 M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) @@ -980,68 +847,56 @@ SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) DC( 7: 9, 7: 9) = DirCos DC(10:12, 10:12) = DirCos - M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) + M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed END SUBROUTINE ElemM - -!------------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------------ - +!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices SUBROUTINE ApplyConstr(Init,p) - - - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(IN) :: p + TYPE(SD_InitType ),INTENT(INOUT):: Init + TYPE(SD_ParameterType),INTENT(IN ):: p - INTEGER :: I !, J, k - INTEGER :: row_n !bgn_j, end_j, + INTEGER :: I !, J, k + INTEGER :: row_n !bgn_j, end_j, DO I = 1, p%NReact*6 row_n = Init%BCs(I, 1) - IF (Init%BCs(I, 2) == 1) THEN - Init%K(row_n, :) = 0 - Init%K(:, row_n) = 0 - Init%K(row_n, row_n) = 1 - - Init%M(row_n, :) = 0 - Init%M(:, row_n) = 0 - Init%M(row_n, row_n) = 0 !0.00001 !what is this???? I changed this to 0. RRD 7/31 - ENDIF - - ENDDO ! I - - + Init%K(row_n,: )= 0 + Init%K(: ,row_n)= 0 + Init%K(row_n,row_n)= 1 + Init%M(row_n,: )= 0 + Init%M(: ,row_n)= 0 + Init%M(row_n,row_n)= 0 + ENDIF + ENDDO ! I, loop on reaction nodes END SUBROUTINE ApplyConstr + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!> calculates the lumped forces and moments due to gravity on a given element: +!! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: +!! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, +!! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 SUBROUTINE ElemG(A, L, rho, DirCos, F, g) -! this routine calculates the lumped forces and moments due to gravity on a given element: -! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: -! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, -! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 -!------------------------------------------------------------------------------------------------------ - REAL(ReKi), INTENT( OUT) :: F(12) ! returned loads. positions 1-6 are the loads for node 1; 7-12 are loads for node 2. - REAL(ReKi), INTENT( IN ) :: A ! area - REAL(ReKi), INTENT( IN ) :: g ! gravity - REAL(ReKi), INTENT( IN ) :: L ! element length - REAL(ReKi), INTENT( IN ) :: rho - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) ! direction cosine matrix (for determining distance between nodes 1 and 2) - - REAL(ReKi) :: TempCoeff - REAL(ReKi) :: w ! weight per unit length - + REAL(ReKi), INTENT( IN ) :: A !< area + REAL(ReKi), INTENT( IN ) :: L !< element length + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix (for determining distance between nodes 1 and 2) + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1; 7-12 are loads for node 2. + REAL(ReKi) :: TempCoeff + REAL(ReKi) :: w ! weight per unit length F = 0 ! initialize whole array to zero, then set the non-zero portions w = rho*A*g ! weight per unit length - ! lumped forces on both nodes (z component only): + ! lumped forces on both nodes (z component only): F(3) = -0.5*L*w F(9) = F(3) - ! lumped moments on node 1 (x and y components only): + ! lumped moments on node 1 (x and y components only): ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice @@ -1053,31 +908,25 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) F(11) = -F(5) !F(12) is 0 for g along z alone - END SUBROUTINE ElemG !------------------------------------------------------------------------------------------------------ +!> Calculates the lumped gravity forces at the nodes given the element geometry +!! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 +!! bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) -!bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. - - !This rountine calculates the lumped gravity forces at the nodes given the element geometry - !It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 - REAL(ReKi), INTENT( OUT) :: F(12) - REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !X-sectional areas at node 1 and node 2, t2/t1 thickness ratio - REAL(ReKi), INTENT( IN ) :: g !gravity - REAL(ReKi), INTENT( IN ) :: L !Length of element - REAL(ReKi), INTENT( IN ) :: rho !density - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) - - !LOCALS + REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !< X-sectional areas at node 1 and node 2, t2/t1 thickness ratio + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( IN ) :: L !< Length of element + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< Direction cosine matrix + REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces + !LOCALS REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force - - A1 = -99999 !bjj initialized this to avoid getting warning by Intel Analyzers; needs to be set differently - A2 = -99999 !bjj initialized this to avoid getting warning by Intel Analyzers; needs to be set differently !Calculate quadratic polynomial coefficients - a0=A1 - a2=( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. !*x**2 - a1= (Area2-Area1)/L -a2*L !*x + a0 = a1 + a2 = ( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. ! *x**2 + a1 = (Area2-Area1)/L -a2*L ! *x !Now calculate the Lumped Forces F = 0 @@ -1092,14 +941,12 @@ SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) !F(5) = TempCoeff*( DirCos(1, 3)*DirCos(2, 2) - DirCos(1, 2)*DirCos(2, 3) ) !RRD attempt at new dircos which keeps x in the X-Y plane - F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent - F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent - !RRD ends + F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent + F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent + !RRD ends F(10) = -F(4) F(11) = -F(5) !F(12) is 0 for g along z alone - - END SUBROUTINE LumpForces END MODULE SD_FEM From 28b43e07e62c7ace12b19eff63389435f8dbd867 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 23 Oct 2019 19:47:20 -0600 Subject: [PATCH 022/377] FlexSub: starting clean up of main --- modules/subdyn/src/SubDyn.f90 | 1991 +++++++++------------------------ 1 file changed, 501 insertions(+), 1490 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 39830a31a..9a2dbabc9 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -37,92 +37,66 @@ Module SubDyn ! NOTE: for debugging, add preprocessor definition SD_SUMMARY_DEBUG ! this will add additional matrices to the SubDyn summary file. !............................ - TYPE(ProgDesc), PARAMETER :: SD_ProgDesc = ProgDesc( 'SubDyn', '', '' ) ! ..... Public Subroutines ................................................................................................... - PUBLIC :: SD_Init ! Initialization routine - PUBLIC :: SD_End ! Ending routine (includes clean up) - PUBLIC :: SD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating - PUBLIC :: SD_CalcOutput ! Routine for computing outputs - PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states - CONTAINS - SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) - REAL(ReKi), INTENT( IN ) :: TP_RefPoint(3) TYPE(MeshType), INTENT( INOUT ) :: inputMesh TYPE(MeshType), INTENT( INOUT ) :: outputMesh INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! NOTE: The initialization of the fields for these meshes is to be handled by FAST/Driver - - CALL MeshCreate( BlankMesh = inputMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = 1 & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. & - ) - - - ! Create the node on the mesh - - CALL MeshPositionNode ( inputMesh & - , 1 & - , TP_RefPoint & - , ErrStat & - , ErrMsg ) !note: assumes identiy matrix as reference orientation - - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Create the mesh element - - CALL MeshConstructElement ( inputMesh & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , 1 & - ) - CALL MeshCommit ( inputMesh & - , ErrStat & - , ErrMsg ) - - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh - - CALL MeshCopy ( SrcMesh = inputMesh & - ,DestMesh = outputMesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. & - ) - + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + ! Create the node on the mesh + CALL MeshPositionNode ( inputMesh & + , 1 & + , TP_RefPoint & + , ErrStat & + , ErrMsg ) !note: assumes identiy matrix as reference orientation + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Create the mesh element + CALL MeshConstructElement ( inputMesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , 1 ) + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh + CALL MeshCopy ( SrcMesh = inputMesh & + ,DestMesh = outputMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) END SUBROUTINE CreateTPMeshes SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, IDC, inputMesh, outputMesh, ErrStat, ErrMsg ) - INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) INTEGER(IntKi), INTENT( IN ) :: NNodes_I ! number interface nodes i.e. Y2 stuff at the beginning @@ -135,8 +109,7 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, TYPE(MeshType), INTENT( INOUT ) :: outputMesh INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - + ! Local variables INTEGER :: I ! generic counter variable INTEGER :: nodeIndx @@ -146,108 +119,73 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, ,ErrStat = ErrStat & ,ErrMess = ErrMsg & ,Force = .TRUE. & - ,Moment = .TRUE. & - ) - - + ,Moment = .TRUE. ) !--------------------------------------------------------------------- ! Interface nodes !--------------------------------------------------------------------- - DO I = 1,NNodes_I - - ! Create the node on the mesh + ! Create the node on the mesh nodeIndx = IDI(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID - CALL MeshPositionNode ( inputMesh & , I & , Nodes(nodeIndx,2:4) & ! position , ErrStat & - , ErrMsg ) - + , ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN - - - ! Create the mesh element - + + ! Create the mesh element CALL MeshConstructElement ( inputMesh & , ELEMENT_POINT & , ErrStat & , ErrMsg & - , I & - ) - + , I ) END DO - !--------------------------------------------------------------------- ! Interior nodes !--------------------------------------------------------------------- - DO I = 1,NNodes_L - - ! Create the node on the mesh + ! Create the node on the mesh nodeIndx = IDL(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes - CALL MeshPositionNode ( inputMesh & , I + NNodes_I & - , Nodes(nodeIndx,2:4) & + , Nodes(nodeIndx,2:4) & , ErrStat & - , ErrMsg ) - + , ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN - - - ! Create the mesh element - + + ! Create the mesh element CALL MeshConstructElement ( inputMesh & , ELEMENT_POINT & , ErrStat & , ErrMsg & - , I + NNodes_I & - ) - + , I + NNodes_I ) END DO - !--------------------------------------------------------------------- ! Base Reaction nodes !--------------------------------------------------------------------- - DO I = 1,NNodes_C - - ! Create the node on the mesh + ! Create the node on the mesh nodeIndx = IDC(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID - CALL MeshPositionNode ( inputMesh & , I + NNodes_I + NNodes_L & , Nodes(nodeIndx,2:4) & , ErrStat & - , ErrMsg ) - + , ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN - - ! Create the mesh element - + ! Create the mesh element CALL MeshConstructElement ( inputMesh & , ELEMENT_POINT & , ErrStat & , ErrMsg & - , I + NNodes_I + NNodes_L & - ) - + , I + NNodes_I + NNodes_L ) END DO - - CALL MeshCommit ( inputMesh & - , ErrStat & - , ErrMsg ) - + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN - - - ! Create the Interior Points output mesh as a sibling copy of the input mesh + ! Create the Interior Points output mesh as a sibling copy of the input mesh CALL MeshCopy ( SrcMesh = inputMesh & ,DestMesh = outputMesh & ,CtrlCode = MESH_SIBLING & @@ -259,73 +197,46 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, ,TranslationVel = .TRUE. & ,RotationVel = .TRUE. & ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. & - ) - + ,RotationAcc = .TRUE. ) - ! Set the Orientation (rotational) field for the nodes based on assumed 0 (rotational) deflections - - !Identity should mean no rotation, which is our first guess at the output -RRD - CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) - + ! Set the Orientation (rotational) field for the nodes based on assumed 0 (rotational) deflections + !Identity should mean no rotation, which is our first guess at the output -RRD + CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) END SUBROUTINE CreateY2Meshes !------------------------------------------------------------------------------------------------------ -!> this routine sets the index array that maps SD internal nodes to the Y2Mesh nodes. +!> Set the index array that maps SD internal nodes to the Y2Mesh nodes. !! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, !! so this routine could easily have segmentation faults if any errors exist. SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh ) -!....................................................... - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh - ! locals INTEGER(IntKi) :: i INTEGER(IntKi) :: SDnode INTEGER(IntKi) :: y2Node - y2Node = 0 - - !--------------------------------------------------------------------- - ! Interface nodes - !--------------------------------------------------------------------- + ! Interface nodes (IDI) DO I = 1,SIZE(p%IDI,1)/6 y2Node = y2Node + 1 SDnode = p%IDI(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID - - SDtoMesh( SDnode ) = y2Node - !MeshtoSD( y2Node ) = SDnode + SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO - - - !--------------------------------------------------------------------- - ! Interior nodes - !--------------------------------------------------------------------- + ! Interior nodes (IDL) DO I = 1,SIZE(p%IDL,1)/6 y2Node = y2Node + 1 SDnode = p%IDL(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID - - SDtoMesh( SDnode ) = y2Node - !MeshtoSD( y2Node ) = SDnode + SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO - - - !--------------------------------------------------------------------- - ! Base Reaction nodes - !--------------------------------------------------------------------- - + + ! Base Reaction nodes (IDC) DO I = 1,SIZE(p%IDC,1)/6 y2Node = y2Node + 1 SDnode = p%IDC(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID - - SDtoMesh( SDnode ) = y2Node - !MeshtoSD( y2Node ) = SDnode - + SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO - END SUBROUTINE SD_Y2Mesh_Mapping @@ -335,8 +246,6 @@ END SUBROUTINE SD_Y2Mesh_Mapping !! The parameters are set here and not changed during the simulation. !! The initial states and initial guess for the input are defined. SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) -!.................................................................................................................................. - TYPE(SD_InitInputType), INTENT(IN ) :: InitInput !< Input data for initialization routine TYPE(SD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined TYPE(SD_ParameterType), INTENT( OUT) :: p !< Parameters @@ -356,32 +265,25 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO TYPE(SD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! local variables - - TYPE(SD_InitType) :: Init - - TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file - TYPE(FEM_MatArrays) :: FEMparams ! FEM parameters to be stored and written to summary file - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - + ! local variables + TYPE(SD_InitType) :: Init + TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file + TYPE(FEM_MatArrays) :: FEMparams ! FEM parameters to be stored and written to summary file + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - ! Initialize variables + ! Initialize variables ErrStat = ErrID_None ErrMsg = "" - ! Initialize the NWTC Subroutine Library - + ! Initialize the NWTC Subroutine Library CALL NWTC_Init( ) - ! Display the module information - + ! Display the module information CALL DispNVD( SD_ProgDesc ) InitOut%Ver = SD_ProgDesc - ! transfer glue-code information to data structure for SubDyn initialization: + ! transfer glue-code information to data structure for SubDyn initialization: Init%g = InitInput%g Init%TP_RefPoint = InitInput%TP_RefPoint Init%SubRotateZ = InitInput%SubRotateZ @@ -390,9 +292,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) - - - ! Establish the GLUECODE requested/suggested time step. This may be overridden by SubDyn based on the SDdeltaT parameter of the SubDyn input file. + ! Establish the GLUECODE requested/suggested time step. This may be overridden by SubDyn based on the SDdeltaT parameter of the SubDyn input file. Init%DT = Interval IF ( LEN_TRIM(Init%RootName) == 0 ) THEN CALL GetRoot( InitInput%SDInputFile, Init%RootName ) @@ -400,106 +300,45 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO Init%RootName = TRIM(InitInput%RootName)//'.SD' END IF - - !................................. ! Parse the SubDyn inputs - !................................. - - CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - - - !................................. - !------------- Discretize the structure according to the division size ----------------- - !................................. - - CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2) ! sets Init%NNode, Init%NElm - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! Discretize the structure according to the division size + ! sets Init%NNode, Init%NElm + CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - - CALL AssembleKM(Init,p, ErrStat2, ErrMsg2) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - + ! Assemble Stiffness and mass matrix + CALL AssembleKM(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - !................................. - ! Calculate values for FEMparams (for summary file output only - !................................. - - ! Solve dynamics problem - + ! --- Calculate values for FEMparams (for summary file output only + ! Solve dynamics problem FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change - CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return + ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. + CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return - ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. - - CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - - !................................. - ! Craig-Bampton reduction - !................................. - - - CALL Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2) !sets many parameters... - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + ! --- Craig-Bampton reduction (sets many parameters) + CALL Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return - - !................................. - ! Define initial system states here: - !................................. + ! --- Initial system states IF ( p%qmL > 0 ) THEN - - CALL AllocAry(x%qm, p%qmL, 'x%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - CALL AllocAry(x%qmdot, p%qmL, 'x%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - CALL AllocAry(m%qmdotdot, p%qmL, 'm%qmdotdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL AllocAry(x%qm, p%qmL, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(x%qmdot, p%qmL, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(m%qmdotdot, p%qmL, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return x%qm = 0.0_ReKi x%qmdot = 0.0_ReKi m%qmdotdot= 0.0_ReKi - END IF - xd%DummyDiscState = 0.0_ReKi z%DummyConstrState = 0.0_ReKi - - - ! Allocate OtherState%xdot if using multi-step method; initialize n + + ! Allocate OtherState%xdot if using multi-step method; initialize n IF ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) THEN !bjj: note that the way SD_UpdateStates is implemented, "n" doesn't need to be initialized here Allocate( OtherState%xdot(4), STAT=ErrStat2 ) @@ -509,104 +348,58 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO RETURN END IF ENDIF - - ! allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time - CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Init') + ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time + CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return - !................................. - ! Write the summary file - !................................. - - + ! --- Write the summary file IF ( Init%SSSum ) THEN - !note p%KBB/MBB are KBBt/MBBt - - ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - + ! note p%KBB/MBB are KBBt/MBBt + ! Write a summary of the SubDyn Initialization + CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) ENDIF - - !................................. - ! Initialize Inputs and Outputs - !................................. - - ! Create the input and output meshes associated with Transition Piece reference point - - CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction - - CALL CreateY2Meshes( Init%NNode, Init%Nodes, Init%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + ! --- Initialize Inputs and Outputs + ! Create the input and output meshes associated with Transition Piece reference point + CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction + CALL CreateY2Meshes( Init%NNode, Init%Nodes, Init%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - ! Initialize the outputs & Store mapping between nodes and elements - - CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + ! Initialize the outputs & Store mapping between nodes and elements + CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return - - ! Determine if we need to perform output file handling - + ! Determine if we need to perform output file handling IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ); if(Failed()) return END IF - ! Tell GLUECODE the SubDyn timestep interval - + ! Tell GLUECODE the SubDyn timestep interval Interval = p%SDdeltaT - CALL CleanUp() CONTAINS -!....................................................... - SUBROUTINE CleanUp() + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE CleanUp() CALL SD_DestroyInitType(Init, ErrStat2, ErrMsg2) - CALL SD_DestroyCB_MatArrays( CBparams, ErrStat2, ErrMsg2 ) ! local variables CALL SD_DestroyFEM_MatArrays( FEMparams, ErrStat2, ErrMsg2 ) ! local variables - END SUBROUTINE CleanUp -!....................................................... + END SUBROUTINE SD_Init -!---------------------------------------------------------------------------------------------------------------------------------- - !---------------------------------------------------------------------------------------------------------------------------------- !> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. !! Continuous, discrete, constraint, and other states are updated for t + Interval. SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval TYPE(SD_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at Times @@ -623,36 +416,21 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - - ! Initialize variables - + ! Initialize variables ErrStat = ErrID_None ! no error has occurred ErrMsg = "" IF ( p%qml == 0) RETURN ! no retained modes = no states - IF (p%IntMethod .eq. 1) THEN - CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSEIF (p%IntMethod .eq. 2) THEN - CALL SD_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSEIF (p%IntMethod .eq. 3) THEN - CALL SD_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSE - CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - END IF - - END SUBROUTINE SD_UpdateStates @@ -660,8 +438,6 @@ END SUBROUTINE SD_UpdateStates !---------------------------------------------------------------------------------------------------------------------------------- !> Routine for computing outputs, used in both loose and tight coupling. SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters @@ -674,67 +450,55 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - !locals - - INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays - INTEGER(IntKi) :: I,J ! Counters - REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) - - REAL(ReKi) :: rotations(3) - - REAL(ReKi) :: ULS(p%DOFL), UL0m(p%DOFL), FLt(p%DOFL) ! Temporary values in static improvement method - REAL(ReKi) :: Y1(6) - INTEGER(IntKi) :: startDOF - REAL(ReKi) :: DCM(3,3),junk(6,p%NNodes_L) - REAL(ReKi) :: HydroForces(6*p%NNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) - - TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays + INTEGER(IntKi) :: I,J ! Counters + REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) + REAL(ReKi) :: rotations(3) + REAL(ReKi) :: ULS(p%DOFL), UL0m(p%DOFL), FLt(p%DOFL) ! Temporary values in static improvement method + REAL(ReKi) :: Y1(6) + INTEGER(IntKi) :: startDOF + REAL(ReKi) :: DCM(3,3),junk(6,p%NNodes_L) + REAL(ReKi) :: HydroForces(6*p%NNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) + TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - - ! Compute the small rotation angles given the input direction cosine matrix - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + ! Compute the small rotation angles given the input direction cosine matrix + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return - ! Inputs at the transition piece: + ! Inputs at the transition piece: m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - ! Inputs on interior nodes: + ! Inputs on interior nodes: CALL ConstructUFL( u, p, m%UFL ) - - !________________________________________ - ! Set motion outputs on y%Y2mesh - !________________________________________ - - ! Y2 = C2*x + D2*u + F2 (Eq. 17) - - m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] - m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] - m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] - + !________________________________________ + ! Set motion outputs on y%Y2mesh + !________________________________________ + ! Y2 = C2*x + D2*u + F2 (Eq. 17) + m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] + m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] + m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] + IF ( p%qml > 0) THEN - m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? + m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? + p%F2_61 ! + F2(6) ] ELSE ! There are no states when p%qml=0 (i.e., no retained modes: p%Nmodes=0), so we omit those portions of the equations - m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] + m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] END IF - - !STATIC IMPROVEMENT METHOD ( modify UL ) + !STATIC IMPROVEMENT METHOD ( modify UL ) IF (p%SttcSolve) THEN FLt = MATMUL(p%PhiL_T, m%UFL + p%FGL) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? no (solution: don't call this routine thousands of time to calculate the jacobian) ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? @@ -745,19 +509,15 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = m%UL - UL0M END IF ENDIF - - ! --------------------------------------------------------------------------------- - ! Place the outputs onto interface node portion of Y2 output mesh - ! --------------------------------------------------------------------------------- - + ! --------------------------------------------------------------------------------- + ! Place the outputs onto interface node portion of Y2 output mesh + ! --------------------------------------------------------------------------------- DO I = 1, p%NNodes_I - startDOF = (I-1)*6 + 1 - - ! Construct the direction cosine matrix given the output angles + ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%UR_bar(startDOF + 3), m%UR_bar(startDOF + 4), m%UR_bar(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') y%Y2mesh%TranslationDisp (:,I) = m%UR_bar ( startDOF : startDOF + 2 ) y%Y2mesh%Orientation (:,:,I) = DCM @@ -766,28 +526,23 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%TranslationAcc (:,I) = m%UR_bar_dotdot ( startDOF : startDOF + 2 ) y%Y2mesh%RotationAcc (:,I) = m%UR_bar_dotdot ( startDOF + 3 : startDOF + 5 ) - ENDDO - - + ENDDO - ! --------------------------------------------------------------------------------- - ! Place the outputs onto interior node portion of Y2 output mesh - ! --------------------------------------------------------------------------------- - + ! --------------------------------------------------------------------------------- + ! Place the outputs onto interior node portion of Y2 output mesh + ! --------------------------------------------------------------------------------- DO I = 1, p%NNodes_L !Only interior nodes here - - ! starting index in the master arrays for the current node + ! starting index in the master arrays for the current node startDOF = (I-1)*6 + 1 - ! index into the Y2Mesh + ! index into the Y2Mesh J = p%NNodes_I + I - ! Construct the direction cosine matrix given the output angles + ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UL input angles', m%UL(startDOF + 3), m%UL(startDOF + 4), m%UL(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - - ! Y2 = Interior node displacements and velocities for use as inputs to HydroDyn + ! Y2 = Interior node displacements and velocities for use as inputs to HydroDyn y%Y2mesh%TranslationDisp (:,J) = m%UL ( startDOF : startDOF + 2 ) y%Y2mesh%Orientation (:,:,J) = DCM y%Y2mesh%TranslationVel (:,J) = m%UL_dot ( startDOF : startDOF + 2 ) @@ -796,137 +551,89 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END DO !Repeat for the acceleration, there should be a way to combine into 1 loop - L1 = p%NNodes_I+1 L2 = p%NNodes_I+p%NNodes_L junk= RESHAPE(m%UL_dotdot,(/6 ,p%NNodes_L/)) y%Y2mesh%TranslationAcc ( :,L1:L2) = junk(1:3,:) y%Y2mesh%RotationAcc ( :,L1:L2) = junk(4:6,:) - - ! --------------------------------------------------------------------------------- ! Base reaction nodes ! --------------------------------------------------------------------------------- - L1 = p%NNodes_I+p%NNodes_L+1 L2 = p%NNodes_I+p%NNodes_L+p%NReact y%Y2mesh%TranslationDisp( :,L1:L2) = 0.0 - CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ! set this orientation to the identity matrix - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return y%Y2mesh%TranslationVel ( :,L1:L2) = 0.0 y%Y2mesh%RotationVel ( :,L1:L2) = 0.0 y%Y2mesh%TranslationAcc ( :,L1:L2) = 0.0 y%Y2mesh%RotationAcc ( :,L1:L2) = 0.0 - - !________________________________________ - ! Set loads outputs on y%Y1Mesh - !________________________________________ - - + !________________________________________ + ! Set loads outputs on y%Y1Mesh + !________________________________________ ! --------------------------------------------------------------------------------- !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above ! --------------------------------------------------------------------------------- - ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] - !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES !Aggregate the forces and moments at the interface nodes to the reference point !TODO: where are these HydroTP, HydroForces documented? - DO I = 1, p%NNodes_I - startDOF = (I-1)*6 + 1 - !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5 ) = (/u%LMesh%Force(:,I),u%LMesh%Moment(:,I)/) !(6,NNODES_I) - ENDDO !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below - ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D IF ( p%qml > 0) THEN - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) - ELSE ! No retained modes, so there are no states Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) - END IF - - ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces y%Y1Mesh%Force (:,1) = Y1(1:3) y%Y1Mesh%Moment(:,1) = Y1(4:6) - - !________________________________________ - ! CALCULATE OUTPUT TO BE WRITTEN TO FILE - !________________________________________ - - - ! OutSwtch determines whether or not to actually output results via the WriteOutput array - ! 0 = No one needs the SubDyn outputs provided via the WriteOutput array. - ! 1 = SubDyn will generate an output file of its own. - ! 2 = the caller will handle the outputs, but SubDyn needs to provide them. - ! 3 = Both 1 and 2 - + !________________________________________ + ! CALCULATE OUTPUT TO BE WRITTEN TO FILE + !________________________________________ + ! OutSwtch determines whether or not to actually output results via the WriteOutput array + ! 0 = No one needs the SubDyn outputs provided via the WriteOutput array. + ! 1 = SubDyn will generate an output file of its own. + ! 2 = the caller will handle the outputs, but SubDyn needs to provide them. + ! 3 = Both 1 and 2 IF ( p%OutSwtch > 0 ) THEN - - !_________________________________________________! ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file !find xdot at t - IF ( p%NModes > 0 ) THEN ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() - CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup - RETURN - END IF - + CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear m%qmdotdot=dxdt%qmdot ! Destroy dxdt because it is not necessary for the rest of the subroutine - CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - + CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2); if(Failed()) return END IF - !_________________________________________________! - - ! Write the previous output data into the output file + ! Write the previous output data into the output file IF ( ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) .AND. ( t > m%LastOutTime ) ) THEN IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN m%Decimat=1 !reset counter - CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup - RETURN - END IF + CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat2, ErrMsg2 ); if(Failed()) return ELSE m%Decimat=m%Decimat+1 ENDIF END IF - ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations - CALL SDOut_MapOutputs(t, u,p,x,y, m, AllOuts, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup - RETURN - END IF + ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations + CALL SDOut_MapOutputs(t, u,p,x,y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return ! Put the output data in the WriteOutput array DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims @@ -935,25 +642,26 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%SDWrOutput(I) = y%WriteOutput(I) END IF END DO - m%LastOutTime = t - ENDIF CONTAINS - SUBROUTINE CleanUp + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE CleanUp CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2) - END SUBROUTINE CleanUp + END SUBROUTINE SD_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for computing derivatives of continuous states !! note that this also sets m%UFL and m%udotdot_TP SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters @@ -965,64 +673,44 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta TYPE(SD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - - - ! Initialize ErrStat - + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - ! Compute the first time derivatives of the continuous states here: - - !How is it possible that we have to check this all the time? - !bjj: because INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here - + ! INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here CALL AllocAry(dxdt%qm, p%qmL, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) CALL AllocAry(dxdt%qmdot, p%qmL, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) - IF ( ErrStat >= AbortErrLev ) RETURN + IF ( ErrStat >= AbortErrLev ) RETURN IF ( p%qmL == 0 ) RETURN -! form u(3) in Eq. 10: + ! form u(3) in Eq. 10: m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) -! form u(4) in Eq. 10: + ! form u(4) in Eq. 10: CALL ConstructUFL( u, p, m%UFL ) -!Equation 12: - - !X=A*x + B*u + Fx (Eq 12) + !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) !dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX - - END SUBROUTINE SD_CalcContStateDeriv !----------------------------------------------------------------------------------------------------------------------- SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) - USE NWTC_Library - USE SubDyn_Types - IMPLICIT NONE - CHARACTER(*), INTENT(IN) :: SDInputFile TYPE(SD_InitType) , INTENT(INOUT) :: Init TYPE(SD_ParameterType) , INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable for input and output - CHARACTER(1024) :: PriPath ! The path to the primary input file -!CHARACTER(1024) :: FTitle ! The title line from the primary input file. CHARACTER( 12) :: JunkStrg !Temp variable to store a short string -RRD CHARACTER(1024) :: Line ! String to temporarially hold value of read line INTEGER :: Sttus @@ -1030,817 +718,252 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) LOGICAL :: Echo INTEGER(IntKi) :: UnIn INTEGER(IntKi) :: IOS -INTEGER(IntKi) :: UnEc !Echo file ID +INTEGER(IntKi) :: UnEc !Echo file ID REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings -INTEGER(IntKi) :: I, J, flg, K -REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) -INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) - -UnEc = -1 -Echo = .FALSE. - -CALL GetNewUnit( UnIn ) - -CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat, ErrMsg) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Could not open SubDyn input file: '//TRIM(ErrMsg) - CALL CleanUp() - RETURN -END IF - -CALL GetPath( SDInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. - - -!-------------------------- HEADER --------------------------------------------- - ! Skip header lines -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line '//TRIM(Int2LStr(I)), ErrStat, ErrMsg )!-RRD changed to shorten it - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF -ENDDO - -!-------------------------- SIMULATION CONTROL PARAMETERS ---------------------- - - ! Skip the comment line. - - CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat, ErrMsg ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - !RRD - start modification - ! Echo - Echo input to "[InputFileName].ech". - -CALL ReadVar(UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat, ErrMsg ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - -IF ( Echo ) THEN - CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat, ErrMsg) - IF ( ErrStat /= 0 ) THEN - ErrMsg = "Could not open SubDyn echo file: "//TRIM(ErrMsg) - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - REWIND(UnIn) - !bjj: note we don't need to do error checking here; it was already checked (this is just a repeat of above) - DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line '//TRIM(Int2LStr(I)), ErrStat, ErrMsg, UnEc )!-RRD changed to shorten it - ENDDO - CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat, ErrMsg, UnEc ) - CALL ReadVar( UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat, ErrMsg, UnEc ) -ENDIF - -! Read time step ("default" means use the glue-code default) -CALL ReadVar( UnIn, SDInputFile, Line, 'SDdeltaT', 'Subdyn Time Step',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN ! error reading character string version of SDdeltaT - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - -CALL Conv2UC( Line ) ! Convert Line to upper case. -IF ( TRIM(Line) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. - p%SDdeltaT=Init%DT -ELSE ! The input must have been specified numerically. - READ (Line,*,IOSTAT=IOS) p%SDdeltaT - CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat,ErrMsg ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - - IF ( ( p%SDdeltaT <= 0 ) ) THEN - ErrMsg = ' SDdeltaT must be greater than or equal to 0.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -END IF - - - -! Read Integration Method -CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - -IF ((p%IntMethod < 1) .OR.(p%IntMethod > 4) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': IntMethod must be 1 through 4.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -CALL ReadLVar(UnIn, SDInputFile, p%SttcSolve, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - !RRD - end modification -!-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! FEMMod - FEM switch: element model in the FEM: 0= Euler-Bernoulli(E-B) ; 1=Tapered E-B; 2= 2-node Timoshenko; 3= 2-node tapered Timoshenko - -CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None .or. ( Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': FEMMod must be 0, 1, 2, or 3.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - - ! NDiv - Number sub-elements per member - -CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv, 'NDiv', 'Number of divisions per member',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None .or. ( Init%NDiv < 1 ) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NDiv must be a positive integer' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - - - ! CBMod - Perform C-B flag. -!READ( UnIn, *, IOSTAT=ErrStat ) Init%CBMod -CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod, 'CBMod', 'C-B mod flag',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - - -IF (Init%CBMod) THEN - - ! Nmodes - Number of interal modes to retain. - CALL ReadIVar ( UnIn, SDInputFile, p%Nmodes, 'Nmodes', 'Number of internal modes',ErrStat, ErrMsg, UnEc ) - - IF ( ErrStat /= ErrID_None .or. ( p%Nmodes < 0 ) ) THEN - ErrMsg = ' Nmodes must be a non-negative integer.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - - if ( p%Nmodes > 0 ) THEN - ! Damping ratios for retained modes - ALLOCATE(Init%JDampings(p%Nmodes), STAT=Sttus) - Init%JDampings=WrongNo !Initialize - - IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error allocating memory for the damping ratio array Init%JDampings in SD_Input.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - - CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%Nmodes, 'JDamping', 'Damping ratio of the internal modes', ErrStat, ErrMsg, UnEc ) - ! note that we don't check the ErrStat here; if the user entered fewer than Nmodes values, we will use the - ! last entry to fill in remaining values. - !Check 1st value, we need at least one good value from user or throw error - IF ((Init%JDampings(1) .LT. 0 ) .OR. (Init%JDampings(1) .GE. 100.0)) THEN - ErrMsg = 'Damping ratio should be larger than 0 and less than 100' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ELSE - DO I = 2, p%Nmodes - IF ( Init%JDampings(I) .EQ. WrongNo ) THEN - Init%Jdampings(I:p%Nmodes)=Init%JDampings(I-1) - IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) - ErrStat = ErrID_Info - ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%Nmodes))//'.' - END IF - EXIT - ELSEIF ( ( Init%JDampings(I) .LT. 0 ) .OR.( Init%JDampings(I) .GE. 100.0 ) ) THEN - ErrMsg = 'Damping ratio should be larger than 0 and less than 100' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - ENDDO - ENDIF - IF (ErrStat /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings - WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%Nmodes,NWTC_MaxAryLen)) - END IF - ELSE - CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat, ErrMsg, UnEc ) - END IF - -ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet - - !note at this stage I do not know DOFL yet; Nmodes will be updated later for the FULL FEM CASE. - p%Nmodes = -1 - - !Ignore next line - CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat, ErrMsg, UnEc ) - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - !Read 1 damping value for all modes - ALLOCATE( Init%JDampings(1), STAT = ErrStat ) !This will be de-reallocated later in CB - IF ( ErrStat/= ErrID_None ) THEN - ErrMsg = 'Error allocating array Init%JDampings in SD_Input for CBMOD=false' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat, ErrMsg, UnEc ) - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ELSEIF ( ( Init%JDampings(1) .LT. 0 ) .OR.( Init%JDampings(1) .GE. 100.0 ) ) THEN - ErrMsg = 'Damping ratio should be larger than 0 and less than 100.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - -ENDIF - -IF ((p%Nmodes > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%Nmodes is undefined, but if Nmodes=0 then JDampings does not exist - Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings -END IF - -!---- STRUCTURE JOINTS: joints connect structure members ----------------------------------- - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' STRUCTURE JOINTS ',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! number of joints -CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. ( Init%NJoints < 2 ) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NJoints must be greater than 1' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip two lines -JunkStrg='Headers' -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, 'Joint Coordinates '//TRIM(JunkStrg),ErrStat, ErrMsg, UnEc )!-RRD changed - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - JunkStrg='Units' -ENDDO -!CALL ReadCom( UnIn, SDInputFile, ' Joint Coordinate Headers ', ErrStat ) -! -!IF ( ErrStat /= ErrID_None ) THEN -! CLOSE( UnIn ) -! RETURN -!END IF -! -!CALL ReadCom( UnIn, SDInputFile, ' units ', ErrStat ) -! -!IF ( ErrStat /= ErrID_None ) THEN -! CLOSE( UnIn ) -! RETURN -!END IF - - ! Joints coordinates -ALLOCATE(Init%Joints(Init%NJoints, JointsCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating Joints arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - -DO I = 1, Init%NJoints - -! CALL ReadAry( UnIn, SDInputFile, Init%Joints(I,:), JointsCol, 'Joints', 'Joint number and coordinates', ErrStat, ErrMsg, UnEc ) - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, JointsCol, 'Joints', 'Joint number and coordinates', ErrStat, ErrMsg, UnEc ) - Init%Joints(I,:) = Dummy_ReAry(1:JointsCol) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO - -!---------- GO AHEAD and ROTATE STRUCTURE UF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- - -CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) - -!------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' BASE REACTION JOINTS ',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! Number of reaction joints (The joints should be all clamped for now) -CALL ReadIVar ( UnIn, SDInputFile, p%NReact, 'NReact', 'Number of joints with reaction forces',ErrStat, ErrMsg, UnEc ) -IF ( ErrSTat /= ErrID_None .OR. ( p%NReact < 1 ) .OR. (p%NReact > Init%NJoints) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NReact must be greater than 0 and less than number of joints' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip the comment lines. -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' BASE REACTION JOINTS HEADERS ',ErrStat, ErrMsg, UnEc ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF -END DO - - - ! Joints with reaction forces, joint number and locked/free dof -ALLOCATE(p%Reacts(p%NReact, ReactCol), STAT=Sttus) !-RRD, at one point we will need to move this real array to a long(NReact) and a Logical(Nreact,6) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating Reacts arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -DO I = 1, p%NReact - -! CALL ReadIAry( UnIn, SDInputFile, p%Reacts(I,:), ReactCol, 'Reacts', 'Joint number and dof', ErrStat ,ErrMsg, UnEc) - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat ,ErrMsg, UnEc) - p%Reacts(I,:) = Dummy_IntAry(1:ReactCol) - - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO - - -!------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' INTERFACE JOINTS ',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! Number of interface joints (The joints should be all clamped for now) -CALL ReadIVar ( UnIn, SDInputFile, Init%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. ( Init%NInterf < 0 ).OR. (Init%NInterf > Init%NJoints) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NInterf must be non-negative and less than number of joints.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip the comment line. -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' INTERFACE JOINTS HEADERS ',ErrStat, ErrMsg, UnEc ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF -END DO - - - ! Joints with reaction forces, joint number and locked/free dof -ALLOCATE(Init%Interf(Init%NInterf, InterfCol), STAT=Sttus) !-RRD, at one point we will need to move this real array to a long(NInterf) and a Logical(NInterf,6) - -IF ( Sttus /= 0 ) THEN - !ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating Interf arrays' - ErrMsg='Error allocating array Interf' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -DO I = 1, Init%NInterf - -! CALL ReadIAry( UnIn, SDInputFile, Init%Interf(I,:), InterfCol, 'Interf', 'Interface joint number and dof', ErrStat,ErrMsg, UnEc) - CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat,ErrMsg, UnEc) - Init%Interf(I,:) = Dummy_IntAry(1:InterfCol) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO - -!----------------------------------- MEMBERS -------------------------------------- - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' Members ',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! number of members -CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. p%NMembers < 1 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NMembers must be > 0' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip two lines -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Members Headers ',ErrStat, ErrMsg, UnEc ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF -END DO - - - ! Member connection -RRD one day we will need to take care of COSMIDs for non-circular members -ALLOCATE(Init%Members(p%NMembers, MembersCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating Members arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -DO I = 1, p%NMembers - -! CALL ReadIAry( UnIn, SDInputFile, Init%Members(I,:), MembersCol, 'Members', 'Member number and connectivity ', ErrStat,ErrMsg, UnEc ) - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, MembersCol, 'Members', 'Member number and connectivity ', ErrStat,ErrMsg, UnEc ) - Init%Members(I,:) = Dummy_IntAry(1:MembersCol) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO - -!------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! number of property sets -CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSets, 'NPropSets', 'Number of property sets',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. Init%NPropSets < 1 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NPropSets must be >0' !-RRD changed text - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip two lines -JunkStrg='Headers' -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Property Data 1/2 '//TRIM(JunkStrg),ErrStat, ErrMsg, UnEc )!-RRD changed text - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - JunkStrg='Units' -ENDDO - - - ! Property sets value -ALLOCATE(Init%PropSets(Init%NPropSets, PropSetsCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating PropSets arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -DO I = 1, Init%NPropSets - -! CALL ReadAry( UnIn, SDInputFile, Init%PropSets(I,:), PropSetsCol, 'PropSets', 'PropSets number and values ', ErrStat , ErrMsg, UnEc) - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsCol, 'PropSets', 'PropSets number and values ', ErrStat , ErrMsg, UnEc) - Init%PropSets(I,:) = Dummy_ReAry(1:PropSetsCol) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO - -!------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ - - - ! Skip the comment line. - -CALL ReadCom( UnIn, SDInputFile, ' Member X-Section Property Data 2/2 ',ErrStat, ErrMsg, UnEc )!-RRD changed description - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - ! number of property sets -CALL ReadIVar ( UnIn, SDInputFile, Init%NXPropSets, 'NXPropSets', 'Number of non-circular property sets',ErrStat, ErrMsg, UnEc ) !-RRD changed text -IF ( ErrStat /= ErrID_None .OR. Init%NXPropSets < 0 ) THEN !-RRD changed NPropSets to NXPropsets - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NXPropSets must be >=0' !-RRD changed text - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip two lines -JunkStrg='Headers' -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Property Data 2/2 '//TRIM(JunkStrg),ErrStat, ErrMsg, UnEc ) - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - JunkStrg='Units' -ENDDO - - - ! Property sets value -ALLOCATE(Init%XPropSets(Init%NXPropSets, XPropSetsCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating XPropSets arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - -DO I = 1, Init%NXPropSets - - CALL ReadAry( UnIn, SDInputFile, Init%XPropSets(I,:), XPropSetsCol, 'XPropSets', 'XPropSets ID and values ', ErrStat, ErrMsg, UnEc ) +INTEGER(IntKi) :: I, J, flg, K +REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) +INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) +INTEGER(IntKi) :: ErrStat2 +CHARACTER(ErrMsgLen) :: ErrMsg2 +! Initialize ErrStat +ErrStat = ErrID_None +ErrMsg = "" - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - -ENDDO +UnEc = -1 +Echo = .FALSE. -!---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ +CALL GetNewUnit( UnIn ) + +CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) - ! Skip the comment line. +IF ( ErrStat2 /= ErrID_None ) THEN + Call Abort('Could not open SubDyn input file') + return +END IF -CALL ReadCom( UnIn, SDInputFile, ' Member direction cosine matrices ',ErrStat, ErrMsg, UnEc ) +CALL GetPath( SDInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - ! number of direction cosine matrices -CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. Init%NCOSMs < 0 ) THEN !-RRD changed Propsets to NCONMs and some text in the next line - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': NCOSMs must be >=0' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF +!-------------------------- HEADER --------------------------------------------- +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ); if(Failed()) return - ! Skip two lines -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Cosine Matrices Headers',ErrStat, ErrMsg, UnEc ) +!-------------------------- SIMULATION CONTROL PARAMETERS ---------------------- +CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadVar(UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2); if(Failed()) return - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN +IF ( Echo ) THEN + CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat2, ErrMsg2) + IF ( ErrStat2 /= 0 ) THEN + CALL Abort("Could not open SubDyn echo file") + return END IF -END DO + REWIND(UnIn) + !bjj: note we don't need to do error checking here; it was already checked (this is just a repeat of above) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SIMULATION CONTROL PARAMETERS' , ErrStat2, ErrMsg2, UnEc ) + CALL ReadVar( UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2, UnEc ) +ENDIF +! Read time step ("default" means use the glue-code default) +CALL ReadVar( UnIn, SDInputFile, Line, 'SDdeltaT', 'Subdyn Time Step',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - ! Direction cosine matrices value -ALLOCATE(Init%COSMs(Init%NCOSMs, COSMsCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating COSMs arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF +CALL Conv2UC( Line ) ! Convert Line to upper case. +IF ( TRIM(Line) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. + p%SDdeltaT=Init%DT +ELSE ! The input must have been specified numerically. + READ (Line,*,IOSTAT=IOS) p%SDdeltaT + CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat2,ErrMsg2 ); if(Failed()) return + IF ( ( p%SDdeltaT <= 0 ) ) THEN + call Abort('SDdeltaT must be greater than or equal to 0.') + return + END IF +END IF + +CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, p%SttcSolve, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +!-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- +CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko +CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv , 'NDiv' , 'Number of divisions per member',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod , 'CBMod' , 'C-B mod flag' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -DO I = 1, Init%NCOSMs +IF (Check( (p%IntMethod < 1) .OR.(p%IntMethod > 4) , 'IntMethod must be 1 through 4.')) return +IF (Check( (Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) , 'FEMMod must be 0, 1, 2, or 3.')) return +IF (Check( Init%NDiv < 1 , 'NDiv must be a positive integer')) return - CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat, ErrMsg, UnEc )!-RRD changed text +IF (Init%CBMod) THEN + ! Nmodes - Number of interal modes to retain. + CALL ReadIVar ( UnIn, SDInputFile, p%Nmodes, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF + IF (Check( p%Nmodes < 0 , 'Nmodes must be a non-negative integer.')) return + if ( p%Nmodes > 0 ) THEN + ! Damping ratios for retained modes + CALL AllocAry(Init%JDampings, p%Nmodes, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + Init%JDampings=WrongNo !Initialize -ENDDO - -!------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- - - ! Skip the comment line. + CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%Nmodes, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); + ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the + ! last entry to fill in remaining values. + !Check 1st value, we need at least one good value from user or throw error + IF ((Init%JDampings(1) .LT. 0 ) .OR. (Init%JDampings(1) .GE. 100.0)) THEN + CALL Abort('Damping ratio should be larger than 0 and less than 100') + return + ELSE + DO I = 2, p%Nmodes + IF ( Init%JDampings(I) .EQ. WrongNo ) THEN + Init%Jdampings(I:p%Nmodes)=Init%JDampings(I-1) + IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) + ErrStat = ErrID_Info + ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%Nmodes))//'.' + END IF + EXIT + ELSEIF ( ( Init%JDampings(I) .LT. 0 ) .OR.( Init%JDampings(I) .GE. 100.0 ) ) THEN + CALL Abort('Damping ratio should be larger than 0 and less than 100') + return + ENDIF + ENDDO + ENDIF + IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings + WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%Nmodes,NWTC_MaxAryLen)) + END IF + ELSE + CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + END IF -CALL ReadCom( UnIn, SDInputFile, ' Additional concentrated masses at joints ',ErrStat, ErrMsg, UnEc ) +ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet + !note at this stage I do not know DOFL yet; Nmodes will be updated later for the FULL FEM CASE. + p%Nmodes = -1 + !Ignore next line + CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + !Read 1 damping value for all modes + CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + IF ( ( Init%JDampings(1) .LT. 0 ) .OR.( Init%JDampings(1) .GE. 100.0 ) ) THEN + CALL Abort('Damping ratio should be larger than 0 and less than 100.') + RETURN + ENDIF +ENDIF -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN +IF ((p%Nmodes > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%Nmodes is undefined, but if Nmodes=0 then JDampings does not exist + Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings END IF - ! number of joints that have concentrated masses -CALL ReadIVar ( UnIn, SDInputFile, Init%NCMass, 'NCMass', 'Number of joints that have concentrated masses',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. Init%NCMass < 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//'": NCMass must be >=0' !-RRD changed text - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - - ! Skip two lines -JunkStrg='Headers' -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Concentrated Mass '//TRIM(JunkStrg),ErrStat, ErrMsg, UnEc )!-RRD changed text - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - JunkStrg='Units' +!--------------------- STRUCTURE JOINTS: joints connect structure members ------------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Joints, Init%NJoints, JointsCol, 'Joints', ErrStat2, ErrMsg2 ); if(Failed()) return +DO I = 1, Init%NJoints + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, JointsCol, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + Init%Joints(I,:) = Dummy_ReAry(1:JointsCol) ENDDO -!CALL ReadCom( UnIn, SDInputFile, ' Concentrated Mass'//JunkStrg//, ErrStat )!-RRD changed text -!IF ( ErrStat /= ErrID_None ) THEN -! ErrStat = ErrID_Fatal -! CALL CleanUp() -! RETURN -!END IF - - ! Concentrated mass value -ALLOCATE(Init%CMass(Init%NCMass, CMassCol), STAT=Sttus) - -IF ( Sttus /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating CMass arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF -Init%CMass = 0.0 +IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return -DO I = 1, Init%NCMass +!---------- GO AHEAD and ROTATE STRUCTURE IF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- +CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) - CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat, ErrMsg, UnEc ) +!------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- +! The joints should be all clamped for now +CALL ReadCom ( UnIn, SDInputFile, 'BASE REACTION JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NReact, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(p%Reacts, p%NReact, ReactCol, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +DO I = 1, p%NReact + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return + p%Reacts(I,:) = Dummy_IntAry(1:ReactCol) +ENDDO +IF (Check ( ( p%NReact < 1 ) .OR. (p%NReact > Init%NJoints) , 'NReact must be greater than 0 and less than number of joints')) return - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - +!------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- +! Joints with reaction forces, joint number and locked/free dof +CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Interf, Init%NInterf, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NInterf + CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Interf(I,:) = Dummy_IntAry(1:InterfCol) +ENDDO +IF (Check( ( Init%NInterf < 0 ) .OR. (Init%NInterf > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN + +!----------------------------------- MEMBERS -------------------------------------- +! One day we will need to take care of COSMIDs for non-circular members +CALL ReadCom ( UnIn, SDInputFile, 'Members ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) +DO I = 1, p%NMembers + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, MembersCol, 'Members', 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Members(I,:) = Dummy_IntAry(1:MembersCol) ENDDO +IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return +!------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ +CALL ReadCom ( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSets, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSets, Init%NPropSets, PropSetsCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSets + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSets(I,:) = Dummy_ReAry(1:PropSetsCol) +ENDDO +IF (Check( Init%NPropSets < 1 , 'NPropSets must be >0')) return -!---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ - ! Skip the comment line. -CALL ReadCom( UnIn, SDInputFile, 'OUTPUT',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF +!------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member X-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NXPropSets, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%XPropSets, Init%NXPropSets, XPropSetsCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NXPropSets + CALL ReadAry( UnIn, SDInputFile, Init%XPropSets(I,:), XPropSetsCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NXPropSets < 0, 'NXPropSets must be >=0')) return -CALL ReadLVar(UnIn, SDInputFile, Init%SSSum, 'SSSum', 'Summary File Logic Variable',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF -!IF ( InitOut%SSSum ) p%JEchoFile = TRIM(Init%RootName)//'.sum' +!---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member direction cosine matrices ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%COSMs, Init%NCOSMs, COSMsCol, 'COSMs', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NCOSMs + CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NCOSMs < 0 ,'NCOSMs must be >=0')) return -!bjj: TODO: OutCOSM isn't used anywhere else. -CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF +!------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'Additional concentrated masses at joints ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NCMass, 'NCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%CMass, Init%NCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return +Init%CMass = 0.0 +DO I = 1, Init%NCMass + CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NCMass < 0 , 'NCMass must be >=0')) return -CALL ReadLVar(UnIn, SDInputFile, p%OutAll, 'OutAll', 'Output all Member Forces Logic Variable',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF +!---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ +CALL ReadCom (UnIn, SDInputFile, 'OUTPUT' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. +CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !Store an integer version of it p%OutAllInt= 1 IF ( .NOT. p%OutAll ) p%OutAllInt= 0 - -CALL ReadIVar(UnIn, SDInputFile, p%OutSwtch, 'OutSwtch', 'Output to which file variable',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None .OR. ( p%OutSwtch < 1 ) .OR. ( p%OutSwtch > 3) ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF +CALL ReadIVar(UnIn, SDInputFile, p%OutSwtch, 'OutSwtch', 'Output to which file variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +IF (Check( ( p%OutSwtch < 1 ) .OR. ( p%OutSwtch > 3) ,'OutSwtch must be >0 and <4')) return Swtch: SELECT CASE (p%OutSwtch) CASE (1, 3) Swtch @@ -1848,214 +971,113 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CASE (2) Swtch !pass to glue code CASE DEFAULT Swtch - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN + CALL Abort(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') + return END SELECT Swtch - ! TabDelim - Output format for tabular data. - -CALL ReadLVar ( UnIn, SDInputFile, Init%TabDelim, 'TabDelim', 'Use Tab Delimitation for numerical outputs',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF +CALL ReadLVar ( UnIn, SDInputFile, Init%TabDelim, 'TabDelim', 'Use Tab Delimitation for numerical outputs',ErrStat2, ErrMsg2, UnEc); if(Failed()) return IF ( Init%TabDelim ) THEN p%Delim = TAB ELSE p%Delim = ' ' END IF -! OutDec - Output decimation for tabular data. -CALL ReadIVar ( UnIn, SDInputFile, p%OutDec, 'OutDec', 'Output Decimation',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - -! OutFmt - Output format for tabular data. -CALL ReadVar ( UnIn, SDInputFile, p%OutFmt, 'OutFmt', 'Format for numerical outputs',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - -! OutSFmt - Format for output column headers -CALL ReadVar ( UnIn, SDInputFile, p%OutSFmt, 'OutSFmt', 'Format for output column headers',ErrStat, ErrMsg, UnEc ) - -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - - - ! Skip the comment line. -CALL ReadCom( UnIn, SDInputFile, ' Member Output List SECTION ',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF - -CALL ReadIVar ( UnIn, SDInputFile, p%NMOutputs, 'NMOutputs', 'Number of Members whose output must go into OutJckF and/or FAST .out',ErrStat, ErrMsg, UnEc ) -IF ( ( p%NMOutputs < 0 ) .OR. ( p%NMOutputs > p%NMembers ) .OR. ( p%NMOutputs > 9 )) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//'": NMOutputs must be >=0 and <= minimim(NMembers,9)' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -ENDIF - -! Skip two lines -JunkStrg='Headers' -DO I = 1, 2 - CALL ReadCom( UnIn, SDInputFile, ' Output Member '//TRIM(JunkStrg),ErrStat, ErrMsg, UnEc )!-RRD changed text - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() +CALL ReadIVar( UnIn, SDInputFile, p%OutDec , 'OutDec' , 'Output Decimation' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutFmt , 'OutFmt' , 'Format for numerical outputs' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutSFmt , 'OutSFmt' , 'Format for output column headers' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, ' Member Output List SECTION ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar( UnIn, SDInputFile, p%NMOutputs, 'NMOutputs', 'Number of Members whose output must go into OutJckF and/or FAST .out',ErrStat2, ErrMsg2, UnEc ) +if (Failed()) return +IF (Check ( (p%NMOutputs < 0) .OR. (p%NMOutputs > p%NMembers) .OR. (p%NMOutputs > 9), 'NMOutputs must be >=0 and <= minimim(NMembers,9)')) return + +CALL ReadCom( UnIn, SDInputFile, ' Output Member Headers',ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, ' Output Member Units' ,ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return + +IF ( p%NMOutputs > 0 ) THEN + ! Allocate memory for filled group arrays + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat2 ) !this list contains different arrays for each of its elements + IF ( ErrStat2 /= ErrID_None ) THEN + CALL Abort(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') RETURN - END IF - JunkStrg='Units' -ENDDO - - IF ( p%NMOutputs > 0 ) THEN - ! Allocate memory for filled group arrays - ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat ) !this list contains different arrays for each of its elements - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays' - ! CALL CleanupEchoFile( InitInp%Echo, EchoStore, UnEchoStore ) !STILL TO DO THE ECHO PROPERLY - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - DO I = 1,p%NMOutputs - - READ(UnIn,'(A)',IOSTAT=ErrStat) Line !read into a line + END IF - IF (ErrStat == 0) THEN - - READ(Line,*,IOSTAT=ErrStat) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt - - - IF ( ErrStat /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - - ALLOCATE ( p%MOutLst(I)%NodeCnt( p%MOutLst(I)%NOutCnt ), STAT = ErrStat ) - - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating NodeCnt arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - READ(Line,*,IOSTAT=ErrStat) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt, & - p%MOutLst(I)%NodeCnt - - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error Failed to read member output list properties.' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - - END IF - - ! Check if MemberID is in the member list and the NodeCnt is a valid number - flg = 0 - DO J = 1, p%NMembers - IF(p%MOutLst(I)%MemberID .EQ. Init%Members(j, 1)) THEN - flg = flg + 1 ! flg could be greater than 1, when there are more than 9 internal nodes of a member. - IF( (p%MOutLst(I)%NOutCnt .LT. 10) .and. ((p%MOutLst(I)%NOutCnt .GT. 0)) ) THEN - DO K = 1,p%MOutLst(I)%NOutCnt - ! node number should be less than NDiv + 1 - IF( (p%MOutLst(I)%NodeCnt(k) .GT. (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) .LT. 1) ) THEN - ErrMsg = ' NodeCnt should be less than NDIV+1 and greater than 0. ' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - ENDDO - ELSE - ErrMsg = ' NOutCnt should be less than 10 and greater than 0. ' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - - ENDIF + DO I = 1,p%NMOutputs + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt + IF ( ErrStat2 /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN + CALL Abort(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') + RETURN + END IF + CALL AllocAry( p%MOutLst(I)%NodeCnt, p%MOutLst(I)%NOutCnt, 'NodeCnt', ErrStat2, ErrMsg2); if(Failed()) return + + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt, p%MOutLst(I)%NodeCnt + IF ( Check( ErrStat2 /= 0 , 'Failed to read member output list properties.')) return + + ! Check if MemberID is in the member list and the NodeCnt is a valid number + flg = 0 + DO J = 1, p%NMembers + IF(p%MOutLst(I)%MemberID .EQ. Init%Members(j, 1)) THEN + flg = flg + 1 ! flg could be greater than 1, when there are more than 9 internal nodes of a member. + IF( (p%MOutLst(I)%NOutCnt .LT. 10) .and. ((p%MOutLst(I)%NOutCnt .GT. 0)) ) THEN + DO K = 1,p%MOutLst(I)%NOutCnt + ! node number should be less than NDiv + 1 + IF( (p%MOutLst(I)%NodeCnt(k) .GT. (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) .LT. 1) ) THEN + CALL Abort(' NodeCnt should be less than NDIV+1 and greater than 0. ') + RETURN + ENDIF + ENDDO + ELSE + CALL Abort(' NOutCnt should be less than 10 and greater than 0. ') + RETURN ENDIF - - ENDDO - - IF (flg .EQ. 0) THEN - ErrMsg = ' MemberID is not in the Members list. ' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - ENDIF - - IF ( Echo ) THEN - WRITE( UnEc, '(A)' ) TRIM(Line) - END IF - - END IF - - END DO - - END IF + ENDDO + IF (Check (flg .EQ. 0 , ' MemberID is not in the Members list. ')) return + IF ( Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + END IF + END DO +END IF +! OutList - list of requested parameters to output to a file +CALL ReadCom( UnIn, SDInputFile, 'SSOutList',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - - ! OutList - list of requested parameters to output to a file -! Skip the comment line. -CALL ReadCom( UnIn, SDInputFile, 'SSOutList',ErrStat, ErrMsg, UnEc ) -IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF +ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat2) +If (Check( ErrStat2 /= ErrID_None ,'Error allocating SSOutList arrays')) return -ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat) -IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error in file "'//TRIM(SDInputFile)//': Error allocating SSOutList arrays' - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN -END IF CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, & - 'SSOutList', 'List of outputs requested', ErrStat, ErrMsg, UnEc ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - CALL CleanUp() - RETURN - END IF - - !------------------------------------------------------------------------------------------------- - ! This is the end of the input file - !------------------------------------------------------------------------------------------------- - + 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ) +if(Failed()) return CALL CleanUp() CONTAINS + + LOGICAL FUNCTION Check(Condition, ErrMsg_in) + logical, intent(in) :: Condition + character(len=*), intent(in) :: ErrMsg_in + Check=Condition + if (Check) call Abort(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) + END FUNCTION Check + + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Input') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE Abort(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Init'); + CALL CleanUp() + END SUBROUTINE Abort + SUBROUTINE CleanUp() - CLOSE( UnIn ) IF (Echo) CLOSE( UnEc ) - END SUBROUTINE END SUBROUTINE SD_Input @@ -4210,12 +3232,11 @@ integer(IntKi) function FindNode(iMember,iNode) result(j) end function END FUNCTION MemberLength -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!------------------------------------------------------------------------------------------------------ +!> Calculate member mass, given properties at the ends, keep units consistent +!! For now it works only for circular pipes or for a linearly varying area FUNCTION MemberMass(rho1,D1,t1,rho2,D2,t2,L,ctube) - !This sub takes care of calculating member mass, given properties at the ends, keep units consistent - !For now it works only for circular pipes or for a linearly varying area REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member ! IF ctube=.FALSE. then D1/2=Area at end1/2, t1 and t2 are ignored REAL(ReKi) :: MemberMass !mass @@ -4244,23 +3265,15 @@ FUNCTION MemberMass(rho1,D1,t1,rho2,D2,t2,L,ctube) END FUNCTION MemberMass - -!------------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------------ +!> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR SUBROUTINE SymMatDebug(M,MAT) - !This sub checks whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR - - INTEGER(IntKi), INTENT(IN) :: M ! Number of rows and columns REAL(ReKi),INTENT(IN) :: MAT(M ,M) !matrix to be checked - !LOCALS REAL(ReKi) :: Error,MaxErr !element by element relative difference in (Transpose(MAT)-MAT)/MAT INTEGER(IntKi) :: i, j, imax,jmax !counter and temporary holders - - - !Errors= (TRANSPOSE(MAT)-MAT)/MAT - + MaxErr=0. imax=0 jmax=0 @@ -4277,14 +3290,12 @@ SUBROUTINE SymMatDebug(M,MAT) ENDIF ENDDO ENDDO - + !-------------------------------------- ! write discretized data to a txt file WRITE(*, '(A,e15.6)') 'Matrix SYmmetry Check: Largest (abs) relative error is:', MaxErr WRITE(*, '(A,I4,I4)') 'Matrix SYmmetry Check: (I,J)=', imax,jmax END SUBROUTINE SymMatDebug -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ End Module SubDyn From 8c496013715d436616ef939f6a1487120503daf4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 23 Oct 2019 21:50:52 -0600 Subject: [PATCH 023/377] FlexSub: additional clean up of main --- modules/subdyn/src/SubDyn.f90 | 453 +++++++++++----------------------- 1 file changed, 139 insertions(+), 314 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 9a2dbabc9..06d072cc2 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -711,7 +711,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable for input and output CHARACTER(1024) :: PriPath ! The path to the primary input file -CHARACTER( 12) :: JunkStrg !Temp variable to store a short string -RRD CHARACTER(1024) :: Line ! String to temporarially hold value of read line INTEGER :: Sttus @@ -1084,31 +1083,25 @@ END SUBROUTINE SD_Input !---------------------------------------------------------------------------------------------------------------------------------- +!> Rotate the joint coordinates with respect to global z SUBROUTINE SubRotate(Joints,NJoints,SubRotZ) -!This subroutine rotates the joint coordinates with respect to global z REAL(ReKi), INTENT(IN) :: SubRotZ ! Rotational angle in degrees INTEGER(IntKi), INTENT(IN) :: NJOINTS ! Row size of Joints REAL(ReKi), DIMENSION(NJOINTS,3), INTENT(INOUT) :: JOINTS ! Rotational angle in degrees (Njoints,4) - !locals REAL(ReKi) :: rot !angle in rad REAL(ReKi), DIMENSION(2,2) :: ROTM !rotational matrix (cos matrix with -theta) - rot=pi*SubRotz/180. ROTM=transpose(reshape([ COS(rot), -SIN(rot) , & SIN(rot) , COS(rot)], [2,2] )) Joints(:,2:3)= transpose(matmul(ROTM,transpose(Joints(:,2:3)))) END SUBROUTINE SubRotate - -!---------------------------------------------------------------------------------------------------------------------------------- !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the end of the simulation. SUBROUTINE SD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - TYPE(SD_InputType), INTENT(INOUT) :: u !< System inputs TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameters TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states @@ -1119,62 +1112,30 @@ SUBROUTINE SD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - - ! Initialize ErrStat - + ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - - - ! Place any last minute operations or calculations here: - - ! Close files here: - - - - ! Destroy the input data: - - CALL SD_DestroyInput( u, ErrStat, ErrMsg ) - - - ! Determine if we need to close the output file - + ! Determine if we need to close the output file IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN ! Write out the last stored set of outputs before closing CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat, ErrMsg ) ENDIF - CALL SDOut_CloseOutput( p, ErrStat, ErrMsg ) END IF - - ! Destroy the parameter data: - + ! Destroy data + CALL SD_DestroyInput( u, ErrStat, ErrMsg ) CALL SD_DestroyParam( p, ErrStat, ErrMsg ) - - - ! Destroy the state data: - CALL SD_DestroyContState( x, ErrStat, ErrMsg ) CALL SD_DestroyDiscState( xd, ErrStat, ErrMsg ) CALL SD_DestroyConstrState( z, ErrStat, ErrMsg ) CALL SD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) - CALL SD_DestroyMisc( m, ErrStat, ErrMsg ) - - ! Destroy the output data: - CALL SD_DestroyOutput( y, ErrStat, ErrMsg ) - - - END SUBROUTINE SD_End -!------------------------------------------------------------------------------------------------------ !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential @@ -1185,14 +1146,9 @@ END SUBROUTINE SD_End !! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) !! !! See, e.g., -!! http://en.wikipedia.org/wiki/Linear_multistep_method -!! -!! or -!! -!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< time step number TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t @@ -1205,14 +1161,9 @@ SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - ! local variables TYPE(SD_ContinuousStateType) :: xdot ! Continuous state derivs at t TYPE(SD_InputType) :: u_interp - - - ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -1224,18 +1175,12 @@ SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! we don't need this local copy anymore if (n .le. 2) then - OtherState%n = n - !OtherState%xdot ( 3 - n ) = xdot CALL SD_CopyContState( xdot, OtherState%xdot ( 3 - n ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - CALL SD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - else - if (OtherState%n .lt. n) then - OtherState%n = n CALL SD_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) CALL SD_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) @@ -1243,31 +1188,22 @@ SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg !OtherState%xdot(4) = OtherState%xdot(3) !OtherState%xdot(3) = OtherState%xdot(2) !OtherState%xdot(2) = OtherState%xdot(1) - elseif (OtherState%n .gt. n) then - ErrStat = ErrID_Fatal ErrMsg = ' Backing up in time is not supported with a multistep method ' RETURN - endif - CALL SD_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date - x%qm = x%qm + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qm - 59.*OtherState%xdot(2)%qm + 37.*OtherState%xdot(3)%qm & - 9. * OtherState%xdot(4)%qm ) - x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qmdot - 59.*OtherState%xdot(2)%qmdot & + 37.*OtherState%xdot(3)%qmdot - 9.*OtherState%xdot(4)%qmdot ) - endif - - CALL SD_DestroyContState(xdot, ErrStat, ErrMsg) CALL SD_DestroyInput(u_interp, ErrStat, ErrMsg) - END SUBROUTINE SD_AB4 + !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary !! differential equations: @@ -1281,14 +1217,9 @@ END SUBROUTINE SD_AB4 !! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) !! !! See, e.g., -!! http://en.wikipedia.org/wiki/Linear_multistep_method -!! -!! or -!! -!! K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< time step number TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t @@ -1301,24 +1232,18 @@ SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_InputType) :: u_interp ! Continuous states at t TYPE(SD_ContinuousStateType) :: x_pred ! Continuous states at t TYPE(SD_ContinuousStateType) :: xdot_pred ! Continuous states at t - ! Initialize ErrStat - ErrStat = ErrID_None ErrMsg = "" CALL SD_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) !initialize x_pred - CALL SD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) if (n .gt. 2) then - CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) @@ -1330,14 +1255,10 @@ SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qmdot + 19. * OtherState%xdot(1)%qmdot - 5. * OtherState%xdot(2)%qmdot & + 1. * OtherState%xdot(3)%qmdot ) - CALL SD_DestroyContState( xdot_pred, ErrStat, ErrMsg) ! local copy no longer needed - else - x%qm = x_pred%qm x%qmdot = x_pred%qmdot - endif CALL SD_DestroyContState( x_pred, ErrStat, ErrMsg) ! local copy no longer needed @@ -1361,8 +1282,6 @@ END SUBROUTINE SD_ABM4 !! Runge-Kutta." sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: !! Cambridge University Press, pp. 704-716, 1992. SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< time step number TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t @@ -1375,9 +1294,7 @@ SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_ContinuousStateType) :: xdot ! time derivatives of continuous states TYPE(SD_ContinuousStateType) :: k1 ! RK4 constant; see above TYPE(SD_ContinuousStateType) :: k2 ! RK4 constant; see above @@ -1385,9 +1302,7 @@ SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_ContinuousStateType) :: k4 ! RK4 constant; see above TYPE(SD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x TYPE(SD_InputType) :: u_interp ! interpolated value of inputs - ! Initialize ErrStat - ErrStat = ErrID_None ErrMsg = "" @@ -1405,69 +1320,51 @@ SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! find xdot at t CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) !initializes xdot - - k1%qm = p%SDDeltaT * xdot%qm - k1%qmdot = p%SDDeltaT * xdot%qmdot - + k1%qm = p%SDDeltaT * xdot%qm + k1%qmdot = p%SDDeltaT * xdot%qmdot x_tmp%qm = x%qm + 0.5 * k1%qm x_tmp%qmdot = x%qmdot + 0.5 * k1%qmdot - ! interpolate u to find u_interp = u(t + dt/2) CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%SDDeltaT, ErrStat, ErrMsg) ! find xdot at t + dt/2 CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - k2%qm = p%SDDeltaT * xdot%qm k2%qmdot = p%SDDeltaT * xdot%qmdot - x_tmp%qm = x%qm + 0.5 * k2%qm x_tmp%qmdot = x%qmdot + 0.5 * k2%qmdot ! find xdot at t + dt/2 CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - - k3%qm = p%SDDeltaT * xdot%qm - k3%qmdot = p%SDDeltaT * xdot%qmdot - + k3%qm = p%SDDeltaT * xdot%qm + k3%qmdot = p%SDDeltaT * xdot%qmdot x_tmp%qm = x%qm + k3%qm x_tmp%qmdot = x%qmdot + k3%qmdot - ! interpolate u to find u_interp = u(t + dt) CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) ! find xdot at t + dt CALL SD_CalcContStateDeriv( t + p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - k4%qm = p%SDDeltaT * xdot%qm k4%qmdot = p%SDDeltaT * xdot%qmdot + x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. + x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. - x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. - x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. - - CALL ExitThisRoutine() + CALL CleanUp() -CONTAINS - !............................................................................................................................... - SUBROUTINE ExitThisRoutine() - ! This subroutine destroys all the local variables - !............................................................................................................................... +CONTAINS - ! local variables + SUBROUTINE CleanUp() INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) - - CALL SD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k1, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k2, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k3, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k4, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) - CALL SD_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) - - END SUBROUTINE ExitThisRoutine + END SUBROUTINE CleanUp END SUBROUTINE SD_RK4 @@ -1488,8 +1385,6 @@ END SUBROUTINE SD_RK4 !! Thus x_n+1 = x_n - J^-1 *dt/2 * (2*A*x_n + B *(u_n + u_n+1) +2*Fx) !! or J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) -!.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< time step number TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t @@ -1502,115 +1397,92 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_InputType) :: u_interp ! interpolated value of inputs -! REAL(ReKi) :: junk1(p%qml) !temporary states (qm or qmdot only) (2*A*x_n + B *(u_n + u_n+1) +2*Fx) REAL(ReKi) :: junk2(2*p%qml) !temporary states (qm and qmdot only) - REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP REAL(ReKi) :: UFL2(p%DOFL) ! temporary copy of UFL - - ! Initialize ErrStat - INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = "" - ! Initialize interim vars - CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2,ErrMsg2);CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - - - !Start by getting u_n and u_n+1 - ! interpolate u to find u_interp = u(t) = u_n - CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, m%UFL ) - - ! extrapolate u to find u_interp = u(t + dt)=u_n+1 - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, UFL2 ) - - ! calculate (u_n + u_n+1)/2 - udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) - UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) - - ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - junk2( 1: p%qml)=p%SDDeltaT * x%qmdot !upper portion of array - !junk2(1+p%qml:2*p%qml)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(p%PhiM_T,UFL2) + p%FX) !lower portion of array - junk2(1+p%qml:2*p%qml)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array - ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D - - !.................................................... - ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) - ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - !.................................................... - CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - !IF ( ErrStat >= AbortErrLev ) RETURN - !.................................................... + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2,ErrMsg2);CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: - - x%qm = x%qm - junk2( 1: p%qml) - x%qmdot = x%qmdot - junk2(p%qml+1:2*p%qml) - - - ! clean up temporary variable(s) - CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) + !Start by getting u_n and u_n+1 + ! interpolate u to find u_interp = u(t) = u_n + CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL ConstructUFL( u_interp, p, m%UFL ) + + ! extrapolate u to find u_interp = u(t + dt)=u_n+1 + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL ConstructUFL( u_interp, p, UFL2 ) + + ! calculate (u_n + u_n+1)/2 + udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) + UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) + + ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + junk2( 1: p%qml)=p%SDDeltaT * x%qmdot !upper portion of array + junk2(1+p%qml:2*p%qml)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D + + !.................................................... + ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) + ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + !.................................................... + CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + !IF ( ErrStat >= AbortErrLev ) RETURN + ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: + x%qm = x%qm - junk2( 1: p%qml) + x%qmdot = x%qmdot - junk2(p%qml+1:2*p%qml) + + ! clean up temporary variable(s) + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) + END SUBROUTINE SD_AM2 !------------------------------------------------------------------------------------------------------ +!> Perform Craig Bampton reduction SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine TYPE(SD_ParameterType),INTENT(INOUT) :: p ! Parameters TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(ReKi), ALLOCATABLE :: MRR(:, :) - REAL(ReKi), ALLOCATABLE :: MLL(:, :) - REAL(ReKi), ALLOCATABLE :: MRL(:, :) - - REAL(ReKi), ALLOCATABLE :: KRR(:, :) - REAL(ReKi), ALLOCATABLE :: KLL(:, :) - REAL(ReKi), ALLOCATABLE :: KRL(:, :) - - REAL(ReKi), ALLOCATABLE :: FGR(:) - REAL(ReKi), ALLOCATABLE :: FGL(:) - - REAL(ReKi), ALLOCATABLE :: MBBb(:, :) - REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: FGRb(:) - - REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - + REAL(ReKi), ALLOCATABLE :: MRR(:, :) + REAL(ReKi), ALLOCATABLE :: MLL(:, :) + REAL(ReKi), ALLOCATABLE :: MRL(:, :) + REAL(ReKi), ALLOCATABLE :: KRR(:, :) + REAL(ReKi), ALLOCATABLE :: KLL(:, :) + REAL(ReKi), ALLOCATABLE :: KRL(:, :) + REAL(ReKi), ALLOCATABLE :: FGR(:) + REAL(ReKi), ALLOCATABLE :: FGL(:) + REAL(ReKi), ALLOCATABLE :: MBBb(:, :) + REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: KBBb(:, :) + REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) + REAL(ReKi), ALLOCATABLE :: FGRb(:) + REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" - - - ! number of nodes: + ! number of nodes: p%NNodes_I = Init%NInterf ! Number of interface nodes p%NNodes_L = Init%NNode - p%NReact - p%NNodes_I ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I - -!BJJ: TODO: are these 6's actually TPdofL? - - !DOFS of interface + !DOFS of interface + !BJJ: TODO: are these 6's actually TPdofL? p%DOFI = p%NNodes_I*6 p%DOFC = p%NReact*6 p%DOFR = (p%NReact+p%NNodes_I)*6 ! = p%DOFC + p%DOFI @@ -1618,7 +1490,7 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) IF(Init%CBMod) THEN ! C-B reduction - ! check number of internal modes + ! check number of internal modes IF(p%Nmodes > p%DOFL) THEN CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than maximum. ',ErrStat,ErrMsg,'Craig_Bampton') CALL CleanupCB() @@ -1631,159 +1503,112 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) !So assign value to one temporary variable JDamping1=Init%Jdampings(1) DEALLOCATE(Init%JDampings) - CALL AllocAry( Init%JDampings, p%DOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanupCB() - RETURN - END IF - + CALL AllocAry( Init%JDampings, p%DOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return Init%JDampings = JDamping1 ! set default values for all modes ENDIF CBparams%DOFM = p%Nmodes ! retained modes (all if no C-B reduction) - ! matrix dimension paramters p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) p%URbarL = p%DOFI !=p%NNodes_I*6 ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED - CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - - CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - - CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - - - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUpCB() - RETURN - END IF - -!................................ -! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. -!................................ - - CALL SetIndexArrays(Init, p, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUpCB() - RETURN - END IF - -!................................ -! SET MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on -! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: -!................................ - + CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); if (Failed()) return + + CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if (Failed()) return + + ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. + CALL SetIndexArrays(Init, p, ErrStat2, ErrMsg2) ; if(Failed()) return + + ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on + ! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) -!................................ -! Set p%TI and CBparams%TI2 -!................................ - - CALL TrnsfTI(Init, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUpCB() - RETURN - END IF - -!................................ -! Sets the following values, as documented in the SubDyn Theory Guide: -! CBparams%OmegaL (omega) and CBparams%PhiL from Eq. 2 -! p%PhiL_T and p%PhiLInvOmgL2 for static improvement (will be added to theory guide later?) -! CBparams%PhiR from Eq. 3 -! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. -!................................ - + ! Set p%TI and CBparams%TI2 + CALL TrnsfTI(Init, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + + !................................ + ! Sets the following values, as documented in the SubDyn Theory Guide: + ! CBparams%OmegaL (omega) and CBparams%PhiL from Eq. 2 + ! p%PhiL_T and p%PhiLInvOmgL2 for static improvement + ! CBparams%PhiR from Eq. 3 + ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. + !................................ CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%DOFM, Init, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUpCB() - RETURN - END IF + if(Failed()) return ! to use a little less space, let's deallocate these arrays that we don't need anymore, then allocate the next set of temporary arrays: - IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) - IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) - - ! "b" stands for "bar"; "t" stands for "tilde" - CALL AllocAry( MBBb, p%DOFI, p%DOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( MBmb, p%DOFI, CBparams%DOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( KBBb, p%DOFI, p%DOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( PhiRb, p%DOFL, p%DOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - CALL AllocAry( FGRb, p%DOFI, 'array FGRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUpCB() - RETURN - END IF - - -!................................ -! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to -! MBBb, MBMb, KBBb, PHiRb, FGRb -! (throw out rows/columns of first matrices to create second matrices) -!................................ - + ! "b" stands for "bar"; "t" stands for "tilde" + CALL AllocAry( MBBb, p%DOFI, p%DOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBmb, p%DOFI, CBparams%DOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KBBb, p%DOFI, p%DOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( PhiRb, p%DOFL, p%DOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGRb, p%DOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return + + !................................ + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to + ! MBBb, MBMb, KBBb, PHiRb, FGRb + ! (throw out rows/columns of first matrices to create second matrices) + !................................ CALL CBApplyConstr(p%DOFI, p%DOFR, CBparams%DOFM, p%DOFL, & CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) - - - -!................................ -! set values needed to calculate outputs and update states: -!................................ + !................................ + ! set values needed to calculate outputs and update states: + !................................ CALL SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, CBparams%OmegaL, FGL, CBparams%PhiL, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpCB() + end function Failed + subroutine CleanUpCB() - IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) - IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) - IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) - IF(ALLOCATED(MBBb) ) DEALLOCATE(MBBb) IF(ALLOCATED(MBmb) ) DEALLOCATE(MBmb) IF(ALLOCATED(KBBb) ) DEALLOCATE(KBBb) IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) IF(ALLOCATED(FGRb) ) DEALLOCATE(FGRb) - end subroutine CleanUpCB + END SUBROUTINE Craig_Bampton !------------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------------ From fb44b51e38bb29e4b0beb81e20287e1ed59b710e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 23 Oct 2019 22:36:27 -0600 Subject: [PATCH 024/377] FlexSub: done cleanup of main --- modules/subdyn/src/SubDyn.f90 | 695 +++++++++++----------------------- 1 file changed, 230 insertions(+), 465 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 06d072cc2..e08392a03 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1070,7 +1070,7 @@ END FUNCTION Failed SUBROUTINE Abort(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Init'); + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Input'); CALL CleanUp() END SUBROUTINE Abort @@ -1516,22 +1516,23 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); if (Failed()) return - - CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if (Failed()) return + + CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + + CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. CALL SetIndexArrays(Init, p, ErrStat2, ErrMsg2) ; if(Failed()) return @@ -1588,7 +1589,7 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) contains logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') Failed = ErrStat >= AbortErrLev if (Failed) call CleanUpCB() end function Failed @@ -1610,27 +1611,22 @@ subroutine CleanUpCB() end subroutine CleanUpCB END SUBROUTINE Craig_Bampton + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!> SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT( OUT) :: MRR(p%DOFR, p%DOFR) REAL(ReKi), INTENT( OUT) :: MLL(p%DOFL, p%DOFL) REAL(ReKi), INTENT( OUT) :: MRL(p%DOFR, p%DOFL) REAL(ReKi), INTENT( OUT) :: KRR(p%DOFR, p%DOFR) REAL(ReKi), INTENT( OUT) :: KLL(p%DOFL, p%DOFL) REAL(ReKi), INTENT( OUT) :: KRL(p%DOFR, p%DOFL) - REAL(ReKi), INTENT( OUT) :: FGR(p%DOFR) REAL(ReKi), INTENT( OUT) :: FGL(p%DOFL) - - - ! local variables + ! local variables INTEGER(IntKi) :: I, J, II, JJ - DO I = 1, p%DOFR !Boundary DOFs II = p%IDR(I) @@ -1662,54 +1658,42 @@ SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) ENDDO END SUBROUTINE BreakSysMtrx + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ -SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) -! This routine sets the following values, as documented in the SubDyn Theory Guide: +!> Sets the CB values, as documented in the SubDyn Theory Guide: ! OmegaL (omega) and PhiL from Eq. 2 ! p%PhiL_T and p%PhiLInvOmgL2 for static improvement (will be added to theory guide later?) ! PhiR from Eq. 3 ! MBB, MBM, and KBB from Eq. 4. !................................ - - USE SubDyn_Types +SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) TYPE(SD_InitType), INTENT(IN) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p INTEGER(IntKi), INTENT( in) :: DOFM - REAL(ReKi), INTENT( IN) :: MRR( p%DOFR, p%DOFR) REAL(ReKi), INTENT( IN) :: MLL( p%DOFL, p%DOFL) REAL(ReKi), INTENT( IN) :: MRL( p%DOFR, p%DOFL) REAL(ReKi), INTENT( IN) :: KRR( p%DOFR, p%DOFR) REAL(ReKi), INTENT(INOUT) :: KLL( p%DOFL, p%DOFL) ! on exit, it has been factored (otherwise not changed) REAL(ReKi), INTENT( IN) :: KRL( p%DOFR, p%DOFL) - - - REAL(ReKi), INTENT(INOUT) :: MBB( p%DOFR, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: MBM( p%DOFR, DOFM) - REAL(ReKi), INTENT(INOUT) :: KBB( p%DOFR, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: PhiR(p%DOFL, p%DOFR) - - REAL(ReKi), INTENT(INOUT) :: PhiL(p%DOFL, p%DOFL) !used to be PhiM(DOFL,DOFM), now it is more generic - REAL(ReKi), INTENT(INOUT) :: OmegaL(p%DOFL) !used to be omegaM only ! Eigenvalues - - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - + REAL(ReKi), INTENT(INOUT) :: MBB( p%DOFR, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: MBM( p%DOFR, DOFM) + REAL(ReKi), INTENT(INOUT) :: KBB( p%DOFR, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: PhiR(p%DOFL, p%DOFR) + REAL(ReKi), INTENT(INOUT) :: PhiL(p%DOFL, p%DOFL) !used to be PhiM(DOFL,DOFM), now it is more generic + REAL(ReKi), INTENT(INOUT) :: OmegaL(p%DOFL) !used to be omegaM only ! Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! LOCAL VARIABLES REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%DOFL, p%DOFL) [bjj: made allocatable to try to avoid stack issues] REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%DOFR,p%DOFL) = transpose of PhiR * MLL (temporary storage) - - - INTEGER :: I !, lwork !counter, and varibales for inversion routines INTEGER :: DOFvar !placeholder used to get both PhiL or PhiM into 1 process INTEGER :: ipiv(p%DOFL) !the integer vector ipvt of length min(m,n), containing the pivot indices. !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. - INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' @@ -1717,7 +1701,6 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & ErrStat = ErrID_None ErrMsg = '' - CALL WrScr(' Calculating Internal Modal Eigenvectors') IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT @@ -1730,26 +1713,17 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & ! Set OmegaL and PhiL from Eq. 2 !.................................................... IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - CALL EigenSolve(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - CALL AllocAry( Temp, p%DOFL, p%DOFL, 'Temp', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( MU, p%DOFL, p%DOFL, 'Mu', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - ! normalize PhiL + CALL EigenSolve(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Normalize PhiL ! bjj: break up this equation to avoid as many tenporary variables on the stack - !MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) + ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) + CALL AllocAry( Temp , p%DOFL , p%DOFL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , p%DOFL , p%DOFL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL) Temp = MATMUL( MU, MLL ) MU = MATMUL( Temp, PhiL ) - DEALLOCATE(Temp) - ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) DO I = 1, DOFvar PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) @@ -1758,7 +1732,6 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & PhiL(:,I) = 0.0_ReKi OmegaL(I) = 0.0_ReKi END DO - DEALLOCATE(MU) !.................................................... @@ -1766,7 +1739,6 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & !.................................................... IF (p%SttcSolve) THEN p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement - DO I = 1, p%DOFL p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) ENDDO @@ -1781,21 +1753,15 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & !.................................................... ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) ! ** note this must be done after EigenSolve() because it modifies KLL ** - CALL LAPACK_getrf( p%DOFL, p%DOFL, KLL, ipiv, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN + CALL LAPACK_getrf( p%DOFL, p%DOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N',N=p%DOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN + CALL LAPACK_getrs( TRANS='N',N=p%DOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return !.................................................... ! Set MBB, MBM, and KBB from Eq. 4: !.................................................... - CALL AllocAry( PhiR_T_MLL, p%DOFR, p%DOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) RETURN + CALL AllocAry( PhiR_T_MLL, p%DOFR, p%DOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return PhiR_T_MLL = TRANSPOSE(PhiR) PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) @@ -1814,13 +1780,24 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & KBB = MATMUL(KRL, PhiR) KBB = KBB + KRR +CONTAINS + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CBMatrix') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + if (allocated(Mu )) DEALLOCATE(Mu ) + if (allocated(Temp )) DEALLOCATE(Temp ) + if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) + end subroutine END SUBROUTINE CBMatrix !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!> SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine INTEGER(IntKi), INTENT(IN ) :: DOFI ! # of DOFS of interface nodes INTEGER(IntKi), INTENT(IN ) :: DOFR ! # of DOFS of restrained nodes (restraints and interface) @@ -1828,52 +1805,33 @@ SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) INTEGER(IntKi), INTENT(IN ) :: IDR(DOFR) REAL(ReKi), INTENT(INOUT) :: TI( DOFI,6) ! matrix TI that relates the reduced matrix to the TP, REAL(ReKi), INTENT(INOUT) :: TI2(DOFR,6) ! matrix TI2 that relates to (0,0,0) the overall substructure mass - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! local variables + ! local variables INTEGER :: I, di INTEGER :: rmndr, n - REAL(ReKi) :: x, y, z, dx, dy, dz + REAL(ReKi) :: dx, dy, dz ErrStat = ErrID_None ErrMsg = "" - TI = 0. !INitialize - + TI(:,:) = 0. !Initialize DO I = 1, DOFI di = IDI(I) rmndr = MOD(di, 6) n = CEILING(di/6.0) - x = Init%Nodes(n, 2) - y = Init%Nodes(n, 3) - z = Init%Nodes(n, 4) - - dx = x - Init%TP_RefPoint(1) - dy = y - Init%TP_RefPoint(2) - dz = z - Init%TP_RefPoint(3) + dx = Init%Nodes(n, 2) - Init%TP_RefPoint(1) + dy = Init%Nodes(n, 3) - Init%TP_RefPoint(2) + dz = Init%Nodes(n, 4) - Init%TP_RefPoint(3) SELECT CASE (rmndr) - CASE (1) - TI(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) - - CASE (2) - TI(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) - - CASE (3) - TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) - - CASE (4) - TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - - CASE (5) - TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - - CASE (0) - TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) - + CASE (1); TI(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); TI(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (0); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) CASE DEFAULT ErrStat = ErrID_Fatal ErrMsg = 'Error calculating transformation matrix TI ' @@ -1883,38 +1841,22 @@ SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) ENDDO !Augment with TI2 - TI2 = 0. !INitialize + TI2(:,:) = 0. !Initialize DO I = 1, DOFR di = IDR(I) rmndr = MOD(di, 6) n = CEILING(di/6.0) - x = Init%Nodes(n, 2) - y = Init%Nodes(n, 3) - z = Init%Nodes(n, 4) - - dx = x - dy = y - dz = z + dx = Init%Nodes(n, 2) + dy = Init%Nodes(n, 3) + dz = Init%Nodes(n, 4) SELECT CASE (rmndr) - CASE (1) - TI2(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) - - CASE (2) - TI2(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) - - CASE (3) - TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) - - CASE (4) - TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - - CASE (5) - TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - - CASE (0) - TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) - + CASE (1); TI2(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); TI2(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (0); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) CASE DEFAULT ErrStat = ErrID_Fatal ErrMsg = 'Error calculating transformation matrix TI2 ' @@ -1922,19 +1864,12 @@ SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) END SELECT ENDDO - - END SUBROUTINE TrnsfTI + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!> Return eigenvalues, Omega, and eigenvectors, Phi, SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, ErrMsg ) -! This routine returns eigenvalues, Omega, and eigenvectors, Phi, - - USE NWTC_Library - USE NWTC_ScaLAPACK - - IMPLICIT NONE - + USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix @@ -1946,143 +1881,109 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! RRD: Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! LOCALS REAL(LAKi), ALLOCATABLE :: Omega2(:) !RRD: Eigen-values new system ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 REAL(LAKi), ALLOCATABLE :: Kred(:,:), Mred(:,:) REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), VR(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables - INTEGER :: i INTEGER :: N, LWORK !variables for the eigensolver INTEGER, ALLOCATABLE :: KEY(:) - INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None ErrMsg = '' - !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! IF (Reduced) THEN !bjj: i.e., We need to reduce; it's not reduced yet ! First I need to remove constrained nodes DOFs ! This is actually done when we are printing out the 'full' set of eigenvalues - CALL ReduceKMdofs(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') ! Allocate and initialize Kred ! - CALL ReduceKMdofs(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') ! Allocate and initialize Mred + CALL ReduceKMdofs(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL ReduceKMdofs(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return N=SIZE(Kred,1) ELSE - ! This is actually done whe we are generating the CB-reduced set of eigenvalues, so the the variable 'Reduced' can be a bit confusing. GJH 8/1/13 + ! This is actually done whe we are generating the CB-reduced set of eigenvalues, so the the variable 'Reduced' can be a bit confusing. GJH 8/1/13 N=SIZE(K,1) - CALL AllocAry( Kred, n, n, 'Kred', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( Mred, n, n, 'Mred', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - + CALL AllocAry( Kred, n, n, 'Kred', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( Mred, n, n, 'Mred', ErrStat2, ErrMsg2 ); if(Failed()) return Kred=REAL( K, LAKi ) Mred=REAL( M, LAKi ) ENDIF - - ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - - IF ( NOmega > N ) THEN - CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolve') - CALL CleanupEigen() - RETURN - END IF + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! + IF ( NOmega > N ) THEN + CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolve') + CALL CleanupEigen() + RETURN + END IF - ! allocate working arrays and return arrays for the eigensolver + ! allocate working arrays and return arrays for the eigensolver LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine - CALL AllocAry( Work, lwork, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out + !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out + CALL AllocAry( Work, lwork, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( Omega2, n, 'Omega2', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( ALPHAR, n, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( ALPHAI, n, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( BETA, n, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( VR, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( VL, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( KEY, n, 'KEY', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanupEigen() - RETURN - END IF + CALL AllocAry( KEY, n, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL LAPACK_ggev('N','V',N ,Kred, Mred, ALPHAR, ALPHAI, BETA, VL, VR, work, lwork, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanupEigen() - RETURN - END IF -!if (.not. reduced) call wrmatrix(REAL(VR,ReKi),77,'ES15.8e2') - - ! bjj: This comes from the LAPACK documentation: - ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. - ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less - ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). - + CALL LAPACK_ggev('N','V',N ,Kred, Mred, ALPHAR, ALPHAI, BETA, VL, VR, work, lwork, ErrStat2, ErrMsg2) + if(Failed()) return + !if (.not. reduced) call wrmatrix(REAL(VR,ReKi),77,'ES15.8e2') + ! bjj: This comes from the LAPACK documentation: + ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted DO I=1,N !Initialize the key and calculate Omega2 KEY(I)=I - IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? ELSE Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) END IF ENDDO - - CALL ScaLAPACK_LASRT('I',N,Omega2,key,ErrStat2,ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanupEigen() - RETURN - END IF + CALL ScaLAPACK_LASRT('I',N,Omega2,key,ErrStat2,ErrMsg2); if(Failed()) return - !we need to rearrange eigenvectors based on sorting of Omega2 - !Now rearrange VR based on the new key, also I might have to scale the eigenvectors following generalized mass =idnetity criterion, also if i reduced the matrix I will need to re-expand the eigenvector + !we need to rearrange eigenvectors based on sorting of Omega2 + !Now rearrange VR based on the new key, also I might have to scale the eigenvectors following generalized mass =idnetity criterion, also if i reduced the matrix I will need to re-expand the eigenvector ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) ! result1 = matmul(Mred2,VR) - ! result2 = matmul(transpose(VR),result1) ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors - - !normcoeff=sqrt(matmul(transpose(VR),matmul(Mred2,VR))) !This should be a diagonal matrix which contains the normalization factors - - - VL=VR !temporary storage for sorting VR - DO I=1,N - !VR(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized - VR(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one - ENDDO - - !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! - - !=============================================================================== - !===== Finish EigenSolve - !=============================================================================== + !normcoeff=sqrt(matmul(transpose(VR),matmul(Mred2,VR))) !This should be a diagonal matrix which contains the normalization factors + VL=VR !temporary storage for sorting VR + DO I=1,N + !VR(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized + VR(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one + ENDDO + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! - ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - + ! --- Finish EigenSolve + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! Omega=SQRT( Omega2(1:NOmega) ) !Assign my new Omega and below my new Phi (eigenvectors) [eigenvalues are actually the square of omega] - - IF ( Reduced ) THEN ! this is called for the full system Eigenvalues: - !Need to expand eigenvectors for removed DOFs - CALL UnReduceVRdofs(VR(:,1:NOmega),Phi,N,NOmega, Init,p, ErrStat2, ErrMsg2 ) ! set Phi - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + !Need to expand eigenvectors for removed DOFs, setting Phi + CALL UnReduceVRdofs(VR(:,1:NOmega),Phi,N,NOmega, Init,p, ErrStat2, ErrMsg2 ) ; if(Failed()) return ELSE ! IF (.NOT.(Reduced)) THEN !For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR - ! This is done as part of the CB-reduced eigensolve + ! This is done as part of the CB-reduced eigensolve Phi=REAL( VR(:,1:NOmega), ReKi ) ! eigenvectors ENDIF - CALL CleanupEigen() RETURN CONTAINS -!......................... + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + SUBROUTINE CleanupEigen() - ! deallocate any local variables: - IF (ALLOCATED(Work) ) DEALLOCATE(Work) IF (ALLOCATED(Omega2)) DEALLOCATE(Omega2) !bjj: break in Debug_Doub IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) @@ -2090,38 +1991,30 @@ SUBROUTINE CleanupEigen() IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) IF (ALLOCATED(VR) ) DEALLOCATE(VR) IF (ALLOCATED(VL) ) DEALLOCATE(VL) - IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) IF (ALLOCATED(Kred) ) DEALLOCATE(Kred) IF (ALLOCATED(Mred) ) DEALLOCATE(Mred) - END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolve + !------------------------------------------------------------------------------------------------------ +!> Calculate Kred from K after removing consstrained node DOFs from the full M and K matrices +!!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) -!This routine calculates Kred from K after removing consstrained node DOFs from the full M and K matrices -!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed -!...................... - IMPLICIT NONE - TYPE(SD_InitType), INTENT( in) :: Init TYPE(SD_ParameterType), INTENT( in) :: p - INTEGER, INTENT(IN ) :: TDOF ! Size of matrix K (total DOFs) REAL(ReKi), INTENT(IN ) :: K(TDOF, TDOF) ! full matrix REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Kred(:,:) ! reduced matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals INTEGER :: I, J ! counters into full or reduced matrix INTEGER :: L ! number of DOFs to eliminate - INTEGER, ALLOCATABLE :: idx(:) ! vector to map reduced matrix to full matrix INTEGER :: NReactDOFs INTEGER :: DOF_reduced - INTEGER :: ErrStat2 CHARACTER(1024) :: ErrMsg2 @@ -2135,16 +2028,12 @@ SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) RETURN END IF - CALL AllocAry(idx, TDOF, 'idx', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') - IF (ErrStat >= AbortErrLev) THEN - IF (ALLOCATED(idx)) DEALLOCATE(idx) - RETURN - END IF + CALL AllocAry(idx, TDOF, 'idx', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') + IF (ErrStat >= AbortErrLev) THEN + RETURN + END IF - !........ ! Calculate how many rows/columns need to be eliminated: - !........ DO I = 1, TDOF idx(I) = I END DO @@ -2153,64 +2042,48 @@ SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) DO I = 1, NReactDOFs !Cycle on reaction DOFs IF (Init%BCs(I, 2) == 1) THEN L=L+1 !number of DOFs to eliminate - idx( Init%BCs(I, 1) ) = 0 ! Eliminate this one END IF END DO - !........ ! Allocate the output matrix and the index mapping array - !........ DOF_reduced = TDOF-L - CALL AllocAry(Kred, DOF_reduced, DOF_reduced, 'Kred', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') - IF (ErrStat >= AbortErrLev) THEN - IF (ALLOCATED(idx)) DEALLOCATE(idx) - RETURN - END IF + CALL AllocAry(Kred, DOF_reduced, DOF_reduced, 'Kred', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') + IF (ErrStat >= AbortErrLev) THEN + CALL CleanUp() + RETURN + END IF - !........ ! set the indices we want to keep (i.e., a mapping from reduced to full matrix) - !........ J = 1 DO I=1,TDOF - idx(J) = idx(I) IF ( idx(J) /= 0 ) J = J + 1 - END DO - - !........ ! Remove rows and columns from every row/column in full matrix where Init%BC(:,2) == 1, ! using the mapping created above. (This is a symmetric matrix.) - !........ DO J = 1, DOF_reduced !Cycle on reaction DOFs DO I = 1, DOF_reduced !Cycle on reaction DOFs Kred(I,J) = REAL( K( idx(I), idx(J) ), LAKi ) END DO END DO - - !........ ! clean up local variables: - !........ - - DEALLOCATE(idx) - + CALL CleanUp() +CONTAINS + subroutine CleanUp() + IF (ALLOCATED(idx)) DEALLOCATE(idx) + end subroutine END SUBROUTINE ReduceKMdofs + !------------------------------------------------------------------------------------------------------ -SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) -!This routine calculates augments VRred to VR for the constrained DOFs, somehow reversing what ReducedKM did for matrices +!> Augments VRred to VR for the constrained DOFs, somehow reversing what ReducedKM did for matrices !Note it works for constrained nodes, still to see how to make it work for interface nodes if needed - - USE NWTC_Library - IMPLICIT NONE - +SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT(in ) :: Init TYPE(SD_ParameterType), INTENT(in ) :: p INTEGER, INTENT(IN ) :: rDOF ,RModes !retained DOFs after removing restrained DOFs and retained modes REAL(LAKi), INTENT(IN ) :: VRred(rDOF, rModes) !eigenvector matrix with restrained DOFs removed - REAL(ReKi), INTENT(INOUT) :: VR(:,:) !eigenvalues including the previously removed DOFs INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -2221,100 +2094,82 @@ SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = '' - ALLOCATE(idx(p%NReact*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints - idx=0 !initialize - L=0 !initialize - DO I = 1, p%NReact*6 !Cycle on reaction DOFs - IF (Init%BCs(I, 2) == 1) THEN - idx(I)=Init%BCs(I, 1) !row/col index that was originally eliminated when applying restraints - L=L+1 !number of DOFs to eliminate - ENDIF - ENDDO - + ALLOCATE(idx(p%NReact*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints + idx=0 !initialize + L=0 !initialize + DO I = 1, p%NReact*6 !Cycle on reaction DOFs + IF (Init%BCs(I, 2) == 1) THEN + idx(I)=Init%BCs(I, 1) !row/col index that was originally eliminated when applying restraints + L=L+1 !number of DOFs to eliminate + ENDIF + ENDDO ! PRINT *, ' rDOF+L=',rDOF+L, 'SIZE(Phi2)=',SIZE(VR,1) - ! ALLOCATE(VR(rDOF+L,rModes), STAT = ErrStat ) !Restored eigenvectors with restrained node DOFs included - VR=0.!Initialize - - I2=1 !Initialize - DO I=1,rDOF+L !This loop inserts Vred in VR in all but the removed DOFs + VR=0.!Initialize + + I2=1 !Initialize + DO I=1,rDOF+L !This loop inserts Vred in VR in all but the removed DOFs IF (ALL((idx-I).NE.0)) THEN VR(I,:)=REAL( VRred(I2,:), ReKi ) ! potentially change of precision I2=I2+1 !Note this counter gets updated only if we insert Vred rows into VR ENDIF - ENDDO - - + ENDDO END SUBROUTINE UnReduceVRdofs -!------------------------------------------------------------------------------------------------------ + !------------------------------------------------------------------------------------------------------ SUBROUTINE CBApplyConstr(DOFI, DOFR, DOFM, DOFL, & MBB , MBM , KBB , PHiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) - INTEGER(IntKi), INTENT(IN ) :: DOFR, DOFI, DOFM, DOFL - REAL(ReKi), INTENT(IN ) :: FGR(DOFR) REAL(ReKi), INTENT(IN ) :: MBB(DOFR, DOFR) REAL(ReKi), INTENT(IN ) :: MBM(DOFR, DOFM) REAL(ReKi), INTENT(IN ) :: KBB(DOFR, DOFR) REAL(ReKi), INTENT(IN ) :: PhiR(DOFL, DOFR) - REAL(ReKi), INTENT( OUT) :: MBBb(DOFI, DOFI) REAL(ReKi), INTENT( OUT) :: KBBb(DOFI, DOFI) REAL(ReKi), INTENT( OUT) :: MBMb(DOFI, DOFM) REAL(ReKi), INTENT( OUT) :: FGRb(DOFI) REAL(ReKi), INTENT( OUT) :: PhiRb(DOFL, DOFI) - MBBb = MBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) KBBb = KBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) IF (DOFM > 0) THEN MBMb = MBM(DOFR-DOFI+1:DOFR, : ) END IF - FGRb = FGR(DOFR-DOFI+1:DOFR ) PhiRb = PhiR( :, DOFR-DOFI+1:DOFR) END SUBROUTINE CBApplyConstr -!------------------------------------------------------------------------------------------------------ + !------------------------------------------------------------------------------------------------------ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%DOFI, p%DOFI) REAL(ReKi), INTENT(IN ) :: MBMb( p%DOFI, p%Nmodes) REAL(ReKi), INTENT(IN ) :: KBBb( p%DOFI, p%DOFI) REAL(ReKi), INTENT(IN ) :: PhiL ( p%DOFL, p%DOFL) REAL(ReKi), INTENT(IN ) :: PhiRb( p%DOFL, p%DOFI) REAL(ReKi), INTENT(IN ) :: OmegaL(p%DOFL) - REAL(ReKi), INTENT(IN ) :: FGRb(p%DOFI) REAL(ReKi), INTENT(IN ) :: FGL(p%DOFL) - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables REAL(ReKi) :: TI_transpose(TPdofL,p%DOFI) !bjj: added this so we don't have to take the transpose 5+ times INTEGER(IntKi) :: I integer(IntKi) :: n ! size of jacobian in AM2 calculation INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' ErrStat = ErrID_None ErrMsg = '' - TI_transpose = TRANSPOSE(p%TI) - - - ! Store FGL for later processes + ! Store FGL for later processes IF (p%SttcSolve) THEN p%FGL = FGL ENDIF @@ -2322,38 +2177,31 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) p%PhiRb_TI = MATMUL(PhiRb, p%TI) - !............................... ! equation 46-47 (used to be 9): !............................... - p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt !p%D1_15=-TI_transpose !this is 6x6NIN - IF ( p%NModes > 0 ) THEN ! These values don't exist for DOFM=0; i.e., p%NModes == 0 ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') p%MMB = TRANSPOSE( p%MBM ) != MMBt - p%PhiM = PhiL(:,1:p%Nmodes) - ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%Nmodes) * OmegaL(1:p%Nmodes) ! OmegaM is a one-dimensional array p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%Nmodes) * Init%JDampings(1:p%Nmodes) ! Init%JDampings is also a one-dimensional array - ! B_23, B_24 !p%PhiM_T = TRANSPOSE( p%PhiM ) ! FX ! p%FX = MATMUL( p%PhiM_T, FGL ) != MATMUL( TRANSPOSE(PhiM), FGL ) p%FX = MATMUL( FGL, p%PhiM ) != MATMUL( TRANSPOSE(PhiM), FGL ) because FGL is 1-D - ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped @@ -2378,14 +2226,12 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%FY = MATMUL( p%MBM, p%FX ) & - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) - ! C2_21, C2_42 ! C2_61, C2_62 DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) ENDDO - ! D2_53, D2_63, D2_64 p%D2_63 = MATMUL( p%PhiM, p%MMB ) @@ -2398,18 +2244,14 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! F2_61 p%F2_61 = MATMUL( p%D2_64, FGL ) - !Now calculate a Jacobian used when AM2 is called and store in parameters IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%qmL > 0) n=2*p%qmL - CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ) ! This will be the Jacobian - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN + CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ); if(Failed()) return - ! First we calculate the Jacobian: - ! (note the Jacobian is first stored as p%AM2InvJac) + ! First we calculate the Jacobian: + ! (note the Jacobian is first stored as p%AM2InvJac) p%AM2Jac=0. DO i=1,p%qmL p%AM2Jac(i+p%qmL,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 @@ -2421,15 +2263,11 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%AM2Jac(I,p%qmL+I)=p%SDdeltaT/2. !J12 p%AM2Jac(p%qmL+I,p%qmL+I)=p%AM2Jac(p%qmL+I,p%qmL+I)-1 !J22 complete ENDDO - ! Now need to factor it: + ! Now need to factor it: !I think it could be improved and made more efficient if we can say the matrix is positive definite - CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - + CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2); if(Failed()) return END IF - ELSE ! no retained modes, so ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables @@ -2443,30 +2281,27 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%FY = - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) END IF - - - RETURN + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetParameters') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed END SUBROUTINE SetParameters + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ -SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) -! This routine allocates parameter arrays, based on the dimensions already set in the parameter data type. -!...................................................................................................... +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. +SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - INTEGER(IntKi), INTENT( in) :: DOFM - - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! local variables + ! local variables INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - - ! initialize error handling: + ! initialize error handling: ErrStat = ErrID_None ErrMsg = "" @@ -2474,29 +2309,22 @@ SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) CALL AllocAry( p%KBB, TPdofL, TPdofL, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, TPdofL, TPdofL, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%TI, p%DOFI, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, TPdofL, p%DOFL, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - !CALL AllocAry( p%D1_15, 6, p%DOFI, 'p%D1_15', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FY, TPdofL, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%DOFL, TPdofL, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') if (p%Nmodes > 0 ) THEN CALL AllocAry( p%MBM, TPdofL, DOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MMB, DOFM, TPdofL, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%NOmegaM2, DOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%N2OmegaMJDamp, DOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - !CALL AllocAry( p%PhiM_T, DOFM, p%DOFL, 'p%PhiM_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FX, DOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, TPdofL, DOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, TPdofL, DOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiM, p%DOFL, DOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_61, p%DOFL, DOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_62, p%DOFL, DOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - - CALL AllocAry( p%D1_13, TPdofL, TPdofL, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%NModes == 0 CALL AllocAry( p%D2_63, p%DOFL, TPdofL, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%NModes == 0 CALL AllocAry( p%D2_64, p%DOFL, p%DOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 @@ -2516,92 +2344,68 @@ SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) end if END SUBROUTINE AllocParameters + !------------------------------------------------------------------------------------------------------ +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) -! This routine allocates parameter arrays, based on the dimensions already set in the parameter data type. -!...................................................................................................... - TYPE(SD_MiscVarType), INTENT(INOUT) :: Misc ! Miscellaneous values, used to avoid local copies and/or multiple allocation/deallocation of same variables each call TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! local variables + ! local variables INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - - ! initialize error handling: + ! initialize error handling: ErrStat = ErrID_None ErrMsg = "" ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( Misc%UFL, p%DOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar, p%URbarL, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar_dot, p%URbarL, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar_dotdot,p%URbarL, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL, p%DOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dot, p%DOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dotdot, p%DOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - END SUBROUTINE AllocMiscVars + !------------------------------------------------------------------------------------------------------ +!> Set the index arrays IDI, IDR, IDL, IDC, and IDY. SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) -! this routine sets the index arrays IDI, IDR, IDL, IDC, and IDY. -!....................................................... - - USE qsort_c_module + USE qsort_c_module, only: QsortC TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! local variables + ! local variables INTEGER(IntKi) :: TempIDY(p%DOFC+p%DOFI+p%DOFL, 2) INTEGER(IntKi) :: IDT(Init%TDOF) INTEGER(IntKi) :: I, K ! counters - - - ! initialize error handling: ErrStat = ErrID_None ErrMsg = "" - !................................ - ! index IDI for interface DOFs - !................................ + ! Index IDI for interface DOFs p%IDI = Init%IntFc(1:p%DOFI, 1) !RRD interface DOFs - !................................ - ! index IDC for constraint DOFs - !................................ + ! Index IDC for constraint DOFs p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs - !................................ - ! index IDR for IDR DOFs - !................................ + ! Index IDR for IDR DOFs p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again p%IDR(p%DOFC+1:p%DOFR) = p%IDI ! IDR contains DOFs ofboundaries, constraints first then interface - !................................ - ! index IDL for IDL DOFs - !................................ - ! first set the total DOFs: + ! --- Index IDL for IDL DOFs + ! first set the total DOFs: DO I = 1, Init%TDOF !Total DOFs IDT(I) = I ENDDO - ! remove DOFs on the boundaries: + ! remove DOFs on the boundaries: DO I = 1, p%DOFR !Boundary DOFs (Interface + Constraints) IDT(p%IDR(I)) = 0 !Set 0 wherever DOFs belong to boundaries ENDDO - - ! That leaves the internal DOFs: + ! That leaves the internal DOFs: K = 0 DO I = 1, Init%TDOF IF ( IDT(I) .NE. 0 ) THEN @@ -2609,63 +2413,51 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) p%IDL(K) = IDT(I) !Internal DOFs ENDIF ENDDO - IF ( K /= p%DOFL ) THEN ErrStat = ErrID_Fatal ErrMsg = "SetIndexArrays: IDL or p%DOFL are the incorrect size." RETURN END IF - - !................................ - ! index IDY for all DOFs: - !................................ - ! set the second column of the temp array + ! --- Index IDY for all DOFs: + ! set the second column of the temp array DO I = 1, SIZE(TempIDY,1) TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) ENDDO - ! set the first column of the temp array + ! set the first column of the temp array TempIDY(1:p%DOFI, 1) = p%IDI TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL TempIDY(p%DOFI+p%DOFL+1: p%DOFI+p%DOFL+p%DOFC, 1) = p%IDC - ! sort based on the first column + ! sort based on the first column CALL QsortC( TempIDY ) - ! the second column is the key: + ! the second column is the key: p%IDY = TempIDY(:, 2) - END SUBROUTINE SetIndexArrays + !------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!> SUBROUTINE Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg,Init,p) - TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters - INTEGER(IntKi) :: DOFTP, DOFM - REAL(ReKi) :: MBBt(DOFTP, DOFTP) REAL(ReKi) :: MBmt(DOFTP, DOFM) REAL(ReKi) :: KBBt(DOFTP, DOFTP) REAL(ReKi) :: OmegaM(DOFM) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! local variables - + ! local variables INTEGER(IntKi) :: DOFT, NM, i REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) - REAL(ReKi), Allocatable :: K(:, :) REAL(ReKi), Allocatable :: M(:, :) - Character(1024) :: rootname - ErrStat = ErrID_None ErrMsg = '' DOFT = DOFTP + DOFM NM = DOFT - 3 - Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) K = 0.0 M = 0.0 @@ -2675,91 +2467,70 @@ SUBROUTINE Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMs M(1:DOFTP, 1:DOFTP) = MBBt M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) - DO i = 1, DOFM K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) M(DOFTP+i, DOFTP+i) = 1.0 ENDDO - K(1:DOFTP, 1:DOFTP) = KBBt - ! temporary rootname - rootname = 'C:\test_assemble_C-B' - + ! temporary rootname + rootname = './test_assemble_C-B_out' CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) IF ( ErrStat /= 0 ) RETURN - - + END SUBROUTINE Test_CB_Results !------------------------------------------------------------------------------------------------------ +!> Take the input u LMesh and constructs the appropriate corresponding UFL vector SUBROUTINE ConstructUFL( u, p, UFL ) -! This subroutine takes the input u LMesh and constructs the appropriate corresponding UFL vector -!...................................................................................................... TYPE(SD_InputType), INTENT(IN ) :: u ! Inputs TYPE(SD_ParameterType), INTENT(IN ) :: p ! Parameters REAL(ReKi) :: UFL(p%DOFL) - INTEGER :: I, J, StartDOF ! integers for indexing into mesh and UFL - ! note that p%DOFL = p%NNodes_L*6 - - DO I = 1, p%NNodes_L !Only interior nodes here - - ! starting index in the master arrays for the current node - startDOF = (I-1)*6 + 1 - - ! index into the Y2Mesh - J = p%NNodes_I + I - - ! Construct UFL array from the Force and Moment fields of the input mesh - UFL ( startDOF : startDOF + 2 ) = u%LMesh%Force (:,J) - UFL ( startDOF+3 : startDOF + 5 ) = u%LMesh%Moment(:,J) - - END DO - + ! note that p%DOFL = p%NNodes_L*6 + DO I = 1, p%NNodes_L !Only interior nodes here + ! starting index in the master arrays for the current node + startDOF = (I-1)*6 + 1 + ! index into the Y2Mesh + J = p%NNodes_I + I + ! Construct UFL array from the Force and Moment fields of the input mesh + UFL ( startDOF : startDOF + 2 ) = u%LMesh%Force (:,J) + UFL ( startDOF+3 : startDOF + 5 ) = u%LMesh%Moment(:,J) + END DO END SUBROUTINE -!------------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------------ +!> Output the summary file SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) - !This sub takes care of outputting the summary file - TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use TYPE(FEM_MatArrays), INTENT(IN) :: FEMparams ! FEM parameters that will be passed in for summary file use - INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !LOCALS - INTEGER(IntKi) :: UnSum ! unit number for this summary file - INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors - CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file - + INTEGER(IntKi) :: UnSum ! unit number for this summary file + INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors + CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file + INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders + INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) + REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix + REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3), mlength !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' - - INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders - - INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) - REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix - REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3), mlength !temporary arrays, member i-th direction cosine matrix (global to local) and member length - CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices - - + CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices ErrStat = ErrID_None ErrMsg = "" CALL SD_Y2Mesh_Mapping(p, SDtoMeshIndx ) - + !------------------------------------------------------------------------------------------------------------- ! open txt file !------------------------------------------------------------------------------------------------------------- @@ -2773,7 +2544,6 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) RETURN END IF - !------------------------------------------------------------------------------------------------------------- ! write discretized data to a txt file !------------------------------------------------------------------------------------------------------------- @@ -2781,7 +2551,6 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) ! (it helps in debugging) WRITE(UnSum, '(A)') 'Unless specified, units are consistent with Input units, [SI] system is advised.' WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of nodes (NNodes):',Init%NNode @@ -2928,7 +2697,6 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) - #ifdef SD_SUMMARY_DEBUG @@ -2936,11 +2704,9 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '**** Additional Debugging Information ****' - !------------------------------------------------------------------------------------------------------------- ! write assembed K M to a txt file !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A, I6)') 'FULL FEM K and M matrices. TOTAL FEM TDOFs:', Init%TDOF WRITE(UnSum, '(A)') ('Stiffness matrix K' ) @@ -2997,9 +2763,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) END SUBROUTINE OutSummary -!------------------------------------------------------------------------------------------------------ -!------------------------------------------------------------------------------------------------------ +!------------------------------------------------------------------------------------------------------ !> This function calculates the length of a member FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) TYPE(SD_InitType), INTENT(IN) :: Init !< Input data for initialization routine, this structure contains many variables needed for summary file @@ -3118,8 +2883,8 @@ SUBROUTINE SymMatDebug(M,MAT) !-------------------------------------- ! write discretized data to a txt file - WRITE(*, '(A,e15.6)') 'Matrix SYmmetry Check: Largest (abs) relative error is:', MaxErr - WRITE(*, '(A,I4,I4)') 'Matrix SYmmetry Check: (I,J)=', imax,jmax + WRITE(*, '(A,e15.6)') 'Matrix Symmetry Check: Largest (abs) relative error is:', MaxErr + WRITE(*, '(A,I4,I4)') 'Matrix Symmetry Check: (I,J)=', imax,jmax END SUBROUTINE SymMatDebug From ae6d3792dd3b3c66171f28744a1fc7dd61625ec2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 24 Oct 2019 13:05:17 -0600 Subject: [PATCH 025/377] FlexSub: Replacing Abort with Fatal to avoid clash with Intel extension --- modules/subdyn/src/SD_FEM.f90 | 32 ++++++++++++++++---------------- modules/subdyn/src/SubDyn.f90 | 28 ++++++++++++++-------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index aeca6df92..933f73bf0 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -113,7 +113,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) IF( ( Init%FEMMod .GE. 0 ) .and. (Init%FEMMod .LE. 3) ) THEN NNE = 2 ELSE - CALL Abort('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') + CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') RETURN ENDIF @@ -128,7 +128,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! check the number of interior modes IF ( p%Nmodes .GT. 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN - CALL Abort(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) RETURN ENDIF @@ -178,7 +178,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) J = J + 1 END DO IF ( .NOT. found) THEN - CALL Abort(' Member '//TRIM(Num2LStr(I))//' has JointID'//TRIM(Num2LStr(n-1))//' = '// TRIM(Num2LStr(Node))//' which is not in the node list !') + CALL Fatal(' Member '//TRIM(Num2LStr(I))//' has JointID'//TRIM(Num2LStr(n-1))//' = '// TRIM(Num2LStr(Node))//' which is not in the node list !') RETURN END IF END DO ! loop through nodes/joints @@ -200,7 +200,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) J = J + 1 END DO IF ( .NOT. found) THEN - CALL Abort(' Member '//TRIM(Num2LStr(I))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the Member X-Section Property data!') + CALL Fatal(' Member '//TRIM(Num2LStr(I))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the Member X-Section Property data!') RETURN END IF END DO ! loop through property ids @@ -231,7 +231,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF ENDDO IF (.not. found) THEN - CALL Abort(' React has node not in the node list !') + CALL Fatal(' React has node not in the node list !') RETURN ENDIF DO J = 1, 6 @@ -254,7 +254,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF ENDDO IF (.not. found) THEN - CALL Abort(' Interf has node not in the node list !') + CALL Fatal(' Interf has node not in the node list !') RETURN ENDIF DO J = 1, 6 @@ -286,7 +286,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Node2 = TempMembers(I, 3) IF ( Node1==Node2 ) THEN - CALL Abort(' Same starting and ending node in the member.') + CALL Fatal(' Same starting and ending node in the member.') RETURN ENDIF @@ -300,7 +300,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN - CALL Abort(' Material E,G and rho in a member must be the same') + CALL Fatal(' Material E,G and rho in a member must be the same') RETURN ENDIF @@ -399,11 +399,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL CleanUp_Discrt() CONTAINS - SUBROUTINE Abort(ErrMsg_in) + SUBROUTINE Fatal(ErrMsg_in) CHARACTER(len=*), intent(in) :: ErrMsg_in CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); CALL CleanUp_Discrt() - END SUBROUTINE Abort + END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices @@ -488,15 +488,15 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) ! for current application if (Init%FEMMod == 2) THEN ! tapered Euler-Bernoulli - CALL Abort ('FEMMod = 2 is not implemented.') + CALL Fatal ('FEMMod = 2 is not implemented.') return elseif (Init%FEMMod == 4) THEN ! tapered Timoshenko - CALL Abort ('FEMMod = 2 is not implemented.') + CALL Fatal ('FEMMod = 2 is not implemented.') return elseif ((Init%FEMMod == 1) .or. (Init%FEMMod == 3)) THEN ! ! 1: uniform Euler-Bernouli, 3: uniform Timoshenko else - CALL Abort('FEMMod is not valid. Please choose from 1, 2, 3, and 4. ') + CALL Fatal('FEMMod is not valid. Please choose from 1, 2, 3, and 4. ') return endif @@ -505,7 +505,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL Abort('Error allocating p%ElemProps') + CALL Fatal('Error allocating p%ElemProps') return ENDIF @@ -635,11 +635,11 @@ LOGICAL FUNCTION Failed() if (Failed) call Cleanup_AssembleKM() END FUNCTION Failed - SUBROUTINE Abort(ErrMsg_in) + SUBROUTINE Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); CALL CleanUp_AssembleKM() - END SUBROUTINE Abort + END SUBROUTINE Fatal SUBROUTINE CleanUp_AssembleKM() IF(ALLOCATED(Ke )) DEALLOCATE(Ke ) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index e08392a03..61ab55706 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -738,7 +738,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) IF ( ErrStat2 /= ErrID_None ) THEN - Call Abort('Could not open SubDyn input file') + Call Fatal('Could not open SubDyn input file') return END IF @@ -756,7 +756,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) IF ( Echo ) THEN CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat2, ErrMsg2) IF ( ErrStat2 /= 0 ) THEN - CALL Abort("Could not open SubDyn echo file") + CALL Fatal("Could not open SubDyn echo file") return END IF REWIND(UnIn) @@ -778,7 +778,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat2,ErrMsg2 ); if(Failed()) return IF ( ( p%SDdeltaT <= 0 ) ) THEN - call Abort('SDdeltaT must be greater than or equal to 0.') + call Fatal('SDdeltaT must be greater than or equal to 0.') return END IF END IF @@ -811,7 +811,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! last entry to fill in remaining values. !Check 1st value, we need at least one good value from user or throw error IF ((Init%JDampings(1) .LT. 0 ) .OR. (Init%JDampings(1) .GE. 100.0)) THEN - CALL Abort('Damping ratio should be larger than 0 and less than 100') + CALL Fatal('Damping ratio should be larger than 0 and less than 100') return ELSE DO I = 2, p%Nmodes @@ -823,7 +823,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) END IF EXIT ELSEIF ( ( Init%JDampings(I) .LT. 0 ) .OR.( Init%JDampings(I) .GE. 100.0 ) ) THEN - CALL Abort('Damping ratio should be larger than 0 and less than 100') + CALL Fatal('Damping ratio should be larger than 0 and less than 100') return ENDIF ENDDO @@ -844,7 +844,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return IF ( ( Init%JDampings(1) .LT. 0 ) .OR.( Init%JDampings(1) .GE. 100.0 ) ) THEN - CALL Abort('Damping ratio should be larger than 0 and less than 100.') + CALL Fatal('Damping ratio should be larger than 0 and less than 100.') RETURN ENDIF ENDIF @@ -970,7 +970,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CASE (2) Swtch !pass to glue code CASE DEFAULT Swtch - CALL Abort(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') return END SELECT Swtch @@ -997,7 +997,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! Allocate memory for filled group arrays ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat2 ) !this list contains different arrays for each of its elements IF ( ErrStat2 /= ErrID_None ) THEN - CALL Abort(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') RETURN END IF @@ -1006,7 +1006,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) IF (ErrStat2 == 0) THEN READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt IF ( ErrStat2 /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN - CALL Abort(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') RETURN END IF CALL AllocAry( p%MOutLst(I)%NodeCnt, p%MOutLst(I)%NOutCnt, 'NodeCnt', ErrStat2, ErrMsg2); if(Failed()) return @@ -1023,12 +1023,12 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) DO K = 1,p%MOutLst(I)%NOutCnt ! node number should be less than NDiv + 1 IF( (p%MOutLst(I)%NodeCnt(k) .GT. (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) .LT. 1) ) THEN - CALL Abort(' NodeCnt should be less than NDIV+1 and greater than 0. ') + CALL Fatal(' NodeCnt should be less than NDIV+1 and greater than 0. ') RETURN ENDIF ENDDO ELSE - CALL Abort(' NOutCnt should be less than 10 and greater than 0. ') + CALL Fatal(' NOutCnt should be less than 10 and greater than 0. ') RETURN ENDIF ENDIF @@ -1059,7 +1059,7 @@ LOGICAL FUNCTION Check(Condition, ErrMsg_in) logical, intent(in) :: Condition character(len=*), intent(in) :: ErrMsg_in Check=Condition - if (Check) call Abort(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) + if (Check) call Fatal(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) END FUNCTION Check LOGICAL FUNCTION Failed() @@ -1068,11 +1068,11 @@ LOGICAL FUNCTION Failed() if (Failed) call CleanUp() END FUNCTION Failed - SUBROUTINE Abort(ErrMsg_in) + SUBROUTINE Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Input'); CALL CleanUp() - END SUBROUTINE Abort + END SUBROUTINE Fatal SUBROUTINE CleanUp() CLOSE( UnIn ) From 4231be2e3dc9dba2961230132b44db63f95347e1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 24 Oct 2019 16:48:27 -0600 Subject: [PATCH 026/377] FlexSub: moved is_numeric to NWTC_IO --- modules/hydrodyn/src/UserWaves.f90 | 17 ----------------- modules/nwtc-library/src/NWTC_IO.f90 | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/modules/hydrodyn/src/UserWaves.f90 b/modules/hydrodyn/src/UserWaves.f90 index 495fb3fe2..a2eeb02df 100644 --- a/modules/hydrodyn/src/UserWaves.f90 +++ b/modules/hydrodyn/src/UserWaves.f90 @@ -484,23 +484,6 @@ END SUBROUTINE ReadRealNumber END SUBROUTINE WaveElev_ReadFile -!---------------------------------------------------------------------------------------------------------------------------------- - -FUNCTION is_numeric(string, x) - IMPLICIT NONE - CHARACTER(len=*), INTENT(IN) :: string - REAL(SiKi), INTENT(OUT) :: x - LOGICAL :: is_numeric - - INTEGER :: e,n - CHARACTER(len=12) :: fmt - x = 0.0_SiKi - n=LEN_TRIM(string) - WRITE(fmt,'("(F",I0,".0)")') n - READ(string,fmt,IOSTAT=e) x - is_numeric = e == 0 -END FUNCTION is_numeric - !---------------------------------------------------------------------------------------------------------------------------------- !> This routine initializes the wave kinematics based a set of user-supplied wave elevations !! diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 5109af6c6..bbe8a0415 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -8030,5 +8030,21 @@ SUBROUTINE WrVTK_SP_vectors3D( Un, dataDescr, dims, origin, gridSpacing, gridVal RETURN END SUBROUTINE WrVTK_SP_vectors3D - + + !> Returns true if a string is a number, and returns a real number + FUNCTION is_numeric(string, x) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + REAL(ReKi), INTENT(OUT) :: x + LOGICAL :: is_numeric + + INTEGER :: e,n + CHARACTER(len=12) :: fmt + x = 0.0_SiKi + n=LEN_TRIM(string) + WRITE(fmt,'("(F",I0,".0)")') n + READ(string,fmt,IOSTAT=e) x + is_numeric = e == 0 + END FUNCTION is_numeric + END MODULE NWTC_IO From 152ce272b496b2be150e368ce553bc0dd55f2dc6 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 25 Oct 2019 08:54:42 -0600 Subject: [PATCH 027/377] Fixed bugs with the PotFile data when NBody>1 and NBodyMod>1 --- modules/hydrodyn/src/HydroDyn.f90 | 1 + modules/hydrodyn/src/HydroDyn_Input.f90 | 64 ++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index d29d3edcc..9a8093ada 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -956,6 +956,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I !----------------------------------------- ! Initialize the WAMIT Calculations !----------------------------------------- + InitLocal%WAMIT%WAMITFile = InitLocal%PotFile (i) InitLocal%WAMIT%PtfmVol0 (1) = InitLocal%PtfmVol0 (i) InitLocal%WAMIT%WAMITULEN = InitLocal%WAMITULEN (i) InitLocal%WAMIT%PtfmRefxt (1) = InitLocal%PtfmRefxt (i) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 1fe5bfd55..c6117ccb9 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -35,6 +35,66 @@ MODULE HydroDyn_Input PRIVATE :: CheckMeshOutput CONTAINS + +SUBROUTINE ReadFileList ( UnIn, Fil, CharAry, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + + ! Argument declarations: + + INTEGER, INTENT(IN) :: UnIn !< I/O unit for input file. + INTEGER, INTENT(IN) :: UnEc !< I/O unit for echo file (if > 0). + INTEGER, INTENT(OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + + CHARACTER(*), INTENT(INOUT) :: CharAry(:) !< Character array being read (calling routine dimensions it to max allowable size). + + CHARACTER(*), INTENT(IN) :: Fil !< Name of the input file. + CHARACTER(*), INTENT(IN) :: AryDescr !< Text string describing the variable. + CHARACTER(*), INTENT(IN) :: AryName !< Text string containing the variable name. + + + ! Local declarations: + + INTEGER :: MaxAryLen ! Maximum length of the array being read + INTEGER :: NumWords ! Number of words contained on a line + + CHARACTER(1000) :: OutLine ! Character string read from file, containing output list + CHARACTER(3) :: EndOfFile + + + ! Initialize some values + + ErrStat = ErrID_None + ErrMsg = '' + MaxAryLen = SIZE(CharAry) + + CharAry = '' + + ! Read the line containing output parameters and store them in CharAry(:). + + CALL ReadVar ( UnIn, Fil, OutLine, AryName, AryDescr, ErrStat, ErrMsg, UnEc ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + NumWords = CountWords( OutLine ) ! The number of words in OutLine. + + + ! Check to see if we found the required number of words. + + IF ( NumWords < MaxAryLen ) THEN + + ErrStat = ErrID_Fatal + ErrMsg = 'ReadOutputList: Did not find the required number of Potfile strings on the input file line: only found '//TRIM( Int2LStr(NumWords) )//'.' + RETURN + + ELSE + + CALL GetWords ( OutLine, CharAry(1:NumWords), NumWords ) + + END IF + + RETURN + +END SUBROUTINE ReadFileList !==================================================================================================== FUNCTION CheckMeshOutput( output, numMemberOut, MOutLst, numJointOut ) @@ -905,8 +965,8 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) CALL CleanUp() RETURN END IF - - CALL ReadAry ( UnIn, FileName, InitInp%PotFile, InitInp%nWAMITObj, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) + call ReadFileList ( UnIn, FileName, InitInp%PotFile, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) + !CALL ReadAry ( UnIn, FileName, InitInp%PotFile, InitInp%nWAMITObj, 'PotFile', 'Root name of Potential flow model files', ErrStat2, ErrMsg2, UnEchoLocal ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() From 60c4e0044f7f6e670d4d3fd02c017e9a794151b3 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 25 Oct 2019 08:20:38 -0600 Subject: [PATCH 028/377] Travis Try --- .travis.yml | 74 +++++++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 51 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3e8bf79e..95833fb2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,67 +1,39 @@ # Travis CI configuration -# -# Environment info -# https://docs.travis-ci.com/user/reference/overview/ -# https://docs.travis-ci.com/user/reference/osx/ -# https://docs.travis-ci.com/user/reference/trusty/ language: c -matrix: - include: - - os: linux - dist: bionic - env: FC=/usr/bin/gfortran-7; DOUBLE_PRECISION=OFF - - os: linux - dist: bionic - env: FC=/usr/bin/gfortran-7; DOUBLE_PRECISION=ON; CPP_API=ON; CMAKE_FLAGS="-DBUILD_OPENFAST_CPP_API=$CPP_API" - - os: linux - dist: bionic - env: FC=/usr/bin/gfortran-7; DOUBLE_PRECISION=ON; CPP_API=ON; CMAKE_FLAGS="-DBUILD_OPENFAST_CPP_API=$CPP_API -DGENERATE_TYPES=ON" - - os: osx - osx_image: xcode11 - env: FC=/usr/local/bin/gfortran-7; DOUBLE_PRECISION=ON - - os: osx - osx_image: xcode11 - env: FC=/usr/local/bin/gfortran-7; DOUBLE_PRECISION=OFF - -# macos dependency install -addons: - homebrew: - packages: - - gcc@7 - - yaml-cpp - - hdf5 - - open-mpi - update: true +os: linux +dist: bionic +env: FC=/usr/bin/gfortran-8 ; CXX=/usr/bin/g++-8 ; CC=/usr/bin/gcc-8 +packages: g++-8 +sudo: true before_install: # linux configuration - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install gfortran libblas-dev liblapack-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install g++-8 gfortran-8 libblas-dev liblapack3 liblapack-dev; fi - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CPP_API" == "ON" ]]; then sudo apt-get install libopenmpi-dev libyaml-cpp-dev libhdf5-dev libxml2-dev; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pyenv shell 3.7.1; fi + - apt-cache policy libblas-dev + - apt-cache policy liblapack-dev + - ls -la /usr/lib/x86_64-linux-gnu/liblapa* + - ldd /usr/lib/x86_64-linux-gnu/liblapack.so # common configuration - - pip3 install numpy + - pip install numpy install: - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_TESTING=ON -DBUILD_SHARED_LIBS=ON -DDOUBLE_PRECISION=$DOUBLE_PRECISION $CMAKE_FLAGS - - cat CMakeCache.txt - - make -j4 install + - cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DDOUBLE_PRECISION=OFF + - make -j4 + - cd .. + - git clone https://github.com/ebranlard/weio + - python --version + - pip install -r weio/requirements.txt + - pip install -e weio + - git clone https://github.com/ebranlard/tcf-test + - cp build/glue-codes/openfast/openfast tcf-test + - cd tcf-test script: - # beamdyn unit tests - - if [[ "$DOUBLE_PRECISION" == "ON" ]]; then ctest -VV -R beamdyn_utest; fi - - # beamdyn regression tests - - if [[ "$DOUBLE_PRECISION" == "ON" ]]; then ctest -j4 -VV -R bd_; fi - - # subset of openfast regression tests - # do not run - # - 3, 4, 7, 15, 16, 17 since the free yaw is not well trusted - # - 20, 21 because theyre too long - # THIS IS COMMENTED UNTIL TESTS CAN RELIABLY DETERMINE REGRESSION - # CURRENTLY, TESTS FAIL WITH VERY MINOR DIFFERENCES - # - ctest -VV -j 18 -I 1,1,1,2,5,6,8,9,10,11,12,13,14,18,19,22,23,24,25,26 - # - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ctest -j 18 -I 1,1,1,2,5,6,8,9,10,11,12,13,14,18,19,22,23,24,25,26 ; fi + - ls + - make From 4e0681e2d8d4fdbd7095c53aa00ebe9d323b1688 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 25 Oct 2019 12:55:38 -0600 Subject: [PATCH 029/377] FlexSub: removed is_numeric from NWTC_IO for now --- modules/hydrodyn/src/UserWaves.f90 | 17 +++++++++++++++++ modules/nwtc-library/src/NWTC_IO.f90 | 16 ---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/modules/hydrodyn/src/UserWaves.f90 b/modules/hydrodyn/src/UserWaves.f90 index a2eeb02df..495fb3fe2 100644 --- a/modules/hydrodyn/src/UserWaves.f90 +++ b/modules/hydrodyn/src/UserWaves.f90 @@ -484,6 +484,23 @@ END SUBROUTINE ReadRealNumber END SUBROUTINE WaveElev_ReadFile +!---------------------------------------------------------------------------------------------------------------------------------- + +FUNCTION is_numeric(string, x) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + REAL(SiKi), INTENT(OUT) :: x + LOGICAL :: is_numeric + + INTEGER :: e,n + CHARACTER(len=12) :: fmt + x = 0.0_SiKi + n=LEN_TRIM(string) + WRITE(fmt,'("(F",I0,".0)")') n + READ(string,fmt,IOSTAT=e) x + is_numeric = e == 0 +END FUNCTION is_numeric + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine initializes the wave kinematics based a set of user-supplied wave elevations !! diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index bbe8a0415..672982f54 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -231,7 +231,6 @@ MODULE NWTC_IO MODULE PROCEDURE WrR8AryFileNR MODULE PROCEDURE WrR16AryFileNR END INTERFACE - CONTAINS @@ -8031,20 +8030,5 @@ SUBROUTINE WrVTK_SP_vectors3D( Un, dataDescr, dims, origin, gridSpacing, gridVal END SUBROUTINE WrVTK_SP_vectors3D - !> Returns true if a string is a number, and returns a real number - FUNCTION is_numeric(string, x) - IMPLICIT NONE - CHARACTER(len=*), INTENT(IN) :: string - REAL(ReKi), INTENT(OUT) :: x - LOGICAL :: is_numeric - - INTEGER :: e,n - CHARACTER(len=12) :: fmt - x = 0.0_SiKi - n=LEN_TRIM(string) - WRITE(fmt,'("(F",I0,".0)")') n - READ(string,fmt,IOSTAT=e) x - is_numeric = e == 0 - END FUNCTION is_numeric END MODULE NWTC_IO From 94c799769f9ff9354ca448e456c37e2061947f06 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 25 Oct 2019 13:12:41 -0600 Subject: [PATCH 030/377] FlexSub: Adding new file format, with legacy support --- modules/subdyn/src/SD_FEM.f90 | 71 ++++++++---- modules/subdyn/src/SubDyn.f90 | 99 +++++++++++++++-- modules/subdyn/src/SubDyn_Registry.txt | 4 + modules/subdyn/src/SubDyn_Types.f90 | 144 +++++++++++++++++++++++++ 4 files changed, 287 insertions(+), 31 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 933f73bf0..96614a842 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -28,15 +28,37 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) ! values of these parameters are ordered by their place in SubDyn input file: - INTEGER(IntKi), PARAMETER :: JointsCol = 4 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) + INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction dof array (JointID,RctTDxss,RctTDYss,RctTDZss,RctRDXss,RctRDYss,RctRDZss) INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) - INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) + INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) INTEGER(IntKi), PARAMETER :: PropSetsCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs INTEGER(IntKi), PARAMETER :: XPropSetsCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) + INTEGER(IntKi), PARAMETER :: CablePropSetsCol= 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) + INTEGER(IntKi), PARAMETER :: RigidPropSetsCol= 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) + ! Indices in Members table + INTEGER(IntKi), PARAMETER :: iMType= 4 ! Index in Members table where the type is stored + INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored + + ! Indices in Joints table + INTEGER(IntKi), PARAMETER :: iJointType= 5 ! Index in Joints where the joint type is stored + INTEGER(IntKi), PARAMETER :: iJointDir= 6 ! Index in Joints where the joint-direction are stored + INTEGER(IntKi), PARAMETER :: iJointStiff= 9 ! Index in Joints where the joint-stiffness is stored + INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored + + ! ID for joint types + INTEGER(IntKi), PARAMETER :: idCantilever = 1 + INTEGER(IntKi), PARAMETER :: idUniversal = 2 + INTEGER(IntKi), PARAMETER :: idPin = 3 + INTEGER(IntKi), PARAMETER :: idBall = 4 + + ! ID for member types + INTEGER(IntKi), PARAMETER :: idBeam = 1 + INTEGER(IntKi), PARAMETER :: idCable = 2 + INTEGER(IntKi), PARAMETER :: idRigid = 3 INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsCol,XPropSetsCol,COSMsCol,CMassCol) @@ -104,6 +126,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp + INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 ErrStat = ErrID_None @@ -162,6 +185,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) p%Elems = 0 DO I = 1, p%NMembers p%Elems(I, 1) = I ! element/member number (not MemberID) + p%Elems(I, iMType)= Init%Members(I, iMType) ! !bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. ! loop through the JointIDs for this member and find the corresponding indices into the Joints array @@ -185,9 +209,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! loop through the PropSetIDs for this member and find the corresponding indices into the Joints array ! we're setting these two values: - ! p%Elems(I, 4) = property set for node 1 (note this sets the YoungE, ShearG, and MatDens columns for the ENTIRE element) - ! p%Elems(I, 5) = property set for node 2 (note this should be used only for the XsecD and XsecT properties in the element [for a linear distribution from node 1 to node 2 of D and T]) - DO n=4,5 ! Member column for MPropSetID1 and MPropSetID2 + ! p%Elems(I, 5) = property set for node 1 (note this sets the YoungE, ShearG, and MatDens columns for the ENTIRE element) + ! p%Elems(I, 6) = property set for node 2 (note this should be used only for the XsecD and XsecT properties in the element [for a linear distribution from node 1 to node 2 of D and T]) + DO n=iMProp,iMProp+1 ! Member column for MPropSetID1 and MPropSetID2 Prop = Init%Members(I, n) ! n=4 or 5 ! ...... search for index of property set whose PropSetID matches Prop ...... J = 1 @@ -290,8 +314,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF - Prop1 = TempMembers(I, 4) - Prop2 = TempMembers(I, 5) + eType = TempMembers(I, iMType ) + Prop1 = TempMembers(I, iMProp ) + Prop2 = TempMembers(I, iMProp+1) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 @@ -340,11 +365,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) kprop = kprop + 1 CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, Prop1, kprop, p) + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) nprop = kprop ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, Prop1, Prop1, p) + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) nprop = Prop1 ENDIF @@ -364,18 +389,18 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, & TempProps) kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, nprop, kprop, p) + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) nprop = kprop ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, nprop, nprop, p) + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) ENDIF ENDDO ! the element connect to Node2 kelem = kelem + 1 - CALL SetNewElem(kelem, knode, Node2, nprop, Prop2, p) + CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) ENDDO ! loop over all members @@ -430,19 +455,21 @@ END SUBROUTINE SetNewNode !------------------------------------------------------------------------------------------------------ !> Set properties of element k -SUBROUTINE SetNewElem(k, n1, n2, p1, p2, p) +SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) INTEGER, INTENT(IN ) :: k INTEGER, INTENT(IN ) :: n1 INTEGER, INTENT(IN ) :: n2 + INTEGER, INTENT(IN ) :: eType INTEGER, INTENT(IN ) :: p1 INTEGER, INTENT(IN ) :: p2 TYPE(SD_ParameterType), INTENT(INOUT) :: p - p%Elems(k, 1) = k - p%Elems(k, 2) = n1 - p%Elems(k, 3) = n2 - p%Elems(k, 4) = p1 - p%Elems(k, 5) = p2 + p%Elems(k, 1) = k + p%Elems(k, 2) = n1 + p%Elems(k, 3) = n2 + p%Elems(k, iMType) = eType + p%Elems(k, iMProp ) = p1 + p%Elems(k, iMProp+1) = p2 END SUBROUTINE SetNewElem @@ -483,6 +510,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector INTEGER, DIMENSION(NNE) :: nn ! node number in element INTEGER :: r + INTEGER(IntKi) :: eType INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 @@ -530,9 +558,10 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) N1 = p%Elems(I, 2) N2 = p%Elems(I, NNE + 1) - P1 = p%Elems(I, NNE + 2) - P2 = p%Elems(I, NNE + 3) - + P1 = p%Elems(I, iMProp ) + P2 = p%Elems(I, iMProp+1) + eType = p%Elems(I, iMType) + E = Init%Props(P1, 2) G = Init%Props(P1, 3) rho = Init%Props(P1, 4) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 61ab55706..fa4f49f72 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -713,9 +713,12 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CHARACTER(1024) :: PriPath ! The path to the primary input file CHARACTER(1024) :: Line ! String to temporarially hold value of read line INTEGER :: Sttus - +CHARACTER(64), ALLOCATABLE :: StrArray(:) ! Array of strings, for better control of table inputs LOGICAL :: Echo +LOGICAL :: LegacyFormat +LOGICAL :: bNumeric INTEGER(IntKi) :: UnIn +INTEGER(IntKi) :: nColumns INTEGER(IntKi) :: IOS INTEGER(IntKi) :: UnEc !Echo file ID @@ -859,11 +862,42 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL AllocAry(Init%Joints, Init%NJoints, JointsCol, 'Joints', ErrStat2, ErrMsg2 ); if(Failed()) return -DO I = 1, Init%NJoints - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, JointsCol, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - Init%Joints(I,:) = Dummy_ReAry(1:JointsCol) -ENDDO IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return +! --- Reading first line to detect file format +READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return +! --- Reading first line to detect file format based on number of columns +nColumns=JointsCol +CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return +CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ) +if (ErrStat2/=0) then + ! We try we 4 columns (legacy format) + nColumns = 4 + deallocate(StrArray) + CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return + CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ); if(Failed()) return + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + print*,'Warning: Legacy joints table format detected in SubDyn input file!' + print*,' Some feature might be missing and only partial legacy support is provided.' + print*,' All joints are assumed cantilever, all members regular beams.' + print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' + print*,' Look at the SubDyn API changes to adapt your input files.' + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + Init%Joints(:,5) = idCantilever ! All joints assumed cantilever + Init%Joints(:,6:JointsCol) = 0.0 ! remaining columns set to 0 + LegacyFormat=.True. ! Legacy format - Delete me in 2024 +else + ! New format + LegacyFormat=.False. +endif +! Extract fields from first line +DO I = 1, nColumns + bNumeric = is_numeric(StrArray(I), Init%Joints(1,I)) ! Convert from string to float +ENDDO +! Read remaining lines +DO I = 2, Init%NJoints + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, nColumns, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + Init%Joints(I,:) = Dummy_ReAry(1:nColumns) +ENDDO !---------- GO AHEAD and ROTATE STRUCTURE IF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) @@ -901,9 +935,15 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) +Init%Members(:,:) = 0.0_ReKi +if (LegacyFormat) then + nColumns = 5 +else + nColumns = MembersCol +endif DO I = 1, p%NMembers - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, MembersCol, 'Members', 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - Init%Members(I,:) = Dummy_IntAry(1:MembersCol) + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members', 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) ENDDO IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return @@ -930,6 +970,30 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ENDDO IF (Check( Init%NXPropSets < 0, 'NXPropSets must be >=0')) return + +if (.not. LegacyFormat) then + !-------------------------- CABLE PROPERTIES ------------------------------------- + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NCablePropSets, 'NCablePropSets', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%CablePropSets, Init%NCablePropSets, CablePropSetsCol, 'CablePropSets', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NCablePropSets + CALL ReadAry( UnIn, SDInputFile, Init%CablePropSets(I,:), CablePropSetsCol, 'CablePropSets', 'CablePropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ENDDO + IF (Check( Init%NCablePropSets < 0, 'NCablePropSets must be >=0')) return + !----------------------- RIGID LINK PROPERTIES ------------------------------------ + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NRigidPropSets, 'NRigidPropSets', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%RigidPropSets, Init%NRigidPropSets, RigidPropSetsCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NRigidPropSets + CALL ReadAry( UnIn, SDInputFile, Init%RigidPropSets(I,:), RigidPropSetsCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ENDDO + IF (Check( Init%NRigidPropSets < 0, 'NRigidPropSets must be >=0')) return +endif + !---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ CALL ReadCom ( UnIn, SDInputFile, 'Member direction cosine matrices ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -2562,8 +2626,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem - WRITE(UnSum, '(A8,4(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Prop_I', 'Prop_J' - WRITE(UnSum, '(I8,I10,I10,I10,I10)') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) + WRITE(UnSum, '(A8,5(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Type', 'Prop_I', 'Prop_J' + WRITE(UnSum, '(I8,5(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NProp @@ -2593,7 +2657,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS - propids=Init%Members(i,4:5) + propids=Init%Members(i,iMProp:iMProp+1) mlength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) IF (ErrStat .EQ. ErrID_None) THEN WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & @@ -2888,4 +2952,19 @@ SUBROUTINE SymMatDebug(M,MAT) END SUBROUTINE SymMatDebug +FUNCTION is_numeric(string, x) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + REAL(SiKi), INTENT(OUT) :: x + LOGICAL :: is_numeric + + INTEGER :: e,n + CHARACTER(len=12) :: fmt + x = 0.0_SiKi + n=LEN_TRIM(string) + WRITE(fmt,'("(F",I0,".0)")') n + READ(string,fmt,IOSTAT=e) x + is_numeric = e == 0 +END FUNCTION is_numeric + End Module SubDyn diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index b69c6c3c8..a31dbe7be 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -73,6 +73,8 @@ typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" typedef ^ ^ INTEGER NPropSets - - - "Number of property sets" typedef ^ ^ INTEGER NXPropSets - - - "Number of extended property sets" +typedef ^ ^ INTEGER NCablePropSets - - - "Number of property sets for cables" +typedef ^ ^ INTEGER NRigidPropSets - - - "Number of property sets for rigid links" typedef ^ ^ INTEGER NInterf - - - "Number of joints attached to transition piece" typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" @@ -82,6 +84,8 @@ typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" typedef ^ ^ ReKi PropSets {:}{:} - - "Property sets number and values" typedef ^ ^ ReKi XPropSets {:}{:} - - "Extended property sets" +typedef ^ ^ ReKi CablePropSets {:}{:} - - "Property ID and values for cables" +typedef ^ ^ ReKi RigidPropSets {:}{:} - - "Property ID and values for rigid link" typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index d7ce80aae..a56a837f6 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -112,6 +112,8 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NJoints !< Number of joints of the sub structure [-] INTEGER(IntKi) :: NPropSets !< Number of property sets [-] INTEGER(IntKi) :: NXPropSets !< Number of extended property sets [-] + INTEGER(IntKi) :: NCablePropSets !< Number of property sets for cables [-] + INTEGER(IntKi) :: NRigidPropSets !< Number of property sets for rigid links [-] INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] @@ -121,6 +123,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSets !< Property sets number and values [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: XPropSets !< Extended property sets [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CablePropSets !< Property ID and values for cables [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: RigidPropSets !< Property ID and values for rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] @@ -2565,6 +2569,8 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%NJoints = SrcInitTypeData%NJoints DstInitTypeData%NPropSets = SrcInitTypeData%NPropSets DstInitTypeData%NXPropSets = SrcInitTypeData%NXPropSets + DstInitTypeData%NCablePropSets = SrcInitTypeData%NCablePropSets + DstInitTypeData%NRigidPropSets = SrcInitTypeData%NRigidPropSets DstInitTypeData%NInterf = SrcInitTypeData%NInterf DstInitTypeData%NCMass = SrcInitTypeData%NCMass DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs @@ -2613,6 +2619,34 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%XPropSets = SrcInitTypeData%XPropSets ENDIF +IF (ALLOCATED(SrcInitTypeData%CablePropSets)) THEN + i1_l = LBOUND(SrcInitTypeData%CablePropSets,1) + i1_u = UBOUND(SrcInitTypeData%CablePropSets,1) + i2_l = LBOUND(SrcInitTypeData%CablePropSets,2) + i2_u = UBOUND(SrcInitTypeData%CablePropSets,2) + IF (.NOT. ALLOCATED(DstInitTypeData%CablePropSets)) THEN + ALLOCATE(DstInitTypeData%CablePropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%CablePropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%CablePropSets = SrcInitTypeData%CablePropSets +ENDIF +IF (ALLOCATED(SrcInitTypeData%RigidPropSets)) THEN + i1_l = LBOUND(SrcInitTypeData%RigidPropSets,1) + i1_u = UBOUND(SrcInitTypeData%RigidPropSets,1) + i2_l = LBOUND(SrcInitTypeData%RigidPropSets,2) + i2_u = UBOUND(SrcInitTypeData%RigidPropSets,2) + IF (.NOT. ALLOCATED(DstInitTypeData%RigidPropSets)) THEN + ALLOCATE(DstInitTypeData%RigidPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%RigidPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%RigidPropSets = SrcInitTypeData%RigidPropSets +ENDIF IF (ALLOCATED(SrcInitTypeData%COSMs)) THEN i1_l = LBOUND(SrcInitTypeData%COSMs,1) i1_u = UBOUND(SrcInitTypeData%COSMs,1) @@ -2884,6 +2918,12 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%XPropSets)) THEN DEALLOCATE(InitTypeData%XPropSets) ENDIF +IF (ALLOCATED(InitTypeData%CablePropSets)) THEN + DEALLOCATE(InitTypeData%CablePropSets) +ENDIF +IF (ALLOCATED(InitTypeData%RigidPropSets)) THEN + DEALLOCATE(InitTypeData%RigidPropSets) +ENDIF IF (ALLOCATED(InitTypeData%COSMs)) THEN DEALLOCATE(InitTypeData%COSMs) ENDIF @@ -2983,6 +3023,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! NJoints Int_BufSz = Int_BufSz + 1 ! NPropSets Int_BufSz = Int_BufSz + 1 ! NXPropSets + Int_BufSz = Int_BufSz + 1 ! NCablePropSets + Int_BufSz = Int_BufSz + 1 ! NRigidPropSets Int_BufSz = Int_BufSz + 1 ! NInterf Int_BufSz = Int_BufSz + 1 ! NCMass Int_BufSz = Int_BufSz + 1 ! NCOSMs @@ -3004,6 +3046,16 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! XPropSets upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%XPropSets) ! XPropSets END IF + Int_BufSz = Int_BufSz + 1 ! CablePropSets allocated yes/no + IF ( ALLOCATED(InData%CablePropSets) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CablePropSets upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CablePropSets) ! CablePropSets + END IF + Int_BufSz = Int_BufSz + 1 ! RigidPropSets allocated yes/no + IF ( ALLOCATED(InData%RigidPropSets) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! RigidPropSets upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RigidPropSets) ! RigidPropSets + END IF Int_BufSz = Int_BufSz + 1 ! COSMs allocated yes/no IF ( ALLOCATED(InData%COSMs) ) THEN Int_BufSz = Int_BufSz + 2*2 ! COSMs upper/lower bounds for each dimension @@ -3146,6 +3198,10 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NXPropSets Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCablePropSets + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NRigidPropSets + Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCMass @@ -3206,6 +3262,38 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%XPropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%XPropSets))-1 ) = PACK(InData%XPropSets,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%XPropSets) END IF + IF ( .NOT. ALLOCATED(InData%CablePropSets) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CablePropSets,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CablePropSets,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CablePropSets,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CablePropSets,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CablePropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CablePropSets))-1 ) = PACK(InData%CablePropSets,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CablePropSets) + END IF + IF ( .NOT. ALLOCATED(InData%RigidPropSets) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RigidPropSets,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RigidPropSets,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RigidPropSets,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RigidPropSets,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%RigidPropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RigidPropSets))-1 ) = PACK(InData%RigidPropSets,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%RigidPropSets) + END IF IF ( .NOT. ALLOCATED(InData%COSMs) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3563,6 +3651,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%NXPropSets = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + OutData%NCablePropSets = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NRigidPropSets = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 OutData%NInterf = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NCMass = IntKiBuf( Int_Xferred ) @@ -3653,6 +3745,58 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%XPropSets) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CablePropSets not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CablePropSets)) DEALLOCATE(OutData%CablePropSets) + ALLOCATE(OutData%CablePropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CablePropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CablePropSets)>0) OutData%CablePropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CablePropSets))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CablePropSets) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RigidPropSets not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RigidPropSets)) DEALLOCATE(OutData%RigidPropSets) + ALLOCATE(OutData%RigidPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RigidPropSets.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%RigidPropSets)>0) OutData%RigidPropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RigidPropSets))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%RigidPropSets) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs not allocated Int_Xferred = Int_Xferred + 1 ELSE From 1075a7dc72345962e9af9a6e2855f17b33ddc2fa Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 30 Oct 2019 15:15:26 -0600 Subject: [PATCH 031/377] TCF: Remove the platform force flag usage from WAMIT2 NOTE: this hasn't been tested since the branch this is based on does not currently compile!!!! --- modules/hydrodyn/src/WAMIT2.f90 | 103 +++++++++++--------------------- modules/hydrodyn/src/WAMIT2.txt | 8 --- 2 files changed, 34 insertions(+), 77 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 393bf0f1c..1ea5d84f5 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -3054,35 +3054,25 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF (InitInp%MnDriftF) THEN ! if the flag is true, we are doing this calculation IF (InitInp%MnDrift == 8) THEN ! the .8 files are not complete - p%MnDriftDims(1) = InitInp%PtfmSgF2 - p%MnDriftDims(2) = InitInp%PtfmSwF2 + p%MnDriftDims(1) = .TRUE. + p%MnDriftDims(2) = .TRUE. p%MnDriftDims(3) = .FALSE. ! the .8 files don't contain this dimension p%MnDriftDims(4) = .FALSE. ! the .8 files don't contain this dimension p%MnDriftDims(5) = .FALSE. ! the .8 files don't contain this dimension - p%MnDriftDims(6) = InitInp%PtfmYF2 - !> Now warn me that we changed the calculations in this case... - IF (InitInp%PtfmHvF2) THEN - CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& - 'in the heave direction. No second order heave forces will be calculated within the mean drift calculations.'//NewLine, & - ErrStat, ErrMsg, 'CheckInitInput') - ENDIF - IF (InitInp%PtfmRF2) THEN - CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& - 'for platform roll. No second order roll forces will be calculated within the mean drift calculations.'//NewLine, & - ErrStat, ErrMsg, 'CheckInitInput') - ENDIF - IF (InitInp%PtfmPF2) THEN - CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& - 'for platform pitch. No second order pitching forces will be calculated within the mean drift calculations.'//NewLine, & - ErrStat, ErrMsg, 'CheckInitInput') - ENDIF + p%MnDriftDims(6) = .TRUE. +!FIXME: do I want to include these warnings anymore? +! !> Now warn me that we changed the calculations in this case... +! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& +! 'in the heave direction. No second order heave forces will be calculated within the mean drift calculations.'//NewLine, & +! ErrStat, ErrMsg, 'CheckInitInput') +! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& +! 'for platform roll. No second order roll forces will be calculated within the mean drift calculations.'//NewLine, & +! ErrStat, ErrMsg, 'CheckInitInput') +! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& +! 'for platform pitch. No second order pitching forces will be calculated within the mean drift calculations.'//NewLine, & +! ErrStat, ErrMsg, 'CheckInitInput') ELSE - p%MnDriftDims(1) = InitInp%PtfmSgF2 - p%MnDriftDims(2) = InitInp%PtfmSwF2 - p%MnDriftDims(3) = InitInp%PtfmHvF2 - p%MnDriftDims(4) = InitInp%PtfmRF2 - p%MnDriftDims(5) = InitInp%PtfmPF2 - p%MnDriftDims(6) = InitInp%PtfmYF2 + p%MnDriftDims = .TRUE. ENDIF ELSE p%MnDriftDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something @@ -3098,36 +3088,26 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF (InitInp%NewmanAppF) THEN ! if the flag is true, we are doing this calculation IF (InitInp%NewmanApp == 8) THEN ! the .8 files are not complete - p%NewmanAppDims(1) = InitInp%PtfmSgF2 - p%NewmanAppDims(2) = InitInp%PtfmSwF2 + p%NewmanAppDims(1) = .TRUE. + p%NewmanAppDims(2) = .TRUE. p%NewmanAppDims(3) = .FALSE. ! the .8 files don't contain this dimension p%NewmanAppDims(4) = .FALSE. ! the .8 files don't contain this dimension p%NewmanAppDims(5) = .FALSE. ! the .8 files don't contain this dimension - p%NewmanAppDims(6) = InitInp%PtfmYF2 - !> Now warn me that we changed the calculations in this case... - IF (InitInp%PtfmHvF2) THEN - CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& - 'second order force calculations of platform heave.'//NewLine// & - " No second order heave forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') - ENDIF - IF (InitInp%PtfmRF2) THEN - CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& - 'second order force calculations of platform roll.'//NewLine// & - " No second order roll forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') - ENDIF - IF (InitInp%PtfmPF2) THEN - CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& - 'second order force calculations of platform pitch.'//NewLine// & - " No second order pitching forces will be calculated within the Newman's Approximation calculations.", & - ErrStat, ErrMsg, 'CheckInitInput') - ENDIF + p%NewmanAppDims(6) = .TRUE. +!FIXME: do I want to include these warnings anymore? +! !> Now warn me that we changed the calculations in this case... +! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& +! 'second order force calculations of platform heave.'//NewLine// & +! " No second order heave forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') +! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& +! 'second order force calculations of platform roll.'//NewLine// & +! " No second order roll forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') +! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& +! 'second order force calculations of platform pitch.'//NewLine// & +! " No second order pitching forces will be calculated within the Newman's Approximation calculations.", & +! ErrStat, ErrMsg, 'CheckInitInput') ELSE - p%NewmanAppDims(1) = InitInp%PtfmSgF2 - p%NewmanAppDims(2) = InitInp%PtfmSwF2 - p%NewmanAppDims(3) = InitInp%PtfmHvF2 - p%NewmanAppDims(4) = InitInp%PtfmRF2 - p%NewmanAppDims(5) = InitInp%PtfmPF2 - p%NewmanAppDims(6) = InitInp%PtfmYF2 + p%NewmanAppDims = .TRUE. ENDIF ELSE p%NewmanAppDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something @@ -3142,19 +3122,9 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff !> 3. For the Difference QTF method, IF (InitInp%DiffQTFF) THEN ! if the flag is true, we are doing this calculation - p%DiffQTFDims(1) = InitInp%PtfmSgF2 - p%DiffQTFDims(2) = InitInp%PtfmSwF2 - p%DiffQTFDims(3) = InitInp%PtfmHvF2 - p%DiffQTFDims(4) = InitInp%PtfmRF2 - p%DiffQTFDims(5) = InitInp%PtfmPF2 - p%DiffQTFDims(6) = InitInp%PtfmYF2 + p%DiffQTFDims = .TRUE. ! Also set the MnDrift flags. We will be passing data from the DiffQTF method to the MnDrift method for the first term - p%MnDriftDims(1) = InitInp%PtfmSgF2 - p%MnDriftDims(2) = InitInp%PtfmSwF2 - p%MnDriftDims(3) = InitInp%PtfmHvF2 - p%MnDriftDims(4) = InitInp%PtfmRF2 - p%MnDriftDims(5) = InitInp%PtfmPF2 - p%MnDriftDims(6) = InitInp%PtfmYF2 + p%MnDriftDims = .TRUE. ELSE p%DiffQTFDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something ENDIF @@ -3163,12 +3133,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff !> 4. For the Summation QTF method, IF (InitInp%SumQTFF) THEN ! if the flag is true, we are doing this calculation - p%SumQTFDims(1) = InitInp%PtfmSgF2 - p%SumQTFDims(2) = InitInp%PtfmSwF2 - p%SumQTFDims(3) = InitInp%PtfmHvF2 - p%SumQTFDims(4) = InitInp%PtfmRF2 - p%SumQTFDims(5) = InitInp%PtfmPF2 - p%SumQTFDims(6) = InitInp%PtfmYF2 + p%SumQTFDims = .TRUE. ELSE p%SumQTFDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something ENDIF diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index c52b346ab..8c0f8927c 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -42,14 +42,6 @@ typedef ^ ^ INTEGER NumOuts typedef ^ ^ INTEGER NumOutAll - - - "" - typedef ^ ^ INTEGER WaveMod - - - "The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here." - -typedef ^ ^ LOGICAL PtfmSgF2 - - - "Supplied by Driver: Platform horizontal surge translation force (flag)" - -typedef ^ ^ LOGICAL PtfmSwF2 - - - "Supplied by Driver: Platform horizontal sway translation force (flag)" - -typedef ^ ^ LOGICAL PtfmHvF2 - - - "Supplied by Driver: Platform vertical heave translation force (flag)" - -typedef ^ ^ LOGICAL PtfmRF2 - - - "Supplied by Driver: Platform roll tilt rotation force (flag)" - -typedef ^ ^ LOGICAL PtfmPF2 - - - "Supplied by Driver: Platform pitch tilt rotation force (flag)" - -typedef ^ ^ LOGICAL PtfmYF2 - - - "Supplied by Driver: Platform yaw rotation force (flag)" - - - #[note: only one of MnDriff / NewmanApp / DiffQTF can be non-zero typedef ^ ^ INTEGER MnDrift - - - "Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use}" - typedef ^ ^ INTEGER NewmanApp - - - "Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use}" - From 38a38722952dfd93a82ddb2f31357ab6130d74b2 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 31 Oct 2019 09:39:04 -0600 Subject: [PATCH 032/377] TCF: ported some updates to the CMakeLists.txt files for the build system update. Still does not compile. --- modules/hydrodyn/CMakeLists.txt | 1 + modules/map/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/hydrodyn/CMakeLists.txt b/modules/hydrodyn/CMakeLists.txt index 7f1d6857b..5626c445f 100644 --- a/modules/hydrodyn/CMakeLists.txt +++ b/modules/hydrodyn/CMakeLists.txt @@ -51,6 +51,7 @@ set(HYDRODYN_SOURCES src/HydroDyn_Types.f90 src/Morison_Types.f90 src/SS_Radiation_Types.f90 + src/SS_Excitation_Types.f90 src/WAMIT_Types.f90 src/WAMIT2_Types.f90 src/Waves_Types.f90 diff --git a/modules/map/CMakeLists.txt b/modules/map/CMakeLists.txt index 326bce1f3..5e78fe88e 100644 --- a/modules/map/CMakeLists.txt +++ b/modules/map/CMakeLists.txt @@ -20,14 +20,14 @@ if(WIN32 OR CYGWIN OR MINGW) endif() if (GENERATE_TYPES) + generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Fortran_Types.f90 -noextrap) generate_f90_types(src/MAP_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -ccode) - generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -noextrap) endif() file(GLOB MAP_CLIB_SOURCES src/*.c src/*.cc src/*/*.c src/*/*.cc) file(GLOB MAP_C_HEADERS src/*.h src/*/*.h) -add_library(mapcpplib ${MAP_CLIB_SOURCES} src/MAP_Types.f90) +add_library(mapcpplib ${MAP_CLIB_SOURCES} src/MAP_Types.f90 src/MAP_Fortran_Types.f90) target_include_directories(mapcpplib PUBLIC $ $ From 215ee9dfa745aea2f480005a2627af93db390ac3 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 31 Oct 2019 10:16:33 -0600 Subject: [PATCH 033/377] Bug Fixes for cmake build errors found by andrew-platt --- modules/hydrodyn/CMakeLists.txt | 1 + modules/hydrodyn/src/WAMIT.f90 | 2 +- modules/hydrodyn/src/WAMIT.txt | 2 +- modules/hydrodyn/src/WAMIT_Types.f90 | 4 ++-- modules/map/CMakeLists.txt | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/hydrodyn/CMakeLists.txt b/modules/hydrodyn/CMakeLists.txt index 7f1d6857b..5626c445f 100644 --- a/modules/hydrodyn/CMakeLists.txt +++ b/modules/hydrodyn/CMakeLists.txt @@ -51,6 +51,7 @@ set(HYDRODYN_SOURCES src/HydroDyn_Types.f90 src/Morison_Types.f90 src/SS_Radiation_Types.f90 + src/SS_Excitation_Types.f90 src/WAMIT_Types.f90 src/WAMIT2_Types.f90 src/Waves_Types.f90 diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 1308ca108..25eed45f4 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -62,7 +62,7 @@ subroutine TransformWAMITMatrices( NBody, RotZ, M ) !.................................................................................................................................. integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) - real(SiKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(ReKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices integer(IntKi) :: i,j,ii,jj,iSub,jSub real(R8Ki) :: Rj(3,3) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index c7d732bd1..e4e5180fb 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -21,7 +21,7 @@ param WAMIT/WAMIT unused INTEGER typedef ^ InitInputType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - typedef ^ ^ ReKi Gravity - - - "Supplied by Driver: Gravitational acceleration" "(m/s^2)" -typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m +typedef ^ ^ SiKi WtrDpth - - - "Water depth (positive-valued)" m typedef ^ ^ ReKi PtfmVol0 {:} - - "" - typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - typedef ^ ^ ReKi WAMITULEN - - - "" - diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index c673e7bc8..b8a223cc3 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -43,7 +43,7 @@ MODULE WAMIT_Types INTEGER(IntKi) :: NBody !< [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] [-] INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] REAL(ReKi) :: Gravity !< Supplied by Driver: Gravitational acceleration [(m/s^2)] - REAL(ReKi) :: WtrDpth !< Water depth (positive-valued) [m] + REAL(SiKi) :: WtrDpth !< Water depth (positive-valued) [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmVol0 !< [-] LOGICAL :: HasWAMIT !< .TRUE. if using WAMIT model, .FALSE. otherwise [-] REAL(ReKi) :: WAMITULEN !< [-] @@ -815,7 +815,7 @@ SUBROUTINE WAMIT_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%Gravity = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - OutData%WtrDpth = ReKiBuf( Re_Xferred ) + OutData%WtrDpth = REAL( ReKiBuf( Re_Xferred ), SiKi) Re_Xferred = Re_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmVol0 not allocated Int_Xferred = Int_Xferred + 1 diff --git a/modules/map/CMakeLists.txt b/modules/map/CMakeLists.txt index 326bce1f3..5e78fe88e 100644 --- a/modules/map/CMakeLists.txt +++ b/modules/map/CMakeLists.txt @@ -20,14 +20,14 @@ if(WIN32 OR CYGWIN OR MINGW) endif() if (GENERATE_TYPES) + generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Fortran_Types.f90 -noextrap) generate_f90_types(src/MAP_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -ccode) - generate_f90_types(src/MAP_Fortran_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/MAP_Types.f90 -noextrap) endif() file(GLOB MAP_CLIB_SOURCES src/*.c src/*.cc src/*/*.c src/*/*.cc) file(GLOB MAP_C_HEADERS src/*.h src/*/*.h) -add_library(mapcpplib ${MAP_CLIB_SOURCES} src/MAP_Types.f90) +add_library(mapcpplib ${MAP_CLIB_SOURCES} src/MAP_Types.f90 src/MAP_Fortran_Types.f90) target_include_directories(mapcpplib PUBLIC $ $ From e3d3166bfa0b37ff3eeb42d75deb1f6df432ec75 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 31 Oct 2019 10:17:39 -0600 Subject: [PATCH 034/377] Added PRPMesh as an HD input for (0,0,0) kinematics This changes how we do some of the mesh mapping to generate the integrated Hydro loads. --- modules/hydrodyn/src/HydroDyn.f90 | 204 ++++++++----------- modules/hydrodyn/src/HydroDyn.txt | 17 +- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 108 +++------- modules/hydrodyn/src/HydroDyn_Types.f90 | 190 ++++++++--------- 4 files changed, 216 insertions(+), 303 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 9a8093ada..055158838 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1403,10 +1403,47 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I END IF END IF - ! Define system output initializations (set up mesh) here: + ! Create the input mesh associated with kinematics of the platform reference point + CALL MeshCreate( BlankMesh = u%PRPMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL MeshPositionNode (u%PRPMesh & + , 1 & + , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & + , ErrStat2 & + , ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! Create the input mesh associated with kinematics of the various WAMIT bodies - + CALL MeshConstructElement ( u%PRPMesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , 1 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL MeshCommit ( u%PRPMesh & + , ErrStat2 & + , ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + u%PRPMesh%RemapFlag = .TRUE. + + ! Create the input mesh associated with kinematics of the various WAMIT bodies CALL MeshCreate( BlankMesh = u%WAMITMesh & ,IOS = COMPONENT_INPUT & ,Nnodes = p%NBody & @@ -1417,80 +1454,58 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ,TranslationVel = .TRUE. & ,RotationVel = .TRUE. & ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE.) - ! Create the node on the mesh - + ,RotationAcc = .TRUE. ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - do iBody = 1, p%NBody - + + do iBody = 1, p%NBody theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) orientation = EulerConstruct(theta) - ! Create the node on the mesh - CALL MeshPositionNode (u%WAMITMesh & - , iBody & + CALL MeshPositionNode (u%WAMITMesh & + , iBody & , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & - , ErrStat2 & - , ErrMsg2 & + , ErrStat2 & + , ErrMsg2 & , orientation ) - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! Create the mesh element - CALL MeshConstructElement ( u%WAMITMesh & + CALL MeshConstructElement ( u%WAMITMesh & , ELEMENT_POINT & , ErrStat2 & , ErrMsg2 & - , iBody & - ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - + , iBody ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end do - CALL MeshCommit ( u%WAMITMesh & + CALL MeshCommit ( u%WAMITMesh & , ErrStat2 & , ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF - ! Output mesh for loads at each WAMIT body - - CALL MeshCopy ( SrcMesh = u%WAMITMesh & - ,DestMesh = y%WAMITMesh & + ! Output mesh for loads at each WAMIT body + CALL MeshCopy ( SrcMesh = u%WAMITMesh & + ,DestMesh = y%WAMITMesh & ,CtrlCode = MESH_SIBLING & ,IOS = COMPONENT_OUTPUT & ,ErrStat = ErrStat2 & ,ErrMess = ErrMsg2 & ,Force = .TRUE. & ,Moment = .TRUE. ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF u%WAMITMesh%RemapFlag = .TRUE. y%WAMITMesh%RemapFlag = .TRUE. - ! Create helper mesh to map all Hydrodynamics loads to the platform reference point to (0,0,0) + ! Create helper mesh to map all Hydrodynamics loads to the platform reference point to (0,0,0) CALL MeshCreate ( BlankMesh = m%AllHdroOrigin & ,IOS = COMPONENT_OUTPUT & ,Nnodes = 1 & @@ -1499,73 +1514,34 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ,Force = .TRUE. & ,Moment = .TRUE. ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%AllHdroOrigin') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - ! Create the node on the mesh - CALL MeshPositionNode (m%AllHdroOrigin & - , 1 & + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%AllHdroOrigin') + + CALL MeshPositionNode (m%AllHdroOrigin & + , 1 & , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & , ErrStat2 & , ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - ! Create the mesh element - CALL MeshConstructElement ( m%AllHdroOrigin & + CALL MeshConstructElement ( m%AllHdroOrigin & , ELEMENT_POINT & , ErrStat2 & , ErrMsg2 & - , 1 & - ) + , 1 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - + CALL MeshCommit ( m%AllHdroOrigin & , ErrStat2 & , ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF m%AllHdroOrigin%RemapFlag = .TRUE. - - ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = m%AllHdroOrigin & - , DestMesh = m%AllHdroOrigin_Position & - , CtrlCode = MESH_SIBLING & - , IOS = COMPONENT_INPUT & - , TranslationDisp = .TRUE. & - , Orientation = .TRUE. & - , TranslationVel = .TRUE. & - , RotationVel = .TRUE. & - , TranslationAcc = .TRUE. & - , RotationAcc = .TRUE. & - , ErrStat = ErrStat2 & - , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - m%AllHdroOrigin_Position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. - - - ! Create the Output file if requested - + + ! Create the Output file if requested p%OutSwtch = InitLocal%OutSwtch p%Delim = '' !p%Morison%Delim = p%Delim ! Need to set this from within Morison to follow framework @@ -1580,11 +1556,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I RETURN END IF - if ( u%WAMITMesh%Committed ) then - call MeshMapCreate( u%WAMITMesh, m%AllHdroOrigin_Position, m%HD_MeshMap%uW_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - end if if ( y%WAMITMesh%Committed ) then - call MeshMapCreate( y%WAMITMesh, m%AllHdroOrigin, m%HD_MeshMap%W_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call MeshMapCreate( y%WAMITMesh, m%AllHdroOrigin, m%HD_MeshMap%W_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if IF ( y%Morison%LumpedMesh%Committed ) THEN CALL MeshMapCreate( y%Morison%LumpedMesh, m%AllHdroOrigin, m%HD_MeshMap%M_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -2095,7 +2068,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Integrate all the mesh loads onto the platfrom reference Point (PRP) at (0,0,0) - m%F_Hydro = CalcLoadsAtWRP( y, u, m%AllHdroOrigin, m%AllHdroOrigin_Position, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) + m%F_Hydro = CalcLoadsAtWRP( y, u, m%AllHdroOrigin, u%PRPMesh, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) @@ -2258,12 +2231,12 @@ END SUBROUTINE HydroDyn_CalcConstrStateResidual !---------------------------------------------------------------------------------------------------------------------------------- -function CalcLoadsAtWRP( y, u, AllHdroOrigin, AllHdroOrigin_Position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) +function CalcLoadsAtWRP( y, u, AllHdroOrigin, PRP_Position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) type(HydroDyn_OutputType), intent(inout) :: y ! Hydrodyn outputs type(HydroDyn_InputType), intent(in ) :: u ! Hydrodyn inputs type(MeshType), intent(inout) :: AllHdroOrigin ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call - type(MeshType), intent(inout) :: AllHdroOrigin_Position ! These are the kinematics associated the PRP at (0,0,0). We pass it in to avoid allocating it at each call + type(MeshType), intent(inout) :: PRP_Position ! These are the kinematics associated the PRP at (0,0,0). We pass it in to avoid allocating it at each call type(MeshType), intent(in ) :: MrsnLumpedMesh_Postion ! These are the kinematics associated with the Morison lumped loads mesh. We pass it in to avoid allocating it at each call type(MeshType), intent(in ) :: MrsnDistribMesh_Position ! These are the kinematics associated with the Morison distributed loads mesh. We pass it in to avoid allocating it at each call type(HD_ModuleMapType), intent(inout) :: MeshMapData ! Mesh mapping data structures @@ -2277,17 +2250,10 @@ function CalcLoadsAtWRP( y, u, AllHdroOrigin, AllHdroOrigin_Position, MrsnLumped CalcLoadsAtWRP = 0.0_ReKi - if ( u%WAMITMesh%Committed ) then - ! Just transfer the loads because the meshes are at the same location (0,0,0) - call Transfer_Point_to_Point( u%WAMITMesh, AllHdroOrigin_Position, MeshMapData%uW_P_2_PRP_P, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') - if (ErrStat >= AbortErrLev) return - end if - if ( y%WAMITMesh%Committed ) then ! Just transfer the loads because the meshes are at the same location (0,0,0) - call Transfer_Point_to_Point( y%WAMITMesh, AllHdroOrigin, MeshMapData%W_P_2_PRP_P, ErrStat2, ErrMsg2, u%WAMITMesh, AllHdroOrigin_Position ) + call Transfer_Point_to_Point( y%WAMITMesh, AllHdroOrigin, MeshMapData%W_P_2_PRP_P, ErrStat2, ErrMsg2, u%WAMITMesh, PRP_Position ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') if (ErrStat >= AbortErrLev) return @@ -2300,7 +2266,7 @@ function CalcLoadsAtWRP( y, u, AllHdroOrigin, AllHdroOrigin_Position, MrsnLumped ! This is viscous drag associate with the WAMIT body and/or filled/flooded forces of the WAMIT body - call Transfer_Point_to_Point( y%Morison%LumpedMesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, AllHdroOrigin_Position ) + call Transfer_Point_to_Point( y%Morison%LumpedMesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, PRP_Position ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') if (ErrStat >= AbortErrLev) return @@ -2311,7 +2277,7 @@ function CalcLoadsAtWRP( y, u, AllHdroOrigin, AllHdroOrigin_Position, MrsnLumped if ( y%Morison%DistribMesh%Committed ) then - call Transfer_Line2_to_Point( y%Morison%DistribMesh, AllHdroOrigin, MeshMapData%M_L_2_PRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, AllHdroOrigin_Position ) + call Transfer_Line2_to_Point( y%Morison%DistribMesh, AllHdroOrigin, MeshMapData%M_L_2_PRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, PRP_Position ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') if (ErrStat >= AbortErrLev) return diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index f7a0b345d..354e10660 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -151,7 +151,6 @@ typedef ^ ^ Morison_Oth # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. typedef ^ MiscVarType MeshType AllHdroOrigin - - - "An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - -typedef ^ ^ MeshType AllHdroOrigin_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ MeshType MrsnLumpedMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ MeshType MrsnDistribMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ HD_ModuleMapType HD_MeshMap - - - @@ -203,17 +202,18 @@ typedef ^ ^ CHARACTER(2 typedef ^ ^ CHARACTER(10) Delim - - - "Delimiter string for outputs, defaults to tab-delimiters" - typedef ^ ^ INTEGER UnOutFile - - - "File unit for the HydroDyn outputs" - typedef ^ ^ INTEGER OutDec - - - "Write every OutDec time steps" - -typedef ^ ^ Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - -typedef ^ ^ R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" - -typedef ^ ^ R8Ki dx {:} - - "vector that determines size of perturbation for x (continuous states)" - -typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix" - +typedef ^ ^ Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ^ R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" - +typedef ^ ^ R8Ki dx {:} - - "vector that determines size of perturbation for x (continuous states)" - +typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix" - # # # ..... Inputs .................................................................................................................... # Define inputs that are contained on the mesh here: # typedef ^ InputType Morison_InputType Morison - - - "Morison module inputs" - -typedef ^ InputType MeshType WAMITMesh - - - "Displacements at the WAMIT reference point in the inertial frame" - +typedef ^ InputType MeshType WAMITMesh - - - "Motions at the WAMIT reference point(s) in the inertial frame" - +typedef ^ InputType MeshType PRPMesh - - - "Motions at the Platform reference point in the inertial frame" - # # # ..... Outputs ................................................................................................................... @@ -222,6 +222,5 @@ typedef ^ OutputType WAMIT_Output typedef ^ OutputType WAMIT2_OutputType WAMIT2 - - - "WAMIT2 module outputs" - typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - -typedef ^ OutputType MeshType WAMITMesh - - - "Point Loads at the WAMIT reference point in the inertial frame" - -#typedef ^ OutputType MeshType AllHdroOrigin - - - "All HD-related loads integrated to the origin, (0,0,0) in the inertial frame" - -typedef ^ ^ ReKi WriteOutput {:} - - "" - +typedef ^ OutputType MeshType WAMITMesh - - - "Point Loads at the WAMIT reference point(s) in the inertial frame" - +typedef ^ ^ ReKi WriteOutput {:} - - "Outputs to be written to the output file(s)" - diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 944ad72e5..7054baf4e 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -329,64 +329,10 @@ PROGRAM HydroDynDriver IF ( u(1)%WAMITMesh%Initialized ) THEN - ! Create a motions mesh a (0,0,0) where all kinematics are specified - call MeshCreate( BlankMesh = RefPtMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = 1 & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE.) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - if (errStat >= AbortErrLev) then - ! Clean up and exit - call HD_DvrCleanup() - end if - - theta = (/ 0.0_R8Ki, 0.0_R8Ki, 0.0_R8Ki /) - dcm = EulerConstruct(theta) - - - ! Create the node on the mesh - - CALL MeshPositionNode (RefPtMesh & - , 1 & - , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & - , ErrStat2 & - , ErrMsg2 & - , dcm ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - - - ! Create the mesh element - CALL MeshConstructElement ( RefPtMesh & - , ELEMENT_POINT & - , ErrStat2 & - , ErrMsg2 & - , 1 & - ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - - CALL MeshCommit ( RefPtMesh & - , ErrStat2 & - , ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'WAMIT_Init') - if (errStat >= AbortErrLev) then - ! Clean up and exit - call HD_DvrCleanup() - end if - - RefPtMesh%RemapFlag = .TRUE. ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] - CALL MeshMapCreate( RefPtMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + CALL MeshMapCreate( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() @@ -395,30 +341,27 @@ PROGRAM HydroDynDriver ! Set any steady-state inputs, once before the time-stepping loop IF ( drvrInitInp%WAMITInputsMod /= 2 ) THEN - - - RefPtMesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) - - + + u(1)%PRPMesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) + ! Compute direction cosine matrix from the rotation angles CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uWAMITInSteady(4), ReKi), REAL(drvrInitInp%uWAMITInSteady(5), ReKi), REAL(drvrInitInp%uWAMITInSteady(6), ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - RefPtMesh%Orientation(:,:,1) = dcm + u(1)%PRPMesh%Orientation(:,:,1) = dcm - RefPtMesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) - RefPtMesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) - RefPtMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) - RefPtMesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) + u(1)%PRPMesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) + u(1)%PRPMesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) + u(1)%PRPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) + u(1)%PRPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) ! Map kinematics to the WAMIT mesh with 1 to NBody nodes - CALL Transfer_Point_to_Point( RefPtMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() end if END IF END IF - - + IF ( drvrInitInp%MorisonInputsMod /= 2 ) THEN IF ( u(1)%Morison%DistribMesh%Initialized ) THEN u(1)%Morison%DistribMesh%TranslationDisp(1,:) = drvrInitInp%uMorisonInSteady(1) @@ -481,11 +424,9 @@ PROGRAM HydroDynDriver IF ( u(1)%WAMITMesh%Initialized ) THEN IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN - - - u(1)%WAMITMesh%TranslationDisp(:,1) = WAMITin(n,2:4) - - + + u(1)%PRPMesh%TranslationDisp(:,1) = WAMITin(n,2:4) + ! Compute direction cosine matrix from the rotation angles IF ( abs(WAMITin(n,5)) > maxAngle ) maxAngle = abs(WAMITin(n,5)) @@ -493,19 +434,23 @@ PROGRAM HydroDynDriver IF ( abs(WAMITin(n,7)) > maxAngle ) maxAngle = abs(WAMITin(n,7)) CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%WAMITMesh%Orientation(:,:,1) = dcm - - - u(1)%WAMITMesh%TranslationVel(:,1) = WAMITin(n,8:10) - u(1)%WAMITMesh%RotationVel(:,1) = WAMITin(n,11:13) - u(1)%WAMITMesh%TranslationAcc(:,1) = WAMITin(n,14:16) - u(1)%WAMITMesh%RotationAcc(:,1) = WAMITin(n,17:19) + u(1)%PRPMesh%Orientation(:,:,1) = dcm + u(1)%PRPMesh%TranslationVel(:,1) = WAMITin(n,8:10) + u(1)%PRPMesh%RotationVel(:,1) = WAMITin(n,11:13) + u(1)%PRPMesh%TranslationAcc(:,1) = WAMITin(n,14:16) + u(1)%PRPMesh%RotationAcc(:,1) = WAMITin(n,17:19) + ! Map kinematics to the WAMIT mesh with 1 to NBody nodes + CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + END IF END IF - IF ( u(1)%Morison%DistribMesh%Initialized ) THEN IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN ! Set the Morison Inputs from a time series input file @@ -513,7 +458,6 @@ PROGRAM HydroDynDriver END IF - ! Calculate outputs at n CALL HydroDyn_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index ef56e7b87..03fc2f4a9 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -169,7 +169,6 @@ MODULE HydroDyn_Types ! ========= HydroDyn_MiscVarType ======= TYPE, PUBLIC :: HydroDyn_MiscVarType TYPE(MeshType) :: AllHdroOrigin !< An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] - TYPE(MeshType) :: AllHdroOrigin_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(MeshType) :: MrsnLumpedMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(MeshType) :: MrsnDistribMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(HD_ModuleMapType) :: HD_MeshMap @@ -229,7 +228,8 @@ MODULE HydroDyn_Types ! ========= HydroDyn_InputType ======= TYPE, PUBLIC :: HydroDyn_InputType TYPE(Morison_InputType) :: Morison !< Morison module inputs [-] - TYPE(MeshType) :: WAMITMesh !< Displacements at the WAMIT reference point in the inertial frame [-] + TYPE(MeshType) :: WAMITMesh !< Motions at the WAMIT reference point(s) in the inertial frame [-] + TYPE(MeshType) :: PRPMesh !< Motions at the Platform reference point in the inertial frame [-] END TYPE HydroDyn_InputType ! ======================= ! ========= HydroDyn_OutputType ======= @@ -238,8 +238,8 @@ MODULE HydroDyn_Types TYPE(WAMIT2_OutputType) :: WAMIT2 !< WAMIT2 module outputs [-] TYPE(Waves2_OutputType) :: Waves2 !< Waves2 module outputs [-] TYPE(Morison_OutputType) :: Morison !< Morison module outputs [-] - TYPE(MeshType) :: WAMITMesh !< Point Loads at the WAMIT reference point in the inertial frame [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] + TYPE(MeshType) :: WAMITMesh !< Point Loads at the WAMIT reference point(s) in the inertial frame [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Outputs to be written to the output file(s) [-] END TYPE HydroDyn_OutputType ! ======================= CONTAINS @@ -5890,9 +5890,6 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs CALL MeshCopy( SrcMiscData%AllHdroOrigin, DstMiscData%AllHdroOrigin, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcMiscData%AllHdroOrigin_position, DstMiscData%AllHdroOrigin_position, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN CALL MeshCopy( SrcMiscData%MrsnLumpedMesh_position, DstMiscData%MrsnLumpedMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -5990,7 +5987,6 @@ SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" CALL MeshDestroy( MiscData%AllHdroOrigin, ErrStat, ErrMsg ) - CALL MeshDestroy( MiscData%AllHdroOrigin_position, ErrStat, ErrMsg ) CALL MeshDestroy( MiscData%MrsnLumpedMesh_position, ErrStat, ErrMsg ) CALL MeshDestroy( MiscData%MrsnDistribMesh_position, ErrStat, ErrMsg ) CALL HydroDyn_Destroyhd_modulemaptype( MiscData%HD_MeshMap, ErrStat, ErrMsg ) @@ -6072,23 +6068,6 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! AllHdroOrigin_position: size of buffers for each call to pack subtype - CALL MeshPack( InData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! AllHdroOrigin_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! AllHdroOrigin_position - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! AllHdroOrigin_position - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! AllHdroOrigin_position - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF Int_BufSz = Int_BufSz + 3 ! MrsnLumpedMesh_position: size of buffers for each call to pack subtype CALL MeshPack( InData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnLumpedMesh_position CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -6317,34 +6296,6 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! AllHdroOrigin_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf @@ -6783,46 +6734,6 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%AllHdroOrigin_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! AllHdroOrigin_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) @@ -8788,6 +8699,9 @@ SUBROUTINE HydroDyn_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, Er CALL MeshCopy( SrcInputData%WAMITMesh, DstInputData%WAMITMesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%PRPMesh, DstInputData%PRPMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE HydroDyn_CopyInput SUBROUTINE HydroDyn_DestroyInput( InputData, ErrStat, ErrMsg ) @@ -8801,6 +8715,7 @@ SUBROUTINE HydroDyn_DestroyInput( InputData, ErrStat, ErrMsg ) ErrMsg = "" CALL Morison_DestroyInput( InputData%Morison, ErrStat, ErrMsg ) CALL MeshDestroy( InputData%WAMITMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%PRPMesh, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyInput SUBROUTINE HydroDyn_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -8873,6 +8788,23 @@ SUBROUTINE HydroDyn_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 3 ! PRPMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%PRPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! PRPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PRPMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PRPMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PRPMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -8956,6 +8888,34 @@ SUBROUTINE HydroDyn_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + CALL MeshPack( InData%PRPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! PRPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE HydroDyn_PackInput SUBROUTINE HydroDyn_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -9070,6 +9030,46 @@ SUBROUTINE HydroDyn_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%PRPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! PRPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE HydroDyn_UnPackInput SUBROUTINE HydroDyn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -9849,6 +9849,8 @@ SUBROUTINE HydroDyn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Er CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp1(u1%WAMITMesh, u2%WAMITMesh, tin, u_out%WAMITMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%PRPMesh, u2%PRPMesh, tin, u_out%PRPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE HydroDyn_Input_ExtrapInterp1 @@ -9905,6 +9907,8 @@ SUBROUTINE HydroDyn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp2(u1%WAMITMesh, u2%WAMITMesh, u3%WAMITMesh, tin, u_out%WAMITMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%PRPMesh, u2%PRPMesh, u3%PRPMesh, tin, u_out%PRPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE HydroDyn_Input_ExtrapInterp2 From 624fc08b6fbb9bedfe6284489450b03ecad9bd23 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 31 Oct 2019 11:05:13 -0600 Subject: [PATCH 035/377] TCF: remove platform force flags to 2nd order from input file. CMakeLists update --- modules/hydrodyn/CMakeLists.txt | 1 - modules/hydrodyn/src/HydroDyn_Input.f90 | 16 ---------- modules/hydrodyn/src/WAMIT2_Types.f90 | 42 ------------------------- 3 files changed, 59 deletions(-) diff --git a/modules/hydrodyn/CMakeLists.txt b/modules/hydrodyn/CMakeLists.txt index 5626c445f..e23123863 100644 --- a/modules/hydrodyn/CMakeLists.txt +++ b/modules/hydrodyn/CMakeLists.txt @@ -42,7 +42,6 @@ set(HYDRODYN_SOURCES src/WAMIT2.f90 src/WAMIT2_Output.f90 src/WAMIT_Interp.f90 - src/WAMIT_Output.f90 src/Waves.f90 src/Waves2.f90 src/Waves2_Output.f90 diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index c6117ccb9..6c9ef3451 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -3270,22 +3270,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) - !------------------------------------------------------------------------------------------------- - ! Second order Forces Flags (WAMIT2 Module) - !------------------------------------------------------------------------------------------------- - ! We don't have separate inputs for the second order force component flags, rather they are taken - ! from the platform section in the input file and copied into the InitInp%WAMIT2 derived type. - ! Within the WAMIT2_Init subroutine, they are reset if necessary (some second order output files - ! from WAMIT don't support all force components -- i.e. the *.8 files). - - InitInp%WAMIT2%PtfmSgF2 = InitInp%PtfmSgF - InitInp%WAMIT2%PtfmSwF2 = InitInp%PtfmSwF - InitInp%WAMIT2%PtfmHvF2 = InitInp%PtfmHvF - InitInp%WAMIT2%PtfmRF2 = InitInp%PtfmRF - InitInp%WAMIT2%PtfmPF2 = InitInp%PtfmPF - InitInp%WAMIT2%PtfmYF2 = InitInp%PtfmYF - - !------------------------------------------------------------------------------------------------- ! Second order Forces due to Waves section (WAMIT2 Module) !------------------------------------------------------------------------------------------------- diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index 6c9e6f82a..f96a58af8 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -57,12 +57,6 @@ MODULE WAMIT2_Types INTEGER(IntKi) :: NumOuts !< [-] INTEGER(IntKi) :: NumOutAll !< [-] INTEGER(IntKi) :: WaveMod !< The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here. [-] - LOGICAL :: PtfmSgF2 !< Supplied by Driver: Platform horizontal surge translation force (flag) [-] - LOGICAL :: PtfmSwF2 !< Supplied by Driver: Platform horizontal sway translation force (flag) [-] - LOGICAL :: PtfmHvF2 !< Supplied by Driver: Platform vertical heave translation force (flag) [-] - LOGICAL :: PtfmRF2 !< Supplied by Driver: Platform roll tilt rotation force (flag) [-] - LOGICAL :: PtfmPF2 !< Supplied by Driver: Platform pitch tilt rotation force (flag) [-] - LOGICAL :: PtfmYF2 !< Supplied by Driver: Platform yaw rotation force (flag) [-] INTEGER(IntKi) :: MnDrift !< Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] INTEGER(IntKi) :: NewmanApp !< Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] INTEGER(IntKi) :: DiffQTF !< Full Difference-Frequency forces computed with full QTF's from WAMIT file: {0: No diff-QTF; [10,11, or 12]: WAMIT file to use} [-] @@ -218,12 +212,6 @@ SUBROUTINE WAMIT2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%NumOuts = SrcInitInputData%NumOuts DstInitInputData%NumOutAll = SrcInitInputData%NumOutAll DstInitInputData%WaveMod = SrcInitInputData%WaveMod - DstInitInputData%PtfmSgF2 = SrcInitInputData%PtfmSgF2 - DstInitInputData%PtfmSwF2 = SrcInitInputData%PtfmSwF2 - DstInitInputData%PtfmHvF2 = SrcInitInputData%PtfmHvF2 - DstInitInputData%PtfmRF2 = SrcInitInputData%PtfmRF2 - DstInitInputData%PtfmPF2 = SrcInitInputData%PtfmPF2 - DstInitInputData%PtfmYF2 = SrcInitInputData%PtfmYF2 DstInitInputData%MnDrift = SrcInitInputData%MnDrift DstInitInputData%NewmanApp = SrcInitInputData%NewmanApp DstInitInputData%DiffQTF = SrcInitInputData%DiffQTF @@ -328,12 +316,6 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! NumOuts Int_BufSz = Int_BufSz + 1 ! NumOutAll Int_BufSz = Int_BufSz + 1 ! WaveMod - Int_BufSz = Int_BufSz + 1 ! PtfmSgF2 - Int_BufSz = Int_BufSz + 1 ! PtfmSwF2 - Int_BufSz = Int_BufSz + 1 ! PtfmHvF2 - Int_BufSz = Int_BufSz + 1 ! PtfmRF2 - Int_BufSz = Int_BufSz + 1 ! PtfmPF2 - Int_BufSz = Int_BufSz + 1 ! PtfmYF2 Int_BufSz = Int_BufSz + 1 ! MnDrift Int_BufSz = Int_BufSz + 1 ! NewmanApp Int_BufSz = Int_BufSz + 1 ! DiffQTF @@ -459,18 +441,6 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%WaveMod Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSgF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSwF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmHvF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmRF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmPF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmYF2 , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MnDrift Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NewmanApp @@ -658,18 +628,6 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%WaveMod = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%PtfmSgF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmSwF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmHvF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmRF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmPF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmYF2 = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 OutData%MnDrift = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NewmanApp = IntKiBuf( Int_Xferred ) From d81b6af56976e4ba668c037c00fe9b572ebcc63b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 10:59:02 -0700 Subject: [PATCH 036/377] FlexSub: Starting to introduce Tables for Cable and Rigid --- modules/subdyn/src/SD_FEM.f90 | 229 +++++++++++++++++++++++----------- modules/subdyn/src/SubDyn.f90 | 5 +- 2 files changed, 156 insertions(+), 78 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index c8a787e2a..05ad0690a 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -40,7 +40,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) ! Indices in Members table - INTEGER(IntKi), PARAMETER :: iMType= 4 ! Index in Members table where the type is stored + INTEGER(IntKi), PARAMETER :: iMType= 6 ! Index in Members table where the type is stored INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored ! Indices in Joints table @@ -62,6 +62,12 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsCol,XPropSetsCol,COSMsCol,CMassCol) + INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic + MODULE PROCEDURE FINDLOCI_ReKi + MODULE PROCEDURE FINDLOCI_IntKi + END INTERFACE + + CONTAINS !> Maps nodes to elements @@ -117,16 +123,20 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable - INTEGER :: I, J, n, Node, Node1, Node2, Prop, Prop1, Prop2 + INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 INTEGER :: OldJointIndex(Init%NJoints) INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempProps(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsBeam(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsCable(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsRigid(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp INTEGER(IntKi) :: eType !< Element Type + INTEGER(IntKi) :: mType !< Member Type + CHARACTER(1024) :: sType !< String for element type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 ErrStat = ErrID_None @@ -163,7 +173,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempProps, MaxNProp, PropSetsCol,'TempProps', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsBeam, MaxNProp, PropSetsCol ,'TempPropsBeam', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') IF ( ErrStat >= AbortErrLev ) THEN @@ -183,59 +195,73 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! Initialize Elems, starting with each member as an element (we'll take NDiv into account later) p%Elems = 0 - DO I = 1, p%NMembers - p%Elems(I, 1) = I ! element/member number (not MemberID) - p%Elems(I, iMType)= Init%Members(I, iMType) ! -!bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. - - ! loop through the JointIDs for this member and find the corresponding indices into the Joints array - DO n = 2,3 ! Members column for JointIDs for nodes 1 and 2 - Node = Init%Members(I, n) ! n=2 or 3 - ! ...... search for index of joint whose JointID matches Node ...... - J = 1 - found = .false. - DO WHILE ( .NOT. found .AND. J <= Init%NJoints ) - IF ( Node == NINT(Init%Joints(J, 1)) ) THEN - p%Elems(I, n) = J ! index of the joint/node n-1 (i.e., nodes 1 and 2) - found = .TRUE. - END IF - J = J + 1 - END DO - IF ( .NOT. found) THEN - CALL Fatal(' Member '//TRIM(Num2LStr(I))//' has JointID'//TRIM(Num2LStr(n-1))//' = '// TRIM(Num2LStr(Node))//' which is not in the node list !') - RETURN - END IF - END DO ! loop through nodes/joints - - ! loop through the PropSetIDs for this member and find the corresponding indices into the Joints array - ! we're setting these two values: - ! p%Elems(I, 5) = property set for node 1 (note this sets the YoungE, ShearG, and MatDens columns for the ENTIRE element) - ! p%Elems(I, 6) = property set for node 2 (note this should be used only for the XsecD and XsecT properties in the element [for a linear distribution from node 1 to node 2 of D and T]) + ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables + !bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. + DO iMem = 1, p%NMembers + ! Column 1 : member index (instead of MemberID) + p%Elems(iMem, 1) = iMem + mType = Init%Members(iMem, iMType) ! + ! Column 2-3: Joint index (instead of JointIDs) + p%Elems(iMem, 1) = iMem ! NOTE: element/member number (not MemberID) + do iNode=2,3 + p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) + if (p%Elems(iMem,iNode)<=0) then + CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list !') + return + endif + enddo + ! Column 4-5: PropIndex 1-2 (instead of PropSetID) DO n=iMProp,iMProp+1 ! Member column for MPropSetID1 and MPropSetID2 - Prop = Init%Members(I, n) ! n=4 or 5 - ! ...... search for index of property set whose PropSetID matches Prop ...... - J = 1 - found = .false. - DO WHILE ( .NOT. found .AND. J <= Init%NPropSets ) - IF ( Prop == NINT(Init%PropSets(J, 1)) ) THEN - p%Elems(I, n) = J ! index of the property set n-3 (i.e., property sets 1 and 2) ! note that previously, this used Prop instead of J, which assumed the list of MemberIDs was sequential, starting at 1. - found = .TRUE. - END IF - J = J + 1 - END DO - IF ( .NOT. found) THEN - CALL Fatal(' Member '//TRIM(Num2LStr(I))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the Member X-Section Property data!') - RETURN - END IF - END DO ! loop through property ids - END DO ! loop through members + + if (mType==idBeam) then + sType='Member x-section property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSets(:,1), Init%Members(iMem, n) ) + else if (mType==idCable) then + sType='Cable property' + p%Elems(iMem,n) = FINDLOCI(Init%CablePropSets(:,1), Init%Members(iMem, n) ) + else if (mType==idRigid) then + sType='Rigid property' + p%Elems(iMem,n) = FINDLOCI(Init%RigidPropSets(:,1), Init%Members(iMem, n) ) + else + ! Should not happen + print*,'Element type unknown',mType + STOP + end if + + if (p%Elems(iMem,n)<=0) then + CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the'//trim(sType)//' table!') + endif + END DO !n, loop through property ids + ! Column 6: member type + p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! + END DO !iMem, loop through members ! Initialize TempMembers TempMembers = p%Elems(1:p%NMembers,:) ! Initialize Temp property set, first user defined sets - TempProps = 0 - TempProps(1:Init%NPropSets, :) = Init%PropSets + TempPropsBeam = 0 + TempPropsBeam(1:Init%NPropSets, :) = Init%PropSets + print*,'TempPropsBeam(:,1:5)' + DO I=1,Init%NPropSets + print*,TempPropsBeam(I,1:5) + enddo + + + TempPropsCable = 0 + TempPropsCable(1:Init%NCablePropSets, :) = Init%CablePropSets + print*,'TempPropsCable(:,:)' + DO I=1,Init%NCablePropSets + print*,TempPropsCable(I,1:4) + enddo + + TempPropsRigid = 0 + TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets + print*,'TempPropsRigid(:,:)' + DO I=1,Init%NRigidPropSets + print*,TempPropsRigid(I,:) + enddo + ! Initialize boundary constraint vector ! Change the node number @@ -321,9 +347,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 - IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN + IF ( ( .not. EqualRealNos(TempPropsBeam(Prop1, 2),TempPropsBeam(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempPropsBeam(Prop1, 3),TempPropsBeam(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempPropsBeam(Prop1, 4),TempPropsBeam(Prop2, 4) ) ) ) THEN CALL Fatal(' Material E,G and rho in a member must be the same') RETURN @@ -341,11 +367,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) dy = ( y2 - y1 )/Init%NDiv dz = ( z2 - z1 )/Init%NDiv - d1 = TempProps(Prop1, 5) - t1 = TempProps(Prop1, 6) + d1 = TempPropsBeam(Prop1, 5) + t1 = TempPropsBeam(Prop1, 6) - d2 = TempProps(Prop2, 5) - t2 = TempProps(Prop2, 6) + d2 = TempPropsBeam(Prop2, 5) + t2 = TempPropsBeam(Prop2, 6) dd = ( d2 - d1 )/Init%NDiv dt = ( t2 - t1 )/Init%NDiv @@ -363,7 +389,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) + CALL SetNewProp(kprop, TempPropsBeam(Prop1, 2), TempPropsBeam(Prop1, 3), TempPropsBeam(Prop1, 4), d1+dd, t1+dt, TempPropsBeam) kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) nprop = kprop @@ -385,9 +411,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3),& - Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, & - TempProps) + CALL SetNewProp(kprop, TempPropsBeam(Prop1, 2), TempPropsBeam(Prop1, 3), Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBeam) kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) nprop = kprop @@ -413,13 +437,14 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! set the props in Init Init%NProp = kprop CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%Props', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - IF (ErrStat >= AbortErrLev ) THEN - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat,ErrMsg,'SD_Discrt'); - CALL CleanUp_Discrt() + IF (ErrStat >= AbortErrLev ) THEN + CALL CleanUp_Discrt() RETURN ENDIF !Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps - Init%Props = TempProps(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + Init%Props = TempPropsBeam(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + print*,'Init%Props' + print*, Init%Props CALL CleanUp_Discrt() @@ -432,13 +457,52 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices - IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) + IF (ALLOCATED(TempPropsBeam)) DEALLOCATE(TempPropsBeam) + IF (ALLOCATED(TempPropsCable)) DEALLOCATE(TempPropsCable) + IF (ALLOCATED(TempPropsRigid)) DEALLOCATE(TempPropsRigid) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) END SUBROUTINE CleanUp_Discrt END SUBROUTINE SD_Discrt + +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_ReKi(Array, Val) result(i) + real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == NINT(Array(i)) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_IntKi(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION + + !------------------------------------------------------------------------------------------------------ !> Set properties of node k SUBROUTINE SetNewNode(k, x, y, z, Init) @@ -510,7 +574,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector INTEGER, DIMENSION(NNE) :: nn ! node number in element INTEGER :: r - INTEGER(IntKi) :: eType + INTEGER(IntKi) :: eType !< Member type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 @@ -561,15 +625,28 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) P1 = p%Elems(I, iMProp ) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) - - E = Init%Props(P1, 2) - G = Init%Props(P1, 3) - rho = Init%Props(P1, 4) - D1 = Init%Props(P1, 5) - t1 = Init%Props(P1, 6) - D2 = Init%Props(P2, 5) - t2 = Init%Props(P2, 6) + if (eType==idBeam) then + E = Init%Props(P1, 2) + G = Init%Props(P1, 3) + rho = Init%Props(P1, 4) + D1 = Init%Props(P1, 5) + t1 = Init%Props(P1, 6) + D2 = Init%Props(P2, 5) + t2 = Init%Props(P2, 6) + else if (eType==idCable) then + print*,'Member',I,'eType',eType,'Ps',P1,P2 + print*,'Init%Props',Init%Props + STOP + else if (eType==idRigid) then + print*,'Member',I,'eType',eType,'Ps',P1,P2 + STOP + else + ! Should not happen + print*,'Element type unknown',eType + STOP + end if + x1 = Init%Nodes(N1, 2) y1 = Init%Nodes(N1, 3) z1 = Init%Nodes(N1, 4) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 29b9c80c9..c0274ba94 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -882,8 +882,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' print*,' Look at the SubDyn API changes to adapt your input files.' print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - Init%Joints(:,5) = idCantilever ! All joints assumed cantilever - Init%Joints(:,6:JointsCol) = 0.0 ! remaining columns set to 0 + Init%Joints(:,iJointType) = idCantilever ! All joints assumed cantilever + Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 else ! New format @@ -939,6 +939,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%Members(:,:) = 0.0_ReKi if (LegacyFormat) then nColumns = 5 + Init%Members(:,iMType) = idBeam ! Important, in legacy all members are beams else nColumns = MembersCol endif From 6eb1daed5e71212b4b5151071d10ad0732eff8c4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 12:57:05 -0700 Subject: [PATCH 037/377] FlexSub: Splitting up reindexing function out of discrt --- modules/subdyn/src/SD_FEM.f90 | 196 ++++++++++++++++++++-------------- 1 file changed, 118 insertions(+), 78 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 05ad0690a..743733795 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -115,85 +115,41 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) ENDDO END SUBROUTINE NodeCon - !---------------------------------------------------------------------------- -SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) +!> +! - Creates Nodes and Elems instead of Joints and Members arrays +! - Removes the notion of "ID" and use Index instead +SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) ::Init TYPE(SD_ParameterType), INTENT(INOUT) ::p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 - INTEGER :: OldJointIndex(Init%NJoints) INTEGER :: NNE ! number of nodes per element - INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempPropsBeam(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsCable(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsRigid(:, :) - INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) - INTEGER :: knode, kelem, kprop, nprop - REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp - INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: mType !< Member Type CHARACTER(1024) :: sType !< String for element type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" - - ! number of nodes per element - IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN - NNE = 2 - ELSE - CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') - RETURN - ENDIF - - Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers ! Calculate total number of nodes according to divisions - Init%NElem = p%NMembers*Init%NDiv ! Total number of element - MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) - - ! Calculate total number of nodes and elements according to element types - ! for 3-node or 4-node beam elements - Init%NNode = Init%NNode + (NNE - 2)*Init%NElem - !bjj: replaced with max value instead of NNE: Init%MembersCol = Init%MembersCol + (NNE - 2) - - ! check the number of interior modes - IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) - RETURN - ENDIF - - CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - - CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') ! for two-node element only, otherwise the number of nodes in one element is different - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') !!!! RRD: THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED - CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - - CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsBeam, MaxNProp, PropSetsCol ,'TempPropsBeam', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp_Discrt() - RETURN - ENDIF + ! TODO See if Elems is actually used elsewhere - ! Initialize Nodes + CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initialize Nodes Init%Nodes = 0 DO I = 1,Init%NJoints - OldJointIndex(I) = Init%Joints(I, 1) Init%Nodes(I, 1) = I Init%Nodes(I, 2) = Init%Joints(I, 2) Init%Nodes(I, 3) = Init%Joints(I, 3) Init%Nodes(I, 4) = Init%Joints(I, 4) ENDDO - - ! Initialize Elems, starting with each member as an element (we'll take NDiv into account later) + + ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) p%Elems = 0 ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables !bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. @@ -210,8 +166,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) return endif enddo - ! Column 4-5: PropIndex 1-2 (instead of PropSetID) - DO n=iMProp,iMProp+1 ! Member column for MPropSetID1 and MPropSetID2 + ! Column 4-5: PropIndex 1-2 (instead of PropSetID1&2) + ! NOTE: this index has different meaning depending on the member type ! + DO n=iMProp,iMProp+1 if (mType==idBeam) then sType='Member x-section property' @@ -235,28 +192,106 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! Column 6: member type p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! END DO !iMem, loop through members + + ! TODO in theory, we shouldn't need these anymore + ! deallocate(Init%Members) + ! deallocate(Init%Joints) +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems'); + END SUBROUTINE Fatal +END SUBROUTINE SD_ReIndex_CreateNodesAndElems + +!---------------------------------------------------------------------------- +SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) ::Init + TYPE(SD_ParameterType), INTENT(INOUT) ::p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variable + INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 + INTEGER :: NNE ! number of nodes per element + INTEGER :: MaxNProp + REAL(ReKi), ALLOCATABLE :: TempPropsBeams(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsCable(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsRigid(:, :) + INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) + INTEGER :: knode, kelem, kprop, nprop + REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 + LOGICAL :: found, CreateNewProp + INTEGER(IntKi) :: eType !< Element Type + INTEGER(IntKi) :: mType !< Member Type + CHARACTER(1024) :: sType !< String for element type + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! number of nodes per element + IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN + NNE = 2 + ELSE + CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') + RETURN + ENDIF + + Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers ! Calculate total number of nodes according to divisions + Init%NElem = p%NMembers*Init%NDiv ! Total number of element + MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + + ! Calculate total number of nodes and elements according to element types + ! for 3-node or 4-node beam elements + Init%NNode = Init%NNode + (NNE - 2)*Init%NElem + !bjj: replaced with max value instead of NNE: Init%MembersCol = Init%MembersCol + (NNE - 2) + + ! check the number of interior modes + IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) + RETURN + ENDIF + + CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') ! for two-node element only, otherwise the number of nodes in one element is different + CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') !!!! RRD: THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED + CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + + CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsBeams, MaxNProp, PropSetsCol ,'TempPropsBeams', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp_Discrt() + RETURN + ENDIF + + ! --- + CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return ! Initialize TempMembers TempMembers = p%Elems(1:p%NMembers,:) ! Initialize Temp property set, first user defined sets - TempPropsBeam = 0 - TempPropsBeam(1:Init%NPropSets, :) = Init%PropSets - print*,'TempPropsBeam(:,1:5)' - DO I=1,Init%NPropSets - print*,TempPropsBeam(I,1:5) - enddo - - + TempPropsBeams = 0 TempPropsCable = 0 + TempPropsRigid = 0 + TempPropsBeams(1:Init%NPropSets, :) = Init%PropSets TempPropsCable(1:Init%NCablePropSets, :) = Init%CablePropSets + TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets + print*,'TempPropsBeams(:,1:5)' + DO I=1,Init%NPropSets + print*,TempPropsBeams(I,1:5) + enddo print*,'TempPropsCable(:,:)' DO I=1,Init%NCablePropSets print*,TempPropsCable(I,1:4) enddo - TempPropsRigid = 0 - TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets print*,'TempPropsRigid(:,:)' DO I=1,Init%NRigidPropSets print*,TempPropsRigid(I,:) @@ -347,9 +382,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 - IF ( ( .not. EqualRealNos(TempPropsBeam(Prop1, 2),TempPropsBeam(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempPropsBeam(Prop1, 3),TempPropsBeam(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempPropsBeam(Prop1, 4),TempPropsBeam(Prop2, 4) ) ) ) THEN + IF ( ( .not. EqualRealNos(TempPropsBeams(Prop1, 2),TempPropsBeams(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempPropsBeams(Prop1, 3),TempPropsBeams(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempPropsBeams(Prop1, 4),TempPropsBeams(Prop2, 4) ) ) ) THEN CALL Fatal(' Material E,G and rho in a member must be the same') RETURN @@ -367,11 +402,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) dy = ( y2 - y1 )/Init%NDiv dz = ( z2 - z1 )/Init%NDiv - d1 = TempPropsBeam(Prop1, 5) - t1 = TempPropsBeam(Prop1, 6) + d1 = TempPropsBeams(Prop1, 5) + t1 = TempPropsBeams(Prop1, 6) - d2 = TempPropsBeam(Prop2, 5) - t2 = TempPropsBeam(Prop2, 6) + d2 = TempPropsBeams(Prop2, 5) + t2 = TempPropsBeams(Prop2, 6) dd = ( d2 - d1 )/Init%NDiv dt = ( t2 - t1 )/Init%NDiv @@ -389,7 +424,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsBeam(Prop1, 2), TempPropsBeam(Prop1, 3), TempPropsBeam(Prop1, 4), d1+dd, t1+dt, TempPropsBeam) + CALL SetNewProp(kprop, TempPropsBeams(Prop1, 2), TempPropsBeams(Prop1, 3), TempPropsBeams(Prop1, 4), d1+dd, t1+dt, TempPropsBeams) kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) nprop = kprop @@ -411,7 +446,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsBeam(Prop1, 2), TempPropsBeam(Prop1, 3), Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBeam) + CALL SetNewProp(kprop, TempPropsBeams(Prop1, 2), TempPropsBeams(Prop1, 3), Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBeams) kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) nprop = kprop @@ -442,13 +477,18 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF !Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps - Init%Props = TempPropsBeam(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + Init%Props = TempPropsBeams(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 print*,'Init%Props' print*, Init%Props CALL CleanUp_Discrt() CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) CHARACTER(len=*), intent(in) :: ErrMsg_in CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); @@ -457,7 +497,7 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices - IF (ALLOCATED(TempPropsBeam)) DEALLOCATE(TempPropsBeam) + IF (ALLOCATED(TempPropsBeams)) DEALLOCATE(TempPropsBeams) IF (ALLOCATED(TempPropsCable)) DEALLOCATE(TempPropsCable) IF (ALLOCATED(TempPropsRigid)) DEALLOCATE(TempPropsRigid) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) From c755a88f95012a5b98a738931028596384f59ad3 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 18:13:52 -0700 Subject: [PATCH 038/377] FlexSub: Avoiding alloc for ndiv=1 --- modules/subdyn/src/SD_FEM.f90 | 95 ++++++++++++++++------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 743733795..f7571c9b6 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -240,14 +240,13 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF - Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers ! Calculate total number of nodes according to divisions - Init%NElem = p%NMembers*Init%NDiv ! Total number of element - MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) - - ! Calculate total number of nodes and elements according to element types - ! for 3-node or 4-node beam elements + ! Total number of element + Init%NElem = p%NMembers*Init%NDiv + ! Total number of nodes - Depends on division and number of nodes per element + Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers Init%NNode = Init%NNode + (NNE - 2)*Init%NElem !bjj: replaced with max value instead of NNE: Init%MembersCol = Init%MembersCol + (NNE - 2) + MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) ! check the number of interior modes IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN @@ -259,10 +258,6 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') !!!! RRD: THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsBeams, MaxNProp, PropSetsCol ,'TempPropsBeams', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') IF ( ErrStat >= AbortErrLev ) THEN @@ -270,32 +265,10 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF - ! --- + ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays + ! NOTE: need NNode and NElem CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - ! Initialize TempMembers - TempMembers = p%Elems(1:p%NMembers,:) - - ! Initialize Temp property set, first user defined sets - TempPropsBeams = 0 - TempPropsCable = 0 - TempPropsRigid = 0 - TempPropsBeams(1:Init%NPropSets, :) = Init%PropSets - TempPropsCable(1:Init%NCablePropSets, :) = Init%CablePropSets - TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets - print*,'TempPropsBeams(:,1:5)' - DO I=1,Init%NPropSets - print*,TempPropsBeams(I,1:5) - enddo - print*,'TempPropsCable(:,:)' - DO I=1,Init%NCablePropSets - print*,TempPropsCable(I,1:4) - enddo - - print*,'TempPropsRigid(:,:)' - DO I=1,Init%NRigidPropSets - print*,TempPropsRigid(I,:) - enddo ! Initialize boundary constraint vector @@ -358,13 +331,33 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDDO ENDDO - ! discretize structure according to NDiv - knode = Init%NJoints - kelem = 0 - kprop = Init%NPropSets Init%MemberNodes = 0 - - IF (Init%NDiv > 1) THEN + ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) + if (Init%NDiv==1) then + ! NDiv = 1 + Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) + Init%NProp = Init%NPropSets + + else if (Init%NDiv > 1) then + + ! Initialize Temp arrays that will contain user inputs + input from the subdivided members + CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsBeams, MaxNProp, PropSetsCol ,'TempPropsBeams', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') + TempMembers = p%Elems(1:p%NMembers,:) + TempPropsBeams = 0 + TempPropsCable = 0 + TempPropsRigid = 0 + TempPropsBeams(1:Init%NPropSets, :) = Init%PropSets + TempPropsCable(1:Init%NCablePropSets, :) = Init%CablePropSets + TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets + + ! discretize structure according to NDiv + kelem = 0 + knode = Init%NJoints + kprop = Init%NPropSets + print*,'>>> NDIV>1' DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information ! create new node Node1 = TempMembers(I, 2) @@ -443,8 +436,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) IF ( CreateNewProp ) THEN ! create a new property set - ! k, E, G, rho, d, t, Init - + ! k, E, G, rho, d, t, Init kprop = kprop + 1 CALL SetNewProp(kprop, TempPropsBeams(Prop1, 2), TempPropsBeams(Prop1, 3), Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBeams) kelem = kelem + 1 @@ -452,32 +444,29 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) nprop = kprop ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) - + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) ENDIF ENDDO ! the element connect to Node2 kelem = kelem + 1 CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) - ENDDO ! loop over all members - - ELSE ! NDiv = 1 - - Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) - + ! + Init%NProp = kprop ENDIF ! if NDiv is greater than 1 ! set the props in Init - Init%NProp = kprop CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%Props', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') IF (ErrStat >= AbortErrLev ) THEN CALL CleanUp_Discrt() RETURN ENDIF - !Init%Props(1:kprop, 1:Init%PropSetsCol) = TempProps - Init%Props = TempPropsBeams(1:Init%NProp, :) !!RRD fixed it on 1/23/14 to account for NDIV=1 + if (Init%NDiv==1) then + Init%Props(1:Init%NProp,1 :PropSetsCol) = Init%PropSets(1:Init%NProp, 1:PropSetsCol) + else if (Init%NDiv>1) then + Init%Props = TempPropsBeams(1:Init%NProp, 1:PropSetsCol) + endif print*,'Init%Props' print*, Init%Props From f635ddf84bd1b298e9c371e97f67877fea6f9db6 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 20:13:34 -0700 Subject: [PATCH 039/377] FlexSub: Introducing B,C,R for Beams Cable and Rigid --- Makefile | 49 +++ modules/subdyn/src/SD_FEM.f90 | 126 +++---- modules/subdyn/src/SubDyn.f90 | 50 +-- modules/subdyn/src/SubDyn_Registry.txt | 24 +- modules/subdyn/src/SubDyn_Types.f90 | 484 ++++++++++++++++--------- 5 files changed, 460 insertions(+), 273 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..646fb6813 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +MAKE=make --no-print-directory +MAKE_ARGS=VERBOSE=1 +CMAKE_ARGS=-DCMAKE_BUILD_TYPE=DEBUG -DDOUBLE_PRECISION:BOOL=OFF -DGENERATE_TYPES:BOOL=ON +suffix=-single-db +ifeq ($(OS),Windows_NT) + OS=Windows + suffix=-nmake$(suffix) + CMAKE_ARGS=$(CMAKE_ARGS) -G"NMake Makefiles" + MAKE=nmake + RMDIR=rmdir /S /Q + LIBEXT='.dll' + EXEEXT='.exe' +else + OS=$(shell uname -s) + ifeq ($(OS),Linux) + # ISSUE WITH CMAKE PICKING UP F95 TODO + FC=/usr/bin/gfortran +# FC=/usr/bin/gfortran-7 + LIBEXT='.so' + LIBPRE='lib' + else ifeq ($(OS),Darwin) + LIBEXT='.dylib' + endif + RMDIR=rm -rf +endif +BUILD_DIR=build$(suffix) +TEST_DIR=../tcf-test + + +all: compile copy test + + +$(BUILD_DIR): + @echo "------------------------------------------------------------" + mkdir $(BUILD_DIR) + +compile: $(BUILD_DIR) + @echo "------------------------------------------------------------" + cd $(BUILD_DIR) && cmake $(CMAKE_ARGS) .. && $(MAKE) $(MAKE_ARGS) + +clean: + cd $(BUILD_DIR) && $(MAKE) clean + +copy: + cp $(BUILD_DIR)/glue-codes/openfast/openfast$(EXEEXT) $(TEST_DIR) + +test: + cd $(TEST_DIR) && $(MAKE) + diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index f7571c9b6..19cee298f 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -33,10 +33,10 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) - INTEGER(IntKi), PARAMETER :: PropSetsCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs - INTEGER(IntKi), PARAMETER :: XPropSetsCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) - INTEGER(IntKi), PARAMETER :: CablePropSetsCol= 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) - INTEGER(IntKi), PARAMETER :: RigidPropSetsCol= 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) + INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs + INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) + INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) + INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) ! Indices in Members table @@ -60,7 +60,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idCable = 2 INTEGER(IntKi), PARAMETER :: idRigid = 3 - INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsCol,XPropSetsCol,COSMsCol,CMassCol) + INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi @@ -172,13 +172,13 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) if (mType==idBeam) then sType='Member x-section property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSets(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) else if (mType==idCable) then sType='Cable property' - p%Elems(iMem,n) = FINDLOCI(Init%CablePropSets(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) else if (mType==idRigid) then sType='Rigid property' - p%Elems(iMem,n) = FINDLOCI(Init%RigidPropSets(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) else ! Should not happen print*,'Element type unknown',mType @@ -217,9 +217,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempPropsBeams(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsCable(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsRigid(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsB(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsC(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsR(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 @@ -246,7 +246,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers Init%NNode = Init%NNode + (NNE - 2)*Init%NElem !bjj: replaced with max value instead of NNE: Init%MembersCol = Init%MembersCol + (NNE - 2) - MaxNProp = Init%NPropSets + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) ! check the number of interior modes IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN @@ -254,28 +254,20 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF - CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') ! for two-node element only, otherwise the number of nodes in one element is different - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') !!!! RRD: THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED - CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - - CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp_Discrt() - RETURN - ENDIF + CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different + CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return ! THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED + CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); if(Failed()) return ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays ! NOTE: need NNode and NElem CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - - ! Initialize boundary constraint vector ! Change the node number ! Allocate array that will be p%Reacts renumbered and ordered so that ID does not play a role, just ordinal position number will count -RRD Init%BCs = 0 - TempReacts=0 + TempReacts(1:p%NReact,1:ReactCol)=0 DO I = 1, p%NReact Node1 = p%Reacts(I, 1); !NODE ID TempReacts(I,2:ReactCol)=p%Reacts(I, 2:ReactCol) !Assign all the appropriate fixity to the new Reacts array -RRD @@ -336,27 +328,27 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) if (Init%NDiv==1) then ! NDiv = 1 Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) - Init%NProp = Init%NPropSets + Init%NPropB = Init%NPropSetsB else if (Init%NDiv > 1) then ! Initialize Temp arrays that will contain user inputs + input from the subdivided members - CALL AllocAry(TempMembers, p%NMembers, MembersCol, 'TempMembers', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsBeams, MaxNProp, PropSetsCol ,'TempPropsBeams', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsCable, MaxNProp, CablePropSetsCol,'TempPropsCable', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - CALL AllocAry(TempPropsRigid, MaxNProp, RigidPropSetsCol,'TempPropsRigid', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - TempMembers = p%Elems(1:p%NMembers,:) - TempPropsBeams = 0 - TempPropsCable = 0 - TempPropsRigid = 0 - TempPropsBeams(1:Init%NPropSets, :) = Init%PropSets - TempPropsCable(1:Init%NCablePropSets, :) = Init%CablePropSets - TempPropsRigid(1:Init%NRigidPropSets, :) = Init%RigidPropSets + CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempPropsB, MaxNProp, PropSetsBCol,'TempPropsB', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempPropsC, MaxNProp, PropSetsCCol,'TempPropsC', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempPropsR, MaxNProp, PropSetsRCol,'TempPropsR', ErrStat2, ErrMsg2); if(Failed()) return + TempPropsB = 0 + TempPropsC = 0 + TempPropsR = 0 + TempMembers = p%Elems(1:p%NMembers,:) + TempPropsB(1:Init%NPropSetsB, :) = Init%PropSetsB + TempPropsC(1:Init%NPropSetsC, :) = Init%PropSetsC + TempPropsR(1:Init%NPropSetsR, :) = Init%PropSetsR ! discretize structure according to NDiv kelem = 0 knode = Init%NJoints - kprop = Init%NPropSets + kprop = Init%NPropSetsB print*,'>>> NDIV>1' DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information ! create new node @@ -375,9 +367,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 - IF ( ( .not. EqualRealNos(TempPropsBeams(Prop1, 2),TempPropsBeams(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempPropsBeams(Prop1, 3),TempPropsBeams(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempPropsBeams(Prop1, 4),TempPropsBeams(Prop2, 4) ) ) ) THEN + IF ( ( .not. EqualRealNos(TempPropsB(Prop1, 2),TempPropsB(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 3),TempPropsB(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 4),TempPropsB(Prop2, 4) ) ) ) THEN CALL Fatal(' Material E,G and rho in a member must be the same') RETURN @@ -395,11 +387,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) dy = ( y2 - y1 )/Init%NDiv dz = ( z2 - z1 )/Init%NDiv - d1 = TempPropsBeams(Prop1, 5) - t1 = TempPropsBeams(Prop1, 6) + d1 = TempPropsB(Prop1, 5) + t1 = TempPropsB(Prop1, 6) - d2 = TempPropsBeams(Prop2, 5) - t2 = TempPropsBeams(Prop2, 6) + d2 = TempPropsB(Prop2, 5) + t2 = TempPropsB(Prop2, 6) dd = ( d2 - d1 )/Init%NDiv dt = ( t2 - t1 )/Init%NDiv @@ -417,7 +409,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsBeams(Prop1, 2), TempPropsBeams(Prop1, 3), TempPropsBeams(Prop1, 4), d1+dd, t1+dt, TempPropsBeams) + CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), TempPropsB(Prop1, 4), d1+dd, t1+dt, TempPropsB) kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) nprop = kprop @@ -438,7 +430,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsBeams(Prop1, 2), TempPropsBeams(Prop1, 3), Init%PropSets(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBeams) + CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsB) kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) nprop = kprop @@ -453,22 +445,20 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) ENDDO ! loop over all members ! - Init%NProp = kprop + Init%NPropB = kprop ENDIF ! if NDiv is greater than 1 ! set the props in Init - CALL AllocAry(Init%Props, Init%NProp, PropSetsCol, 'Init%Props', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_Discrt') - IF (ErrStat >= AbortErrLev ) THEN - CALL CleanUp_Discrt() - RETURN - ENDIF + CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return + if (Init%NDiv==1) then - Init%Props(1:Init%NProp,1 :PropSetsCol) = Init%PropSets(1:Init%NProp, 1:PropSetsCol) + Init%PropsB(1:Init%NPropB,1 :PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) else if (Init%NDiv>1) then - Init%Props = TempPropsBeams(1:Init%NProp, 1:PropSetsCol) + Init%PropsB = TempPropsB(1:Init%NPropB, 1:PropSetsBCol) endif - print*,'Init%Props' - print*, Init%Props + + print*,'Init%PropsB' + print*, Init%PropsB CALL CleanUp_Discrt() @@ -476,6 +466,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') Failed = ErrStat >= AbortErrLev + if (Failed) CALL CleanUp_Discrt() END FUNCTION Failed SUBROUTINE Fatal(ErrMsg_in) @@ -486,9 +477,9 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices - IF (ALLOCATED(TempPropsBeams)) DEALLOCATE(TempPropsBeams) - IF (ALLOCATED(TempPropsCable)) DEALLOCATE(TempPropsCable) - IF (ALLOCATED(TempPropsRigid)) DEALLOCATE(TempPropsRigid) + IF (ALLOCATED(TempPropsB)) DEALLOCATE(TempPropsB) + IF (ALLOCATED(TempPropsC)) DEALLOCATE(TempPropsC) + IF (ALLOCATED(TempPropsR)) DEALLOCATE(TempPropsR) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) END SUBROUTINE CleanUp_Discrt @@ -655,16 +646,15 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) if (eType==idBeam) then - E = Init%Props(P1, 2) - G = Init%Props(P1, 3) - rho = Init%Props(P1, 4) - D1 = Init%Props(P1, 5) - t1 = Init%Props(P1, 6) - D2 = Init%Props(P2, 5) - t2 = Init%Props(P2, 6) + E = Init%PropsB(P1, 2) + G = Init%PropsB(P1, 3) + rho = Init%PropsB(P1, 4) + D1 = Init%PropsB(P1, 5) + t1 = Init%PropsB(P1, 6) + D2 = Init%PropsB(P2, 5) + t2 = Init%PropsB(P2, 6) else if (eType==idCable) then print*,'Member',I,'eType',eType,'Ps',P1,P2 - print*,'Init%Props',Init%Props STOP else if (eType==idRigid) then diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index c0274ba94..fa608b864 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -951,48 +951,48 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) !------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ CALL ReadCom ( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSets, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsB, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%PropSets, Init%NPropSets, PropSetsCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return -DO I = 1, Init%NPropSets - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return - Init%PropSets(I,:) = Dummy_ReAry(1:PropSetsCol) +CALL AllocAry(Init%PropSetsB, Init%NPropSetsB, PropSetsBCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSetsB + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSetsB(I,:) = Dummy_ReAry(1:PropSetsBCol) ENDDO -IF (Check( Init%NPropSets < 1 , 'NPropSets must be >0')) return +IF (Check( Init%NPropSetsB < 1 , 'NPropSets must be >0')) return !------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ CALL ReadCom ( UnIn, SDInputFile, 'Member X-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NXPropSets, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsX, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%XPropSets, Init%NXPropSets, XPropSetsCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return -DO I = 1, Init%NXPropSets - CALL ReadAry( UnIn, SDInputFile, Init%XPropSets(I,:), XPropSetsCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSetsX, Init%NPropSetsX, PropSetsXCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NPropSetsX + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsX(I,:), PropSetsXCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ENDDO -IF (Check( Init%NXPropSets < 0, 'NXPropSets must be >=0')) return +IF (Check( Init%NPropSetsX < 0, 'NXPropSets must be >=0')) return if (.not. LegacyFormat) then !-------------------------- CABLE PROPERTIES ------------------------------------- CALL ReadCom ( UnIn, SDInputFile, 'Cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadIVar ( UnIn, SDInputFile, Init%NCablePropSets, 'NCablePropSets', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsC, 'NPropSetsC', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL AllocAry(Init%CablePropSets, Init%NCablePropSets, CablePropSetsCol, 'CablePropSets', ErrStat2, ErrMsg2); if(Failed()) return - DO I = 1, Init%NCablePropSets - CALL ReadAry( UnIn, SDInputFile, Init%CablePropSets(I,:), CablePropSetsCol, 'CablePropSets', 'CablePropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NPropSetsC + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsC(I,:), PropSetsCCol, 'PropSetsC', 'PropSetsC ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ENDDO - IF (Check( Init%NCablePropSets < 0, 'NCablePropSets must be >=0')) return + IF (Check( Init%NPropSetsC < 0, 'NPropSetsCable must be >=0')) return !----------------------- RIGID LINK PROPERTIES ------------------------------------ CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadIVar ( UnIn, SDInputFile, Init%NRigidPropSets, 'NRigidPropSets', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsR, 'NPropSetsR', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL AllocAry(Init%RigidPropSets, Init%NRigidPropSets, RigidPropSetsCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return - DO I = 1, Init%NRigidPropSets - CALL ReadAry( UnIn, SDInputFile, Init%RigidPropSets(I,:), RigidPropSetsCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NPropSetsR + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsR(I,:), PropSetsRCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ENDDO - IF (Check( Init%NRigidPropSets < 0, 'NRigidPropSets must be >=0')) return + IF (Check( Init%NPropSetsR < 0, 'NPropSetsRigid must be >=0')) return endif !---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ @@ -2631,9 +2631,9 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(I8,5(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NProp + WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NPropB WRITE(UnSum, '(A8,5(A15))') 'Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' - WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%Props(i, 1)), (Init%Props(i, j), j = 2, 6), i = 1, Init%NProp) + WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%NReact*6 @@ -2662,8 +2662,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) mlength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) IF (ErrStat .EQ. ErrID_None) THEN WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & - MemberMass(Init%PropSets(propids(1),4),Init%PropSets(propids(1),5),Init%PropSets(propids(1),6), & - Init%PropSets(propids(2),4),Init%PropSets(propids(2),5),Init%PropSets(propids(2),6), mlength, .TRUE.), & + MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & + Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mlength, .TRUE.), & ' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) ELSE RETURN diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index a31dbe7be..3c97a6318 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -71,10 +71,10 @@ typedef ^ ^ ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" typedef ^ ^ ReKi g - - - "Gravity acceleration" typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" -typedef ^ ^ INTEGER NPropSets - - - "Number of property sets" -typedef ^ ^ INTEGER NXPropSets - - - "Number of extended property sets" -typedef ^ ^ INTEGER NCablePropSets - - - "Number of property sets for cables" -typedef ^ ^ INTEGER NRigidPropSets - - - "Number of property sets for rigid links" +typedef ^ ^ INTEGER NPropSetsX - - - "Number of extended property sets" +typedef ^ ^ INTEGER NPropSetsB - - - "Number of property sets for beams" +typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" +typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" typedef ^ ^ INTEGER NInterf - - - "Number of joints attached to transition piece" typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" @@ -82,10 +82,10 @@ typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" -typedef ^ ^ ReKi PropSets {:}{:} - - "Property sets number and values" -typedef ^ ^ ReKi XPropSets {:}{:} - - "Extended property sets" -typedef ^ ^ ReKi CablePropSets {:}{:} - - "Property ID and values for cables" -typedef ^ ^ ReKi RigidPropSets {:}{:} - - "Property ID and values for rigid link" +typedef ^ ^ ReKi PropSetsB {:}{:} - - "Property sets number and values" +typedef ^ ^ ReKi PropSetsC {:}{:} - - "Property ID and values for cables" +typedef ^ ^ ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" +typedef ^ ^ ReKi PropSetsX {:}{:} - - "Extended property sets" typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" @@ -97,10 +97,14 @@ typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJ #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ typedef ^ ^ INTEGER NNode - - - "Total number of nodes" typedef ^ ^ INTEGER NElem - - - "Total number of elements" -typedef ^ ^ INTEGER NProp - - - "Total number of property sets" +typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" +typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" +typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" typedef ^ ^ INTEGER TDOF - - - "Total degree of freedom" typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" -typedef ^ ^ ReKi Props {:}{:} - - "Property sets and values" +typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" +typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" +typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" typedef ^ ^ ReKi F {:} - - "System force vector" N diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a56a837f6..4cdfcf6e1 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -110,10 +110,10 @@ MODULE SubDyn_Types REAL(ReKi) :: g !< Gravity acceleration [-] REAL(DbKi) :: DT !< Time step from Glue Code [seconds] INTEGER(IntKi) :: NJoints !< Number of joints of the sub structure [-] - INTEGER(IntKi) :: NPropSets !< Number of property sets [-] - INTEGER(IntKi) :: NXPropSets !< Number of extended property sets [-] - INTEGER(IntKi) :: NCablePropSets !< Number of property sets for cables [-] - INTEGER(IntKi) :: NRigidPropSets !< Number of property sets for rigid links [-] + INTEGER(IntKi) :: NPropSetsX !< Number of extended property sets [-] + INTEGER(IntKi) :: NPropSetsB !< Number of property sets for beams [-] + INTEGER(IntKi) :: NPropSetsC !< Number of property sets for cables [-] + INTEGER(IntKi) :: NPropSetsR !< Number of property sets for rigid links [-] INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] @@ -121,10 +121,10 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NDiv !< Number of divisions for each member [-] LOGICAL :: CBMod !< Perform C-B flag [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSets !< Property sets number and values [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: XPropSets !< Extended property sets [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CablePropSets !< Property ID and values for cables [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: RigidPropSets !< Property ID and values for rigid link [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsB !< Property sets number and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsC !< Property ID and values for cables [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsR !< Property ID and values for rigid link [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsX !< Extended property sets [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] @@ -135,10 +135,14 @@ MODULE SubDyn_Types LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] INTEGER(IntKi) :: NNode !< Total number of nodes [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] - INTEGER(IntKi) :: NProp !< Total number of property sets [-] + INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] + INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] + INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] INTEGER(IntKi) :: TDOF !< Total degree of freedom [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Props !< Property sets and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] @@ -2567,10 +2571,10 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%g = SrcInitTypeData%g DstInitTypeData%DT = SrcInitTypeData%DT DstInitTypeData%NJoints = SrcInitTypeData%NJoints - DstInitTypeData%NPropSets = SrcInitTypeData%NPropSets - DstInitTypeData%NXPropSets = SrcInitTypeData%NXPropSets - DstInitTypeData%NCablePropSets = SrcInitTypeData%NCablePropSets - DstInitTypeData%NRigidPropSets = SrcInitTypeData%NRigidPropSets + DstInitTypeData%NPropSetsX = SrcInitTypeData%NPropSetsX + DstInitTypeData%NPropSetsB = SrcInitTypeData%NPropSetsB + DstInitTypeData%NPropSetsC = SrcInitTypeData%NPropSetsC + DstInitTypeData%NPropSetsR = SrcInitTypeData%NPropSetsR DstInitTypeData%NInterf = SrcInitTypeData%NInterf DstInitTypeData%NCMass = SrcInitTypeData%NCMass DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs @@ -2591,61 +2595,61 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%Joints = SrcInitTypeData%Joints ENDIF -IF (ALLOCATED(SrcInitTypeData%PropSets)) THEN - i1_l = LBOUND(SrcInitTypeData%PropSets,1) - i1_u = UBOUND(SrcInitTypeData%PropSets,1) - i2_l = LBOUND(SrcInitTypeData%PropSets,2) - i2_u = UBOUND(SrcInitTypeData%PropSets,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropSets)) THEN - ALLOCATE(DstInitTypeData%PropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitTypeData%PropSetsB)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsB,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsB,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsB,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsB,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsB)) THEN + ALLOCATE(DstInitTypeData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsB.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitTypeData%PropSets = SrcInitTypeData%PropSets + DstInitTypeData%PropSetsB = SrcInitTypeData%PropSetsB ENDIF -IF (ALLOCATED(SrcInitTypeData%XPropSets)) THEN - i1_l = LBOUND(SrcInitTypeData%XPropSets,1) - i1_u = UBOUND(SrcInitTypeData%XPropSets,1) - i2_l = LBOUND(SrcInitTypeData%XPropSets,2) - i2_u = UBOUND(SrcInitTypeData%XPropSets,2) - IF (.NOT. ALLOCATED(DstInitTypeData%XPropSets)) THEN - ALLOCATE(DstInitTypeData%XPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitTypeData%PropSetsC)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsC,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsC,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsC,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsC,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsC)) THEN + ALLOCATE(DstInitTypeData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%XPropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsC.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitTypeData%XPropSets = SrcInitTypeData%XPropSets + DstInitTypeData%PropSetsC = SrcInitTypeData%PropSetsC ENDIF -IF (ALLOCATED(SrcInitTypeData%CablePropSets)) THEN - i1_l = LBOUND(SrcInitTypeData%CablePropSets,1) - i1_u = UBOUND(SrcInitTypeData%CablePropSets,1) - i2_l = LBOUND(SrcInitTypeData%CablePropSets,2) - i2_u = UBOUND(SrcInitTypeData%CablePropSets,2) - IF (.NOT. ALLOCATED(DstInitTypeData%CablePropSets)) THEN - ALLOCATE(DstInitTypeData%CablePropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitTypeData%PropSetsR)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsR,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsR,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsR,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsR,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsR)) THEN + ALLOCATE(DstInitTypeData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%CablePropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsR.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitTypeData%CablePropSets = SrcInitTypeData%CablePropSets + DstInitTypeData%PropSetsR = SrcInitTypeData%PropSetsR ENDIF -IF (ALLOCATED(SrcInitTypeData%RigidPropSets)) THEN - i1_l = LBOUND(SrcInitTypeData%RigidPropSets,1) - i1_u = UBOUND(SrcInitTypeData%RigidPropSets,1) - i2_l = LBOUND(SrcInitTypeData%RigidPropSets,2) - i2_u = UBOUND(SrcInitTypeData%RigidPropSets,2) - IF (.NOT. ALLOCATED(DstInitTypeData%RigidPropSets)) THEN - ALLOCATE(DstInitTypeData%RigidPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitTypeData%PropSetsX)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsX,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsX,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsX,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsX,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsX)) THEN + ALLOCATE(DstInitTypeData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%RigidPropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsX.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitTypeData%RigidPropSets = SrcInitTypeData%RigidPropSets + DstInitTypeData%PropSetsX = SrcInitTypeData%PropSetsX ENDIF IF (ALLOCATED(SrcInitTypeData%COSMs)) THEN i1_l = LBOUND(SrcInitTypeData%COSMs,1) @@ -2731,7 +2735,9 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim DstInitTypeData%NNode = SrcInitTypeData%NNode DstInitTypeData%NElem = SrcInitTypeData%NElem - DstInitTypeData%NProp = SrcInitTypeData%NProp + DstInitTypeData%NPropB = SrcInitTypeData%NPropB + DstInitTypeData%NPropC = SrcInitTypeData%NPropC + DstInitTypeData%NPropR = SrcInitTypeData%NPropR DstInitTypeData%TDOF = SrcInitTypeData%TDOF IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN i1_l = LBOUND(SrcInitTypeData%Nodes,1) @@ -2747,19 +2753,47 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%Nodes = SrcInitTypeData%Nodes ENDIF -IF (ALLOCATED(SrcInitTypeData%Props)) THEN - i1_l = LBOUND(SrcInitTypeData%Props,1) - i1_u = UBOUND(SrcInitTypeData%Props,1) - i2_l = LBOUND(SrcInitTypeData%Props,2) - i2_u = UBOUND(SrcInitTypeData%Props,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Props)) THEN - ALLOCATE(DstInitTypeData%Props(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitTypeData%PropsB)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsB,1) + i1_u = UBOUND(SrcInitTypeData%PropsB,1) + i2_l = LBOUND(SrcInitTypeData%PropsB,2) + i2_u = UBOUND(SrcInitTypeData%PropsB,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsB)) THEN + ALLOCATE(DstInitTypeData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Props.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsB.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitTypeData%Props = SrcInitTypeData%Props + DstInitTypeData%PropsB = SrcInitTypeData%PropsB +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropsC)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsC,1) + i1_u = UBOUND(SrcInitTypeData%PropsC,1) + i2_l = LBOUND(SrcInitTypeData%PropsC,2) + i2_u = UBOUND(SrcInitTypeData%PropsC,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsC)) THEN + ALLOCATE(DstInitTypeData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropsC = SrcInitTypeData%PropsC +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropsR)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsR,1) + i1_u = UBOUND(SrcInitTypeData%PropsR,1) + i2_l = LBOUND(SrcInitTypeData%PropsR,2) + i2_u = UBOUND(SrcInitTypeData%PropsR,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsR)) THEN + ALLOCATE(DstInitTypeData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropsR = SrcInitTypeData%PropsR ENDIF IF (ALLOCATED(SrcInitTypeData%K)) THEN i1_l = LBOUND(SrcInitTypeData%K,1) @@ -2912,17 +2946,17 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%Joints)) THEN DEALLOCATE(InitTypeData%Joints) ENDIF -IF (ALLOCATED(InitTypeData%PropSets)) THEN - DEALLOCATE(InitTypeData%PropSets) +IF (ALLOCATED(InitTypeData%PropSetsB)) THEN + DEALLOCATE(InitTypeData%PropSetsB) ENDIF -IF (ALLOCATED(InitTypeData%XPropSets)) THEN - DEALLOCATE(InitTypeData%XPropSets) +IF (ALLOCATED(InitTypeData%PropSetsC)) THEN + DEALLOCATE(InitTypeData%PropSetsC) ENDIF -IF (ALLOCATED(InitTypeData%CablePropSets)) THEN - DEALLOCATE(InitTypeData%CablePropSets) +IF (ALLOCATED(InitTypeData%PropSetsR)) THEN + DEALLOCATE(InitTypeData%PropSetsR) ENDIF -IF (ALLOCATED(InitTypeData%RigidPropSets)) THEN - DEALLOCATE(InitTypeData%RigidPropSets) +IF (ALLOCATED(InitTypeData%PropSetsX)) THEN + DEALLOCATE(InitTypeData%PropSetsX) ENDIF IF (ALLOCATED(InitTypeData%COSMs)) THEN DEALLOCATE(InitTypeData%COSMs) @@ -2945,8 +2979,14 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%Nodes)) THEN DEALLOCATE(InitTypeData%Nodes) ENDIF -IF (ALLOCATED(InitTypeData%Props)) THEN - DEALLOCATE(InitTypeData%Props) +IF (ALLOCATED(InitTypeData%PropsB)) THEN + DEALLOCATE(InitTypeData%PropsB) +ENDIF +IF (ALLOCATED(InitTypeData%PropsC)) THEN + DEALLOCATE(InitTypeData%PropsC) +ENDIF +IF (ALLOCATED(InitTypeData%PropsR)) THEN + DEALLOCATE(InitTypeData%PropsR) ENDIF IF (ALLOCATED(InitTypeData%K)) THEN DEALLOCATE(InitTypeData%K) @@ -3021,10 +3061,10 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Re_BufSz = Re_BufSz + 1 ! g Db_BufSz = Db_BufSz + 1 ! DT Int_BufSz = Int_BufSz + 1 ! NJoints - Int_BufSz = Int_BufSz + 1 ! NPropSets - Int_BufSz = Int_BufSz + 1 ! NXPropSets - Int_BufSz = Int_BufSz + 1 ! NCablePropSets - Int_BufSz = Int_BufSz + 1 ! NRigidPropSets + Int_BufSz = Int_BufSz + 1 ! NPropSetsX + Int_BufSz = Int_BufSz + 1 ! NPropSetsB + Int_BufSz = Int_BufSz + 1 ! NPropSetsC + Int_BufSz = Int_BufSz + 1 ! NPropSetsR Int_BufSz = Int_BufSz + 1 ! NInterf Int_BufSz = Int_BufSz + 1 ! NCMass Int_BufSz = Int_BufSz + 1 ! NCOSMs @@ -3036,25 +3076,25 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! Joints upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%Joints) ! Joints END IF - Int_BufSz = Int_BufSz + 1 ! PropSets allocated yes/no - IF ( ALLOCATED(InData%PropSets) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropSets upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropSets) ! PropSets + Int_BufSz = Int_BufSz + 1 ! PropSetsB allocated yes/no + IF ( ALLOCATED(InData%PropSetsB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsB) ! PropSetsB END IF - Int_BufSz = Int_BufSz + 1 ! XPropSets allocated yes/no - IF ( ALLOCATED(InData%XPropSets) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! XPropSets upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%XPropSets) ! XPropSets + Int_BufSz = Int_BufSz + 1 ! PropSetsC allocated yes/no + IF ( ALLOCATED(InData%PropSetsC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsC) ! PropSetsC END IF - Int_BufSz = Int_BufSz + 1 ! CablePropSets allocated yes/no - IF ( ALLOCATED(InData%CablePropSets) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CablePropSets upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CablePropSets) ! CablePropSets + Int_BufSz = Int_BufSz + 1 ! PropSetsR allocated yes/no + IF ( ALLOCATED(InData%PropSetsR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsR) ! PropSetsR END IF - Int_BufSz = Int_BufSz + 1 ! RigidPropSets allocated yes/no - IF ( ALLOCATED(InData%RigidPropSets) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! RigidPropSets upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%RigidPropSets) ! RigidPropSets + Int_BufSz = Int_BufSz + 1 ! PropSetsX allocated yes/no + IF ( ALLOCATED(InData%PropSetsX) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsX) ! PropSetsX END IF Int_BufSz = Int_BufSz + 1 ! COSMs allocated yes/no IF ( ALLOCATED(InData%COSMs) ) THEN @@ -3090,17 +3130,29 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! TabDelim Int_BufSz = Int_BufSz + 1 ! NNode Int_BufSz = Int_BufSz + 1 ! NElem - Int_BufSz = Int_BufSz + 1 ! NProp + Int_BufSz = Int_BufSz + 1 ! NPropB + Int_BufSz = Int_BufSz + 1 ! NPropC + Int_BufSz = Int_BufSz + 1 ! NPropR Int_BufSz = Int_BufSz + 1 ! TDOF Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no IF ( ALLOCATED(InData%Nodes) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%Nodes) ! Nodes END IF - Int_BufSz = Int_BufSz + 1 ! Props allocated yes/no - IF ( ALLOCATED(InData%Props) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Props upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Props) ! Props + Int_BufSz = Int_BufSz + 1 ! PropsB allocated yes/no + IF ( ALLOCATED(InData%PropsB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsB) ! PropsB + END IF + Int_BufSz = Int_BufSz + 1 ! PropsC allocated yes/no + IF ( ALLOCATED(InData%PropsC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsC) ! PropsC + END IF + Int_BufSz = Int_BufSz + 1 ! PropsR allocated yes/no + IF ( ALLOCATED(InData%PropsR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsR) ! PropsR END IF Int_BufSz = Int_BufSz + 1 ! K allocated yes/no IF ( ALLOCATED(InData%K) ) THEN @@ -3194,13 +3246,13 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Db_Xferred = Db_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSets + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsX Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NXPropSets + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsB Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCablePropSets + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsC Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NRigidPropSets + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsR Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf Int_Xferred = Int_Xferred + 1 @@ -3230,69 +3282,69 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%Joints)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Joints))-1 ) = PACK(InData%Joints,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%Joints) END IF - IF ( .NOT. ALLOCATED(InData%PropSets) ) THEN + IF ( .NOT. ALLOCATED(InData%PropSetsB) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSets,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSets,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSets,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSets,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSets))-1 ) = PACK(InData%PropSets,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSets) + IF (SIZE(InData%PropSetsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsB))-1 ) = PACK(InData%PropSetsB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsB) END IF - IF ( .NOT. ALLOCATED(InData%XPropSets) ) THEN + IF ( .NOT. ALLOCATED(InData%PropSetsC) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%XPropSets,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XPropSets,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%XPropSets,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%XPropSets,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%XPropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%XPropSets))-1 ) = PACK(InData%XPropSets,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%XPropSets) + IF (SIZE(InData%PropSetsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsC))-1 ) = PACK(InData%PropSetsC,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsC) END IF - IF ( .NOT. ALLOCATED(InData%CablePropSets) ) THEN + IF ( .NOT. ALLOCATED(InData%PropSetsR) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CablePropSets,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CablePropSets,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CablePropSets,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CablePropSets,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CablePropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CablePropSets))-1 ) = PACK(InData%CablePropSets,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CablePropSets) + IF (SIZE(InData%PropSetsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsR))-1 ) = PACK(InData%PropSetsR,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsR) END IF - IF ( .NOT. ALLOCATED(InData%RigidPropSets) ) THEN + IF ( .NOT. ALLOCATED(InData%PropSetsX) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%RigidPropSets,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RigidPropSets,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%RigidPropSets,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RigidPropSets,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%RigidPropSets)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RigidPropSets))-1 ) = PACK(InData%RigidPropSets,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%RigidPropSets) + IF (SIZE(InData%PropSetsX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsX))-1 ) = PACK(InData%PropSetsX,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsX) END IF IF ( .NOT. ALLOCATED(InData%COSMs) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3396,7 +3448,11 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NProp + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropC + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropR Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%TDOF Int_Xferred = Int_Xferred + 1 @@ -3416,21 +3472,53 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%Nodes)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Nodes))-1 ) = PACK(InData%Nodes,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%Nodes) END IF - IF ( .NOT. ALLOCATED(InData%Props) ) THEN + IF ( .NOT. ALLOCATED(InData%PropsB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsB))-1 ) = PACK(InData%PropsB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsB) + END IF + IF ( .NOT. ALLOCATED(InData%PropsC) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Props,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Props,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Props,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Props,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Props)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Props))-1 ) = PACK(InData%Props,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Props) + IF (SIZE(InData%PropsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsC))-1 ) = PACK(InData%PropsC,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsC) + END IF + IF ( .NOT. ALLOCATED(InData%PropsR) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsR))-1 ) = PACK(InData%PropsR,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsR) END IF IF ( .NOT. ALLOCATED(InData%K) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3647,13 +3735,13 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Db_Xferred = Db_Xferred + 1 OutData%NJoints = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NPropSets = IntKiBuf( Int_Xferred ) + OutData%NPropSetsX = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NXPropSets = IntKiBuf( Int_Xferred ) + OutData%NPropSetsB = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NCablePropSets = IntKiBuf( Int_Xferred ) + OutData%NPropSetsC = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NRigidPropSets = IntKiBuf( Int_Xferred ) + OutData%NPropSetsR = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NInterf = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -3693,7 +3781,7 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%Joints) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSets not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsB not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -3703,10 +3791,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropSets)) DEALLOCATE(OutData%PropSets) - ALLOCATE(OutData%PropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PropSetsB)) DEALLOCATE(OutData%PropSetsB) + ALLOCATE(OutData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsB.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -3715,11 +3803,11 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%PropSets)>0) OutData%PropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSets))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSets) + IF (SIZE(OutData%PropSetsB)>0) OutData%PropSetsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsB) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! XPropSets not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsC not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -3729,10 +3817,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%XPropSets)) DEALLOCATE(OutData%XPropSets) - ALLOCATE(OutData%XPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PropSetsC)) DEALLOCATE(OutData%PropSetsC) + ALLOCATE(OutData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%XPropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsC.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -3741,11 +3829,11 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%XPropSets)>0) OutData%XPropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%XPropSets))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%XPropSets) + IF (SIZE(OutData%PropSetsC)>0) OutData%PropSetsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsC))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsC) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CablePropSets not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsR not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -3755,10 +3843,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CablePropSets)) DEALLOCATE(OutData%CablePropSets) - ALLOCATE(OutData%CablePropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PropSetsR)) DEALLOCATE(OutData%PropSetsR) + ALLOCATE(OutData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CablePropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsR.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -3767,11 +3855,11 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%CablePropSets)>0) OutData%CablePropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CablePropSets))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CablePropSets) + IF (SIZE(OutData%PropSetsR)>0) OutData%PropSetsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsR))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsR) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RigidPropSets not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsX not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -3781,10 +3869,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%RigidPropSets)) DEALLOCATE(OutData%RigidPropSets) - ALLOCATE(OutData%RigidPropSets(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PropSetsX)) DEALLOCATE(OutData%PropSetsX) + ALLOCATE(OutData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RigidPropSets.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsX.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -3793,8 +3881,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%RigidPropSets)>0) OutData%RigidPropSets = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RigidPropSets))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%RigidPropSets) + IF (SIZE(OutData%PropSetsX)>0) OutData%PropSetsX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsX))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsX) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs not allocated @@ -3959,7 +4047,11 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%NElem = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NProp = IntKiBuf( Int_Xferred ) + OutData%NPropB = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropC = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropR = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%TDOF = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -3989,7 +4081,59 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%Nodes) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Props not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropsB)) DEALLOCATE(OutData%PropsB) + ALLOCATE(OutData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropsB)>0) OutData%PropsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsC not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropsC)) DEALLOCATE(OutData%PropsC) + ALLOCATE(OutData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropsC)>0) OutData%PropsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsC))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsC) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsR not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -3999,10 +4143,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Props)) DEALLOCATE(OutData%Props) - ALLOCATE(OutData%Props(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PropsR)) DEALLOCATE(OutData%PropsR) + ALLOCATE(OutData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Props.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsR.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -4011,8 +4155,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%Props)>0) OutData%Props = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Props))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Props) + IF (SIZE(OutData%PropsR)>0) OutData%PropsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsR))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsR) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K not allocated From 7c82dd70100572b9a54be94a7b77a2c9b0c56be2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 20:57:41 -0700 Subject: [PATCH 040/377] FlexSub: Cable and rigid are not divided when NDiv>1 --- modules/subdyn/src/SD_FEM.f90 | 76 +++++++++++++++----------- modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 2 +- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 19cee298f..5cec5289b 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -218,8 +218,6 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp REAL(ReKi), ALLOCATABLE :: TempPropsB(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsC(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsR(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 @@ -241,12 +239,10 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF ! Total number of element - Init%NElem = p%NMembers*Init%NDiv + Init%NElem = p%NMembers*Init%NDiv ! TODO TODO TODO: THIS IS A MAX SINCE CABLE AND RIGID CANNOT BE SUBDIVIDED ! Total number of nodes - Depends on division and number of nodes per element Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - Init%NNode = Init%NNode + (NNE - 2)*Init%NElem - !bjj: replaced with max value instead of NNE: Init%MembersCol = Init%MembersCol + (NNE - 2) - MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO ! check the number of interior modes IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN @@ -332,41 +328,53 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) else if (Init%NDiv > 1) then + ! Discretize structure according to NDiv + ! - Elems is fully reinitialized, connectivity needs to be done again using SetNewElem + ! - Nodes are not reinitialized, but appended to NNodes + ! + ! Initialize Temp arrays that will contain user inputs + input from the subdivided members + ! We don't know how many properties will be needed, so allocated to size MaxNProp + MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(TempPropsB, MaxNProp, PropSetsBCol,'TempPropsB', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempPropsC, MaxNProp, PropSetsCCol,'TempPropsC', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempPropsR, MaxNProp, PropSetsRCol,'TempPropsR', ErrStat2, ErrMsg2); if(Failed()) return - TempPropsB = 0 - TempPropsC = 0 - TempPropsR = 0 + TempPropsB = -9999. TempMembers = p%Elems(1:p%NMembers,:) TempPropsB(1:Init%NPropSetsB, :) = Init%PropSetsB - TempPropsC(1:Init%NPropSetsC, :) = Init%PropSetsC - TempPropsR(1:Init%NPropSetsR, :) = Init%PropSetsR - ! discretize structure according to NDiv kelem = 0 knode = Init%NJoints kprop = Init%NPropSetsB print*,'>>> NDIV>1' DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information - ! create new node + ! Member data Node1 = TempMembers(I, 2) Node2 = TempMembers(I, 3) + Prop1 = TempMembers(I, iMProp ) + Prop2 = TempMembers(I, iMProp+1) + eType = TempMembers(I, iMType ) IF ( Node1==Node2 ) THEN CALL Fatal(' Same starting and ending node in the member.') RETURN ENDIF - eType = TempMembers(I, iMType ) - Prop1 = TempMembers(I, iMProp ) - Prop2 = TempMembers(I, iMProp+1) - + if (eType/=idBeam) then + ! --- Cables and rigid links are not subdivided + ! No need to create new properties or new nodes + print*,'Member',I, 'not subdivided since it is not a beam. Looping through.' + Init%MemberNodes(I, 1) = Node1 + Init%MemberNodes(I, 2) = Node2 + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p) + + continue + endif + + ! --- Subdivision of beams Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 - + IF ( ( .not. EqualRealNos(TempPropsB(Prop1, 2),TempPropsB(Prop2, 2) ) ) & .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 3),TempPropsB(Prop2, 3) ) ) & .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 4),TempPropsB(Prop2, 4) ) ) ) THEN @@ -404,7 +412,6 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 2) = knode CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) - IF ( CreateNewProp ) THEN ! create a new property set ! k, E, G, rho, d, t, Init @@ -412,7 +419,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), TempPropsB(Prop1, 4), d1+dd, t1+dt, TempPropsB) kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) - nprop = kprop + nprop = kprop ELSE kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) @@ -433,7 +440,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsB) kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) - nprop = kprop + nprop = kprop ELSE kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) @@ -446,19 +453,27 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDDO ! loop over all members ! Init%NPropB = kprop + Init%NElem = kelem ! TODO since not all members might have been divided + Init%NNode = knode ! TODO since not all members might have been divided + ENDIF ! if NDiv is greater than 1 ! set the props in Init - CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return if (Init%NDiv==1) then - Init%PropsB(1:Init%NPropB,1 :PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) + Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) else if (Init%NDiv>1) then - Init%PropsB = TempPropsB(1:Init%NPropB, 1:PropSetsBCol) + Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempPropsB(1:Init%NPropB, 1:PropSetsBCol) endif - print*,'Init%PropsB' - print*, Init%PropsB + ! --- Cables and rigid link properties (these cannot be subdivided, so direct copy of inputs) + Init%NPropC = Init%NPropSetsC + Init%NPropR = Init%NPropSetsR + CALL AllocAry(Init%PropsC, Init%NPropC, PropSetsCCol, 'Init%PropsCable', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropsR, Init%NPropR, PropSetsRCol, 'Init%PropsRigid', ErrStat2, ErrMsg2); if(Failed()) return + Init%PropsC(1:Init%NPropC, 1:PropSetsCCol) = Init%PropSetsC(1:Init%NPropC, 1:PropSetsCCol) + Init%PropsR(1:Init%NPropR, 1:PropSetsRCol) = Init%PropSetsR(1:Init%NPropR, 1:PropSetsRCol) CALL CleanUp_Discrt() @@ -478,8 +493,6 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices IF (ALLOCATED(TempPropsB)) DEALLOCATE(TempPropsB) - IF (ALLOCATED(TempPropsC)) DEALLOCATE(TempPropsC) - IF (ALLOCATED(TempPropsR)) DEALLOCATE(TempPropsR) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) END SUBROUTINE CleanUp_Discrt @@ -551,14 +564,15 @@ SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) p%Elems(k, 1) = k p%Elems(k, 2) = n1 p%Elems(k, 3) = n2 - p%Elems(k, iMType) = eType p%Elems(k, iMProp ) = p1 p%Elems(k, iMProp+1) = p2 + p%Elems(k, iMType) = eType END SUBROUTINE SetNewElem !------------------------------------------------------------------------------------------------------ !> Set material properties of element k +!! NOTE: this is only for a beam SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) INTEGER , INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: E, G, rho, d, t diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3c97a6318..3c53d5139 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -112,7 +112,7 @@ typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" -typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and nodes in the member" +typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4cdfcf6e1..4f0fc74ef 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -150,7 +150,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and nodes in the member [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and list of nodes making up a member (>2 if subdivided) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] LOGICAL :: SSSum !< SubDyn Summary File Flag [-] From 6da56f39ef9de9dee0ac6a4b9550a99b6505bfba Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Nov 2019 21:54:59 -0700 Subject: [PATCH 041/377] FlexSub: simplifying reindexing of BC and Fc --- modules/subdyn/src/SD_FEM.f90 | 136 +++++++++++++++++----------------- 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 5cec5289b..929afeba5 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -117,17 +117,18 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) END SUBROUTINE NodeCon !---------------------------------------------------------------------------- !> -! - Creates Nodes and Elems instead of Joints and Members arrays ! - Removes the notion of "ID" and use Index instead +! - Creates Nodes (use indices instead of ID), similar to Joints array +! - Creates Elems (use indices instead of ID) similar to Members array +! - Updates Reacts (use indices instead of ID) +! - Updates Interf (use indices instead of ID) SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) ::Init TYPE(SD_ParameterType), INTENT(INOUT) ::p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable - INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 - INTEGER :: NNE ! number of nodes per element - LOGICAL :: found, CreateNewProp + INTEGER :: I, n, iMem, iNode, JointID INTEGER(IntKi) :: mType !< Member Type CHARACTER(1024) :: sType !< String for element type INTEGER(IntKi) :: ErrStat2 @@ -142,17 +143,48 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) ! --- Initialize Nodes Init%Nodes = 0 - DO I = 1,Init%NJoints - Init%Nodes(I, 1) = I + do I = 1,Init%NJoints + Init%Nodes(I, 1) = I ! JointID replaced by index I Init%Nodes(I, 2) = Init%Joints(I, 2) Init%Nodes(I, 3) = Init%Joints(I, 3) Init%Nodes(I, 4) = Init%Joints(I, 4) - ENDDO + enddo + + ! --- Re-Initialize Reactions, pointing to index instead of JointID + do I = 1, p%NReact + JointID=p%Reacts(I,1) + p%Reacts(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index + if (p%Reacts(I,1)<=0) then + CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! --- Re-Initialize interface joints, pointing to index instead of JointID + Init%IntFc = 0 + do I = 1, Init%NInterf + JointID=Init%Interf(I,1) + Init%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (Init%Interf(I,1)<=0) then + CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! Change numbering in concentrated mass matrix + do I = 1, Init%NCMass + JointID = Init%CMass(I,1) + Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (Init%Interf(I,1)<=0) then + CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) p%Elems = 0 ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables - !bjj: TODO: JMJ wants check that YoungE, ShearG, and MatDens are equal in the two properties because we aren't going to interpolate them. This should be less confusing for users. DO iMem = 1, p%NMembers ! Column 1 : member index (instead of MemberID) p%Elems(iMem, 1) = iMem @@ -162,7 +194,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) do iNode=2,3 p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) if (p%Elems(iMem,iNode)<=0) then - CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list !') + CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list!') return endif enddo @@ -186,7 +218,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) end if if (p%Elems(iMem,n)<=0) then - CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has PropSetID'//TRIM(Num2LStr(n-3))//' = '//TRIM(Num2LStr(Prop))//' which is not in the'//trim(sType)//' table!') + CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//'the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') endif END DO !n, loop through property ids ! Column 6: member type @@ -214,11 +246,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable - INTEGER :: I, iMem, J, n, iNode, Node, Node1, Node2, Prop, Prop1, Prop2 + INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp REAL(ReKi), ALLOCATABLE :: TempPropsB(:, :) - INTEGER, ALLOCATABLE :: TempMembers(:, :) ,TempReacts(:,:) + INTEGER, ALLOCATABLE :: TempMembers(:, :) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp @@ -242,7 +274,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%NElem = p%NMembers*Init%NDiv ! TODO TODO TODO: THIS IS A MAX SINCE CABLE AND RIGID CANNOT BE SUBDIVIDED ! Total number of nodes - Depends on division and number of nodes per element Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO + Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. ! check the number of interior modes IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN @@ -251,74 +283,24 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return ! THIS MAY NEED TO CHANGE IF NOT ALL NODES ARE RESTRAINED CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempReacts, p%NReact, ReactCol, 'TempReacts', ErrStat2, ErrMsg2); if(Failed()) return ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays ! NOTE: need NNode and NElem CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - ! Initialize boundary constraint vector - ! Change the node number - ! Allocate array that will be p%Reacts renumbered and ordered so that ID does not play a role, just ordinal position number will count -RRD - Init%BCs = 0 - TempReacts(1:p%NReact,1:ReactCol)=0 - DO I = 1, p%NReact - Node1 = p%Reacts(I, 1); !NODE ID - TempReacts(I,2:ReactCol)=p%Reacts(I, 2:ReactCol) !Assign all the appropriate fixity to the new Reacts array -RRD - found = .false. - DO J = 1, Init%NJoints - IF ( Node1 == NINT(Init%Joints(J, 1)) ) THEN - Node2 = J - found = .true. - TempReacts(I,1)=Node2 !New node ID for p!React -RRD - EXIT !Exit J loop if node found -RRD - ENDIF - ENDDO - IF (.not. found) THEN - CALL Fatal(' React has node not in the node list !') - RETURN - ENDIF - DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = (Node2-1)*6+J; - Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); - ENDDO - ENDDO - p%Reacts=TempReacts !UPDATED REACTS + ! --- Initialize boundary constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first + CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitConstr(Init, p) - ! Initialize interface constraint vector - ! Change the node number - Init%IntFc = 0 + ! --- Initialize interface constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first DO I = 1, Init%NInterf - Node1 = Init%Interf(I, 1); - found = .false. - DO J = 1, Init%NJoints - IF ( Node1 == NINT(Init%Joints(J, 1)) ) THEN - Node2 = J - found = .true. - ENDIF - ENDDO - IF (.not. found) THEN - CALL Fatal(' Interf has node not in the node list !') - RETURN - ENDIF DO J = 1, 6 - Init%IntFc( (I-1)*6+J, 1) = (Node2-1)*6+J; + Init%IntFc( (I-1)*6+J, 1) = (Init%Interf(I,1)-1)*6+J; ! TODO assumes order of DOF, and needs Interf1 reindexed Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); ENDDO ENDDO - ! Change numbering in concentrated mass matrix - DO I = 1, Init%NCMass - Node1 = NINT( Init%CMass(I, 1) ) - DO J = 1, Init%NJoints - IF ( Node1 == NINT(Init%Joints(J, 1)) ) THEN - Init%CMass(I, 1) = J !bjj: todo: check this. if there is no return after this is found, are we overwritting the value if Node1 == NINT(Init%Joints(J, 1)) is true for multiple Js? - ENDIF - ENDDO - ENDDO - Init%MemberNodes = 0 ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) if (Init%NDiv==1) then @@ -494,7 +476,6 @@ SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices IF (ALLOCATED(TempPropsB)) DEALLOCATE(TempPropsB) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) - IF (ALLOCATED(TempReacts)) DEALLOCATE(TempReacts) END SUBROUTINE CleanUp_Discrt END SUBROUTINE SD_Discrt @@ -991,6 +972,23 @@ SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) END SUBROUTINE ElemM !------------------------------------------------------------------------------------------------------ +!> Sets a list of DOF indices and the value these DOF should have +!! NOTE: need p%Reacts to have an updated first column that uses indices and not JointID +SUBROUTINE InitConstr(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + ! + INTEGER(IntKi) :: I,J + + Init%BCs = 0 + DO I = 1, p%NReact + DO J = 1, 6 + Init%BCs( (I-1)*6+J, 1) = (p%Reacts(I,1)-1)*6+J; ! DOF Index, looping through Joints in index order + Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); + ENDDO + ENDDO +END SUBROUTINE InitConstr + !> Apply constraint (Boundary conditions) on Mass and Stiffness matrices SUBROUTINE ApplyConstr(Init,p) TYPE(SD_InitType ),INTENT(INOUT):: Init From 92d6c59ced441d84568c4167ce3b032101b20e60 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 Nov 2019 11:51:12 -0700 Subject: [PATCH 042/377] FlexSub: renamed tempprop --- modules/subdyn/src/SD_FEM.f90 | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 929afeba5..190f036bc 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -249,14 +249,12 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempPropsB(:, :) + REAL(ReKi), ALLOCATABLE :: TempProps(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp INTEGER(IntKi) :: eType !< Element Type - INTEGER(IntKi) :: mType !< Member Type - CHARACTER(1024) :: sType !< String for element type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 ErrStat = ErrID_None @@ -319,15 +317,14 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! We don't know how many properties will be needed, so allocated to size MaxNProp MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempPropsB, MaxNProp, PropSetsBCol,'TempPropsB', ErrStat2, ErrMsg2); if(Failed()) return - TempPropsB = -9999. + CALL AllocAry(TempProps, MaxNProp, PropSetsBCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return + TempProps = -9999. TempMembers = p%Elems(1:p%NMembers,:) - TempPropsB(1:Init%NPropSetsB, :) = Init%PropSetsB + TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB kelem = 0 knode = Init%NJoints kprop = Init%NPropSetsB - print*,'>>> NDIV>1' DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information ! Member data Node1 = TempMembers(I, 2) @@ -357,9 +354,9 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, Init%NDiv+1) = Node2 - IF ( ( .not. EqualRealNos(TempPropsB(Prop1, 2),TempPropsB(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 3),TempPropsB(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempPropsB(Prop1, 4),TempPropsB(Prop2, 4) ) ) ) THEN + IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN CALL Fatal(' Material E,G and rho in a member must be the same') RETURN @@ -377,11 +374,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) dy = ( y2 - y1 )/Init%NDiv dz = ( z2 - z1 )/Init%NDiv - d1 = TempPropsB(Prop1, 5) - t1 = TempPropsB(Prop1, 6) + d1 = TempProps(Prop1, 5) + t1 = TempProps(Prop1, 6) - d2 = TempPropsB(Prop2, 5) - t2 = TempPropsB(Prop2, 6) + d2 = TempProps(Prop2, 5) + t2 = TempProps(Prop2, 6) dd = ( d2 - d1 )/Init%NDiv dt = ( t2 - t1 )/Init%NDiv @@ -398,7 +395,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), TempPropsB(Prop1, 4), d1+dd, t1+dt, TempPropsB) + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) kelem = kelem + 1 CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) nprop = kprop @@ -419,7 +416,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! create a new property set ! k, E, G, rho, d, t, Init kprop = kprop + 1 - CALL SetNewProp(kprop, TempPropsB(Prop1, 2), TempPropsB(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsB) + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) kelem = kelem + 1 CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) nprop = kprop @@ -446,7 +443,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) if (Init%NDiv==1) then Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) else if (Init%NDiv>1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempPropsB(1:Init%NPropB, 1:PropSetsBCol) + Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempProps(1:Init%NPropB, 1:PropSetsBCol) endif ! --- Cables and rigid link properties (these cannot be subdivided, so direct copy of inputs) @@ -474,7 +471,7 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices - IF (ALLOCATED(TempPropsB)) DEALLOCATE(TempPropsB) + IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) END SUBROUTINE CleanUp_Discrt From 6067e1e959f376bdc6d95bde6b5b623210409674 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 11 Nov 2019 16:03:40 -0700 Subject: [PATCH 043/377] Update error checking on for available dimensions in 2nd order. --- modules/hydrodyn/src/WAMIT2.f90 | 99 ++++++++++++++------------------- 1 file changed, 42 insertions(+), 57 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 1ea5d84f5..78844e1a4 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -226,8 +226,6 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Local Variables -! TYPE(FFT_DataType) :: FFT_Data !< the instance of the FFT module we're using - INTEGER(IntKi) :: I !< Generic counter INTEGER(IntKi) :: J !< Generic counter @@ -399,15 +397,17 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data3D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the MnDrift method.', ErrStat,ErrMsg,'WAMIT2_Init') + CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE IF ( MnDriftData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data4D%LoadComponents(I) ) )& - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the MnDrift method.', ErrStat,ErrMsg,'WAMIT2_Init') + CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE ! We didn't find any data to use... CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') @@ -424,20 +424,18 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( NewmanAppData%DataIs3D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 - IF ( p%NewmanAppDims(I) ) THEN - IF ( .NOT. NewmanAppData%Data3D%LoadComponents(I) ) & - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the NewmanApp method.', ErrStat,ErrMsg,'WAMIT2_Init') - END IF + IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data3D%LoadComponents(I) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE IF ( NewmanAppData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 - IF ( p%NewmanAppDims(I) ) THEN - IF ( .NOT. NewmanAppData%Data4D%LoadComponents(I) ) & - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the NewmanApp method.', ErrStat,ErrMsg,'WAMIT2_Init') - END IF + IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data4D%LoadComponents(I) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') @@ -454,11 +452,10 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( DiffQTFData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 - IF ( p%DiffQTFDims(I) ) THEN - IF ( .NOT. DiffQTFData%Data4D%LoadComponents(I) ) & - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the DiffQTF method.', ErrStat,ErrMsg,'WAMIT2_Init') - END IF + IF ( p%DiffQTFDims(I) .AND. ( .NOT. DiffQTFData%Data4D%LoadComponents(I) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the DiffQTF method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') @@ -475,11 +472,10 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( SumQTFData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file DO I=1,6 - IF ( p%SumQTFDims(I) ) THEN - IF ( .NOT. SumQTFData%Data4D%LoadComponents(I) ) & - CALL SetErrStat( ErrID_Fatal, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the SumQTF method.', ErrStat,ErrMsg,'WAMIT2_Init') - END IF + IF ( p%SumQTFDims(I) .AND. ( .NOT. SumQTFData%Data4D%LoadComponents(I) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(I))//' force component for the SumQTF method. Setting this component to zero.', & + ErrStat,ErrMsg,'WAMIT2_Init') ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') @@ -1087,8 +1083,14 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Set the MnDrift force to 0.0 (Even ones we don't calculate) MnDriftForce(I) = 0.0_SiKi - ! Only on the dimensions we requested - IF ( p%MnDriftDims(I) ) THEN + IF (MnDriftData%DataIs3D) THEN + TmpFlag = MnDriftData%Data3D%LoadComponents(I) + ELSE + TmpFlag = MnDriftData%Data4D%LoadComponents(I) + END IF + + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%MnDriftDims(I) .AND. TmpFlag ) THEN ! Set an initial search index for the 3D and 4D array interpolation LastIndex3 = (/0,0,0/) @@ -1595,8 +1597,14 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg NewmanTerm1C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) NewmanTerm2C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) - ! Only on the dimensions we requested - IF ( p%NewmanAppDims(I) ) THEN + IF (NewmanAppData%DataIs3D) THEN + TmpFlag = NewmanAppData%Data3D%LoadComponents(I) + ELSE + TmpFlag = NewmanAppData%Data4D%LoadComponents(I) + END IF + + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%NewmanAppDims(I) .AND. TmpFlag ) THEN ! Set an initial search index for the 3D and 4D array interpolation LastIndex3 = (/0,0,0/) @@ -2054,8 +2062,8 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Now loop through all the dimensions and perform the calculation DO I=1,6 - ! Only on the dimensions we requested - IF ( p%DiffQTFDims(I) ) THEN + ! Only on the dimensions we requested, and it exists in the dataset + IF ( p%DiffQTFDims(I) .AND. DiffQTFData%Data4D%LoadComponents(I) ) THEN ! Set an initial search index for the 4D array interpolation @@ -2464,8 +2472,8 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Now loop through all the dimensions and perform the calculation DO I=1,6 - ! Only on the dimensions we requested - IF ( p%SumQTFDims(I) ) THEN + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%SumQTFDims(I) .AND. SumQTFData%Data4D%LoadComponents(I) ) THEN ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays @@ -3060,17 +3068,6 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff p%MnDriftDims(4) = .FALSE. ! the .8 files don't contain this dimension p%MnDriftDims(5) = .FALSE. ! the .8 files don't contain this dimension p%MnDriftDims(6) = .TRUE. -!FIXME: do I want to include these warnings anymore? -! !> Now warn me that we changed the calculations in this case... -! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& -! 'in the heave direction. No second order heave forces will be calculated within the mean drift calculations.'//NewLine, & -! ErrStat, ErrMsg, 'CheckInitInput') -! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& -! 'for platform roll. No second order roll forces will be calculated within the mean drift calculations.'//NewLine, & -! ErrStat, ErrMsg, 'CheckInitInput') -! CALL SetErrStat( ErrID_Warn, ' WARNING: the .8 WAMIT output file does not contain information for second order forces '//& -! 'for platform pitch. No second order pitching forces will be calculated within the mean drift calculations.'//NewLine, & -! ErrStat, ErrMsg, 'CheckInitInput') ELSE p%MnDriftDims = .TRUE. ENDIF @@ -3094,18 +3091,6 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff p%NewmanAppDims(4) = .FALSE. ! the .8 files don't contain this dimension p%NewmanAppDims(5) = .FALSE. ! the .8 files don't contain this dimension p%NewmanAppDims(6) = .TRUE. -!FIXME: do I want to include these warnings anymore? -! !> Now warn me that we changed the calculations in this case... -! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& -! 'second order force calculations of platform heave.'//NewLine// & -! " No second order heave forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') -! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& -! 'second order force calculations of platform roll.'//NewLine// & -! " No second order roll forces will be calculated within the Newman's Approximation calculations.", ErrStat, ErrMsg, 'CheckInitInput') -! CALL SetErrStat( ErrID_Warn, ' Warning: the .8 WAMIT output file does not contain information that can be used for '//& -! 'second order force calculations of platform pitch.'//NewLine// & -! " No second order pitching forces will be calculated within the Newman's Approximation calculations.", & -! ErrStat, ErrMsg, 'CheckInitInput') ELSE p%NewmanAppDims = .TRUE. ENDIF From 1a9098e883a3e1d4dbe9121be2c6cf29f6d1bf2a Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 12:00:06 -0700 Subject: [PATCH 044/377] TCF: aligning code block --- modules/hydrodyn/src/WAMIT2.f90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 78844e1a4..a581e5ed4 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -1083,11 +1083,11 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Set the MnDrift force to 0.0 (Even ones we don't calculate) MnDriftForce(I) = 0.0_SiKi - IF (MnDriftData%DataIs3D) THEN - TmpFlag = MnDriftData%Data3D%LoadComponents(I) - ELSE - TmpFlag = MnDriftData%Data4D%LoadComponents(I) - END IF + IF (MnDriftData%DataIs3D) THEN + TmpFlag = MnDriftData%Data3D%LoadComponents(I) + ELSE + TmpFlag = MnDriftData%Data4D%LoadComponents(I) + END IF ! Only on the dimensions we requested, and if it is present in the data IF ( p%MnDriftDims(I) .AND. TmpFlag ) THEN From ce60d72e0e3a9f4e4536fc024543d434b1f3b095 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 13:13:42 -0700 Subject: [PATCH 045/377] Fix precision issue in WAMIT module so double precision compiles --- modules/hydrodyn/src/.WAMIT.f90.swp | Bin 0 -> 16384 bytes modules/hydrodyn/src/WAMIT.f90 | 2 +- modules/hydrodyn/src/WAMIT.txt | 2 +- modules/hydrodyn/src/WAMIT_Types.f90 | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 modules/hydrodyn/src/.WAMIT.f90.swp diff --git a/modules/hydrodyn/src/.WAMIT.f90.swp b/modules/hydrodyn/src/.WAMIT.f90.swp new file mode 100644 index 0000000000000000000000000000000000000000..04ec972b42c4b53bff8ca2ffdfb2f35aca2f5745 GIT binary patch literal 16384 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 CWl9nN literal 0 HcmV?d00001 diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 25eed45f4..1308ca108 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -62,7 +62,7 @@ subroutine TransformWAMITMatrices( NBody, RotZ, M ) !.................................................................................................................................. integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) - real(ReKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(SiKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices integer(IntKi) :: i,j,ii,jj,iSub,jSub real(R8Ki) :: Rj(3,3) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index e4e5180fb..bd9720a24 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -118,7 +118,7 @@ typedef ^ ParameterType INTEGER typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - typedef ^ ^ ReKi F_HS_Moment_Offset {:}{:} - - "The offset moment due to the COB being offset from the WAMIT body's local location {matrix 3xNBody}" N-m typedef ^ ^ ReKi HdroAdMsI {:}{:} - - "" (sec) -typedef ^ ^ ReKi HdroSttc {:}{:} - - "" - +typedef ^ ^ SiKi HdroSttc {:}{:} - - "" - typedef ^ ^ INTEGER RdtnMod - - - "" - typedef ^ ^ INTEGER ExctnMod - - - "" - typedef ^ ^ SiKi WaveExctn {:}{:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index b8a223cc3..8d3173dde 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -134,7 +134,7 @@ MODULE WAMIT_Types INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_HS_Moment_Offset !< The offset moment due to the COB being offset from the WAMIT body's local location {matrix 3xNBody} [N-m] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: HdroAdMsI !< [(sec)] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: HdroSttc !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: HdroSttc !< [-] INTEGER(IntKi) :: RdtnMod !< [-] INTEGER(IntKi) :: ExctnMod !< [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveExctn !< [-] @@ -4821,7 +4821,7 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%HdroSttc)>0) OutData%HdroSttc = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroSttc))-1 ), mask2, 0.0_ReKi ) + IF (SIZE(OutData%HdroSttc)>0) OutData%HdroSttc = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroSttc))-1 ), mask2, 0.0_ReKi ), SiKi) Re_Xferred = Re_Xferred + SIZE(OutData%HdroSttc) DEALLOCATE(mask2) END IF From 81ff0c013bbdbd9d529e80c2c6cc4f087e70c8ab Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 12 Nov 2019 15:28:17 -0700 Subject: [PATCH 046/377] Updated Wave Exctn transform work for NBodyMod 1,3 --- modules/hydrodyn/src/WAMIT.f90 | 30 ++++++++++++++++++++++------ modules/hydrodyn/src/WAMIT.txt | 4 ++-- modules/hydrodyn/src/WAMIT_Types.f90 | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 25eed45f4..26b760893 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -62,7 +62,7 @@ subroutine TransformWAMITMatrices( NBody, RotZ, M ) !.................................................................................................................................. integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) - real(ReKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(SiKi), intent( inout ) :: M(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices integer(IntKi) :: i,j,ii,jj,iSub,jSub real(R8Ki) :: Rj(3,3) @@ -194,7 +194,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Error handling CHARACTER(1024) :: ErrMsg2 ! Temporary error message for calls INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls - + real(SiKi) :: tmp1, tmp2, tmp4, tmp5 ! Temporary transformation terms ! Initialize data @@ -992,7 +992,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Transform the wave excitation coefs !==================================== - + ! TODO: Need to create rotation corrrection for NBODYMOD = 1,3, but do not use Fxy and do not adjust beta (tmpAngle) if ( p%NBodyMod == 2 ) then ! Since NBodyMod = 2, then NBody = 1 for this WAMIT object (this requirement is encoded at the HydroDyn module level) @@ -1001,8 +1001,8 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init IF ( ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the HdroExctn_Local array.', ErrStat, ErrMsg, 'WAMIT_Init') CALL Cleanup() - RETURN - END IF + RETURN + END IF do K = 1,6 ! Loop through all wave excitation forces and moments do J = 1, NInpWvDir @@ -1019,7 +1019,6 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init do J = 1, NInpWvDir do I = 1, NInpFreq - ! Fxy = exp(-j * k(w) * ( X*cos(Beta(w)) + Y*sin(Beta(w)) ) WaveNmbr = WaveNumber ( HdroFreq(I), InitInp%Gravity, InitInp%WtrDpth ) tmpAngle = WaveNmbr * ( InitInp%PtfmRefxt(1)*cos(HdroWvDir(J)*D2R) + InitInp%PtfmRefyt(1)*sin(HdroWvDir(J)*D2R) ) @@ -1037,6 +1036,25 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init end do end do deallocate(HdroExctn_Local) + else + + ! Apply rotation only for NBodyMod = 1,3 + do J = 1, NInpWvDir + do I = 1, NInpFreq + + tmp1 = ( HdroExctn(I,J,1)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn(I,J,2)*sin(InitInp%PtfmRefztRot(1)) ) + tmp2 = ( HdroExctn(I,J,1)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn(I,J,2)*cos(InitInp%PtfmRefztRot(1)) ) + tmp4 = ( HdroExctn(I,J,4)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn(I,J,5)*sin(InitInp%PtfmRefztRot(1)) ) + tmp5 = ( HdroExctn(I,J,4)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn(I,J,5)*cos(InitInp%PtfmRefztRot(1)) ) + + HdroExctn(I,J,1) = tmp1 + HdroExctn(I,J,2) = tmp2 + HdroExctn(I,J,4) = tmp4 + HdroExctn(I,J,5) = tmp5 + + end do + end do + end if ! Compute the positive-frequency components (including zero) of the discrete diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index e4e5180fb..34fdda8be 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -117,8 +117,8 @@ typedef ^ ^ Conv_Rdtn_O typedef ^ ParameterType INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - typedef ^ ^ ReKi F_HS_Moment_Offset {:}{:} - - "The offset moment due to the COB being offset from the WAMIT body's local location {matrix 3xNBody}" N-m -typedef ^ ^ ReKi HdroAdMsI {:}{:} - - "" (sec) -typedef ^ ^ ReKi HdroSttc {:}{:} - - "" - +typedef ^ ^ SiKi HdroAdMsI {:}{:} - - "" (sec) +typedef ^ ^ SiKi HdroSttc {:}{:} - - "" - typedef ^ ^ INTEGER RdtnMod - - - "" - typedef ^ ^ INTEGER ExctnMod - - - "" - typedef ^ ^ SiKi WaveExctn {:}{:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index b8a223cc3..cfba05f76 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -133,8 +133,8 @@ MODULE WAMIT_Types INTEGER(IntKi) :: NBody !< [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] [-] INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_HS_Moment_Offset !< The offset moment due to the COB being offset from the WAMIT body's local location {matrix 3xNBody} [N-m] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: HdroAdMsI !< [(sec)] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: HdroSttc !< [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: HdroAdMsI !< [(sec)] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: HdroSttc !< [-] INTEGER(IntKi) :: RdtnMod !< [-] INTEGER(IntKi) :: ExctnMod !< [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveExctn !< [-] @@ -4795,7 +4795,7 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%HdroAdMsI)>0) OutData%HdroAdMsI = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroAdMsI))-1 ), mask2, 0.0_ReKi ) + IF (SIZE(OutData%HdroAdMsI)>0) OutData%HdroAdMsI = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroAdMsI))-1 ), mask2, 0.0_ReKi ), SiKi) Re_Xferred = Re_Xferred + SIZE(OutData%HdroAdMsI) DEALLOCATE(mask2) END IF @@ -4821,7 +4821,7 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%HdroSttc)>0) OutData%HdroSttc = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroSttc))-1 ), mask2, 0.0_ReKi ) + IF (SIZE(OutData%HdroSttc)>0) OutData%HdroSttc = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%HdroSttc))-1 ), mask2, 0.0_ReKi ), SiKi) Re_Xferred = Re_Xferred + SIZE(OutData%HdroSttc) DEALLOCATE(mask2) END IF From 42f752d226f4a8123314c85a39b5c32032797cf2 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 16:03:13 -0700 Subject: [PATCH 047/377] TCF: start adding multiple bodies to WAMIT2 --- modules/hydrodyn/src/.HydroDyn.f90.swp | Bin 0 -> 237568 bytes modules/hydrodyn/src/.WAMIT.f90.swp | Bin 16384 -> 0 bytes modules/hydrodyn/src/.WAMIT2.f90.swp | Bin 0 -> 385024 bytes modules/hydrodyn/src/.WAMIT2.txt.swp | Bin 0 -> 28672 bytes modules/hydrodyn/src/HydroDyn.f90 | 37 +++- modules/hydrodyn/src/WAMIT2.f90 | 10 +- modules/hydrodyn/src/WAMIT2.txt | 6 + modules/hydrodyn/src/WAMIT2_Types.f90 | 242 +++++++++++++++++++++++++ 8 files changed, 287 insertions(+), 8 deletions(-) create mode 100644 modules/hydrodyn/src/.HydroDyn.f90.swp delete mode 100644 modules/hydrodyn/src/.WAMIT.f90.swp create mode 100644 modules/hydrodyn/src/.WAMIT2.f90.swp create mode 100644 modules/hydrodyn/src/.WAMIT2.txt.swp diff --git a/modules/hydrodyn/src/.HydroDyn.f90.swp b/modules/hydrodyn/src/.HydroDyn.f90.swp new file mode 100644 index 0000000000000000000000000000000000000000..489a7aba168739f4c0bce7fc780abf77705e7a24 GIT binary patch literal 237568 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 literal 0 HcmV?d00001 diff --git a/modules/hydrodyn/src/.WAMIT.f90.swp b/modules/hydrodyn/src/.WAMIT.f90.swp deleted file mode 100644 index 04ec972b42c4b53bff8ca2ffdfb2f35aca2f5745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 CWl9nN diff --git a/modules/hydrodyn/src/.WAMIT2.f90.swp b/modules/hydrodyn/src/.WAMIT2.f90.swp new file mode 100644 index 0000000000000000000000000000000000000000..ced1ccc895ad89ea1a9020d9a1116e4371d81556 GIT binary patch literal 385024 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

$=3A>dQypnYPqa8 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 Q8}hm$xI@BCUL(}=zs%@5XaE2J literal 0 HcmV?d00001 diff --git a/modules/hydrodyn/src/.WAMIT2.txt.swp b/modules/hydrodyn/src/.WAMIT2.txt.swp new file mode 100644 index 0000000000000000000000000000000000000000..04cb592e4c79c9da774e2c5df8d111fc244166d9 GIT binary patch literal 28672 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 Djy%l> literal 0 HcmV?d00001 diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 055158838..3daed999c 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1014,21 +1014,46 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Only call the WAMIT2_Init if one of the flags is set for a calculation IF ( InitLocal%WAMIT2%MnDriftF .OR. InitLocal%WAMIT2%NewmanAppF .OR. InitLocal%WAMIT2%DiffQTFF .OR. InitLocal%WAMIT2%SumQTFF ) THEN - - + + ! Copy Waves initialization output into the initialization input type for the WAMIT module InitLocal%WAMIT2%RhoXg = Waves_InitOut%RhoXg InitLocal%WAMIT2%NStepWave = Waves_InitOut%NStepWave InitLocal%WAMIT2%NStepWave2 = Waves_InitOut%NStepWave2 InitLocal%WAMIT2%WaveDirMin = Waves_InitOut%WaveDirMin InitLocal%WAMIT2%WaveDirMax = Waves_InitOut%WaveDirMax InitLocal%WAMIT2%WaveDOmega = Waves_InitOut%WaveDOmega - + InitLocal%WAMIT2%NBodyMod = InitLocal%NBodyMod ! There are restrictions in WAMIT2 on which files may be used for MnDriftF or NewmanAppF for BodyMod > 1 + ! Temporarily move arrays to init input for WAMIT2 (save some space) CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT2%WaveTime) CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT2%WaveElevC0) CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT2%WaveDirArr) - - + + ! Determine how many WAMIT2 modules we need based on NBody and NBodyMod + if (p%NBodyMod == 1) then + InitLocal%WAMIT2%NBody = InitLocal%NBody ! The WAMIT2 object will contain all NBody WAMIT2 bodies + + ! Allocate WAMIT2 InitInp arrays based on NBodyMod and copy the inputfile data into the WAMIT2 init data (entire arrays' worth for NBodyMod=1 + call AllocAry( InitLocal%WAMIT%PtfmRefxt , InitLocal%NBody, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefyt , InitLocal%NBody, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefzt , InitLocal%NBody, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefztRot, InitLocal%NBody, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + else + InitLocal%WAMIT2%NBody = 1_IntKi ! The WAMIT2 object will contain all NBody WAMIT2 bodies + + ! Allocate WAMIT2 InitInp arrays based on NBodyMod and copy the inputfile data into the 1st WAMIT body init data for NBodyMod > 1 + call AllocAry( InitLocal%WAMIT%PtfmRefxt , 1, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefyt , 1, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefzt , 1, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT%PtfmRefztRot, 1, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + endif + + if ( ErrStat >= AbortErrLev ) then + call CleanUp() + return + end if + CALL WAMIT2_Init(InitLocal%WAMIT2, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, z%WAMIT2, OtherState%WAMIT2, & y%WAMIT2, m%WAMIT2, Interval, InitOut%WAMIT2, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -1036,7 +1061,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL CleanUp() RETURN END IF - + ! move arrays back CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveTime, p%WaveTime ) CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveElevC0, Waves_InitOut%WaveElevC0) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index a581e5ed4..a009c18f2 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -2792,6 +2792,10 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ' MnDriftF flag should be set to true by calling program for MnDrift /= 0.'//NewLine// & ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') END IF + IF ( InitInp%NBody > 1 .AND. InitInp%MnDrift == 8 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation cannot be used with input file type 8 when more than 1 WAMIT body is present.', & + ErrStat, ErrMsg, 'CheckInitInput') + END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' MnDrift can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & @@ -2816,13 +2820,15 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ' NewmanAppF flag should be set to true by calling program for NewmanApp /= 0.'//NewLine// & ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') END IF + IF ( InitInp%NBody > 1 .AND. InitInp%NewmanApp == 8 ) THEN + CALL SetErrStat( ErrID_Fatal, ' Newman''s approximation cannot be used with input file type 8 when more than 1 WAMIT body is present.', & + ErrStat, ErrMsg, 'CheckInitInput') + END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' NewmanApp can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') END IF - - IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index 8c0f8927c..609d33b48 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -20,6 +20,12 @@ param WAMIT2/WAMIT2 unused INTEGER MaxWAMIT2Ou typedef WAMIT2/WAMIT2 InitInputType LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - typedef ^ ^ CHARACTER(1024) WAMITFile - - - "Root of the filename for WAMIT2 outputs" - typedef ^ ^ INTEGER UnSum - - - "The unit number for the HydroDyn summary file" - +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ ReKi PtfmRefxt {:} - - "The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefyt {:} - - "The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefzt {:} - - "The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians typedef ^ ^ ReKi WAMITULEN - - - "WAMIT unit length scale" - typedef ^ ^ ReKi RhoXg - - - "Density * Gravity -- from the Waves module." - diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index f96a58af8..fc98380e1 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -39,6 +39,12 @@ MODULE WAMIT2_Types LOGICAL :: HasWAMIT !< .TRUE. if using WAMIT model, .FALSE. otherwise [-] CHARACTER(1024) :: WAMITFile !< Root of the filename for WAMIT2 outputs [-] INTEGER(IntKi) :: UnSum !< The unit number for the HydroDyn summary file [-] + INTEGER(IntKi) :: NBody !< [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] [-] + INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefxt !< The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefyt !< The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefzt !< The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] REAL(ReKi) :: WAMITULEN !< WAMIT unit length scale [-] REAL(ReKi) :: RhoXg !< Density * Gravity -- from the Waves module. [-] INTEGER(IntKi) :: NStepWave !< Total number of frequency components = total number of time steps in the incident wave [-] @@ -159,6 +165,56 @@ SUBROUTINE WAMIT2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%HasWAMIT = SrcInitInputData%HasWAMIT DstInitInputData%WAMITFile = SrcInitInputData%WAMITFile DstInitInputData%UnSum = SrcInitInputData%UnSum + DstInitInputData%NBody = SrcInitInputData%NBody + DstInitInputData%NBodyMod = SrcInitInputData%NBodyMod +IF (ALLOCATED(SrcInitInputData%PtfmRefxt)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefxt,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefxt,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefxt)) THEN + ALLOCATE(DstInitInputData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefxt = SrcInitInputData%PtfmRefxt +ENDIF +IF (ALLOCATED(SrcInitInputData%PtfmRefyt)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefyt,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefyt,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefyt)) THEN + ALLOCATE(DstInitInputData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefyt = SrcInitInputData%PtfmRefyt +ENDIF +IF (ALLOCATED(SrcInitInputData%PtfmRefzt)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefzt,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefzt,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefzt)) THEN + ALLOCATE(DstInitInputData%PtfmRefzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefzt = SrcInitInputData%PtfmRefzt +ENDIF +IF (ALLOCATED(SrcInitInputData%PtfmRefztRot)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefztRot,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefztRot,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefztRot)) THEN + ALLOCATE(DstInitInputData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefztRot = SrcInitInputData%PtfmRefztRot +ENDIF DstInitInputData%WAMITULEN = SrcInitInputData%WAMITULEN DstInitInputData%RhoXg = SrcInitInputData%RhoXg DstInitInputData%NStepWave = SrcInitInputData%NStepWave @@ -237,6 +293,18 @@ SUBROUTINE WAMIT2_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitInputData%PtfmRefxt)) THEN + DEALLOCATE(InitInputData%PtfmRefxt) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefyt)) THEN + DEALLOCATE(InitInputData%PtfmRefyt) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefzt)) THEN + DEALLOCATE(InitInputData%PtfmRefzt) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefztRot)) THEN + DEALLOCATE(InitInputData%PtfmRefztRot) +ENDIF IF (ALLOCATED(InitInputData%WaveElevC0)) THEN DEALLOCATE(InitInputData%WaveElevC0) ENDIF @@ -286,6 +354,28 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! HasWAMIT Int_BufSz = Int_BufSz + 1*LEN(InData%WAMITFile) ! WAMITFile Int_BufSz = Int_BufSz + 1 ! UnSum + Int_BufSz = Int_BufSz + 1 ! NBody + Int_BufSz = Int_BufSz + 1 ! NBodyMod + Int_BufSz = Int_BufSz + 1 ! PtfmRefxt allocated yes/no + IF ( ALLOCATED(InData%PtfmRefxt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefxt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefxt) ! PtfmRefxt + END IF + Int_BufSz = Int_BufSz + 1 ! PtfmRefyt allocated yes/no + IF ( ALLOCATED(InData%PtfmRefyt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefyt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefyt) ! PtfmRefyt + END IF + Int_BufSz = Int_BufSz + 1 ! PtfmRefzt allocated yes/no + IF ( ALLOCATED(InData%PtfmRefzt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefzt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefzt) ! PtfmRefzt + END IF + Int_BufSz = Int_BufSz + 1 ! PtfmRefztRot allocated yes/no + IF ( ALLOCATED(InData%PtfmRefztRot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefztRot upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PtfmRefztRot) ! PtfmRefztRot + END IF Re_BufSz = Re_BufSz + 1 ! WAMITULEN Re_BufSz = Re_BufSz + 1 ! RhoXg Int_BufSz = Int_BufSz + 1 ! NStepWave @@ -365,6 +455,62 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO ! I IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%UnSum Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefxt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefxt))-1 ) = PACK(InData%PtfmRefxt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefxt) + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefyt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefyt))-1 ) = PACK(InData%PtfmRefyt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefyt) + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefzt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefzt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefzt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefzt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefzt))-1 ) = PACK(InData%PtfmRefzt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefzt) + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefztRot)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%PtfmRefztRot))-1 ) = PACK(InData%PtfmRefztRot,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%PtfmRefztRot) + END IF ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WAMITULEN Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%RhoXg @@ -513,6 +659,102 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO ! I OutData%UnSum = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) + ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefxt)>0) OutData%PtfmRefxt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefxt))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefxt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) + ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefyt)>0) OutData%PtfmRefyt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefyt))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefyt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefzt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefzt)) DEALLOCATE(OutData%PtfmRefzt) + ALLOCATE(OutData%PtfmRefzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefzt)>0) OutData%PtfmRefzt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefzt))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefzt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefztRot)>0) OutData%PtfmRefztRot = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%PtfmRefztRot))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%PtfmRefztRot) + DEALLOCATE(mask1) + END IF OutData%WAMITULEN = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%RhoXg = ReKiBuf( Re_Xferred ) From eb3807e4c1e02e64963156a53c2eb26cd5b3eec1 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 18:02:59 -0700 Subject: [PATCH 048/377] TCF: removing temporary files accidentally added in last commit --- modules/hydrodyn/src/.HydroDyn.f90.swp | Bin 237568 -> 0 bytes modules/hydrodyn/src/.WAMIT2.f90.swp | Bin 385024 -> 0 bytes modules/hydrodyn/src/.WAMIT2.txt.swp | Bin 28672 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 modules/hydrodyn/src/.HydroDyn.f90.swp delete mode 100644 modules/hydrodyn/src/.WAMIT2.f90.swp delete mode 100644 modules/hydrodyn/src/.WAMIT2.txt.swp diff --git a/modules/hydrodyn/src/.HydroDyn.f90.swp b/modules/hydrodyn/src/.HydroDyn.f90.swp deleted file mode 100644 index 489a7aba168739f4c0bce7fc780abf77705e7a24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237568 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 diff --git a/modules/hydrodyn/src/.WAMIT2.f90.swp b/modules/hydrodyn/src/.WAMIT2.f90.swp deleted file mode 100644 index ced1ccc895ad89ea1a9020d9a1116e4371d81556..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385024 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

$=3A>dQypnYPqa8 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 Q8}hm$xI@BCUL(}=zs%@5XaE2J diff --git a/modules/hydrodyn/src/.WAMIT2.txt.swp b/modules/hydrodyn/src/.WAMIT2.txt.swp deleted file mode 100644 index 04cb592e4c79c9da774e2c5df8d111fc244166d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 Djy%l> From d31a135fcc9942392cfaeafaebb9cf0066f30678 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 18:03:43 -0700 Subject: [PATCH 049/377] Adding single precision constants to nwtc-library I needed a couple single precision ones to simplify precision issues in HD. --- modules/nwtc-library/src/NWTC_Num.f90 | 24 ++++++++++++++++++++- modules/nwtc-library/src/SysGnuLinux.f90 | 11 ++++++++-- modules/nwtc-library/src/SysGnuWin.f90 | 11 ++++++++-- modules/nwtc-library/src/SysIFL.f90 | 10 +++++++-- modules/nwtc-library/src/SysIVF.f90 | 10 +++++++-- modules/nwtc-library/src/SysIVF_Labview.f90 | 11 ++++++++-- modules/nwtc-library/src/SysMatlab.f90 | 10 +++++++-- 7 files changed, 74 insertions(+), 13 deletions(-) diff --git a/modules/nwtc-library/src/NWTC_Num.f90 b/modules/nwtc-library/src/NWTC_Num.f90 index 836fc56e4..8b099077f 100644 --- a/modules/nwtc-library/src/NWTC_Num.f90 +++ b/modules/nwtc-library/src/NWTC_Num.f90 @@ -55,6 +55,18 @@ MODULE NWTC_Num REAL(ReKi) :: TwoByPi !< 2/Pi REAL(ReKi) :: TwoPi !< 2*Pi + REAL(SiKi) :: D2R_S !< Factor to convert degrees to radians in single precision + REAL(SiKi) :: Inf_S !< IEEE value for NaN (not-a-number) in single precision + REAL(SiKi) :: Inv2Pi_S !< 0.5/Pi (1/(2*Pi)) in single precision + REAL(SiKi) :: NaN_S !< IEEE value for Inf (infinity) in single precision + REAL(SiKi) :: Pi_S !< Ratio of a circle's circumference to its diameter in single precision + REAL(SiKi) :: PiBy2_S !< Pi/2 in single precision + REAL(SiKi) :: R2D_S !< Factor to convert radians to degrees in single precision + REAL(SiKi) :: RPM2RPS_S !< Factor to convert revolutions per minute to radians per second in single precision + REAL(SiKi) :: RPS2RPM_S !< Factor to convert radians per second to revolutions per minute in single precision + REAL(SiKi) :: TwoByPi_S !< 2/Pi in single precision + REAL(SiKi) :: TwoPi_S !< 2*Pi in single precision + !======================================================================= ! Create interfaces for generic routines that use specific routines. @@ -5054,9 +5066,19 @@ SUBROUTINE SetConstants( ) TwoPi = 2.0_ReKi*Pi Inv2Pi = 0.5_ReKi/Pi ! 1.0/TwoPi + Pi_S = ACOS( -1.0_SiKi ) + D2R_S = Pi_S/180.0_SiKi + R2D_S = 180.0_SiKi/Pi_S + PiBy2_S = Pi_S/2.0_SiKi + RPM2RPS_S = Pi_S/30.0_SiKi + RPS2RPM_S = 30.0_SiKi/Pi_S + TwoByPi_S = 2.0_SiKi/Pi_S + TwoPi_S = 2.0_SiKi*Pi_S + Inv2Pi_S = 0.5_SiKi/Pi_S ! 1.0_SiKi/TwoPi_S + ! IEEE constants: - CALL Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + CALL Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) RETURN diff --git a/modules/nwtc-library/src/SysGnuLinux.f90 b/modules/nwtc-library/src/SysGnuLinux.f90 index 7257e3256..71a678f37 100644 --- a/modules/nwtc-library/src/SysGnuLinux.f90 +++ b/modules/nwtc-library/src/SysGnuLinux.f90 @@ -32,7 +32,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -288,7 +288,7 @@ SUBROUTINE ProgExit ( StatCode ) END SUBROUTINE ProgExit ! ( StatCode ) !======================================================================= -SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE ! values for not-a-number and infinity in sindle and double @@ -301,10 +301,13 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S ! IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S ! IEEE value for Inf (infinity) in single precision ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) REAL(DbKi) :: Neg_D ! a negative real(DbKi) number REAL(ReKi) :: Neg ! a negative real(ReKi) number + REAL(SiKi) :: Neg_S ! a negative real(SiKi) number ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. @@ -314,16 +317,20 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) Neg_D = -1.0_DbKi Neg = -1.0_ReKi + Neg_S = -1.0_SiKi NaN_D = SQRT ( Neg_D ) NaN = SQRT ( Neg ) + NaN_S = SQRT ( Neg_S ) ! set variables to zero to calculate Infs (using division by zero) Neg_D = 0.0_DbKi Neg = 0.0_ReKi + Neg_S = 0.0_SiKi Inf_D = 1.0_DbKi / Neg_D Inf = 1.0_ReKi / Neg + Inf_S = 1.0_SiKi / Neg_S #endif END SUBROUTINE Set_IEEE_Constants diff --git a/modules/nwtc-library/src/SysGnuWin.f90 b/modules/nwtc-library/src/SysGnuWin.f90 index e0ca2c198..8ec225c39 100644 --- a/modules/nwtc-library/src/SysGnuWin.f90 +++ b/modules/nwtc-library/src/SysGnuWin.f90 @@ -32,7 +32,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -288,7 +288,7 @@ SUBROUTINE ProgExit ( StatCode ) END SUBROUTINE ProgExit ! ( StatCode ) !======================================================================= -SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE ! values for not-a-number and infinity in sindle and double @@ -301,10 +301,13 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(DbKi), INTENT(inout) :: NaN_D ! IEEE value for Inf (infinity) in double precision REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S ! IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S ! IEEE value for Inf (infinity) in single precision ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) REAL(DbKi) :: Neg_D ! a negative real(DbKi) number REAL(ReKi) :: Neg ! a negative real(ReKi) number + REAL(SiKi) :: Neg_S ! a negative real(SiKi) number ! if compiling with floating-point-exception traps, this will not work, so we've added a compiler directive. @@ -314,16 +317,20 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) Neg_D = -1.0_DbKi Neg = -1.0_ReKi + Neg_S = -1.0_SiKi NaN_D = SQRT ( Neg_D ) NaN = SQRT ( Neg ) + NaN_S = SQRT ( Neg_S ) ! set variables to zero to calculate Infs (using division by zero) Neg_D = 0.0_DbKi Neg = 0.0_ReKi + Neg_S = 0.0_SiKi Inf_D = 1.0_DbKi / Neg_D Inf = 1.0_ReKi / Neg + Inf_S = 1.0_SiKi / Neg_S #endif END SUBROUTINE Set_IEEE_Constants diff --git a/modules/nwtc-library/src/SysIFL.f90 b/modules/nwtc-library/src/SysIFL.f90 index 14fc97337..0dd184053 100644 --- a/modules/nwtc-library/src/SysIFL.f90 +++ b/modules/nwtc-library/src/SysIFL.f90 @@ -32,7 +32,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -294,7 +294,7 @@ SUBROUTINE ProgExit ( StatCode ) END SUBROUTINE ProgExit ! ( StatCode ) !======================================================================= -SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE ! values for not-a-number and infinity in sindle and double @@ -310,13 +310,19 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S ! IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S ! IEEE value for Inf (infinity) in single precision + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + NaN_S = ieee_value(0.0_SiKi, ieee_quiet_nan) + Inf_S = ieee_value(0.0_SiKi, ieee_positive_inf) + END SUBROUTINE Set_IEEE_Constants !======================================================================= SUBROUTINE UsrAlarm diff --git a/modules/nwtc-library/src/SysIVF.f90 b/modules/nwtc-library/src/SysIVF.f90 index ac0c2aefd..15d67062c 100644 --- a/modules/nwtc-library/src/SysIVF.f90 +++ b/modules/nwtc-library/src/SysIVF.f90 @@ -32,7 +32,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -298,7 +298,7 @@ END SUBROUTINE ProgExit ! ( StatCode ) !! precision) This uses standard F03 intrinsic routines, !! however Gnu has not yet implemented it, so we've placed this !! routine in the system-specific code. -SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) +SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) USE, INTRINSIC :: ieee_arithmetic ! use this for compilers that have implemented ieee_arithmetic from F03 standard (otherwise see logic in SysGnu*.f90) @@ -308,12 +308,18 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(ReKi), INTENT(inout) :: Inf !< IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN !< IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S !< IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S !< IEEE value for Inf (infinity) in single precision + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + NaN_S = ieee_value(0.0_SiKi, ieee_quiet_nan) + Inf_S = ieee_value(0.0_SiKi, ieee_positive_inf) + END SUBROUTINE Set_IEEE_Constants !======================================================================= !> This routine generates an alarm to warn the user that something went wrong. diff --git a/modules/nwtc-library/src/SysIVF_Labview.f90 b/modules/nwtc-library/src/SysIVF_Labview.f90 index 05dc72ae5..40b1600e9 100644 --- a/modules/nwtc-library/src/SysIVF_Labview.f90 +++ b/modules/nwtc-library/src/SysIVF_Labview.f90 @@ -43,7 +43,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! Actually, it can't be removed until we get Intel's FLUSH working. (mlb) ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -362,7 +362,7 @@ SUBROUTINE ProgExit ( StatCode ) END SUBROUTINE ProgExit ! ( StatCode ) !======================================================================= - SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE ! values for not-a-number and infinity in sindle and double @@ -377,6 +377,9 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S ! IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S ! IEEE value for Inf (infinity) in single precision + ! local variables for getting values of NaN and Inf (not necessary when using ieee_arithmetic) REAL(DbKi) :: Neg_D ! a negative real(DbKi) number REAL(ReKi) :: Neg ! a negative real(ReKi) number @@ -389,16 +392,20 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) ! set variables to negative numbers to calculate NaNs (compilers may complain when taking sqrt of negative constants) Neg_D = -1.0_DbKi Neg = -1.0_ReKi + Neg_S = -1.0_SiKi NaN_D = SQRT ( Neg_D ) NaN = SQRT ( Neg ) + NaN_S = SQRT ( Neg_S ) ! set variables to zero to calculate Infs (using division by zero) Neg_D = 0.0_DbKi Neg = 0.0_ReKi + Neg_S = 0.0_SiKi Inf_D = 1.0_DbKi / Neg_D Inf = 1.0_ReKi / Neg + Inf_S = 1.0_SiKi / Neg_S #endif END SUBROUTINE Set_IEEE_Constants diff --git a/modules/nwtc-library/src/SysMatlab.f90 b/modules/nwtc-library/src/SysMatlab.f90 index 56180f0eb..cd90670c1 100644 --- a/modules/nwtc-library/src/SysMatlab.f90 +++ b/modules/nwtc-library/src/SysMatlab.f90 @@ -42,7 +42,7 @@ MODULE SysSubs ! SUBROUTINE OpenCon ! Actually, it can't be removed until we get Intel's FLUSH working. (mlb) ! SUBROUTINE OpenUnfInpBEFile ( Un, InFile, RecLen, Error ) ! SUBROUTINE ProgExit ( StatCode ) - ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + ! SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! SUBROUTINE UsrAlarm ! SUBROUTINE WrNR ( Str ) ! SUBROUTINE WrOver ( Str ) @@ -386,7 +386,7 @@ SUBROUTINE ProgExit ( StatCode ) END SUBROUTINE ProgExit ! ( StatCode ) !======================================================================= - SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) + SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf, NaN_S, Inf_S ) ! routine that sets the values of NaN_D, Inf_D, NaN, Inf (IEEE ! values for not-a-number and infinity in sindle and double @@ -403,6 +403,9 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) REAL(ReKi), INTENT(inout) :: Inf ! IEEE value for NaN (not-a-number) REAL(ReKi), INTENT(inout) :: NaN ! IEEE value for Inf (infinity) + REAL(SiKi), INTENT(inout) :: Inf_S ! IEEE value for NaN (not-a-number) in single precision + REAL(SiKi), INTENT(inout) :: NaN_S ! IEEE value for Inf (infinity) in single precision + NaN_D = ieee_value(0.0_DbKi, ieee_quiet_nan) Inf_D = ieee_value(0.0_DbKi, ieee_positive_inf) @@ -410,6 +413,9 @@ SUBROUTINE Set_IEEE_Constants( NaN_D, Inf_D, NaN, Inf ) NaN = ieee_value(0.0_ReKi, ieee_quiet_nan) Inf = ieee_value(0.0_ReKi, ieee_positive_inf) + NaN_S = ieee_value(0.0_SiKi, ieee_quiet_nan) + Inf_S = ieee_value(0.0_SiKi, ieee_positive_inf) + END SUBROUTINE Set_IEEE_Constants !======================================================================= From ee82b50ecbe257355fd96ba693d0460b4ca767c8 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Nov 2019 18:10:36 -0700 Subject: [PATCH 050/377] TCF: modify Waves, Waves2, WAMIT2 for REAL conversion precision --- modules/hydrodyn/src/WAMIT2.f90 | 104 +++++++++++++++--------------- modules/hydrodyn/src/Waves.f90 | 2 +- modules/hydrodyn/src/Waves2.f90 | 110 ++++++++++++++++---------------- 3 files changed, 108 insertions(+), 108 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index a009c18f2..d0f8ae4fa 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -68,7 +68,7 @@ MODULE WAMIT2 !! It is used by the DispNVD routine in the library and as header !! information in output files. - REAL(DbKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of DbKi. + REAL(SiKi), PARAMETER, PRIVATE :: OnePlusEps = 1.0 + EPSILON(OnePlusEps) ! The number slighty greater than unity in the precision of SiKi. ! ..... Public Subroutines ................................................................................................... @@ -795,7 +795,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF COMPLEX(SiKi) :: aWaveElevC !< Wave elevation of current frequency component. NStepWave2 normalization is removed. - REAL(SiKi) :: Omega1 !< Wave frequency of this component + REAL(ReKi) :: Omega1 !< Wave frequency of this component ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms @@ -1108,7 +1108,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. - aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 ! Calculate the frequency Omega1 = J * InitInp%WaveDOmega @@ -1122,7 +1122,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( MnDriftData%DataIs3D ) THEN ! Set the (omega1,beta1,beta2) point we are looking for. - Coord3 = (/ Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! get the interpolated value for F(omega1,beta1,beta2) CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, MnDriftData%Data3D%WvFreq1, & @@ -1131,7 +1131,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ELSE ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! get the interpolated value for F(omega1,omega2,beta1,beta2) CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, MnDriftData%Data4D%WvFreq1, MnDriftData%Data4D%WvFreq2, & @@ -1143,7 +1143,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ELSE ! outside the frequency range - QTF_Value = CMPLX(0.0_SiKi,0.0_SiKi) + QTF_Value = CMPLX(0.0,0.0,SiKi) ENDIF ! frequency check @@ -1160,7 +1160,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the mean drift. ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So ! we throw the complex part out. - QTF_Value = CMPLX(REAL(QTF_Value),0.0_SiKi) + QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) ! Now put it all together... note the frequency stepsize is multiplied after the summation @@ -1264,7 +1264,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1t(:) !< First term in the newman calculation, time domain. Current load dimension. COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2t(:) !< Second term in the newman calculation, time domain. Current load dimension. COMPLEX(SiKi) :: aWaveElevC !< Wave elevation of current frequency component. NStepWave2 factor removed. - REAL(SiKi) :: Omega1 !< Wave frequency of this component + REAL(ReKi) :: Omega1 !< Wave frequency of this component ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms @@ -1594,8 +1594,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg DO I=1,6 ! set zero frequency term to zero - NewmanTerm1C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) - NewmanTerm2C(0) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm1C(0) = CMPLX(0.0, 0.0, SiKi) + NewmanTerm2C(0) = CMPLX(0.0, 0.0, SiKi) IF (NewmanAppData%DataIs3D) THEN TmpFlag = NewmanAppData%Data3D%LoadComponents(I) @@ -1622,7 +1622,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! First get the wave amplitude -- must be reconstructed from the WaveElevC array. First index is the real (1) or ! imaginary (2) part. Divide by NStepWave2 so that the wave amplitude is of the same form as the paper. - aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 ! Calculate the frequency Omega1 = J * InitInp%WaveDOmega @@ -1634,7 +1634,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF ( NewmanAppData%DataIs3D ) THEN ! Set the (omega1,beta1,beta2) point we are looking for. - Coord3 = (/ Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! get the interpolated value for F(omega1,beta1,beta2) CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, NewmanAppData%Data3D%WvFreq1, & @@ -1643,7 +1643,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ELSE ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! get the interpolated value for F(omega1,omega2,beta1,beta2) CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, NewmanAppData%Data4D%WvFreq1, NewmanAppData%Data4D%WvFreq2, & @@ -1655,7 +1655,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ELSE ! outside the frequency range - QTF_Value = CMPLX(0.0_SiKi,0.0_SiKi) + QTF_Value = CMPLX(0.0,0.0,SiKi) ENDIF ! frequency check @@ -1679,24 +1679,24 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So ! we throw the complex part out. - QTF_Value = CMPLX(REAL(QTF_Value),0.0_SiKi) + QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) ! Now we place these results into the arrays IF (REAL(QTF_Value) > 0.0_SiKi) THEN NewmanTerm1C(J) = aWaveElevC * (QTF_Value)**0.5_SiKi - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ELSE IF (REAL(QTF_Value) < 0.0_SiKi) THEN - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) NewmanTerm2C(J) = aWaveElevC * (-QTF_Value)**0.5_SiKi ELSE ! at 0 - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi) + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ENDIF @@ -1841,10 +1841,10 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS COMPLEX(SiKi) :: TmpHMinusC !< Temporary variable for holding the current value of \f$ H^- \f$ COMPLEX(SiKi) :: aWaveElevC1 !< Wave elevation of the first frequency component. NStepWave2 factor removed. COMPLEX(SiKi) :: aWaveElevC2 !< Wave elevation of the second frequency component. NStepWave2 factor removed. - REAL(SiKi) :: OmegaDiff !< Wave difference frequency + REAL(ReKi) :: OmegaDiff !< Wave difference frequency REAL(SiKi), ALLOCATABLE :: TmpDiffQTFForce(:) !< The resulting diffQTF force for this load component - REAL(SiKi) :: Omega1 !< First wave frequency - REAL(SiKi) :: Omega2 !< Second wave frequency + REAL(ReKi) :: Omega1 !< First wave frequency + REAL(ReKi) :: Omega2 !< Second wave frequency REAL(SiKi) :: MnDriftForce(6) !< Mean drift force (first term). MnDrift_InitCalc routine will return this. ! Interpolation routine indices and value to search for, and smaller array to pass @@ -2073,7 +2073,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS TmpData4D = DiffQTFData%Data4D%DataSet(:,:,:,:,I) ! Initialize the temporary array to zero. - TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi) + TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ! Outer loop to create the TmpComplexArr @@ -2087,7 +2087,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS IF ( (OmegaDiff >= InitInp%WvLowCOffD) .AND. (OmegaDiff <= InitInp%WvHiCOffD) ) THEN ! Set the \f$ H^- \f$ term to zero before we start - TmpHMinusC = CMPLX(0.0_SiKi,0.0_SiKi) + TmpHMinusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ! Do the sum over H^- @@ -2099,11 +2099,11 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Find the Wave amplitudes 1 and 2 - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K)) / InitInp%NStepWave2 - aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K)) / InitInp%NStepWave2 + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K), SiKi) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K), SiKi) / InitInp%NStepWave2 ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ Omega1, Omega2, InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & @@ -2128,7 +2128,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ELSE ! outside the frequency range, so - TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi) + TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ENDIF ! frequency check @@ -2280,9 +2280,9 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat COMPLEX(SiKi) :: TmpHPlusC !< Temporary variable for holding the current value of \f$ H^+ \f$ COMPLEX(SiKi) :: aWaveElevC1 !< Wave elevation of the first frequency component. NStepWave2 factor removed. COMPLEX(SiKi) :: aWaveElevC2 !< Wave elevation of the second frequency component. NStepWave2 factor removed. - REAL(SiKi) :: OmegaSum !< Wave difference frequency - REAL(SiKi) :: Omega1 !< First wave frequency - REAL(SiKi) :: Omega2 !< Second wave frequency + REAL(ReKi) :: OmegaSum !< Wave difference frequency + REAL(ReKi) :: Omega1 !< First wave frequency + REAL(ReKi) :: Omega2 !< Second wave frequency ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq @@ -2495,7 +2495,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat LastIndex4 = (/0,0,0,0/) ! Initialize the array to zero - Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi) + Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ! The limits look a little funny. But remember we are placing the value in the 2*J location, @@ -2504,7 +2504,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat DO J=1,FLOOR(REAL(InitInp%NStepWave2-1)/2.0_SiKi) ! The frequency - Omega1 = J * InitInp%WaveDOmega + Omega1 = REAL(J,ReKi) * InitInp%WaveDOmega OmegaSum = 2.0_SiKi * Omega1 ! the sum frequency ! Only perform calculations if the difference frequency is in the right range @@ -2512,10 +2512,10 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Find the wave amplitude at frequency omega - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J)) / InitInp%NStepWave2 + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi ) / InitInp%NStepWave2 ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ Omega1, Omega1, InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & @@ -2547,7 +2547,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat LastIndex4 = (/0,0,0,0/) ! Initialize the temporary arrays for each term to zero. - Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi) + Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ! Check the limits for the high frequency cutoff. If WvHiCOffS is less than the @@ -2583,7 +2583,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Set the \f$ H^+ \f$ term to zero before we start - TmpHPlusC = CMPLX(0.0_SiKi,0.0_SiKi) + TmpHPlusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ! Only perform calculations if the difference frequency is in the right range @@ -2603,11 +2603,11 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat Omega2 = (J-K) * InitInp%WaveDOmega ! Find the wave amplitude at frequency omega. Remove the NStepWave2 normalization built into WaveElevC0 from Waves module - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1, K), InitInp%WaveElevC0(2, K)) / InitInp%NStepWave2 - aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,J-K), InitInp%WaveElevC0(2,J-K)) / InitInp%NStepWave2 + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1, K), InitInp%WaveElevC0(2, K), SiKi ) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,J-K), InitInp%WaveElevC0(2,J-K), SiKi ) / InitInp%NStepWave2 ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ Omega1, Omega2, InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & @@ -2653,7 +2653,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,I) gets overwritten later, so I'm setting the array bounds to be -1. - SumQTFForce(J,I) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J))) + SumQTFForce(J,I) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J), SiKi)) ENDDO ! Copy the last first term to the last so that it is cyclic @@ -3445,7 +3445,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) ELSE IF ( RawData3D(I,1) < 0 ) THEN ! Leave it alone. We will have to fix it afterwards. ELSE - RawData3D(I,1) = TwoPi/RawData3D(I,1) ! First column is Tau1 + RawData3D(I,1) = TwoPi_S/RawData3D(I,1) ! First column is Tau1 ENDIF ENDDO @@ -3786,7 +3786,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) ! Store the data after dimensionalizing Data3D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) = & - InitInp%RhoXg * InitInp%WAMITULEN**K * CMPLX(RawData3D(I,7),RawData3D(I,8)) + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K,SiKi) * CMPLX(RawData3D(I,7),RawData3D(I,8),SiKi) ! Set flag indicating that this value has been inserted. Data3D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4) ) = .TRUE. @@ -4192,14 +4192,14 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ELSE IF ( RawData4D(I,1) < 0 ) THEN ! Leave it alone. We will have to fix it afterwards. ELSE - RawData4D(I,1) = TwoPi/RawData4D(I,1) ! First column is Tau1 + RawData4D(I,1) = TwoPi_S/RawData4D(I,1) ! First column is Tau1 ENDIF IF ( EqualRealNos(RawData4D(I,2), 0.0_SiKi) ) THEN ! Leave it alone. We will have to fix it afterwards. ELSE IF ( RawData4D(I,2) < 0 ) THEN ! Leave it alone. We will have to fix it afterwards. ELSE - RawData4D(I,2) = TwoPi/RawData4D(I,2) ! First column is Tau2 + RawData4D(I,2) = TwoPi_S/RawData4D(I,2) ! First column is Tau2 ENDIF ENDDO @@ -4632,7 +4632,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ! Store the data after dimensionalizing Data4D%DataSet( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = & - InitInp%RhoXg * InitInp%WAMITULEN**K * CMPLX(RawData4D(I,8),RawData4D(I,9)) + REAL(InitInp%RhoXg * InitInp%WAMITULEN**K,SiKi) * CMPLX(RawData4D(I,8),RawData4D(I,9),SiKi) ! Set flag indicating that this value has been inserted. Data4D%DataMask( TmpCoord(1), TmpCoord(2), TmpCoord(3), TmpCoord(4), TmpCoord(5) ) = .TRUE. @@ -4730,17 +4730,17 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) !---------------------------------------------------------------------------------- IF (.NOT. HaveZeroFreq1) THEN - Data4D%DataSet( 1:2,:,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range + Data4D%DataSet( 1:2,:,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values to zero for everything before entered frequency range Data4D%DataMask(1:2,:,:,:,:) = .TRUE. ! Set the mask for these first two frequencies ENDIF - Data4D%DataSet( Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) + Data4D%DataSet( Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) Data4D%DataMask(Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = .TRUE. ! Set the mask for the last two frequencies IF (.NOT. HaveZeroFreq2) THEN - Data4D%DataSet( :,1:2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range + Data4D%DataSet( :,1:2,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values to zero for everything before entered frequency range Data4D%DataMask(:,1:2,:,:,:) = .TRUE. ! Set the mask for these first two frequencies ENDIF - Data4D%DataSet( :,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) + Data4D%DataSet( :,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) Data4D%DataMask(:,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = .TRUE. ! Set the mask for the last two frequencies @@ -5176,7 +5176,7 @@ SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum IsRealNum = .TRUE. else IsRealNum = .FALSE. - ValueRead = NaN ! This is NaN as defined in the NWTC_Num. + ValueRead = NaN_S ! This is NaN as defined in the NWTC_Num. ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine ErrSTat = ErrID_Severe endif @@ -5242,7 +5242,7 @@ SUBROUTINE ReadRealNumber(UnitNum, FileName, VarName, VarRead, StrRead, IsRealNu IsRealNum = .TRUE. else IsRealNum = .FALSE. - VarRead = NaN ! This is NaN as defined in the NWTC_Num. + VarRead = NaN_S ! This is NaN as defined in the NWTC_Num. ErrMsg = 'Not a real number. '//TRIM(ErrMsgTmp)//NewLine ErrStat = ErrStatTmp ! The ErrStatTmp returned by the ReadNum routine is an ErrID level. endif diff --git a/modules/hydrodyn/src/Waves.f90 b/modules/hydrodyn/src/Waves.f90 index 44f90bbd0..d12063102 100644 --- a/modules/hydrodyn/src/Waves.f90 +++ b/modules/hydrodyn/src/Waves.f90 @@ -338,7 +338,7 @@ FUNCTION WaveNumber ( Omega, g, h ) ELSE ! Omega > 0.0; solve for the wavenumber as usual. - C = Omega*Omega*h/g + C = Omega*Omega*h/REAL(g,SiKi) CC = C*C diff --git a/modules/hydrodyn/src/Waves2.f90 b/modules/hydrodyn/src/Waves2.f90 index 33e92f807..cccc0ac34 100644 --- a/modules/hydrodyn/src/Waves2.f90 +++ b/modules/hydrodyn/src/Waves2.f90 @@ -348,7 +348,7 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array WaveElevC0Norm.',ErrStat,ErrMsg,'Waves2_Init') DO I=0,InitInp%NStepWave2 - WaveElevC0Norm(I) = CMPLX( InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I) ) / REAL(InitInp%NStepWave2) + WaveElevC0Norm(I) = CMPLX( InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I), SiKi ) / REAL(InitInp%NStepWave2,SiKi) ENDDO !-------------------------------------------------------------------------------- @@ -647,13 +647,13 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, ! Reset the \f$ H_{\mu^-} \f$ terms to zero before calculating. - WaveVel2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveDynP2CDiff = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2xCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2yCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2zCDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveDynP2CDiff = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ! \f$ \mu^- \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^-} \f$ terms used in the IFFT to find the timeseries. @@ -688,8 +688,8 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !! + \left( |\vec{k_n}| \sin \theta_n - |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & - + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + * ( ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) - k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) ! Get value for \f$ B^- \f$ for the n,m index pair @@ -699,10 +699,10 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Calculate \f$ U^- \f$ terms for the velocity calculations (\f$B^-\f$ provided by waves2::transfuncb_minus) ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor !> * \f$ _x{U}_{nm}^- = B_{nm}^- \left(k_n \cos \theta_n - k_m \cos \theta_m \right) \f$ - Ux_nm_minus = B_minus * ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) + Ux_nm_minus = B_minus * ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) - k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) !> * \f$ _y{U}_{nm}^- = B_{nm}^- \left(k_n \sin \theta_n - k_m \sin \theta_m \right) \f$ - Uy_nm_minus = B_minus * ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) + Uy_nm_minus = B_minus * ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) !> * \f$ _z{U}_{nm}^- = \imath B_{nm}^- k_{nm} \tanh \left( k_{nm} ( h + z ) \right) \f$ Uz_nm_minus = ImagNmbr * B_minus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) @@ -716,7 +716,7 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Dynamic pressure !> * \f$ P_{nm}^- = \rho_\mathrm{w} B_{nm}^- \omega_{\mu^-} \f$ - DynP_nm_minus = InitInp%WtrDens * B_minus * Omega_minus + DynP_nm_minus = REAL(InitInp%WtrDens,SiKi) * B_minus * Omega_minus @@ -1018,21 +1018,21 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, ! Reset the \f$ H_{\mu^+} \f$ terms to zero before calculating. - WaveVel2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveDynP2CSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi) - - WaveVel2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveVel2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveAcc2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) - WaveDynP2CSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi) + WaveVel2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2xCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2yCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2zCSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveDynP2CSumT1 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + + WaveVel2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveVel2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2xCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2yCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveAcc2zCSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + WaveDynP2CSumT2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) !--------------- @@ -1074,8 +1074,8 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !! + |\vec{k_n}| \sin \theta_n ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & - + 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + * ( 2.0_SiKi * k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + 2.0_SiKi * k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) ! Get value for \f$ B+ \f$ for the n,m index pair @@ -1085,10 +1085,10 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Calculate \f$ U^+ \f$ terms for the velocity calculations (\f$B^+\f$ provided by waves2::transfuncb_plus) ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor !> * \f$ _x{U}_{nn}^+ = B_{nn}^+ 2 k_n \cos \theta_n \f$ - Ux_nm_plus = B_plus * 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) + Ux_nm_plus = B_plus * 2.0_SiKi * k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) !> * \f$ _y{U}_{nn}^+ = B_{nn}^+ 2 k_n \sin \theta_n \f$ - Uy_nm_plus = B_plus * 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + Uy_nm_plus = B_plus * 2.0_SiKi * k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) !> * \f$ _z{U}_{nn}^+ = \imath B_{nn}^+ k_{nn} \tanh \left( k_{nn} ( h + z ) \right) \f$ Uz_nm_plus = ImagNmbr * B_plus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) @@ -1102,7 +1102,7 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Dynamic pressure !> * \f$ P_{nn}^+ = \rho_\mathrm{w} B_{nn}^+ \omega_{\mu^+} \f$ - DynP_nm_plus = InitInp%WtrDens * B_plus * Omega_plus + DynP_nm_plus = REAL(InitInp%WtrDens, SiKi) * B_plus * Omega_plus @@ -1176,8 +1176,8 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !! + \left( |\vec{k_n}| \sin \theta_n + |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & - + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) + * ( ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) + k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinxi(WaveKinPrimeMap(I)) & + + ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) * InitInp%WaveKinyi(WaveKinPrimeMap(I)) )) ! Get value for \f$ B+ \f$ for the n,m index pair @@ -1187,10 +1187,10 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Calculate \f$ U^+ \f$ terms for the velocity calculations (\f$B^+\f$ provided by waves2::transfuncb_plus) ! NOTE: InitInp%WtrDpth + WaveKinzi0Prime(I) is the height above the ocean floor !> * \f$ _x{U}_{nm}^+ = B_{nm}^+ \left(k_n \cos \theta_n + k_m \cos \theta_m \right) \f$ - Ux_nm_plus = B_plus * ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) + Ux_nm_plus = B_plus * ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) + k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) !> * \f$ _y{U}_{nm}^+ = B_{nm}^+ \left(k_n \sin \theta_n + k_m \sin \theta_m \right) \f$ - Uy_nm_plus = B_plus * ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) + Uy_nm_plus = B_plus * ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) !> * \f$ _z{U}_{nm}^+ = \imath B_{nm}^+ k_{nm} \tanh \left( k_{nm} ( h + z ) \right) \f$ Uz_nm_plus = ImagNmbr * B_plus * k_nm * tanh( k_nm * ( InitInp%WtrDpth + WaveKinzi0Prime(I) ) ) @@ -1204,7 +1204,7 @@ SUBROUTINE Waves2_Init( InitInp, u, p, x, xd, z, OtherState, y, misc, Interval, !> Dynamic pressure !> * \f$ P_{nm}^+ = \rho_\mathrm{w} B_{nm}^+ \omega_{\mu^+} \f$ - DynP_nm_plus = InitInp%WtrDens * B_plus * Omega_plus + DynP_nm_plus = REAL(InitInp%WtrDens,SiKi) * B_plus * Omega_plus @@ -1444,7 +1444,7 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Diff(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrSta ! Note that TmpFreqSeries was allocated in the calling routine. Probably bad programming ! practice, but I didn't want to have to allocate it at each point. - TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi) + TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) WaveElevSeriesAtXY = 0.0_SiKi ! \f$ \mu^- \f$ loop. This loop is used to construct the full set of \f$ H_{\mu^-} \f$ terms used in the IFFT to find the timeseries. @@ -1476,7 +1476,7 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Diff(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrSta !! !! The value of \f$ D^-_{nm} \f$ is found from by the ::TransFuncD_minus routine. - L_minus = (( D_minus - k_n * k_m * COS(D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m)) - R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi !4.0_SiKi + L_minus = (( D_minus - k_n * k_m * COS(D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitInp%WaveDirArr(m)) - R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi !4.0_SiKi ! Calculate the terms \f$ n,m \f$ necessary for calculations @@ -1490,8 +1490,8 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Diff(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrSta !! + \left( |\vec{k_n}| \sin \theta_n - |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) - k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * XCoord & - + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * YCoord )) + * ( ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) - k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) * XCoord & + + ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) - k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) * YCoord )) !> ### Calculate the inner summation \f$ H^-(\omega_{\mu^-}) \f$ terms for the velocity, acceleration, and pressure. ### @@ -1572,8 +1572,8 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Sum(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStat ! Note that TmpFreqSeries was allocated in the calling routine. Probably bad programming ! practice, but I didn't want to have to allocate it at each point. - TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi) ! used for first term - TmpFreqSeries2 = CMPLX(0.0_SiKi, 0.0_SiKi) ! used for second term + TmpFreqSeries = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ! used for first term + TmpFreqSeries2 = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ! used for second term WaveElevSeriesAtXY = 0.0_SiKi @@ -1612,8 +1612,8 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Sum(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStat !! + |\vec{k_n}| \sin \theta_n ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( 2.0_SiKi * k_n * COS( D2R*InitInp%WaveDirArr(n) ) * XCoord & - + 2.0_SiKi * k_n * SIN( D2R*InitInp%WaveDirArr(n) ) * YCoord )) + * ( 2.0_SiKi * k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) * XCoord & + + 2.0_SiKi * k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) * YCoord )) ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. Note that the phase @@ -1668,7 +1668,7 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Sum(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStat !! + (R_n+R_m) \right] \f$ !! !! The value of \f$ D^-_{nm} \f$ is found from by the ::TransFuncD_plus routine. - L_plus = (( D_plus - k_n * k_m * COS(D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m)) + R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi + L_plus = (( D_plus - k_n * k_m * COS(D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitInp%WaveDirArr(m)) + R_n * R_m )/SQRT( R_n * R_m ) + R_n + R_m) / 4.0_SiKi !> Calculate the dot product of the wavenumbers with the (x,y) location !! This is given by: @@ -1679,8 +1679,8 @@ SUBROUTINE WaveElevTimeSeriesAtXY_Sum(Xcoord,Ycoord, WaveElevSeriesAtXY, ErrStat !! + \left( |\vec{k_n}| \sin \theta_n + |\vec{k_m}| sin \theta_m \right) ~ y \right] \right) \f$ WaveElevxyPrime0 = exp( - ImagNmbr & - * ( ( k_n * COS( D2R*InitInp%WaveDirArr(n) ) + k_m * COS( D2R*InitInp%WaveDirArr(m) ) ) * XCoord & - + ( k_n * SIN( D2R*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R*InitInp%WaveDirArr(m) ) ) * YCoord )) + * ( ( k_n * COS( D2R_S*InitInp%WaveDirArr(n) ) + k_m * COS( D2R_S*InitInp%WaveDirArr(m) ) ) * XCoord & + + ( k_n * SIN( D2R_S*InitInp%WaveDirArr(n) ) + k_m * SIN( D2R_S*InitInp%WaveDirArr(m) ) ) * YCoord )) @@ -1783,7 +1783,7 @@ FUNCTION TransFuncB_minus(n,m,k_n,k_m,z) ! Calculation of B_minus - TransFuncB_minus = InitInp%Gravity*InitInp%Gravity / ( 4.0_SiKi * Omega_n * Omega_m ) & + TransFuncB_minus = REAL(InitInp%Gravity*InitInp%Gravity,SiKi) / ( 4.0_SiKi * Omega_n * Omega_m ) & * COSHNumOvrCOSHDen(k_nm, REAL(InitInp%WtrDpth,SiKi), z) * D_minus / ( Omega_n - Omega_m ) @@ -1844,7 +1844,7 @@ FUNCTION TransFuncB_plus(n,m,k_n,k_m,z) D_plus = TransFuncD_plus(n,m,k_n,k_m,R_n,R_m) ! Calculation of B_plus - TransFuncB_plus = InitInp%Gravity*InitInp%Gravity / ( 4.0_SiKi * Omega_n * Omega_m ) & + TransFuncB_plus = REAL(InitInp%Gravity*InitInp%Gravity,SiKi) / ( 4.0_SiKi * Omega_n * Omega_m ) & * COSHNumOvrCOSHDen(k_nm, REAL(InitInp%WtrDpth,SiKi), z) * D_plus / ( Omega_n + Omega_m ) @@ -1960,7 +1960,7 @@ FUNCTION TransFuncD_minus(n,m,k_n,k_m,R_n,R_m) ! Calculate the two pieces of the numerator Num1 = SqrtRnMinusRm * ( SQRT(R_m) * ( k_n*k_n - R_n*R_n ) - SQRT(R_n) * ( k_m*k_m - R_m*R_m ) ) - Num2 = 2*SqrtRnMinusRm*SqrtRnMinusRm*( k_n * k_m * COS( D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m) ) + R_n*R_m ) + Num2 = 2*SqrtRnMinusRm*SqrtRnMinusRm*( k_n * k_m * COS( D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitInp%WaveDirArr(m) ) + R_n*R_m ) ! Calculate the denominator Den = SqrtRnMinusRm*SqrtRnMinusRm - k_nm * tanh( k_nm * InitInp%WtrDpth ) @@ -2024,7 +2024,7 @@ FUNCTION TransFuncD_plus(n,m,k_n,k_m,R_n,R_m) ! Calculate the two pieces of the numerator Num1 = SqrtRnPlusRm * ( SQRT(R_m) * ( k_n*k_n - R_n*R_n ) + SQRT(R_n) * ( k_m*k_m - R_m*R_m ) ) - Num2 = 2*SqrtRnPlusRm*SqrtRnPlusRm*( k_n * k_m * COS( D2R*InitInp%WaveDirArr(n) - D2R*InitInp%WaveDirArr(m) ) - R_n*R_m ) + Num2 = 2*SqrtRnPlusRm*SqrtRnPlusRm*( k_n * k_m * COS( D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitInp%WaveDirArr(m) ) - R_n*R_m ) ! Calculate the denominator Den = SqrtRnPlusRm*SqrtRnPlusRm - k_nm * tanh( k_nm * InitInp%WtrDpth ) @@ -2058,7 +2058,7 @@ FUNCTION k_nm_minus(n,m,k_n,k_m) k_nm_minus = 0.0_SiKi ! This is just to eliminate any numerical error ELSE !bjj: added abs() because we were getting very small negative numbers here (which should be 0). - k_nm_minus = sqrt( abs( k_n * k_n + k_m * k_m - 2 * k_n * k_m * cos( D2R*InitInp%WaveDirArr(n) - D2R*InitINp%WaveDirArr(m) ) ) ) + k_nm_minus = sqrt( abs( k_n * k_n + k_m * k_m - 2 * k_n * k_m * cos( D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitINp%WaveDirArr(m) ) ) ) ENDIF END FUNCTION k_nm_minus @@ -2083,7 +2083,7 @@ FUNCTION k_nm_plus(n,m,k_n,k_m) IF (n == m ) THEN k_nm_plus = 2.0_SiKi * k_n ! This is just to eliminate any numerical error. ELSE - k_nm_plus = sqrt( k_n * k_n + k_m * k_m + 2 * k_n * k_m * cos( D2R*InitInp%WaveDirArr(n) - D2R*InitINp%WaveDirArr(m) ) ) + k_nm_plus = sqrt( k_n * k_n + k_m * k_m + 2_SiKi * k_n * k_m * cos( D2R_S*InitInp%WaveDirArr(n) - D2R_S*InitINp%WaveDirArr(m) ) ) ENDIF END FUNCTION k_nm_plus From 2d513b3bcd4e93f2ed2571f58382ef7fdd4b1e2b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 14 Nov 2019 14:41:57 -0700 Subject: [PATCH 051/377] TCF: remove the platform force flags from HD input file Also changed pointer for r-test repository to branch with these changes. --- modules/hydrodyn/src/HydroDyn.txt | 12 -- modules/hydrodyn/src/HydroDyn_Input.f90 | 252 +++++++++--------------- modules/hydrodyn/src/HydroDyn_Types.f90 | 108 ---------- modules/hydrodyn/src/WAMIT.txt | 6 - modules/hydrodyn/src/WAMIT_Types.f90 | 42 ---- reg_tests/r-test | 2 +- 6 files changed, 92 insertions(+), 330 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 354e10660..93f3c0120 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -35,18 +35,6 @@ typedef ^ ^ LOGICAL typedef ^ ^ SiKi WaveElevXY {:}{:} - - "Supplied by Driver: X-Y locations for WaveElevation output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number." "m,-" typedef ^ ^ ReKi PtfmLocationX - - - "Supplied by Driver: X coordinate of platform location in the wave field" "m" typedef ^ ^ ReKi PtfmLocationY - - - "Supplied by Driver: Y coordinate of platform location in the wave field" "m" -typedef ^ ^ CHARACTER(80) PtfmSgFChr - - - "Platform horizontal surge translation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmSgF - - - "Optionally Supplied by Driver: Platform horizontal surge translation force (flag)" - -typedef ^ ^ CHARACTER(80) PtfmSwFChr - - - "Platform horizontal sway translation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmSwF - - - "Optionally Supplied by Driver: Platform horizontal sway translation force (flag)" - -typedef ^ ^ CHARACTER(80) PtfmHvFChr - - - "Platform vertical heave translation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmHvF - - - "Optionally Supplied by Driver: Platform vertical heave translation force (flag)" - -typedef ^ ^ CHARACTER(80) PtfmRFChr - - - "Platform roll tilt rotation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmRF - - - "Optionally Supplied by Driver: Platform roll tilt rotation force (flag)" - -typedef ^ ^ CHARACTER(80) PtfmPFChr - - - "Platform pitch tilt rotation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmPF - - - "Optionally Supplied by Driver: Platform pitch tilt rotation force (flag)" - -typedef ^ ^ CHARACTER(80) PtfmYFChr - - - "Platform yaw rotation force (flag) or DEFAULT" - -typedef ^ ^ LOGICAL PtfmYF - - - "Optionally Supplied by Driver: Platform yaw rotation force (flag)" - typedef ^ ^ ReKi AddF0 {:}{:} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - typedef ^ ^ ReKi AddCLin {:}{:}{:} - - "Additional stiffness matrix" - typedef ^ ^ ReKi AddBLin {:}{:}{:} - - "Additional linear damping matrix" - diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 6c9ef3451..afb8859e6 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -1131,97 +1131,97 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) - !------------------------------------------------------------------------------------------------- - ! Data section for Floating platform force flags - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'Floating platform force flags header', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - - ! PtfmSgFChr - Platform horizontal surge translation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmSgFChr, 'PtfmSgFChr', 'Platform horizontal surge translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmSgFChr ) ! Convert Line to upper case. - - - ! PtfmSwFChr - Platform horizontal sway translation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmSwFChr, 'PtfmSwFChr', 'Platform horizontal sway translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmSwFChr ) ! Convert Line to upper case. - - - ! PtfmHvFChr - Platform vertical heave translation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmHvFChr, 'PtfmHvFChr', 'Platform vertical heave translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmHvFChr ) ! Convert Line to upper case. - - - ! PtfmRFChr - Platform roll tilt rotation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmRFChr, 'PtfmRFChr', 'Platform roll tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmRFChr ) ! Convert Line to upper case. - - - ! PtfmPFChr - Platform pitch tilt rotation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmPFChr, 'PtfmPFChr', 'Platform pitch tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmPFChr ) ! Convert Line to upper case. - - - ! PtfmYFChr - Platform yaw rotation force flag - - CALL ReadVar ( UnIn, FileName, InitInp%PtfmYFChr, 'PtfmYFChr', 'Platform yaw rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) - - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - CALL Conv2UC( InitInp%PtfmYFChr ) ! Convert Line to upper case. +! !------------------------------------------------------------------------------------------------- +! ! Data section for Floating platform force flags +! !------------------------------------------------------------------------------------------------- +! +! ! Header +! +! CALL ReadCom( UnIn, FileName, 'Floating platform force flags header', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! +! ! PtfmSgFChr - Platform horizontal surge translation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmSgFChr, 'PtfmSgFChr', 'Platform horizontal surge translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmSgFChr ) ! Convert Line to upper case. +! +! +! ! PtfmSwFChr - Platform horizontal sway translation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmSwFChr, 'PtfmSwFChr', 'Platform horizontal sway translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmSwFChr ) ! Convert Line to upper case. +! +! +! ! PtfmHvFChr - Platform vertical heave translation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmHvFChr, 'PtfmHvFChr', 'Platform vertical heave translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmHvFChr ) ! Convert Line to upper case. +! +! +! ! PtfmRFChr - Platform roll tilt rotation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmRFChr, 'PtfmRFChr', 'Platform roll tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmRFChr ) ! Convert Line to upper case. +! +! +! ! PtfmPFChr - Platform pitch tilt rotation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmPFChr, 'PtfmPFChr', 'Platform pitch tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmPFChr ) ! Convert Line to upper case. +! +! +! ! PtfmYFChr - Platform yaw rotation force flag +! +! CALL ReadVar ( UnIn, FileName, InitInp%PtfmYFChr, 'PtfmYFChr', 'Platform yaw rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) +! +! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) +! IF (ErrStat >= AbortErrLev) THEN +! CALL CleanUp() +! RETURN +! END IF +! +! CALL Conv2UC( InitInp%PtfmYFChr ) ! Convert Line to upper case. @@ -3199,76 +3199,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF - !------------------------------------------------------------------------------------------------- - ! Data section for Floating platform force flags - !------------------------------------------------------------------------------------------------- - -!FIXME: ADP -- the error handling in this section is broken. - - ! If DEFAULT was requested, then the required value has already been set by the calling program - IF ( TRIM(InitInp%PtfmSgFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmSgFChr,*,IOSTAT=IOS) InitInp%PtfmSgF - CALL CheckIOS ( IOS, "", 'PtfmSgF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - IF ( TRIM(InitInp%PtfmSwFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmSwFChr,*,IOSTAT=IOS) InitInp%PtfmSwF - CALL CheckIOS ( IOS, "", 'PtfmSwF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - IF ( TRIM(InitInp%PtfmHvFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmHvFChr,*,IOSTAT=IOS) InitInp%PtfmHvF - CALL CheckIOS ( IOS, "", 'PtfmHvF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - IF ( TRIM(InitInp%PtfmRFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmRFChr,*,IOSTAT=IOS) InitInp%PtfmRF - CALL CheckIOS ( IOS, "", 'PtfmRF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - IF ( TRIM(InitInp%PtfmPFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmPFChr,*,IOSTAT=IOS) InitInp%PtfmPF - CALL CheckIOS ( IOS, "", 'PtfmPF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - IF ( TRIM(InitInp%PtfmYFChr) /= 'DEFAULT' ) THEN - - READ (InitInp%PtfmYFChr,*,IOSTAT=IOS) InitInp%PtfmYF - CALL CheckIOS ( IOS, "", 'PtfmYF', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - END IF - - - ! Add checks that all platform DOF flags are true. TODO: Allow true or false once these have been implemented - - IF ( ( .NOT. InitInp%PtfmSgF ) .OR. ( .NOT. InitInp%PtfmSwF ) .OR. ( .NOT. InitInp%PtfmHvF ) .OR. ( .NOT. InitInp%PtfmRF ) .OR. ( .NOT. InitInp%PtfmPF ) .OR. ( .NOT. InitInp%PtfmYF ) )THEN -! CALL SetErrStat( ErrID_Fatal,'All platform DOF parameters must be set to TRUE. Future versions of HydroDyn will support values of TRUE, FALSE, or DEFAULT.',ErrStat,ErrMsg,RoutineName) - CALL SetErrStat( ErrID_Warn,' Only the second-order floating platform force calculations (WAMIT2 sub-module) allow for selectively dissabling force DOF parameters, the first order (WAMIT sub-module) does not and will calculate all dimensions. Future versions of HydroDyn will support values of TRUE, FALSE, or DEFAULT for both modules.',ErrStat,ErrMsg,RoutineName) - END IF - - !------------------------------------------------------------------------------------------------- ! Second order Forces due to Waves section (WAMIT2 Module) diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 03fc2f4a9..77acaa408 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -56,18 +56,6 @@ MODULE HydroDyn_Types REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< Supplied by Driver: X-Y locations for WaveElevation output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number. [m,-] REAL(ReKi) :: PtfmLocationX !< Supplied by Driver: X coordinate of platform location in the wave field [m] REAL(ReKi) :: PtfmLocationY !< Supplied by Driver: Y coordinate of platform location in the wave field [m] - CHARACTER(80) :: PtfmSgFChr !< Platform horizontal surge translation force (flag) or DEFAULT [-] - LOGICAL :: PtfmSgF !< Optionally Supplied by Driver: Platform horizontal surge translation force (flag) [-] - CHARACTER(80) :: PtfmSwFChr !< Platform horizontal sway translation force (flag) or DEFAULT [-] - LOGICAL :: PtfmSwF !< Optionally Supplied by Driver: Platform horizontal sway translation force (flag) [-] - CHARACTER(80) :: PtfmHvFChr !< Platform vertical heave translation force (flag) or DEFAULT [-] - LOGICAL :: PtfmHvF !< Optionally Supplied by Driver: Platform vertical heave translation force (flag) [-] - CHARACTER(80) :: PtfmRFChr !< Platform roll tilt rotation force (flag) or DEFAULT [-] - LOGICAL :: PtfmRF !< Optionally Supplied by Driver: Platform roll tilt rotation force (flag) [-] - CHARACTER(80) :: PtfmPFChr !< Platform pitch tilt rotation force (flag) or DEFAULT [-] - LOGICAL :: PtfmPF !< Optionally Supplied by Driver: Platform pitch tilt rotation force (flag) [-] - CHARACTER(80) :: PtfmYFChr !< Platform yaw rotation force (flag) or DEFAULT [-] - LOGICAL :: PtfmYF !< Optionally Supplied by Driver: Platform yaw rotation force (flag) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddCLin !< Additional stiffness matrix [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddBLin !< Additional linear damping matrix [-] @@ -284,18 +272,6 @@ SUBROUTINE HydroDyn_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ENDIF DstInitInputData%PtfmLocationX = SrcInitInputData%PtfmLocationX DstInitInputData%PtfmLocationY = SrcInitInputData%PtfmLocationY - DstInitInputData%PtfmSgFChr = SrcInitInputData%PtfmSgFChr - DstInitInputData%PtfmSgF = SrcInitInputData%PtfmSgF - DstInitInputData%PtfmSwFChr = SrcInitInputData%PtfmSwFChr - DstInitInputData%PtfmSwF = SrcInitInputData%PtfmSwF - DstInitInputData%PtfmHvFChr = SrcInitInputData%PtfmHvFChr - DstInitInputData%PtfmHvF = SrcInitInputData%PtfmHvF - DstInitInputData%PtfmRFChr = SrcInitInputData%PtfmRFChr - DstInitInputData%PtfmRF = SrcInitInputData%PtfmRF - DstInitInputData%PtfmPFChr = SrcInitInputData%PtfmPFChr - DstInitInputData%PtfmPF = SrcInitInputData%PtfmPF - DstInitInputData%PtfmYFChr = SrcInitInputData%PtfmYFChr - DstInitInputData%PtfmYF = SrcInitInputData%PtfmYF IF (ALLOCATED(SrcInitInputData%AddF0)) THEN i1_l = LBOUND(SrcInitInputData%AddF0,1) i1_u = UBOUND(SrcInitInputData%AddF0,1) @@ -640,18 +616,6 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF Re_BufSz = Re_BufSz + 1 ! PtfmLocationX Re_BufSz = Re_BufSz + 1 ! PtfmLocationY - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmSgFChr) ! PtfmSgFChr - Int_BufSz = Int_BufSz + 1 ! PtfmSgF - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmSwFChr) ! PtfmSwFChr - Int_BufSz = Int_BufSz + 1 ! PtfmSwF - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmHvFChr) ! PtfmHvFChr - Int_BufSz = Int_BufSz + 1 ! PtfmHvF - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmRFChr) ! PtfmRFChr - Int_BufSz = Int_BufSz + 1 ! PtfmRF - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmPFChr) ! PtfmPFChr - Int_BufSz = Int_BufSz + 1 ! PtfmPF - Int_BufSz = Int_BufSz + 1*LEN(InData%PtfmYFChr) ! PtfmYFChr - Int_BufSz = Int_BufSz + 1 ! PtfmYF Int_BufSz = Int_BufSz + 1 ! AddF0 allocated yes/no IF ( ALLOCATED(InData%AddF0) ) THEN Int_BufSz = Int_BufSz + 2*2 ! AddF0 upper/lower bounds for each dimension @@ -912,42 +876,6 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%PtfmLocationY Re_Xferred = Re_Xferred + 1 - DO I = 1, LEN(InData%PtfmSgFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSgFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSgF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmSwFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSwFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSwF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmHvFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmHvFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmHvF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmRFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmRFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmRF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmPFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmPFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmPF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmYFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmYFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmYF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%AddF0) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1465,42 +1393,6 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%PtfmLocationY = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - DO I = 1, LEN(OutData%PtfmSgFChr) - OutData%PtfmSgFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmSgF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmSwFChr) - OutData%PtfmSwFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmSwF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmHvFChr) - OutData%PtfmHvFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmHvF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmRFChr) - OutData%PtfmRFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmRF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmPFChr) - OutData%PtfmPFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmPF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmYFChr) - OutData%PtfmYFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmYF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddF0 not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index 34fdda8be..723de28e0 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -127,12 +127,6 @@ typedef ^ ^ Conv_Rdtn_P typedef ^ ^ SS_Rad_ParameterType SS_Rdtn - - - "" - typedef ^ ^ SS_Exc_ParameterType SS_Exctn - - - "" - typedef ^ ^ DbKi DT - - - "" - -typedef ^ ^ LOGICAL PtfmSgF - - - "" - -typedef ^ ^ LOGICAL PtfmSwF - - - "" - -typedef ^ ^ LOGICAL PtfmHvF - - - "" - -typedef ^ ^ LOGICAL PtfmRF - - - "" - -typedef ^ ^ LOGICAL PtfmPF - - - "" - -typedef ^ ^ LOGICAL PtfmYF - - - "" - typedef ^ ^ OutParmType OutParam {:} - - "" - typedef ^ ^ INTEGER NumOuts - - - "" - typedef ^ ^ INTEGER NumOutAll - - - "" - diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index cfba05f76..29a0695a3 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -143,12 +143,6 @@ MODULE WAMIT_Types TYPE(SS_Rad_ParameterType) :: SS_Rdtn !< [-] TYPE(SS_Exc_ParameterType) :: SS_Exctn !< [-] REAL(DbKi) :: DT !< [-] - LOGICAL :: PtfmSgF !< [-] - LOGICAL :: PtfmSwF !< [-] - LOGICAL :: PtfmHvF !< [-] - LOGICAL :: PtfmRF !< [-] - LOGICAL :: PtfmPF !< [-] - LOGICAL :: PtfmYF !< [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] INTEGER(IntKi) :: NumOuts !< [-] INTEGER(IntKi) :: NumOutAll !< [-] @@ -4239,12 +4233,6 @@ SUBROUTINE WAMIT_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMs CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN DstParamData%DT = SrcParamData%DT - DstParamData%PtfmSgF = SrcParamData%PtfmSgF - DstParamData%PtfmSwF = SrcParamData%PtfmSwF - DstParamData%PtfmHvF = SrcParamData%PtfmHvF - DstParamData%PtfmRF = SrcParamData%PtfmRF - DstParamData%PtfmPF = SrcParamData%PtfmPF - DstParamData%PtfmYF = SrcParamData%PtfmYF IF (ALLOCATED(SrcParamData%OutParam)) THEN i1_l = LBOUND(SrcParamData%OutParam,1) i1_u = UBOUND(SrcParamData%OutParam,1) @@ -4414,12 +4402,6 @@ SUBROUTINE WAMIT_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, DEALLOCATE(Int_Buf) END IF Db_BufSz = Db_BufSz + 1 ! DT - Int_BufSz = Int_BufSz + 1 ! PtfmSgF - Int_BufSz = Int_BufSz + 1 ! PtfmSwF - Int_BufSz = Int_BufSz + 1 ! PtfmHvF - Int_BufSz = Int_BufSz + 1 ! PtfmRF - Int_BufSz = Int_BufSz + 1 ! PtfmPF - Int_BufSz = Int_BufSz + 1 ! PtfmYF Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no IF ( ALLOCATED(InData%OutParam) ) THEN Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension @@ -4636,18 +4618,6 @@ SUBROUTINE WAMIT_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, ENDIF DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSgF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmSwF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmHvF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmRF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmPF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PtfmYF , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4979,18 +4949,6 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) OutData%DT = DbKiBuf( Db_Xferred ) Db_Xferred = Db_Xferred + 1 - OutData%PtfmSgF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmSwF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmHvF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmRF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmPF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmYF = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/reg_tests/r-test b/reg_tests/r-test index ff0edea69..0d7bc558c 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit ff0edea69b7e182d247302ecf68967b2a4016635 +Subproject commit 0d7bc558c9b5cd08d5350412b0dd06e2bdaad0f3 From f58b12a487f28439c874188b805bf73c2aef4f96 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 14 Nov 2019 14:42:45 -0700 Subject: [PATCH 052/377] TCF: fix for segfault on NBodyMod1 case --- modules/hydrodyn/src/HydroDyn.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 3daed999c..f3681b37f 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1981,6 +1981,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, m%F_PtfmAdd = p%AddF0(:,1) - matmul(p%AddCLin(:,:,1), q) - matmul(p%AddBLin(:,:,1), qdot) - matmul(p%AddBQuad(:,:,1), qdotsq) do iBody = 1, p%NBody indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 ! Attach to the output point mesh y%WAMITMesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2) y%WAMITMesh%Moment(:,iBody) = m%F_PtfmAdd(indxStart+3:indxEnd) From b25c2704c3fa66ac3e0ecb98643e9807687bb1a1 Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Wed, 20 Nov 2019 16:31:12 -0700 Subject: [PATCH 053/377] Expansion of HydroDyn_DriverCode to drive multiple WAMIT bodies indepenently. --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 113 ++++++++++++++++++- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 7054baf4e..81815118e 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -98,6 +98,8 @@ PROGRAM HydroDynDriver REAL(ReKi), ALLOCATABLE :: WAMITin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for WAMIT REAL(ReKi), ALLOCATABLE :: Morisonin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for Morison elements + INTEGER(IntKi) :: NBody ! Number of WAMIT bodies to work with if prescribing kinematics on each body (WAMITInputsMod<0) + INTEGER(IntKi) :: I ! Generic loop counter INTEGER(IntKi) :: J ! Generic loop counter INTEGER(IntKi) :: n ! Loop counter (for time step) @@ -238,6 +240,40 @@ PROGRAM HydroDynDriver CLOSE ( UnWAMITInp ) END IF + ! multi-body kinematics driver option (time, PRP DOFs 1-6, body1 DOFs 1-6, body2 DOFs 1-6...) + IF ( drvrInitInp%WAMITInputsMod < 0 ) THEN + + NBODY = -drvrInitInp%WAMITInputsMod + ! Open the WAMIT inputs data file + CALL GetNewUnit( UnWAMITInp ) + CALL OpenFInpFile ( UnWAMITInp, drvrInitInp%WAMITInputsFile, ErrStat, ErrMsg ) + IF (ErrStat >=AbortErrLev) STOP + + + ALLOCATE ( WAMITin(drvrInitInp%NSteps, 7+6*NBODY), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for WAMITin array.' + CALL WrScr( ErrMsg ) + CLOSE( UnWAMITInp ) + STOP + END IF + + DO n = 1,drvrInitInp%NSteps + READ (UnWAMITInp,*,IOSTAT=ErrStat) (WAMITin (n,J), J=1,7+6*NBODY) + + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error reading the WAMIT input time-series file (for multiple bodies). ' + CALL WrScr( ErrMsg ) + STOP + END IF + END DO + + ! Close the inputs file + CLOSE ( UnWAMITInp ) + ELSE + NBody = 0 + END IF + IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN ! Open the Morison inputs data file @@ -340,7 +376,7 @@ PROGRAM HydroDynDriver ! Set any steady-state inputs, once before the time-stepping loop - IF ( drvrInitInp%WAMITInputsMod /= 2 ) THEN + IF (( drvrInitInp%WAMITInputsMod /= 2 ) .AND. ( drvrInitInp%WAMITInputsMod >= 0 )) THEN u(1)%PRPMesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) @@ -414,6 +450,7 @@ PROGRAM HydroDynDriver Time = 0.0 CALL SimStatus_FirstTime( TiLstPrn, PrevClockTime, SimStrtTime, UsrTime2, time, InitInData%TMax ) + ! loop through time steps DO n = 1, drvrInitInp%NSteps Time = (n-1) * drvrInitInp%TimeInterval @@ -422,7 +459,8 @@ PROGRAM HydroDynDriver ! Modify u (likely from the outputs of another module or a set of test conditions) here: IF ( u(1)%WAMITMesh%Initialized ) THEN - + + ! WAMITInputsMod 2: Reads time series of positions, velocities, and accelerations for the platform reference point IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN u(1)%PRPMesh%TranslationDisp(:,1) = WAMITin(n,2:4) @@ -448,8 +486,77 @@ PROGRAM HydroDynDriver end if END IF + + + !@mhall: new kinematics input for moving bodies individually + ! WAMITInputsMod < 0: Reads time series of positions for each body individually, and uses finite differences to also get velocities and accelerations. + ! The number of bodies is the negative of WAMITInputsMod. + IF ( drvrInitInp%WAMITInputsMod < 0 ) THEN + + ! platform reference point (PRP), and body 1-NBody displacements + u(1)%PRPMesh%TranslationDisp(:,1) = WAMITin(n,2:4) + DO I=1,NBody + u(1)%WAMITMesh%TranslationDisp(:,I) = WAMITin(n, 6*I+2:6*I+4) + END DO + + ! PRP and body 1-NBody orientations (skipping the maxAngle stuff) + CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'PRP orientation', ErrStat, ErrMsg ) + u(1)%PRPMesh%Orientation(:,:,1) = dcm + DO I=1, NBody + CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,6*I+5),ReKi), REAL(WAMITin(n,6*I+6),ReKi), REAL(WAMITin(n,6*I+7),ReKi), dcm, 'body '//I//' orientation', ErrStat, ErrMsg ) + u(1)%PRPMesh%Orientation(:,:,1) = dcm + END DO + + ! use finite differences for velocities and accelerations + IF (n == 1) THEN ! use forward differences for first time step + + u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n+1, 2:4) - WAMITin(n , 2:4))/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n+1, 5:7) - WAMITin(n , 5:7))/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n+2, 2:4) - 2*WAMITin(n+1, 2:4) + WAMITin(n, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n+2, 5:7) - 2*WAMITin(n+1, 5:7) + WAMITin(n, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + + DO I=1,NBody + u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - WAMITin(n , 6*I+2:6*I+4))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - WAMITin(n , 6*I+5:6*I+7))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n+2, 6*I+2:6*I+4) - 2*WAMITin(n+1, 6*I+2:6*I+4) + WAMITin(n, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n+2, 6*I+5:6*I+7) - 2*WAMITin(n+1, 6*I+5:6*I+7) + WAMITin(n, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + END DO + + ELSE IF (n == drvrInitInp%NSteps) THEN ! use backward differences for last time step + + u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n, 2:4) - WAMITin(n-1, 2:4))/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n, 5:7) - WAMITin(n-1, 5:7))/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n, 2:4) - 2*WAMITin(n-1, 2:4) + WAMITin(n-2, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n, 5:7) - 2*WAMITin(n-1, 5:7) + WAMITin(n-2, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + + DO I=1,NBody + u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n, 6*I+2:6*I+4) - WAMITin(n-1, 6*I+2:6*I+4))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n, 6*I+5:6*I+7) - WAMITin(n-1, 6*I+5:6*I+7))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n, 6*I+2:6*I+4) - 2*WAMITin(n-1, 6*I+2:6*I+4) + WAMITin(n-2, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n, 6*I+5:6*I+7) - 2*WAMITin(n-1, 6*I+5:6*I+7) + WAMITin(n-2, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + END DO + + ELSE ! otherwise use central differences for intermediate time steps + + u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n+1, 2:4) - WAMITin(n-1, 2:4))*0.5/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n+1, 5:7) - WAMITin(n-1, 5:7))*0.5/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n+1, 2:4) - 2*WAMITin(n, 2:4) + WAMITin(n-1, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n+1, 5:7) - 2*WAMITin(n, 5:7) + WAMITin(n-1, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + + DO I=1,NBody + u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - WAMITin(n-1, 6*I+2:6*I+4))*0.5/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - WAMITin(n-1, 6*I+5:6*I+7))*0.5/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - 2*WAMITin(n, 6*I+2:6*I+4) + WAMITin(n-1, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - 2*WAMITin(n, 6*I+5:6*I+7) + WAMITin(n-1, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + END DO + + END + + END IF + !@mhall: end of addition + - END IF + END IF ! ( u(1)%WAMITMesh%Initialized ) IF ( u(1)%Morison%DistribMesh%Initialized ) THEN IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN From 59fcdc96be117e841885ab6d74d1fcf4a6795766 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 11:43:06 -0700 Subject: [PATCH 054/377] FlexSub: implemented pretension cable but output may need update --- modules/subdyn/src/SD_FEM.f90 | 261 +++++++++++++++++++------ modules/subdyn/src/SubDyn.f90 | 2 +- modules/subdyn/src/SubDyn_Registry.txt | 24 +-- modules/subdyn/src/SubDyn_Types.f90 | 25 ++- 4 files changed, 231 insertions(+), 81 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 190f036bc..5243c4d81 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -573,7 +573,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, Jn, Kn + INTEGER :: I, J, K, Jn, Kn, iTmp INTEGER, PARAMETER :: NNE=2 ! number of nodes in one element, fixed to 2 INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes @@ -581,9 +581,11 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) REAL(ReKi) :: x1, y1, z1, x2, y2, z2 ! coordinates of the nodes REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices REAL(ReKi) :: L ! length of the element + REAL(ReKi) :: T0 ! pretension force in cable [N] REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector + REAL(ReKi), ALLOCATABLE :: FCe(:) ! Pretension force from cable element INTEGER, DIMENSION(NNE) :: nn ! node number in element INTEGER :: r INTEGER(IntKi) :: eType !< Member type @@ -616,6 +618,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) CALL AllocAry( Ke, NNE*6, NNE*6 , 'Ke', ErrStat2, ErrMsg2); if(Failed()) return; ! element stiffness matrix CALL AllocAry( Me, NNE*6, NNE*6 , 'Me', ErrStat2, ErrMsg2); if(Failed()) return; ! element mass matrix CALL AllocAry( FGe, NNE*6, 'FGe', ErrStat2, ErrMsg2); if(Failed()) return; ! element gravity force vector + CALL AllocAry( FCe, NNE*6, 'FCe', ErrStat2, ErrMsg2); if(Failed()) return; ! element pretension force vector CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector @@ -637,6 +640,12 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) P1 = p%Elems(I, iMProp ) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) + + ! --- Length and Directional cosine + CALL GetDirCos(Init%Nodes(N1,2:4), Init%Nodes(N2,2:4), DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return + + + FCe = 0.0_ReKi if (eType==idBeam) then E = Init%PropsB(P1, 2) G = Init%PropsB(P1, 3) @@ -645,78 +654,101 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) t1 = Init%PropsB(P1, 6) D2 = Init%PropsB(P2, 5) t2 = Init%PropsB(P2, 6) + r1 = 0.25*(D1 + D2) + t = 0.5*(t1+t2) + IF ( EqualRealNos(t, 0.0_ReKi) ) THEN + r2 = 0 + ELSE + r2 = r1 - t + ENDIF + A = Pi_D*(r1*r1-r2*r2) + Ixx = 0.25*Pi_D*(r1**4-r2**4) + Iyy = Ixx + Jzz = 2.0*Ixx + + IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli + Shear = .false. + kappa = 0 + ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko + Shear = .true. + ! kappa = 0.53 + ! equation 13 (Steinboeck et al) in SubDyn Theory Manual + nu = E / (2.0_ReKi*G) - 1.0_ReKi + D_outer = 2.0_ReKi * r1 ! average (outer) diameter + D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter + ratioSq = ( D_inner / D_outer)**2 + kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & + / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) + ENDIF + ! Storing Beam specific properties + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%kappa = kappa + p%ElemProps(i)%YoungE = E + p%ElemProps(i)%ShearG = G + + ! Element matrices and loads + CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) + CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) else if (eType==idCable) then print*,'Member',I,'eType',eType,'Ps',P1,P2 - STOP + A = 1 ! Arbitrary set to 1 + E = Init%PropsC(P1, 2)/A ! Young's modulus, E=EA/A [N/m^2] + rho = Init%PropsC(P1, 3) ! Material density [kg/m3] + T0 = Init%PropsC(P1, 4) ! Pretension force [N] + ! Storing Cable specific properties + p%ElemProps(i)%T0 = T0 + + ! Element matrices and loads + CALL ElemK_Cable(A, L, E, T0, DirCos, Ke) + CALL ElemM_Cable(A, L, rho, DirCos, Me) + CALL ElemF_Cable(A, L, T0, DirCos, FCe) + print*,'K' + do iTmp=1,12 + print'(12(E9.1))',Ke(iTmp,1:12) + enddo + print*,'M' + do iTmp=1,12 + print'(12(E9.1))',Me(iTmp,1:12) + enddo + print*,'F' + print'(12(E9.1))',FCe(1:12) + else if (eType==idRigid) then print*,'Member',I,'eType',eType,'Ps',P1,P2 - STOP + A = 1 ! Arbitrary set to 1 + rho = Init%PropsR(P1, 2) + ! Element matrices and loads + Ke(1:6,1:6)=0 + if ( EqualRealNos(rho, 0.0_ReKi) ) then + Me(1:6,1:6)=0 + else + !CALL ElemM_(A, L, rho, DirCos, Me) + print*,'Mass matrix for rigid members rho/=0 TODO' + STOP + endif else ! Should not happen print*,'Element type unknown',eType STOP end if - x1 = Init%Nodes(N1, 2) - y1 = Init%Nodes(N1, 3) - z1 = Init%Nodes(N1, 4) - - x2 = Init%Nodes(N2, 2) - y2 = Init%Nodes(N2, 3) - z2 = Init%Nodes(N2, 4) - - CALL GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return - - r1 = 0.25*(D1 + D2) - t = 0.5*(t1+t2) - - IF ( EqualRealNos(t, 0.0_ReKi) ) THEN - r2 = 0 - ELSE - r2 = r1 - t - ENDIF - - A = Pi_D*(r1*r1-r2*r2) - Ixx = 0.25*Pi_D*(r1**4-r2**4) - Iyy = Ixx - Jzz = 2.0*Ixx - - IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli - Shear = .false. - kappa = 0 - ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko - Shear = .true. - ! kappa = 0.53 - ! equation 13 (Steinboeck et al) in SubDyn Theory Manual - nu = E / (2.0_ReKi*G) - 1.0_ReKi - D_outer = 2.0_ReKi * r1 ! average (outer) diameter - D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter - ratioSq = ( D_inner / D_outer)**2 - kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & - / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) - ENDIF - - p%ElemProps(i)%Area = A + ! --- Properties common to all element types: + p%ElemProps(i)%Area = A p%ElemProps(i)%Length = L - p%ElemProps(i)%Ixx = Ixx - p%ElemProps(i)%Iyy = Iyy - p%ElemProps(i)%Jzz = Jzz - p%ElemProps(i)%Shear = Shear - p%ElemProps(i)%kappa = kappa - p%ElemProps(i)%YoungE = E - p%ElemProps(i)%ShearG = G - p%ElemProps(i)%Rho = rho + p%ElemProps(i)%Rho = rho p%ElemProps(i)%DirCos = DirCos - - CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) - CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) + ! --- Gravity common to all element CALL ElemG(A, L, rho, DirCos, FGe, Init%g) + ! assemble element matrices to global matrices DO J = 1, NNE jn = nn(j) - Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) ) + Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) )+ FCe( (J*6-5):(J*6) ) DO K = 1, NNE kn = nn(k) Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) @@ -772,8 +804,8 @@ END SUBROUTINE AssembleKM !! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix !! in the FAST framework. It seems to be used consistantly in the code (i.e., the transpose !! of this matrix is used later). -SUBROUTINE GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat, ErrMsg) - REAL(ReKi) , INTENT(IN ) :: x1, y1, z1, x2, y2, z2 ! (x,y,z) positions of two nodes making up an element +SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) + REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) positions of two nodes making up an element REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix REAL(ReKi) , INTENT( OUT) :: L ! length of element INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation @@ -782,9 +814,9 @@ SUBROUTINE GetDirCos(X1, Y1, Z1, X2, Y2, Z2, DirCos, L, ErrStat, ErrMsg) ErrMsg = "" ErrStat = ErrID_None - Dy=y2-y1 - Dx=x2-x1 - Dz=z2-z1 + Dx=P2(1)-P1(1) + Dy=P2(2)-P1(2) + Dz=P2(3)-P1(3) Dxy = sqrt( Dx**2 + Dy**2 ) L = sqrt( Dx**2 + Dy**2 + Dz**2) @@ -898,7 +930,50 @@ SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed END SUBROUTINE ElemK +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for pretension cable +!! Element coordinate system: z along the cable! +SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) + REAL(ReKi), INTENT( IN) :: A, L, E + REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT(OUT) :: K(12, 12) + ! Local variables + REAL(ReKi) :: L0, Eps0, EAL0, EE + REAL(ReKi) :: DC(12, 12) + + Eps0 = T0/(E*A) + L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 + EAL0 = E*A*L0 + EE = EAL0* Eps0/(1+Eps0) + K(1:12,1:12)=0 + + ! Note: only translatoinal DOF involved (1-3, 7-9) + K(1,1)= EE + K(2,2)= EE + K(3,3)= EAL0 + + K(1,7)= -EE + K(2,8)= -EE + K(3,9)= -EAL0 + + K(7,1)= -EE + K(8,2)= -EE + K(9,3)= -EAL0 + + K(7,7)= EE + K(8,8)= EE + K(9,9)= EAL0 + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed +END SUBROUTINE ElemK_Cable !------------------------------------------------------------------------------------------------------ !> Element mass matrix for classical beam elements SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) @@ -968,6 +1043,44 @@ SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) END SUBROUTINE ElemM +!> Element stiffness matrix for pretension cable +SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) + REAL(ReKi), INTENT( IN) :: A, L, rho + REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT(OUT) :: M(12, 12) + ! Local variables + REAL(ReKi) :: DC(12, 12) + REAL(ReKi) :: t + + t = rho*A*L; + + M(1:12,1:12) = 0 + + M( 1, 1) = 13._ReKi/35._ReKi * t + M( 2, 2) = 13._ReKi/35._ReKi * t + M( 3, 3) = t/3.0_ReKi + + M( 7, 7) = 13._ReKi/35._ReKi * t + M( 8, 8) = 13._ReKi/35._ReKi * t + M( 9, 9) = t/3.0_ReKi + + M( 1, 7) = 9._ReKi/70._ReKi * t + M( 2, 8) = 9._ReKi/70._ReKi * t + M( 3, 9) = t/6.0_ReKi + + M( 7, 1) = 9._ReKi/70._ReKi * t + M( 8, 2) = 9._ReKi/70._ReKi * t + M( 9, 3) = t/6.0_ReKi + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed +END SUBROUTINE ElemM_Cable + !------------------------------------------------------------------------------------------------------ !> Sets a list of DOF indices and the value these DOF should have !! NOTE: need p%Reacts to have an updated first column that uses indices and not JointID @@ -1043,6 +1156,34 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) !F(12) is 0 for g along z alone END SUBROUTINE ElemG + +!> +SUBROUTINE ElemF_Cable(A, L, T0, DirCos, F) + REAL(ReKi), INTENT( IN ) :: A !< area + REAL(ReKi), INTENT( IN ) :: L !< element length + REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] + REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. + ! Local variables + REAL(ReKi) :: L0, Eps0, EAL0, EE + REAL(ReKi) :: DC(12, 12) + + F(1:12) = 0 ! init + F(3) = +T0 + F(9) = -T0 + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + F = MATMUL(DC, F)! TODO: change me if DirCos convention is transposed + +END SUBROUTINE ElemF_Cable + + + !------------------------------------------------------------------------------------------------------ !> Calculates the lumped gravity forces at the nodes given the element geometry !! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index fa608b864..188b79bb7 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2687,7 +2687,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) XYZ2=Init%Nodes(Init%Members(i,3),2:4) ENDIF ENDDO - CALL GetDirCos(XYZ1(1), XYZ1(2), XYZ1(3), XYZ2(1), XYZ2(2), XYZ2(3), DirCos, mlength, ErrStat, ErrMsg) + CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mlength, ErrStat, ErrMsg) DirCos=TRANSPOSE(DirCos) !This is now global to local WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3c53d5139..1795f196d 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -52,17 +52,19 @@ typedef ^ FEM_MatArrays INTEGER NOmega - - - "Number of full FEM Eigenvalues (fo typedef ^ FEM_MatArrays ReKi Modes {:}{:} - - "Eigenmodes of full FEM model, we calculate them all" # -typedef ^ ElemPropType ReKi Area - - - "Area of an element" -typedef ^ ^ ReKi Length - - - "Length of an element" -typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" -typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" -typedef ^ ^ ReKi Kappa - - - "Shear coefficient" -typedef ^ ^ ReKi YoungE - - - "Young's modulus" -typedef ^ ^ ReKi ShearG - - - "Shear modulus" -typedef ^ ^ ReKi Rho - - - "Density" -typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" +typedef ^ ElemPropType ReKi Length - - - "Length of an element" +typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" +typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" +typedef ^ ^ ReKi Kappa - - - "Shear coefficient" +typedef ^ ^ ReKi YoungE - - - "Young's modulus" +typedef ^ ^ ReKi ShearG - - - "Shear modulus" N/m^2 +# Properties common to all element types: +typedef ^ ^ ReKi Area - - - "Area of an element" m^2 +typedef ^ ^ ReKi Rho - - - "Density" kg/m^3 +typedef ^ ^ ReKi T0 - - - "Pretension " N +typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" # ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ #--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4f0fc74ef..16df7140c 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -89,7 +89,6 @@ MODULE SubDyn_Types ! ======================= ! ========= ElemPropType ======= TYPE, PUBLIC :: ElemPropType - REAL(ReKi) :: Area !< Area of an element [-] REAL(ReKi) :: Length !< Length of an element [-] REAL(ReKi) :: Ixx !< Moment of inertia of an element [-] REAL(ReKi) :: Iyy !< Moment of inertia of an element [-] @@ -97,8 +96,10 @@ MODULE SubDyn_Types LOGICAL :: Shear !< Use timoshenko (true) E-B (false) [-] REAL(ReKi) :: Kappa !< Shear coefficient [-] REAL(ReKi) :: YoungE !< Young's modulus [-] - REAL(ReKi) :: ShearG !< Shear modulus [-] - REAL(ReKi) :: Rho !< Density [-] + REAL(ReKi) :: ShearG !< Shear modulus [N/m^2] + REAL(ReKi) :: Area !< Area of an element [m^2] + REAL(ReKi) :: Rho !< Density [kg/m^3] + REAL(ReKi) :: T0 !< Pretension [N] REAL(ReKi) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] END TYPE ElemPropType ! ======================= @@ -2359,7 +2360,6 @@ SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCo ! ErrStat = ErrID_None ErrMsg = "" - DstElemPropTypeData%Area = SrcElemPropTypeData%Area DstElemPropTypeData%Length = SrcElemPropTypeData%Length DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy @@ -2368,7 +2368,9 @@ SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCo DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG + DstElemPropTypeData%Area = SrcElemPropTypeData%Area DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho + DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos END SUBROUTINE SD_CopyElemPropType @@ -2418,7 +2420,6 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! Area Re_BufSz = Re_BufSz + 1 ! Length Re_BufSz = Re_BufSz + 1 ! Ixx Re_BufSz = Re_BufSz + 1 ! Iyy @@ -2427,7 +2428,9 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = Re_BufSz + 1 ! Kappa Re_BufSz = Re_BufSz + 1 ! YoungE Re_BufSz = Re_BufSz + 1 ! ShearG + Re_BufSz = Re_BufSz + 1 ! Area Re_BufSz = Re_BufSz + 1 ! Rho + Re_BufSz = Re_BufSz + 1 ! T0 Re_BufSz = Re_BufSz + SIZE(InData%DirCos) ! DirCos IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -2456,8 +2459,6 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Area - Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Length Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ixx @@ -2474,8 +2475,12 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%ShearG Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Area + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Rho Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%T0 + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%DirCos) END SUBROUTINE SD_PackElemPropType @@ -2514,8 +2519,6 @@ SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%Area = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 OutData%Length = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%Ixx = ReKiBuf( Re_Xferred ) @@ -2532,8 +2535,12 @@ SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%ShearG = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%Area = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%Rho = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%T0 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 i1_l = LBOUND(OutData%DirCos,1) i1_u = UBOUND(OutData%DirCos,1) i2_l = LBOUND(OutData%DirCos,2) From 68c473abfce2aaad846e5e65cb6681271cf34979 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 17:58:47 -0700 Subject: [PATCH 055/377] FlexSub: usng correct matrices for output elements --- modules/subdyn/src/SD_FEM.f90 | 33 ++++++++------- modules/subdyn/src/SubDyn_Output.f90 | 61 +++++++++++++++++++++------- 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 5243c4d81..c6e4e0fd7 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -86,11 +86,11 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) CALL AllocAry(Init%NodesConnE, Init%NNode, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; CALL AllocAry(Init%NodesConnN, Init%NNode, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; Init%NodesConnE = 0 - Init%NodesConnN = 0 + Init%NodesConnN = -99999 ! Not Used ! find the node connectivity, nodes/elements that connect to a common node DO I = 1, Init%NNode - Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array + !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array k = 0 DO J = 1, Init%NElem !This should be vectorized IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element @@ -99,19 +99,23 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); endif Init%NodesConnE(I, k + 1) = p%Elems(J, 1) - Init%NodesConnN(I, k + 1) = p%Elems(J, 3) - IF ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element + !if ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) then + ! Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element + !else + ! Init%NodesConnN(I, k + 1) = p%Elems(J, 3) + !endif ENDIF ENDDO - IF( k>1 )THEN ! sort the nodes ascendingly - SortA(1:k, 1) = Init%NodesConnN(I, 3:(k+2)) - CALL QsortC( SortA(1:k, 1:1) ) - Init%NodesConnN(I, 3:(k+2)) = SortA(1:k, 1) - ENDIF + !IF( k>1 )THEN ! sort the nodes ascendingly + ! SortA(1:k, 1) = Init%NodesConnN(I, 3:(k+2)) + ! CALL QsortC( SortA(1:k, 1:1) ) + ! Init%NodesConnN(I, 3:(k+2)) = SortA(1:k, 1) + !ENDIF Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column - Init%NodesConnN(I, 2) = k + !Init%NodesConnN(I, 2) = k + !print*,'ConnE',I,'val',Init%NodesConnE(I, 1:5) ENDDO END SUBROUTINE NodeCon @@ -630,9 +634,8 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) ! loop over all elements DO I = 1, Init%NElem - DO J = 1, NNE - NN(J) = p%Elems(I, J + 1) - ENDDO + NN(1) = p%Elems(I, 2) + NN(2) = p%Elems(I, 3) N1 = p%Elems(I, 2) N2 = p%Elems(I, NNE + 1) @@ -722,9 +725,9 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) A = 1 ! Arbitrary set to 1 rho = Init%PropsR(P1, 2) ! Element matrices and loads - Ke(1:6,1:6)=0 + Ke(1:12,1:12)=0 if ( EqualRealNos(rho, 0.0_ReKi) ) then - Me(1:6,1:6)=0 + Me(1:12,1:12)=0 else !CALL ElemM_(A, L, rho, DirCos, Me) print*,'Mass matrix for rigid members rho/=0 TODO' diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 1a5e3c38a..8faf8a965 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -3776,7 +3776,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module paramters + TYPE(SD_ParameterType), INTENT( INOUT ), target :: p ! SubDyn module paramters TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine @@ -3788,6 +3788,9 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters INTEGER(IntKi) :: Junk !Temporary Holders INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time + INTEGER(IntKi) :: eType + TYPE(ElemPropType), pointer :: eP !< Element Property, Alias to shorten notations + REAL(ReKi) :: FCe(12) ! Pretension force from cable element !------------------------------------------------------------------------------------------------- ! Initialize local variables !------------------------------------------------------------------------------------------------- @@ -3901,28 +3904,56 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) K2=0 !Initialize counter DO K=1, NconEls L=Init%NodesConnE(p%MoutLst(I)%NodeIDs(J),k+1) !k-th Element Number - M=p%Elems(L,2:3) !1st and 2nd node of the k-th element + M = p%Elems(L,2:3) !1st and 2nd node of the k-th element + eType = p%Elems(L, iMType) - !Select only the other node, not the one where elements connect to + !Select only the other node, not the one where elements connect to + IF (M(1) .EQ. p%MoutLst(I)%NodeIDs(J)) then + Junk=M(2) + else Junk=M(1) - IF (M(1) .EQ. p%MoutLst(I)%NodeIDs(J)) Junk=M(2) + endif IF (ANY(Init%MemberNodes(p%MoutLst(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + !print*,'L',L, 'M',M + !print*,'etype',eType IF (K2 .EQ. 2) EXIT K2=K2+1 p%MoutLst(I)%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 - p%MoutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MoutLst(I)%NodeIDs(J) ) p%MoutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element - - !Calculate Ke, Me to be used for output - CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & - p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & - p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) - CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& - p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) - - CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst(I)%Fg(:,J,K2), Init%g ) + IF (M(2) .EQ. p%MoutLst(I)%NodeIDs(J) )then + p%MoutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element + else + p%MoutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element + endif + + eP => p%elemprops(L) + if (eType==idBeam) then + !Calculate Ke, Me to be used for output + CALL ElemK( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) + CALL ElemM( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho , eP%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) + FCe(1:12)=0 + + else if (eType==idCable) then + CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2)) + CALL ElemM_Cable(ep%Area, ep%Length, ep%rho , ep%DirCos, p%MoutLst(I)%Me(:,:,J,K2)) + CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, FCe) + + else if (eType==idRigid) then + FCe(1:12)=0 + p%MoutLst(I)%Ke(1:12,1:12,J,K2) =0.0_ReKi + if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then + p%MoutLst(I)%Me(1:12,1:12,J,K2)=0.0_ReKi + else + !CALL ElemM_(A, L, rho, DirCos, Me) + print*,'SD_Output: Mass matrix for rigid members rho/=0 TODO' + STOP + endif + endif + + CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, p%MoutLst(I)%Fg(:,J,K2), Init%g ) + ! Adding cable element force to gravity vector + p%MoutLst(I)%Fg(:,J,K2) = p%MoutLst(I)%Fg(:,J,K2) + FCe(1:12) END IF ENDDO ENDDO From 7a27f378bd8761e140fc691ea3644855355117c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 18:41:29 -0700 Subject: [PATCH 056/377] FlexSub: introducing wrappers for element M, K, F --- modules/subdyn/src/SD_FEM.f90 | 156 ++++++++++++++----------- modules/subdyn/src/SubDyn_Output.f90 | 65 ++++++----- modules/subdyn/src/SubDyn_Registry.txt | 3 +- modules/subdyn/src/SubDyn_Types.f90 | 7 ++ 4 files changed, 131 insertions(+), 100 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index c6e4e0fd7..eeb197514 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -588,8 +588,8 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) REAL(ReKi) :: T0 ! pretension force in cable [N] REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear - REAL(ReKi), ALLOCATABLE :: Ke(:,:), Me(:, :), FGe(:) ! element stiffness and mass matrices gravity force vector - REAL(ReKi), ALLOCATABLE :: FCe(:) ! Pretension force from cable element + REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector + REAL(ReKi) :: FCe(12) ! Pretension force from cable element INTEGER, DIMENSION(NNE) :: nn ! node number in element INTEGER :: r INTEGER(IntKi) :: eType !< Member type @@ -619,24 +619,16 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) return ENDIF - CALL AllocAry( Ke, NNE*6, NNE*6 , 'Ke', ErrStat2, ErrMsg2); if(Failed()) return; ! element stiffness matrix - CALL AllocAry( Me, NNE*6, NNE*6 , 'Me', ErrStat2, ErrMsg2); if(Failed()) return; ! element mass matrix - CALL AllocAry( FGe, NNE*6, 'FGe', ErrStat2, ErrMsg2); if(Failed()) return; ! element gravity force vector - CALL AllocAry( FCe, NNE*6, 'FCe', ErrStat2, ErrMsg2); if(Failed()) return; ! element pretension force vector CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector Init%K = 0.0_ReKi Init%M = 0.0_ReKi Init%FG = 0.0_ReKi - - ! loop over all elements + ! Loop over all elements and set ElementProperties DO I = 1, Init%NElem - NN(1) = p%Elems(I, 2) - NN(2) = p%Elems(I, 3) - N1 = p%Elems(I, 2) N2 = p%Elems(I, NNE + 1) @@ -644,11 +636,13 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) - ! --- Length and Directional cosine - CALL GetDirCos(Init%Nodes(N1,2:4), Init%Nodes(N2,2:4), DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return - + ! --- Properties common to all element types: + CALL GetDirCos(Init%Nodes(N1,2:4), Init%Nodes(N2,2:4), DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos + p%ElemProps(i)%eType = eType + p%ElemProps(i)%Length = L + p%ElemProps(i)%DirCos = DirCos - FCe = 0.0_ReKi + ! --- Properties that are specific to some elements if (eType==idBeam) then E = Init%PropsB(P1, 2) G = Init%PropsB(P1, 3) @@ -691,63 +685,39 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) p%ElemProps(i)%kappa = kappa p%ElemProps(i)%YoungE = E p%ElemProps(i)%ShearG = G + p%ElemProps(i)%Area = A + p%ElemProps(i)%Rho = rho - ! Element matrices and loads - CALL ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, Ke) - CALL ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, Me) else if (eType==idCable) then print*,'Member',I,'eType',eType,'Ps',P1,P2 - A = 1 ! Arbitrary set to 1 - E = Init%PropsC(P1, 2)/A ! Young's modulus, E=EA/A [N/m^2] - rho = Init%PropsC(P1, 3) ! Material density [kg/m3] - T0 = Init%PropsC(P1, 4) ! Pretension force [N] - ! Storing Cable specific properties - p%ElemProps(i)%T0 = T0 - - ! Element matrices and loads - CALL ElemK_Cable(A, L, E, T0, DirCos, Ke) - CALL ElemM_Cable(A, L, rho, DirCos, Me) - CALL ElemF_Cable(A, L, T0, DirCos, FCe) - print*,'K' - do iTmp=1,12 - print'(12(E9.1))',Ke(iTmp,1:12) - enddo - print*,'M' - do iTmp=1,12 - print'(12(E9.1))',Me(iTmp,1:12) - enddo - print*,'F' - print'(12(E9.1))',FCe(1:12) + p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 + p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] + p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] + p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] - else if (eType==idRigid) then print*,'Member',I,'eType',eType,'Ps',P1,P2 - A = 1 ! Arbitrary set to 1 - rho = Init%PropsR(P1, 2) - ! Element matrices and loads - Ke(1:12,1:12)=0 - if ( EqualRealNos(rho, 0.0_ReKi) ) then - Me(1:12,1:12)=0 - else - !CALL ElemM_(A, L, rho, DirCos, Me) - print*,'Mass matrix for rigid members rho/=0 TODO' - STOP - endif + p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 + p%ElemProps(i)%Rho = Init%PropsR(P1, 2) + else ! Should not happen print*,'Element type unknown',eType STOP end if + ENDDO ! I end loop over elements + + + ! loop over all elements + DO I = 1, Init%NElem + NN(1) = p%Elems(I, 2) + NN(2) = p%Elems(I, 3) + + ! --- Element Me,Ke,Fg, Fce + CALL ElemM(p%ElemProps(i), Me) + CALL ElemK(p%ElemProps(i), Ke) + CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) - ! --- Properties common to all element types: - p%ElemProps(i)%Area = A - p%ElemProps(i)%Length = L - p%ElemProps(i)%Rho = rho - p%ElemProps(i)%DirCos = DirCos - ! --- Gravity common to all element - CALL ElemG(A, L, rho, DirCos, FGe, Init%g) - - ! assemble element matrices to global matrices DO J = 1, NNE jn = nn(j) @@ -794,9 +764,7 @@ SUBROUTINE Fatal(ErrMsg_in) END SUBROUTINE Fatal SUBROUTINE CleanUp_AssembleKM() - IF(ALLOCATED(Ke )) DEALLOCATE(Ke ) - IF(ALLOCATED(Me )) DEALLOCATE(Me ) - IF(ALLOCATED(FGe)) DEALLOCATE(FGe) + !pass END SUBROUTINE CleanUp_AssembleKM END SUBROUTINE AssembleKM @@ -856,11 +824,65 @@ SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) END SUBROUTINE GetDirCos + +SUBROUTINE ElemM(ep, Me) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(OUT) :: Me(12, 12) + if (ep%eType==idBeam) then + !Calculate Ke, Me to be used for output + CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) + + else if (ep%eType==idCable) then + CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) + + else if (ep%eType==idRigid) then + if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then + Me=0.0_ReKi + else + !CALL ElemM_(A, L, rho, DirCos, Me) + print*,'SD_GEM: Mass matrix for rigid members rho/=0 TODO' + STOP + endif + endif +END SUBROUTINE ElemM + +SUBROUTINE ElemK(ep, Ke) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(OUT) :: Ke(12, 12) + + if (ep%eType==idBeam) then + CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) + + else if (ep%eType==idCable) then + CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) + + else if (ep%eType==idRigid) then + Ke = 0.0_ReKi + endif +END SUBROUTINE ElemK + +SUBROUTINE ElemF(ep, gravity, Fg, Fo) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity + REAL(ReKi), INTENT(OUT) :: Fg(12) + REAL(ReKi), INTENT(OUT) :: Fo(12) + if (ep%eType==idBeam) then + Fo(1:12)=0 + else if (ep%eType==idCable) then + CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, Fo) + else if (ep%eType==idRigid) then + Fo(1:12)=0 + endif + CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) +END SUBROUTINE ElemF + + + !------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for classical beam elements !! shear is true -- non-tapered Timoshenko beam !! shear is false -- non-tapered Euler-Bernoulli beam -SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) +SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa REAL(ReKi), INTENT( IN) :: DirCos(3,3) LOGICAL , INTENT( IN) :: Shear @@ -932,7 +954,7 @@ SUBROUTINE ElemK(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed -END SUBROUTINE ElemK +END SUBROUTINE ElemK_Beam !------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for pretension cable !! Element coordinate system: z along the cable! @@ -979,7 +1001,7 @@ SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) END SUBROUTINE ElemK_Cable !------------------------------------------------------------------------------------------------------ !> Element mass matrix for classical beam elements -SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) +SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho REAL(ReKi), INTENT( IN) :: DirCos(3,3) REAL(ReKi), INTENT(OUT) :: M(12, 12) @@ -1044,7 +1066,7 @@ SUBROUTINE ElemM(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed -END SUBROUTINE ElemM +END SUBROUTINE ElemM_Beam !> Element stiffness matrix for pretension cable SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 8faf8a965..2913564ad 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -3766,14 +3766,9 @@ MODULE SubDyn_Output CONTAINS -SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) -! This subroutine initializes the output module, checking if the output parameter list (OutList) +!> This subroutine initializes the output module, checking if the output parameter list (OutList) ! contains valid names, and opening the output file if there are any requested outputs -!---------------------------------------------------------------------------------------------------- - - -! Passed variables - +SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data TYPE(SD_ParameterType), INTENT( INOUT ), target :: p ! SubDyn module paramters @@ -3782,9 +3777,9 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters INTEGER(IntKi) :: Junk !Temporary Holders INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time @@ -3928,28 +3923,28 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) endif eP => p%elemprops(L) - if (eType==idBeam) then + !if (eType==idBeam) then !Calculate Ke, Me to be used for output - CALL ElemK( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) - CALL ElemM( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho , eP%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) + CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) + CALL ElemM_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho , eP%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) FCe(1:12)=0 - else if (eType==idCable) then - CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2)) - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho , ep%DirCos, p%MoutLst(I)%Me(:,:,J,K2)) - CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, FCe) - - else if (eType==idRigid) then - FCe(1:12)=0 - p%MoutLst(I)%Ke(1:12,1:12,J,K2) =0.0_ReKi - if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then - p%MoutLst(I)%Me(1:12,1:12,J,K2)=0.0_ReKi - else - !CALL ElemM_(A, L, rho, DirCos, Me) - print*,'SD_Output: Mass matrix for rigid members rho/=0 TODO' - STOP - endif - endif +! else if (eType==idCable) then +! CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2)) +! CALL ElemM_Cable(ep%Area, ep%Length, ep%rho , ep%DirCos, p%MoutLst(I)%Me(:,:,J,K2)) +! CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, FCe) +! +! else if (eType==idRigid) then +! FCe(1:12)=0 +! p%MoutLst(I)%Ke(1:12,1:12,J,K2) =0.0_ReKi +! if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then +! p%MoutLst(I)%Me(1:12,1:12,J,K2)=0.0_ReKi +! else +! !CALL ElemM_(A, L, rho, DirCos, Me) +! print*,'SD_Output: Mass matrix for rigid members rho/=0 TODO' +! STOP +! endif +! endif CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, p%MoutLst(I)%Fg(:,J,K2), Init%g ) ! Adding cable element force to gravity vector @@ -4014,10 +4009,10 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF (M(2) .EQ. p%MoutLst2(I)%NodeIDs(J) ) p%MoutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element !Calculate Ke, Me to be used for output - CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst2(I)%Ke2(:,:,K2) ) - CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Me2(:,:,K2) ) CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Fg2(:,K2), Init%g ) @@ -4120,10 +4115,10 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF (M(2) .EQ. p%MoutLst3(I)%Noutcnt ) p%MoutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element !Calculate Ke, Me to be used for output - CALL ElemK( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst3(I)%Ke(:,:,1,K) ) - CALL ElemM( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Me(:,:,1,K) ) CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Fg(:,1,K), Init%g ) @@ -4164,6 +4159,12 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) RETURN +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SDOut_Init') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed END SUBROUTINE SDOut_Init !------------------------------------------------------------------------------------------------------ diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 1795f196d..7da019794 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -52,7 +52,8 @@ typedef ^ FEM_MatArrays INTEGER NOmega - - - "Number of full FEM Eigenvalues (fo typedef ^ FEM_MatArrays ReKi Modes {:}{:} - - "Eigenmodes of full FEM model, we calculate them all" # -typedef ^ ElemPropType ReKi Length - - - "Length of an element" +typedef ^ ElemPropType IntKi eType - - - "Element Type" +typedef ^ ^ ReKi Length - - - "Length of an element" typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 16df7140c..bdd7c1fbe 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -89,6 +89,7 @@ MODULE SubDyn_Types ! ======================= ! ========= ElemPropType ======= TYPE, PUBLIC :: ElemPropType + INTEGER(IntKi) :: eType !< Element Type [-] REAL(ReKi) :: Length !< Length of an element [-] REAL(ReKi) :: Ixx !< Moment of inertia of an element [-] REAL(ReKi) :: Iyy !< Moment of inertia of an element [-] @@ -2360,6 +2361,7 @@ SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCo ! ErrStat = ErrID_None ErrMsg = "" + DstElemPropTypeData%eType = SrcElemPropTypeData%eType DstElemPropTypeData%Length = SrcElemPropTypeData%Length DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy @@ -2420,6 +2422,7 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! eType Re_BufSz = Re_BufSz + 1 ! Length Re_BufSz = Re_BufSz + 1 ! Ixx Re_BufSz = Re_BufSz + 1 ! Iyy @@ -2459,6 +2462,8 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%eType + Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Length Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ixx @@ -2519,6 +2524,8 @@ SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 + OutData%eType = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 OutData%Length = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%Ixx = ReKiBuf( Re_Xferred ) From 3909de74625b65fe66edd3c955b5720f4845b0a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 19:03:45 -0700 Subject: [PATCH 057/377] FlexSub: splitted element properties and matrix assembly --- modules/subdyn/src/SD_FEM.f90 | 139 +++++++++++++++++----------------- modules/subdyn/src/SubDyn.f90 | 5 ++ 2 files changed, 75 insertions(+), 69 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index eeb197514..1cdbdeee0 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -570,73 +570,41 @@ SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) END SUBROUTINE SetNewProp !------------------------------------------------------------------------------------------------------ -!> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init +!> Set Element properties p%ElemProps, different properties are set depening on element type.. +SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, Jn, Kn, iTmp - INTEGER, PARAMETER :: NNE=2 ! number of nodes in one element, fixed to 2 + INTEGER :: I, J, K, iTmp INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section - REAL(ReKi) :: x1, y1, z1, x2, y2, z2 ! coordinates of the nodes REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices REAL(ReKi) :: L ! length of the element REAL(ReKi) :: T0 ! pretension force in cable [N] REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear - REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector - REAL(ReKi) :: FCe(12) ! Pretension force from cable element - INTEGER, DIMENSION(NNE) :: nn ! node number in element - INTEGER :: r INTEGER(IntKi) :: eType !< Member type INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 + ErrMsg = "" + ErrStat = ErrID_None - ! for current application - if (Init%FEMMod == 2) THEN ! tapered Euler-Bernoulli - CALL Fatal ('FEMMod = 2 is not implemented.') - return - elseif (Init%FEMMod == 4) THEN ! tapered Timoshenko - CALL Fatal ('FEMMod = 2 is not implemented.') - return - elseif ((Init%FEMMod == 1) .or. (Init%FEMMod == 3)) THEN ! - ! 1: uniform Euler-Bernouli, 3: uniform Timoshenko - else - CALL Fatal('FEMMod is not valid. Please choose from 1, 2, 3, and 4. ') - return - endif - - ! total degrees of freedom of the system - Init%TDOF = 6*Init%NNode - - ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL Fatal('Error allocating p%ElemProps') - return - ENDIF - - CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%m, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - Init%K = 0.0_ReKi - Init%M = 0.0_ReKi - Init%FG = 0.0_ReKi + ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2); ErrMsg2='Error allocating p%ElemProps' + if(Failed()) return ! Loop over all elements and set ElementProperties - DO I = 1, Init%NElem - - N1 = p%Elems(I, 2) - N2 = p%Elems(I, NNE + 1) + do I = 1, Init%NElem + N1 = p%Elems(I, 2) + N2 = p%Elems(I, 3) P1 = p%Elems(I, iMProp ) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) - ! --- Properties common to all element types: + ! --- Properties common to all element types: L, DirCos (and Area and rho) CALL GetDirCos(Init%Nodes(N1,2:4), Init%Nodes(N2,2:4), DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos p%ElemProps(i)%eType = eType p%ElemProps(i)%Length = L @@ -653,20 +621,20 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) t2 = Init%PropsB(P2, 6) r1 = 0.25*(D1 + D2) t = 0.5*(t1+t2) - IF ( EqualRealNos(t, 0.0_ReKi) ) THEN + if ( EqualRealNos(t, 0.0_ReKi) ) then r2 = 0 - ELSE + else r2 = r1 - t - ENDIF + endif A = Pi_D*(r1*r1-r2*r2) Ixx = 0.25*Pi_D*(r1**4-r2**4) Iyy = Ixx Jzz = 2.0*Ixx - IF( Init%FEMMod == 1 ) THEN ! uniform Euler-Bernoulli + if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli Shear = .false. kappa = 0 - ELSEIF( Init%FEMMod == 3 ) THEN ! uniform Timoshenko + elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko Shear = .true. ! kappa = 0.53 ! equation 13 (Steinboeck et al) in SubDyn Theory Manual @@ -676,13 +644,13 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) ratioSq = ( D_inner / D_outer)**2 kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) - ENDIF + endif ! Storing Beam specific properties - p%ElemProps(i)%Ixx = Ixx - p%ElemProps(i)%Iyy = Iyy - p%ElemProps(i)%Jzz = Jzz - p%ElemProps(i)%Shear = Shear - p%ElemProps(i)%kappa = kappa + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%kappa = kappa p%ElemProps(i)%YoungE = E p%ElemProps(i)%ShearG = G p%ElemProps(i)%Area = A @@ -705,13 +673,46 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) print*,'Element type unknown',eType STOP end if - ENDDO ! I end loop over elements + enddo ! I end loop over elements +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed +END SUBROUTINE SetElementProperties +!------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector +SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K, jn, kn + INTEGER :: iGlob + REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + INTEGER, DIMENSION(2) :: nn ! node number in element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + ErrMsg = "" + ErrStat = ErrID_None + + ! total degrees of freedom of the system + Init%TDOF = 6*Init%NNode + + CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + Init%K = 0.0_ReKi + Init%M = 0.0_ReKi + Init%FG = 0.0_ReKi - ! loop over all elements - DO I = 1, Init%NElem - NN(1) = p%Elems(I, 2) - NN(2) = p%Elems(I, 3) + ! loop over all elements, compute element matrices and assemble into global matrices + DO i = 1, Init%NElem + nn(1) = p%Elems(i, 2) + nn(2) = p%Elems(i, 3) ! --- Element Me,Ke,Fg, Fce CALL ElemM(p%ElemProps(i), Me) @@ -719,33 +720,33 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) ! assemble element matrices to global matrices - DO J = 1, NNE + DO J = 1, 2 jn = nn(j) Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) )+ FCe( (J*6-5):(J*6) ) - DO K = 1, NNE + DO K = 1, 2 kn = nn(k) Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Me( (J*6-5):(J*6), (K*6-5):(K*6) ) ENDDO !K ENDDO !J - ENDDO ! I end loop over elements + ENDDO ! end loop over elements , i ! add concentrated mass DO I = 1, Init%NCMass DO J = 1, 3 - r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J - Init%M(r, r) = Init%M(r, r) + Init%CMass(I, 2) + iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) ENDDO DO J = 4, 6 - r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J - Init%M(r, r) = Init%M(r, r) + Init%CMass(I, J-1) + iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) ENDDO ENDDO ! Loop on concentrated mass ! add concentrated mass induced gravity force DO I = 1, Init%NCMass - r = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 - Init%FG(r) = Init%FG(r) - Init%CMass(I, 2)*Init%g + iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 + Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO ! I concentrated mass induced gravity CALL CleanUp_AssembleKM() diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 188b79bb7..96f0dd804 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -307,6 +307,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! sets Init%NNode, Init%NElm CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + ! Set element properties (p%ElemProps) + CALL SetElementProperties(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + ! Assemble Stiffness and mass matrix CALL AssembleKM(Init,p, ErrStat2, ErrMsg2); if(Failed()) return @@ -797,6 +800,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) IF (Check( (p%IntMethod < 1) .OR.(p%IntMethod > 4) , 'IntMethod must be 1 through 4.')) return IF (Check( (Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) , 'FEMMod must be 0, 1, 2, or 3.')) return IF (Check( Init%NDiv < 1 , 'NDiv must be a positive integer')) return +IF (Check( Init%FEMMod==2 , 'FEMMod = 2 (tapered Euler-Bernoulli) not implemented')) return +IF (Check( Init%FEMMod==4 , 'FEMMod = 4 (tapered Timoshenko) not implemented')) return IF (Init%CBMod) THEN ! Nmodes - Number of interal modes to retain. From 79fb2547ffc22fe4e32956ea28af945ae3c8949e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 19:12:34 -0700 Subject: [PATCH 058/377] FlexSub: starting to cleanup outputs --- modules/subdyn/CMakeLists.txt | 1 + modules/subdyn/src/SubDyn_Output.f90 | 3745 +------------------ modules/subdyn/src/SubDyn_Output_Params.f90 | 3723 ++++++++++++++++++ 3 files changed, 3733 insertions(+), 3736 deletions(-) create mode 100644 modules/subdyn/src/SubDyn_Output_Params.f90 diff --git a/modules/subdyn/CMakeLists.txt b/modules/subdyn/CMakeLists.txt index fa0fdbc85..12bf2ae5e 100644 --- a/modules/subdyn/CMakeLists.txt +++ b/modules/subdyn/CMakeLists.txt @@ -22,6 +22,7 @@ set(SUBDYN_SOURCES src/SubDyn.f90 src/SD_FEM.f90 src/SubDyn_Output.f90 + src/SubDyn_Output_Params.f90 src/qsort_c_module.f90 src/SubDyn_Types.f90 ) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 2913564ad..ee711c92f 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -18,3740 +18,18 @@ ! !********************************************************************************************************************************** MODULE SubDyn_Output + USE NWTC_Library + USE SubDyn_Types + USE SD_FEM + USE SubDyn_Output_Params, only: MNfmKe, MNfmMe, MNTDss, MNRDe, MNTRAe, IntfSS, IntfTRss, IntfTRAss, ReactSS + USE SubDyn_Output_Params, only: ParamIndxAry, ParamUnitsAry, ValidParamAry, SSqm01, SSqmd01, SSqmdd01 - ! This MODULE stores variables used for output. + IMPLICIT NONE - USE NWTC_Library - USE SubDyn_Types - USE SD_FEM - IMPLICIT NONE - - ! The maximum number of output channels which can be output by the code. + ! The maximum number of output channels which can be output by the code. INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 PRIVATE - - ! Indices for computing output channels: - ! NOTES: - ! (1) These parameters are in the order stored in "OutListParameters.xlsx" - ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter - - ! Time: - - INTEGER, PARAMETER :: Time = 0 - - - ! Member Forces: - - INTEGER(IntKi), PARAMETER :: M1N1FKxe = 1 - INTEGER(IntKi), PARAMETER :: M1N2FKxe = 2 - INTEGER(IntKi), PARAMETER :: M1N3FKxe = 3 - INTEGER(IntKi), PARAMETER :: M1N4FKxe = 4 - INTEGER(IntKi), PARAMETER :: M1N5FKxe = 5 - INTEGER(IntKi), PARAMETER :: M1N6FKxe = 6 - INTEGER(IntKi), PARAMETER :: M1N7FKxe = 7 - INTEGER(IntKi), PARAMETER :: M1N8FKxe = 8 - INTEGER(IntKi), PARAMETER :: M1N9FKxe = 9 - INTEGER(IntKi), PARAMETER :: M2N1FKxe = 10 - INTEGER(IntKi), PARAMETER :: M2N2FKxe = 11 - INTEGER(IntKi), PARAMETER :: M2N3FKxe = 12 - INTEGER(IntKi), PARAMETER :: M2N4FKxe = 13 - INTEGER(IntKi), PARAMETER :: M2N5FKxe = 14 - INTEGER(IntKi), PARAMETER :: M2N6FKxe = 15 - INTEGER(IntKi), PARAMETER :: M2N7FKxe = 16 - INTEGER(IntKi), PARAMETER :: M2N8FKxe = 17 - INTEGER(IntKi), PARAMETER :: M2N9FKxe = 18 - INTEGER(IntKi), PARAMETER :: M3N1FKxe = 19 - INTEGER(IntKi), PARAMETER :: M3N2FKxe = 20 - INTEGER(IntKi), PARAMETER :: M3N3FKxe = 21 - INTEGER(IntKi), PARAMETER :: M3N4FKxe = 22 - INTEGER(IntKi), PARAMETER :: M3N5FKxe = 23 - INTEGER(IntKi), PARAMETER :: M3N6FKxe = 24 - INTEGER(IntKi), PARAMETER :: M3N7FKxe = 25 - INTEGER(IntKi), PARAMETER :: M3N8FKxe = 26 - INTEGER(IntKi), PARAMETER :: M3N9FKxe = 27 - INTEGER(IntKi), PARAMETER :: M4N1FKxe = 28 - INTEGER(IntKi), PARAMETER :: M4N2FKxe = 29 - INTEGER(IntKi), PARAMETER :: M4N3FKxe = 30 - INTEGER(IntKi), PARAMETER :: M4N4FKxe = 31 - INTEGER(IntKi), PARAMETER :: M4N5FKxe = 32 - INTEGER(IntKi), PARAMETER :: M4N6FKxe = 33 - INTEGER(IntKi), PARAMETER :: M4N7FKxe = 34 - INTEGER(IntKi), PARAMETER :: M4N8FKxe = 35 - INTEGER(IntKi), PARAMETER :: M4N9FKxe = 36 - INTEGER(IntKi), PARAMETER :: M5N1FKxe = 37 - INTEGER(IntKi), PARAMETER :: M5N2FKxe = 38 - INTEGER(IntKi), PARAMETER :: M5N3FKxe = 39 - INTEGER(IntKi), PARAMETER :: M5N4FKxe = 40 - INTEGER(IntKi), PARAMETER :: M5N5FKxe = 41 - INTEGER(IntKi), PARAMETER :: M5N6FKxe = 42 - INTEGER(IntKi), PARAMETER :: M5N7FKxe = 43 - INTEGER(IntKi), PARAMETER :: M5N8FKxe = 44 - INTEGER(IntKi), PARAMETER :: M5N9FKxe = 45 - INTEGER(IntKi), PARAMETER :: M6N1FKxe = 46 - INTEGER(IntKi), PARAMETER :: M6N2FKxe = 47 - INTEGER(IntKi), PARAMETER :: M6N3FKxe = 48 - INTEGER(IntKi), PARAMETER :: M6N4FKxe = 49 - INTEGER(IntKi), PARAMETER :: M6N5FKxe = 50 - INTEGER(IntKi), PARAMETER :: M6N6FKxe = 51 - INTEGER(IntKi), PARAMETER :: M6N7FKxe = 52 - INTEGER(IntKi), PARAMETER :: M6N8FKxe = 53 - INTEGER(IntKi), PARAMETER :: M6N9FKxe = 54 - INTEGER(IntKi), PARAMETER :: M7N1FKxe = 55 - INTEGER(IntKi), PARAMETER :: M7N2FKxe = 56 - INTEGER(IntKi), PARAMETER :: M7N3FKxe = 57 - INTEGER(IntKi), PARAMETER :: M7N4FKxe = 58 - INTEGER(IntKi), PARAMETER :: M7N5FKxe = 59 - INTEGER(IntKi), PARAMETER :: M7N6FKxe = 60 - INTEGER(IntKi), PARAMETER :: M7N7FKxe = 61 - INTEGER(IntKi), PARAMETER :: M7N8FKxe = 62 - INTEGER(IntKi), PARAMETER :: M7N9FKxe = 63 - INTEGER(IntKi), PARAMETER :: M8N1FKxe = 64 - INTEGER(IntKi), PARAMETER :: M8N2FKxe = 65 - INTEGER(IntKi), PARAMETER :: M8N3FKxe = 66 - INTEGER(IntKi), PARAMETER :: M8N4FKxe = 67 - INTEGER(IntKi), PARAMETER :: M8N5FKxe = 68 - INTEGER(IntKi), PARAMETER :: M8N6FKxe = 69 - INTEGER(IntKi), PARAMETER :: M8N7FKxe = 70 - INTEGER(IntKi), PARAMETER :: M8N8FKxe = 71 - INTEGER(IntKi), PARAMETER :: M8N9FKxe = 72 - INTEGER(IntKi), PARAMETER :: M9N1FKxe = 73 - INTEGER(IntKi), PARAMETER :: M9N2FKxe = 74 - INTEGER(IntKi), PARAMETER :: M9N3FKxe = 75 - INTEGER(IntKi), PARAMETER :: M9N4FKxe = 76 - INTEGER(IntKi), PARAMETER :: M9N5FKxe = 77 - INTEGER(IntKi), PARAMETER :: M9N6FKxe = 78 - INTEGER(IntKi), PARAMETER :: M9N7FKxe = 79 - INTEGER(IntKi), PARAMETER :: M9N8FKxe = 80 - INTEGER(IntKi), PARAMETER :: M9N9FKxe = 81 - INTEGER(IntKi), PARAMETER :: M1N1FKye = 82 - INTEGER(IntKi), PARAMETER :: M1N2FKye = 83 - INTEGER(IntKi), PARAMETER :: M1N3FKye = 84 - INTEGER(IntKi), PARAMETER :: M1N4FKye = 85 - INTEGER(IntKi), PARAMETER :: M1N5FKye = 86 - INTEGER(IntKi), PARAMETER :: M1N6FKye = 87 - INTEGER(IntKi), PARAMETER :: M1N7FKye = 88 - INTEGER(IntKi), PARAMETER :: M1N8FKye = 89 - INTEGER(IntKi), PARAMETER :: M1N9FKye = 90 - INTEGER(IntKi), PARAMETER :: M2N1FKye = 91 - INTEGER(IntKi), PARAMETER :: M2N2FKye = 92 - INTEGER(IntKi), PARAMETER :: M2N3FKye = 93 - INTEGER(IntKi), PARAMETER :: M2N4FKye = 94 - INTEGER(IntKi), PARAMETER :: M2N5FKye = 95 - INTEGER(IntKi), PARAMETER :: M2N6FKye = 96 - INTEGER(IntKi), PARAMETER :: M2N7FKye = 97 - INTEGER(IntKi), PARAMETER :: M2N8FKye = 98 - INTEGER(IntKi), PARAMETER :: M2N9FKye = 99 - INTEGER(IntKi), PARAMETER :: M3N1FKye = 100 - INTEGER(IntKi), PARAMETER :: M3N2FKye = 101 - INTEGER(IntKi), PARAMETER :: M3N3FKye = 102 - INTEGER(IntKi), PARAMETER :: M3N4FKye = 103 - INTEGER(IntKi), PARAMETER :: M3N5FKye = 104 - INTEGER(IntKi), PARAMETER :: M3N6FKye = 105 - INTEGER(IntKi), PARAMETER :: M3N7FKye = 106 - INTEGER(IntKi), PARAMETER :: M3N8FKye = 107 - INTEGER(IntKi), PARAMETER :: M3N9FKye = 108 - INTEGER(IntKi), PARAMETER :: M4N1FKye = 109 - INTEGER(IntKi), PARAMETER :: M4N2FKye = 110 - INTEGER(IntKi), PARAMETER :: M4N3FKye = 111 - INTEGER(IntKi), PARAMETER :: M4N4FKye = 112 - INTEGER(IntKi), PARAMETER :: M4N5FKye = 113 - INTEGER(IntKi), PARAMETER :: M4N6FKye = 114 - INTEGER(IntKi), PARAMETER :: M4N7FKye = 115 - INTEGER(IntKi), PARAMETER :: M4N8FKye = 116 - INTEGER(IntKi), PARAMETER :: M4N9FKye = 117 - INTEGER(IntKi), PARAMETER :: M5N1FKye = 118 - INTEGER(IntKi), PARAMETER :: M5N2FKye = 119 - INTEGER(IntKi), PARAMETER :: M5N3FKye = 120 - INTEGER(IntKi), PARAMETER :: M5N4FKye = 121 - INTEGER(IntKi), PARAMETER :: M5N5FKye = 122 - INTEGER(IntKi), PARAMETER :: M5N6FKye = 123 - INTEGER(IntKi), PARAMETER :: M5N7FKye = 124 - INTEGER(IntKi), PARAMETER :: M5N8FKye = 125 - INTEGER(IntKi), PARAMETER :: M5N9FKye = 126 - INTEGER(IntKi), PARAMETER :: M6N1FKye = 127 - INTEGER(IntKi), PARAMETER :: M6N2FKye = 128 - INTEGER(IntKi), PARAMETER :: M6N3FKye = 129 - INTEGER(IntKi), PARAMETER :: M6N4FKye = 130 - INTEGER(IntKi), PARAMETER :: M6N5FKye = 131 - INTEGER(IntKi), PARAMETER :: M6N6FKye = 132 - INTEGER(IntKi), PARAMETER :: M6N7FKye = 133 - INTEGER(IntKi), PARAMETER :: M6N8FKye = 134 - INTEGER(IntKi), PARAMETER :: M6N9FKye = 135 - INTEGER(IntKi), PARAMETER :: M7N1FKye = 136 - INTEGER(IntKi), PARAMETER :: M7N2FKye = 137 - INTEGER(IntKi), PARAMETER :: M7N3FKye = 138 - INTEGER(IntKi), PARAMETER :: M7N4FKye = 139 - INTEGER(IntKi), PARAMETER :: M7N5FKye = 140 - INTEGER(IntKi), PARAMETER :: M7N6FKye = 141 - INTEGER(IntKi), PARAMETER :: M7N7FKye = 142 - INTEGER(IntKi), PARAMETER :: M7N8FKye = 143 - INTEGER(IntKi), PARAMETER :: M7N9FKye = 144 - INTEGER(IntKi), PARAMETER :: M8N1FKye = 145 - INTEGER(IntKi), PARAMETER :: M8N2FKye = 146 - INTEGER(IntKi), PARAMETER :: M8N3FKye = 147 - INTEGER(IntKi), PARAMETER :: M8N4FKye = 148 - INTEGER(IntKi), PARAMETER :: M8N5FKye = 149 - INTEGER(IntKi), PARAMETER :: M8N6FKye = 150 - INTEGER(IntKi), PARAMETER :: M8N7FKye = 151 - INTEGER(IntKi), PARAMETER :: M8N8FKye = 152 - INTEGER(IntKi), PARAMETER :: M8N9FKye = 153 - INTEGER(IntKi), PARAMETER :: M9N1FKye = 154 - INTEGER(IntKi), PARAMETER :: M9N2FKye = 155 - INTEGER(IntKi), PARAMETER :: M9N3FKye = 156 - INTEGER(IntKi), PARAMETER :: M9N4FKye = 157 - INTEGER(IntKi), PARAMETER :: M9N5FKye = 158 - INTEGER(IntKi), PARAMETER :: M9N6FKye = 159 - INTEGER(IntKi), PARAMETER :: M9N7FKye = 160 - INTEGER(IntKi), PARAMETER :: M9N8FKye = 161 - INTEGER(IntKi), PARAMETER :: M9N9FKye = 162 - INTEGER(IntKi), PARAMETER :: M1N1FKze = 163 - INTEGER(IntKi), PARAMETER :: M1N2FKze = 164 - INTEGER(IntKi), PARAMETER :: M1N3FKze = 165 - INTEGER(IntKi), PARAMETER :: M1N4FKze = 166 - INTEGER(IntKi), PARAMETER :: M1N5FKze = 167 - INTEGER(IntKi), PARAMETER :: M1N6FKze = 168 - INTEGER(IntKi), PARAMETER :: M1N7FKze = 169 - INTEGER(IntKi), PARAMETER :: M1N8FKze = 170 - INTEGER(IntKi), PARAMETER :: M1N9FKze = 171 - INTEGER(IntKi), PARAMETER :: M2N1FKze = 172 - INTEGER(IntKi), PARAMETER :: M2N2FKze = 173 - INTEGER(IntKi), PARAMETER :: M2N3FKze = 174 - INTEGER(IntKi), PARAMETER :: M2N4FKze = 175 - INTEGER(IntKi), PARAMETER :: M2N5FKze = 176 - INTEGER(IntKi), PARAMETER :: M2N6FKze = 177 - INTEGER(IntKi), PARAMETER :: M2N7FKze = 178 - INTEGER(IntKi), PARAMETER :: M2N8FKze = 179 - INTEGER(IntKi), PARAMETER :: M2N9FKze = 180 - INTEGER(IntKi), PARAMETER :: M3N1FKze = 181 - INTEGER(IntKi), PARAMETER :: M3N2FKze = 182 - INTEGER(IntKi), PARAMETER :: M3N3FKze = 183 - INTEGER(IntKi), PARAMETER :: M3N4FKze = 184 - INTEGER(IntKi), PARAMETER :: M3N5FKze = 185 - INTEGER(IntKi), PARAMETER :: M3N6FKze = 186 - INTEGER(IntKi), PARAMETER :: M3N7FKze = 187 - INTEGER(IntKi), PARAMETER :: M3N8FKze = 188 - INTEGER(IntKi), PARAMETER :: M3N9FKze = 189 - INTEGER(IntKi), PARAMETER :: M4N1FKze = 190 - INTEGER(IntKi), PARAMETER :: M4N2FKze = 191 - INTEGER(IntKi), PARAMETER :: M4N3FKze = 192 - INTEGER(IntKi), PARAMETER :: M4N4FKze = 193 - INTEGER(IntKi), PARAMETER :: M4N5FKze = 194 - INTEGER(IntKi), PARAMETER :: M4N6FKze = 195 - INTEGER(IntKi), PARAMETER :: M4N7FKze = 196 - INTEGER(IntKi), PARAMETER :: M4N8FKze = 197 - INTEGER(IntKi), PARAMETER :: M4N9FKze = 198 - INTEGER(IntKi), PARAMETER :: M5N1FKze = 199 - INTEGER(IntKi), PARAMETER :: M5N2FKze = 200 - INTEGER(IntKi), PARAMETER :: M5N3FKze = 201 - INTEGER(IntKi), PARAMETER :: M5N4FKze = 202 - INTEGER(IntKi), PARAMETER :: M5N5FKze = 203 - INTEGER(IntKi), PARAMETER :: M5N6FKze = 204 - INTEGER(IntKi), PARAMETER :: M5N7FKze = 205 - INTEGER(IntKi), PARAMETER :: M5N8FKze = 206 - INTEGER(IntKi), PARAMETER :: M5N9FKze = 207 - INTEGER(IntKi), PARAMETER :: M6N1FKze = 208 - INTEGER(IntKi), PARAMETER :: M6N2FKze = 209 - INTEGER(IntKi), PARAMETER :: M6N3FKze = 210 - INTEGER(IntKi), PARAMETER :: M6N4FKze = 211 - INTEGER(IntKi), PARAMETER :: M6N5FKze = 212 - INTEGER(IntKi), PARAMETER :: M6N6FKze = 213 - INTEGER(IntKi), PARAMETER :: M6N7FKze = 214 - INTEGER(IntKi), PARAMETER :: M6N8FKze = 215 - INTEGER(IntKi), PARAMETER :: M6N9FKze = 216 - INTEGER(IntKi), PARAMETER :: M7N1FKze = 217 - INTEGER(IntKi), PARAMETER :: M7N2FKze = 218 - INTEGER(IntKi), PARAMETER :: M7N3FKze = 219 - INTEGER(IntKi), PARAMETER :: M7N4FKze = 220 - INTEGER(IntKi), PARAMETER :: M7N5FKze = 221 - INTEGER(IntKi), PARAMETER :: M7N6FKze = 222 - INTEGER(IntKi), PARAMETER :: M7N7FKze = 223 - INTEGER(IntKi), PARAMETER :: M7N8FKze = 224 - INTEGER(IntKi), PARAMETER :: M7N9FKze = 225 - INTEGER(IntKi), PARAMETER :: M8N1FKze = 226 - INTEGER(IntKi), PARAMETER :: M8N2FKze = 227 - INTEGER(IntKi), PARAMETER :: M8N3FKze = 228 - INTEGER(IntKi), PARAMETER :: M8N4FKze = 229 - INTEGER(IntKi), PARAMETER :: M8N5FKze = 230 - INTEGER(IntKi), PARAMETER :: M8N6FKze = 231 - INTEGER(IntKi), PARAMETER :: M8N7FKze = 232 - INTEGER(IntKi), PARAMETER :: M8N8FKze = 233 - INTEGER(IntKi), PARAMETER :: M8N9FKze = 234 - INTEGER(IntKi), PARAMETER :: M9N1FKze = 235 - INTEGER(IntKi), PARAMETER :: M9N2FKze = 236 - INTEGER(IntKi), PARAMETER :: M9N3FKze = 237 - INTEGER(IntKi), PARAMETER :: M9N4FKze = 238 - INTEGER(IntKi), PARAMETER :: M9N5FKze = 239 - INTEGER(IntKi), PARAMETER :: M9N6FKze = 240 - INTEGER(IntKi), PARAMETER :: M9N7FKze = 241 - INTEGER(IntKi), PARAMETER :: M9N8FKze = 242 - INTEGER(IntKi), PARAMETER :: M9N9FKze = 243 - INTEGER(IntKi), PARAMETER :: M1N1FMxe = 244 - INTEGER(IntKi), PARAMETER :: M1N2FMxe = 245 - INTEGER(IntKi), PARAMETER :: M1N3FMxe = 246 - INTEGER(IntKi), PARAMETER :: M1N4FMxe = 247 - INTEGER(IntKi), PARAMETER :: M1N5FMxe = 248 - INTEGER(IntKi), PARAMETER :: M1N6FMxe = 249 - INTEGER(IntKi), PARAMETER :: M1N7FMxe = 250 - INTEGER(IntKi), PARAMETER :: M1N8FMxe = 251 - INTEGER(IntKi), PARAMETER :: M1N9FMxe = 252 - INTEGER(IntKi), PARAMETER :: M2N1FMxe = 253 - INTEGER(IntKi), PARAMETER :: M2N2FMxe = 254 - INTEGER(IntKi), PARAMETER :: M2N3FMxe = 255 - INTEGER(IntKi), PARAMETER :: M2N4FMxe = 256 - INTEGER(IntKi), PARAMETER :: M2N5FMxe = 257 - INTEGER(IntKi), PARAMETER :: M2N6FMxe = 258 - INTEGER(IntKi), PARAMETER :: M2N7FMxe = 259 - INTEGER(IntKi), PARAMETER :: M2N8FMxe = 260 - INTEGER(IntKi), PARAMETER :: M2N9FMxe = 261 - INTEGER(IntKi), PARAMETER :: M3N1FMxe = 262 - INTEGER(IntKi), PARAMETER :: M3N2FMxe = 263 - INTEGER(IntKi), PARAMETER :: M3N3FMxe = 264 - INTEGER(IntKi), PARAMETER :: M3N4FMxe = 265 - INTEGER(IntKi), PARAMETER :: M3N5FMxe = 266 - INTEGER(IntKi), PARAMETER :: M3N6FMxe = 267 - INTEGER(IntKi), PARAMETER :: M3N7FMxe = 268 - INTEGER(IntKi), PARAMETER :: M3N8FMxe = 269 - INTEGER(IntKi), PARAMETER :: M3N9FMxe = 270 - INTEGER(IntKi), PARAMETER :: M4N1FMxe = 271 - INTEGER(IntKi), PARAMETER :: M4N2FMxe = 272 - INTEGER(IntKi), PARAMETER :: M4N3FMxe = 273 - INTEGER(IntKi), PARAMETER :: M4N4FMxe = 274 - INTEGER(IntKi), PARAMETER :: M4N5FMxe = 275 - INTEGER(IntKi), PARAMETER :: M4N6FMxe = 276 - INTEGER(IntKi), PARAMETER :: M4N7FMxe = 277 - INTEGER(IntKi), PARAMETER :: M4N8FMxe = 278 - INTEGER(IntKi), PARAMETER :: M4N9FMxe = 279 - INTEGER(IntKi), PARAMETER :: M5N1FMxe = 280 - INTEGER(IntKi), PARAMETER :: M5N2FMxe = 281 - INTEGER(IntKi), PARAMETER :: M5N3FMxe = 282 - INTEGER(IntKi), PARAMETER :: M5N4FMxe = 283 - INTEGER(IntKi), PARAMETER :: M5N5FMxe = 284 - INTEGER(IntKi), PARAMETER :: M5N6FMxe = 285 - INTEGER(IntKi), PARAMETER :: M5N7FMxe = 286 - INTEGER(IntKi), PARAMETER :: M5N8FMxe = 287 - INTEGER(IntKi), PARAMETER :: M5N9FMxe = 288 - INTEGER(IntKi), PARAMETER :: M6N1FMxe = 289 - INTEGER(IntKi), PARAMETER :: M6N2FMxe = 290 - INTEGER(IntKi), PARAMETER :: M6N3FMxe = 291 - INTEGER(IntKi), PARAMETER :: M6N4FMxe = 292 - INTEGER(IntKi), PARAMETER :: M6N5FMxe = 293 - INTEGER(IntKi), PARAMETER :: M6N6FMxe = 294 - INTEGER(IntKi), PARAMETER :: M6N7FMxe = 295 - INTEGER(IntKi), PARAMETER :: M6N8FMxe = 296 - INTEGER(IntKi), PARAMETER :: M6N9FMxe = 297 - INTEGER(IntKi), PARAMETER :: M7N1FMxe = 298 - INTEGER(IntKi), PARAMETER :: M7N2FMxe = 299 - INTEGER(IntKi), PARAMETER :: M7N3FMxe = 300 - INTEGER(IntKi), PARAMETER :: M7N4FMxe = 301 - INTEGER(IntKi), PARAMETER :: M7N5FMxe = 302 - INTEGER(IntKi), PARAMETER :: M7N6FMxe = 303 - INTEGER(IntKi), PARAMETER :: M7N7FMxe = 304 - INTEGER(IntKi), PARAMETER :: M7N8FMxe = 305 - INTEGER(IntKi), PARAMETER :: M7N9FMxe = 306 - INTEGER(IntKi), PARAMETER :: M8N1FMxe = 307 - INTEGER(IntKi), PARAMETER :: M8N2FMxe = 308 - INTEGER(IntKi), PARAMETER :: M8N3FMxe = 309 - INTEGER(IntKi), PARAMETER :: M8N4FMxe = 310 - INTEGER(IntKi), PARAMETER :: M8N5FMxe = 311 - INTEGER(IntKi), PARAMETER :: M8N6FMxe = 312 - INTEGER(IntKi), PARAMETER :: M8N7FMxe = 313 - INTEGER(IntKi), PARAMETER :: M8N8FMxe = 314 - INTEGER(IntKi), PARAMETER :: M8N9FMxe = 315 - INTEGER(IntKi), PARAMETER :: M9N1FMxe = 316 - INTEGER(IntKi), PARAMETER :: M9N2FMxe = 317 - INTEGER(IntKi), PARAMETER :: M9N3FMxe = 318 - INTEGER(IntKi), PARAMETER :: M9N4FMxe = 319 - INTEGER(IntKi), PARAMETER :: M9N5FMxe = 320 - INTEGER(IntKi), PARAMETER :: M9N6FMxe = 321 - INTEGER(IntKi), PARAMETER :: M9N7FMxe = 322 - INTEGER(IntKi), PARAMETER :: M9N8FMxe = 323 - INTEGER(IntKi), PARAMETER :: M9N9FMxe = 324 - INTEGER(IntKi), PARAMETER :: M1N1FMye = 325 - INTEGER(IntKi), PARAMETER :: M1N2FMye = 326 - INTEGER(IntKi), PARAMETER :: M1N3FMye = 327 - INTEGER(IntKi), PARAMETER :: M1N4FMye = 328 - INTEGER(IntKi), PARAMETER :: M1N5FMye = 329 - INTEGER(IntKi), PARAMETER :: M1N6FMye = 330 - INTEGER(IntKi), PARAMETER :: M1N7FMye = 331 - INTEGER(IntKi), PARAMETER :: M1N8FMye = 332 - INTEGER(IntKi), PARAMETER :: M1N9FMye = 333 - INTEGER(IntKi), PARAMETER :: M2N1FMye = 334 - INTEGER(IntKi), PARAMETER :: M2N2FMye = 335 - INTEGER(IntKi), PARAMETER :: M2N3FMye = 336 - INTEGER(IntKi), PARAMETER :: M2N4FMye = 337 - INTEGER(IntKi), PARAMETER :: M2N5FMye = 338 - INTEGER(IntKi), PARAMETER :: M2N6FMye = 339 - INTEGER(IntKi), PARAMETER :: M2N7FMye = 340 - INTEGER(IntKi), PARAMETER :: M2N8FMye = 341 - INTEGER(IntKi), PARAMETER :: M2N9FMye = 342 - INTEGER(IntKi), PARAMETER :: M3N1FMye = 343 - INTEGER(IntKi), PARAMETER :: M3N2FMye = 344 - INTEGER(IntKi), PARAMETER :: M3N3FMye = 345 - INTEGER(IntKi), PARAMETER :: M3N4FMye = 346 - INTEGER(IntKi), PARAMETER :: M3N5FMye = 347 - INTEGER(IntKi), PARAMETER :: M3N6FMye = 348 - INTEGER(IntKi), PARAMETER :: M3N7FMye = 349 - INTEGER(IntKi), PARAMETER :: M3N8FMye = 350 - INTEGER(IntKi), PARAMETER :: M3N9FMye = 351 - INTEGER(IntKi), PARAMETER :: M4N1FMye = 352 - INTEGER(IntKi), PARAMETER :: M4N2FMye = 353 - INTEGER(IntKi), PARAMETER :: M4N3FMye = 354 - INTEGER(IntKi), PARAMETER :: M4N4FMye = 355 - INTEGER(IntKi), PARAMETER :: M4N5FMye = 356 - INTEGER(IntKi), PARAMETER :: M4N6FMye = 357 - INTEGER(IntKi), PARAMETER :: M4N7FMye = 358 - INTEGER(IntKi), PARAMETER :: M4N8FMye = 359 - INTEGER(IntKi), PARAMETER :: M4N9FMye = 360 - INTEGER(IntKi), PARAMETER :: M5N1FMye = 361 - INTEGER(IntKi), PARAMETER :: M5N2FMye = 362 - INTEGER(IntKi), PARAMETER :: M5N3FMye = 363 - INTEGER(IntKi), PARAMETER :: M5N4FMye = 364 - INTEGER(IntKi), PARAMETER :: M5N5FMye = 365 - INTEGER(IntKi), PARAMETER :: M5N6FMye = 366 - INTEGER(IntKi), PARAMETER :: M5N7FMye = 367 - INTEGER(IntKi), PARAMETER :: M5N8FMye = 368 - INTEGER(IntKi), PARAMETER :: M5N9FMye = 369 - INTEGER(IntKi), PARAMETER :: M6N1FMye = 370 - INTEGER(IntKi), PARAMETER :: M6N2FMye = 371 - INTEGER(IntKi), PARAMETER :: M6N3FMye = 372 - INTEGER(IntKi), PARAMETER :: M6N4FMye = 373 - INTEGER(IntKi), PARAMETER :: M6N5FMye = 374 - INTEGER(IntKi), PARAMETER :: M6N6FMye = 375 - INTEGER(IntKi), PARAMETER :: M6N7FMye = 376 - INTEGER(IntKi), PARAMETER :: M6N8FMye = 377 - INTEGER(IntKi), PARAMETER :: M6N9FMye = 378 - INTEGER(IntKi), PARAMETER :: M7N1FMye = 379 - INTEGER(IntKi), PARAMETER :: M7N2FMye = 380 - INTEGER(IntKi), PARAMETER :: M7N3FMye = 381 - INTEGER(IntKi), PARAMETER :: M7N4FMye = 382 - INTEGER(IntKi), PARAMETER :: M7N5FMye = 383 - INTEGER(IntKi), PARAMETER :: M7N6FMye = 384 - INTEGER(IntKi), PARAMETER :: M7N7FMye = 385 - INTEGER(IntKi), PARAMETER :: M7N8FMye = 386 - INTEGER(IntKi), PARAMETER :: M7N9FMye = 387 - INTEGER(IntKi), PARAMETER :: M8N1FMye = 388 - INTEGER(IntKi), PARAMETER :: M8N2FMye = 389 - INTEGER(IntKi), PARAMETER :: M8N3FMye = 390 - INTEGER(IntKi), PARAMETER :: M8N4FMye = 391 - INTEGER(IntKi), PARAMETER :: M8N5FMye = 392 - INTEGER(IntKi), PARAMETER :: M8N6FMye = 393 - INTEGER(IntKi), PARAMETER :: M8N7FMye = 394 - INTEGER(IntKi), PARAMETER :: M8N8FMye = 395 - INTEGER(IntKi), PARAMETER :: M8N9FMye = 396 - INTEGER(IntKi), PARAMETER :: M9N1FMye = 397 - INTEGER(IntKi), PARAMETER :: M9N2FMye = 398 - INTEGER(IntKi), PARAMETER :: M9N3FMye = 399 - INTEGER(IntKi), PARAMETER :: M9N4FMye = 400 - INTEGER(IntKi), PARAMETER :: M9N5FMye = 401 - INTEGER(IntKi), PARAMETER :: M9N6FMye = 402 - INTEGER(IntKi), PARAMETER :: M9N7FMye = 403 - INTEGER(IntKi), PARAMETER :: M9N8FMye = 404 - INTEGER(IntKi), PARAMETER :: M9N9FMye = 405 - INTEGER(IntKi), PARAMETER :: M1N1FMze = 406 - INTEGER(IntKi), PARAMETER :: M1N2FMze = 407 - INTEGER(IntKi), PARAMETER :: M1N3FMze = 408 - INTEGER(IntKi), PARAMETER :: M1N4FMze = 409 - INTEGER(IntKi), PARAMETER :: M1N5FMze = 410 - INTEGER(IntKi), PARAMETER :: M1N6FMze = 411 - INTEGER(IntKi), PARAMETER :: M1N7FMze = 412 - INTEGER(IntKi), PARAMETER :: M1N8FMze = 413 - INTEGER(IntKi), PARAMETER :: M1N9FMze = 414 - INTEGER(IntKi), PARAMETER :: M2N1FMze = 415 - INTEGER(IntKi), PARAMETER :: M2N2FMze = 416 - INTEGER(IntKi), PARAMETER :: M2N3FMze = 417 - INTEGER(IntKi), PARAMETER :: M2N4FMze = 418 - INTEGER(IntKi), PARAMETER :: M2N5FMze = 419 - INTEGER(IntKi), PARAMETER :: M2N6FMze = 420 - INTEGER(IntKi), PARAMETER :: M2N7FMze = 421 - INTEGER(IntKi), PARAMETER :: M2N8FMze = 422 - INTEGER(IntKi), PARAMETER :: M2N9FMze = 423 - INTEGER(IntKi), PARAMETER :: M3N1FMze = 424 - INTEGER(IntKi), PARAMETER :: M3N2FMze = 425 - INTEGER(IntKi), PARAMETER :: M3N3FMze = 426 - INTEGER(IntKi), PARAMETER :: M3N4FMze = 427 - INTEGER(IntKi), PARAMETER :: M3N5FMze = 428 - INTEGER(IntKi), PARAMETER :: M3N6FMze = 429 - INTEGER(IntKi), PARAMETER :: M3N7FMze = 430 - INTEGER(IntKi), PARAMETER :: M3N8FMze = 431 - INTEGER(IntKi), PARAMETER :: M3N9FMze = 432 - INTEGER(IntKi), PARAMETER :: M4N1FMze = 433 - INTEGER(IntKi), PARAMETER :: M4N2FMze = 434 - INTEGER(IntKi), PARAMETER :: M4N3FMze = 435 - INTEGER(IntKi), PARAMETER :: M4N4FMze = 436 - INTEGER(IntKi), PARAMETER :: M4N5FMze = 437 - INTEGER(IntKi), PARAMETER :: M4N6FMze = 438 - INTEGER(IntKi), PARAMETER :: M4N7FMze = 439 - INTEGER(IntKi), PARAMETER :: M4N8FMze = 440 - INTEGER(IntKi), PARAMETER :: M4N9FMze = 441 - INTEGER(IntKi), PARAMETER :: M5N1FMze = 442 - INTEGER(IntKi), PARAMETER :: M5N2FMze = 443 - INTEGER(IntKi), PARAMETER :: M5N3FMze = 444 - INTEGER(IntKi), PARAMETER :: M5N4FMze = 445 - INTEGER(IntKi), PARAMETER :: M5N5FMze = 446 - INTEGER(IntKi), PARAMETER :: M5N6FMze = 447 - INTEGER(IntKi), PARAMETER :: M5N7FMze = 448 - INTEGER(IntKi), PARAMETER :: M5N8FMze = 449 - INTEGER(IntKi), PARAMETER :: M5N9FMze = 450 - INTEGER(IntKi), PARAMETER :: M6N1FMze = 451 - INTEGER(IntKi), PARAMETER :: M6N2FMze = 452 - INTEGER(IntKi), PARAMETER :: M6N3FMze = 453 - INTEGER(IntKi), PARAMETER :: M6N4FMze = 454 - INTEGER(IntKi), PARAMETER :: M6N5FMze = 455 - INTEGER(IntKi), PARAMETER :: M6N6FMze = 456 - INTEGER(IntKi), PARAMETER :: M6N7FMze = 457 - INTEGER(IntKi), PARAMETER :: M6N8FMze = 458 - INTEGER(IntKi), PARAMETER :: M6N9FMze = 459 - INTEGER(IntKi), PARAMETER :: M7N1FMze = 460 - INTEGER(IntKi), PARAMETER :: M7N2FMze = 461 - INTEGER(IntKi), PARAMETER :: M7N3FMze = 462 - INTEGER(IntKi), PARAMETER :: M7N4FMze = 463 - INTEGER(IntKi), PARAMETER :: M7N5FMze = 464 - INTEGER(IntKi), PARAMETER :: M7N6FMze = 465 - INTEGER(IntKi), PARAMETER :: M7N7FMze = 466 - INTEGER(IntKi), PARAMETER :: M7N8FMze = 467 - INTEGER(IntKi), PARAMETER :: M7N9FMze = 468 - INTEGER(IntKi), PARAMETER :: M8N1FMze = 469 - INTEGER(IntKi), PARAMETER :: M8N2FMze = 470 - INTEGER(IntKi), PARAMETER :: M8N3FMze = 471 - INTEGER(IntKi), PARAMETER :: M8N4FMze = 472 - INTEGER(IntKi), PARAMETER :: M8N5FMze = 473 - INTEGER(IntKi), PARAMETER :: M8N6FMze = 474 - INTEGER(IntKi), PARAMETER :: M8N7FMze = 475 - INTEGER(IntKi), PARAMETER :: M8N8FMze = 476 - INTEGER(IntKi), PARAMETER :: M8N9FMze = 477 - INTEGER(IntKi), PARAMETER :: M9N1FMze = 478 - INTEGER(IntKi), PARAMETER :: M9N2FMze = 479 - INTEGER(IntKi), PARAMETER :: M9N3FMze = 480 - INTEGER(IntKi), PARAMETER :: M9N4FMze = 481 - INTEGER(IntKi), PARAMETER :: M9N5FMze = 482 - INTEGER(IntKi), PARAMETER :: M9N6FMze = 483 - INTEGER(IntKi), PARAMETER :: M9N7FMze = 484 - INTEGER(IntKi), PARAMETER :: M9N8FMze = 485 - INTEGER(IntKi), PARAMETER :: M9N9FMze = 486 - INTEGER(IntKi), PARAMETER :: M1N1MKxe = 487 - INTEGER(IntKi), PARAMETER :: M1N2MKxe = 488 - INTEGER(IntKi), PARAMETER :: M1N3MKxe = 489 - INTEGER(IntKi), PARAMETER :: M1N4MKxe = 490 - INTEGER(IntKi), PARAMETER :: M1N5MKxe = 491 - INTEGER(IntKi), PARAMETER :: M1N6MKxe = 492 - INTEGER(IntKi), PARAMETER :: M1N7MKxe = 493 - INTEGER(IntKi), PARAMETER :: M1N8MKxe = 494 - INTEGER(IntKi), PARAMETER :: M1N9MKxe = 495 - INTEGER(IntKi), PARAMETER :: M2N1MKxe = 496 - INTEGER(IntKi), PARAMETER :: M2N2MKxe = 497 - INTEGER(IntKi), PARAMETER :: M2N3MKxe = 498 - INTEGER(IntKi), PARAMETER :: M2N4MKxe = 499 - INTEGER(IntKi), PARAMETER :: M2N5MKxe = 500 - INTEGER(IntKi), PARAMETER :: M2N6MKxe = 501 - INTEGER(IntKi), PARAMETER :: M2N7MKxe = 502 - INTEGER(IntKi), PARAMETER :: M2N8MKxe = 503 - INTEGER(IntKi), PARAMETER :: M2N9MKxe = 504 - INTEGER(IntKi), PARAMETER :: M3N1MKxe = 505 - INTEGER(IntKi), PARAMETER :: M3N2MKxe = 506 - INTEGER(IntKi), PARAMETER :: M3N3MKxe = 507 - INTEGER(IntKi), PARAMETER :: M3N4MKxe = 508 - INTEGER(IntKi), PARAMETER :: M3N5MKxe = 509 - INTEGER(IntKi), PARAMETER :: M3N6MKxe = 510 - INTEGER(IntKi), PARAMETER :: M3N7MKxe = 511 - INTEGER(IntKi), PARAMETER :: M3N8MKxe = 512 - INTEGER(IntKi), PARAMETER :: M3N9MKxe = 513 - INTEGER(IntKi), PARAMETER :: M4N1MKxe = 514 - INTEGER(IntKi), PARAMETER :: M4N2MKxe = 515 - INTEGER(IntKi), PARAMETER :: M4N3MKxe = 516 - INTEGER(IntKi), PARAMETER :: M4N4MKxe = 517 - INTEGER(IntKi), PARAMETER :: M4N5MKxe = 518 - INTEGER(IntKi), PARAMETER :: M4N6MKxe = 519 - INTEGER(IntKi), PARAMETER :: M4N7MKxe = 520 - INTEGER(IntKi), PARAMETER :: M4N8MKxe = 521 - INTEGER(IntKi), PARAMETER :: M4N9MKxe = 522 - INTEGER(IntKi), PARAMETER :: M5N1MKxe = 523 - INTEGER(IntKi), PARAMETER :: M5N2MKxe = 524 - INTEGER(IntKi), PARAMETER :: M5N3MKxe = 525 - INTEGER(IntKi), PARAMETER :: M5N4MKxe = 526 - INTEGER(IntKi), PARAMETER :: M5N5MKxe = 527 - INTEGER(IntKi), PARAMETER :: M5N6MKxe = 528 - INTEGER(IntKi), PARAMETER :: M5N7MKxe = 529 - INTEGER(IntKi), PARAMETER :: M5N8MKxe = 530 - INTEGER(IntKi), PARAMETER :: M5N9MKxe = 531 - INTEGER(IntKi), PARAMETER :: M6N1MKxe = 532 - INTEGER(IntKi), PARAMETER :: M6N2MKxe = 533 - INTEGER(IntKi), PARAMETER :: M6N3MKxe = 534 - INTEGER(IntKi), PARAMETER :: M6N4MKxe = 535 - INTEGER(IntKi), PARAMETER :: M6N5MKxe = 536 - INTEGER(IntKi), PARAMETER :: M6N6MKxe = 537 - INTEGER(IntKi), PARAMETER :: M6N7MKxe = 538 - INTEGER(IntKi), PARAMETER :: M6N8MKxe = 539 - INTEGER(IntKi), PARAMETER :: M6N9MKxe = 540 - INTEGER(IntKi), PARAMETER :: M7N1MKxe = 541 - INTEGER(IntKi), PARAMETER :: M7N2MKxe = 542 - INTEGER(IntKi), PARAMETER :: M7N3MKxe = 543 - INTEGER(IntKi), PARAMETER :: M7N4MKxe = 544 - INTEGER(IntKi), PARAMETER :: M7N5MKxe = 545 - INTEGER(IntKi), PARAMETER :: M7N6MKxe = 546 - INTEGER(IntKi), PARAMETER :: M7N7MKxe = 547 - INTEGER(IntKi), PARAMETER :: M7N8MKxe = 548 - INTEGER(IntKi), PARAMETER :: M7N9MKxe = 549 - INTEGER(IntKi), PARAMETER :: M8N1MKxe = 550 - INTEGER(IntKi), PARAMETER :: M8N2MKxe = 551 - INTEGER(IntKi), PARAMETER :: M8N3MKxe = 552 - INTEGER(IntKi), PARAMETER :: M8N4MKxe = 553 - INTEGER(IntKi), PARAMETER :: M8N5MKxe = 554 - INTEGER(IntKi), PARAMETER :: M8N6MKxe = 555 - INTEGER(IntKi), PARAMETER :: M8N7MKxe = 556 - INTEGER(IntKi), PARAMETER :: M8N8MKxe = 557 - INTEGER(IntKi), PARAMETER :: M8N9MKxe = 558 - INTEGER(IntKi), PARAMETER :: M9N1MKxe = 559 - INTEGER(IntKi), PARAMETER :: M9N2MKxe = 560 - INTEGER(IntKi), PARAMETER :: M9N3MKxe = 561 - INTEGER(IntKi), PARAMETER :: M9N4MKxe = 562 - INTEGER(IntKi), PARAMETER :: M9N5MKxe = 563 - INTEGER(IntKi), PARAMETER :: M9N6MKxe = 564 - INTEGER(IntKi), PARAMETER :: M9N7MKxe = 565 - INTEGER(IntKi), PARAMETER :: M9N8MKxe = 566 - INTEGER(IntKi), PARAMETER :: M9N9MKxe = 567 - INTEGER(IntKi), PARAMETER :: M1N1MKye = 568 - INTEGER(IntKi), PARAMETER :: M1N2MKye = 569 - INTEGER(IntKi), PARAMETER :: M1N3MKye = 570 - INTEGER(IntKi), PARAMETER :: M1N4MKye = 571 - INTEGER(IntKi), PARAMETER :: M1N5MKye = 572 - INTEGER(IntKi), PARAMETER :: M1N6MKye = 573 - INTEGER(IntKi), PARAMETER :: M1N7MKye = 574 - INTEGER(IntKi), PARAMETER :: M1N8MKye = 575 - INTEGER(IntKi), PARAMETER :: M1N9MKye = 576 - INTEGER(IntKi), PARAMETER :: M2N1MKye = 577 - INTEGER(IntKi), PARAMETER :: M2N2MKye = 578 - INTEGER(IntKi), PARAMETER :: M2N3MKye = 579 - INTEGER(IntKi), PARAMETER :: M2N4MKye = 580 - INTEGER(IntKi), PARAMETER :: M2N5MKye = 581 - INTEGER(IntKi), PARAMETER :: M2N6MKye = 582 - INTEGER(IntKi), PARAMETER :: M2N7MKye = 583 - INTEGER(IntKi), PARAMETER :: M2N8MKye = 584 - INTEGER(IntKi), PARAMETER :: M2N9MKye = 585 - INTEGER(IntKi), PARAMETER :: M3N1MKye = 586 - INTEGER(IntKi), PARAMETER :: M3N2MKye = 587 - INTEGER(IntKi), PARAMETER :: M3N3MKye = 588 - INTEGER(IntKi), PARAMETER :: M3N4MKye = 589 - INTEGER(IntKi), PARAMETER :: M3N5MKye = 590 - INTEGER(IntKi), PARAMETER :: M3N6MKye = 591 - INTEGER(IntKi), PARAMETER :: M3N7MKye = 592 - INTEGER(IntKi), PARAMETER :: M3N8MKye = 593 - INTEGER(IntKi), PARAMETER :: M3N9MKye = 594 - INTEGER(IntKi), PARAMETER :: M4N1MKye = 595 - INTEGER(IntKi), PARAMETER :: M4N2MKye = 596 - INTEGER(IntKi), PARAMETER :: M4N3MKye = 597 - INTEGER(IntKi), PARAMETER :: M4N4MKye = 598 - INTEGER(IntKi), PARAMETER :: M4N5MKye = 599 - INTEGER(IntKi), PARAMETER :: M4N6MKye = 600 - INTEGER(IntKi), PARAMETER :: M4N7MKye = 601 - INTEGER(IntKi), PARAMETER :: M4N8MKye = 602 - INTEGER(IntKi), PARAMETER :: M4N9MKye = 603 - INTEGER(IntKi), PARAMETER :: M5N1MKye = 604 - INTEGER(IntKi), PARAMETER :: M5N2MKye = 605 - INTEGER(IntKi), PARAMETER :: M5N3MKye = 606 - INTEGER(IntKi), PARAMETER :: M5N4MKye = 607 - INTEGER(IntKi), PARAMETER :: M5N5MKye = 608 - INTEGER(IntKi), PARAMETER :: M5N6MKye = 609 - INTEGER(IntKi), PARAMETER :: M5N7MKye = 610 - INTEGER(IntKi), PARAMETER :: M5N8MKye = 611 - INTEGER(IntKi), PARAMETER :: M5N9MKye = 612 - INTEGER(IntKi), PARAMETER :: M6N1MKye = 613 - INTEGER(IntKi), PARAMETER :: M6N2MKye = 614 - INTEGER(IntKi), PARAMETER :: M6N3MKye = 615 - INTEGER(IntKi), PARAMETER :: M6N4MKye = 616 - INTEGER(IntKi), PARAMETER :: M6N5MKye = 617 - INTEGER(IntKi), PARAMETER :: M6N6MKye = 618 - INTEGER(IntKi), PARAMETER :: M6N7MKye = 619 - INTEGER(IntKi), PARAMETER :: M6N8MKye = 620 - INTEGER(IntKi), PARAMETER :: M6N9MKye = 621 - INTEGER(IntKi), PARAMETER :: M7N1MKye = 622 - INTEGER(IntKi), PARAMETER :: M7N2MKye = 623 - INTEGER(IntKi), PARAMETER :: M7N3MKye = 624 - INTEGER(IntKi), PARAMETER :: M7N4MKye = 625 - INTEGER(IntKi), PARAMETER :: M7N5MKye = 626 - INTEGER(IntKi), PARAMETER :: M7N6MKye = 627 - INTEGER(IntKi), PARAMETER :: M7N7MKye = 628 - INTEGER(IntKi), PARAMETER :: M7N8MKye = 629 - INTEGER(IntKi), PARAMETER :: M7N9MKye = 630 - INTEGER(IntKi), PARAMETER :: M8N1MKye = 631 - INTEGER(IntKi), PARAMETER :: M8N2MKye = 632 - INTEGER(IntKi), PARAMETER :: M8N3MKye = 633 - INTEGER(IntKi), PARAMETER :: M8N4MKye = 634 - INTEGER(IntKi), PARAMETER :: M8N5MKye = 635 - INTEGER(IntKi), PARAMETER :: M8N6MKye = 636 - INTEGER(IntKi), PARAMETER :: M8N7MKye = 637 - INTEGER(IntKi), PARAMETER :: M8N8MKye = 638 - INTEGER(IntKi), PARAMETER :: M8N9MKye = 639 - INTEGER(IntKi), PARAMETER :: M9N1MKye = 640 - INTEGER(IntKi), PARAMETER :: M9N2MKye = 641 - INTEGER(IntKi), PARAMETER :: M9N3MKye = 642 - INTEGER(IntKi), PARAMETER :: M9N4MKye = 643 - INTEGER(IntKi), PARAMETER :: M9N5MKye = 644 - INTEGER(IntKi), PARAMETER :: M9N6MKye = 645 - INTEGER(IntKi), PARAMETER :: M9N7MKye = 646 - INTEGER(IntKi), PARAMETER :: M9N8MKye = 647 - INTEGER(IntKi), PARAMETER :: M9N9MKye = 648 - INTEGER(IntKi), PARAMETER :: M1N1MKze = 649 - INTEGER(IntKi), PARAMETER :: M1N2MKze = 650 - INTEGER(IntKi), PARAMETER :: M1N3MKze = 651 - INTEGER(IntKi), PARAMETER :: M1N4MKze = 652 - INTEGER(IntKi), PARAMETER :: M1N5MKze = 653 - INTEGER(IntKi), PARAMETER :: M1N6MKze = 654 - INTEGER(IntKi), PARAMETER :: M1N7MKze = 655 - INTEGER(IntKi), PARAMETER :: M1N8MKze = 656 - INTEGER(IntKi), PARAMETER :: M1N9MKze = 657 - INTEGER(IntKi), PARAMETER :: M2N1MKze = 658 - INTEGER(IntKi), PARAMETER :: M2N2MKze = 659 - INTEGER(IntKi), PARAMETER :: M2N3MKze = 660 - INTEGER(IntKi), PARAMETER :: M2N4MKze = 661 - INTEGER(IntKi), PARAMETER :: M2N5MKze = 662 - INTEGER(IntKi), PARAMETER :: M2N6MKze = 663 - INTEGER(IntKi), PARAMETER :: M2N7MKze = 664 - INTEGER(IntKi), PARAMETER :: M2N8MKze = 665 - INTEGER(IntKi), PARAMETER :: M2N9MKze = 666 - INTEGER(IntKi), PARAMETER :: M3N1MKze = 667 - INTEGER(IntKi), PARAMETER :: M3N2MKze = 668 - INTEGER(IntKi), PARAMETER :: M3N3MKze = 669 - INTEGER(IntKi), PARAMETER :: M3N4MKze = 670 - INTEGER(IntKi), PARAMETER :: M3N5MKze = 671 - INTEGER(IntKi), PARAMETER :: M3N6MKze = 672 - INTEGER(IntKi), PARAMETER :: M3N7MKze = 673 - INTEGER(IntKi), PARAMETER :: M3N8MKze = 674 - INTEGER(IntKi), PARAMETER :: M3N9MKze = 675 - INTEGER(IntKi), PARAMETER :: M4N1MKze = 676 - INTEGER(IntKi), PARAMETER :: M4N2MKze = 677 - INTEGER(IntKi), PARAMETER :: M4N3MKze = 678 - INTEGER(IntKi), PARAMETER :: M4N4MKze = 679 - INTEGER(IntKi), PARAMETER :: M4N5MKze = 680 - INTEGER(IntKi), PARAMETER :: M4N6MKze = 681 - INTEGER(IntKi), PARAMETER :: M4N7MKze = 682 - INTEGER(IntKi), PARAMETER :: M4N8MKze = 683 - INTEGER(IntKi), PARAMETER :: M4N9MKze = 684 - INTEGER(IntKi), PARAMETER :: M5N1MKze = 685 - INTEGER(IntKi), PARAMETER :: M5N2MKze = 686 - INTEGER(IntKi), PARAMETER :: M5N3MKze = 687 - INTEGER(IntKi), PARAMETER :: M5N4MKze = 688 - INTEGER(IntKi), PARAMETER :: M5N5MKze = 689 - INTEGER(IntKi), PARAMETER :: M5N6MKze = 690 - INTEGER(IntKi), PARAMETER :: M5N7MKze = 691 - INTEGER(IntKi), PARAMETER :: M5N8MKze = 692 - INTEGER(IntKi), PARAMETER :: M5N9MKze = 693 - INTEGER(IntKi), PARAMETER :: M6N1MKze = 694 - INTEGER(IntKi), PARAMETER :: M6N2MKze = 695 - INTEGER(IntKi), PARAMETER :: M6N3MKze = 696 - INTEGER(IntKi), PARAMETER :: M6N4MKze = 697 - INTEGER(IntKi), PARAMETER :: M6N5MKze = 698 - INTEGER(IntKi), PARAMETER :: M6N6MKze = 699 - INTEGER(IntKi), PARAMETER :: M6N7MKze = 700 - INTEGER(IntKi), PARAMETER :: M6N8MKze = 701 - INTEGER(IntKi), PARAMETER :: M6N9MKze = 702 - INTEGER(IntKi), PARAMETER :: M7N1MKze = 703 - INTEGER(IntKi), PARAMETER :: M7N2MKze = 704 - INTEGER(IntKi), PARAMETER :: M7N3MKze = 705 - INTEGER(IntKi), PARAMETER :: M7N4MKze = 706 - INTEGER(IntKi), PARAMETER :: M7N5MKze = 707 - INTEGER(IntKi), PARAMETER :: M7N6MKze = 708 - INTEGER(IntKi), PARAMETER :: M7N7MKze = 709 - INTEGER(IntKi), PARAMETER :: M7N8MKze = 710 - INTEGER(IntKi), PARAMETER :: M7N9MKze = 711 - INTEGER(IntKi), PARAMETER :: M8N1MKze = 712 - INTEGER(IntKi), PARAMETER :: M8N2MKze = 713 - INTEGER(IntKi), PARAMETER :: M8N3MKze = 714 - INTEGER(IntKi), PARAMETER :: M8N4MKze = 715 - INTEGER(IntKi), PARAMETER :: M8N5MKze = 716 - INTEGER(IntKi), PARAMETER :: M8N6MKze = 717 - INTEGER(IntKi), PARAMETER :: M8N7MKze = 718 - INTEGER(IntKi), PARAMETER :: M8N8MKze = 719 - INTEGER(IntKi), PARAMETER :: M8N9MKze = 720 - INTEGER(IntKi), PARAMETER :: M9N1MKze = 721 - INTEGER(IntKi), PARAMETER :: M9N2MKze = 722 - INTEGER(IntKi), PARAMETER :: M9N3MKze = 723 - INTEGER(IntKi), PARAMETER :: M9N4MKze = 724 - INTEGER(IntKi), PARAMETER :: M9N5MKze = 725 - INTEGER(IntKi), PARAMETER :: M9N6MKze = 726 - INTEGER(IntKi), PARAMETER :: M9N7MKze = 727 - INTEGER(IntKi), PARAMETER :: M9N8MKze = 728 - INTEGER(IntKi), PARAMETER :: M9N9MKze = 729 - INTEGER(IntKi), PARAMETER :: M1N1MMxe = 730 - INTEGER(IntKi), PARAMETER :: M1N2MMxe = 731 - INTEGER(IntKi), PARAMETER :: M1N3MMxe = 732 - INTEGER(IntKi), PARAMETER :: M1N4MMxe = 733 - INTEGER(IntKi), PARAMETER :: M1N5MMxe = 734 - INTEGER(IntKi), PARAMETER :: M1N6MMxe = 735 - INTEGER(IntKi), PARAMETER :: M1N7MMxe = 736 - INTEGER(IntKi), PARAMETER :: M1N8MMxe = 737 - INTEGER(IntKi), PARAMETER :: M1N9MMxe = 738 - INTEGER(IntKi), PARAMETER :: M2N1MMxe = 739 - INTEGER(IntKi), PARAMETER :: M2N2MMxe = 740 - INTEGER(IntKi), PARAMETER :: M2N3MMxe = 741 - INTEGER(IntKi), PARAMETER :: M2N4MMxe = 742 - INTEGER(IntKi), PARAMETER :: M2N5MMxe = 743 - INTEGER(IntKi), PARAMETER :: M2N6MMxe = 744 - INTEGER(IntKi), PARAMETER :: M2N7MMxe = 745 - INTEGER(IntKi), PARAMETER :: M2N8MMxe = 746 - INTEGER(IntKi), PARAMETER :: M2N9MMxe = 747 - INTEGER(IntKi), PARAMETER :: M3N1MMxe = 748 - INTEGER(IntKi), PARAMETER :: M3N2MMxe = 749 - INTEGER(IntKi), PARAMETER :: M3N3MMxe = 750 - INTEGER(IntKi), PARAMETER :: M3N4MMxe = 751 - INTEGER(IntKi), PARAMETER :: M3N5MMxe = 752 - INTEGER(IntKi), PARAMETER :: M3N6MMxe = 753 - INTEGER(IntKi), PARAMETER :: M3N7MMxe = 754 - INTEGER(IntKi), PARAMETER :: M3N8MMxe = 755 - INTEGER(IntKi), PARAMETER :: M3N9MMxe = 756 - INTEGER(IntKi), PARAMETER :: M4N1MMxe = 757 - INTEGER(IntKi), PARAMETER :: M4N2MMxe = 758 - INTEGER(IntKi), PARAMETER :: M4N3MMxe = 759 - INTEGER(IntKi), PARAMETER :: M4N4MMxe = 760 - INTEGER(IntKi), PARAMETER :: M4N5MMxe = 761 - INTEGER(IntKi), PARAMETER :: M4N6MMxe = 762 - INTEGER(IntKi), PARAMETER :: M4N7MMxe = 763 - INTEGER(IntKi), PARAMETER :: M4N8MMxe = 764 - INTEGER(IntKi), PARAMETER :: M4N9MMxe = 765 - INTEGER(IntKi), PARAMETER :: M5N1MMxe = 766 - INTEGER(IntKi), PARAMETER :: M5N2MMxe = 767 - INTEGER(IntKi), PARAMETER :: M5N3MMxe = 768 - INTEGER(IntKi), PARAMETER :: M5N4MMxe = 769 - INTEGER(IntKi), PARAMETER :: M5N5MMxe = 770 - INTEGER(IntKi), PARAMETER :: M5N6MMxe = 771 - INTEGER(IntKi), PARAMETER :: M5N7MMxe = 772 - INTEGER(IntKi), PARAMETER :: M5N8MMxe = 773 - INTEGER(IntKi), PARAMETER :: M5N9MMxe = 774 - INTEGER(IntKi), PARAMETER :: M6N1MMxe = 775 - INTEGER(IntKi), PARAMETER :: M6N2MMxe = 776 - INTEGER(IntKi), PARAMETER :: M6N3MMxe = 777 - INTEGER(IntKi), PARAMETER :: M6N4MMxe = 778 - INTEGER(IntKi), PARAMETER :: M6N5MMxe = 779 - INTEGER(IntKi), PARAMETER :: M6N6MMxe = 780 - INTEGER(IntKi), PARAMETER :: M6N7MMxe = 781 - INTEGER(IntKi), PARAMETER :: M6N8MMxe = 782 - INTEGER(IntKi), PARAMETER :: M6N9MMxe = 783 - INTEGER(IntKi), PARAMETER :: M7N1MMxe = 784 - INTEGER(IntKi), PARAMETER :: M7N2MMxe = 785 - INTEGER(IntKi), PARAMETER :: M7N3MMxe = 786 - INTEGER(IntKi), PARAMETER :: M7N4MMxe = 787 - INTEGER(IntKi), PARAMETER :: M7N5MMxe = 788 - INTEGER(IntKi), PARAMETER :: M7N6MMxe = 789 - INTEGER(IntKi), PARAMETER :: M7N7MMxe = 790 - INTEGER(IntKi), PARAMETER :: M7N8MMxe = 791 - INTEGER(IntKi), PARAMETER :: M7N9MMxe = 792 - INTEGER(IntKi), PARAMETER :: M8N1MMxe = 793 - INTEGER(IntKi), PARAMETER :: M8N2MMxe = 794 - INTEGER(IntKi), PARAMETER :: M8N3MMxe = 795 - INTEGER(IntKi), PARAMETER :: M8N4MMxe = 796 - INTEGER(IntKi), PARAMETER :: M8N5MMxe = 797 - INTEGER(IntKi), PARAMETER :: M8N6MMxe = 798 - INTEGER(IntKi), PARAMETER :: M8N7MMxe = 799 - INTEGER(IntKi), PARAMETER :: M8N8MMxe = 800 - INTEGER(IntKi), PARAMETER :: M8N9MMxe = 801 - INTEGER(IntKi), PARAMETER :: M9N1MMxe = 802 - INTEGER(IntKi), PARAMETER :: M9N2MMxe = 803 - INTEGER(IntKi), PARAMETER :: M9N3MMxe = 804 - INTEGER(IntKi), PARAMETER :: M9N4MMxe = 805 - INTEGER(IntKi), PARAMETER :: M9N5MMxe = 806 - INTEGER(IntKi), PARAMETER :: M9N6MMxe = 807 - INTEGER(IntKi), PARAMETER :: M9N7MMxe = 808 - INTEGER(IntKi), PARAMETER :: M9N8MMxe = 809 - INTEGER(IntKi), PARAMETER :: M9N9MMxe = 810 - INTEGER(IntKi), PARAMETER :: M1N1MMye = 811 - INTEGER(IntKi), PARAMETER :: M1N2MMye = 812 - INTEGER(IntKi), PARAMETER :: M1N3MMye = 813 - INTEGER(IntKi), PARAMETER :: M1N4MMye = 814 - INTEGER(IntKi), PARAMETER :: M1N5MMye = 815 - INTEGER(IntKi), PARAMETER :: M1N6MMye = 816 - INTEGER(IntKi), PARAMETER :: M1N7MMye = 817 - INTEGER(IntKi), PARAMETER :: M1N8MMye = 818 - INTEGER(IntKi), PARAMETER :: M1N9MMye = 819 - INTEGER(IntKi), PARAMETER :: M2N1MMye = 820 - INTEGER(IntKi), PARAMETER :: M2N2MMye = 821 - INTEGER(IntKi), PARAMETER :: M2N3MMye = 822 - INTEGER(IntKi), PARAMETER :: M2N4MMye = 823 - INTEGER(IntKi), PARAMETER :: M2N5MMye = 824 - INTEGER(IntKi), PARAMETER :: M2N6MMye = 825 - INTEGER(IntKi), PARAMETER :: M2N7MMye = 826 - INTEGER(IntKi), PARAMETER :: M2N8MMye = 827 - INTEGER(IntKi), PARAMETER :: M2N9MMye = 828 - INTEGER(IntKi), PARAMETER :: M3N1MMye = 829 - INTEGER(IntKi), PARAMETER :: M3N2MMye = 830 - INTEGER(IntKi), PARAMETER :: M3N3MMye = 831 - INTEGER(IntKi), PARAMETER :: M3N4MMye = 832 - INTEGER(IntKi), PARAMETER :: M3N5MMye = 833 - INTEGER(IntKi), PARAMETER :: M3N6MMye = 834 - INTEGER(IntKi), PARAMETER :: M3N7MMye = 835 - INTEGER(IntKi), PARAMETER :: M3N8MMye = 836 - INTEGER(IntKi), PARAMETER :: M3N9MMye = 837 - INTEGER(IntKi), PARAMETER :: M4N1MMye = 838 - INTEGER(IntKi), PARAMETER :: M4N2MMye = 839 - INTEGER(IntKi), PARAMETER :: M4N3MMye = 840 - INTEGER(IntKi), PARAMETER :: M4N4MMye = 841 - INTEGER(IntKi), PARAMETER :: M4N5MMye = 842 - INTEGER(IntKi), PARAMETER :: M4N6MMye = 843 - INTEGER(IntKi), PARAMETER :: M4N7MMye = 844 - INTEGER(IntKi), PARAMETER :: M4N8MMye = 845 - INTEGER(IntKi), PARAMETER :: M4N9MMye = 846 - INTEGER(IntKi), PARAMETER :: M5N1MMye = 847 - INTEGER(IntKi), PARAMETER :: M5N2MMye = 848 - INTEGER(IntKi), PARAMETER :: M5N3MMye = 849 - INTEGER(IntKi), PARAMETER :: M5N4MMye = 850 - INTEGER(IntKi), PARAMETER :: M5N5MMye = 851 - INTEGER(IntKi), PARAMETER :: M5N6MMye = 852 - INTEGER(IntKi), PARAMETER :: M5N7MMye = 853 - INTEGER(IntKi), PARAMETER :: M5N8MMye = 854 - INTEGER(IntKi), PARAMETER :: M5N9MMye = 855 - INTEGER(IntKi), PARAMETER :: M6N1MMye = 856 - INTEGER(IntKi), PARAMETER :: M6N2MMye = 857 - INTEGER(IntKi), PARAMETER :: M6N3MMye = 858 - INTEGER(IntKi), PARAMETER :: M6N4MMye = 859 - INTEGER(IntKi), PARAMETER :: M6N5MMye = 860 - INTEGER(IntKi), PARAMETER :: M6N6MMye = 861 - INTEGER(IntKi), PARAMETER :: M6N7MMye = 862 - INTEGER(IntKi), PARAMETER :: M6N8MMye = 863 - INTEGER(IntKi), PARAMETER :: M6N9MMye = 864 - INTEGER(IntKi), PARAMETER :: M7N1MMye = 865 - INTEGER(IntKi), PARAMETER :: M7N2MMye = 866 - INTEGER(IntKi), PARAMETER :: M7N3MMye = 867 - INTEGER(IntKi), PARAMETER :: M7N4MMye = 868 - INTEGER(IntKi), PARAMETER :: M7N5MMye = 869 - INTEGER(IntKi), PARAMETER :: M7N6MMye = 870 - INTEGER(IntKi), PARAMETER :: M7N7MMye = 871 - INTEGER(IntKi), PARAMETER :: M7N8MMye = 872 - INTEGER(IntKi), PARAMETER :: M7N9MMye = 873 - INTEGER(IntKi), PARAMETER :: M8N1MMye = 874 - INTEGER(IntKi), PARAMETER :: M8N2MMye = 875 - INTEGER(IntKi), PARAMETER :: M8N3MMye = 876 - INTEGER(IntKi), PARAMETER :: M8N4MMye = 877 - INTEGER(IntKi), PARAMETER :: M8N5MMye = 878 - INTEGER(IntKi), PARAMETER :: M8N6MMye = 879 - INTEGER(IntKi), PARAMETER :: M8N7MMye = 880 - INTEGER(IntKi), PARAMETER :: M8N8MMye = 881 - INTEGER(IntKi), PARAMETER :: M8N9MMye = 882 - INTEGER(IntKi), PARAMETER :: M9N1MMye = 883 - INTEGER(IntKi), PARAMETER :: M9N2MMye = 884 - INTEGER(IntKi), PARAMETER :: M9N3MMye = 885 - INTEGER(IntKi), PARAMETER :: M9N4MMye = 886 - INTEGER(IntKi), PARAMETER :: M9N5MMye = 887 - INTEGER(IntKi), PARAMETER :: M9N6MMye = 888 - INTEGER(IntKi), PARAMETER :: M9N7MMye = 889 - INTEGER(IntKi), PARAMETER :: M9N8MMye = 890 - INTEGER(IntKi), PARAMETER :: M9N9MMye = 891 - INTEGER(IntKi), PARAMETER :: M1N1MMze = 892 - INTEGER(IntKi), PARAMETER :: M1N2MMze = 893 - INTEGER(IntKi), PARAMETER :: M1N3MMze = 894 - INTEGER(IntKi), PARAMETER :: M1N4MMze = 895 - INTEGER(IntKi), PARAMETER :: M1N5MMze = 896 - INTEGER(IntKi), PARAMETER :: M1N6MMze = 897 - INTEGER(IntKi), PARAMETER :: M1N7MMze = 898 - INTEGER(IntKi), PARAMETER :: M1N8MMze = 899 - INTEGER(IntKi), PARAMETER :: M1N9MMze = 900 - INTEGER(IntKi), PARAMETER :: M2N1MMze = 901 - INTEGER(IntKi), PARAMETER :: M2N2MMze = 902 - INTEGER(IntKi), PARAMETER :: M2N3MMze = 903 - INTEGER(IntKi), PARAMETER :: M2N4MMze = 904 - INTEGER(IntKi), PARAMETER :: M2N5MMze = 905 - INTEGER(IntKi), PARAMETER :: M2N6MMze = 906 - INTEGER(IntKi), PARAMETER :: M2N7MMze = 907 - INTEGER(IntKi), PARAMETER :: M2N8MMze = 908 - INTEGER(IntKi), PARAMETER :: M2N9MMze = 909 - INTEGER(IntKi), PARAMETER :: M3N1MMze = 910 - INTEGER(IntKi), PARAMETER :: M3N2MMze = 911 - INTEGER(IntKi), PARAMETER :: M3N3MMze = 912 - INTEGER(IntKi), PARAMETER :: M3N4MMze = 913 - INTEGER(IntKi), PARAMETER :: M3N5MMze = 914 - INTEGER(IntKi), PARAMETER :: M3N6MMze = 915 - INTEGER(IntKi), PARAMETER :: M3N7MMze = 916 - INTEGER(IntKi), PARAMETER :: M3N8MMze = 917 - INTEGER(IntKi), PARAMETER :: M3N9MMze = 918 - INTEGER(IntKi), PARAMETER :: M4N1MMze = 919 - INTEGER(IntKi), PARAMETER :: M4N2MMze = 920 - INTEGER(IntKi), PARAMETER :: M4N3MMze = 921 - INTEGER(IntKi), PARAMETER :: M4N4MMze = 922 - INTEGER(IntKi), PARAMETER :: M4N5MMze = 923 - INTEGER(IntKi), PARAMETER :: M4N6MMze = 924 - INTEGER(IntKi), PARAMETER :: M4N7MMze = 925 - INTEGER(IntKi), PARAMETER :: M4N8MMze = 926 - INTEGER(IntKi), PARAMETER :: M4N9MMze = 927 - INTEGER(IntKi), PARAMETER :: M5N1MMze = 928 - INTEGER(IntKi), PARAMETER :: M5N2MMze = 929 - INTEGER(IntKi), PARAMETER :: M5N3MMze = 930 - INTEGER(IntKi), PARAMETER :: M5N4MMze = 931 - INTEGER(IntKi), PARAMETER :: M5N5MMze = 932 - INTEGER(IntKi), PARAMETER :: M5N6MMze = 933 - INTEGER(IntKi), PARAMETER :: M5N7MMze = 934 - INTEGER(IntKi), PARAMETER :: M5N8MMze = 935 - INTEGER(IntKi), PARAMETER :: M5N9MMze = 936 - INTEGER(IntKi), PARAMETER :: M6N1MMze = 937 - INTEGER(IntKi), PARAMETER :: M6N2MMze = 938 - INTEGER(IntKi), PARAMETER :: M6N3MMze = 939 - INTEGER(IntKi), PARAMETER :: M6N4MMze = 940 - INTEGER(IntKi), PARAMETER :: M6N5MMze = 941 - INTEGER(IntKi), PARAMETER :: M6N6MMze = 942 - INTEGER(IntKi), PARAMETER :: M6N7MMze = 943 - INTEGER(IntKi), PARAMETER :: M6N8MMze = 944 - INTEGER(IntKi), PARAMETER :: M6N9MMze = 945 - INTEGER(IntKi), PARAMETER :: M7N1MMze = 946 - INTEGER(IntKi), PARAMETER :: M7N2MMze = 947 - INTEGER(IntKi), PARAMETER :: M7N3MMze = 948 - INTEGER(IntKi), PARAMETER :: M7N4MMze = 949 - INTEGER(IntKi), PARAMETER :: M7N5MMze = 950 - INTEGER(IntKi), PARAMETER :: M7N6MMze = 951 - INTEGER(IntKi), PARAMETER :: M7N7MMze = 952 - INTEGER(IntKi), PARAMETER :: M7N8MMze = 953 - INTEGER(IntKi), PARAMETER :: M7N9MMze = 954 - INTEGER(IntKi), PARAMETER :: M8N1MMze = 955 - INTEGER(IntKi), PARAMETER :: M8N2MMze = 956 - INTEGER(IntKi), PARAMETER :: M8N3MMze = 957 - INTEGER(IntKi), PARAMETER :: M8N4MMze = 958 - INTEGER(IntKi), PARAMETER :: M8N5MMze = 959 - INTEGER(IntKi), PARAMETER :: M8N6MMze = 960 - INTEGER(IntKi), PARAMETER :: M8N7MMze = 961 - INTEGER(IntKi), PARAMETER :: M8N8MMze = 962 - INTEGER(IntKi), PARAMETER :: M8N9MMze = 963 - INTEGER(IntKi), PARAMETER :: M9N1MMze = 964 - INTEGER(IntKi), PARAMETER :: M9N2MMze = 965 - INTEGER(IntKi), PARAMETER :: M9N3MMze = 966 - INTEGER(IntKi), PARAMETER :: M9N4MMze = 967 - INTEGER(IntKi), PARAMETER :: M9N5MMze = 968 - INTEGER(IntKi), PARAMETER :: M9N6MMze = 969 - INTEGER(IntKi), PARAMETER :: M9N7MMze = 970 - INTEGER(IntKi), PARAMETER :: M9N8MMze = 971 - INTEGER(IntKi), PARAMETER :: M9N9MMze = 972 - - - ! Displacements: - - INTEGER(IntKi), PARAMETER :: M1N1TDxss = 973 - INTEGER(IntKi), PARAMETER :: M1N2TDxss = 974 - INTEGER(IntKi), PARAMETER :: M1N3TDxss = 975 - INTEGER(IntKi), PARAMETER :: M1N4TDxss = 976 - INTEGER(IntKi), PARAMETER :: M1N5TDxss = 977 - INTEGER(IntKi), PARAMETER :: M1N6TDxss = 978 - INTEGER(IntKi), PARAMETER :: M1N7TDxss = 979 - INTEGER(IntKi), PARAMETER :: M1N8TDxss = 980 - INTEGER(IntKi), PARAMETER :: M1N9TDxss = 981 - INTEGER(IntKi), PARAMETER :: M2N1TDxss = 982 - INTEGER(IntKi), PARAMETER :: M2N2TDxss = 983 - INTEGER(IntKi), PARAMETER :: M2N3TDxss = 984 - INTEGER(IntKi), PARAMETER :: M2N4TDxss = 985 - INTEGER(IntKi), PARAMETER :: M2N5TDxss = 986 - INTEGER(IntKi), PARAMETER :: M2N6TDxss = 987 - INTEGER(IntKi), PARAMETER :: M2N7TDxss = 988 - INTEGER(IntKi), PARAMETER :: M2N8TDxss = 989 - INTEGER(IntKi), PARAMETER :: M2N9TDxss = 990 - INTEGER(IntKi), PARAMETER :: M3N1TDxss = 991 - INTEGER(IntKi), PARAMETER :: M3N2TDxss = 992 - INTEGER(IntKi), PARAMETER :: M3N3TDxss = 993 - INTEGER(IntKi), PARAMETER :: M3N4TDxss = 994 - INTEGER(IntKi), PARAMETER :: M3N5TDxss = 995 - INTEGER(IntKi), PARAMETER :: M3N6TDxss = 996 - INTEGER(IntKi), PARAMETER :: M3N7TDxss = 997 - INTEGER(IntKi), PARAMETER :: M3N8TDxss = 998 - INTEGER(IntKi), PARAMETER :: M3N9TDxss = 999 - INTEGER(IntKi), PARAMETER :: M4N1TDxss = 1000 - INTEGER(IntKi), PARAMETER :: M4N2TDxss = 1001 - INTEGER(IntKi), PARAMETER :: M4N3TDxss = 1002 - INTEGER(IntKi), PARAMETER :: M4N4TDxss = 1003 - INTEGER(IntKi), PARAMETER :: M4N5TDxss = 1004 - INTEGER(IntKi), PARAMETER :: M4N6TDxss = 1005 - INTEGER(IntKi), PARAMETER :: M4N7TDxss = 1006 - INTEGER(IntKi), PARAMETER :: M4N8TDxss = 1007 - INTEGER(IntKi), PARAMETER :: M4N9TDxss = 1008 - INTEGER(IntKi), PARAMETER :: M5N1TDxss = 1009 - INTEGER(IntKi), PARAMETER :: M5N2TDxss = 1010 - INTEGER(IntKi), PARAMETER :: M5N3TDxss = 1011 - INTEGER(IntKi), PARAMETER :: M5N4TDxss = 1012 - INTEGER(IntKi), PARAMETER :: M5N5TDxss = 1013 - INTEGER(IntKi), PARAMETER :: M5N6TDxss = 1014 - INTEGER(IntKi), PARAMETER :: M5N7TDxss = 1015 - INTEGER(IntKi), PARAMETER :: M5N8TDxss = 1016 - INTEGER(IntKi), PARAMETER :: M5N9TDxss = 1017 - INTEGER(IntKi), PARAMETER :: M6N1TDxss = 1018 - INTEGER(IntKi), PARAMETER :: M6N2TDxss = 1019 - INTEGER(IntKi), PARAMETER :: M6N3TDxss = 1020 - INTEGER(IntKi), PARAMETER :: M6N4TDxss = 1021 - INTEGER(IntKi), PARAMETER :: M6N5TDxss = 1022 - INTEGER(IntKi), PARAMETER :: M6N6TDxss = 1023 - INTEGER(IntKi), PARAMETER :: M6N7TDxss = 1024 - INTEGER(IntKi), PARAMETER :: M6N8TDxss = 1025 - INTEGER(IntKi), PARAMETER :: M6N9TDxss = 1026 - INTEGER(IntKi), PARAMETER :: M7N1TDxss = 1027 - INTEGER(IntKi), PARAMETER :: M7N2TDxss = 1028 - INTEGER(IntKi), PARAMETER :: M7N3TDxss = 1029 - INTEGER(IntKi), PARAMETER :: M7N4TDxss = 1030 - INTEGER(IntKi), PARAMETER :: M7N5TDxss = 1031 - INTEGER(IntKi), PARAMETER :: M7N6TDxss = 1032 - INTEGER(IntKi), PARAMETER :: M7N7TDxss = 1033 - INTEGER(IntKi), PARAMETER :: M7N8TDxss = 1034 - INTEGER(IntKi), PARAMETER :: M7N9TDxss = 1035 - INTEGER(IntKi), PARAMETER :: M8N1TDxss = 1036 - INTEGER(IntKi), PARAMETER :: M8N2TDxss = 1037 - INTEGER(IntKi), PARAMETER :: M8N3TDxss = 1038 - INTEGER(IntKi), PARAMETER :: M8N4TDxss = 1039 - INTEGER(IntKi), PARAMETER :: M8N5TDxss = 1040 - INTEGER(IntKi), PARAMETER :: M8N6TDxss = 1041 - INTEGER(IntKi), PARAMETER :: M8N7TDxss = 1042 - INTEGER(IntKi), PARAMETER :: M8N8TDxss = 1043 - INTEGER(IntKi), PARAMETER :: M8N9TDxss = 1044 - INTEGER(IntKi), PARAMETER :: M9N1TDxss = 1045 - INTEGER(IntKi), PARAMETER :: M9N2TDxss = 1046 - INTEGER(IntKi), PARAMETER :: M9N3TDxss = 1047 - INTEGER(IntKi), PARAMETER :: M9N4TDxss = 1048 - INTEGER(IntKi), PARAMETER :: M9N5TDxss = 1049 - INTEGER(IntKi), PARAMETER :: M9N6TDxss = 1050 - INTEGER(IntKi), PARAMETER :: M9N7TDxss = 1051 - INTEGER(IntKi), PARAMETER :: M9N8TDxss = 1052 - INTEGER(IntKi), PARAMETER :: M9N9TDxss = 1053 - INTEGER(IntKi), PARAMETER :: M1N1TDyss = 1054 - INTEGER(IntKi), PARAMETER :: M1N2TDyss = 1055 - INTEGER(IntKi), PARAMETER :: M1N3TDyss = 1056 - INTEGER(IntKi), PARAMETER :: M1N4TDyss = 1057 - INTEGER(IntKi), PARAMETER :: M1N5TDyss = 1058 - INTEGER(IntKi), PARAMETER :: M1N6TDyss = 1059 - INTEGER(IntKi), PARAMETER :: M1N7TDyss = 1060 - INTEGER(IntKi), PARAMETER :: M1N8TDyss = 1061 - INTEGER(IntKi), PARAMETER :: M1N9TDyss = 1062 - INTEGER(IntKi), PARAMETER :: M2N1TDyss = 1063 - INTEGER(IntKi), PARAMETER :: M2N2TDyss = 1064 - INTEGER(IntKi), PARAMETER :: M2N3TDyss = 1065 - INTEGER(IntKi), PARAMETER :: M2N4TDyss = 1066 - INTEGER(IntKi), PARAMETER :: M2N5TDyss = 1067 - INTEGER(IntKi), PARAMETER :: M2N6TDyss = 1068 - INTEGER(IntKi), PARAMETER :: M2N7TDyss = 1069 - INTEGER(IntKi), PARAMETER :: M2N8TDyss = 1070 - INTEGER(IntKi), PARAMETER :: M2N9TDyss = 1071 - INTEGER(IntKi), PARAMETER :: M3N1TDyss = 1072 - INTEGER(IntKi), PARAMETER :: M3N2TDyss = 1073 - INTEGER(IntKi), PARAMETER :: M3N3TDyss = 1074 - INTEGER(IntKi), PARAMETER :: M3N4TDyss = 1075 - INTEGER(IntKi), PARAMETER :: M3N5TDyss = 1076 - INTEGER(IntKi), PARAMETER :: M3N6TDyss = 1077 - INTEGER(IntKi), PARAMETER :: M3N7TDyss = 1078 - INTEGER(IntKi), PARAMETER :: M3N8TDyss = 1079 - INTEGER(IntKi), PARAMETER :: M3N9TDyss = 1080 - INTEGER(IntKi), PARAMETER :: M4N1TDyss = 1081 - INTEGER(IntKi), PARAMETER :: M4N2TDyss = 1082 - INTEGER(IntKi), PARAMETER :: M4N3TDyss = 1083 - INTEGER(IntKi), PARAMETER :: M4N4TDyss = 1084 - INTEGER(IntKi), PARAMETER :: M4N5TDyss = 1085 - INTEGER(IntKi), PARAMETER :: M4N6TDyss = 1086 - INTEGER(IntKi), PARAMETER :: M4N7TDyss = 1087 - INTEGER(IntKi), PARAMETER :: M4N8TDyss = 1088 - INTEGER(IntKi), PARAMETER :: M4N9TDyss = 1089 - INTEGER(IntKi), PARAMETER :: M5N1TDyss = 1090 - INTEGER(IntKi), PARAMETER :: M5N2TDyss = 1091 - INTEGER(IntKi), PARAMETER :: M5N3TDyss = 1092 - INTEGER(IntKi), PARAMETER :: M5N4TDyss = 1093 - INTEGER(IntKi), PARAMETER :: M5N5TDyss = 1094 - INTEGER(IntKi), PARAMETER :: M5N6TDyss = 1095 - INTEGER(IntKi), PARAMETER :: M5N7TDyss = 1096 - INTEGER(IntKi), PARAMETER :: M5N8TDyss = 1097 - INTEGER(IntKi), PARAMETER :: M5N9TDyss = 1098 - INTEGER(IntKi), PARAMETER :: M6N1TDyss = 1099 - INTEGER(IntKi), PARAMETER :: M6N2TDyss = 1100 - INTEGER(IntKi), PARAMETER :: M6N3TDyss = 1101 - INTEGER(IntKi), PARAMETER :: M6N4TDyss = 1102 - INTEGER(IntKi), PARAMETER :: M6N5TDyss = 1103 - INTEGER(IntKi), PARAMETER :: M6N6TDyss = 1104 - INTEGER(IntKi), PARAMETER :: M6N7TDyss = 1105 - INTEGER(IntKi), PARAMETER :: M6N8TDyss = 1106 - INTEGER(IntKi), PARAMETER :: M6N9TDyss = 1107 - INTEGER(IntKi), PARAMETER :: M7N1TDyss = 1108 - INTEGER(IntKi), PARAMETER :: M7N2TDyss = 1109 - INTEGER(IntKi), PARAMETER :: M7N3TDyss = 1110 - INTEGER(IntKi), PARAMETER :: M7N4TDyss = 1111 - INTEGER(IntKi), PARAMETER :: M7N5TDyss = 1112 - INTEGER(IntKi), PARAMETER :: M7N6TDyss = 1113 - INTEGER(IntKi), PARAMETER :: M7N7TDyss = 1114 - INTEGER(IntKi), PARAMETER :: M7N8TDyss = 1115 - INTEGER(IntKi), PARAMETER :: M7N9TDyss = 1116 - INTEGER(IntKi), PARAMETER :: M8N1TDyss = 1117 - INTEGER(IntKi), PARAMETER :: M8N2TDyss = 1118 - INTEGER(IntKi), PARAMETER :: M8N3TDyss = 1119 - INTEGER(IntKi), PARAMETER :: M8N4TDyss = 1120 - INTEGER(IntKi), PARAMETER :: M8N5TDyss = 1121 - INTEGER(IntKi), PARAMETER :: M8N6TDyss = 1122 - INTEGER(IntKi), PARAMETER :: M8N7TDyss = 1123 - INTEGER(IntKi), PARAMETER :: M8N8TDyss = 1124 - INTEGER(IntKi), PARAMETER :: M8N9TDyss = 1125 - INTEGER(IntKi), PARAMETER :: M9N1TDyss = 1126 - INTEGER(IntKi), PARAMETER :: M9N2TDyss = 1127 - INTEGER(IntKi), PARAMETER :: M9N3TDyss = 1128 - INTEGER(IntKi), PARAMETER :: M9N4TDyss = 1129 - INTEGER(IntKi), PARAMETER :: M9N5TDyss = 1130 - INTEGER(IntKi), PARAMETER :: M9N6TDyss = 1131 - INTEGER(IntKi), PARAMETER :: M9N7TDyss = 1132 - INTEGER(IntKi), PARAMETER :: M9N8TDyss = 1133 - INTEGER(IntKi), PARAMETER :: M9N9TDyss = 1134 - INTEGER(IntKi), PARAMETER :: M1N1TDzss = 1135 - INTEGER(IntKi), PARAMETER :: M1N2TDzss = 1136 - INTEGER(IntKi), PARAMETER :: M1N3TDzss = 1137 - INTEGER(IntKi), PARAMETER :: M1N4TDzss = 1138 - INTEGER(IntKi), PARAMETER :: M1N5TDzss = 1139 - INTEGER(IntKi), PARAMETER :: M1N6TDzss = 1140 - INTEGER(IntKi), PARAMETER :: M1N7TDzss = 1141 - INTEGER(IntKi), PARAMETER :: M1N8TDzss = 1142 - INTEGER(IntKi), PARAMETER :: M1N9TDzss = 1143 - INTEGER(IntKi), PARAMETER :: M2N1TDzss = 1144 - INTEGER(IntKi), PARAMETER :: M2N2TDzss = 1145 - INTEGER(IntKi), PARAMETER :: M2N3TDzss = 1146 - INTEGER(IntKi), PARAMETER :: M2N4TDzss = 1147 - INTEGER(IntKi), PARAMETER :: M2N5TDzss = 1148 - INTEGER(IntKi), PARAMETER :: M2N6TDzss = 1149 - INTEGER(IntKi), PARAMETER :: M2N7TDzss = 1150 - INTEGER(IntKi), PARAMETER :: M2N8TDzss = 1151 - INTEGER(IntKi), PARAMETER :: M2N9TDzss = 1152 - INTEGER(IntKi), PARAMETER :: M3N1TDzss = 1153 - INTEGER(IntKi), PARAMETER :: M3N2TDzss = 1154 - INTEGER(IntKi), PARAMETER :: M3N3TDzss = 1155 - INTEGER(IntKi), PARAMETER :: M3N4TDzss = 1156 - INTEGER(IntKi), PARAMETER :: M3N5TDzss = 1157 - INTEGER(IntKi), PARAMETER :: M3N6TDzss = 1158 - INTEGER(IntKi), PARAMETER :: M3N7TDzss = 1159 - INTEGER(IntKi), PARAMETER :: M3N8TDzss = 1160 - INTEGER(IntKi), PARAMETER :: M3N9TDzss = 1161 - INTEGER(IntKi), PARAMETER :: M4N1TDzss = 1162 - INTEGER(IntKi), PARAMETER :: M4N2TDzss = 1163 - INTEGER(IntKi), PARAMETER :: M4N3TDzss = 1164 - INTEGER(IntKi), PARAMETER :: M4N4TDzss = 1165 - INTEGER(IntKi), PARAMETER :: M4N5TDzss = 1166 - INTEGER(IntKi), PARAMETER :: M4N6TDzss = 1167 - INTEGER(IntKi), PARAMETER :: M4N7TDzss = 1168 - INTEGER(IntKi), PARAMETER :: M4N8TDzss = 1169 - INTEGER(IntKi), PARAMETER :: M4N9TDzss = 1170 - INTEGER(IntKi), PARAMETER :: M5N1TDzss = 1171 - INTEGER(IntKi), PARAMETER :: M5N2TDzss = 1172 - INTEGER(IntKi), PARAMETER :: M5N3TDzss = 1173 - INTEGER(IntKi), PARAMETER :: M5N4TDzss = 1174 - INTEGER(IntKi), PARAMETER :: M5N5TDzss = 1175 - INTEGER(IntKi), PARAMETER :: M5N6TDzss = 1176 - INTEGER(IntKi), PARAMETER :: M5N7TDzss = 1177 - INTEGER(IntKi), PARAMETER :: M5N8TDzss = 1178 - INTEGER(IntKi), PARAMETER :: M5N9TDzss = 1179 - INTEGER(IntKi), PARAMETER :: M6N1TDzss = 1180 - INTEGER(IntKi), PARAMETER :: M6N2TDzss = 1181 - INTEGER(IntKi), PARAMETER :: M6N3TDzss = 1182 - INTEGER(IntKi), PARAMETER :: M6N4TDzss = 1183 - INTEGER(IntKi), PARAMETER :: M6N5TDzss = 1184 - INTEGER(IntKi), PARAMETER :: M6N6TDzss = 1185 - INTEGER(IntKi), PARAMETER :: M6N7TDzss = 1186 - INTEGER(IntKi), PARAMETER :: M6N8TDzss = 1187 - INTEGER(IntKi), PARAMETER :: M6N9TDzss = 1188 - INTEGER(IntKi), PARAMETER :: M7N1TDzss = 1189 - INTEGER(IntKi), PARAMETER :: M7N2TDzss = 1190 - INTEGER(IntKi), PARAMETER :: M7N3TDzss = 1191 - INTEGER(IntKi), PARAMETER :: M7N4TDzss = 1192 - INTEGER(IntKi), PARAMETER :: M7N5TDzss = 1193 - INTEGER(IntKi), PARAMETER :: M7N6TDzss = 1194 - INTEGER(IntKi), PARAMETER :: M7N7TDzss = 1195 - INTEGER(IntKi), PARAMETER :: M7N8TDzss = 1196 - INTEGER(IntKi), PARAMETER :: M7N9TDzss = 1197 - INTEGER(IntKi), PARAMETER :: M8N1TDzss = 1198 - INTEGER(IntKi), PARAMETER :: M8N2TDzss = 1199 - INTEGER(IntKi), PARAMETER :: M8N3TDzss = 1200 - INTEGER(IntKi), PARAMETER :: M8N4TDzss = 1201 - INTEGER(IntKi), PARAMETER :: M8N5TDzss = 1202 - INTEGER(IntKi), PARAMETER :: M8N6TDzss = 1203 - INTEGER(IntKi), PARAMETER :: M8N7TDzss = 1204 - INTEGER(IntKi), PARAMETER :: M8N8TDzss = 1205 - INTEGER(IntKi), PARAMETER :: M8N9TDzss = 1206 - INTEGER(IntKi), PARAMETER :: M9N1TDzss = 1207 - INTEGER(IntKi), PARAMETER :: M9N2TDzss = 1208 - INTEGER(IntKi), PARAMETER :: M9N3TDzss = 1209 - INTEGER(IntKi), PARAMETER :: M9N4TDzss = 1210 - INTEGER(IntKi), PARAMETER :: M9N5TDzss = 1211 - INTEGER(IntKi), PARAMETER :: M9N6TDzss = 1212 - INTEGER(IntKi), PARAMETER :: M9N7TDzss = 1213 - INTEGER(IntKi), PARAMETER :: M9N8TDzss = 1214 - INTEGER(IntKi), PARAMETER :: M9N9TDzss = 1215 - INTEGER(IntKi), PARAMETER :: M1N1RDxe = 1216 - INTEGER(IntKi), PARAMETER :: M1N2RDxe = 1217 - INTEGER(IntKi), PARAMETER :: M1N3RDxe = 1218 - INTEGER(IntKi), PARAMETER :: M1N4RDxe = 1219 - INTEGER(IntKi), PARAMETER :: M1N5RDxe = 1220 - INTEGER(IntKi), PARAMETER :: M1N6RDxe = 1221 - INTEGER(IntKi), PARAMETER :: M1N7RDxe = 1222 - INTEGER(IntKi), PARAMETER :: M1N8RDxe = 1223 - INTEGER(IntKi), PARAMETER :: M1N9RDxe = 1224 - INTEGER(IntKi), PARAMETER :: M2N1RDxe = 1225 - INTEGER(IntKi), PARAMETER :: M2N2RDxe = 1226 - INTEGER(IntKi), PARAMETER :: M2N3RDxe = 1227 - INTEGER(IntKi), PARAMETER :: M2N4RDxe = 1228 - INTEGER(IntKi), PARAMETER :: M2N5RDxe = 1229 - INTEGER(IntKi), PARAMETER :: M2N6RDxe = 1230 - INTEGER(IntKi), PARAMETER :: M2N7RDxe = 1231 - INTEGER(IntKi), PARAMETER :: M2N8RDxe = 1232 - INTEGER(IntKi), PARAMETER :: M2N9RDxe = 1233 - INTEGER(IntKi), PARAMETER :: M3N1RDxe = 1234 - INTEGER(IntKi), PARAMETER :: M3N2RDxe = 1235 - INTEGER(IntKi), PARAMETER :: M3N3RDxe = 1236 - INTEGER(IntKi), PARAMETER :: M3N4RDxe = 1237 - INTEGER(IntKi), PARAMETER :: M3N5RDxe = 1238 - INTEGER(IntKi), PARAMETER :: M3N6RDxe = 1239 - INTEGER(IntKi), PARAMETER :: M3N7RDxe = 1240 - INTEGER(IntKi), PARAMETER :: M3N8RDxe = 1241 - INTEGER(IntKi), PARAMETER :: M3N9RDxe = 1242 - INTEGER(IntKi), PARAMETER :: M4N1RDxe = 1243 - INTEGER(IntKi), PARAMETER :: M4N2RDxe = 1244 - INTEGER(IntKi), PARAMETER :: M4N3RDxe = 1245 - INTEGER(IntKi), PARAMETER :: M4N4RDxe = 1246 - INTEGER(IntKi), PARAMETER :: M4N5RDxe = 1247 - INTEGER(IntKi), PARAMETER :: M4N6RDxe = 1248 - INTEGER(IntKi), PARAMETER :: M4N7RDxe = 1249 - INTEGER(IntKi), PARAMETER :: M4N8RDxe = 1250 - INTEGER(IntKi), PARAMETER :: M4N9RDxe = 1251 - INTEGER(IntKi), PARAMETER :: M5N1RDxe = 1252 - INTEGER(IntKi), PARAMETER :: M5N2RDxe = 1253 - INTEGER(IntKi), PARAMETER :: M5N3RDxe = 1254 - INTEGER(IntKi), PARAMETER :: M5N4RDxe = 1255 - INTEGER(IntKi), PARAMETER :: M5N5RDxe = 1256 - INTEGER(IntKi), PARAMETER :: M5N6RDxe = 1257 - INTEGER(IntKi), PARAMETER :: M5N7RDxe = 1258 - INTEGER(IntKi), PARAMETER :: M5N8RDxe = 1259 - INTEGER(IntKi), PARAMETER :: M5N9RDxe = 1260 - INTEGER(IntKi), PARAMETER :: M6N1RDxe = 1261 - INTEGER(IntKi), PARAMETER :: M6N2RDxe = 1262 - INTEGER(IntKi), PARAMETER :: M6N3RDxe = 1263 - INTEGER(IntKi), PARAMETER :: M6N4RDxe = 1264 - INTEGER(IntKi), PARAMETER :: M6N5RDxe = 1265 - INTEGER(IntKi), PARAMETER :: M6N6RDxe = 1266 - INTEGER(IntKi), PARAMETER :: M6N7RDxe = 1267 - INTEGER(IntKi), PARAMETER :: M6N8RDxe = 1268 - INTEGER(IntKi), PARAMETER :: M6N9RDxe = 1269 - INTEGER(IntKi), PARAMETER :: M7N1RDxe = 1270 - INTEGER(IntKi), PARAMETER :: M7N2RDxe = 1271 - INTEGER(IntKi), PARAMETER :: M7N3RDxe = 1272 - INTEGER(IntKi), PARAMETER :: M7N4RDxe = 1273 - INTEGER(IntKi), PARAMETER :: M7N5RDxe = 1274 - INTEGER(IntKi), PARAMETER :: M7N6RDxe = 1275 - INTEGER(IntKi), PARAMETER :: M7N7RDxe = 1276 - INTEGER(IntKi), PARAMETER :: M7N8RDxe = 1277 - INTEGER(IntKi), PARAMETER :: M7N9RDxe = 1278 - INTEGER(IntKi), PARAMETER :: M8N1RDxe = 1279 - INTEGER(IntKi), PARAMETER :: M8N2RDxe = 1280 - INTEGER(IntKi), PARAMETER :: M8N3RDxe = 1281 - INTEGER(IntKi), PARAMETER :: M8N4RDxe = 1282 - INTEGER(IntKi), PARAMETER :: M8N5RDxe = 1283 - INTEGER(IntKi), PARAMETER :: M8N6RDxe = 1284 - INTEGER(IntKi), PARAMETER :: M8N7RDxe = 1285 - INTEGER(IntKi), PARAMETER :: M8N8RDxe = 1286 - INTEGER(IntKi), PARAMETER :: M8N9RDxe = 1287 - INTEGER(IntKi), PARAMETER :: M9N1RDxe = 1288 - INTEGER(IntKi), PARAMETER :: M9N2RDxe = 1289 - INTEGER(IntKi), PARAMETER :: M9N3RDxe = 1290 - INTEGER(IntKi), PARAMETER :: M9N4RDxe = 1291 - INTEGER(IntKi), PARAMETER :: M9N5RDxe = 1292 - INTEGER(IntKi), PARAMETER :: M9N6RDxe = 1293 - INTEGER(IntKi), PARAMETER :: M9N7RDxe = 1294 - INTEGER(IntKi), PARAMETER :: M9N8RDxe = 1295 - INTEGER(IntKi), PARAMETER :: M9N9RDxe = 1296 - INTEGER(IntKi), PARAMETER :: M1N1RDye = 1297 - INTEGER(IntKi), PARAMETER :: M1N2RDye = 1298 - INTEGER(IntKi), PARAMETER :: M1N3RDye = 1299 - INTEGER(IntKi), PARAMETER :: M1N4RDye = 1300 - INTEGER(IntKi), PARAMETER :: M1N5RDye = 1301 - INTEGER(IntKi), PARAMETER :: M1N6RDye = 1302 - INTEGER(IntKi), PARAMETER :: M1N7RDye = 1303 - INTEGER(IntKi), PARAMETER :: M1N8RDye = 1304 - INTEGER(IntKi), PARAMETER :: M1N9RDye = 1305 - INTEGER(IntKi), PARAMETER :: M2N1RDye = 1306 - INTEGER(IntKi), PARAMETER :: M2N2RDye = 1307 - INTEGER(IntKi), PARAMETER :: M2N3RDye = 1308 - INTEGER(IntKi), PARAMETER :: M2N4RDye = 1309 - INTEGER(IntKi), PARAMETER :: M2N5RDye = 1310 - INTEGER(IntKi), PARAMETER :: M2N6RDye = 1311 - INTEGER(IntKi), PARAMETER :: M2N7RDye = 1312 - INTEGER(IntKi), PARAMETER :: M2N8RDye = 1313 - INTEGER(IntKi), PARAMETER :: M2N9RDye = 1314 - INTEGER(IntKi), PARAMETER :: M3N1RDye = 1315 - INTEGER(IntKi), PARAMETER :: M3N2RDye = 1316 - INTEGER(IntKi), PARAMETER :: M3N3RDye = 1317 - INTEGER(IntKi), PARAMETER :: M3N4RDye = 1318 - INTEGER(IntKi), PARAMETER :: M3N5RDye = 1319 - INTEGER(IntKi), PARAMETER :: M3N6RDye = 1320 - INTEGER(IntKi), PARAMETER :: M3N7RDye = 1321 - INTEGER(IntKi), PARAMETER :: M3N8RDye = 1322 - INTEGER(IntKi), PARAMETER :: M3N9RDye = 1323 - INTEGER(IntKi), PARAMETER :: M4N1RDye = 1324 - INTEGER(IntKi), PARAMETER :: M4N2RDye = 1325 - INTEGER(IntKi), PARAMETER :: M4N3RDye = 1326 - INTEGER(IntKi), PARAMETER :: M4N4RDye = 1327 - INTEGER(IntKi), PARAMETER :: M4N5RDye = 1328 - INTEGER(IntKi), PARAMETER :: M4N6RDye = 1329 - INTEGER(IntKi), PARAMETER :: M4N7RDye = 1330 - INTEGER(IntKi), PARAMETER :: M4N8RDye = 1331 - INTEGER(IntKi), PARAMETER :: M4N9RDye = 1332 - INTEGER(IntKi), PARAMETER :: M5N1RDye = 1333 - INTEGER(IntKi), PARAMETER :: M5N2RDye = 1334 - INTEGER(IntKi), PARAMETER :: M5N3RDye = 1335 - INTEGER(IntKi), PARAMETER :: M5N4RDye = 1336 - INTEGER(IntKi), PARAMETER :: M5N5RDye = 1337 - INTEGER(IntKi), PARAMETER :: M5N6RDye = 1338 - INTEGER(IntKi), PARAMETER :: M5N7RDye = 1339 - INTEGER(IntKi), PARAMETER :: M5N8RDye = 1340 - INTEGER(IntKi), PARAMETER :: M5N9RDye = 1341 - INTEGER(IntKi), PARAMETER :: M6N1RDye = 1342 - INTEGER(IntKi), PARAMETER :: M6N2RDye = 1343 - INTEGER(IntKi), PARAMETER :: M6N3RDye = 1344 - INTEGER(IntKi), PARAMETER :: M6N4RDye = 1345 - INTEGER(IntKi), PARAMETER :: M6N5RDye = 1346 - INTEGER(IntKi), PARAMETER :: M6N6RDye = 1347 - INTEGER(IntKi), PARAMETER :: M6N7RDye = 1348 - INTEGER(IntKi), PARAMETER :: M6N8RDye = 1349 - INTEGER(IntKi), PARAMETER :: M6N9RDye = 1350 - INTEGER(IntKi), PARAMETER :: M7N1RDye = 1351 - INTEGER(IntKi), PARAMETER :: M7N2RDye = 1352 - INTEGER(IntKi), PARAMETER :: M7N3RDye = 1353 - INTEGER(IntKi), PARAMETER :: M7N4RDye = 1354 - INTEGER(IntKi), PARAMETER :: M7N5RDye = 1355 - INTEGER(IntKi), PARAMETER :: M7N6RDye = 1356 - INTEGER(IntKi), PARAMETER :: M7N7RDye = 1357 - INTEGER(IntKi), PARAMETER :: M7N8RDye = 1358 - INTEGER(IntKi), PARAMETER :: M7N9RDye = 1359 - INTEGER(IntKi), PARAMETER :: M8N1RDye = 1360 - INTEGER(IntKi), PARAMETER :: M8N2RDye = 1361 - INTEGER(IntKi), PARAMETER :: M8N3RDye = 1362 - INTEGER(IntKi), PARAMETER :: M8N4RDye = 1363 - INTEGER(IntKi), PARAMETER :: M8N5RDye = 1364 - INTEGER(IntKi), PARAMETER :: M8N6RDye = 1365 - INTEGER(IntKi), PARAMETER :: M8N7RDye = 1366 - INTEGER(IntKi), PARAMETER :: M8N8RDye = 1367 - INTEGER(IntKi), PARAMETER :: M8N9RDye = 1368 - INTEGER(IntKi), PARAMETER :: M9N1RDye = 1369 - INTEGER(IntKi), PARAMETER :: M9N2RDye = 1370 - INTEGER(IntKi), PARAMETER :: M9N3RDye = 1371 - INTEGER(IntKi), PARAMETER :: M9N4RDye = 1372 - INTEGER(IntKi), PARAMETER :: M9N5RDye = 1373 - INTEGER(IntKi), PARAMETER :: M9N6RDye = 1374 - INTEGER(IntKi), PARAMETER :: M9N7RDye = 1375 - INTEGER(IntKi), PARAMETER :: M9N8RDye = 1376 - INTEGER(IntKi), PARAMETER :: M9N9RDye = 1377 - INTEGER(IntKi), PARAMETER :: M1N1RDze = 1378 - INTEGER(IntKi), PARAMETER :: M1N2RDze = 1379 - INTEGER(IntKi), PARAMETER :: M1N3RDze = 1380 - INTEGER(IntKi), PARAMETER :: M1N4RDze = 1381 - INTEGER(IntKi), PARAMETER :: M1N5RDze = 1382 - INTEGER(IntKi), PARAMETER :: M1N6RDze = 1383 - INTEGER(IntKi), PARAMETER :: M1N7RDze = 1384 - INTEGER(IntKi), PARAMETER :: M1N8RDze = 1385 - INTEGER(IntKi), PARAMETER :: M1N9RDze = 1386 - INTEGER(IntKi), PARAMETER :: M2N1RDze = 1387 - INTEGER(IntKi), PARAMETER :: M2N2RDze = 1388 - INTEGER(IntKi), PARAMETER :: M2N3RDze = 1389 - INTEGER(IntKi), PARAMETER :: M2N4RDze = 1390 - INTEGER(IntKi), PARAMETER :: M2N5RDze = 1391 - INTEGER(IntKi), PARAMETER :: M2N6RDze = 1392 - INTEGER(IntKi), PARAMETER :: M2N7RDze = 1393 - INTEGER(IntKi), PARAMETER :: M2N8RDze = 1394 - INTEGER(IntKi), PARAMETER :: M2N9RDze = 1395 - INTEGER(IntKi), PARAMETER :: M3N1RDze = 1396 - INTEGER(IntKi), PARAMETER :: M3N2RDze = 1397 - INTEGER(IntKi), PARAMETER :: M3N3RDze = 1398 - INTEGER(IntKi), PARAMETER :: M3N4RDze = 1399 - INTEGER(IntKi), PARAMETER :: M3N5RDze = 1400 - INTEGER(IntKi), PARAMETER :: M3N6RDze = 1401 - INTEGER(IntKi), PARAMETER :: M3N7RDze = 1402 - INTEGER(IntKi), PARAMETER :: M3N8RDze = 1403 - INTEGER(IntKi), PARAMETER :: M3N9RDze = 1404 - INTEGER(IntKi), PARAMETER :: M4N1RDze = 1405 - INTEGER(IntKi), PARAMETER :: M4N2RDze = 1406 - INTEGER(IntKi), PARAMETER :: M4N3RDze = 1407 - INTEGER(IntKi), PARAMETER :: M4N4RDze = 1408 - INTEGER(IntKi), PARAMETER :: M4N5RDze = 1409 - INTEGER(IntKi), PARAMETER :: M4N6RDze = 1410 - INTEGER(IntKi), PARAMETER :: M4N7RDze = 1411 - INTEGER(IntKi), PARAMETER :: M4N8RDze = 1412 - INTEGER(IntKi), PARAMETER :: M4N9RDze = 1413 - INTEGER(IntKi), PARAMETER :: M5N1RDze = 1414 - INTEGER(IntKi), PARAMETER :: M5N2RDze = 1415 - INTEGER(IntKi), PARAMETER :: M5N3RDze = 1416 - INTEGER(IntKi), PARAMETER :: M5N4RDze = 1417 - INTEGER(IntKi), PARAMETER :: M5N5RDze = 1418 - INTEGER(IntKi), PARAMETER :: M5N6RDze = 1419 - INTEGER(IntKi), PARAMETER :: M5N7RDze = 1420 - INTEGER(IntKi), PARAMETER :: M5N8RDze = 1421 - INTEGER(IntKi), PARAMETER :: M5N9RDze = 1422 - INTEGER(IntKi), PARAMETER :: M6N1RDze = 1423 - INTEGER(IntKi), PARAMETER :: M6N2RDze = 1424 - INTEGER(IntKi), PARAMETER :: M6N3RDze = 1425 - INTEGER(IntKi), PARAMETER :: M6N4RDze = 1426 - INTEGER(IntKi), PARAMETER :: M6N5RDze = 1427 - INTEGER(IntKi), PARAMETER :: M6N6RDze = 1428 - INTEGER(IntKi), PARAMETER :: M6N7RDze = 1429 - INTEGER(IntKi), PARAMETER :: M6N8RDze = 1430 - INTEGER(IntKi), PARAMETER :: M6N9RDze = 1431 - INTEGER(IntKi), PARAMETER :: M7N1RDze = 1432 - INTEGER(IntKi), PARAMETER :: M7N2RDze = 1433 - INTEGER(IntKi), PARAMETER :: M7N3RDze = 1434 - INTEGER(IntKi), PARAMETER :: M7N4RDze = 1435 - INTEGER(IntKi), PARAMETER :: M7N5RDze = 1436 - INTEGER(IntKi), PARAMETER :: M7N6RDze = 1437 - INTEGER(IntKi), PARAMETER :: M7N7RDze = 1438 - INTEGER(IntKi), PARAMETER :: M7N8RDze = 1439 - INTEGER(IntKi), PARAMETER :: M7N9RDze = 1440 - INTEGER(IntKi), PARAMETER :: M8N1RDze = 1441 - INTEGER(IntKi), PARAMETER :: M8N2RDze = 1442 - INTEGER(IntKi), PARAMETER :: M8N3RDze = 1443 - INTEGER(IntKi), PARAMETER :: M8N4RDze = 1444 - INTEGER(IntKi), PARAMETER :: M8N5RDze = 1445 - INTEGER(IntKi), PARAMETER :: M8N6RDze = 1446 - INTEGER(IntKi), PARAMETER :: M8N7RDze = 1447 - INTEGER(IntKi), PARAMETER :: M8N8RDze = 1448 - INTEGER(IntKi), PARAMETER :: M8N9RDze = 1449 - INTEGER(IntKi), PARAMETER :: M9N1RDze = 1450 - INTEGER(IntKi), PARAMETER :: M9N2RDze = 1451 - INTEGER(IntKi), PARAMETER :: M9N3RDze = 1452 - INTEGER(IntKi), PARAMETER :: M9N4RDze = 1453 - INTEGER(IntKi), PARAMETER :: M9N5RDze = 1454 - INTEGER(IntKi), PARAMETER :: M9N6RDze = 1455 - INTEGER(IntKi), PARAMETER :: M9N7RDze = 1456 - INTEGER(IntKi), PARAMETER :: M9N8RDze = 1457 - INTEGER(IntKi), PARAMETER :: M9N9RDze = 1458 - - - ! Accelerations: - - INTEGER(IntKi), PARAMETER :: M1N1TAxe = 1459 - INTEGER(IntKi), PARAMETER :: M1N2TAxe = 1460 - INTEGER(IntKi), PARAMETER :: M1N3TAxe = 1461 - INTEGER(IntKi), PARAMETER :: M1N4TAxe = 1462 - INTEGER(IntKi), PARAMETER :: M1N5TAxe = 1463 - INTEGER(IntKi), PARAMETER :: M1N6TAxe = 1464 - INTEGER(IntKi), PARAMETER :: M1N7TAxe = 1465 - INTEGER(IntKi), PARAMETER :: M1N8TAxe = 1466 - INTEGER(IntKi), PARAMETER :: M1N9TAxe = 1467 - INTEGER(IntKi), PARAMETER :: M2N1TAxe = 1468 - INTEGER(IntKi), PARAMETER :: M2N2TAxe = 1469 - INTEGER(IntKi), PARAMETER :: M2N3TAxe = 1470 - INTEGER(IntKi), PARAMETER :: M2N4TAxe = 1471 - INTEGER(IntKi), PARAMETER :: M2N5TAxe = 1472 - INTEGER(IntKi), PARAMETER :: M2N6TAxe = 1473 - INTEGER(IntKi), PARAMETER :: M2N7TAxe = 1474 - INTEGER(IntKi), PARAMETER :: M2N8TAxe = 1475 - INTEGER(IntKi), PARAMETER :: M2N9TAxe = 1476 - INTEGER(IntKi), PARAMETER :: M3N1TAxe = 1477 - INTEGER(IntKi), PARAMETER :: M3N2TAxe = 1478 - INTEGER(IntKi), PARAMETER :: M3N3TAxe = 1479 - INTEGER(IntKi), PARAMETER :: M3N4TAxe = 1480 - INTEGER(IntKi), PARAMETER :: M3N5TAxe = 1481 - INTEGER(IntKi), PARAMETER :: M3N6TAxe = 1482 - INTEGER(IntKi), PARAMETER :: M3N7TAxe = 1483 - INTEGER(IntKi), PARAMETER :: M3N8TAxe = 1484 - INTEGER(IntKi), PARAMETER :: M3N9TAxe = 1485 - INTEGER(IntKi), PARAMETER :: M4N1TAxe = 1486 - INTEGER(IntKi), PARAMETER :: M4N2TAxe = 1487 - INTEGER(IntKi), PARAMETER :: M4N3TAxe = 1488 - INTEGER(IntKi), PARAMETER :: M4N4TAxe = 1489 - INTEGER(IntKi), PARAMETER :: M4N5TAxe = 1490 - INTEGER(IntKi), PARAMETER :: M4N6TAxe = 1491 - INTEGER(IntKi), PARAMETER :: M4N7TAxe = 1492 - INTEGER(IntKi), PARAMETER :: M4N8TAxe = 1493 - INTEGER(IntKi), PARAMETER :: M4N9TAxe = 1494 - INTEGER(IntKi), PARAMETER :: M5N1TAxe = 1495 - INTEGER(IntKi), PARAMETER :: M5N2TAxe = 1496 - INTEGER(IntKi), PARAMETER :: M5N3TAxe = 1497 - INTEGER(IntKi), PARAMETER :: M5N4TAxe = 1498 - INTEGER(IntKi), PARAMETER :: M5N5TAxe = 1499 - INTEGER(IntKi), PARAMETER :: M5N6TAxe = 1500 - INTEGER(IntKi), PARAMETER :: M5N7TAxe = 1501 - INTEGER(IntKi), PARAMETER :: M5N8TAxe = 1502 - INTEGER(IntKi), PARAMETER :: M5N9TAxe = 1503 - INTEGER(IntKi), PARAMETER :: M6N1TAxe = 1504 - INTEGER(IntKi), PARAMETER :: M6N2TAxe = 1505 - INTEGER(IntKi), PARAMETER :: M6N3TAxe = 1506 - INTEGER(IntKi), PARAMETER :: M6N4TAxe = 1507 - INTEGER(IntKi), PARAMETER :: M6N5TAxe = 1508 - INTEGER(IntKi), PARAMETER :: M6N6TAxe = 1509 - INTEGER(IntKi), PARAMETER :: M6N7TAxe = 1510 - INTEGER(IntKi), PARAMETER :: M6N8TAxe = 1511 - INTEGER(IntKi), PARAMETER :: M6N9TAxe = 1512 - INTEGER(IntKi), PARAMETER :: M7N1TAxe = 1513 - INTEGER(IntKi), PARAMETER :: M7N2TAxe = 1514 - INTEGER(IntKi), PARAMETER :: M7N3TAxe = 1515 - INTEGER(IntKi), PARAMETER :: M7N4TAxe = 1516 - INTEGER(IntKi), PARAMETER :: M7N5TAxe = 1517 - INTEGER(IntKi), PARAMETER :: M7N6TAxe = 1518 - INTEGER(IntKi), PARAMETER :: M7N7TAxe = 1519 - INTEGER(IntKi), PARAMETER :: M7N8TAxe = 1520 - INTEGER(IntKi), PARAMETER :: M7N9TAxe = 1521 - INTEGER(IntKi), PARAMETER :: M8N1TAxe = 1522 - INTEGER(IntKi), PARAMETER :: M8N2TAxe = 1523 - INTEGER(IntKi), PARAMETER :: M8N3TAxe = 1524 - INTEGER(IntKi), PARAMETER :: M8N4TAxe = 1525 - INTEGER(IntKi), PARAMETER :: M8N5TAxe = 1526 - INTEGER(IntKi), PARAMETER :: M8N6TAxe = 1527 - INTEGER(IntKi), PARAMETER :: M8N7TAxe = 1528 - INTEGER(IntKi), PARAMETER :: M8N8TAxe = 1529 - INTEGER(IntKi), PARAMETER :: M8N9TAxe = 1530 - INTEGER(IntKi), PARAMETER :: M9N1TAxe = 1531 - INTEGER(IntKi), PARAMETER :: M9N2TAxe = 1532 - INTEGER(IntKi), PARAMETER :: M9N3TAxe = 1533 - INTEGER(IntKi), PARAMETER :: M9N4TAxe = 1534 - INTEGER(IntKi), PARAMETER :: M9N5TAxe = 1535 - INTEGER(IntKi), PARAMETER :: M9N6TAxe = 1536 - INTEGER(IntKi), PARAMETER :: M9N7TAxe = 1537 - INTEGER(IntKi), PARAMETER :: M9N8TAxe = 1538 - INTEGER(IntKi), PARAMETER :: M9N9TAxe = 1539 - INTEGER(IntKi), PARAMETER :: M1N1TAye = 1540 - INTEGER(IntKi), PARAMETER :: M1N2TAye = 1541 - INTEGER(IntKi), PARAMETER :: M1N3TAye = 1542 - INTEGER(IntKi), PARAMETER :: M1N4TAye = 1543 - INTEGER(IntKi), PARAMETER :: M1N5TAye = 1544 - INTEGER(IntKi), PARAMETER :: M1N6TAye = 1545 - INTEGER(IntKi), PARAMETER :: M1N7TAye = 1546 - INTEGER(IntKi), PARAMETER :: M1N8TAye = 1547 - INTEGER(IntKi), PARAMETER :: M1N9TAye = 1548 - INTEGER(IntKi), PARAMETER :: M2N1TAye = 1549 - INTEGER(IntKi), PARAMETER :: M2N2TAye = 1550 - INTEGER(IntKi), PARAMETER :: M2N3TAye = 1551 - INTEGER(IntKi), PARAMETER :: M2N4TAye = 1552 - INTEGER(IntKi), PARAMETER :: M2N5TAye = 1553 - INTEGER(IntKi), PARAMETER :: M2N6TAye = 1554 - INTEGER(IntKi), PARAMETER :: M2N7TAye = 1555 - INTEGER(IntKi), PARAMETER :: M2N8TAye = 1556 - INTEGER(IntKi), PARAMETER :: M2N9TAye = 1557 - INTEGER(IntKi), PARAMETER :: M3N1TAye = 1558 - INTEGER(IntKi), PARAMETER :: M3N2TAye = 1559 - INTEGER(IntKi), PARAMETER :: M3N3TAye = 1560 - INTEGER(IntKi), PARAMETER :: M3N4TAye = 1561 - INTEGER(IntKi), PARAMETER :: M3N5TAye = 1562 - INTEGER(IntKi), PARAMETER :: M3N6TAye = 1563 - INTEGER(IntKi), PARAMETER :: M3N7TAye = 1564 - INTEGER(IntKi), PARAMETER :: M3N8TAye = 1565 - INTEGER(IntKi), PARAMETER :: M3N9TAye = 1566 - INTEGER(IntKi), PARAMETER :: M4N1TAye = 1567 - INTEGER(IntKi), PARAMETER :: M4N2TAye = 1568 - INTEGER(IntKi), PARAMETER :: M4N3TAye = 1569 - INTEGER(IntKi), PARAMETER :: M4N4TAye = 1570 - INTEGER(IntKi), PARAMETER :: M4N5TAye = 1571 - INTEGER(IntKi), PARAMETER :: M4N6TAye = 1572 - INTEGER(IntKi), PARAMETER :: M4N7TAye = 1573 - INTEGER(IntKi), PARAMETER :: M4N8TAye = 1574 - INTEGER(IntKi), PARAMETER :: M4N9TAye = 1575 - INTEGER(IntKi), PARAMETER :: M5N1TAye = 1576 - INTEGER(IntKi), PARAMETER :: M5N2TAye = 1577 - INTEGER(IntKi), PARAMETER :: M5N3TAye = 1578 - INTEGER(IntKi), PARAMETER :: M5N4TAye = 1579 - INTEGER(IntKi), PARAMETER :: M5N5TAye = 1580 - INTEGER(IntKi), PARAMETER :: M5N6TAye = 1581 - INTEGER(IntKi), PARAMETER :: M5N7TAye = 1582 - INTEGER(IntKi), PARAMETER :: M5N8TAye = 1583 - INTEGER(IntKi), PARAMETER :: M5N9TAye = 1584 - INTEGER(IntKi), PARAMETER :: M6N1TAye = 1585 - INTEGER(IntKi), PARAMETER :: M6N2TAye = 1586 - INTEGER(IntKi), PARAMETER :: M6N3TAye = 1587 - INTEGER(IntKi), PARAMETER :: M6N4TAye = 1588 - INTEGER(IntKi), PARAMETER :: M6N5TAye = 1589 - INTEGER(IntKi), PARAMETER :: M6N6TAye = 1590 - INTEGER(IntKi), PARAMETER :: M6N7TAye = 1591 - INTEGER(IntKi), PARAMETER :: M6N8TAye = 1592 - INTEGER(IntKi), PARAMETER :: M6N9TAye = 1593 - INTEGER(IntKi), PARAMETER :: M7N1TAye = 1594 - INTEGER(IntKi), PARAMETER :: M7N2TAye = 1595 - INTEGER(IntKi), PARAMETER :: M7N3TAye = 1596 - INTEGER(IntKi), PARAMETER :: M7N4TAye = 1597 - INTEGER(IntKi), PARAMETER :: M7N5TAye = 1598 - INTEGER(IntKi), PARAMETER :: M7N6TAye = 1599 - INTEGER(IntKi), PARAMETER :: M7N7TAye = 1600 - INTEGER(IntKi), PARAMETER :: M7N8TAye = 1601 - INTEGER(IntKi), PARAMETER :: M7N9TAye = 1602 - INTEGER(IntKi), PARAMETER :: M8N1TAye = 1603 - INTEGER(IntKi), PARAMETER :: M8N2TAye = 1604 - INTEGER(IntKi), PARAMETER :: M8N3TAye = 1605 - INTEGER(IntKi), PARAMETER :: M8N4TAye = 1606 - INTEGER(IntKi), PARAMETER :: M8N5TAye = 1607 - INTEGER(IntKi), PARAMETER :: M8N6TAye = 1608 - INTEGER(IntKi), PARAMETER :: M8N7TAye = 1609 - INTEGER(IntKi), PARAMETER :: M8N8TAye = 1610 - INTEGER(IntKi), PARAMETER :: M8N9TAye = 1611 - INTEGER(IntKi), PARAMETER :: M9N1TAye = 1612 - INTEGER(IntKi), PARAMETER :: M9N2TAye = 1613 - INTEGER(IntKi), PARAMETER :: M9N3TAye = 1614 - INTEGER(IntKi), PARAMETER :: M9N4TAye = 1615 - INTEGER(IntKi), PARAMETER :: M9N5TAye = 1616 - INTEGER(IntKi), PARAMETER :: M9N6TAye = 1617 - INTEGER(IntKi), PARAMETER :: M9N7TAye = 1618 - INTEGER(IntKi), PARAMETER :: M9N8TAye = 1619 - INTEGER(IntKi), PARAMETER :: M9N9TAye = 1620 - INTEGER(IntKi), PARAMETER :: M1N1TAze = 1621 - INTEGER(IntKi), PARAMETER :: M1N2TAze = 1622 - INTEGER(IntKi), PARAMETER :: M1N3TAze = 1623 - INTEGER(IntKi), PARAMETER :: M1N4TAze = 1624 - INTEGER(IntKi), PARAMETER :: M1N5TAze = 1625 - INTEGER(IntKi), PARAMETER :: M1N6TAze = 1626 - INTEGER(IntKi), PARAMETER :: M1N7TAze = 1627 - INTEGER(IntKi), PARAMETER :: M1N8TAze = 1628 - INTEGER(IntKi), PARAMETER :: M1N9TAze = 1629 - INTEGER(IntKi), PARAMETER :: M2N1TAze = 1630 - INTEGER(IntKi), PARAMETER :: M2N2TAze = 1631 - INTEGER(IntKi), PARAMETER :: M2N3TAze = 1632 - INTEGER(IntKi), PARAMETER :: M2N4TAze = 1633 - INTEGER(IntKi), PARAMETER :: M2N5TAze = 1634 - INTEGER(IntKi), PARAMETER :: M2N6TAze = 1635 - INTEGER(IntKi), PARAMETER :: M2N7TAze = 1636 - INTEGER(IntKi), PARAMETER :: M2N8TAze = 1637 - INTEGER(IntKi), PARAMETER :: M2N9TAze = 1638 - INTEGER(IntKi), PARAMETER :: M3N1TAze = 1639 - INTEGER(IntKi), PARAMETER :: M3N2TAze = 1640 - INTEGER(IntKi), PARAMETER :: M3N3TAze = 1641 - INTEGER(IntKi), PARAMETER :: M3N4TAze = 1642 - INTEGER(IntKi), PARAMETER :: M3N5TAze = 1643 - INTEGER(IntKi), PARAMETER :: M3N6TAze = 1644 - INTEGER(IntKi), PARAMETER :: M3N7TAze = 1645 - INTEGER(IntKi), PARAMETER :: M3N8TAze = 1646 - INTEGER(IntKi), PARAMETER :: M3N9TAze = 1647 - INTEGER(IntKi), PARAMETER :: M4N1TAze = 1648 - INTEGER(IntKi), PARAMETER :: M4N2TAze = 1649 - INTEGER(IntKi), PARAMETER :: M4N3TAze = 1650 - INTEGER(IntKi), PARAMETER :: M4N4TAze = 1651 - INTEGER(IntKi), PARAMETER :: M4N5TAze = 1652 - INTEGER(IntKi), PARAMETER :: M4N6TAze = 1653 - INTEGER(IntKi), PARAMETER :: M4N7TAze = 1654 - INTEGER(IntKi), PARAMETER :: M4N8TAze = 1655 - INTEGER(IntKi), PARAMETER :: M4N9TAze = 1656 - INTEGER(IntKi), PARAMETER :: M5N1TAze = 1657 - INTEGER(IntKi), PARAMETER :: M5N2TAze = 1658 - INTEGER(IntKi), PARAMETER :: M5N3TAze = 1659 - INTEGER(IntKi), PARAMETER :: M5N4TAze = 1660 - INTEGER(IntKi), PARAMETER :: M5N5TAze = 1661 - INTEGER(IntKi), PARAMETER :: M5N6TAze = 1662 - INTEGER(IntKi), PARAMETER :: M5N7TAze = 1663 - INTEGER(IntKi), PARAMETER :: M5N8TAze = 1664 - INTEGER(IntKi), PARAMETER :: M5N9TAze = 1665 - INTEGER(IntKi), PARAMETER :: M6N1TAze = 1666 - INTEGER(IntKi), PARAMETER :: M6N2TAze = 1667 - INTEGER(IntKi), PARAMETER :: M6N3TAze = 1668 - INTEGER(IntKi), PARAMETER :: M6N4TAze = 1669 - INTEGER(IntKi), PARAMETER :: M6N5TAze = 1670 - INTEGER(IntKi), PARAMETER :: M6N6TAze = 1671 - INTEGER(IntKi), PARAMETER :: M6N7TAze = 1672 - INTEGER(IntKi), PARAMETER :: M6N8TAze = 1673 - INTEGER(IntKi), PARAMETER :: M6N9TAze = 1674 - INTEGER(IntKi), PARAMETER :: M7N1TAze = 1675 - INTEGER(IntKi), PARAMETER :: M7N2TAze = 1676 - INTEGER(IntKi), PARAMETER :: M7N3TAze = 1677 - INTEGER(IntKi), PARAMETER :: M7N4TAze = 1678 - INTEGER(IntKi), PARAMETER :: M7N5TAze = 1679 - INTEGER(IntKi), PARAMETER :: M7N6TAze = 1680 - INTEGER(IntKi), PARAMETER :: M7N7TAze = 1681 - INTEGER(IntKi), PARAMETER :: M7N8TAze = 1682 - INTEGER(IntKi), PARAMETER :: M7N9TAze = 1683 - INTEGER(IntKi), PARAMETER :: M8N1TAze = 1684 - INTEGER(IntKi), PARAMETER :: M8N2TAze = 1685 - INTEGER(IntKi), PARAMETER :: M8N3TAze = 1686 - INTEGER(IntKi), PARAMETER :: M8N4TAze = 1687 - INTEGER(IntKi), PARAMETER :: M8N5TAze = 1688 - INTEGER(IntKi), PARAMETER :: M8N6TAze = 1689 - INTEGER(IntKi), PARAMETER :: M8N7TAze = 1690 - INTEGER(IntKi), PARAMETER :: M8N8TAze = 1691 - INTEGER(IntKi), PARAMETER :: M8N9TAze = 1692 - INTEGER(IntKi), PARAMETER :: M9N1TAze = 1693 - INTEGER(IntKi), PARAMETER :: M9N2TAze = 1694 - INTEGER(IntKi), PARAMETER :: M9N3TAze = 1695 - INTEGER(IntKi), PARAMETER :: M9N4TAze = 1696 - INTEGER(IntKi), PARAMETER :: M9N5TAze = 1697 - INTEGER(IntKi), PARAMETER :: M9N6TAze = 1698 - INTEGER(IntKi), PARAMETER :: M9N7TAze = 1699 - INTEGER(IntKi), PARAMETER :: M9N8TAze = 1700 - INTEGER(IntKi), PARAMETER :: M9N9TAze = 1701 - INTEGER(IntKi), PARAMETER :: M1N1RAxe = 1702 - INTEGER(IntKi), PARAMETER :: M1N2RAxe = 1703 - INTEGER(IntKi), PARAMETER :: M1N3RAxe = 1704 - INTEGER(IntKi), PARAMETER :: M1N4RAxe = 1705 - INTEGER(IntKi), PARAMETER :: M1N5RAxe = 1706 - INTEGER(IntKi), PARAMETER :: M1N6RAxe = 1707 - INTEGER(IntKi), PARAMETER :: M1N7RAxe = 1708 - INTEGER(IntKi), PARAMETER :: M1N8RAxe = 1709 - INTEGER(IntKi), PARAMETER :: M1N9RAxe = 1710 - INTEGER(IntKi), PARAMETER :: M2N1RAxe = 1711 - INTEGER(IntKi), PARAMETER :: M2N2RAxe = 1712 - INTEGER(IntKi), PARAMETER :: M2N3RAxe = 1713 - INTEGER(IntKi), PARAMETER :: M2N4RAxe = 1714 - INTEGER(IntKi), PARAMETER :: M2N5RAxe = 1715 - INTEGER(IntKi), PARAMETER :: M2N6RAxe = 1716 - INTEGER(IntKi), PARAMETER :: M2N7RAxe = 1717 - INTEGER(IntKi), PARAMETER :: M2N8RAxe = 1718 - INTEGER(IntKi), PARAMETER :: M2N9RAxe = 1719 - INTEGER(IntKi), PARAMETER :: M3N1RAxe = 1720 - INTEGER(IntKi), PARAMETER :: M3N2RAxe = 1721 - INTEGER(IntKi), PARAMETER :: M3N3RAxe = 1722 - INTEGER(IntKi), PARAMETER :: M3N4RAxe = 1723 - INTEGER(IntKi), PARAMETER :: M3N5RAxe = 1724 - INTEGER(IntKi), PARAMETER :: M3N6RAxe = 1725 - INTEGER(IntKi), PARAMETER :: M3N7RAxe = 1726 - INTEGER(IntKi), PARAMETER :: M3N8RAxe = 1727 - INTEGER(IntKi), PARAMETER :: M3N9RAxe = 1728 - INTEGER(IntKi), PARAMETER :: M4N1RAxe = 1729 - INTEGER(IntKi), PARAMETER :: M4N2RAxe = 1730 - INTEGER(IntKi), PARAMETER :: M4N3RAxe = 1731 - INTEGER(IntKi), PARAMETER :: M4N4RAxe = 1732 - INTEGER(IntKi), PARAMETER :: M4N5RAxe = 1733 - INTEGER(IntKi), PARAMETER :: M4N6RAxe = 1734 - INTEGER(IntKi), PARAMETER :: M4N7RAxe = 1735 - INTEGER(IntKi), PARAMETER :: M4N8RAxe = 1736 - INTEGER(IntKi), PARAMETER :: M4N9RAxe = 1737 - INTEGER(IntKi), PARAMETER :: M5N1RAxe = 1738 - INTEGER(IntKi), PARAMETER :: M5N2RAxe = 1739 - INTEGER(IntKi), PARAMETER :: M5N3RAxe = 1740 - INTEGER(IntKi), PARAMETER :: M5N4RAxe = 1741 - INTEGER(IntKi), PARAMETER :: M5N5RAxe = 1742 - INTEGER(IntKi), PARAMETER :: M5N6RAxe = 1743 - INTEGER(IntKi), PARAMETER :: M5N7RAxe = 1744 - INTEGER(IntKi), PARAMETER :: M5N8RAxe = 1745 - INTEGER(IntKi), PARAMETER :: M5N9RAxe = 1746 - INTEGER(IntKi), PARAMETER :: M6N1RAxe = 1747 - INTEGER(IntKi), PARAMETER :: M6N2RAxe = 1748 - INTEGER(IntKi), PARAMETER :: M6N3RAxe = 1749 - INTEGER(IntKi), PARAMETER :: M6N4RAxe = 1750 - INTEGER(IntKi), PARAMETER :: M6N5RAxe = 1751 - INTEGER(IntKi), PARAMETER :: M6N6RAxe = 1752 - INTEGER(IntKi), PARAMETER :: M6N7RAxe = 1753 - INTEGER(IntKi), PARAMETER :: M6N8RAxe = 1754 - INTEGER(IntKi), PARAMETER :: M6N9RAxe = 1755 - INTEGER(IntKi), PARAMETER :: M7N1RAxe = 1756 - INTEGER(IntKi), PARAMETER :: M7N2RAxe = 1757 - INTEGER(IntKi), PARAMETER :: M7N3RAxe = 1758 - INTEGER(IntKi), PARAMETER :: M7N4RAxe = 1759 - INTEGER(IntKi), PARAMETER :: M7N5RAxe = 1760 - INTEGER(IntKi), PARAMETER :: M7N6RAxe = 1761 - INTEGER(IntKi), PARAMETER :: M7N7RAxe = 1762 - INTEGER(IntKi), PARAMETER :: M7N8RAxe = 1763 - INTEGER(IntKi), PARAMETER :: M7N9RAxe = 1764 - INTEGER(IntKi), PARAMETER :: M8N1RAxe = 1765 - INTEGER(IntKi), PARAMETER :: M8N2RAxe = 1766 - INTEGER(IntKi), PARAMETER :: M8N3RAxe = 1767 - INTEGER(IntKi), PARAMETER :: M8N4RAxe = 1768 - INTEGER(IntKi), PARAMETER :: M8N5RAxe = 1769 - INTEGER(IntKi), PARAMETER :: M8N6RAxe = 1770 - INTEGER(IntKi), PARAMETER :: M8N7RAxe = 1771 - INTEGER(IntKi), PARAMETER :: M8N8RAxe = 1772 - INTEGER(IntKi), PARAMETER :: M8N9RAxe = 1773 - INTEGER(IntKi), PARAMETER :: M9N1RAxe = 1774 - INTEGER(IntKi), PARAMETER :: M9N2RAxe = 1775 - INTEGER(IntKi), PARAMETER :: M9N3RAxe = 1776 - INTEGER(IntKi), PARAMETER :: M9N4RAxe = 1777 - INTEGER(IntKi), PARAMETER :: M9N5RAxe = 1778 - INTEGER(IntKi), PARAMETER :: M9N6RAxe = 1779 - INTEGER(IntKi), PARAMETER :: M9N7RAxe = 1780 - INTEGER(IntKi), PARAMETER :: M9N8RAxe = 1781 - INTEGER(IntKi), PARAMETER :: M9N9RAxe = 1782 - INTEGER(IntKi), PARAMETER :: M1N1RAye = 1783 - INTEGER(IntKi), PARAMETER :: M1N2RAye = 1784 - INTEGER(IntKi), PARAMETER :: M1N3RAye = 1785 - INTEGER(IntKi), PARAMETER :: M1N4RAye = 1786 - INTEGER(IntKi), PARAMETER :: M1N5RAye = 1787 - INTEGER(IntKi), PARAMETER :: M1N6RAye = 1788 - INTEGER(IntKi), PARAMETER :: M1N7RAye = 1789 - INTEGER(IntKi), PARAMETER :: M1N8RAye = 1790 - INTEGER(IntKi), PARAMETER :: M1N9RAye = 1791 - INTEGER(IntKi), PARAMETER :: M2N1RAye = 1792 - INTEGER(IntKi), PARAMETER :: M2N2RAye = 1793 - INTEGER(IntKi), PARAMETER :: M2N3RAye = 1794 - INTEGER(IntKi), PARAMETER :: M2N4RAye = 1795 - INTEGER(IntKi), PARAMETER :: M2N5RAye = 1796 - INTEGER(IntKi), PARAMETER :: M2N6RAye = 1797 - INTEGER(IntKi), PARAMETER :: M2N7RAye = 1798 - INTEGER(IntKi), PARAMETER :: M2N8RAye = 1799 - INTEGER(IntKi), PARAMETER :: M2N9RAye = 1800 - INTEGER(IntKi), PARAMETER :: M3N1RAye = 1801 - INTEGER(IntKi), PARAMETER :: M3N2RAye = 1802 - INTEGER(IntKi), PARAMETER :: M3N3RAye = 1803 - INTEGER(IntKi), PARAMETER :: M3N4RAye = 1804 - INTEGER(IntKi), PARAMETER :: M3N5RAye = 1805 - INTEGER(IntKi), PARAMETER :: M3N6RAye = 1806 - INTEGER(IntKi), PARAMETER :: M3N7RAye = 1807 - INTEGER(IntKi), PARAMETER :: M3N8RAye = 1808 - INTEGER(IntKi), PARAMETER :: M3N9RAye = 1809 - INTEGER(IntKi), PARAMETER :: M4N1RAye = 1810 - INTEGER(IntKi), PARAMETER :: M4N2RAye = 1811 - INTEGER(IntKi), PARAMETER :: M4N3RAye = 1812 - INTEGER(IntKi), PARAMETER :: M4N4RAye = 1813 - INTEGER(IntKi), PARAMETER :: M4N5RAye = 1814 - INTEGER(IntKi), PARAMETER :: M4N6RAye = 1815 - INTEGER(IntKi), PARAMETER :: M4N7RAye = 1816 - INTEGER(IntKi), PARAMETER :: M4N8RAye = 1817 - INTEGER(IntKi), PARAMETER :: M4N9RAye = 1818 - INTEGER(IntKi), PARAMETER :: M5N1RAye = 1819 - INTEGER(IntKi), PARAMETER :: M5N2RAye = 1820 - INTEGER(IntKi), PARAMETER :: M5N3RAye = 1821 - INTEGER(IntKi), PARAMETER :: M5N4RAye = 1822 - INTEGER(IntKi), PARAMETER :: M5N5RAye = 1823 - INTEGER(IntKi), PARAMETER :: M5N6RAye = 1824 - INTEGER(IntKi), PARAMETER :: M5N7RAye = 1825 - INTEGER(IntKi), PARAMETER :: M5N8RAye = 1826 - INTEGER(IntKi), PARAMETER :: M5N9RAye = 1827 - INTEGER(IntKi), PARAMETER :: M6N1RAye = 1828 - INTEGER(IntKi), PARAMETER :: M6N2RAye = 1829 - INTEGER(IntKi), PARAMETER :: M6N3RAye = 1830 - INTEGER(IntKi), PARAMETER :: M6N4RAye = 1831 - INTEGER(IntKi), PARAMETER :: M6N5RAye = 1832 - INTEGER(IntKi), PARAMETER :: M6N6RAye = 1833 - INTEGER(IntKi), PARAMETER :: M6N7RAye = 1834 - INTEGER(IntKi), PARAMETER :: M6N8RAye = 1835 - INTEGER(IntKi), PARAMETER :: M6N9RAye = 1836 - INTEGER(IntKi), PARAMETER :: M7N1RAye = 1837 - INTEGER(IntKi), PARAMETER :: M7N2RAye = 1838 - INTEGER(IntKi), PARAMETER :: M7N3RAye = 1839 - INTEGER(IntKi), PARAMETER :: M7N4RAye = 1840 - INTEGER(IntKi), PARAMETER :: M7N5RAye = 1841 - INTEGER(IntKi), PARAMETER :: M7N6RAye = 1842 - INTEGER(IntKi), PARAMETER :: M7N7RAye = 1843 - INTEGER(IntKi), PARAMETER :: M7N8RAye = 1844 - INTEGER(IntKi), PARAMETER :: M7N9RAye = 1845 - INTEGER(IntKi), PARAMETER :: M8N1RAye = 1846 - INTEGER(IntKi), PARAMETER :: M8N2RAye = 1847 - INTEGER(IntKi), PARAMETER :: M8N3RAye = 1848 - INTEGER(IntKi), PARAMETER :: M8N4RAye = 1849 - INTEGER(IntKi), PARAMETER :: M8N5RAye = 1850 - INTEGER(IntKi), PARAMETER :: M8N6RAye = 1851 - INTEGER(IntKi), PARAMETER :: M8N7RAye = 1852 - INTEGER(IntKi), PARAMETER :: M8N8RAye = 1853 - INTEGER(IntKi), PARAMETER :: M8N9RAye = 1854 - INTEGER(IntKi), PARAMETER :: M9N1RAye = 1855 - INTEGER(IntKi), PARAMETER :: M9N2RAye = 1856 - INTEGER(IntKi), PARAMETER :: M9N3RAye = 1857 - INTEGER(IntKi), PARAMETER :: M9N4RAye = 1858 - INTEGER(IntKi), PARAMETER :: M9N5RAye = 1859 - INTEGER(IntKi), PARAMETER :: M9N6RAye = 1860 - INTEGER(IntKi), PARAMETER :: M9N7RAye = 1861 - INTEGER(IntKi), PARAMETER :: M9N8RAye = 1862 - INTEGER(IntKi), PARAMETER :: M9N9RAye = 1863 - INTEGER(IntKi), PARAMETER :: M1N1RAze = 1864 - INTEGER(IntKi), PARAMETER :: M1N2RAze = 1865 - INTEGER(IntKi), PARAMETER :: M1N3RAze = 1866 - INTEGER(IntKi), PARAMETER :: M1N4RAze = 1867 - INTEGER(IntKi), PARAMETER :: M1N5RAze = 1868 - INTEGER(IntKi), PARAMETER :: M1N6RAze = 1869 - INTEGER(IntKi), PARAMETER :: M1N7RAze = 1870 - INTEGER(IntKi), PARAMETER :: M1N8RAze = 1871 - INTEGER(IntKi), PARAMETER :: M1N9RAze = 1872 - INTEGER(IntKi), PARAMETER :: M2N1RAze = 1873 - INTEGER(IntKi), PARAMETER :: M2N2RAze = 1874 - INTEGER(IntKi), PARAMETER :: M2N3RAze = 1875 - INTEGER(IntKi), PARAMETER :: M2N4RAze = 1876 - INTEGER(IntKi), PARAMETER :: M2N5RAze = 1877 - INTEGER(IntKi), PARAMETER :: M2N6RAze = 1878 - INTEGER(IntKi), PARAMETER :: M2N7RAze = 1879 - INTEGER(IntKi), PARAMETER :: M2N8RAze = 1880 - INTEGER(IntKi), PARAMETER :: M2N9RAze = 1881 - INTEGER(IntKi), PARAMETER :: M3N1RAze = 1882 - INTEGER(IntKi), PARAMETER :: M3N2RAze = 1883 - INTEGER(IntKi), PARAMETER :: M3N3RAze = 1884 - INTEGER(IntKi), PARAMETER :: M3N4RAze = 1885 - INTEGER(IntKi), PARAMETER :: M3N5RAze = 1886 - INTEGER(IntKi), PARAMETER :: M3N6RAze = 1887 - INTEGER(IntKi), PARAMETER :: M3N7RAze = 1888 - INTEGER(IntKi), PARAMETER :: M3N8RAze = 1889 - INTEGER(IntKi), PARAMETER :: M3N9RAze = 1890 - INTEGER(IntKi), PARAMETER :: M4N1RAze = 1891 - INTEGER(IntKi), PARAMETER :: M4N2RAze = 1892 - INTEGER(IntKi), PARAMETER :: M4N3RAze = 1893 - INTEGER(IntKi), PARAMETER :: M4N4RAze = 1894 - INTEGER(IntKi), PARAMETER :: M4N5RAze = 1895 - INTEGER(IntKi), PARAMETER :: M4N6RAze = 1896 - INTEGER(IntKi), PARAMETER :: M4N7RAze = 1897 - INTEGER(IntKi), PARAMETER :: M4N8RAze = 1898 - INTEGER(IntKi), PARAMETER :: M4N9RAze = 1899 - INTEGER(IntKi), PARAMETER :: M5N1RAze = 1900 - INTEGER(IntKi), PARAMETER :: M5N2RAze = 1901 - INTEGER(IntKi), PARAMETER :: M5N3RAze = 1902 - INTEGER(IntKi), PARAMETER :: M5N4RAze = 1903 - INTEGER(IntKi), PARAMETER :: M5N5RAze = 1904 - INTEGER(IntKi), PARAMETER :: M5N6RAze = 1905 - INTEGER(IntKi), PARAMETER :: M5N7RAze = 1906 - INTEGER(IntKi), PARAMETER :: M5N8RAze = 1907 - INTEGER(IntKi), PARAMETER :: M5N9RAze = 1908 - INTEGER(IntKi), PARAMETER :: M6N1RAze = 1909 - INTEGER(IntKi), PARAMETER :: M6N2RAze = 1910 - INTEGER(IntKi), PARAMETER :: M6N3RAze = 1911 - INTEGER(IntKi), PARAMETER :: M6N4RAze = 1912 - INTEGER(IntKi), PARAMETER :: M6N5RAze = 1913 - INTEGER(IntKi), PARAMETER :: M6N6RAze = 1914 - INTEGER(IntKi), PARAMETER :: M6N7RAze = 1915 - INTEGER(IntKi), PARAMETER :: M6N8RAze = 1916 - INTEGER(IntKi), PARAMETER :: M6N9RAze = 1917 - INTEGER(IntKi), PARAMETER :: M7N1RAze = 1918 - INTEGER(IntKi), PARAMETER :: M7N2RAze = 1919 - INTEGER(IntKi), PARAMETER :: M7N3RAze = 1920 - INTEGER(IntKi), PARAMETER :: M7N4RAze = 1921 - INTEGER(IntKi), PARAMETER :: M7N5RAze = 1922 - INTEGER(IntKi), PARAMETER :: M7N6RAze = 1923 - INTEGER(IntKi), PARAMETER :: M7N7RAze = 1924 - INTEGER(IntKi), PARAMETER :: M7N8RAze = 1925 - INTEGER(IntKi), PARAMETER :: M7N9RAze = 1926 - INTEGER(IntKi), PARAMETER :: M8N1RAze = 1927 - INTEGER(IntKi), PARAMETER :: M8N2RAze = 1928 - INTEGER(IntKi), PARAMETER :: M8N3RAze = 1929 - INTEGER(IntKi), PARAMETER :: M8N4RAze = 1930 - INTEGER(IntKi), PARAMETER :: M8N5RAze = 1931 - INTEGER(IntKi), PARAMETER :: M8N6RAze = 1932 - INTEGER(IntKi), PARAMETER :: M8N7RAze = 1933 - INTEGER(IntKi), PARAMETER :: M8N8RAze = 1934 - INTEGER(IntKi), PARAMETER :: M8N9RAze = 1935 - INTEGER(IntKi), PARAMETER :: M9N1RAze = 1936 - INTEGER(IntKi), PARAMETER :: M9N2RAze = 1937 - INTEGER(IntKi), PARAMETER :: M9N3RAze = 1938 - INTEGER(IntKi), PARAMETER :: M9N4RAze = 1939 - INTEGER(IntKi), PARAMETER :: M9N5RAze = 1940 - INTEGER(IntKi), PARAMETER :: M9N6RAze = 1941 - INTEGER(IntKi), PARAMETER :: M9N7RAze = 1942 - INTEGER(IntKi), PARAMETER :: M9N8RAze = 1943 - INTEGER(IntKi), PARAMETER :: M9N9RAze = 1944 - - - ! Reactions: - - INTEGER(IntKi), PARAMETER :: ReactFXss = 1945 - INTEGER(IntKi), PARAMETER :: ReactFYss = 1946 - INTEGER(IntKi), PARAMETER :: ReactFZss = 1947 - INTEGER(IntKi), PARAMETER :: ReactMXss = 1948 - INTEGER(IntKi), PARAMETER :: ReactMYss = 1949 - INTEGER(IntKi), PARAMETER :: ReactMZss = 1950 - INTEGER(IntKi), PARAMETER :: IntfFXss = 1951 - INTEGER(IntKi), PARAMETER :: IntfFYss = 1952 - INTEGER(IntKi), PARAMETER :: IntfFZss = 1953 - INTEGER(IntKi), PARAMETER :: IntfMXss = 1954 - INTEGER(IntKi), PARAMETER :: IntfMYss = 1955 - INTEGER(IntKi), PARAMETER :: IntfMZss = 1956 - - - ! Interface Deflections: - - INTEGER(IntKi), PARAMETER :: IntfTDXss = 1957 - INTEGER(IntKi), PARAMETER :: IntfTDYss = 1958 - INTEGER(IntKi), PARAMETER :: IntfTDZss = 1959 - INTEGER(IntKi), PARAMETER :: IntfRDXss = 1960 - INTEGER(IntKi), PARAMETER :: IntfRDYss = 1961 - INTEGER(IntKi), PARAMETER :: IntfRDZss = 1962 - - - ! Interface Accelerations: - - INTEGER(IntKi), PARAMETER :: IntfTAXss = 1963 - INTEGER(IntKi), PARAMETER :: IntfTAYss = 1964 - INTEGER(IntKi), PARAMETER :: IntfTAZss = 1965 - INTEGER(IntKi), PARAMETER :: IntfRAXss = 1966 - INTEGER(IntKi), PARAMETER :: IntfRAYss = 1967 - INTEGER(IntKi), PARAMETER :: IntfRAZss = 1968 - - - ! Modal Parameters: - - INTEGER(IntKi), PARAMETER :: SSqm01 = 1969 - INTEGER(IntKi), PARAMETER :: SSqm02 = 1970 - INTEGER(IntKi), PARAMETER :: SSqm03 = 1971 - INTEGER(IntKi), PARAMETER :: SSqm04 = 1972 - INTEGER(IntKi), PARAMETER :: SSqm05 = 1973 - INTEGER(IntKi), PARAMETER :: SSqm06 = 1974 - INTEGER(IntKi), PARAMETER :: SSqm07 = 1975 - INTEGER(IntKi), PARAMETER :: SSqm08 = 1976 - INTEGER(IntKi), PARAMETER :: SSqm09 = 1977 - INTEGER(IntKi), PARAMETER :: SSqm10 = 1978 - INTEGER(IntKi), PARAMETER :: SSqm11 = 1979 - INTEGER(IntKi), PARAMETER :: SSqm12 = 1980 - INTEGER(IntKi), PARAMETER :: SSqm13 = 1981 - INTEGER(IntKi), PARAMETER :: SSqm14 = 1982 - INTEGER(IntKi), PARAMETER :: SSqm15 = 1983 - INTEGER(IntKi), PARAMETER :: SSqm16 = 1984 - INTEGER(IntKi), PARAMETER :: SSqm17 = 1985 - INTEGER(IntKi), PARAMETER :: SSqm18 = 1986 - INTEGER(IntKi), PARAMETER :: SSqm19 = 1987 - INTEGER(IntKi), PARAMETER :: SSqm20 = 1988 - INTEGER(IntKi), PARAMETER :: SSqm21 = 1989 - INTEGER(IntKi), PARAMETER :: SSqm22 = 1990 - INTEGER(IntKi), PARAMETER :: SSqm23 = 1991 - INTEGER(IntKi), PARAMETER :: SSqm24 = 1992 - INTEGER(IntKi), PARAMETER :: SSqm25 = 1993 - INTEGER(IntKi), PARAMETER :: SSqm26 = 1994 - INTEGER(IntKi), PARAMETER :: SSqm27 = 1995 - INTEGER(IntKi), PARAMETER :: SSqm28 = 1996 - INTEGER(IntKi), PARAMETER :: SSqm29 = 1997 - INTEGER(IntKi), PARAMETER :: SSqm30 = 1998 - INTEGER(IntKi), PARAMETER :: SSqm31 = 1999 - INTEGER(IntKi), PARAMETER :: SSqm32 = 2000 - INTEGER(IntKi), PARAMETER :: SSqm33 = 2001 - INTEGER(IntKi), PARAMETER :: SSqm34 = 2002 - INTEGER(IntKi), PARAMETER :: SSqm35 = 2003 - INTEGER(IntKi), PARAMETER :: SSqm36 = 2004 - INTEGER(IntKi), PARAMETER :: SSqm37 = 2005 - INTEGER(IntKi), PARAMETER :: SSqm38 = 2006 - INTEGER(IntKi), PARAMETER :: SSqm39 = 2007 - INTEGER(IntKi), PARAMETER :: SSqm40 = 2008 - INTEGER(IntKi), PARAMETER :: SSqm41 = 2009 - INTEGER(IntKi), PARAMETER :: SSqm42 = 2010 - INTEGER(IntKi), PARAMETER :: SSqm43 = 2011 - INTEGER(IntKi), PARAMETER :: SSqm44 = 2012 - INTEGER(IntKi), PARAMETER :: SSqm45 = 2013 - INTEGER(IntKi), PARAMETER :: SSqm46 = 2014 - INTEGER(IntKi), PARAMETER :: SSqm47 = 2015 - INTEGER(IntKi), PARAMETER :: SSqm48 = 2016 - INTEGER(IntKi), PARAMETER :: SSqm49 = 2017 - INTEGER(IntKi), PARAMETER :: SSqm50 = 2018 - INTEGER(IntKi), PARAMETER :: SSqm51 = 2019 - INTEGER(IntKi), PARAMETER :: SSqm52 = 2020 - INTEGER(IntKi), PARAMETER :: SSqm53 = 2021 - INTEGER(IntKi), PARAMETER :: SSqm54 = 2022 - INTEGER(IntKi), PARAMETER :: SSqm55 = 2023 - INTEGER(IntKi), PARAMETER :: SSqm56 = 2024 - INTEGER(IntKi), PARAMETER :: SSqm57 = 2025 - INTEGER(IntKi), PARAMETER :: SSqm58 = 2026 - INTEGER(IntKi), PARAMETER :: SSqm59 = 2027 - INTEGER(IntKi), PARAMETER :: SSqm60 = 2028 - INTEGER(IntKi), PARAMETER :: SSqm61 = 2029 - INTEGER(IntKi), PARAMETER :: SSqm62 = 2030 - INTEGER(IntKi), PARAMETER :: SSqm63 = 2031 - INTEGER(IntKi), PARAMETER :: SSqm64 = 2032 - INTEGER(IntKi), PARAMETER :: SSqm65 = 2033 - INTEGER(IntKi), PARAMETER :: SSqm66 = 2034 - INTEGER(IntKi), PARAMETER :: SSqm67 = 2035 - INTEGER(IntKi), PARAMETER :: SSqm68 = 2036 - INTEGER(IntKi), PARAMETER :: SSqm69 = 2037 - INTEGER(IntKi), PARAMETER :: SSqm70 = 2038 - INTEGER(IntKi), PARAMETER :: SSqm71 = 2039 - INTEGER(IntKi), PARAMETER :: SSqm72 = 2040 - INTEGER(IntKi), PARAMETER :: SSqm73 = 2041 - INTEGER(IntKi), PARAMETER :: SSqm74 = 2042 - INTEGER(IntKi), PARAMETER :: SSqm75 = 2043 - INTEGER(IntKi), PARAMETER :: SSqm76 = 2044 - INTEGER(IntKi), PARAMETER :: SSqm77 = 2045 - INTEGER(IntKi), PARAMETER :: SSqm78 = 2046 - INTEGER(IntKi), PARAMETER :: SSqm79 = 2047 - INTEGER(IntKi), PARAMETER :: SSqm80 = 2048 - INTEGER(IntKi), PARAMETER :: SSqm81 = 2049 - INTEGER(IntKi), PARAMETER :: SSqm82 = 2050 - INTEGER(IntKi), PARAMETER :: SSqm83 = 2051 - INTEGER(IntKi), PARAMETER :: SSqm84 = 2052 - INTEGER(IntKi), PARAMETER :: SSqm85 = 2053 - INTEGER(IntKi), PARAMETER :: SSqm86 = 2054 - INTEGER(IntKi), PARAMETER :: SSqm87 = 2055 - INTEGER(IntKi), PARAMETER :: SSqm88 = 2056 - INTEGER(IntKi), PARAMETER :: SSqm89 = 2057 - INTEGER(IntKi), PARAMETER :: SSqm90 = 2058 - INTEGER(IntKi), PARAMETER :: SSqm91 = 2059 - INTEGER(IntKi), PARAMETER :: SSqm92 = 2060 - INTEGER(IntKi), PARAMETER :: SSqm93 = 2061 - INTEGER(IntKi), PARAMETER :: SSqm94 = 2062 - INTEGER(IntKi), PARAMETER :: SSqm95 = 2063 - INTEGER(IntKi), PARAMETER :: SSqm96 = 2064 - INTEGER(IntKi), PARAMETER :: SSqm97 = 2065 - INTEGER(IntKi), PARAMETER :: SSqm98 = 2066 - INTEGER(IntKi), PARAMETER :: SSqm99 = 2067 - INTEGER(IntKi), PARAMETER :: SSqmd01 = 2068 - INTEGER(IntKi), PARAMETER :: SSqmd02 = 2069 - INTEGER(IntKi), PARAMETER :: SSqmd03 = 2070 - INTEGER(IntKi), PARAMETER :: SSqmd04 = 2071 - INTEGER(IntKi), PARAMETER :: SSqmd05 = 2072 - INTEGER(IntKi), PARAMETER :: SSqmd06 = 2073 - INTEGER(IntKi), PARAMETER :: SSqmd07 = 2074 - INTEGER(IntKi), PARAMETER :: SSqmd08 = 2075 - INTEGER(IntKi), PARAMETER :: SSqmd09 = 2076 - INTEGER(IntKi), PARAMETER :: SSqmd10 = 2077 - INTEGER(IntKi), PARAMETER :: SSqmd11 = 2078 - INTEGER(IntKi), PARAMETER :: SSqmd12 = 2079 - INTEGER(IntKi), PARAMETER :: SSqmd13 = 2080 - INTEGER(IntKi), PARAMETER :: SSqmd14 = 2081 - INTEGER(IntKi), PARAMETER :: SSqmd15 = 2082 - INTEGER(IntKi), PARAMETER :: SSqmd16 = 2083 - INTEGER(IntKi), PARAMETER :: SSqmd17 = 2084 - INTEGER(IntKi), PARAMETER :: SSqmd18 = 2085 - INTEGER(IntKi), PARAMETER :: SSqmd19 = 2086 - INTEGER(IntKi), PARAMETER :: SSqmd20 = 2087 - INTEGER(IntKi), PARAMETER :: SSqmd21 = 2088 - INTEGER(IntKi), PARAMETER :: SSqmd22 = 2089 - INTEGER(IntKi), PARAMETER :: SSqmd23 = 2090 - INTEGER(IntKi), PARAMETER :: SSqmd24 = 2091 - INTEGER(IntKi), PARAMETER :: SSqmd25 = 2092 - INTEGER(IntKi), PARAMETER :: SSqmd26 = 2093 - INTEGER(IntKi), PARAMETER :: SSqmd27 = 2094 - INTEGER(IntKi), PARAMETER :: SSqmd28 = 2095 - INTEGER(IntKi), PARAMETER :: SSqmd29 = 2096 - INTEGER(IntKi), PARAMETER :: SSqmd30 = 2097 - INTEGER(IntKi), PARAMETER :: SSqmd31 = 2098 - INTEGER(IntKi), PARAMETER :: SSqmd32 = 2099 - INTEGER(IntKi), PARAMETER :: SSqmd33 = 2100 - INTEGER(IntKi), PARAMETER :: SSqmd34 = 2101 - INTEGER(IntKi), PARAMETER :: SSqmd35 = 2102 - INTEGER(IntKi), PARAMETER :: SSqmd36 = 2103 - INTEGER(IntKi), PARAMETER :: SSqmd37 = 2104 - INTEGER(IntKi), PARAMETER :: SSqmd38 = 2105 - INTEGER(IntKi), PARAMETER :: SSqmd39 = 2106 - INTEGER(IntKi), PARAMETER :: SSqmd40 = 2107 - INTEGER(IntKi), PARAMETER :: SSqmd41 = 2108 - INTEGER(IntKi), PARAMETER :: SSqmd42 = 2109 - INTEGER(IntKi), PARAMETER :: SSqmd43 = 2110 - INTEGER(IntKi), PARAMETER :: SSqmd44 = 2111 - INTEGER(IntKi), PARAMETER :: SSqmd45 = 2112 - INTEGER(IntKi), PARAMETER :: SSqmd46 = 2113 - INTEGER(IntKi), PARAMETER :: SSqmd47 = 2114 - INTEGER(IntKi), PARAMETER :: SSqmd48 = 2115 - INTEGER(IntKi), PARAMETER :: SSqmd49 = 2116 - INTEGER(IntKi), PARAMETER :: SSqmd50 = 2117 - INTEGER(IntKi), PARAMETER :: SSqmd51 = 2118 - INTEGER(IntKi), PARAMETER :: SSqmd52 = 2119 - INTEGER(IntKi), PARAMETER :: SSqmd53 = 2120 - INTEGER(IntKi), PARAMETER :: SSqmd54 = 2121 - INTEGER(IntKi), PARAMETER :: SSqmd55 = 2122 - INTEGER(IntKi), PARAMETER :: SSqmd56 = 2123 - INTEGER(IntKi), PARAMETER :: SSqmd57 = 2124 - INTEGER(IntKi), PARAMETER :: SSqmd58 = 2125 - INTEGER(IntKi), PARAMETER :: SSqmd59 = 2126 - INTEGER(IntKi), PARAMETER :: SSqmd60 = 2127 - INTEGER(IntKi), PARAMETER :: SSqmd61 = 2128 - INTEGER(IntKi), PARAMETER :: SSqmd62 = 2129 - INTEGER(IntKi), PARAMETER :: SSqmd63 = 2130 - INTEGER(IntKi), PARAMETER :: SSqmd64 = 2131 - INTEGER(IntKi), PARAMETER :: SSqmd65 = 2132 - INTEGER(IntKi), PARAMETER :: SSqmd66 = 2133 - INTEGER(IntKi), PARAMETER :: SSqmd67 = 2134 - INTEGER(IntKi), PARAMETER :: SSqmd68 = 2135 - INTEGER(IntKi), PARAMETER :: SSqmd69 = 2136 - INTEGER(IntKi), PARAMETER :: SSqmd70 = 2137 - INTEGER(IntKi), PARAMETER :: SSqmd71 = 2138 - INTEGER(IntKi), PARAMETER :: SSqmd72 = 2139 - INTEGER(IntKi), PARAMETER :: SSqmd73 = 2140 - INTEGER(IntKi), PARAMETER :: SSqmd74 = 2141 - INTEGER(IntKi), PARAMETER :: SSqmd75 = 2142 - INTEGER(IntKi), PARAMETER :: SSqmd76 = 2143 - INTEGER(IntKi), PARAMETER :: SSqmd77 = 2144 - INTEGER(IntKi), PARAMETER :: SSqmd78 = 2145 - INTEGER(IntKi), PARAMETER :: SSqmd79 = 2146 - INTEGER(IntKi), PARAMETER :: SSqmd80 = 2147 - INTEGER(IntKi), PARAMETER :: SSqmd81 = 2148 - INTEGER(IntKi), PARAMETER :: SSqmd82 = 2149 - INTEGER(IntKi), PARAMETER :: SSqmd83 = 2150 - INTEGER(IntKi), PARAMETER :: SSqmd84 = 2151 - INTEGER(IntKi), PARAMETER :: SSqmd85 = 2152 - INTEGER(IntKi), PARAMETER :: SSqmd86 = 2153 - INTEGER(IntKi), PARAMETER :: SSqmd87 = 2154 - INTEGER(IntKi), PARAMETER :: SSqmd88 = 2155 - INTEGER(IntKi), PARAMETER :: SSqmd89 = 2156 - INTEGER(IntKi), PARAMETER :: SSqmd90 = 2157 - INTEGER(IntKi), PARAMETER :: SSqmd91 = 2158 - INTEGER(IntKi), PARAMETER :: SSqmd92 = 2159 - INTEGER(IntKi), PARAMETER :: SSqmd93 = 2160 - INTEGER(IntKi), PARAMETER :: SSqmd94 = 2161 - INTEGER(IntKi), PARAMETER :: SSqmd95 = 2162 - INTEGER(IntKi), PARAMETER :: SSqmd96 = 2163 - INTEGER(IntKi), PARAMETER :: SSqmd97 = 2164 - INTEGER(IntKi), PARAMETER :: SSqmd98 = 2165 - INTEGER(IntKi), PARAMETER :: SSqmd99 = 2166 - INTEGER(IntKi), PARAMETER :: SSqmdd01 = 2167 - INTEGER(IntKi), PARAMETER :: SSqmdd02 = 2168 - INTEGER(IntKi), PARAMETER :: SSqmdd03 = 2169 - INTEGER(IntKi), PARAMETER :: SSqmdd04 = 2170 - INTEGER(IntKi), PARAMETER :: SSqmdd05 = 2171 - INTEGER(IntKi), PARAMETER :: SSqmdd06 = 2172 - INTEGER(IntKi), PARAMETER :: SSqmdd07 = 2173 - INTEGER(IntKi), PARAMETER :: SSqmdd08 = 2174 - INTEGER(IntKi), PARAMETER :: SSqmdd09 = 2175 - INTEGER(IntKi), PARAMETER :: SSqmdd10 = 2176 - INTEGER(IntKi), PARAMETER :: SSqmdd11 = 2177 - INTEGER(IntKi), PARAMETER :: SSqmdd12 = 2178 - INTEGER(IntKi), PARAMETER :: SSqmdd13 = 2179 - INTEGER(IntKi), PARAMETER :: SSqmdd14 = 2180 - INTEGER(IntKi), PARAMETER :: SSqmdd15 = 2181 - INTEGER(IntKi), PARAMETER :: SSqmdd16 = 2182 - INTEGER(IntKi), PARAMETER :: SSqmdd17 = 2183 - INTEGER(IntKi), PARAMETER :: SSqmdd18 = 2184 - INTEGER(IntKi), PARAMETER :: SSqmdd19 = 2185 - INTEGER(IntKi), PARAMETER :: SSqmdd20 = 2186 - INTEGER(IntKi), PARAMETER :: SSqmdd21 = 2187 - INTEGER(IntKi), PARAMETER :: SSqmdd22 = 2188 - INTEGER(IntKi), PARAMETER :: SSqmdd23 = 2189 - INTEGER(IntKi), PARAMETER :: SSqmdd24 = 2190 - INTEGER(IntKi), PARAMETER :: SSqmdd25 = 2191 - INTEGER(IntKi), PARAMETER :: SSqmdd26 = 2192 - INTEGER(IntKi), PARAMETER :: SSqmdd27 = 2193 - INTEGER(IntKi), PARAMETER :: SSqmdd28 = 2194 - INTEGER(IntKi), PARAMETER :: SSqmdd29 = 2195 - INTEGER(IntKi), PARAMETER :: SSqmdd30 = 2196 - INTEGER(IntKi), PARAMETER :: SSqmdd31 = 2197 - INTEGER(IntKi), PARAMETER :: SSqmdd32 = 2198 - INTEGER(IntKi), PARAMETER :: SSqmdd33 = 2199 - INTEGER(IntKi), PARAMETER :: SSqmdd34 = 2200 - INTEGER(IntKi), PARAMETER :: SSqmdd35 = 2201 - INTEGER(IntKi), PARAMETER :: SSqmdd36 = 2202 - INTEGER(IntKi), PARAMETER :: SSqmdd37 = 2203 - INTEGER(IntKi), PARAMETER :: SSqmdd38 = 2204 - INTEGER(IntKi), PARAMETER :: SSqmdd39 = 2205 - INTEGER(IntKi), PARAMETER :: SSqmdd40 = 2206 - INTEGER(IntKi), PARAMETER :: SSqmdd41 = 2207 - INTEGER(IntKi), PARAMETER :: SSqmdd42 = 2208 - INTEGER(IntKi), PARAMETER :: SSqmdd43 = 2209 - INTEGER(IntKi), PARAMETER :: SSqmdd44 = 2210 - INTEGER(IntKi), PARAMETER :: SSqmdd45 = 2211 - INTEGER(IntKi), PARAMETER :: SSqmdd46 = 2212 - INTEGER(IntKi), PARAMETER :: SSqmdd47 = 2213 - INTEGER(IntKi), PARAMETER :: SSqmdd48 = 2214 - INTEGER(IntKi), PARAMETER :: SSqmdd49 = 2215 - INTEGER(IntKi), PARAMETER :: SSqmdd50 = 2216 - INTEGER(IntKi), PARAMETER :: SSqmdd51 = 2217 - INTEGER(IntKi), PARAMETER :: SSqmdd52 = 2218 - INTEGER(IntKi), PARAMETER :: SSqmdd53 = 2219 - INTEGER(IntKi), PARAMETER :: SSqmdd54 = 2220 - INTEGER(IntKi), PARAMETER :: SSqmdd55 = 2221 - INTEGER(IntKi), PARAMETER :: SSqmdd56 = 2222 - INTEGER(IntKi), PARAMETER :: SSqmdd57 = 2223 - INTEGER(IntKi), PARAMETER :: SSqmdd58 = 2224 - INTEGER(IntKi), PARAMETER :: SSqmdd59 = 2225 - INTEGER(IntKi), PARAMETER :: SSqmdd60 = 2226 - INTEGER(IntKi), PARAMETER :: SSqmdd61 = 2227 - INTEGER(IntKi), PARAMETER :: SSqmdd62 = 2228 - INTEGER(IntKi), PARAMETER :: SSqmdd63 = 2229 - INTEGER(IntKi), PARAMETER :: SSqmdd64 = 2230 - INTEGER(IntKi), PARAMETER :: SSqmdd65 = 2231 - INTEGER(IntKi), PARAMETER :: SSqmdd66 = 2232 - INTEGER(IntKi), PARAMETER :: SSqmdd67 = 2233 - INTEGER(IntKi), PARAMETER :: SSqmdd68 = 2234 - INTEGER(IntKi), PARAMETER :: SSqmdd69 = 2235 - INTEGER(IntKi), PARAMETER :: SSqmdd70 = 2236 - INTEGER(IntKi), PARAMETER :: SSqmdd71 = 2237 - INTEGER(IntKi), PARAMETER :: SSqmdd72 = 2238 - INTEGER(IntKi), PARAMETER :: SSqmdd73 = 2239 - INTEGER(IntKi), PARAMETER :: SSqmdd74 = 2240 - INTEGER(IntKi), PARAMETER :: SSqmdd75 = 2241 - INTEGER(IntKi), PARAMETER :: SSqmdd76 = 2242 - INTEGER(IntKi), PARAMETER :: SSqmdd77 = 2243 - INTEGER(IntKi), PARAMETER :: SSqmdd78 = 2244 - INTEGER(IntKi), PARAMETER :: SSqmdd79 = 2245 - INTEGER(IntKi), PARAMETER :: SSqmdd80 = 2246 - INTEGER(IntKi), PARAMETER :: SSqmdd81 = 2247 - INTEGER(IntKi), PARAMETER :: SSqmdd82 = 2248 - INTEGER(IntKi), PARAMETER :: SSqmdd83 = 2249 - INTEGER(IntKi), PARAMETER :: SSqmdd84 = 2250 - INTEGER(IntKi), PARAMETER :: SSqmdd85 = 2251 - INTEGER(IntKi), PARAMETER :: SSqmdd86 = 2252 - INTEGER(IntKi), PARAMETER :: SSqmdd87 = 2253 - INTEGER(IntKi), PARAMETER :: SSqmdd88 = 2254 - INTEGER(IntKi), PARAMETER :: SSqmdd89 = 2255 - INTEGER(IntKi), PARAMETER :: SSqmdd90 = 2256 - INTEGER(IntKi), PARAMETER :: SSqmdd91 = 2257 - INTEGER(IntKi), PARAMETER :: SSqmdd92 = 2258 - INTEGER(IntKi), PARAMETER :: SSqmdd93 = 2259 - INTEGER(IntKi), PARAMETER :: SSqmdd94 = 2260 - INTEGER(IntKi), PARAMETER :: SSqmdd95 = 2261 - INTEGER(IntKi), PARAMETER :: SSqmdd96 = 2262 - INTEGER(IntKi), PARAMETER :: SSqmdd97 = 2263 - INTEGER(IntKi), PARAMETER :: SSqmdd98 = 2264 - INTEGER(IntKi), PARAMETER :: SSqmdd99 = 2265 - - - ! The maximum number of output channels which can be output by the code. - !INTEGER(IntKi), PARAMETER :: MaxOutPts = 2265 - -!End of code generated by Matlab script - - INTEGER, PARAMETER :: MNfmKe(6,9,9) = reshape((/ M1N1FKxe,M1N1FKye,M1N1FKze,M1N1MKxe,M1N1MKye,M1N1MKze, & - M1N2FKxe,M1N2FKye,M1N2FKze,M1N2MKxe,M1N2MKye,M1N2MKze, & - M1N3FKxe,M1N3FKye,M1N3FKze,M1N3MKxe,M1N3MKye,M1N3MKze, & - M1N4FKxe,M1N4FKye,M1N4FKze,M1N4MKxe,M1N4MKye,M1N4MKze, & - M1N5FKxe,M1N5FKye,M1N5FKze,M1N5MKxe,M1N5MKye,M1N5MKze, & - M1N6FKxe,M1N6FKye,M1N6FKze,M1N6MKxe,M1N6MKye,M1N6MKze, & - M1N7FKxe,M1N7FKye,M1N7FKze,M1N7MKxe,M1N7MKye,M1N7MKze, & - M1N8FKxe,M1N8FKye,M1N8FKze,M1N8MKxe,M1N8MKye,M1N8MKze, & - M1N9FKxe,M1N9FKye,M1N9FKze,M1N9MKxe,M1N9MKye,M1N9MKze, & - M2N1FKxe,M2N1FKye,M2N1FKze,M2N1MKxe,M2N1MKye,M2N1MKze, & - M2N2FKxe,M2N2FKye,M2N2FKze,M2N2MKxe,M2N2MKye,M2N2MKze, & - M2N3FKxe,M2N3FKye,M2N3FKze,M2N3MKxe,M2N3MKye,M2N3MKze, & - M2N4FKxe,M2N4FKye,M2N4FKze,M2N4MKxe,M2N4MKye,M2N4MKze, & - M2N5FKxe,M2N5FKye,M2N5FKze,M2N5MKxe,M2N5MKye,M2N5MKze, & - M2N6FKxe,M2N6FKye,M2N6FKze,M2N6MKxe,M2N6MKye,M2N6MKze, & - M2N7FKxe,M2N7FKye,M2N7FKze,M2N7MKxe,M2N7MKye,M2N7MKze, & - M2N8FKxe,M2N8FKye,M2N8FKze,M2N8MKxe,M2N8MKye,M2N8MKze, & - M2N9FKxe,M2N9FKye,M2N9FKze,M2N9MKxe,M2N9MKye,M2N9MKze, & - M3N1FKxe,M3N1FKye,M3N1FKze,M3N1MKxe,M3N1MKye,M3N1MKze, & - M3N2FKxe,M3N2FKye,M3N2FKze,M3N2MKxe,M3N2MKye,M3N2MKze, & - M3N3FKxe,M3N3FKye,M3N3FKze,M3N3MKxe,M3N3MKye,M3N3MKze, & - M3N4FKxe,M3N4FKye,M3N4FKze,M3N4MKxe,M3N4MKye,M3N4MKze, & - M3N5FKxe,M3N5FKye,M3N5FKze,M3N5MKxe,M3N5MKye,M3N5MKze, & - M3N6FKxe,M3N6FKye,M3N6FKze,M3N6MKxe,M3N6MKye,M3N6MKze, & - M3N7FKxe,M3N7FKye,M3N7FKze,M3N7MKxe,M3N7MKye,M3N7MKze, & - M3N8FKxe,M3N8FKye,M3N8FKze,M3N8MKxe,M3N8MKye,M3N8MKze, & - M3N9FKxe,M3N9FKye,M3N9FKze,M3N9MKxe,M3N9MKye,M3N9MKze, & - M4N1FKxe,M4N1FKye,M4N1FKze,M4N1MKxe,M4N1MKye,M4N1MKze, & - M4N2FKxe,M4N2FKye,M4N2FKze,M4N2MKxe,M4N2MKye,M4N2MKze, & - M4N3FKxe,M4N3FKye,M4N3FKze,M4N3MKxe,M4N3MKye,M4N3MKze, & - M4N4FKxe,M4N4FKye,M4N4FKze,M4N4MKxe,M4N4MKye,M4N4MKze, & - M4N5FKxe,M4N5FKye,M4N5FKze,M4N5MKxe,M4N5MKye,M4N5MKze, & - M4N6FKxe,M4N6FKye,M4N6FKze,M4N6MKxe,M4N6MKye,M4N6MKze, & - M4N7FKxe,M4N7FKye,M4N7FKze,M4N7MKxe,M4N7MKye,M4N7MKze, & - M4N8FKxe,M4N8FKye,M4N8FKze,M4N8MKxe,M4N8MKye,M4N8MKze, & - M4N9FKxe,M4N9FKye,M4N9FKze,M4N9MKxe,M4N9MKye,M4N9MKze, & - M5N1FKxe,M5N1FKye,M5N1FKze,M5N1MKxe,M5N1MKye,M5N1MKze, & - M5N2FKxe,M5N2FKye,M5N2FKze,M5N2MKxe,M5N2MKye,M5N2MKze, & - M5N3FKxe,M5N3FKye,M5N3FKze,M5N3MKxe,M5N3MKye,M5N3MKze, & - M5N4FKxe,M5N4FKye,M5N4FKze,M5N4MKxe,M5N4MKye,M5N4MKze, & - M5N5FKxe,M5N5FKye,M5N5FKze,M5N5MKxe,M5N5MKye,M5N5MKze, & - M5N6FKxe,M5N6FKye,M5N6FKze,M5N6MKxe,M5N6MKye,M5N6MKze, & - M5N7FKxe,M5N7FKye,M5N7FKze,M5N7MKxe,M5N7MKye,M5N7MKze, & - M5N8FKxe,M5N8FKye,M5N8FKze,M5N8MKxe,M5N8MKye,M5N8MKze, & - M5N9FKxe,M5N9FKye,M5N9FKze,M5N9MKxe,M5N9MKye,M5N9MKze, & - M6N1FKxe,M6N1FKye,M6N1FKze,M6N1MKxe,M6N1MKye,M6N1MKze, & - M6N2FKxe,M6N2FKye,M6N2FKze,M6N2MKxe,M6N2MKye,M6N2MKze, & - M6N3FKxe,M6N3FKye,M6N3FKze,M6N3MKxe,M6N3MKye,M6N3MKze, & - M6N4FKxe,M6N4FKye,M6N4FKze,M6N4MKxe,M6N4MKye,M6N4MKze, & - M6N5FKxe,M6N5FKye,M6N5FKze,M6N5MKxe,M6N5MKye,M6N5MKze, & - M6N6FKxe,M6N6FKye,M6N6FKze,M6N6MKxe,M6N6MKye,M6N6MKze, & - M6N7FKxe,M6N7FKye,M6N7FKze,M6N7MKxe,M6N7MKye,M6N7MKze, & - M6N8FKxe,M6N8FKye,M6N8FKze,M6N8MKxe,M6N8MKye,M6N8MKze, & - M6N9FKxe,M6N9FKye,M6N9FKze,M6N9MKxe,M6N9MKye,M6N9MKze, & - M7N1FKxe,M7N1FKye,M7N1FKze,M7N1MKxe,M7N1MKye,M7N1MKze, & - M7N2FKxe,M7N2FKye,M7N2FKze,M7N2MKxe,M7N2MKye,M7N2MKze, & - M7N3FKxe,M7N3FKye,M7N3FKze,M7N3MKxe,M7N3MKye,M7N3MKze, & - M7N4FKxe,M7N4FKye,M7N4FKze,M7N4MKxe,M7N4MKye,M7N4MKze, & - M7N5FKxe,M7N5FKye,M7N5FKze,M7N5MKxe,M7N5MKye,M7N5MKze, & - M7N6FKxe,M7N6FKye,M7N6FKze,M7N6MKxe,M7N6MKye,M7N6MKze, & - M7N7FKxe,M7N7FKye,M7N7FKze,M7N7MKxe,M7N7MKye,M7N7MKze, & - M7N8FKxe,M7N8FKye,M7N8FKze,M7N8MKxe,M7N8MKye,M7N8MKze, & - M7N9FKxe,M7N9FKye,M7N9FKze,M7N9MKxe,M7N9MKye,M7N9MKze, & - M8N1FKxe,M8N1FKye,M8N1FKze,M8N1MKxe,M8N1MKye,M8N1MKze, & - M8N2FKxe,M8N2FKye,M8N2FKze,M8N2MKxe,M8N2MKye,M8N2MKze, & - M8N3FKxe,M8N3FKye,M8N3FKze,M8N3MKxe,M8N3MKye,M8N3MKze, & - M8N4FKxe,M8N4FKye,M8N4FKze,M8N4MKxe,M8N4MKye,M8N4MKze, & - M8N5FKxe,M8N5FKye,M8N5FKze,M8N5MKxe,M8N5MKye,M8N5MKze, & - M8N6FKxe,M8N6FKye,M8N6FKze,M8N6MKxe,M8N6MKye,M8N6MKze, & - M8N7FKxe,M8N7FKye,M8N7FKze,M8N7MKxe,M8N7MKye,M8N7MKze, & - M8N8FKxe,M8N8FKye,M8N8FKze,M8N8MKxe,M8N8MKye,M8N8MKze, & - M8N9FKxe,M8N9FKye,M8N9FKze,M8N9MKxe,M8N9MKye,M8N9MKze, & - M9N1FKxe,M9N1FKye,M9N1FKze,M9N1MKxe,M9N1MKye,M9N1MKze, & - M9N2FKxe,M9N2FKye,M9N2FKze,M9N2MKxe,M9N2MKye,M9N2MKze, & - M9N3FKxe,M9N3FKye,M9N3FKze,M9N3MKxe,M9N3MKye,M9N3MKze, & - M9N4FKxe,M9N4FKye,M9N4FKze,M9N4MKxe,M9N4MKye,M9N4MKze, & - M9N5FKxe,M9N5FKye,M9N5FKze,M9N5MKxe,M9N5MKye,M9N5MKze, & - M9N6FKxe,M9N6FKye,M9N6FKze,M9N6MKxe,M9N6MKye,M9N6MKze, & - M9N7FKxe,M9N7FKye,M9N7FKze,M9N7MKxe,M9N7MKye,M9N7MKze, & - M9N8FKxe,M9N8FKye,M9N8FKze,M9N8MKxe,M9N8MKye,M9N8MKze, & - M9N9FKxe,M9N9FKye,M9N9FKze,M9N9MKxe,M9N9MKye,M9N9MKze /),(/6,9,9/)) - - - - INTEGER, PARAMETER :: MNfmMe(6,9,9) = reshape((/ M1N1FMxe,M1N1FMye,M1N1FMze,M1N1MMxe,M1N1MMye,M1N1MMze, & - M1N2FMxe,M1N2FMye,M1N2FMze,M1N2MMxe,M1N2MMye,M1N2MMze, & - M1N3FMxe,M1N3FMye,M1N3FMze,M1N3MMxe,M1N3MMye,M1N3MMze, & - M1N4FMxe,M1N4FMye,M1N4FMze,M1N4MMxe,M1N4MMye,M1N4MMze, & - M1N5FMxe,M1N5FMye,M1N5FMze,M1N5MMxe,M1N5MMye,M1N5MMze, & - M1N6FMxe,M1N6FMye,M1N6FMze,M1N6MMxe,M1N6MMye,M1N6MMze, & - M1N7FMxe,M1N7FMye,M1N7FMze,M1N7MMxe,M1N7MMye,M1N7MMze, & - M1N8FMxe,M1N8FMye,M1N8FMze,M1N8MMxe,M1N8MMye,M1N8MMze, & - M1N9FMxe,M1N9FMye,M1N9FMze,M1N9MMxe,M1N9MMye,M1N9MMze, & - M2N1FMxe,M2N1FMye,M2N1FMze,M2N1MMxe,M2N1MMye,M2N1MMze, & - M2N2FMxe,M2N2FMye,M2N2FMze,M2N2MMxe,M2N2MMye,M2N2MMze, & - M2N3FMxe,M2N3FMye,M2N3FMze,M2N3MMxe,M2N3MMye,M2N3MMze, & - M2N4FMxe,M2N4FMye,M2N4FMze,M2N4MMxe,M2N4MMye,M2N4MMze, & - M2N5FMxe,M2N5FMye,M2N5FMze,M2N5MMxe,M2N5MMye,M2N5MMze, & - M2N6FMxe,M2N6FMye,M2N6FMze,M2N6MMxe,M2N6MMye,M2N6MMze, & - M2N7FMxe,M2N7FMye,M2N7FMze,M2N7MMxe,M2N7MMye,M2N7MMze, & - M2N8FMxe,M2N8FMye,M2N8FMze,M2N8MMxe,M2N8MMye,M2N8MMze, & - M2N9FMxe,M2N9FMye,M2N9FMze,M2N9MMxe,M2N9MMye,M2N9MMze, & - M3N1FMxe,M3N1FMye,M3N1FMze,M3N1MMxe,M3N1MMye,M3N1MMze, & - M3N2FMxe,M3N2FMye,M3N2FMze,M3N2MMxe,M3N2MMye,M3N2MMze, & - M3N3FMxe,M3N3FMye,M3N3FMze,M3N3MMxe,M3N3MMye,M3N3MMze, & - M3N4FMxe,M3N4FMye,M3N4FMze,M3N4MMxe,M3N4MMye,M3N4MMze, & - M3N5FMxe,M3N5FMye,M3N5FMze,M3N5MMxe,M3N5MMye,M3N5MMze, & - M3N6FMxe,M3N6FMye,M3N6FMze,M3N6MMxe,M3N6MMye,M3N6MMze, & - M3N7FMxe,M3N7FMye,M3N7FMze,M3N7MMxe,M3N7MMye,M3N7MMze, & - M3N8FMxe,M3N8FMye,M3N8FMze,M3N8MMxe,M3N8MMye,M3N8MMze, & - M3N9FMxe,M3N9FMye,M3N9FMze,M3N9MMxe,M3N9MMye,M3N9MMze, & - M4N1FMxe,M4N1FMye,M4N1FMze,M4N1MMxe,M4N1MMye,M4N1MMze, & - M4N2FMxe,M4N2FMye,M4N2FMze,M4N2MMxe,M4N2MMye,M4N2MMze, & - M4N3FMxe,M4N3FMye,M4N3FMze,M4N3MMxe,M4N3MMye,M4N3MMze, & - M4N4FMxe,M4N4FMye,M4N4FMze,M4N4MMxe,M4N4MMye,M4N4MMze, & - M4N5FMxe,M4N5FMye,M4N5FMze,M4N5MMxe,M4N5MMye,M4N5MMze, & - M4N6FMxe,M4N6FMye,M4N6FMze,M4N6MMxe,M4N6MMye,M4N6MMze, & - M4N7FMxe,M4N7FMye,M4N7FMze,M4N7MMxe,M4N7MMye,M4N7MMze, & - M4N8FMxe,M4N8FMye,M4N8FMze,M4N8MMxe,M4N8MMye,M4N8MMze, & - M4N9FMxe,M4N9FMye,M4N9FMze,M4N9MMxe,M4N9MMye,M4N9MMze, & - M5N1FMxe,M5N1FMye,M5N1FMze,M5N1MMxe,M5N1MMye,M5N1MMze, & - M5N2FMxe,M5N2FMye,M5N2FMze,M5N2MMxe,M5N2MMye,M5N2MMze, & - M5N3FMxe,M5N3FMye,M5N3FMze,M5N3MMxe,M5N3MMye,M5N3MMze, & - M5N4FMxe,M5N4FMye,M5N4FMze,M5N4MMxe,M5N4MMye,M5N4MMze, & - M5N5FMxe,M5N5FMye,M5N5FMze,M5N5MMxe,M5N5MMye,M5N5MMze, & - M5N6FMxe,M5N6FMye,M5N6FMze,M5N6MMxe,M5N6MMye,M5N6MMze, & - M5N7FMxe,M5N7FMye,M5N7FMze,M5N7MMxe,M5N7MMye,M5N7MMze, & - M5N8FMxe,M5N8FMye,M5N8FMze,M5N8MMxe,M5N8MMye,M5N8MMze, & - M5N9FMxe,M5N9FMye,M5N9FMze,M5N9MMxe,M5N9MMye,M5N9MMze, & - M6N1FMxe,M6N1FMye,M6N1FMze,M6N1MMxe,M6N1MMye,M6N1MMze, & - M6N2FMxe,M6N2FMye,M6N2FMze,M6N2MMxe,M6N2MMye,M6N2MMze, & - M6N3FMxe,M6N3FMye,M6N3FMze,M6N3MMxe,M6N3MMye,M6N3MMze, & - M6N4FMxe,M6N4FMye,M6N4FMze,M6N4MMxe,M6N4MMye,M6N4MMze, & - M6N5FMxe,M6N5FMye,M6N5FMze,M6N5MMxe,M6N5MMye,M6N5MMze, & - M6N6FMxe,M6N6FMye,M6N6FMze,M6N6MMxe,M6N6MMye,M6N6MMze, & - M6N7FMxe,M6N7FMye,M6N7FMze,M6N7MMxe,M6N7MMye,M6N7MMze, & - M6N8FMxe,M6N8FMye,M6N8FMze,M6N8MMxe,M6N8MMye,M6N8MMze, & - M6N9FMxe,M6N9FMye,M6N9FMze,M6N9MMxe,M6N9MMye,M6N9MMze, & - M7N1FMxe,M7N1FMye,M7N1FMze,M7N1MMxe,M7N1MMye,M7N1MMze, & - M7N2FMxe,M7N2FMye,M7N2FMze,M7N2MMxe,M7N2MMye,M7N2MMze, & - M7N3FMxe,M7N3FMye,M7N3FMze,M7N3MMxe,M7N3MMye,M7N3MMze, & - M7N4FMxe,M7N4FMye,M7N4FMze,M7N4MMxe,M7N4MMye,M7N4MMze, & - M7N5FMxe,M7N5FMye,M7N5FMze,M7N5MMxe,M7N5MMye,M7N5MMze, & - M7N6FMxe,M7N6FMye,M7N6FMze,M7N6MMxe,M7N6MMye,M7N6MMze, & - M7N7FMxe,M7N7FMye,M7N7FMze,M7N7MMxe,M7N7MMye,M7N7MMze, & - M7N8FMxe,M7N8FMye,M7N8FMze,M7N8MMxe,M7N8MMye,M7N8MMze, & - M7N9FMxe,M7N9FMye,M7N9FMze,M7N9MMxe,M7N9MMye,M7N9MMze, & - M8N1FMxe,M8N1FMye,M8N1FMze,M8N1MMxe,M8N1MMye,M8N1MMze, & - M8N2FMxe,M8N2FMye,M8N2FMze,M8N2MMxe,M8N2MMye,M8N2MMze, & - M8N3FMxe,M8N3FMye,M8N3FMze,M8N3MMxe,M8N3MMye,M8N3MMze, & - M8N4FMxe,M8N4FMye,M8N4FMze,M8N4MMxe,M8N4MMye,M8N4MMze, & - M8N5FMxe,M8N5FMye,M8N5FMze,M8N5MMxe,M8N5MMye,M8N5MMze, & - M8N6FMxe,M8N6FMye,M8N6FMze,M8N6MMxe,M8N6MMye,M8N6MMze, & - M8N7FMxe,M8N7FMye,M8N7FMze,M8N7MMxe,M8N7MMye,M8N7MMze, & - M8N8FMxe,M8N8FMye,M8N8FMze,M8N8MMxe,M8N8MMye,M8N8MMze, & - M8N9FMxe,M8N9FMye,M8N9FMze,M8N9MMxe,M8N9MMye,M8N9MMze, & - M9N1FMxe,M9N1FMye,M9N1FMze,M9N1MMxe,M9N1MMye,M9N1MMze, & - M9N2FMxe,M9N2FMye,M9N2FMze,M9N2MMxe,M9N2MMye,M9N2MMze, & - M9N3FMxe,M9N3FMye,M9N3FMze,M9N3MMxe,M9N3MMye,M9N3MMze, & - M9N4FMxe,M9N4FMye,M9N4FMze,M9N4MMxe,M9N4MMye,M9N4MMze, & - M9N5FMxe,M9N5FMye,M9N5FMze,M9N5MMxe,M9N5MMye,M9N5MMze, & - M9N6FMxe,M9N6FMye,M9N6FMze,M9N6MMxe,M9N6MMye,M9N6MMze, & - M9N7FMxe,M9N7FMye,M9N7FMze,M9N7MMxe,M9N7MMye,M9N7MMze, & - M9N8FMxe,M9N8FMye,M9N8FMze,M9N8MMxe,M9N8MMye,M9N8MMze, & - M9N9FMxe,M9N9FMye,M9N9FMze,M9N9MMxe,M9N9MMye,M9N9MMze /),(/6,9,9/)) - - INTEGER, PARAMETER :: MNTDss(3,9,9) = reshape((/M1N1TDxss,M1N1TDyss,M1N1TDzss, & - M1N2TDxss,M1N2TDyss,M1N2TDzss, & - M1N3TDxss,M1N3TDyss,M1N3TDzss, & - M1N4TDxss,M1N4TDyss,M1N4TDzss, & - M1N5TDxss,M1N5TDyss,M1N5TDzss, & - M1N6TDxss,M1N6TDyss,M1N6TDzss, & - M1N7TDxss,M1N7TDyss,M1N7TDzss, & - M1N8TDxss,M1N8TDyss,M1N8TDzss, & - M1N9TDxss,M1N9TDyss,M1N9TDzss, & - M2N1TDxss,M2N1TDyss,M2N1TDzss, & - M2N2TDxss,M2N2TDyss,M2N2TDzss, & - M2N3TDxss,M2N3TDyss,M2N3TDzss, & - M2N4TDxss,M2N4TDyss,M2N4TDzss, & - M2N5TDxss,M2N5TDyss,M2N5TDzss, & - M2N6TDxss,M2N6TDyss,M2N6TDzss, & - M2N7TDxss,M2N7TDyss,M2N7TDzss, & - M2N8TDxss,M2N8TDyss,M2N8TDzss, & - M2N9TDxss,M2N9TDyss,M2N9TDzss, & - M3N1TDxss,M3N1TDyss,M3N1TDzss, & - M3N2TDxss,M3N2TDyss,M3N2TDzss, & - M3N3TDxss,M3N3TDyss,M3N3TDzss, & - M3N4TDxss,M3N4TDyss,M3N4TDzss, & - M3N5TDxss,M3N5TDyss,M3N5TDzss, & - M3N6TDxss,M3N6TDyss,M3N6TDzss, & - M3N7TDxss,M3N7TDyss,M3N7TDzss, & - M3N8TDxss,M3N8TDyss,M3N8TDzss, & - M3N9TDxss,M3N9TDyss,M3N9TDzss, & - M4N1TDxss,M4N1TDyss,M4N1TDzss, & - M4N2TDxss,M4N2TDyss,M4N2TDzss, & - M4N3TDxss,M4N3TDyss,M4N3TDzss, & - M4N4TDxss,M4N4TDyss,M4N4TDzss, & - M4N5TDxss,M4N5TDyss,M4N5TDzss, & - M4N6TDxss,M4N6TDyss,M4N6TDzss, & - M4N7TDxss,M4N7TDyss,M4N7TDzss, & - M4N8TDxss,M4N8TDyss,M4N8TDzss, & - M4N9TDxss,M4N9TDyss,M4N9TDzss, & - M5N1TDxss,M5N1TDyss,M5N1TDzss, & - M5N2TDxss,M5N2TDyss,M5N2TDzss, & - M5N3TDxss,M5N3TDyss,M5N3TDzss, & - M5N4TDxss,M5N4TDyss,M5N4TDzss, & - M5N5TDxss,M5N5TDyss,M5N5TDzss, & - M5N6TDxss,M5N6TDyss,M5N6TDzss, & - M5N7TDxss,M5N7TDyss,M5N7TDzss, & - M5N8TDxss,M5N8TDyss,M5N8TDzss, & - M5N9TDxss,M5N9TDyss,M5N9TDzss, & - M6N1TDxss,M6N1TDyss,M6N1TDzss, & - M6N2TDxss,M6N2TDyss,M6N2TDzss, & - M6N3TDxss,M6N3TDyss,M6N3TDzss, & - M6N4TDxss,M6N4TDyss,M6N4TDzss, & - M6N5TDxss,M6N5TDyss,M6N5TDzss, & - M6N6TDxss,M6N6TDyss,M6N6TDzss, & - M6N7TDxss,M6N7TDyss,M6N7TDzss, & - M6N8TDxss,M6N8TDyss,M6N8TDzss, & - M6N9TDxss,M6N9TDyss,M6N9TDzss, & - M7N1TDxss,M7N1TDyss,M7N1TDzss, & - M7N2TDxss,M7N2TDyss,M7N2TDzss, & - M7N3TDxss,M7N3TDyss,M7N3TDzss, & - M7N4TDxss,M7N4TDyss,M7N4TDzss, & - M7N5TDxss,M7N5TDyss,M7N5TDzss, & - M7N6TDxss,M7N6TDyss,M7N6TDzss, & - M7N7TDxss,M7N7TDyss,M7N7TDzss, & - M7N8TDxss,M7N8TDyss,M7N8TDzss, & - M7N9TDxss,M7N9TDyss,M7N9TDzss, & - M8N1TDxss,M8N1TDyss,M8N1TDzss, & - M8N2TDxss,M8N2TDyss,M8N2TDzss, & - M8N3TDxss,M8N3TDyss,M8N3TDzss, & - M8N4TDxss,M8N4TDyss,M8N4TDzss, & - M8N5TDxss,M8N5TDyss,M8N5TDzss, & - M8N6TDxss,M8N6TDyss,M8N6TDzss, & - M8N7TDxss,M8N7TDyss,M8N7TDzss, & - M8N8TDxss,M8N8TDyss,M8N8TDzss, & - M8N9TDxss,M8N9TDyss,M8N9TDzss, & - M9N1TDxss,M9N1TDyss,M9N1TDzss, & - M9N2TDxss,M9N2TDyss,M9N2TDzss, & - M9N3TDxss,M9N3TDyss,M9N3TDzss, & - M9N4TDxss,M9N4TDyss,M9N4TDzss, & - M9N5TDxss,M9N5TDyss,M9N5TDzss, & - M9N6TDxss,M9N6TDyss,M9N6TDzss, & - M9N7TDxss,M9N7TDyss,M9N7TDzss, & - M9N8TDxss,M9N8TDyss,M9N8TDzss, & - M9N9TDxss,M9N9TDyss,M9N9TDzss/), (/3,9,9/)) - -INTEGER, PARAMETER :: MNRDe (3,9,9) = reshape((/M1N1RDxe,M1N1RDye,M1N1RDze, & - M1N2RDxe,M1N2RDye,M1N2RDze, & - M1N3RDxe,M1N3RDye,M1N3RDze, & - M1N4RDxe,M1N4RDye,M1N4RDze, & - M1N5RDxe,M1N5RDye,M1N5RDze, & - M1N6RDxe,M1N6RDye,M1N6RDze, & - M1N7RDxe,M1N7RDye,M1N7RDze, & - M1N8RDxe,M1N8RDye,M1N8RDze, & - M1N9RDxe,M1N9RDye,M1N9RDze, & - M2N1RDxe,M2N1RDye,M2N1RDze, & - M2N2RDxe,M2N2RDye,M2N2RDze, & - M2N3RDxe,M2N3RDye,M2N3RDze, & - M2N4RDxe,M2N4RDye,M2N4RDze, & - M2N5RDxe,M2N5RDye,M2N5RDze, & - M2N6RDxe,M2N6RDye,M2N6RDze, & - M2N7RDxe,M2N7RDye,M2N7RDze, & - M2N8RDxe,M2N8RDye,M2N8RDze, & - M2N9RDxe,M2N9RDye,M2N9RDze, & - M3N1RDxe,M3N1RDye,M3N1RDze, & - M3N2RDxe,M3N2RDye,M3N2RDze, & - M3N3RDxe,M3N3RDye,M3N3RDze, & - M3N4RDxe,M3N4RDye,M3N4RDze, & - M3N5RDxe,M3N5RDye,M3N5RDze, & - M3N6RDxe,M3N6RDye,M3N6RDze, & - M3N7RDxe,M3N7RDye,M3N7RDze, & - M3N8RDxe,M3N8RDye,M3N8RDze, & - M3N9RDxe,M3N9RDye,M3N9RDze, & - M4N1RDxe,M4N1RDye,M4N1RDze, & - M4N2RDxe,M4N2RDye,M4N2RDze, & - M4N3RDxe,M4N3RDye,M4N3RDze, & - M4N4RDxe,M4N4RDye,M4N4RDze, & - M4N5RDxe,M4N5RDye,M4N5RDze, & - M4N6RDxe,M4N6RDye,M4N6RDze, & - M4N7RDxe,M4N7RDye,M4N7RDze, & - M4N8RDxe,M4N8RDye,M4N8RDze, & - M4N9RDxe,M4N9RDye,M4N9RDze, & - M5N1RDxe,M5N1RDye,M5N1RDze, & - M5N2RDxe,M5N2RDye,M5N2RDze, & - M5N3RDxe,M5N3RDye,M5N3RDze, & - M5N4RDxe,M5N4RDye,M5N4RDze, & - M5N5RDxe,M5N5RDye,M5N5RDze, & - M5N6RDxe,M5N6RDye,M5N6RDze, & - M5N7RDxe,M5N7RDye,M5N7RDze, & - M5N8RDxe,M5N8RDye,M5N8RDze, & - M5N9RDxe,M5N9RDye,M5N9RDze, & - M6N1RDxe,M6N1RDye,M6N1RDze, & - M6N2RDxe,M6N2RDye,M6N2RDze, & - M6N3RDxe,M6N3RDye,M6N3RDze, & - M6N4RDxe,M6N4RDye,M6N4RDze, & - M6N5RDxe,M6N5RDye,M6N5RDze, & - M6N6RDxe,M6N6RDye,M6N6RDze, & - M6N7RDxe,M6N7RDye,M6N7RDze, & - M6N8RDxe,M6N8RDye,M6N8RDze, & - M6N9RDxe,M6N9RDye,M6N9RDze, & - M7N1RDxe,M7N1RDye,M7N1RDze, & - M7N2RDxe,M7N2RDye,M7N2RDze, & - M7N3RDxe,M7N3RDye,M7N3RDze, & - M7N4RDxe,M7N4RDye,M7N4RDze, & - M7N5RDxe,M7N5RDye,M7N5RDze, & - M7N6RDxe,M7N6RDye,M7N6RDze, & - M7N7RDxe,M7N7RDye,M7N7RDze, & - M7N8RDxe,M7N8RDye,M7N8RDze, & - M7N9RDxe,M7N9RDye,M7N9RDze, & - M8N1RDxe,M8N1RDye,M8N1RDze, & - M8N2RDxe,M8N2RDye,M8N2RDze, & - M8N3RDxe,M8N3RDye,M8N3RDze, & - M8N4RDxe,M8N4RDye,M8N4RDze, & - M8N5RDxe,M8N5RDye,M8N5RDze, & - M8N6RDxe,M8N6RDye,M8N6RDze, & - M8N7RDxe,M8N7RDye,M8N7RDze, & - M8N8RDxe,M8N8RDye,M8N8RDze, & - M8N9RDxe,M8N9RDye,M8N9RDze, & - M9N1RDxe,M9N1RDye,M9N1RDze, & - M9N2RDxe,M9N2RDye,M9N2RDze, & - M9N3RDxe,M9N3RDye,M9N3RDze, & - M9N4RDxe,M9N4RDye,M9N4RDze, & - M9N5RDxe,M9N5RDye,M9N5RDze, & - M9N6RDxe,M9N6RDye,M9N6RDze, & - M9N7RDxe,M9N7RDye,M9N7RDze, & - M9N8RDxe,M9N8RDye,M9N8RDze, & - M9N9RDxe,M9N9RDye,M9N9RDze/), (/3,9,9/)) - - - INTEGER, PARAMETER :: MNTRAe(6,9,9) = reshape( (/M1N1TAxe,M1N1TAye,M1N1TAze,M1N1RAxe,M1N1RAye,M1N1RAze, & - M1N2TAxe,M1N2TAye,M1N2TAze,M1N2RAxe,M1N2RAye,M1N2RAze, & - M1N3TAxe,M1N3TAye,M1N3TAze,M1N3RAxe,M1N3RAye,M1N3RAze, & - M1N4TAxe,M1N4TAye,M1N4TAze,M1N4RAxe,M1N4RAye,M1N4RAze, & - M1N5TAxe,M1N5TAye,M1N5TAze,M1N5RAxe,M1N5RAye,M1N5RAze, & - M1N6TAxe,M1N6TAye,M1N6TAze,M1N6RAxe,M1N6RAye,M1N6RAze, & - M1N7TAxe,M1N7TAye,M1N7TAze,M1N7RAxe,M1N7RAye,M1N7RAze, & - M1N8TAxe,M1N8TAye,M1N8TAze,M1N8RAxe,M1N8RAye,M1N8RAze, & - M1N9TAxe,M1N9TAye,M1N9TAze,M1N9RAxe,M1N9RAye,M1N9RAze, & - M2N1TAxe,M2N1TAye,M2N1TAze,M2N1RAxe,M2N1RAye,M2N1RAze, & - M2N2TAxe,M2N2TAye,M2N2TAze,M2N2RAxe,M2N2RAye,M2N2RAze, & - M2N3TAxe,M2N3TAye,M2N3TAze,M2N3RAxe,M2N3RAye,M2N3RAze, & - M2N4TAxe,M2N4TAye,M2N4TAze,M2N4RAxe,M2N4RAye,M2N4RAze, & - M2N5TAxe,M2N5TAye,M2N5TAze,M2N5RAxe,M2N5RAye,M2N5RAze, & - M2N6TAxe,M2N6TAye,M2N6TAze,M2N6RAxe,M2N6RAye,M2N6RAze, & - M2N7TAxe,M2N7TAye,M2N7TAze,M2N7RAxe,M2N7RAye,M2N7RAze, & - M2N8TAxe,M2N8TAye,M2N8TAze,M2N8RAxe,M2N8RAye,M2N8RAze, & - M2N9TAxe,M2N9TAye,M2N9TAze,M2N9RAxe,M2N9RAye,M2N9RAze, & - M3N1TAxe,M3N1TAye,M3N1TAze,M3N1RAxe,M3N1RAye,M3N1RAze, & - M3N2TAxe,M3N2TAye,M3N2TAze,M3N2RAxe,M3N2RAye,M3N2RAze, & - M3N3TAxe,M3N3TAye,M3N3TAze,M3N3RAxe,M3N3RAye,M3N3RAze, & - M3N4TAxe,M3N4TAye,M3N4TAze,M3N4RAxe,M3N4RAye,M3N4RAze, & - M3N5TAxe,M3N5TAye,M3N5TAze,M3N5RAxe,M3N5RAye,M3N5RAze, & - M3N6TAxe,M3N6TAye,M3N6TAze,M3N6RAxe,M3N6RAye,M3N6RAze, & - M3N7TAxe,M3N7TAye,M3N7TAze,M3N7RAxe,M3N7RAye,M3N7RAze, & - M3N8TAxe,M3N8TAye,M3N8TAze,M3N8RAxe,M3N8RAye,M3N8RAze, & - M3N9TAxe,M3N9TAye,M3N9TAze,M3N9RAxe,M3N9RAye,M3N9RAze, & - M4N1TAxe,M4N1TAye,M4N1TAze,M4N1RAxe,M4N1RAye,M4N1RAze, & - M4N2TAxe,M4N2TAye,M4N2TAze,M4N2RAxe,M4N2RAye,M4N2RAze, & - M4N3TAxe,M4N3TAye,M4N3TAze,M4N3RAxe,M4N3RAye,M4N3RAze, & - M4N4TAxe,M4N4TAye,M4N4TAze,M4N4RAxe,M4N4RAye,M4N4RAze, & - M4N5TAxe,M4N5TAye,M4N5TAze,M4N5RAxe,M4N5RAye,M4N5RAze, & - M4N6TAxe,M4N6TAye,M4N6TAze,M4N6RAxe,M4N6RAye,M4N6RAze, & - M4N7TAxe,M4N7TAye,M4N7TAze,M4N7RAxe,M4N7RAye,M4N7RAze, & - M4N8TAxe,M4N8TAye,M4N8TAze,M4N8RAxe,M4N8RAye,M4N8RAze, & - M4N9TAxe,M4N9TAye,M4N9TAze,M4N9RAxe,M4N9RAye,M4N9RAze, & - M5N1TAxe,M5N1TAye,M5N1TAze,M5N1RAxe,M5N1RAye,M5N1RAze, & - M5N2TAxe,M5N2TAye,M5N2TAze,M5N2RAxe,M5N2RAye,M5N2RAze, & - M5N3TAxe,M5N3TAye,M5N3TAze,M5N3RAxe,M5N3RAye,M5N3RAze, & - M5N4TAxe,M5N4TAye,M5N4TAze,M5N4RAxe,M5N4RAye,M5N4RAze, & - M5N5TAxe,M5N5TAye,M5N5TAze,M5N5RAxe,M5N5RAye,M5N5RAze, & - M5N6TAxe,M5N6TAye,M5N6TAze,M5N6RAxe,M5N6RAye,M5N6RAze, & - M5N7TAxe,M5N7TAye,M5N7TAze,M5N7RAxe,M5N7RAye,M5N7RAze, & - M5N8TAxe,M5N8TAye,M5N8TAze,M5N8RAxe,M5N8RAye,M5N8RAze, & - M5N9TAxe,M5N9TAye,M5N9TAze,M5N9RAxe,M5N9RAye,M5N9RAze, & - M6N1TAxe,M6N1TAye,M6N1TAze,M6N1RAxe,M6N1RAye,M6N1RAze, & - M6N2TAxe,M6N2TAye,M6N2TAze,M6N2RAxe,M6N2RAye,M6N2RAze, & - M6N3TAxe,M6N3TAye,M6N3TAze,M6N3RAxe,M6N3RAye,M6N3RAze, & - M6N4TAxe,M6N4TAye,M6N4TAze,M6N4RAxe,M6N4RAye,M6N4RAze, & - M6N5TAxe,M6N5TAye,M6N5TAze,M6N5RAxe,M6N5RAye,M6N5RAze, & - M6N6TAxe,M6N6TAye,M6N6TAze,M6N6RAxe,M6N6RAye,M6N6RAze, & - M6N7TAxe,M6N7TAye,M6N7TAze,M6N7RAxe,M6N7RAye,M6N7RAze, & - M6N8TAxe,M6N8TAye,M6N8TAze,M6N8RAxe,M6N8RAye,M6N8RAze, & - M6N9TAxe,M6N9TAye,M6N9TAze,M6N9RAxe,M6N9RAye,M6N9RAze, & - M7N1TAxe,M7N1TAye,M7N1TAze,M7N1RAxe,M7N1RAye,M7N1RAze, & - M7N2TAxe,M7N2TAye,M7N2TAze,M7N2RAxe,M7N2RAye,M7N2RAze, & - M7N3TAxe,M7N3TAye,M7N3TAze,M7N3RAxe,M7N3RAye,M7N3RAze, & - M7N4TAxe,M7N4TAye,M7N4TAze,M7N4RAxe,M7N4RAye,M7N4RAze, & - M7N5TAxe,M7N5TAye,M7N5TAze,M7N5RAxe,M7N5RAye,M7N5RAze, & - M7N6TAxe,M7N6TAye,M7N6TAze,M7N6RAxe,M7N6RAye,M7N6RAze, & - M7N7TAxe,M7N7TAye,M7N7TAze,M7N7RAxe,M7N7RAye,M7N7RAze, & - M7N8TAxe,M7N8TAye,M7N8TAze,M7N8RAxe,M7N8RAye,M7N8RAze, & - M7N9TAxe,M7N9TAye,M7N9TAze,M7N9RAxe,M7N9RAye,M7N9RAze, & - M8N1TAxe,M8N1TAye,M8N1TAze,M8N1RAxe,M8N1RAye,M8N1RAze, & - M8N2TAxe,M8N2TAye,M8N2TAze,M8N2RAxe,M8N2RAye,M8N2RAze, & - M8N3TAxe,M8N3TAye,M8N3TAze,M8N3RAxe,M8N3RAye,M8N3RAze, & - M8N4TAxe,M8N4TAye,M8N4TAze,M8N4RAxe,M8N4RAye,M8N4RAze, & - M8N5TAxe,M8N5TAye,M8N5TAze,M8N5RAxe,M8N5RAye,M8N5RAze, & - M8N6TAxe,M8N6TAye,M8N6TAze,M8N6RAxe,M8N6RAye,M8N6RAze, & - M8N7TAxe,M8N7TAye,M8N7TAze,M8N7RAxe,M8N7RAye,M8N7RAze, & - M8N8TAxe,M8N8TAye,M8N8TAze,M8N8RAxe,M8N8RAye,M8N8RAze, & - M8N9TAxe,M8N9TAye,M8N9TAze,M8N9RAxe,M8N9RAye,M8N9RAze, & - M9N1TAxe,M9N1TAye,M9N1TAze,M9N1RAxe,M9N1RAye,M9N1RAze, & - M9N2TAxe,M9N2TAye,M9N2TAze,M9N2RAxe,M9N2RAye,M9N2RAze, & - M9N3TAxe,M9N3TAye,M9N3TAze,M9N3RAxe,M9N3RAye,M9N3RAze, & - M9N4TAxe,M9N4TAye,M9N4TAze,M9N4RAxe,M9N4RAye,M9N4RAze, & - M9N5TAxe,M9N5TAye,M9N5TAze,M9N5RAxe,M9N5RAye,M9N5RAze, & - M9N6TAxe,M9N6TAye,M9N6TAze,M9N6RAxe,M9N6RAye,M9N6RAze, & - M9N7TAxe,M9N7TAye,M9N7TAze,M9N7RAxe,M9N7RAye,M9N7RAze, & - M9N8TAxe,M9N8TAye,M9N8TAze,M9N8RAxe,M9N8RAye,M9N8RAze, & - M9N9TAxe,M9N9TAye,M9N9TAze,M9N9RAxe,M9N9RAye,M9N9RAze/), (/6,9,9/)) - - INTEGER, PARAMETER :: ReactSS(6) = (/ReactFXss, ReactFYss, ReactFZss , & - ReactMXss, ReactMYss, ReactMZss/) - - INTEGER, PARAMETER :: IntfSS(6) = (/IntfFXss, IntfFYss, IntfFZss , & - IntfMXss, IntfMYss, IntfMZss/) - - - INTEGER, PARAMETER :: IntfTRss(6) = (/IntfTDXss, IntfTDYss, IntfTDZss , & - IntfRDXss, IntfRDYss, IntfRDZss/) - - INTEGER, PARAMETER :: IntfTRAss(6) = (/IntfTAXss, IntfTAYss, IntfTAZss , & - IntfRAXss, IntfRAYss, IntfRAZss/) - - - - - - - - CHARACTER(10), PARAMETER :: ValidParamAry(2265) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "INTFFXSS ","INTFFYSS ","INTFFZSS ","INTFMXSS ","INTFMYSS ","INTFMZSS ","INTFRAXSS", & - "INTFRAYSS","INTFRAZSS","INTFRDXSS","INTFRDYSS","INTFRDZSS","INTFTAXSS","INTFTAYSS", & - "INTFTAZSS","INTFTDXSS","INTFTDYSS","INTFTDZSS","M1N1FKXE ","M1N1FKYE ","M1N1FKZE ", & - "M1N1FMXE ","M1N1FMYE ","M1N1FMZE ","M1N1MKXE ","M1N1MKYE ","M1N1MKZE ","M1N1MMXE ", & - "M1N1MMYE ","M1N1MMZE ","M1N1RAXE ","M1N1RAYE ","M1N1RAZE ","M1N1RDXE ","M1N1RDYE ", & - "M1N1RDZE ","M1N1TAXE ","M1N1TAYE ","M1N1TAZE ","M1N1TDXSS","M1N1TDYSS","M1N1TDZSS", & - "M1N2FKXE ","M1N2FKYE ","M1N2FKZE ","M1N2FMXE ","M1N2FMYE ","M1N2FMZE ","M1N2MKXE ", & - "M1N2MKYE ","M1N2MKZE ","M1N2MMXE ","M1N2MMYE ","M1N2MMZE ","M1N2RAXE ","M1N2RAYE ", & - "M1N2RAZE ","M1N2RDXE ","M1N2RDYE ","M1N2RDZE ","M1N2TAXE ","M1N2TAYE ","M1N2TAZE ", & - "M1N2TDXSS","M1N2TDYSS","M1N2TDZSS","M1N3FKXE ","M1N3FKYE ","M1N3FKZE ","M1N3FMXE ", & - "M1N3FMYE ","M1N3FMZE ","M1N3MKXE ","M1N3MKYE ","M1N3MKZE ","M1N3MMXE ","M1N3MMYE ", & - "M1N3MMZE ","M1N3RAXE ","M1N3RAYE ","M1N3RAZE ","M1N3RDXE ","M1N3RDYE ","M1N3RDZE ", & - "M1N3TAXE ","M1N3TAYE ","M1N3TAZE ","M1N3TDXSS","M1N3TDYSS","M1N3TDZSS","M1N4FKXE ", & - "M1N4FKYE ","M1N4FKZE ","M1N4FMXE ","M1N4FMYE ","M1N4FMZE ","M1N4MKXE ","M1N4MKYE ", & - "M1N4MKZE ","M1N4MMXE ","M1N4MMYE ","M1N4MMZE ","M1N4RAXE ","M1N4RAYE ","M1N4RAZE ", & - "M1N4RDXE ","M1N4RDYE ","M1N4RDZE ","M1N4TAXE ","M1N4TAYE ","M1N4TAZE ","M1N4TDXSS", & - "M1N4TDYSS","M1N4TDZSS","M1N5FKXE ","M1N5FKYE ","M1N5FKZE ","M1N5FMXE ","M1N5FMYE ", & - "M1N5FMZE ","M1N5MKXE ","M1N5MKYE ","M1N5MKZE ","M1N5MMXE ","M1N5MMYE ","M1N5MMZE ", & - "M1N5RAXE ","M1N5RAYE ","M1N5RAZE ","M1N5RDXE ","M1N5RDYE ","M1N5RDZE ","M1N5TAXE ", & - "M1N5TAYE ","M1N5TAZE ","M1N5TDXSS","M1N5TDYSS","M1N5TDZSS","M1N6FKXE ","M1N6FKYE ", & - "M1N6FKZE ","M1N6FMXE ","M1N6FMYE ","M1N6FMZE ","M1N6MKXE ","M1N6MKYE ","M1N6MKZE ", & - "M1N6MMXE ","M1N6MMYE ","M1N6MMZE ","M1N6RAXE ","M1N6RAYE ","M1N6RAZE ","M1N6RDXE ", & - "M1N6RDYE ","M1N6RDZE ","M1N6TAXE ","M1N6TAYE ","M1N6TAZE ","M1N6TDXSS","M1N6TDYSS", & - "M1N6TDZSS","M1N7FKXE ","M1N7FKYE ","M1N7FKZE ","M1N7FMXE ","M1N7FMYE ","M1N7FMZE ", & - "M1N7MKXE ","M1N7MKYE ","M1N7MKZE ","M1N7MMXE ","M1N7MMYE ","M1N7MMZE ","M1N7RAXE ", & - "M1N7RAYE ","M1N7RAZE ","M1N7RDXE ","M1N7RDYE ","M1N7RDZE ","M1N7TAXE ","M1N7TAYE ", & - "M1N7TAZE ","M1N7TDXSS","M1N7TDYSS","M1N7TDZSS","M1N8FKXE ","M1N8FKYE ","M1N8FKZE ", & - "M1N8FMXE ","M1N8FMYE ","M1N8FMZE ","M1N8MKXE ","M1N8MKYE ","M1N8MKZE ","M1N8MMXE ", & - "M1N8MMYE ","M1N8MMZE ","M1N8RAXE ","M1N8RAYE ","M1N8RAZE ","M1N8RDXE ","M1N8RDYE ", & - "M1N8RDZE ","M1N8TAXE ","M1N8TAYE ","M1N8TAZE ","M1N8TDXSS","M1N8TDYSS","M1N8TDZSS", & - "M1N9FKXE ","M1N9FKYE ","M1N9FKZE ","M1N9FMXE ","M1N9FMYE ","M1N9FMZE ","M1N9MKXE ", & - "M1N9MKYE ","M1N9MKZE ","M1N9MMXE ","M1N9MMYE ","M1N9MMZE ","M1N9RAXE ","M1N9RAYE ", & - "M1N9RAZE ","M1N9RDXE ","M1N9RDYE ","M1N9RDZE ","M1N9TAXE ","M1N9TAYE ","M1N9TAZE ", & - "M1N9TDXSS","M1N9TDYSS","M1N9TDZSS","M2N1FKXE ","M2N1FKYE ","M2N1FKZE ","M2N1FMXE ", & - "M2N1FMYE ","M2N1FMZE ","M2N1MKXE ","M2N1MKYE ","M2N1MKZE ","M2N1MMXE ","M2N1MMYE ", & - "M2N1MMZE ","M2N1RAXE ","M2N1RAYE ","M2N1RAZE ","M2N1RDXE ","M2N1RDYE ","M2N1RDZE ", & - "M2N1TAXE ","M2N1TAYE ","M2N1TAZE ","M2N1TDXSS","M2N1TDYSS","M2N1TDZSS","M2N2FKXE ", & - "M2N2FKYE ","M2N2FKZE ","M2N2FMXE ","M2N2FMYE ","M2N2FMZE ","M2N2MKXE ","M2N2MKYE ", & - "M2N2MKZE ","M2N2MMXE ","M2N2MMYE ","M2N2MMZE ","M2N2RAXE ","M2N2RAYE ","M2N2RAZE ", & - "M2N2RDXE ","M2N2RDYE ","M2N2RDZE ","M2N2TAXE ","M2N2TAYE ","M2N2TAZE ","M2N2TDXSS", & - "M2N2TDYSS","M2N2TDZSS","M2N3FKXE ","M2N3FKYE ","M2N3FKZE ","M2N3FMXE ","M2N3FMYE ", & - "M2N3FMZE ","M2N3MKXE ","M2N3MKYE ","M2N3MKZE ","M2N3MMXE ","M2N3MMYE ","M2N3MMZE ", & - "M2N3RAXE ","M2N3RAYE ","M2N3RAZE ","M2N3RDXE ","M2N3RDYE ","M2N3RDZE ","M2N3TAXE ", & - "M2N3TAYE ","M2N3TAZE ","M2N3TDXSS","M2N3TDYSS","M2N3TDZSS","M2N4FKXE ","M2N4FKYE ", & - "M2N4FKZE ","M2N4FMXE ","M2N4FMYE ","M2N4FMZE ","M2N4MKXE ","M2N4MKYE ","M2N4MKZE ", & - "M2N4MMXE ","M2N4MMYE ","M2N4MMZE ","M2N4RAXE ","M2N4RAYE ","M2N4RAZE ","M2N4RDXE ", & - "M2N4RDYE ","M2N4RDZE ","M2N4TAXE ","M2N4TAYE ","M2N4TAZE ","M2N4TDXSS","M2N4TDYSS", & - "M2N4TDZSS","M2N5FKXE ","M2N5FKYE ","M2N5FKZE ","M2N5FMXE ","M2N5FMYE ","M2N5FMZE ", & - "M2N5MKXE ","M2N5MKYE ","M2N5MKZE ","M2N5MMXE ","M2N5MMYE ","M2N5MMZE ","M2N5RAXE ", & - "M2N5RAYE ","M2N5RAZE ","M2N5RDXE ","M2N5RDYE ","M2N5RDZE ","M2N5TAXE ","M2N5TAYE ", & - "M2N5TAZE ","M2N5TDXSS","M2N5TDYSS","M2N5TDZSS","M2N6FKXE ","M2N6FKYE ","M2N6FKZE ", & - "M2N6FMXE ","M2N6FMYE ","M2N6FMZE ","M2N6MKXE ","M2N6MKYE ","M2N6MKZE ","M2N6MMXE ", & - "M2N6MMYE ","M2N6MMZE ","M2N6RAXE ","M2N6RAYE ","M2N6RAZE ","M2N6RDXE ","M2N6RDYE ", & - "M2N6RDZE ","M2N6TAXE ","M2N6TAYE ","M2N6TAZE ","M2N6TDXSS","M2N6TDYSS","M2N6TDZSS", & - "M2N7FKXE ","M2N7FKYE ","M2N7FKZE ","M2N7FMXE ","M2N7FMYE ","M2N7FMZE ","M2N7MKXE ", & - "M2N7MKYE ","M2N7MKZE ","M2N7MMXE ","M2N7MMYE ","M2N7MMZE ","M2N7RAXE ","M2N7RAYE ", & - "M2N7RAZE ","M2N7RDXE ","M2N7RDYE ","M2N7RDZE ","M2N7TAXE ","M2N7TAYE ","M2N7TAZE ", & - "M2N7TDXSS","M2N7TDYSS","M2N7TDZSS","M2N8FKXE ","M2N8FKYE ","M2N8FKZE ","M2N8FMXE ", & - "M2N8FMYE ","M2N8FMZE ","M2N8MKXE ","M2N8MKYE ","M2N8MKZE ","M2N8MMXE ","M2N8MMYE ", & - "M2N8MMZE ","M2N8RAXE ","M2N8RAYE ","M2N8RAZE ","M2N8RDXE ","M2N8RDYE ","M2N8RDZE ", & - "M2N8TAXE ","M2N8TAYE ","M2N8TAZE ","M2N8TDXSS","M2N8TDYSS","M2N8TDZSS","M2N9FKXE ", & - "M2N9FKYE ","M2N9FKZE ","M2N9FMXE ","M2N9FMYE ","M2N9FMZE ","M2N9MKXE ","M2N9MKYE ", & - "M2N9MKZE ","M2N9MMXE ","M2N9MMYE ","M2N9MMZE ","M2N9RAXE ","M2N9RAYE ","M2N9RAZE ", & - "M2N9RDXE ","M2N9RDYE ","M2N9RDZE ","M2N9TAXE ","M2N9TAYE ","M2N9TAZE ","M2N9TDXSS", & - "M2N9TDYSS","M2N9TDZSS","M3N1FKXE ","M3N1FKYE ","M3N1FKZE ","M3N1FMXE ","M3N1FMYE ", & - "M3N1FMZE ","M3N1MKXE ","M3N1MKYE ","M3N1MKZE ","M3N1MMXE ","M3N1MMYE ","M3N1MMZE ", & - "M3N1RAXE ","M3N1RAYE ","M3N1RAZE ","M3N1RDXE ","M3N1RDYE ","M3N1RDZE ","M3N1TAXE ", & - "M3N1TAYE ","M3N1TAZE ","M3N1TDXSS","M3N1TDYSS","M3N1TDZSS","M3N2FKXE ","M3N2FKYE ", & - "M3N2FKZE ","M3N2FMXE ","M3N2FMYE ","M3N2FMZE ","M3N2MKXE ","M3N2MKYE ","M3N2MKZE ", & - "M3N2MMXE ","M3N2MMYE ","M3N2MMZE ","M3N2RAXE ","M3N2RAYE ","M3N2RAZE ","M3N2RDXE ", & - "M3N2RDYE ","M3N2RDZE ","M3N2TAXE ","M3N2TAYE ","M3N2TAZE ","M3N2TDXSS","M3N2TDYSS", & - "M3N2TDZSS","M3N3FKXE ","M3N3FKYE ","M3N3FKZE ","M3N3FMXE ","M3N3FMYE ","M3N3FMZE ", & - "M3N3MKXE ","M3N3MKYE ","M3N3MKZE ","M3N3MMXE ","M3N3MMYE ","M3N3MMZE ","M3N3RAXE ", & - "M3N3RAYE ","M3N3RAZE ","M3N3RDXE ","M3N3RDYE ","M3N3RDZE ","M3N3TAXE ","M3N3TAYE ", & - "M3N3TAZE ","M3N3TDXSS","M3N3TDYSS","M3N3TDZSS","M3N4FKXE ","M3N4FKYE ","M3N4FKZE ", & - "M3N4FMXE ","M3N4FMYE ","M3N4FMZE ","M3N4MKXE ","M3N4MKYE ","M3N4MKZE ","M3N4MMXE ", & - "M3N4MMYE ","M3N4MMZE ","M3N4RAXE ","M3N4RAYE ","M3N4RAZE ","M3N4RDXE ","M3N4RDYE ", & - "M3N4RDZE ","M3N4TAXE ","M3N4TAYE ","M3N4TAZE ","M3N4TDXSS","M3N4TDYSS","M3N4TDZSS", & - "M3N5FKXE ","M3N5FKYE ","M3N5FKZE ","M3N5FMXE ","M3N5FMYE ","M3N5FMZE ","M3N5MKXE ", & - "M3N5MKYE ","M3N5MKZE ","M3N5MMXE ","M3N5MMYE ","M3N5MMZE ","M3N5RAXE ","M3N5RAYE ", & - "M3N5RAZE ","M3N5RDXE ","M3N5RDYE ","M3N5RDZE ","M3N5TAXE ","M3N5TAYE ","M3N5TAZE ", & - "M3N5TDXSS","M3N5TDYSS","M3N5TDZSS","M3N6FKXE ","M3N6FKYE ","M3N6FKZE ","M3N6FMXE ", & - "M3N6FMYE ","M3N6FMZE ","M3N6MKXE ","M3N6MKYE ","M3N6MKZE ","M3N6MMXE ","M3N6MMYE ", & - "M3N6MMZE ","M3N6RAXE ","M3N6RAYE ","M3N6RAZE ","M3N6RDXE ","M3N6RDYE ","M3N6RDZE ", & - "M3N6TAXE ","M3N6TAYE ","M3N6TAZE ","M3N6TDXSS","M3N6TDYSS","M3N6TDZSS","M3N7FKXE ", & - "M3N7FKYE ","M3N7FKZE ","M3N7FMXE ","M3N7FMYE ","M3N7FMZE ","M3N7MKXE ","M3N7MKYE ", & - "M3N7MKZE ","M3N7MMXE ","M3N7MMYE ","M3N7MMZE ","M3N7RAXE ","M3N7RAYE ","M3N7RAZE ", & - "M3N7RDXE ","M3N7RDYE ","M3N7RDZE ","M3N7TAXE ","M3N7TAYE ","M3N7TAZE ","M3N7TDXSS", & - "M3N7TDYSS","M3N7TDZSS","M3N8FKXE ","M3N8FKYE ","M3N8FKZE ","M3N8FMXE ","M3N8FMYE ", & - "M3N8FMZE ","M3N8MKXE ","M3N8MKYE ","M3N8MKZE ","M3N8MMXE ","M3N8MMYE ","M3N8MMZE ", & - "M3N8RAXE ","M3N8RAYE ","M3N8RAZE ","M3N8RDXE ","M3N8RDYE ","M3N8RDZE ","M3N8TAXE ", & - "M3N8TAYE ","M3N8TAZE ","M3N8TDXSS","M3N8TDYSS","M3N8TDZSS","M3N9FKXE ","M3N9FKYE ", & - "M3N9FKZE ","M3N9FMXE ","M3N9FMYE ","M3N9FMZE ","M3N9MKXE ","M3N9MKYE ","M3N9MKZE ", & - "M3N9MMXE ","M3N9MMYE ","M3N9MMZE ","M3N9RAXE ","M3N9RAYE ","M3N9RAZE ","M3N9RDXE ", & - "M3N9RDYE ","M3N9RDZE ","M3N9TAXE ","M3N9TAYE ","M3N9TAZE ","M3N9TDXSS","M3N9TDYSS", & - "M3N9TDZSS","M4N1FKXE ","M4N1FKYE ","M4N1FKZE ","M4N1FMXE ","M4N1FMYE ","M4N1FMZE ", & - "M4N1MKXE ","M4N1MKYE ","M4N1MKZE ","M4N1MMXE ","M4N1MMYE ","M4N1MMZE ","M4N1RAXE ", & - "M4N1RAYE ","M4N1RAZE ","M4N1RDXE ","M4N1RDYE ","M4N1RDZE ","M4N1TAXE ","M4N1TAYE ", & - "M4N1TAZE ","M4N1TDXSS","M4N1TDYSS","M4N1TDZSS","M4N2FKXE ","M4N2FKYE ","M4N2FKZE ", & - "M4N2FMXE ","M4N2FMYE ","M4N2FMZE ","M4N2MKXE ","M4N2MKYE ","M4N2MKZE ","M4N2MMXE ", & - "M4N2MMYE ","M4N2MMZE ","M4N2RAXE ","M4N2RAYE ","M4N2RAZE ","M4N2RDXE ","M4N2RDYE ", & - "M4N2RDZE ","M4N2TAXE ","M4N2TAYE ","M4N2TAZE ","M4N2TDXSS","M4N2TDYSS","M4N2TDZSS", & - "M4N3FKXE ","M4N3FKYE ","M4N3FKZE ","M4N3FMXE ","M4N3FMYE ","M4N3FMZE ","M4N3MKXE ", & - "M4N3MKYE ","M4N3MKZE ","M4N3MMXE ","M4N3MMYE ","M4N3MMZE ","M4N3RAXE ","M4N3RAYE ", & - "M4N3RAZE ","M4N3RDXE ","M4N3RDYE ","M4N3RDZE ","M4N3TAXE ","M4N3TAYE ","M4N3TAZE ", & - "M4N3TDXSS","M4N3TDYSS","M4N3TDZSS","M4N4FKXE ","M4N4FKYE ","M4N4FKZE ","M4N4FMXE ", & - "M4N4FMYE ","M4N4FMZE ","M4N4MKXE ","M4N4MKYE ","M4N4MKZE ","M4N4MMXE ","M4N4MMYE ", & - "M4N4MMZE ","M4N4RAXE ","M4N4RAYE ","M4N4RAZE ","M4N4RDXE ","M4N4RDYE ","M4N4RDZE ", & - "M4N4TAXE ","M4N4TAYE ","M4N4TAZE ","M4N4TDXSS","M4N4TDYSS","M4N4TDZSS","M4N5FKXE ", & - "M4N5FKYE ","M4N5FKZE ","M4N5FMXE ","M4N5FMYE ","M4N5FMZE ","M4N5MKXE ","M4N5MKYE ", & - "M4N5MKZE ","M4N5MMXE ","M4N5MMYE ","M4N5MMZE ","M4N5RAXE ","M4N5RAYE ","M4N5RAZE ", & - "M4N5RDXE ","M4N5RDYE ","M4N5RDZE ","M4N5TAXE ","M4N5TAYE ","M4N5TAZE ","M4N5TDXSS", & - "M4N5TDYSS","M4N5TDZSS","M4N6FKXE ","M4N6FKYE ","M4N6FKZE ","M4N6FMXE ","M4N6FMYE ", & - "M4N6FMZE ","M4N6MKXE ","M4N6MKYE ","M4N6MKZE ","M4N6MMXE ","M4N6MMYE ","M4N6MMZE ", & - "M4N6RAXE ","M4N6RAYE ","M4N6RAZE ","M4N6RDXE ","M4N6RDYE ","M4N6RDZE ","M4N6TAXE ", & - "M4N6TAYE ","M4N6TAZE ","M4N6TDXSS","M4N6TDYSS","M4N6TDZSS","M4N7FKXE ","M4N7FKYE ", & - "M4N7FKZE ","M4N7FMXE ","M4N7FMYE ","M4N7FMZE ","M4N7MKXE ","M4N7MKYE ","M4N7MKZE ", & - "M4N7MMXE ","M4N7MMYE ","M4N7MMZE ","M4N7RAXE ","M4N7RAYE ","M4N7RAZE ","M4N7RDXE ", & - "M4N7RDYE ","M4N7RDZE ","M4N7TAXE ","M4N7TAYE ","M4N7TAZE ","M4N7TDXSS","M4N7TDYSS", & - "M4N7TDZSS","M4N8FKXE ","M4N8FKYE ","M4N8FKZE ","M4N8FMXE ","M4N8FMYE ","M4N8FMZE ", & - "M4N8MKXE ","M4N8MKYE ","M4N8MKZE ","M4N8MMXE ","M4N8MMYE ","M4N8MMZE ","M4N8RAXE ", & - "M4N8RAYE ","M4N8RAZE ","M4N8RDXE ","M4N8RDYE ","M4N8RDZE ","M4N8TAXE ","M4N8TAYE ", & - "M4N8TAZE ","M4N8TDXSS","M4N8TDYSS","M4N8TDZSS","M4N9FKXE ","M4N9FKYE ","M4N9FKZE ", & - "M4N9FMXE ","M4N9FMYE ","M4N9FMZE ","M4N9MKXE ","M4N9MKYE ","M4N9MKZE ","M4N9MMXE ", & - "M4N9MMYE ","M4N9MMZE ","M4N9RAXE ","M4N9RAYE ","M4N9RAZE ","M4N9RDXE ","M4N9RDYE ", & - "M4N9RDZE ","M4N9TAXE ","M4N9TAYE ","M4N9TAZE ","M4N9TDXSS","M4N9TDYSS","M4N9TDZSS", & - "M5N1FKXE ","M5N1FKYE ","M5N1FKZE ","M5N1FMXE ","M5N1FMYE ","M5N1FMZE ","M5N1MKXE ", & - "M5N1MKYE ","M5N1MKZE ","M5N1MMXE ","M5N1MMYE ","M5N1MMZE ","M5N1RAXE ","M5N1RAYE ", & - "M5N1RAZE ","M5N1RDXE ","M5N1RDYE ","M5N1RDZE ","M5N1TAXE ","M5N1TAYE ","M5N1TAZE ", & - "M5N1TDXSS","M5N1TDYSS","M5N1TDZSS","M5N2FKXE ","M5N2FKYE ","M5N2FKZE ","M5N2FMXE ", & - "M5N2FMYE ","M5N2FMZE ","M5N2MKXE ","M5N2MKYE ","M5N2MKZE ","M5N2MMXE ","M5N2MMYE ", & - "M5N2MMZE ","M5N2RAXE ","M5N2RAYE ","M5N2RAZE ","M5N2RDXE ","M5N2RDYE ","M5N2RDZE ", & - "M5N2TAXE ","M5N2TAYE ","M5N2TAZE ","M5N2TDXSS","M5N2TDYSS","M5N2TDZSS","M5N3FKXE ", & - "M5N3FKYE ","M5N3FKZE ","M5N3FMXE ","M5N3FMYE ","M5N3FMZE ","M5N3MKXE ","M5N3MKYE ", & - "M5N3MKZE ","M5N3MMXE ","M5N3MMYE ","M5N3MMZE ","M5N3RAXE ","M5N3RAYE ","M5N3RAZE ", & - "M5N3RDXE ","M5N3RDYE ","M5N3RDZE ","M5N3TAXE ","M5N3TAYE ","M5N3TAZE ","M5N3TDXSS", & - "M5N3TDYSS","M5N3TDZSS","M5N4FKXE ","M5N4FKYE ","M5N4FKZE ","M5N4FMXE ","M5N4FMYE ", & - "M5N4FMZE ","M5N4MKXE ","M5N4MKYE ","M5N4MKZE ","M5N4MMXE ","M5N4MMYE ","M5N4MMZE ", & - "M5N4RAXE ","M5N4RAYE ","M5N4RAZE ","M5N4RDXE ","M5N4RDYE ","M5N4RDZE ","M5N4TAXE ", & - "M5N4TAYE ","M5N4TAZE ","M5N4TDXSS","M5N4TDYSS","M5N4TDZSS","M5N5FKXE ","M5N5FKYE ", & - "M5N5FKZE ","M5N5FMXE ","M5N5FMYE ","M5N5FMZE ","M5N5MKXE ","M5N5MKYE ","M5N5MKZE ", & - "M5N5MMXE ","M5N5MMYE ","M5N5MMZE ","M5N5RAXE ","M5N5RAYE ","M5N5RAZE ","M5N5RDXE ", & - "M5N5RDYE ","M5N5RDZE ","M5N5TAXE ","M5N5TAYE ","M5N5TAZE ","M5N5TDXSS","M5N5TDYSS", & - "M5N5TDZSS","M5N6FKXE ","M5N6FKYE ","M5N6FKZE ","M5N6FMXE ","M5N6FMYE ","M5N6FMZE ", & - "M5N6MKXE ","M5N6MKYE ","M5N6MKZE ","M5N6MMXE ","M5N6MMYE ","M5N6MMZE ","M5N6RAXE ", & - "M5N6RAYE ","M5N6RAZE ","M5N6RDXE ","M5N6RDYE ","M5N6RDZE ","M5N6TAXE ","M5N6TAYE ", & - "M5N6TAZE ","M5N6TDXSS","M5N6TDYSS","M5N6TDZSS","M5N7FKXE ","M5N7FKYE ","M5N7FKZE ", & - "M5N7FMXE ","M5N7FMYE ","M5N7FMZE ","M5N7MKXE ","M5N7MKYE ","M5N7MKZE ","M5N7MMXE ", & - "M5N7MMYE ","M5N7MMZE ","M5N7RAXE ","M5N7RAYE ","M5N7RAZE ","M5N7RDXE ","M5N7RDYE ", & - "M5N7RDZE ","M5N7TAXE ","M5N7TAYE ","M5N7TAZE ","M5N7TDXSS","M5N7TDYSS","M5N7TDZSS", & - "M5N8FKXE ","M5N8FKYE ","M5N8FKZE ","M5N8FMXE ","M5N8FMYE ","M5N8FMZE ","M5N8MKXE ", & - "M5N8MKYE ","M5N8MKZE ","M5N8MMXE ","M5N8MMYE ","M5N8MMZE ","M5N8RAXE ","M5N8RAYE ", & - "M5N8RAZE ","M5N8RDXE ","M5N8RDYE ","M5N8RDZE ","M5N8TAXE ","M5N8TAYE ","M5N8TAZE ", & - "M5N8TDXSS","M5N8TDYSS","M5N8TDZSS","M5N9FKXE ","M5N9FKYE ","M5N9FKZE ","M5N9FMXE ", & - "M5N9FMYE ","M5N9FMZE ","M5N9MKXE ","M5N9MKYE ","M5N9MKZE ","M5N9MMXE ","M5N9MMYE ", & - "M5N9MMZE ","M5N9RAXE ","M5N9RAYE ","M5N9RAZE ","M5N9RDXE ","M5N9RDYE ","M5N9RDZE ", & - "M5N9TAXE ","M5N9TAYE ","M5N9TAZE ","M5N9TDXSS","M5N9TDYSS","M5N9TDZSS","M6N1FKXE ", & - "M6N1FKYE ","M6N1FKZE ","M6N1FMXE ","M6N1FMYE ","M6N1FMZE ","M6N1MKXE ","M6N1MKYE ", & - "M6N1MKZE ","M6N1MMXE ","M6N1MMYE ","M6N1MMZE ","M6N1RAXE ","M6N1RAYE ","M6N1RAZE ", & - "M6N1RDXE ","M6N1RDYE ","M6N1RDZE ","M6N1TAXE ","M6N1TAYE ","M6N1TAZE ","M6N1TDXSS", & - "M6N1TDYSS","M6N1TDZSS","M6N2FKXE ","M6N2FKYE ","M6N2FKZE ","M6N2FMXE ","M6N2FMYE ", & - "M6N2FMZE ","M6N2MKXE ","M6N2MKYE ","M6N2MKZE ","M6N2MMXE ","M6N2MMYE ","M6N2MMZE ", & - "M6N2RAXE ","M6N2RAYE ","M6N2RAZE ","M6N2RDXE ","M6N2RDYE ","M6N2RDZE ","M6N2TAXE ", & - "M6N2TAYE ","M6N2TAZE ","M6N2TDXSS","M6N2TDYSS","M6N2TDZSS","M6N3FKXE ","M6N3FKYE ", & - "M6N3FKZE ","M6N3FMXE ","M6N3FMYE ","M6N3FMZE ","M6N3MKXE ","M6N3MKYE ","M6N3MKZE ", & - "M6N3MMXE ","M6N3MMYE ","M6N3MMZE ","M6N3RAXE ","M6N3RAYE ","M6N3RAZE ","M6N3RDXE ", & - "M6N3RDYE ","M6N3RDZE ","M6N3TAXE ","M6N3TAYE ","M6N3TAZE ","M6N3TDXSS","M6N3TDYSS", & - "M6N3TDZSS","M6N4FKXE ","M6N4FKYE ","M6N4FKZE ","M6N4FMXE ","M6N4FMYE ","M6N4FMZE ", & - "M6N4MKXE ","M6N4MKYE ","M6N4MKZE ","M6N4MMXE ","M6N4MMYE ","M6N4MMZE ","M6N4RAXE ", & - "M6N4RAYE ","M6N4RAZE ","M6N4RDXE ","M6N4RDYE ","M6N4RDZE ","M6N4TAXE ","M6N4TAYE ", & - "M6N4TAZE ","M6N4TDXSS","M6N4TDYSS","M6N4TDZSS","M6N5FKXE ","M6N5FKYE ","M6N5FKZE ", & - "M6N5FMXE ","M6N5FMYE ","M6N5FMZE ","M6N5MKXE ","M6N5MKYE ","M6N5MKZE ","M6N5MMXE ", & - "M6N5MMYE ","M6N5MMZE ","M6N5RAXE ","M6N5RAYE ","M6N5RAZE ","M6N5RDXE ","M6N5RDYE ", & - "M6N5RDZE ","M6N5TAXE ","M6N5TAYE ","M6N5TAZE ","M6N5TDXSS","M6N5TDYSS","M6N5TDZSS", & - "M6N6FKXE ","M6N6FKYE ","M6N6FKZE ","M6N6FMXE ","M6N6FMYE ","M6N6FMZE ","M6N6MKXE ", & - "M6N6MKYE ","M6N6MKZE ","M6N6MMXE ","M6N6MMYE ","M6N6MMZE ","M6N6RAXE ","M6N6RAYE ", & - "M6N6RAZE ","M6N6RDXE ","M6N6RDYE ","M6N6RDZE ","M6N6TAXE ","M6N6TAYE ","M6N6TAZE ", & - "M6N6TDXSS","M6N6TDYSS","M6N6TDZSS","M6N7FKXE ","M6N7FKYE ","M6N7FKZE ","M6N7FMXE ", & - "M6N7FMYE ","M6N7FMZE ","M6N7MKXE ","M6N7MKYE ","M6N7MKZE ","M6N7MMXE ","M6N7MMYE ", & - "M6N7MMZE ","M6N7RAXE ","M6N7RAYE ","M6N7RAZE ","M6N7RDXE ","M6N7RDYE ","M6N7RDZE ", & - "M6N7TAXE ","M6N7TAYE ","M6N7TAZE ","M6N7TDXSS","M6N7TDYSS","M6N7TDZSS","M6N8FKXE ", & - "M6N8FKYE ","M6N8FKZE ","M6N8FMXE ","M6N8FMYE ","M6N8FMZE ","M6N8MKXE ","M6N8MKYE ", & - "M6N8MKZE ","M6N8MMXE ","M6N8MMYE ","M6N8MMZE ","M6N8RAXE ","M6N8RAYE ","M6N8RAZE ", & - "M6N8RDXE ","M6N8RDYE ","M6N8RDZE ","M6N8TAXE ","M6N8TAYE ","M6N8TAZE ","M6N8TDXSS", & - "M6N8TDYSS","M6N8TDZSS","M6N9FKXE ","M6N9FKYE ","M6N9FKZE ","M6N9FMXE ","M6N9FMYE ", & - "M6N9FMZE ","M6N9MKXE ","M6N9MKYE ","M6N9MKZE ","M6N9MMXE ","M6N9MMYE ","M6N9MMZE ", & - "M6N9RAXE ","M6N9RAYE ","M6N9RAZE ","M6N9RDXE ","M6N9RDYE ","M6N9RDZE ","M6N9TAXE ", & - "M6N9TAYE ","M6N9TAZE ","M6N9TDXSS","M6N9TDYSS","M6N9TDZSS","M7N1FKXE ","M7N1FKYE ", & - "M7N1FKZE ","M7N1FMXE ","M7N1FMYE ","M7N1FMZE ","M7N1MKXE ","M7N1MKYE ","M7N1MKZE ", & - "M7N1MMXE ","M7N1MMYE ","M7N1MMZE ","M7N1RAXE ","M7N1RAYE ","M7N1RAZE ","M7N1RDXE ", & - "M7N1RDYE ","M7N1RDZE ","M7N1TAXE ","M7N1TAYE ","M7N1TAZE ","M7N1TDXSS","M7N1TDYSS", & - "M7N1TDZSS","M7N2FKXE ","M7N2FKYE ","M7N2FKZE ","M7N2FMXE ","M7N2FMYE ","M7N2FMZE ", & - "M7N2MKXE ","M7N2MKYE ","M7N2MKZE ","M7N2MMXE ","M7N2MMYE ","M7N2MMZE ","M7N2RAXE ", & - "M7N2RAYE ","M7N2RAZE ","M7N2RDXE ","M7N2RDYE ","M7N2RDZE ","M7N2TAXE ","M7N2TAYE ", & - "M7N2TAZE ","M7N2TDXSS","M7N2TDYSS","M7N2TDZSS","M7N3FKXE ","M7N3FKYE ","M7N3FKZE ", & - "M7N3FMXE ","M7N3FMYE ","M7N3FMZE ","M7N3MKXE ","M7N3MKYE ","M7N3MKZE ","M7N3MMXE ", & - "M7N3MMYE ","M7N3MMZE ","M7N3RAXE ","M7N3RAYE ","M7N3RAZE ","M7N3RDXE ","M7N3RDYE ", & - "M7N3RDZE ","M7N3TAXE ","M7N3TAYE ","M7N3TAZE ","M7N3TDXSS","M7N3TDYSS","M7N3TDZSS", & - "M7N4FKXE ","M7N4FKYE ","M7N4FKZE ","M7N4FMXE ","M7N4FMYE ","M7N4FMZE ","M7N4MKXE ", & - "M7N4MKYE ","M7N4MKZE ","M7N4MMXE ","M7N4MMYE ","M7N4MMZE ","M7N4RAXE ","M7N4RAYE ", & - "M7N4RAZE ","M7N4RDXE ","M7N4RDYE ","M7N4RDZE ","M7N4TAXE ","M7N4TAYE ","M7N4TAZE ", & - "M7N4TDXSS","M7N4TDYSS","M7N4TDZSS","M7N5FKXE ","M7N5FKYE ","M7N5FKZE ","M7N5FMXE ", & - "M7N5FMYE ","M7N5FMZE ","M7N5MKXE ","M7N5MKYE ","M7N5MKZE ","M7N5MMXE ","M7N5MMYE ", & - "M7N5MMZE ","M7N5RAXE ","M7N5RAYE ","M7N5RAZE ","M7N5RDXE ","M7N5RDYE ","M7N5RDZE ", & - "M7N5TAXE ","M7N5TAYE ","M7N5TAZE ","M7N5TDXSS","M7N5TDYSS","M7N5TDZSS","M7N6FKXE ", & - "M7N6FKYE ","M7N6FKZE ","M7N6FMXE ","M7N6FMYE ","M7N6FMZE ","M7N6MKXE ","M7N6MKYE ", & - "M7N6MKZE ","M7N6MMXE ","M7N6MMYE ","M7N6MMZE ","M7N6RAXE ","M7N6RAYE ","M7N6RAZE ", & - "M7N6RDXE ","M7N6RDYE ","M7N6RDZE ","M7N6TAXE ","M7N6TAYE ","M7N6TAZE ","M7N6TDXSS", & - "M7N6TDYSS","M7N6TDZSS","M7N7FKXE ","M7N7FKYE ","M7N7FKZE ","M7N7FMXE ","M7N7FMYE ", & - "M7N7FMZE ","M7N7MKXE ","M7N7MKYE ","M7N7MKZE ","M7N7MMXE ","M7N7MMYE ","M7N7MMZE ", & - "M7N7RAXE ","M7N7RAYE ","M7N7RAZE ","M7N7RDXE ","M7N7RDYE ","M7N7RDZE ","M7N7TAXE ", & - "M7N7TAYE ","M7N7TAZE ","M7N7TDXSS","M7N7TDYSS","M7N7TDZSS","M7N8FKXE ","M7N8FKYE ", & - "M7N8FKZE ","M7N8FMXE ","M7N8FMYE ","M7N8FMZE ","M7N8MKXE ","M7N8MKYE ","M7N8MKZE ", & - "M7N8MMXE ","M7N8MMYE ","M7N8MMZE ","M7N8RAXE ","M7N8RAYE ","M7N8RAZE ","M7N8RDXE ", & - "M7N8RDYE ","M7N8RDZE ","M7N8TAXE ","M7N8TAYE ","M7N8TAZE ","M7N8TDXSS","M7N8TDYSS", & - "M7N8TDZSS","M7N9FKXE ","M7N9FKYE ","M7N9FKZE ","M7N9FMXE ","M7N9FMYE ","M7N9FMZE ", & - "M7N9MKXE ","M7N9MKYE ","M7N9MKZE ","M7N9MMXE ","M7N9MMYE ","M7N9MMZE ","M7N9RAXE ", & - "M7N9RAYE ","M7N9RAZE ","M7N9RDXE ","M7N9RDYE ","M7N9RDZE ","M7N9TAXE ","M7N9TAYE ", & - "M7N9TAZE ","M7N9TDXSS","M7N9TDYSS","M7N9TDZSS","M8N1FKXE ","M8N1FKYE ","M8N1FKZE ", & - "M8N1FMXE ","M8N1FMYE ","M8N1FMZE ","M8N1MKXE ","M8N1MKYE ","M8N1MKZE ","M8N1MMXE ", & - "M8N1MMYE ","M8N1MMZE ","M8N1RAXE ","M8N1RAYE ","M8N1RAZE ","M8N1RDXE ","M8N1RDYE ", & - "M8N1RDZE ","M8N1TAXE ","M8N1TAYE ","M8N1TAZE ","M8N1TDXSS","M8N1TDYSS","M8N1TDZSS", & - "M8N2FKXE ","M8N2FKYE ","M8N2FKZE ","M8N2FMXE ","M8N2FMYE ","M8N2FMZE ","M8N2MKXE ", & - "M8N2MKYE ","M8N2MKZE ","M8N2MMXE ","M8N2MMYE ","M8N2MMZE ","M8N2RAXE ","M8N2RAYE ", & - "M8N2RAZE ","M8N2RDXE ","M8N2RDYE ","M8N2RDZE ","M8N2TAXE ","M8N2TAYE ","M8N2TAZE ", & - "M8N2TDXSS","M8N2TDYSS","M8N2TDZSS","M8N3FKXE ","M8N3FKYE ","M8N3FKZE ","M8N3FMXE ", & - "M8N3FMYE ","M8N3FMZE ","M8N3MKXE ","M8N3MKYE ","M8N3MKZE ","M8N3MMXE ","M8N3MMYE ", & - "M8N3MMZE ","M8N3RAXE ","M8N3RAYE ","M8N3RAZE ","M8N3RDXE ","M8N3RDYE ","M8N3RDZE ", & - "M8N3TAXE ","M8N3TAYE ","M8N3TAZE ","M8N3TDXSS","M8N3TDYSS","M8N3TDZSS","M8N4FKXE ", & - "M8N4FKYE ","M8N4FKZE ","M8N4FMXE ","M8N4FMYE ","M8N4FMZE ","M8N4MKXE ","M8N4MKYE ", & - "M8N4MKZE ","M8N4MMXE ","M8N4MMYE ","M8N4MMZE ","M8N4RAXE ","M8N4RAYE ","M8N4RAZE ", & - "M8N4RDXE ","M8N4RDYE ","M8N4RDZE ","M8N4TAXE ","M8N4TAYE ","M8N4TAZE ","M8N4TDXSS", & - "M8N4TDYSS","M8N4TDZSS","M8N5FKXE ","M8N5FKYE ","M8N5FKZE ","M8N5FMXE ","M8N5FMYE ", & - "M8N5FMZE ","M8N5MKXE ","M8N5MKYE ","M8N5MKZE ","M8N5MMXE ","M8N5MMYE ","M8N5MMZE ", & - "M8N5RAXE ","M8N5RAYE ","M8N5RAZE ","M8N5RDXE ","M8N5RDYE ","M8N5RDZE ","M8N5TAXE ", & - "M8N5TAYE ","M8N5TAZE ","M8N5TDXSS","M8N5TDYSS","M8N5TDZSS","M8N6FKXE ","M8N6FKYE ", & - "M8N6FKZE ","M8N6FMXE ","M8N6FMYE ","M8N6FMZE ","M8N6MKXE ","M8N6MKYE ","M8N6MKZE ", & - "M8N6MMXE ","M8N6MMYE ","M8N6MMZE ","M8N6RAXE ","M8N6RAYE ","M8N6RAZE ","M8N6RDXE ", & - "M8N6RDYE ","M8N6RDZE ","M8N6TAXE ","M8N6TAYE ","M8N6TAZE ","M8N6TDXSS","M8N6TDYSS", & - "M8N6TDZSS","M8N7FKXE ","M8N7FKYE ","M8N7FKZE ","M8N7FMXE ","M8N7FMYE ","M8N7FMZE ", & - "M8N7MKXE ","M8N7MKYE ","M8N7MKZE ","M8N7MMXE ","M8N7MMYE ","M8N7MMZE ","M8N7RAXE ", & - "M8N7RAYE ","M8N7RAZE ","M8N7RDXE ","M8N7RDYE ","M8N7RDZE ","M8N7TAXE ","M8N7TAYE ", & - "M8N7TAZE ","M8N7TDXSS","M8N7TDYSS","M8N7TDZSS","M8N8FKXE ","M8N8FKYE ","M8N8FKZE ", & - "M8N8FMXE ","M8N8FMYE ","M8N8FMZE ","M8N8MKXE ","M8N8MKYE ","M8N8MKZE ","M8N8MMXE ", & - "M8N8MMYE ","M8N8MMZE ","M8N8RAXE ","M8N8RAYE ","M8N8RAZE ","M8N8RDXE ","M8N8RDYE ", & - "M8N8RDZE ","M8N8TAXE ","M8N8TAYE ","M8N8TAZE ","M8N8TDXSS","M8N8TDYSS","M8N8TDZSS", & - "M8N9FKXE ","M8N9FKYE ","M8N9FKZE ","M8N9FMXE ","M8N9FMYE ","M8N9FMZE ","M8N9MKXE ", & - "M8N9MKYE ","M8N9MKZE ","M8N9MMXE ","M8N9MMYE ","M8N9MMZE ","M8N9RAXE ","M8N9RAYE ", & - "M8N9RAZE ","M8N9RDXE ","M8N9RDYE ","M8N9RDZE ","M8N9TAXE ","M8N9TAYE ","M8N9TAZE ", & - "M8N9TDXSS","M8N9TDYSS","M8N9TDZSS","M9N1FKXE ","M9N1FKYE ","M9N1FKZE ","M9N1FMXE ", & - "M9N1FMYE ","M9N1FMZE ","M9N1MKXE ","M9N1MKYE ","M9N1MKZE ","M9N1MMXE ","M9N1MMYE ", & - "M9N1MMZE ","M9N1RAXE ","M9N1RAYE ","M9N1RAZE ","M9N1RDXE ","M9N1RDYE ","M9N1RDZE ", & - "M9N1TAXE ","M9N1TAYE ","M9N1TAZE ","M9N1TDXSS","M9N1TDYSS","M9N1TDZSS","M9N2FKXE ", & - "M9N2FKYE ","M9N2FKZE ","M9N2FMXE ","M9N2FMYE ","M9N2FMZE ","M9N2MKXE ","M9N2MKYE ", & - "M9N2MKZE ","M9N2MMXE ","M9N2MMYE ","M9N2MMZE ","M9N2RAXE ","M9N2RAYE ","M9N2RAZE ", & - "M9N2RDXE ","M9N2RDYE ","M9N2RDZE ","M9N2TAXE ","M9N2TAYE ","M9N2TAZE ","M9N2TDXSS", & - "M9N2TDYSS","M9N2TDZSS","M9N3FKXE ","M9N3FKYE ","M9N3FKZE ","M9N3FMXE ","M9N3FMYE ", & - "M9N3FMZE ","M9N3MKXE ","M9N3MKYE ","M9N3MKZE ","M9N3MMXE ","M9N3MMYE ","M9N3MMZE ", & - "M9N3RAXE ","M9N3RAYE ","M9N3RAZE ","M9N3RDXE ","M9N3RDYE ","M9N3RDZE ","M9N3TAXE ", & - "M9N3TAYE ","M9N3TAZE ","M9N3TDXSS","M9N3TDYSS","M9N3TDZSS","M9N4FKXE ","M9N4FKYE ", & - "M9N4FKZE ","M9N4FMXE ","M9N4FMYE ","M9N4FMZE ","M9N4MKXE ","M9N4MKYE ","M9N4MKZE ", & - "M9N4MMXE ","M9N4MMYE ","M9N4MMZE ","M9N4RAXE ","M9N4RAYE ","M9N4RAZE ","M9N4RDXE ", & - "M9N4RDYE ","M9N4RDZE ","M9N4TAXE ","M9N4TAYE ","M9N4TAZE ","M9N4TDXSS","M9N4TDYSS", & - "M9N4TDZSS","M9N5FKXE ","M9N5FKYE ","M9N5FKZE ","M9N5FMXE ","M9N5FMYE ","M9N5FMZE ", & - "M9N5MKXE ","M9N5MKYE ","M9N5MKZE ","M9N5MMXE ","M9N5MMYE ","M9N5MMZE ","M9N5RAXE ", & - "M9N5RAYE ","M9N5RAZE ","M9N5RDXE ","M9N5RDYE ","M9N5RDZE ","M9N5TAXE ","M9N5TAYE ", & - "M9N5TAZE ","M9N5TDXSS","M9N5TDYSS","M9N5TDZSS","M9N6FKXE ","M9N6FKYE ","M9N6FKZE ", & - "M9N6FMXE ","M9N6FMYE ","M9N6FMZE ","M9N6MKXE ","M9N6MKYE ","M9N6MKZE ","M9N6MMXE ", & - "M9N6MMYE ","M9N6MMZE ","M9N6RAXE ","M9N6RAYE ","M9N6RAZE ","M9N6RDXE ","M9N6RDYE ", & - "M9N6RDZE ","M9N6TAXE ","M9N6TAYE ","M9N6TAZE ","M9N6TDXSS","M9N6TDYSS","M9N6TDZSS", & - "M9N7FKXE ","M9N7FKYE ","M9N7FKZE ","M9N7FMXE ","M9N7FMYE ","M9N7FMZE ","M9N7MKXE ", & - "M9N7MKYE ","M9N7MKZE ","M9N7MMXE ","M9N7MMYE ","M9N7MMZE ","M9N7RAXE ","M9N7RAYE ", & - "M9N7RAZE ","M9N7RDXE ","M9N7RDYE ","M9N7RDZE ","M9N7TAXE ","M9N7TAYE ","M9N7TAZE ", & - "M9N7TDXSS","M9N7TDYSS","M9N7TDZSS","M9N8FKXE ","M9N8FKYE ","M9N8FKZE ","M9N8FMXE ", & - "M9N8FMYE ","M9N8FMZE ","M9N8MKXE ","M9N8MKYE ","M9N8MKZE ","M9N8MMXE ","M9N8MMYE ", & - "M9N8MMZE ","M9N8RAXE ","M9N8RAYE ","M9N8RAZE ","M9N8RDXE ","M9N8RDYE ","M9N8RDZE ", & - "M9N8TAXE ","M9N8TAYE ","M9N8TAZE ","M9N8TDXSS","M9N8TDYSS","M9N8TDZSS","M9N9FKXE ", & - "M9N9FKYE ","M9N9FKZE ","M9N9FMXE ","M9N9FMYE ","M9N9FMZE ","M9N9MKXE ","M9N9MKYE ", & - "M9N9MKZE ","M9N9MMXE ","M9N9MMYE ","M9N9MMZE ","M9N9RAXE ","M9N9RAYE ","M9N9RAZE ", & - "M9N9RDXE ","M9N9RDYE ","M9N9RDZE ","M9N9TAXE ","M9N9TAYE ","M9N9TAZE ","M9N9TDXSS", & - "M9N9TDYSS","M9N9TDZSS","REACTFXSS","REACTFYSS","REACTFZSS","REACTMXSS","REACTMYSS", & - "REACTMZSS","SSQM01 ","SSQM02 ","SSQM03 ","SSQM04 ","SSQM05 ","SSQM06 ", & - "SSQM07 ","SSQM08 ","SSQM09 ","SSQM10 ","SSQM11 ","SSQM12 ","SSQM13 ", & - "SSQM14 ","SSQM15 ","SSQM16 ","SSQM17 ","SSQM18 ","SSQM19 ","SSQM20 ", & - "SSQM21 ","SSQM22 ","SSQM23 ","SSQM24 ","SSQM25 ","SSQM26 ","SSQM27 ", & - "SSQM28 ","SSQM29 ","SSQM30 ","SSQM31 ","SSQM32 ","SSQM33 ","SSQM34 ", & - "SSQM35 ","SSQM36 ","SSQM37 ","SSQM38 ","SSQM39 ","SSQM40 ","SSQM41 ", & - "SSQM42 ","SSQM43 ","SSQM44 ","SSQM45 ","SSQM46 ","SSQM47 ","SSQM48 ", & - "SSQM49 ","SSQM50 ","SSQM51 ","SSQM52 ","SSQM53 ","SSQM54 ","SSQM55 ", & - "SSQM56 ","SSQM57 ","SSQM58 ","SSQM59 ","SSQM60 ","SSQM61 ","SSQM62 ", & - "SSQM63 ","SSQM64 ","SSQM65 ","SSQM66 ","SSQM67 ","SSQM68 ","SSQM69 ", & - "SSQM70 ","SSQM71 ","SSQM72 ","SSQM73 ","SSQM74 ","SSQM75 ","SSQM76 ", & - "SSQM77 ","SSQM78 ","SSQM79 ","SSQM80 ","SSQM81 ","SSQM82 ","SSQM83 ", & - "SSQM84 ","SSQM85 ","SSQM86 ","SSQM87 ","SSQM88 ","SSQM89 ","SSQM90 ", & - "SSQM91 ","SSQM92 ","SSQM93 ","SSQM94 ","SSQM95 ","SSQM96 ","SSQM97 ", & - "SSQM98 ","SSQM99 ","SSQMD01 ","SSQMD02 ","SSQMD03 ","SSQMD04 ","SSQMD05 ", & - "SSQMD06 ","SSQMD07 ","SSQMD08 ","SSQMD09 ","SSQMD10 ","SSQMD11 ","SSQMD12 ", & - "SSQMD13 ","SSQMD14 ","SSQMD15 ","SSQMD16 ","SSQMD17 ","SSQMD18 ","SSQMD19 ", & - "SSQMD20 ","SSQMD21 ","SSQMD22 ","SSQMD23 ","SSQMD24 ","SSQMD25 ","SSQMD26 ", & - "SSQMD27 ","SSQMD28 ","SSQMD29 ","SSQMD30 ","SSQMD31 ","SSQMD32 ","SSQMD33 ", & - "SSQMD34 ","SSQMD35 ","SSQMD36 ","SSQMD37 ","SSQMD38 ","SSQMD39 ","SSQMD40 ", & - "SSQMD41 ","SSQMD42 ","SSQMD43 ","SSQMD44 ","SSQMD45 ","SSQMD46 ","SSQMD47 ", & - "SSQMD48 ","SSQMD49 ","SSQMD50 ","SSQMD51 ","SSQMD52 ","SSQMD53 ","SSQMD54 ", & - "SSQMD55 ","SSQMD56 ","SSQMD57 ","SSQMD58 ","SSQMD59 ","SSQMD60 ","SSQMD61 ", & - "SSQMD62 ","SSQMD63 ","SSQMD64 ","SSQMD65 ","SSQMD66 ","SSQMD67 ","SSQMD68 ", & - "SSQMD69 ","SSQMD70 ","SSQMD71 ","SSQMD72 ","SSQMD73 ","SSQMD74 ","SSQMD75 ", & - "SSQMD76 ","SSQMD77 ","SSQMD78 ","SSQMD79 ","SSQMD80 ","SSQMD81 ","SSQMD82 ", & - "SSQMD83 ","SSQMD84 ","SSQMD85 ","SSQMD86 ","SSQMD87 ","SSQMD88 ","SSQMD89 ", & - "SSQMD90 ","SSQMD91 ","SSQMD92 ","SSQMD93 ","SSQMD94 ","SSQMD95 ","SSQMD96 ", & - "SSQMD97 ","SSQMD98 ","SSQMD99 ","SSQMDD01 ","SSQMDD02 ","SSQMDD03 ","SSQMDD04 ", & - "SSQMDD05 ","SSQMDD06 ","SSQMDD07 ","SSQMDD08 ","SSQMDD09 ","SSQMDD10 ","SSQMDD11 ", & - "SSQMDD12 ","SSQMDD13 ","SSQMDD14 ","SSQMDD15 ","SSQMDD16 ","SSQMDD17 ","SSQMDD18 ", & - "SSQMDD19 ","SSQMDD20 ","SSQMDD21 ","SSQMDD22 ","SSQMDD23 ","SSQMDD24 ","SSQMDD25 ", & - "SSQMDD26 ","SSQMDD27 ","SSQMDD28 ","SSQMDD29 ","SSQMDD30 ","SSQMDD31 ","SSQMDD32 ", & - "SSQMDD33 ","SSQMDD34 ","SSQMDD35 ","SSQMDD36 ","SSQMDD37 ","SSQMDD38 ","SSQMDD39 ", & - "SSQMDD40 ","SSQMDD41 ","SSQMDD42 ","SSQMDD43 ","SSQMDD44 ","SSQMDD45 ","SSQMDD46 ", & - "SSQMDD47 ","SSQMDD48 ","SSQMDD49 ","SSQMDD50 ","SSQMDD51 ","SSQMDD52 ","SSQMDD53 ", & - "SSQMDD54 ","SSQMDD55 ","SSQMDD56 ","SSQMDD57 ","SSQMDD58 ","SSQMDD59 ","SSQMDD60 ", & - "SSQMDD61 ","SSQMDD62 ","SSQMDD63 ","SSQMDD64 ","SSQMDD65 ","SSQMDD66 ","SSQMDD67 ", & - "SSQMDD68 ","SSQMDD69 ","SSQMDD70 ","SSQMDD71 ","SSQMDD72 ","SSQMDD73 ","SSQMDD74 ", & - "SSQMDD75 ","SSQMDD76 ","SSQMDD77 ","SSQMDD78 ","SSQMDD79 ","SSQMDD80 ","SSQMDD81 ", & - "SSQMDD82 ","SSQMDD83 ","SSQMDD84 ","SSQMDD85 ","SSQMDD86 ","SSQMDD87 ","SSQMDD88 ", & - "SSQMDD89 ","SSQMDD90 ","SSQMDD91 ","SSQMDD92 ","SSQMDD93 ","SSQMDD94 ","SSQMDD95 ", & - "SSQMDD96 ","SSQMDD97 ","SSQMDD98 ","SSQMDD99 "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(2265) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - IntfFXss , IntfFYss , IntfFZss , IntfMXss , IntfMYss , IntfMZss , IntfRAXss , & - IntfRAYss , IntfRAZss , IntfRDXss , IntfRDYss , IntfRDZss , IntfTAXss , IntfTAYss , & - IntfTAZss , IntfTDXss , IntfTDYss , IntfTDZss , M1N1FKxe , M1N1FKye , M1N1FKze , & - M1N1FMxe , M1N1FMye , M1N1FMze , M1N1MKxe , M1N1MKye , M1N1MKze , M1N1MMxe , & - M1N1MMye , M1N1MMze , M1N1RAxe , M1N1RAye , M1N1RAze , M1N1RDxe , M1N1RDye , & - M1N1RDze , M1N1TAxe , M1N1TAye , M1N1TAze , M1N1TDxss , M1N1TDyss , M1N1TDzss , & - M1N2FKxe , M1N2FKye , M1N2FKze , M1N2FMxe , M1N2FMye , M1N2FMze , M1N2MKxe , & - M1N2MKye , M1N2MKze , M1N2MMxe , M1N2MMye , M1N2MMze , M1N2RAxe , M1N2RAye , & - M1N2RAze , M1N2RDxe , M1N2RDye , M1N2RDze , M1N2TAxe , M1N2TAye , M1N2TAze , & - M1N2TDxss , M1N2TDyss , M1N2TDzss , M1N3FKxe , M1N3FKye , M1N3FKze , M1N3FMxe , & - M1N3FMye , M1N3FMze , M1N3MKxe , M1N3MKye , M1N3MKze , M1N3MMxe , M1N3MMye , & - M1N3MMze , M1N3RAxe , M1N3RAye , M1N3RAze , M1N3RDxe , M1N3RDye , M1N3RDze , & - M1N3TAxe , M1N3TAye , M1N3TAze , M1N3TDxss , M1N3TDyss , M1N3TDzss , M1N4FKxe , & - M1N4FKye , M1N4FKze , M1N4FMxe , M1N4FMye , M1N4FMze , M1N4MKxe , M1N4MKye , & - M1N4MKze , M1N4MMxe , M1N4MMye , M1N4MMze , M1N4RAxe , M1N4RAye , M1N4RAze , & - M1N4RDxe , M1N4RDye , M1N4RDze , M1N4TAxe , M1N4TAye , M1N4TAze , M1N4TDxss , & - M1N4TDyss , M1N4TDzss , M1N5FKxe , M1N5FKye , M1N5FKze , M1N5FMxe , M1N5FMye , & - M1N5FMze , M1N5MKxe , M1N5MKye , M1N5MKze , M1N5MMxe , M1N5MMye , M1N5MMze , & - M1N5RAxe , M1N5RAye , M1N5RAze , M1N5RDxe , M1N5RDye , M1N5RDze , M1N5TAxe , & - M1N5TAye , M1N5TAze , M1N5TDxss , M1N5TDyss , M1N5TDzss , M1N6FKxe , M1N6FKye , & - M1N6FKze , M1N6FMxe , M1N6FMye , M1N6FMze , M1N6MKxe , M1N6MKye , M1N6MKze , & - M1N6MMxe , M1N6MMye , M1N6MMze , M1N6RAxe , M1N6RAye , M1N6RAze , M1N6RDxe , & - M1N6RDye , M1N6RDze , M1N6TAxe , M1N6TAye , M1N6TAze , M1N6TDxss , M1N6TDyss , & - M1N6TDzss , M1N7FKxe , M1N7FKye , M1N7FKze , M1N7FMxe , M1N7FMye , M1N7FMze , & - M1N7MKxe , M1N7MKye , M1N7MKze , M1N7MMxe , M1N7MMye , M1N7MMze , M1N7RAxe , & - M1N7RAye , M1N7RAze , M1N7RDxe , M1N7RDye , M1N7RDze , M1N7TAxe , M1N7TAye , & - M1N7TAze , M1N7TDxss , M1N7TDyss , M1N7TDzss , M1N8FKxe , M1N8FKye , M1N8FKze , & - M1N8FMxe , M1N8FMye , M1N8FMze , M1N8MKxe , M1N8MKye , M1N8MKze , M1N8MMxe , & - M1N8MMye , M1N8MMze , M1N8RAxe , M1N8RAye , M1N8RAze , M1N8RDxe , M1N8RDye , & - M1N8RDze , M1N8TAxe , M1N8TAye , M1N8TAze , M1N8TDxss , M1N8TDyss , M1N8TDzss , & - M1N9FKxe , M1N9FKye , M1N9FKze , M1N9FMxe , M1N9FMye , M1N9FMze , M1N9MKxe , & - M1N9MKye , M1N9MKze , M1N9MMxe , M1N9MMye , M1N9MMze , M1N9RAxe , M1N9RAye , & - M1N9RAze , M1N9RDxe , M1N9RDye , M1N9RDze , M1N9TAxe , M1N9TAye , M1N9TAze , & - M1N9TDxss , M1N9TDyss , M1N9TDzss , M2N1FKxe , M2N1FKye , M2N1FKze , M2N1FMxe , & - M2N1FMye , M2N1FMze , M2N1MKxe , M2N1MKye , M2N1MKze , M2N1MMxe , M2N1MMye , & - M2N1MMze , M2N1RAxe , M2N1RAye , M2N1RAze , M2N1RDxe , M2N1RDye , M2N1RDze , & - M2N1TAxe , M2N1TAye , M2N1TAze , M2N1TDxss , M2N1TDyss , M2N1TDzss , M2N2FKxe , & - M2N2FKye , M2N2FKze , M2N2FMxe , M2N2FMye , M2N2FMze , M2N2MKxe , M2N2MKye , & - M2N2MKze , M2N2MMxe , M2N2MMye , M2N2MMze , M2N2RAxe , M2N2RAye , M2N2RAze , & - M2N2RDxe , M2N2RDye , M2N2RDze , M2N2TAxe , M2N2TAye , M2N2TAze , M2N2TDxss , & - M2N2TDyss , M2N2TDzss , M2N3FKxe , M2N3FKye , M2N3FKze , M2N3FMxe , M2N3FMye , & - M2N3FMze , M2N3MKxe , M2N3MKye , M2N3MKze , M2N3MMxe , M2N3MMye , M2N3MMze , & - M2N3RAxe , M2N3RAye , M2N3RAze , M2N3RDxe , M2N3RDye , M2N3RDze , M2N3TAxe , & - M2N3TAye , M2N3TAze , M2N3TDxss , M2N3TDyss , M2N3TDzss , M2N4FKxe , M2N4FKye , & - M2N4FKze , M2N4FMxe , M2N4FMye , M2N4FMze , M2N4MKxe , M2N4MKye , M2N4MKze , & - M2N4MMxe , M2N4MMye , M2N4MMze , M2N4RAxe , M2N4RAye , M2N4RAze , M2N4RDxe , & - M2N4RDye , M2N4RDze , M2N4TAxe , M2N4TAye , M2N4TAze , M2N4TDxss , M2N4TDyss , & - M2N4TDzss , M2N5FKxe , M2N5FKye , M2N5FKze , M2N5FMxe , M2N5FMye , M2N5FMze , & - M2N5MKxe , M2N5MKye , M2N5MKze , M2N5MMxe , M2N5MMye , M2N5MMze , M2N5RAxe , & - M2N5RAye , M2N5RAze , M2N5RDxe , M2N5RDye , M2N5RDze , M2N5TAxe , M2N5TAye , & - M2N5TAze , M2N5TDxss , M2N5TDyss , M2N5TDzss , M2N6FKxe , M2N6FKye , M2N6FKze , & - M2N6FMxe , M2N6FMye , M2N6FMze , M2N6MKxe , M2N6MKye , M2N6MKze , M2N6MMxe , & - M2N6MMye , M2N6MMze , M2N6RAxe , M2N6RAye , M2N6RAze , M2N6RDxe , M2N6RDye , & - M2N6RDze , M2N6TAxe , M2N6TAye , M2N6TAze , M2N6TDxss , M2N6TDyss , M2N6TDzss , & - M2N7FKxe , M2N7FKye , M2N7FKze , M2N7FMxe , M2N7FMye , M2N7FMze , M2N7MKxe , & - M2N7MKye , M2N7MKze , M2N7MMxe , M2N7MMye , M2N7MMze , M2N7RAxe , M2N7RAye , & - M2N7RAze , M2N7RDxe , M2N7RDye , M2N7RDze , M2N7TAxe , M2N7TAye , M2N7TAze , & - M2N7TDxss , M2N7TDyss , M2N7TDzss , M2N8FKxe , M2N8FKye , M2N8FKze , M2N8FMxe , & - M2N8FMye , M2N8FMze , M2N8MKxe , M2N8MKye , M2N8MKze , M2N8MMxe , M2N8MMye , & - M2N8MMze , M2N8RAxe , M2N8RAye , M2N8RAze , M2N8RDxe , M2N8RDye , M2N8RDze , & - M2N8TAxe , M2N8TAye , M2N8TAze , M2N8TDxss , M2N8TDyss , M2N8TDzss , M2N9FKxe , & - M2N9FKye , M2N9FKze , M2N9FMxe , M2N9FMye , M2N9FMze , M2N9MKxe , M2N9MKye , & - M2N9MKze , M2N9MMxe , M2N9MMye , M2N9MMze , M2N9RAxe , M2N9RAye , M2N9RAze , & - M2N9RDxe , M2N9RDye , M2N9RDze , M2N9TAxe , M2N9TAye , M2N9TAze , M2N9TDxss , & - M2N9TDyss , M2N9TDzss , M3N1FKxe , M3N1FKye , M3N1FKze , M3N1FMxe , M3N1FMye , & - M3N1FMze , M3N1MKxe , M3N1MKye , M3N1MKze , M3N1MMxe , M3N1MMye , M3N1MMze , & - M3N1RAxe , M3N1RAye , M3N1RAze , M3N1RDxe , M3N1RDye , M3N1RDze , M3N1TAxe , & - M3N1TAye , M3N1TAze , M3N1TDxss , M3N1TDyss , M3N1TDzss , M3N2FKxe , M3N2FKye , & - M3N2FKze , M3N2FMxe , M3N2FMye , M3N2FMze , M3N2MKxe , M3N2MKye , M3N2MKze , & - M3N2MMxe , M3N2MMye , M3N2MMze , M3N2RAxe , M3N2RAye , M3N2RAze , M3N2RDxe , & - M3N2RDye , M3N2RDze , M3N2TAxe , M3N2TAye , M3N2TAze , M3N2TDxss , M3N2TDyss , & - M3N2TDzss , M3N3FKxe , M3N3FKye , M3N3FKze , M3N3FMxe , M3N3FMye , M3N3FMze , & - M3N3MKxe , M3N3MKye , M3N3MKze , M3N3MMxe , M3N3MMye , M3N3MMze , M3N3RAxe , & - M3N3RAye , M3N3RAze , M3N3RDxe , M3N3RDye , M3N3RDze , M3N3TAxe , M3N3TAye , & - M3N3TAze , M3N3TDxss , M3N3TDyss , M3N3TDzss , M3N4FKxe , M3N4FKye , M3N4FKze , & - M3N4FMxe , M3N4FMye , M3N4FMze , M3N4MKxe , M3N4MKye , M3N4MKze , M3N4MMxe , & - M3N4MMye , M3N4MMze , M3N4RAxe , M3N4RAye , M3N4RAze , M3N4RDxe , M3N4RDye , & - M3N4RDze , M3N4TAxe , M3N4TAye , M3N4TAze , M3N4TDxss , M3N4TDyss , M3N4TDzss , & - M3N5FKxe , M3N5FKye , M3N5FKze , M3N5FMxe , M3N5FMye , M3N5FMze , M3N5MKxe , & - M3N5MKye , M3N5MKze , M3N5MMxe , M3N5MMye , M3N5MMze , M3N5RAxe , M3N5RAye , & - M3N5RAze , M3N5RDxe , M3N5RDye , M3N5RDze , M3N5TAxe , M3N5TAye , M3N5TAze , & - M3N5TDxss , M3N5TDyss , M3N5TDzss , M3N6FKxe , M3N6FKye , M3N6FKze , M3N6FMxe , & - M3N6FMye , M3N6FMze , M3N6MKxe , M3N6MKye , M3N6MKze , M3N6MMxe , M3N6MMye , & - M3N6MMze , M3N6RAxe , M3N6RAye , M3N6RAze , M3N6RDxe , M3N6RDye , M3N6RDze , & - M3N6TAxe , M3N6TAye , M3N6TAze , M3N6TDxss , M3N6TDyss , M3N6TDzss , M3N7FKxe , & - M3N7FKye , M3N7FKze , M3N7FMxe , M3N7FMye , M3N7FMze , M3N7MKxe , M3N7MKye , & - M3N7MKze , M3N7MMxe , M3N7MMye , M3N7MMze , M3N7RAxe , M3N7RAye , M3N7RAze , & - M3N7RDxe , M3N7RDye , M3N7RDze , M3N7TAxe , M3N7TAye , M3N7TAze , M3N7TDxss , & - M3N7TDyss , M3N7TDzss , M3N8FKxe , M3N8FKye , M3N8FKze , M3N8FMxe , M3N8FMye , & - M3N8FMze , M3N8MKxe , M3N8MKye , M3N8MKze , M3N8MMxe , M3N8MMye , M3N8MMze , & - M3N8RAxe , M3N8RAye , M3N8RAze , M3N8RDxe , M3N8RDye , M3N8RDze , M3N8TAxe , & - M3N8TAye , M3N8TAze , M3N8TDxss , M3N8TDyss , M3N8TDzss , M3N9FKxe , M3N9FKye , & - M3N9FKze , M3N9FMxe , M3N9FMye , M3N9FMze , M3N9MKxe , M3N9MKye , M3N9MKze , & - M3N9MMxe , M3N9MMye , M3N9MMze , M3N9RAxe , M3N9RAye , M3N9RAze , M3N9RDxe , & - M3N9RDye , M3N9RDze , M3N9TAxe , M3N9TAye , M3N9TAze , M3N9TDxss , M3N9TDyss , & - M3N9TDzss , M4N1FKxe , M4N1FKye , M4N1FKze , M4N1FMxe , M4N1FMye , M4N1FMze , & - M4N1MKxe , M4N1MKye , M4N1MKze , M4N1MMxe , M4N1MMye , M4N1MMze , M4N1RAxe , & - M4N1RAye , M4N1RAze , M4N1RDxe , M4N1RDye , M4N1RDze , M4N1TAxe , M4N1TAye , & - M4N1TAze , M4N1TDxss , M4N1TDyss , M4N1TDzss , M4N2FKxe , M4N2FKye , M4N2FKze , & - M4N2FMxe , M4N2FMye , M4N2FMze , M4N2MKxe , M4N2MKye , M4N2MKze , M4N2MMxe , & - M4N2MMye , M4N2MMze , M4N2RAxe , M4N2RAye , M4N2RAze , M4N2RDxe , M4N2RDye , & - M4N2RDze , M4N2TAxe , M4N2TAye , M4N2TAze , M4N2TDxss , M4N2TDyss , M4N2TDzss , & - M4N3FKxe , M4N3FKye , M4N3FKze , M4N3FMxe , M4N3FMye , M4N3FMze , M4N3MKxe , & - M4N3MKye , M4N3MKze , M4N3MMxe , M4N3MMye , M4N3MMze , M4N3RAxe , M4N3RAye , & - M4N3RAze , M4N3RDxe , M4N3RDye , M4N3RDze , M4N3TAxe , M4N3TAye , M4N3TAze , & - M4N3TDxss , M4N3TDyss , M4N3TDzss , M4N4FKxe , M4N4FKye , M4N4FKze , M4N4FMxe , & - M4N4FMye , M4N4FMze , M4N4MKxe , M4N4MKye , M4N4MKze , M4N4MMxe , M4N4MMye , & - M4N4MMze , M4N4RAxe , M4N4RAye , M4N4RAze , M4N4RDxe , M4N4RDye , M4N4RDze , & - M4N4TAxe , M4N4TAye , M4N4TAze , M4N4TDxss , M4N4TDyss , M4N4TDzss , M4N5FKxe , & - M4N5FKye , M4N5FKze , M4N5FMxe , M4N5FMye , M4N5FMze , M4N5MKxe , M4N5MKye , & - M4N5MKze , M4N5MMxe , M4N5MMye , M4N5MMze , M4N5RAxe , M4N5RAye , M4N5RAze , & - M4N5RDxe , M4N5RDye , M4N5RDze , M4N5TAxe , M4N5TAye , M4N5TAze , M4N5TDxss , & - M4N5TDyss , M4N5TDzss , M4N6FKxe , M4N6FKye , M4N6FKze , M4N6FMxe , M4N6FMye , & - M4N6FMze , M4N6MKxe , M4N6MKye , M4N6MKze , M4N6MMxe , M4N6MMye , M4N6MMze , & - M4N6RAxe , M4N6RAye , M4N6RAze , M4N6RDxe , M4N6RDye , M4N6RDze , M4N6TAxe , & - M4N6TAye , M4N6TAze , M4N6TDxss , M4N6TDyss , M4N6TDzss , M4N7FKxe , M4N7FKye , & - M4N7FKze , M4N7FMxe , M4N7FMye , M4N7FMze , M4N7MKxe , M4N7MKye , M4N7MKze , & - M4N7MMxe , M4N7MMye , M4N7MMze , M4N7RAxe , M4N7RAye , M4N7RAze , M4N7RDxe , & - M4N7RDye , M4N7RDze , M4N7TAxe , M4N7TAye , M4N7TAze , M4N7TDxss , M4N7TDyss , & - M4N7TDzss , M4N8FKxe , M4N8FKye , M4N8FKze , M4N8FMxe , M4N8FMye , M4N8FMze , & - M4N8MKxe , M4N8MKye , M4N8MKze , M4N8MMxe , M4N8MMye , M4N8MMze , M4N8RAxe , & - M4N8RAye , M4N8RAze , M4N8RDxe , M4N8RDye , M4N8RDze , M4N8TAxe , M4N8TAye , & - M4N8TAze , M4N8TDxss , M4N8TDyss , M4N8TDzss , M4N9FKxe , M4N9FKye , M4N9FKze , & - M4N9FMxe , M4N9FMye , M4N9FMze , M4N9MKxe , M4N9MKye , M4N9MKze , M4N9MMxe , & - M4N9MMye , M4N9MMze , M4N9RAxe , M4N9RAye , M4N9RAze , M4N9RDxe , M4N9RDye , & - M4N9RDze , M4N9TAxe , M4N9TAye , M4N9TAze , M4N9TDxss , M4N9TDyss , M4N9TDzss , & - M5N1FKxe , M5N1FKye , M5N1FKze , M5N1FMxe , M5N1FMye , M5N1FMze , M5N1MKxe , & - M5N1MKye , M5N1MKze , M5N1MMxe , M5N1MMye , M5N1MMze , M5N1RAxe , M5N1RAye , & - M5N1RAze , M5N1RDxe , M5N1RDye , M5N1RDze , M5N1TAxe , M5N1TAye , M5N1TAze , & - M5N1TDxss , M5N1TDyss , M5N1TDzss , M5N2FKxe , M5N2FKye , M5N2FKze , M5N2FMxe , & - M5N2FMye , M5N2FMze , M5N2MKxe , M5N2MKye , M5N2MKze , M5N2MMxe , M5N2MMye , & - M5N2MMze , M5N2RAxe , M5N2RAye , M5N2RAze , M5N2RDxe , M5N2RDye , M5N2RDze , & - M5N2TAxe , M5N2TAye , M5N2TAze , M5N2TDxss , M5N2TDyss , M5N2TDzss , M5N3FKxe , & - M5N3FKye , M5N3FKze , M5N3FMxe , M5N3FMye , M5N3FMze , M5N3MKxe , M5N3MKye , & - M5N3MKze , M5N3MMxe , M5N3MMye , M5N3MMze , M5N3RAxe , M5N3RAye , M5N3RAze , & - M5N3RDxe , M5N3RDye , M5N3RDze , M5N3TAxe , M5N3TAye , M5N3TAze , M5N3TDxss , & - M5N3TDyss , M5N3TDzss , M5N4FKxe , M5N4FKye , M5N4FKze , M5N4FMxe , M5N4FMye , & - M5N4FMze , M5N4MKxe , M5N4MKye , M5N4MKze , M5N4MMxe , M5N4MMye , M5N4MMze , & - M5N4RAxe , M5N4RAye , M5N4RAze , M5N4RDxe , M5N4RDye , M5N4RDze , M5N4TAxe , & - M5N4TAye , M5N4TAze , M5N4TDxss , M5N4TDyss , M5N4TDzss , M5N5FKxe , M5N5FKye , & - M5N5FKze , M5N5FMxe , M5N5FMye , M5N5FMze , M5N5MKxe , M5N5MKye , M5N5MKze , & - M5N5MMxe , M5N5MMye , M5N5MMze , M5N5RAxe , M5N5RAye , M5N5RAze , M5N5RDxe , & - M5N5RDye , M5N5RDze , M5N5TAxe , M5N5TAye , M5N5TAze , M5N5TDxss , M5N5TDyss , & - M5N5TDzss , M5N6FKxe , M5N6FKye , M5N6FKze , M5N6FMxe , M5N6FMye , M5N6FMze , & - M5N6MKxe , M5N6MKye , M5N6MKze , M5N6MMxe , M5N6MMye , M5N6MMze , M5N6RAxe , & - M5N6RAye , M5N6RAze , M5N6RDxe , M5N6RDye , M5N6RDze , M5N6TAxe , M5N6TAye , & - M5N6TAze , M5N6TDxss , M5N6TDyss , M5N6TDzss , M5N7FKxe , M5N7FKye , M5N7FKze , & - M5N7FMxe , M5N7FMye , M5N7FMze , M5N7MKxe , M5N7MKye , M5N7MKze , M5N7MMxe , & - M5N7MMye , M5N7MMze , M5N7RAxe , M5N7RAye , M5N7RAze , M5N7RDxe , M5N7RDye , & - M5N7RDze , M5N7TAxe , M5N7TAye , M5N7TAze , M5N7TDxss , M5N7TDyss , M5N7TDzss , & - M5N8FKxe , M5N8FKye , M5N8FKze , M5N8FMxe , M5N8FMye , M5N8FMze , M5N8MKxe , & - M5N8MKye , M5N8MKze , M5N8MMxe , M5N8MMye , M5N8MMze , M5N8RAxe , M5N8RAye , & - M5N8RAze , M5N8RDxe , M5N8RDye , M5N8RDze , M5N8TAxe , M5N8TAye , M5N8TAze , & - M5N8TDxss , M5N8TDyss , M5N8TDzss , M5N9FKxe , M5N9FKye , M5N9FKze , M5N9FMxe , & - M5N9FMye , M5N9FMze , M5N9MKxe , M5N9MKye , M5N9MKze , M5N9MMxe , M5N9MMye , & - M5N9MMze , M5N9RAxe , M5N9RAye , M5N9RAze , M5N9RDxe , M5N9RDye , M5N9RDze , & - M5N9TAxe , M5N9TAye , M5N9TAze , M5N9TDxss , M5N9TDyss , M5N9TDzss , M6N1FKxe , & - M6N1FKye , M6N1FKze , M6N1FMxe , M6N1FMye , M6N1FMze , M6N1MKxe , M6N1MKye , & - M6N1MKze , M6N1MMxe , M6N1MMye , M6N1MMze , M6N1RAxe , M6N1RAye , M6N1RAze , & - M6N1RDxe , M6N1RDye , M6N1RDze , M6N1TAxe , M6N1TAye , M6N1TAze , M6N1TDxss , & - M6N1TDyss , M6N1TDzss , M6N2FKxe , M6N2FKye , M6N2FKze , M6N2FMxe , M6N2FMye , & - M6N2FMze , M6N2MKxe , M6N2MKye , M6N2MKze , M6N2MMxe , M6N2MMye , M6N2MMze , & - M6N2RAxe , M6N2RAye , M6N2RAze , M6N2RDxe , M6N2RDye , M6N2RDze , M6N2TAxe , & - M6N2TAye , M6N2TAze , M6N2TDxss , M6N2TDyss , M6N2TDzss , M6N3FKxe , M6N3FKye , & - M6N3FKze , M6N3FMxe , M6N3FMye , M6N3FMze , M6N3MKxe , M6N3MKye , M6N3MKze , & - M6N3MMxe , M6N3MMye , M6N3MMze , M6N3RAxe , M6N3RAye , M6N3RAze , M6N3RDxe , & - M6N3RDye , M6N3RDze , M6N3TAxe , M6N3TAye , M6N3TAze , M6N3TDxss , M6N3TDyss , & - M6N3TDzss , M6N4FKxe , M6N4FKye , M6N4FKze , M6N4FMxe , M6N4FMye , M6N4FMze , & - M6N4MKxe , M6N4MKye , M6N4MKze , M6N4MMxe , M6N4MMye , M6N4MMze , M6N4RAxe , & - M6N4RAye , M6N4RAze , M6N4RDxe , M6N4RDye , M6N4RDze , M6N4TAxe , M6N4TAye , & - M6N4TAze , M6N4TDxss , M6N4TDyss , M6N4TDzss , M6N5FKxe , M6N5FKye , M6N5FKze , & - M6N5FMxe , M6N5FMye , M6N5FMze , M6N5MKxe , M6N5MKye , M6N5MKze , M6N5MMxe , & - M6N5MMye , M6N5MMze , M6N5RAxe , M6N5RAye , M6N5RAze , M6N5RDxe , M6N5RDye , & - M6N5RDze , M6N5TAxe , M6N5TAye , M6N5TAze , M6N5TDxss , M6N5TDyss , M6N5TDzss , & - M6N6FKxe , M6N6FKye , M6N6FKze , M6N6FMxe , M6N6FMye , M6N6FMze , M6N6MKxe , & - M6N6MKye , M6N6MKze , M6N6MMxe , M6N6MMye , M6N6MMze , M6N6RAxe , M6N6RAye , & - M6N6RAze , M6N6RDxe , M6N6RDye , M6N6RDze , M6N6TAxe , M6N6TAye , M6N6TAze , & - M6N6TDxss , M6N6TDyss , M6N6TDzss , M6N7FKxe , M6N7FKye , M6N7FKze , M6N7FMxe , & - M6N7FMye , M6N7FMze , M6N7MKxe , M6N7MKye , M6N7MKze , M6N7MMxe , M6N7MMye , & - M6N7MMze , M6N7RAxe , M6N7RAye , M6N7RAze , M6N7RDxe , M6N7RDye , M6N7RDze , & - M6N7TAxe , M6N7TAye , M6N7TAze , M6N7TDxss , M6N7TDyss , M6N7TDzss , M6N8FKxe , & - M6N8FKye , M6N8FKze , M6N8FMxe , M6N8FMye , M6N8FMze , M6N8MKxe , M6N8MKye , & - M6N8MKze , M6N8MMxe , M6N8MMye , M6N8MMze , M6N8RAxe , M6N8RAye , M6N8RAze , & - M6N8RDxe , M6N8RDye , M6N8RDze , M6N8TAxe , M6N8TAye , M6N8TAze , M6N8TDxss , & - M6N8TDyss , M6N8TDzss , M6N9FKxe , M6N9FKye , M6N9FKze , M6N9FMxe , M6N9FMye , & - M6N9FMze , M6N9MKxe , M6N9MKye , M6N9MKze , M6N9MMxe , M6N9MMye , M6N9MMze , & - M6N9RAxe , M6N9RAye , M6N9RAze , M6N9RDxe , M6N9RDye , M6N9RDze , M6N9TAxe , & - M6N9TAye , M6N9TAze , M6N9TDxss , M6N9TDyss , M6N9TDzss , M7N1FKxe , M7N1FKye , & - M7N1FKze , M7N1FMxe , M7N1FMye , M7N1FMze , M7N1MKxe , M7N1MKye , M7N1MKze , & - M7N1MMxe , M7N1MMye , M7N1MMze , M7N1RAxe , M7N1RAye , M7N1RAze , M7N1RDxe , & - M7N1RDye , M7N1RDze , M7N1TAxe , M7N1TAye , M7N1TAze , M7N1TDxss , M7N1TDyss , & - M7N1TDzss , M7N2FKxe , M7N2FKye , M7N2FKze , M7N2FMxe , M7N2FMye , M7N2FMze , & - M7N2MKxe , M7N2MKye , M7N2MKze , M7N2MMxe , M7N2MMye , M7N2MMze , M7N2RAxe , & - M7N2RAye , M7N2RAze , M7N2RDxe , M7N2RDye , M7N2RDze , M7N2TAxe , M7N2TAye , & - M7N2TAze , M7N2TDxss , M7N2TDyss , M7N2TDzss , M7N3FKxe , M7N3FKye , M7N3FKze , & - M7N3FMxe , M7N3FMye , M7N3FMze , M7N3MKxe , M7N3MKye , M7N3MKze , M7N3MMxe , & - M7N3MMye , M7N3MMze , M7N3RAxe , M7N3RAye , M7N3RAze , M7N3RDxe , M7N3RDye , & - M7N3RDze , M7N3TAxe , M7N3TAye , M7N3TAze , M7N3TDxss , M7N3TDyss , M7N3TDzss , & - M7N4FKxe , M7N4FKye , M7N4FKze , M7N4FMxe , M7N4FMye , M7N4FMze , M7N4MKxe , & - M7N4MKye , M7N4MKze , M7N4MMxe , M7N4MMye , M7N4MMze , M7N4RAxe , M7N4RAye , & - M7N4RAze , M7N4RDxe , M7N4RDye , M7N4RDze , M7N4TAxe , M7N4TAye , M7N4TAze , & - M7N4TDxss , M7N4TDyss , M7N4TDzss , M7N5FKxe , M7N5FKye , M7N5FKze , M7N5FMxe , & - M7N5FMye , M7N5FMze , M7N5MKxe , M7N5MKye , M7N5MKze , M7N5MMxe , M7N5MMye , & - M7N5MMze , M7N5RAxe , M7N5RAye , M7N5RAze , M7N5RDxe , M7N5RDye , M7N5RDze , & - M7N5TAxe , M7N5TAye , M7N5TAze , M7N5TDxss , M7N5TDyss , M7N5TDzss , M7N6FKxe , & - M7N6FKye , M7N6FKze , M7N6FMxe , M7N6FMye , M7N6FMze , M7N6MKxe , M7N6MKye , & - M7N6MKze , M7N6MMxe , M7N6MMye , M7N6MMze , M7N6RAxe , M7N6RAye , M7N6RAze , & - M7N6RDxe , M7N6RDye , M7N6RDze , M7N6TAxe , M7N6TAye , M7N6TAze , M7N6TDxss , & - M7N6TDyss , M7N6TDzss , M7N7FKxe , M7N7FKye , M7N7FKze , M7N7FMxe , M7N7FMye , & - M7N7FMze , M7N7MKxe , M7N7MKye , M7N7MKze , M7N7MMxe , M7N7MMye , M7N7MMze , & - M7N7RAxe , M7N7RAye , M7N7RAze , M7N7RDxe , M7N7RDye , M7N7RDze , M7N7TAxe , & - M7N7TAye , M7N7TAze , M7N7TDxss , M7N7TDyss , M7N7TDzss , M7N8FKxe , M7N8FKye , & - M7N8FKze , M7N8FMxe , M7N8FMye , M7N8FMze , M7N8MKxe , M7N8MKye , M7N8MKze , & - M7N8MMxe , M7N8MMye , M7N8MMze , M7N8RAxe , M7N8RAye , M7N8RAze , M7N8RDxe , & - M7N8RDye , M7N8RDze , M7N8TAxe , M7N8TAye , M7N8TAze , M7N8TDxss , M7N8TDyss , & - M7N8TDzss , M7N9FKxe , M7N9FKye , M7N9FKze , M7N9FMxe , M7N9FMye , M7N9FMze , & - M7N9MKxe , M7N9MKye , M7N9MKze , M7N9MMxe , M7N9MMye , M7N9MMze , M7N9RAxe , & - M7N9RAye , M7N9RAze , M7N9RDxe , M7N9RDye , M7N9RDze , M7N9TAxe , M7N9TAye , & - M7N9TAze , M7N9TDxss , M7N9TDyss , M7N9TDzss , M8N1FKxe , M8N1FKye , M8N1FKze , & - M8N1FMxe , M8N1FMye , M8N1FMze , M8N1MKxe , M8N1MKye , M8N1MKze , M8N1MMxe , & - M8N1MMye , M8N1MMze , M8N1RAxe , M8N1RAye , M8N1RAze , M8N1RDxe , M8N1RDye , & - M8N1RDze , M8N1TAxe , M8N1TAye , M8N1TAze , M8N1TDxss , M8N1TDyss , M8N1TDzss , & - M8N2FKxe , M8N2FKye , M8N2FKze , M8N2FMxe , M8N2FMye , M8N2FMze , M8N2MKxe , & - M8N2MKye , M8N2MKze , M8N2MMxe , M8N2MMye , M8N2MMze , M8N2RAxe , M8N2RAye , & - M8N2RAze , M8N2RDxe , M8N2RDye , M8N2RDze , M8N2TAxe , M8N2TAye , M8N2TAze , & - M8N2TDxss , M8N2TDyss , M8N2TDzss , M8N3FKxe , M8N3FKye , M8N3FKze , M8N3FMxe , & - M8N3FMye , M8N3FMze , M8N3MKxe , M8N3MKye , M8N3MKze , M8N3MMxe , M8N3MMye , & - M8N3MMze , M8N3RAxe , M8N3RAye , M8N3RAze , M8N3RDxe , M8N3RDye , M8N3RDze , & - M8N3TAxe , M8N3TAye , M8N3TAze , M8N3TDxss , M8N3TDyss , M8N3TDzss , M8N4FKxe , & - M8N4FKye , M8N4FKze , M8N4FMxe , M8N4FMye , M8N4FMze , M8N4MKxe , M8N4MKye , & - M8N4MKze , M8N4MMxe , M8N4MMye , M8N4MMze , M8N4RAxe , M8N4RAye , M8N4RAze , & - M8N4RDxe , M8N4RDye , M8N4RDze , M8N4TAxe , M8N4TAye , M8N4TAze , M8N4TDxss , & - M8N4TDyss , M8N4TDzss , M8N5FKxe , M8N5FKye , M8N5FKze , M8N5FMxe , M8N5FMye , & - M8N5FMze , M8N5MKxe , M8N5MKye , M8N5MKze , M8N5MMxe , M8N5MMye , M8N5MMze , & - M8N5RAxe , M8N5RAye , M8N5RAze , M8N5RDxe , M8N5RDye , M8N5RDze , M8N5TAxe , & - M8N5TAye , M8N5TAze , M8N5TDxss , M8N5TDyss , M8N5TDzss , M8N6FKxe , M8N6FKye , & - M8N6FKze , M8N6FMxe , M8N6FMye , M8N6FMze , M8N6MKxe , M8N6MKye , M8N6MKze , & - M8N6MMxe , M8N6MMye , M8N6MMze , M8N6RAxe , M8N6RAye , M8N6RAze , M8N6RDxe , & - M8N6RDye , M8N6RDze , M8N6TAxe , M8N6TAye , M8N6TAze , M8N6TDxss , M8N6TDyss , & - M8N6TDzss , M8N7FKxe , M8N7FKye , M8N7FKze , M8N7FMxe , M8N7FMye , M8N7FMze , & - M8N7MKxe , M8N7MKye , M8N7MKze , M8N7MMxe , M8N7MMye , M8N7MMze , M8N7RAxe , & - M8N7RAye , M8N7RAze , M8N7RDxe , M8N7RDye , M8N7RDze , M8N7TAxe , M8N7TAye , & - M8N7TAze , M8N7TDxss , M8N7TDyss , M8N7TDzss , M8N8FKxe , M8N8FKye , M8N8FKze , & - M8N8FMxe , M8N8FMye , M8N8FMze , M8N8MKxe , M8N8MKye , M8N8MKze , M8N8MMxe , & - M8N8MMye , M8N8MMze , M8N8RAxe , M8N8RAye , M8N8RAze , M8N8RDxe , M8N8RDye , & - M8N8RDze , M8N8TAxe , M8N8TAye , M8N8TAze , M8N8TDxss , M8N8TDyss , M8N8TDzss , & - M8N9FKxe , M8N9FKye , M8N9FKze , M8N9FMxe , M8N9FMye , M8N9FMze , M8N9MKxe , & - M8N9MKye , M8N9MKze , M8N9MMxe , M8N9MMye , M8N9MMze , M8N9RAxe , M8N9RAye , & - M8N9RAze , M8N9RDxe , M8N9RDye , M8N9RDze , M8N9TAxe , M8N9TAye , M8N9TAze , & - M8N9TDxss , M8N9TDyss , M8N9TDzss , M9N1FKxe , M9N1FKye , M9N1FKze , M9N1FMxe , & - M9N1FMye , M9N1FMze , M9N1MKxe , M9N1MKye , M9N1MKze , M9N1MMxe , M9N1MMye , & - M9N1MMze , M9N1RAxe , M9N1RAye , M9N1RAze , M9N1RDxe , M9N1RDye , M9N1RDze , & - M9N1TAxe , M9N1TAye , M9N1TAze , M9N1TDxss , M9N1TDyss , M9N1TDzss , M9N2FKxe , & - M9N2FKye , M9N2FKze , M9N2FMxe , M9N2FMye , M9N2FMze , M9N2MKxe , M9N2MKye , & - M9N2MKze , M9N2MMxe , M9N2MMye , M9N2MMze , M9N2RAxe , M9N2RAye , M9N2RAze , & - M9N2RDxe , M9N2RDye , M9N2RDze , M9N2TAxe , M9N2TAye , M9N2TAze , M9N2TDxss , & - M9N2TDyss , M9N2TDzss , M9N3FKxe , M9N3FKye , M9N3FKze , M9N3FMxe , M9N3FMye , & - M9N3FMze , M9N3MKxe , M9N3MKye , M9N3MKze , M9N3MMxe , M9N3MMye , M9N3MMze , & - M9N3RAxe , M9N3RAye , M9N3RAze , M9N3RDxe , M9N3RDye , M9N3RDze , M9N3TAxe , & - M9N3TAye , M9N3TAze , M9N3TDxss , M9N3TDyss , M9N3TDzss , M9N4FKxe , M9N4FKye , & - M9N4FKze , M9N4FMxe , M9N4FMye , M9N4FMze , M9N4MKxe , M9N4MKye , M9N4MKze , & - M9N4MMxe , M9N4MMye , M9N4MMze , M9N4RAxe , M9N4RAye , M9N4RAze , M9N4RDxe , & - M9N4RDye , M9N4RDze , M9N4TAxe , M9N4TAye , M9N4TAze , M9N4TDxss , M9N4TDyss , & - M9N4TDzss , M9N5FKxe , M9N5FKye , M9N5FKze , M9N5FMxe , M9N5FMye , M9N5FMze , & - M9N5MKxe , M9N5MKye , M9N5MKze , M9N5MMxe , M9N5MMye , M9N5MMze , M9N5RAxe , & - M9N5RAye , M9N5RAze , M9N5RDxe , M9N5RDye , M9N5RDze , M9N5TAxe , M9N5TAye , & - M9N5TAze , M9N5TDxss , M9N5TDyss , M9N5TDzss , M9N6FKxe , M9N6FKye , M9N6FKze , & - M9N6FMxe , M9N6FMye , M9N6FMze , M9N6MKxe , M9N6MKye , M9N6MKze , M9N6MMxe , & - M9N6MMye , M9N6MMze , M9N6RAxe , M9N6RAye , M9N6RAze , M9N6RDxe , M9N6RDye , & - M9N6RDze , M9N6TAxe , M9N6TAye , M9N6TAze , M9N6TDxss , M9N6TDyss , M9N6TDzss , & - M9N7FKxe , M9N7FKye , M9N7FKze , M9N7FMxe , M9N7FMye , M9N7FMze , M9N7MKxe , & - M9N7MKye , M9N7MKze , M9N7MMxe , M9N7MMye , M9N7MMze , M9N7RAxe , M9N7RAye , & - M9N7RAze , M9N7RDxe , M9N7RDye , M9N7RDze , M9N7TAxe , M9N7TAye , M9N7TAze , & - M9N7TDxss , M9N7TDyss , M9N7TDzss , M9N8FKxe , M9N8FKye , M9N8FKze , M9N8FMxe , & - M9N8FMye , M9N8FMze , M9N8MKxe , M9N8MKye , M9N8MKze , M9N8MMxe , M9N8MMye , & - M9N8MMze , M9N8RAxe , M9N8RAye , M9N8RAze , M9N8RDxe , M9N8RDye , M9N8RDze , & - M9N8TAxe , M9N8TAye , M9N8TAze , M9N8TDxss , M9N8TDyss , M9N8TDzss , M9N9FKxe , & - M9N9FKye , M9N9FKze , M9N9FMxe , M9N9FMye , M9N9FMze , M9N9MKxe , M9N9MKye , & - M9N9MKze , M9N9MMxe , M9N9MMye , M9N9MMze , M9N9RAxe , M9N9RAye , M9N9RAze , & - M9N9RDxe , M9N9RDye , M9N9RDze , M9N9TAxe , M9N9TAye , M9N9TAze , M9N9TDxss , & - M9N9TDyss , M9N9TDzss , ReactFXss , ReactFYss , ReactFZss , ReactMXss , ReactMYss , & - ReactMZss , SSqm01 , SSqm02 , SSqm03 , SSqm04 , SSqm05 , SSqm06 , & - SSqm07 , SSqm08 , SSqm09 , SSqm10 , SSqm11 , SSqm12 , SSqm13 , & - SSqm14 , SSqm15 , SSqm16 , SSqm17 , SSqm18 , SSqm19 , SSqm20 , & - SSqm21 , SSqm22 , SSqm23 , SSqm24 , SSqm25 , SSqm26 , SSqm27 , & - SSqm28 , SSqm29 , SSqm30 , SSqm31 , SSqm32 , SSqm33 , SSqm34 , & - SSqm35 , SSqm36 , SSqm37 , SSqm38 , SSqm39 , SSqm40 , SSqm41 , & - SSqm42 , SSqm43 , SSqm44 , SSqm45 , SSqm46 , SSqm47 , SSqm48 , & - SSqm49 , SSqm50 , SSqm51 , SSqm52 , SSqm53 , SSqm54 , SSqm55 , & - SSqm56 , SSqm57 , SSqm58 , SSqm59 , SSqm60 , SSqm61 , SSqm62 , & - SSqm63 , SSqm64 , SSqm65 , SSqm66 , SSqm67 , SSqm68 , SSqm69 , & - SSqm70 , SSqm71 , SSqm72 , SSqm73 , SSqm74 , SSqm75 , SSqm76 , & - SSqm77 , SSqm78 , SSqm79 , SSqm80 , SSqm81 , SSqm82 , SSqm83 , & - SSqm84 , SSqm85 , SSqm86 , SSqm87 , SSqm88 , SSqm89 , SSqm90 , & - SSqm91 , SSqm92 , SSqm93 , SSqm94 , SSqm95 , SSqm96 , SSqm97 , & - SSqm98 , SSqm99 , SSqmd01 , SSqmd02 , SSqmd03 , SSqmd04 , SSqmd05 , & - SSqmd06 , SSqmd07 , SSqmd08 , SSqmd09 , SSqmd10 , SSqmd11 , SSqmd12 , & - SSqmd13 , SSqmd14 , SSqmd15 , SSqmd16 , SSqmd17 , SSqmd18 , SSqmd19 , & - SSqmd20 , SSqmd21 , SSqmd22 , SSqmd23 , SSqmd24 , SSqmd25 , SSqmd26 , & - SSqmd27 , SSqmd28 , SSqmd29 , SSqmd30 , SSqmd31 , SSqmd32 , SSqmd33 , & - SSqmd34 , SSqmd35 , SSqmd36 , SSqmd37 , SSqmd38 , SSqmd39 , SSqmd40 , & - SSqmd41 , SSqmd42 , SSqmd43 , SSqmd44 , SSqmd45 , SSqmd46 , SSqmd47 , & - SSqmd48 , SSqmd49 , SSqmd50 , SSqmd51 , SSqmd52 , SSqmd53 , SSqmd54 , & - SSqmd55 , SSqmd56 , SSqmd57 , SSqmd58 , SSqmd59 , SSqmd60 , SSqmd61 , & - SSqmd62 , SSqmd63 , SSqmd64 , SSqmd65 , SSqmd66 , SSqmd67 , SSqmd68 , & - SSqmd69 , SSqmd70 , SSqmd71 , SSqmd72 , SSqmd73 , SSqmd74 , SSqmd75 , & - SSqmd76 , SSqmd77 , SSqmd78 , SSqmd79 , SSqmd80 , SSqmd81 , SSqmd82 , & - SSqmd83 , SSqmd84 , SSqmd85 , SSqmd86 , SSqmd87 , SSqmd88 , SSqmd89 , & - SSqmd90 , SSqmd91 , SSqmd92 , SSqmd93 , SSqmd94 , SSqmd95 , SSqmd96 , & - SSqmd97 , SSqmd98 , SSqmd99 , SSqmdd01 , SSqmdd02 , SSqmdd03 , SSqmdd04 , & - SSqmdd05 , SSqmdd06 , SSqmdd07 , SSqmdd08 , SSqmdd09 , SSqmdd10 , SSqmdd11 , & - SSqmdd12 , SSqmdd13 , SSqmdd14 , SSqmdd15 , SSqmdd16 , SSqmdd17 , SSqmdd18 , & - SSqmdd19 , SSqmdd20 , SSqmdd21 , SSqmdd22 , SSqmdd23 , SSqmdd24 , SSqmdd25 , & - SSqmdd26 , SSqmdd27 , SSqmdd28 , SSqmdd29 , SSqmdd30 , SSqmdd31 , SSqmdd32 , & - SSqmdd33 , SSqmdd34 , SSqmdd35 , SSqmdd36 , SSqmdd37 , SSqmdd38 , SSqmdd39 , & - SSqmdd40 , SSqmdd41 , SSqmdd42 , SSqmdd43 , SSqmdd44 , SSqmdd45 , SSqmdd46 , & - SSqmdd47 , SSqmdd48 , SSqmdd49 , SSqmdd50 , SSqmdd51 , SSqmdd52 , SSqmdd53 , & - SSqmdd54 , SSqmdd55 , SSqmdd56 , SSqmdd57 , SSqmdd58 , SSqmdd59 , SSqmdd60 , & - SSqmdd61 , SSqmdd62 , SSqmdd63 , SSqmdd64 , SSqmdd65 , SSqmdd66 , SSqmdd67 , & - SSqmdd68 , SSqmdd69 , SSqmdd70 , SSqmdd71 , SSqmdd72 , SSqmdd73 , SSqmdd74 , & - SSqmdd75 , SSqmdd76 , SSqmdd77 , SSqmdd78 , SSqmdd79 , SSqmdd80 , SSqmdd81 , & - SSqmdd82 , SSqmdd83 , SSqmdd84 , SSqmdd85 , SSqmdd86 , SSqmdd87 , SSqmdd88 , & - SSqmdd89 , SSqmdd90 , SSqmdd91 , SSqmdd92 , SSqmdd93 , SSqmdd94 , SSqmdd95 , & - SSqmdd96 , SSqmdd97 , SSqmdd98 , SSqmdd99 /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(2265) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(Nm) ","(Nm) ", & - "(Nm) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) "/) - - -!End of code generated by Matlab script - - - ! ..... Public Subroutines ................................................................................................... PUBLIC :: SDOut_CloseSum PUBLIC :: SDOut_OpenSum @@ -3847,12 +125,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF ( ErrStat /=0) RETURN DO I=1,p%NMOutputs - ALLOCATE( p%MOutLst(I)%NodeIDs(p%MoutLst(I)%NoutCnt), STAT = ErrStat ) - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%NodeIDs arrays in SDOut_Init' - RETURN - END IF + CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MoutLst(I)%NoutCnt, 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2) ; if(Failed()) return p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MoutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting ALLOCATE( p%MOutLst(I)%ElmIDs(p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !ElmIDs has for each selected node within the member, several element numbers to refer to for averaging (max 2 elements) @@ -4163,7 +436,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SDOut_Init') Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() +! if (Failed) call CleanUp() END FUNCTION Failed END SUBROUTINE SDOut_Init diff --git a/modules/subdyn/src/SubDyn_Output_Params.f90 b/modules/subdyn/src/SubDyn_Output_Params.f90 new file mode 100644 index 000000000..4844a51f1 --- /dev/null +++ b/modules/subdyn/src/SubDyn_Output_Params.f90 @@ -0,0 +1,3723 @@ +module SubDyn_Output_Params + use NWTC_Library + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + IMPLICIT NONE + + PUBLIC + + ! Time: + INTEGER, PARAMETER :: Time = 0 + + ! Member Forces: + + INTEGER(IntKi), PARAMETER :: M1N1FKxe = 1 + INTEGER(IntKi), PARAMETER :: M1N2FKxe = 2 + INTEGER(IntKi), PARAMETER :: M1N3FKxe = 3 + INTEGER(IntKi), PARAMETER :: M1N4FKxe = 4 + INTEGER(IntKi), PARAMETER :: M1N5FKxe = 5 + INTEGER(IntKi), PARAMETER :: M1N6FKxe = 6 + INTEGER(IntKi), PARAMETER :: M1N7FKxe = 7 + INTEGER(IntKi), PARAMETER :: M1N8FKxe = 8 + INTEGER(IntKi), PARAMETER :: M1N9FKxe = 9 + INTEGER(IntKi), PARAMETER :: M2N1FKxe = 10 + INTEGER(IntKi), PARAMETER :: M2N2FKxe = 11 + INTEGER(IntKi), PARAMETER :: M2N3FKxe = 12 + INTEGER(IntKi), PARAMETER :: M2N4FKxe = 13 + INTEGER(IntKi), PARAMETER :: M2N5FKxe = 14 + INTEGER(IntKi), PARAMETER :: M2N6FKxe = 15 + INTEGER(IntKi), PARAMETER :: M2N7FKxe = 16 + INTEGER(IntKi), PARAMETER :: M2N8FKxe = 17 + INTEGER(IntKi), PARAMETER :: M2N9FKxe = 18 + INTEGER(IntKi), PARAMETER :: M3N1FKxe = 19 + INTEGER(IntKi), PARAMETER :: M3N2FKxe = 20 + INTEGER(IntKi), PARAMETER :: M3N3FKxe = 21 + INTEGER(IntKi), PARAMETER :: M3N4FKxe = 22 + INTEGER(IntKi), PARAMETER :: M3N5FKxe = 23 + INTEGER(IntKi), PARAMETER :: M3N6FKxe = 24 + INTEGER(IntKi), PARAMETER :: M3N7FKxe = 25 + INTEGER(IntKi), PARAMETER :: M3N8FKxe = 26 + INTEGER(IntKi), PARAMETER :: M3N9FKxe = 27 + INTEGER(IntKi), PARAMETER :: M4N1FKxe = 28 + INTEGER(IntKi), PARAMETER :: M4N2FKxe = 29 + INTEGER(IntKi), PARAMETER :: M4N3FKxe = 30 + INTEGER(IntKi), PARAMETER :: M4N4FKxe = 31 + INTEGER(IntKi), PARAMETER :: M4N5FKxe = 32 + INTEGER(IntKi), PARAMETER :: M4N6FKxe = 33 + INTEGER(IntKi), PARAMETER :: M4N7FKxe = 34 + INTEGER(IntKi), PARAMETER :: M4N8FKxe = 35 + INTEGER(IntKi), PARAMETER :: M4N9FKxe = 36 + INTEGER(IntKi), PARAMETER :: M5N1FKxe = 37 + INTEGER(IntKi), PARAMETER :: M5N2FKxe = 38 + INTEGER(IntKi), PARAMETER :: M5N3FKxe = 39 + INTEGER(IntKi), PARAMETER :: M5N4FKxe = 40 + INTEGER(IntKi), PARAMETER :: M5N5FKxe = 41 + INTEGER(IntKi), PARAMETER :: M5N6FKxe = 42 + INTEGER(IntKi), PARAMETER :: M5N7FKxe = 43 + INTEGER(IntKi), PARAMETER :: M5N8FKxe = 44 + INTEGER(IntKi), PARAMETER :: M5N9FKxe = 45 + INTEGER(IntKi), PARAMETER :: M6N1FKxe = 46 + INTEGER(IntKi), PARAMETER :: M6N2FKxe = 47 + INTEGER(IntKi), PARAMETER :: M6N3FKxe = 48 + INTEGER(IntKi), PARAMETER :: M6N4FKxe = 49 + INTEGER(IntKi), PARAMETER :: M6N5FKxe = 50 + INTEGER(IntKi), PARAMETER :: M6N6FKxe = 51 + INTEGER(IntKi), PARAMETER :: M6N7FKxe = 52 + INTEGER(IntKi), PARAMETER :: M6N8FKxe = 53 + INTEGER(IntKi), PARAMETER :: M6N9FKxe = 54 + INTEGER(IntKi), PARAMETER :: M7N1FKxe = 55 + INTEGER(IntKi), PARAMETER :: M7N2FKxe = 56 + INTEGER(IntKi), PARAMETER :: M7N3FKxe = 57 + INTEGER(IntKi), PARAMETER :: M7N4FKxe = 58 + INTEGER(IntKi), PARAMETER :: M7N5FKxe = 59 + INTEGER(IntKi), PARAMETER :: M7N6FKxe = 60 + INTEGER(IntKi), PARAMETER :: M7N7FKxe = 61 + INTEGER(IntKi), PARAMETER :: M7N8FKxe = 62 + INTEGER(IntKi), PARAMETER :: M7N9FKxe = 63 + INTEGER(IntKi), PARAMETER :: M8N1FKxe = 64 + INTEGER(IntKi), PARAMETER :: M8N2FKxe = 65 + INTEGER(IntKi), PARAMETER :: M8N3FKxe = 66 + INTEGER(IntKi), PARAMETER :: M8N4FKxe = 67 + INTEGER(IntKi), PARAMETER :: M8N5FKxe = 68 + INTEGER(IntKi), PARAMETER :: M8N6FKxe = 69 + INTEGER(IntKi), PARAMETER :: M8N7FKxe = 70 + INTEGER(IntKi), PARAMETER :: M8N8FKxe = 71 + INTEGER(IntKi), PARAMETER :: M8N9FKxe = 72 + INTEGER(IntKi), PARAMETER :: M9N1FKxe = 73 + INTEGER(IntKi), PARAMETER :: M9N2FKxe = 74 + INTEGER(IntKi), PARAMETER :: M9N3FKxe = 75 + INTEGER(IntKi), PARAMETER :: M9N4FKxe = 76 + INTEGER(IntKi), PARAMETER :: M9N5FKxe = 77 + INTEGER(IntKi), PARAMETER :: M9N6FKxe = 78 + INTEGER(IntKi), PARAMETER :: M9N7FKxe = 79 + INTEGER(IntKi), PARAMETER :: M9N8FKxe = 80 + INTEGER(IntKi), PARAMETER :: M9N9FKxe = 81 + INTEGER(IntKi), PARAMETER :: M1N1FKye = 82 + INTEGER(IntKi), PARAMETER :: M1N2FKye = 83 + INTEGER(IntKi), PARAMETER :: M1N3FKye = 84 + INTEGER(IntKi), PARAMETER :: M1N4FKye = 85 + INTEGER(IntKi), PARAMETER :: M1N5FKye = 86 + INTEGER(IntKi), PARAMETER :: M1N6FKye = 87 + INTEGER(IntKi), PARAMETER :: M1N7FKye = 88 + INTEGER(IntKi), PARAMETER :: M1N8FKye = 89 + INTEGER(IntKi), PARAMETER :: M1N9FKye = 90 + INTEGER(IntKi), PARAMETER :: M2N1FKye = 91 + INTEGER(IntKi), PARAMETER :: M2N2FKye = 92 + INTEGER(IntKi), PARAMETER :: M2N3FKye = 93 + INTEGER(IntKi), PARAMETER :: M2N4FKye = 94 + INTEGER(IntKi), PARAMETER :: M2N5FKye = 95 + INTEGER(IntKi), PARAMETER :: M2N6FKye = 96 + INTEGER(IntKi), PARAMETER :: M2N7FKye = 97 + INTEGER(IntKi), PARAMETER :: M2N8FKye = 98 + INTEGER(IntKi), PARAMETER :: M2N9FKye = 99 + INTEGER(IntKi), PARAMETER :: M3N1FKye = 100 + INTEGER(IntKi), PARAMETER :: M3N2FKye = 101 + INTEGER(IntKi), PARAMETER :: M3N3FKye = 102 + INTEGER(IntKi), PARAMETER :: M3N4FKye = 103 + INTEGER(IntKi), PARAMETER :: M3N5FKye = 104 + INTEGER(IntKi), PARAMETER :: M3N6FKye = 105 + INTEGER(IntKi), PARAMETER :: M3N7FKye = 106 + INTEGER(IntKi), PARAMETER :: M3N8FKye = 107 + INTEGER(IntKi), PARAMETER :: M3N9FKye = 108 + INTEGER(IntKi), PARAMETER :: M4N1FKye = 109 + INTEGER(IntKi), PARAMETER :: M4N2FKye = 110 + INTEGER(IntKi), PARAMETER :: M4N3FKye = 111 + INTEGER(IntKi), PARAMETER :: M4N4FKye = 112 + INTEGER(IntKi), PARAMETER :: M4N5FKye = 113 + INTEGER(IntKi), PARAMETER :: M4N6FKye = 114 + INTEGER(IntKi), PARAMETER :: M4N7FKye = 115 + INTEGER(IntKi), PARAMETER :: M4N8FKye = 116 + INTEGER(IntKi), PARAMETER :: M4N9FKye = 117 + INTEGER(IntKi), PARAMETER :: M5N1FKye = 118 + INTEGER(IntKi), PARAMETER :: M5N2FKye = 119 + INTEGER(IntKi), PARAMETER :: M5N3FKye = 120 + INTEGER(IntKi), PARAMETER :: M5N4FKye = 121 + INTEGER(IntKi), PARAMETER :: M5N5FKye = 122 + INTEGER(IntKi), PARAMETER :: M5N6FKye = 123 + INTEGER(IntKi), PARAMETER :: M5N7FKye = 124 + INTEGER(IntKi), PARAMETER :: M5N8FKye = 125 + INTEGER(IntKi), PARAMETER :: M5N9FKye = 126 + INTEGER(IntKi), PARAMETER :: M6N1FKye = 127 + INTEGER(IntKi), PARAMETER :: M6N2FKye = 128 + INTEGER(IntKi), PARAMETER :: M6N3FKye = 129 + INTEGER(IntKi), PARAMETER :: M6N4FKye = 130 + INTEGER(IntKi), PARAMETER :: M6N5FKye = 131 + INTEGER(IntKi), PARAMETER :: M6N6FKye = 132 + INTEGER(IntKi), PARAMETER :: M6N7FKye = 133 + INTEGER(IntKi), PARAMETER :: M6N8FKye = 134 + INTEGER(IntKi), PARAMETER :: M6N9FKye = 135 + INTEGER(IntKi), PARAMETER :: M7N1FKye = 136 + INTEGER(IntKi), PARAMETER :: M7N2FKye = 137 + INTEGER(IntKi), PARAMETER :: M7N3FKye = 138 + INTEGER(IntKi), PARAMETER :: M7N4FKye = 139 + INTEGER(IntKi), PARAMETER :: M7N5FKye = 140 + INTEGER(IntKi), PARAMETER :: M7N6FKye = 141 + INTEGER(IntKi), PARAMETER :: M7N7FKye = 142 + INTEGER(IntKi), PARAMETER :: M7N8FKye = 143 + INTEGER(IntKi), PARAMETER :: M7N9FKye = 144 + INTEGER(IntKi), PARAMETER :: M8N1FKye = 145 + INTEGER(IntKi), PARAMETER :: M8N2FKye = 146 + INTEGER(IntKi), PARAMETER :: M8N3FKye = 147 + INTEGER(IntKi), PARAMETER :: M8N4FKye = 148 + INTEGER(IntKi), PARAMETER :: M8N5FKye = 149 + INTEGER(IntKi), PARAMETER :: M8N6FKye = 150 + INTEGER(IntKi), PARAMETER :: M8N7FKye = 151 + INTEGER(IntKi), PARAMETER :: M8N8FKye = 152 + INTEGER(IntKi), PARAMETER :: M8N9FKye = 153 + INTEGER(IntKi), PARAMETER :: M9N1FKye = 154 + INTEGER(IntKi), PARAMETER :: M9N2FKye = 155 + INTEGER(IntKi), PARAMETER :: M9N3FKye = 156 + INTEGER(IntKi), PARAMETER :: M9N4FKye = 157 + INTEGER(IntKi), PARAMETER :: M9N5FKye = 158 + INTEGER(IntKi), PARAMETER :: M9N6FKye = 159 + INTEGER(IntKi), PARAMETER :: M9N7FKye = 160 + INTEGER(IntKi), PARAMETER :: M9N8FKye = 161 + INTEGER(IntKi), PARAMETER :: M9N9FKye = 162 + INTEGER(IntKi), PARAMETER :: M1N1FKze = 163 + INTEGER(IntKi), PARAMETER :: M1N2FKze = 164 + INTEGER(IntKi), PARAMETER :: M1N3FKze = 165 + INTEGER(IntKi), PARAMETER :: M1N4FKze = 166 + INTEGER(IntKi), PARAMETER :: M1N5FKze = 167 + INTEGER(IntKi), PARAMETER :: M1N6FKze = 168 + INTEGER(IntKi), PARAMETER :: M1N7FKze = 169 + INTEGER(IntKi), PARAMETER :: M1N8FKze = 170 + INTEGER(IntKi), PARAMETER :: M1N9FKze = 171 + INTEGER(IntKi), PARAMETER :: M2N1FKze = 172 + INTEGER(IntKi), PARAMETER :: M2N2FKze = 173 + INTEGER(IntKi), PARAMETER :: M2N3FKze = 174 + INTEGER(IntKi), PARAMETER :: M2N4FKze = 175 + INTEGER(IntKi), PARAMETER :: M2N5FKze = 176 + INTEGER(IntKi), PARAMETER :: M2N6FKze = 177 + INTEGER(IntKi), PARAMETER :: M2N7FKze = 178 + INTEGER(IntKi), PARAMETER :: M2N8FKze = 179 + INTEGER(IntKi), PARAMETER :: M2N9FKze = 180 + INTEGER(IntKi), PARAMETER :: M3N1FKze = 181 + INTEGER(IntKi), PARAMETER :: M3N2FKze = 182 + INTEGER(IntKi), PARAMETER :: M3N3FKze = 183 + INTEGER(IntKi), PARAMETER :: M3N4FKze = 184 + INTEGER(IntKi), PARAMETER :: M3N5FKze = 185 + INTEGER(IntKi), PARAMETER :: M3N6FKze = 186 + INTEGER(IntKi), PARAMETER :: M3N7FKze = 187 + INTEGER(IntKi), PARAMETER :: M3N8FKze = 188 + INTEGER(IntKi), PARAMETER :: M3N9FKze = 189 + INTEGER(IntKi), PARAMETER :: M4N1FKze = 190 + INTEGER(IntKi), PARAMETER :: M4N2FKze = 191 + INTEGER(IntKi), PARAMETER :: M4N3FKze = 192 + INTEGER(IntKi), PARAMETER :: M4N4FKze = 193 + INTEGER(IntKi), PARAMETER :: M4N5FKze = 194 + INTEGER(IntKi), PARAMETER :: M4N6FKze = 195 + INTEGER(IntKi), PARAMETER :: M4N7FKze = 196 + INTEGER(IntKi), PARAMETER :: M4N8FKze = 197 + INTEGER(IntKi), PARAMETER :: M4N9FKze = 198 + INTEGER(IntKi), PARAMETER :: M5N1FKze = 199 + INTEGER(IntKi), PARAMETER :: M5N2FKze = 200 + INTEGER(IntKi), PARAMETER :: M5N3FKze = 201 + INTEGER(IntKi), PARAMETER :: M5N4FKze = 202 + INTEGER(IntKi), PARAMETER :: M5N5FKze = 203 + INTEGER(IntKi), PARAMETER :: M5N6FKze = 204 + INTEGER(IntKi), PARAMETER :: M5N7FKze = 205 + INTEGER(IntKi), PARAMETER :: M5N8FKze = 206 + INTEGER(IntKi), PARAMETER :: M5N9FKze = 207 + INTEGER(IntKi), PARAMETER :: M6N1FKze = 208 + INTEGER(IntKi), PARAMETER :: M6N2FKze = 209 + INTEGER(IntKi), PARAMETER :: M6N3FKze = 210 + INTEGER(IntKi), PARAMETER :: M6N4FKze = 211 + INTEGER(IntKi), PARAMETER :: M6N5FKze = 212 + INTEGER(IntKi), PARAMETER :: M6N6FKze = 213 + INTEGER(IntKi), PARAMETER :: M6N7FKze = 214 + INTEGER(IntKi), PARAMETER :: M6N8FKze = 215 + INTEGER(IntKi), PARAMETER :: M6N9FKze = 216 + INTEGER(IntKi), PARAMETER :: M7N1FKze = 217 + INTEGER(IntKi), PARAMETER :: M7N2FKze = 218 + INTEGER(IntKi), PARAMETER :: M7N3FKze = 219 + INTEGER(IntKi), PARAMETER :: M7N4FKze = 220 + INTEGER(IntKi), PARAMETER :: M7N5FKze = 221 + INTEGER(IntKi), PARAMETER :: M7N6FKze = 222 + INTEGER(IntKi), PARAMETER :: M7N7FKze = 223 + INTEGER(IntKi), PARAMETER :: M7N8FKze = 224 + INTEGER(IntKi), PARAMETER :: M7N9FKze = 225 + INTEGER(IntKi), PARAMETER :: M8N1FKze = 226 + INTEGER(IntKi), PARAMETER :: M8N2FKze = 227 + INTEGER(IntKi), PARAMETER :: M8N3FKze = 228 + INTEGER(IntKi), PARAMETER :: M8N4FKze = 229 + INTEGER(IntKi), PARAMETER :: M8N5FKze = 230 + INTEGER(IntKi), PARAMETER :: M8N6FKze = 231 + INTEGER(IntKi), PARAMETER :: M8N7FKze = 232 + INTEGER(IntKi), PARAMETER :: M8N8FKze = 233 + INTEGER(IntKi), PARAMETER :: M8N9FKze = 234 + INTEGER(IntKi), PARAMETER :: M9N1FKze = 235 + INTEGER(IntKi), PARAMETER :: M9N2FKze = 236 + INTEGER(IntKi), PARAMETER :: M9N3FKze = 237 + INTEGER(IntKi), PARAMETER :: M9N4FKze = 238 + INTEGER(IntKi), PARAMETER :: M9N5FKze = 239 + INTEGER(IntKi), PARAMETER :: M9N6FKze = 240 + INTEGER(IntKi), PARAMETER :: M9N7FKze = 241 + INTEGER(IntKi), PARAMETER :: M9N8FKze = 242 + INTEGER(IntKi), PARAMETER :: M9N9FKze = 243 + INTEGER(IntKi), PARAMETER :: M1N1FMxe = 244 + INTEGER(IntKi), PARAMETER :: M1N2FMxe = 245 + INTEGER(IntKi), PARAMETER :: M1N3FMxe = 246 + INTEGER(IntKi), PARAMETER :: M1N4FMxe = 247 + INTEGER(IntKi), PARAMETER :: M1N5FMxe = 248 + INTEGER(IntKi), PARAMETER :: M1N6FMxe = 249 + INTEGER(IntKi), PARAMETER :: M1N7FMxe = 250 + INTEGER(IntKi), PARAMETER :: M1N8FMxe = 251 + INTEGER(IntKi), PARAMETER :: M1N9FMxe = 252 + INTEGER(IntKi), PARAMETER :: M2N1FMxe = 253 + INTEGER(IntKi), PARAMETER :: M2N2FMxe = 254 + INTEGER(IntKi), PARAMETER :: M2N3FMxe = 255 + INTEGER(IntKi), PARAMETER :: M2N4FMxe = 256 + INTEGER(IntKi), PARAMETER :: M2N5FMxe = 257 + INTEGER(IntKi), PARAMETER :: M2N6FMxe = 258 + INTEGER(IntKi), PARAMETER :: M2N7FMxe = 259 + INTEGER(IntKi), PARAMETER :: M2N8FMxe = 260 + INTEGER(IntKi), PARAMETER :: M2N9FMxe = 261 + INTEGER(IntKi), PARAMETER :: M3N1FMxe = 262 + INTEGER(IntKi), PARAMETER :: M3N2FMxe = 263 + INTEGER(IntKi), PARAMETER :: M3N3FMxe = 264 + INTEGER(IntKi), PARAMETER :: M3N4FMxe = 265 + INTEGER(IntKi), PARAMETER :: M3N5FMxe = 266 + INTEGER(IntKi), PARAMETER :: M3N6FMxe = 267 + INTEGER(IntKi), PARAMETER :: M3N7FMxe = 268 + INTEGER(IntKi), PARAMETER :: M3N8FMxe = 269 + INTEGER(IntKi), PARAMETER :: M3N9FMxe = 270 + INTEGER(IntKi), PARAMETER :: M4N1FMxe = 271 + INTEGER(IntKi), PARAMETER :: M4N2FMxe = 272 + INTEGER(IntKi), PARAMETER :: M4N3FMxe = 273 + INTEGER(IntKi), PARAMETER :: M4N4FMxe = 274 + INTEGER(IntKi), PARAMETER :: M4N5FMxe = 275 + INTEGER(IntKi), PARAMETER :: M4N6FMxe = 276 + INTEGER(IntKi), PARAMETER :: M4N7FMxe = 277 + INTEGER(IntKi), PARAMETER :: M4N8FMxe = 278 + INTEGER(IntKi), PARAMETER :: M4N9FMxe = 279 + INTEGER(IntKi), PARAMETER :: M5N1FMxe = 280 + INTEGER(IntKi), PARAMETER :: M5N2FMxe = 281 + INTEGER(IntKi), PARAMETER :: M5N3FMxe = 282 + INTEGER(IntKi), PARAMETER :: M5N4FMxe = 283 + INTEGER(IntKi), PARAMETER :: M5N5FMxe = 284 + INTEGER(IntKi), PARAMETER :: M5N6FMxe = 285 + INTEGER(IntKi), PARAMETER :: M5N7FMxe = 286 + INTEGER(IntKi), PARAMETER :: M5N8FMxe = 287 + INTEGER(IntKi), PARAMETER :: M5N9FMxe = 288 + INTEGER(IntKi), PARAMETER :: M6N1FMxe = 289 + INTEGER(IntKi), PARAMETER :: M6N2FMxe = 290 + INTEGER(IntKi), PARAMETER :: M6N3FMxe = 291 + INTEGER(IntKi), PARAMETER :: M6N4FMxe = 292 + INTEGER(IntKi), PARAMETER :: M6N5FMxe = 293 + INTEGER(IntKi), PARAMETER :: M6N6FMxe = 294 + INTEGER(IntKi), PARAMETER :: M6N7FMxe = 295 + INTEGER(IntKi), PARAMETER :: M6N8FMxe = 296 + INTEGER(IntKi), PARAMETER :: M6N9FMxe = 297 + INTEGER(IntKi), PARAMETER :: M7N1FMxe = 298 + INTEGER(IntKi), PARAMETER :: M7N2FMxe = 299 + INTEGER(IntKi), PARAMETER :: M7N3FMxe = 300 + INTEGER(IntKi), PARAMETER :: M7N4FMxe = 301 + INTEGER(IntKi), PARAMETER :: M7N5FMxe = 302 + INTEGER(IntKi), PARAMETER :: M7N6FMxe = 303 + INTEGER(IntKi), PARAMETER :: M7N7FMxe = 304 + INTEGER(IntKi), PARAMETER :: M7N8FMxe = 305 + INTEGER(IntKi), PARAMETER :: M7N9FMxe = 306 + INTEGER(IntKi), PARAMETER :: M8N1FMxe = 307 + INTEGER(IntKi), PARAMETER :: M8N2FMxe = 308 + INTEGER(IntKi), PARAMETER :: M8N3FMxe = 309 + INTEGER(IntKi), PARAMETER :: M8N4FMxe = 310 + INTEGER(IntKi), PARAMETER :: M8N5FMxe = 311 + INTEGER(IntKi), PARAMETER :: M8N6FMxe = 312 + INTEGER(IntKi), PARAMETER :: M8N7FMxe = 313 + INTEGER(IntKi), PARAMETER :: M8N8FMxe = 314 + INTEGER(IntKi), PARAMETER :: M8N9FMxe = 315 + INTEGER(IntKi), PARAMETER :: M9N1FMxe = 316 + INTEGER(IntKi), PARAMETER :: M9N2FMxe = 317 + INTEGER(IntKi), PARAMETER :: M9N3FMxe = 318 + INTEGER(IntKi), PARAMETER :: M9N4FMxe = 319 + INTEGER(IntKi), PARAMETER :: M9N5FMxe = 320 + INTEGER(IntKi), PARAMETER :: M9N6FMxe = 321 + INTEGER(IntKi), PARAMETER :: M9N7FMxe = 322 + INTEGER(IntKi), PARAMETER :: M9N8FMxe = 323 + INTEGER(IntKi), PARAMETER :: M9N9FMxe = 324 + INTEGER(IntKi), PARAMETER :: M1N1FMye = 325 + INTEGER(IntKi), PARAMETER :: M1N2FMye = 326 + INTEGER(IntKi), PARAMETER :: M1N3FMye = 327 + INTEGER(IntKi), PARAMETER :: M1N4FMye = 328 + INTEGER(IntKi), PARAMETER :: M1N5FMye = 329 + INTEGER(IntKi), PARAMETER :: M1N6FMye = 330 + INTEGER(IntKi), PARAMETER :: M1N7FMye = 331 + INTEGER(IntKi), PARAMETER :: M1N8FMye = 332 + INTEGER(IntKi), PARAMETER :: M1N9FMye = 333 + INTEGER(IntKi), PARAMETER :: M2N1FMye = 334 + INTEGER(IntKi), PARAMETER :: M2N2FMye = 335 + INTEGER(IntKi), PARAMETER :: M2N3FMye = 336 + INTEGER(IntKi), PARAMETER :: M2N4FMye = 337 + INTEGER(IntKi), PARAMETER :: M2N5FMye = 338 + INTEGER(IntKi), PARAMETER :: M2N6FMye = 339 + INTEGER(IntKi), PARAMETER :: M2N7FMye = 340 + INTEGER(IntKi), PARAMETER :: M2N8FMye = 341 + INTEGER(IntKi), PARAMETER :: M2N9FMye = 342 + INTEGER(IntKi), PARAMETER :: M3N1FMye = 343 + INTEGER(IntKi), PARAMETER :: M3N2FMye = 344 + INTEGER(IntKi), PARAMETER :: M3N3FMye = 345 + INTEGER(IntKi), PARAMETER :: M3N4FMye = 346 + INTEGER(IntKi), PARAMETER :: M3N5FMye = 347 + INTEGER(IntKi), PARAMETER :: M3N6FMye = 348 + INTEGER(IntKi), PARAMETER :: M3N7FMye = 349 + INTEGER(IntKi), PARAMETER :: M3N8FMye = 350 + INTEGER(IntKi), PARAMETER :: M3N9FMye = 351 + INTEGER(IntKi), PARAMETER :: M4N1FMye = 352 + INTEGER(IntKi), PARAMETER :: M4N2FMye = 353 + INTEGER(IntKi), PARAMETER :: M4N3FMye = 354 + INTEGER(IntKi), PARAMETER :: M4N4FMye = 355 + INTEGER(IntKi), PARAMETER :: M4N5FMye = 356 + INTEGER(IntKi), PARAMETER :: M4N6FMye = 357 + INTEGER(IntKi), PARAMETER :: M4N7FMye = 358 + INTEGER(IntKi), PARAMETER :: M4N8FMye = 359 + INTEGER(IntKi), PARAMETER :: M4N9FMye = 360 + INTEGER(IntKi), PARAMETER :: M5N1FMye = 361 + INTEGER(IntKi), PARAMETER :: M5N2FMye = 362 + INTEGER(IntKi), PARAMETER :: M5N3FMye = 363 + INTEGER(IntKi), PARAMETER :: M5N4FMye = 364 + INTEGER(IntKi), PARAMETER :: M5N5FMye = 365 + INTEGER(IntKi), PARAMETER :: M5N6FMye = 366 + INTEGER(IntKi), PARAMETER :: M5N7FMye = 367 + INTEGER(IntKi), PARAMETER :: M5N8FMye = 368 + INTEGER(IntKi), PARAMETER :: M5N9FMye = 369 + INTEGER(IntKi), PARAMETER :: M6N1FMye = 370 + INTEGER(IntKi), PARAMETER :: M6N2FMye = 371 + INTEGER(IntKi), PARAMETER :: M6N3FMye = 372 + INTEGER(IntKi), PARAMETER :: M6N4FMye = 373 + INTEGER(IntKi), PARAMETER :: M6N5FMye = 374 + INTEGER(IntKi), PARAMETER :: M6N6FMye = 375 + INTEGER(IntKi), PARAMETER :: M6N7FMye = 376 + INTEGER(IntKi), PARAMETER :: M6N8FMye = 377 + INTEGER(IntKi), PARAMETER :: M6N9FMye = 378 + INTEGER(IntKi), PARAMETER :: M7N1FMye = 379 + INTEGER(IntKi), PARAMETER :: M7N2FMye = 380 + INTEGER(IntKi), PARAMETER :: M7N3FMye = 381 + INTEGER(IntKi), PARAMETER :: M7N4FMye = 382 + INTEGER(IntKi), PARAMETER :: M7N5FMye = 383 + INTEGER(IntKi), PARAMETER :: M7N6FMye = 384 + INTEGER(IntKi), PARAMETER :: M7N7FMye = 385 + INTEGER(IntKi), PARAMETER :: M7N8FMye = 386 + INTEGER(IntKi), PARAMETER :: M7N9FMye = 387 + INTEGER(IntKi), PARAMETER :: M8N1FMye = 388 + INTEGER(IntKi), PARAMETER :: M8N2FMye = 389 + INTEGER(IntKi), PARAMETER :: M8N3FMye = 390 + INTEGER(IntKi), PARAMETER :: M8N4FMye = 391 + INTEGER(IntKi), PARAMETER :: M8N5FMye = 392 + INTEGER(IntKi), PARAMETER :: M8N6FMye = 393 + INTEGER(IntKi), PARAMETER :: M8N7FMye = 394 + INTEGER(IntKi), PARAMETER :: M8N8FMye = 395 + INTEGER(IntKi), PARAMETER :: M8N9FMye = 396 + INTEGER(IntKi), PARAMETER :: M9N1FMye = 397 + INTEGER(IntKi), PARAMETER :: M9N2FMye = 398 + INTEGER(IntKi), PARAMETER :: M9N3FMye = 399 + INTEGER(IntKi), PARAMETER :: M9N4FMye = 400 + INTEGER(IntKi), PARAMETER :: M9N5FMye = 401 + INTEGER(IntKi), PARAMETER :: M9N6FMye = 402 + INTEGER(IntKi), PARAMETER :: M9N7FMye = 403 + INTEGER(IntKi), PARAMETER :: M9N8FMye = 404 + INTEGER(IntKi), PARAMETER :: M9N9FMye = 405 + INTEGER(IntKi), PARAMETER :: M1N1FMze = 406 + INTEGER(IntKi), PARAMETER :: M1N2FMze = 407 + INTEGER(IntKi), PARAMETER :: M1N3FMze = 408 + INTEGER(IntKi), PARAMETER :: M1N4FMze = 409 + INTEGER(IntKi), PARAMETER :: M1N5FMze = 410 + INTEGER(IntKi), PARAMETER :: M1N6FMze = 411 + INTEGER(IntKi), PARAMETER :: M1N7FMze = 412 + INTEGER(IntKi), PARAMETER :: M1N8FMze = 413 + INTEGER(IntKi), PARAMETER :: M1N9FMze = 414 + INTEGER(IntKi), PARAMETER :: M2N1FMze = 415 + INTEGER(IntKi), PARAMETER :: M2N2FMze = 416 + INTEGER(IntKi), PARAMETER :: M2N3FMze = 417 + INTEGER(IntKi), PARAMETER :: M2N4FMze = 418 + INTEGER(IntKi), PARAMETER :: M2N5FMze = 419 + INTEGER(IntKi), PARAMETER :: M2N6FMze = 420 + INTEGER(IntKi), PARAMETER :: M2N7FMze = 421 + INTEGER(IntKi), PARAMETER :: M2N8FMze = 422 + INTEGER(IntKi), PARAMETER :: M2N9FMze = 423 + INTEGER(IntKi), PARAMETER :: M3N1FMze = 424 + INTEGER(IntKi), PARAMETER :: M3N2FMze = 425 + INTEGER(IntKi), PARAMETER :: M3N3FMze = 426 + INTEGER(IntKi), PARAMETER :: M3N4FMze = 427 + INTEGER(IntKi), PARAMETER :: M3N5FMze = 428 + INTEGER(IntKi), PARAMETER :: M3N6FMze = 429 + INTEGER(IntKi), PARAMETER :: M3N7FMze = 430 + INTEGER(IntKi), PARAMETER :: M3N8FMze = 431 + INTEGER(IntKi), PARAMETER :: M3N9FMze = 432 + INTEGER(IntKi), PARAMETER :: M4N1FMze = 433 + INTEGER(IntKi), PARAMETER :: M4N2FMze = 434 + INTEGER(IntKi), PARAMETER :: M4N3FMze = 435 + INTEGER(IntKi), PARAMETER :: M4N4FMze = 436 + INTEGER(IntKi), PARAMETER :: M4N5FMze = 437 + INTEGER(IntKi), PARAMETER :: M4N6FMze = 438 + INTEGER(IntKi), PARAMETER :: M4N7FMze = 439 + INTEGER(IntKi), PARAMETER :: M4N8FMze = 440 + INTEGER(IntKi), PARAMETER :: M4N9FMze = 441 + INTEGER(IntKi), PARAMETER :: M5N1FMze = 442 + INTEGER(IntKi), PARAMETER :: M5N2FMze = 443 + INTEGER(IntKi), PARAMETER :: M5N3FMze = 444 + INTEGER(IntKi), PARAMETER :: M5N4FMze = 445 + INTEGER(IntKi), PARAMETER :: M5N5FMze = 446 + INTEGER(IntKi), PARAMETER :: M5N6FMze = 447 + INTEGER(IntKi), PARAMETER :: M5N7FMze = 448 + INTEGER(IntKi), PARAMETER :: M5N8FMze = 449 + INTEGER(IntKi), PARAMETER :: M5N9FMze = 450 + INTEGER(IntKi), PARAMETER :: M6N1FMze = 451 + INTEGER(IntKi), PARAMETER :: M6N2FMze = 452 + INTEGER(IntKi), PARAMETER :: M6N3FMze = 453 + INTEGER(IntKi), PARAMETER :: M6N4FMze = 454 + INTEGER(IntKi), PARAMETER :: M6N5FMze = 455 + INTEGER(IntKi), PARAMETER :: M6N6FMze = 456 + INTEGER(IntKi), PARAMETER :: M6N7FMze = 457 + INTEGER(IntKi), PARAMETER :: M6N8FMze = 458 + INTEGER(IntKi), PARAMETER :: M6N9FMze = 459 + INTEGER(IntKi), PARAMETER :: M7N1FMze = 460 + INTEGER(IntKi), PARAMETER :: M7N2FMze = 461 + INTEGER(IntKi), PARAMETER :: M7N3FMze = 462 + INTEGER(IntKi), PARAMETER :: M7N4FMze = 463 + INTEGER(IntKi), PARAMETER :: M7N5FMze = 464 + INTEGER(IntKi), PARAMETER :: M7N6FMze = 465 + INTEGER(IntKi), PARAMETER :: M7N7FMze = 466 + INTEGER(IntKi), PARAMETER :: M7N8FMze = 467 + INTEGER(IntKi), PARAMETER :: M7N9FMze = 468 + INTEGER(IntKi), PARAMETER :: M8N1FMze = 469 + INTEGER(IntKi), PARAMETER :: M8N2FMze = 470 + INTEGER(IntKi), PARAMETER :: M8N3FMze = 471 + INTEGER(IntKi), PARAMETER :: M8N4FMze = 472 + INTEGER(IntKi), PARAMETER :: M8N5FMze = 473 + INTEGER(IntKi), PARAMETER :: M8N6FMze = 474 + INTEGER(IntKi), PARAMETER :: M8N7FMze = 475 + INTEGER(IntKi), PARAMETER :: M8N8FMze = 476 + INTEGER(IntKi), PARAMETER :: M8N9FMze = 477 + INTEGER(IntKi), PARAMETER :: M9N1FMze = 478 + INTEGER(IntKi), PARAMETER :: M9N2FMze = 479 + INTEGER(IntKi), PARAMETER :: M9N3FMze = 480 + INTEGER(IntKi), PARAMETER :: M9N4FMze = 481 + INTEGER(IntKi), PARAMETER :: M9N5FMze = 482 + INTEGER(IntKi), PARAMETER :: M9N6FMze = 483 + INTEGER(IntKi), PARAMETER :: M9N7FMze = 484 + INTEGER(IntKi), PARAMETER :: M9N8FMze = 485 + INTEGER(IntKi), PARAMETER :: M9N9FMze = 486 + INTEGER(IntKi), PARAMETER :: M1N1MKxe = 487 + INTEGER(IntKi), PARAMETER :: M1N2MKxe = 488 + INTEGER(IntKi), PARAMETER :: M1N3MKxe = 489 + INTEGER(IntKi), PARAMETER :: M1N4MKxe = 490 + INTEGER(IntKi), PARAMETER :: M1N5MKxe = 491 + INTEGER(IntKi), PARAMETER :: M1N6MKxe = 492 + INTEGER(IntKi), PARAMETER :: M1N7MKxe = 493 + INTEGER(IntKi), PARAMETER :: M1N8MKxe = 494 + INTEGER(IntKi), PARAMETER :: M1N9MKxe = 495 + INTEGER(IntKi), PARAMETER :: M2N1MKxe = 496 + INTEGER(IntKi), PARAMETER :: M2N2MKxe = 497 + INTEGER(IntKi), PARAMETER :: M2N3MKxe = 498 + INTEGER(IntKi), PARAMETER :: M2N4MKxe = 499 + INTEGER(IntKi), PARAMETER :: M2N5MKxe = 500 + INTEGER(IntKi), PARAMETER :: M2N6MKxe = 501 + INTEGER(IntKi), PARAMETER :: M2N7MKxe = 502 + INTEGER(IntKi), PARAMETER :: M2N8MKxe = 503 + INTEGER(IntKi), PARAMETER :: M2N9MKxe = 504 + INTEGER(IntKi), PARAMETER :: M3N1MKxe = 505 + INTEGER(IntKi), PARAMETER :: M3N2MKxe = 506 + INTEGER(IntKi), PARAMETER :: M3N3MKxe = 507 + INTEGER(IntKi), PARAMETER :: M3N4MKxe = 508 + INTEGER(IntKi), PARAMETER :: M3N5MKxe = 509 + INTEGER(IntKi), PARAMETER :: M3N6MKxe = 510 + INTEGER(IntKi), PARAMETER :: M3N7MKxe = 511 + INTEGER(IntKi), PARAMETER :: M3N8MKxe = 512 + INTEGER(IntKi), PARAMETER :: M3N9MKxe = 513 + INTEGER(IntKi), PARAMETER :: M4N1MKxe = 514 + INTEGER(IntKi), PARAMETER :: M4N2MKxe = 515 + INTEGER(IntKi), PARAMETER :: M4N3MKxe = 516 + INTEGER(IntKi), PARAMETER :: M4N4MKxe = 517 + INTEGER(IntKi), PARAMETER :: M4N5MKxe = 518 + INTEGER(IntKi), PARAMETER :: M4N6MKxe = 519 + INTEGER(IntKi), PARAMETER :: M4N7MKxe = 520 + INTEGER(IntKi), PARAMETER :: M4N8MKxe = 521 + INTEGER(IntKi), PARAMETER :: M4N9MKxe = 522 + INTEGER(IntKi), PARAMETER :: M5N1MKxe = 523 + INTEGER(IntKi), PARAMETER :: M5N2MKxe = 524 + INTEGER(IntKi), PARAMETER :: M5N3MKxe = 525 + INTEGER(IntKi), PARAMETER :: M5N4MKxe = 526 + INTEGER(IntKi), PARAMETER :: M5N5MKxe = 527 + INTEGER(IntKi), PARAMETER :: M5N6MKxe = 528 + INTEGER(IntKi), PARAMETER :: M5N7MKxe = 529 + INTEGER(IntKi), PARAMETER :: M5N8MKxe = 530 + INTEGER(IntKi), PARAMETER :: M5N9MKxe = 531 + INTEGER(IntKi), PARAMETER :: M6N1MKxe = 532 + INTEGER(IntKi), PARAMETER :: M6N2MKxe = 533 + INTEGER(IntKi), PARAMETER :: M6N3MKxe = 534 + INTEGER(IntKi), PARAMETER :: M6N4MKxe = 535 + INTEGER(IntKi), PARAMETER :: M6N5MKxe = 536 + INTEGER(IntKi), PARAMETER :: M6N6MKxe = 537 + INTEGER(IntKi), PARAMETER :: M6N7MKxe = 538 + INTEGER(IntKi), PARAMETER :: M6N8MKxe = 539 + INTEGER(IntKi), PARAMETER :: M6N9MKxe = 540 + INTEGER(IntKi), PARAMETER :: M7N1MKxe = 541 + INTEGER(IntKi), PARAMETER :: M7N2MKxe = 542 + INTEGER(IntKi), PARAMETER :: M7N3MKxe = 543 + INTEGER(IntKi), PARAMETER :: M7N4MKxe = 544 + INTEGER(IntKi), PARAMETER :: M7N5MKxe = 545 + INTEGER(IntKi), PARAMETER :: M7N6MKxe = 546 + INTEGER(IntKi), PARAMETER :: M7N7MKxe = 547 + INTEGER(IntKi), PARAMETER :: M7N8MKxe = 548 + INTEGER(IntKi), PARAMETER :: M7N9MKxe = 549 + INTEGER(IntKi), PARAMETER :: M8N1MKxe = 550 + INTEGER(IntKi), PARAMETER :: M8N2MKxe = 551 + INTEGER(IntKi), PARAMETER :: M8N3MKxe = 552 + INTEGER(IntKi), PARAMETER :: M8N4MKxe = 553 + INTEGER(IntKi), PARAMETER :: M8N5MKxe = 554 + INTEGER(IntKi), PARAMETER :: M8N6MKxe = 555 + INTEGER(IntKi), PARAMETER :: M8N7MKxe = 556 + INTEGER(IntKi), PARAMETER :: M8N8MKxe = 557 + INTEGER(IntKi), PARAMETER :: M8N9MKxe = 558 + INTEGER(IntKi), PARAMETER :: M9N1MKxe = 559 + INTEGER(IntKi), PARAMETER :: M9N2MKxe = 560 + INTEGER(IntKi), PARAMETER :: M9N3MKxe = 561 + INTEGER(IntKi), PARAMETER :: M9N4MKxe = 562 + INTEGER(IntKi), PARAMETER :: M9N5MKxe = 563 + INTEGER(IntKi), PARAMETER :: M9N6MKxe = 564 + INTEGER(IntKi), PARAMETER :: M9N7MKxe = 565 + INTEGER(IntKi), PARAMETER :: M9N8MKxe = 566 + INTEGER(IntKi), PARAMETER :: M9N9MKxe = 567 + INTEGER(IntKi), PARAMETER :: M1N1MKye = 568 + INTEGER(IntKi), PARAMETER :: M1N2MKye = 569 + INTEGER(IntKi), PARAMETER :: M1N3MKye = 570 + INTEGER(IntKi), PARAMETER :: M1N4MKye = 571 + INTEGER(IntKi), PARAMETER :: M1N5MKye = 572 + INTEGER(IntKi), PARAMETER :: M1N6MKye = 573 + INTEGER(IntKi), PARAMETER :: M1N7MKye = 574 + INTEGER(IntKi), PARAMETER :: M1N8MKye = 575 + INTEGER(IntKi), PARAMETER :: M1N9MKye = 576 + INTEGER(IntKi), PARAMETER :: M2N1MKye = 577 + INTEGER(IntKi), PARAMETER :: M2N2MKye = 578 + INTEGER(IntKi), PARAMETER :: M2N3MKye = 579 + INTEGER(IntKi), PARAMETER :: M2N4MKye = 580 + INTEGER(IntKi), PARAMETER :: M2N5MKye = 581 + INTEGER(IntKi), PARAMETER :: M2N6MKye = 582 + INTEGER(IntKi), PARAMETER :: M2N7MKye = 583 + INTEGER(IntKi), PARAMETER :: M2N8MKye = 584 + INTEGER(IntKi), PARAMETER :: M2N9MKye = 585 + INTEGER(IntKi), PARAMETER :: M3N1MKye = 586 + INTEGER(IntKi), PARAMETER :: M3N2MKye = 587 + INTEGER(IntKi), PARAMETER :: M3N3MKye = 588 + INTEGER(IntKi), PARAMETER :: M3N4MKye = 589 + INTEGER(IntKi), PARAMETER :: M3N5MKye = 590 + INTEGER(IntKi), PARAMETER :: M3N6MKye = 591 + INTEGER(IntKi), PARAMETER :: M3N7MKye = 592 + INTEGER(IntKi), PARAMETER :: M3N8MKye = 593 + INTEGER(IntKi), PARAMETER :: M3N9MKye = 594 + INTEGER(IntKi), PARAMETER :: M4N1MKye = 595 + INTEGER(IntKi), PARAMETER :: M4N2MKye = 596 + INTEGER(IntKi), PARAMETER :: M4N3MKye = 597 + INTEGER(IntKi), PARAMETER :: M4N4MKye = 598 + INTEGER(IntKi), PARAMETER :: M4N5MKye = 599 + INTEGER(IntKi), PARAMETER :: M4N6MKye = 600 + INTEGER(IntKi), PARAMETER :: M4N7MKye = 601 + INTEGER(IntKi), PARAMETER :: M4N8MKye = 602 + INTEGER(IntKi), PARAMETER :: M4N9MKye = 603 + INTEGER(IntKi), PARAMETER :: M5N1MKye = 604 + INTEGER(IntKi), PARAMETER :: M5N2MKye = 605 + INTEGER(IntKi), PARAMETER :: M5N3MKye = 606 + INTEGER(IntKi), PARAMETER :: M5N4MKye = 607 + INTEGER(IntKi), PARAMETER :: M5N5MKye = 608 + INTEGER(IntKi), PARAMETER :: M5N6MKye = 609 + INTEGER(IntKi), PARAMETER :: M5N7MKye = 610 + INTEGER(IntKi), PARAMETER :: M5N8MKye = 611 + INTEGER(IntKi), PARAMETER :: M5N9MKye = 612 + INTEGER(IntKi), PARAMETER :: M6N1MKye = 613 + INTEGER(IntKi), PARAMETER :: M6N2MKye = 614 + INTEGER(IntKi), PARAMETER :: M6N3MKye = 615 + INTEGER(IntKi), PARAMETER :: M6N4MKye = 616 + INTEGER(IntKi), PARAMETER :: M6N5MKye = 617 + INTEGER(IntKi), PARAMETER :: M6N6MKye = 618 + INTEGER(IntKi), PARAMETER :: M6N7MKye = 619 + INTEGER(IntKi), PARAMETER :: M6N8MKye = 620 + INTEGER(IntKi), PARAMETER :: M6N9MKye = 621 + INTEGER(IntKi), PARAMETER :: M7N1MKye = 622 + INTEGER(IntKi), PARAMETER :: M7N2MKye = 623 + INTEGER(IntKi), PARAMETER :: M7N3MKye = 624 + INTEGER(IntKi), PARAMETER :: M7N4MKye = 625 + INTEGER(IntKi), PARAMETER :: M7N5MKye = 626 + INTEGER(IntKi), PARAMETER :: M7N6MKye = 627 + INTEGER(IntKi), PARAMETER :: M7N7MKye = 628 + INTEGER(IntKi), PARAMETER :: M7N8MKye = 629 + INTEGER(IntKi), PARAMETER :: M7N9MKye = 630 + INTEGER(IntKi), PARAMETER :: M8N1MKye = 631 + INTEGER(IntKi), PARAMETER :: M8N2MKye = 632 + INTEGER(IntKi), PARAMETER :: M8N3MKye = 633 + INTEGER(IntKi), PARAMETER :: M8N4MKye = 634 + INTEGER(IntKi), PARAMETER :: M8N5MKye = 635 + INTEGER(IntKi), PARAMETER :: M8N6MKye = 636 + INTEGER(IntKi), PARAMETER :: M8N7MKye = 637 + INTEGER(IntKi), PARAMETER :: M8N8MKye = 638 + INTEGER(IntKi), PARAMETER :: M8N9MKye = 639 + INTEGER(IntKi), PARAMETER :: M9N1MKye = 640 + INTEGER(IntKi), PARAMETER :: M9N2MKye = 641 + INTEGER(IntKi), PARAMETER :: M9N3MKye = 642 + INTEGER(IntKi), PARAMETER :: M9N4MKye = 643 + INTEGER(IntKi), PARAMETER :: M9N5MKye = 644 + INTEGER(IntKi), PARAMETER :: M9N6MKye = 645 + INTEGER(IntKi), PARAMETER :: M9N7MKye = 646 + INTEGER(IntKi), PARAMETER :: M9N8MKye = 647 + INTEGER(IntKi), PARAMETER :: M9N9MKye = 648 + INTEGER(IntKi), PARAMETER :: M1N1MKze = 649 + INTEGER(IntKi), PARAMETER :: M1N2MKze = 650 + INTEGER(IntKi), PARAMETER :: M1N3MKze = 651 + INTEGER(IntKi), PARAMETER :: M1N4MKze = 652 + INTEGER(IntKi), PARAMETER :: M1N5MKze = 653 + INTEGER(IntKi), PARAMETER :: M1N6MKze = 654 + INTEGER(IntKi), PARAMETER :: M1N7MKze = 655 + INTEGER(IntKi), PARAMETER :: M1N8MKze = 656 + INTEGER(IntKi), PARAMETER :: M1N9MKze = 657 + INTEGER(IntKi), PARAMETER :: M2N1MKze = 658 + INTEGER(IntKi), PARAMETER :: M2N2MKze = 659 + INTEGER(IntKi), PARAMETER :: M2N3MKze = 660 + INTEGER(IntKi), PARAMETER :: M2N4MKze = 661 + INTEGER(IntKi), PARAMETER :: M2N5MKze = 662 + INTEGER(IntKi), PARAMETER :: M2N6MKze = 663 + INTEGER(IntKi), PARAMETER :: M2N7MKze = 664 + INTEGER(IntKi), PARAMETER :: M2N8MKze = 665 + INTEGER(IntKi), PARAMETER :: M2N9MKze = 666 + INTEGER(IntKi), PARAMETER :: M3N1MKze = 667 + INTEGER(IntKi), PARAMETER :: M3N2MKze = 668 + INTEGER(IntKi), PARAMETER :: M3N3MKze = 669 + INTEGER(IntKi), PARAMETER :: M3N4MKze = 670 + INTEGER(IntKi), PARAMETER :: M3N5MKze = 671 + INTEGER(IntKi), PARAMETER :: M3N6MKze = 672 + INTEGER(IntKi), PARAMETER :: M3N7MKze = 673 + INTEGER(IntKi), PARAMETER :: M3N8MKze = 674 + INTEGER(IntKi), PARAMETER :: M3N9MKze = 675 + INTEGER(IntKi), PARAMETER :: M4N1MKze = 676 + INTEGER(IntKi), PARAMETER :: M4N2MKze = 677 + INTEGER(IntKi), PARAMETER :: M4N3MKze = 678 + INTEGER(IntKi), PARAMETER :: M4N4MKze = 679 + INTEGER(IntKi), PARAMETER :: M4N5MKze = 680 + INTEGER(IntKi), PARAMETER :: M4N6MKze = 681 + INTEGER(IntKi), PARAMETER :: M4N7MKze = 682 + INTEGER(IntKi), PARAMETER :: M4N8MKze = 683 + INTEGER(IntKi), PARAMETER :: M4N9MKze = 684 + INTEGER(IntKi), PARAMETER :: M5N1MKze = 685 + INTEGER(IntKi), PARAMETER :: M5N2MKze = 686 + INTEGER(IntKi), PARAMETER :: M5N3MKze = 687 + INTEGER(IntKi), PARAMETER :: M5N4MKze = 688 + INTEGER(IntKi), PARAMETER :: M5N5MKze = 689 + INTEGER(IntKi), PARAMETER :: M5N6MKze = 690 + INTEGER(IntKi), PARAMETER :: M5N7MKze = 691 + INTEGER(IntKi), PARAMETER :: M5N8MKze = 692 + INTEGER(IntKi), PARAMETER :: M5N9MKze = 693 + INTEGER(IntKi), PARAMETER :: M6N1MKze = 694 + INTEGER(IntKi), PARAMETER :: M6N2MKze = 695 + INTEGER(IntKi), PARAMETER :: M6N3MKze = 696 + INTEGER(IntKi), PARAMETER :: M6N4MKze = 697 + INTEGER(IntKi), PARAMETER :: M6N5MKze = 698 + INTEGER(IntKi), PARAMETER :: M6N6MKze = 699 + INTEGER(IntKi), PARAMETER :: M6N7MKze = 700 + INTEGER(IntKi), PARAMETER :: M6N8MKze = 701 + INTEGER(IntKi), PARAMETER :: M6N9MKze = 702 + INTEGER(IntKi), PARAMETER :: M7N1MKze = 703 + INTEGER(IntKi), PARAMETER :: M7N2MKze = 704 + INTEGER(IntKi), PARAMETER :: M7N3MKze = 705 + INTEGER(IntKi), PARAMETER :: M7N4MKze = 706 + INTEGER(IntKi), PARAMETER :: M7N5MKze = 707 + INTEGER(IntKi), PARAMETER :: M7N6MKze = 708 + INTEGER(IntKi), PARAMETER :: M7N7MKze = 709 + INTEGER(IntKi), PARAMETER :: M7N8MKze = 710 + INTEGER(IntKi), PARAMETER :: M7N9MKze = 711 + INTEGER(IntKi), PARAMETER :: M8N1MKze = 712 + INTEGER(IntKi), PARAMETER :: M8N2MKze = 713 + INTEGER(IntKi), PARAMETER :: M8N3MKze = 714 + INTEGER(IntKi), PARAMETER :: M8N4MKze = 715 + INTEGER(IntKi), PARAMETER :: M8N5MKze = 716 + INTEGER(IntKi), PARAMETER :: M8N6MKze = 717 + INTEGER(IntKi), PARAMETER :: M8N7MKze = 718 + INTEGER(IntKi), PARAMETER :: M8N8MKze = 719 + INTEGER(IntKi), PARAMETER :: M8N9MKze = 720 + INTEGER(IntKi), PARAMETER :: M9N1MKze = 721 + INTEGER(IntKi), PARAMETER :: M9N2MKze = 722 + INTEGER(IntKi), PARAMETER :: M9N3MKze = 723 + INTEGER(IntKi), PARAMETER :: M9N4MKze = 724 + INTEGER(IntKi), PARAMETER :: M9N5MKze = 725 + INTEGER(IntKi), PARAMETER :: M9N6MKze = 726 + INTEGER(IntKi), PARAMETER :: M9N7MKze = 727 + INTEGER(IntKi), PARAMETER :: M9N8MKze = 728 + INTEGER(IntKi), PARAMETER :: M9N9MKze = 729 + INTEGER(IntKi), PARAMETER :: M1N1MMxe = 730 + INTEGER(IntKi), PARAMETER :: M1N2MMxe = 731 + INTEGER(IntKi), PARAMETER :: M1N3MMxe = 732 + INTEGER(IntKi), PARAMETER :: M1N4MMxe = 733 + INTEGER(IntKi), PARAMETER :: M1N5MMxe = 734 + INTEGER(IntKi), PARAMETER :: M1N6MMxe = 735 + INTEGER(IntKi), PARAMETER :: M1N7MMxe = 736 + INTEGER(IntKi), PARAMETER :: M1N8MMxe = 737 + INTEGER(IntKi), PARAMETER :: M1N9MMxe = 738 + INTEGER(IntKi), PARAMETER :: M2N1MMxe = 739 + INTEGER(IntKi), PARAMETER :: M2N2MMxe = 740 + INTEGER(IntKi), PARAMETER :: M2N3MMxe = 741 + INTEGER(IntKi), PARAMETER :: M2N4MMxe = 742 + INTEGER(IntKi), PARAMETER :: M2N5MMxe = 743 + INTEGER(IntKi), PARAMETER :: M2N6MMxe = 744 + INTEGER(IntKi), PARAMETER :: M2N7MMxe = 745 + INTEGER(IntKi), PARAMETER :: M2N8MMxe = 746 + INTEGER(IntKi), PARAMETER :: M2N9MMxe = 747 + INTEGER(IntKi), PARAMETER :: M3N1MMxe = 748 + INTEGER(IntKi), PARAMETER :: M3N2MMxe = 749 + INTEGER(IntKi), PARAMETER :: M3N3MMxe = 750 + INTEGER(IntKi), PARAMETER :: M3N4MMxe = 751 + INTEGER(IntKi), PARAMETER :: M3N5MMxe = 752 + INTEGER(IntKi), PARAMETER :: M3N6MMxe = 753 + INTEGER(IntKi), PARAMETER :: M3N7MMxe = 754 + INTEGER(IntKi), PARAMETER :: M3N8MMxe = 755 + INTEGER(IntKi), PARAMETER :: M3N9MMxe = 756 + INTEGER(IntKi), PARAMETER :: M4N1MMxe = 757 + INTEGER(IntKi), PARAMETER :: M4N2MMxe = 758 + INTEGER(IntKi), PARAMETER :: M4N3MMxe = 759 + INTEGER(IntKi), PARAMETER :: M4N4MMxe = 760 + INTEGER(IntKi), PARAMETER :: M4N5MMxe = 761 + INTEGER(IntKi), PARAMETER :: M4N6MMxe = 762 + INTEGER(IntKi), PARAMETER :: M4N7MMxe = 763 + INTEGER(IntKi), PARAMETER :: M4N8MMxe = 764 + INTEGER(IntKi), PARAMETER :: M4N9MMxe = 765 + INTEGER(IntKi), PARAMETER :: M5N1MMxe = 766 + INTEGER(IntKi), PARAMETER :: M5N2MMxe = 767 + INTEGER(IntKi), PARAMETER :: M5N3MMxe = 768 + INTEGER(IntKi), PARAMETER :: M5N4MMxe = 769 + INTEGER(IntKi), PARAMETER :: M5N5MMxe = 770 + INTEGER(IntKi), PARAMETER :: M5N6MMxe = 771 + INTEGER(IntKi), PARAMETER :: M5N7MMxe = 772 + INTEGER(IntKi), PARAMETER :: M5N8MMxe = 773 + INTEGER(IntKi), PARAMETER :: M5N9MMxe = 774 + INTEGER(IntKi), PARAMETER :: M6N1MMxe = 775 + INTEGER(IntKi), PARAMETER :: M6N2MMxe = 776 + INTEGER(IntKi), PARAMETER :: M6N3MMxe = 777 + INTEGER(IntKi), PARAMETER :: M6N4MMxe = 778 + INTEGER(IntKi), PARAMETER :: M6N5MMxe = 779 + INTEGER(IntKi), PARAMETER :: M6N6MMxe = 780 + INTEGER(IntKi), PARAMETER :: M6N7MMxe = 781 + INTEGER(IntKi), PARAMETER :: M6N8MMxe = 782 + INTEGER(IntKi), PARAMETER :: M6N9MMxe = 783 + INTEGER(IntKi), PARAMETER :: M7N1MMxe = 784 + INTEGER(IntKi), PARAMETER :: M7N2MMxe = 785 + INTEGER(IntKi), PARAMETER :: M7N3MMxe = 786 + INTEGER(IntKi), PARAMETER :: M7N4MMxe = 787 + INTEGER(IntKi), PARAMETER :: M7N5MMxe = 788 + INTEGER(IntKi), PARAMETER :: M7N6MMxe = 789 + INTEGER(IntKi), PARAMETER :: M7N7MMxe = 790 + INTEGER(IntKi), PARAMETER :: M7N8MMxe = 791 + INTEGER(IntKi), PARAMETER :: M7N9MMxe = 792 + INTEGER(IntKi), PARAMETER :: M8N1MMxe = 793 + INTEGER(IntKi), PARAMETER :: M8N2MMxe = 794 + INTEGER(IntKi), PARAMETER :: M8N3MMxe = 795 + INTEGER(IntKi), PARAMETER :: M8N4MMxe = 796 + INTEGER(IntKi), PARAMETER :: M8N5MMxe = 797 + INTEGER(IntKi), PARAMETER :: M8N6MMxe = 798 + INTEGER(IntKi), PARAMETER :: M8N7MMxe = 799 + INTEGER(IntKi), PARAMETER :: M8N8MMxe = 800 + INTEGER(IntKi), PARAMETER :: M8N9MMxe = 801 + INTEGER(IntKi), PARAMETER :: M9N1MMxe = 802 + INTEGER(IntKi), PARAMETER :: M9N2MMxe = 803 + INTEGER(IntKi), PARAMETER :: M9N3MMxe = 804 + INTEGER(IntKi), PARAMETER :: M9N4MMxe = 805 + INTEGER(IntKi), PARAMETER :: M9N5MMxe = 806 + INTEGER(IntKi), PARAMETER :: M9N6MMxe = 807 + INTEGER(IntKi), PARAMETER :: M9N7MMxe = 808 + INTEGER(IntKi), PARAMETER :: M9N8MMxe = 809 + INTEGER(IntKi), PARAMETER :: M9N9MMxe = 810 + INTEGER(IntKi), PARAMETER :: M1N1MMye = 811 + INTEGER(IntKi), PARAMETER :: M1N2MMye = 812 + INTEGER(IntKi), PARAMETER :: M1N3MMye = 813 + INTEGER(IntKi), PARAMETER :: M1N4MMye = 814 + INTEGER(IntKi), PARAMETER :: M1N5MMye = 815 + INTEGER(IntKi), PARAMETER :: M1N6MMye = 816 + INTEGER(IntKi), PARAMETER :: M1N7MMye = 817 + INTEGER(IntKi), PARAMETER :: M1N8MMye = 818 + INTEGER(IntKi), PARAMETER :: M1N9MMye = 819 + INTEGER(IntKi), PARAMETER :: M2N1MMye = 820 + INTEGER(IntKi), PARAMETER :: M2N2MMye = 821 + INTEGER(IntKi), PARAMETER :: M2N3MMye = 822 + INTEGER(IntKi), PARAMETER :: M2N4MMye = 823 + INTEGER(IntKi), PARAMETER :: M2N5MMye = 824 + INTEGER(IntKi), PARAMETER :: M2N6MMye = 825 + INTEGER(IntKi), PARAMETER :: M2N7MMye = 826 + INTEGER(IntKi), PARAMETER :: M2N8MMye = 827 + INTEGER(IntKi), PARAMETER :: M2N9MMye = 828 + INTEGER(IntKi), PARAMETER :: M3N1MMye = 829 + INTEGER(IntKi), PARAMETER :: M3N2MMye = 830 + INTEGER(IntKi), PARAMETER :: M3N3MMye = 831 + INTEGER(IntKi), PARAMETER :: M3N4MMye = 832 + INTEGER(IntKi), PARAMETER :: M3N5MMye = 833 + INTEGER(IntKi), PARAMETER :: M3N6MMye = 834 + INTEGER(IntKi), PARAMETER :: M3N7MMye = 835 + INTEGER(IntKi), PARAMETER :: M3N8MMye = 836 + INTEGER(IntKi), PARAMETER :: M3N9MMye = 837 + INTEGER(IntKi), PARAMETER :: M4N1MMye = 838 + INTEGER(IntKi), PARAMETER :: M4N2MMye = 839 + INTEGER(IntKi), PARAMETER :: M4N3MMye = 840 + INTEGER(IntKi), PARAMETER :: M4N4MMye = 841 + INTEGER(IntKi), PARAMETER :: M4N5MMye = 842 + INTEGER(IntKi), PARAMETER :: M4N6MMye = 843 + INTEGER(IntKi), PARAMETER :: M4N7MMye = 844 + INTEGER(IntKi), PARAMETER :: M4N8MMye = 845 + INTEGER(IntKi), PARAMETER :: M4N9MMye = 846 + INTEGER(IntKi), PARAMETER :: M5N1MMye = 847 + INTEGER(IntKi), PARAMETER :: M5N2MMye = 848 + INTEGER(IntKi), PARAMETER :: M5N3MMye = 849 + INTEGER(IntKi), PARAMETER :: M5N4MMye = 850 + INTEGER(IntKi), PARAMETER :: M5N5MMye = 851 + INTEGER(IntKi), PARAMETER :: M5N6MMye = 852 + INTEGER(IntKi), PARAMETER :: M5N7MMye = 853 + INTEGER(IntKi), PARAMETER :: M5N8MMye = 854 + INTEGER(IntKi), PARAMETER :: M5N9MMye = 855 + INTEGER(IntKi), PARAMETER :: M6N1MMye = 856 + INTEGER(IntKi), PARAMETER :: M6N2MMye = 857 + INTEGER(IntKi), PARAMETER :: M6N3MMye = 858 + INTEGER(IntKi), PARAMETER :: M6N4MMye = 859 + INTEGER(IntKi), PARAMETER :: M6N5MMye = 860 + INTEGER(IntKi), PARAMETER :: M6N6MMye = 861 + INTEGER(IntKi), PARAMETER :: M6N7MMye = 862 + INTEGER(IntKi), PARAMETER :: M6N8MMye = 863 + INTEGER(IntKi), PARAMETER :: M6N9MMye = 864 + INTEGER(IntKi), PARAMETER :: M7N1MMye = 865 + INTEGER(IntKi), PARAMETER :: M7N2MMye = 866 + INTEGER(IntKi), PARAMETER :: M7N3MMye = 867 + INTEGER(IntKi), PARAMETER :: M7N4MMye = 868 + INTEGER(IntKi), PARAMETER :: M7N5MMye = 869 + INTEGER(IntKi), PARAMETER :: M7N6MMye = 870 + INTEGER(IntKi), PARAMETER :: M7N7MMye = 871 + INTEGER(IntKi), PARAMETER :: M7N8MMye = 872 + INTEGER(IntKi), PARAMETER :: M7N9MMye = 873 + INTEGER(IntKi), PARAMETER :: M8N1MMye = 874 + INTEGER(IntKi), PARAMETER :: M8N2MMye = 875 + INTEGER(IntKi), PARAMETER :: M8N3MMye = 876 + INTEGER(IntKi), PARAMETER :: M8N4MMye = 877 + INTEGER(IntKi), PARAMETER :: M8N5MMye = 878 + INTEGER(IntKi), PARAMETER :: M8N6MMye = 879 + INTEGER(IntKi), PARAMETER :: M8N7MMye = 880 + INTEGER(IntKi), PARAMETER :: M8N8MMye = 881 + INTEGER(IntKi), PARAMETER :: M8N9MMye = 882 + INTEGER(IntKi), PARAMETER :: M9N1MMye = 883 + INTEGER(IntKi), PARAMETER :: M9N2MMye = 884 + INTEGER(IntKi), PARAMETER :: M9N3MMye = 885 + INTEGER(IntKi), PARAMETER :: M9N4MMye = 886 + INTEGER(IntKi), PARAMETER :: M9N5MMye = 887 + INTEGER(IntKi), PARAMETER :: M9N6MMye = 888 + INTEGER(IntKi), PARAMETER :: M9N7MMye = 889 + INTEGER(IntKi), PARAMETER :: M9N8MMye = 890 + INTEGER(IntKi), PARAMETER :: M9N9MMye = 891 + INTEGER(IntKi), PARAMETER :: M1N1MMze = 892 + INTEGER(IntKi), PARAMETER :: M1N2MMze = 893 + INTEGER(IntKi), PARAMETER :: M1N3MMze = 894 + INTEGER(IntKi), PARAMETER :: M1N4MMze = 895 + INTEGER(IntKi), PARAMETER :: M1N5MMze = 896 + INTEGER(IntKi), PARAMETER :: M1N6MMze = 897 + INTEGER(IntKi), PARAMETER :: M1N7MMze = 898 + INTEGER(IntKi), PARAMETER :: M1N8MMze = 899 + INTEGER(IntKi), PARAMETER :: M1N9MMze = 900 + INTEGER(IntKi), PARAMETER :: M2N1MMze = 901 + INTEGER(IntKi), PARAMETER :: M2N2MMze = 902 + INTEGER(IntKi), PARAMETER :: M2N3MMze = 903 + INTEGER(IntKi), PARAMETER :: M2N4MMze = 904 + INTEGER(IntKi), PARAMETER :: M2N5MMze = 905 + INTEGER(IntKi), PARAMETER :: M2N6MMze = 906 + INTEGER(IntKi), PARAMETER :: M2N7MMze = 907 + INTEGER(IntKi), PARAMETER :: M2N8MMze = 908 + INTEGER(IntKi), PARAMETER :: M2N9MMze = 909 + INTEGER(IntKi), PARAMETER :: M3N1MMze = 910 + INTEGER(IntKi), PARAMETER :: M3N2MMze = 911 + INTEGER(IntKi), PARAMETER :: M3N3MMze = 912 + INTEGER(IntKi), PARAMETER :: M3N4MMze = 913 + INTEGER(IntKi), PARAMETER :: M3N5MMze = 914 + INTEGER(IntKi), PARAMETER :: M3N6MMze = 915 + INTEGER(IntKi), PARAMETER :: M3N7MMze = 916 + INTEGER(IntKi), PARAMETER :: M3N8MMze = 917 + INTEGER(IntKi), PARAMETER :: M3N9MMze = 918 + INTEGER(IntKi), PARAMETER :: M4N1MMze = 919 + INTEGER(IntKi), PARAMETER :: M4N2MMze = 920 + INTEGER(IntKi), PARAMETER :: M4N3MMze = 921 + INTEGER(IntKi), PARAMETER :: M4N4MMze = 922 + INTEGER(IntKi), PARAMETER :: M4N5MMze = 923 + INTEGER(IntKi), PARAMETER :: M4N6MMze = 924 + INTEGER(IntKi), PARAMETER :: M4N7MMze = 925 + INTEGER(IntKi), PARAMETER :: M4N8MMze = 926 + INTEGER(IntKi), PARAMETER :: M4N9MMze = 927 + INTEGER(IntKi), PARAMETER :: M5N1MMze = 928 + INTEGER(IntKi), PARAMETER :: M5N2MMze = 929 + INTEGER(IntKi), PARAMETER :: M5N3MMze = 930 + INTEGER(IntKi), PARAMETER :: M5N4MMze = 931 + INTEGER(IntKi), PARAMETER :: M5N5MMze = 932 + INTEGER(IntKi), PARAMETER :: M5N6MMze = 933 + INTEGER(IntKi), PARAMETER :: M5N7MMze = 934 + INTEGER(IntKi), PARAMETER :: M5N8MMze = 935 + INTEGER(IntKi), PARAMETER :: M5N9MMze = 936 + INTEGER(IntKi), PARAMETER :: M6N1MMze = 937 + INTEGER(IntKi), PARAMETER :: M6N2MMze = 938 + INTEGER(IntKi), PARAMETER :: M6N3MMze = 939 + INTEGER(IntKi), PARAMETER :: M6N4MMze = 940 + INTEGER(IntKi), PARAMETER :: M6N5MMze = 941 + INTEGER(IntKi), PARAMETER :: M6N6MMze = 942 + INTEGER(IntKi), PARAMETER :: M6N7MMze = 943 + INTEGER(IntKi), PARAMETER :: M6N8MMze = 944 + INTEGER(IntKi), PARAMETER :: M6N9MMze = 945 + INTEGER(IntKi), PARAMETER :: M7N1MMze = 946 + INTEGER(IntKi), PARAMETER :: M7N2MMze = 947 + INTEGER(IntKi), PARAMETER :: M7N3MMze = 948 + INTEGER(IntKi), PARAMETER :: M7N4MMze = 949 + INTEGER(IntKi), PARAMETER :: M7N5MMze = 950 + INTEGER(IntKi), PARAMETER :: M7N6MMze = 951 + INTEGER(IntKi), PARAMETER :: M7N7MMze = 952 + INTEGER(IntKi), PARAMETER :: M7N8MMze = 953 + INTEGER(IntKi), PARAMETER :: M7N9MMze = 954 + INTEGER(IntKi), PARAMETER :: M8N1MMze = 955 + INTEGER(IntKi), PARAMETER :: M8N2MMze = 956 + INTEGER(IntKi), PARAMETER :: M8N3MMze = 957 + INTEGER(IntKi), PARAMETER :: M8N4MMze = 958 + INTEGER(IntKi), PARAMETER :: M8N5MMze = 959 + INTEGER(IntKi), PARAMETER :: M8N6MMze = 960 + INTEGER(IntKi), PARAMETER :: M8N7MMze = 961 + INTEGER(IntKi), PARAMETER :: M8N8MMze = 962 + INTEGER(IntKi), PARAMETER :: M8N9MMze = 963 + INTEGER(IntKi), PARAMETER :: M9N1MMze = 964 + INTEGER(IntKi), PARAMETER :: M9N2MMze = 965 + INTEGER(IntKi), PARAMETER :: M9N3MMze = 966 + INTEGER(IntKi), PARAMETER :: M9N4MMze = 967 + INTEGER(IntKi), PARAMETER :: M9N5MMze = 968 + INTEGER(IntKi), PARAMETER :: M9N6MMze = 969 + INTEGER(IntKi), PARAMETER :: M9N7MMze = 970 + INTEGER(IntKi), PARAMETER :: M9N8MMze = 971 + INTEGER(IntKi), PARAMETER :: M9N9MMze = 972 + + + ! Displacements: + + INTEGER(IntKi), PARAMETER :: M1N1TDxss = 973 + INTEGER(IntKi), PARAMETER :: M1N2TDxss = 974 + INTEGER(IntKi), PARAMETER :: M1N3TDxss = 975 + INTEGER(IntKi), PARAMETER :: M1N4TDxss = 976 + INTEGER(IntKi), PARAMETER :: M1N5TDxss = 977 + INTEGER(IntKi), PARAMETER :: M1N6TDxss = 978 + INTEGER(IntKi), PARAMETER :: M1N7TDxss = 979 + INTEGER(IntKi), PARAMETER :: M1N8TDxss = 980 + INTEGER(IntKi), PARAMETER :: M1N9TDxss = 981 + INTEGER(IntKi), PARAMETER :: M2N1TDxss = 982 + INTEGER(IntKi), PARAMETER :: M2N2TDxss = 983 + INTEGER(IntKi), PARAMETER :: M2N3TDxss = 984 + INTEGER(IntKi), PARAMETER :: M2N4TDxss = 985 + INTEGER(IntKi), PARAMETER :: M2N5TDxss = 986 + INTEGER(IntKi), PARAMETER :: M2N6TDxss = 987 + INTEGER(IntKi), PARAMETER :: M2N7TDxss = 988 + INTEGER(IntKi), PARAMETER :: M2N8TDxss = 989 + INTEGER(IntKi), PARAMETER :: M2N9TDxss = 990 + INTEGER(IntKi), PARAMETER :: M3N1TDxss = 991 + INTEGER(IntKi), PARAMETER :: M3N2TDxss = 992 + INTEGER(IntKi), PARAMETER :: M3N3TDxss = 993 + INTEGER(IntKi), PARAMETER :: M3N4TDxss = 994 + INTEGER(IntKi), PARAMETER :: M3N5TDxss = 995 + INTEGER(IntKi), PARAMETER :: M3N6TDxss = 996 + INTEGER(IntKi), PARAMETER :: M3N7TDxss = 997 + INTEGER(IntKi), PARAMETER :: M3N8TDxss = 998 + INTEGER(IntKi), PARAMETER :: M3N9TDxss = 999 + INTEGER(IntKi), PARAMETER :: M4N1TDxss = 1000 + INTEGER(IntKi), PARAMETER :: M4N2TDxss = 1001 + INTEGER(IntKi), PARAMETER :: M4N3TDxss = 1002 + INTEGER(IntKi), PARAMETER :: M4N4TDxss = 1003 + INTEGER(IntKi), PARAMETER :: M4N5TDxss = 1004 + INTEGER(IntKi), PARAMETER :: M4N6TDxss = 1005 + INTEGER(IntKi), PARAMETER :: M4N7TDxss = 1006 + INTEGER(IntKi), PARAMETER :: M4N8TDxss = 1007 + INTEGER(IntKi), PARAMETER :: M4N9TDxss = 1008 + INTEGER(IntKi), PARAMETER :: M5N1TDxss = 1009 + INTEGER(IntKi), PARAMETER :: M5N2TDxss = 1010 + INTEGER(IntKi), PARAMETER :: M5N3TDxss = 1011 + INTEGER(IntKi), PARAMETER :: M5N4TDxss = 1012 + INTEGER(IntKi), PARAMETER :: M5N5TDxss = 1013 + INTEGER(IntKi), PARAMETER :: M5N6TDxss = 1014 + INTEGER(IntKi), PARAMETER :: M5N7TDxss = 1015 + INTEGER(IntKi), PARAMETER :: M5N8TDxss = 1016 + INTEGER(IntKi), PARAMETER :: M5N9TDxss = 1017 + INTEGER(IntKi), PARAMETER :: M6N1TDxss = 1018 + INTEGER(IntKi), PARAMETER :: M6N2TDxss = 1019 + INTEGER(IntKi), PARAMETER :: M6N3TDxss = 1020 + INTEGER(IntKi), PARAMETER :: M6N4TDxss = 1021 + INTEGER(IntKi), PARAMETER :: M6N5TDxss = 1022 + INTEGER(IntKi), PARAMETER :: M6N6TDxss = 1023 + INTEGER(IntKi), PARAMETER :: M6N7TDxss = 1024 + INTEGER(IntKi), PARAMETER :: M6N8TDxss = 1025 + INTEGER(IntKi), PARAMETER :: M6N9TDxss = 1026 + INTEGER(IntKi), PARAMETER :: M7N1TDxss = 1027 + INTEGER(IntKi), PARAMETER :: M7N2TDxss = 1028 + INTEGER(IntKi), PARAMETER :: M7N3TDxss = 1029 + INTEGER(IntKi), PARAMETER :: M7N4TDxss = 1030 + INTEGER(IntKi), PARAMETER :: M7N5TDxss = 1031 + INTEGER(IntKi), PARAMETER :: M7N6TDxss = 1032 + INTEGER(IntKi), PARAMETER :: M7N7TDxss = 1033 + INTEGER(IntKi), PARAMETER :: M7N8TDxss = 1034 + INTEGER(IntKi), PARAMETER :: M7N9TDxss = 1035 + INTEGER(IntKi), PARAMETER :: M8N1TDxss = 1036 + INTEGER(IntKi), PARAMETER :: M8N2TDxss = 1037 + INTEGER(IntKi), PARAMETER :: M8N3TDxss = 1038 + INTEGER(IntKi), PARAMETER :: M8N4TDxss = 1039 + INTEGER(IntKi), PARAMETER :: M8N5TDxss = 1040 + INTEGER(IntKi), PARAMETER :: M8N6TDxss = 1041 + INTEGER(IntKi), PARAMETER :: M8N7TDxss = 1042 + INTEGER(IntKi), PARAMETER :: M8N8TDxss = 1043 + INTEGER(IntKi), PARAMETER :: M8N9TDxss = 1044 + INTEGER(IntKi), PARAMETER :: M9N1TDxss = 1045 + INTEGER(IntKi), PARAMETER :: M9N2TDxss = 1046 + INTEGER(IntKi), PARAMETER :: M9N3TDxss = 1047 + INTEGER(IntKi), PARAMETER :: M9N4TDxss = 1048 + INTEGER(IntKi), PARAMETER :: M9N5TDxss = 1049 + INTEGER(IntKi), PARAMETER :: M9N6TDxss = 1050 + INTEGER(IntKi), PARAMETER :: M9N7TDxss = 1051 + INTEGER(IntKi), PARAMETER :: M9N8TDxss = 1052 + INTEGER(IntKi), PARAMETER :: M9N9TDxss = 1053 + INTEGER(IntKi), PARAMETER :: M1N1TDyss = 1054 + INTEGER(IntKi), PARAMETER :: M1N2TDyss = 1055 + INTEGER(IntKi), PARAMETER :: M1N3TDyss = 1056 + INTEGER(IntKi), PARAMETER :: M1N4TDyss = 1057 + INTEGER(IntKi), PARAMETER :: M1N5TDyss = 1058 + INTEGER(IntKi), PARAMETER :: M1N6TDyss = 1059 + INTEGER(IntKi), PARAMETER :: M1N7TDyss = 1060 + INTEGER(IntKi), PARAMETER :: M1N8TDyss = 1061 + INTEGER(IntKi), PARAMETER :: M1N9TDyss = 1062 + INTEGER(IntKi), PARAMETER :: M2N1TDyss = 1063 + INTEGER(IntKi), PARAMETER :: M2N2TDyss = 1064 + INTEGER(IntKi), PARAMETER :: M2N3TDyss = 1065 + INTEGER(IntKi), PARAMETER :: M2N4TDyss = 1066 + INTEGER(IntKi), PARAMETER :: M2N5TDyss = 1067 + INTEGER(IntKi), PARAMETER :: M2N6TDyss = 1068 + INTEGER(IntKi), PARAMETER :: M2N7TDyss = 1069 + INTEGER(IntKi), PARAMETER :: M2N8TDyss = 1070 + INTEGER(IntKi), PARAMETER :: M2N9TDyss = 1071 + INTEGER(IntKi), PARAMETER :: M3N1TDyss = 1072 + INTEGER(IntKi), PARAMETER :: M3N2TDyss = 1073 + INTEGER(IntKi), PARAMETER :: M3N3TDyss = 1074 + INTEGER(IntKi), PARAMETER :: M3N4TDyss = 1075 + INTEGER(IntKi), PARAMETER :: M3N5TDyss = 1076 + INTEGER(IntKi), PARAMETER :: M3N6TDyss = 1077 + INTEGER(IntKi), PARAMETER :: M3N7TDyss = 1078 + INTEGER(IntKi), PARAMETER :: M3N8TDyss = 1079 + INTEGER(IntKi), PARAMETER :: M3N9TDyss = 1080 + INTEGER(IntKi), PARAMETER :: M4N1TDyss = 1081 + INTEGER(IntKi), PARAMETER :: M4N2TDyss = 1082 + INTEGER(IntKi), PARAMETER :: M4N3TDyss = 1083 + INTEGER(IntKi), PARAMETER :: M4N4TDyss = 1084 + INTEGER(IntKi), PARAMETER :: M4N5TDyss = 1085 + INTEGER(IntKi), PARAMETER :: M4N6TDyss = 1086 + INTEGER(IntKi), PARAMETER :: M4N7TDyss = 1087 + INTEGER(IntKi), PARAMETER :: M4N8TDyss = 1088 + INTEGER(IntKi), PARAMETER :: M4N9TDyss = 1089 + INTEGER(IntKi), PARAMETER :: M5N1TDyss = 1090 + INTEGER(IntKi), PARAMETER :: M5N2TDyss = 1091 + INTEGER(IntKi), PARAMETER :: M5N3TDyss = 1092 + INTEGER(IntKi), PARAMETER :: M5N4TDyss = 1093 + INTEGER(IntKi), PARAMETER :: M5N5TDyss = 1094 + INTEGER(IntKi), PARAMETER :: M5N6TDyss = 1095 + INTEGER(IntKi), PARAMETER :: M5N7TDyss = 1096 + INTEGER(IntKi), PARAMETER :: M5N8TDyss = 1097 + INTEGER(IntKi), PARAMETER :: M5N9TDyss = 1098 + INTEGER(IntKi), PARAMETER :: M6N1TDyss = 1099 + INTEGER(IntKi), PARAMETER :: M6N2TDyss = 1100 + INTEGER(IntKi), PARAMETER :: M6N3TDyss = 1101 + INTEGER(IntKi), PARAMETER :: M6N4TDyss = 1102 + INTEGER(IntKi), PARAMETER :: M6N5TDyss = 1103 + INTEGER(IntKi), PARAMETER :: M6N6TDyss = 1104 + INTEGER(IntKi), PARAMETER :: M6N7TDyss = 1105 + INTEGER(IntKi), PARAMETER :: M6N8TDyss = 1106 + INTEGER(IntKi), PARAMETER :: M6N9TDyss = 1107 + INTEGER(IntKi), PARAMETER :: M7N1TDyss = 1108 + INTEGER(IntKi), PARAMETER :: M7N2TDyss = 1109 + INTEGER(IntKi), PARAMETER :: M7N3TDyss = 1110 + INTEGER(IntKi), PARAMETER :: M7N4TDyss = 1111 + INTEGER(IntKi), PARAMETER :: M7N5TDyss = 1112 + INTEGER(IntKi), PARAMETER :: M7N6TDyss = 1113 + INTEGER(IntKi), PARAMETER :: M7N7TDyss = 1114 + INTEGER(IntKi), PARAMETER :: M7N8TDyss = 1115 + INTEGER(IntKi), PARAMETER :: M7N9TDyss = 1116 + INTEGER(IntKi), PARAMETER :: M8N1TDyss = 1117 + INTEGER(IntKi), PARAMETER :: M8N2TDyss = 1118 + INTEGER(IntKi), PARAMETER :: M8N3TDyss = 1119 + INTEGER(IntKi), PARAMETER :: M8N4TDyss = 1120 + INTEGER(IntKi), PARAMETER :: M8N5TDyss = 1121 + INTEGER(IntKi), PARAMETER :: M8N6TDyss = 1122 + INTEGER(IntKi), PARAMETER :: M8N7TDyss = 1123 + INTEGER(IntKi), PARAMETER :: M8N8TDyss = 1124 + INTEGER(IntKi), PARAMETER :: M8N9TDyss = 1125 + INTEGER(IntKi), PARAMETER :: M9N1TDyss = 1126 + INTEGER(IntKi), PARAMETER :: M9N2TDyss = 1127 + INTEGER(IntKi), PARAMETER :: M9N3TDyss = 1128 + INTEGER(IntKi), PARAMETER :: M9N4TDyss = 1129 + INTEGER(IntKi), PARAMETER :: M9N5TDyss = 1130 + INTEGER(IntKi), PARAMETER :: M9N6TDyss = 1131 + INTEGER(IntKi), PARAMETER :: M9N7TDyss = 1132 + INTEGER(IntKi), PARAMETER :: M9N8TDyss = 1133 + INTEGER(IntKi), PARAMETER :: M9N9TDyss = 1134 + INTEGER(IntKi), PARAMETER :: M1N1TDzss = 1135 + INTEGER(IntKi), PARAMETER :: M1N2TDzss = 1136 + INTEGER(IntKi), PARAMETER :: M1N3TDzss = 1137 + INTEGER(IntKi), PARAMETER :: M1N4TDzss = 1138 + INTEGER(IntKi), PARAMETER :: M1N5TDzss = 1139 + INTEGER(IntKi), PARAMETER :: M1N6TDzss = 1140 + INTEGER(IntKi), PARAMETER :: M1N7TDzss = 1141 + INTEGER(IntKi), PARAMETER :: M1N8TDzss = 1142 + INTEGER(IntKi), PARAMETER :: M1N9TDzss = 1143 + INTEGER(IntKi), PARAMETER :: M2N1TDzss = 1144 + INTEGER(IntKi), PARAMETER :: M2N2TDzss = 1145 + INTEGER(IntKi), PARAMETER :: M2N3TDzss = 1146 + INTEGER(IntKi), PARAMETER :: M2N4TDzss = 1147 + INTEGER(IntKi), PARAMETER :: M2N5TDzss = 1148 + INTEGER(IntKi), PARAMETER :: M2N6TDzss = 1149 + INTEGER(IntKi), PARAMETER :: M2N7TDzss = 1150 + INTEGER(IntKi), PARAMETER :: M2N8TDzss = 1151 + INTEGER(IntKi), PARAMETER :: M2N9TDzss = 1152 + INTEGER(IntKi), PARAMETER :: M3N1TDzss = 1153 + INTEGER(IntKi), PARAMETER :: M3N2TDzss = 1154 + INTEGER(IntKi), PARAMETER :: M3N3TDzss = 1155 + INTEGER(IntKi), PARAMETER :: M3N4TDzss = 1156 + INTEGER(IntKi), PARAMETER :: M3N5TDzss = 1157 + INTEGER(IntKi), PARAMETER :: M3N6TDzss = 1158 + INTEGER(IntKi), PARAMETER :: M3N7TDzss = 1159 + INTEGER(IntKi), PARAMETER :: M3N8TDzss = 1160 + INTEGER(IntKi), PARAMETER :: M3N9TDzss = 1161 + INTEGER(IntKi), PARAMETER :: M4N1TDzss = 1162 + INTEGER(IntKi), PARAMETER :: M4N2TDzss = 1163 + INTEGER(IntKi), PARAMETER :: M4N3TDzss = 1164 + INTEGER(IntKi), PARAMETER :: M4N4TDzss = 1165 + INTEGER(IntKi), PARAMETER :: M4N5TDzss = 1166 + INTEGER(IntKi), PARAMETER :: M4N6TDzss = 1167 + INTEGER(IntKi), PARAMETER :: M4N7TDzss = 1168 + INTEGER(IntKi), PARAMETER :: M4N8TDzss = 1169 + INTEGER(IntKi), PARAMETER :: M4N9TDzss = 1170 + INTEGER(IntKi), PARAMETER :: M5N1TDzss = 1171 + INTEGER(IntKi), PARAMETER :: M5N2TDzss = 1172 + INTEGER(IntKi), PARAMETER :: M5N3TDzss = 1173 + INTEGER(IntKi), PARAMETER :: M5N4TDzss = 1174 + INTEGER(IntKi), PARAMETER :: M5N5TDzss = 1175 + INTEGER(IntKi), PARAMETER :: M5N6TDzss = 1176 + INTEGER(IntKi), PARAMETER :: M5N7TDzss = 1177 + INTEGER(IntKi), PARAMETER :: M5N8TDzss = 1178 + INTEGER(IntKi), PARAMETER :: M5N9TDzss = 1179 + INTEGER(IntKi), PARAMETER :: M6N1TDzss = 1180 + INTEGER(IntKi), PARAMETER :: M6N2TDzss = 1181 + INTEGER(IntKi), PARAMETER :: M6N3TDzss = 1182 + INTEGER(IntKi), PARAMETER :: M6N4TDzss = 1183 + INTEGER(IntKi), PARAMETER :: M6N5TDzss = 1184 + INTEGER(IntKi), PARAMETER :: M6N6TDzss = 1185 + INTEGER(IntKi), PARAMETER :: M6N7TDzss = 1186 + INTEGER(IntKi), PARAMETER :: M6N8TDzss = 1187 + INTEGER(IntKi), PARAMETER :: M6N9TDzss = 1188 + INTEGER(IntKi), PARAMETER :: M7N1TDzss = 1189 + INTEGER(IntKi), PARAMETER :: M7N2TDzss = 1190 + INTEGER(IntKi), PARAMETER :: M7N3TDzss = 1191 + INTEGER(IntKi), PARAMETER :: M7N4TDzss = 1192 + INTEGER(IntKi), PARAMETER :: M7N5TDzss = 1193 + INTEGER(IntKi), PARAMETER :: M7N6TDzss = 1194 + INTEGER(IntKi), PARAMETER :: M7N7TDzss = 1195 + INTEGER(IntKi), PARAMETER :: M7N8TDzss = 1196 + INTEGER(IntKi), PARAMETER :: M7N9TDzss = 1197 + INTEGER(IntKi), PARAMETER :: M8N1TDzss = 1198 + INTEGER(IntKi), PARAMETER :: M8N2TDzss = 1199 + INTEGER(IntKi), PARAMETER :: M8N3TDzss = 1200 + INTEGER(IntKi), PARAMETER :: M8N4TDzss = 1201 + INTEGER(IntKi), PARAMETER :: M8N5TDzss = 1202 + INTEGER(IntKi), PARAMETER :: M8N6TDzss = 1203 + INTEGER(IntKi), PARAMETER :: M8N7TDzss = 1204 + INTEGER(IntKi), PARAMETER :: M8N8TDzss = 1205 + INTEGER(IntKi), PARAMETER :: M8N9TDzss = 1206 + INTEGER(IntKi), PARAMETER :: M9N1TDzss = 1207 + INTEGER(IntKi), PARAMETER :: M9N2TDzss = 1208 + INTEGER(IntKi), PARAMETER :: M9N3TDzss = 1209 + INTEGER(IntKi), PARAMETER :: M9N4TDzss = 1210 + INTEGER(IntKi), PARAMETER :: M9N5TDzss = 1211 + INTEGER(IntKi), PARAMETER :: M9N6TDzss = 1212 + INTEGER(IntKi), PARAMETER :: M9N7TDzss = 1213 + INTEGER(IntKi), PARAMETER :: M9N8TDzss = 1214 + INTEGER(IntKi), PARAMETER :: M9N9TDzss = 1215 + INTEGER(IntKi), PARAMETER :: M1N1RDxe = 1216 + INTEGER(IntKi), PARAMETER :: M1N2RDxe = 1217 + INTEGER(IntKi), PARAMETER :: M1N3RDxe = 1218 + INTEGER(IntKi), PARAMETER :: M1N4RDxe = 1219 + INTEGER(IntKi), PARAMETER :: M1N5RDxe = 1220 + INTEGER(IntKi), PARAMETER :: M1N6RDxe = 1221 + INTEGER(IntKi), PARAMETER :: M1N7RDxe = 1222 + INTEGER(IntKi), PARAMETER :: M1N8RDxe = 1223 + INTEGER(IntKi), PARAMETER :: M1N9RDxe = 1224 + INTEGER(IntKi), PARAMETER :: M2N1RDxe = 1225 + INTEGER(IntKi), PARAMETER :: M2N2RDxe = 1226 + INTEGER(IntKi), PARAMETER :: M2N3RDxe = 1227 + INTEGER(IntKi), PARAMETER :: M2N4RDxe = 1228 + INTEGER(IntKi), PARAMETER :: M2N5RDxe = 1229 + INTEGER(IntKi), PARAMETER :: M2N6RDxe = 1230 + INTEGER(IntKi), PARAMETER :: M2N7RDxe = 1231 + INTEGER(IntKi), PARAMETER :: M2N8RDxe = 1232 + INTEGER(IntKi), PARAMETER :: M2N9RDxe = 1233 + INTEGER(IntKi), PARAMETER :: M3N1RDxe = 1234 + INTEGER(IntKi), PARAMETER :: M3N2RDxe = 1235 + INTEGER(IntKi), PARAMETER :: M3N3RDxe = 1236 + INTEGER(IntKi), PARAMETER :: M3N4RDxe = 1237 + INTEGER(IntKi), PARAMETER :: M3N5RDxe = 1238 + INTEGER(IntKi), PARAMETER :: M3N6RDxe = 1239 + INTEGER(IntKi), PARAMETER :: M3N7RDxe = 1240 + INTEGER(IntKi), PARAMETER :: M3N8RDxe = 1241 + INTEGER(IntKi), PARAMETER :: M3N9RDxe = 1242 + INTEGER(IntKi), PARAMETER :: M4N1RDxe = 1243 + INTEGER(IntKi), PARAMETER :: M4N2RDxe = 1244 + INTEGER(IntKi), PARAMETER :: M4N3RDxe = 1245 + INTEGER(IntKi), PARAMETER :: M4N4RDxe = 1246 + INTEGER(IntKi), PARAMETER :: M4N5RDxe = 1247 + INTEGER(IntKi), PARAMETER :: M4N6RDxe = 1248 + INTEGER(IntKi), PARAMETER :: M4N7RDxe = 1249 + INTEGER(IntKi), PARAMETER :: M4N8RDxe = 1250 + INTEGER(IntKi), PARAMETER :: M4N9RDxe = 1251 + INTEGER(IntKi), PARAMETER :: M5N1RDxe = 1252 + INTEGER(IntKi), PARAMETER :: M5N2RDxe = 1253 + INTEGER(IntKi), PARAMETER :: M5N3RDxe = 1254 + INTEGER(IntKi), PARAMETER :: M5N4RDxe = 1255 + INTEGER(IntKi), PARAMETER :: M5N5RDxe = 1256 + INTEGER(IntKi), PARAMETER :: M5N6RDxe = 1257 + INTEGER(IntKi), PARAMETER :: M5N7RDxe = 1258 + INTEGER(IntKi), PARAMETER :: M5N8RDxe = 1259 + INTEGER(IntKi), PARAMETER :: M5N9RDxe = 1260 + INTEGER(IntKi), PARAMETER :: M6N1RDxe = 1261 + INTEGER(IntKi), PARAMETER :: M6N2RDxe = 1262 + INTEGER(IntKi), PARAMETER :: M6N3RDxe = 1263 + INTEGER(IntKi), PARAMETER :: M6N4RDxe = 1264 + INTEGER(IntKi), PARAMETER :: M6N5RDxe = 1265 + INTEGER(IntKi), PARAMETER :: M6N6RDxe = 1266 + INTEGER(IntKi), PARAMETER :: M6N7RDxe = 1267 + INTEGER(IntKi), PARAMETER :: M6N8RDxe = 1268 + INTEGER(IntKi), PARAMETER :: M6N9RDxe = 1269 + INTEGER(IntKi), PARAMETER :: M7N1RDxe = 1270 + INTEGER(IntKi), PARAMETER :: M7N2RDxe = 1271 + INTEGER(IntKi), PARAMETER :: M7N3RDxe = 1272 + INTEGER(IntKi), PARAMETER :: M7N4RDxe = 1273 + INTEGER(IntKi), PARAMETER :: M7N5RDxe = 1274 + INTEGER(IntKi), PARAMETER :: M7N6RDxe = 1275 + INTEGER(IntKi), PARAMETER :: M7N7RDxe = 1276 + INTEGER(IntKi), PARAMETER :: M7N8RDxe = 1277 + INTEGER(IntKi), PARAMETER :: M7N9RDxe = 1278 + INTEGER(IntKi), PARAMETER :: M8N1RDxe = 1279 + INTEGER(IntKi), PARAMETER :: M8N2RDxe = 1280 + INTEGER(IntKi), PARAMETER :: M8N3RDxe = 1281 + INTEGER(IntKi), PARAMETER :: M8N4RDxe = 1282 + INTEGER(IntKi), PARAMETER :: M8N5RDxe = 1283 + INTEGER(IntKi), PARAMETER :: M8N6RDxe = 1284 + INTEGER(IntKi), PARAMETER :: M8N7RDxe = 1285 + INTEGER(IntKi), PARAMETER :: M8N8RDxe = 1286 + INTEGER(IntKi), PARAMETER :: M8N9RDxe = 1287 + INTEGER(IntKi), PARAMETER :: M9N1RDxe = 1288 + INTEGER(IntKi), PARAMETER :: M9N2RDxe = 1289 + INTEGER(IntKi), PARAMETER :: M9N3RDxe = 1290 + INTEGER(IntKi), PARAMETER :: M9N4RDxe = 1291 + INTEGER(IntKi), PARAMETER :: M9N5RDxe = 1292 + INTEGER(IntKi), PARAMETER :: M9N6RDxe = 1293 + INTEGER(IntKi), PARAMETER :: M9N7RDxe = 1294 + INTEGER(IntKi), PARAMETER :: M9N8RDxe = 1295 + INTEGER(IntKi), PARAMETER :: M9N9RDxe = 1296 + INTEGER(IntKi), PARAMETER :: M1N1RDye = 1297 + INTEGER(IntKi), PARAMETER :: M1N2RDye = 1298 + INTEGER(IntKi), PARAMETER :: M1N3RDye = 1299 + INTEGER(IntKi), PARAMETER :: M1N4RDye = 1300 + INTEGER(IntKi), PARAMETER :: M1N5RDye = 1301 + INTEGER(IntKi), PARAMETER :: M1N6RDye = 1302 + INTEGER(IntKi), PARAMETER :: M1N7RDye = 1303 + INTEGER(IntKi), PARAMETER :: M1N8RDye = 1304 + INTEGER(IntKi), PARAMETER :: M1N9RDye = 1305 + INTEGER(IntKi), PARAMETER :: M2N1RDye = 1306 + INTEGER(IntKi), PARAMETER :: M2N2RDye = 1307 + INTEGER(IntKi), PARAMETER :: M2N3RDye = 1308 + INTEGER(IntKi), PARAMETER :: M2N4RDye = 1309 + INTEGER(IntKi), PARAMETER :: M2N5RDye = 1310 + INTEGER(IntKi), PARAMETER :: M2N6RDye = 1311 + INTEGER(IntKi), PARAMETER :: M2N7RDye = 1312 + INTEGER(IntKi), PARAMETER :: M2N8RDye = 1313 + INTEGER(IntKi), PARAMETER :: M2N9RDye = 1314 + INTEGER(IntKi), PARAMETER :: M3N1RDye = 1315 + INTEGER(IntKi), PARAMETER :: M3N2RDye = 1316 + INTEGER(IntKi), PARAMETER :: M3N3RDye = 1317 + INTEGER(IntKi), PARAMETER :: M3N4RDye = 1318 + INTEGER(IntKi), PARAMETER :: M3N5RDye = 1319 + INTEGER(IntKi), PARAMETER :: M3N6RDye = 1320 + INTEGER(IntKi), PARAMETER :: M3N7RDye = 1321 + INTEGER(IntKi), PARAMETER :: M3N8RDye = 1322 + INTEGER(IntKi), PARAMETER :: M3N9RDye = 1323 + INTEGER(IntKi), PARAMETER :: M4N1RDye = 1324 + INTEGER(IntKi), PARAMETER :: M4N2RDye = 1325 + INTEGER(IntKi), PARAMETER :: M4N3RDye = 1326 + INTEGER(IntKi), PARAMETER :: M4N4RDye = 1327 + INTEGER(IntKi), PARAMETER :: M4N5RDye = 1328 + INTEGER(IntKi), PARAMETER :: M4N6RDye = 1329 + INTEGER(IntKi), PARAMETER :: M4N7RDye = 1330 + INTEGER(IntKi), PARAMETER :: M4N8RDye = 1331 + INTEGER(IntKi), PARAMETER :: M4N9RDye = 1332 + INTEGER(IntKi), PARAMETER :: M5N1RDye = 1333 + INTEGER(IntKi), PARAMETER :: M5N2RDye = 1334 + INTEGER(IntKi), PARAMETER :: M5N3RDye = 1335 + INTEGER(IntKi), PARAMETER :: M5N4RDye = 1336 + INTEGER(IntKi), PARAMETER :: M5N5RDye = 1337 + INTEGER(IntKi), PARAMETER :: M5N6RDye = 1338 + INTEGER(IntKi), PARAMETER :: M5N7RDye = 1339 + INTEGER(IntKi), PARAMETER :: M5N8RDye = 1340 + INTEGER(IntKi), PARAMETER :: M5N9RDye = 1341 + INTEGER(IntKi), PARAMETER :: M6N1RDye = 1342 + INTEGER(IntKi), PARAMETER :: M6N2RDye = 1343 + INTEGER(IntKi), PARAMETER :: M6N3RDye = 1344 + INTEGER(IntKi), PARAMETER :: M6N4RDye = 1345 + INTEGER(IntKi), PARAMETER :: M6N5RDye = 1346 + INTEGER(IntKi), PARAMETER :: M6N6RDye = 1347 + INTEGER(IntKi), PARAMETER :: M6N7RDye = 1348 + INTEGER(IntKi), PARAMETER :: M6N8RDye = 1349 + INTEGER(IntKi), PARAMETER :: M6N9RDye = 1350 + INTEGER(IntKi), PARAMETER :: M7N1RDye = 1351 + INTEGER(IntKi), PARAMETER :: M7N2RDye = 1352 + INTEGER(IntKi), PARAMETER :: M7N3RDye = 1353 + INTEGER(IntKi), PARAMETER :: M7N4RDye = 1354 + INTEGER(IntKi), PARAMETER :: M7N5RDye = 1355 + INTEGER(IntKi), PARAMETER :: M7N6RDye = 1356 + INTEGER(IntKi), PARAMETER :: M7N7RDye = 1357 + INTEGER(IntKi), PARAMETER :: M7N8RDye = 1358 + INTEGER(IntKi), PARAMETER :: M7N9RDye = 1359 + INTEGER(IntKi), PARAMETER :: M8N1RDye = 1360 + INTEGER(IntKi), PARAMETER :: M8N2RDye = 1361 + INTEGER(IntKi), PARAMETER :: M8N3RDye = 1362 + INTEGER(IntKi), PARAMETER :: M8N4RDye = 1363 + INTEGER(IntKi), PARAMETER :: M8N5RDye = 1364 + INTEGER(IntKi), PARAMETER :: M8N6RDye = 1365 + INTEGER(IntKi), PARAMETER :: M8N7RDye = 1366 + INTEGER(IntKi), PARAMETER :: M8N8RDye = 1367 + INTEGER(IntKi), PARAMETER :: M8N9RDye = 1368 + INTEGER(IntKi), PARAMETER :: M9N1RDye = 1369 + INTEGER(IntKi), PARAMETER :: M9N2RDye = 1370 + INTEGER(IntKi), PARAMETER :: M9N3RDye = 1371 + INTEGER(IntKi), PARAMETER :: M9N4RDye = 1372 + INTEGER(IntKi), PARAMETER :: M9N5RDye = 1373 + INTEGER(IntKi), PARAMETER :: M9N6RDye = 1374 + INTEGER(IntKi), PARAMETER :: M9N7RDye = 1375 + INTEGER(IntKi), PARAMETER :: M9N8RDye = 1376 + INTEGER(IntKi), PARAMETER :: M9N9RDye = 1377 + INTEGER(IntKi), PARAMETER :: M1N1RDze = 1378 + INTEGER(IntKi), PARAMETER :: M1N2RDze = 1379 + INTEGER(IntKi), PARAMETER :: M1N3RDze = 1380 + INTEGER(IntKi), PARAMETER :: M1N4RDze = 1381 + INTEGER(IntKi), PARAMETER :: M1N5RDze = 1382 + INTEGER(IntKi), PARAMETER :: M1N6RDze = 1383 + INTEGER(IntKi), PARAMETER :: M1N7RDze = 1384 + INTEGER(IntKi), PARAMETER :: M1N8RDze = 1385 + INTEGER(IntKi), PARAMETER :: M1N9RDze = 1386 + INTEGER(IntKi), PARAMETER :: M2N1RDze = 1387 + INTEGER(IntKi), PARAMETER :: M2N2RDze = 1388 + INTEGER(IntKi), PARAMETER :: M2N3RDze = 1389 + INTEGER(IntKi), PARAMETER :: M2N4RDze = 1390 + INTEGER(IntKi), PARAMETER :: M2N5RDze = 1391 + INTEGER(IntKi), PARAMETER :: M2N6RDze = 1392 + INTEGER(IntKi), PARAMETER :: M2N7RDze = 1393 + INTEGER(IntKi), PARAMETER :: M2N8RDze = 1394 + INTEGER(IntKi), PARAMETER :: M2N9RDze = 1395 + INTEGER(IntKi), PARAMETER :: M3N1RDze = 1396 + INTEGER(IntKi), PARAMETER :: M3N2RDze = 1397 + INTEGER(IntKi), PARAMETER :: M3N3RDze = 1398 + INTEGER(IntKi), PARAMETER :: M3N4RDze = 1399 + INTEGER(IntKi), PARAMETER :: M3N5RDze = 1400 + INTEGER(IntKi), PARAMETER :: M3N6RDze = 1401 + INTEGER(IntKi), PARAMETER :: M3N7RDze = 1402 + INTEGER(IntKi), PARAMETER :: M3N8RDze = 1403 + INTEGER(IntKi), PARAMETER :: M3N9RDze = 1404 + INTEGER(IntKi), PARAMETER :: M4N1RDze = 1405 + INTEGER(IntKi), PARAMETER :: M4N2RDze = 1406 + INTEGER(IntKi), PARAMETER :: M4N3RDze = 1407 + INTEGER(IntKi), PARAMETER :: M4N4RDze = 1408 + INTEGER(IntKi), PARAMETER :: M4N5RDze = 1409 + INTEGER(IntKi), PARAMETER :: M4N6RDze = 1410 + INTEGER(IntKi), PARAMETER :: M4N7RDze = 1411 + INTEGER(IntKi), PARAMETER :: M4N8RDze = 1412 + INTEGER(IntKi), PARAMETER :: M4N9RDze = 1413 + INTEGER(IntKi), PARAMETER :: M5N1RDze = 1414 + INTEGER(IntKi), PARAMETER :: M5N2RDze = 1415 + INTEGER(IntKi), PARAMETER :: M5N3RDze = 1416 + INTEGER(IntKi), PARAMETER :: M5N4RDze = 1417 + INTEGER(IntKi), PARAMETER :: M5N5RDze = 1418 + INTEGER(IntKi), PARAMETER :: M5N6RDze = 1419 + INTEGER(IntKi), PARAMETER :: M5N7RDze = 1420 + INTEGER(IntKi), PARAMETER :: M5N8RDze = 1421 + INTEGER(IntKi), PARAMETER :: M5N9RDze = 1422 + INTEGER(IntKi), PARAMETER :: M6N1RDze = 1423 + INTEGER(IntKi), PARAMETER :: M6N2RDze = 1424 + INTEGER(IntKi), PARAMETER :: M6N3RDze = 1425 + INTEGER(IntKi), PARAMETER :: M6N4RDze = 1426 + INTEGER(IntKi), PARAMETER :: M6N5RDze = 1427 + INTEGER(IntKi), PARAMETER :: M6N6RDze = 1428 + INTEGER(IntKi), PARAMETER :: M6N7RDze = 1429 + INTEGER(IntKi), PARAMETER :: M6N8RDze = 1430 + INTEGER(IntKi), PARAMETER :: M6N9RDze = 1431 + INTEGER(IntKi), PARAMETER :: M7N1RDze = 1432 + INTEGER(IntKi), PARAMETER :: M7N2RDze = 1433 + INTEGER(IntKi), PARAMETER :: M7N3RDze = 1434 + INTEGER(IntKi), PARAMETER :: M7N4RDze = 1435 + INTEGER(IntKi), PARAMETER :: M7N5RDze = 1436 + INTEGER(IntKi), PARAMETER :: M7N6RDze = 1437 + INTEGER(IntKi), PARAMETER :: M7N7RDze = 1438 + INTEGER(IntKi), PARAMETER :: M7N8RDze = 1439 + INTEGER(IntKi), PARAMETER :: M7N9RDze = 1440 + INTEGER(IntKi), PARAMETER :: M8N1RDze = 1441 + INTEGER(IntKi), PARAMETER :: M8N2RDze = 1442 + INTEGER(IntKi), PARAMETER :: M8N3RDze = 1443 + INTEGER(IntKi), PARAMETER :: M8N4RDze = 1444 + INTEGER(IntKi), PARAMETER :: M8N5RDze = 1445 + INTEGER(IntKi), PARAMETER :: M8N6RDze = 1446 + INTEGER(IntKi), PARAMETER :: M8N7RDze = 1447 + INTEGER(IntKi), PARAMETER :: M8N8RDze = 1448 + INTEGER(IntKi), PARAMETER :: M8N9RDze = 1449 + INTEGER(IntKi), PARAMETER :: M9N1RDze = 1450 + INTEGER(IntKi), PARAMETER :: M9N2RDze = 1451 + INTEGER(IntKi), PARAMETER :: M9N3RDze = 1452 + INTEGER(IntKi), PARAMETER :: M9N4RDze = 1453 + INTEGER(IntKi), PARAMETER :: M9N5RDze = 1454 + INTEGER(IntKi), PARAMETER :: M9N6RDze = 1455 + INTEGER(IntKi), PARAMETER :: M9N7RDze = 1456 + INTEGER(IntKi), PARAMETER :: M9N8RDze = 1457 + INTEGER(IntKi), PARAMETER :: M9N9RDze = 1458 + + + ! Accelerations: + + INTEGER(IntKi), PARAMETER :: M1N1TAxe = 1459 + INTEGER(IntKi), PARAMETER :: M1N2TAxe = 1460 + INTEGER(IntKi), PARAMETER :: M1N3TAxe = 1461 + INTEGER(IntKi), PARAMETER :: M1N4TAxe = 1462 + INTEGER(IntKi), PARAMETER :: M1N5TAxe = 1463 + INTEGER(IntKi), PARAMETER :: M1N6TAxe = 1464 + INTEGER(IntKi), PARAMETER :: M1N7TAxe = 1465 + INTEGER(IntKi), PARAMETER :: M1N8TAxe = 1466 + INTEGER(IntKi), PARAMETER :: M1N9TAxe = 1467 + INTEGER(IntKi), PARAMETER :: M2N1TAxe = 1468 + INTEGER(IntKi), PARAMETER :: M2N2TAxe = 1469 + INTEGER(IntKi), PARAMETER :: M2N3TAxe = 1470 + INTEGER(IntKi), PARAMETER :: M2N4TAxe = 1471 + INTEGER(IntKi), PARAMETER :: M2N5TAxe = 1472 + INTEGER(IntKi), PARAMETER :: M2N6TAxe = 1473 + INTEGER(IntKi), PARAMETER :: M2N7TAxe = 1474 + INTEGER(IntKi), PARAMETER :: M2N8TAxe = 1475 + INTEGER(IntKi), PARAMETER :: M2N9TAxe = 1476 + INTEGER(IntKi), PARAMETER :: M3N1TAxe = 1477 + INTEGER(IntKi), PARAMETER :: M3N2TAxe = 1478 + INTEGER(IntKi), PARAMETER :: M3N3TAxe = 1479 + INTEGER(IntKi), PARAMETER :: M3N4TAxe = 1480 + INTEGER(IntKi), PARAMETER :: M3N5TAxe = 1481 + INTEGER(IntKi), PARAMETER :: M3N6TAxe = 1482 + INTEGER(IntKi), PARAMETER :: M3N7TAxe = 1483 + INTEGER(IntKi), PARAMETER :: M3N8TAxe = 1484 + INTEGER(IntKi), PARAMETER :: M3N9TAxe = 1485 + INTEGER(IntKi), PARAMETER :: M4N1TAxe = 1486 + INTEGER(IntKi), PARAMETER :: M4N2TAxe = 1487 + INTEGER(IntKi), PARAMETER :: M4N3TAxe = 1488 + INTEGER(IntKi), PARAMETER :: M4N4TAxe = 1489 + INTEGER(IntKi), PARAMETER :: M4N5TAxe = 1490 + INTEGER(IntKi), PARAMETER :: M4N6TAxe = 1491 + INTEGER(IntKi), PARAMETER :: M4N7TAxe = 1492 + INTEGER(IntKi), PARAMETER :: M4N8TAxe = 1493 + INTEGER(IntKi), PARAMETER :: M4N9TAxe = 1494 + INTEGER(IntKi), PARAMETER :: M5N1TAxe = 1495 + INTEGER(IntKi), PARAMETER :: M5N2TAxe = 1496 + INTEGER(IntKi), PARAMETER :: M5N3TAxe = 1497 + INTEGER(IntKi), PARAMETER :: M5N4TAxe = 1498 + INTEGER(IntKi), PARAMETER :: M5N5TAxe = 1499 + INTEGER(IntKi), PARAMETER :: M5N6TAxe = 1500 + INTEGER(IntKi), PARAMETER :: M5N7TAxe = 1501 + INTEGER(IntKi), PARAMETER :: M5N8TAxe = 1502 + INTEGER(IntKi), PARAMETER :: M5N9TAxe = 1503 + INTEGER(IntKi), PARAMETER :: M6N1TAxe = 1504 + INTEGER(IntKi), PARAMETER :: M6N2TAxe = 1505 + INTEGER(IntKi), PARAMETER :: M6N3TAxe = 1506 + INTEGER(IntKi), PARAMETER :: M6N4TAxe = 1507 + INTEGER(IntKi), PARAMETER :: M6N5TAxe = 1508 + INTEGER(IntKi), PARAMETER :: M6N6TAxe = 1509 + INTEGER(IntKi), PARAMETER :: M6N7TAxe = 1510 + INTEGER(IntKi), PARAMETER :: M6N8TAxe = 1511 + INTEGER(IntKi), PARAMETER :: M6N9TAxe = 1512 + INTEGER(IntKi), PARAMETER :: M7N1TAxe = 1513 + INTEGER(IntKi), PARAMETER :: M7N2TAxe = 1514 + INTEGER(IntKi), PARAMETER :: M7N3TAxe = 1515 + INTEGER(IntKi), PARAMETER :: M7N4TAxe = 1516 + INTEGER(IntKi), PARAMETER :: M7N5TAxe = 1517 + INTEGER(IntKi), PARAMETER :: M7N6TAxe = 1518 + INTEGER(IntKi), PARAMETER :: M7N7TAxe = 1519 + INTEGER(IntKi), PARAMETER :: M7N8TAxe = 1520 + INTEGER(IntKi), PARAMETER :: M7N9TAxe = 1521 + INTEGER(IntKi), PARAMETER :: M8N1TAxe = 1522 + INTEGER(IntKi), PARAMETER :: M8N2TAxe = 1523 + INTEGER(IntKi), PARAMETER :: M8N3TAxe = 1524 + INTEGER(IntKi), PARAMETER :: M8N4TAxe = 1525 + INTEGER(IntKi), PARAMETER :: M8N5TAxe = 1526 + INTEGER(IntKi), PARAMETER :: M8N6TAxe = 1527 + INTEGER(IntKi), PARAMETER :: M8N7TAxe = 1528 + INTEGER(IntKi), PARAMETER :: M8N8TAxe = 1529 + INTEGER(IntKi), PARAMETER :: M8N9TAxe = 1530 + INTEGER(IntKi), PARAMETER :: M9N1TAxe = 1531 + INTEGER(IntKi), PARAMETER :: M9N2TAxe = 1532 + INTEGER(IntKi), PARAMETER :: M9N3TAxe = 1533 + INTEGER(IntKi), PARAMETER :: M9N4TAxe = 1534 + INTEGER(IntKi), PARAMETER :: M9N5TAxe = 1535 + INTEGER(IntKi), PARAMETER :: M9N6TAxe = 1536 + INTEGER(IntKi), PARAMETER :: M9N7TAxe = 1537 + INTEGER(IntKi), PARAMETER :: M9N8TAxe = 1538 + INTEGER(IntKi), PARAMETER :: M9N9TAxe = 1539 + INTEGER(IntKi), PARAMETER :: M1N1TAye = 1540 + INTEGER(IntKi), PARAMETER :: M1N2TAye = 1541 + INTEGER(IntKi), PARAMETER :: M1N3TAye = 1542 + INTEGER(IntKi), PARAMETER :: M1N4TAye = 1543 + INTEGER(IntKi), PARAMETER :: M1N5TAye = 1544 + INTEGER(IntKi), PARAMETER :: M1N6TAye = 1545 + INTEGER(IntKi), PARAMETER :: M1N7TAye = 1546 + INTEGER(IntKi), PARAMETER :: M1N8TAye = 1547 + INTEGER(IntKi), PARAMETER :: M1N9TAye = 1548 + INTEGER(IntKi), PARAMETER :: M2N1TAye = 1549 + INTEGER(IntKi), PARAMETER :: M2N2TAye = 1550 + INTEGER(IntKi), PARAMETER :: M2N3TAye = 1551 + INTEGER(IntKi), PARAMETER :: M2N4TAye = 1552 + INTEGER(IntKi), PARAMETER :: M2N5TAye = 1553 + INTEGER(IntKi), PARAMETER :: M2N6TAye = 1554 + INTEGER(IntKi), PARAMETER :: M2N7TAye = 1555 + INTEGER(IntKi), PARAMETER :: M2N8TAye = 1556 + INTEGER(IntKi), PARAMETER :: M2N9TAye = 1557 + INTEGER(IntKi), PARAMETER :: M3N1TAye = 1558 + INTEGER(IntKi), PARAMETER :: M3N2TAye = 1559 + INTEGER(IntKi), PARAMETER :: M3N3TAye = 1560 + INTEGER(IntKi), PARAMETER :: M3N4TAye = 1561 + INTEGER(IntKi), PARAMETER :: M3N5TAye = 1562 + INTEGER(IntKi), PARAMETER :: M3N6TAye = 1563 + INTEGER(IntKi), PARAMETER :: M3N7TAye = 1564 + INTEGER(IntKi), PARAMETER :: M3N8TAye = 1565 + INTEGER(IntKi), PARAMETER :: M3N9TAye = 1566 + INTEGER(IntKi), PARAMETER :: M4N1TAye = 1567 + INTEGER(IntKi), PARAMETER :: M4N2TAye = 1568 + INTEGER(IntKi), PARAMETER :: M4N3TAye = 1569 + INTEGER(IntKi), PARAMETER :: M4N4TAye = 1570 + INTEGER(IntKi), PARAMETER :: M4N5TAye = 1571 + INTEGER(IntKi), PARAMETER :: M4N6TAye = 1572 + INTEGER(IntKi), PARAMETER :: M4N7TAye = 1573 + INTEGER(IntKi), PARAMETER :: M4N8TAye = 1574 + INTEGER(IntKi), PARAMETER :: M4N9TAye = 1575 + INTEGER(IntKi), PARAMETER :: M5N1TAye = 1576 + INTEGER(IntKi), PARAMETER :: M5N2TAye = 1577 + INTEGER(IntKi), PARAMETER :: M5N3TAye = 1578 + INTEGER(IntKi), PARAMETER :: M5N4TAye = 1579 + INTEGER(IntKi), PARAMETER :: M5N5TAye = 1580 + INTEGER(IntKi), PARAMETER :: M5N6TAye = 1581 + INTEGER(IntKi), PARAMETER :: M5N7TAye = 1582 + INTEGER(IntKi), PARAMETER :: M5N8TAye = 1583 + INTEGER(IntKi), PARAMETER :: M5N9TAye = 1584 + INTEGER(IntKi), PARAMETER :: M6N1TAye = 1585 + INTEGER(IntKi), PARAMETER :: M6N2TAye = 1586 + INTEGER(IntKi), PARAMETER :: M6N3TAye = 1587 + INTEGER(IntKi), PARAMETER :: M6N4TAye = 1588 + INTEGER(IntKi), PARAMETER :: M6N5TAye = 1589 + INTEGER(IntKi), PARAMETER :: M6N6TAye = 1590 + INTEGER(IntKi), PARAMETER :: M6N7TAye = 1591 + INTEGER(IntKi), PARAMETER :: M6N8TAye = 1592 + INTEGER(IntKi), PARAMETER :: M6N9TAye = 1593 + INTEGER(IntKi), PARAMETER :: M7N1TAye = 1594 + INTEGER(IntKi), PARAMETER :: M7N2TAye = 1595 + INTEGER(IntKi), PARAMETER :: M7N3TAye = 1596 + INTEGER(IntKi), PARAMETER :: M7N4TAye = 1597 + INTEGER(IntKi), PARAMETER :: M7N5TAye = 1598 + INTEGER(IntKi), PARAMETER :: M7N6TAye = 1599 + INTEGER(IntKi), PARAMETER :: M7N7TAye = 1600 + INTEGER(IntKi), PARAMETER :: M7N8TAye = 1601 + INTEGER(IntKi), PARAMETER :: M7N9TAye = 1602 + INTEGER(IntKi), PARAMETER :: M8N1TAye = 1603 + INTEGER(IntKi), PARAMETER :: M8N2TAye = 1604 + INTEGER(IntKi), PARAMETER :: M8N3TAye = 1605 + INTEGER(IntKi), PARAMETER :: M8N4TAye = 1606 + INTEGER(IntKi), PARAMETER :: M8N5TAye = 1607 + INTEGER(IntKi), PARAMETER :: M8N6TAye = 1608 + INTEGER(IntKi), PARAMETER :: M8N7TAye = 1609 + INTEGER(IntKi), PARAMETER :: M8N8TAye = 1610 + INTEGER(IntKi), PARAMETER :: M8N9TAye = 1611 + INTEGER(IntKi), PARAMETER :: M9N1TAye = 1612 + INTEGER(IntKi), PARAMETER :: M9N2TAye = 1613 + INTEGER(IntKi), PARAMETER :: M9N3TAye = 1614 + INTEGER(IntKi), PARAMETER :: M9N4TAye = 1615 + INTEGER(IntKi), PARAMETER :: M9N5TAye = 1616 + INTEGER(IntKi), PARAMETER :: M9N6TAye = 1617 + INTEGER(IntKi), PARAMETER :: M9N7TAye = 1618 + INTEGER(IntKi), PARAMETER :: M9N8TAye = 1619 + INTEGER(IntKi), PARAMETER :: M9N9TAye = 1620 + INTEGER(IntKi), PARAMETER :: M1N1TAze = 1621 + INTEGER(IntKi), PARAMETER :: M1N2TAze = 1622 + INTEGER(IntKi), PARAMETER :: M1N3TAze = 1623 + INTEGER(IntKi), PARAMETER :: M1N4TAze = 1624 + INTEGER(IntKi), PARAMETER :: M1N5TAze = 1625 + INTEGER(IntKi), PARAMETER :: M1N6TAze = 1626 + INTEGER(IntKi), PARAMETER :: M1N7TAze = 1627 + INTEGER(IntKi), PARAMETER :: M1N8TAze = 1628 + INTEGER(IntKi), PARAMETER :: M1N9TAze = 1629 + INTEGER(IntKi), PARAMETER :: M2N1TAze = 1630 + INTEGER(IntKi), PARAMETER :: M2N2TAze = 1631 + INTEGER(IntKi), PARAMETER :: M2N3TAze = 1632 + INTEGER(IntKi), PARAMETER :: M2N4TAze = 1633 + INTEGER(IntKi), PARAMETER :: M2N5TAze = 1634 + INTEGER(IntKi), PARAMETER :: M2N6TAze = 1635 + INTEGER(IntKi), PARAMETER :: M2N7TAze = 1636 + INTEGER(IntKi), PARAMETER :: M2N8TAze = 1637 + INTEGER(IntKi), PARAMETER :: M2N9TAze = 1638 + INTEGER(IntKi), PARAMETER :: M3N1TAze = 1639 + INTEGER(IntKi), PARAMETER :: M3N2TAze = 1640 + INTEGER(IntKi), PARAMETER :: M3N3TAze = 1641 + INTEGER(IntKi), PARAMETER :: M3N4TAze = 1642 + INTEGER(IntKi), PARAMETER :: M3N5TAze = 1643 + INTEGER(IntKi), PARAMETER :: M3N6TAze = 1644 + INTEGER(IntKi), PARAMETER :: M3N7TAze = 1645 + INTEGER(IntKi), PARAMETER :: M3N8TAze = 1646 + INTEGER(IntKi), PARAMETER :: M3N9TAze = 1647 + INTEGER(IntKi), PARAMETER :: M4N1TAze = 1648 + INTEGER(IntKi), PARAMETER :: M4N2TAze = 1649 + INTEGER(IntKi), PARAMETER :: M4N3TAze = 1650 + INTEGER(IntKi), PARAMETER :: M4N4TAze = 1651 + INTEGER(IntKi), PARAMETER :: M4N5TAze = 1652 + INTEGER(IntKi), PARAMETER :: M4N6TAze = 1653 + INTEGER(IntKi), PARAMETER :: M4N7TAze = 1654 + INTEGER(IntKi), PARAMETER :: M4N8TAze = 1655 + INTEGER(IntKi), PARAMETER :: M4N9TAze = 1656 + INTEGER(IntKi), PARAMETER :: M5N1TAze = 1657 + INTEGER(IntKi), PARAMETER :: M5N2TAze = 1658 + INTEGER(IntKi), PARAMETER :: M5N3TAze = 1659 + INTEGER(IntKi), PARAMETER :: M5N4TAze = 1660 + INTEGER(IntKi), PARAMETER :: M5N5TAze = 1661 + INTEGER(IntKi), PARAMETER :: M5N6TAze = 1662 + INTEGER(IntKi), PARAMETER :: M5N7TAze = 1663 + INTEGER(IntKi), PARAMETER :: M5N8TAze = 1664 + INTEGER(IntKi), PARAMETER :: M5N9TAze = 1665 + INTEGER(IntKi), PARAMETER :: M6N1TAze = 1666 + INTEGER(IntKi), PARAMETER :: M6N2TAze = 1667 + INTEGER(IntKi), PARAMETER :: M6N3TAze = 1668 + INTEGER(IntKi), PARAMETER :: M6N4TAze = 1669 + INTEGER(IntKi), PARAMETER :: M6N5TAze = 1670 + INTEGER(IntKi), PARAMETER :: M6N6TAze = 1671 + INTEGER(IntKi), PARAMETER :: M6N7TAze = 1672 + INTEGER(IntKi), PARAMETER :: M6N8TAze = 1673 + INTEGER(IntKi), PARAMETER :: M6N9TAze = 1674 + INTEGER(IntKi), PARAMETER :: M7N1TAze = 1675 + INTEGER(IntKi), PARAMETER :: M7N2TAze = 1676 + INTEGER(IntKi), PARAMETER :: M7N3TAze = 1677 + INTEGER(IntKi), PARAMETER :: M7N4TAze = 1678 + INTEGER(IntKi), PARAMETER :: M7N5TAze = 1679 + INTEGER(IntKi), PARAMETER :: M7N6TAze = 1680 + INTEGER(IntKi), PARAMETER :: M7N7TAze = 1681 + INTEGER(IntKi), PARAMETER :: M7N8TAze = 1682 + INTEGER(IntKi), PARAMETER :: M7N9TAze = 1683 + INTEGER(IntKi), PARAMETER :: M8N1TAze = 1684 + INTEGER(IntKi), PARAMETER :: M8N2TAze = 1685 + INTEGER(IntKi), PARAMETER :: M8N3TAze = 1686 + INTEGER(IntKi), PARAMETER :: M8N4TAze = 1687 + INTEGER(IntKi), PARAMETER :: M8N5TAze = 1688 + INTEGER(IntKi), PARAMETER :: M8N6TAze = 1689 + INTEGER(IntKi), PARAMETER :: M8N7TAze = 1690 + INTEGER(IntKi), PARAMETER :: M8N8TAze = 1691 + INTEGER(IntKi), PARAMETER :: M8N9TAze = 1692 + INTEGER(IntKi), PARAMETER :: M9N1TAze = 1693 + INTEGER(IntKi), PARAMETER :: M9N2TAze = 1694 + INTEGER(IntKi), PARAMETER :: M9N3TAze = 1695 + INTEGER(IntKi), PARAMETER :: M9N4TAze = 1696 + INTEGER(IntKi), PARAMETER :: M9N5TAze = 1697 + INTEGER(IntKi), PARAMETER :: M9N6TAze = 1698 + INTEGER(IntKi), PARAMETER :: M9N7TAze = 1699 + INTEGER(IntKi), PARAMETER :: M9N8TAze = 1700 + INTEGER(IntKi), PARAMETER :: M9N9TAze = 1701 + INTEGER(IntKi), PARAMETER :: M1N1RAxe = 1702 + INTEGER(IntKi), PARAMETER :: M1N2RAxe = 1703 + INTEGER(IntKi), PARAMETER :: M1N3RAxe = 1704 + INTEGER(IntKi), PARAMETER :: M1N4RAxe = 1705 + INTEGER(IntKi), PARAMETER :: M1N5RAxe = 1706 + INTEGER(IntKi), PARAMETER :: M1N6RAxe = 1707 + INTEGER(IntKi), PARAMETER :: M1N7RAxe = 1708 + INTEGER(IntKi), PARAMETER :: M1N8RAxe = 1709 + INTEGER(IntKi), PARAMETER :: M1N9RAxe = 1710 + INTEGER(IntKi), PARAMETER :: M2N1RAxe = 1711 + INTEGER(IntKi), PARAMETER :: M2N2RAxe = 1712 + INTEGER(IntKi), PARAMETER :: M2N3RAxe = 1713 + INTEGER(IntKi), PARAMETER :: M2N4RAxe = 1714 + INTEGER(IntKi), PARAMETER :: M2N5RAxe = 1715 + INTEGER(IntKi), PARAMETER :: M2N6RAxe = 1716 + INTEGER(IntKi), PARAMETER :: M2N7RAxe = 1717 + INTEGER(IntKi), PARAMETER :: M2N8RAxe = 1718 + INTEGER(IntKi), PARAMETER :: M2N9RAxe = 1719 + INTEGER(IntKi), PARAMETER :: M3N1RAxe = 1720 + INTEGER(IntKi), PARAMETER :: M3N2RAxe = 1721 + INTEGER(IntKi), PARAMETER :: M3N3RAxe = 1722 + INTEGER(IntKi), PARAMETER :: M3N4RAxe = 1723 + INTEGER(IntKi), PARAMETER :: M3N5RAxe = 1724 + INTEGER(IntKi), PARAMETER :: M3N6RAxe = 1725 + INTEGER(IntKi), PARAMETER :: M3N7RAxe = 1726 + INTEGER(IntKi), PARAMETER :: M3N8RAxe = 1727 + INTEGER(IntKi), PARAMETER :: M3N9RAxe = 1728 + INTEGER(IntKi), PARAMETER :: M4N1RAxe = 1729 + INTEGER(IntKi), PARAMETER :: M4N2RAxe = 1730 + INTEGER(IntKi), PARAMETER :: M4N3RAxe = 1731 + INTEGER(IntKi), PARAMETER :: M4N4RAxe = 1732 + INTEGER(IntKi), PARAMETER :: M4N5RAxe = 1733 + INTEGER(IntKi), PARAMETER :: M4N6RAxe = 1734 + INTEGER(IntKi), PARAMETER :: M4N7RAxe = 1735 + INTEGER(IntKi), PARAMETER :: M4N8RAxe = 1736 + INTEGER(IntKi), PARAMETER :: M4N9RAxe = 1737 + INTEGER(IntKi), PARAMETER :: M5N1RAxe = 1738 + INTEGER(IntKi), PARAMETER :: M5N2RAxe = 1739 + INTEGER(IntKi), PARAMETER :: M5N3RAxe = 1740 + INTEGER(IntKi), PARAMETER :: M5N4RAxe = 1741 + INTEGER(IntKi), PARAMETER :: M5N5RAxe = 1742 + INTEGER(IntKi), PARAMETER :: M5N6RAxe = 1743 + INTEGER(IntKi), PARAMETER :: M5N7RAxe = 1744 + INTEGER(IntKi), PARAMETER :: M5N8RAxe = 1745 + INTEGER(IntKi), PARAMETER :: M5N9RAxe = 1746 + INTEGER(IntKi), PARAMETER :: M6N1RAxe = 1747 + INTEGER(IntKi), PARAMETER :: M6N2RAxe = 1748 + INTEGER(IntKi), PARAMETER :: M6N3RAxe = 1749 + INTEGER(IntKi), PARAMETER :: M6N4RAxe = 1750 + INTEGER(IntKi), PARAMETER :: M6N5RAxe = 1751 + INTEGER(IntKi), PARAMETER :: M6N6RAxe = 1752 + INTEGER(IntKi), PARAMETER :: M6N7RAxe = 1753 + INTEGER(IntKi), PARAMETER :: M6N8RAxe = 1754 + INTEGER(IntKi), PARAMETER :: M6N9RAxe = 1755 + INTEGER(IntKi), PARAMETER :: M7N1RAxe = 1756 + INTEGER(IntKi), PARAMETER :: M7N2RAxe = 1757 + INTEGER(IntKi), PARAMETER :: M7N3RAxe = 1758 + INTEGER(IntKi), PARAMETER :: M7N4RAxe = 1759 + INTEGER(IntKi), PARAMETER :: M7N5RAxe = 1760 + INTEGER(IntKi), PARAMETER :: M7N6RAxe = 1761 + INTEGER(IntKi), PARAMETER :: M7N7RAxe = 1762 + INTEGER(IntKi), PARAMETER :: M7N8RAxe = 1763 + INTEGER(IntKi), PARAMETER :: M7N9RAxe = 1764 + INTEGER(IntKi), PARAMETER :: M8N1RAxe = 1765 + INTEGER(IntKi), PARAMETER :: M8N2RAxe = 1766 + INTEGER(IntKi), PARAMETER :: M8N3RAxe = 1767 + INTEGER(IntKi), PARAMETER :: M8N4RAxe = 1768 + INTEGER(IntKi), PARAMETER :: M8N5RAxe = 1769 + INTEGER(IntKi), PARAMETER :: M8N6RAxe = 1770 + INTEGER(IntKi), PARAMETER :: M8N7RAxe = 1771 + INTEGER(IntKi), PARAMETER :: M8N8RAxe = 1772 + INTEGER(IntKi), PARAMETER :: M8N9RAxe = 1773 + INTEGER(IntKi), PARAMETER :: M9N1RAxe = 1774 + INTEGER(IntKi), PARAMETER :: M9N2RAxe = 1775 + INTEGER(IntKi), PARAMETER :: M9N3RAxe = 1776 + INTEGER(IntKi), PARAMETER :: M9N4RAxe = 1777 + INTEGER(IntKi), PARAMETER :: M9N5RAxe = 1778 + INTEGER(IntKi), PARAMETER :: M9N6RAxe = 1779 + INTEGER(IntKi), PARAMETER :: M9N7RAxe = 1780 + INTEGER(IntKi), PARAMETER :: M9N8RAxe = 1781 + INTEGER(IntKi), PARAMETER :: M9N9RAxe = 1782 + INTEGER(IntKi), PARAMETER :: M1N1RAye = 1783 + INTEGER(IntKi), PARAMETER :: M1N2RAye = 1784 + INTEGER(IntKi), PARAMETER :: M1N3RAye = 1785 + INTEGER(IntKi), PARAMETER :: M1N4RAye = 1786 + INTEGER(IntKi), PARAMETER :: M1N5RAye = 1787 + INTEGER(IntKi), PARAMETER :: M1N6RAye = 1788 + INTEGER(IntKi), PARAMETER :: M1N7RAye = 1789 + INTEGER(IntKi), PARAMETER :: M1N8RAye = 1790 + INTEGER(IntKi), PARAMETER :: M1N9RAye = 1791 + INTEGER(IntKi), PARAMETER :: M2N1RAye = 1792 + INTEGER(IntKi), PARAMETER :: M2N2RAye = 1793 + INTEGER(IntKi), PARAMETER :: M2N3RAye = 1794 + INTEGER(IntKi), PARAMETER :: M2N4RAye = 1795 + INTEGER(IntKi), PARAMETER :: M2N5RAye = 1796 + INTEGER(IntKi), PARAMETER :: M2N6RAye = 1797 + INTEGER(IntKi), PARAMETER :: M2N7RAye = 1798 + INTEGER(IntKi), PARAMETER :: M2N8RAye = 1799 + INTEGER(IntKi), PARAMETER :: M2N9RAye = 1800 + INTEGER(IntKi), PARAMETER :: M3N1RAye = 1801 + INTEGER(IntKi), PARAMETER :: M3N2RAye = 1802 + INTEGER(IntKi), PARAMETER :: M3N3RAye = 1803 + INTEGER(IntKi), PARAMETER :: M3N4RAye = 1804 + INTEGER(IntKi), PARAMETER :: M3N5RAye = 1805 + INTEGER(IntKi), PARAMETER :: M3N6RAye = 1806 + INTEGER(IntKi), PARAMETER :: M3N7RAye = 1807 + INTEGER(IntKi), PARAMETER :: M3N8RAye = 1808 + INTEGER(IntKi), PARAMETER :: M3N9RAye = 1809 + INTEGER(IntKi), PARAMETER :: M4N1RAye = 1810 + INTEGER(IntKi), PARAMETER :: M4N2RAye = 1811 + INTEGER(IntKi), PARAMETER :: M4N3RAye = 1812 + INTEGER(IntKi), PARAMETER :: M4N4RAye = 1813 + INTEGER(IntKi), PARAMETER :: M4N5RAye = 1814 + INTEGER(IntKi), PARAMETER :: M4N6RAye = 1815 + INTEGER(IntKi), PARAMETER :: M4N7RAye = 1816 + INTEGER(IntKi), PARAMETER :: M4N8RAye = 1817 + INTEGER(IntKi), PARAMETER :: M4N9RAye = 1818 + INTEGER(IntKi), PARAMETER :: M5N1RAye = 1819 + INTEGER(IntKi), PARAMETER :: M5N2RAye = 1820 + INTEGER(IntKi), PARAMETER :: M5N3RAye = 1821 + INTEGER(IntKi), PARAMETER :: M5N4RAye = 1822 + INTEGER(IntKi), PARAMETER :: M5N5RAye = 1823 + INTEGER(IntKi), PARAMETER :: M5N6RAye = 1824 + INTEGER(IntKi), PARAMETER :: M5N7RAye = 1825 + INTEGER(IntKi), PARAMETER :: M5N8RAye = 1826 + INTEGER(IntKi), PARAMETER :: M5N9RAye = 1827 + INTEGER(IntKi), PARAMETER :: M6N1RAye = 1828 + INTEGER(IntKi), PARAMETER :: M6N2RAye = 1829 + INTEGER(IntKi), PARAMETER :: M6N3RAye = 1830 + INTEGER(IntKi), PARAMETER :: M6N4RAye = 1831 + INTEGER(IntKi), PARAMETER :: M6N5RAye = 1832 + INTEGER(IntKi), PARAMETER :: M6N6RAye = 1833 + INTEGER(IntKi), PARAMETER :: M6N7RAye = 1834 + INTEGER(IntKi), PARAMETER :: M6N8RAye = 1835 + INTEGER(IntKi), PARAMETER :: M6N9RAye = 1836 + INTEGER(IntKi), PARAMETER :: M7N1RAye = 1837 + INTEGER(IntKi), PARAMETER :: M7N2RAye = 1838 + INTEGER(IntKi), PARAMETER :: M7N3RAye = 1839 + INTEGER(IntKi), PARAMETER :: M7N4RAye = 1840 + INTEGER(IntKi), PARAMETER :: M7N5RAye = 1841 + INTEGER(IntKi), PARAMETER :: M7N6RAye = 1842 + INTEGER(IntKi), PARAMETER :: M7N7RAye = 1843 + INTEGER(IntKi), PARAMETER :: M7N8RAye = 1844 + INTEGER(IntKi), PARAMETER :: M7N9RAye = 1845 + INTEGER(IntKi), PARAMETER :: M8N1RAye = 1846 + INTEGER(IntKi), PARAMETER :: M8N2RAye = 1847 + INTEGER(IntKi), PARAMETER :: M8N3RAye = 1848 + INTEGER(IntKi), PARAMETER :: M8N4RAye = 1849 + INTEGER(IntKi), PARAMETER :: M8N5RAye = 1850 + INTEGER(IntKi), PARAMETER :: M8N6RAye = 1851 + INTEGER(IntKi), PARAMETER :: M8N7RAye = 1852 + INTEGER(IntKi), PARAMETER :: M8N8RAye = 1853 + INTEGER(IntKi), PARAMETER :: M8N9RAye = 1854 + INTEGER(IntKi), PARAMETER :: M9N1RAye = 1855 + INTEGER(IntKi), PARAMETER :: M9N2RAye = 1856 + INTEGER(IntKi), PARAMETER :: M9N3RAye = 1857 + INTEGER(IntKi), PARAMETER :: M9N4RAye = 1858 + INTEGER(IntKi), PARAMETER :: M9N5RAye = 1859 + INTEGER(IntKi), PARAMETER :: M9N6RAye = 1860 + INTEGER(IntKi), PARAMETER :: M9N7RAye = 1861 + INTEGER(IntKi), PARAMETER :: M9N8RAye = 1862 + INTEGER(IntKi), PARAMETER :: M9N9RAye = 1863 + INTEGER(IntKi), PARAMETER :: M1N1RAze = 1864 + INTEGER(IntKi), PARAMETER :: M1N2RAze = 1865 + INTEGER(IntKi), PARAMETER :: M1N3RAze = 1866 + INTEGER(IntKi), PARAMETER :: M1N4RAze = 1867 + INTEGER(IntKi), PARAMETER :: M1N5RAze = 1868 + INTEGER(IntKi), PARAMETER :: M1N6RAze = 1869 + INTEGER(IntKi), PARAMETER :: M1N7RAze = 1870 + INTEGER(IntKi), PARAMETER :: M1N8RAze = 1871 + INTEGER(IntKi), PARAMETER :: M1N9RAze = 1872 + INTEGER(IntKi), PARAMETER :: M2N1RAze = 1873 + INTEGER(IntKi), PARAMETER :: M2N2RAze = 1874 + INTEGER(IntKi), PARAMETER :: M2N3RAze = 1875 + INTEGER(IntKi), PARAMETER :: M2N4RAze = 1876 + INTEGER(IntKi), PARAMETER :: M2N5RAze = 1877 + INTEGER(IntKi), PARAMETER :: M2N6RAze = 1878 + INTEGER(IntKi), PARAMETER :: M2N7RAze = 1879 + INTEGER(IntKi), PARAMETER :: M2N8RAze = 1880 + INTEGER(IntKi), PARAMETER :: M2N9RAze = 1881 + INTEGER(IntKi), PARAMETER :: M3N1RAze = 1882 + INTEGER(IntKi), PARAMETER :: M3N2RAze = 1883 + INTEGER(IntKi), PARAMETER :: M3N3RAze = 1884 + INTEGER(IntKi), PARAMETER :: M3N4RAze = 1885 + INTEGER(IntKi), PARAMETER :: M3N5RAze = 1886 + INTEGER(IntKi), PARAMETER :: M3N6RAze = 1887 + INTEGER(IntKi), PARAMETER :: M3N7RAze = 1888 + INTEGER(IntKi), PARAMETER :: M3N8RAze = 1889 + INTEGER(IntKi), PARAMETER :: M3N9RAze = 1890 + INTEGER(IntKi), PARAMETER :: M4N1RAze = 1891 + INTEGER(IntKi), PARAMETER :: M4N2RAze = 1892 + INTEGER(IntKi), PARAMETER :: M4N3RAze = 1893 + INTEGER(IntKi), PARAMETER :: M4N4RAze = 1894 + INTEGER(IntKi), PARAMETER :: M4N5RAze = 1895 + INTEGER(IntKi), PARAMETER :: M4N6RAze = 1896 + INTEGER(IntKi), PARAMETER :: M4N7RAze = 1897 + INTEGER(IntKi), PARAMETER :: M4N8RAze = 1898 + INTEGER(IntKi), PARAMETER :: M4N9RAze = 1899 + INTEGER(IntKi), PARAMETER :: M5N1RAze = 1900 + INTEGER(IntKi), PARAMETER :: M5N2RAze = 1901 + INTEGER(IntKi), PARAMETER :: M5N3RAze = 1902 + INTEGER(IntKi), PARAMETER :: M5N4RAze = 1903 + INTEGER(IntKi), PARAMETER :: M5N5RAze = 1904 + INTEGER(IntKi), PARAMETER :: M5N6RAze = 1905 + INTEGER(IntKi), PARAMETER :: M5N7RAze = 1906 + INTEGER(IntKi), PARAMETER :: M5N8RAze = 1907 + INTEGER(IntKi), PARAMETER :: M5N9RAze = 1908 + INTEGER(IntKi), PARAMETER :: M6N1RAze = 1909 + INTEGER(IntKi), PARAMETER :: M6N2RAze = 1910 + INTEGER(IntKi), PARAMETER :: M6N3RAze = 1911 + INTEGER(IntKi), PARAMETER :: M6N4RAze = 1912 + INTEGER(IntKi), PARAMETER :: M6N5RAze = 1913 + INTEGER(IntKi), PARAMETER :: M6N6RAze = 1914 + INTEGER(IntKi), PARAMETER :: M6N7RAze = 1915 + INTEGER(IntKi), PARAMETER :: M6N8RAze = 1916 + INTEGER(IntKi), PARAMETER :: M6N9RAze = 1917 + INTEGER(IntKi), PARAMETER :: M7N1RAze = 1918 + INTEGER(IntKi), PARAMETER :: M7N2RAze = 1919 + INTEGER(IntKi), PARAMETER :: M7N3RAze = 1920 + INTEGER(IntKi), PARAMETER :: M7N4RAze = 1921 + INTEGER(IntKi), PARAMETER :: M7N5RAze = 1922 + INTEGER(IntKi), PARAMETER :: M7N6RAze = 1923 + INTEGER(IntKi), PARAMETER :: M7N7RAze = 1924 + INTEGER(IntKi), PARAMETER :: M7N8RAze = 1925 + INTEGER(IntKi), PARAMETER :: M7N9RAze = 1926 + INTEGER(IntKi), PARAMETER :: M8N1RAze = 1927 + INTEGER(IntKi), PARAMETER :: M8N2RAze = 1928 + INTEGER(IntKi), PARAMETER :: M8N3RAze = 1929 + INTEGER(IntKi), PARAMETER :: M8N4RAze = 1930 + INTEGER(IntKi), PARAMETER :: M8N5RAze = 1931 + INTEGER(IntKi), PARAMETER :: M8N6RAze = 1932 + INTEGER(IntKi), PARAMETER :: M8N7RAze = 1933 + INTEGER(IntKi), PARAMETER :: M8N8RAze = 1934 + INTEGER(IntKi), PARAMETER :: M8N9RAze = 1935 + INTEGER(IntKi), PARAMETER :: M9N1RAze = 1936 + INTEGER(IntKi), PARAMETER :: M9N2RAze = 1937 + INTEGER(IntKi), PARAMETER :: M9N3RAze = 1938 + INTEGER(IntKi), PARAMETER :: M9N4RAze = 1939 + INTEGER(IntKi), PARAMETER :: M9N5RAze = 1940 + INTEGER(IntKi), PARAMETER :: M9N6RAze = 1941 + INTEGER(IntKi), PARAMETER :: M9N7RAze = 1942 + INTEGER(IntKi), PARAMETER :: M9N8RAze = 1943 + INTEGER(IntKi), PARAMETER :: M9N9RAze = 1944 + + + ! Reactions: + + INTEGER(IntKi), PARAMETER :: ReactFXss = 1945 + INTEGER(IntKi), PARAMETER :: ReactFYss = 1946 + INTEGER(IntKi), PARAMETER :: ReactFZss = 1947 + INTEGER(IntKi), PARAMETER :: ReactMXss = 1948 + INTEGER(IntKi), PARAMETER :: ReactMYss = 1949 + INTEGER(IntKi), PARAMETER :: ReactMZss = 1950 + INTEGER(IntKi), PARAMETER :: IntfFXss = 1951 + INTEGER(IntKi), PARAMETER :: IntfFYss = 1952 + INTEGER(IntKi), PARAMETER :: IntfFZss = 1953 + INTEGER(IntKi), PARAMETER :: IntfMXss = 1954 + INTEGER(IntKi), PARAMETER :: IntfMYss = 1955 + INTEGER(IntKi), PARAMETER :: IntfMZss = 1956 + + + ! Interface Deflections: + + INTEGER(IntKi), PARAMETER :: IntfTDXss = 1957 + INTEGER(IntKi), PARAMETER :: IntfTDYss = 1958 + INTEGER(IntKi), PARAMETER :: IntfTDZss = 1959 + INTEGER(IntKi), PARAMETER :: IntfRDXss = 1960 + INTEGER(IntKi), PARAMETER :: IntfRDYss = 1961 + INTEGER(IntKi), PARAMETER :: IntfRDZss = 1962 + + + ! Interface Accelerations: + + INTEGER(IntKi), PARAMETER :: IntfTAXss = 1963 + INTEGER(IntKi), PARAMETER :: IntfTAYss = 1964 + INTEGER(IntKi), PARAMETER :: IntfTAZss = 1965 + INTEGER(IntKi), PARAMETER :: IntfRAXss = 1966 + INTEGER(IntKi), PARAMETER :: IntfRAYss = 1967 + INTEGER(IntKi), PARAMETER :: IntfRAZss = 1968 + + + ! Modal Parameters: + + INTEGER(IntKi), PARAMETER :: SSqm01 = 1969 + INTEGER(IntKi), PARAMETER :: SSqm02 = 1970 + INTEGER(IntKi), PARAMETER :: SSqm03 = 1971 + INTEGER(IntKi), PARAMETER :: SSqm04 = 1972 + INTEGER(IntKi), PARAMETER :: SSqm05 = 1973 + INTEGER(IntKi), PARAMETER :: SSqm06 = 1974 + INTEGER(IntKi), PARAMETER :: SSqm07 = 1975 + INTEGER(IntKi), PARAMETER :: SSqm08 = 1976 + INTEGER(IntKi), PARAMETER :: SSqm09 = 1977 + INTEGER(IntKi), PARAMETER :: SSqm10 = 1978 + INTEGER(IntKi), PARAMETER :: SSqm11 = 1979 + INTEGER(IntKi), PARAMETER :: SSqm12 = 1980 + INTEGER(IntKi), PARAMETER :: SSqm13 = 1981 + INTEGER(IntKi), PARAMETER :: SSqm14 = 1982 + INTEGER(IntKi), PARAMETER :: SSqm15 = 1983 + INTEGER(IntKi), PARAMETER :: SSqm16 = 1984 + INTEGER(IntKi), PARAMETER :: SSqm17 = 1985 + INTEGER(IntKi), PARAMETER :: SSqm18 = 1986 + INTEGER(IntKi), PARAMETER :: SSqm19 = 1987 + INTEGER(IntKi), PARAMETER :: SSqm20 = 1988 + INTEGER(IntKi), PARAMETER :: SSqm21 = 1989 + INTEGER(IntKi), PARAMETER :: SSqm22 = 1990 + INTEGER(IntKi), PARAMETER :: SSqm23 = 1991 + INTEGER(IntKi), PARAMETER :: SSqm24 = 1992 + INTEGER(IntKi), PARAMETER :: SSqm25 = 1993 + INTEGER(IntKi), PARAMETER :: SSqm26 = 1994 + INTEGER(IntKi), PARAMETER :: SSqm27 = 1995 + INTEGER(IntKi), PARAMETER :: SSqm28 = 1996 + INTEGER(IntKi), PARAMETER :: SSqm29 = 1997 + INTEGER(IntKi), PARAMETER :: SSqm30 = 1998 + INTEGER(IntKi), PARAMETER :: SSqm31 = 1999 + INTEGER(IntKi), PARAMETER :: SSqm32 = 2000 + INTEGER(IntKi), PARAMETER :: SSqm33 = 2001 + INTEGER(IntKi), PARAMETER :: SSqm34 = 2002 + INTEGER(IntKi), PARAMETER :: SSqm35 = 2003 + INTEGER(IntKi), PARAMETER :: SSqm36 = 2004 + INTEGER(IntKi), PARAMETER :: SSqm37 = 2005 + INTEGER(IntKi), PARAMETER :: SSqm38 = 2006 + INTEGER(IntKi), PARAMETER :: SSqm39 = 2007 + INTEGER(IntKi), PARAMETER :: SSqm40 = 2008 + INTEGER(IntKi), PARAMETER :: SSqm41 = 2009 + INTEGER(IntKi), PARAMETER :: SSqm42 = 2010 + INTEGER(IntKi), PARAMETER :: SSqm43 = 2011 + INTEGER(IntKi), PARAMETER :: SSqm44 = 2012 + INTEGER(IntKi), PARAMETER :: SSqm45 = 2013 + INTEGER(IntKi), PARAMETER :: SSqm46 = 2014 + INTEGER(IntKi), PARAMETER :: SSqm47 = 2015 + INTEGER(IntKi), PARAMETER :: SSqm48 = 2016 + INTEGER(IntKi), PARAMETER :: SSqm49 = 2017 + INTEGER(IntKi), PARAMETER :: SSqm50 = 2018 + INTEGER(IntKi), PARAMETER :: SSqm51 = 2019 + INTEGER(IntKi), PARAMETER :: SSqm52 = 2020 + INTEGER(IntKi), PARAMETER :: SSqm53 = 2021 + INTEGER(IntKi), PARAMETER :: SSqm54 = 2022 + INTEGER(IntKi), PARAMETER :: SSqm55 = 2023 + INTEGER(IntKi), PARAMETER :: SSqm56 = 2024 + INTEGER(IntKi), PARAMETER :: SSqm57 = 2025 + INTEGER(IntKi), PARAMETER :: SSqm58 = 2026 + INTEGER(IntKi), PARAMETER :: SSqm59 = 2027 + INTEGER(IntKi), PARAMETER :: SSqm60 = 2028 + INTEGER(IntKi), PARAMETER :: SSqm61 = 2029 + INTEGER(IntKi), PARAMETER :: SSqm62 = 2030 + INTEGER(IntKi), PARAMETER :: SSqm63 = 2031 + INTEGER(IntKi), PARAMETER :: SSqm64 = 2032 + INTEGER(IntKi), PARAMETER :: SSqm65 = 2033 + INTEGER(IntKi), PARAMETER :: SSqm66 = 2034 + INTEGER(IntKi), PARAMETER :: SSqm67 = 2035 + INTEGER(IntKi), PARAMETER :: SSqm68 = 2036 + INTEGER(IntKi), PARAMETER :: SSqm69 = 2037 + INTEGER(IntKi), PARAMETER :: SSqm70 = 2038 + INTEGER(IntKi), PARAMETER :: SSqm71 = 2039 + INTEGER(IntKi), PARAMETER :: SSqm72 = 2040 + INTEGER(IntKi), PARAMETER :: SSqm73 = 2041 + INTEGER(IntKi), PARAMETER :: SSqm74 = 2042 + INTEGER(IntKi), PARAMETER :: SSqm75 = 2043 + INTEGER(IntKi), PARAMETER :: SSqm76 = 2044 + INTEGER(IntKi), PARAMETER :: SSqm77 = 2045 + INTEGER(IntKi), PARAMETER :: SSqm78 = 2046 + INTEGER(IntKi), PARAMETER :: SSqm79 = 2047 + INTEGER(IntKi), PARAMETER :: SSqm80 = 2048 + INTEGER(IntKi), PARAMETER :: SSqm81 = 2049 + INTEGER(IntKi), PARAMETER :: SSqm82 = 2050 + INTEGER(IntKi), PARAMETER :: SSqm83 = 2051 + INTEGER(IntKi), PARAMETER :: SSqm84 = 2052 + INTEGER(IntKi), PARAMETER :: SSqm85 = 2053 + INTEGER(IntKi), PARAMETER :: SSqm86 = 2054 + INTEGER(IntKi), PARAMETER :: SSqm87 = 2055 + INTEGER(IntKi), PARAMETER :: SSqm88 = 2056 + INTEGER(IntKi), PARAMETER :: SSqm89 = 2057 + INTEGER(IntKi), PARAMETER :: SSqm90 = 2058 + INTEGER(IntKi), PARAMETER :: SSqm91 = 2059 + INTEGER(IntKi), PARAMETER :: SSqm92 = 2060 + INTEGER(IntKi), PARAMETER :: SSqm93 = 2061 + INTEGER(IntKi), PARAMETER :: SSqm94 = 2062 + INTEGER(IntKi), PARAMETER :: SSqm95 = 2063 + INTEGER(IntKi), PARAMETER :: SSqm96 = 2064 + INTEGER(IntKi), PARAMETER :: SSqm97 = 2065 + INTEGER(IntKi), PARAMETER :: SSqm98 = 2066 + INTEGER(IntKi), PARAMETER :: SSqm99 = 2067 + INTEGER(IntKi), PARAMETER :: SSqmd01 = 2068 + INTEGER(IntKi), PARAMETER :: SSqmd02 = 2069 + INTEGER(IntKi), PARAMETER :: SSqmd03 = 2070 + INTEGER(IntKi), PARAMETER :: SSqmd04 = 2071 + INTEGER(IntKi), PARAMETER :: SSqmd05 = 2072 + INTEGER(IntKi), PARAMETER :: SSqmd06 = 2073 + INTEGER(IntKi), PARAMETER :: SSqmd07 = 2074 + INTEGER(IntKi), PARAMETER :: SSqmd08 = 2075 + INTEGER(IntKi), PARAMETER :: SSqmd09 = 2076 + INTEGER(IntKi), PARAMETER :: SSqmd10 = 2077 + INTEGER(IntKi), PARAMETER :: SSqmd11 = 2078 + INTEGER(IntKi), PARAMETER :: SSqmd12 = 2079 + INTEGER(IntKi), PARAMETER :: SSqmd13 = 2080 + INTEGER(IntKi), PARAMETER :: SSqmd14 = 2081 + INTEGER(IntKi), PARAMETER :: SSqmd15 = 2082 + INTEGER(IntKi), PARAMETER :: SSqmd16 = 2083 + INTEGER(IntKi), PARAMETER :: SSqmd17 = 2084 + INTEGER(IntKi), PARAMETER :: SSqmd18 = 2085 + INTEGER(IntKi), PARAMETER :: SSqmd19 = 2086 + INTEGER(IntKi), PARAMETER :: SSqmd20 = 2087 + INTEGER(IntKi), PARAMETER :: SSqmd21 = 2088 + INTEGER(IntKi), PARAMETER :: SSqmd22 = 2089 + INTEGER(IntKi), PARAMETER :: SSqmd23 = 2090 + INTEGER(IntKi), PARAMETER :: SSqmd24 = 2091 + INTEGER(IntKi), PARAMETER :: SSqmd25 = 2092 + INTEGER(IntKi), PARAMETER :: SSqmd26 = 2093 + INTEGER(IntKi), PARAMETER :: SSqmd27 = 2094 + INTEGER(IntKi), PARAMETER :: SSqmd28 = 2095 + INTEGER(IntKi), PARAMETER :: SSqmd29 = 2096 + INTEGER(IntKi), PARAMETER :: SSqmd30 = 2097 + INTEGER(IntKi), PARAMETER :: SSqmd31 = 2098 + INTEGER(IntKi), PARAMETER :: SSqmd32 = 2099 + INTEGER(IntKi), PARAMETER :: SSqmd33 = 2100 + INTEGER(IntKi), PARAMETER :: SSqmd34 = 2101 + INTEGER(IntKi), PARAMETER :: SSqmd35 = 2102 + INTEGER(IntKi), PARAMETER :: SSqmd36 = 2103 + INTEGER(IntKi), PARAMETER :: SSqmd37 = 2104 + INTEGER(IntKi), PARAMETER :: SSqmd38 = 2105 + INTEGER(IntKi), PARAMETER :: SSqmd39 = 2106 + INTEGER(IntKi), PARAMETER :: SSqmd40 = 2107 + INTEGER(IntKi), PARAMETER :: SSqmd41 = 2108 + INTEGER(IntKi), PARAMETER :: SSqmd42 = 2109 + INTEGER(IntKi), PARAMETER :: SSqmd43 = 2110 + INTEGER(IntKi), PARAMETER :: SSqmd44 = 2111 + INTEGER(IntKi), PARAMETER :: SSqmd45 = 2112 + INTEGER(IntKi), PARAMETER :: SSqmd46 = 2113 + INTEGER(IntKi), PARAMETER :: SSqmd47 = 2114 + INTEGER(IntKi), PARAMETER :: SSqmd48 = 2115 + INTEGER(IntKi), PARAMETER :: SSqmd49 = 2116 + INTEGER(IntKi), PARAMETER :: SSqmd50 = 2117 + INTEGER(IntKi), PARAMETER :: SSqmd51 = 2118 + INTEGER(IntKi), PARAMETER :: SSqmd52 = 2119 + INTEGER(IntKi), PARAMETER :: SSqmd53 = 2120 + INTEGER(IntKi), PARAMETER :: SSqmd54 = 2121 + INTEGER(IntKi), PARAMETER :: SSqmd55 = 2122 + INTEGER(IntKi), PARAMETER :: SSqmd56 = 2123 + INTEGER(IntKi), PARAMETER :: SSqmd57 = 2124 + INTEGER(IntKi), PARAMETER :: SSqmd58 = 2125 + INTEGER(IntKi), PARAMETER :: SSqmd59 = 2126 + INTEGER(IntKi), PARAMETER :: SSqmd60 = 2127 + INTEGER(IntKi), PARAMETER :: SSqmd61 = 2128 + INTEGER(IntKi), PARAMETER :: SSqmd62 = 2129 + INTEGER(IntKi), PARAMETER :: SSqmd63 = 2130 + INTEGER(IntKi), PARAMETER :: SSqmd64 = 2131 + INTEGER(IntKi), PARAMETER :: SSqmd65 = 2132 + INTEGER(IntKi), PARAMETER :: SSqmd66 = 2133 + INTEGER(IntKi), PARAMETER :: SSqmd67 = 2134 + INTEGER(IntKi), PARAMETER :: SSqmd68 = 2135 + INTEGER(IntKi), PARAMETER :: SSqmd69 = 2136 + INTEGER(IntKi), PARAMETER :: SSqmd70 = 2137 + INTEGER(IntKi), PARAMETER :: SSqmd71 = 2138 + INTEGER(IntKi), PARAMETER :: SSqmd72 = 2139 + INTEGER(IntKi), PARAMETER :: SSqmd73 = 2140 + INTEGER(IntKi), PARAMETER :: SSqmd74 = 2141 + INTEGER(IntKi), PARAMETER :: SSqmd75 = 2142 + INTEGER(IntKi), PARAMETER :: SSqmd76 = 2143 + INTEGER(IntKi), PARAMETER :: SSqmd77 = 2144 + INTEGER(IntKi), PARAMETER :: SSqmd78 = 2145 + INTEGER(IntKi), PARAMETER :: SSqmd79 = 2146 + INTEGER(IntKi), PARAMETER :: SSqmd80 = 2147 + INTEGER(IntKi), PARAMETER :: SSqmd81 = 2148 + INTEGER(IntKi), PARAMETER :: SSqmd82 = 2149 + INTEGER(IntKi), PARAMETER :: SSqmd83 = 2150 + INTEGER(IntKi), PARAMETER :: SSqmd84 = 2151 + INTEGER(IntKi), PARAMETER :: SSqmd85 = 2152 + INTEGER(IntKi), PARAMETER :: SSqmd86 = 2153 + INTEGER(IntKi), PARAMETER :: SSqmd87 = 2154 + INTEGER(IntKi), PARAMETER :: SSqmd88 = 2155 + INTEGER(IntKi), PARAMETER :: SSqmd89 = 2156 + INTEGER(IntKi), PARAMETER :: SSqmd90 = 2157 + INTEGER(IntKi), PARAMETER :: SSqmd91 = 2158 + INTEGER(IntKi), PARAMETER :: SSqmd92 = 2159 + INTEGER(IntKi), PARAMETER :: SSqmd93 = 2160 + INTEGER(IntKi), PARAMETER :: SSqmd94 = 2161 + INTEGER(IntKi), PARAMETER :: SSqmd95 = 2162 + INTEGER(IntKi), PARAMETER :: SSqmd96 = 2163 + INTEGER(IntKi), PARAMETER :: SSqmd97 = 2164 + INTEGER(IntKi), PARAMETER :: SSqmd98 = 2165 + INTEGER(IntKi), PARAMETER :: SSqmd99 = 2166 + INTEGER(IntKi), PARAMETER :: SSqmdd01 = 2167 + INTEGER(IntKi), PARAMETER :: SSqmdd02 = 2168 + INTEGER(IntKi), PARAMETER :: SSqmdd03 = 2169 + INTEGER(IntKi), PARAMETER :: SSqmdd04 = 2170 + INTEGER(IntKi), PARAMETER :: SSqmdd05 = 2171 + INTEGER(IntKi), PARAMETER :: SSqmdd06 = 2172 + INTEGER(IntKi), PARAMETER :: SSqmdd07 = 2173 + INTEGER(IntKi), PARAMETER :: SSqmdd08 = 2174 + INTEGER(IntKi), PARAMETER :: SSqmdd09 = 2175 + INTEGER(IntKi), PARAMETER :: SSqmdd10 = 2176 + INTEGER(IntKi), PARAMETER :: SSqmdd11 = 2177 + INTEGER(IntKi), PARAMETER :: SSqmdd12 = 2178 + INTEGER(IntKi), PARAMETER :: SSqmdd13 = 2179 + INTEGER(IntKi), PARAMETER :: SSqmdd14 = 2180 + INTEGER(IntKi), PARAMETER :: SSqmdd15 = 2181 + INTEGER(IntKi), PARAMETER :: SSqmdd16 = 2182 + INTEGER(IntKi), PARAMETER :: SSqmdd17 = 2183 + INTEGER(IntKi), PARAMETER :: SSqmdd18 = 2184 + INTEGER(IntKi), PARAMETER :: SSqmdd19 = 2185 + INTEGER(IntKi), PARAMETER :: SSqmdd20 = 2186 + INTEGER(IntKi), PARAMETER :: SSqmdd21 = 2187 + INTEGER(IntKi), PARAMETER :: SSqmdd22 = 2188 + INTEGER(IntKi), PARAMETER :: SSqmdd23 = 2189 + INTEGER(IntKi), PARAMETER :: SSqmdd24 = 2190 + INTEGER(IntKi), PARAMETER :: SSqmdd25 = 2191 + INTEGER(IntKi), PARAMETER :: SSqmdd26 = 2192 + INTEGER(IntKi), PARAMETER :: SSqmdd27 = 2193 + INTEGER(IntKi), PARAMETER :: SSqmdd28 = 2194 + INTEGER(IntKi), PARAMETER :: SSqmdd29 = 2195 + INTEGER(IntKi), PARAMETER :: SSqmdd30 = 2196 + INTEGER(IntKi), PARAMETER :: SSqmdd31 = 2197 + INTEGER(IntKi), PARAMETER :: SSqmdd32 = 2198 + INTEGER(IntKi), PARAMETER :: SSqmdd33 = 2199 + INTEGER(IntKi), PARAMETER :: SSqmdd34 = 2200 + INTEGER(IntKi), PARAMETER :: SSqmdd35 = 2201 + INTEGER(IntKi), PARAMETER :: SSqmdd36 = 2202 + INTEGER(IntKi), PARAMETER :: SSqmdd37 = 2203 + INTEGER(IntKi), PARAMETER :: SSqmdd38 = 2204 + INTEGER(IntKi), PARAMETER :: SSqmdd39 = 2205 + INTEGER(IntKi), PARAMETER :: SSqmdd40 = 2206 + INTEGER(IntKi), PARAMETER :: SSqmdd41 = 2207 + INTEGER(IntKi), PARAMETER :: SSqmdd42 = 2208 + INTEGER(IntKi), PARAMETER :: SSqmdd43 = 2209 + INTEGER(IntKi), PARAMETER :: SSqmdd44 = 2210 + INTEGER(IntKi), PARAMETER :: SSqmdd45 = 2211 + INTEGER(IntKi), PARAMETER :: SSqmdd46 = 2212 + INTEGER(IntKi), PARAMETER :: SSqmdd47 = 2213 + INTEGER(IntKi), PARAMETER :: SSqmdd48 = 2214 + INTEGER(IntKi), PARAMETER :: SSqmdd49 = 2215 + INTEGER(IntKi), PARAMETER :: SSqmdd50 = 2216 + INTEGER(IntKi), PARAMETER :: SSqmdd51 = 2217 + INTEGER(IntKi), PARAMETER :: SSqmdd52 = 2218 + INTEGER(IntKi), PARAMETER :: SSqmdd53 = 2219 + INTEGER(IntKi), PARAMETER :: SSqmdd54 = 2220 + INTEGER(IntKi), PARAMETER :: SSqmdd55 = 2221 + INTEGER(IntKi), PARAMETER :: SSqmdd56 = 2222 + INTEGER(IntKi), PARAMETER :: SSqmdd57 = 2223 + INTEGER(IntKi), PARAMETER :: SSqmdd58 = 2224 + INTEGER(IntKi), PARAMETER :: SSqmdd59 = 2225 + INTEGER(IntKi), PARAMETER :: SSqmdd60 = 2226 + INTEGER(IntKi), PARAMETER :: SSqmdd61 = 2227 + INTEGER(IntKi), PARAMETER :: SSqmdd62 = 2228 + INTEGER(IntKi), PARAMETER :: SSqmdd63 = 2229 + INTEGER(IntKi), PARAMETER :: SSqmdd64 = 2230 + INTEGER(IntKi), PARAMETER :: SSqmdd65 = 2231 + INTEGER(IntKi), PARAMETER :: SSqmdd66 = 2232 + INTEGER(IntKi), PARAMETER :: SSqmdd67 = 2233 + INTEGER(IntKi), PARAMETER :: SSqmdd68 = 2234 + INTEGER(IntKi), PARAMETER :: SSqmdd69 = 2235 + INTEGER(IntKi), PARAMETER :: SSqmdd70 = 2236 + INTEGER(IntKi), PARAMETER :: SSqmdd71 = 2237 + INTEGER(IntKi), PARAMETER :: SSqmdd72 = 2238 + INTEGER(IntKi), PARAMETER :: SSqmdd73 = 2239 + INTEGER(IntKi), PARAMETER :: SSqmdd74 = 2240 + INTEGER(IntKi), PARAMETER :: SSqmdd75 = 2241 + INTEGER(IntKi), PARAMETER :: SSqmdd76 = 2242 + INTEGER(IntKi), PARAMETER :: SSqmdd77 = 2243 + INTEGER(IntKi), PARAMETER :: SSqmdd78 = 2244 + INTEGER(IntKi), PARAMETER :: SSqmdd79 = 2245 + INTEGER(IntKi), PARAMETER :: SSqmdd80 = 2246 + INTEGER(IntKi), PARAMETER :: SSqmdd81 = 2247 + INTEGER(IntKi), PARAMETER :: SSqmdd82 = 2248 + INTEGER(IntKi), PARAMETER :: SSqmdd83 = 2249 + INTEGER(IntKi), PARAMETER :: SSqmdd84 = 2250 + INTEGER(IntKi), PARAMETER :: SSqmdd85 = 2251 + INTEGER(IntKi), PARAMETER :: SSqmdd86 = 2252 + INTEGER(IntKi), PARAMETER :: SSqmdd87 = 2253 + INTEGER(IntKi), PARAMETER :: SSqmdd88 = 2254 + INTEGER(IntKi), PARAMETER :: SSqmdd89 = 2255 + INTEGER(IntKi), PARAMETER :: SSqmdd90 = 2256 + INTEGER(IntKi), PARAMETER :: SSqmdd91 = 2257 + INTEGER(IntKi), PARAMETER :: SSqmdd92 = 2258 + INTEGER(IntKi), PARAMETER :: SSqmdd93 = 2259 + INTEGER(IntKi), PARAMETER :: SSqmdd94 = 2260 + INTEGER(IntKi), PARAMETER :: SSqmdd95 = 2261 + INTEGER(IntKi), PARAMETER :: SSqmdd96 = 2262 + INTEGER(IntKi), PARAMETER :: SSqmdd97 = 2263 + INTEGER(IntKi), PARAMETER :: SSqmdd98 = 2264 + INTEGER(IntKi), PARAMETER :: SSqmdd99 = 2265 + + + ! The maximum number of output channels which can be output by the code. + !INTEGER(IntKi), PARAMETER :: MaxOutPts = 2265 + +!End of code generated by Matlab script + + INTEGER, PARAMETER :: MNfmKe(6,9,9) = reshape((/ M1N1FKxe,M1N1FKye,M1N1FKze,M1N1MKxe,M1N1MKye,M1N1MKze, & + M1N2FKxe,M1N2FKye,M1N2FKze,M1N2MKxe,M1N2MKye,M1N2MKze, & + M1N3FKxe,M1N3FKye,M1N3FKze,M1N3MKxe,M1N3MKye,M1N3MKze, & + M1N4FKxe,M1N4FKye,M1N4FKze,M1N4MKxe,M1N4MKye,M1N4MKze, & + M1N5FKxe,M1N5FKye,M1N5FKze,M1N5MKxe,M1N5MKye,M1N5MKze, & + M1N6FKxe,M1N6FKye,M1N6FKze,M1N6MKxe,M1N6MKye,M1N6MKze, & + M1N7FKxe,M1N7FKye,M1N7FKze,M1N7MKxe,M1N7MKye,M1N7MKze, & + M1N8FKxe,M1N8FKye,M1N8FKze,M1N8MKxe,M1N8MKye,M1N8MKze, & + M1N9FKxe,M1N9FKye,M1N9FKze,M1N9MKxe,M1N9MKye,M1N9MKze, & + M2N1FKxe,M2N1FKye,M2N1FKze,M2N1MKxe,M2N1MKye,M2N1MKze, & + M2N2FKxe,M2N2FKye,M2N2FKze,M2N2MKxe,M2N2MKye,M2N2MKze, & + M2N3FKxe,M2N3FKye,M2N3FKze,M2N3MKxe,M2N3MKye,M2N3MKze, & + M2N4FKxe,M2N4FKye,M2N4FKze,M2N4MKxe,M2N4MKye,M2N4MKze, & + M2N5FKxe,M2N5FKye,M2N5FKze,M2N5MKxe,M2N5MKye,M2N5MKze, & + M2N6FKxe,M2N6FKye,M2N6FKze,M2N6MKxe,M2N6MKye,M2N6MKze, & + M2N7FKxe,M2N7FKye,M2N7FKze,M2N7MKxe,M2N7MKye,M2N7MKze, & + M2N8FKxe,M2N8FKye,M2N8FKze,M2N8MKxe,M2N8MKye,M2N8MKze, & + M2N9FKxe,M2N9FKye,M2N9FKze,M2N9MKxe,M2N9MKye,M2N9MKze, & + M3N1FKxe,M3N1FKye,M3N1FKze,M3N1MKxe,M3N1MKye,M3N1MKze, & + M3N2FKxe,M3N2FKye,M3N2FKze,M3N2MKxe,M3N2MKye,M3N2MKze, & + M3N3FKxe,M3N3FKye,M3N3FKze,M3N3MKxe,M3N3MKye,M3N3MKze, & + M3N4FKxe,M3N4FKye,M3N4FKze,M3N4MKxe,M3N4MKye,M3N4MKze, & + M3N5FKxe,M3N5FKye,M3N5FKze,M3N5MKxe,M3N5MKye,M3N5MKze, & + M3N6FKxe,M3N6FKye,M3N6FKze,M3N6MKxe,M3N6MKye,M3N6MKze, & + M3N7FKxe,M3N7FKye,M3N7FKze,M3N7MKxe,M3N7MKye,M3N7MKze, & + M3N8FKxe,M3N8FKye,M3N8FKze,M3N8MKxe,M3N8MKye,M3N8MKze, & + M3N9FKxe,M3N9FKye,M3N9FKze,M3N9MKxe,M3N9MKye,M3N9MKze, & + M4N1FKxe,M4N1FKye,M4N1FKze,M4N1MKxe,M4N1MKye,M4N1MKze, & + M4N2FKxe,M4N2FKye,M4N2FKze,M4N2MKxe,M4N2MKye,M4N2MKze, & + M4N3FKxe,M4N3FKye,M4N3FKze,M4N3MKxe,M4N3MKye,M4N3MKze, & + M4N4FKxe,M4N4FKye,M4N4FKze,M4N4MKxe,M4N4MKye,M4N4MKze, & + M4N5FKxe,M4N5FKye,M4N5FKze,M4N5MKxe,M4N5MKye,M4N5MKze, & + M4N6FKxe,M4N6FKye,M4N6FKze,M4N6MKxe,M4N6MKye,M4N6MKze, & + M4N7FKxe,M4N7FKye,M4N7FKze,M4N7MKxe,M4N7MKye,M4N7MKze, & + M4N8FKxe,M4N8FKye,M4N8FKze,M4N8MKxe,M4N8MKye,M4N8MKze, & + M4N9FKxe,M4N9FKye,M4N9FKze,M4N9MKxe,M4N9MKye,M4N9MKze, & + M5N1FKxe,M5N1FKye,M5N1FKze,M5N1MKxe,M5N1MKye,M5N1MKze, & + M5N2FKxe,M5N2FKye,M5N2FKze,M5N2MKxe,M5N2MKye,M5N2MKze, & + M5N3FKxe,M5N3FKye,M5N3FKze,M5N3MKxe,M5N3MKye,M5N3MKze, & + M5N4FKxe,M5N4FKye,M5N4FKze,M5N4MKxe,M5N4MKye,M5N4MKze, & + M5N5FKxe,M5N5FKye,M5N5FKze,M5N5MKxe,M5N5MKye,M5N5MKze, & + M5N6FKxe,M5N6FKye,M5N6FKze,M5N6MKxe,M5N6MKye,M5N6MKze, & + M5N7FKxe,M5N7FKye,M5N7FKze,M5N7MKxe,M5N7MKye,M5N7MKze, & + M5N8FKxe,M5N8FKye,M5N8FKze,M5N8MKxe,M5N8MKye,M5N8MKze, & + M5N9FKxe,M5N9FKye,M5N9FKze,M5N9MKxe,M5N9MKye,M5N9MKze, & + M6N1FKxe,M6N1FKye,M6N1FKze,M6N1MKxe,M6N1MKye,M6N1MKze, & + M6N2FKxe,M6N2FKye,M6N2FKze,M6N2MKxe,M6N2MKye,M6N2MKze, & + M6N3FKxe,M6N3FKye,M6N3FKze,M6N3MKxe,M6N3MKye,M6N3MKze, & + M6N4FKxe,M6N4FKye,M6N4FKze,M6N4MKxe,M6N4MKye,M6N4MKze, & + M6N5FKxe,M6N5FKye,M6N5FKze,M6N5MKxe,M6N5MKye,M6N5MKze, & + M6N6FKxe,M6N6FKye,M6N6FKze,M6N6MKxe,M6N6MKye,M6N6MKze, & + M6N7FKxe,M6N7FKye,M6N7FKze,M6N7MKxe,M6N7MKye,M6N7MKze, & + M6N8FKxe,M6N8FKye,M6N8FKze,M6N8MKxe,M6N8MKye,M6N8MKze, & + M6N9FKxe,M6N9FKye,M6N9FKze,M6N9MKxe,M6N9MKye,M6N9MKze, & + M7N1FKxe,M7N1FKye,M7N1FKze,M7N1MKxe,M7N1MKye,M7N1MKze, & + M7N2FKxe,M7N2FKye,M7N2FKze,M7N2MKxe,M7N2MKye,M7N2MKze, & + M7N3FKxe,M7N3FKye,M7N3FKze,M7N3MKxe,M7N3MKye,M7N3MKze, & + M7N4FKxe,M7N4FKye,M7N4FKze,M7N4MKxe,M7N4MKye,M7N4MKze, & + M7N5FKxe,M7N5FKye,M7N5FKze,M7N5MKxe,M7N5MKye,M7N5MKze, & + M7N6FKxe,M7N6FKye,M7N6FKze,M7N6MKxe,M7N6MKye,M7N6MKze, & + M7N7FKxe,M7N7FKye,M7N7FKze,M7N7MKxe,M7N7MKye,M7N7MKze, & + M7N8FKxe,M7N8FKye,M7N8FKze,M7N8MKxe,M7N8MKye,M7N8MKze, & + M7N9FKxe,M7N9FKye,M7N9FKze,M7N9MKxe,M7N9MKye,M7N9MKze, & + M8N1FKxe,M8N1FKye,M8N1FKze,M8N1MKxe,M8N1MKye,M8N1MKze, & + M8N2FKxe,M8N2FKye,M8N2FKze,M8N2MKxe,M8N2MKye,M8N2MKze, & + M8N3FKxe,M8N3FKye,M8N3FKze,M8N3MKxe,M8N3MKye,M8N3MKze, & + M8N4FKxe,M8N4FKye,M8N4FKze,M8N4MKxe,M8N4MKye,M8N4MKze, & + M8N5FKxe,M8N5FKye,M8N5FKze,M8N5MKxe,M8N5MKye,M8N5MKze, & + M8N6FKxe,M8N6FKye,M8N6FKze,M8N6MKxe,M8N6MKye,M8N6MKze, & + M8N7FKxe,M8N7FKye,M8N7FKze,M8N7MKxe,M8N7MKye,M8N7MKze, & + M8N8FKxe,M8N8FKye,M8N8FKze,M8N8MKxe,M8N8MKye,M8N8MKze, & + M8N9FKxe,M8N9FKye,M8N9FKze,M8N9MKxe,M8N9MKye,M8N9MKze, & + M9N1FKxe,M9N1FKye,M9N1FKze,M9N1MKxe,M9N1MKye,M9N1MKze, & + M9N2FKxe,M9N2FKye,M9N2FKze,M9N2MKxe,M9N2MKye,M9N2MKze, & + M9N3FKxe,M9N3FKye,M9N3FKze,M9N3MKxe,M9N3MKye,M9N3MKze, & + M9N4FKxe,M9N4FKye,M9N4FKze,M9N4MKxe,M9N4MKye,M9N4MKze, & + M9N5FKxe,M9N5FKye,M9N5FKze,M9N5MKxe,M9N5MKye,M9N5MKze, & + M9N6FKxe,M9N6FKye,M9N6FKze,M9N6MKxe,M9N6MKye,M9N6MKze, & + M9N7FKxe,M9N7FKye,M9N7FKze,M9N7MKxe,M9N7MKye,M9N7MKze, & + M9N8FKxe,M9N8FKye,M9N8FKze,M9N8MKxe,M9N8MKye,M9N8MKze, & + M9N9FKxe,M9N9FKye,M9N9FKze,M9N9MKxe,M9N9MKye,M9N9MKze /),(/6,9,9/)) + + + + INTEGER, PARAMETER :: MNfmMe(6,9,9) = reshape((/ M1N1FMxe,M1N1FMye,M1N1FMze,M1N1MMxe,M1N1MMye,M1N1MMze, & + M1N2FMxe,M1N2FMye,M1N2FMze,M1N2MMxe,M1N2MMye,M1N2MMze, & + M1N3FMxe,M1N3FMye,M1N3FMze,M1N3MMxe,M1N3MMye,M1N3MMze, & + M1N4FMxe,M1N4FMye,M1N4FMze,M1N4MMxe,M1N4MMye,M1N4MMze, & + M1N5FMxe,M1N5FMye,M1N5FMze,M1N5MMxe,M1N5MMye,M1N5MMze, & + M1N6FMxe,M1N6FMye,M1N6FMze,M1N6MMxe,M1N6MMye,M1N6MMze, & + M1N7FMxe,M1N7FMye,M1N7FMze,M1N7MMxe,M1N7MMye,M1N7MMze, & + M1N8FMxe,M1N8FMye,M1N8FMze,M1N8MMxe,M1N8MMye,M1N8MMze, & + M1N9FMxe,M1N9FMye,M1N9FMze,M1N9MMxe,M1N9MMye,M1N9MMze, & + M2N1FMxe,M2N1FMye,M2N1FMze,M2N1MMxe,M2N1MMye,M2N1MMze, & + M2N2FMxe,M2N2FMye,M2N2FMze,M2N2MMxe,M2N2MMye,M2N2MMze, & + M2N3FMxe,M2N3FMye,M2N3FMze,M2N3MMxe,M2N3MMye,M2N3MMze, & + M2N4FMxe,M2N4FMye,M2N4FMze,M2N4MMxe,M2N4MMye,M2N4MMze, & + M2N5FMxe,M2N5FMye,M2N5FMze,M2N5MMxe,M2N5MMye,M2N5MMze, & + M2N6FMxe,M2N6FMye,M2N6FMze,M2N6MMxe,M2N6MMye,M2N6MMze, & + M2N7FMxe,M2N7FMye,M2N7FMze,M2N7MMxe,M2N7MMye,M2N7MMze, & + M2N8FMxe,M2N8FMye,M2N8FMze,M2N8MMxe,M2N8MMye,M2N8MMze, & + M2N9FMxe,M2N9FMye,M2N9FMze,M2N9MMxe,M2N9MMye,M2N9MMze, & + M3N1FMxe,M3N1FMye,M3N1FMze,M3N1MMxe,M3N1MMye,M3N1MMze, & + M3N2FMxe,M3N2FMye,M3N2FMze,M3N2MMxe,M3N2MMye,M3N2MMze, & + M3N3FMxe,M3N3FMye,M3N3FMze,M3N3MMxe,M3N3MMye,M3N3MMze, & + M3N4FMxe,M3N4FMye,M3N4FMze,M3N4MMxe,M3N4MMye,M3N4MMze, & + M3N5FMxe,M3N5FMye,M3N5FMze,M3N5MMxe,M3N5MMye,M3N5MMze, & + M3N6FMxe,M3N6FMye,M3N6FMze,M3N6MMxe,M3N6MMye,M3N6MMze, & + M3N7FMxe,M3N7FMye,M3N7FMze,M3N7MMxe,M3N7MMye,M3N7MMze, & + M3N8FMxe,M3N8FMye,M3N8FMze,M3N8MMxe,M3N8MMye,M3N8MMze, & + M3N9FMxe,M3N9FMye,M3N9FMze,M3N9MMxe,M3N9MMye,M3N9MMze, & + M4N1FMxe,M4N1FMye,M4N1FMze,M4N1MMxe,M4N1MMye,M4N1MMze, & + M4N2FMxe,M4N2FMye,M4N2FMze,M4N2MMxe,M4N2MMye,M4N2MMze, & + M4N3FMxe,M4N3FMye,M4N3FMze,M4N3MMxe,M4N3MMye,M4N3MMze, & + M4N4FMxe,M4N4FMye,M4N4FMze,M4N4MMxe,M4N4MMye,M4N4MMze, & + M4N5FMxe,M4N5FMye,M4N5FMze,M4N5MMxe,M4N5MMye,M4N5MMze, & + M4N6FMxe,M4N6FMye,M4N6FMze,M4N6MMxe,M4N6MMye,M4N6MMze, & + M4N7FMxe,M4N7FMye,M4N7FMze,M4N7MMxe,M4N7MMye,M4N7MMze, & + M4N8FMxe,M4N8FMye,M4N8FMze,M4N8MMxe,M4N8MMye,M4N8MMze, & + M4N9FMxe,M4N9FMye,M4N9FMze,M4N9MMxe,M4N9MMye,M4N9MMze, & + M5N1FMxe,M5N1FMye,M5N1FMze,M5N1MMxe,M5N1MMye,M5N1MMze, & + M5N2FMxe,M5N2FMye,M5N2FMze,M5N2MMxe,M5N2MMye,M5N2MMze, & + M5N3FMxe,M5N3FMye,M5N3FMze,M5N3MMxe,M5N3MMye,M5N3MMze, & + M5N4FMxe,M5N4FMye,M5N4FMze,M5N4MMxe,M5N4MMye,M5N4MMze, & + M5N5FMxe,M5N5FMye,M5N5FMze,M5N5MMxe,M5N5MMye,M5N5MMze, & + M5N6FMxe,M5N6FMye,M5N6FMze,M5N6MMxe,M5N6MMye,M5N6MMze, & + M5N7FMxe,M5N7FMye,M5N7FMze,M5N7MMxe,M5N7MMye,M5N7MMze, & + M5N8FMxe,M5N8FMye,M5N8FMze,M5N8MMxe,M5N8MMye,M5N8MMze, & + M5N9FMxe,M5N9FMye,M5N9FMze,M5N9MMxe,M5N9MMye,M5N9MMze, & + M6N1FMxe,M6N1FMye,M6N1FMze,M6N1MMxe,M6N1MMye,M6N1MMze, & + M6N2FMxe,M6N2FMye,M6N2FMze,M6N2MMxe,M6N2MMye,M6N2MMze, & + M6N3FMxe,M6N3FMye,M6N3FMze,M6N3MMxe,M6N3MMye,M6N3MMze, & + M6N4FMxe,M6N4FMye,M6N4FMze,M6N4MMxe,M6N4MMye,M6N4MMze, & + M6N5FMxe,M6N5FMye,M6N5FMze,M6N5MMxe,M6N5MMye,M6N5MMze, & + M6N6FMxe,M6N6FMye,M6N6FMze,M6N6MMxe,M6N6MMye,M6N6MMze, & + M6N7FMxe,M6N7FMye,M6N7FMze,M6N7MMxe,M6N7MMye,M6N7MMze, & + M6N8FMxe,M6N8FMye,M6N8FMze,M6N8MMxe,M6N8MMye,M6N8MMze, & + M6N9FMxe,M6N9FMye,M6N9FMze,M6N9MMxe,M6N9MMye,M6N9MMze, & + M7N1FMxe,M7N1FMye,M7N1FMze,M7N1MMxe,M7N1MMye,M7N1MMze, & + M7N2FMxe,M7N2FMye,M7N2FMze,M7N2MMxe,M7N2MMye,M7N2MMze, & + M7N3FMxe,M7N3FMye,M7N3FMze,M7N3MMxe,M7N3MMye,M7N3MMze, & + M7N4FMxe,M7N4FMye,M7N4FMze,M7N4MMxe,M7N4MMye,M7N4MMze, & + M7N5FMxe,M7N5FMye,M7N5FMze,M7N5MMxe,M7N5MMye,M7N5MMze, & + M7N6FMxe,M7N6FMye,M7N6FMze,M7N6MMxe,M7N6MMye,M7N6MMze, & + M7N7FMxe,M7N7FMye,M7N7FMze,M7N7MMxe,M7N7MMye,M7N7MMze, & + M7N8FMxe,M7N8FMye,M7N8FMze,M7N8MMxe,M7N8MMye,M7N8MMze, & + M7N9FMxe,M7N9FMye,M7N9FMze,M7N9MMxe,M7N9MMye,M7N9MMze, & + M8N1FMxe,M8N1FMye,M8N1FMze,M8N1MMxe,M8N1MMye,M8N1MMze, & + M8N2FMxe,M8N2FMye,M8N2FMze,M8N2MMxe,M8N2MMye,M8N2MMze, & + M8N3FMxe,M8N3FMye,M8N3FMze,M8N3MMxe,M8N3MMye,M8N3MMze, & + M8N4FMxe,M8N4FMye,M8N4FMze,M8N4MMxe,M8N4MMye,M8N4MMze, & + M8N5FMxe,M8N5FMye,M8N5FMze,M8N5MMxe,M8N5MMye,M8N5MMze, & + M8N6FMxe,M8N6FMye,M8N6FMze,M8N6MMxe,M8N6MMye,M8N6MMze, & + M8N7FMxe,M8N7FMye,M8N7FMze,M8N7MMxe,M8N7MMye,M8N7MMze, & + M8N8FMxe,M8N8FMye,M8N8FMze,M8N8MMxe,M8N8MMye,M8N8MMze, & + M8N9FMxe,M8N9FMye,M8N9FMze,M8N9MMxe,M8N9MMye,M8N9MMze, & + M9N1FMxe,M9N1FMye,M9N1FMze,M9N1MMxe,M9N1MMye,M9N1MMze, & + M9N2FMxe,M9N2FMye,M9N2FMze,M9N2MMxe,M9N2MMye,M9N2MMze, & + M9N3FMxe,M9N3FMye,M9N3FMze,M9N3MMxe,M9N3MMye,M9N3MMze, & + M9N4FMxe,M9N4FMye,M9N4FMze,M9N4MMxe,M9N4MMye,M9N4MMze, & + M9N5FMxe,M9N5FMye,M9N5FMze,M9N5MMxe,M9N5MMye,M9N5MMze, & + M9N6FMxe,M9N6FMye,M9N6FMze,M9N6MMxe,M9N6MMye,M9N6MMze, & + M9N7FMxe,M9N7FMye,M9N7FMze,M9N7MMxe,M9N7MMye,M9N7MMze, & + M9N8FMxe,M9N8FMye,M9N8FMze,M9N8MMxe,M9N8MMye,M9N8MMze, & + M9N9FMxe,M9N9FMye,M9N9FMze,M9N9MMxe,M9N9MMye,M9N9MMze /),(/6,9,9/)) + + INTEGER, PARAMETER :: MNTDss(3,9,9) = reshape((/M1N1TDxss,M1N1TDyss,M1N1TDzss, & + M1N2TDxss,M1N2TDyss,M1N2TDzss, & + M1N3TDxss,M1N3TDyss,M1N3TDzss, & + M1N4TDxss,M1N4TDyss,M1N4TDzss, & + M1N5TDxss,M1N5TDyss,M1N5TDzss, & + M1N6TDxss,M1N6TDyss,M1N6TDzss, & + M1N7TDxss,M1N7TDyss,M1N7TDzss, & + M1N8TDxss,M1N8TDyss,M1N8TDzss, & + M1N9TDxss,M1N9TDyss,M1N9TDzss, & + M2N1TDxss,M2N1TDyss,M2N1TDzss, & + M2N2TDxss,M2N2TDyss,M2N2TDzss, & + M2N3TDxss,M2N3TDyss,M2N3TDzss, & + M2N4TDxss,M2N4TDyss,M2N4TDzss, & + M2N5TDxss,M2N5TDyss,M2N5TDzss, & + M2N6TDxss,M2N6TDyss,M2N6TDzss, & + M2N7TDxss,M2N7TDyss,M2N7TDzss, & + M2N8TDxss,M2N8TDyss,M2N8TDzss, & + M2N9TDxss,M2N9TDyss,M2N9TDzss, & + M3N1TDxss,M3N1TDyss,M3N1TDzss, & + M3N2TDxss,M3N2TDyss,M3N2TDzss, & + M3N3TDxss,M3N3TDyss,M3N3TDzss, & + M3N4TDxss,M3N4TDyss,M3N4TDzss, & + M3N5TDxss,M3N5TDyss,M3N5TDzss, & + M3N6TDxss,M3N6TDyss,M3N6TDzss, & + M3N7TDxss,M3N7TDyss,M3N7TDzss, & + M3N8TDxss,M3N8TDyss,M3N8TDzss, & + M3N9TDxss,M3N9TDyss,M3N9TDzss, & + M4N1TDxss,M4N1TDyss,M4N1TDzss, & + M4N2TDxss,M4N2TDyss,M4N2TDzss, & + M4N3TDxss,M4N3TDyss,M4N3TDzss, & + M4N4TDxss,M4N4TDyss,M4N4TDzss, & + M4N5TDxss,M4N5TDyss,M4N5TDzss, & + M4N6TDxss,M4N6TDyss,M4N6TDzss, & + M4N7TDxss,M4N7TDyss,M4N7TDzss, & + M4N8TDxss,M4N8TDyss,M4N8TDzss, & + M4N9TDxss,M4N9TDyss,M4N9TDzss, & + M5N1TDxss,M5N1TDyss,M5N1TDzss, & + M5N2TDxss,M5N2TDyss,M5N2TDzss, & + M5N3TDxss,M5N3TDyss,M5N3TDzss, & + M5N4TDxss,M5N4TDyss,M5N4TDzss, & + M5N5TDxss,M5N5TDyss,M5N5TDzss, & + M5N6TDxss,M5N6TDyss,M5N6TDzss, & + M5N7TDxss,M5N7TDyss,M5N7TDzss, & + M5N8TDxss,M5N8TDyss,M5N8TDzss, & + M5N9TDxss,M5N9TDyss,M5N9TDzss, & + M6N1TDxss,M6N1TDyss,M6N1TDzss, & + M6N2TDxss,M6N2TDyss,M6N2TDzss, & + M6N3TDxss,M6N3TDyss,M6N3TDzss, & + M6N4TDxss,M6N4TDyss,M6N4TDzss, & + M6N5TDxss,M6N5TDyss,M6N5TDzss, & + M6N6TDxss,M6N6TDyss,M6N6TDzss, & + M6N7TDxss,M6N7TDyss,M6N7TDzss, & + M6N8TDxss,M6N8TDyss,M6N8TDzss, & + M6N9TDxss,M6N9TDyss,M6N9TDzss, & + M7N1TDxss,M7N1TDyss,M7N1TDzss, & + M7N2TDxss,M7N2TDyss,M7N2TDzss, & + M7N3TDxss,M7N3TDyss,M7N3TDzss, & + M7N4TDxss,M7N4TDyss,M7N4TDzss, & + M7N5TDxss,M7N5TDyss,M7N5TDzss, & + M7N6TDxss,M7N6TDyss,M7N6TDzss, & + M7N7TDxss,M7N7TDyss,M7N7TDzss, & + M7N8TDxss,M7N8TDyss,M7N8TDzss, & + M7N9TDxss,M7N9TDyss,M7N9TDzss, & + M8N1TDxss,M8N1TDyss,M8N1TDzss, & + M8N2TDxss,M8N2TDyss,M8N2TDzss, & + M8N3TDxss,M8N3TDyss,M8N3TDzss, & + M8N4TDxss,M8N4TDyss,M8N4TDzss, & + M8N5TDxss,M8N5TDyss,M8N5TDzss, & + M8N6TDxss,M8N6TDyss,M8N6TDzss, & + M8N7TDxss,M8N7TDyss,M8N7TDzss, & + M8N8TDxss,M8N8TDyss,M8N8TDzss, & + M8N9TDxss,M8N9TDyss,M8N9TDzss, & + M9N1TDxss,M9N1TDyss,M9N1TDzss, & + M9N2TDxss,M9N2TDyss,M9N2TDzss, & + M9N3TDxss,M9N3TDyss,M9N3TDzss, & + M9N4TDxss,M9N4TDyss,M9N4TDzss, & + M9N5TDxss,M9N5TDyss,M9N5TDzss, & + M9N6TDxss,M9N6TDyss,M9N6TDzss, & + M9N7TDxss,M9N7TDyss,M9N7TDzss, & + M9N8TDxss,M9N8TDyss,M9N8TDzss, & + M9N9TDxss,M9N9TDyss,M9N9TDzss/), (/3,9,9/)) + +INTEGER, PARAMETER :: MNRDe (3,9,9) = reshape((/M1N1RDxe,M1N1RDye,M1N1RDze, & + M1N2RDxe,M1N2RDye,M1N2RDze, & + M1N3RDxe,M1N3RDye,M1N3RDze, & + M1N4RDxe,M1N4RDye,M1N4RDze, & + M1N5RDxe,M1N5RDye,M1N5RDze, & + M1N6RDxe,M1N6RDye,M1N6RDze, & + M1N7RDxe,M1N7RDye,M1N7RDze, & + M1N8RDxe,M1N8RDye,M1N8RDze, & + M1N9RDxe,M1N9RDye,M1N9RDze, & + M2N1RDxe,M2N1RDye,M2N1RDze, & + M2N2RDxe,M2N2RDye,M2N2RDze, & + M2N3RDxe,M2N3RDye,M2N3RDze, & + M2N4RDxe,M2N4RDye,M2N4RDze, & + M2N5RDxe,M2N5RDye,M2N5RDze, & + M2N6RDxe,M2N6RDye,M2N6RDze, & + M2N7RDxe,M2N7RDye,M2N7RDze, & + M2N8RDxe,M2N8RDye,M2N8RDze, & + M2N9RDxe,M2N9RDye,M2N9RDze, & + M3N1RDxe,M3N1RDye,M3N1RDze, & + M3N2RDxe,M3N2RDye,M3N2RDze, & + M3N3RDxe,M3N3RDye,M3N3RDze, & + M3N4RDxe,M3N4RDye,M3N4RDze, & + M3N5RDxe,M3N5RDye,M3N5RDze, & + M3N6RDxe,M3N6RDye,M3N6RDze, & + M3N7RDxe,M3N7RDye,M3N7RDze, & + M3N8RDxe,M3N8RDye,M3N8RDze, & + M3N9RDxe,M3N9RDye,M3N9RDze, & + M4N1RDxe,M4N1RDye,M4N1RDze, & + M4N2RDxe,M4N2RDye,M4N2RDze, & + M4N3RDxe,M4N3RDye,M4N3RDze, & + M4N4RDxe,M4N4RDye,M4N4RDze, & + M4N5RDxe,M4N5RDye,M4N5RDze, & + M4N6RDxe,M4N6RDye,M4N6RDze, & + M4N7RDxe,M4N7RDye,M4N7RDze, & + M4N8RDxe,M4N8RDye,M4N8RDze, & + M4N9RDxe,M4N9RDye,M4N9RDze, & + M5N1RDxe,M5N1RDye,M5N1RDze, & + M5N2RDxe,M5N2RDye,M5N2RDze, & + M5N3RDxe,M5N3RDye,M5N3RDze, & + M5N4RDxe,M5N4RDye,M5N4RDze, & + M5N5RDxe,M5N5RDye,M5N5RDze, & + M5N6RDxe,M5N6RDye,M5N6RDze, & + M5N7RDxe,M5N7RDye,M5N7RDze, & + M5N8RDxe,M5N8RDye,M5N8RDze, & + M5N9RDxe,M5N9RDye,M5N9RDze, & + M6N1RDxe,M6N1RDye,M6N1RDze, & + M6N2RDxe,M6N2RDye,M6N2RDze, & + M6N3RDxe,M6N3RDye,M6N3RDze, & + M6N4RDxe,M6N4RDye,M6N4RDze, & + M6N5RDxe,M6N5RDye,M6N5RDze, & + M6N6RDxe,M6N6RDye,M6N6RDze, & + M6N7RDxe,M6N7RDye,M6N7RDze, & + M6N8RDxe,M6N8RDye,M6N8RDze, & + M6N9RDxe,M6N9RDye,M6N9RDze, & + M7N1RDxe,M7N1RDye,M7N1RDze, & + M7N2RDxe,M7N2RDye,M7N2RDze, & + M7N3RDxe,M7N3RDye,M7N3RDze, & + M7N4RDxe,M7N4RDye,M7N4RDze, & + M7N5RDxe,M7N5RDye,M7N5RDze, & + M7N6RDxe,M7N6RDye,M7N6RDze, & + M7N7RDxe,M7N7RDye,M7N7RDze, & + M7N8RDxe,M7N8RDye,M7N8RDze, & + M7N9RDxe,M7N9RDye,M7N9RDze, & + M8N1RDxe,M8N1RDye,M8N1RDze, & + M8N2RDxe,M8N2RDye,M8N2RDze, & + M8N3RDxe,M8N3RDye,M8N3RDze, & + M8N4RDxe,M8N4RDye,M8N4RDze, & + M8N5RDxe,M8N5RDye,M8N5RDze, & + M8N6RDxe,M8N6RDye,M8N6RDze, & + M8N7RDxe,M8N7RDye,M8N7RDze, & + M8N8RDxe,M8N8RDye,M8N8RDze, & + M8N9RDxe,M8N9RDye,M8N9RDze, & + M9N1RDxe,M9N1RDye,M9N1RDze, & + M9N2RDxe,M9N2RDye,M9N2RDze, & + M9N3RDxe,M9N3RDye,M9N3RDze, & + M9N4RDxe,M9N4RDye,M9N4RDze, & + M9N5RDxe,M9N5RDye,M9N5RDze, & + M9N6RDxe,M9N6RDye,M9N6RDze, & + M9N7RDxe,M9N7RDye,M9N7RDze, & + M9N8RDxe,M9N8RDye,M9N8RDze, & + M9N9RDxe,M9N9RDye,M9N9RDze/), (/3,9,9/)) + + + INTEGER, PARAMETER :: MNTRAe(6,9,9) = reshape( (/M1N1TAxe,M1N1TAye,M1N1TAze,M1N1RAxe,M1N1RAye,M1N1RAze, & + M1N2TAxe,M1N2TAye,M1N2TAze,M1N2RAxe,M1N2RAye,M1N2RAze, & + M1N3TAxe,M1N3TAye,M1N3TAze,M1N3RAxe,M1N3RAye,M1N3RAze, & + M1N4TAxe,M1N4TAye,M1N4TAze,M1N4RAxe,M1N4RAye,M1N4RAze, & + M1N5TAxe,M1N5TAye,M1N5TAze,M1N5RAxe,M1N5RAye,M1N5RAze, & + M1N6TAxe,M1N6TAye,M1N6TAze,M1N6RAxe,M1N6RAye,M1N6RAze, & + M1N7TAxe,M1N7TAye,M1N7TAze,M1N7RAxe,M1N7RAye,M1N7RAze, & + M1N8TAxe,M1N8TAye,M1N8TAze,M1N8RAxe,M1N8RAye,M1N8RAze, & + M1N9TAxe,M1N9TAye,M1N9TAze,M1N9RAxe,M1N9RAye,M1N9RAze, & + M2N1TAxe,M2N1TAye,M2N1TAze,M2N1RAxe,M2N1RAye,M2N1RAze, & + M2N2TAxe,M2N2TAye,M2N2TAze,M2N2RAxe,M2N2RAye,M2N2RAze, & + M2N3TAxe,M2N3TAye,M2N3TAze,M2N3RAxe,M2N3RAye,M2N3RAze, & + M2N4TAxe,M2N4TAye,M2N4TAze,M2N4RAxe,M2N4RAye,M2N4RAze, & + M2N5TAxe,M2N5TAye,M2N5TAze,M2N5RAxe,M2N5RAye,M2N5RAze, & + M2N6TAxe,M2N6TAye,M2N6TAze,M2N6RAxe,M2N6RAye,M2N6RAze, & + M2N7TAxe,M2N7TAye,M2N7TAze,M2N7RAxe,M2N7RAye,M2N7RAze, & + M2N8TAxe,M2N8TAye,M2N8TAze,M2N8RAxe,M2N8RAye,M2N8RAze, & + M2N9TAxe,M2N9TAye,M2N9TAze,M2N9RAxe,M2N9RAye,M2N9RAze, & + M3N1TAxe,M3N1TAye,M3N1TAze,M3N1RAxe,M3N1RAye,M3N1RAze, & + M3N2TAxe,M3N2TAye,M3N2TAze,M3N2RAxe,M3N2RAye,M3N2RAze, & + M3N3TAxe,M3N3TAye,M3N3TAze,M3N3RAxe,M3N3RAye,M3N3RAze, & + M3N4TAxe,M3N4TAye,M3N4TAze,M3N4RAxe,M3N4RAye,M3N4RAze, & + M3N5TAxe,M3N5TAye,M3N5TAze,M3N5RAxe,M3N5RAye,M3N5RAze, & + M3N6TAxe,M3N6TAye,M3N6TAze,M3N6RAxe,M3N6RAye,M3N6RAze, & + M3N7TAxe,M3N7TAye,M3N7TAze,M3N7RAxe,M3N7RAye,M3N7RAze, & + M3N8TAxe,M3N8TAye,M3N8TAze,M3N8RAxe,M3N8RAye,M3N8RAze, & + M3N9TAxe,M3N9TAye,M3N9TAze,M3N9RAxe,M3N9RAye,M3N9RAze, & + M4N1TAxe,M4N1TAye,M4N1TAze,M4N1RAxe,M4N1RAye,M4N1RAze, & + M4N2TAxe,M4N2TAye,M4N2TAze,M4N2RAxe,M4N2RAye,M4N2RAze, & + M4N3TAxe,M4N3TAye,M4N3TAze,M4N3RAxe,M4N3RAye,M4N3RAze, & + M4N4TAxe,M4N4TAye,M4N4TAze,M4N4RAxe,M4N4RAye,M4N4RAze, & + M4N5TAxe,M4N5TAye,M4N5TAze,M4N5RAxe,M4N5RAye,M4N5RAze, & + M4N6TAxe,M4N6TAye,M4N6TAze,M4N6RAxe,M4N6RAye,M4N6RAze, & + M4N7TAxe,M4N7TAye,M4N7TAze,M4N7RAxe,M4N7RAye,M4N7RAze, & + M4N8TAxe,M4N8TAye,M4N8TAze,M4N8RAxe,M4N8RAye,M4N8RAze, & + M4N9TAxe,M4N9TAye,M4N9TAze,M4N9RAxe,M4N9RAye,M4N9RAze, & + M5N1TAxe,M5N1TAye,M5N1TAze,M5N1RAxe,M5N1RAye,M5N1RAze, & + M5N2TAxe,M5N2TAye,M5N2TAze,M5N2RAxe,M5N2RAye,M5N2RAze, & + M5N3TAxe,M5N3TAye,M5N3TAze,M5N3RAxe,M5N3RAye,M5N3RAze, & + M5N4TAxe,M5N4TAye,M5N4TAze,M5N4RAxe,M5N4RAye,M5N4RAze, & + M5N5TAxe,M5N5TAye,M5N5TAze,M5N5RAxe,M5N5RAye,M5N5RAze, & + M5N6TAxe,M5N6TAye,M5N6TAze,M5N6RAxe,M5N6RAye,M5N6RAze, & + M5N7TAxe,M5N7TAye,M5N7TAze,M5N7RAxe,M5N7RAye,M5N7RAze, & + M5N8TAxe,M5N8TAye,M5N8TAze,M5N8RAxe,M5N8RAye,M5N8RAze, & + M5N9TAxe,M5N9TAye,M5N9TAze,M5N9RAxe,M5N9RAye,M5N9RAze, & + M6N1TAxe,M6N1TAye,M6N1TAze,M6N1RAxe,M6N1RAye,M6N1RAze, & + M6N2TAxe,M6N2TAye,M6N2TAze,M6N2RAxe,M6N2RAye,M6N2RAze, & + M6N3TAxe,M6N3TAye,M6N3TAze,M6N3RAxe,M6N3RAye,M6N3RAze, & + M6N4TAxe,M6N4TAye,M6N4TAze,M6N4RAxe,M6N4RAye,M6N4RAze, & + M6N5TAxe,M6N5TAye,M6N5TAze,M6N5RAxe,M6N5RAye,M6N5RAze, & + M6N6TAxe,M6N6TAye,M6N6TAze,M6N6RAxe,M6N6RAye,M6N6RAze, & + M6N7TAxe,M6N7TAye,M6N7TAze,M6N7RAxe,M6N7RAye,M6N7RAze, & + M6N8TAxe,M6N8TAye,M6N8TAze,M6N8RAxe,M6N8RAye,M6N8RAze, & + M6N9TAxe,M6N9TAye,M6N9TAze,M6N9RAxe,M6N9RAye,M6N9RAze, & + M7N1TAxe,M7N1TAye,M7N1TAze,M7N1RAxe,M7N1RAye,M7N1RAze, & + M7N2TAxe,M7N2TAye,M7N2TAze,M7N2RAxe,M7N2RAye,M7N2RAze, & + M7N3TAxe,M7N3TAye,M7N3TAze,M7N3RAxe,M7N3RAye,M7N3RAze, & + M7N4TAxe,M7N4TAye,M7N4TAze,M7N4RAxe,M7N4RAye,M7N4RAze, & + M7N5TAxe,M7N5TAye,M7N5TAze,M7N5RAxe,M7N5RAye,M7N5RAze, & + M7N6TAxe,M7N6TAye,M7N6TAze,M7N6RAxe,M7N6RAye,M7N6RAze, & + M7N7TAxe,M7N7TAye,M7N7TAze,M7N7RAxe,M7N7RAye,M7N7RAze, & + M7N8TAxe,M7N8TAye,M7N8TAze,M7N8RAxe,M7N8RAye,M7N8RAze, & + M7N9TAxe,M7N9TAye,M7N9TAze,M7N9RAxe,M7N9RAye,M7N9RAze, & + M8N1TAxe,M8N1TAye,M8N1TAze,M8N1RAxe,M8N1RAye,M8N1RAze, & + M8N2TAxe,M8N2TAye,M8N2TAze,M8N2RAxe,M8N2RAye,M8N2RAze, & + M8N3TAxe,M8N3TAye,M8N3TAze,M8N3RAxe,M8N3RAye,M8N3RAze, & + M8N4TAxe,M8N4TAye,M8N4TAze,M8N4RAxe,M8N4RAye,M8N4RAze, & + M8N5TAxe,M8N5TAye,M8N5TAze,M8N5RAxe,M8N5RAye,M8N5RAze, & + M8N6TAxe,M8N6TAye,M8N6TAze,M8N6RAxe,M8N6RAye,M8N6RAze, & + M8N7TAxe,M8N7TAye,M8N7TAze,M8N7RAxe,M8N7RAye,M8N7RAze, & + M8N8TAxe,M8N8TAye,M8N8TAze,M8N8RAxe,M8N8RAye,M8N8RAze, & + M8N9TAxe,M8N9TAye,M8N9TAze,M8N9RAxe,M8N9RAye,M8N9RAze, & + M9N1TAxe,M9N1TAye,M9N1TAze,M9N1RAxe,M9N1RAye,M9N1RAze, & + M9N2TAxe,M9N2TAye,M9N2TAze,M9N2RAxe,M9N2RAye,M9N2RAze, & + M9N3TAxe,M9N3TAye,M9N3TAze,M9N3RAxe,M9N3RAye,M9N3RAze, & + M9N4TAxe,M9N4TAye,M9N4TAze,M9N4RAxe,M9N4RAye,M9N4RAze, & + M9N5TAxe,M9N5TAye,M9N5TAze,M9N5RAxe,M9N5RAye,M9N5RAze, & + M9N6TAxe,M9N6TAye,M9N6TAze,M9N6RAxe,M9N6RAye,M9N6RAze, & + M9N7TAxe,M9N7TAye,M9N7TAze,M9N7RAxe,M9N7RAye,M9N7RAze, & + M9N8TAxe,M9N8TAye,M9N8TAze,M9N8RAxe,M9N8RAye,M9N8RAze, & + M9N9TAxe,M9N9TAye,M9N9TAze,M9N9RAxe,M9N9RAye,M9N9RAze/), (/6,9,9/)) + + INTEGER, PARAMETER :: ReactSS(6) = (/ReactFXss, ReactFYss, ReactFZss , & + ReactMXss, ReactMYss, ReactMZss/) + + INTEGER, PARAMETER :: IntfSS(6) = (/IntfFXss, IntfFYss, IntfFZss , & + IntfMXss, IntfMYss, IntfMZss/) + + + INTEGER, PARAMETER :: IntfTRss(6) = (/IntfTDXss, IntfTDYss, IntfTDZss , & + IntfRDXss, IntfRDYss, IntfRDZss/) + + INTEGER, PARAMETER :: IntfTRAss(6) = (/IntfTAXss, IntfTAYss, IntfTAZss , & + IntfRAXss, IntfRAYss, IntfRAZss/) + + + + + + + + CHARACTER(10), PARAMETER :: ValidParamAry(2265) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "INTFFXSS ","INTFFYSS ","INTFFZSS ","INTFMXSS ","INTFMYSS ","INTFMZSS ","INTFRAXSS", & + "INTFRAYSS","INTFRAZSS","INTFRDXSS","INTFRDYSS","INTFRDZSS","INTFTAXSS","INTFTAYSS", & + "INTFTAZSS","INTFTDXSS","INTFTDYSS","INTFTDZSS","M1N1FKXE ","M1N1FKYE ","M1N1FKZE ", & + "M1N1FMXE ","M1N1FMYE ","M1N1FMZE ","M1N1MKXE ","M1N1MKYE ","M1N1MKZE ","M1N1MMXE ", & + "M1N1MMYE ","M1N1MMZE ","M1N1RAXE ","M1N1RAYE ","M1N1RAZE ","M1N1RDXE ","M1N1RDYE ", & + "M1N1RDZE ","M1N1TAXE ","M1N1TAYE ","M1N1TAZE ","M1N1TDXSS","M1N1TDYSS","M1N1TDZSS", & + "M1N2FKXE ","M1N2FKYE ","M1N2FKZE ","M1N2FMXE ","M1N2FMYE ","M1N2FMZE ","M1N2MKXE ", & + "M1N2MKYE ","M1N2MKZE ","M1N2MMXE ","M1N2MMYE ","M1N2MMZE ","M1N2RAXE ","M1N2RAYE ", & + "M1N2RAZE ","M1N2RDXE ","M1N2RDYE ","M1N2RDZE ","M1N2TAXE ","M1N2TAYE ","M1N2TAZE ", & + "M1N2TDXSS","M1N2TDYSS","M1N2TDZSS","M1N3FKXE ","M1N3FKYE ","M1N3FKZE ","M1N3FMXE ", & + "M1N3FMYE ","M1N3FMZE ","M1N3MKXE ","M1N3MKYE ","M1N3MKZE ","M1N3MMXE ","M1N3MMYE ", & + "M1N3MMZE ","M1N3RAXE ","M1N3RAYE ","M1N3RAZE ","M1N3RDXE ","M1N3RDYE ","M1N3RDZE ", & + "M1N3TAXE ","M1N3TAYE ","M1N3TAZE ","M1N3TDXSS","M1N3TDYSS","M1N3TDZSS","M1N4FKXE ", & + "M1N4FKYE ","M1N4FKZE ","M1N4FMXE ","M1N4FMYE ","M1N4FMZE ","M1N4MKXE ","M1N4MKYE ", & + "M1N4MKZE ","M1N4MMXE ","M1N4MMYE ","M1N4MMZE ","M1N4RAXE ","M1N4RAYE ","M1N4RAZE ", & + "M1N4RDXE ","M1N4RDYE ","M1N4RDZE ","M1N4TAXE ","M1N4TAYE ","M1N4TAZE ","M1N4TDXSS", & + "M1N4TDYSS","M1N4TDZSS","M1N5FKXE ","M1N5FKYE ","M1N5FKZE ","M1N5FMXE ","M1N5FMYE ", & + "M1N5FMZE ","M1N5MKXE ","M1N5MKYE ","M1N5MKZE ","M1N5MMXE ","M1N5MMYE ","M1N5MMZE ", & + "M1N5RAXE ","M1N5RAYE ","M1N5RAZE ","M1N5RDXE ","M1N5RDYE ","M1N5RDZE ","M1N5TAXE ", & + "M1N5TAYE ","M1N5TAZE ","M1N5TDXSS","M1N5TDYSS","M1N5TDZSS","M1N6FKXE ","M1N6FKYE ", & + "M1N6FKZE ","M1N6FMXE ","M1N6FMYE ","M1N6FMZE ","M1N6MKXE ","M1N6MKYE ","M1N6MKZE ", & + "M1N6MMXE ","M1N6MMYE ","M1N6MMZE ","M1N6RAXE ","M1N6RAYE ","M1N6RAZE ","M1N6RDXE ", & + "M1N6RDYE ","M1N6RDZE ","M1N6TAXE ","M1N6TAYE ","M1N6TAZE ","M1N6TDXSS","M1N6TDYSS", & + "M1N6TDZSS","M1N7FKXE ","M1N7FKYE ","M1N7FKZE ","M1N7FMXE ","M1N7FMYE ","M1N7FMZE ", & + "M1N7MKXE ","M1N7MKYE ","M1N7MKZE ","M1N7MMXE ","M1N7MMYE ","M1N7MMZE ","M1N7RAXE ", & + "M1N7RAYE ","M1N7RAZE ","M1N7RDXE ","M1N7RDYE ","M1N7RDZE ","M1N7TAXE ","M1N7TAYE ", & + "M1N7TAZE ","M1N7TDXSS","M1N7TDYSS","M1N7TDZSS","M1N8FKXE ","M1N8FKYE ","M1N8FKZE ", & + "M1N8FMXE ","M1N8FMYE ","M1N8FMZE ","M1N8MKXE ","M1N8MKYE ","M1N8MKZE ","M1N8MMXE ", & + "M1N8MMYE ","M1N8MMZE ","M1N8RAXE ","M1N8RAYE ","M1N8RAZE ","M1N8RDXE ","M1N8RDYE ", & + "M1N8RDZE ","M1N8TAXE ","M1N8TAYE ","M1N8TAZE ","M1N8TDXSS","M1N8TDYSS","M1N8TDZSS", & + "M1N9FKXE ","M1N9FKYE ","M1N9FKZE ","M1N9FMXE ","M1N9FMYE ","M1N9FMZE ","M1N9MKXE ", & + "M1N9MKYE ","M1N9MKZE ","M1N9MMXE ","M1N9MMYE ","M1N9MMZE ","M1N9RAXE ","M1N9RAYE ", & + "M1N9RAZE ","M1N9RDXE ","M1N9RDYE ","M1N9RDZE ","M1N9TAXE ","M1N9TAYE ","M1N9TAZE ", & + "M1N9TDXSS","M1N9TDYSS","M1N9TDZSS","M2N1FKXE ","M2N1FKYE ","M2N1FKZE ","M2N1FMXE ", & + "M2N1FMYE ","M2N1FMZE ","M2N1MKXE ","M2N1MKYE ","M2N1MKZE ","M2N1MMXE ","M2N1MMYE ", & + "M2N1MMZE ","M2N1RAXE ","M2N1RAYE ","M2N1RAZE ","M2N1RDXE ","M2N1RDYE ","M2N1RDZE ", & + "M2N1TAXE ","M2N1TAYE ","M2N1TAZE ","M2N1TDXSS","M2N1TDYSS","M2N1TDZSS","M2N2FKXE ", & + "M2N2FKYE ","M2N2FKZE ","M2N2FMXE ","M2N2FMYE ","M2N2FMZE ","M2N2MKXE ","M2N2MKYE ", & + "M2N2MKZE ","M2N2MMXE ","M2N2MMYE ","M2N2MMZE ","M2N2RAXE ","M2N2RAYE ","M2N2RAZE ", & + "M2N2RDXE ","M2N2RDYE ","M2N2RDZE ","M2N2TAXE ","M2N2TAYE ","M2N2TAZE ","M2N2TDXSS", & + "M2N2TDYSS","M2N2TDZSS","M2N3FKXE ","M2N3FKYE ","M2N3FKZE ","M2N3FMXE ","M2N3FMYE ", & + "M2N3FMZE ","M2N3MKXE ","M2N3MKYE ","M2N3MKZE ","M2N3MMXE ","M2N3MMYE ","M2N3MMZE ", & + "M2N3RAXE ","M2N3RAYE ","M2N3RAZE ","M2N3RDXE ","M2N3RDYE ","M2N3RDZE ","M2N3TAXE ", & + "M2N3TAYE ","M2N3TAZE ","M2N3TDXSS","M2N3TDYSS","M2N3TDZSS","M2N4FKXE ","M2N4FKYE ", & + "M2N4FKZE ","M2N4FMXE ","M2N4FMYE ","M2N4FMZE ","M2N4MKXE ","M2N4MKYE ","M2N4MKZE ", & + "M2N4MMXE ","M2N4MMYE ","M2N4MMZE ","M2N4RAXE ","M2N4RAYE ","M2N4RAZE ","M2N4RDXE ", & + "M2N4RDYE ","M2N4RDZE ","M2N4TAXE ","M2N4TAYE ","M2N4TAZE ","M2N4TDXSS","M2N4TDYSS", & + "M2N4TDZSS","M2N5FKXE ","M2N5FKYE ","M2N5FKZE ","M2N5FMXE ","M2N5FMYE ","M2N5FMZE ", & + "M2N5MKXE ","M2N5MKYE ","M2N5MKZE ","M2N5MMXE ","M2N5MMYE ","M2N5MMZE ","M2N5RAXE ", & + "M2N5RAYE ","M2N5RAZE ","M2N5RDXE ","M2N5RDYE ","M2N5RDZE ","M2N5TAXE ","M2N5TAYE ", & + "M2N5TAZE ","M2N5TDXSS","M2N5TDYSS","M2N5TDZSS","M2N6FKXE ","M2N6FKYE ","M2N6FKZE ", & + "M2N6FMXE ","M2N6FMYE ","M2N6FMZE ","M2N6MKXE ","M2N6MKYE ","M2N6MKZE ","M2N6MMXE ", & + "M2N6MMYE ","M2N6MMZE ","M2N6RAXE ","M2N6RAYE ","M2N6RAZE ","M2N6RDXE ","M2N6RDYE ", & + "M2N6RDZE ","M2N6TAXE ","M2N6TAYE ","M2N6TAZE ","M2N6TDXSS","M2N6TDYSS","M2N6TDZSS", & + "M2N7FKXE ","M2N7FKYE ","M2N7FKZE ","M2N7FMXE ","M2N7FMYE ","M2N7FMZE ","M2N7MKXE ", & + "M2N7MKYE ","M2N7MKZE ","M2N7MMXE ","M2N7MMYE ","M2N7MMZE ","M2N7RAXE ","M2N7RAYE ", & + "M2N7RAZE ","M2N7RDXE ","M2N7RDYE ","M2N7RDZE ","M2N7TAXE ","M2N7TAYE ","M2N7TAZE ", & + "M2N7TDXSS","M2N7TDYSS","M2N7TDZSS","M2N8FKXE ","M2N8FKYE ","M2N8FKZE ","M2N8FMXE ", & + "M2N8FMYE ","M2N8FMZE ","M2N8MKXE ","M2N8MKYE ","M2N8MKZE ","M2N8MMXE ","M2N8MMYE ", & + "M2N8MMZE ","M2N8RAXE ","M2N8RAYE ","M2N8RAZE ","M2N8RDXE ","M2N8RDYE ","M2N8RDZE ", & + "M2N8TAXE ","M2N8TAYE ","M2N8TAZE ","M2N8TDXSS","M2N8TDYSS","M2N8TDZSS","M2N9FKXE ", & + "M2N9FKYE ","M2N9FKZE ","M2N9FMXE ","M2N9FMYE ","M2N9FMZE ","M2N9MKXE ","M2N9MKYE ", & + "M2N9MKZE ","M2N9MMXE ","M2N9MMYE ","M2N9MMZE ","M2N9RAXE ","M2N9RAYE ","M2N9RAZE ", & + "M2N9RDXE ","M2N9RDYE ","M2N9RDZE ","M2N9TAXE ","M2N9TAYE ","M2N9TAZE ","M2N9TDXSS", & + "M2N9TDYSS","M2N9TDZSS","M3N1FKXE ","M3N1FKYE ","M3N1FKZE ","M3N1FMXE ","M3N1FMYE ", & + "M3N1FMZE ","M3N1MKXE ","M3N1MKYE ","M3N1MKZE ","M3N1MMXE ","M3N1MMYE ","M3N1MMZE ", & + "M3N1RAXE ","M3N1RAYE ","M3N1RAZE ","M3N1RDXE ","M3N1RDYE ","M3N1RDZE ","M3N1TAXE ", & + "M3N1TAYE ","M3N1TAZE ","M3N1TDXSS","M3N1TDYSS","M3N1TDZSS","M3N2FKXE ","M3N2FKYE ", & + "M3N2FKZE ","M3N2FMXE ","M3N2FMYE ","M3N2FMZE ","M3N2MKXE ","M3N2MKYE ","M3N2MKZE ", & + "M3N2MMXE ","M3N2MMYE ","M3N2MMZE ","M3N2RAXE ","M3N2RAYE ","M3N2RAZE ","M3N2RDXE ", & + "M3N2RDYE ","M3N2RDZE ","M3N2TAXE ","M3N2TAYE ","M3N2TAZE ","M3N2TDXSS","M3N2TDYSS", & + "M3N2TDZSS","M3N3FKXE ","M3N3FKYE ","M3N3FKZE ","M3N3FMXE ","M3N3FMYE ","M3N3FMZE ", & + "M3N3MKXE ","M3N3MKYE ","M3N3MKZE ","M3N3MMXE ","M3N3MMYE ","M3N3MMZE ","M3N3RAXE ", & + "M3N3RAYE ","M3N3RAZE ","M3N3RDXE ","M3N3RDYE ","M3N3RDZE ","M3N3TAXE ","M3N3TAYE ", & + "M3N3TAZE ","M3N3TDXSS","M3N3TDYSS","M3N3TDZSS","M3N4FKXE ","M3N4FKYE ","M3N4FKZE ", & + "M3N4FMXE ","M3N4FMYE ","M3N4FMZE ","M3N4MKXE ","M3N4MKYE ","M3N4MKZE ","M3N4MMXE ", & + "M3N4MMYE ","M3N4MMZE ","M3N4RAXE ","M3N4RAYE ","M3N4RAZE ","M3N4RDXE ","M3N4RDYE ", & + "M3N4RDZE ","M3N4TAXE ","M3N4TAYE ","M3N4TAZE ","M3N4TDXSS","M3N4TDYSS","M3N4TDZSS", & + "M3N5FKXE ","M3N5FKYE ","M3N5FKZE ","M3N5FMXE ","M3N5FMYE ","M3N5FMZE ","M3N5MKXE ", & + "M3N5MKYE ","M3N5MKZE ","M3N5MMXE ","M3N5MMYE ","M3N5MMZE ","M3N5RAXE ","M3N5RAYE ", & + "M3N5RAZE ","M3N5RDXE ","M3N5RDYE ","M3N5RDZE ","M3N5TAXE ","M3N5TAYE ","M3N5TAZE ", & + "M3N5TDXSS","M3N5TDYSS","M3N5TDZSS","M3N6FKXE ","M3N6FKYE ","M3N6FKZE ","M3N6FMXE ", & + "M3N6FMYE ","M3N6FMZE ","M3N6MKXE ","M3N6MKYE ","M3N6MKZE ","M3N6MMXE ","M3N6MMYE ", & + "M3N6MMZE ","M3N6RAXE ","M3N6RAYE ","M3N6RAZE ","M3N6RDXE ","M3N6RDYE ","M3N6RDZE ", & + "M3N6TAXE ","M3N6TAYE ","M3N6TAZE ","M3N6TDXSS","M3N6TDYSS","M3N6TDZSS","M3N7FKXE ", & + "M3N7FKYE ","M3N7FKZE ","M3N7FMXE ","M3N7FMYE ","M3N7FMZE ","M3N7MKXE ","M3N7MKYE ", & + "M3N7MKZE ","M3N7MMXE ","M3N7MMYE ","M3N7MMZE ","M3N7RAXE ","M3N7RAYE ","M3N7RAZE ", & + "M3N7RDXE ","M3N7RDYE ","M3N7RDZE ","M3N7TAXE ","M3N7TAYE ","M3N7TAZE ","M3N7TDXSS", & + "M3N7TDYSS","M3N7TDZSS","M3N8FKXE ","M3N8FKYE ","M3N8FKZE ","M3N8FMXE ","M3N8FMYE ", & + "M3N8FMZE ","M3N8MKXE ","M3N8MKYE ","M3N8MKZE ","M3N8MMXE ","M3N8MMYE ","M3N8MMZE ", & + "M3N8RAXE ","M3N8RAYE ","M3N8RAZE ","M3N8RDXE ","M3N8RDYE ","M3N8RDZE ","M3N8TAXE ", & + "M3N8TAYE ","M3N8TAZE ","M3N8TDXSS","M3N8TDYSS","M3N8TDZSS","M3N9FKXE ","M3N9FKYE ", & + "M3N9FKZE ","M3N9FMXE ","M3N9FMYE ","M3N9FMZE ","M3N9MKXE ","M3N9MKYE ","M3N9MKZE ", & + "M3N9MMXE ","M3N9MMYE ","M3N9MMZE ","M3N9RAXE ","M3N9RAYE ","M3N9RAZE ","M3N9RDXE ", & + "M3N9RDYE ","M3N9RDZE ","M3N9TAXE ","M3N9TAYE ","M3N9TAZE ","M3N9TDXSS","M3N9TDYSS", & + "M3N9TDZSS","M4N1FKXE ","M4N1FKYE ","M4N1FKZE ","M4N1FMXE ","M4N1FMYE ","M4N1FMZE ", & + "M4N1MKXE ","M4N1MKYE ","M4N1MKZE ","M4N1MMXE ","M4N1MMYE ","M4N1MMZE ","M4N1RAXE ", & + "M4N1RAYE ","M4N1RAZE ","M4N1RDXE ","M4N1RDYE ","M4N1RDZE ","M4N1TAXE ","M4N1TAYE ", & + "M4N1TAZE ","M4N1TDXSS","M4N1TDYSS","M4N1TDZSS","M4N2FKXE ","M4N2FKYE ","M4N2FKZE ", & + "M4N2FMXE ","M4N2FMYE ","M4N2FMZE ","M4N2MKXE ","M4N2MKYE ","M4N2MKZE ","M4N2MMXE ", & + "M4N2MMYE ","M4N2MMZE ","M4N2RAXE ","M4N2RAYE ","M4N2RAZE ","M4N2RDXE ","M4N2RDYE ", & + "M4N2RDZE ","M4N2TAXE ","M4N2TAYE ","M4N2TAZE ","M4N2TDXSS","M4N2TDYSS","M4N2TDZSS", & + "M4N3FKXE ","M4N3FKYE ","M4N3FKZE ","M4N3FMXE ","M4N3FMYE ","M4N3FMZE ","M4N3MKXE ", & + "M4N3MKYE ","M4N3MKZE ","M4N3MMXE ","M4N3MMYE ","M4N3MMZE ","M4N3RAXE ","M4N3RAYE ", & + "M4N3RAZE ","M4N3RDXE ","M4N3RDYE ","M4N3RDZE ","M4N3TAXE ","M4N3TAYE ","M4N3TAZE ", & + "M4N3TDXSS","M4N3TDYSS","M4N3TDZSS","M4N4FKXE ","M4N4FKYE ","M4N4FKZE ","M4N4FMXE ", & + "M4N4FMYE ","M4N4FMZE ","M4N4MKXE ","M4N4MKYE ","M4N4MKZE ","M4N4MMXE ","M4N4MMYE ", & + "M4N4MMZE ","M4N4RAXE ","M4N4RAYE ","M4N4RAZE ","M4N4RDXE ","M4N4RDYE ","M4N4RDZE ", & + "M4N4TAXE ","M4N4TAYE ","M4N4TAZE ","M4N4TDXSS","M4N4TDYSS","M4N4TDZSS","M4N5FKXE ", & + "M4N5FKYE ","M4N5FKZE ","M4N5FMXE ","M4N5FMYE ","M4N5FMZE ","M4N5MKXE ","M4N5MKYE ", & + "M4N5MKZE ","M4N5MMXE ","M4N5MMYE ","M4N5MMZE ","M4N5RAXE ","M4N5RAYE ","M4N5RAZE ", & + "M4N5RDXE ","M4N5RDYE ","M4N5RDZE ","M4N5TAXE ","M4N5TAYE ","M4N5TAZE ","M4N5TDXSS", & + "M4N5TDYSS","M4N5TDZSS","M4N6FKXE ","M4N6FKYE ","M4N6FKZE ","M4N6FMXE ","M4N6FMYE ", & + "M4N6FMZE ","M4N6MKXE ","M4N6MKYE ","M4N6MKZE ","M4N6MMXE ","M4N6MMYE ","M4N6MMZE ", & + "M4N6RAXE ","M4N6RAYE ","M4N6RAZE ","M4N6RDXE ","M4N6RDYE ","M4N6RDZE ","M4N6TAXE ", & + "M4N6TAYE ","M4N6TAZE ","M4N6TDXSS","M4N6TDYSS","M4N6TDZSS","M4N7FKXE ","M4N7FKYE ", & + "M4N7FKZE ","M4N7FMXE ","M4N7FMYE ","M4N7FMZE ","M4N7MKXE ","M4N7MKYE ","M4N7MKZE ", & + "M4N7MMXE ","M4N7MMYE ","M4N7MMZE ","M4N7RAXE ","M4N7RAYE ","M4N7RAZE ","M4N7RDXE ", & + "M4N7RDYE ","M4N7RDZE ","M4N7TAXE ","M4N7TAYE ","M4N7TAZE ","M4N7TDXSS","M4N7TDYSS", & + "M4N7TDZSS","M4N8FKXE ","M4N8FKYE ","M4N8FKZE ","M4N8FMXE ","M4N8FMYE ","M4N8FMZE ", & + "M4N8MKXE ","M4N8MKYE ","M4N8MKZE ","M4N8MMXE ","M4N8MMYE ","M4N8MMZE ","M4N8RAXE ", & + "M4N8RAYE ","M4N8RAZE ","M4N8RDXE ","M4N8RDYE ","M4N8RDZE ","M4N8TAXE ","M4N8TAYE ", & + "M4N8TAZE ","M4N8TDXSS","M4N8TDYSS","M4N8TDZSS","M4N9FKXE ","M4N9FKYE ","M4N9FKZE ", & + "M4N9FMXE ","M4N9FMYE ","M4N9FMZE ","M4N9MKXE ","M4N9MKYE ","M4N9MKZE ","M4N9MMXE ", & + "M4N9MMYE ","M4N9MMZE ","M4N9RAXE ","M4N9RAYE ","M4N9RAZE ","M4N9RDXE ","M4N9RDYE ", & + "M4N9RDZE ","M4N9TAXE ","M4N9TAYE ","M4N9TAZE ","M4N9TDXSS","M4N9TDYSS","M4N9TDZSS", & + "M5N1FKXE ","M5N1FKYE ","M5N1FKZE ","M5N1FMXE ","M5N1FMYE ","M5N1FMZE ","M5N1MKXE ", & + "M5N1MKYE ","M5N1MKZE ","M5N1MMXE ","M5N1MMYE ","M5N1MMZE ","M5N1RAXE ","M5N1RAYE ", & + "M5N1RAZE ","M5N1RDXE ","M5N1RDYE ","M5N1RDZE ","M5N1TAXE ","M5N1TAYE ","M5N1TAZE ", & + "M5N1TDXSS","M5N1TDYSS","M5N1TDZSS","M5N2FKXE ","M5N2FKYE ","M5N2FKZE ","M5N2FMXE ", & + "M5N2FMYE ","M5N2FMZE ","M5N2MKXE ","M5N2MKYE ","M5N2MKZE ","M5N2MMXE ","M5N2MMYE ", & + "M5N2MMZE ","M5N2RAXE ","M5N2RAYE ","M5N2RAZE ","M5N2RDXE ","M5N2RDYE ","M5N2RDZE ", & + "M5N2TAXE ","M5N2TAYE ","M5N2TAZE ","M5N2TDXSS","M5N2TDYSS","M5N2TDZSS","M5N3FKXE ", & + "M5N3FKYE ","M5N3FKZE ","M5N3FMXE ","M5N3FMYE ","M5N3FMZE ","M5N3MKXE ","M5N3MKYE ", & + "M5N3MKZE ","M5N3MMXE ","M5N3MMYE ","M5N3MMZE ","M5N3RAXE ","M5N3RAYE ","M5N3RAZE ", & + "M5N3RDXE ","M5N3RDYE ","M5N3RDZE ","M5N3TAXE ","M5N3TAYE ","M5N3TAZE ","M5N3TDXSS", & + "M5N3TDYSS","M5N3TDZSS","M5N4FKXE ","M5N4FKYE ","M5N4FKZE ","M5N4FMXE ","M5N4FMYE ", & + "M5N4FMZE ","M5N4MKXE ","M5N4MKYE ","M5N4MKZE ","M5N4MMXE ","M5N4MMYE ","M5N4MMZE ", & + "M5N4RAXE ","M5N4RAYE ","M5N4RAZE ","M5N4RDXE ","M5N4RDYE ","M5N4RDZE ","M5N4TAXE ", & + "M5N4TAYE ","M5N4TAZE ","M5N4TDXSS","M5N4TDYSS","M5N4TDZSS","M5N5FKXE ","M5N5FKYE ", & + "M5N5FKZE ","M5N5FMXE ","M5N5FMYE ","M5N5FMZE ","M5N5MKXE ","M5N5MKYE ","M5N5MKZE ", & + "M5N5MMXE ","M5N5MMYE ","M5N5MMZE ","M5N5RAXE ","M5N5RAYE ","M5N5RAZE ","M5N5RDXE ", & + "M5N5RDYE ","M5N5RDZE ","M5N5TAXE ","M5N5TAYE ","M5N5TAZE ","M5N5TDXSS","M5N5TDYSS", & + "M5N5TDZSS","M5N6FKXE ","M5N6FKYE ","M5N6FKZE ","M5N6FMXE ","M5N6FMYE ","M5N6FMZE ", & + "M5N6MKXE ","M5N6MKYE ","M5N6MKZE ","M5N6MMXE ","M5N6MMYE ","M5N6MMZE ","M5N6RAXE ", & + "M5N6RAYE ","M5N6RAZE ","M5N6RDXE ","M5N6RDYE ","M5N6RDZE ","M5N6TAXE ","M5N6TAYE ", & + "M5N6TAZE ","M5N6TDXSS","M5N6TDYSS","M5N6TDZSS","M5N7FKXE ","M5N7FKYE ","M5N7FKZE ", & + "M5N7FMXE ","M5N7FMYE ","M5N7FMZE ","M5N7MKXE ","M5N7MKYE ","M5N7MKZE ","M5N7MMXE ", & + "M5N7MMYE ","M5N7MMZE ","M5N7RAXE ","M5N7RAYE ","M5N7RAZE ","M5N7RDXE ","M5N7RDYE ", & + "M5N7RDZE ","M5N7TAXE ","M5N7TAYE ","M5N7TAZE ","M5N7TDXSS","M5N7TDYSS","M5N7TDZSS", & + "M5N8FKXE ","M5N8FKYE ","M5N8FKZE ","M5N8FMXE ","M5N8FMYE ","M5N8FMZE ","M5N8MKXE ", & + "M5N8MKYE ","M5N8MKZE ","M5N8MMXE ","M5N8MMYE ","M5N8MMZE ","M5N8RAXE ","M5N8RAYE ", & + "M5N8RAZE ","M5N8RDXE ","M5N8RDYE ","M5N8RDZE ","M5N8TAXE ","M5N8TAYE ","M5N8TAZE ", & + "M5N8TDXSS","M5N8TDYSS","M5N8TDZSS","M5N9FKXE ","M5N9FKYE ","M5N9FKZE ","M5N9FMXE ", & + "M5N9FMYE ","M5N9FMZE ","M5N9MKXE ","M5N9MKYE ","M5N9MKZE ","M5N9MMXE ","M5N9MMYE ", & + "M5N9MMZE ","M5N9RAXE ","M5N9RAYE ","M5N9RAZE ","M5N9RDXE ","M5N9RDYE ","M5N9RDZE ", & + "M5N9TAXE ","M5N9TAYE ","M5N9TAZE ","M5N9TDXSS","M5N9TDYSS","M5N9TDZSS","M6N1FKXE ", & + "M6N1FKYE ","M6N1FKZE ","M6N1FMXE ","M6N1FMYE ","M6N1FMZE ","M6N1MKXE ","M6N1MKYE ", & + "M6N1MKZE ","M6N1MMXE ","M6N1MMYE ","M6N1MMZE ","M6N1RAXE ","M6N1RAYE ","M6N1RAZE ", & + "M6N1RDXE ","M6N1RDYE ","M6N1RDZE ","M6N1TAXE ","M6N1TAYE ","M6N1TAZE ","M6N1TDXSS", & + "M6N1TDYSS","M6N1TDZSS","M6N2FKXE ","M6N2FKYE ","M6N2FKZE ","M6N2FMXE ","M6N2FMYE ", & + "M6N2FMZE ","M6N2MKXE ","M6N2MKYE ","M6N2MKZE ","M6N2MMXE ","M6N2MMYE ","M6N2MMZE ", & + "M6N2RAXE ","M6N2RAYE ","M6N2RAZE ","M6N2RDXE ","M6N2RDYE ","M6N2RDZE ","M6N2TAXE ", & + "M6N2TAYE ","M6N2TAZE ","M6N2TDXSS","M6N2TDYSS","M6N2TDZSS","M6N3FKXE ","M6N3FKYE ", & + "M6N3FKZE ","M6N3FMXE ","M6N3FMYE ","M6N3FMZE ","M6N3MKXE ","M6N3MKYE ","M6N3MKZE ", & + "M6N3MMXE ","M6N3MMYE ","M6N3MMZE ","M6N3RAXE ","M6N3RAYE ","M6N3RAZE ","M6N3RDXE ", & + "M6N3RDYE ","M6N3RDZE ","M6N3TAXE ","M6N3TAYE ","M6N3TAZE ","M6N3TDXSS","M6N3TDYSS", & + "M6N3TDZSS","M6N4FKXE ","M6N4FKYE ","M6N4FKZE ","M6N4FMXE ","M6N4FMYE ","M6N4FMZE ", & + "M6N4MKXE ","M6N4MKYE ","M6N4MKZE ","M6N4MMXE ","M6N4MMYE ","M6N4MMZE ","M6N4RAXE ", & + "M6N4RAYE ","M6N4RAZE ","M6N4RDXE ","M6N4RDYE ","M6N4RDZE ","M6N4TAXE ","M6N4TAYE ", & + "M6N4TAZE ","M6N4TDXSS","M6N4TDYSS","M6N4TDZSS","M6N5FKXE ","M6N5FKYE ","M6N5FKZE ", & + "M6N5FMXE ","M6N5FMYE ","M6N5FMZE ","M6N5MKXE ","M6N5MKYE ","M6N5MKZE ","M6N5MMXE ", & + "M6N5MMYE ","M6N5MMZE ","M6N5RAXE ","M6N5RAYE ","M6N5RAZE ","M6N5RDXE ","M6N5RDYE ", & + "M6N5RDZE ","M6N5TAXE ","M6N5TAYE ","M6N5TAZE ","M6N5TDXSS","M6N5TDYSS","M6N5TDZSS", & + "M6N6FKXE ","M6N6FKYE ","M6N6FKZE ","M6N6FMXE ","M6N6FMYE ","M6N6FMZE ","M6N6MKXE ", & + "M6N6MKYE ","M6N6MKZE ","M6N6MMXE ","M6N6MMYE ","M6N6MMZE ","M6N6RAXE ","M6N6RAYE ", & + "M6N6RAZE ","M6N6RDXE ","M6N6RDYE ","M6N6RDZE ","M6N6TAXE ","M6N6TAYE ","M6N6TAZE ", & + "M6N6TDXSS","M6N6TDYSS","M6N6TDZSS","M6N7FKXE ","M6N7FKYE ","M6N7FKZE ","M6N7FMXE ", & + "M6N7FMYE ","M6N7FMZE ","M6N7MKXE ","M6N7MKYE ","M6N7MKZE ","M6N7MMXE ","M6N7MMYE ", & + "M6N7MMZE ","M6N7RAXE ","M6N7RAYE ","M6N7RAZE ","M6N7RDXE ","M6N7RDYE ","M6N7RDZE ", & + "M6N7TAXE ","M6N7TAYE ","M6N7TAZE ","M6N7TDXSS","M6N7TDYSS","M6N7TDZSS","M6N8FKXE ", & + "M6N8FKYE ","M6N8FKZE ","M6N8FMXE ","M6N8FMYE ","M6N8FMZE ","M6N8MKXE ","M6N8MKYE ", & + "M6N8MKZE ","M6N8MMXE ","M6N8MMYE ","M6N8MMZE ","M6N8RAXE ","M6N8RAYE ","M6N8RAZE ", & + "M6N8RDXE ","M6N8RDYE ","M6N8RDZE ","M6N8TAXE ","M6N8TAYE ","M6N8TAZE ","M6N8TDXSS", & + "M6N8TDYSS","M6N8TDZSS","M6N9FKXE ","M6N9FKYE ","M6N9FKZE ","M6N9FMXE ","M6N9FMYE ", & + "M6N9FMZE ","M6N9MKXE ","M6N9MKYE ","M6N9MKZE ","M6N9MMXE ","M6N9MMYE ","M6N9MMZE ", & + "M6N9RAXE ","M6N9RAYE ","M6N9RAZE ","M6N9RDXE ","M6N9RDYE ","M6N9RDZE ","M6N9TAXE ", & + "M6N9TAYE ","M6N9TAZE ","M6N9TDXSS","M6N9TDYSS","M6N9TDZSS","M7N1FKXE ","M7N1FKYE ", & + "M7N1FKZE ","M7N1FMXE ","M7N1FMYE ","M7N1FMZE ","M7N1MKXE ","M7N1MKYE ","M7N1MKZE ", & + "M7N1MMXE ","M7N1MMYE ","M7N1MMZE ","M7N1RAXE ","M7N1RAYE ","M7N1RAZE ","M7N1RDXE ", & + "M7N1RDYE ","M7N1RDZE ","M7N1TAXE ","M7N1TAYE ","M7N1TAZE ","M7N1TDXSS","M7N1TDYSS", & + "M7N1TDZSS","M7N2FKXE ","M7N2FKYE ","M7N2FKZE ","M7N2FMXE ","M7N2FMYE ","M7N2FMZE ", & + "M7N2MKXE ","M7N2MKYE ","M7N2MKZE ","M7N2MMXE ","M7N2MMYE ","M7N2MMZE ","M7N2RAXE ", & + "M7N2RAYE ","M7N2RAZE ","M7N2RDXE ","M7N2RDYE ","M7N2RDZE ","M7N2TAXE ","M7N2TAYE ", & + "M7N2TAZE ","M7N2TDXSS","M7N2TDYSS","M7N2TDZSS","M7N3FKXE ","M7N3FKYE ","M7N3FKZE ", & + "M7N3FMXE ","M7N3FMYE ","M7N3FMZE ","M7N3MKXE ","M7N3MKYE ","M7N3MKZE ","M7N3MMXE ", & + "M7N3MMYE ","M7N3MMZE ","M7N3RAXE ","M7N3RAYE ","M7N3RAZE ","M7N3RDXE ","M7N3RDYE ", & + "M7N3RDZE ","M7N3TAXE ","M7N3TAYE ","M7N3TAZE ","M7N3TDXSS","M7N3TDYSS","M7N3TDZSS", & + "M7N4FKXE ","M7N4FKYE ","M7N4FKZE ","M7N4FMXE ","M7N4FMYE ","M7N4FMZE ","M7N4MKXE ", & + "M7N4MKYE ","M7N4MKZE ","M7N4MMXE ","M7N4MMYE ","M7N4MMZE ","M7N4RAXE ","M7N4RAYE ", & + "M7N4RAZE ","M7N4RDXE ","M7N4RDYE ","M7N4RDZE ","M7N4TAXE ","M7N4TAYE ","M7N4TAZE ", & + "M7N4TDXSS","M7N4TDYSS","M7N4TDZSS","M7N5FKXE ","M7N5FKYE ","M7N5FKZE ","M7N5FMXE ", & + "M7N5FMYE ","M7N5FMZE ","M7N5MKXE ","M7N5MKYE ","M7N5MKZE ","M7N5MMXE ","M7N5MMYE ", & + "M7N5MMZE ","M7N5RAXE ","M7N5RAYE ","M7N5RAZE ","M7N5RDXE ","M7N5RDYE ","M7N5RDZE ", & + "M7N5TAXE ","M7N5TAYE ","M7N5TAZE ","M7N5TDXSS","M7N5TDYSS","M7N5TDZSS","M7N6FKXE ", & + "M7N6FKYE ","M7N6FKZE ","M7N6FMXE ","M7N6FMYE ","M7N6FMZE ","M7N6MKXE ","M7N6MKYE ", & + "M7N6MKZE ","M7N6MMXE ","M7N6MMYE ","M7N6MMZE ","M7N6RAXE ","M7N6RAYE ","M7N6RAZE ", & + "M7N6RDXE ","M7N6RDYE ","M7N6RDZE ","M7N6TAXE ","M7N6TAYE ","M7N6TAZE ","M7N6TDXSS", & + "M7N6TDYSS","M7N6TDZSS","M7N7FKXE ","M7N7FKYE ","M7N7FKZE ","M7N7FMXE ","M7N7FMYE ", & + "M7N7FMZE ","M7N7MKXE ","M7N7MKYE ","M7N7MKZE ","M7N7MMXE ","M7N7MMYE ","M7N7MMZE ", & + "M7N7RAXE ","M7N7RAYE ","M7N7RAZE ","M7N7RDXE ","M7N7RDYE ","M7N7RDZE ","M7N7TAXE ", & + "M7N7TAYE ","M7N7TAZE ","M7N7TDXSS","M7N7TDYSS","M7N7TDZSS","M7N8FKXE ","M7N8FKYE ", & + "M7N8FKZE ","M7N8FMXE ","M7N8FMYE ","M7N8FMZE ","M7N8MKXE ","M7N8MKYE ","M7N8MKZE ", & + "M7N8MMXE ","M7N8MMYE ","M7N8MMZE ","M7N8RAXE ","M7N8RAYE ","M7N8RAZE ","M7N8RDXE ", & + "M7N8RDYE ","M7N8RDZE ","M7N8TAXE ","M7N8TAYE ","M7N8TAZE ","M7N8TDXSS","M7N8TDYSS", & + "M7N8TDZSS","M7N9FKXE ","M7N9FKYE ","M7N9FKZE ","M7N9FMXE ","M7N9FMYE ","M7N9FMZE ", & + "M7N9MKXE ","M7N9MKYE ","M7N9MKZE ","M7N9MMXE ","M7N9MMYE ","M7N9MMZE ","M7N9RAXE ", & + "M7N9RAYE ","M7N9RAZE ","M7N9RDXE ","M7N9RDYE ","M7N9RDZE ","M7N9TAXE ","M7N9TAYE ", & + "M7N9TAZE ","M7N9TDXSS","M7N9TDYSS","M7N9TDZSS","M8N1FKXE ","M8N1FKYE ","M8N1FKZE ", & + "M8N1FMXE ","M8N1FMYE ","M8N1FMZE ","M8N1MKXE ","M8N1MKYE ","M8N1MKZE ","M8N1MMXE ", & + "M8N1MMYE ","M8N1MMZE ","M8N1RAXE ","M8N1RAYE ","M8N1RAZE ","M8N1RDXE ","M8N1RDYE ", & + "M8N1RDZE ","M8N1TAXE ","M8N1TAYE ","M8N1TAZE ","M8N1TDXSS","M8N1TDYSS","M8N1TDZSS", & + "M8N2FKXE ","M8N2FKYE ","M8N2FKZE ","M8N2FMXE ","M8N2FMYE ","M8N2FMZE ","M8N2MKXE ", & + "M8N2MKYE ","M8N2MKZE ","M8N2MMXE ","M8N2MMYE ","M8N2MMZE ","M8N2RAXE ","M8N2RAYE ", & + "M8N2RAZE ","M8N2RDXE ","M8N2RDYE ","M8N2RDZE ","M8N2TAXE ","M8N2TAYE ","M8N2TAZE ", & + "M8N2TDXSS","M8N2TDYSS","M8N2TDZSS","M8N3FKXE ","M8N3FKYE ","M8N3FKZE ","M8N3FMXE ", & + "M8N3FMYE ","M8N3FMZE ","M8N3MKXE ","M8N3MKYE ","M8N3MKZE ","M8N3MMXE ","M8N3MMYE ", & + "M8N3MMZE ","M8N3RAXE ","M8N3RAYE ","M8N3RAZE ","M8N3RDXE ","M8N3RDYE ","M8N3RDZE ", & + "M8N3TAXE ","M8N3TAYE ","M8N3TAZE ","M8N3TDXSS","M8N3TDYSS","M8N3TDZSS","M8N4FKXE ", & + "M8N4FKYE ","M8N4FKZE ","M8N4FMXE ","M8N4FMYE ","M8N4FMZE ","M8N4MKXE ","M8N4MKYE ", & + "M8N4MKZE ","M8N4MMXE ","M8N4MMYE ","M8N4MMZE ","M8N4RAXE ","M8N4RAYE ","M8N4RAZE ", & + "M8N4RDXE ","M8N4RDYE ","M8N4RDZE ","M8N4TAXE ","M8N4TAYE ","M8N4TAZE ","M8N4TDXSS", & + "M8N4TDYSS","M8N4TDZSS","M8N5FKXE ","M8N5FKYE ","M8N5FKZE ","M8N5FMXE ","M8N5FMYE ", & + "M8N5FMZE ","M8N5MKXE ","M8N5MKYE ","M8N5MKZE ","M8N5MMXE ","M8N5MMYE ","M8N5MMZE ", & + "M8N5RAXE ","M8N5RAYE ","M8N5RAZE ","M8N5RDXE ","M8N5RDYE ","M8N5RDZE ","M8N5TAXE ", & + "M8N5TAYE ","M8N5TAZE ","M8N5TDXSS","M8N5TDYSS","M8N5TDZSS","M8N6FKXE ","M8N6FKYE ", & + "M8N6FKZE ","M8N6FMXE ","M8N6FMYE ","M8N6FMZE ","M8N6MKXE ","M8N6MKYE ","M8N6MKZE ", & + "M8N6MMXE ","M8N6MMYE ","M8N6MMZE ","M8N6RAXE ","M8N6RAYE ","M8N6RAZE ","M8N6RDXE ", & + "M8N6RDYE ","M8N6RDZE ","M8N6TAXE ","M8N6TAYE ","M8N6TAZE ","M8N6TDXSS","M8N6TDYSS", & + "M8N6TDZSS","M8N7FKXE ","M8N7FKYE ","M8N7FKZE ","M8N7FMXE ","M8N7FMYE ","M8N7FMZE ", & + "M8N7MKXE ","M8N7MKYE ","M8N7MKZE ","M8N7MMXE ","M8N7MMYE ","M8N7MMZE ","M8N7RAXE ", & + "M8N7RAYE ","M8N7RAZE ","M8N7RDXE ","M8N7RDYE ","M8N7RDZE ","M8N7TAXE ","M8N7TAYE ", & + "M8N7TAZE ","M8N7TDXSS","M8N7TDYSS","M8N7TDZSS","M8N8FKXE ","M8N8FKYE ","M8N8FKZE ", & + "M8N8FMXE ","M8N8FMYE ","M8N8FMZE ","M8N8MKXE ","M8N8MKYE ","M8N8MKZE ","M8N8MMXE ", & + "M8N8MMYE ","M8N8MMZE ","M8N8RAXE ","M8N8RAYE ","M8N8RAZE ","M8N8RDXE ","M8N8RDYE ", & + "M8N8RDZE ","M8N8TAXE ","M8N8TAYE ","M8N8TAZE ","M8N8TDXSS","M8N8TDYSS","M8N8TDZSS", & + "M8N9FKXE ","M8N9FKYE ","M8N9FKZE ","M8N9FMXE ","M8N9FMYE ","M8N9FMZE ","M8N9MKXE ", & + "M8N9MKYE ","M8N9MKZE ","M8N9MMXE ","M8N9MMYE ","M8N9MMZE ","M8N9RAXE ","M8N9RAYE ", & + "M8N9RAZE ","M8N9RDXE ","M8N9RDYE ","M8N9RDZE ","M8N9TAXE ","M8N9TAYE ","M8N9TAZE ", & + "M8N9TDXSS","M8N9TDYSS","M8N9TDZSS","M9N1FKXE ","M9N1FKYE ","M9N1FKZE ","M9N1FMXE ", & + "M9N1FMYE ","M9N1FMZE ","M9N1MKXE ","M9N1MKYE ","M9N1MKZE ","M9N1MMXE ","M9N1MMYE ", & + "M9N1MMZE ","M9N1RAXE ","M9N1RAYE ","M9N1RAZE ","M9N1RDXE ","M9N1RDYE ","M9N1RDZE ", & + "M9N1TAXE ","M9N1TAYE ","M9N1TAZE ","M9N1TDXSS","M9N1TDYSS","M9N1TDZSS","M9N2FKXE ", & + "M9N2FKYE ","M9N2FKZE ","M9N2FMXE ","M9N2FMYE ","M9N2FMZE ","M9N2MKXE ","M9N2MKYE ", & + "M9N2MKZE ","M9N2MMXE ","M9N2MMYE ","M9N2MMZE ","M9N2RAXE ","M9N2RAYE ","M9N2RAZE ", & + "M9N2RDXE ","M9N2RDYE ","M9N2RDZE ","M9N2TAXE ","M9N2TAYE ","M9N2TAZE ","M9N2TDXSS", & + "M9N2TDYSS","M9N2TDZSS","M9N3FKXE ","M9N3FKYE ","M9N3FKZE ","M9N3FMXE ","M9N3FMYE ", & + "M9N3FMZE ","M9N3MKXE ","M9N3MKYE ","M9N3MKZE ","M9N3MMXE ","M9N3MMYE ","M9N3MMZE ", & + "M9N3RAXE ","M9N3RAYE ","M9N3RAZE ","M9N3RDXE ","M9N3RDYE ","M9N3RDZE ","M9N3TAXE ", & + "M9N3TAYE ","M9N3TAZE ","M9N3TDXSS","M9N3TDYSS","M9N3TDZSS","M9N4FKXE ","M9N4FKYE ", & + "M9N4FKZE ","M9N4FMXE ","M9N4FMYE ","M9N4FMZE ","M9N4MKXE ","M9N4MKYE ","M9N4MKZE ", & + "M9N4MMXE ","M9N4MMYE ","M9N4MMZE ","M9N4RAXE ","M9N4RAYE ","M9N4RAZE ","M9N4RDXE ", & + "M9N4RDYE ","M9N4RDZE ","M9N4TAXE ","M9N4TAYE ","M9N4TAZE ","M9N4TDXSS","M9N4TDYSS", & + "M9N4TDZSS","M9N5FKXE ","M9N5FKYE ","M9N5FKZE ","M9N5FMXE ","M9N5FMYE ","M9N5FMZE ", & + "M9N5MKXE ","M9N5MKYE ","M9N5MKZE ","M9N5MMXE ","M9N5MMYE ","M9N5MMZE ","M9N5RAXE ", & + "M9N5RAYE ","M9N5RAZE ","M9N5RDXE ","M9N5RDYE ","M9N5RDZE ","M9N5TAXE ","M9N5TAYE ", & + "M9N5TAZE ","M9N5TDXSS","M9N5TDYSS","M9N5TDZSS","M9N6FKXE ","M9N6FKYE ","M9N6FKZE ", & + "M9N6FMXE ","M9N6FMYE ","M9N6FMZE ","M9N6MKXE ","M9N6MKYE ","M9N6MKZE ","M9N6MMXE ", & + "M9N6MMYE ","M9N6MMZE ","M9N6RAXE ","M9N6RAYE ","M9N6RAZE ","M9N6RDXE ","M9N6RDYE ", & + "M9N6RDZE ","M9N6TAXE ","M9N6TAYE ","M9N6TAZE ","M9N6TDXSS","M9N6TDYSS","M9N6TDZSS", & + "M9N7FKXE ","M9N7FKYE ","M9N7FKZE ","M9N7FMXE ","M9N7FMYE ","M9N7FMZE ","M9N7MKXE ", & + "M9N7MKYE ","M9N7MKZE ","M9N7MMXE ","M9N7MMYE ","M9N7MMZE ","M9N7RAXE ","M9N7RAYE ", & + "M9N7RAZE ","M9N7RDXE ","M9N7RDYE ","M9N7RDZE ","M9N7TAXE ","M9N7TAYE ","M9N7TAZE ", & + "M9N7TDXSS","M9N7TDYSS","M9N7TDZSS","M9N8FKXE ","M9N8FKYE ","M9N8FKZE ","M9N8FMXE ", & + "M9N8FMYE ","M9N8FMZE ","M9N8MKXE ","M9N8MKYE ","M9N8MKZE ","M9N8MMXE ","M9N8MMYE ", & + "M9N8MMZE ","M9N8RAXE ","M9N8RAYE ","M9N8RAZE ","M9N8RDXE ","M9N8RDYE ","M9N8RDZE ", & + "M9N8TAXE ","M9N8TAYE ","M9N8TAZE ","M9N8TDXSS","M9N8TDYSS","M9N8TDZSS","M9N9FKXE ", & + "M9N9FKYE ","M9N9FKZE ","M9N9FMXE ","M9N9FMYE ","M9N9FMZE ","M9N9MKXE ","M9N9MKYE ", & + "M9N9MKZE ","M9N9MMXE ","M9N9MMYE ","M9N9MMZE ","M9N9RAXE ","M9N9RAYE ","M9N9RAZE ", & + "M9N9RDXE ","M9N9RDYE ","M9N9RDZE ","M9N9TAXE ","M9N9TAYE ","M9N9TAZE ","M9N9TDXSS", & + "M9N9TDYSS","M9N9TDZSS","REACTFXSS","REACTFYSS","REACTFZSS","REACTMXSS","REACTMYSS", & + "REACTMZSS","SSQM01 ","SSQM02 ","SSQM03 ","SSQM04 ","SSQM05 ","SSQM06 ", & + "SSQM07 ","SSQM08 ","SSQM09 ","SSQM10 ","SSQM11 ","SSQM12 ","SSQM13 ", & + "SSQM14 ","SSQM15 ","SSQM16 ","SSQM17 ","SSQM18 ","SSQM19 ","SSQM20 ", & + "SSQM21 ","SSQM22 ","SSQM23 ","SSQM24 ","SSQM25 ","SSQM26 ","SSQM27 ", & + "SSQM28 ","SSQM29 ","SSQM30 ","SSQM31 ","SSQM32 ","SSQM33 ","SSQM34 ", & + "SSQM35 ","SSQM36 ","SSQM37 ","SSQM38 ","SSQM39 ","SSQM40 ","SSQM41 ", & + "SSQM42 ","SSQM43 ","SSQM44 ","SSQM45 ","SSQM46 ","SSQM47 ","SSQM48 ", & + "SSQM49 ","SSQM50 ","SSQM51 ","SSQM52 ","SSQM53 ","SSQM54 ","SSQM55 ", & + "SSQM56 ","SSQM57 ","SSQM58 ","SSQM59 ","SSQM60 ","SSQM61 ","SSQM62 ", & + "SSQM63 ","SSQM64 ","SSQM65 ","SSQM66 ","SSQM67 ","SSQM68 ","SSQM69 ", & + "SSQM70 ","SSQM71 ","SSQM72 ","SSQM73 ","SSQM74 ","SSQM75 ","SSQM76 ", & + "SSQM77 ","SSQM78 ","SSQM79 ","SSQM80 ","SSQM81 ","SSQM82 ","SSQM83 ", & + "SSQM84 ","SSQM85 ","SSQM86 ","SSQM87 ","SSQM88 ","SSQM89 ","SSQM90 ", & + "SSQM91 ","SSQM92 ","SSQM93 ","SSQM94 ","SSQM95 ","SSQM96 ","SSQM97 ", & + "SSQM98 ","SSQM99 ","SSQMD01 ","SSQMD02 ","SSQMD03 ","SSQMD04 ","SSQMD05 ", & + "SSQMD06 ","SSQMD07 ","SSQMD08 ","SSQMD09 ","SSQMD10 ","SSQMD11 ","SSQMD12 ", & + "SSQMD13 ","SSQMD14 ","SSQMD15 ","SSQMD16 ","SSQMD17 ","SSQMD18 ","SSQMD19 ", & + "SSQMD20 ","SSQMD21 ","SSQMD22 ","SSQMD23 ","SSQMD24 ","SSQMD25 ","SSQMD26 ", & + "SSQMD27 ","SSQMD28 ","SSQMD29 ","SSQMD30 ","SSQMD31 ","SSQMD32 ","SSQMD33 ", & + "SSQMD34 ","SSQMD35 ","SSQMD36 ","SSQMD37 ","SSQMD38 ","SSQMD39 ","SSQMD40 ", & + "SSQMD41 ","SSQMD42 ","SSQMD43 ","SSQMD44 ","SSQMD45 ","SSQMD46 ","SSQMD47 ", & + "SSQMD48 ","SSQMD49 ","SSQMD50 ","SSQMD51 ","SSQMD52 ","SSQMD53 ","SSQMD54 ", & + "SSQMD55 ","SSQMD56 ","SSQMD57 ","SSQMD58 ","SSQMD59 ","SSQMD60 ","SSQMD61 ", & + "SSQMD62 ","SSQMD63 ","SSQMD64 ","SSQMD65 ","SSQMD66 ","SSQMD67 ","SSQMD68 ", & + "SSQMD69 ","SSQMD70 ","SSQMD71 ","SSQMD72 ","SSQMD73 ","SSQMD74 ","SSQMD75 ", & + "SSQMD76 ","SSQMD77 ","SSQMD78 ","SSQMD79 ","SSQMD80 ","SSQMD81 ","SSQMD82 ", & + "SSQMD83 ","SSQMD84 ","SSQMD85 ","SSQMD86 ","SSQMD87 ","SSQMD88 ","SSQMD89 ", & + "SSQMD90 ","SSQMD91 ","SSQMD92 ","SSQMD93 ","SSQMD94 ","SSQMD95 ","SSQMD96 ", & + "SSQMD97 ","SSQMD98 ","SSQMD99 ","SSQMDD01 ","SSQMDD02 ","SSQMDD03 ","SSQMDD04 ", & + "SSQMDD05 ","SSQMDD06 ","SSQMDD07 ","SSQMDD08 ","SSQMDD09 ","SSQMDD10 ","SSQMDD11 ", & + "SSQMDD12 ","SSQMDD13 ","SSQMDD14 ","SSQMDD15 ","SSQMDD16 ","SSQMDD17 ","SSQMDD18 ", & + "SSQMDD19 ","SSQMDD20 ","SSQMDD21 ","SSQMDD22 ","SSQMDD23 ","SSQMDD24 ","SSQMDD25 ", & + "SSQMDD26 ","SSQMDD27 ","SSQMDD28 ","SSQMDD29 ","SSQMDD30 ","SSQMDD31 ","SSQMDD32 ", & + "SSQMDD33 ","SSQMDD34 ","SSQMDD35 ","SSQMDD36 ","SSQMDD37 ","SSQMDD38 ","SSQMDD39 ", & + "SSQMDD40 ","SSQMDD41 ","SSQMDD42 ","SSQMDD43 ","SSQMDD44 ","SSQMDD45 ","SSQMDD46 ", & + "SSQMDD47 ","SSQMDD48 ","SSQMDD49 ","SSQMDD50 ","SSQMDD51 ","SSQMDD52 ","SSQMDD53 ", & + "SSQMDD54 ","SSQMDD55 ","SSQMDD56 ","SSQMDD57 ","SSQMDD58 ","SSQMDD59 ","SSQMDD60 ", & + "SSQMDD61 ","SSQMDD62 ","SSQMDD63 ","SSQMDD64 ","SSQMDD65 ","SSQMDD66 ","SSQMDD67 ", & + "SSQMDD68 ","SSQMDD69 ","SSQMDD70 ","SSQMDD71 ","SSQMDD72 ","SSQMDD73 ","SSQMDD74 ", & + "SSQMDD75 ","SSQMDD76 ","SSQMDD77 ","SSQMDD78 ","SSQMDD79 ","SSQMDD80 ","SSQMDD81 ", & + "SSQMDD82 ","SSQMDD83 ","SSQMDD84 ","SSQMDD85 ","SSQMDD86 ","SSQMDD87 ","SSQMDD88 ", & + "SSQMDD89 ","SSQMDD90 ","SSQMDD91 ","SSQMDD92 ","SSQMDD93 ","SSQMDD94 ","SSQMDD95 ", & + "SSQMDD96 ","SSQMDD97 ","SSQMDD98 ","SSQMDD99 "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(2265) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + IntfFXss , IntfFYss , IntfFZss , IntfMXss , IntfMYss , IntfMZss , IntfRAXss , & + IntfRAYss , IntfRAZss , IntfRDXss , IntfRDYss , IntfRDZss , IntfTAXss , IntfTAYss , & + IntfTAZss , IntfTDXss , IntfTDYss , IntfTDZss , M1N1FKxe , M1N1FKye , M1N1FKze , & + M1N1FMxe , M1N1FMye , M1N1FMze , M1N1MKxe , M1N1MKye , M1N1MKze , M1N1MMxe , & + M1N1MMye , M1N1MMze , M1N1RAxe , M1N1RAye , M1N1RAze , M1N1RDxe , M1N1RDye , & + M1N1RDze , M1N1TAxe , M1N1TAye , M1N1TAze , M1N1TDxss , M1N1TDyss , M1N1TDzss , & + M1N2FKxe , M1N2FKye , M1N2FKze , M1N2FMxe , M1N2FMye , M1N2FMze , M1N2MKxe , & + M1N2MKye , M1N2MKze , M1N2MMxe , M1N2MMye , M1N2MMze , M1N2RAxe , M1N2RAye , & + M1N2RAze , M1N2RDxe , M1N2RDye , M1N2RDze , M1N2TAxe , M1N2TAye , M1N2TAze , & + M1N2TDxss , M1N2TDyss , M1N2TDzss , M1N3FKxe , M1N3FKye , M1N3FKze , M1N3FMxe , & + M1N3FMye , M1N3FMze , M1N3MKxe , M1N3MKye , M1N3MKze , M1N3MMxe , M1N3MMye , & + M1N3MMze , M1N3RAxe , M1N3RAye , M1N3RAze , M1N3RDxe , M1N3RDye , M1N3RDze , & + M1N3TAxe , M1N3TAye , M1N3TAze , M1N3TDxss , M1N3TDyss , M1N3TDzss , M1N4FKxe , & + M1N4FKye , M1N4FKze , M1N4FMxe , M1N4FMye , M1N4FMze , M1N4MKxe , M1N4MKye , & + M1N4MKze , M1N4MMxe , M1N4MMye , M1N4MMze , M1N4RAxe , M1N4RAye , M1N4RAze , & + M1N4RDxe , M1N4RDye , M1N4RDze , M1N4TAxe , M1N4TAye , M1N4TAze , M1N4TDxss , & + M1N4TDyss , M1N4TDzss , M1N5FKxe , M1N5FKye , M1N5FKze , M1N5FMxe , M1N5FMye , & + M1N5FMze , M1N5MKxe , M1N5MKye , M1N5MKze , M1N5MMxe , M1N5MMye , M1N5MMze , & + M1N5RAxe , M1N5RAye , M1N5RAze , M1N5RDxe , M1N5RDye , M1N5RDze , M1N5TAxe , & + M1N5TAye , M1N5TAze , M1N5TDxss , M1N5TDyss , M1N5TDzss , M1N6FKxe , M1N6FKye , & + M1N6FKze , M1N6FMxe , M1N6FMye , M1N6FMze , M1N6MKxe , M1N6MKye , M1N6MKze , & + M1N6MMxe , M1N6MMye , M1N6MMze , M1N6RAxe , M1N6RAye , M1N6RAze , M1N6RDxe , & + M1N6RDye , M1N6RDze , M1N6TAxe , M1N6TAye , M1N6TAze , M1N6TDxss , M1N6TDyss , & + M1N6TDzss , M1N7FKxe , M1N7FKye , M1N7FKze , M1N7FMxe , M1N7FMye , M1N7FMze , & + M1N7MKxe , M1N7MKye , M1N7MKze , M1N7MMxe , M1N7MMye , M1N7MMze , M1N7RAxe , & + M1N7RAye , M1N7RAze , M1N7RDxe , M1N7RDye , M1N7RDze , M1N7TAxe , M1N7TAye , & + M1N7TAze , M1N7TDxss , M1N7TDyss , M1N7TDzss , M1N8FKxe , M1N8FKye , M1N8FKze , & + M1N8FMxe , M1N8FMye , M1N8FMze , M1N8MKxe , M1N8MKye , M1N8MKze , M1N8MMxe , & + M1N8MMye , M1N8MMze , M1N8RAxe , M1N8RAye , M1N8RAze , M1N8RDxe , M1N8RDye , & + M1N8RDze , M1N8TAxe , M1N8TAye , M1N8TAze , M1N8TDxss , M1N8TDyss , M1N8TDzss , & + M1N9FKxe , M1N9FKye , M1N9FKze , M1N9FMxe , M1N9FMye , M1N9FMze , M1N9MKxe , & + M1N9MKye , M1N9MKze , M1N9MMxe , M1N9MMye , M1N9MMze , M1N9RAxe , M1N9RAye , & + M1N9RAze , M1N9RDxe , M1N9RDye , M1N9RDze , M1N9TAxe , M1N9TAye , M1N9TAze , & + M1N9TDxss , M1N9TDyss , M1N9TDzss , M2N1FKxe , M2N1FKye , M2N1FKze , M2N1FMxe , & + M2N1FMye , M2N1FMze , M2N1MKxe , M2N1MKye , M2N1MKze , M2N1MMxe , M2N1MMye , & + M2N1MMze , M2N1RAxe , M2N1RAye , M2N1RAze , M2N1RDxe , M2N1RDye , M2N1RDze , & + M2N1TAxe , M2N1TAye , M2N1TAze , M2N1TDxss , M2N1TDyss , M2N1TDzss , M2N2FKxe , & + M2N2FKye , M2N2FKze , M2N2FMxe , M2N2FMye , M2N2FMze , M2N2MKxe , M2N2MKye , & + M2N2MKze , M2N2MMxe , M2N2MMye , M2N2MMze , M2N2RAxe , M2N2RAye , M2N2RAze , & + M2N2RDxe , M2N2RDye , M2N2RDze , M2N2TAxe , M2N2TAye , M2N2TAze , M2N2TDxss , & + M2N2TDyss , M2N2TDzss , M2N3FKxe , M2N3FKye , M2N3FKze , M2N3FMxe , M2N3FMye , & + M2N3FMze , M2N3MKxe , M2N3MKye , M2N3MKze , M2N3MMxe , M2N3MMye , M2N3MMze , & + M2N3RAxe , M2N3RAye , M2N3RAze , M2N3RDxe , M2N3RDye , M2N3RDze , M2N3TAxe , & + M2N3TAye , M2N3TAze , M2N3TDxss , M2N3TDyss , M2N3TDzss , M2N4FKxe , M2N4FKye , & + M2N4FKze , M2N4FMxe , M2N4FMye , M2N4FMze , M2N4MKxe , M2N4MKye , M2N4MKze , & + M2N4MMxe , M2N4MMye , M2N4MMze , M2N4RAxe , M2N4RAye , M2N4RAze , M2N4RDxe , & + M2N4RDye , M2N4RDze , M2N4TAxe , M2N4TAye , M2N4TAze , M2N4TDxss , M2N4TDyss , & + M2N4TDzss , M2N5FKxe , M2N5FKye , M2N5FKze , M2N5FMxe , M2N5FMye , M2N5FMze , & + M2N5MKxe , M2N5MKye , M2N5MKze , M2N5MMxe , M2N5MMye , M2N5MMze , M2N5RAxe , & + M2N5RAye , M2N5RAze , M2N5RDxe , M2N5RDye , M2N5RDze , M2N5TAxe , M2N5TAye , & + M2N5TAze , M2N5TDxss , M2N5TDyss , M2N5TDzss , M2N6FKxe , M2N6FKye , M2N6FKze , & + M2N6FMxe , M2N6FMye , M2N6FMze , M2N6MKxe , M2N6MKye , M2N6MKze , M2N6MMxe , & + M2N6MMye , M2N6MMze , M2N6RAxe , M2N6RAye , M2N6RAze , M2N6RDxe , M2N6RDye , & + M2N6RDze , M2N6TAxe , M2N6TAye , M2N6TAze , M2N6TDxss , M2N6TDyss , M2N6TDzss , & + M2N7FKxe , M2N7FKye , M2N7FKze , M2N7FMxe , M2N7FMye , M2N7FMze , M2N7MKxe , & + M2N7MKye , M2N7MKze , M2N7MMxe , M2N7MMye , M2N7MMze , M2N7RAxe , M2N7RAye , & + M2N7RAze , M2N7RDxe , M2N7RDye , M2N7RDze , M2N7TAxe , M2N7TAye , M2N7TAze , & + M2N7TDxss , M2N7TDyss , M2N7TDzss , M2N8FKxe , M2N8FKye , M2N8FKze , M2N8FMxe , & + M2N8FMye , M2N8FMze , M2N8MKxe , M2N8MKye , M2N8MKze , M2N8MMxe , M2N8MMye , & + M2N8MMze , M2N8RAxe , M2N8RAye , M2N8RAze , M2N8RDxe , M2N8RDye , M2N8RDze , & + M2N8TAxe , M2N8TAye , M2N8TAze , M2N8TDxss , M2N8TDyss , M2N8TDzss , M2N9FKxe , & + M2N9FKye , M2N9FKze , M2N9FMxe , M2N9FMye , M2N9FMze , M2N9MKxe , M2N9MKye , & + M2N9MKze , M2N9MMxe , M2N9MMye , M2N9MMze , M2N9RAxe , M2N9RAye , M2N9RAze , & + M2N9RDxe , M2N9RDye , M2N9RDze , M2N9TAxe , M2N9TAye , M2N9TAze , M2N9TDxss , & + M2N9TDyss , M2N9TDzss , M3N1FKxe , M3N1FKye , M3N1FKze , M3N1FMxe , M3N1FMye , & + M3N1FMze , M3N1MKxe , M3N1MKye , M3N1MKze , M3N1MMxe , M3N1MMye , M3N1MMze , & + M3N1RAxe , M3N1RAye , M3N1RAze , M3N1RDxe , M3N1RDye , M3N1RDze , M3N1TAxe , & + M3N1TAye , M3N1TAze , M3N1TDxss , M3N1TDyss , M3N1TDzss , M3N2FKxe , M3N2FKye , & + M3N2FKze , M3N2FMxe , M3N2FMye , M3N2FMze , M3N2MKxe , M3N2MKye , M3N2MKze , & + M3N2MMxe , M3N2MMye , M3N2MMze , M3N2RAxe , M3N2RAye , M3N2RAze , M3N2RDxe , & + M3N2RDye , M3N2RDze , M3N2TAxe , M3N2TAye , M3N2TAze , M3N2TDxss , M3N2TDyss , & + M3N2TDzss , M3N3FKxe , M3N3FKye , M3N3FKze , M3N3FMxe , M3N3FMye , M3N3FMze , & + M3N3MKxe , M3N3MKye , M3N3MKze , M3N3MMxe , M3N3MMye , M3N3MMze , M3N3RAxe , & + M3N3RAye , M3N3RAze , M3N3RDxe , M3N3RDye , M3N3RDze , M3N3TAxe , M3N3TAye , & + M3N3TAze , M3N3TDxss , M3N3TDyss , M3N3TDzss , M3N4FKxe , M3N4FKye , M3N4FKze , & + M3N4FMxe , M3N4FMye , M3N4FMze , M3N4MKxe , M3N4MKye , M3N4MKze , M3N4MMxe , & + M3N4MMye , M3N4MMze , M3N4RAxe , M3N4RAye , M3N4RAze , M3N4RDxe , M3N4RDye , & + M3N4RDze , M3N4TAxe , M3N4TAye , M3N4TAze , M3N4TDxss , M3N4TDyss , M3N4TDzss , & + M3N5FKxe , M3N5FKye , M3N5FKze , M3N5FMxe , M3N5FMye , M3N5FMze , M3N5MKxe , & + M3N5MKye , M3N5MKze , M3N5MMxe , M3N5MMye , M3N5MMze , M3N5RAxe , M3N5RAye , & + M3N5RAze , M3N5RDxe , M3N5RDye , M3N5RDze , M3N5TAxe , M3N5TAye , M3N5TAze , & + M3N5TDxss , M3N5TDyss , M3N5TDzss , M3N6FKxe , M3N6FKye , M3N6FKze , M3N6FMxe , & + M3N6FMye , M3N6FMze , M3N6MKxe , M3N6MKye , M3N6MKze , M3N6MMxe , M3N6MMye , & + M3N6MMze , M3N6RAxe , M3N6RAye , M3N6RAze , M3N6RDxe , M3N6RDye , M3N6RDze , & + M3N6TAxe , M3N6TAye , M3N6TAze , M3N6TDxss , M3N6TDyss , M3N6TDzss , M3N7FKxe , & + M3N7FKye , M3N7FKze , M3N7FMxe , M3N7FMye , M3N7FMze , M3N7MKxe , M3N7MKye , & + M3N7MKze , M3N7MMxe , M3N7MMye , M3N7MMze , M3N7RAxe , M3N7RAye , M3N7RAze , & + M3N7RDxe , M3N7RDye , M3N7RDze , M3N7TAxe , M3N7TAye , M3N7TAze , M3N7TDxss , & + M3N7TDyss , M3N7TDzss , M3N8FKxe , M3N8FKye , M3N8FKze , M3N8FMxe , M3N8FMye , & + M3N8FMze , M3N8MKxe , M3N8MKye , M3N8MKze , M3N8MMxe , M3N8MMye , M3N8MMze , & + M3N8RAxe , M3N8RAye , M3N8RAze , M3N8RDxe , M3N8RDye , M3N8RDze , M3N8TAxe , & + M3N8TAye , M3N8TAze , M3N8TDxss , M3N8TDyss , M3N8TDzss , M3N9FKxe , M3N9FKye , & + M3N9FKze , M3N9FMxe , M3N9FMye , M3N9FMze , M3N9MKxe , M3N9MKye , M3N9MKze , & + M3N9MMxe , M3N9MMye , M3N9MMze , M3N9RAxe , M3N9RAye , M3N9RAze , M3N9RDxe , & + M3N9RDye , M3N9RDze , M3N9TAxe , M3N9TAye , M3N9TAze , M3N9TDxss , M3N9TDyss , & + M3N9TDzss , M4N1FKxe , M4N1FKye , M4N1FKze , M4N1FMxe , M4N1FMye , M4N1FMze , & + M4N1MKxe , M4N1MKye , M4N1MKze , M4N1MMxe , M4N1MMye , M4N1MMze , M4N1RAxe , & + M4N1RAye , M4N1RAze , M4N1RDxe , M4N1RDye , M4N1RDze , M4N1TAxe , M4N1TAye , & + M4N1TAze , M4N1TDxss , M4N1TDyss , M4N1TDzss , M4N2FKxe , M4N2FKye , M4N2FKze , & + M4N2FMxe , M4N2FMye , M4N2FMze , M4N2MKxe , M4N2MKye , M4N2MKze , M4N2MMxe , & + M4N2MMye , M4N2MMze , M4N2RAxe , M4N2RAye , M4N2RAze , M4N2RDxe , M4N2RDye , & + M4N2RDze , M4N2TAxe , M4N2TAye , M4N2TAze , M4N2TDxss , M4N2TDyss , M4N2TDzss , & + M4N3FKxe , M4N3FKye , M4N3FKze , M4N3FMxe , M4N3FMye , M4N3FMze , M4N3MKxe , & + M4N3MKye , M4N3MKze , M4N3MMxe , M4N3MMye , M4N3MMze , M4N3RAxe , M4N3RAye , & + M4N3RAze , M4N3RDxe , M4N3RDye , M4N3RDze , M4N3TAxe , M4N3TAye , M4N3TAze , & + M4N3TDxss , M4N3TDyss , M4N3TDzss , M4N4FKxe , M4N4FKye , M4N4FKze , M4N4FMxe , & + M4N4FMye , M4N4FMze , M4N4MKxe , M4N4MKye , M4N4MKze , M4N4MMxe , M4N4MMye , & + M4N4MMze , M4N4RAxe , M4N4RAye , M4N4RAze , M4N4RDxe , M4N4RDye , M4N4RDze , & + M4N4TAxe , M4N4TAye , M4N4TAze , M4N4TDxss , M4N4TDyss , M4N4TDzss , M4N5FKxe , & + M4N5FKye , M4N5FKze , M4N5FMxe , M4N5FMye , M4N5FMze , M4N5MKxe , M4N5MKye , & + M4N5MKze , M4N5MMxe , M4N5MMye , M4N5MMze , M4N5RAxe , M4N5RAye , M4N5RAze , & + M4N5RDxe , M4N5RDye , M4N5RDze , M4N5TAxe , M4N5TAye , M4N5TAze , M4N5TDxss , & + M4N5TDyss , M4N5TDzss , M4N6FKxe , M4N6FKye , M4N6FKze , M4N6FMxe , M4N6FMye , & + M4N6FMze , M4N6MKxe , M4N6MKye , M4N6MKze , M4N6MMxe , M4N6MMye , M4N6MMze , & + M4N6RAxe , M4N6RAye , M4N6RAze , M4N6RDxe , M4N6RDye , M4N6RDze , M4N6TAxe , & + M4N6TAye , M4N6TAze , M4N6TDxss , M4N6TDyss , M4N6TDzss , M4N7FKxe , M4N7FKye , & + M4N7FKze , M4N7FMxe , M4N7FMye , M4N7FMze , M4N7MKxe , M4N7MKye , M4N7MKze , & + M4N7MMxe , M4N7MMye , M4N7MMze , M4N7RAxe , M4N7RAye , M4N7RAze , M4N7RDxe , & + M4N7RDye , M4N7RDze , M4N7TAxe , M4N7TAye , M4N7TAze , M4N7TDxss , M4N7TDyss , & + M4N7TDzss , M4N8FKxe , M4N8FKye , M4N8FKze , M4N8FMxe , M4N8FMye , M4N8FMze , & + M4N8MKxe , M4N8MKye , M4N8MKze , M4N8MMxe , M4N8MMye , M4N8MMze , M4N8RAxe , & + M4N8RAye , M4N8RAze , M4N8RDxe , M4N8RDye , M4N8RDze , M4N8TAxe , M4N8TAye , & + M4N8TAze , M4N8TDxss , M4N8TDyss , M4N8TDzss , M4N9FKxe , M4N9FKye , M4N9FKze , & + M4N9FMxe , M4N9FMye , M4N9FMze , M4N9MKxe , M4N9MKye , M4N9MKze , M4N9MMxe , & + M4N9MMye , M4N9MMze , M4N9RAxe , M4N9RAye , M4N9RAze , M4N9RDxe , M4N9RDye , & + M4N9RDze , M4N9TAxe , M4N9TAye , M4N9TAze , M4N9TDxss , M4N9TDyss , M4N9TDzss , & + M5N1FKxe , M5N1FKye , M5N1FKze , M5N1FMxe , M5N1FMye , M5N1FMze , M5N1MKxe , & + M5N1MKye , M5N1MKze , M5N1MMxe , M5N1MMye , M5N1MMze , M5N1RAxe , M5N1RAye , & + M5N1RAze , M5N1RDxe , M5N1RDye , M5N1RDze , M5N1TAxe , M5N1TAye , M5N1TAze , & + M5N1TDxss , M5N1TDyss , M5N1TDzss , M5N2FKxe , M5N2FKye , M5N2FKze , M5N2FMxe , & + M5N2FMye , M5N2FMze , M5N2MKxe , M5N2MKye , M5N2MKze , M5N2MMxe , M5N2MMye , & + M5N2MMze , M5N2RAxe , M5N2RAye , M5N2RAze , M5N2RDxe , M5N2RDye , M5N2RDze , & + M5N2TAxe , M5N2TAye , M5N2TAze , M5N2TDxss , M5N2TDyss , M5N2TDzss , M5N3FKxe , & + M5N3FKye , M5N3FKze , M5N3FMxe , M5N3FMye , M5N3FMze , M5N3MKxe , M5N3MKye , & + M5N3MKze , M5N3MMxe , M5N3MMye , M5N3MMze , M5N3RAxe , M5N3RAye , M5N3RAze , & + M5N3RDxe , M5N3RDye , M5N3RDze , M5N3TAxe , M5N3TAye , M5N3TAze , M5N3TDxss , & + M5N3TDyss , M5N3TDzss , M5N4FKxe , M5N4FKye , M5N4FKze , M5N4FMxe , M5N4FMye , & + M5N4FMze , M5N4MKxe , M5N4MKye , M5N4MKze , M5N4MMxe , M5N4MMye , M5N4MMze , & + M5N4RAxe , M5N4RAye , M5N4RAze , M5N4RDxe , M5N4RDye , M5N4RDze , M5N4TAxe , & + M5N4TAye , M5N4TAze , M5N4TDxss , M5N4TDyss , M5N4TDzss , M5N5FKxe , M5N5FKye , & + M5N5FKze , M5N5FMxe , M5N5FMye , M5N5FMze , M5N5MKxe , M5N5MKye , M5N5MKze , & + M5N5MMxe , M5N5MMye , M5N5MMze , M5N5RAxe , M5N5RAye , M5N5RAze , M5N5RDxe , & + M5N5RDye , M5N5RDze , M5N5TAxe , M5N5TAye , M5N5TAze , M5N5TDxss , M5N5TDyss , & + M5N5TDzss , M5N6FKxe , M5N6FKye , M5N6FKze , M5N6FMxe , M5N6FMye , M5N6FMze , & + M5N6MKxe , M5N6MKye , M5N6MKze , M5N6MMxe , M5N6MMye , M5N6MMze , M5N6RAxe , & + M5N6RAye , M5N6RAze , M5N6RDxe , M5N6RDye , M5N6RDze , M5N6TAxe , M5N6TAye , & + M5N6TAze , M5N6TDxss , M5N6TDyss , M5N6TDzss , M5N7FKxe , M5N7FKye , M5N7FKze , & + M5N7FMxe , M5N7FMye , M5N7FMze , M5N7MKxe , M5N7MKye , M5N7MKze , M5N7MMxe , & + M5N7MMye , M5N7MMze , M5N7RAxe , M5N7RAye , M5N7RAze , M5N7RDxe , M5N7RDye , & + M5N7RDze , M5N7TAxe , M5N7TAye , M5N7TAze , M5N7TDxss , M5N7TDyss , M5N7TDzss , & + M5N8FKxe , M5N8FKye , M5N8FKze , M5N8FMxe , M5N8FMye , M5N8FMze , M5N8MKxe , & + M5N8MKye , M5N8MKze , M5N8MMxe , M5N8MMye , M5N8MMze , M5N8RAxe , M5N8RAye , & + M5N8RAze , M5N8RDxe , M5N8RDye , M5N8RDze , M5N8TAxe , M5N8TAye , M5N8TAze , & + M5N8TDxss , M5N8TDyss , M5N8TDzss , M5N9FKxe , M5N9FKye , M5N9FKze , M5N9FMxe , & + M5N9FMye , M5N9FMze , M5N9MKxe , M5N9MKye , M5N9MKze , M5N9MMxe , M5N9MMye , & + M5N9MMze , M5N9RAxe , M5N9RAye , M5N9RAze , M5N9RDxe , M5N9RDye , M5N9RDze , & + M5N9TAxe , M5N9TAye , M5N9TAze , M5N9TDxss , M5N9TDyss , M5N9TDzss , M6N1FKxe , & + M6N1FKye , M6N1FKze , M6N1FMxe , M6N1FMye , M6N1FMze , M6N1MKxe , M6N1MKye , & + M6N1MKze , M6N1MMxe , M6N1MMye , M6N1MMze , M6N1RAxe , M6N1RAye , M6N1RAze , & + M6N1RDxe , M6N1RDye , M6N1RDze , M6N1TAxe , M6N1TAye , M6N1TAze , M6N1TDxss , & + M6N1TDyss , M6N1TDzss , M6N2FKxe , M6N2FKye , M6N2FKze , M6N2FMxe , M6N2FMye , & + M6N2FMze , M6N2MKxe , M6N2MKye , M6N2MKze , M6N2MMxe , M6N2MMye , M6N2MMze , & + M6N2RAxe , M6N2RAye , M6N2RAze , M6N2RDxe , M6N2RDye , M6N2RDze , M6N2TAxe , & + M6N2TAye , M6N2TAze , M6N2TDxss , M6N2TDyss , M6N2TDzss , M6N3FKxe , M6N3FKye , & + M6N3FKze , M6N3FMxe , M6N3FMye , M6N3FMze , M6N3MKxe , M6N3MKye , M6N3MKze , & + M6N3MMxe , M6N3MMye , M6N3MMze , M6N3RAxe , M6N3RAye , M6N3RAze , M6N3RDxe , & + M6N3RDye , M6N3RDze , M6N3TAxe , M6N3TAye , M6N3TAze , M6N3TDxss , M6N3TDyss , & + M6N3TDzss , M6N4FKxe , M6N4FKye , M6N4FKze , M6N4FMxe , M6N4FMye , M6N4FMze , & + M6N4MKxe , M6N4MKye , M6N4MKze , M6N4MMxe , M6N4MMye , M6N4MMze , M6N4RAxe , & + M6N4RAye , M6N4RAze , M6N4RDxe , M6N4RDye , M6N4RDze , M6N4TAxe , M6N4TAye , & + M6N4TAze , M6N4TDxss , M6N4TDyss , M6N4TDzss , M6N5FKxe , M6N5FKye , M6N5FKze , & + M6N5FMxe , M6N5FMye , M6N5FMze , M6N5MKxe , M6N5MKye , M6N5MKze , M6N5MMxe , & + M6N5MMye , M6N5MMze , M6N5RAxe , M6N5RAye , M6N5RAze , M6N5RDxe , M6N5RDye , & + M6N5RDze , M6N5TAxe , M6N5TAye , M6N5TAze , M6N5TDxss , M6N5TDyss , M6N5TDzss , & + M6N6FKxe , M6N6FKye , M6N6FKze , M6N6FMxe , M6N6FMye , M6N6FMze , M6N6MKxe , & + M6N6MKye , M6N6MKze , M6N6MMxe , M6N6MMye , M6N6MMze , M6N6RAxe , M6N6RAye , & + M6N6RAze , M6N6RDxe , M6N6RDye , M6N6RDze , M6N6TAxe , M6N6TAye , M6N6TAze , & + M6N6TDxss , M6N6TDyss , M6N6TDzss , M6N7FKxe , M6N7FKye , M6N7FKze , M6N7FMxe , & + M6N7FMye , M6N7FMze , M6N7MKxe , M6N7MKye , M6N7MKze , M6N7MMxe , M6N7MMye , & + M6N7MMze , M6N7RAxe , M6N7RAye , M6N7RAze , M6N7RDxe , M6N7RDye , M6N7RDze , & + M6N7TAxe , M6N7TAye , M6N7TAze , M6N7TDxss , M6N7TDyss , M6N7TDzss , M6N8FKxe , & + M6N8FKye , M6N8FKze , M6N8FMxe , M6N8FMye , M6N8FMze , M6N8MKxe , M6N8MKye , & + M6N8MKze , M6N8MMxe , M6N8MMye , M6N8MMze , M6N8RAxe , M6N8RAye , M6N8RAze , & + M6N8RDxe , M6N8RDye , M6N8RDze , M6N8TAxe , M6N8TAye , M6N8TAze , M6N8TDxss , & + M6N8TDyss , M6N8TDzss , M6N9FKxe , M6N9FKye , M6N9FKze , M6N9FMxe , M6N9FMye , & + M6N9FMze , M6N9MKxe , M6N9MKye , M6N9MKze , M6N9MMxe , M6N9MMye , M6N9MMze , & + M6N9RAxe , M6N9RAye , M6N9RAze , M6N9RDxe , M6N9RDye , M6N9RDze , M6N9TAxe , & + M6N9TAye , M6N9TAze , M6N9TDxss , M6N9TDyss , M6N9TDzss , M7N1FKxe , M7N1FKye , & + M7N1FKze , M7N1FMxe , M7N1FMye , M7N1FMze , M7N1MKxe , M7N1MKye , M7N1MKze , & + M7N1MMxe , M7N1MMye , M7N1MMze , M7N1RAxe , M7N1RAye , M7N1RAze , M7N1RDxe , & + M7N1RDye , M7N1RDze , M7N1TAxe , M7N1TAye , M7N1TAze , M7N1TDxss , M7N1TDyss , & + M7N1TDzss , M7N2FKxe , M7N2FKye , M7N2FKze , M7N2FMxe , M7N2FMye , M7N2FMze , & + M7N2MKxe , M7N2MKye , M7N2MKze , M7N2MMxe , M7N2MMye , M7N2MMze , M7N2RAxe , & + M7N2RAye , M7N2RAze , M7N2RDxe , M7N2RDye , M7N2RDze , M7N2TAxe , M7N2TAye , & + M7N2TAze , M7N2TDxss , M7N2TDyss , M7N2TDzss , M7N3FKxe , M7N3FKye , M7N3FKze , & + M7N3FMxe , M7N3FMye , M7N3FMze , M7N3MKxe , M7N3MKye , M7N3MKze , M7N3MMxe , & + M7N3MMye , M7N3MMze , M7N3RAxe , M7N3RAye , M7N3RAze , M7N3RDxe , M7N3RDye , & + M7N3RDze , M7N3TAxe , M7N3TAye , M7N3TAze , M7N3TDxss , M7N3TDyss , M7N3TDzss , & + M7N4FKxe , M7N4FKye , M7N4FKze , M7N4FMxe , M7N4FMye , M7N4FMze , M7N4MKxe , & + M7N4MKye , M7N4MKze , M7N4MMxe , M7N4MMye , M7N4MMze , M7N4RAxe , M7N4RAye , & + M7N4RAze , M7N4RDxe , M7N4RDye , M7N4RDze , M7N4TAxe , M7N4TAye , M7N4TAze , & + M7N4TDxss , M7N4TDyss , M7N4TDzss , M7N5FKxe , M7N5FKye , M7N5FKze , M7N5FMxe , & + M7N5FMye , M7N5FMze , M7N5MKxe , M7N5MKye , M7N5MKze , M7N5MMxe , M7N5MMye , & + M7N5MMze , M7N5RAxe , M7N5RAye , M7N5RAze , M7N5RDxe , M7N5RDye , M7N5RDze , & + M7N5TAxe , M7N5TAye , M7N5TAze , M7N5TDxss , M7N5TDyss , M7N5TDzss , M7N6FKxe , & + M7N6FKye , M7N6FKze , M7N6FMxe , M7N6FMye , M7N6FMze , M7N6MKxe , M7N6MKye , & + M7N6MKze , M7N6MMxe , M7N6MMye , M7N6MMze , M7N6RAxe , M7N6RAye , M7N6RAze , & + M7N6RDxe , M7N6RDye , M7N6RDze , M7N6TAxe , M7N6TAye , M7N6TAze , M7N6TDxss , & + M7N6TDyss , M7N6TDzss , M7N7FKxe , M7N7FKye , M7N7FKze , M7N7FMxe , M7N7FMye , & + M7N7FMze , M7N7MKxe , M7N7MKye , M7N7MKze , M7N7MMxe , M7N7MMye , M7N7MMze , & + M7N7RAxe , M7N7RAye , M7N7RAze , M7N7RDxe , M7N7RDye , M7N7RDze , M7N7TAxe , & + M7N7TAye , M7N7TAze , M7N7TDxss , M7N7TDyss , M7N7TDzss , M7N8FKxe , M7N8FKye , & + M7N8FKze , M7N8FMxe , M7N8FMye , M7N8FMze , M7N8MKxe , M7N8MKye , M7N8MKze , & + M7N8MMxe , M7N8MMye , M7N8MMze , M7N8RAxe , M7N8RAye , M7N8RAze , M7N8RDxe , & + M7N8RDye , M7N8RDze , M7N8TAxe , M7N8TAye , M7N8TAze , M7N8TDxss , M7N8TDyss , & + M7N8TDzss , M7N9FKxe , M7N9FKye , M7N9FKze , M7N9FMxe , M7N9FMye , M7N9FMze , & + M7N9MKxe , M7N9MKye , M7N9MKze , M7N9MMxe , M7N9MMye , M7N9MMze , M7N9RAxe , & + M7N9RAye , M7N9RAze , M7N9RDxe , M7N9RDye , M7N9RDze , M7N9TAxe , M7N9TAye , & + M7N9TAze , M7N9TDxss , M7N9TDyss , M7N9TDzss , M8N1FKxe , M8N1FKye , M8N1FKze , & + M8N1FMxe , M8N1FMye , M8N1FMze , M8N1MKxe , M8N1MKye , M8N1MKze , M8N1MMxe , & + M8N1MMye , M8N1MMze , M8N1RAxe , M8N1RAye , M8N1RAze , M8N1RDxe , M8N1RDye , & + M8N1RDze , M8N1TAxe , M8N1TAye , M8N1TAze , M8N1TDxss , M8N1TDyss , M8N1TDzss , & + M8N2FKxe , M8N2FKye , M8N2FKze , M8N2FMxe , M8N2FMye , M8N2FMze , M8N2MKxe , & + M8N2MKye , M8N2MKze , M8N2MMxe , M8N2MMye , M8N2MMze , M8N2RAxe , M8N2RAye , & + M8N2RAze , M8N2RDxe , M8N2RDye , M8N2RDze , M8N2TAxe , M8N2TAye , M8N2TAze , & + M8N2TDxss , M8N2TDyss , M8N2TDzss , M8N3FKxe , M8N3FKye , M8N3FKze , M8N3FMxe , & + M8N3FMye , M8N3FMze , M8N3MKxe , M8N3MKye , M8N3MKze , M8N3MMxe , M8N3MMye , & + M8N3MMze , M8N3RAxe , M8N3RAye , M8N3RAze , M8N3RDxe , M8N3RDye , M8N3RDze , & + M8N3TAxe , M8N3TAye , M8N3TAze , M8N3TDxss , M8N3TDyss , M8N3TDzss , M8N4FKxe , & + M8N4FKye , M8N4FKze , M8N4FMxe , M8N4FMye , M8N4FMze , M8N4MKxe , M8N4MKye , & + M8N4MKze , M8N4MMxe , M8N4MMye , M8N4MMze , M8N4RAxe , M8N4RAye , M8N4RAze , & + M8N4RDxe , M8N4RDye , M8N4RDze , M8N4TAxe , M8N4TAye , M8N4TAze , M8N4TDxss , & + M8N4TDyss , M8N4TDzss , M8N5FKxe , M8N5FKye , M8N5FKze , M8N5FMxe , M8N5FMye , & + M8N5FMze , M8N5MKxe , M8N5MKye , M8N5MKze , M8N5MMxe , M8N5MMye , M8N5MMze , & + M8N5RAxe , M8N5RAye , M8N5RAze , M8N5RDxe , M8N5RDye , M8N5RDze , M8N5TAxe , & + M8N5TAye , M8N5TAze , M8N5TDxss , M8N5TDyss , M8N5TDzss , M8N6FKxe , M8N6FKye , & + M8N6FKze , M8N6FMxe , M8N6FMye , M8N6FMze , M8N6MKxe , M8N6MKye , M8N6MKze , & + M8N6MMxe , M8N6MMye , M8N6MMze , M8N6RAxe , M8N6RAye , M8N6RAze , M8N6RDxe , & + M8N6RDye , M8N6RDze , M8N6TAxe , M8N6TAye , M8N6TAze , M8N6TDxss , M8N6TDyss , & + M8N6TDzss , M8N7FKxe , M8N7FKye , M8N7FKze , M8N7FMxe , M8N7FMye , M8N7FMze , & + M8N7MKxe , M8N7MKye , M8N7MKze , M8N7MMxe , M8N7MMye , M8N7MMze , M8N7RAxe , & + M8N7RAye , M8N7RAze , M8N7RDxe , M8N7RDye , M8N7RDze , M8N7TAxe , M8N7TAye , & + M8N7TAze , M8N7TDxss , M8N7TDyss , M8N7TDzss , M8N8FKxe , M8N8FKye , M8N8FKze , & + M8N8FMxe , M8N8FMye , M8N8FMze , M8N8MKxe , M8N8MKye , M8N8MKze , M8N8MMxe , & + M8N8MMye , M8N8MMze , M8N8RAxe , M8N8RAye , M8N8RAze , M8N8RDxe , M8N8RDye , & + M8N8RDze , M8N8TAxe , M8N8TAye , M8N8TAze , M8N8TDxss , M8N8TDyss , M8N8TDzss , & + M8N9FKxe , M8N9FKye , M8N9FKze , M8N9FMxe , M8N9FMye , M8N9FMze , M8N9MKxe , & + M8N9MKye , M8N9MKze , M8N9MMxe , M8N9MMye , M8N9MMze , M8N9RAxe , M8N9RAye , & + M8N9RAze , M8N9RDxe , M8N9RDye , M8N9RDze , M8N9TAxe , M8N9TAye , M8N9TAze , & + M8N9TDxss , M8N9TDyss , M8N9TDzss , M9N1FKxe , M9N1FKye , M9N1FKze , M9N1FMxe , & + M9N1FMye , M9N1FMze , M9N1MKxe , M9N1MKye , M9N1MKze , M9N1MMxe , M9N1MMye , & + M9N1MMze , M9N1RAxe , M9N1RAye , M9N1RAze , M9N1RDxe , M9N1RDye , M9N1RDze , & + M9N1TAxe , M9N1TAye , M9N1TAze , M9N1TDxss , M9N1TDyss , M9N1TDzss , M9N2FKxe , & + M9N2FKye , M9N2FKze , M9N2FMxe , M9N2FMye , M9N2FMze , M9N2MKxe , M9N2MKye , & + M9N2MKze , M9N2MMxe , M9N2MMye , M9N2MMze , M9N2RAxe , M9N2RAye , M9N2RAze , & + M9N2RDxe , M9N2RDye , M9N2RDze , M9N2TAxe , M9N2TAye , M9N2TAze , M9N2TDxss , & + M9N2TDyss , M9N2TDzss , M9N3FKxe , M9N3FKye , M9N3FKze , M9N3FMxe , M9N3FMye , & + M9N3FMze , M9N3MKxe , M9N3MKye , M9N3MKze , M9N3MMxe , M9N3MMye , M9N3MMze , & + M9N3RAxe , M9N3RAye , M9N3RAze , M9N3RDxe , M9N3RDye , M9N3RDze , M9N3TAxe , & + M9N3TAye , M9N3TAze , M9N3TDxss , M9N3TDyss , M9N3TDzss , M9N4FKxe , M9N4FKye , & + M9N4FKze , M9N4FMxe , M9N4FMye , M9N4FMze , M9N4MKxe , M9N4MKye , M9N4MKze , & + M9N4MMxe , M9N4MMye , M9N4MMze , M9N4RAxe , M9N4RAye , M9N4RAze , M9N4RDxe , & + M9N4RDye , M9N4RDze , M9N4TAxe , M9N4TAye , M9N4TAze , M9N4TDxss , M9N4TDyss , & + M9N4TDzss , M9N5FKxe , M9N5FKye , M9N5FKze , M9N5FMxe , M9N5FMye , M9N5FMze , & + M9N5MKxe , M9N5MKye , M9N5MKze , M9N5MMxe , M9N5MMye , M9N5MMze , M9N5RAxe , & + M9N5RAye , M9N5RAze , M9N5RDxe , M9N5RDye , M9N5RDze , M9N5TAxe , M9N5TAye , & + M9N5TAze , M9N5TDxss , M9N5TDyss , M9N5TDzss , M9N6FKxe , M9N6FKye , M9N6FKze , & + M9N6FMxe , M9N6FMye , M9N6FMze , M9N6MKxe , M9N6MKye , M9N6MKze , M9N6MMxe , & + M9N6MMye , M9N6MMze , M9N6RAxe , M9N6RAye , M9N6RAze , M9N6RDxe , M9N6RDye , & + M9N6RDze , M9N6TAxe , M9N6TAye , M9N6TAze , M9N6TDxss , M9N6TDyss , M9N6TDzss , & + M9N7FKxe , M9N7FKye , M9N7FKze , M9N7FMxe , M9N7FMye , M9N7FMze , M9N7MKxe , & + M9N7MKye , M9N7MKze , M9N7MMxe , M9N7MMye , M9N7MMze , M9N7RAxe , M9N7RAye , & + M9N7RAze , M9N7RDxe , M9N7RDye , M9N7RDze , M9N7TAxe , M9N7TAye , M9N7TAze , & + M9N7TDxss , M9N7TDyss , M9N7TDzss , M9N8FKxe , M9N8FKye , M9N8FKze , M9N8FMxe , & + M9N8FMye , M9N8FMze , M9N8MKxe , M9N8MKye , M9N8MKze , M9N8MMxe , M9N8MMye , & + M9N8MMze , M9N8RAxe , M9N8RAye , M9N8RAze , M9N8RDxe , M9N8RDye , M9N8RDze , & + M9N8TAxe , M9N8TAye , M9N8TAze , M9N8TDxss , M9N8TDyss , M9N8TDzss , M9N9FKxe , & + M9N9FKye , M9N9FKze , M9N9FMxe , M9N9FMye , M9N9FMze , M9N9MKxe , M9N9MKye , & + M9N9MKze , M9N9MMxe , M9N9MMye , M9N9MMze , M9N9RAxe , M9N9RAye , M9N9RAze , & + M9N9RDxe , M9N9RDye , M9N9RDze , M9N9TAxe , M9N9TAye , M9N9TAze , M9N9TDxss , & + M9N9TDyss , M9N9TDzss , ReactFXss , ReactFYss , ReactFZss , ReactMXss , ReactMYss , & + ReactMZss , SSqm01 , SSqm02 , SSqm03 , SSqm04 , SSqm05 , SSqm06 , & + SSqm07 , SSqm08 , SSqm09 , SSqm10 , SSqm11 , SSqm12 , SSqm13 , & + SSqm14 , SSqm15 , SSqm16 , SSqm17 , SSqm18 , SSqm19 , SSqm20 , & + SSqm21 , SSqm22 , SSqm23 , SSqm24 , SSqm25 , SSqm26 , SSqm27 , & + SSqm28 , SSqm29 , SSqm30 , SSqm31 , SSqm32 , SSqm33 , SSqm34 , & + SSqm35 , SSqm36 , SSqm37 , SSqm38 , SSqm39 , SSqm40 , SSqm41 , & + SSqm42 , SSqm43 , SSqm44 , SSqm45 , SSqm46 , SSqm47 , SSqm48 , & + SSqm49 , SSqm50 , SSqm51 , SSqm52 , SSqm53 , SSqm54 , SSqm55 , & + SSqm56 , SSqm57 , SSqm58 , SSqm59 , SSqm60 , SSqm61 , SSqm62 , & + SSqm63 , SSqm64 , SSqm65 , SSqm66 , SSqm67 , SSqm68 , SSqm69 , & + SSqm70 , SSqm71 , SSqm72 , SSqm73 , SSqm74 , SSqm75 , SSqm76 , & + SSqm77 , SSqm78 , SSqm79 , SSqm80 , SSqm81 , SSqm82 , SSqm83 , & + SSqm84 , SSqm85 , SSqm86 , SSqm87 , SSqm88 , SSqm89 , SSqm90 , & + SSqm91 , SSqm92 , SSqm93 , SSqm94 , SSqm95 , SSqm96 , SSqm97 , & + SSqm98 , SSqm99 , SSqmd01 , SSqmd02 , SSqmd03 , SSqmd04 , SSqmd05 , & + SSqmd06 , SSqmd07 , SSqmd08 , SSqmd09 , SSqmd10 , SSqmd11 , SSqmd12 , & + SSqmd13 , SSqmd14 , SSqmd15 , SSqmd16 , SSqmd17 , SSqmd18 , SSqmd19 , & + SSqmd20 , SSqmd21 , SSqmd22 , SSqmd23 , SSqmd24 , SSqmd25 , SSqmd26 , & + SSqmd27 , SSqmd28 , SSqmd29 , SSqmd30 , SSqmd31 , SSqmd32 , SSqmd33 , & + SSqmd34 , SSqmd35 , SSqmd36 , SSqmd37 , SSqmd38 , SSqmd39 , SSqmd40 , & + SSqmd41 , SSqmd42 , SSqmd43 , SSqmd44 , SSqmd45 , SSqmd46 , SSqmd47 , & + SSqmd48 , SSqmd49 , SSqmd50 , SSqmd51 , SSqmd52 , SSqmd53 , SSqmd54 , & + SSqmd55 , SSqmd56 , SSqmd57 , SSqmd58 , SSqmd59 , SSqmd60 , SSqmd61 , & + SSqmd62 , SSqmd63 , SSqmd64 , SSqmd65 , SSqmd66 , SSqmd67 , SSqmd68 , & + SSqmd69 , SSqmd70 , SSqmd71 , SSqmd72 , SSqmd73 , SSqmd74 , SSqmd75 , & + SSqmd76 , SSqmd77 , SSqmd78 , SSqmd79 , SSqmd80 , SSqmd81 , SSqmd82 , & + SSqmd83 , SSqmd84 , SSqmd85 , SSqmd86 , SSqmd87 , SSqmd88 , SSqmd89 , & + SSqmd90 , SSqmd91 , SSqmd92 , SSqmd93 , SSqmd94 , SSqmd95 , SSqmd96 , & + SSqmd97 , SSqmd98 , SSqmd99 , SSqmdd01 , SSqmdd02 , SSqmdd03 , SSqmdd04 , & + SSqmdd05 , SSqmdd06 , SSqmdd07 , SSqmdd08 , SSqmdd09 , SSqmdd10 , SSqmdd11 , & + SSqmdd12 , SSqmdd13 , SSqmdd14 , SSqmdd15 , SSqmdd16 , SSqmdd17 , SSqmdd18 , & + SSqmdd19 , SSqmdd20 , SSqmdd21 , SSqmdd22 , SSqmdd23 , SSqmdd24 , SSqmdd25 , & + SSqmdd26 , SSqmdd27 , SSqmdd28 , SSqmdd29 , SSqmdd30 , SSqmdd31 , SSqmdd32 , & + SSqmdd33 , SSqmdd34 , SSqmdd35 , SSqmdd36 , SSqmdd37 , SSqmdd38 , SSqmdd39 , & + SSqmdd40 , SSqmdd41 , SSqmdd42 , SSqmdd43 , SSqmdd44 , SSqmdd45 , SSqmdd46 , & + SSqmdd47 , SSqmdd48 , SSqmdd49 , SSqmdd50 , SSqmdd51 , SSqmdd52 , SSqmdd53 , & + SSqmdd54 , SSqmdd55 , SSqmdd56 , SSqmdd57 , SSqmdd58 , SSqmdd59 , SSqmdd60 , & + SSqmdd61 , SSqmdd62 , SSqmdd63 , SSqmdd64 , SSqmdd65 , SSqmdd66 , SSqmdd67 , & + SSqmdd68 , SSqmdd69 , SSqmdd70 , SSqmdd71 , SSqmdd72 , SSqmdd73 , SSqmdd74 , & + SSqmdd75 , SSqmdd76 , SSqmdd77 , SSqmdd78 , SSqmdd79 , SSqmdd80 , SSqmdd81 , & + SSqmdd82 , SSqmdd83 , SSqmdd84 , SSqmdd85 , SSqmdd86 , SSqmdd87 , SSqmdd88 , & + SSqmdd89 , SSqmdd90 , SSqmdd91 , SSqmdd92 , SSqmdd93 , SSqmdd94 , SSqmdd95 , & + SSqmdd96 , SSqmdd97 , SSqmdd98 , SSqmdd99 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(2265) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(Nm) ","(Nm) ", & + "(Nm) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) "/) + + +!End of code generated by Matlab script +end module SubDyn_Output_Params From a312da7172ee4c6b1dce77a43b886e771f882590 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Dec 2019 19:41:38 -0700 Subject: [PATCH 059/377] FlexSub: more cleanup of outputs --- modules/subdyn/src/SubDyn_Output.f90 | 381 ++++++++------------------- 1 file changed, 105 insertions(+), 276 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index ee711c92f..1fcd4ec24 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -47,122 +47,56 @@ MODULE SubDyn_Output !> This subroutine initializes the output module, checking if the output parameter list (OutList) ! contains valid names, and opening the output file if there are any requested outputs SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module - TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( INOUT ), target :: p ! SubDyn module paramters - TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables - TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data - REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! Local variables - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters - INTEGER(IntKi) :: Junk !Temporary Holders - INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time - INTEGER(IntKi) :: eType - TYPE(ElemPropType), pointer :: eP !< Element Property, Alias to shorten notations - REAL(ReKi) :: FCe(12) ! Pretension force from cable element -!------------------------------------------------------------------------------------------------- -! Initialize local variables -!------------------------------------------------------------------------------------------------- -ErrStat = 0 -ErrMsg="" - -p%OutAllDims=12*p%Nmembers*2 !size of AllOut Member Joint forces - -!------------------------------------------------------------------------------------------------- -! Check that the variables in OutList are valid -!------------------------------------------------------------------------------------------------- - -! SDOut_Data%NumOuts = HDO_InitData%NumOuts - CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat, ErrMsg ) - IF ( ErrStat /= 0 ) RETURN - -!------------------------------------------------------------------------------------------------- -! INITIALIZE FAST-TYPE OUTPUT (y) -!------------------------------------------------------------------------------------------------- - !ALLOCATE( y%Y1(TPdofL), STAT = ErrStat ) - !IF ( ErrStat/= 0 ) THEN - ! ErrStat = ErrID_Fatal - ! ErrMsg = 'Error allocating output Y1 array in SDOut_Init' - ! RETURN - !END IF - -!------------------------------------------------------------------------------------------------- -! Open the output file, if necessary, and write the header -!------------------------------------------------------------------------------------------------- - - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested - - + TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module + TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data + TYPE(SD_ParameterType), INTENT( INOUT ), target :: p ! SubDyn module paramters + TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables + TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data + REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters + INTEGER(IntKi) :: Junk !Temporary Holders + INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time + INTEGER(IntKi) :: eType + TYPE(ElemPropType), pointer :: eP !< Element Property, Alias to shorten notations + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + ErrStat = 0 + ErrMsg="" + + p%OutAllDims=12*p%Nmembers*2 !size of AllOut Member Joint forces + + ! Check that the variables in OutList are valid + CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat2, ErrMsg2 ); if(Failed()) return + + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested ! Allocate SDWrOuput which is used to store a time step's worth of output channels, prior to writing to a file. - ALLOCATE( misc%SDWrOutput( p%NumOuts +p%OutAllInt*p%OutAllDims), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for SDWrOutput array.' - ErrStat = ErrID_Fatal - RETURN - END IF + CALL AllocAry(misc%SDWrOutput, p%NumOuts +p%OutAllInt*p%OutAllDims, 'SDWrOutupt', ErrStat2, ErrMsg2) ; if(Failed()) return misc%SDWrOutput = 0.0_ReKi misc%LastOutTime = 0.0_DbKi misc%Decimat = 0 !Allocate WriteOuput - ALLOCATE( y%WriteOutput( p%NumOuts +p%OutAllInt*p%OutAllDims), STAT = ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating space for WriteOutput array.' - ErrStat = ErrID_Fatal - RETURN - END IF + CALL AllocAry(y%WriteOutput, p%NumOuts +p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return y%WriteOutput = 0 - !Do some final mapping and carry out housekeeping to calculate some of the output variable - - - !Store mapping between nodes and elements - CALL NodeCon(Init,p,ErrStat, ErrMsg) - IF ( ErrStat /=0) RETURN + !Store mapping between nodes and elements + CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return DO I=1,p%NMOutputs - CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MoutLst(I)%NoutCnt, 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2) ; if(Failed()) return - p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MoutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting + CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MoutLst(I)%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%ElmIDs, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%ElmNds, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Me, 12, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Ke, 12, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Fg, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - ALLOCATE( p%MOutLst(I)%ElmIDs(p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !ElmIDs has for each selected node within the member, several element numbers to refer to for averaging (max 2 elements) - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%ElmIDs arrays in SDOut_Init' - RETURN - END IF + p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MoutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting p%MOutLst(I)%ElmIDs=0 !Initialize to 0 - - ALLOCATE( p%MOutLst(I)%ElmNds(p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !ElmNds has for each selected node within the member, for each element number to refer to for averaging, the flag 1 or 2 depending on whether it is the 1st or last node of that element - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%ElmNds arrays in SDOut_Init' - RETURN - END IF - - ALLOCATE( p%MOutLst(I)%Me(12,12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Me has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x12 matrix - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%Me arrays in SDOut_Init' - RETURN - END IF - ALLOCATE( p%MOutLst(I)%Ke(12,12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Ke has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x12 matrix - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%Ke arrays in SDOut_Init' - RETURN - END IF - ALLOCATE( p%MOutLst(I)%Fg(12,p%MoutLst(I)%NoutCnt,p%NAvgEls), STAT = ErrStat ) !Fg has for each selected node within the member, and for each element attached to that node for averaging (max 2) a 12x1 vector - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst(I)%Fg arrays in SDOut_Init' - RETURN - END IF - - + p%MOutLst(I)%ElmNds=0 !Initialize to 0 DO J=1,p%MoutLst(I)%NoutCnt !Iterate on requested nodes for that member !I need to get at most 2 elements that belong to the same MoutLst(I)%MemberID @@ -223,41 +157,26 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ! Adding cable element force to gravity vector p%MoutLst(I)%Fg(:,J,K2) = p%MoutLst(I)%Fg(:,J,K2) + FCe(1:12) END IF - ENDDO - ENDDO - - ENDDO - - - - END IF ! there are any requested outputs + ENDDO ! K, NconEls + ENDDO !J, Noutcnt + ENDDO !I, NMOutputs + END IF ! there are any requested outputs - IF (p%OutAll) THEN !I need to store all member end forces and moments + IF (p%OutAll) THEN !I need to store all member end forces and moments - ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat ) !this list contains different arrays for each of its elements - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst2 array in SDOut_Init' - RETURN - END IF - + ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat2 ) !this list contains different arrays for each of its elements + ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init' DO I=1,p%NMembers + p%MOutLst2(I)%MemberID=I !Assign memberID for all members - - ALLOCATE( p%MOutLst2(I)%NodeIDs(Init%Ndiv+1), STAT = ErrStat ) !1st and last node of member - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst2(I)%NodeIDs arrays in SDOut_Init' - RETURN - END IF + CALL AllocAry(p%MOutLst2(I)%NodeIDs, Init%Ndiv+1 , 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return p%MOutLst2(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member !Now I need to find out which elements are attached to those nodes and still belong to the member I !ElmID2s could contain the same element twice if Ndiv=1 p%MOutLst2(I)%ElmID2s=0 !Initialize to 0 - DO J=1,Init%Ndiv+1,Init%Ndiv !Iterate on requested nodes for that member (first and last) !I need to get at most 2 elements that belong to the same I Member @@ -275,9 +194,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF (M(1) .EQ. p%MoutLst2(I)%NodeIDs(J)) Junk=M(2) IF (ANY(Init%MemberNodes(p%MoutLst2(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member - p%MoutLst2(I)%ElmID2s(K2)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for - p%MoutLst2(I)%ElmNd2s(K2)=1 !store whether first or second node of element IF (M(2) .EQ. p%MoutLst2(I)%NodeIDs(J) ) p%MoutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element @@ -291,146 +208,72 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) EXIT !We found the element for that node, exit loop on elements ENDIF - - ENDDO - ENDDO - ENDDO - - - ENDIF - - !_____________________________________REACTIONS_____________________________________________ -p%OutReact = .FALSE. -DO I=1,p%NumOuts - if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" - p%OutReact =.TRUE. - EXIT ENDIF -ENDDO - IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being - - ALLOCATE ( p%MOutLst3(p%NReact), STAT = ErrStat ) !this list contains different arrays for each of its elements - IF ( ErrStat /= ErrID_None ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3 array in SDOut_Init' - RETURN - END IF - - - DO I=1,p%NReact !For all constrained node + !_____________________________________REACTIONS_____________________________________________ + p%OutReact = .FALSE. + DO I=1,p%NumOuts + if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" + p%OutReact =.TRUE. + EXIT + ENDIF + ENDDO - p%MOutLst3(I)%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array - - !Next stuff to be eliminated - !ALLOCATE( p%MOutLst3(I)%NodeIDs(Init%Ndiv+1), STAT = ErrStat ) ! - ! IF ( ErrStat/= 0 ) THEN - ! ErrStat = ErrID_Fatal - ! ErrMsg = 'Error allocating p%MOutLst3(I)%NodeIDs arrays in SDOut_Init' - ! RETURN - ! END IF - ! - !p%MOutLst3(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member - !Now I need to find out which elements are attached to those nodes and still belong to the member I - !ElmID2s could contain the same element twice if Ndiv=1 - !p%MOutLst3(I)%ElmID2s=0 !Initialize to 0 - - !I need to get ALL the elements that belong to the same joint - !make use of MemberNodes and NodesConnE - - NconEls=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint - - ALLOCATE( p%MOutLst3(I)%ElmIDs(1,NconEls), STAT = ErrStat ) !element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other Moutlst - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3(I)%ElmIDs arrays in SDOut_Init' - RETURN - END IF - - ALLOCATE( p%MOutLst3(I)%ElmNds(1,NconEls), STAT = ErrStat ) !This array contains for each element connected to the joint, a flag that tells me whether the joint is node 1 or 2 for the elements - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3(I)%ElmIDs arrays in SDOut_Init' - RETURN - END IF - - ALLOCATE( p%MOutLst3(I)%Me(12,12,1,NconEls), STAT = ErrStat ) !Me has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3(I)%Me arrays in SDOut_Init' - RETURN - END IF - ALLOCATE( p%MOutLst3(I)%Ke(12,12,1,NconEls), STAT = ErrStat ) !Ke has for each selected joint, and for each element attached to that node a 12x12 matrix - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3(I)%Ke arrays in SDOut_Init' - RETURN - END IF - ALLOCATE( p%MOutLst3(I)%Fg(12,1,NconEls), STAT = ErrStat ) !Fg has for each selected joint, and for each element attached to that node a 12x1 vector - IF ( ErrStat/= 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'Error allocating p%MOutLst3(I)%Ke arrays in SDOut_Init' - RETURN - END IF - - DO K=1, NconEls - L=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node - - p%MoutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for - - M=p%Elems(L,2:3) !1st and 2nd node of the k-th element - - !Select whether the joint is the 1st or second node of the element - p%MoutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MoutLst3(I)%Noutcnt ) p%MoutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element - - !Calculate Ke, Me to be used for output - CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & - p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & - p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst3(I)%Ke(:,:,1,K) ) - CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& - p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Me(:,:,1,K) ) - CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Fg(:,1,K), Init%g ) - - - ENDDO - - ENDDO + IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being + + ALLOCATE ( p%MOutLst3(p%NReact), STAT = ErrStat2) !this list contains different arrays for each of its elements + ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init' + if(Failed()) return + + DO I=1,p%NReact !For all constrained node + p%MOutLst3(I)%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array + NconEls=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint + ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other Moutlst + ! Me: has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) + ! Ke: has for each selected joint, and for each element attached to that node a 12x12 matrix + CALL AllocAry(p%MOutLst3(I)%ElmIDs, 1, NconEls, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst3(I)%ElmNds, 1, NconEls, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst3(I)%Me, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst3(I)%Ke, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst3(I)%Fg, 12 , 1, NconEls, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - !Store the matrix that will let me calculate single point reaction at the base of structure - CALL ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) - ENDIF + DO K=1, NconEls + L=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node - - - ! These variables are to help follow the framework template, but the data in them is simply a copy of data - ! already available in the OutParam data structure + p%MoutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for - ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF + M=p%Elems(L,2:3) !1st and 2nd node of the k-th element - ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts+p%OutAllint*p%OutAllDims), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF + !Select whether the joint is the 1st or second node of the element + p%MoutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MoutLst3(I)%Noutcnt ) p%MoutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element - + !Calculate Ke, Me to be used for output + CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & + p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & + p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst3(I)%Ke(:,:,1,K) ) + CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& + p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Me(:,:,1,K) ) + CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Fg(:,1,K), Init%g ) + ENDDO + ENDDO + !Store the matrix that will let me calculate single point reaction at the base of structure + CALL ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) + ENDIF + + ! These variables are to help follow the framework template, but the data in them is simply a copy of data + ! already available in the OutParam data structure + CALL AllocAry(InitOut%WriteOutputHdr, p%NumOuts+p%OutAllint*p%OutAllDims, 'WriteOutputHdr', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(InitOut%WriteOutputUnt, p%NumOuts+p%OutAllint*p%OutAllDims, 'WriteOutputUnt', ErrStat2, ErrMsg2); if(Failed()) return DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims - InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) END DO - -RETURN + RETURN CONTAINS LOGICAL FUNCTION Failed() @@ -486,33 +329,19 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) rmndr = MOD(I, 6) !It gives me the column index among the 6 different kinds SELECT CASE (rmndr) - CASE (1) - p%TIreact(4:6, I) = (/0.0_ReKi, z, -y/) - - CASE (2) - p%TIreact(4:6, I) = (/-z, 0.0_ReKi, x/) - - CASE (3) - p%TIreact(4:6, I) = (/y, -x, 0.0_ReKi/) - - CASE (4) - p%TIreact(4:6, I) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - - CASE (5) - p%TIreact(4:6, I) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - - CASE (0) - p%TIreact(4:6, I) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + CASE (1); p%TIreact(4:6, I) = (/0.0_ReKi , z , -y/) + CASE (2); p%TIreact(4:6, I) = (/-z , 0.0_ReKi , x/) + CASE (3); p%TIreact(4:6, I) = (/y , -x , 0.0_ReKi/) + CASE (4); p%TIreact(4:6, I) = (/1.0_ReKi , 0.0_ReKi , 0.0_ReKi/) + CASE (5); p%TIreact(4:6, I) = (/0.0_ReKi , 1.0_ReKi , 0.0_ReKi/) + CASE (0); p%TIreact(4:6, I) = (/0.0_ReKi , 0.0_ReKi , 1.0_ReKi/) CASE DEFAULT ErrStat = ErrID_Fatal ErrMsg = 'Error calculating transformation matrix TIreact ' RETURN END SELECT - ENDDO - - END SUBROUTINE ReactMatx !==================================================================================================== From 7cea49c87e476a5c7c5c224ff948a1b02cf09050 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 6 Dec 2019 09:57:32 -0700 Subject: [PATCH 060/377] FlexSub: cleanup of outputs --- modules/subdyn/src/SubDyn_Output.f90 | 314 +++++++-------------------- 1 file changed, 81 insertions(+), 233 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 1fcd4ec24..0675fba60 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -284,44 +284,37 @@ END FUNCTION Failed END SUBROUTINE SDOut_Init !------------------------------------------------------------------------------------------------------ +!>This subroutine allocates and calculated TIreact, Matrix to go from local reactions at constrained nodes to single point reactions SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) -!This subroutine allocates and calculated TIreact, Matrix to go from local reactions at constrained nodes to single point reactions TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT( INOUT) :: p ! Parameter data REAL(ReKi), INTENT(IN) :: WtrDpth INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! local variables + ! local variables INTEGER :: I !counter INTEGER :: rmndr !type-column index INTEGER :: n !node ID INTEGER(IntKi) :: DOFC ! DOFC = Init%NReact*6 REAL(ReKi) :: x, y, z !coordinates - - !Initialize ErrStat=ErrID_None ErrMsg="" DOFC = p%NReact*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure - ALLOCATE ( p%TIreact(6,DOFC), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for TIreact array.' - ErrStat = ErrID_Fatal - RETURN - END IF + CALL AllocAry(p%TIreact, 6,DOFC, 'p%TIReact', ErrStat, ErrMsg ) + if ( ErrStat /= ErrID_None ) return p%TIreact=0 !Initialize DO I=1,3 !Take care of first three rows - p%TIreact(I,I:DOFC:6)=1 + p%TIreact(I,I:DOFC:6)=1 ENDDO !Other rows done per column actually DO I = 1, DOFC - n = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) + n = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) ! TODO different DOF ordering x = Init%Nodes(n, 2) y = Init%Nodes(n, 3) @@ -338,7 +331,7 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) CASE DEFAULT ErrStat = ErrID_Fatal - ErrMsg = 'Error calculating transformation matrix TIreact ' + ErrMsg = 'Error calculating transformation matrix TIreact, wrong column index ' RETURN END SELECT ENDDO @@ -389,6 +382,8 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg uddout =0 !Initialize and populate with Udotdot data uddout(1 : p%URbarL ) = m%UR_bar_dotdot uddout(p%URbarL+1 : p%URbarL+p%DOFL ) = m%UL_dotdot + + ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency ! Only generate member-based outputs for the number of user-requested member outputs !Now store and identify needed output as requested by user @@ -401,55 +396,47 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg DO J=1,p%MoutLst(I)%NOutCnt !Iterate on requested nodes for that member !I need to average across potentially up to 2 elements !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second - K=p%MOutLst(I)%ElmIDs(J,1) !element number - K2=p%MOutLst(I)%ElmNds(J,1) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node + K = p%MOutLst(I)%ElmIDs(J,1) !element number + K2= p%MOutLst(I)%ElmNds(J,1) !first or second node of the element to be considered + !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 - K3=p%Elems(K,2:3) !first and second node ID associated with element K - - L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout - L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - - DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local dir-cosine matrix - + L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local dir-cosine matrix !I need to find the Udotdot() for the two nodes of the element of interest !I need to move the displacements to the local ref system - - ! bjj: added these temporary storage variables so that the CALC_LOCAL call doesn't created - ! new temporary *every time* it's called + ! bjj: added these temporary storage variables so that the CALC_NODE_FORCES call doesn't created + ! new temporary *every time* it's called Tmp_Udotdot(1: 6) = uddout( L : L+5 ) Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) - Tmp_y2(1: 6) = yout( L : L+5 ) Tmp_y2(7:12) = yout( L2 : L2+5 ) - - CALL CALC_LOCAL( DIRCOS,p%MOutLst(I)%Me(:,:,J,1),p%MOutLst(I)%Ke(:,:,J,1),Tmp_Udotdot, & + CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst(I)%Me(:,:,J,1),p%MOutLst(I)%Ke(:,:,J,1),Tmp_Udotdot, & Tmp_y2,p%MoutLst(I)%Fg(:,J,1), K2,FM_elm,FK_elm) FM_elm2=sgn*FM_elm FK_elm2=sgn*FK_elm IF (p%MOutLst(I)%ElmIDs(J,p%NavgEls) .NE. 0) THEN !element number - K=p%MOutLst(I)%ElmIDs(J,p%NavgEls) !element number - K2=p%MOutLst(I)%ElmNds(J,p%NavgEls) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node - sgn=-1 - IF (K2 .EQ. 2) sgn= +1 - + K = p%MOutLst(I)%ElmIDs(J,p%NavgEls) !element number + K2 = p%MOutLst(I)%ElmNds(J,p%NavgEls) !first or second node of the element to be considered + !Assign the sign depending on whether it is the 1st or second node + sgn=-1 + IF (K2 .EQ. 2) sgn= +1 K3=p%Elems(K,2:3) !first and second node ID associated with element K - L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout - L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - CALL CALC_LOCAL(DIRCOS,p%MOutLst(I)%Me(:,:,J,p%NavgEls),p%MOutLst(I)%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order + L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + CALL CALC_NODE_FORCES(DIRCOS,p%MOutLst(I)%Me(:,:,J,p%NavgEls),p%MOutLst(I)%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst(I)%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average ENDIF - !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts + ! Store in AllOuts !Forces and moments AllOuts(MNfmKe (:,J,I)) = FK_elm2 !static forces and moments (6) Local Ref AllOuts(MNfmMe (:,J,I)) = FM_elm2 !dynamic forces and moments (6) Local Ref @@ -457,73 +444,54 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg L=p%IDY( (p%MOutLst(I)%NodeIDs(J)-1)*6 +1 )! starting index for nodeID(J) within yout AllOuts(MNTDss (:,J,I)) = yout(L:L+2) !Displacement- Rotational - I need to get the direction cosine matrix to tranform rotations - In Local reference Element Ref Sys - AllOuts(MNRDe (:,J,I)) = matmul(DIRCOS,yout(L+3:L+5) ) !local ref !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations AllOuts(MNTRAe (1:3,J,I)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref AllOuts(MNTRAe (4:6,J,I)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref - - - ENDDO + ENDDO ! J, Loop on requested nodes for that member - ENDDO + ENDDO ! I, Loop on member outputs END IF - IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES - DO I=1,p%NMembers !Cycle on all members DO J=1,2 !Iterate on requested nodes for that member (first and last) K=p%MOutLst2(I)%ElmID2s(J) !element number K2=p%MOutLst2(I)%ElmNd2s(J) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 - K3=p%Elems(K,2:3) !first and second node ID associated with element K - - L=p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - - DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local - - CALL CALC_LOCAL( DIRCOS,p%MOutLst2(I)%Me2(:,:,J),p%MOutLst2(I)%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local + CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst2(I)%Me2(:,:,J),p%MOutLst2(I)%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst2(I)%Fg2(:,J), K2,FM_elm,FK_elm) - - ! FM_elm2=sgn*FM_elm - ! FK_elm2=sgn*FK_elm - - !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts + ! Store in All Outs L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index L2=L+11 - AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) - - ENDDO - ENDDO - + AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) + ENDDO !J, nodes 1 and 2 + ENDDO ! I, Loop on members ENDIF - !Assign interface forces and moments - AllOuts(IntfSS(1:TPdofL))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign - + AllOuts(IntfSS(1:TPdofL))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign !Assign interface translations and rotations at the TP ref point AllOuts(IntfTRss(1:TPdofL))=m%u_TP - !Assign interface translations and rotations accelerations AllOuts(IntfTRAss(1:TPdofL))= m%udotdot_TP - + ! Assign all SSqm, SSqmdot, SSqmdotdot - ! We only have space for the first 99 values + ! We only have space for the first 99 values maxOutModes = min(p%Nmodes,99) - IF ( maxOutModes > 0 ) THEN - !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) - Allouts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) - Allouts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) - Allouts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) - END IF + IF ( maxOutModes > 0 ) THEN + !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) + Allouts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) + Allouts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) + Allouts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) + END IF !Need to Calculate Reaction Forces Now, but only if requested IF (p%OutReact) THEN @@ -544,51 +512,40 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Find the joint forces DO J=1,SIZE(p%MOutLst3(I)%ElmIDs(1,:)) !for all the elements connected (normally 1) - - K=p%MOutLst3(I)%ElmIDs(1,J) !element number - K2=p%MOutLst3(I)%ElmNds(1,J) !first or second node of the element to be considered - + K = p%MOutLst3(I)%ElmIDs(1,J) ! element number + K2 = p%MOutLst3(I)%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered !Assign the sign depending on whether it is the 1st or second node K3=p%Elems(K,2:3) !first and second node ID associated with element K - - L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout + L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - DIRCOS=tranSpose(p%elemprops(K)%DirCos)! global to local - - CALL CALC_LOCAL( DIRCOS,p%MOutLst3(I)%Me(:,:,1,J),p%MOutLst3(I)%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst3(I)%Me(:,:,1,J),p%MOutLst3(I)%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst3(I)%Fg(:,1,J), K2,FM_elm,FK_elm) - !transform back to global, need to do 3 at a time since cosine matrix is 3x3 DO L=1,2 FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 ENDDO - ENDDO !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise - !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt !The index in Y2mesh is? !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) - ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ENDDO - - !NOW HERE I WOULD NEED TO PUT IT INTO AllOuts - - AllOuts( ReactSS(1:TPdofL) ) = matmul(p%TIreact,ReactNs) + ! Store into AllOuts + AllOuts( ReactSS(1:TPdofL) ) = matmul(p%TIreact,ReactNs) ENDIF + if (allocated(ReactNs)) deallocate(ReactNs) - if (allocated(ReactNs)) deallocate(ReactNs) - END SUBROUTINE SDOut_MapOutputs !==================================================================================================== - SUBROUTINE CALC_LOCAL(DIRCOS,Me,Ke,Udotdot,Y2,Fg, K2,FM_elm,FK_elm) + SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, K2,FM_nod,FK_nod) !This function calculates for the given element the static and dynamic forces, given K and M of the element, and !output quantities Udotdot and Y2 containing the !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked @@ -597,88 +554,59 @@ SUBROUTINE CALC_LOCAL(DIRCOS,Me,Ke,Udotdot,Y2,Fg, K2,FM_elm,FK_elm) Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces Integer(IntKi), INTENT(IN) :: K2 !1 or 2 depending on node of interest - REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_elm, FK_elm !output static and dynamic forces and moments - - !Locals - INTEGER(IntKi) ::L !counter - REAL(DbKi), DIMENSION(12) ::Junk,Junk1,Junk3,Junk4 ! temporary storage for output stuff + REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments + !Locals + INTEGER(IntKi) :: L !counter + REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage - Junk=matmul(Me,Udotdot) !GLOBAL REFERENCE - Junk1=matmul(Ke,Y2) !GLOBAL REFERENCE - Junk1=Junk1- Fg !GLOBAL REFERENCE - DO L=1,4 - Junk3((L-1)*3+1:L*3)= matmul(DIRCOS, Junk( (L-1)*3+1:L*3 ) ) - Junk4((L-1)*3+1:L*3) = matmul(DIRCOS, Junk1( (L-1)*3+1:L*3 ) ) + FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE + FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE + FF_glb = FF_glb - Fg ! GLOBAL REFERENCE + DO L=1,4 ! Transforming coordinates 3 at a time + FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) + FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) ENDDO - - - FM_elm=Junk3(6*(k2-1)+1:k2*6) - FK_elm=Junk4(6*(k2-1)+1:k2*6) - + FM_nod=FM_elm(6*(k2-1)+1:k2*6) ! k2=1, 1:6, k2=2 7:12 + FK_nod=FF_elm(6*(k2-1)+1:k2*6) - END SUBROUTINE CALC_LOCAL + END SUBROUTINE CALC_NODE_FORCES - !==================================================================================================== +!==================================================================================================== SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) - - - ! Passed variables - INTEGER, INTENT( IN ) :: UnSum ! the unit number for the SubDyn summary file INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - ! Local variables + ! Local variables INTEGER :: Stat ! status from I/) operation - - ! Initialize ErrStat - ErrStat = ErrID_None ErrMsg = "" - - ! Write any closing information in the summary file - + ! Write any closing information in the summary file IF ( UnSum > 0 ) THEN - WRITE (UnSum,'(/,A/)', IOSTAT=Stat) 'This summary file was closed on '//CurDate()//' at '//CurTime()//'.' IF (Stat /= 0) THEN ErrStat = ErrID_FATAL ErrMsg = ' Problem writing to summary file.' END IF - ! Close the file - CLOSE( UnSum, IOSTAT=Stat ) IF (Stat /= 0) THEN ErrStat = ErrID_FATAL ErrMsg = TRIM(ErrMsg)//' Problem closing summary file.' END IF - IF ( ErrStat /= ErrID_None ) ErrMsg = 'SDOut_CloseSum'//TRIM(ErrMsg) - END IF - END SUBROUTINE SDOut_CloseSum !==================================================================================================== SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) - - - ! Passed variables - INTEGER, INTENT( OUT ) :: UnSum ! the unit number for the SubDyn summary file CHARACTER(*), INTENT( IN ) :: SummaryName ! the name of the SubDyn summary file TYPE(ProgDesc), INTENT( IN ) :: SD_Prog ! the name/version/date of the program INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer :: ErrStat2 - ! Initialize ErrStat - ErrStat = ErrID_None ErrMsg = "" - CALL GetNewUnit( UnSum ) CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) @@ -687,12 +615,9 @@ SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) RETURN END IF - - ! Write the summary file header - + ! Write the summary file header WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) 'This summary file was generated by '//TRIM( SD_Prog%Name )//& ' '//TRIM( SD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' - END SUBROUTINE SDOut_OpenSum !==================================================================================================== @@ -700,37 +625,23 @@ SUBROUTINE SDOut_OpenOutput( ProgVer, OutRootName, p, InitOut, ErrStat, ErrMsg ! This subroutine initialized the output module, checking if the output parameter list (OutList) ! contains valid names, and opening the output file if there are any requested outputs !---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - + ! Passed variables TYPE(ProgDesc), INTENT( IN ) :: ProgVer CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file TYPE(SD_ParameterType), INTENT( INOUT ) :: p TYPE(SD_InitOutPutType ), INTENT( IN ) :: InitOut ! INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables + ! Local variables INTEGER :: I ! Generic loop counter CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. CHARACTER(200) :: Frmt ! a string to hold a format statement INTEGER :: ErrStat2 - - !------------------------------------------------------------------------------------------------- - ! Initialize local variables - !------------------------------------------------------------------------------------------------- ErrStat = ErrID_None ErrMsg = "" - - !------------------------------------------------------------------------------------------------- ! Open the output file, if necessary, and write the header - !------------------------------------------------------------------------------------------------- - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file - - ! Open the file for output + ! Open the file for output OutFileName = TRIM(OutRootName)//'.out' CALL GetNewUnit( p%UnJckF ) @@ -739,31 +650,20 @@ SUBROUTINE SDOut_OpenOutput( ProgVer, OutRootName, p, InitOut, ErrStat, ErrMsg ErrMsg = ' Error opening SubDyn-level output file: '//TRIM(ErrMsg) RETURN END IF - - ! Write the output file header - + ! Write the output file header WRITE (p%UnJckF,'(/,A/)', IOSTAT=ErrStat2) 'These predictions were generated by '//TRIM(GETNVD(ProgVer))//& ' on '//CurDate()//' at '//CurTime()//'.' WRITE(p%UnJckF, '(//)') ! add 3 lines to make file format consistant with FAST v8 (headers on line 7; units on line 8) [this allows easier post-processing] - ! Write the names of the output parameters: - + ! Write the names of the output parameters: Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 'Time' ), ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - - ! Write the units of the output parameters: + ! Write the units of the output parameters: WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 's'), ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - - - END IF ! there are any requested outputs - - RETURN - END SUBROUTINE SDOut_OpenOutput !==================================================================================================== @@ -774,44 +674,26 @@ SUBROUTINE SDOut_CloseOutput ( p, ErrStat, ErrMsg ) ! This function cleans up after running the SubDyn output module. It closes the output file, ! releases memory, and resets the number of outputs requested to 0. !---------------------------------------------------------------------------------------------------- - - ! Passed variables - - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - -! ! Internal variables LOGICAL :: Err - - !------------------------------------------------------------------------------------------------- - ! Initialize error information - !------------------------------------------------------------------------------------------------- ErrStat = 0 ErrMsg = "" - Err = .FALSE. - !------------------------------------------------------------------------------------------------- ! Close our output file - !------------------------------------------------------------------------------------------------- CLOSE( p%UnJckF, IOSTAT = ErrStat ) IF ( ErrStat /= 0 ) Err = .TRUE. - - - !------------------------------------------------------------------------------------------------- ! Make sure ErrStat is non-zero if an error occurred - !------------------------------------------------------------------------------------------------- IF ( Err ) ErrStat = ErrID_Fatal - RETURN END SUBROUTINE SDOut_CloseOutput !==================================================================================================== - SUBROUTINE SDOut_WriteOutputNames( UnJckF, p, ErrStat, ErrMsg ) INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file @@ -833,9 +715,7 @@ END SUBROUTINE SDOut_WriteOutputNames !==================================================================================================== - SUBROUTINE SDOut_WriteOutputUnits( UnJckF, p, ErrStat, ErrMsg ) - INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs @@ -858,24 +738,17 @@ SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) ! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file ! opened in SDOut_Init() !---------------------------------------------------------------------------------------------------- - - ! Passed variables INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file REAL(DbKi), INTENT( IN ) :: Time ! Time for this output REAL(ReKi), INTENT( IN ) :: SDWrOutput(:) ! SubDyn module's output data TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables - ! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array + ! Local variables INTEGER :: I ! Generic loop counter CHARACTER(200) :: Frmt ! a string to hold a format statement - - ! Initialize ErrStat and determine if it makes any sense to write output - IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnJckF < 0 ) THEN ErrStat = ErrID_Fatal ErrMsg = ' To write outputs for SubDyn there must be a valid file ID and OutParam must be allocated.' @@ -884,18 +757,11 @@ SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) ErrStat = ErrID_None END IF - ! Write the output parameters to the file - Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutFmt )//'))' - WRITE(UnJckF,Frmt) Time, ( p%Delim, SDWrOutput(I), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - - RETURN - - END SUBROUTINE SDOut_WriteOutputs !==================================================================================================== @@ -908,35 +774,22 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) ! name, and units of the output channels). ! NOTE OutParam is populated here !---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module parameter data CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables. - + ! Local variables. INTEGER :: I,J,K ! Generic loop-counting index. INTEGER :: INDX ! Index for valid arrays - CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). !CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. CHARACTER(ChanLen), DIMENSION(24) :: ToTUnits,ToTNames,ToTNames0 - LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration - LOGICAL :: CheckOutListAgain InvalidOutput = .FALSE. -!End of code generated by Matlab script - ! mark invalid output channels: - DO k=p%Nmodes+1,99 InvalidOutput(SSqm01 +k-1) = .true. InvalidOutput(SSqmd01 +k-1) = .true. @@ -963,7 +816,6 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) END DO END DO - !------------------------------------------------------------------------------------------------- ! ALLOCATE the OutParam array !------------------------------------------------------------------------------------------------- @@ -983,7 +835,6 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) !!!p%OutParam(0)%Units = '(sec)' ! !!!p%OutParam(0)%Indx = Time !!!p%OutParam(0)%SignM = 1 - DO I = 1,p%NumOuts @@ -1053,10 +904,7 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%Indx= MaxOutPts+(/(J, J=1, p%OutAllDims)/) ENDIF - RETURN END SUBROUTINE SDOut_ChkOutLst - - !==================================================================================================== From 6f52cbd277511e8e54b5b8381cb8c1043a665e7a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 6 Dec 2019 10:29:16 -0700 Subject: [PATCH 061/377] FlexSub: using wrapper function for M, K, F --- modules/subdyn/src/SubDyn_Output.f90 | 143 ++++++++++----------------- 1 file changed, 53 insertions(+), 90 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 0675fba60..e3f7e74b5 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -49,7 +49,7 @@ MODULE SubDyn_Output SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( INOUT ), target :: p ! SubDyn module paramters + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module paramters TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine @@ -62,7 +62,6 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) INTEGER(IntKi) :: Junk !Temporary Holders INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time INTEGER(IntKi) :: eType - TYPE(ElemPropType), pointer :: eP !< Element Property, Alias to shorten notations REAL(ReKi) :: FCe(12) ! Pretension force from cable element ErrStat = 0 ErrMsg="" @@ -87,75 +86,49 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return DO I=1,p%NMOutputs - CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MoutLst(I)%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%ElmIDs, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%ElmNds, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Me, 12, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Ke, 12, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Fg, 12, p%MoutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MoutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting + CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MOutLst(I)%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%ElmIDs, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%ElmNds, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Me, 12, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Ke, 12, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst(I)%Fg, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + + p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MOutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting p%MOutLst(I)%ElmIDs=0 !Initialize to 0 p%MOutLst(I)%ElmNds=0 !Initialize to 0 - DO J=1,p%MoutLst(I)%NoutCnt !Iterate on requested nodes for that member - !I need to get at most 2 elements that belong to the same MoutLst(I)%MemberID + DO J=1,p%MOutLst(I)%NoutCnt !Iterate on requested nodes for that member + !I need to get at most 2 elements that belong to the same MOutLst(I)%MemberID !make use of MemberNodes and NodesConnE - NconEls=Init%NodesConnE(p%MoutLst(I)%NodeIDs(J),1)!Number of elements connecting to the j-th node + NconEls=Init%NodesConnE(p%MOutLst(I)%NodeIDs(J),1)!Number of elements connecting to the j-th node K2=0 !Initialize counter DO K=1, NconEls - L=Init%NodesConnE(p%MoutLst(I)%NodeIDs(J),k+1) !k-th Element Number + L=Init%NodesConnE(p%MOutLst(I)%NodeIDs(J),k+1) !k-th Element Number M = p%Elems(L,2:3) !1st and 2nd node of the k-th element eType = p%Elems(L, iMType) !Select only the other node, not the one where elements connect to - IF (M(1) .EQ. p%MoutLst(I)%NodeIDs(J)) then + IF (M(1) .EQ. p%MOutLst(I)%NodeIDs(J)) then Junk=M(2) else Junk=M(1) endif - IF (ANY(Init%MemberNodes(p%MoutLst(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member - !print*,'L',L, 'M',M - !print*,'etype',eType + IF (ANY(Init%MemberNodes(p%MOutLst(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member IF (K2 .EQ. 2) EXIT K2=K2+1 - p%MoutLst(I)%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 - - IF (M(2) .EQ. p%MoutLst(I)%NodeIDs(J) )then - p%MoutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element + p%MOutLst(I)%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 + IF (M(2) .EQ. p%MOutLst(I)%NodeIDs(J) )then + p%MOutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element else - p%MoutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element + p%MOutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element endif - - eP => p%elemprops(L) - !if (eType==idBeam) then - !Calculate Ke, Me to be used for output - CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2) ) - CALL ElemM_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho , eP%DirCos, p%MoutLst(I)%Me(:,:,J,K2) ) - FCe(1:12)=0 - -! else if (eType==idCable) then -! CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, p%MoutLst(I)%Ke(:,:,J,K2)) -! CALL ElemM_Cable(ep%Area, ep%Length, ep%rho , ep%DirCos, p%MoutLst(I)%Me(:,:,J,K2)) -! CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, FCe) -! -! else if (eType==idRigid) then -! FCe(1:12)=0 -! p%MoutLst(I)%Ke(1:12,1:12,J,K2) =0.0_ReKi -! if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then -! p%MoutLst(I)%Me(1:12,1:12,J,K2)=0.0_ReKi -! else -! !CALL ElemM_(A, L, rho, DirCos, Me) -! print*,'SD_Output: Mass matrix for rigid members rho/=0 TODO' -! STOP -! endif -! endif - - CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, p%MoutLst(I)%Fg(:,J,K2), Init%g ) - ! Adding cable element force to gravity vector - p%MoutLst(I)%Fg(:,J,K2) = p%MoutLst(I)%Fg(:,J,K2) + FCe(1:12) + ! --- Element Me, Ke, Fg, Fce + CALL ElemM(p%ElemProps(L), p%MOutLst(I)%Me(:,:,J,K2)) + CALL ElemK(p%ElemProps(L), p%MOutLst(I)%Ke(:,:,J,K2)) + CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst(I)%Fg(:,J,K2), FCe) + p%MOutLst(I)%Fg(:,J,K2) = p%MOutLst(I)%Fg(:,J,K2) + FCe(1:12) ! Adding cable element force END IF ENDDO ! K, NconEls ENDDO !J, Noutcnt @@ -182,29 +155,26 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) !I need to get at most 2 elements that belong to the same I Member !make use of MemberNodes and NodesConnE - NconEls=Init%NodesConnE(p%MoutLst2(I)%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member + NconEls=Init%NodesConnE(p%MOutLst2(I)%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member K2= J/(Init%Ndiv+1)+1 !store this quantity used later, basically 1 or 2 depending on J DO K=1, NconEls - L=Init%NodesConnE(p%MoutLst2(I)%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node + L=Init%NodesConnE(p%MOutLst2(I)%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node M=p%Elems(L,2:3) !1st and 2nd node of the k-th element !Select only the other node, not the one where elements connect to Junk=M(1) - IF (M(1) .EQ. p%MoutLst2(I)%NodeIDs(J)) Junk=M(2) + IF (M(1) .EQ. p%MOutLst2(I)%NodeIDs(J)) Junk=M(2) - IF (ANY(Init%MemberNodes(p%MoutLst2(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member - p%MoutLst2(I)%ElmID2s(K2)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for - p%MoutLst2(I)%ElmNd2s(K2)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MoutLst2(I)%NodeIDs(J) ) p%MoutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element - - !Calculate Ke, Me to be used for output - CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & - p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & - p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst2(I)%Ke2(:,:,K2) ) - CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& - p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Me2(:,:,K2) ) - CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst2(I)%Fg2(:,K2), Init%g ) + IF (ANY(Init%MemberNodes(p%MOutLst2(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + p%MOutLst2(I)%ElmID2s(K2)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for + p%MOutLst2(I)%ElmNd2s(K2)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MOutLst2(I)%NodeIDs(J) ) p%MOutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element + ! --- Element Me, Ke, Fg, Fce + CALL ElemM(p%ElemProps(L), p%MOutLst2(I)%Me2(:,:,K2)) + CALL ElemK(p%ElemProps(L), p%MOutLst2(I)%Ke2(:,:,K2)) + CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst2(I)%Fg2(:,K2), FCe) + p%MOutLst2(I)%Fg2(:,K2) = p%MOutLst2(I)%Fg2(:,K2) + FCe(1:12) ! Adding cable element force EXIT !We found the element for that node, exit loop on elements ENDIF @@ -212,7 +182,6 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ENDDO ENDDO ENDIF - !_____________________________________REACTIONS_____________________________________________ p%OutReact = .FALSE. DO I=1,p%NumOuts @@ -230,8 +199,8 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) DO I=1,p%NReact !For all constrained node p%MOutLst3(I)%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array - NconEls=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint - ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other Moutlst + NconEls=Init%NodesConnE(p%MOutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint + ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other MOutLst ! Me: has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) ! Ke: has for each selected joint, and for each element attached to that node a 12x12 matrix CALL AllocAry(p%MOutLst3(I)%ElmIDs, 1, NconEls, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return @@ -241,23 +210,17 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL AllocAry(p%MOutLst3(I)%Fg, 12 , 1, NconEls, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return DO K=1, NconEls - L=Init%NodesConnE(p%MoutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node - - p%MoutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for - + L=Init%NodesConnE(p%MOutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node + p%MOutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for M=p%Elems(L,2:3) !1st and 2nd node of the k-th element - !Select whether the joint is the 1st or second node of the element - p%MoutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MoutLst3(I)%Noutcnt ) p%MoutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element - - !Calculate Ke, Me to be used for output - CALL ElemK_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy, & - p%elemprops(L)%Jzz, p%elemprops(L)%Shear, p%elemprops(L)%kappa, p%elemprops(L)%YoungE, & - p%elemprops(L)%ShearG, p%elemprops(L)%DirCos, p%MoutLst3(I)%Ke(:,:,1,K) ) - CALL ElemM_Beam( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%Ixx, p%elemprops(L)%Iyy,& - p%elemprops(L)%Jzz, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Me(:,:,1,K) ) - CALL ElemG( p%elemprops(L)%Area, p%elemprops(L)%Length, p%elemprops(L)%rho, p%elemprops(L)%DirCos, p%MoutLst3(I)%Fg(:,1,K), Init%g ) + p%MOutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MOutLst3(I)%Noutcnt ) p%MOutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element + ! --- Element Me, Ke, Fg, Fce + CALL ElemM(p%ElemProps(L), p%MOutLst3(I)%Me(:,:,1,K)) + CALL ElemK(p%ElemProps(L), p%MOutLst3(I)%Ke(:,:,1,K)) + CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst3(I)%Fg(:,1,K), FCe) + p%MOutLst3(I)%Fg(:,1,K) = p%MOutLst3(I)%Fg(:,1,K) + FCe(1:12) ! Adding cable element force ENDDO ENDDO !Store the matrix that will let me calculate single point reaction at the base of structure @@ -393,7 +356,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 DO I=1,p%NMOutputs !I know el # and whether it is 1st node or second node - DO J=1,p%MoutLst(I)%NOutCnt !Iterate on requested nodes for that member + DO J=1,p%MOutLst(I)%NOutCnt !Iterate on requested nodes for that member !I need to average across potentially up to 2 elements !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second K = p%MOutLst(I)%ElmIDs(J,1) !element number @@ -414,7 +377,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Tmp_y2(1: 6) = yout( L : L+5 ) Tmp_y2(7:12) = yout( L2 : L2+5 ) CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst(I)%Me(:,:,J,1),p%MOutLst(I)%Ke(:,:,J,1),Tmp_Udotdot, & - Tmp_y2,p%MoutLst(I)%Fg(:,J,1), K2,FM_elm,FK_elm) + Tmp_y2,p%MOutLst(I)%Fg(:,J,1), K2,FM_elm,FK_elm) FM_elm2=sgn*FM_elm FK_elm2=sgn*FK_elm @@ -430,7 +393,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout CALL CALC_NODE_FORCES(DIRCOS,p%MOutLst(I)%Me(:,:,J,p%NavgEls),p%MOutLst(I)%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst(I)%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst(I)%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average @@ -467,7 +430,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst2(I)%Me2(:,:,J),p%MOutLst2(I)%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst2(I)%Fg2(:,J), K2,FM_elm,FK_elm) + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst2(I)%Fg2(:,J), K2,FM_elm,FK_elm) ! Store in All Outs L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index L2=L+11 @@ -521,7 +484,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst3(I)%Me(:,:,1,J),p%MOutLst3(I)%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MoutLst3(I)%Fg(:,1,J), K2,FM_elm,FK_elm) + (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst3(I)%Fg(:,1,J), K2,FM_elm,FK_elm) !transform back to global, need to do 3 at a time since cosine matrix is 3x3 DO L=1,2 FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF @@ -799,7 +762,7 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) DO I=1,9 !I know el # and whether it is 1st node or second node if (I <= p%NMOutputs) then - INDX=p%MoutLst(I)%NOutCnt+1 + INDX=p%MOutLst(I)%NOutCnt+1 else INDX = 1 end if From 146744323a779c27a5079c972b02f7ca9a100578 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 6 Dec 2019 10:45:17 -0700 Subject: [PATCH 062/377] FlexSub: using pointer alias to shorten notation --- modules/subdyn/src/SD_FEM.f90 | 18 ++++++--- modules/subdyn/src/SubDyn_Output.f90 | 60 ++++++++++++++-------------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 1cdbdeee0..91c6acad6 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -610,6 +610,17 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%Length = L p%ElemProps(i)%DirCos = DirCos + ! Init to excessive values to detect any issue + p%ElemProps(i)%Ixx = -9.99e+36 + p%ElemProps(i)%Iyy = -9.99e+36 + p%ElemProps(i)%Jzz = -9.99e+36 + p%ElemProps(i)%Kappa = -9.99e+36 + p%ElemProps(i)%YoungE = -9.99e+36 + p%ElemProps(i)%ShearG = -9.99e+36 + p%ElemProps(i)%Area = -9.99e+36 + p%ElemProps(i)%Rho = -9.99e+36 + p%ElemProps(i)%T0 = -9.99e+36 + ! --- Properties that are specific to some elements if (eType==idBeam) then E = Init%PropsB(P1, 2) @@ -870,7 +881,7 @@ SUBROUTINE ElemF(ep, gravity, Fg, Fo) if (ep%eType==idBeam) then Fo(1:12)=0 else if (ep%eType==idCable) then - CALL ElemF_Cable(ep%Area, ep%Length, ep%T0 , ep%DirCos, Fo) + CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) else if (ep%eType==idRigid) then Fo(1:12)=0 endif @@ -1184,14 +1195,11 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) END SUBROUTINE ElemG !> -SUBROUTINE ElemF_Cable(A, L, T0, DirCos, F) - REAL(ReKi), INTENT( IN ) :: A !< area - REAL(ReKi), INTENT( IN ) :: L !< element length +SUBROUTINE ElemF_Cable(T0, DirCos, F) REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. ! Local variables - REAL(ReKi) :: L0, Eps0, EAL0, EE REAL(ReKi) :: DC(12, 12) F(1:12) = 0 ! init diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index e3f7e74b5..aafe5d76e 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -312,7 +312,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg TYPE(SD_InputType), INTENT( IN ) :: u ! SubDyn module's input data TYPE(SD_ContinuousStateType), INTENT( IN ) :: x ! SubDyn module's states data TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + TYPE(SD_ParameterType), target,INTENT( IN ) :: p ! SubDyn module's parameter data TYPE(SD_MiscVarType), INTENT( INOUT ) :: m ! Misc/optimization variables REAL(ReKi), INTENT( OUT ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation @@ -331,6 +331,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Real(reKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs Real(ReKi), DIMENSION(p%URbarL+p%DOFL+6*p%Nreact) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs Integer(IntKi) ::sgn !+1/-1 for node force calculations + type(MeshAuxDataType), pointer :: pLst ErrStat = ErrID_None ErrMsg = "" @@ -356,11 +357,12 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 DO I=1,p%NMOutputs !I know el # and whether it is 1st node or second node - DO J=1,p%MOutLst(I)%NOutCnt !Iterate on requested nodes for that member + pLst=>p%MOutLst(I) + DO J=1,pLst%NOutCnt !Iterate on requested nodes for that member !I need to average across potentially up to 2 elements !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second - K = p%MOutLst(I)%ElmIDs(J,1) !element number - K2= p%MOutLst(I)%ElmNds(J,1) !first or second node of the element to be considered + K = pLst%ElmIDs(J,1) !element number + K2= pLst%ElmNds(J,1) !first or second node of the element to be considered !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 @@ -376,24 +378,22 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) Tmp_y2(1: 6) = yout( L : L+5 ) Tmp_y2(7:12) = yout( L2 : L2+5 ) - CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst(I)%Me(:,:,J,1),p%MOutLst(I)%Ke(:,:,J,1),Tmp_Udotdot, & - Tmp_y2,p%MOutLst(I)%Fg(:,J,1), K2,FM_elm,FK_elm) + CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,J,1),pLst%Ke(:,:,J,1),Tmp_Udotdot, Tmp_y2,pLst%Fg(:,J,1), K2,FM_elm,FK_elm) FM_elm2=sgn*FM_elm FK_elm2=sgn*FK_elm IF (p%MOutLst(I)%ElmIDs(J,p%NavgEls) .NE. 0) THEN !element number - K = p%MOutLst(I)%ElmIDs(J,p%NavgEls) !element number - K2 = p%MOutLst(I)%ElmNds(J,p%NavgEls) !first or second node of the element to be considered + K = pLst%ElmIDs(J,p%NavgEls) !element number + K2 = pLst%ElmNds(J,p%NavgEls) !first or second node of the element to be considered !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 K3=p%Elems(K,2:3) !first and second node ID associated with element K - L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - CALL CALC_NODE_FORCES(DIRCOS,p%MOutLst(I)%Me(:,:,J,p%NavgEls),p%MOutLst(I)%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst(I)%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) + CALL CALC_NODE_FORCES(DIRCOS,pLst%Me(:,:,J,p%NavgEls),pLst%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average @@ -417,11 +417,12 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ENDDO ! I, Loop on member outputs END IF - IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES - DO I=1,p%NMembers !Cycle on all members - DO J=1,2 !Iterate on requested nodes for that member (first and last) - K=p%MOutLst2(I)%ElmID2s(J) !element number - K2=p%MOutLst2(I)%ElmNd2s(J) !first or second node of the element to be considered + IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES + DO I=1,p%NMembers !Cycle on all members + pLst=>p%MOutLst2(I) + DO J=1,2 !Iterate on requested nodes for that member (first and last) + K =pLst%ElmID2s(J) !element number + K2=pLst%ElmNd2s(J) !first or second node of the element to be considered !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 @@ -429,8 +430,8 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst2(I)%Me2(:,:,J),p%MOutLst2(I)%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst2(I)%Fg2(:,J), K2,FM_elm,FK_elm) + CALL CALC_NODE_FORCES( DIRCOS, pLst%Me2(:,:,J),pLst%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg2(:,J), K2,FM_elm,FK_elm) ! Store in All Outs L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index L2=L+11 @@ -469,22 +470,19 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ReactNs = 0.0 !Initialize DO I=1,p%NReact !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh - - FK_elm2=0. !Initialize + FK_elm2=0. !Initialize for cumulative force FM_elm2=0. !Initialize - + pLst => p%MOutLst3(I) !Find the joint forces - DO J=1,SIZE(p%MOutLst3(I)%ElmIDs(1,:)) !for all the elements connected (normally 1) - K = p%MOutLst3(I)%ElmIDs(1,J) ! element number - K2 = p%MOutLst3(I)%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node - K3=p%Elems(K,2:3) !first and second node ID associated with element K - L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order - L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout + DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) + K = pLst%ElmIDs(1,J) ! element number + K2 = pLst%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered + K3 = p%Elems(K,2:3) !first and second node ID associated with element K + L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order + L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - - CALL CALC_NODE_FORCES( DIRCOS,p%MOutLst3(I)%Me(:,:,1,J),p%MOutLst3(I)%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), p%MOutLst3(I)%Fg(:,1,J), K2,FM_elm,FK_elm) + CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,1,J),pLst%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,1,J), K2,FM_elm,FK_elm) !transform back to global, need to do 3 at a time since cosine matrix is 3x3 DO L=1,2 FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF From ef1730f008ee7db8b68c2447619f26afbe803359 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 6 Dec 2019 11:25:28 -0700 Subject: [PATCH 063/377] FlexSub: removing '2' arrays --- modules/subdyn/src/SubDyn_Output.f90 | 33 ++++++---- modules/subdyn/src/SubDyn_Registry.txt | 5 -- modules/subdyn/src/SubDyn_Types.f90 | 90 -------------------------- 3 files changed, 19 insertions(+), 109 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index aafe5d76e..0d5958feb 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -142,14 +142,19 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init' DO I=1,p%NMembers + CALL AllocAry(p%MOutLst2(I)%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst2(I)%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst2(I)%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst2(I)%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst2(I)%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(p%MOutLst2(I)%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return p%MOutLst2(I)%MemberID=I !Assign memberID for all members - CALL AllocAry(p%MOutLst2(I)%NodeIDs, Init%Ndiv+1 , 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return p%MOutLst2(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member !Now I need to find out which elements are attached to those nodes and still belong to the member I - !ElmID2s could contain the same element twice if Ndiv=1 - p%MOutLst2(I)%ElmID2s=0 !Initialize to 0 + !ElmIDs could contain the same element twice if Ndiv=1 + p%MOutLst2(I)%ElmIDs=0 !Initialize to 0 DO J=1,Init%Ndiv+1,Init%Ndiv !Iterate on requested nodes for that member (first and last) !I need to get at most 2 elements that belong to the same I Member @@ -167,14 +172,14 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF (M(1) .EQ. p%MOutLst2(I)%NodeIDs(J)) Junk=M(2) IF (ANY(Init%MemberNodes(p%MOutLst2(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member - p%MOutLst2(I)%ElmID2s(K2)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for - p%MOutLst2(I)%ElmNd2s(K2)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MOutLst2(I)%NodeIDs(J) ) p%MOutLst2(I)%ElmNd2s(K2)=2 !store whether first or second node of element + p%MOutLst2(I)%ElmIDs(K2,1)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for + p%MOutLst2(I)%ElmNds(K2,1)=1 !store whether first or second node of element + IF (M(2) .EQ. p%MOutLst2(I)%NodeIDs(J) ) p%MOutLst2(I)%ElmNds(K2,1)=2 !store whether first or second node of element ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), p%MOutLst2(I)%Me2(:,:,K2)) - CALL ElemK(p%ElemProps(L), p%MOutLst2(I)%Ke2(:,:,K2)) - CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst2(I)%Fg2(:,K2), FCe) - p%MOutLst2(I)%Fg2(:,K2) = p%MOutLst2(I)%Fg2(:,K2) + FCe(1:12) ! Adding cable element force + CALL ElemM(p%ElemProps(L), p%MOutLst2(I)%Me(:,:,K2, 1)) + CALL ElemK(p%ElemProps(L), p%MOutLst2(I)%Ke(:,:,K2, 1)) + CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst2(I)%Fg(:,K2,1), FCe) + p%MOutLst2(I)%Fg(:,K2,1) = p%MOutLst2(I)%Fg(:,K2,1) + FCe(1:12) ! Adding cable element force EXIT !We found the element for that node, exit loop on elements ENDIF @@ -421,8 +426,8 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg DO I=1,p%NMembers !Cycle on all members pLst=>p%MOutLst2(I) DO J=1,2 !Iterate on requested nodes for that member (first and last) - K =pLst%ElmID2s(J) !element number - K2=pLst%ElmNd2s(J) !first or second node of the element to be considered + K =pLst%ElmIDs(J,1) !element number + K2=pLst%ElmNds(J,1) !first or second node of the element to be considered !Assign the sign depending on whether it is the 1st or second node sgn=-1 IF (K2 .EQ. 2) sgn= +1 @@ -430,8 +435,8 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS, pLst%Me2(:,:,J),pLst%Ke2(:,:,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg2(:,J), K2,FM_elm,FK_elm) + CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,J,1),pLst%Ke(:,:,J,1),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,J,1), K2,FM_elm,FK_elm) ! Store in All Outs L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index L2=L+11 diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 7da019794..06b6bc449 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -29,14 +29,9 @@ typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" -typedef ^ MeshAuxDataType INTEGER ElmID2s {2} - - "Element IDs connected to each joint node" -typedef ^ MeshAuxDataType INTEGER ElmNd2s {2} - - Flag to indicate 1st or 2nd node of element which is attached to "member joint (for outAll)" typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" -typedef ^ MeshAuxDataType ReKi Me2 {12}{12}{2} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Ke2 {12}{12}{2} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Fg2 {12}{2} - - "Gravity load vector connected to each joint element for outAll output" # CB_MatArrays: Matrices and arrays for CB summary typedef SubDyn/SD CB_MatArrays INTEGER DOFM - - - "retained degrees of freedom (modes)" typedef ^ CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index bdd7c1fbe..509da2b38 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -58,14 +58,9 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIDs !< Node IDs associated with ordinal numbers for the output member [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmIDs !< Element IDs connected to each NodeIDs; max 10 elements [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmNds !< Flag to indicate 1st or 2nd node of element for each ElmIDs [-] - INTEGER(IntKi) , DIMENSION(1:2) :: ElmID2s !< Element IDs connected to each joint node [-] - INTEGER(IntKi) , DIMENSION(1:2) :: ElmNd2s !< Flag [to] REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] - REAL(ReKi) , DIMENSION(1:12,1:12,1:2) :: Me2 !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(1:12,1:12,1:2) :: Ke2 !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(1:12,1:2) :: Fg2 !< Gravity load vector connected to each joint element for outAll output [-] END TYPE MeshAuxDataType ! ======================= ! ========= CB_MatArrays ======= @@ -885,8 +880,6 @@ SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeDat END IF DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds ENDIF - DstMeshAuxDataTypeData%ElmID2s = SrcMeshAuxDataTypeData%ElmID2s - DstMeshAuxDataTypeData%ElmNd2s = SrcMeshAuxDataTypeData%ElmNd2s IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) @@ -939,9 +932,6 @@ SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeDat END IF DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg ENDIF - DstMeshAuxDataTypeData%Me2 = SrcMeshAuxDataTypeData%Me2 - DstMeshAuxDataTypeData%Ke2 = SrcMeshAuxDataTypeData%Ke2 - DstMeshAuxDataTypeData%Fg2 = SrcMeshAuxDataTypeData%Fg2 END SUBROUTINE SD_CopyMeshAuxDataType SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) @@ -1033,8 +1023,6 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds END IF - Int_BufSz = Int_BufSz + SIZE(InData%ElmID2s) ! ElmID2s - Int_BufSz = Int_BufSz + SIZE(InData%ElmNd2s) ! ElmNd2s Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no IF ( ALLOCATED(InData%Me) ) THEN Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension @@ -1050,9 +1038,6 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%Fg) ! Fg END IF - Re_BufSz = Re_BufSz + SIZE(InData%Me2) ! Me2 - Re_BufSz = Re_BufSz + SIZE(InData%Ke2) ! Ke2 - Re_BufSz = Re_BufSz + SIZE(InData%Fg2) ! Fg2 IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1142,10 +1127,6 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IF (SIZE(InData%ElmNds)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmNds))-1 ) = PACK(InData%ElmNds,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%ElmNds) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmID2s))-1 ) = PACK(InData%ElmID2s,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElmID2s) - IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmNd2s))-1 ) = PACK(InData%ElmNd2s,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElmNd2s) IF ( .NOT. ALLOCATED(InData%Me) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1209,12 +1190,6 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IF (SIZE(InData%Fg)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fg))-1 ) = PACK(InData%Fg,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%Fg) END IF - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Me2))-1 ) = PACK(InData%Me2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Me2) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ke2))-1 ) = PACK(InData%Ke2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Ke2) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fg2))-1 ) = PACK(InData%Fg2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fg2) END SUBROUTINE SD_PackMeshAuxDataType SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1355,28 +1330,6 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = Int_Xferred + SIZE(OutData%ElmNds) DEALLOCATE(mask2) END IF - i1_l = LBOUND(OutData%ElmID2s,1) - i1_u = UBOUND(OutData%ElmID2s,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%ElmID2s = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmID2s))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElmID2s) - DEALLOCATE(mask1) - i1_l = LBOUND(OutData%ElmNd2s,1) - i1_u = UBOUND(OutData%ElmNd2s,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%ElmNd2s = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmNd2s))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElmNd2s) - DEALLOCATE(mask1) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -1470,49 +1423,6 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + SIZE(OutData%Fg) DEALLOCATE(mask3) END IF - i1_l = LBOUND(OutData%Me2,1) - i1_u = UBOUND(OutData%Me2,1) - i2_l = LBOUND(OutData%Me2,2) - i2_u = UBOUND(OutData%Me2,2) - i3_l = LBOUND(OutData%Me2,3) - i3_u = UBOUND(OutData%Me2,3) - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - OutData%Me2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Me2))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Me2) - DEALLOCATE(mask3) - i1_l = LBOUND(OutData%Ke2,1) - i1_u = UBOUND(OutData%Ke2,1) - i2_l = LBOUND(OutData%Ke2,2) - i2_u = UBOUND(OutData%Ke2,2) - i3_l = LBOUND(OutData%Ke2,3) - i3_u = UBOUND(OutData%Ke2,3) - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - OutData%Ke2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ke2))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Ke2) - DEALLOCATE(mask3) - i1_l = LBOUND(OutData%Fg2,1) - i1_u = UBOUND(OutData%Fg2,1) - i2_l = LBOUND(OutData%Fg2,2) - i2_u = UBOUND(OutData%Fg2,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%Fg2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fg2))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fg2) - DEALLOCATE(mask2) END SUBROUTINE SD_UnPackMeshAuxDataType SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) From c1070767e910dd58844944a179b981e20a084823 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 6 Dec 2019 11:37:50 -0700 Subject: [PATCH 064/377] FlexSub: more aliasing --- modules/subdyn/src/SubDyn_Output.f90 | 152 +++++++++++++-------------- 1 file changed, 72 insertions(+), 80 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 0d5958feb..cccc8537d 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -47,21 +47,21 @@ MODULE SubDyn_Output !> This subroutine initializes the output module, checking if the output parameter list (OutList) ! contains valid names, and opening the output file if there are any requested outputs SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module - TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module paramters - TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables - TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data - REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module + TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data + TYPE(SD_ParameterType), target, INTENT( INOUT ) :: p ! SubDyn module paramters + TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables + TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data + REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables INTEGER(IntKi) :: ErrStat2 ! Error status of the operation CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters INTEGER(IntKi) :: Junk !Temporary Holders INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time - INTEGER(IntKi) :: eType + type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities REAL(ReKi) :: FCe(12) ! Pretension force from cable element ErrStat = 0 ErrMsg="" @@ -86,49 +86,47 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return DO I=1,p%NMOutputs - CALL AllocAry(p%MOutLst(I)%NodeIDs, p%MOutLst(I)%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%ElmIDs, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%ElmNds, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Me, 12, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Ke, 12, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst(I)%Fg, 12, p%MOutLst(I)%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - p%MOutLst(I)%NodeIDs=Init%MemberNodes(p%MOutLst(I)%MemberID,p%MOutLst(I)%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting - p%MOutLst(I)%ElmIDs=0 !Initialize to 0 - p%MOutLst(I)%ElmNds=0 !Initialize to 0 - - DO J=1,p%MOutLst(I)%NoutCnt !Iterate on requested nodes for that member + pLst => p%MOutLst(I) + CALL AllocAry(pLst%NodeIDs, pLst%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + + pLst%NodeIDs=Init%MemberNodes(pLst%MemberID,pLst%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting + pLst%ElmIDs=0 !Initialize to 0 + pLst%ElmNds=0 !Initialize to 0 + + DO J=1,pLst%NoutCnt !Iterate on requested nodes for that member !I need to get at most 2 elements that belong to the same MOutLst(I)%MemberID !make use of MemberNodes and NodesConnE - NconEls=Init%NodesConnE(p%MOutLst(I)%NodeIDs(J),1)!Number of elements connecting to the j-th node + NconEls=Init%NodesConnE(pLst%NodeIDs(J),1)!Number of elements connecting to the j-th node K2=0 !Initialize counter DO K=1, NconEls - L=Init%NodesConnE(p%MOutLst(I)%NodeIDs(J),k+1) !k-th Element Number + L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number M = p%Elems(L,2:3) !1st and 2nd node of the k-th element - eType = p%Elems(L, iMType) - !Select only the other node, not the one where elements connect to - IF (M(1) .EQ. p%MOutLst(I)%NodeIDs(J)) then + IF (M(1) .EQ. pLst%NodeIDs(J)) then Junk=M(2) else Junk=M(1) endif - - IF (ANY(Init%MemberNodes(p%MOutLst(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + IF (ANY(Init%MemberNodes(pLst%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member IF (K2 .EQ. 2) EXIT K2=K2+1 - p%MOutLst(I)%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 - IF (M(2) .EQ. p%MOutLst(I)%NodeIDs(J) )then - p%MOutLst(I)%ElmNds(J,K2)=2 !store whether first or second node of element + pLst%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 + IF (M(2) .EQ. pLst%NodeIDs(J) )then + pLst%ElmNds(J,K2)=2 !store whether first or second node of element else - p%MOutLst(I)%ElmNds(J,K2)=1 !store whether first or second node of element + pLst%ElmNds(J,K2)=1 !store whether first or second node of element endif ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), p%MOutLst(I)%Me(:,:,J,K2)) - CALL ElemK(p%ElemProps(L), p%MOutLst(I)%Ke(:,:,J,K2)) - CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst(I)%Fg(:,J,K2), FCe) - p%MOutLst(I)%Fg(:,J,K2) = p%MOutLst(I)%Fg(:,J,K2) + FCe(1:12) ! Adding cable element force + CALL ElemM(p%ElemProps(L), pLst%Me(:,:,J,K2)) + CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,J,K2)) + CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,J,K2), FCe) + pLst%Fg(:,J,K2) = pLst%Fg(:,J,K2) + FCe(1:12) ! Adding cable element force END IF ENDDO ! K, NconEls ENDDO !J, Noutcnt @@ -142,45 +140,38 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init' DO I=1,p%NMembers - CALL AllocAry(p%MOutLst2(I)%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst2(I)%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst2(I)%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst2(I)%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst2(I)%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst2(I)%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - p%MOutLst2(I)%MemberID=I !Assign memberID for all members - p%MOutLst2(I)%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member - + pLst => p%MOutLst2(I) + CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + pLst%MemberID=I !Assign memberID for all members + pLst%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member !Now I need to find out which elements are attached to those nodes and still belong to the member I !ElmIDs could contain the same element twice if Ndiv=1 - p%MOutLst2(I)%ElmIDs=0 !Initialize to 0 - + pLst%ElmIDs=0 !Initialize to 0 DO J=1,Init%Ndiv+1,Init%Ndiv !Iterate on requested nodes for that member (first and last) !I need to get at most 2 elements that belong to the same I Member !make use of MemberNodes and NodesConnE - - NconEls=Init%NodesConnE(p%MOutLst2(I)%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member - + NconEls=Init%NodesConnE(pLst%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member K2= J/(Init%Ndiv+1)+1 !store this quantity used later, basically 1 or 2 depending on J - DO K=1, NconEls - L=Init%NodesConnE(p%MOutLst2(I)%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node + L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node M=p%Elems(L,2:3) !1st and 2nd node of the k-th element !Select only the other node, not the one where elements connect to Junk=M(1) - IF (M(1) .EQ. p%MOutLst2(I)%NodeIDs(J)) Junk=M(2) - - IF (ANY(Init%MemberNodes(p%MOutLst2(I)%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member - p%MOutLst2(I)%ElmIDs(K2,1)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for - p%MOutLst2(I)%ElmNds(K2,1)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MOutLst2(I)%NodeIDs(J) ) p%MOutLst2(I)%ElmNds(K2,1)=2 !store whether first or second node of element + IF (M(1) .EQ. pLst%NodeIDs(J)) Junk=M(2) + IF (ANY(Init%MemberNodes(pLst%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + pLst%ElmIDs(K2,1)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for + pLst%ElmNds(K2,1)=1 !store whether first or second node of element + IF (M(2) .EQ. pLst%NodeIDs(J) ) pLst%ElmNds(K2,1)=2 !store whether first or second node of element ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), p%MOutLst2(I)%Me(:,:,K2, 1)) - CALL ElemK(p%ElemProps(L), p%MOutLst2(I)%Ke(:,:,K2, 1)) - CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst2(I)%Fg(:,K2,1), FCe) - p%MOutLst2(I)%Fg(:,K2,1) = p%MOutLst2(I)%Fg(:,K2,1) + FCe(1:12) ! Adding cable element force - + CALL ElemM(p%ElemProps(L), pLst%Me(:,:,K2, 1)) + CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,K2, 1)) + CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,K2,1), FCe) + pLst%Fg(:,K2,1) = pLst%Fg(:,K2,1) + FCe(1:12) ! Adding cable element force EXIT !We found the element for that node, exit loop on elements ENDIF ENDDO @@ -203,29 +194,30 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) if(Failed()) return DO I=1,p%NReact !For all constrained node - p%MOutLst3(I)%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array - NconEls=Init%NodesConnE(p%MOutLst3(I)%Noutcnt,1) !Number of elements connecting to the joint + pLst => p%MOutLst3(I) + pLst%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array + NconEls=Init%NodesConnE(pLst%Noutcnt,1) !Number of elements connecting to the joint ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other MOutLst ! Me: has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) ! Ke: has for each selected joint, and for each element attached to that node a 12x12 matrix - CALL AllocAry(p%MOutLst3(I)%ElmIDs, 1, NconEls, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst3(I)%ElmNds, 1, NconEls, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst3(I)%Me, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst3(I)%Ke, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(p%MOutLst3(I)%Fg, 12 , 1, NconEls, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, 1, NconEls, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 1, NconEls, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12 , 1, NconEls, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return DO K=1, NconEls - L=Init%NodesConnE(p%MOutLst3(I)%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node - p%MOutLst3(I)%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for + L=Init%NodesConnE(pLst%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node + pLst%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for M=p%Elems(L,2:3) !1st and 2nd node of the k-th element !Select whether the joint is the 1st or second node of the element - p%MOutLst3(I)%ElmNds(1,K)=1 !store whether first or second node of element - IF (M(2) .EQ. p%MOutLst3(I)%Noutcnt ) p%MOutLst3(I)%ElmNds(1,K)=2 !store whether first or second node of element + pLst%ElmNds(1,K)=1 !store whether first or second node of element + IF (M(2) .EQ. pLst%Noutcnt ) pLst%ElmNds(1,K)=2 !store whether first or second node of element ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), p%MOutLst3(I)%Me(:,:,1,K)) - CALL ElemK(p%ElemProps(L), p%MOutLst3(I)%Ke(:,:,1,K)) - CALL ElemF(p%ElemProps(L), Init%g, p%MOutLst3(I)%Fg(:,1,K), FCe) - p%MOutLst3(I)%Fg(:,1,K) = p%MOutLst3(I)%Fg(:,1,K) + FCe(1:12) ! Adding cable element force + CALL ElemM(p%ElemProps(L), pLst%Me(:,:,1,K)) + CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,1,K)) + CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,1,K), FCe) + pLst%Fg(:,1,K) = pLst%Fg(:,1,K) + FCe(1:12) ! Adding cable element force ENDDO ENDDO !Store the matrix that will let me calculate single point reaction at the base of structure @@ -336,7 +328,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Real(reKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs Real(ReKi), DIMENSION(p%URbarL+p%DOFL+6*p%Nreact) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs Integer(IntKi) ::sgn !+1/-1 for node force calculations - type(MeshAuxDataType), pointer :: pLst + type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities ErrStat = ErrID_None ErrMsg = "" From b3f94b23bbc8ddc60292b2091725b70099c56106 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 09:42:03 -0700 Subject: [PATCH 065/377] FlexSub: fixed summary file formatting issue --- modules/subdyn/src/SubDyn.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 96f0dd804..f21143450 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2632,8 +2632,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem - WRITE(UnSum, '(A8,5(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Type', 'Prop_I', 'Prop_J' - WRITE(UnSum, '(I8,5(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) + WRITE(UnSum, '(A10,5(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Type', 'Prop_I', 'Prop_J' + WRITE(UnSum, '(6(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NPropB From fa535fdf6c45cb423ea2fa1211c89ae92b4911a0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 10:06:10 -0700 Subject: [PATCH 066/377] FlexSub: renamed ids, and implemented nDOFUnconstrained --- modules/subdyn/src/SD_FEM.f90 | 94 +++++++++++++++++++++-------------- modules/subdyn/src/SubDyn.f90 | 4 +- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 91c6acad6..610c69455 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -50,15 +50,15 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored ! ID for joint types - INTEGER(IntKi), PARAMETER :: idCantilever = 1 - INTEGER(IntKi), PARAMETER :: idUniversal = 2 - INTEGER(IntKi), PARAMETER :: idPin = 3 - INTEGER(IntKi), PARAMETER :: idBall = 4 + INTEGER(IntKi), PARAMETER :: idJointCantilever = 1 + INTEGER(IntKi), PARAMETER :: idJointUniversal = 2 + INTEGER(IntKi), PARAMETER :: idJointPin = 3 + INTEGER(IntKi), PARAMETER :: idJointBall = 4 ! ID for member types - INTEGER(IntKi), PARAMETER :: idBeam = 1 - INTEGER(IntKi), PARAMETER :: idCable = 2 - INTEGER(IntKi), PARAMETER :: idRigid = 3 + INTEGER(IntKi), PARAMETER :: idMemberBeam = 1 + INTEGER(IntKi), PARAMETER :: idMemberCable = 2 + INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) @@ -146,12 +146,10 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return ! --- Initialize Nodes - Init%Nodes = 0 + Init%Nodes = -999999 ! Init to unphysical values do I = 1,Init%NJoints - Init%Nodes(I, 1) = I ! JointID replaced by index I - Init%Nodes(I, 2) = Init%Joints(I, 2) - Init%Nodes(I, 3) = Init%Joints(I, 3) - Init%Nodes(I, 4) = Init%Joints(I, 4) + Init%Nodes(I, 1) = I ! JointID replaced by index I + Init%Nodes(I, 2:JointsCol) = Init%Joints(I, 2:JointsCol) ! All the rest is copied enddo ! --- Re-Initialize Reactions, pointing to index instead of JointID @@ -206,13 +204,13 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) ! NOTE: this index has different meaning depending on the member type ! DO n=iMProp,iMProp+1 - if (mType==idBeam) then + if (mType==idMemberBeam) then sType='Member x-section property' p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) - else if (mType==idCable) then + else if (mType==idMemberCable) then sType='Cable property' p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) - else if (mType==idRigid) then + else if (mType==idMemberRigid) then sType='Rigid property' p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) else @@ -342,7 +340,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) RETURN ENDIF - if (eType/=idBeam) then + if (eType/=idMemberBeam) then ! --- Cables and rigid links are not subdivided ! No need to create new properties or new nodes print*,'Member',I, 'not subdivided since it is not a beam. Looping through.' @@ -393,7 +391,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! node connect to Node1 knode = knode + 1 Init%MemberNodes(I, 2) = knode - CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) + CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) ! Set Init%Nodes(knode,:) IF ( CreateNewProp ) THEN ! create a new property set @@ -414,7 +412,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) knode = knode + 1 Init%MemberNodes(I, J+1) = knode - CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) + CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) ! Set Init%Nodes(knode,:) IF ( CreateNewProp ) THEN ! create a new property set @@ -525,10 +523,15 @@ SUBROUTINE SetNewNode(k, x, y, z, Init) INTEGER, INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: x, y, z - Init%Nodes(k, 1) = k - Init%Nodes(k, 2) = x - Init%Nodes(k, 3) = y - Init%Nodes(k, 4) = z + Init%Nodes(k, 1) = k + Init%Nodes(k, 2) = x + Init%Nodes(k, 3) = y + Init%Nodes(k, 4) = z + Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever + ! Properties below are for non-cantilever joints + Init%Nodes(k, iJointDir:iJointDir+2) = -99999 + Init%Nodes(k, iJointStiff) = -99999 + Init%Nodes(k, iJointDamp) = -99999 END SUBROUTINE SetNewNode @@ -622,7 +625,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%T0 = -9.99e+36 ! --- Properties that are specific to some elements - if (eType==idBeam) then + if (eType==idMemberBeam) then E = Init%PropsB(P1, 2) G = Init%PropsB(P1, 3) rho = Init%PropsB(P1, 4) @@ -667,14 +670,14 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%Area = A p%ElemProps(i)%Rho = rho - else if (eType==idCable) then + else if (eType==idMemberCable) then print*,'Member',I,'eType',eType,'Ps',P1,P2 p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] - else if (eType==idRigid) then + else if (eType==idMemberRigid) then print*,'Member',I,'eType',eType,'Ps',P1,P2 p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 p%ElemProps(i)%Rho = Init%PropsR(P1, 2) @@ -709,9 +712,14 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) CHARACTER(1024) :: ErrMsg2 ErrMsg = "" ErrStat = ErrID_None + + + + - ! total degrees of freedom of the system - Init%TDOF = 6*Init%NNode + ! total unconstrained degrees of freedom of the system + Init%TDOF = nDOF_Unconstrained() + print*,'nDOF_unconstrained',Init%TDOF, 6*Init%NNode CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix @@ -778,6 +786,20 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_AssembleKM() !pass END SUBROUTINE CleanUp_AssembleKM + + INTEGER(IntKi) FUNCTION nDOF_Unconstrained() + integer(IntKi) :: i + integer(IntKi) :: m + nDOF_Unconstrained=0 + do i = 1,Init%NNode + if (Init%Nodes(i,iJointType) == idJointCantilever ) then + nDOF_Unconstrained = nDOF_Unconstrained + 6 + else + m = Init%NodesConnE(i,1) ! Col1: number of elements connected to this joint + nDOF_Unconstrained = nDOF_Unconstrained + 3 + 3*m + endif + end do + END FUNCTION END SUBROUTINE AssembleKM @@ -840,14 +862,14 @@ END SUBROUTINE GetDirCos SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(ReKi), INTENT(OUT) :: Me(12, 12) - if (ep%eType==idBeam) then + if (ep%eType==idMemberBeam) then !Calculate Ke, Me to be used for output CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) - else if (ep%eType==idCable) then + else if (ep%eType==idMemberCable) then CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) - else if (ep%eType==idRigid) then + else if (ep%eType==idMemberRigid) then if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then Me=0.0_ReKi else @@ -862,13 +884,13 @@ SUBROUTINE ElemK(ep, Ke) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(ReKi), INTENT(OUT) :: Ke(12, 12) - if (ep%eType==idBeam) then + if (ep%eType==idMemberBeam) then CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) - else if (ep%eType==idCable) then + else if (ep%eType==idMemberCable) then CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) - else if (ep%eType==idRigid) then + else if (ep%eType==idMemberRigid) then Ke = 0.0_ReKi endif END SUBROUTINE ElemK @@ -878,11 +900,11 @@ SUBROUTINE ElemF(ep, gravity, Fg, Fo) REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity REAL(ReKi), INTENT(OUT) :: Fg(12) REAL(ReKi), INTENT(OUT) :: Fo(12) - if (ep%eType==idBeam) then + if (ep%eType==idMemberBeam) then Fo(1:12)=0 - else if (ep%eType==idCable) then + else if (ep%eType==idMemberCable) then CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) - else if (ep%eType==idRigid) then + else if (ep%eType==idMemberRigid) then Fo(1:12)=0 endif CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f21143450..ee48797f9 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -887,7 +887,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' print*,' Look at the SubDyn API changes to adapt your input files.' print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - Init%Joints(:,iJointType) = idCantilever ! All joints assumed cantilever + Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 else @@ -944,7 +944,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%Members(:,:) = 0.0_ReKi if (LegacyFormat) then nColumns = 5 - Init%Members(:,iMType) = idBeam ! Important, in legacy all members are beams + Init%Members(:,iMType) = idMemberBeam ! Important, in legacy all members are beams else nColumns = MembersCol endif From edd147b307e5164cac166db0bbd3851b97ace31b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 12:04:58 -0700 Subject: [PATCH 067/377] FlexSub: introducing IntegerList and corresponding unittests --- modules/subdyn/CMakeLists.txt | 2 + modules/subdyn/src/IntegerList.f90 | 270 +++++++++++++++++++++++++ modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src/SubDyn.f90 | 4 + modules/subdyn/src/SubDyn_Registry.txt | 5 + modules/subdyn/src/SubDyn_Tests.f90 | 180 +++++++++++++++++ modules/subdyn/src/SubDyn_Types.f90 | 200 +++++++++++++++++- 7 files changed, 656 insertions(+), 7 deletions(-) create mode 100644 modules/subdyn/src/IntegerList.f90 create mode 100644 modules/subdyn/src/SubDyn_Tests.f90 diff --git a/modules/subdyn/CMakeLists.txt b/modules/subdyn/CMakeLists.txt index 12bf2ae5e..61afff133 100644 --- a/modules/subdyn/CMakeLists.txt +++ b/modules/subdyn/CMakeLists.txt @@ -24,6 +24,8 @@ set(SUBDYN_SOURCES src/SubDyn_Output.f90 src/SubDyn_Output_Params.f90 src/qsort_c_module.f90 + src/SubDyn_Tests.f90 + src/IntegerList.f90 src/SubDyn_Types.f90 ) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 new file mode 100644 index 000000000..d08c698f9 --- /dev/null +++ b/modules/subdyn/src/IntegerList.f90 @@ -0,0 +1,270 @@ +!> Module providing suport for an integer list stored as an array and not a chained list +!! Used since registry does not support pointer with recursive types. +module IntegerList + use SubDyn_Types, only: IList + use NWTC_Library, only: IntKi, ReKi, AllocAry, ErrID_None, ErrID_Fatal, num2lstr + + implicit none + + public :: IList + + public :: init + public :: len + public :: append + public :: pop + public :: get + public :: find + public :: sort + public :: reverse +contains + + !> Initialize an integer list + subroutine init(L,n,default_val,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), intent(in) :: n !< number of initial values + integer(IntKi), intent(in) :: default_val !< default values + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + + call AllocAry(L%List, n, 'L%List', ErrStat, ErrMsg) + if (ErrStat/=ErrID_None) return + L%List(1:n) = default_val + + end subroutine init + + !> Returns list length + integer function len(L) + type(IList), intent(in) :: L + if (allocated(L%List)) then + len=size(L%List) + else + len=0 + endif + end function len + + !> Append element to list + subroutine append(L,e, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: e + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) then + call resize_array(L%List,len(L)+1,e) + else + call init(L, 1, e, ErrStat, ErrMsg) + endif + end subroutine append + + !> Get element i from list + integer function get(L,i, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: i + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + if ((i<=0).or.(i>len(L))) then + ErrStat=ErrID_Fatal + ErrMsg="Index out of bound "//trim(num2lstr(i))//", list length is "//trim(num2lstr(len(L))) + get=-9999 + else + ErrStat = ErrID_None + ErrMsg = "" + get = L%List(i) ! No error handling, throws "index array out of bound", like a regular array + endif + end function get + + !> Pop last element of the list and reduce list size by 1 + integer function pop(L,ErrStat,ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + pop = get(L, n, ErrStat, ErrMsg) ! index array out of bound will be thrown + call resize_array(L%List,n-1,0) + end function pop + + !> Sort list + subroutine sort(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) then + call sort_in_place(L%List) + else + ErrStat=ErrID_Fatal + ErrMsg="Cannot sort a list not allocated" + endif + end subroutine sort + + !> Reverse list + subroutine reverse(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: i + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + do i =1,int(n/2) + call swap(i, n-i+1) + enddo + contains + subroutine swap(i,j) + integer(IntKi), intent(in) :: i,j + integer(IntKi) :: tmp + tmp=L%List(i) + L%List(i) = L%List(j) + L%List(j) = tmp + end + end subroutine reverse + + + !> Returns index of element e in L, returns 0 if not found + !! NOTE: list but be sorted to call this function + integer(IntKi) function find(L, e, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in ) :: e + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) then + find = binary_search(L%List, e) + else + ErrStat=ErrID_Fatal + ErrMsg="Cannot find in an unallocated list" + find=0 + endif + end function find + + !> Print + subroutine print(L, varname, u_opt) + type(IList), intent(in) :: L + character(len=*),intent(in) :: varname + integer(IntKi), intent(in),optional :: u_opt + ! + character(len=*),parameter :: IFMT='I7.0' !< + integer(IntKi) :: u + integer(IntKi) :: n + character(len=20) :: fmt + ! Optional args + if (present(u_opt)) then + u=u_opt + else + u=6 + endif + n=len(L) + if (n>0) then + write(fmt,*) n + write(u,"(A,A,"// adjustl(fmt)//IFMT//",A)") varname,"=[",L%List,"];" + else + write(u,'(A,A)') varname,'=[];' + endif + end subroutine print + + ! -------------------------------------------------------------------------------- + ! --- Generic helper functions (should be part of NWTC library) + ! -------------------------------------------------------------------------------- + !> Sort integer array in place + pure subroutine sort_in_place(a) + integer(IntKi), intent(inout), dimension(:) :: a + integer(IntKi) :: temp + integer(IntKi) :: i, j + do i = 2, size(a) + j = i - 1 + temp = a(i) + do while (j>=1 .and. a(j)>temp) + a(j+1) = a(j) + j = j - 1 + if (j<1) then + exit + endif + end do + a(j+1) = temp + end do + end subroutine sort_in_place + + !> Performs binary search and return the largest index such that x(i) <= x0 + !! allows equlity + Integer(IntKi) function binary_search(x, x0) result(i_inf) + ! Arguments declarations + integer(IntKi), dimension(:),intent(in) :: x !< x *sorted* vector + integer(IntKi), intent(in) :: x0 !< + ! Variable declarations + integer(IntKi) :: i_sup !< + integer(IntKi) :: mid !< + i_inf=1 + i_sup=size(x) + ! Safety test + if (x0=x(i_sup)) then + i_inf=i_sup + return + end if + ! We loop until we narrow down to one index + do while (i_inf+1 Resize integer array of dimension 1 + subroutine resize_array(array,nNewSize,default_val) + integer(IntKi),dimension(:),allocatable,intent(inout) :: array + integer(IntKi) , intent(in) :: nNewSize + integer(IntKi), intent(in) :: default_val + ! Local variables + integer(IntKi),dimension(:),allocatable :: tmp !< backup of input + integer(IntKi) :: nDimTmp + integer(IntKi) :: AllocateStatus + ! To save memory, if nNewSize is below second dim, we take the min + nDimTmp= min(size(array,1),nNewSize) + ! Making of copy of the input + allocate(tmp(1:nDimTmp), STAT = AllocateStatus) + if (AllocateStatus /= 0) STOP "*** Not enough memory ***" + tmp(1:nDimTmp)=array(1:nDimTmp) + ! Reallocating the array + deallocate(array) + allocate(array(1:nNewSize), STAT = AllocateStatus) + if (AllocateStatus /= 0) STOP "*** Not enough memory ***" + ! We copy the original data into it + array(1:nDimTmp)=tmp(1:nDimTmp) + if(nDimTmp+1<=nNewSize) array(nDimTmp+1:nNewSize)=default_val + end subroutine + + !> Append two integer arrays of dimension 1 + subroutine append_arrays(array1,n1,array2,n2) + integer(IntKi), dimension(:), allocatable :: array1 + integer(IntKi), dimension(:) :: array2 + integer(IntKi), intent(inout) :: n1 !< SIDE EFFECTS + integer(IntKi), intent(in) :: n2 + ! Local variables + integer :: nNew + nNew=n1+n2 + ! --- Making enough space if needed + if(nNew>size(array1,1)) then + call resize_array(array1,nNew,0) + endif + ! --- Appending + array1((n1+1):(n1+n2))=array2(1:n2) + ! updating n1 + n1=n1+n2; + end subroutine + +end module IntegerList diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 610c69455..fb5be8676 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -23,7 +23,7 @@ MODULE SD_FEM INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors - INTEGER(IntKi), PARAMETER :: MaxMemjnt = 10 ! Maximum number of members at one joint + INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ee48797f9..14eac8a6d 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -27,6 +27,7 @@ Module SubDyn USE NWTC_LAPACK USE SubDyn_Types USE SubDyn_Output + USE SubDyn_Tests USE SD_FEM IMPLICIT NONE @@ -282,6 +283,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Display the module information CALL DispNVD( SD_ProgDesc ) InitOut%Ver = SD_ProgDesc + + ! --- Test + CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return ! transfer glue-code information to data structure for SubDyn initialization: Init%g = InitInput%g diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 06b6bc449..4c0e081e1 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -9,6 +9,11 @@ include Registry_NWTC_Library.txt # # Keyword ModuleName/ModName Derived data type Field type Variable name Dimemsion of the variable Initial value not used Description Units +typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" + +! integer, dimension(:), pointer :: data => null() +! type(IList), pointer :: next => null() + # ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 new file mode 100644 index 000000000..8c17624de --- /dev/null +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -0,0 +1,180 @@ +module SubDyn_Tests + use NWTC_Library + USE SubDyn_Types + USE SD_FEM + use IntegerList + + public :: SD_Tests + private + + character(len=255),save :: testname + interface test_equal; module procedure & + test_equal_i1, & + test_equal_i0 + end interface +contains + + ! -------------------------------------------------------------------------------- + ! --- Helper functions (should be part of NWTC library) + ! -------------------------------------------------------------------------------- + subroutine test_success(info,bPrint_in) + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + end subroutine + + subroutine test_fail(info,bPrint_in,bStop_in) + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + logical, intent(in), optional :: bStop_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + if(present(bStop_in)) then + if(bStop_in) then + STOP + endif + else + STOP + endif + end subroutine + + subroutine test_equal_i0(Var,iTry,iRef) + ! Arguments + character(len=*), intent(in) :: Var + integer, intent(in) :: iTry !< + integer, intent(in) :: iRef !< + ! Variables + character(len=255) :: InfoAbs + if(iRef/=iTry) then + write(InfoAbs,'(A,I0,A,I0)') trim(Var),iRef,'/',iTry + call test_fail(InfoAbs) + STOP -1 !OTHER-COMPILER + STOP ! COMPAQ-COMPILER + else + write(InfoAbs,'(A,A,I0)') trim(Var),' ok ',iRef + call test_success(InfoAbs) + endif + end subroutine + + subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + integer, dimension(:), intent(in) :: VecTry !< + integer, dimension(:), intent(in) :: VecRef !< + logical, intent(in) :: bTest + logical, intent(in) :: bPrintOnly + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + ! + cpt=0 + do i=1,size(VecRef) + if(VecRef(i)/=VecTry(i)) then + cpt=cpt+1 + endif + enddo + if(cpt>0) then + write(InfoAbs,'(A,I0)') trim(Var)//' Elements different: ',cpt + if(present(bPassed)) then + bPassed=.false. + endif + else + write(InfoAbs,'(A)') trim(Var)//' reproduced to identity' + if(present(bPassed)) then + bPassed=.true. + endif + endif + if(bPrintOnly) then + print'(A)',trim(InfoAbs) + endif + if(bTest) then + if(cpt>0) then + call test_fail(InfoAbs) + STOP -1 !OTHER-COMPILER + STOP ! COMPAQ-COMPILER + else + call test_success(InfoAbs) + endif + endif + end subroutine + + + + + ! --------------------------------------------------------------------------------} + ! --- Specific SubDyn tests + ! --------------------------------------------------------------------------------{ + subroutine Test_lists(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + type(IList) :: L1 + type(IList) :: L2 + integer(IntKi) :: e + ErrStat = ErrID_None + ErrMsg = "" + testname='Lists' + + call init(L1, 0, 0 ,ErrStat, ErrMsg) + call init(L2, 10, 12,ErrStat, ErrMsg) + + ! test len + call test_equal('length',0 ,len(L1)) + call test_equal('length',10,len(L2)) + + ! test append + call append(L1, 5, ErrStat, ErrMsg) + call append(L1, 3, ErrStat, ErrMsg) + call append(L1, 1, ErrStat, ErrMsg) + call test_equal('appnd',L1%List, (/5,3,1/) , .true. , .false.) + + ! test get + call test_equal('get ',get(L1,2, ErrStat, ErrMsg), 3) + e = get(L1,0, ErrStat, ErrMsg) + call test_equal('get <0 ', ErrStat, ErrID_Fatal) + e = get(L1,7, ErrStat, ErrMsg) + call test_equal('get >n ', ErrStat, ErrID_Fatal) + + ! test sort + call sort(L1, ErrStat, ErrMsg) + call test_equal('sort ',L1%List, (/1,3,5/) , .true. , .false.) + + ! test reverse + call reverse(L1, ErrStat, ErrMsg) + call test_equal('rev ',L1%List, (/5,3,1/) , .true. , .false.) + + ! test pop + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 1) + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 3) + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 5) + + end subroutine + + subroutine SD_Tests(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + call Test_lists(ErrStat2, ErrMsg2) + end subroutine SD_Tests + + +end module SubDyn_Tests diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 509da2b38..38c9cc4cb 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -33,6 +33,11 @@ MODULE SubDyn_Types !--------------------------------------------------------------------------------------------------------------------------------- USE NWTC_Library IMPLICIT NONE +! ========= IList ======= + TYPE, PUBLIC :: IList + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: List !< List of integers [-] + END TYPE IList +! ======================= ! ========= SD_InitInputType ======= TYPE, PUBLIC :: SD_InitInputType CHARACTER(1024) :: SDInputFile !< Name of the input file [-] @@ -277,9 +282,9 @@ MODULE SubDyn_Types END TYPE SD_OutputType ! ======================= CONTAINS - SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData + SUBROUTINE SD_CopyIList( SrcIListData, DstIListData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IList), INTENT(IN) :: SrcIListData + TYPE(IList), INTENT(INOUT) :: DstIListData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -291,6 +296,192 @@ SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyIList' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcIListData%List)) THEN + i1_l = LBOUND(SrcIListData%List,1) + i1_u = UBOUND(SrcIListData%List,1) + IF (.NOT. ALLOCATED(DstIListData%List)) THEN + ALLOCATE(DstIListData%List(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIListData%List.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstIListData%List = SrcIListData%List +ENDIF + END SUBROUTINE SD_CopyIList + + SUBROUTINE SD_DestroyIList( IListData, ErrStat, ErrMsg ) + TYPE(IList), INTENT(INOUT) :: IListData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyIList' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(IListData%List)) THEN + DEALLOCATE(IListData%List) +ENDIF + END SUBROUTINE SD_DestroyIList + + SUBROUTINE SD_PackIList( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IList), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackIList' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! List allocated yes/no + IF ( ALLOCATED(InData%List) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! List upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%List) ! List + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%List) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%List,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%List,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%List)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%List))-1 ) = PACK(InData%List,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%List) + END IF + END SUBROUTINE SD_PackIList + + SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IList), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackIList' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! List not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%List)) DEALLOCATE(OutData%List) + ALLOCATE(OutData%List(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%List.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%List)>0) OutData%List = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%List))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%List) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackIList + + SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' ! ErrStat = ErrID_None @@ -420,9 +611,6 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' From 43071a48b1cf332f79a7bbd3dabb34db0928ab5a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 14:15:02 -0700 Subject: [PATCH 068/377] FlexSub: distribution of DOF accross joints and members --- modules/subdyn/src/SD_FEM.f90 | 91 ++++++++++- modules/subdyn/src/SubDyn.f90 | 5 +- modules/subdyn/src/SubDyn_Output.f90 | 2 - modules/subdyn/src/SubDyn_Registry.txt | 2 + modules/subdyn/src/SubDyn_Types.f90 | 211 +++++++++++++++++++++++++ 5 files changed, 307 insertions(+), 4 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index fb5be8676..c8c0135ab 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -695,11 +695,94 @@ LOGICAL FUNCTION Failed() END FUNCTION Failed END SUBROUTINE SetElementProperties + +!> Distribute global DOF indices to joints and members +SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) + use IntegerList, only: init_list => init , len + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_MiscVarType), INTENT(INOUT) :: m + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer(IntKi) :: iJoint, k + integer(IntKi) :: iPrev + integer(IntKi) :: iMember + integer(IntKi) :: idMember + integer(IntKi) :: nRot ! Number of rotational DOFs (multiple of 3) to be used at the joint + integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 + integer(IntKi), dimension(6) :: DOFJoint_Old + integer(IntKi) :: ErrStat2 + character(1024) :: ErrMsg2 + ErrMsg = "" + ErrStat = ErrID_None + + allocate(m%JointsDOF(1:Init%NNode), stat=ErrStat2) + ErrMsg2="Error allocating JointsDOF" + if(Failed()) return + + call AllocAry(m%MembersDOF, 12, Init%NElem, 'MembersDOF', ErrStat2, ErrMsg2); if(Failed()) return; + + m%MembersDOF=-9999 + + iPrev =0 + do iJoint = 1, Init%NNode + ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) + if (Init%Nodes(iJoint,iJointType) == idJointCantilever ) then + nRot=3 + else + nRot= 3*Init%NodesConnE(iJoint,1) ! Col1: number of elements connected to this joint + endif + call init_list(m%JointsDOF(iJoint), 3+nRot, iPrev, ErrStat2, ErrMsg2) + m%JointsDOF(iJoint)%List(1:(3+nRot)) = (/ ((iMember+iPrev), iMember=1,3+nRot) /) + + ! --- Distribute to members + do iMember = 1, Init%NodesConnE(iJoint,1) ! members connected to joint iJ + idMember = Init%NodesConnE(iJoint,iMember+1) + if (iJoint == p%Elems(idMember, 2)) then ! Current joint is Member node 1 + iOff = 0 + else ! Current joint is Member node 2 + iOff = 6 + endif + m%MembersDOF(iOff+1:iOff+3, idMember) = m%JointsDOF(iJoint)%List(1:3) + if (Init%Nodes(iJoint,iJointType) == idJointCantilever ) then + m%MembersDOF(iOff+4:iOff+6, idMember) = m%JointsDOF(iJoint)%List(4:6) + else + m%MembersDOF(iOff+4:iOff+6, idMember) = m%JointsDOF(iJoint)%List(3*iMember+1:3*iMember+3) + endif + enddo ! iMember, loop on members connect to joint + iPrev = iPrev + len(m%JointsDOF(iJoint)) + enddo ! iJoint, loop on joints + + ! --- Safety check + if (any(m%MembersDOF<0)) then + ErrStat=ErrID_Fatal + ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" + endif + + ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) + do idMember = 1, Init%NElem + iJoint = p%Elems(idMember, 2) + DOFJoint_Old= (/ ((iJoint*6-5+k), k=0,5) /) + if ( any( (m%MembersDOF(1:6, idMember) /= DOFJoint_Old)) ) then + ErrStat=ErrID_Fatal + ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iMember="//trim(Num2LStr(idMember)) + return + endif + enddo + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed +END SUBROUTINE DistributeDOF + !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) +SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_MiscVarType), INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables @@ -721,6 +804,9 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) Init%TDOF = nDOF_Unconstrained() print*,'nDOF_unconstrained',Init%TDOF, 6*Init%NNode + ! --- Allocated DOF indices to joints and members + call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector @@ -739,6 +825,7 @@ SUBROUTINE AssembleKM(Init,p, ErrStat, ErrMsg) CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) ! assemble element matrices to global matrices + DO J = 1, 2 jn = nn(j) Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) )+ FCe( (J*6-5):(J*6) ) @@ -803,6 +890,8 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM + + !------------------------------------------------------------------------------------------------------ !> Computes directional cosine matrix DirCos !! rrd: This should be from local to global diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 14eac8a6d..ee5a3fce6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -314,8 +314,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Set element properties (p%ElemProps) CALL SetElementProperties(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + !Store mapping between nodes and elements + CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return + ! Assemble Stiffness and mass matrix - CALL AssembleKM(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + CALL AssembleKM(Init,p, m, ErrStat2, ErrMsg2); if(Failed()) return ! --- Calculate values for FEMparams (for summary file output only ! Solve dynamics problem diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index cccc8537d..a2491fb20 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -82,8 +82,6 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL AllocAry(y%WriteOutput, p%NumOuts +p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return y%WriteOutput = 0 - !Store mapping between nodes and elements - CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return DO I=1,p%NMOutputs pLst => p%MOutLst(I) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 4c0e081e1..d9cf40bfe 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -152,6 +152,8 @@ typedef ^ ^ ReKi UL_dotdot {:} typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" +typedef ^ ^ IList JointsDOF {:} - - "DOF indices of each joints in assembled system " "-" +typedef ^ ^ IntKi MembersDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given memeber in assembled system " "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 38c9cc4cb..8f99b1636 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -196,6 +196,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: JointsDOF !< DOF indices of each joints in assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MembersDOF !< 12 DOF indices of node 1 and 2 of a given memeber in assembled system [-] END TYPE SD_MiscVarType ! ======================= ! ========= SD_ParameterType ======= @@ -5315,6 +5317,7 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMisc' @@ -5434,6 +5437,36 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstMiscData%LastOutTime = SrcMiscData%LastOutTime DstMiscData%Decimat = SrcMiscData%Decimat +IF (ALLOCATED(SrcMiscData%JointsDOF)) THEN + i1_l = LBOUND(SrcMiscData%JointsDOF,1) + i1_u = UBOUND(SrcMiscData%JointsDOF,1) + IF (.NOT. ALLOCATED(DstMiscData%JointsDOF)) THEN + ALLOCATE(DstMiscData%JointsDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%JointsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%JointsDOF,1), UBOUND(SrcMiscData%JointsDOF,1) + CALL SD_Copyilist( SrcMiscData%JointsDOF(i1), DstMiscData%JointsDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcMiscData%MembersDOF)) THEN + i1_l = LBOUND(SrcMiscData%MembersDOF,1) + i1_u = UBOUND(SrcMiscData%MembersDOF,1) + i2_l = LBOUND(SrcMiscData%MembersDOF,2) + i2_u = UBOUND(SrcMiscData%MembersDOF,2) + IF (.NOT. ALLOCATED(DstMiscData%MembersDOF)) THEN + ALLOCATE(DstMiscData%MembersDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%MembersDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%MembersDOF = SrcMiscData%MembersDOF +ENDIF END SUBROUTINE SD_CopyMisc SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) @@ -5471,6 +5504,15 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDIF IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) +ENDIF +IF (ALLOCATED(MiscData%JointsDOF)) THEN +DO i1 = LBOUND(MiscData%JointsDOF,1), UBOUND(MiscData%JointsDOF,1) + CALL SD_Destroyilist( MiscData%JointsDOF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%JointsDOF) +ENDIF +IF (ALLOCATED(MiscData%MembersDOF)) THEN + DEALLOCATE(MiscData%MembersDOF) ENDIF END SUBROUTINE SD_DestroyMisc @@ -5559,6 +5601,35 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz END IF Db_BufSz = Db_BufSz + 1 ! LastOutTime Int_BufSz = Int_BufSz + 1 ! Decimat + Int_BufSz = Int_BufSz + 1 ! JointsDOF allocated yes/no + IF ( ALLOCATED(InData%JointsDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! JointsDOF upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%JointsDOF,1), UBOUND(InData%JointsDOF,1) + Int_BufSz = Int_BufSz + 3 ! JointsDOF: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%JointsDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! JointsDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! JointsDOF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! JointsDOF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! JointsDOF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MembersDOF allocated yes/no + IF ( ALLOCATED(InData%MembersDOF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MembersDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MembersDOF) ! MembersDOF + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5713,6 +5784,63 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Db_Xferred = Db_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%JointsDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%JointsDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JointsDOF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%JointsDOF,1), UBOUND(InData%JointsDOF,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%JointsDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! JointsDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MembersDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MembersDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MembersDOF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MembersDOF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MembersDOF,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MembersDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%MembersDOF))-1 ) = PACK(InData%MembersDOF,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%MembersDOF) + END IF END SUBROUTINE SD_PackMisc SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -5735,6 +5863,7 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMisc' @@ -5992,6 +6121,88 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Db_Xferred = Db_Xferred + 1 OutData%Decimat = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JointsDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%JointsDOF)) DEALLOCATE(OutData%JointsDOF) + ALLOCATE(OutData%JointsDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JointsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%JointsDOF,1), UBOUND(OutData%JointsDOF,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%JointsDOF(i1), ErrStat2, ErrMsg2 ) ! JointsDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MembersDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MembersDOF)) DEALLOCATE(OutData%MembersDOF) + ALLOCATE(OutData%MembersDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MembersDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MembersDOF)>0) OutData%MembersDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%MembersDOF))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%MembersDOF) + DEALLOCATE(mask2) + END IF END SUBROUTINE SD_UnPackMisc SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) From 30725d2000e439eade4c9c4d30b85eeb78684c92 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 15:20:25 -0700 Subject: [PATCH 069/377] FlexSub: using DOF indices in assembly --- modules/subdyn/src/SD_FEM.f90 | 56 +++++------ modules/subdyn/src/SubDyn_Registry.txt | 4 +- modules/subdyn/src/SubDyn_Types.f90 | 124 ++++++++++++------------- 3 files changed, 86 insertions(+), 98 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index c8c0135ab..01e7ff621 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -716,13 +716,12 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) ErrMsg = "" ErrStat = ErrID_None - allocate(m%JointsDOF(1:Init%NNode), stat=ErrStat2) - ErrMsg2="Error allocating JointsDOF" + allocate(m%NodesDOF(1:Init%NNode), stat=ErrStat2) + ErrMsg2="Error allocating NodesDOF" if(Failed()) return - call AllocAry(m%MembersDOF, 12, Init%NElem, 'MembersDOF', ErrStat2, ErrMsg2); if(Failed()) return; - - m%MembersDOF=-9999 + call AllocAry(m%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; + m%ElemsDOF=-9999 iPrev =0 do iJoint = 1, Init%NNode @@ -732,8 +731,8 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) else nRot= 3*Init%NodesConnE(iJoint,1) ! Col1: number of elements connected to this joint endif - call init_list(m%JointsDOF(iJoint), 3+nRot, iPrev, ErrStat2, ErrMsg2) - m%JointsDOF(iJoint)%List(1:(3+nRot)) = (/ ((iMember+iPrev), iMember=1,3+nRot) /) + call init_list(m%NodesDOF(iJoint), 3+nRot, iPrev, ErrStat2, ErrMsg2) + m%NodesDOF(iJoint)%List(1:(3+nRot)) = (/ ((iMember+iPrev), iMember=1,3+nRot) /) ! --- Distribute to members do iMember = 1, Init%NodesConnE(iJoint,1) ! members connected to joint iJ @@ -743,18 +742,18 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) else ! Current joint is Member node 2 iOff = 6 endif - m%MembersDOF(iOff+1:iOff+3, idMember) = m%JointsDOF(iJoint)%List(1:3) + m%ElemsDOF(iOff+1:iOff+3, idMember) = m%NodesDOF(iJoint)%List(1:3) if (Init%Nodes(iJoint,iJointType) == idJointCantilever ) then - m%MembersDOF(iOff+4:iOff+6, idMember) = m%JointsDOF(iJoint)%List(4:6) + m%ElemsDOF(iOff+4:iOff+6, idMember) = m%NodesDOF(iJoint)%List(4:6) else - m%MembersDOF(iOff+4:iOff+6, idMember) = m%JointsDOF(iJoint)%List(3*iMember+1:3*iMember+3) + m%ElemsDOF(iOff+4:iOff+6, idMember) = m%NodesDOF(iJoint)%List(3*iMember+1:3*iMember+3) endif enddo ! iMember, loop on members connect to joint - iPrev = iPrev + len(m%JointsDOF(iJoint)) + iPrev = iPrev + len(m%NodesDOF(iJoint)) enddo ! iJoint, loop on joints ! --- Safety check - if (any(m%MembersDOF<0)) then + if (any(m%ElemsDOF<0)) then ErrStat=ErrID_Fatal ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" endif @@ -763,7 +762,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) do idMember = 1, Init%NElem iJoint = p%Elems(idMember, 2) DOFJoint_Old= (/ ((iJoint*6-5+k), k=0,5) /) - if ( any( (m%MembersDOF(1:6, idMember) /= DOFJoint_Old)) ) then + if ( any( (m%ElemsDOF(1:6, idMember) /= DOFJoint_Old)) ) then ErrStat=ErrID_Fatal ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iMember="//trim(Num2LStr(idMember)) return @@ -793,12 +792,10 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) INTEGER, DIMENSION(2) :: nn ! node number in element INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system ErrMsg = "" ErrStat = ErrID_None - - - - ! total unconstrained degrees of freedom of the system Init%TDOF = nDOF_Unconstrained() @@ -816,42 +813,33 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) ! loop over all elements, compute element matrices and assemble into global matrices DO i = 1, Init%NElem - nn(1) = p%Elems(i, 2) - nn(2) = p%Elems(i, 3) - ! --- Element Me,Ke,Fg, Fce CALL ElemM(p%ElemProps(i), Me) CALL ElemK(p%ElemProps(i), Ke) CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) - ! assemble element matrices to global matrices - - DO J = 1, 2 - jn = nn(j) - Init%FG( (jn*6-5):(jn*6) ) = Init%FG( (jn*6-5):(jn*6) ) + FGe( (J*6-5):(J*6) )+ FCe( (J*6-5):(J*6) ) - DO K = 1, 2 - kn = nn(k) - Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%K( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Ke( (J*6-5):(J*6), (K*6-5):(K*6) ) - Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) = Init%M( (jn*6-5):(jn*6), (kn*6-5):(kn*6) ) + Me( (J*6-5):(J*6), (K*6-5):(K*6) ) - ENDDO !K - ENDDO !J + ! --- Assembly in global unconstrained system + IDOF = m%ElemsDOF(1:12, i) + Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) + Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) + Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) ENDDO ! end loop over elements , i ! add concentrated mass DO I = 1, Init%NCMass DO J = 1, 3 - iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + iGlob = m%NodesDOF(i)%List(J) ! ux, uy, uz Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) ENDDO DO J = 4, 6 - iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + J + iGlob = m%NodesDOF(i)%List(J) ! theta_x, theta_y, theta_z Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) ENDDO ENDDO ! Loop on concentrated mass ! add concentrated mass induced gravity force DO I = 1, Init%NCMass - iGlob = ( NINT(Init%CMass(I, 1)) - 1 )*6 + 3 + iGlob = m%NodesDOF(i)%List(3) ! uz Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO ! I concentrated mass induced gravity diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index d9cf40bfe..f1f0f941a 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -152,8 +152,8 @@ typedef ^ ^ ReKi UL_dotdot {:} typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" -typedef ^ ^ IList JointsDOF {:} - - "DOF indices of each joints in assembled system " "-" -typedef ^ ^ IntKi MembersDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given memeber in assembled system " "-" +typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 8f99b1636..9f37d8f2c 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -196,8 +196,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: JointsDOF !< DOF indices of each joints in assembled system [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MembersDOF !< 12 DOF indices of node 1 and 2 of a given memeber in assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] END TYPE SD_MiscVarType ! ======================= ! ========= SD_ParameterType ======= @@ -5437,35 +5437,35 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstMiscData%LastOutTime = SrcMiscData%LastOutTime DstMiscData%Decimat = SrcMiscData%Decimat -IF (ALLOCATED(SrcMiscData%JointsDOF)) THEN - i1_l = LBOUND(SrcMiscData%JointsDOF,1) - i1_u = UBOUND(SrcMiscData%JointsDOF,1) - IF (.NOT. ALLOCATED(DstMiscData%JointsDOF)) THEN - ALLOCATE(DstMiscData%JointsDOF(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%NodesDOF)) THEN + i1_l = LBOUND(SrcMiscData%NodesDOF,1) + i1_u = UBOUND(SrcMiscData%NodesDOF,1) + IF (.NOT. ALLOCATED(DstMiscData%NodesDOF)) THEN + ALLOCATE(DstMiscData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%JointsDOF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%NodesDOF.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DO i1 = LBOUND(SrcMiscData%JointsDOF,1), UBOUND(SrcMiscData%JointsDOF,1) - CALL SD_Copyilist( SrcMiscData%JointsDOF(i1), DstMiscData%JointsDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(SrcMiscData%NodesDOF,1), UBOUND(SrcMiscData%NodesDOF,1) + CALL SD_Copyilist( SrcMiscData%NodesDOF(i1), DstMiscData%NodesDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF -IF (ALLOCATED(SrcMiscData%MembersDOF)) THEN - i1_l = LBOUND(SrcMiscData%MembersDOF,1) - i1_u = UBOUND(SrcMiscData%MembersDOF,1) - i2_l = LBOUND(SrcMiscData%MembersDOF,2) - i2_u = UBOUND(SrcMiscData%MembersDOF,2) - IF (.NOT. ALLOCATED(DstMiscData%MembersDOF)) THEN - ALLOCATE(DstMiscData%MembersDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%ElemsDOF)) THEN + i1_l = LBOUND(SrcMiscData%ElemsDOF,1) + i1_u = UBOUND(SrcMiscData%ElemsDOF,1) + i2_l = LBOUND(SrcMiscData%ElemsDOF,2) + i2_u = UBOUND(SrcMiscData%ElemsDOF,2) + IF (.NOT. ALLOCATED(DstMiscData%ElemsDOF)) THEN + ALLOCATE(DstMiscData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%MembersDOF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%MembersDOF = SrcMiscData%MembersDOF + DstMiscData%ElemsDOF = SrcMiscData%ElemsDOF ENDIF END SUBROUTINE SD_CopyMisc @@ -5505,14 +5505,14 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) ENDIF -IF (ALLOCATED(MiscData%JointsDOF)) THEN -DO i1 = LBOUND(MiscData%JointsDOF,1), UBOUND(MiscData%JointsDOF,1) - CALL SD_Destroyilist( MiscData%JointsDOF(i1), ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%NodesDOF)) THEN +DO i1 = LBOUND(MiscData%NodesDOF,1), UBOUND(MiscData%NodesDOF,1) + CALL SD_Destroyilist( MiscData%NodesDOF(i1), ErrStat, ErrMsg ) ENDDO - DEALLOCATE(MiscData%JointsDOF) + DEALLOCATE(MiscData%NodesDOF) ENDIF -IF (ALLOCATED(MiscData%MembersDOF)) THEN - DEALLOCATE(MiscData%MembersDOF) +IF (ALLOCATED(MiscData%ElemsDOF)) THEN + DEALLOCATE(MiscData%ElemsDOF) ENDIF END SUBROUTINE SD_DestroyMisc @@ -5601,34 +5601,34 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz END IF Db_BufSz = Db_BufSz + 1 ! LastOutTime Int_BufSz = Int_BufSz + 1 ! Decimat - Int_BufSz = Int_BufSz + 1 ! JointsDOF allocated yes/no - IF ( ALLOCATED(InData%JointsDOF) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! JointsDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no + IF ( ALLOCATED(InData%NodesDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension ! Allocate buffers for subtypes, if any (we'll get sizes from these) - DO i1 = LBOUND(InData%JointsDOF,1), UBOUND(InData%JointsDOF,1) - Int_BufSz = Int_BufSz + 3 ! JointsDOF: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%JointsDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! JointsDOF + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOF: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! JointsDOF + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOF Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! JointsDOF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOF Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! JointsDOF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOF Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! MembersDOF allocated yes/no - IF ( ALLOCATED(InData%MembersDOF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MembersDOF upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%MembersDOF) ! MembersDOF + Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no + IF ( ALLOCATED(InData%ElemsDOF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -5784,18 +5784,18 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Db_Xferred = Db_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%JointsDOF) ) THEN + IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%JointsDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JointsDOF,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOF,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%JointsDOF,1), UBOUND(InData%JointsDOF,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%JointsDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! JointsDOF + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5825,21 +5825,21 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%MembersDOF) ) THEN + IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MembersDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MembersDOF,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MembersDOF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MembersDOF,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%MembersDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%MembersDOF))-1 ) = PACK(InData%MembersDOF,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%MembersDOF) + IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) END IF END SUBROUTINE SD_PackMisc @@ -6121,20 +6121,20 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Db_Xferred = Db_Xferred + 1 OutData%Decimat = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JointsDOF not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%JointsDOF)) DEALLOCATE(OutData%JointsDOF) - ALLOCATE(OutData%JointsDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%NodesDOF)) DEALLOCATE(OutData%NodesDOF) + ALLOCATE(OutData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JointsDOF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOF.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%JointsDOF,1), UBOUND(OutData%JointsDOF,1) + DO i1 = LBOUND(OutData%NodesDOF,1), UBOUND(OutData%NodesDOF,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -6168,7 +6168,7 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%JointsDOF(i1), ErrStat2, ErrMsg2 ) ! JointsDOF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOF(i1), ErrStat2, ErrMsg2 ) ! NodesDOF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6177,7 +6177,7 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MembersDOF not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -6187,10 +6187,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MembersDOF)) DEALLOCATE(OutData%MembersDOF) - ALLOCATE(OutData%MembersDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%ElemsDOF)) DEALLOCATE(OutData%ElemsDOF) + ALLOCATE(OutData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MembersDOF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -6199,8 +6199,8 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%MembersDOF)>0) OutData%MembersDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%MembersDOF))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%MembersDOF) + IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) DEALLOCATE(mask2) END IF END SUBROUTINE SD_UnPackMisc From f5c50572c78916f33ef3e0de1cfc131674b813ca Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 15:43:38 -0700 Subject: [PATCH 070/377] FlexSub: small renaming of variables --- modules/subdyn/src/SD_FEM.f90 | 70 ++++++++++++++++------------ modules/subdyn/src/SubDyn_Output.f90 | 27 +++++------ 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 01e7ff621..98b235b12 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -696,7 +696,10 @@ END FUNCTION Failed END SUBROUTINE SetElementProperties -!> Distribute global DOF indices to joints and members +!> Distribute global DOF indices to nodes and elements +!! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs +!! For other joint type -> Condensation of the 3 translational DOF +!! -> Keeping 3 rotational DOF for each memeber connected to the joint SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) use IntegerList, only: init_list => init , len TYPE(SD_InitType), INTENT(INOUT) :: Init @@ -704,13 +707,13 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) TYPE(SD_MiscVarType), INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer(IntKi) :: iJoint, k - integer(IntKi) :: iPrev - integer(IntKi) :: iMember - integer(IntKi) :: idMember + integer(IntKi) :: iNode, k + integer(IntKi) :: iPrev ! Cumulative counter over the global DOF + integer(IntKi) :: iElem ! + integer(IntKi) :: idElem integer(IntKi) :: nRot ! Number of rotational DOFs (multiple of 3) to be used at the joint integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 - integer(IntKi), dimension(6) :: DOFJoint_Old + integer(IntKi), dimension(6) :: DOFNode_Old integer(IntKi) :: ErrStat2 character(1024) :: ErrMsg2 ErrMsg = "" @@ -724,33 +727,33 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) m%ElemsDOF=-9999 iPrev =0 - do iJoint = 1, Init%NNode + do iNode = 1, Init%NNode ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) - if (Init%Nodes(iJoint,iJointType) == idJointCantilever ) then + if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then nRot=3 else - nRot= 3*Init%NodesConnE(iJoint,1) ! Col1: number of elements connected to this joint + nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint endif - call init_list(m%NodesDOF(iJoint), 3+nRot, iPrev, ErrStat2, ErrMsg2) - m%NodesDOF(iJoint)%List(1:(3+nRot)) = (/ ((iMember+iPrev), iMember=1,3+nRot) /) + call init_list(m%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) + m%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) ! --- Distribute to members - do iMember = 1, Init%NodesConnE(iJoint,1) ! members connected to joint iJ - idMember = Init%NodesConnE(iJoint,iMember+1) - if (iJoint == p%Elems(idMember, 2)) then ! Current joint is Member node 1 + do iElem = 1, Init%NodesConnE(iNode,1) ! members connected to joint iJ + idElem = Init%NodesConnE(iNode,iElem+1) + if (iNode == p%Elems(idElem, 2)) then ! Current joint is Elem node 1 iOff = 0 - else ! Current joint is Member node 2 + else ! Current joint is Elem node 2 iOff = 6 endif - m%ElemsDOF(iOff+1:iOff+3, idMember) = m%NodesDOF(iJoint)%List(1:3) - if (Init%Nodes(iJoint,iJointType) == idJointCantilever ) then - m%ElemsDOF(iOff+4:iOff+6, idMember) = m%NodesDOF(iJoint)%List(4:6) + m%ElemsDOF(iOff+1:iOff+3, idElem) = m%NodesDOF(iNode)%List(1:3) + if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then + m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(4:6) else - m%ElemsDOF(iOff+4:iOff+6, idMember) = m%NodesDOF(iJoint)%List(3*iMember+1:3*iMember+3) + m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) endif - enddo ! iMember, loop on members connect to joint - iPrev = iPrev + len(m%NodesDOF(iJoint)) - enddo ! iJoint, loop on joints + enddo ! iElem, loop on members connect to joint + iPrev = iPrev + len(m%NodesDOF(iNode)) + enddo ! iNode, loop on joints ! --- Safety check if (any(m%ElemsDOF<0)) then @@ -759,15 +762,20 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) endif ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) - do idMember = 1, Init%NElem - iJoint = p%Elems(idMember, 2) - DOFJoint_Old= (/ ((iJoint*6-5+k), k=0,5) /) - if ( any( (m%ElemsDOF(1:6, idMember) /= DOFJoint_Old)) ) then - ErrStat=ErrID_Fatal - ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iMember="//trim(Num2LStr(idMember)) - return - endif - enddo + if (Init%NNode == count( Init%Nodes(:, iJointType) == idJointCantilever)) then + do idElem = 1, Init%NElem + iNode = p%Elems(idElem, 2) + DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) + if ( any( (m%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then + ErrStat=ErrID_Fatal + ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iElem="//trim(Num2LStr(idElem)) + return + endif + enddo + else + print*,'Not performing safety check' ! remove me in the future + STOP + endif CONTAINS LOGICAL FUNCTION Failed() diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index a2491fb20..65980194d 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -66,7 +66,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ErrStat = 0 ErrMsg="" - p%OutAllDims=12*p%Nmembers*2 !size of AllOut Member Joint forces + p%OutAllDims=12*p%NMembers*2 !size of AllOut Member Joint forces ! Check that the variables in OutList are valid CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat2, ErrMsg2 ); if(Failed()) return @@ -156,8 +156,8 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) NconEls=Init%NodesConnE(pLst%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member K2= J/(Init%Ndiv+1)+1 !store this quantity used later, basically 1 or 2 depending on J DO K=1, NconEls - L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node - M=p%Elems(L,2:3) !1st and 2nd node of the k-th element + L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node + M=p%Elems(L,2:3) !1st and 2nd node of the k-th element !Select only the other node, not the one where elements connect to Junk=M(1) IF (M(1) .EQ. pLst%NodeIDs(J)) Junk=M(2) @@ -252,7 +252,7 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) ! local variables INTEGER :: I !counter INTEGER :: rmndr !type-column index - INTEGER :: n !node ID + INTEGER :: nodeID !node ID INTEGER(IntKi) :: DOFC ! DOFC = Init%NReact*6 REAL(ReKi) :: x, y, z !coordinates ErrStat=ErrID_None @@ -260,7 +260,7 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) DOFC = p%NReact*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure - CALL AllocAry(p%TIreact, 6,DOFC, 'p%TIReact', ErrStat, ErrMsg ) + CALL AllocAry(p%TIreact, 6, DOFC, 'p%TIReact', ErrStat, ErrMsg ) if ( ErrStat /= ErrID_None ) return p%TIreact=0 !Initialize @@ -271,12 +271,11 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) !Other rows done per column actually DO I = 1, DOFC + nodeID = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) - n = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) ! TODO different DOF ordering - - x = Init%Nodes(n, 2) - y = Init%Nodes(n, 3) - z = Init%Nodes(n, 4) + WtrDpth + x = Init%Nodes(nodeID, 2) + y = Init%Nodes(nodeID, 3) + z = Init%Nodes(nodeID, 4) + WtrDpth rmndr = MOD(I, 6) !It gives me the column index among the 6 different kinds SELECT CASE (rmndr) @@ -286,7 +285,6 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) CASE (4); p%TIreact(4:6, I) = (/1.0_ReKi , 0.0_ReKi , 0.0_ReKi/) CASE (5); p%TIreact(4:6, I) = (/0.0_ReKi , 1.0_ReKi , 0.0_ReKi/) CASE (0); p%TIreact(4:6, I) = (/0.0_ReKi , 0.0_ReKi , 1.0_ReKi/) - CASE DEFAULT ErrStat = ErrID_Fatal ErrMsg = 'Error calculating transformation matrix TIreact, wrong column index ' @@ -323,7 +321,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL - Real(reKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs + Real(ReKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs Real(ReKi), DIMENSION(p%URbarL+p%DOFL+6*p%Nreact) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs Integer(IntKi) ::sgn !+1/-1 for node force calculations type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities @@ -836,7 +834,6 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) ELSE ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' ErrStat = ErrID_Fatal -! RETURN p%OutParam(I)%Units = 'INVALID' p%OutParam(I)%Indx = 0 p%OutParam(I)%SignM = 0 ! this will print all zeros @@ -847,9 +844,9 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) IF (p%OutAll) THEN !Finish populating the OutParam with all the joint forces and moments ToTNames0=RESHAPE(SPREAD( (/"FKxe", "FKye", "FKze", "MKxe", "MKye", "MKze", "FMxe", "FMye", "FMze", "MMxe", "MMye", "MMze"/), 2, 2), (/24/) ) ToTUnits=RESHAPE(SPREAD( (/"(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)", "(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)"/), 2, 2), (/24/) ) - DO I=1,p%Nmembers + DO I=1,p%NMembers DO K=1,2 - DO J=1,12 !looks like I cnanot vectorize TRIM etc in Fortran + DO J=1,12 TotNames(J+(K-1)*12)=TRIM("M"//Int2Lstr(I))//TRIM("J"//Int2Lstr(K))//TRIM(TotNames0(J)) ENDDO ENDDO From 37ef444a1b80ae99b29ee743552fc4a158fb6867 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 16:27:44 -0700 Subject: [PATCH 071/377] FlexSub: BCs and IntFc use uneliminated DOF index, outputs and IDY might need update --- modules/subdyn/src/SD_FEM.f90 | 78 +++++++++++++++------------- modules/subdyn/src/SubDyn.f90 | 11 ++-- modules/subdyn/src/SubDyn_Output.f90 | 2 +- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 98b235b12..eae597ee0 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -163,7 +163,6 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) enddo ! --- Re-Initialize interface joints, pointing to index instead of JointID - Init%IntFc = 0 do I = 1, Init%NInterf JointID=Init%Interf(I,1) Init%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) @@ -283,23 +282,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different - CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays ! NOTE: need NNode and NElem CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Initialize boundary constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return - CALL InitConstr(Init, p) - - ! --- Initialize interface constraint vector - TODO: assumes order of DOF, NOTE: Needs Reindexing first - DO I = 1, Init%NInterf - DO J = 1, 6 - Init%IntFc( (I-1)*6+J, 1) = (Init%Interf(I,1)-1)*6+J; ! TODO assumes order of DOF, and needs Interf1 reindexed - Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); - ENDDO - ENDDO Init%MemberNodes = 0 ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) @@ -696,14 +683,14 @@ END FUNCTION Failed END SUBROUTINE SetElementProperties -!> Distribute global DOF indices to nodes and elements +!> Distribute global DOF indices corresponding to Nodes, Elements, BCs, Reactions !! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs !! For other joint type -> Condensation of the 3 translational DOF !! -> Keeping 3 rotational DOF for each memeber connected to the joint SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) use IntegerList, only: init_list => init , len TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_ParameterType), INTENT(IN ) :: p TYPE(SD_MiscVarType), INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -755,6 +742,14 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) iPrev = iPrev + len(m%NodesDOF(iNode)) enddo ! iNode, loop on joints + ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first + CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitBCs(Init, p) + + ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first + CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitIntFc(Init, p) + ! --- Safety check if (any(m%ElemsDOF<0)) then ErrStat=ErrID_Fatal @@ -782,6 +777,39 @@ LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') Failed = ErrStat >= AbortErrLev END FUNCTION Failed + + !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have + !! NOTE: need p%Reacts to have an updated first column that uses indices and not JointIDs + SUBROUTINE InitBCs(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + Init%BCs = 0 + DO I = 1, p%NReact + iNode = p%Reacts(I,1) ! Node index + DO J = 1, 6 + Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) + Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); + ENDDO + ENDDO + END SUBROUTINE InitBCs + + !> Sets a list of DOF indices and the value these DOF should have + !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs + SUBROUTINE InitIntFc(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + Init%IntFc = 0 + DO I = 1, Init%NInterf + iNode = Init%Interf(I,1) ! Node index + DO J = 1, 6 + Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) + Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); + ENDDO + ENDDO + END SUBROUTINE InitIntFc + END SUBROUTINE DistributeDOF !------------------------------------------------------------------------------------------------------ @@ -809,9 +837,6 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) Init%TDOF = nDOF_Unconstrained() print*,'nDOF_unconstrained',Init%TDOF, 6*Init%NNode - ! --- Allocated DOF indices to joints and members - call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector @@ -1225,23 +1250,6 @@ SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed END SUBROUTINE ElemM_Cable -!------------------------------------------------------------------------------------------------------ -!> Sets a list of DOF indices and the value these DOF should have -!! NOTE: need p%Reacts to have an updated first column that uses indices and not JointID -SUBROUTINE InitConstr(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - ! - INTEGER(IntKi) :: I,J - - Init%BCs = 0 - DO I = 1, p%NReact - DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = (p%Reacts(I,1)-1)*6+J; ! DOF Index, looping through Joints in index order - Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); - ENDDO - ENDDO -END SUBROUTINE InitConstr !> Apply constraint (Boundary conditions) on Mass and Stiffness matrices SUBROUTINE ApplyConstr(Init,p) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ee5a3fce6..9a0ccd7a6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -317,6 +317,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO !Store mapping between nodes and elements CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return + ! --- Allocated DOF indices to joints and members + call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; + ! Assemble Stiffness and mass matrix CALL AssembleKM(Init,p, m, ErrStat2, ErrMsg2); if(Failed()) return @@ -2464,10 +2467,10 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) ErrMsg = "" ! Index IDI for interface DOFs - p%IDI = Init%IntFc(1:p%DOFI, 1) !RRD interface DOFs + p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs in global uneliminated system ! Index IDC for constraint DOFs - p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs + p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs in global uneliminated system ! Index IDR for IDR DOFs p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again @@ -2502,8 +2505,8 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) ENDDO ! set the first column of the temp array - TempIDY(1:p%DOFI, 1) = p%IDI - TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL + TempIDY(1:p%DOFI, 1) = p%IDI + TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL TempIDY(p%DOFI+p%DOFL+1: p%DOFI+p%DOFL+p%DOFC, 1) = p%IDC ! sort based on the first column CALL QsortC( TempIDY ) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 65980194d..d6d7c5afe 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -489,7 +489,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !The index in Y2mesh is? !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) - ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES + ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ! TODO TODO TODO assumed DOF order maybe ENDDO ! Store into AllOuts AllOuts( ReactSS(1:TPdofL) ) = matmul(p%TIreact,ReactNs) From 7bad49428cf2f6c2c1e48e9d89a88287dfe9a4f8 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 9 Dec 2019 17:34:07 -0700 Subject: [PATCH 072/377] FlexSub: fix some array boundaries in debug --- Makefile | 2 +- modules/subdyn/src/SD_FEM.f90 | 12 ++-- modules/subdyn/src/SubDyn.f90 | 91 ++++++++++++----------------- modules/subdyn/src/SubDyn_Tests.f90 | 48 +++++++++++++++ 4 files changed, 92 insertions(+), 61 deletions(-) diff --git a/Makefile b/Makefile index 646fb6813..cb07b2b06 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ MAKE=make --no-print-directory MAKE_ARGS=VERBOSE=1 -CMAKE_ARGS=-DCMAKE_BUILD_TYPE=DEBUG -DDOUBLE_PRECISION:BOOL=OFF -DGENERATE_TYPES:BOOL=ON +CMAKE_ARGS=-DCMAKE_BUILD_TYPE=Debug -DDOUBLE_PRECISION:BOOL=OFF -DGENERATE_TYPES:BOOL=ON suffix=-single-db ifeq ($(OS),Windows_NT) OS=Windows diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index eae597ee0..be5d262ef 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -601,12 +601,12 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%DirCos = DirCos ! Init to excessive values to detect any issue - p%ElemProps(i)%Ixx = -9.99e+36 - p%ElemProps(i)%Iyy = -9.99e+36 - p%ElemProps(i)%Jzz = -9.99e+36 - p%ElemProps(i)%Kappa = -9.99e+36 - p%ElemProps(i)%YoungE = -9.99e+36 - p%ElemProps(i)%ShearG = -9.99e+36 + p%ElemProps(i)%Ixx = -9.99e+36 + p%ElemProps(i)%Iyy = -9.99e+36 + p%ElemProps(i)%Jzz = -9.99e+36 + p%ElemProps(i)%Kappa = -9.99e+36 + p%ElemProps(i)%YoungE = -9.99e+36 + p%ElemProps(i)%ShearG = -9.99e+36 p%ElemProps(i)%Area = -9.99e+36 p%ElemProps(i)%Rho = -9.99e+36 p%ElemProps(i)%T0 = -9.99e+36 diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 9a0ccd7a6..9d27336ba 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -911,7 +911,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! Read remaining lines DO I = 2, Init%NJoints CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, nColumns, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - Init%Joints(I,:) = Dummy_ReAry(1:nColumns) + Init%Joints(I,1:nColumns) = Dummy_ReAry(1:nColumns) ENDDO IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return @@ -1008,6 +1008,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadAry( UnIn, SDInputFile, Init%PropSetsR(I,:), PropSetsRCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ENDDO IF (Check( Init%NPropSetsR < 0, 'NPropSetsRigid must be >=0')) return +else + Init%NPropSetsC=0 + Init%NPropSetsR=0 + CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return endif !---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ @@ -2475,7 +2480,7 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) ! Index IDR for IDR DOFs p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again p%IDR(p%DOFC+1:p%DOFR) = p%IDI ! IDR contains DOFs ofboundaries, constraints first then interface - + ! --- Index IDL for IDL DOFs ! first set the total DOFs: DO I = 1, Init%TDOF !Total DOFs @@ -2512,56 +2517,28 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) CALL QsortC( TempIDY ) ! the second column is the key: p%IDY = TempIDY(:, 2) - -END SUBROUTINE SetIndexArrays -!------------------------------------------------------------------------------------------------------ -!> -SUBROUTINE Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg,Init,p) - TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters - INTEGER(IntKi) :: DOFTP, DOFM - REAL(ReKi) :: MBBt(DOFTP, DOFTP) - REAL(ReKi) :: MBmt(DOFTP, DOFM) - REAL(ReKi) :: KBBt(DOFTP, DOFTP) - REAL(ReKi) :: OmegaM(DOFM) - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: DOFT, NM, i - REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) - REAL(ReKi), Allocatable :: K(:, :) - REAL(ReKi), Allocatable :: M(:, :) - Character(1024) :: rootname - ErrStat = ErrID_None - ErrMsg = '' - - DOFT = DOFTP + DOFM - NM = DOFT - 3 - Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) - K = 0.0 - M = 0.0 - OmegaCB = 0.0 - PhiCB = 0.0 - - M(1:DOFTP, 1:DOFTP) = MBBt - M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt - M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) - - DO i = 1, DOFM - K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) - M(DOFTP+i, DOFTP+i) = 1.0 - ENDDO - - K(1:DOFTP, 1:DOFTP) = KBBt - ! temporary rootname - rootname = './test_assemble_C-B_out' +! do I = 1, p%DOFI !Total DOFs +! print*,'IDI ',I, p%IDI(I) +! enddo +! do I = 1, p%DOFC !Total DOFs +! print*,'IDR_c',I, p%IDR(I) +! enddo +! do I = p%DOFC+1,p%DOFR +! print*,'IDR_c',I, p%IDR(I) +! enddo +! do I = 1, p%DOFL !Total DOFs +! print*,'IDL ',I, p%IDL(I) +! enddo +! do I = 1, p%DOFC !Total DOFs +! print*,'IDC ',I, p%IDC(I) +! enddo +! do I = 1, size(p%IDY) +! print*,'IDY ',I, p%IDY(I) +! enddo - CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) - IF ( ErrStat /= 0 ) RETURN - -END SUBROUTINE Test_CB_Results +END SUBROUTINE SetIndexArrays !------------------------------------------------------------------------------------------------------ !> Take the input u LMesh and constructs the appropriate corresponding UFL vector @@ -2599,6 +2576,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders + INTEGER(IntKi) :: mType ! Member Type INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3), mlength !temporary arrays, member i-th direction cosine matrix (global to local) and member length @@ -2673,13 +2651,18 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS - propids=Init%Members(i,iMProp:iMProp+1) + propids=p%Elems(i,iMProp:iMProp+1) mlength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) IF (ErrStat .EQ. ErrID_None) THEN - WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & - MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & - Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mlength, .TRUE.), & - ' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + mType = Init%Members(I, iMType) ! + if (mType==idMemberBeam) then + WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & + MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & + Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mlength, .TRUE.), & + ' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + else + WRITE(UnSum, '(A)') 'TODO, member mass for non-beam elements' + endif ELSE RETURN ENDIF diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 8c17624de..efba2f9c1 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -116,6 +116,54 @@ subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) ! --------------------------------------------------------------------------------} ! --- Specific SubDyn tests ! --------------------------------------------------------------------------------{ + subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg,Init,p) + TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters + INTEGER(IntKi) :: DOFTP, DOFM + REAL(ReKi) :: MBBt(DOFTP, DOFTP) + REAL(ReKi) :: MBmt(DOFTP, DOFM) + REAL(ReKi) :: KBBt(DOFTP, DOFTP) + REAL(ReKi) :: OmegaM(DOFM) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: DOFT, NM, i + REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) + REAL(ReKi), Allocatable :: K(:, :) + REAL(ReKi), Allocatable :: M(:, :) + Character(1024) :: rootname + ErrStat = ErrID_None + ErrMsg = '' + print*,'This test is not a unit test' + + DOFT = DOFTP + DOFM + NM = DOFT - 3 + Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) + K = 0.0 + M = 0.0 + OmegaCB = 0.0 + PhiCB = 0.0 + + M(1:DOFTP, 1:DOFTP) = MBBt + M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt + M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) + + DO i = 1, DOFM + K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) + M(DOFTP+i, DOFTP+i) = 1.0 + ENDDO + + K(1:DOFTP, 1:DOFTP) = KBBt + + ! temporary rootname + rootname = './test_assemble_C-B_out' + + ! NOTE: Eigensolve is in SubDyn + !CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) + IF ( ErrStat /= 0 ) RETURN + end subroutine Test_CB_Results + + subroutine Test_lists(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg From 43204b3d6296cb0817a61868c6b0e82080b07696 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 16 Dec 2019 12:37:06 -0700 Subject: [PATCH 073/377] Draft of more glue-code changes --- .../openfast-library/src/FAST_Registry.txt | 1 + modules/openfast-library/src/FAST_Solver.f90 | 14 +- modules/openfast-library/src/FAST_Types.f90 | 90 +++ vs-build/FASTlib/FASTlib.vfproj | 650 +++++++++--------- vs-build/MAPlib/MAP_dll.vcxproj | 34 +- vs-build/Registry/FAST_Registry.vcxproj | 60 +- 6 files changed, 514 insertions(+), 335 deletions(-) diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index 2bc3c92cc..4a6cdda50 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -407,6 +407,7 @@ typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P {:} - - "Map ElastoDyn B typedef FAST FAST_ModuleMapType MeshMapType BD_P_2_ED_P {:} - - "Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh" typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P_Hub {:} - - "ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator" # ED <-> HD +typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_PRP_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn platform reference Point" typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_W_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point" typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point (from either y%WAMITMesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh" typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point" diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 1b8a17746..1f835eb0e 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -924,7 +924,11 @@ SUBROUTINE Transfer_ED_to_HD( y_ED, u_HD, MeshMapData, ErrStat, ErrMsg ) IF ( u_HD%WAMITMesh%Committed ) THEN - ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, + ! Transfer the ED outputs of the platform motions to the HD input of which represents the same data + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_ED_to_HD (u_HD%PRPMesh)' ) + + ! These are the motions for the lumped point loads associated the WAMIT body(ies) and include: hydrostatics, radiation memory effect, ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, ! hydrodynamic added mass @@ -2465,8 +2469,12 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & CALL Transfer_SD_to_HD( y_SD, u_HD%Morison%LumpedMesh, u_HD%Morison%DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! Map ED outputs to HD inputs (keeping the accelerations we just calculated): + ! Map ED outputs to HD inputs (keeping the accelerations we just calculated): + ! Transfer the ED outputs of the platform motions to the HD input of which represents the same data + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName ) + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -4063,6 +4071,8 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M ! HydroDyn WAMIT point mesh to/from ElastoDyn point mesh CALL MeshMapCreate( HD%y%AllHdroOrigin, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) + CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_PRP_P' ) CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) END IF diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index b73547398..acc72f471 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -479,6 +479,7 @@ MODULE FAST_Types TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_BD_P !< Map ElastoDyn BladeRootMotion meshes to BeamDyn RootMotion point meshes [-] TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: BD_P_2_ED_P !< Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh [-] TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_BD_P_Hub !< ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator [-] + TYPE(MeshMapType) :: ED_P_2_HD_PRP_P !< Map ElastoDyn PlatformPtMesh to HydroDyn platform reference Point [-] TYPE(MeshMapType) :: ED_P_2_HD_W_P !< Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point [-] TYPE(MeshMapType) :: HD_W_P_2_ED_P !< Map HydroDyn WAMIT Point (from either y%WAMITMesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh [-] TYPE(MeshMapType) :: ED_P_2_HD_M_P !< Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point [-] @@ -23440,6 +23441,9 @@ SUBROUTINE FAST_CopyModuleMapType( SrcModuleMapTypeData, DstModuleMapTypeData, C IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_PRP_P, DstModuleMapTypeData%ED_P_2_HD_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_W_P, DstModuleMapTypeData%ED_P_2_HD_W_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -23742,6 +23746,7 @@ SUBROUTINE FAST_DestroyModuleMapType( ModuleMapTypeData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ModuleMapTypeData%ED_P_2_BD_P_Hub) ENDIF + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_PRP_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_W_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_W_P_2_ED_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_M_P, ErrStat, ErrMsg ) @@ -23941,6 +23946,23 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF END DO END IF + Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_PRP_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_HD_PRP_P + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_HD_PRP_P + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_HD_PRP_P + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_W_P: size of buffers for each call to pack subtype CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_W_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -24885,6 +24907,34 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ENDIF END DO END IF + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_W_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -26442,6 +26492,46 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) ! ED_P_2_HD_PRP_P + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index 6596b7c8b..ad5bc1d13 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -117,16 +117,16 @@ - + - - - - + + + + @@ -135,25 +135,25 @@ - - + + - - - + - + - + + + @@ -165,25 +165,25 @@ - - + + - - - + - + - + + + @@ -191,25 +191,25 @@ - - + + - - - + - + - + + + @@ -217,25 +217,25 @@ - - + + - - - + - + - + + + @@ -243,25 +243,25 @@ - - + + - - - + - + - + + + @@ -282,25 +282,25 @@ - - + + - - - + - + - + + + @@ -311,25 +311,25 @@ - - + + - - - + - + - + + + @@ -342,25 +342,25 @@ - - + + - - - + - + - + + + @@ -372,25 +372,25 @@ - - + + - - - + - + - + + + @@ -403,25 +403,25 @@ - - + + - - - + - + - + + + @@ -432,25 +432,25 @@ - - + + - - - + - + - + + + @@ -464,25 +464,25 @@ - - + + - - - + - + - + + + @@ -490,25 +490,25 @@ - - + + - - - + - + - + + + @@ -516,25 +516,25 @@ - - + + - - - + - + - + + + @@ -542,25 +542,25 @@ - - + + - - - + - + - + + + @@ -568,25 +568,25 @@ - - + + - - - + - + - + + + @@ -594,25 +594,25 @@ - - + + - - - + - + - + + + @@ -620,50 +620,50 @@ - - + + - - - + - + - + + + - - + + - - - + - + - + + + @@ -672,50 +672,50 @@ - - + + - - - + - + - + + + - - + + - - - + - + - + + + @@ -745,25 +745,25 @@ - - + + - - - + - + - + + + @@ -773,25 +773,25 @@ - - + + - - - + - + - + + + @@ -814,25 +814,25 @@ - - + + - - - + - + - + + + @@ -840,25 +840,25 @@ - - + + - - - + - + - + + + @@ -866,25 +866,25 @@ - - + + - - - + - + - + + + @@ -892,25 +892,25 @@ - - + + - - - + - + - + + + @@ -918,25 +918,25 @@ - - + + - - - + - + - + + + @@ -944,25 +944,25 @@ - - + + - - - + - + - + + + @@ -970,25 +970,25 @@ - - + + - - - + - + - + + + @@ -996,25 +996,25 @@ - - + + - - - + - + - + + + @@ -1034,25 +1034,25 @@ - - + + - - - + - + - + + + @@ -1062,26 +1062,26 @@ - - - + + + - - - + - + - + + + @@ -1089,25 +1089,25 @@ - - + + - - - + - + - + + + @@ -1118,25 +1118,25 @@ - - + + - - - + - + - + + + @@ -1148,25 +1148,25 @@ - - + + - - - + - + - + + + @@ -1178,25 +1178,25 @@ - - + + - - - + - + - + + + @@ -1204,25 +1204,25 @@ - - + + - - - + - + - + + + @@ -1230,50 +1230,50 @@ - - + + - - - + - + - + + + - - + + - - - + - + - + + + @@ -1296,42 +1296,42 @@ - + - + - - + + - - + + - - - + - + - + + + @@ -1342,25 +1342,25 @@ - - + + - - - + - + - + + + @@ -1368,25 +1368,25 @@ - - + + - - - + - + - + + + @@ -1402,25 +1402,25 @@ - - + + - - - + - + - + + + @@ -1434,25 +1434,25 @@ - - + + - - - + - + - + + + diff --git a/vs-build/MAPlib/MAP_dll.vcxproj b/vs-build/MAPlib/MAP_dll.vcxproj index f1df704ea..5f096038d 100644 --- a/vs-build/MAPlib/MAP_dll.vcxproj +++ b/vs-build/MAPlib/MAP_dll.vcxproj @@ -28,26 +28,52 @@ DynamicLibrary true - v140 + v142 + Unicode + + + DynamicLibrary + true + v142 Unicode DynamicLibrary true - v140 + v142 + Unicode + + + DynamicLibrary + true + v142 Unicode DynamicLibrary false - v140 + v142 + true + Unicode + + + DynamicLibrary + false + v142 true Unicode DynamicLibrary false - v140 + v142 + true + Unicode + + + DynamicLibrary + false + v142 true Unicode diff --git a/vs-build/Registry/FAST_Registry.vcxproj b/vs-build/Registry/FAST_Registry.vcxproj index 40649f85f..f770733e6 100644 --- a/vs-build/Registry/FAST_Registry.vcxproj +++ b/vs-build/Registry/FAST_Registry.vcxproj @@ -28,27 +28,79 @@ Application true Unicode - v140 + v142 + + + Application + true + Unicode + v142 + + + Application + true + Unicode + v142 Application true Unicode - v140 + v142 + + + Application + true + Unicode + v142 + + + Application + true + Unicode + v142 Application false true Unicode - v140 + v142 + + + Application + false + true + Unicode + v142 + + + Application + false + true + Unicode + v142 Application false true Unicode - v140 + v142 + + + Application + false + true + Unicode + v142 + + + Application + false + true + Unicode + v142 From 410024bc21b85d60106770c7e9886efcdcaec760 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 16 Dec 2019 17:28:27 -0700 Subject: [PATCH 074/377] FlexSub: using a generic function to remove matrix DOF --- modules/subdyn/src/SD_FEM.f90 | 40 ++++++++++++- modules/subdyn/src/SubDyn.f90 | 87 ++++++++++------------------- modules/subdyn/src/SubDyn_Tests.f90 | 3 +- 3 files changed, 68 insertions(+), 62 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index be5d262ef..ddec9bac8 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -69,7 +69,42 @@ MODULE SD_FEM CONTAINS +!------------------------------------------------------------------------------------------------------ +!> Remove degrees of freedom from a matrix (lines and rows) +!! Generic function +SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) + REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix + logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) + REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER :: I, J ! counters into full matrix + INTEGER :: Ir, Jr ! counters into reduced matrix + INTEGER :: nr ! number of reduced DOF + ErrStat = ErrID_None + ErrMsg = '' + + nr= count(bDOF) + CALL AllocAry(Ared, nr, nr, 'Ared', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return + + ! Remove rows and columns from A when bDOF is + Jr=0 + do J = 1, size(A,1) + if (bDOF(J)) then + Jr=Jr+1 + Ir=0 + do I = 1, size(A,1) + if (bDOF(I)) then + Ir=Ir+1 + Ared(Ir, Jr) = REAL( A(I, J), LAKi ) + end if + end do + endif + end do +END SUBROUTINE RemoveDOF +!------------------------------------------------------------------------------------------------------ !> Maps nodes to elements !! allocate NodesConnE and NodesConnN SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) @@ -577,6 +612,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear INTEGER(IntKi) :: eType !< Member type + REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element INTEGER(IntKi) :: ErrStat2 CHARACTER(1024) :: ErrMsg2 ErrMsg = "" @@ -595,7 +631,9 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) eType = p%Elems(I, iMType) ! --- Properties common to all element types: L, DirCos (and Area and rho) - CALL GetDirCos(Init%Nodes(N1,2:4), Init%Nodes(N2,2:4), DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos + Point1 = Init%Nodes(N1,2:4) + Point2 = Init%Nodes(N2,2:4) + CALL GetDirCos(Point1, Point2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos p%ElemProps(i)%eType = eType p%ElemProps(i)%Length = L p%ElemProps(i)%DirCos = DirCos diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 9d27336ba..1d4245bfc 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1953,13 +1953,13 @@ END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors, Phi, -SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, ErrMsg ) +SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init,p, Phi, Omega, ErrStat, ErrMsg ) USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix INTEGER, INTENT(IN ) :: NOmega ! RRD: no. of requested eigenvalues - LOGICAL, INTENT(IN ) :: Reduced ! Whether or not to reduce matrices, this will be removed altogether later, when reduction will be done apriori + LOGICAL, INTENT(IN ) :: bRemoveConstraints ! Whether or not to reduce matrices, this will be removed altogether later, when reduction will be done apriori TYPE(SD_InitType), INTENT(IN ) :: Init TYPE(SD_ParameterType), INTENT(IN ) :: p REAL(ReKi), INTENT( OUT) :: Phi(nDOF, NOmega) ! RRD: Returned Eigenvectors @@ -1982,14 +1982,14 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, ErrMsg = '' !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! - IF (Reduced) THEN !bjj: i.e., We need to reduce; it's not reduced yet + IF (bRemoveConstraints) THEN ! First I need to remove constrained nodes DOFs ! This is actually done when we are printing out the 'full' set of eigenvalues - CALL ReduceKMdofs(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return - CALL ReduceKMdofs(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RemoveBCConstraints(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RemoveBCConstraints(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return N=SIZE(Kred,1) ELSE - ! This is actually done whe we are generating the CB-reduced set of eigenvalues, so the the variable 'Reduced' can be a bit confusing. GJH 8/1/13 + ! This is actually done whe we are generating the CB-reduced set of eigenvalues N=SIZE(K,1) CALL AllocAry( Kred, n, n, 'Kred', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry( Mred, n, n, 'Mred', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -2012,7 +2012,7 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, CALL AllocAry( ALPHAI, n, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( BETA, n, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( VR, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( VL, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( VL, n, n, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( KEY, n, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return CALL LAPACK_ggev('N','V',N ,Kred, Mred, ALPHAR, ALPHAI, BETA, VL, VR, work, lwork, ErrStat2, ErrMsg2) @@ -2050,10 +2050,10 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, Reduced, Init,p, Phi, Omega, ErrStat, ! --- Finish EigenSolve ! Note: NOmega must be <= N, which is the length of Omega2, Phi! Omega=SQRT( Omega2(1:NOmega) ) !Assign my new Omega and below my new Phi (eigenvectors) [eigenvalues are actually the square of omega] - IF ( Reduced ) THEN ! this is called for the full system Eigenvalues: + IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: !Need to expand eigenvectors for removed DOFs, setting Phi CALL UnReduceVRdofs(VR(:,1:NOmega),Phi,N,NOmega, Init,p, ErrStat2, ErrMsg2 ) ; if(Failed()) return - ELSE ! IF (.NOT.(Reduced)) THEN !For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR + ELSE ! For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR ! This is done as part of the CB-reduced eigensolve Phi=REAL( VR(:,1:NOmega), ReKi ) ! eigenvectors ENDIF @@ -2086,20 +2086,18 @@ END SUBROUTINE EigenSolve !------------------------------------------------------------------------------------------------------ !> Calculate Kred from K after removing consstrained node DOFs from the full M and K matrices !!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed -SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) +SUBROUTINE RemoveBCConstraints(Ared,A,TDOF, Init,p, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT( in) :: Init TYPE(SD_ParameterType), INTENT( in) :: p INTEGER, INTENT(IN ) :: TDOF ! Size of matrix K (total DOFs) - REAL(ReKi), INTENT(IN ) :: K(TDOF, TDOF) ! full matrix - REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Kred(:,:) ! reduced matrix + REAL(ReKi), INTENT(IN ) :: A(TDOF, TDOF) ! full matrix + REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals - INTEGER :: I, J ! counters into full or reduced matrix - INTEGER :: L ! number of DOFs to eliminate - INTEGER, ALLOCATABLE :: idx(:) ! vector to map reduced matrix to full matrix + INTEGER :: I ! counters into full or reduced matrix + logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) INTEGER :: NReactDOFs - INTEGER :: DOF_reduced INTEGER :: ErrStat2 CHARACTER(1024) :: ErrMsg2 @@ -2109,60 +2107,31 @@ SUBROUTINE ReduceKMdofs(Kred,K,TDOF, Init,p, ErrStat, ErrMsg ) NReactDOFs = p%NReact*6 !p%DOFC IF (NReactDOFs > TDOF) THEN ErrStat = ErrID_Fatal - ErrMsg = 'ReduceKMdofs:invalid matrix sizes.' + ErrMsg = 'RemoveBCConstraints:invalid matrix sizes.' RETURN END IF - CALL AllocAry(idx, TDOF, 'idx', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') + CALL AllocAry(bDOF, TDOF, 'bDOF', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'RemoveBCConstraints') IF (ErrStat >= AbortErrLev) THEN RETURN END IF - - ! Calculate how many rows/columns need to be eliminated: - DO I = 1, TDOF - idx(I) = I - END DO - - L = 0 + + ! Setting array of DOF, true if we keep them + bDOF(1:TDOF)=.True. DO I = 1, NReactDOFs !Cycle on reaction DOFs IF (Init%BCs(I, 2) == 1) THEN - L=L+1 !number of DOFs to eliminate - idx( Init%BCs(I, 1) ) = 0 ! Eliminate this one + bDOF(Init%BCs(I, 1)) = .False. ! Eliminate this one END IF END DO - - ! Allocate the output matrix and the index mapping array - DOF_reduced = TDOF-L - CALL AllocAry(Kred, DOF_reduced, DOF_reduced, 'Kred', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'ReduceKMdofs') - IF (ErrStat >= AbortErrLev) THEN - CALL CleanUp() - RETURN - END IF - - ! set the indices we want to keep (i.e., a mapping from reduced to full matrix) - J = 1 - DO I=1,TDOF - idx(J) = idx(I) - IF ( idx(J) /= 0 ) J = J + 1 - END DO - - ! Remove rows and columns from every row/column in full matrix where Init%BC(:,2) == 1, - ! using the mapping created above. (This is a symmetric matrix.) - DO J = 1, DOF_reduced !Cycle on reaction DOFs - DO I = 1, DOF_reduced !Cycle on reaction DOFs - Kred(I,J) = REAL( K( idx(I), idx(J) ), LAKi ) - END DO - END DO - ! clean up local variables: - CALL CleanUp() -CONTAINS - subroutine CleanUp() - IF (ALLOCATED(idx)) DEALLOCATE(idx) - end subroutine -END SUBROUTINE ReduceKMdofs + ! --- Creating Ared = A[bDOF,bDOF], reduced version + call RemoveDOF(A, bDOF, Ared, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'RemoveBCConstraints') + deallocate(bDOF) +END SUBROUTINE RemoveBCConstraints + + !------------------------------------------------------------------------------------------------------ -!> Augments VRred to VR for the constrained DOFs, somehow reversing what ReducedKM did for matrices +!> Augments VRred to VR for the constrained DOFs, somehow reversing what RemoveBCConstraints did for matrices !Note it works for constrained nodes, still to see how to make it work for interface nodes if needed SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT(in ) :: Init @@ -2551,7 +2520,7 @@ SUBROUTINE ConstructUFL( u, p, UFL ) ! note that p%DOFL = p%NNodes_L*6 DO I = 1, p%NNodes_L !Only interior nodes here ! starting index in the master arrays for the current node - startDOF = (I-1)*6 + 1 + startDOF = (I-1)*6 + 1 ! TODO ! index into the Y2Mesh J = p%NNodes_I + I ! Construct UFL array from the Force and Moment fields of the input mesh diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index efba2f9c1..3add94653 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -102,8 +102,7 @@ subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) if(bTest) then if(cpt>0) then call test_fail(InfoAbs) - STOP -1 !OTHER-COMPILER - STOP ! COMPAQ-COMPILER + STOP else call test_success(InfoAbs) endif From 80d19574079421169efc7b8768c2556d9ea4d0ec Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 16 Dec 2019 18:14:06 -0700 Subject: [PATCH 075/377] FlexSub: using a generic function to insert matrix DOF --- modules/subdyn/src/SD_FEM.f90 | 40 ++++++++++++++++++++- modules/subdyn/src/SubDyn.f90 | 67 +++++++++++++++-------------------- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ddec9bac8..375cf959f 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -71,7 +71,6 @@ MODULE SD_FEM CONTAINS !------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) -!! Generic function SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) @@ -103,6 +102,45 @@ SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) endif end do END SUBROUTINE RemoveDOF + +!> Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) +SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) + REAL(LAKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix + logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) + REAL(ReKi), INTENT(IN ) :: DefaultVal ! Default value to fill the + REAL(ReKi) , INTENT(INOUT) :: A(:,:) ! Full matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER :: I ! counter into full matrix + INTEGER :: Ir ! counter into reduced matrix + INTEGER :: n ! number of DOF (fullsystem) + ErrStat = ErrID_None + ErrMsg = '' + n= size(bDOF) + IF ( size(Ared,1) > n) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'InsertDOFrows: Number of reduced rows needs to be lower than full system rows' + RETURN + END IF + IF ( size(Ared,2) /= size(A,2) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'InsertDOFrows: Inconsistent number of columns between A and Ared' + RETURN + END IF + !CALL AllocAry(A, n, size(Ared,2), 'A', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return + + ! Use rows from Ared when bDOF is true, use default value otherwise + ir=0 ! initialize + do i=1,n + if (bDOF(i)) then + ir =ir +1 + A(i,:)=real( Ared(ir,:), ReKi ) + else + A(i,:)=DefaultVal + endif + enddo +END SUBROUTINE InsertDOFrows !------------------------------------------------------------------------------------------------------ !> Maps nodes to elements diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 1d4245bfc..5dbd116ae 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1953,7 +1953,7 @@ END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors, Phi, -SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init,p, Phi, Omega, ErrStat, ErrMsg ) +SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega, ErrStat, ErrMsg ) USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix @@ -1977,16 +1977,19 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init,p, Phi, Omega INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 + logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) ErrStat = ErrID_None ErrMsg = '' !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! IF (bRemoveConstraints) THEN - ! First I need to remove constrained nodes DOFs + ! Removing constrained nodes DOFs ! This is actually done when we are printing out the 'full' set of eigenvalues - CALL RemoveBCConstraints(Kred,K,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return - CALL RemoveBCConstraints(Mred,M,nDOF, Init,p, ErrStat2, ErrMsg2 ); if(Failed()) return + ! Mred = M[bDOF,bDOF], Kred = K[bDOF,bDOF] + call SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(M, bDOF, Mred, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(M, bDOF, Kred, ErrStat2, ErrMsg2); if(Failed()) return N=SIZE(Kred,1) ELSE ! This is actually done whe we are generating the CB-reduced set of eigenvalues @@ -2031,7 +2034,7 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init,p, Phi, Omega Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) END IF ENDDO - CALL ScaLAPACK_LASRT('I',N,Omega2,key,ErrStat2,ErrMsg2); if(Failed()) return + CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return !we need to rearrange eigenvectors based on sorting of Omega2 !Now rearrange VR based on the new key, also I might have to scale the eigenvectors following generalized mass =idnetity criterion, also if i reduced the matrix I will need to re-expand the eigenvector @@ -2052,7 +2055,7 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init,p, Phi, Omega Omega=SQRT( Omega2(1:NOmega) ) !Assign my new Omega and below my new Phi (eigenvectors) [eigenvalues are actually the square of omega] IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: !Need to expand eigenvectors for removed DOFs, setting Phi - CALL UnReduceVRdofs(VR(:,1:NOmega),Phi,N,NOmega, Init,p, ErrStat2, ErrMsg2 ) ; if(Failed()) return + CALL InsertDOFrows(VR(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return ELSE ! For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR ! This is done as part of the CB-reduced eigensolve Phi=REAL( VR(:,1:NOmega), ReKi ) ! eigenvectors @@ -2079,54 +2082,42 @@ SUBROUTINE CleanupEigen() IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) IF (ALLOCATED(Kred) ) DEALLOCATE(Kred) IF (ALLOCATED(Mred) ) DEALLOCATE(Mred) + IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolve -!------------------------------------------------------------------------------------------------------ -!> Calculate Kred from K after removing consstrained node DOFs from the full M and K matrices -!!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed -SUBROUTINE RemoveBCConstraints(Ared,A,TDOF, Init,p, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT( in) :: Init - TYPE(SD_ParameterType), INTENT( in) :: p - INTEGER, INTENT(IN ) :: TDOF ! Size of matrix K (total DOFs) - REAL(ReKi), INTENT(IN ) :: A(TDOF, TDOF) ! full matrix - REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +!> Returns a list of boolean which are true if a DOF is not part of a BC constraint +SUBROUTINE SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT( in) :: Init + TYPE(SD_ParameterType), INTENT( in) :: p + INTEGER(IntKi), INTENT( in) :: nDOF + LOGICAL, ALLOCATABLE, INTENT( out) :: bDOF(:) ! Mask, False for DOF that are Constraints BC DOF + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals INTEGER :: I ! counters into full or reduced matrix - logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) INTEGER :: NReactDOFs - INTEGER :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 - ErrStat = ErrID_None ErrMsg = '' - + NReactDOFs = p%NReact*6 !p%DOFC - IF (NReactDOFs > TDOF) THEN + IF (NReactDOFs > nDOF) THEN ErrStat = ErrID_Fatal - ErrMsg = 'RemoveBCConstraints:invalid matrix sizes.' + ErrMsg = 'SelectNonBCConstraintsDOF: invalid matrix sizes.' RETURN END IF - - CALL AllocAry(bDOF, TDOF, 'bDOF', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'RemoveBCConstraints') - IF (ErrStat >= AbortErrLev) THEN - RETURN - END IF + + CALL AllocAry(bDOF, nDOF, 'bDOF', ErrStat, ErrMsg ); IF (ErrStat >= AbortErrLev) RETURN ! Setting array of DOF, true if we keep them - bDOF(1:TDOF)=.True. - DO I = 1, NReactDOFs !Cycle on reaction DOFs - IF (Init%BCs(I, 2) == 1) THEN + bDOF(1:nDOF)=.True. + do I = 1, NReactDOFs !Cycle on reaction DOFs + if (Init%BCs(I, 2) == 1) THEN bDOF(Init%BCs(I, 1)) = .False. ! Eliminate this one - END IF - END DO - ! --- Creating Ared = A[bDOF,bDOF], reduced version - call RemoveDOF(A, bDOF, Ared, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,'RemoveBCConstraints') - deallocate(bDOF) -END SUBROUTINE RemoveBCConstraints + end if + end do +END SUBROUTINE From 9fa1056d9635169fb37356dc1522c24b551f3e81 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 17 Dec 2019 14:27:30 -0700 Subject: [PATCH 076/377] TCF: update FAST glue code for changes in WAMIT mesh name --- modules/openfast-library/src/FAST_Lin.f90 | 12 ++++++------ modules/openfast-library/src/FAST_Solver.f90 | 14 +++++++------- modules/openfast-library/src/FAST_Subs.f90 | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 428c4fe6b..8d040edab 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -1753,7 +1753,7 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, ! we're just going to assume u_ED%PlatformPtMesh is committed - if ( HD%y%AllHdroOrigin%Committed ) then ! meshes for floating + if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) @@ -1761,7 +1761,7 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, ! we're mapping loads, so we also need the sibling meshes' displacements: HD_Start = Indx_u_HD_PlatformRef_Start(HD%Input(1), y_FAST) - call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) ! HD is source in the mapping, so we want M_{uSm} @@ -2177,13 +2177,13 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, ! we're just going to assume u_ED%PlatformPtMesh is committed - if ( HD%y%AllHdroOrigin%Committed ) then ! meshes for floating + if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices !!! ! while forming dUdy, too. - ! call Linearize_Point_to_Point( HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + ! call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations HD_Out_Start = Indx_y_HD_AllHdro_Start(HD%y, y_FAST) ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Loads(HD%y%AllHdroOrigin, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) + call Assemble_dUdy_Loads(HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) @@ -3745,7 +3745,7 @@ FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) END FUNCTION Indx_y_HD_PlatformRef_Start !---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the y_HD%AllHdroOrigin mesh in the FAST linearization outputs. +!> This routine returns the starting index for the y_HD%WAMITMesh mesh in the FAST linearization outputs. FUNCTION Indx_y_HD_AllHdro_Start(y_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 1b8a17746..09b64cc7d 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -1721,7 +1721,7 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh) !u_HD and u_mapped_positions contain the displaced positions for load calculations CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force @@ -2799,7 +2799,7 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, !.................. ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh) !u_HD and u_mapped_positions contain the displaced positions for load calculations CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) ELSE @@ -3738,7 +3738,7 @@ SUBROUTINE ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp IF (HD%Input(1)%WAMITMesh%Committed) THEN HD%Input(1)%WAMITMesh%RemapFlag = .FALSE. HD%y%WAMITMesh%RemapFlag = .FALSE. - HD%y%AllHdroOrigin%RemapFlag = .FALSE. + HD%y%WAMITMesh%RemapFlag = .FALSE. END IF IF (HD%Input(1)%Morison%LumpedMesh%Committed) THEN HD%Input(1)%Morison%LumpedMesh%RemapFlag = .FALSE. @@ -4059,21 +4059,21 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M ! we're just going to assume ED%Input(1)%PlatformPtMesh is committed - IF ( HD%y%AllHdroOrigin%Committed ) THEN ! meshes for floating + IF ( HD%y%WAMITMesh%Committed ) THEN ! meshes for floating ! HydroDyn WAMIT point mesh to/from ElastoDyn point mesh - CALL MeshMapCreate( HD%y%AllHdroOrigin, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( HD%y%WAMITMesh, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) END IF - ! ElastoDyn point mesh HydroDyn Morison point mesh (ED sets inputs, but gets outputs from HD%y%AllHdroOrigin in floating case) + ! ElastoDyn point mesh HydroDyn Morison point mesh (ED sets inputs, but gets outputs from HD%y%WAMITMesh in floating case) IF ( HD%Input(1)%Morison%LumpedMesh%Committed ) THEN CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_M_P' ) END IF - ! ElastoDyn point mesh to HydroDyn Morison line mesh (ED sets inputs, but gets outputs from HD%y%AllHdroOrigin in floating case) + ! ElastoDyn point mesh to HydroDyn Morison line mesh (ED sets inputs, but gets outputs from HD%y%WAMITMesh in floating case) IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_M_L' ) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 1d15e49a0..5d99f6a41 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -5143,7 +5143,7 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD14, AD, IfW, O !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%OutFileRoot)//'.HD_MorisonDistrib_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WAMITMesh, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) outputFields = .false. else call MeshWrVTK(p_FAST%TurbinePos, HD%y%WAMITMesh, trim(VTK_path)//'.HD_WAMITMesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) @@ -5306,7 +5306,7 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD14, AD, IfW, IF ( p_FAST%CompHydro == Module_HD ) THEN if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WAMITMesh, trim(VTK_path)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, Twidth, HD%Input(1)%WAMITMesh ) outputFields = .false. else OutputFields = p_FAST%VTK_fields From b99c10c547cf213522129dc37db6127646ba41e1 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 18 Dec 2019 17:23:14 -0700 Subject: [PATCH 077/377] Merged the r-test updates from dev The tests all attempt to run, so the input files are at least compatible with the code base --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index a4f1e449a..3f0a62739 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit a4f1e449a2b3abab25f2bbb0d8e72702b942bc2e +Subproject commit 3f0a62739887cf00e59de7a7363b4c27920ea350 From cdb7e4212a2dfd2614901582b4b3a51288b28645 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 18 Dec 2019 19:45:07 -0700 Subject: [PATCH 078/377] [BugFix] missing copy for Conv_Rdtn_UpdateStates Also some improvements to the error handling in that routine. Also fix to bug in trying to allocate the wrong array in WAMIT2 initialization --- modules/hydrodyn/src/Conv_Radiation.f90 | 17 +++++++++++------ modules/hydrodyn/src/HydroDyn.f90 | 16 ++++++++-------- modules/hydrodyn/src/WAMIT.f90 | 4 ---- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/hydrodyn/src/Conv_Radiation.f90 b/modules/hydrodyn/src/Conv_Radiation.f90 index c510bacf2..4f8d74077 100644 --- a/modules/hydrodyn/src/Conv_Radiation.f90 +++ b/modules/hydrodyn/src/Conv_Radiation.f90 @@ -469,7 +469,8 @@ SUBROUTINE Conv_Rdtn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherS TYPE(Conv_Rdtn_InputType) :: u !< Instantaneous inputs INTEGER(IntKi) :: ErrStat2 !< Error status of the operation (secondary error) CHARACTER(ErrMsgLen) :: ErrMsg2 !< Error message if ErrStat2 /= ErrID_None - + character(*), parameter :: RoutineName = 'Conv_Rdtn_UpdateStates' + ! Initialize variables @@ -482,8 +483,12 @@ SUBROUTINE Conv_Rdtn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherS ! Get the inputs at time t, based on the array of values sent by the glue code: + call Conv_Rdtn_CopyInput( Inputs(1), u, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + - CALL Conv_Rdtn_Input_ExtrapInterp( Inputs, InputTimes, u, t, ErrStat, ErrMsg ) + CALL Conv_Rdtn_Input_ExtrapInterp( Inputs, InputTimes, u, t, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -491,7 +496,8 @@ SUBROUTINE Conv_Rdtn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherS ! Note that xd [discrete state] is changed in Conv_Rdtn_UpdateDiscState() so xd will now contain values at t+Interval ! We'll first make a copy that contains xd at time t, which will be used in computing the constraint states - CALL Conv_Rdtn_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + CALL Conv_Rdtn_UpdateDiscState( t, n, u, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ! Integrate (update) continuous states (x) here: @@ -630,9 +636,8 @@ SUBROUTINE Conv_Rdtn_UpdateDiscState( Time, n, u, p, x, xd, z, OtherState, m, Er ErrStat = ErrID_None ErrMsg = "" - - - + + ! Find the index xd%IndRdtn, where RdtnTime(IndRdtn) is the largest value in ! RdtnTime(:) that is less than or equal to Time and find the amount of ! time remaining from this calculation: diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index f3681b37f..2fdec3ecb 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1034,18 +1034,18 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitLocal%WAMIT2%NBody = InitLocal%NBody ! The WAMIT2 object will contain all NBody WAMIT2 bodies ! Allocate WAMIT2 InitInp arrays based on NBodyMod and copy the inputfile data into the WAMIT2 init data (entire arrays' worth for NBodyMod=1 - call AllocAry( InitLocal%WAMIT%PtfmRefxt , InitLocal%NBody, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefyt , InitLocal%NBody, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefzt , InitLocal%NBody, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefztRot, InitLocal%NBody, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefxt , InitLocal%NBody, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefyt , InitLocal%NBody, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefzt , InitLocal%NBody, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefztRot, InitLocal%NBody, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) else InitLocal%WAMIT2%NBody = 1_IntKi ! The WAMIT2 object will contain all NBody WAMIT2 bodies ! Allocate WAMIT2 InitInp arrays based on NBodyMod and copy the inputfile data into the 1st WAMIT body init data for NBodyMod > 1 - call AllocAry( InitLocal%WAMIT%PtfmRefxt , 1, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefyt , 1, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefzt , 1, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call AllocAry( InitLocal%WAMIT%PtfmRefztRot, 1, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefxt , 1, "PtfmRefxt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefyt , 1, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefzt , 1, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call AllocAry( InitLocal%WAMIT2%PtfmRefztRot, 1, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) endif diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 26b760893..6da101e79 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -1496,10 +1496,6 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState nTime = size(Inputs) - - - - IF ( p%RdtnMod == 1 ) THEN ! Update the convolution radiation memory effect sub-module's state ! Allocate array of Conv_Rdtn inputs From c2075ca20c2d0ed22e77d622495ae2f04f2d3e59 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2019 09:55:22 -0700 Subject: [PATCH 079/377] Update pointer to r-test. All HD test cases run, except for the subdyn ones (think SD might getting the wrong mesh in the glue code from HD -- something to figure out sometime). --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index 3f0a62739..ed4e66186 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 3f0a62739887cf00e59de7a7363b4c27920ea350 +Subproject commit ed4e6618670108527a6071c6a91d8fe504d37b18 From 503157e67be1945afb984d926ee732e4aeb482f4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 19 Dec 2019 11:44:59 -0700 Subject: [PATCH 080/377] FlexSub: setting up rigid assemblies and couting number of DOF after elimination --- modules/subdyn/src/IntegerList.f90 | 61 ++++-- modules/subdyn/src/SD_FEM.f90 | 302 +++++++++++++++++++++++++++- modules/subdyn/src/SubDyn.f90 | 19 +- modules/subdyn/src/SubDyn_Tests.f90 | 4 +- 4 files changed, 357 insertions(+), 29 deletions(-) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index d08c698f9..b2dfcb7a1 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -8,7 +8,8 @@ module IntegerList public :: IList - public :: init + public :: init_list + public :: destroy_list public :: len public :: append public :: pop @@ -16,10 +17,14 @@ module IntegerList public :: find public :: sort public :: reverse + interface pop + module procedure pop_last + module procedure pop_item + end interface contains !> Initialize an integer list - subroutine init(L,n,default_val,ErrStat,ErrMsg) + subroutine init_list(L,n,default_val,ErrStat,ErrMsg) type(IList), intent(inout) :: L !< List integer(IntKi), intent(in) :: n !< number of initial values integer(IntKi), intent(in) :: default_val !< default values @@ -32,7 +37,17 @@ subroutine init(L,n,default_val,ErrStat,ErrMsg) if (ErrStat/=ErrID_None) return L%List(1:n) = default_val - end subroutine init + end subroutine init_list + + !> Deallocate list + subroutine destroy_list(L,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) deallocate(L%List) + end subroutine destroy_list !> Returns list length integer function len(L) @@ -55,7 +70,7 @@ subroutine append(L,e, ErrStat, ErrMsg) if (allocated(L%List)) then call resize_array(L%List,len(L)+1,e) else - call init(L, 1, e, ErrStat, ErrMsg) + call init_list(L, 1, e, ErrStat, ErrMsg) endif end subroutine append @@ -77,7 +92,7 @@ integer function get(L,i, ErrStat, ErrMsg) end function get !> Pop last element of the list and reduce list size by 1 - integer function pop(L,ErrStat,ErrMsg) + integer function pop_last(L,ErrStat,ErrMsg) type(IList), intent(inout) :: L integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None @@ -85,9 +100,24 @@ integer function pop(L,ErrStat,ErrMsg) ErrStat = ErrID_None ErrMsg = "" n=len(L) - pop = get(L, n, ErrStat, ErrMsg) ! index array out of bound will be thrown + pop_last = get(L, n, ErrStat, ErrMsg) ! index array out of bound will be thrown call resize_array(L%List,n-1,0) - end function pop + end function pop_last + + !> Pop element i from the list and reduce the size of the list by 1 + integer function pop_item(L,i,ErrStat,ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: i + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + pop_item = get(L, i, ErrStat, ErrMsg) ! index array out of bound will be thrown + L%List(i:n-1)=L%List(i+1:n) + call resize_array(L%List,n-1,0) + end function pop_item !> Sort list subroutine sort(L, ErrStat, ErrMsg) @@ -137,17 +167,20 @@ integer(IntKi) function find(L, e, ErrStat, ErrMsg) character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None ErrStat = ErrID_None ErrMsg = "" - if (allocated(L%List)) then - find = binary_search(L%List, e) + if (len(L)>0) then + find = binary_search(L%List, e) ! Binary search returns index for inequality List(i)<=e + if (find>0) then + if (L%List(find)/=e) then + find=-1 + endif + endif else - ErrStat=ErrID_Fatal - ErrMsg="Cannot find in an unallocated list" - find=0 + find=-1 endif end function find !> Print - subroutine print(L, varname, u_opt) + subroutine print_list(L, varname, u_opt) type(IList), intent(in) :: L character(len=*),intent(in) :: varname integer(IntKi), intent(in),optional :: u_opt @@ -169,7 +202,7 @@ subroutine print(L, varname, u_opt) else write(u,'(A,A)') varname,'=[];' endif - end subroutine print + end subroutine print_list ! -------------------------------------------------------------------------------- ! --- Generic helper functions (should be part of NWTC library) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 375cf959f..3ad6127bd 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -192,6 +192,62 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) ENDDO END SUBROUTINE NodeCon + +!---------------------------------------------------------------------------- +!> Check if two elements are connected +!! returns true if they are, and return which node (1 or 2) of each element is involved +LOGICAL FUNCTION ElementsConnected(p, ie1, ie2, iWhichNode_e1, iWhichNode_e2) + TYPE(SD_ParameterType), INTENT(IN) :: p + INTEGER(IntKi), INTENT(IN) :: ie1, ie2 ! Indices of elements + INTEGER(IntKi), INTENT(OUT) :: iWhichNode_e1, iWhichNode_e2 ! 1 or 2 if node 1 or node 2 + if ((p%Elems(ie1, 2) == p%Elems(ie2, 2))) then ! node 1 connected to node 1 + iWhichNode_e1=1 + iWhichNode_e2=1 + ElementsConnected=.True. + else if((p%Elems(ie1, 2) == p%Elems(ie2, 3))) then ! node 1 connected to node 2 + iWhichNode_e1=1 + iWhichNode_e2=2 + ElementsConnected=.True. + else if((p%Elems(ie1, 3) == p%Elems(ie2, 2))) then ! node 2 connected to node 1 + iWhichNode_e1=2 + iWhichNode_e2=1 + ElementsConnected=.True. + else if((p%Elems(ie1, 3) == p%Elems(ie2, 3))) then ! node 2 connected to node 2 + iWhichNode_e1=2 + iWhichNode_e2=2 + ElementsConnected=.True. + else + ElementsConnected=.False. + iWhichNode_e1=-1 + iWhichNode_e2=-1 + endif +END FUNCTION ElementsConnected + +!> Loop through a list of elements and returns a list of unique joints +TYPE(IList) FUNCTION JointsList(p, Elements) + use IntegerList, only: init_list, append, find, sort + use IntegerList, only: print_list + TYPE(SD_ParameterType), INTENT(IN) :: p + integer(IntKi), dimension(:), INTENT(IN) :: Elements + integer(IntKi) :: ie, ei, j1, j2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + + call init_list(JointsList, 0, 0, ErrStat2, ErrMsg2) + do ie = 1, size(Elements) + ei = Elements(ie) ! Element index + j1 = p%Elems(ei,2) ! Joint 1 + j2 = p%Elems(ei,3) ! Joint 2 + ! Append joints indices if not in list already + if (find(JointsList, j1, ErrStat2, ErrMsg2)<=0) call append(JointsList, j1, ErrStat2, ErrMsg2) + if (find(JointsList, j2, ErrStat2, ErrMsg2)<=0) call append(JointsList, j2, ErrStat2, ErrMsg2) + ! Sorting required by find function + call sort(JointsList, ErrStat2, ErrMsg2) + enddo + call print_list(JointsList, 'Joint list') +END FUNCTION JointsList + + !---------------------------------------------------------------------------- !> ! - Removes the notion of "ID" and use Index instead @@ -292,7 +348,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) end if if (p%Elems(iMem,n)<=0) then - CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//'the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') + CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') endif END DO !n, loop through property ids ! Column 6: member type @@ -764,7 +820,7 @@ END SUBROUTINE SetElementProperties !! For other joint type -> Condensation of the 3 translational DOF !! -> Keeping 3 rotational DOF for each memeber connected to the joint SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) - use IntegerList, only: init_list => init , len + use IntegerList, only: init_list, len TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(IN ) :: p TYPE(SD_MiscVarType), INTENT(INOUT) :: m @@ -986,9 +1042,247 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END FUNCTION END SUBROUTINE AssembleKM +!------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector +SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_MiscVarType), INTENT(INOUT) :: m + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA + integer(IntKi) :: nDOF + ErrStat = ErrID_None + ErrMsg = "" + call RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat2, ErrMsg2); if(Failed()) return + + nDOF = nDOF_ConstraintReduced() + print*,'nDOF constraint elim', nDOF + deallocate(RAm1) + deallocate(RA) + deallocate(njRA) + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'DirectElimination') + Failed = ErrStat >= AbortErrLev + !if (Failed) call Cleanup_AssembleKM() + END FUNCTION Failed + + !SUBROUTINE Fatal(ErrMsg_in) + ! character(len=*), intent(in) :: ErrMsg_in + ! CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); + ! CALL CleanUp_AssembleKM() + !END SUBROUTINE Fatal + + !SUBROUTINE CleanUp_AssembleKM() + !pass + !END SUBROUTINE CleanUp_AssembleKM + + !> Returns number of DOF after constraint reduction (via the matrix T) + INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() + integer(IntKi) :: iNode + integer(IntKi) :: ia ! Index on rigid link assembly + integer(IntKi) :: m ! Number of elements connected to a joint + nDOF_ConstraintReduced = 0 + + ! Rigid assemblies contribution + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) + + ! Contribution from all the other joints + do iNode = 1, Init%NNode + m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + + if (Init%Nodes(iNode,iJointType) == idJointPin ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m + print*,'Node',iNode, 'is a pin joint' + + elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m + print*,'Node',iNode, 'is an universal joint' + + elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 3*m + print*,'Node',iNode, 'is a ball joint' + + elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p)) then + ! This joint is involved in a rigid link assembly, we skip it (accounted for above) + print*,'Node',iNode, 'is involved in a RA' + else + ! That's a regular Cantilever joint + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 + !print*,'Node',iNode, 'is a regular cantilever' + endif + else + ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal + endif + end do + END FUNCTION nDOF_ConstraintReduced +END SUBROUTINE DirectElimination +!------------------------------------------------------------------------------------------------------ +!> Returns list of rigid link elements (Er) +TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, append + use IntegerList, only: print_list + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: ie !< Index on elements + ErrStat = ErrID_None + ErrMsg = "" + ! --- Establish a list of rigid link elements + call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); + + do ie = 1, Init%NElem + if (p%ElemProps(ie)%eType == idMemberRigid) then + call append(RigidLinkElements, ie, ErrStat, ErrMsg); + endif + end do + call print_list(RigidLinkElements,'Rigid element list') +END FUNCTION RigidLinkElements + +!------------------------------------------------------------------------------------------------------ +!> Returns true if one of the element connected to the node is a rigid link +LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) + INTEGER(IntKi), INTENT(IN ) :: iJoint + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + ! Local variables + integer(IntKi) :: ie !< Loop index on elements + integer(IntKi) :: ei !< Element index + integer(IntKi) :: m ! Number of elements connected to a joint + + NodeHasRigidElem = .False. ! default return value + + ! Loop through elements connected to node J + do ie = 1, Init%NodesConnE(iJoint, 1) + ei = Init%NodesConnE(iJoint, ie+1) + if (p%ElemProps(ei)%eType == idMemberRigid) then + NodeHasRigidElem = .True. + return ! we exit as soon as one rigid member is found + endif + enddo +END FUNCTION NodeHasRigidElem + +!------------------------------------------------------------------------------------------------------ +!> Setup a list of rigid link assemblies (RA) +SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA + integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + ! Local variables + type(IList) :: Er !< List of rigid elements + type(IList) :: Ea !< List of elements in a rigid assembly + integer(IntKi) :: nRA !< Number of rigid assemblies + integer(IntKi) :: ie !< Index on elements + integer(IntKi) :: ia !< Index on assemblies + integer(IntKi) :: e0 !< Index of an element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(1024) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + allocate(RAm1(1:Init%NElem)) + RAm1(1:Init%NElem) = -1 + + ! --- Establish a list of rigid link elements + Er = RigidLinkElements(Init, p, ErrStat2, ErrMsg2) + nRA=0 + do while (len(Er)>0) + nRA=nRA+1 + ! Creating List Ea of elements of a given assembly + call init_list(Ea, 0, 0, ErrStat2, ErrMsg2); + e0 = pop(Er, ErrStat2, ErrMsg2); + call append(Ea, e0, ErrStat2, ErrMsg2); + call AddNeighbors(e0, Er, Ea) + call print_list(Ea,'Rigid assembly') + do ie = 1, len(Ea) + e0 = get(Ea, ie, ErrStat2, ErrMsg2) + RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to + enddo + call destroy_list(Ea, ErrStat2, ErrMsg2) + enddo + call destroy_list(Er, ErrStat2, ErrMsg2) + + ! --- Creating RA, array of lists of assembly elements. + ! Note: exactly the same as all the Ea created above, but we didn't know the total number of RA + allocate(RA(1:nRA)) + do ia = 1, nRA + call init_list(RA(ia), 0, 0, ErrStat2, ErrMsg2) + enddo + do ie = 1, Init%NElem + ia = RAm1(ie) ! Index of the assembly the element belongs to: RA^{-1}(ie) = ia + if (ia>0) then + call append(RA(ia), ie, ErrStat2, ErrMsg2) + endif + enddo + do ia = 1, nRA + call print_list(RA(ia),'Rigid assembly') + enddo + + ! --- Counting unique joints involved in Rigid assembly + allocate(njRA(1:nRA)) + do ia = 1, nRA + ! Getting list of joints involved in RA(ia) + Er = JointsList(p, RA(ia)%List) + njRA(ia) = len(Er) + call destroy_list(Er, ErrStat2, ErrMsg2) + enddo + print*,'njRA',njRA +CONTAINS + !> The neighbors of e0 (that are found within the list Er) are added to the list Ea + RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) + integer(IntKi), intent(in) :: e0 !< Index of an element + type(IList), intent(inout) :: Er !< List of rigid elements + type(IList), intent(inout) :: Ea !< List of elements in a rigid assembly + type(IList) :: En !< List of neighbors of e0 + integer (IntKi) :: ik + integer (IntKi) :: ek, ek2 + integer (IntKi) :: iWhichNode_e0, iWhichNode_ek + call init_list(En, 0, 0, ErrStat2, ErrMsg2) + ! Loop through all elements, setup list of e0-neighbors, add them to Ea, remove them from Er + ik=0 + do while (ik< len(Er)) + ik=ik+1 + ek = Er%List(ik) + if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then + print*,'Element ',ek,'is connected to ',e0,'via its node',iWhichNode_ek + ! Remove element from Er (a rigid element can belong to only one assembly) + ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before + ik=ik-1 + if (ek/=ek2) then + print*,'Problem in popping',ek,ek2 + endif + call append(En, ek, ErrStat2, ErrMsg2) + call append(Ea, ek, ErrStat2, ErrMsg2) + endif + enddo + ! Loop through neighbors and recursively add neighbors of neighbors + do ik = 1, len(En) + ek = En%List(ik) + call AddNeighbors(ek, Er, Ea) + enddo + call destroy_list(En, ErrStat2, ErrMsg2) + END SUBROUTINE AddNeighbors + + +END SUBROUTINE RigidLinkAssemblies + !------------------------------------------------------------------------------------------------------ !> Computes directional cosine matrix DirCos !! rrd: This should be from local to global @@ -1059,9 +1353,9 @@ SUBROUTINE ElemM(ep, Me) if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then Me=0.0_ReKi else + print*,'SD_FEM: Mass matrix for rigid members rho/=0 TODO' + CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) !CALL ElemM_(A, L, rho, DirCos, Me) - print*,'SD_GEM: Mass matrix for rigid members rho/=0 TODO' - STOP endif endif END SUBROUTINE ElemM diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 5dbd116ae..62ffff708 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -51,8 +51,8 @@ Module SubDyn SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) REAL(ReKi), INTENT( IN ) :: TP_RefPoint(3) - TYPE(MeshType), INTENT( INOUT ) :: inputMesh - TYPE(MeshType), INTENT( INOUT ) :: outputMesh + TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%TPMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y1Mesh INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -106,8 +106,8 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, INTEGER(IntKi), INTENT( IN ) :: IDL(NNodes_L*6) INTEGER(IntKi), INTENT( IN ) :: NNodes_C ! number base reaction nodes i.e. Y2 stuff after interior stuff INTEGER(IntKi), INTENT( IN ) :: IDC(NNodes_C*6) - TYPE(MeshType), INTENT( INOUT ) :: inputMesh - TYPE(MeshType), INTENT( INOUT ) :: outputMesh + TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%LMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y2Mesh INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables @@ -321,18 +321,19 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; ! Assemble Stiffness and mass matrix - CALL AssembleKM(Init,p, m, ErrStat2, ErrMsg2); if(Failed()) return + CALL AssembleKM(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return ! --- Calculate values for FEMparams (for summary file output only ! Solve dynamics problem + ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change - CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - - ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! --- Elimination + CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return ! --- Craig-Bampton reduction (sets many parameters) diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 3add94653..86df3cf26 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -173,8 +173,8 @@ subroutine Test_lists(ErrStat,ErrMsg) ErrMsg = "" testname='Lists' - call init(L1, 0, 0 ,ErrStat, ErrMsg) - call init(L2, 10, 12,ErrStat, ErrMsg) + call init_list(L1, 0, 0 ,ErrStat, ErrMsg) + call init_list(L2, 10, 12,ErrStat, ErrMsg) ! test len call test_equal('length',0 ,len(L1)) From 9d80cdf13df7b7e9d0b10bc6182d0d2ba28f6d80 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2019 14:35:54 -0700 Subject: [PATCH 081/377] TCF: WAMIT2 add RoutineName parameters to subroutines for readability --- modules/hydrodyn/src/WAMIT2.f90 | 286 ++++++++++++++++---------------- 1 file changed, 146 insertions(+), 140 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index d0f8ae4fa..9440924ac 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -791,6 +791,8 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS INTEGER(IntKi) :: I !< Generic counter INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter + CHARACTER(*), PARAMETER :: RoutineName = 'MnDrift_InitCalc' + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -819,7 +821,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( InitInp%WvLowCOffD > 0.0_SiKi ) THEN CALL SetErrStat( ErrID_Warn, ' WvLowCOffD > 0.0, so no mean drift term is calculated (the mean drift uses only the equal '//& - 'frequency terms of the QTF). Setting the mean drift force to 0.',ErrStat,ErrMsg,'MnDrift_InitCalc') + 'frequency terms of the QTF). Setting the mean drift force to 0.',ErrStat,ErrMsg,RoutineName) MnDriftForce = 0.0_SiKi RETURN ENDIF @@ -836,7 +838,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( MINVAL( MnDriftData%Data3D%WvFreq1 ) > InitInp%WvLowCOffD ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data3D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -844,7 +846,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( (MAXVAL(MnDriftData%Data3D%WvFreq1 ) < InitInp%WvHiCOffD) ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data3D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,RoutineName) ENDIF ELSE IF ( MnDriftData%DataIs4D ) THEN ! only check if not 3D data. If there is 3D data, we default to using it for calculations @@ -853,12 +855,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( MINVAL( MnDriftData%Data4D%WvFreq1 ) > InitInp%WvLowCOffD ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data4D%WvFreq1)))// & ' rad/s first wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is above the low frequency cutoff set by WvLowCOff.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is above the low frequency cutoff set by WvLowCOff.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( MINVAL( MnDriftData%Data4D%WvFreq2 ) > InitInp%WvLowCOff ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(MnDriftData%Data4D%WvFreq2)))// & ' rad/s for second wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is above the low frequency cutoff set by WvLowCOffD.',ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -866,17 +868,17 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( (MAXVAL(MnDriftData%Data4D%WvFreq1) < InitInp%WvHiCOffD) ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data4D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( (MAXVAL(MnDriftData%Data4D%WvFreq2) < InitInp%WvHiCOffD) ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(MnDriftData%Data4D%WvFreq1)))// & ' rad/s second wave period) data in '//TRIM(MnDriftData%Filename)// & - ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,'MnDrift_InitCalc') + ' is below the high frequency cutoff set by WvHiCOffD.',ErrStat,ErrMsg,RoutineName) ENDIF ELSE ! This is a catastrophic issue. We should not have called this routine without data that is usable for the MnDrift calculation - CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,'MnDrift_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -891,12 +893,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(MnDriftData%Data3D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'MnDrift_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data3D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(MnDriftData%Data3D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'MnDrift_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -908,7 +910,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS (minval(MnDriftData%data3d%WvDir2) > 150.0_SiKi) .OR. (maxval(MnDriftData%data3d%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'MnDrift_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -916,12 +918,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -930,12 +932,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF @@ -947,12 +949,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(MnDriftData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'MnDrift_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (MnDriftData%Data4D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(MnDriftData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(MnDriftData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'MnDrift_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -964,7 +966,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS (MINVAL(MnDriftData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(MnDriftData%Data4D%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'MnDrift_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -973,12 +975,12 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -987,19 +989,19 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(MnDriftData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF ELSE ! No data. This is a catastrophic issue. We should not have called this routine without data that is usable for the MnDrift calculation - CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,'MnDrift_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation called without data.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -1019,7 +1021,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! If we need to create the 3D data set, then CALL Copy_InitData4Dto3D( MnDriftData%Data4D, MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'MnDrift_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev) RETURN MnDriftData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. @@ -1046,7 +1048,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(MnDriftData%Filename)//' is too sparse '// & 'for the interpolation routine used in the mean drift calculation. At some later point, we will allow for '// & - 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'MnDrift_InitCalc') + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,RoutineName) RETURN ENDIF @@ -1062,11 +1064,11 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF (MnDriftData%DataIs3D) THEN ALLOCATE( TmpData3D(MnDriftData%Data3D%NumWvFreq1, MnDriftData%Data3D%NumWvDir1,MnDriftData%Data3D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 3D QTF data.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ELSE ALLOCATE( TmpData4D(MnDriftData%Data4D%NumWvFreq1,MnDriftData%Data4D%NumWvFreq2,MnDriftData%Data4D%NumWvDir1,MnDriftData%Data4D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & - ErrStat, ErrMsg, 'MnDrift_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ! If something went wrong during allocation of the temporary arrays... @@ -1149,7 +1151,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Check and make sure nothing bombed in the interpolation that we need to be aware of - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'MnDrift_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1255,7 +1257,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using - + CHARACTER(*), PARAMETER :: RoutineName = 'NewmanApp_InitCalc' + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -1294,7 +1297,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data3D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is above the low frequency cutoff set by WvLowCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -1303,7 +1306,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data3D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is below the high frequency cutoff set by WvHiCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ELSE IF ( NewmanAppData%DataIs4D ) THEN ! only check if not 3D data. If there is 3D data, we default to using it for calculations @@ -1313,13 +1316,13 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data4D%WvFreq1)))// & ' rad/s first wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is above the low frequency cutoff set by WvLowCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MINVAL( NewmanAppData%Data4D%WvFreq2 ) > InitInp%WvLowCOff ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(NewmanAppData%Data4D%WvFreq2)))// & ' rad/s for second wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is above the low frequency cutoff set by WvLowCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -1328,18 +1331,18 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data4D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is below the high frequency cutoff set by WvHiCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MAXVAL(NewmanAppData%Data4D%WvFreq2) < InitInp%WvHiCOff ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(NewmanAppData%Data4D%WvFreq1)))// & ' rad/s second wave period) data in '//TRIM(NewmanAppData%Filename)// & ' is below the high frequency cutoff set by WvHiCOff.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ELSE ! This is a catastrophic issue. We should not have called this routine without data that is usable for the NewmanApp calculation - CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -1354,12 +1357,12 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(NewmanAppData%Data3D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data3D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(NewmanAppData%Data3D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -1371,7 +1374,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg (minval(NewmanAppData%data3d%WvDir2) > 150.0_SiKi) .OR. (maxval(NewmanAppData%data3d%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -1379,12 +1382,12 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -1393,12 +1396,12 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF @@ -1410,12 +1413,12 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(NewmanAppData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (NewmanAppData%Data4D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(NewmanAppData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(NewmanAppData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'NewmanApp_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -1427,7 +1430,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg (MINVAL(NewmanAppData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(NewmanAppData%Data4D%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -1436,12 +1439,12 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -1450,19 +1453,19 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF ( InitInp%WaveDirMin < MINVAL(NewmanAppData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF ELSE ! No data. This is a catastrophic issue. We should not have called this routine without data that is usable for the NewmanApp calculation - CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' Newman approximation calculation called without data.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -1482,7 +1485,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! If we need to create the 3D data set, then CALL Copy_InitData4Dto3D( NewmanAppData%Data4D, NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev) RETURN NewmanAppData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. @@ -1509,7 +1512,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(NewmanAppData%Filename)//' is too sparse '// & 'for the interpolation routine used in the Newman approximation calculation. At some later point, we will allow for '// & - 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,RoutineName) RETURN ENDIF @@ -1530,30 +1533,30 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg IF (NewmanAppData%DataIs3D) THEN ALLOCATE( TmpData3D(NewmanAppData%Data3D%NumWvFreq1, NewmanAppData%Data3D%NumWvDir1,NewmanAppData%Data3D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 3D QTF data.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ELSE ALLOCATE( TmpData4D(NewmanAppData%Data4D%NumWvFreq1,NewmanAppData%Data4D%NumWvFreq1,NewmanAppData%Data4D%NumWvDir1,NewmanAppData%Data4D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & - ErrStat, ErrMsg, 'NewmanApp_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ! Setup the arrays holding the Newman terms, both the complex frequency domain and real time domain pieces ALLOCATE( NewmanTerm1t( 0:InitInp%NStepWave ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the first term of the Newmans '// & - 'approximation in the time domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + 'approximation in the time domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( NewmanTerm2t( 0:InitInp%NStepWave ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & - 'approximation in the time domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + 'approximation in the time domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( NewmanTerm1C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the first term of the Newmans '// & - 'approximation in the frequency domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + 'approximation in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( NewmanTerm2C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & - 'approximation in the frequency domain.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + 'approximation in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( NewmanAppForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the resulting Newmans '// & - 'approximation of the 2nd order force.',ErrStat, ErrMsg, 'NewmanApp_InitCalc') + 'approximation of the 2nd order force.',ErrStat, ErrMsg, RoutineName) @@ -1576,7 +1579,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Initialize the FFT library CALL InitCFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) ! Complex result FFT initialize - CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1662,7 +1665,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Check and make sure nothing bombed in the interpolation that we need to be aware of - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1706,7 +1709,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Now we apply the FFT to the first piece. CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1720,7 +1723,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Now we apply the FFT to the second piece. CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1748,7 +1751,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Done with the FFT library routines, so end them. CALL ExitCFFT(FFT_Data, ErrStatTmp) - CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'NewmanApp_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -1833,7 +1836,8 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using - + CHARACTER(*), PARAMETER :: RoutineName = 'DiffQTF_InitCalc' + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -1869,13 +1873,13 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(DiffQTFData%Data4D%WvFreq1)))// & ' rad/s first wave period) data in '//TRIM(DiffQTFData%Filename)// & ' is above the low frequency cutoff set by WvLowCOffD.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MINVAL( DiffQTFData%Data4D%WvFreq2 ) > InitInp%WvLowCOffD ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(DiffQTFData%Data4D%WvFreq2)))// & ' rad/s for second wave period) data in '//TRIM(DiffQTFData%Filename)// & ' is above the low frequency cutoff set by WvLowCOffD.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -1884,18 +1888,18 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(DiffQTFData%Data4D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(DiffQTFData%Filename)// & ' is below the high frequency cutoff set by WvHiCOffD.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MAXVAL(DiffQTFData%Data4D%WvFreq2) < InitInp%WvHiCOffD ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(DiffQTFData%Data4D%WvFreq1)))// & ' rad/s second wave period) data in '//TRIM(DiffQTFData%Filename)// & ' is below the high frequency cutoff set by WvHiCOffD.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ELSE ! This is a catastrophic issue. We should not have called this routine without data that is usable for the DiffQTF calculation - CALL SetErrStat( ErrID_Fatal, ' The full Difference QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' The full Difference QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -1908,12 +1912,12 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(DiffQTFData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(DiffQTFData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (DiffQTFData%Data4D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(DiffQTFData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(DiffQTFData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -1925,7 +1929,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS (MINVAL(DiffQTFData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(DiffQTFData%Data4D%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -1934,12 +1938,12 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(DiffQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -1948,12 +1952,12 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS IF ( InitInp%WaveDirMin < MINVAL(DiffQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF @@ -1974,7 +1978,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(DiffQTFData%Filename)//' is too sparse '// & 'for the interpolation routine used in the full Difference QTF calculation. At some later point, we will allow for '// & - 'sparse data when a different interpolation routine is implemented.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + 'sparse data when a different interpolation routine is implemented.',ErrStat,ErrMsg,RoutineName) RETURN ENDIF @@ -1986,19 +1990,19 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Setup temporary arrays that we will be passing the data to the interpolation routines in. ALLOCATE( TmpData4D(DiffQTFData%Data4D%NumWvFreq1,DiffQTFData%Data4D%NumWvFreq1,DiffQTFData%Data4D%NumWvDir1,DiffQTFData%Data4D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & - ErrStat, ErrMsg, 'DiffQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ! Setup the arrays holding the DiffQTF terms, both the complex frequency domain and real time domain pieces ALLOCATE( TmpDiffQTFForce( 0:InitInp%NStepWave), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & - 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) ALLOCATE( TmpComplexArr( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & - 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( DiffQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & - 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'DiffQTF_InitCalc') + 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) ! If something went wrong during allocation of the temporary arrays... IF ( ErrStat >= AbortErrLev ) THEN @@ -2016,7 +2020,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Initialize the FFT library. Do not apply normalization. CALL InitFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'DiffQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) @@ -2030,8 +2034,8 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Before we continue, we will get the MnDriftForce results. ! --> Note that we can pass the DiffQTFData directly since we are using the same type for both - CALL MnDrift_InitCalc( InitInp, p, DiffQTFData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'DiffQTF_InitCalc' ) + CALL MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) @@ -2047,7 +2051,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS IF ( p%DiffQTFDims(I) .AND. (.NOT. p%MnDriftDims(I)) ) & CALL SetErrStat( ErrID_Fatal,' The DiffQTF method requires the use of the MnDrift method for the first term. '// & 'Something went wrong and the MnDrift method returned a different number of load components.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDDO IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -2108,7 +2112,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & DiffQTFData%Data4D%WvDir1, DiffQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'DiffQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) @@ -2138,7 +2142,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Now we apply the FFT to the result of the sum CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:), FFT_Data, ErrStatTmp ) CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & - ErrStat,ErrMsg,'DiffQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) @@ -2164,7 +2168,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Done with the FFT library routines, so end them. CALL ExitFFT(FFT_Data, ErrStatTmp) - CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'DiffQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) @@ -2269,7 +2273,8 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using. For the first term in the equation. - + CHARACTER(*), PARAMETER :: RoutineName = 'SumQTF_InitCalc' + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -2306,13 +2311,13 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(SumQTFData%Data4D%WvFreq1)))// & ' rad/s first wave period) data in '//TRIM(SumQTFData%Filename)// & ' is above the low frequency cutoff set by WvLowCOffS.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MINVAL( SumQTFData%Data4D%WvFreq2 ) > InitInp%WvLowCOffS ) THEN CALL SetErrStat( ErrID_Fatal,' The lowest frequency ( '//TRIM(Num2LStr(MINVAL(SumQTFData%Data4D%WvFreq2)))// & ' rad/s for second wave period) data in '//TRIM(SumQTFData%Filename)// & ' is above the low frequency cutoff set by WvLowCOffS.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ! Check the high frequency cutoff -- using the Difference high frequency cutoff. The first order high frequency @@ -2321,18 +2326,18 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(SumQTFData%Data4D%WvFreq1)))// & ' rad/s for first wave period) data in '//TRIM(SumQTFData%Filename)// & ' is below the high frequency cutoff set by WvHiCOffS.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF IF ( MAXVAL(SumQTFData%Data4D%WvFreq2) < InitInp%WvHiCOffS ) THEN CALL SetErrStat( ErrID_Fatal,' The highest frequency ( '//TRIM(Num2LStr(MAXVAL(SumQTFData%Data4D%WvFreq1)))// & ' rad/s second wave period) data in '//TRIM(SumQTFData%Filename)// & ' is below the high frequency cutoff set by WvHiCOffS.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ENDIF ELSE ! This is a catastrophic issue. We should not have called this routine without data that is usable for the SumQTF calculation - CALL SetErrStat( ErrID_Fatal, ' The full Sum QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,'SumQTF_InitCalc') + CALL SetErrStat( ErrID_Fatal, ' The full Sum QTF method requires 4D data, and was not passed any.',ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) RETURN @@ -2345,12 +2350,12 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(SumQTFData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(SumQTFData%Data4D%WvDir1(1)))//' degrees (first wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE IF ( InitInp%WaveMultiDir .AND. (SumQTFData%Data4D%NumWvDir2 == 1) ) THEN CALL SetErrStat( ErrID_Fatal,' WAMIT output file '//TRIM(SumQTFData%Filename)//' only contains one wave '// & 'direction at '//TRIM(Num2LStr(SumQTFData%Data4D%WvDir2(1)))//' degrees (second wave direction). '// & 'It cannot be used with multidirectional waves. Set WvDirMod to 0 to use this file.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) ELSE ! See Known Issues #1 at the top of this file. There may be problems if the data spans the +/- Pi boundary. For @@ -2362,7 +2367,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat (MINVAL(SumQTFData%Data4D%WvDir2) > 150.0_SiKi) .OR. (MAXVAL(SumQTFData%Data4D%WvDir2) < -150.0_SiKi) ) THEN CALL SetErrStat( ErrID_Warn,' There may be issues with how the wave direction data is handled when the wave '// & 'direction of interest is near the +/- 180 direction. This is a known issue with '// & - 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,'SumQTF_InitCalc') + 'the WAMIT2 module that has not yet been addressed.',ErrStat,ErrMsg,RoutineName) ENDIF ! Now check the limits for the first wave direction @@ -2371,12 +2376,12 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat IF ( InitInp%WaveDirMin < MINVAL(SumQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'SumQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & - ErrStat, ErrMsg, 'SumQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF @@ -2385,12 +2390,12 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat IF ( InitInp%WaveDirMin < MINVAL(SumQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Minimum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMin))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'SumQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & - ErrStat, ErrMsg, 'SumQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ENDIF ENDIF @@ -2411,7 +2416,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(SumQTFData%Filename)//' is too sparse '// & 'for the interpolation routine used in the full sum QTF calculation. At some later point, we will allow for '// & - 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,'SumQTF_InitCalc') + 'sparse data when a different interpolation routine is implimented.',ErrStat,ErrMsg,RoutineName) RETURN ENDIF @@ -2423,25 +2428,25 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Setup temporary arrays that we will be passing the data to the interpolation routines in. ALLOCATE( TmpData4D(SumQTFData%Data4D%NumWvFreq1,SumQTFData%Data4D%NumWvFreq1,SumQTFData%Data4D%NumWvDir1,SumQTFData%Data4D%NumWvDir2),STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate temporary array for interpolation of 4D QTF data.', & - ErrStat, ErrMsg, 'SumQTF_InitCalc') + ErrStat, ErrMsg, RoutineName) ! Setup the arrays holding the SumQTF terms, both the complex frequency domain and real time domain pieces ALLOCATE( Term1ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the first term of one load component of the full sum '// & - 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( Term2ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & - 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( Term1Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the first term of one load component of the full sum '// & - 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( Term2Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & - 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( SumQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & - 'QTF 2nd order force time series.',ErrStat, ErrMsg, 'SumQTF_InitCalc') + 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) ! If something went wrong during allocation of the temporary arrays... IF ( ErrStat >= AbortErrLev ) THEN @@ -2460,7 +2465,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Initialize the FFT library. Normalization not required in this formulation. CALL InitFFT ( InitInp%NStepWave, FFT_Data, .FALSE., ErrStatTmp ) ! FIXME: - CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'SumQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while initializing the FFT.',ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) IF (ALLOCATED(SumQTFForce)) DEALLOCATE(SumQTFForce,STAT=ErrStatTmp) @@ -2520,7 +2525,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'SumQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) RETURN @@ -2569,7 +2574,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! TRIM(Num2LStr(InitInp%NStepWave2*InitInp%WaveDOmega))// & ! ' radians/second. If you need those frequencies, decrease WaveDT. For reference, 2*PI '// & ! 'radians/second corresponds to a wavelength of ~1 meter.',& - ! ErrStat,ErrMsg,'SumQTF_InitCalc') + ! ErrStat,ErrMsg,RoutineName) ! ENDIF @@ -2612,7 +2617,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,'SumQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) RETURN @@ -2636,7 +2641,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Now we apply the FFT to the result of the sum. CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:), FFT_Data, ErrStatTmp ) CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) RETURN @@ -2645,7 +2650,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Now we apply the FFT to the result of the sum. CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:), FFT_Data, ErrStatTmp ) CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & - ErrStat,ErrMsg,'SumQTF_InitCalc') + ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) RETURN @@ -2667,7 +2672,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Done with the FFT library routines, so end them. CALL ExitFFT(FFT_Data, ErrStatTmp) - CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,'SumQTF_InitCalc') + CALL SetErrStat(ErrStatTmp,'Error occured while cleaning up after the FFTs.', ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) RETURN @@ -2719,7 +2724,8 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ! Temporary Error Variables INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the local error status CHARACTER(2048) :: ErrMsgTmp !< Temporary error message variable - + CHARACTER(*), PARAMETER :: RoutineName = 'CheckInitInput' + !> ## Subroutine contents !-------------------------------------------------------------------------------- @@ -2770,7 +2776,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( ( InitInp%MnDrift /= 0 .AND. InitInp%NewmanApp /= 0 ) .OR. & ( InitInp%DiffQTF /= 0 .AND. InitInp%NewmanApp /= 0 ) .OR. & ( InitInp%MnDrift /= 0 .AND. InitInp%DiffQTF /= 0 ) ) THEN - CALL SetErrStat( ErrID_Fatal, ' Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero.', ErrStat, ErrMsg, 'CheckInitInput') + CALL SetErrStat( ErrID_Fatal, ' Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero.', ErrStat, ErrMsg, RoutineName) END IF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -2784,22 +2790,22 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( InitInp%MnDriftF ) THEN ! Should be false in this case, so if true there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' MnDriftF flag should be set to false by calling program for MnDrift = 0.'//NewLine// & - ' --> This should have been checked by the calling program.',ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.',ErrStat, ErrMsg, RoutineName) END IF ELSE IF( InitInp%MnDrift >= 7 .AND. InitInp%MnDrift <= 12 ) THEN ! Valid values IF ( .not. InitInp%MnDriftF ) THEN ! Should be true in this case, so if false there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' MnDriftF flag should be set to true by calling program for MnDrift /= 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( InitInp%NBody > 1 .AND. InitInp%MnDrift == 8 ) THEN CALL SetErrStat( ErrID_Fatal, ' Mean drift calculation cannot be used with input file type 8 when more than 1 WAMIT body is present.', & - ErrStat, ErrMsg, 'CheckInitInput') + ErrStat, ErrMsg, RoutineName) END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' MnDrift can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -2812,22 +2818,22 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( InitInp%NewmanAppF ) THEN ! Should be false in this case, so if true there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' NewmanAppF flag should be set to false by calling program for NewmanApp = 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF ELSE IF( InitInp%NewmanApp >= 7 .AND. InitInp%NewmanApp <= 12 ) THEN ! Valid values IF ( InitInp%NewmanAppF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' NewmanAppF flag should be set to true by calling program for NewmanApp /= 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( InitInp%NBody > 1 .AND. InitInp%NewmanApp == 8 ) THEN CALL SetErrStat( ErrID_Fatal, ' Newman''s approximation cannot be used with input file type 8 when more than 1 WAMIT body is present.', & - ErrStat, ErrMsg, 'CheckInitInput') + ErrStat, ErrMsg, RoutineName) END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' NewmanApp can only have values of 0, 7, 8, 9, 10, 11, or 12. '//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -2841,18 +2847,18 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( InitInp%DiffQTFF .eqv. .TRUE. ) THEN ! Should be false in this case, so if true there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' DiffQTFF flag should be set to false by calling program for DiffQTF = 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF ELSE IF( InitInp%DiffQTF >= 10 .AND. InitInp%DiffQTF <= 12 ) THEN ! Valid values IF ( InitInp%DiffQTFF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' DiffQTFF flag should be set to true by calling program for DiffQTF /= 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' DiffQTF can only have values of 0, 10, 11, or 12. '//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -2866,18 +2872,18 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( InitInp%SumQTFF .eqv. .TRUE. ) THEN ! Should be false in this case, so if true there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' SumQTFF flag should be set to false by calling program for SumQTF = 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF ELSE IF( InitInp%SumQTF >= 10 .AND. InitInp%SumQTF <= 12 ) THEN ! Valid values IF ( InitInp%SumQTFF .eqv. .FALSE. ) THEN ! Should be true in this case, so if false there is a problem CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init: '//NewLine// & ' SumQTFF flag should be set to true by calling program for SumQTF /= 0.'//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF ELSE CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' SumQTF can only have values of 0, 10, 11, or 12. '//NewLine// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) END IF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -2898,7 +2904,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( ( InitInp%WvHiCOffD < InitInp%WvLowCOffD ) .OR. ( InitInp%WvLowCOffD < 0.0 ) ) THEN CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' WvHiCOffD must be larger than WvLowCOffD. Both must be positive.'// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF @@ -2911,7 +2917,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff IF ( ( InitInp%WvHiCOffS < InitInp%WvLowCOffS ) .OR. ( InitInp%WvLowCOffS < 0.0 ) ) THEN CALL SetErrStat( ErrID_Fatal, ' Programming Error in call to WAMIT2_Init: '//NewLine// & ' WvHiCOffS must be larger than WvLowCOffS. Both must be positive.'// & - ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, 'CheckInitInput') + ' --> This should have been checked by the calling program.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF @@ -2940,7 +2946,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ENDIF IF ( TmpFileExist .eqv. .FALSE. ) THEN CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(MnDriftData%Filename)// & - ' required by the MnDrift option.', ErrStat, ErrMsg, 'CheckInitInput') + ' required by the MnDrift option.', ErrStat, ErrMsg, RoutineName) CALL CLeanup RETURN END IF @@ -2964,7 +2970,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ENDIF IF ( TmpFileExist .eqv. .FALSE. ) THEN CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(NewmanAppData%Filename)// & - ' required by the NewmanApp option.', ErrStat, ErrMsg, 'CheckInitInput') + ' required by the NewmanApp option.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF @@ -2981,7 +2987,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff INQUIRE( file=TRIM(DiffQTFData%Filename), exist=TmpFileExist ) IF ( TmpFileExist .eqv. .FALSE. ) THEN CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(DiffQTFData%Filename)// & - ' required by the DiffQTF option.', ErrStat, ErrMsg, 'CheckInitInput') + ' required by the DiffQTF option.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF @@ -2998,7 +3004,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff INQUIRE( file=TRIM(SumQTFData%Filename), exist=TmpFileExist ) IF ( .not. TmpFileExist ) THEN CALL SetErrStat( ErrID_Fatal, ' Cannot find the WAMIT file '//TRIM(SumQTFData%Filename)// & - ' required by the SumQTF option.', ErrStat, ErrMsg, 'CheckInitInput') + ' required by the SumQTF option.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF @@ -3017,7 +3023,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff CALL SetErrStat( ErrID_Fatal, ' Programming error in call to WAMIT2_Init:'//NewLine// & ' --> Expected array for WaveElevC0 to be of size 2x'//TRIM(Num2LStr(InitInp%NStepWave2 + 1))// & ' (2x(NStepWave2+1)), but instead received array of size '// & - TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,1)))//'x'//TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,2)))//'.', ErrStat, ErrMsg, 'CheckInitInput') + TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,1)))//'x'//TRIM(Num2LStr(SIZE(InitInp%WaveElevC0,2)))//'.', ErrStat, ErrMsg, RoutineName) CALL CleanUp RETURN END IF From 31dd00f85d3835a79cabfd1d104fa3984a38010a Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2019 16:42:44 -0700 Subject: [PATCH 082/377] TCF: add p%NBody and p%NBodyNum --- modules/hydrodyn/src/WAMIT2.f90 | 22 +++++++++++++++------- modules/hydrodyn/src/WAMIT2.txt | 2 ++ modules/hydrodyn/src/WAMIT2_Types.f90 | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 9440924ac..1d6ccfe83 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -645,7 +645,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Create the input and output meshes associated with lumped loads CALL MeshCreate( BlankMesh = u%Mesh , & IOS = COMPONENT_INPUT , & - Nnodes = 1 , & + Nnodes = p%NBody , & ErrStat = ErrStatTmp , & ErrMess = ErrMsgTmp , & TranslationDisp = .TRUE. , & @@ -661,14 +661,22 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini RETURN END IF - ! Create the node on the mesh - CALL MeshPositionNode (u%Mesh, 1, (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/), ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + DO ThisBodyNum = 1,p%NBody - ! Create the mesh element - CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, 1 ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + ! Set orientation and position for each body in mesh + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(ThisBodyNum)/) + orientation = EulerConstruct(theta) + XYZloc = (/InitInp%PtfmRefxt(ThisBodyNum), InitInp%PtfmRefyt(ThisBodyNum), InitInp%PtfmRefzt(ThisBodyNum)/) + ! Create the node on the mesh + CALL MeshPositionNode (u%Mesh, ThisBodyNum, XYZloc, ErrStatTmp, ErrMsgTmp, orientation ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + + ! Create the mesh element + CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, ThisBodyNum ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) + ENDDO + CALL MeshCommit ( u%Mesh, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') IF ( ErrStat >= AbortErrLev ) THEN diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index 609d33b48..d479a39af 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -104,6 +104,8 @@ typedef ^ ^ ReKi F_Waves2 typedef ^ ParameterType SiKi WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec typedef ^ ^ IntKi NStepWave - - - "Number of wave time steps" - typedef ^ ^ DbKi DT - - - "" - +typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - +typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - #The 2nd order force time series typedef ^ ^ SiKi WaveExctn2 {:}{:} - - "Time series of the resulting 2nd order force (first index is timestep, second index is load component)" (N) diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index fc98380e1..d2248e64f 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -116,6 +116,8 @@ MODULE WAMIT2_Types REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] INTEGER(IntKi) :: NStepWave !< Number of wave time steps [-] REAL(DbKi) :: DT !< [-] + INTEGER(IntKi) :: NBody !< [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] [-] + INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveExctn2 !< Time series of the resulting 2nd order force (first index is timestep, second index is load component) [(N)] LOGICAL , DIMENSION(1:6) :: MnDriftDims !< Flags for which dimensions to calculate in MnDrift calculations [-] LOGICAL , DIMENSION(1:6) :: NewmanAppDims !< Flags for which dimensions to calculate in NewmanApp calculations [-] @@ -1857,6 +1859,8 @@ SUBROUTINE WAMIT2_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM ENDIF DstParamData%NStepWave = SrcParamData%NStepWave DstParamData%DT = SrcParamData%DT + DstParamData%NBody = SrcParamData%NBody + DstParamData%NBodyMod = SrcParamData%NBodyMod IF (ALLOCATED(SrcParamData%WaveExctn2)) THEN i1_l = LBOUND(SrcParamData%WaveExctn2,1) i1_u = UBOUND(SrcParamData%WaveExctn2,1) @@ -1968,6 +1972,8 @@ SUBROUTINE WAMIT2_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg END IF Int_BufSz = Int_BufSz + 1 ! NStepWave Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NBody + Int_BufSz = Int_BufSz + 1 ! NBodyMod Int_BufSz = Int_BufSz + 1 ! WaveExctn2 allocated yes/no IF ( ALLOCATED(InData%WaveExctn2) ) THEN Int_BufSz = Int_BufSz + 2*2 ! WaveExctn2 upper/lower bounds for each dimension @@ -2055,6 +2061,10 @@ SUBROUTINE WAMIT2_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveExctn2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2209,6 +2219,10 @@ SUBROUTINE WAMIT2_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Int_Xferred = Int_Xferred + 1 OutData%DT = DbKiBuf( Db_Xferred ) Db_Xferred = Db_Xferred + 1 + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn2 not allocated Int_Xferred = Int_Xferred + 1 ELSE From 604e1b59cd6d4b66a61e3e5198b469f758c99aee Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2019 16:46:25 -0700 Subject: [PATCH 083/377] TCF: multiple body handling of WAMIT2 input files --- modules/hydrodyn/src/WAMIT2.f90 | 214 ++++++++++++++++++++------------ 1 file changed, 132 insertions(+), 82 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 1d6ccfe83..ceeb7f4e6 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -115,7 +115,7 @@ MODULE WAMIT2 !> This type is only used locally for holding data during the Initialization. It will not be used outside of the WAMIT2_Init !! routine. The 3D data is of the form F_k( WvFreq1, WvDir1, WvDir2, k ) where k is coordinate index to the load components - !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumWvDir1,NumWvDir2,6). The LoadComponents array + !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumWvDir1,NumWvDir2,6*NumBodies). The LoadComponents array !! contains flags that will indicate which of the LoadComponents were read in from the data file. !! !! The DataMask array is of the same size as the DataSet matrix and corresponds to it. Each point in DataMask that is true @@ -126,8 +126,9 @@ MODULE WAMIT2 INTEGER(IntKi) :: NumWvFreq1 !< Number of frequencies in first frequency direction set INTEGER(IntKi) :: NumWvDir1 !< Number of wave directions in first wave direction set INTEGER(IntKi) :: NumWvDir2 !< Number of wave directions in second wave direction set - LOGICAL :: DataIsSparse(6) !< Flag to indicate if the data is sparse or complete. One per component direction - LOGICAL :: LoadComponents(6) !< Which load components actually exist in the input file + INTEGER(IntKi) :: NumBodies !< Number of bodies in the file (based on highest LoadComponent listed) + LOGICAL, ALLOCATABLE :: DataIsSparse(:) !< Flag to indicate if the data is sparse or complete. One per component direction + LOGICAL, ALLOCATABLE :: LoadComponents(:) !< Which load components actually exist in the input file COMPLEX(SiKi), ALLOCATABLE :: DataSet(:,:,:,:) !< Storage for 3D data from the 2nd order WAMIT file LOGICAL, ALLOCATABLE :: DataMask(:,:,:,:) !< Mask for knowing which data points are complete, which are missing REAL(SiKi), ALLOCATABLE :: WvFreq1(:) !< (1:NumFreq1) elements -- values correspond to index 1 of DataSet @@ -138,7 +139,7 @@ MODULE WAMIT2 !> This type is only used locally for holding data during the Initialization. It will not be used outside of the WAMIT2_Init !! routine. The 4D data is of the form F_k( WvFreq1, WvFreq2, WvDir1, WvDir2, k ) where k is coordinate index to the load components - !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumFreq2,NumWvDir1,NumWvDir2,6). The LoadComponents + !! (surge, sway, heave, roll, pitch, yaw). DataSet is of size (NumFreq1,NumFreq2,NumWvDir1,NumWvDir2,6*NumBodies). The LoadComponents !! array contains flags that will indicate which of the LoadComponents were read in from the data file. !! !! The DataMask array is of the same size as the DataSet matrix and corresponds to it. Each point in DataMask that is true @@ -149,10 +150,11 @@ MODULE WAMIT2 INTEGER(IntKi) :: NumWvFreq2 !< Number of frequencies in second frequency direction set INTEGER(IntKi) :: NumWvDir1 !< Number of wave directions in first wave direction set INTEGER(IntKi) :: NumWvDir2 !< Number of wave directions in second wave direction set - LOGICAL :: DataIsSparse(6) !< Flag to indicate if the data is sparse or complete. One per component direction + INTEGER(IntKi) :: NumBodies !< Number of bodies in the file (based on highest LoadComponent listed) + LOGICAL, ALLOCATABLE :: DataIsSparse(:) !< Flag to indicate if the data is sparse or complete. One per component direction LOGICAL :: WvFreqDiagComplete !< Flag to indicate if the diagonal element is complete or not (Omega_m, Omega_m). LOGICAL :: IsSumForce !< Flag to indicate that this is a sum type array. Used in setting the F_{nm} term from F_{mn} term. - LOGICAL :: LoadComponents(6) !< Which load components actually exist in the input file + LOGICAL, ALLOCATABLE :: LoadComponents(:) !< Which load components actually exist in the input file COMPLEX(SiKi), ALLOCATABLE :: DataSet(:,:,:,:,:) !< Storage for 4D data from the 2nd order WAMIT file LOGICAL, ALLOCATABLE :: DataMask(:,:,:,:,:) !< Mask for knowing which data points are complete, which are missing REAL(SiKi), ALLOCATABLE :: WvFreq1(:) !< (1:NumFreq1) elements -- values correspond to index 1 of DataSet @@ -228,6 +230,11 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Local Variables INTEGER(IntKi) :: I !< Generic counter INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: ThisBodyNum !< Current body number + REAL(R8Ki) :: theta(3) !< rotation about z for ThisBodyNum (0 about x,y) + REAL(R8Ki) :: orientation(3,3) !< Orientation matrix for orientation of ThisBodyNum + REAL(ReKi) :: XYZloc(3) !< Starting position of this WAMIT2 body + ! QTF storage -- from the data files that are read in TYPE(W2_DiffData_Type) :: MnDriftData !< Data storage for the Mean Drift method @@ -244,6 +251,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Temporary error trapping variables INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for holding the error status returned from a CALL statement CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for holding the error message returned from a CALL statement + CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Init' !> ### Subroutine contents @@ -294,7 +302,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> 1. Check the data file related values (_MnDrift_, _MnDriftF_ etc). Also copy over important things from _InitInp_ to _p_ and _InitOut_. CALL CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -310,14 +318,14 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%MnDriftF ) THEN IF ( MnDriftData%DataIs3D ) THEN CALL Read_DataFile3D( TRIM(MnDriftData%Filename), MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSEIF ( MnDriftData%DataIs4D ) THEN MnDriftData%Data4D%IsSumForce = .FALSE. CALL Read_DataFile4D( TRIM(MnDriftData%Filename), MnDriftData%Data4D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift method flags incorrectly set by '// & - 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + 'CheckInitInput subroutine.', ErrStat, ErrMsg, RoutineName ) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -330,14 +338,14 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%NewmanAppF ) THEN IF ( NewmanAppData%DataIs3D ) THEN CALL Read_DataFile3D( TRIM(NewmanAppData%Filename), NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSEIF ( NewmanAppData%DataIs4D ) THEN NewmanAppData%Data4D%IsSumForce = .FALSE. CALL Read_DataFile4D( TRIM(NewmanAppData%Filename), NewmanAppData%Data4D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp method flags incorrectly set by '// & - 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + 'CheckInitInput subroutine.', ErrStat, ErrMsg, RoutineName ) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -352,14 +360,14 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%DiffQTFF ) THEN IF ( DiffQTFData%DataIs3D ) THEN CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF method flags incorrectly set by '// & - 'CheckInitInput subroutine. 3D data cannot be used in the DiffQTF method.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + 'CheckInitInput subroutine. 3D data cannot be used in the DiffQTF method.', ErrStat, ErrMsg, RoutineName ) ELSEIF ( DiffQTFData%DataIs4D ) THEN DiffQTFData%Data4D%IsSumForce = .FALSE. CALL Read_DataFile4D( TRIM(DiffQTFData%Filename), DiffQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF method flags incorrectly set by '// & - 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + 'CheckInitInput subroutine.', ErrStat, ErrMsg, RoutineName ) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -373,10 +381,10 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( SumQTFData%DataIs4D ) THEN SumQTFData%Data4D%IsSumForce = .TRUE. CALL Read_DataFile4D( TRIM(SumQTFData%Filename), SumQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF method flags incorrectly set by '// & - 'CheckInitInput subroutine.', ErrStat, ErrMsg, 'WAMIT2_Init' ) + 'CheckInitInput subroutine.', ErrStat, ErrMsg, RoutineName ) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -395,22 +403,22 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%MnDriftF ) THEN IF ( MnDriftData%DataIs3D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,MnDriftData%Data3D%NumBodies IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data3D%LoadComponents(I) ) ) & CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE IF ( MnDriftData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,MnDriftData%Data4D%NumBodies IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data4D%LoadComponents(I) ) )& CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE ! We didn't find any data to use... - CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -423,22 +431,22 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%NewmanAppF ) THEN IF ( NewmanAppData%DataIs3D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,NewmanAppData%Data3D%NumBodies IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data3D%LoadComponents(I) ) ) & CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE IF ( NewmanAppData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,NewmanAppData%Data4D%NumBodies IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data4D%LoadComponents(I) ) ) & CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE - CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -451,14 +459,14 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%DiffQTFF ) THEN IF ( DiffQTFData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,DiffQTFData%Data4D%NumBodies IF ( p%DiffQTFDims(I) .AND. ( .NOT. DiffQTFData%Data4D%LoadComponents(I) ) ) & CALL SetErrStat( ErrID_Warn, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the DiffQTF method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE - CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -471,14 +479,14 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%SumQTFF ) THEN IF ( SumQTFData%DataIs4D ) THEN ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,6 + DO I=1,SumQTFData%Data4D%NumBodies IF ( p%SumQTFDims(I) .AND. ( .NOT. SumQTFData%Data4D%LoadComponents(I) ) ) & CALL SetErrStat( ErrID_Warn, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & TRIM(Num2LStr(I))//' force component for the SumQTF method. Setting this component to zero.', & - ErrStat,ErrMsg,'WAMIT2_Init') + ErrStat,ErrMsg,RoutineName) ENDDO ELSE - CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -522,8 +530,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order mean drift force.' ) - CALL MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + CALL MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -536,8 +544,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( " Calculating second order difference-frequency force using the Newman's approximation." ) - CALL NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsgTmp, ErrStatTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + CALL NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanAppForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -552,8 +560,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order difference-frequency force using the full quadratic transfer function.' ) - CALL DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsgTmp, ErrStatTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + CALL DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -566,8 +574,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order sum-frequency force using the full quadratic transfer function.' ) - CALL SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsgTmp, ErrStatTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init' ) + CALL SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -655,7 +663,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini TranslationAcc = .FALSE. , & RotationAcc = .FALSE.) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -678,7 +686,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ENDDO CALL MeshCommit ( u%Mesh, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -687,7 +695,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini CALL MeshCopy( SrcMesh=u%Mesh, DestMesh=y%Mesh, CtrlCode=MESH_SIBLING, IOS=COMPONENT_OUTPUT, & ErrStat=ErrStatTmp, ErrMess=ErrMsgTmp, Force=.TRUE., Moment=.TRUE. ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -701,7 +709,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Initialize the outputs CALL WMT2OUT_Init( InitInp, y, p, InitOut, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WAMIT2_Init') + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp RETURN @@ -779,12 +787,13 @@ END SUBROUTINE CleanUp !! Since the frequency range of the QTF has not yet been checked, we will do that now. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrStat ) + SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: MnDriftData !< Data storage for the MnDrift method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), INTENT( OUT) :: MnDriftForce(6) !< Force data. Index 1 is the force component. Constant for all time. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -810,6 +819,8 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms + REAL(SiKi) :: RotateZ !< The rotation to apply to the body + REAL(SiKi) :: OffsetXY(2) !< The phase shift offset to apply to the body REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset COMPLEX(SiKi),ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) @@ -1021,7 +1032,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS IF ( .NOT. MnDriftData%DataIs3D .AND. MnDriftData%Data4D%WvFreqDiagComplete ) THEN TmpFlag = .FALSE. ! if this goes true, then we need to convert to 3D data - DO I=1,6 + DO I=1,MnDriftData%Data4D%NumBodies IF ( p%MnDriftDims(I) ) THEN ! Flag indicating which dimension we are calculating for IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) ) TmpFlag = .TRUE. ENDIF @@ -1045,11 +1056,11 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. TmpFlag = .FALSE. IF ( MnDriftData%DataIs3D ) THEN - DO I=1,6 + DO I=1,MnDriftData%Data3D%NumBodies IF ( MnDriftData%Data3D%DataIsSparse(I) .AND. MnDriftData%Data3D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. ENDDO ELSE ! must be 4D -- we checked that we had something at the start of this routine. - DO I=1,6 + DO I=1,MnDriftData%Data4D%NumBodies IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. ENDDO ENDIF @@ -1244,12 +1255,13 @@ END SUBROUTINE MnDrift_InitCalc !! Since the frequency range of the QTF has not yet been checked, we will do that now. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg, ErrStat ) + SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanAppForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: NewmanAppData !< Data storage for the NewmanApp method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: NewmanAppForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1823,12 +1835,13 @@ END SUBROUTINE NewmanApp_InitCalc !! Since the frequency range of the QTF has not yet been checked, we will do that now as well. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrStat ) + SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: DiffQTFData !< Data storage for the DiffQTF method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: DiffQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2042,7 +2055,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Before we continue, we will get the MnDriftForce results. ! --> Note that we can pass the DiffQTFData directly since we are using the same type for both - CALL MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL MnDrift_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -2262,12 +2275,13 @@ END SUBROUTINE DiffQTF_InitCalc !! if the cutoff for the highest sum frequency, _WvHiCOffS_ is above the Nyquist frequency. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ) + SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_SumData_Type), INTENT(INOUT) :: SumQTFData !< Data storage for the SumQTF method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: SumQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -3054,6 +3068,12 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff p%DT = Interval ! Timestep from calling program + !-------------------------------------------------------------------------------- + !> 3. WAMIT body related information + !-------------------------------------------------------------------------------- + + p%NBody = InitInp%NBody ! Number of bodies WAMIT2 sees + p%NBodyMod = InitInp%NBodyMod ! How multiple bodys are treated !-------------------------------------------------------------------------------- @@ -3266,7 +3286,6 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) ErrStatTmp = ErrID_None ErrMsg = '' ErrMsgTmp = '' - Data3D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. HaveZeroFreq1 = .FALSE. ! If we find a zero frequency, we will set this to true @@ -3561,9 +3580,14 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) CALL UniqueRealValues( RawData3D(:,4), TmpRealArr, K, ErrStatTmp,ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) - ! If the value of K is more than 6, we have some serious issues - IF ( K > 6 ) CALL SetErrStat( ErrID_Fatal, ' More than 6 load components found in column 4 of '// & - TRIM(Filename3D)//'.', ErrStat,ErrMsg,RoutineName) + ! Now figure out how many bodies there are. Each body will have up to 6 components. The component + ! column can be up to 6*N where N is the number of bodies in the file. We will assume that we don't + ! skip groups of bodies. + Data3D%NumBodies = ceiling((maxval(TmpRealArr)-0.1_ReKi) / 6.0_ReKi) ! Account for any uncertainty in the number + IF ( Data3D%NumBodies < 1 ) CALL SetErrStat( ErrID_Fatal, ' No WAMIT bodies found (no positive load component numbers in column 4) in '// & + TRIM(Filename3D)//'.', ErrStat,ErrMsg,RoutineName ) + IF ( Data3D%NumBodies > 1 ) CALL SetErrStat( ErrID_Info, ' Found data for '//TRIM(Num2LStr(Data3D%NumBodies))//' WAMIT bodies in '// & + TRIM(Filename3D)//'.', ErrStat,ErrMsg,RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) @@ -3574,13 +3598,21 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) RETURN ENDIF + + ! Now that we know how many bodies are in the file, allocate the size of the arrays + CALL AllocAry( Data3D%DataIsSparse, 6*Data3D%NumBodies, ' Array for tracking which dimension indices are sparsely populated', ErrStatTmp, ErrMsgTmp ) + CALL AllocAry( Data3D%LoadComponents, 6*Data3D%NumBodies, ' Array for tracking which dimension indices contain information', ErrStatTmp, ErrMsgTmp ) + Data3D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. + + ! Now check the values we got back and set the LoadComponents flags for those with data. The ! load component direction must be between 1 and 6 (translational: 1,2,3; rotational: 4,5,6). Data3D%LoadComponents = .FALSE. DO I=1,K - IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6 ) THEN + IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6*Data3D%NumBodies ) THEN CALL SetErrStat( ErrID_Fatal, ' Load components listed in column 4 of '//TRIM(Filename3D)// & - ' must be between 1 and 6.', ErrStat,ErrMsg,RoutineName) + ' must be between 1 and '//TRIM(Num2LStr(6*Data3D%NumBodies))//' for '//TRIM(Num2LStr(Data3D%NumBodies))// & + ' WAMIT bodies.', ErrStat,ErrMsg,RoutineName) IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) @@ -4010,7 +4042,6 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ErrStatTmp = ErrID_None ErrMsg = '' ErrMsgTmp = '' - Data4D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. HaveZeroFreq1 = .FALSE. ! If we find a zero frequency, we will set this to true HaveZeroFreq2 = .FALSE. ! If we find a zero frequency, we will set this to true @@ -4337,29 +4368,42 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ! Find out which load components are actually in use CALL UniqueRealValues( RawData4D(:,5), TmpRealArr, K, ErrStatTmp,ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) - ! If the value of K is more than 6, we have some serious issues - IF ( K > 6 ) CALL SetErrStat( ErrID_Fatal, ' More than 6 load components found in column 4 of '// & - TRIM(Filename4D)//'.', ErrStat,ErrMsg,RoutineName) + ! Now figure out how many bodies there are. Each body will have up to 6 components. The component + ! column can be up to 6*N where N is the number of bodies in the file. We will assume that we don't + ! skip groups of bodies. + Data4D%NumBodies = ceiling((maxval(TmpRealArr)-0.1_ReKi) / 6.0_ReKi) ! Account for any uncertainty in the number + IF ( Data4D%NumBodies < 1 ) CALL SetErrStat( ErrID_Fatal, ' No WAMIT bodies found (no positive load component numbers in column 4) in '// & + TRIM(Filename4D)//'.', ErrStat,ErrMsg,RoutineName ) + IF ( Data4D%NumBodies > 1 ) CALL SetErrStat( ErrID_Info, ' Found data for '//TRIM(Num2LStr(Data4D%NumBodies))//' WAMIT bodies in '// & + TRIM(Filename4D)//'.', ErrStat,ErrMsg,RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) - IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) - IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) CALL CleanUp RETURN ENDIF + + ! Now that we know how many bodies are in the file, allocate the size of the arrays + CALL AllocAry( Data4D%DataIsSparse, 6*Data4D%NumBodies, ' Array for tracking which dimension indices are sparsely populated', ErrStatTmp, ErrMsgTmp ) + CALL AllocAry( Data4D%LoadComponents, 6*Data4D%NumBodies, ' Array for tracking which dimension indices contain information', ErrStatTmp, ErrMsgTmp ) + Data4D%DataIsSparse = .TRUE. ! Assume the data is sparse, then change this after checking on the dimensions of interest. + + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + + ! Now check the values we got back and set the LoadComponents flags for those with data. The ! load component direction must be between 1 and 6 (translational: 1,2,3; rotational: 4,5,6). Data4D%LoadComponents = .FALSE. DO I=1,K - IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6 ) THEN + IF ( NINT(TmpRealArr(I)) < 1 .OR. NINT(TmpRealArr(K)) > 6*Data4D%NumBodies ) THEN CALL SetErrStat( ErrID_Fatal, ' Load components listed in column 4 of '//TRIM(Filename4D)// & - ' must be between 1 and 6.', ErrStat,ErrMsg,RoutineName) + ' must be between 1 and '//TRIM(Num2LStr(6*Data4D%NumBodies))//' for '//TRIM(Num2LStr(Data4D%NumBodies))// & + ' WAMIT bodies.', ErrStat,ErrMsg,RoutineName) IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) @@ -4549,7 +4593,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) CALL CleanUp RETURN ENDIF - TmpCoord(1) = TmpCoord(1) + ( WvFreq1LoIdx - 1 ) ! shift to the point in the Data3D%WvFreq1 array by adding the zero frequency step function + TmpCoord(1) = TmpCoord(1) + ( WvFreq1LoIdx - 1 ) ! shift to the point in the Data4D%WvFreq1 array by adding the zero frequency step function ! Find the location in the WvFreq2 array that this point corresponds to. We will check only between the ! cutoffs that were added to the frequency range. This is contained within TmpWvFreq2 from reading in. @@ -4565,7 +4609,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) CALL CleanUp RETURN ENDIF - TmpCoord(2) = TmpCoord(2) + ( WvFreq2LoIdx - 1 ) ! shift to the point in the Data3D%WvFreq2 array by adding the zero frequency step function + TmpCoord(2) = TmpCoord(2) + ( WvFreq2LoIdx - 1 ) ! shift to the point in the Data4D%WvFreq2 array by adding the zero frequency step function ! Find the location in the WvDir1 array that this point corresponds to. CALL LocateStp( RawData4D(I,3), Data4D%WvDir1, TmpCoord(3), Data4D%NumWvDir1 ) @@ -4863,7 +4907,7 @@ END SUBROUTINE Read_DataFile4D - !> This subroutine counts the number of uniqe values in an array and returns a sorted array of them. + !> This subroutine counts the number of unique values in an array and returns a sorted array of them. !! This is called by the _Read_DataFile3D_ and _Read_DataFile4D_ routines. SUBROUTINE UniqueRealValues( DataArrayIn, DataArrayOut, NumUnique, ErrStat, ErrMsg ) IMPLICIT NONE @@ -5585,6 +5629,7 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) INTEGER(IntKi) :: L !< Generic counter INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls + CHARACTER(*), PARAMETER :: RoutineName = 'Copy_InitData4Dto3D' ! Initialize the error handling @@ -5596,20 +5641,20 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) ! Make sure we aren't trying to copy 4D sum frequency data in to a 3D type that only holds information for difference frequencies IF ( Data4D%IsSumForce ) THEN - CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D sum-frequency data into a 3D difference frequency type.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D sum-frequency data into a 3D difference frequency type.', ErrStat, ErrMsg,RoutineName) RETURN ENDIF ! Make sure the dimensions work IF ( Data4D%NumWvFreq1 /= Data4D%NumWvFreq2 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when NumFreq1 /= NumFreq2.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when NumFreq1 /= NumFreq2.', ErrStat, ErrMsg,RoutineName) RETURN ENDIF ! Make sure that the frequencies actually match each other DO I=1,Data4D%NumWvFreq1 IF ( .NOT. EqualRealNos(Data4D%WvFreq1(I), Data4D%WvFreq2(I)) ) THEN - CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when wave frequencies are not the same.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data to 3D data when wave frequencies are not the same.', ErrStat, ErrMsg,RoutineName) RETURN ENDIF ENDDO @@ -5623,7 +5668,7 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) IF (ALLOCATED(Data3D%WvDir1)) ErrStatTmp = ErrID_Fatal IF (ALLOCATED(Data3D%WvDir2)) ErrStatTmp = ErrID_Fatal IF ( ErrStatTmp >= ErrID_Fatal ) THEN - CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data into a populated 3D dataset.', ErrStat, ErrMsg,'Copy_InitData4Dto3D') + CALL SetErrStat( ErrID_Fatal, ' Attempted to copy 4D data into a populated 3D dataset.', ErrStat, ErrMsg,RoutineName) ENDIF @@ -5632,22 +5677,26 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) Data3D%NumWvFreq1 = Data4D%NumWvFreq1 Data3D%NumWvDir1 = Data4D%NumWvDir1 Data3D%NumWvDir2 = Data4D%NumWvDir2 - Data3D%LoadComponents = Data4D%LoadComponents + Data3D%NumBodies = Data4D%NumBodies ! Now allocate the storage arrays ALLOCATE( Data3D%DataSet( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataSet to store '// & - 'the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,'Copy_InitData4Dto3D') + 'the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) ALLOCATE( Data3D%DataMask( Data3D%NumWvFreq1, Data3D%NumWvDir1, Data3D%NumWvDir2, 6 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array Data3D%DataMask to store '// & - 'the information on the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,'Copy_InitData4Dto3D') + 'the information on the 3D 2nd order WAMIT data.', ErrStat,ErrMsg,RoutineName) CALL AllocAry( Data3D%WvFreq1, Data3D%NumWvFreq1, 'Data3D WvFreq array', ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) CALL AllocAry( Data3D%WvDir1, Data3D%NumWvDir1, 'Data3D WvDir1 array', ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) CALL AllocAry( Data3D%WvDir2, Data3D%NumWvDir2, 'Data3D WvDir2 array', ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'Copy_InitData4Dto3D' ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( Data3D%LoadComponents, 6*Data3D%NumBodies, 'Data3D LoadComponents array', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry( Data3D%DataIsSparse, 6*Data3D%NumBodies, 'Data3D DataIsSparse array', ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL Destroy_InitData3D( Data3D ) @@ -5659,6 +5708,7 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) Data3D%WvFreq1 = Data4D%WvFreq1 Data3D%WvDir1 = Data4D%WvDir1 Data3D%WvDir2 = Data4D%WvDir2 + Data3D%LoadComponents = Data4D%LoadComponents DO I=1,Data3D%NumWvFreq1 Data3D%DataSet(I,:,:,:) = Data4D%DataSet(I,I,:,:,:) From 0cc311c8c63ba868920215855a1533a63d01f2ef Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 20 Dec 2019 10:05:15 -0700 Subject: [PATCH 084/377] TCF: remove WAMIT_Output.f90 file (somehow got readded) --- modules/hydrodyn/src/WAMIT_Output.f90 | 603 -------------------------- 1 file changed, 603 deletions(-) delete mode 100644 modules/hydrodyn/src/WAMIT_Output.f90 diff --git a/modules/hydrodyn/src/WAMIT_Output.f90 b/modules/hydrodyn/src/WAMIT_Output.f90 deleted file mode 100644 index 1d5480ed3..000000000 --- a/modules/hydrodyn/src/WAMIT_Output.f90 +++ /dev/null @@ -1,603 +0,0 @@ -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2013-2015 National Renewable Energy Laboratory -! -! This file is part of HydroDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -MODULE WAMIT_Output - - ! This MODULE stores variables used for output. - - USE NWTC_Library - USE WAMIT_Types - !USE HydroDyn_Output_Types - USE Waves - IMPLICIT NONE - - PRIVATE - - ! Indices for computing output channels: - ! NOTES: - ! (1) These parameters are in the order stored in "OutListParameters.xlsx" - ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter - - INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - 1 - - ! WAMIT Body Forces: - - INTEGER(IntKi), PARAMETER :: WavesF1xi = 1 - INTEGER(IntKi), PARAMETER :: WavesF1yi = 2 - INTEGER(IntKi), PARAMETER :: WavesF1zi = 3 - INTEGER(IntKi), PARAMETER :: WavesM1xi = 4 - INTEGER(IntKi), PARAMETER :: WavesM1yi = 5 - INTEGER(IntKi), PARAMETER :: WavesM1zi = 6 - INTEGER(IntKi), PARAMETER :: HdrStcFxi = 7 - INTEGER(IntKi), PARAMETER :: HdrStcFyi = 8 - INTEGER(IntKi), PARAMETER :: HdrStcFzi = 9 - INTEGER(IntKi), PARAMETER :: HdrStcMxi = 10 - INTEGER(IntKi), PARAMETER :: HdrStcMyi = 11 - INTEGER(IntKi), PARAMETER :: HdrStcMzi = 12 - INTEGER(IntKi), PARAMETER :: RdtnFxi = 13 - INTEGER(IntKi), PARAMETER :: RdtnFyi = 14 - INTEGER(IntKi), PARAMETER :: RdtnFzi = 15 - INTEGER(IntKi), PARAMETER :: RdtnMxi = 16 - INTEGER(IntKi), PARAMETER :: RdtnMyi = 17 - INTEGER(IntKi), PARAMETER :: RdtnMzi = 18 - - - -!End of code generated by Matlab script - - - INTEGER, PARAMETER :: FWaves1(6) = (/WavesF1xi,WavesF1yi,WavesF1zi,WavesM1xi,WavesM1yi,WavesM1zi/) - INTEGER, PARAMETER :: FHdrSttc(6) = (/HdrStcFxi,HdrStcFyi,HdrStcFzi,HdrStcMxi,HdrStcMyi,HdrStcMzi/) - INTEGER, PARAMETER :: FRdtn(6) = (/RdtnFxi,RdtnFyi,RdtnFzi,RdtnMxi,RdtnMyi,RdtnMzi/) - - - - ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" -! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these -! lines should be modified in the Matlab script and/or Excel worksheet as necessary. -! This code was generated by Write_ChckOutLst.m at 21-Mar-2013 08:13:04. - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(18) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "HDRSTCFXI","HDRSTCFYI","HDRSTCFZI","HDRSTCMXI","HDRSTCMYI","HDRSTCMZI", & - "RDTNFXI ","RDTNFYI ","RDTNFZI ","RDTNMXI ","RDTNMYI ","RDTNMZI ", & - "WAVESF1XI","WAVESF1YI","WAVESF1ZI","WAVESM1XI","WAVESM1YI","WAVESM1ZI"/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(18) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - HdrStcFxi , HdrStcFyi , HdrStcFzi , HdrStcMxi , HdrStcMyi , HdrStcMzi , & - RdtnFxi , RdtnFyi , RdtnFzi , RdtnMxi , RdtnMyi , RdtnMzi , & - WavesF1xi, WavesF1yi, WavesF1zi, WavesM1xi, WavesM1yi, WavesM1zi/) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(18) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) "/) - - - REAL(ReKi) :: AllOuts(MaxWAMITOutputs) ! Array of all possible outputs - - ! ..... Public Subroutines ................................................................................................... - PUBLIC :: WMTOUT_MapOutputs - PUBLIC :: WMTOUT_WriteOutputNames - PUBLIC :: WMTOUT_WriteOutputUnits - PUBLIC :: WMTOUT_WriteOutputs - PUBLIC :: WMTOUT_Init - PUBLIC :: WMTOUT_DestroyParam - PUBLIC :: GetWAMITChannels - -CONTAINS - - - - -!!==================================================================================================== -!SUBROUTINE WMTOUT_MapOutputs( CurrentTime, NBody, BodyID, y, F_Waves1, F_HS, F_Rdtn, F_PtfmAM, AllOuts, ErrStat, ErrMsg ) -!! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput -!! This is called by WAMIT_CalcOutput() at each time step. -!!---------------------------------------------------------------------------------------------------- -! REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds -! integer(IntKi), intent( in ) :: NBody ! If NBody > 1 then BodyID is ignored. If NBody = 1 then BodyID is used and force arrays are 6 elements long otherwise they are 6*NBody long -! integer(IntKi), intent( in ) :: BodyID ! The body index for this WAMIT object within the HydroDyn context when NBodyMod > 1, if NBody> 1 then BodyID is ignored -! TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data -! REAL(ReKi), INTENT( IN ) :: F_Waves1(:) -! REAL(ReKi), INTENT( IN ) :: F_HS(:) -! REAL(ReKi), INTENT( IN ) :: F_Rdtn(:) -! REAL(ReKi), INTENT( IN ) :: F_PtfmAM(:) -! REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMITOutputs) -! INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation -! CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! -! integer(IntKi) :: iBody, startIndx, endIndx ! indices -! -! ErrStat = ErrID_None -! ErrMsg = "" -! -! -! ! Need to use individual components of force for output reporting, the y%mesh data has total forces from all contributions -! -! if ( NBody == 1 ) then -! -! ! This happens when NBodyMod > 1, in which case, each WAMIT object is for a single body, but there may be multiple bodies in the HydroDyn model, -! ! so we need to use BodyID to determine the index into the complete HydroDyn list of WAMIT bodies -! -! AllOuts(FWaves (BodyID)) = F_Waves1 -! AllOuts(FHdrSttc(BodyID)) = F_HS -! AllOuts(FRdtn (BodyID)) = F_Rdtn + F_PtfmAM -! -! else -! ! The only happens if NBodyMod = 1, and all HydroDyn WAMIT bodies are represented in this single WAMIT object -! do iBody = 1,NBody -! startIndx = 6*(iBody-1) + 1 -! endIndx = startIndx + 5 -! AllOuts(FWaves (iBody)) = F_Waves1(startIndx:endIndx) -! AllOuts(FHdrSttc(iBody)) = F_HS(startIndx:endIndx) -! AllOuts(FRdtn (iBody)) = F_Rdtn(startIndx:endIndx) + F_PtfmAM(startIndx:endIndx) -! end do -! -! end if -! -!END SUBROUTINE WMTOUT_MapOutputs - - -!==================================================================================================== - -SUBROUTINE WMTOUT_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file - TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) - -END SUBROUTINE WMTOUT_WriteOutputNames - -!==================================================================================================== - - -SUBROUTINE WMTOUT_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file - TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) - -END SUBROUTINE WMTOUT_WriteOutputUnits - -!==================================================================================================== -SUBROUTINE WMTOUT_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) -! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file -! opened in WMTOUT_Init() -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - INTEGER , INTENT( IN ) :: UnOutFile - REAL(DbKi), INTENT( IN ) :: Time ! Time for this output - TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! WAMIT's output data - TYPE(WAMIT_ParameterType), INTENT( IN ) :: p ! WAMIT parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables -! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array - INTEGER :: I ! Generic loop counter - CHARACTER(200) :: Frmt ! a string to hold a format statement - - - - ! Initialize ErrStat and determine if it makes any sense to write output - - IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN - ErrMsg = ' No WAMIT outputs written. The OutParam array must be allocated and there must be a valid output file identifier before we can write outputs.' - ErrStat = ErrID_Warn - RETURN - ELSE - ErrStat = ErrID_None - ErrMsg = '' - END IF - - - - - - ! Write the output parameters to the file - - Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - - WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) - - - RETURN - - -END SUBROUTINE WMTOUT_WriteOutputs - - - -!==================================================================================================== -SUBROUTINE WMTOUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) -! This subroutine initialized the output module, checking if the output parameter list (OutList) -! contains valid names, and opening the output file if there are any requested outputs -!---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - - - TYPE(WAMIT_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module - TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! This module's internal data - TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p - TYPE(WAMIT_InitOutputType), INTENT( OUT ) :: InitOut - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables - INTEGER :: I ! Generic loop counter -! INTEGER :: J ! Generic loop counter -! INTEGER :: Indx ! Counts the current index into the WaveKinNd array -! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. -! CHARACTER(200) :: Frmt ! a string to hold a format statement - - !------------------------------------------------------------------------------------------------- - ! Initialize local variables - !------------------------------------------------------------------------------------------------- - - - ErrStat = ErrID_None - ErrMsg = "" - - - - - !------------------------------------------------------------------------------------------------- - ! Check that the variables in OutList are valid - !------------------------------------------------------------------------------------------------- - - - CALL WMTOUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) - IF ( ErrStat /= 0 ) RETURN - - - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file - - ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutput array.' - ErrStat = ErrID_Fatal - RETURN - END IF - y%WriteOutput = 0.0_ReKi - - ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - DO I = 1,p%NumOuts - - InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) - - END DO - - END IF ! there are any requested outputs - - RETURN - -END SUBROUTINE WMTOUT_Init - - -!==================================================================================================== -FUNCTION GetWAMITChannels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) -! This routine checks the names of inputted output channels, checks to see if they -! below to the list of available WAMIT channels. - -!---------------------------------------------------------------------------------------------------- - INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels - CHARACTER(10), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. - CHARACTER(10), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT output channels. - LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER GetWAMITChannels ! The number of channels found in this module - - ! Local variables. - - INTEGER :: I ! Generic loop-counting index. - INTEGER :: count ! Generic loop-counting index. - INTEGER :: INDX ! Index for valid arrays - - CHARACTER(10) :: OutListTmp ! A string to temporarily hold OutList(I). - CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. -! LOGICAL :: InvalidOutput(MaxWAMITOutputs) ! This array determines if the output channel is valid for this configuration - LOGICAL :: CheckOutListAgain - - LOGICAL :: newFoundMask (NUserOutputs) ! A Mask indicating whether a user requested channel belongs to a modules output channels. - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - GetWAMITChannels = 0 - - newFoundMask = .FALSE. - - - DO I = 1,NUserOutputs - IF (.NOT. foundMask(I) ) THEN - OutListTmp = UserOutputs(I) -! foundMask(I) = .FALSE. - CheckOutListAgain = .FALSE. - - ! Reverse the sign (+/-) of the output channel if the user prefixed the - ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". - - - - IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN - - OutListTmp = OutListTmp(2:) - ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) - CheckOutListAgain = .TRUE. - - END IF - - CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case - - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - - IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again - ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - END IF - - IF ( Indx > 0 ) THEN - newfoundMask(I) = .TRUE. - foundMask(I) = .TRUE. - GetWAMITChannels = GetWAMITChannels + 1 - - !ELSE - ! foundMask(I) = .FALSE. - END IF - END IF -END DO - - -IF ( GetWAMITChannels > 0 ) THEN - - count = 1 - ! Test that num channels does not exceed max possible channels due to size of OutList - !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating memory for the OutList array in the GetWAMITChannels function.' - ErrStat = ErrID_Fatal - RETURN - END IF - - DO I = 1,NUserOutputs - IF ( newfoundMask(I) ) THEN - OutList(count) = UserOutputs(I) - count = count + 1 - END IF - - END DO - -END IF - -END FUNCTION GetWAMITChannels - - -!==================================================================================================== -SUBROUTINE WMTOUT_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) -! This routine checks the names of inputted output channels, checks to see if any of them are ill- -! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, -! name, and units of the output channels). -! Note that the Wamit module must be initialized prior to calling this function (if it -! is being used) so that it can correctly determine if the Lines outputs are valid. -!---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - - TYPE(WAMIT_OutputType), INTENT( INOUT ) :: y ! This module's internal data - TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT platform module - CHARACTER(10), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables. - - INTEGER :: I ! Generic loop-counting index. -! INTEGER :: J ! Generic loop-counting index. - INTEGER :: INDX ! Index for valid arrays - - CHARACTER(10) :: OutListTmp ! A string to temporarily hold OutList(I). - CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. - - - ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" -! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these -! lines should be modified in the Matlab script and/or Excel worksheet as necessary. -! This code was generated by Write_ChckOutLst.m at 09-Jan-2013 14:53:03. - - LOGICAL :: InvalidOutput(MaxWAMITOutputs) ! This array determines if the output channel is valid for this configuration - - LOGICAL :: CheckOutListAgain - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - InvalidOutput = .FALSE. - -!End of code generated by Matlab script - - !------------------------------------------------------------------------------------------------- - ! ALLOCATE the OutParam array - !------------------------------------------------------------------------------------------------- - ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating memory for the OutParam array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - - - DO I = 1,p%NumOuts - - p%OutParam(I)%Name = OutList(I) - OutListTmp = OutList(I) - - - ! Reverse the sign (+/-) of the output channel if the user prefixed the - ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". - - CheckOutListAgain = .FALSE. - - IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN - p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) - CheckOutListAgain = .TRUE. - p%OutParam(I)%SignM = 1 - ELSE - p%OutParam(I)%SignM = 1 - END IF - - CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case - - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - - IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again - p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - END IF - - IF ( Indx > 0 ) THEN - p%OutParam(I)%Indx = ParamIndxAry(Indx) - IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%Indx = 1 - p%OutParam(I)%SignM = 0 - ELSE - p%OutParam(I)%Units = ParamUnitsAry(Indx) - END IF - ELSE - ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' - ErrStat = ErrID_Fatal -! RETURN - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%Indx = 1 - p%OutParam(I)%SignM = 0 ! this will print all zeros - END IF - - END DO - - - RETURN -END SUBROUTINE WMTOUT_ChkOutLst - - -!==================================================================================================== -SUBROUTINE WMTOUT_DestroyParam ( p, ErrStat, ErrMsg ) -! This function cleans up after running the WAMIT output module. It closes the output file, -! releases memory, and resets the number of outputs requested to 0. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - TYPE(WAMIT_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT module - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - -! ! Internal variables - LOGICAL :: Err - - - !------------------------------------------------------------------------------------------------- - ! Initialize error information - !------------------------------------------------------------------------------------------------- - ErrStat = ErrID_None - ErrMsg = "" - Err = .FALSE. - - - - !------------------------------------------------------------------------------------------------- - ! Deallocate arrays - !------------------------------------------------------------------------------------------------- - IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) - IF ( ErrStat /= 0 ) Err = .TRUE. - - !------------------------------------------------------------------------------------------------- - ! Reset number of outputs - !------------------------------------------------------------------------------------------------- - p%NumOuts = 0 - p%UnOutFile = -1 - - !p%WaveKinNd = -1 ! set this array to "invalid" - - !------------------------------------------------------------------------------------------------- - ! Make sure ErrStat is non-zero if an error occurred - !------------------------------------------------------------------------------------------------- - IF ( Err ) ErrStat = ErrID_Fatal - - RETURN - -END SUBROUTINE WMTOUT_DestroyParam -!==================================================================================================== - - -END MODULE WAMIT_Output From 19ec97380b87ba7ba47d822b1eb7a6753a5f876e Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 20 Dec 2019 10:18:31 -0700 Subject: [PATCH 085/377] TCF add the HydroDynOutListParameters.xlsx file --- .../hydrodyn/src/HydroDynOutListParameters.xlsx | Bin 0 -> 94610 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 modules/hydrodyn/src/HydroDynOutListParameters.xlsx diff --git a/modules/hydrodyn/src/HydroDynOutListParameters.xlsx b/modules/hydrodyn/src/HydroDynOutListParameters.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d7aa4b51625f42283cb62fdb059689f7ed0b4967 GIT binary patch literal 94610 zcmeFY^8{P@ zyEgazInVjNo^$?!=kSB#nsu!;Yu3EyJu{b=hB6vDF$yNiT@(})29)60V~=1|6qI;O z6ci$qyLSwqIy$&oIJg?W@Oo$A@|w%j-i|&8{SIpu${jHO|NZih=u^$;6 zpQWtQlI>HU7+sUZ_up_-UQxr&apu*u;T@RIm)8U-RGk4W)z$qMT#qD;v1&i}khnaz z4lL{PnjypRqzONXQ)-H!^_j|fqP56MCh@`yo7Ewt;8EZh-yPCdI~9b2noTi;ZnzO0 zd~*9ue0YVLT~RiSx#QY`s9s}x#)>o&{spu(^+wF0gVcjg`q{iP&I3_-B5H0EB7J)|ZaxC$%5vP2*PX2vt9KDK z=GOd+A7U!Y*>*UvI$}=S|R`=#8 zwxYUk*~?HA20g0!i)QDgsJ~>jcS?fGYlXA^#*L;z zrV{fvaiu?rs%(#^ko38jShm)c5n{hm`T ztxt5akCbW;&T~>iM#R4H5+C0=WY8DDNBtAG1~HTA|px zeN~6|LW2%8?|zveZ@O<|t$5jYOtY)6c$QE+FPV6S9=vm-&`DpS%Pxh!mtdVMDU7B1 z$To2zRjmQ@@!;s!AHoStOpg*8o~Pv4eCXjJrn-DX&iHiFLa&P2l4e_!wld#G)L5A* z&sOWtTU6QIB?kVq?3Frimb)wFrQcTN#!`OcxYiwQK?JAFM)^>2gj>ex1mlPa?;T^b z$SMynXjj^P)+k{IXu~}Na7?b~IyLGR}%xaTJ zV`6yGT0kMS6kBv2c7N;1Pli_RxueDAUWAWC1>Tb<@x54WJ?MllJxUfO>^$^UsoZo5 zH_^TOC@>lDpZ&>}+^2RSUm+*nn6V^pc+qVw&3l^sxWNtI#Eu0|b=$-Xa(K!w%6u<=o6wv0c?az5X=Rf%yc+jPR=uX`P9-x& zu&(IqIiqb>Y7Kix(N@(-I9G=Y)uRVOZPZ-@IpO%|Z`3Njb=z z7IM5cbgOO7hBV?;

31TTG`t_A*~^=!Ztk;+pmIMfv^da9KLuDeY^DI2S{gimL(Er+- zh0QmMWSj7n%&&=t2Gh!KA3TZcd3>-=nghDe2DR8OlRNilC^Xi0h!IThFR=u7&t87P zX^;QO$1fQjIJ-Wzs~({EME|Mx&W$`d-(6zZ-9~>-woAddzH(D}&f=TT<(gSQ;#U`S z^3xjWkgwM9JvXEr#o;V!j2WwMi;RL-t6slp6+6CnXLB-+EQn{XSi#=iP5V!s38b`K z`<4Ah#`Sh_hK)%w&W;-56~k95{HrqOnyO2_uP0gG8hPU^*tYGmy(Ag#N2(0JswfGz zFrE}W8*1se@Hai4UwIe1Tj?$4l|ZPqRJSyXqNW^18JgJKMbZE6q&z3j{w2B8R@%tj zhfJ3fM?_!h%;y~Z2Eu2mbCeOG-}6{&l8%NVSnNu^|IwYUn&V&>FYf7EcxJ=ni>J;` zJubq5?ZY~+qNJxSZSqZj_oc&R0@fVw?tDG_0efM1PREm{b|Fm->RSwxX@pkN0Gt1v z5O#k|+G>cRpqw_K{@>8cheU62x~(I%=y+Z$clk~Gk28mtMr_J_4b91kFBVbV{mHI& z*Q$DSYlA8{%f9YrEOsN#A_mwhW1VO%S#;1XdxRe8_1|5@W9k!;zAk|HULUSUT^0NZ z>2;Jg7LYFGTAYVmou6+m&4GWzqi$NRmkyVQj|LZN)jf=9TNiHLA52{zbwj*w=x#dI zAyQJ;M;Axe*Mn47L5`!+#_#>SE)csrbAO^T_gWVvZ_dxJ5vkYGtx{6H%{~rz2g@TIlDQ?HPUvE9HPIi~(x)EfHlAIS2y~YsVb5F?8`N3J)8O-QZ`q1@eZMS>& z27a-0<#JwAMwbMipK2_CAQ0CfQBlUNbL#MwrNPcY zE7zOe&Qi1}>0d3Sio;?ET_1SGZi2K>7u{US*5<+zzhC-m#l zkSpoTM-a%7^H~(6^~U+;U~REw{8f{e7aU={3-PUQxjF29dsafS)3Ys2OLtRWbmb9e zFk_X`E7mwV@B7~Ce8rC&GU3taf79Bl9(7Z`*AhXOfshn16OTNG_;?>}BBmN)txfRS zUg?{o>rTf^<6=SE35f8AMc>Pv_Usg+iZY3@Fy5ggbSE2v_L67Ti4I5ULIT~8yh zRNyl`Lv(vDrJJuiG243s`?%@H9kf!mnuii1hW6QaEZCgU7+)6lm4vyL@)}yJ#32T- z-tK9xm+13;8SjY}&O7;>?7aA~k&c(hpgZ*NrCRM);Lo>dq~a5>=lwg?%r*rlWsU_A zd6n*n%Bz^`_ma?~w`=#``$oTw+L4IgPE4P!f5|@8T&v|c2pc^9sK56f*F!po(%qq$ z_Ul7RTBWpLKUbw@P6&7Il7qj?1hfesDLz%}4E!nA`Bd?{>B=QS_pkkh4+U-rCFQQ4 zoZu^QTzoAeTznR_r?o=!$Y;wUV9M)D4)v0a`1rQa6nC*q%z`DEw>eAMT{fO}n{`>R ze|Ny6NGn;|eO8Tso#7Py#oCkAiL&9shy4T!Zw?QJDyFxt@A=71!Xx&;?r(;ZV&`lW z`6emn8VhjK7e4w?=DlnvR?C*NQ zoFJ6d-OEkDTTEgh(l;lsy4%R8VeP^aD<>-t&(=CrVxE1Q#Es$%UHjrSADt+0RBl{{@nX`8u<`AJSfl;^RB2>uVn$-5 z_;^4fRNQ7JhU>b5pu5zdRpg+|!q9s@KCwDpn5A`guZcr!&9K!YXW9aq*XwJesO)6i zaCpz}^Oe?CtvaFjtmMw+N=xxRO8V(Ml)Yrn=eY+C7njI$fa_MUUv3kGtWFbhqL=cpET zgEbtLm@S1)ihS3noP{`NlMEK$!2?FknmKZhZAT!aes8^>?9BH6jfsrT*(qA{RTRP? z-m)lU;Vm1Mu}l#X57}H2s4{7a8oyI)*y>cSx0hs2>@tg<5;RL}A4ua6NCgvSb^mqs z6#r&+Re-kvl(`i_I3zoXK(v_mzSFE37OY{1vxbjDBh{dho#R{68TjhYnGWgJb#Rbb z7QwmG(V)!BYP6_vK7X-Rw5sV@I@9MvJF#>DLmj)1XTOO{5V`y1T2|CZZ$>9uqakKe zS{~01iAxB(`|(><)W8@ORjN^qx5I_xsr*8E2S*&wIiRP19ulXT!8;95N~b7-!rrx$ zcm66|87%^mI+X4w4Exn1tS``U#paL1@m=-ocCt~!{AJ}gvbbfja;s0HVe0yJJ7cJ! z^+s@lH;J4Mz7NF6^K_`9+@22+RAoM4emG0L-zRGymL(JQBkK&yhLGPLzRkcpmVcM* zSia6AKCxv}l8c^qqDP$uUbBhq)LMs85wxKF@t*fF+8Hfbbn;_n?U2z62S&fUtx%0@ zM(ZC;0vnP7^t{@A=C*Lbjci8OA7t5qng+pX=+1g}oH!3A-#yFR*Dm$pYZ+*{OA|i+ zJ)&0(9Oe-Q@zE@gK%b2^IRmx&E;R z*h$E<_^BCUgXj&ZyZQq$z1*oM0hs>`=HNEoclHI_Pu|64hPIgn_KE@XvnQ7me`fStfneyC#zCK*1ceJO(+l!C)FpnwEix!2MEpfb7 zgIh6iDpu%)7sImJpFB8EXeIIsGz;{Ya8%^Lp5CRwlCd+z2Rr+lofIXUeT>%gsW}M2 zAa(&NtyK4S`GqjL@+e(JBi^np(1ZQ^Jei7@YD|-4)KVF(c{HYB8S;6mbqv5C=!i6i zY&+}d3sfI)k)x2g7A1I4L?_#_BqmzyzHkfqPKuP<*3#sfy0gWpAS_Zh!8`D|D(<{J=gwTki$R2-M3c4gEGDXNvYb+GZFONAi{ z@A(j&FTn7DE)adfqm07Su-g|_fCBd@AEXza2ByZ$_J;_%0!z2@R2HDa4jUE2a9%>-Nku!1d?uFsG0=nS zGxF?`t7E8Pg0ymWibI?q=mNsGGFHgql$(-}1|zkHs~%Ai+e&_A*GeHA?cK>do5YhQTMQKR@^-&EO5$ZbCMfZ-D-wViz3Z^C9w zgzOmd0VzAhaALDwnbHt&G8S1hNWlhXH)Rw(lvx3XSFG<=vj;Tiw(`QPlYJ8)g#Isw zRtBCZemi{60^k`~XF~WTP$+&fZ}uq~vF$1Yf0(F!z))pNJzEDxZuQ$0CvddG((o?3 zzan$*@0#5s0pl+>1f#K-!P@r(2$_(mqH>h~@f(K*>u~i>H>FpRg4tJ%2V!+>NKoGw z^>X$%i;%Ek;)NVz^WEz;1QJUoFOxQ+o$YceLw%yjMy<))#jVT;19lXK0M;2#J?ZM0K!DWm}TM-pN+UX3^vG=#6M` zHI&?4`%O)}mgxTCfu6PQhH`WWImc9ACr13!k{`Lzdqs>teiRc3_SxP~v|T;9Gmx$O ziRRFN#6QF`XhSCBP5CRPm%VywiBjkUUI}3Ya#gZZ0qS>5w$S?pogv|CaxAW#t2%5Q z1j9HoA4kzm*kWGgZa&pidm&2@^Rn=+e6n;Bb)*!{2c&|pn4XG?u*la3DZ`j==3|@W z;`vGqFRD=zXK=^wxJAsfJQW>hgD+~8478zJB=eUv^|r&?eiTHYA8O#$bePDwqeoJ# zpW0B7oscYJXVSM_;v9TLKh_wbOV9Z+9?8~86yF5aBSy_9T#9TjyG+z4Sbf3bDzWNQ zcwa>$QCwTmc|CiczR-BcquBg~4%<^gbHBy_|B&Y$kM5NlG1ki*wq{YMW#`O~SG){n zX6?*yi*Ic(Sv1vS#_UH6bpED8kxZ`rhvb+f06SB(?J{f?vmfhrID?#jhr~L_v!ei? zr-WR+uO96P)m!4h$NBxiubM)=4*i^0&2?!@zIRZyLk~Va)WHxHr3t1p{5GE4;^@V# z36)OOTuyvaui$`^Y(=4Uc434gtBh1Hp7h5HLS}#Gh;yUiT9r)_76GcY#J4)@DOtn; z`3bGlCK-%f&la&hJG%@b%#K+?wiv1G7S&?_c!ejb^cu`cw`5Vbf=)4%OB{fI# zi;c8>{4iDaSlcd!L1(@~a`iVlY)2|4BTvomC>olwJ;<=`Vi|PKA#7x+WJ~bJR*9@T zj0#g_xkD6jM?an@fm{*HcTqMW?M{H`+p%RE%KF;3724$?;Ok!#8eO6i; zUT0MOl1IEtkrzcq*7j$iLbxinIM#SJ+9YW*m?!imtH*AweYc&k=33oJ!+^auBU7(HhCPJ1YvA;@S8=*4 zrYhbaduX;U_UEYk-LDiZo0{MlO-pBqr$Du~?Fe>@1Mr0N*IBOz)o0HN>8oGl@r|PA zzkBs~1%E&=mgU#TXXO`WwQ>&WX?6`XJWz#d*&RB*{n76n56gn@a&EM-G;DjoBYLXc+(`i>*Kjx=Pk7 zrWryi6~tYvMf%$6GH^{S_F!BcjO!Co#m1pI5*U2f0!A8&$dCPv9ZzKvbw?tbt-_E| z_;i3!hSGtF$LX;tUObg+Afu>eD8GzlOjmNG)5Tl08LE<`E>3XW4jL(T(Yt3-doK&}YPjWh<4|C@9@^{{A0#AK0EQ zVOIaj+nK8*1tAf1~FT1a(5%6q6DHSIvG zN>&5a6zVt_s?}kj)Vfi^XRWYkgI#=AvwP)b`c;4QpN2E4EA~LbcLdhR1 zW8R0eK6+NTZ?3E(wj3(YW_m8mry`Ub>Z}2|*I$U-J+hf8S???1Vo)@79PWA!_0Jhu zXK?+o%<-gSo>ad%R2lFW?&GBPiBpMF7Q=~qI_pCZslZvol$0}7 zQxc(c?&#kRkm?tyf6k7M&F-XT!q+d8%tkq+s%Vg~6v}(G@&ewK}8;c20627FNQw*mAS^Az${F`HVf=pYz`|2GfGm zJr??bkP00=Uy+?W4;TH<_|7}k-JhPkSDCJkZcuov4r~6heWYd>!e~^)xqX;lBCeML z#j2MxRG=;`wPANtHN4ynhvL0%(ly+Fm<-*ex0t0}CA6mqt!v0H`6+0>*~mXD_Vd8N zzJ1JOwqb3eTC$I2mNE9=f#rnm-!IVPg(7UI3zOI1-y*u48MPlMR19m2zuazsE-H0s zH>>n|BC$n0cjxDUQ!o_ek&5A;dqVd3&Y{pxkoR)4)d>yxoW33kbA?Y=@7q5{;XB{z z%iodV8cSq|s*1l=@7y6ZvsSTVXv+4pA}7|~mqv$x`4@(2Wt*eWS`81X!F&@3wYklm zNd9UTJwDH*bQ_;&gH9OISy?O7Mz_Q4{@J`@`)*!CyD_eSeO{@} zJ(!@q3quz($sdYYt#FHdE~yF9@}CtPW0M#2s)lV^*+UVl#n5LQzgonf8XhL!U%axK zy^|=G$THht{?+E59$P%;uhUO?Bjbq`@kc|+&<}Yc2L-K9-hfFt0+}vH|B+EeMv$N16gA$r)gO$RxgD-8LA!osNhx`n&lraN>Ir|#DFR>~QQ!rm^}2g1_Fpm>Qn9NGCLTbWxA!F}c!4#4ahf*SJeDH18QKL&rs zvO4B8{h}-%$-rcj!x_|Sr+Ubwzx4$gp649p)&tLuvn4H)7!DEm>aZBL$B10PcmNhs z*@D3l1RE~vm#Wybt&wkyXY7qG5Evu9)=F|-o@kh?-A)={=;ghz4r-C-$m`=>6;rJS zvs$Gsd~dBN7isQ1jx)=cc*tO3n1`ZlN~vQAd9!#Y5yvg*?H1Q!lRI;+@jzxD@=}s5 ze@)Vjk(Lv)=%lyzn_Euc_hWzBFqOi(YW>XYt5HBJNCa{#-cpsM7mR zqn($rP>l_UqIsr`hA1E;(56>VVA1&6GAemW`Hr5R6BsT|Dqhnq^gv}_&L?##6$C-a{VnAw^SYC z)b7eS-S*S9626lVnrubW>JnTp+kz7QA`xoKtst{Hy~JX&lF=j!UCsL;Fje@pDJE)9 zTB?jrxe=AttXPpJOetQu2dA6fFw=RkI7bh^^|LN2hnQ7DA!H}KBH(3a7uG~@ab2hm ztM1I@*A+{W?vE85pU*n=z?N3gjjPwQG-T#q%2(Lj?RX#W^;ks+7qPmBTimP2Rd2ge zvgeiA{S8|(u9a~R!{pK5>vQP{pGac zGMoziK(pC+!Ed}pblL)Szv49Bu3VAT|FYrDf$?#5=60pHtEpWA1w|nJ1oe zXHHCy`wiUfsy6K+;MI8Tr<3=T3IPAKzQQTBA?aarNehKNFIq`@P|O}5RMj$6y)#RA zxBJJ;jR^eu7r_Ur#w$ghgkgQ$#9o%p^0h$BXaiamS}uD^W}y zQG^@YlJs~ZMog(H#A)DigU#}u+7+d%Yin4T>jo$e4r&L-? z_?kn`E+<|-r`fTLZao^qtnXsm=sljf9Af*Rzu8!g<#csuo`(m;oheAyL7zj4KiT_s zNLS&Q7+!K2tZ4|_8!xiC!IK$yYpTK^H)bto*F{;klSZEWJ1K7{O7vk~X*m{y`wK_a zKL2z*jEa&`QEOdPJE{S-Qg(}Jca^uV+rh%Wiin)8Z?zo7viL`AaQk$3sR_xUIrQ%} zwrCwu5%u5vf~Pl=BgJ?8hBVyA*``~z8 z#Wpc?4WLS^mwOQ0awH0>|+C#F7 zm%@I)oY3Rf)i@U(M`PBRY495UyA>s^&m45eYMClH^j~s>HZ~ffx!Ge@Wd4#DlFmvq zoy#p?I+40sT`#M_>1n(6b*aKRH|KrO!19!|2nCAkrd|SN7Pd+dn-*ez>cRiK9Ng_B zNe48ML!&@nJs9e(Ety>CsoY+S-Ti9baC$V#nSA2=BV7Q{1|jK!r`8()H&$PdQpYV56_vZv z=ShZB;BeIu(@vDVCvW-z9jaV9@U^~%O&)v>{&?8`R%l~{4CE-h3VVw2s)qZY$36a3 zm#pmFuU}7xR_0>V%guc{iET;Ph@GtQGCbDJr#b3)nOuuSz3$GI`N#Z5)I*s>d%+_D zqK*pEpK~r#Ni|4jx3@Xs0!LSdV+|%T1IH{5DLjn8T`-p{vDNk8%h4GqUrbJF3D6-> zzNpni0zdg}tF5ag%4BZ!rF8;dv2Z@L%!H&%3xS)UFTX!K{MD|~$TgztbxmnRLXch* z|M?#)4Vq#yzSDxOFo-R1(P9sPT}A{ZSYMw!_s^+C$+9AfQ7E>kdMhN(Z2_}>a}kMd zR_R1Xs4eR%b*5R#g#k?qqnZubN~Gv2TVl{&OR3N zAhYAwOt%{>3Ck^4tRNj3>oca*9V-$UD;cf|obHWAT{tfC@gM)Jj%R7{{Z1zHyd}Xo zZw!C7Z8t2-ZJ4cqXKN|(UM;s{f|%dXlhEHiVJ36*N#P{N=FkB9no|9sijsMv+tquc zD5lBMbXI%Zka36iQq5S&`gIkKxnYeG1(b$@WaOEXe=;=He~PotgfqrG@0=K}C*(tai}U$1PSL%6*gKHHIbqzWzxSa^TL%1{`9 zLjDlj=kFs=40y7ffWLW=`LXC;>7%cnEKvE8PioFYbB5{>==5Il!ur^~zN@5v9n5DQ z+YP3X&ir!kuyGnm?`Sh!nj{I$!>HeU`x#F5ntfV#>x&Ng+`!wtzbsd1*ODBs@ns7OA#FbK0j(}^jf4_A0k zq@su^|CB-fLz&WLq{K`>T>8vG+YBLjyM@!W0b=B=+12*C{;RQcoxdiAZx%P+6So&T zx8?NTXSAEUy82{EQfO-qth+rlbU(IM32e4XlO83MtkdTBnS-%;b>rX7`sELAVav?m zfVoMFK1~|>+`E4bxX_9Se-RJ#*RRBD=nTb+M+$VF3TZlBt%OKm^IjS``_cpZ6e!W(IG1;Kwc_qe#lcPxE?k#E0*|SN z6$n@J`2$E7G{{AN9j& z1q?_4azz!m`wT%kS-@i%hNX}bd!$KtknS3&kp00bPco53)AoQAZB(f^Rnk|~e(PL3 zbg!#AVTh-#YMgd3fA;U7^Kbo7kP#YUZ9Ra6`cocwfyq<@v5k$*tC&&F{cJS^Tc%fs z;=i6-YngV%WtJbY$CfO7IFU`M3OjG|k77X>xeJP)H-*-A@9wT^3_pLb1)MHVEc2}I zmas*OK8;d&8ZPhMGB*{r7MmW%b+Xi6j6U!*kcNAYDXTeuv-N40Eq>Nh-1Q zh&>x{`CA?))QBp;E)&pHt#lbYrfl z4Lqo}GAePP+^wM1%kgKFe%YgE4nf1o;hsDyp_2-7G<@9bwoz)os~5>2?G1dk<& z7Zom?-=5V4`Fxu+(N;z^&J{0+?U8hG=Vn7}%Z?}+UxeaCi|!s`W_-~*`>M0g`NG|b z7Tc6#Sbi-CrS>!7z|7=iFcEYIxL()4Ngik9Y=%rLgul^vvw5 zkxPw*x~bn1HFI%cc_|=IQK9=~fX*y78yH2GvrCr}f_S}SQ`@0T6{;9TCgF>Jrg@Nb zXEDNd8(h}n>5e|wD?0SBVM9i@DmV`|T+>G@oa{@VM~sE=S&_6u+h9bHJ*0&O%b-k} zBNygD=k7z`VgEk`|E{ttG%0CAayU1l2e_KWh_(u;7~0#Xz#Wjkgt@63DShPW?=Ag@Hi7l< z`)(ipG^>%QXR))#w5U-37&^R9pcqa&C(N(=*Tircmk;@POAhHp*d#(KM_>MZ3v`w% ze9ZjHvRDgij<7ZQc3H}rKHKWkvj@X$%SVDm9RJE6DX2@xS(4Nj-G@KpJfthR_LZv& z`)yV=Alu3bb?gDj6twH*n=$T%6x2CJ^>GFMyX?KO`gyDhj!6Z!Ji*(L9$u^zs9$e{ zbDW3+hqCTi#2d`u21B@m6qu2-Wv#5|xId&ebv2qNOlX!eG1)2sDnicp9%^%J)qJ(s=%>-Po$4M{rb;)*s{3yo}_^N35_qu zAmd+V1=z18>Dim`5yRG8`TDPp2Q_bi4lMzj_$v#~rrSH)*vv7rax5$hrv6ZtsfikG*(n>&03a zTl$eadM6F-S5!H#`1t#x>JwktX-xItm`g&qexDA9C$Q;_I)BX8k@y}8QeMX3)UMZ4 zv7d4Oe$h!Zm2`lG>wGtn9DES0t9hKO$30myyxT{JT!N^+b`L^%9S35*x0F=JEyv!( ztlfQDP5;D7BZ@zf<-(%@xMs_aTd+h*Oh~9o8n!z zgNA5e%2*l89zK}D;bZ&JnP1$6#_!?avq1Ci+Y{^Jxh>p}ogmxiU-EEz{rJ$_fH8%Q z70)YHZ0QFmCbR1_{_$6lZkYH3>?ig06~NmV)wLc`Q_}2bT7|<~lKv~Awfrrm;9kWM84B70WCE%l^Qe#r z50|RCq4Xor52Akm@2sBanzST6;(nC&B=Q7@%x)dore3yfpg#E5bY0M)6#=h5nV06z z0&=Sy>-D54(_}!X=zTotW{$+O$dX6@(|!pxuOg60_pSWI4hdc>@vjK*GwifvamhVJuw_b6#LBG4T?<`O!tF{>dl*2I^$gD4dmLj9;j% zKAcVL-gwrLiE~5>5ISo@He|xgKS=}$oUDmyBG}?B({#U~4fO{c3dFl67np5q;U}(w zf#klyQ_q)~h8p8RYEvB2q_B{8PW54`Z$ACw$;W1v0o7|<3L~Z(oEE_WP-9I#HOf`1 zM5BNQRs`^Rn|k>JXC>{~Nbz_K(o#KquL!Yz#-ERc$3Wsu89^#U{_Qrc?mb<5@Qwz- zG|2P>f!Qxayq2H5-)9@IClAMMgM5UsNIyizO>wN%iz1}E#3u9|;%?l>vDmaJjMJk8 zMu3Tv(6!$px<^hbPpy(nzXi1%r)Ps@i~J`jY2tLV#nJh73s-vO7J-!dR(i?HB2Iw> z>an@mZCD4Fqy4BB#tB0~+90<3K8QMMrjvoARCB`SAgNYaRs4IL_&!=$*RTsJW%Z+E zjcuP4!~$r-`Q0NC3y*a%3AMy$A5Q6;Rq+8JN)7EX=I%rh`H`K`zl9AU(H5%S-}Vvd zVwKeBAMIIu43NAX1m^C#>Og-hjYR1qA$9k+UW|`f+Y0ekzPY^7FF8<>-!nfRT0vd_ z63+_>^F(O01zaF^_!NTTnP#>SC(geRH5`=y6rch2`MZEYTktRQ0i@WxHl;1t)}z3V z9O;Gj#r-TIBL~pNLM>(g2U3zG*e0|Ew|D?2{AG9_93v2=gz>EF0|1<)O#+{tI3cwT zIs2;B&aa~XNGk+xky64Apn9PD6)_$2`&)ocAKlzNfJG_|ps1Q{1SJ3hyczVot_uEv zYTVDOGtH?)N0j1#Y2939a7f7BR~-~IDx>~YVJJF^js!M<^SzKBgv+k3!?&$ddSq+^ zlU5r#riE-lSxxE{>wP0N&=b}a)Ea70s3Ty2fi$3EQ8^4L_XC*bdzSLAk*jClzPNX5 zA>Ac%-`j8l0%nc7mpuCIA&V;yW}F;y=ZOz8SDlp362;&ur=%n!!c^%LZKJ^cnzorI z>p}ynHF{fp_rulYmA z?tQrjfprN&Hk@SaXPXKcteUcQZqR|BJnAn~s$D0~4R1-GrWK=rs!BYDWRHj2Ttq<$;C zPSr8wrdNP)r1re_r4^q0lLum>X?TWL1hON9d~mTbD|@uNPDxQ3a_iZ;X1O<7zefd!oC>F{J2iI?e? z+t3XBUD#O(zy;4MZBoh#S z^a`XcX=oq$bSi>IK$SPmTK<`6bgzx%^MB-ZrSTWMTl*q2RBF{>;!(*uD09Jl!n$2W zxu93X89v4zrR|6L>z13Ygo}_}rtG1Ac>^Y1&+ig0Rm(rMnx833dk@-p5jy5w>VMl_Jq%GMJnZ>XCWQdxW{d1oWWdFnaBB3F% zUTMHx)WT`K(k>Mze;tgJm$3h?1v}S_QoPaiuhltz{mPzV&azi29XPAV3BorX*dLH~ z^{HqeXwcQ>fwm3#oMnmDBZVjl#byW{vN4E^9+~{0&hwkQ9~F1LoZS0ZIuH={s^aW7 zVJgowu~ny8&r=l8d$U(R6v^{Z25FWLmK?A5i58l)c5$jg$*)v&xXSrL$~QNpAHf1= zab&R;^8g#N&wT#if!!)zU{7=N`0%m)&!YRl{nkUwj{jbx0?c}tQr7~8ZSHMvA#vor zW!N{S{GVQ8dB*NH_EYYy+tWZE9n#rT$_%tY-Z;9JJ9ZnQ!Jk#^j)U?U5KI<8P4n)D zDb_?$bdKA$5Ype1r&t@cBR)$1VKQ08{VV=@7zI#n%;<`{t)naaV&b+n)TDq6lHLH> zz-NSX|D9n8novngg0U{BN0i9c&=!NE2DtVwIw)H-gZX0{5lA{_MJzssp#5h;nda?; zwkR)-RD|n00-4FZ z0+!oMyK7_T`u+tk2oqHUpbs^W&9ML)+qH&(v;Fr1$bylq2r7=n(JYWSat^TQwv#uH zu2||mp!=qe(efD?ao6A2;~W1Sq7NUtJ<%~JHC)WQbNP|9e;P@H+Z%vZ9!aKmizX3AjZgZp#{}G4L-Krn~jQ|w` zo?H6ASuFY7WqQi3iqn(-rK0FhxBsl}eiQ$%c=v6t4!mC)d4gI65F>VE{`Pk5Ez`;& zt9cSTTaTJCw#BCeYlKBV40CVYTGQ?`OupzHKrtv0oGKemu23S`T0BV&K5}&$Euxd5y z89ZY6t+9J=J$KTVW-;%2)N}7h!Qsy{&@o2KP*H$eM*q?jO;s`M$w?9Kbf2lmad^^_ z6EWWagK!NO@;y#%sW}b*GFkh9SN-sDeax#~?l1|t)Ja(Wp8q2otwd|~qLj&+7K`m< zaofoy>Ax|?)=aglx!{EquL5_ies-yi&j4)m5(+4AG0Tq=u!~@&&*+t#SW0am@NXuH z@NVmpK`6-h{lMiu~DVvF~sLb4~|K*`OF(P>i4w5AiD8x zHm;_2oFZ9UUn7X(qn`?7@CWFA?dc`nX2-T5HR>A1h)+$C0i3+O%NIcc+)Qjh^(;|C zxPC|IoZ|&}`~Df0R{7c_C+v4u zs@{4r<0pfySv}DA?gcnp`y`+0(fjnG7nTXW9de+{Y*}n3*J$xPD$8%ZI^Ufz7CsxL z+iTUI`TMLB2UO$6PvB-}tM7`DjG2UN)Eo$dF7trwKgs+v>2-Z%z>uZ^FD1a+D&Vdk zOF;)2Fn1rFpm_olRC17wJol`?8uU)IQ)OX!MenKguhLVNi(2L~;|SfHwb1(woirVPkMkjX#-8fFHg->MTO+%^Wd zdBiRH#9R5Jx|B$Y1J2Zu0T;()PGcR}Br1C47VP@-u zD?!)W=I7t|V_)uVCTM&ct&e;*nT@mlq%8$HgellItg$}CKu`TGVR?^5`}Gj2>QGV;lD?cFof0xh}$Ef>~HOf^80i_|}=5p~#&{aRRNjOno=v;HcD&-n6mO=~A> z`epr{DQM__()kRetdKKF+qx1!>yo)~Hh7&N3-?&DVi*1fRYG*>p5m}(h-l$6OUC+6tR}^Zd_!?`Q#40HKbnJ$d=WT;HM((( z2B}6kx+n$?1La}y%Y1@?3m?w>AA}#}WWApMCKxYd2=VN}5>sV}x24(T4eGOh_%xDd zQt0A=i=an?B5qhVg4M}e|H zP#ZQ&5jA#y&*kau7k|SGg9}%gEf7Dr`_1A00W4z?etEvLwg$QU`F7kS1KX_Cx z**$|`h;K_P_!_VJD(MB_PKD$bSwYGY__bz|8zVO+1|Ig>WD0Oai4}5Mi zM=8ULn~KQ=-}(#0{!!3^@@)Nw8Ht3{U=SJyXK z|EI4oe_c_AV-KOAbi*NP>5ZC(Jbw?ZJa%zg5cD>WO!?CDH1Q- zflsyd`YI*IfT<_iF2(M;suQ*_qjOey&&yAd-pbtL+b`;eBb+F1Y^Z74F!2`+(ukD_bq^2x(c+E}b#4bgZ_o3Ktv{pE%@>=y*IVkw;JeMUc0?-Oo^%W3 z+T>=hw^jP)_^7vWO8RH(F#`NAi&J+m1ma{4U$~@WiZ1GB-OWL7t>doIV(Z1)^+HI9 z?&``y;}m|+&4jum1mRk8iWrV@-ZO^4d%2}=HixgTGE2J79AVAA=eeZKUO+l^b9sh; zMrRDU8Sy*Y>x5qpSHVE5IPw%Sal&%~8;n_O^*uU3Ok79d8|$zAiKs%rkHF8AqtwfB z806a!kMxb_+16Yy(fNzF@IS1$Yc3@Rh119Cq=r&tKGdb)BgDhg5HjJLv(rOqNTqa0 z?@itH#LoUX-NFsLHPx~8VyPs3sn_^qdu1Vt+W{f*{(7NqF){TI%uky;`{v?ww^n^Y zTH2?Hv9-1JrgsH$Q0D&Ckp1vz3*TeZ?}ko#&db-yoC8q@UwL=5y@dF4<9D{wX}q`C z?BjGa?zg)ojPD3(z7oEo;&y0hg?QFMZuT5+5ED(I>+=J|&Ajio-c}zEE0f$) zy_@ccgoY=E5z4CKeFZnK`&+3u%4z~7V(Vy|uDhkFQU;ByA@AYMyPj0;sZU4TZ;YaB zZtNgu7yln$?;S{W|Na5nE0L9vJu*W^GLF5;CS+!hN=C@uLdGE?j=fi*aVWd&nGum> z6OwUcKJU+=`+I-Czvp@Wys!KHx!%|Hx?b0MQ!TZup8k<=t6p9I^MEP)*bOzeX88?v zba?#WbbVv%_E$5Vp9L_BUCYy79X$=&4}LzXy?*Rm;qblhSd!QJ^v}=ZuN}T^_tVCk z#$|&14%^xQHTo?tZm-|9dI3A}c^|U)!r?*SAKS2lCc2#X&Lyn9SQpI0Z9OZRoK}=~ zHlqa$p)UEIx@_V})#%Rwm)C#F^|`m*O|xk#Ei0`3T`q#7HndH2+IC#W)d%huC56r%XPReYN8 zL&v3nbS-Uc+@+H(dDn5x5A>Fefj-CUVoaMse)h@V=I-4^C8>4(dc9R6v(Dq_@YWnb z)tZ)P9tM8gcVwJ@0&BP-JrQua_V(?J)amY44t2XF<@KsNot9VHwZ@iM=bSFQI^5s7 zd8O0$!k-uNS34G-xzoN;YQ%n{ow#(vEn8*tVbzy-g!yjQkY9yvamRqnRF$sS&5N~C zTHIcpOb(id8rr8n9!xiV5fqVzwFw|Po1{Y5Y=?By-x^q8+SAL}+~{}{`+NTtQ_IPh zj|^7?hh8x`WNh^M|M8XyJ$^;)?b@u^@n+@6*@2C3KDf`fR>&vf{>;Jr_r2d<`KJ6@ za%Q8*5BK@W7aM$@A;tUHkAyP_7gKqE zWk&-4^VjDY=Dd?z$r_sDiLKf!+n)!f5Hlk?cMi2W1_UHA*p56y5!r!@sg}-xj9#l* zN3A%5t=c`k+AwPeKjw2iImdysx7u(WWyKx660;!+xQocUetm>=UbIvuz2 zXJ&Il)g0BIXevFxN2(@N%d_K9=@nUB&OjL0`}=p+ZC{dK$lW)2Z{&G9#xEK>Q3&_* z;10X63PG7PrP$M^3MwW-i|jA&4~`xn_=#!txu$M4f8|A~`Nr!Qb#VpSXUiHLJ(o|v zkN1t-AC6$dF%*u;p5z>)(!SK~ssAhWd-5JVOG%#Y(Uf$^OP^4kq8DLrakAT&2;>Z( ze$?Ke;ELreNgTe_dM8wS)gwHo`x9%eq$(sMzxH75Li(Q7B1TKhH!Ysn?0U?(&AY)V z?i;cReE(B&DX-Wak_W}B?|drY&^PCaCyJVdeMslJwXFz!|-ggW$c-%B^VbJ@3( zc>PHOUasbfh_hrUB*VHq!-}D-b)8GCSocmSHwPrCW)CI{&0)`Cy+>G-VrxWb{2q>> zOb`n9jH%;zt_L^au-a0`qG2IWALbrTwNh8Je=M>&)Bcl}Fopa4n<5nx#P>$HY&tnC znoIj>Z;0>9yki@SQ)$8s2C+U!{Dg~}qtsDlkeATvNR%Lv92WB*K{&G~_fTy#Tn`@e z2RcQHg$D1o=LJDU=6LD4qV)aURO_DZzw+JHhD9F zoF4qUuc8{anv!Iwg&GDMj+$C1DI@g7V~t<)e$a_!wfZsZe0GjPcB*xP0|bts{H4e6 zDz7h>%+Azos$t9#VikB+wn1)QzIRm%ttgjs#Wd<#OA4Hi2b1$0Ec3OO5H?C2-{+q} zdQu8p7~bIMtJjp^WTN34wyFJ&JVg5>_QYSl_SEx2cM7;G9@6|QI2oAS31NJG*O`O> zcqN)x4;lCY_R-<|E*EAmjei^mVW`0)O&Cjo8`QBagS!#TvfXq6v8j4+Lyqr1&y2AR zz`A!IE(-an3_%{w%+*ErUfe|gKWKrAd^~E3QVQ}IhBDoMl;UT-KGgXlH(C?}s!E?fnlq7^*a(Ihj~; z;)SNkF?-{=w<$3Q6?9UnBEH01tLti&U2dyPgG7(Rm{hyDIk>6TJHT)09d3Th)mq7j zUZ*J%S-{B<^0|eX7{}t+Ek2l{uddHC`E>TXD6VYlC6NVsAS?u5(LM%890(GJcgbGV z`fE9_; z`jK#idr4NmpZgXBhzn7$Eu=**&HcaCh7@J$XXp(fa>pSDe9~vUD8BjuV;lx4AM#+T z(l}=ou3ddYte@d-bd5$Cef2NvFZXh|$I1fsCK-IlX1;Goc|StLE)`#%&XZCrtMine z?z?H)kZMyJBk0+f#@lnO-7p#Qw#jy-o~T2JgTL)sNzd|VgpNe2snd$Y1t1b^yXJW< z|2B<0x5mD4#Tq|-PfDk8adB49vSFl7w;u1cw;}z;hp7$xhAemwrh-OeHl|^}CXC1J z-o4U%^3=;;F!hHcZc03dzvQDU%YAMy$TRU!!bvoiE<+z);qAruHl180seS4?ZJl7`iirq$wt%I1N?9Or5rV*#98^r zgT|qI(GE3K)9Irv^p>m-`UYudNM9Lzq-htQh}n1*juJ|0u`jXTYp3O0CyT&|dT){T zi~gGX1o7xL!isQ`jlbK-^8w$iiK*>tT8X#ENx~#r2XgOIDwjz#N+=KRRUB(n3J5g% zzEF~W!4cKpjfv#?pjG-6V8RaWONOZZ)A6=k!>oK$5MtX`8VQyJ1bp zeVKSv2;4O=CGld>j*rxM_iG5OrzLKY%(+;V%l*z_W`{}E9j4{<8iR~#mmQT*#_}^1$VZW@<=SRxIWTF9=Kg)mbxh4C z6_N^~hk>f)cis> z@guoWy_K!g+Zu#4kbd}{BA>_Qz*yKAXBb>amP=Q)W=jRZ=u)ZYK(Bcarg*U~Ptu0) znY>NHYa{X0UyUli@l1zcsX4Hu2DF{ae(at(RMR$u0ot}(v}J^+`vkf`KbYi z60IWuG~*K{=(^UoxaL~Tk8T;P?-K$ga5+KxU;7kSJ&%Y-lhL-z;Z!bv1AZyK$=f!Z#?=`GfY$@J5Kpec1iGSy-%-k}FBrv9l0U9DSS&T9RR=>o1TuD~|d8+oj_(-KZ z!sao)8iy*xN1E}=h8@025nv@z#MUVs0#iX06O+mr%e`A*DJ(-eM;AhEcVbCDF z&YaS}3P7}R?EHu$^3I`jX!0;!*q~IgDmPc+Fk$T`4koerde5{6Gk*?)&!L~fQsQf) zQa}1(47@H8M!Yk>dPEI}Rkzl3x8c7)X;EJoWjjbY+_|E#wD`gpwdoP`>d$v-+yA z_yY&8lZb|WD_BRUT%mB#P-I>Rmu{+WmE2Dj)R##L@z_YSm$G4gsd+H`8eGUpC51k$ zn}O!?p3MOMDHuK$-egGDo+1ewAeAuLJU%fz6xcQe10L|_v!n?Rem{w8aOrLnTu-VmKua-M6s7r3dF1!V`Dzl=6!Zec&fG2nj0GP)ByH_j1$ zF)ol({%g*1^IN>&C+4c6a?CAyhIT1aIBVm3P0<*dKjq7~u?SNqE92lnS06W z6WwQVuyIJ^;MuZVAN)FJD0X3@x0tV|P7cLowXHlx(J%Wkf3hMpS4AdN zCgQ8kMy+>?N;R&qtow_2W|fVvtRHhf`q)dXwf6Z91`h2I(7b>Lb)3}3g0jQSTIDbKgY@(Ig zB-?{Rl6E@cVD6*~U8d!|9(j1)!U@HWUXAf|=rys@aIoZ29smB!*BZ{x z4r&;mp`mhDG`e0jak^35fs%BRjg|~z{cn`w6}PdR&^GS`ue)W5a56cr5B#9EQo~;x zAzzK$w@ZnOM)#ut?Rj~S@*RNVXS!O&#?V&KYpffcs~;8{lOuJiG>qqP9N_YcV(b)k z#Q$~zAB+GM1(GelE~c8kqTvIoa$?16^;h8{p}In>rb7&=I^0vNo#@Jq=xTcA43%z+ zJMXL?K4rcsZ7F}Zg^QMKta^P92E4pL=Yk^_3d-_^W&rbe4#Sse*zDp*q#5?wLjyn0 zpjB)no#gTKqK<9@dUaqhdLaOsfWv+C83v8%HaejT z^KtrBa&@JNqSv_BLx4NO)TTpOuL{hp~F`@15*TG?wN$p zbLx5uASe(3oykV+1fj~}fyA?kIDAF9jtSVm4+1#+FT<}us-?|cOhI2FzW@LLMbKEj zkQ|x#3A(@GRmu*od>3uh&oChRFWuoYL_>RYY!iQg>p&YB5uhQ^Yyt;DXyeaV)Tu*Zu{2s_xxCuUk+SIuOQRt|B4OG|n zg)P)%Xmnv3LyW32gKO|3SkfMVO<9$Vh9dwJ7`XdIz)jI>r49J#NCHRtZ!XaN)wB_( zae$TU2^wGCaV*+wsIAaDsis~pmvIcCE>sUN#xp7!^Q@hmW!GzYrrUr;Z}R$&?vnX8V~71(>B zO$I>}pG$GM^gl=!Lj*YoaVPzIxE?eUTyW}Lpo1#IBz8J3m}dWjYT+h89_kn8YS8_{ z{bGsUvOFCK{KXBEZqRP|1|i`0VCSNkJ^D^jsG9$cjglY9JRRt)e=kNy&)(}C2apH> zZJa9?!r^P=JQ0V?CZFMYs;Yc64T!P;o9UR1I1U5g89F-Cv}u4ZE5>DepfaIjdKN*k z)G}D^g|3X$DcYz97tsv1DSak?PDKdi*JmXM!X4cAu0zQWqj0>?hzND=M+Z93AiAE# z2C5Ll)PVJ+0R!ag=Y}Vs=^}PkyVG2(VDT1dP)KPtO6nB-&b;-unbL8wk+Vt5cvwgX+!)(@T z^x;fg8a{&5_nwO^wvs|wKpSC&ZAaLrTW3A|{DKTrEo>=UNmDqap2yzMr1O}?2LXzS zlYbdf6OQjO6scyze*`sPr&;HrYw9Mg8o8Zi|5jy9`20&*$_1I1%Br@WaArb9WL}(NITuRjaPFV+X}8z z2ZH`*lm`4D1Y@;hBhVXn$wg2t5hpJkj8Sh5ryrfk0tLO+XA2pwro6;iC#?MI#}h~3 z$Nv!k$3!dv{L0ay&)Fq#bX(z?va|l_!a4G`Ed>de2{=Gv%9rb%+s8@=JO{NK-(!r# zma$RnUA92LOc+-OT(Hnjy(axh1w$v8_EcEuOos$eiQ(KyhEClPOd{_j8x=*E)jt8< zaw^vAviJE6uU~!Q2u*lE6e4dbnF!Y7>uQP$&}?{qD87*A6Fb>OsJRMZ;xa_M#uiU4 zqe)g2ftH9a97<10eJK3L({tHK7WEBAaEQnW(w)1R6deimT5yP~;J-ctMW!778k;-y zl8GStwl;VxY2L-;B8Za>a~g`+c}HF*r0**!O`ic@p8hofls!VOVT9R!h!^R>h%5wy z4T!C(9|-ms3`65|0*XO;Fzb332sR3X@A!}rL<#U=G8yo11Jn2b1v}#vn34jmrm4t4u3WtZ z7>ei3$B~Dr8_36f#9YH;BAGahAVTp4Na^s_=fl7>AlNk-0_|~VwEyMB;{iEAB~!|Ja}(ak!>e7X^BSrYvY4t)xXjvyva6#DBiHIhO|m!yd?& zzkcn^&@rnU!!bo6xLR#(Jq9G>d|cR`qER6?lvjb^Gv*`N4yb?$o^jTJJAf4D3V}v* z_|0H{|9WS(ChVmzxJpq?LDg&K#cp%V?jybIU?eN)80w^3uniDnG?vkJe#*9WZV zaN&)VYy#S80#18v!uf5~xCY1tXCu|n22J~OlU)R$PNKq%IDq#qdH)I`q#bZ?r~c>N z%_;}_|3vy~w5ajC27`Q81_3Xc!q1td* zgBhJQ0;+Tjl3E6$q8Iw2O$;(u0yj{KE?5+IoR+cpuP)%Yr&QiwWGP|mi69rTUge7Sn> ztk0~JDUaQg-4Agj{eQ7r#d371mDJU|YP=9f4dOR?q?*Nl!;cRX|3c3`VwxFX$hx>O z@J@dI$HboC`}0T=OAjVUNDAZ(bDB1Y)ohXrn%@b(8D3n*(i`0v?-w zT(7?KO?ohoHyiD{N2H0basho59G5+zSV#?`WTC0G2%1_C8&nX)V8_T&2c&s3sAZm( z;xhPQt3Hk+_s9#h(1?^C(dW$LR;gfCc_J@gcqZWS_xt4VcLP9=oQXcEG4EllbQ! z<*IDx+uT2Kk28C+Ed1*_@G)WbFJ_=%3rh8keTFlD$phe`)9^na}RjK0u9IM1U%0i+t|TQF&;XX%4>B5z^cwE1a7IR&&&cy8L>n7P+`wks+5aUIJp zLNT69MzbgL;S36V3sD7HdR)y(KzT>c?4SkQaV*|=2*}gGzS-kN2!`Eeu-!v$gJ(<# zV_^!pD!FAS*`QVXXA{l?=*3WMY+5pX9fkm@!14;63M;gnU>8LJ{r0MS{~M@(aeuC?f_UAEp6@I!){Hztt z73f{hq%LZh^u0Wm{mQp4*AAgH7eNKOmZ^Yy4{3X#-5m6Gr+#S9xpPky>}vCjQQ_fW zB|*m>y@#S%kKW88&B6dZ2@0XY4Qjqw7%lmQvm69_&JE2B^y*_T9&p*8c{~^@_>h-R zty1F%z;XiWiEa94Mu1o>cvu0>b&E#t$)A0*`OsI$2YdrUDF6XmhfjWCkrh11oE4{Q zLl&wY=v*+4kw;e;4zM1ejRwy)w6>Q!r?H=dSB(qnBeYQ>p~$aFKl0|l6_X*;w3`wo z>&|RoD_L`2_vBy;1#e6{PrV8f!2`veG;EEP{_`CSd&XP33C?C)z4#^a0E6udF*y5SCz#hgh}{8-0G;1o;h7OZh73L-3^TPYBY68h*{% z1B}x~L(ujlOfo~~Iq-4H3t$TsPPV&6JJ_eL*n(j3OMQt18)y=g-F0)A(}oy}Dr(4g1~o^cVB8#GJ<6wc-7xNNOz zvI80V1wbOktSY3^C!|oyLlWJ;(kz!gfu9p48VhDCLdn=0%x(VQhcV;_Kz!xGHmLW| zL))F!qA|rpW#|;waq}8@l<@rH_4O54>3e|`dX|{q$VI;kX?&RiKbiO(u;T5zXcW8A zn+Cn-ozd&XDAbA2&yolv=nelTMO{CZZ!ef2kPJ}YD_pxZHJ!ZX$Nb7_qj9IfA`QP$ zG#HZ7_e>ok=)%5NgJ%?3H1Inj<)1Fl@1g$Mk^)|)fE#GfAnRH+SMb3T^*=EK;6qI~ znCByZ0eBK2cEa&U6AMJ1RU>pKeMu$It2m6p05eFp=2wCUXFZf~#7mWX~l0rhE+@lLC~ zeI6bP^=_O|-Z#~ldlE__(2r=~B{MOBzK!gfprUiQ#&d8*`ak>%{Y>IPMZ-5+VartX zyPYsUL}g*E6GYA?_gPZ`8{FATVt_V)AG{{5WFyJcP0nvytkTdShMxaWRT`Cbo?UJm z^_nmbUQxW3gu+cf=$&PfqCQa_s(mnxY8Xg~vb$%AEld&v`X6}7qa9aAOSn@LjX`KZ zzqf|4JuebxO_|U76j3EM@eR~$>^obl8Bl72w1ggzI3RR4HlT`tF7)WuM^znPh<@Fe_rvPw9l?&QXz35!FV2Lsbzt)pdn(H(NC0`!8>z z2sp7P443N%;o}kUhts|TUbj;0n0<|K!F5M+E!zX|9wkS&pl?bE%+#1ZSY@8~r`CNI z;bcS$w4N@RdwXcJWISjI7vD#1?aX|>6ypQG z!?h~uY}~Tt%UE;qa@X6M(W)c5A8LWQZYP=nwf8ps7_`;iu~Kfacj$a~5mE?HpJBna zPKqlx@|5Jgr2U&%Y1@IHw`C7AVv7=nMfnTI;9Z+uS0RVUyB9JXOEEg_6gym#HeIf} zrQ0NG1hMSquk#v~7@Q+cir^ZWj%b$>%Vp=(9#ifzAbWAPU0Zj#kI8bPIahQ$g?Bl^ z)*0}n7Sx1+;7?Q@XM*UD@B31uPk##gDaB2WCle z%dt#)b@8Q(BYsJ%>J^#}1wdHObzvE}OU=53^C!*KXhjm^zLUl@WF1IWDw+3bm1I#% z1wZlVNIp{3ok{A^M2^q(k6U>>@n)TfE!XUl& zAe&l-vyykUcBch_xeiBKIY{8Z&9R%~TLzet*X(C)CP{)CYX0*eU68`BJ6e%q$-YE@Ri8a7L+G5|@x8 z^Lpd6Gt!tDtdoA08hLtK!FSo0p^#ruQgotK#QU3E0{fFPs_7S^bjO{L_~M4Az8+c< z3qeU7iA75sJFiCu^79J!aK0IlLI`D~5*&RZ0XjjC2e3IhOBHcA6rgq;W*h4yPaZ&t z-|R|{Q+n=lCDy!Dm8Qy#=0w8t0NX5P_a$(KX)ddk)EuiO?5G&mwB-u}m&NRH{&bg8PEf*6nMnNa1E;*Gp9`L*DxGO#|K?9j{X2w(&>U zC(^yuGycbIOahzIACQMudvRZ@f4a;)XewpfrT+TRV2MMm3}VrrWLDU!J1xl;&P7m+ z#n4Py;)QTI+Q6euT;1EV<|qYDfHFFKD&N(wc6-K4U=F){ogq;tOv3&p{g z*qqmk*(uR*xCu&IreA$g)za}G$}4f_W%&Iv{_Nb}M>{`0@o$PX`9B7~_Pu&CcR2ot zcj9R4%S@iSnDlcXUr(QaHs^Lj|s<@lVVS`m{E%Kdh?DJCy2rMd?|hk+$v@ zU0l}B)BnuKGn-RtHkRJ%GFBpB@~t0cPD&`>R*J?>O#AB?;)uVJVd@_(G0mYEpb|}F z-MkIerkx0%!Q4r`8yysNYI}FV#(4gjHTdk;PpwSe%4KP7cRt*#x_jywCMII&!A5T_#BULHLK*WvTxjZyLxtDQ;0#_uy;DiYPqP+)5Lra!R}dZ0C*9yM$-g z>^$ZOAG1TY20`|(*z<2%L)|FQ?kV65NIC)DJKc+)D0Wn#J5PK<8I?$0a-{tk{2m{2 z^Y$fN@HM4)bE?^@LYN=o+e8A_cOY1Id_58!*`{3p+SpD%l_IA0aDLAA9rq_BptB!{ zkw#-7=8cIEiu_1LV3O2_WOCi+WO@xyWi>osx{?MgGB?z*sr%~XDcpAX%CtbvaJkz# zF<_Dm7cvp_62+*98amtJM?f*K(7T)?Z5jN!#R2G;Q&CiZO$4I&V#q`(wS>GzwzTD! zI!0mt{C9q&0Dblncez|9?}gmpvyOz@E^l)2hnXDcbgj~&+twq6u*~Y1z{CW&D+EQ0H#jnqLR>TgMx9+2E^|Z0(Yhy0X%~z zAk_Rrxh*j5l?1LKxsHEvWDoUy{U)ti||9_ zsf34aYmrQXh7PF5E>VFdE<64`$T=uK+Rq7F0{+Cb1YgQ1#2?@*pVIL;SrF8KEWyQN zH3DW~fx`dF4=Bn0t%UIYl;dUvI?3)^kb{p>I13e~lxNIAu=!qNS7{HSQRGvasRW!z zB|^<{KUM^VV8wTOqw#Cw&9r5!QU*cDVvzSaPtRy*)TXv)%1K$FkdqqFK-a4QjKEgEox}R=zvZ3Y(#?i>BUeW zm|2hf^Ly&b*n9du=)nXwU;X}eDo!4Z z&n$b#%ctOlXxZ%k*Q=_JZg!n4Us#aA09iU{I10|vfkBih$7+sn03(DmfPrzvKJC;E z#4u?`1_!w9%AcsVn)<8=@q;HM_#wWv}c&0dG8K4SZFfZh@40`)zp{) zq2K;JG3}$Sj)i9ae3_|-6S`3@c>w@&RQ{v(^l}vX=A`?J!}Mcdxjo*NIHS_z6b%n! zUTA5AW_X}g<^0|uC`SO-&<9vTX4$z3K^CSg4hA5bd|euV9y(CFmdWg-RV_7NyUK*- zY<3oke<@ksmYA4HKI1z`*u|IfT5W0&)X)wF5Wu9ZmOXj zK{|w0i;S6ND1;q??NK6SQTDa`?Pp5*MF?Tp3`mvf&@>pZT0euTI`#2Y+N~<9tvVsKlNlt_fcP^( zdT}H0sV&tdqAK$4z-Ti=7yd(ZQ`RG~lhLUhUXQ8?_?pra_;N}kK%L(NH~frLHOQa% zJs)rozb{9Tv+k7Qe1WB*q(sQz{N!JZGh4Bx|vTi4R5Yqn?I!MtVD9~c3bb@s4Fd6LfV1Fvw8 zJ-H4;oS!*Xmx-nwL)Gy8#}EVjdTB6Y7yC&c&h|*IRDtYD1=)qEt?uzW|Bvt)aZJ#~ z17OgXea6y$bV@?o!g+?6XHRSWxb`9(&D5czbWqV)if5-5I?a5`hA%6Rv?AlYh3M z!PFuAOsP&jqYZ7_I4ANMv}-R~A=Bzl=;zBrp{fEtJ#g(f_rW*uWLYNz;E`L-b5;_e zFLA+}*BKz7J!mET%{6G7L3;phJWCMpV27@w|3Cq@Ex`QD$Xck%K@S^)hR^=z8^ri| znrWO>)n{PYhwyW!>(79@arL2N!E>Re_x(L*ux|LmSX1ITbJbCW1K_Vv?iA|K_sam< z!OvqKd?Wy6|Cv+gokz`sedt9p9kwomf$W()Oakg}bAphpY(y`h4vir1s zxm{74Njl`JU}l(B=T8vIP#_cYGUrRd(MtmMx%;LJ(chQ#c(*xs$o4Nun*Y&M$2Kvr zZ=`bmH&?zmX(#7=(pni$xc#2lFfr1*pk`q6ka)f7cx8Ox(<8%apg%bw z`*8mx+CT(x{_RxoXE$nfEbyrpFA}m;X)62=_Zpi{h<2X%yQ;D~${votw>+3oYpP1p zv&TSvy`4zZRVIHTju3-+ir<~nhK2-v%ZDT)Q4KnvkG^e6%Sl}?t2g(FTtRK#l8!H) zClh3Hlq$W`wV)-vAT) zrVa29T8I82Tw}`x#Mx|8`N!-A^iMKv;>0v0_0(G{WCL0NY5bshP)ax)t`d< z9BC@FeY1Etk-%X9N~z!2!cc_4^Pqn0kXb;kuatcu2E`5KtH5$BKp}ZB?aeF#5c)Ub zhJGFO?yUtcy2;ozkr?bC_0K@iX}{&e-*w;^0|pbVaYHXO2c?(n0z{NNa!lWpuihA@ zU#u^i47#y@EU|+++BeuWH|*i*$SR@Hq>u%FlYiMAydV&!Y_=ZCW{E`YFW)@w8NMYx z8Jy48HYqYwnvrIdwfhQuKg#V=$*#GF7fnE?ZLH;0jc37RLwhuf_baNQnF#X5yz8SY zUJ#dTvGgY#BM<|^>KA5rMz4j*i2T_{YVcvOhWhI@!0+tY{ffHM%(Q{U3n4N$dw(LW zg^6g8FuS20tE8E;Bz|MGc@4!CCNqU`;zn(Z3FzgziF{MWdSCggJx0*G3l%w30f$H7 zrf(`&Q(Kra{P!8B*%L6xM8BBuY2CsPp#m}QNS=H)^?T=sNbhL{UPYU^ z6>h{<%7ZIUIbZW47o6~d-eDfi^1s9a2~ywNdQDq+Ujb8M7s-y6bh3>bdG&lJy(Jx( zfYvX~lJM7`W&Kp{;ArM-PpPQ|d&p-_{|&fG4pw%K#G}tfhV6aJNSvI=1}liv0~{q@ z?*Ph?AQ@&oHk%U@?x|vk4*CEr`~vN7MqzobF7ZEy($@L5`@jJ4l1{MJFDQ%tN085* zi9IUu=4{cThh1aV+Oe` z_k|=v{Zy5eR~~b`{oNT%60yvlU!#acOIsMvL7hcAluMIkYarxAv?BX4eq*;;P^Fgb zN3dr}f`vSxtw`QT?R=}SjRa+3va*4m6Va;dM-p#4!-rz|mbt+$C1lTxGx8+rnvM@t zrOmtzL&Svh>+87l;TrnJQG0Lk^BL6dJuaEg5$^pLRS~ zHA_Urt`J9PUx@5W%MD{YtEel%45W3Fx zSM6$IlCHC*`&vEmrcSdKP$}}!JLj&7iUA`c-$V!#ncKJv*VGS=x>E9U*YIuZ7r~}B z;^4EZ50*>Ax~`=QwYFXSa?#EJ?nJZ&K?VD`rjpIVcpu{d09`V~RxnTJ=gSX9v~#m~ zW|8MM-_is&cebs=n@)sy^K0xO)cLQbY0@st;-&m`>>hNex9y@JDNqjCeefLEoe7E< zV|NKVMQ10Ms1Wc}mK675ge`d}Q<5);cipg~6#{mEBNg~O z_77@!E;-f^-E;SqdfKHZ#GtFkFnuL9&6bDU(cU0UyoWlMtFCO*LLh0?&HOehZf|gY zE}BR=1PXe;Exgn?XCityL+vI}gspqPZCvcWI3SS)62JVBL0k9=0+T7jO#0w@ zx~ei0%u6KQw%(yV>MC`8*-s!%ZkeD%6)^QqqLWD{X3auFe-0tiNthycf+!`*C;!0R2;o3wkm zT^-^)Qn>IIdfdqH^(G!J#~XP&2(@5f)YpWQgRgVZ^|sy3q_|`e*}n1y%(PFryl$k6 z>RZdzk`>yn_J6MP&V?K*9D~AekSmxck_Xt6PgeL15*+4&-*r8ULdFXaguN^hO$3LLZ!gzpk$4rxKkZI-GgP0^dgK) z20wpVn7yw`7s6;ih9@w6NTgE5V8r`0tC3OWADFUha;Y^C_84I~q`{9f&3@Q-Mz&A9_~+GShH=UnKgQl+k&Kd z`Dcl)hKMJlPnSptQwZ>3iOWj@`PvFEo{NAxV29jRf1ZHnk!Nh|ICD=YnRgD1&l0Cg zR%m}Y_xXBPy~A?!Ri>p9L0S-9>+JziJ1S$5jQr;K5;6u$jn`!lmbfTu%}r3mj6?H6 zd2=q@@S$kEhUD16IL3$gj}@Pm@V$~%RxX|Cx@Icuub8Vkdq=1`|A<*GMe8|yiz%-bE$t?A2cftsX8gzZ9gDlk^A`b*=-at%h3Gq z$~4=IyQ(_Z{gy^yHmV|j91ZwianSnj1ZTXQHc_H^%D6A^Fod88ex>>>)%tk>3 z>7UM?UiAHvLGKNxY2llS$+4hBS*Z@Hkh)y;{xb^82S;e0*=DpV02dAobCvVOiF~3L zVt=s!b3G_y7^<|_5L+x6{`9(-iiyP1kFgZr9aa2A(dQSvHT!VvGlm>nv#&b zVvE|W1A>`VRhf+lD91LMRfbZ5T=`#zl-n6-$ad}Ewpbuv*!AC<`aB&ZCfD`XJ6N{s z1I3r9YyO}v=4M8~j;Ga+s~{(zI0pIc>;5>XBNES`EfoEH3+@y{F?6zLHL?r*(NawA z@qh{?rQAo?>@gU&5)=ScGWIZW^#X$NV#AT4<$Qd+_TNf6WFT!jC@5>itf?M}2!p~< z5pA^lLDxCRy({GvE0I1?Lh;7@f(^G2ZY(I*z_5UL`>RHybZeG%BS)gK9;HdkpQl;~<+lENh`@YEYsFeyEOJ0P_Ro}pKS+4K7JCf@ zlilJUfC7FOhpINf6ctA^G=CQ|oL25*{QcLz4u%{$qa|6`%EteEtq$@(-CNt7X@W6o zGl$t?JzM`=5B~2}CgnPb?)H*KIoAA<6WcGBQN*;6l1JM`iDU-77BOA}iQpDxJFy4n zS_ONDT>BI|qm>fLlnkDATnpG4Ihh~Rq!s$1)d@lj%o7TYVVHKdrWtY-OGqT!JyCAd zq_YBL`DET=#}mq&D^<&{0lBgPY? z6_hCjo++RETaVpuY&RvA?+&yp-|9uCbL1kLwkE!PB{@& zvcu#%!a#7hXjnx6ggg$=fBkcJA{p*24$#Un#qwp6+xoc>5x64O59v~6eYB!H^RAt=B95r9$>|L3IdB#o{DilG!AMiuVvD04}$Zq zKDfeou!Z_8VNbC-!rT2b%Y?~lWRR~i6Ni4Q{s5GBii}d(r4OW6ILwrS5 zw(Ecq)l&-z*v{QYQ(qMrG9n6AH!2_hNzzk_(watos_Y2jEQ%T(NhrSWI87Jy*amjg zp{t$pWR{2S9-;Kk?*zKr79|R`Bh+?z?_!h%Di|MMm#k{kiLx&h>u!HY_4Kk8>4)bL zPJ*@K(F-Kr)zI~~frO!!#Or3w2%FtqWQ=kL5A@XrSsqDWYr4$%;4bE!KKXDf%GhQu zMz5JDf)q)KyY0V9dVDCEf{pe$SY(MthC1cNzkV@PYHP=iZ?7Rp`JwB5*VejY(EJ@F zV-x(yY89h0O<4QVWtr}MnPYpA&vJ*r^JZ?HsL#QVi+e3xsV-8)VNhv|>kWQ;FTJW2 z$G59J@ve`C$_`7SB(Q+~@p3{uiOkv&4LhUeUGZ?jM=KvIuF@-Ly?g$dFZNIqP1Rmrf+BB zc@W|)xau3H16K*CG}6SiYaz+cX>+E*F*mwF+NV`R`%aG*6FHY_x^x7lE_JA9h4P!EJ_{T6^2~nS`bws}Y}kh0jQUOig>m@=Nlz z>MCMW-K$(J;ie%HM7UfIFFuwzKDSb=G7dM}Dv`WiGZJN&CQAE05B$s4UdN6D;^h+b zCaWK7dNPQubnUrY!mUCiL^O_#A5mWqGfp8i4I})B<>i?AxaKGSUA!7D3b(z0m5ob& zT46|>F!v}I=EL9ydqQQASS82H3H20~g2rLUt2I1yS82$urB)qz*gC}1NuL~DdRvuL zK{6fL5FK1z@>!}L??tPr)X9<6m}oNOL$L116T}wZQU1oEldS6n@2%TZ7sss>-x`PC z2R2(@ene)jZvu!yJV+&4bMVcT=;7A>_MFH|!c;l_G6|07I{Z2+114PFo?J1rQJQ%5 zTofr*^7XPHhj2VD+8c_1KgPX&mu&K5{ziKy5ZywH%nu$GGPlP<K0@avMKQJfd8mf)aZ z4MW~tA39r%xH7HHmhj*ZiN|!8u-iltXq9HVOL`rjpCr_8Hd(c|xTS?dQvTz8kxS&C z@;Aaw0AjJNWsdJ+RYl^I9BBZG_SP52Sa?5)U)f-_z_>_j0_(zrxIJSxZbeI(uN*gK zCI1oaT*HK@G2SOGiaNZt?jUK0;z1f-oh7RPlulU& zE$lB!o==^aD8IORUD%JMGr9GWTN5yklx;2JvpPdn3&#CdeDd9ZQm4zTM#@pOG>qo7 zd~;!p7Y=LXdt@1IVgImu*V7KMDlO2zpXmA=l=7vgJyk72j-T+AQk5V5#86;}=VSje zy}@e#Jx)l@~;lE)*WtdIrQHq+8JQJNv)%ef9xt6G}asxKREy(G@rl1nLc%5fko zzC;InsDgaRbL5jB@)^mZF#!hmxfqH}Dd8w8!yIlKY#rE1+4t0N%R2dWL@=`-4yp_k`sme6U<8t?e z{Totu*F6QiMB33u#SPK=j!!$XnTkVzJyp7+EG=UK8CLo}7x}y&5yU<0k8}}ab*+&9 zvd{dvd+L*Tc};DbRh)er4qNvpo|LCTlHPD^TZgDtnm)jC#Yy9cI$isvZ($)nf4b4+ zPYAX|zj;M;FTb}xYaU}_g5|n$t#v5bLmR3e%IR5tqwkfaVKm>+tI>-BS3jtb{{~{hM5MF9*>|7TKVP$%&Xwu_Z*_SHcOh{2XDa5+Zk$Xd zvxsJN0^8hZ5h74Y&%wDP(o!TyZ`^O8wv z&yHHNr(c4OchiDSejk5jnn~#67ZmnUF^n?rpb9+Inw5MxHG7|z*Xy~D;;%2?QJa*l z0PFvUt}hR$Y5l@3QD_pWq)w6{lm^X%Q>f!!a=Be8-AEk`8b~8)P*g<8kd%ZdR5YLz zDwU!MDJ4e|O`1q0P2XDYJ}2()`@TQh_I~$z*Sm&iJ!|bF^jwLZc+9-w#9KuTC4z9< zF1_@3f5oy?Pmu@VN{~6}gJsiX~ z`Tu~$2QlK|ZhCmi$F4Of^7#Mb`KL1HWxcViTX%G}XQ_{+Yu@kZ-TCUU#c64)mclO= z)9N0+P*`kUdfG=p*^-s*q;Y!KF1s^&dgb3iGfuiXLJD}&P|}k;s+HMr+cy5x_2k13 zgBO6~{i!^3F|Ej?x$H@-%bev_C%ayE_@0)&-;lP$JJhcEQNt2uuBz_6FY8r(`z_{H zdP&FaxWxNSD9A%ga6zGSmZgi$QMnB>mK@2IJaW^Df$!X&d<0|m-`nhxy`=wWjbkl8 zy(SCX{ML#r)4Yg9{gtj;)mLp0h%|BVEV)&CPqNa&#>YePd6ByY)8{O|Pu0wf+ss>Q zvzEh+Mumcm=-C@@cz)gr@qTt!^_f#GWg#<+;o&mR-DZh1D*v8{v8)qqSR`ffr}C9I z=NcYNEu*@*r#<)OQ^#3LBvkY?cGqtWh&UwTCb@YcM%TfD zkyPYpFe6DI&kR9=V4Y{;NxAv#8*6XoJ&3wKu9BBJV;;?O-;_&PaSx4_g3`=`8|<v!w_LM2C|Rbh z{HpmP2s1=WZGX^Q_G;x-)sF3~W66;0UA$HVxq^Z=UhqhR=)GRKvFrX3fygA8ZQ0MS z$$`9+SH!botqXn{WSz3^vAg&4q!hK$SNC#zley1=#y6DpIUJm4(NQ8ReNsV1&pE4c zwyIw2j*6LE&w+*3S>JDP0achN*?EeKn9Ka<%60KjxaB=+W--%8?NLnaRGvD%Sdci* zTDHhmHl+0amz4`Ce^56s>oX5)&RBLP0-l*&p^>L3Ta?&Q>Ueph&Z{f10q>FRN7q35 zfs@8Pt&_*YdX|BkIv-W5UN2P?{2YxmC#T`gN;re(*PJ|?B8kM7Zf`v8>w6`w3t#7ca{-A&i>Hop4u_P%<}oyH)Y2=8RcI zwx&y@I}o11@vL;!us??TyPRq+WS1v5jc3>KMy~Vpi!2gpr=A!$^7UtIE6#Xg7^ie48t3Ue(196;8)>7>? zA*E}`QC?dMrpI!8=f;F26;cY%?T%3KDK{F177TL*tw%I&1l*kvZg>f`^TxAN?+H=Uaf$?mGOi(?&6oF98VEBtx76Nb51 zNGEd{;Biao7ag1u$cEF6U>8%IL&z~B8`Mo7E#n-9tfRJ;_W*ZFJ*xloNIoGCDfvr zyUrL`0FiNHcjgkN4<1VAvq>tI>1}~XVp{>=#vWO15F6mdcXN9a*qbLI z2^VQ5M|N5XUo1|uVvF)+hr2LcWNip2?OAG1brpn;cg=Au@O8ZKSToMnXR|h0J5kBJ zMmXQz8@H9j{Y;41(F=vtLh`=73A~u|;G8O-_-0wnqj4fM81f5+?~&c%7e^gPfd+x| zV|$3*l>p~$AquI<;>}H3A$%QWaICp+>Wb8+&!ep{(7d(vk4^he301BM0%fXW7TU?3=>3n07 zj3ArhPDtX}Iy81?B?e+#eayjZ9_?CD)KTXL|I+E#(3rG1z8KW0l06`a5aDYeW6VAIr&Q)YNUPWxSs|Gf903eX^_ z!WVftI$4aaiLTooc>kCB(^Iex7HaRgH_$i7jp?%y?5X(MjkKb@`Qu;58t>%Ow@>pI zP0KR+XDpzpD`^G)jnIUtsSN;7Bvt9L{y!G&>Fpbk8L%8nRC|t)Tbovo|FEOt$=#Ro z@*!X5wL}*3ixfq#yB{%FmRYDND$IrBaNLdqE!?hz} z2PjzIpcPdPm%=T^npc&MQo6vHXg3gAE!7|Vd>AzjLD$AC;0M?Isci~fI*=LFnf?fZ zWL6jO8lpi2Y&cR8Iq(Ws;UWGoc#>H*YOX|p5?ZK=Z_*MFvEZBhzT74CxG*t(coRKB z;o<6OF?=T#%E)PsI-piH{wvGUk6VZQf(}D2Pm}FOM_eM2Zn#gfz;_ke8Duen{Xmw! z_Z9EE?(cAp_@F#Zg}$eEv%hDh3jHmls_YTFY)_{DLq{(s0D&gy7=izD&hbBjwoJrW z)d3E}otP-UAdr-V;4jzl1>jb&S8wUH#Gc;jo>h`)M<*o*r5EcjW$|drVFD$k+kMTI z!4A(!(C*E>DVL&DOiHC8JMf!F-&HfoT4$|q2RIYA0oW2aa2T-l!-l@^VG|lJ&FCG;4SlczpOT7PmVd!43JoEX6?`DHO#cI1=3&yVCBzV}h?_u0^ zSo1DU91`C+N5EW0%YK)j9s3g6g|*-B!Sr?ARW>p{2R*?$H_kwnw@?HwZUaEm{bA*yuB zxaWo8ng>-@%%BpFtKjb|p28yL_Z0&w{&z)R$L!xk=%b;(;02k=&U3uir8uQvtTmWDr4RMO+sFuFY;P=iJN>aWv6W%WUl<-V zA?+z*Qau687FJ-Kzo}BM3U%Ow$(h^3_GX$n)85^$P@Azgr{Q8kvp5InA&Ds&2HB%?LEpGd#==-(-n!0}!g4g)~(F(V> zo>DYb8I00T-OEPnxn6DY{?;kQhoveV5T|7s1jcz5@hxSeFQTS3?7|mQVfngjKMxiL zc#g1`c-GGqf)`}0#k{1usmCBYUNT!KU1b5s;Ti?eQqY{{NxwV(=h{|2p#LKqrrE&@ z13z!E8`uVUr9gr8-Ubtj^Z6Y~hsXcqA-eCkTh;TCS0Pf;V(eT(K%_YW^Jvxp9lH>cJ0q>y z>A0ApAo9LQsOo{;eGeU>Cv&Unc`%P*KxjlaL}0@GB^b!FP&j7FF-?@2J_Th2lo9&@ zds!R87ju1TR&@h;ovrqVyFfG)0BFuNdUXn+6ORVtLajQyrvSVr2+&CghaH`Sq>MXa(e36yEOstvmCp(eZxVa;ve!Z$fE$sbMLad{ zS*x~S>uiC|GLyaugv&gdvS2%4Gi!L$d=aMT%P5T{910tblN<>F^c-Chmb}(+b%lFe^4t-GHQj7p zxsYGBVHGS}v^Ifv0afX-AJon)>*Jb4(LfZu#3x~&SOIAi0$4Q`h)e`6Ax}n<5wSF3 z_rWfqA$sNCd}_pL$<{zoan6_Qa1#RuwDjx&nZU#2OX89(bn>Rl{k9;SVole(l?&NP zo-K=-?sI1~70qR&&nbi~%D16}u^WW}|xQ2&eC4&{`WCCGsg@V~81CIMW?8cG6yo@~qY7Kv)+#?W}1t)491cN0{b zk9`0T8d*kDwfOuCZv<3yFYKYpwM7yg1q#oqZhvVWSo)Dh66^Do3xT&9h zU7yf{=cdXL)O+6Am&(@mB7cP1UEz7Fk=HF(WSiNLHs&4N;m52QGhgkwHfz4#`Q$q1 z@AiIKjWh)I<6D0I!Br8wdIkXbZCeG7iL27RAQI+XnzF)-#|@(`MGI!*(fo>mSG$BihRw+ zW5XF=Zf<_nEPet)s*lhG8QpZfXsf@DLcI&Ycz!kTDN9>RZzr#TeZWD)jjfMmN;;_4 zmUZr(!SpXc@^-{>A=AH$t3w{qYhu(ii>5ZsMdlFd4?}9%t-g_@Y%g^w*i4|uS&TIP z?a=gv+7TtEueR6y1oYGqD3(2bzP}v;RFn|r8@#We428%BA^4&pbWVlLg;7g0uN%`1 zP^-Z60M$`5q~S_EwmZLLkHiHT<;=6zx|8|6uiD|5q2C=0q{^RNC2y4uRzz=7oqP6ga`)LZW3HMY%631w2*KMt6*eb-$7Dl z+t8e@TO+rCUY%i=kOlF6DU^jobIS@z#_0m;Xy6}tFvP_%nj<2zg?}EFpuy>~+9YU; zzQpC1GPcElU&1}@t4sS9TwuQlcv$_pf9hQ1J!NgxKct)qEAzEK&Gb&TULA0#8u?%L zjhLqhAB?(XZ?si{MhLD@0B8u0um(U{&Mng#8Neoz zf6y)a+1mTkImVh?FaY|(JlM1GP+~*ZV6^l++P>u;NO5q~I2x3OR7wHBtS|S6pGHB$ zo{ME3v2~6ByURe?CZHfZ>Dzn9X~uvKUK=JJJQ((yfp&h_JlH;^-PnW&OJK%Gf028g zMqX{Kz(DX90vD#d5{kKiqp zAv2)RMKQE8_x*hTzRQd+^och1z;ybzv)()lL-*=g2=~CA;wG`Rj+SUds&UnRXZEIQ zhTs^r?2EF(xL72BP_;IYl%+y1PO7r4!;doiL?OvS_xrl36Av!vA%O#}Oi1*)s(QI` zj+g9`f3tL%fHDuw8okO*o(87KXi7^xzr=ff2f)n35s#r5fYZXQ8*lO}RO7^g$9%Y$ zie7{j>K0I z%`ec5cK`SNKhXTuRLkqAv5gr1YT?>rm#yP)R$m_gYx!mERy+pPGR-`|?>aHpYFhvG zoTr8aNGO^l#>OLMGs+hP9(W5ew6aR6x<28AAbk33+Y%r8?{2E!d4-yb=7>8@$TfNH@D zIheF9yntBZ)XRPEyF5~wi7YYacF!W=GoZ>YFQT+$x=2=L6oaCkv;m_E1-dG<-KIhc zW1CAD1TeQ*MJ=!SQ~qGc@qhmLCb8_pJ4M=li_6VX#zwcLK!6@A}9+m6p7Xp>MDKuKMeh(iCu^++;vAUg*j!*bFSr zN~=t$;qv%CjR&$pO0aQ*IP}HZuHX(G0>%e|zg4sgxykv zzjYi$H}UxF^&(Q3d15mI8iCSkGb^7wi!@bAb;bEAKyW$0O7W@af%viD)rf_=Y+R;Z zF%XD!Unenc#wY^#&KxsIZgEG>InGvl;7O+~)$8&iz1alb<4YF7T`jf)g7G zL}uk(?(cV0rWjYS;oX1nOp*Y1>GVZ0lx5q&*uqVRCuT!qiTqe2ptaj|=$j8o1Z?7| zZN7NasyMn%$Pi_HnWKu7Rs+*eN%fb3b=Z4cF{c+wIWo#(pN;lGkR3u``~4<>3CkS<7_=}=tt&9&wEijk#7UFi(hXjn*!UN zYf|6&SOywxkUv4EvDeQ?9be)My$2{T25bK=>(dIX+#;9a#332+WPX0#cK+&&KSJF} z+qU+S546<;lVG3THj)NG4RNeJf9XLZom`=MuPORpUnq1h>^xeFZ52X_7^($fYw@PI z*_$0B|G*dkU=mykU=9($m@H0=s5JR7ypHh~kAWZ1b8JgEBgHoL&hHyF1OqEGE@~3& z@-{&R``>Ass*hmjUjHfmyt=!?FK{8;=F)BcUMg|qgRmzfa_*ey220s-76%l*Kk58sJk%vo zIIvAIwSbbzJ-Y-4x1yj&EZSwh#F!Pi4}y8SLC(5!d`YT!y6K8(r{bk+_NamRfb@s9 zs_l9d7{3atDKA0brA|iymrvd4KAGG|Bsq8*z2I|I39?>VVa;C$!Y_S_LF_o5RI{rp zLLl;)T{e$|^cU5uS^f$Mxd7U&7F>!NR*@+gK`>3Mm5rV1{IDZP<2kBWIWru-o+}ly?ql{A*{}ynV^QL>uSVli!sH+6{L_I z%wAVEsueg4ZZLy4_fCuR&75ff^}8`kO#DvG6#G18t?l_1JIciKh4mV6PU{?;3K4 zp2nlFqfxc*_d`h|FdGO1wt!SMu?B|#Akn?vLanV#kh)xdOF;D4-u#KrO%p?t28?|!&woAK+}m_pTy`Q?3JPHHZpEb#-Q>3^ePAW7fZnR-S&CEA$z<31Q~&^E zB&^Kur0kp3D1uOUqq31R&QYXd4|%{wedMd)i<6|nArw+KNhO^|3YBacWo%wTjj*d0LZmB-v9nR#IY3&oNS4@RE>1WEp_<@?S}708S_rLSUh$-rfNcxg0d8}K|t34_An$_%l; zOlQNId&HOn5hYy};1ahG1lDf#k|UVjUNQ*)2TW-Zq8HtJ&t|f5^je zuXe{i%yV|xL^HsWLWcl}EC_o25Pj*74_9tMLKuiZfF)oT%`fMw>Q!w}B5XgjSh>gS z?_sq>`5zq^Avyl!Uf{UxF}u1k?`2=4N)QdoUQ1GM1LY4R(rmVA6O{6#JqDe|PS!C? zq+RD+o{ug9b3$*RQ$U?`jlmlXO*PmuW1l@CQ~e|ZIj#V_WBpbf!ln8f^0zb|n!dnL zgERZtsz)>-+pbm(WPW7vXzo^dyrq1kj)Y^(0*qRX~FQ=ZVa15gw;2o^Pe zG1do@FiTbFkDrLo_RuPYjgd~lnHZU!9sD=9knS-F{4=xlI`_C1iJ#U<+J$XCQZI0d=-z6I$ow8ji0HHUFLGRO#y%J@LYO{my<_kYMSt{M7g2M zQT8)#OQ>H61Z8TqsNpM6bwZfFy2t*CK}BR75x0g5JJQE*Va&-})^!EuM&O;S8S!qC zN0!o88khA=!^;jVRVxBjfVmiU+W{SA6c3a2Qy0iyGqe2*U1$2jSk85%jFdDOvt|~L z=8y;7YXaF#1*7I9Aj-1JMgtk**w@h|TL3l)*(dTKT-cK1NE#1U>^r+`Y)#eV_Q! zwL2k}L6snXBl{57(WrZNMQ3EFOaZ`Y4%0}$!w%p%<=Y$vhPY@2yGc%w*IL}U8Sg|- zuhsbzz#HlJ!a4nrO*|z4l8A5))4Gi*+}z5$+ckepSNxYBFYJep>pYjN4F z-~kER*`81v%`?p+qOKAk`eqQ|5MN3-YhwswbIu>BJ%tN|O8y=*@33A{)WYi=k&}8& zs16WbF4wGR;g|y>w0bF7vmtmH!{E`t=R9g{Yxg7Op6Rrr;8)U~8FA10rq9%@wD|o( z4tJcKv6*x#)J7iMq6%%P|0{Hu;H~=u3(tJ*U-2Cvtgyn)i>3JM&qg=;<>D=(PQt%~=hKH{K?h?^izhiTOUn{FY3LlmcGRmp(B+ z^`rHLY+13#!RJaqn;IpzJ|8i6ORs30wPC=vme!>NamW-wNHlc=0od`FWK-A}fT9-Q=S?OPBNMDlG|>Go$}oa&azS z`NNaiu;BGzI30+%vSx$UqBtZJnVHq-sH&$5=!QD4DWc~3sMo0)rTe$77b=0lZJKk= z;z57yk3^Kn)HVC5Z4&iA{AiS_BT;+>_cUmo{H(9cMqdmUc2o$9tngJn z4z%yjj8}ylLrM>ngqwRRhpo-{hudmyUi^|GxfWQZ{@hU3G6T?6H@-;8rnc~)fbgH< zmkah(#S)=2swm^Q-P7d-S5BOd+RFDuMNi(!s!Qz5d*5MRBJ!rzF+F=(yq4CyG2H1BrE@8DEo*87L{+D=pwtx3c=GrH;J$FIsN-tfL5XMuGhuB7KJZsaL=BTd=*@ob0 zpIyWBVLlAo%9r;|qg7$6!FeG&NQo=kMOQS#Q$zW7SG8?K@YsMq8|_H4gb-(1=;m-!e72bav>>-hkIK zUm5p$R{m{n1-hw-JdrRl?Yo&goF4eegF-b(Ea`eSOi#^sw*H%Q6T7;+b~p>!TJc6R z!fL&b(fZ{A#>Zqj<-v@W^vkvEmTb=}hSShrTfaq&x@464c*FM?nX^5ddnPYPtj^!K z;rz2vt;3&1+|AxJ(E5X4k-d$U`OLHMJKwHC#}gt_iD&#=`4T0_t?vez=F!7zEw6|& zlDHgB<)R(ZRd*CWkC!|SmO(eW)CL=wV@@kZO%&f-=k>u4e2#>}G;VRS5s-eHKr7n0?Blm(et|SJ79C z=IzFVW}6f-F>wf5Ty2+;OTFS&dDjEIXCCd~inAX#D;&~9w?pG?i(lK!sk`w zRM825ZWrZms{HK=2~xOqwtd4RavOxqF6p3s*Gsuwy+U~o=N37(CvpB}yTmr}NuNQy zT?Mm>?OT*D1U>81xKVtxJWc%`y>hBoi>wBfVyE3o1lF5|Mlb+__`vWFAGB$QnTCD z9Na|v+mf?y!)*^2NJg0F_{oIMSbo3u(c%FA*_LP&u!-H0H-5`F@IE;+9x4`$ZSF!J z2KDU<+Q<`@=ou|R+s%##8+kl&1_`1bxIaY8MInr?aZjeNruG7sn-X0S?4wSaQbq5hvSG=6t>f&R=Qg`Y&TC@%{Wj}U80U7( z5-b9yOe8O0ZlgP-eK6fAw|cDdmcSO5gw@lEcl|C%+cA%;}XB#P0RkKf2xNvoDPvyCsUs<*n`nP#cg_i znZuWL80=@ZXa4gc$U)0JdeHi<&etw59SFDl=DGJInGa8-YDtt7mSMaSOZPBU(5~O7 z@Kr(T`NQ4-(c{<0ZO;WyQ(%d15K2m$vuf|!)FjCMJ=Af9LC!-!veh>oga`j2x7ae( zG34V?%6c|K^gCIQRLyE25P4%f?^lzM(7VHzdXFy=y?xAP|MxcyV4)waMMK>oS>F2M zNA6pQc`?-HX0Y97Ywiu2ZIoQGylML8g+()1jKzrg_lMqDyR_r#rLu>KX+FPmj*&HoK}J zBCNg3jwO{co60Cpw38&=ys@!AW%K(Zv}a z+>+Pe2y=3^Gxu!ya(>75@`nlAc&z9ctb(`u8zOY%9dOK z=L;CszL)G-$Mm0iA|8?;%ox#>!GFAqAmvzhflb1A(gHCl=Ntp&NCaQs!uU3lYj{5W z@A95OLOD?I8YhfwItKkbFU^N-b^Kj^3}67117UzJ_G>z;(t8TNA=WG#-JCJY3$!=H zpS$bgDz0m`W3M(iT|kTh=?6Ef#OU&|73ZLud1Tmn<#Y-;xdaK+&V$-rPiuD6aI z;G^8Op`KoS7kk%=z+4Wxe6~8cynjjc2GBsF)NUYeL5Aoc@uHJ5)E zm@7Uus$iy+wnZw9H}L0;aMqODJr|~=Yu70~x*L6f-l%vD&T7hS*W-)%YG9AqvY@i( zE+?P$rmxfUdu#V-U_Gwom2p@MeNElO#--#>*^G2iuEWle#Hvb8%RcbM-n z7L!U7ZLiaH}z!SA~8aakXCu)etk=af8! zy*~RzuFXj2^F4cg3OLu~YA+nQcF{$#rUVVuectfr&Smi7>?PZwQn@pGoiG4>p>z85jgVu)%@3TvtR)JYyk{Oc{53~HcA?q(#Z(D- zZ@xdZ%D0t<6ll%!V=p^Di9B>VG;s}8zpiMYv&XY&xR8AYqIoF4`l0;tt*D3;j%Ps?aw}Nh zLPqW)5AqBTu>J%VCpz@~%<%Y45Ht`JV$0VndtqPMlQ z#m2u3LX07ie!rzHd5|5lIf+kf+W*h(?`g>(h%z>(kNwEY$au-Hq z&>Hu};OLcr-$x>zq3`irp8qxQCIQ$`XZV6|oJe303n82m7Rfa53|i6knl_^iRNY6b z0B`5}-TO38phie0A|+I!0=3k6ZBBuN#`j-=+@SXHhURv$+GecizO^NL2Ser{a&l;% z-}S*&Wtak=UqH1+_6`I9e20WQ%5#0dzCQnc?X`KM^l0v%#7zIhC?d@CX;0fs$&C2e zhwB%CG`TXRRwyy;v;U()&K9sp+V*}(>tfcv|ACXvuRcO8?h zK}+NsMcM3XQVAc(&DH~RK-@r)FF$s;RaY#RtMIu1X2UtP9J<}{#WT;npIP}Zp-o|d zVFWz-S8$V7WK+M*uMmg3X`)i&F1RwQa|x91*k zn?DH6U`h|>14|gB9Go=MTvD^MTy7Z0G3xS6CJaJKZ?P+BwqcwA(vV#ua{LWG$os%! zJYf6z-kdYdU%A?!{=CQW(r<5%;c;@f8Z42C=_1L%uHhAXA`j?JqhJrvIm7+E0lw^Q z&?CE&gn0J}#b(X&0+3NMrsB@@tPzzy@)|^d8vFpWoR}1t%Wt}k;nV`5i%!YcOrJO& z{>KA*-xXfrrcn=kWj_}=t_4wfYnc9efuBVJL`OHYUtfno^>ftMkU+)cy*c2>wZ+XDD-=H)Uub~K{FEp}Q7~p}#hAJOMO+uEy zsY;9KBUkDxsh4n;Bgco2@p8zUEX#MAtCA1v?7*jh6&miZ;kkcaW_V+3DUUgA!znMO zIK2$J#D*_PnB4$8WCve2CMyDlchA*~c4b`el=_IYa1H`4nbPi&DF z>se`5;u`fjclayh<9KO-7EI)G#TDgl-sAIq8eZQ}s7#`N24DC!v7(lF^kagrEAL8L zL%JEaEfH~CbnkJTev468m$d}cwG-yMvZG$xG|~U(%Kmiwhhfy}@2sS@-+`gGMfapo zJbS((K;7QrDK^Cp>5mhsft_~-@rzg0GiXDxh-_#cT*c>i#JR(;Sjsh3H} zhZa})rrW=-hI4_i8ui*kned^?VTs76HD{H74?G|c`J?57s7jcYj=iq8xC%?<(54F| zu~=|CnEP{tX4!IeaftL*`|L0cg!cPae7}&bVqaKzi&~HAQ9^_?Pm||% z9bMgz34SX`cC!QG+$qZ|)ei*$_QEnb+pRfU*zs+dDR4GI`t)Q z9TLjcdDRC`(`GQtTFOKhSbbqdr z)2x)LyHh)jlMSm27mzJ=LD(35oRAdy%&=-pM!e~|joZZVxLc+7FDSCD)i)1s{yIAB zs4lTOxkAnfMYNG@r=^zkO-IA)d*t7wxrzZjf@va*WWzSmufzTQWnzp=ZY!R1YOi|| zwCaR}5;1YbfF{j;V=)4HVF4c`gFKWYo4>*@4x|A>R}A4xg0N(Cx5IkdXqR;gB#rsWe^3)@b#euv51cyuz=w(l}}-HKpmg$Yzm+Wrd&2! zW@goWB7|A+tt`uRad;Il^`uT?O8dgPK3T`Hv#x|c4);bsO!e_DM z1i>!R>5*KLv56EO3yEtKisVy~ZU z$az$7=;&iYrzC1ANHIuC=#gI~9IQddLL31^<)NNgZKqdw3KDk$|w|9E}4!6A}uDYq^Wuq}C zz9#h9NA5~cy;GjlBGNBc)$*x?59yXo(xHCO73%anr$#eI`ETgU_45=z@y@zc?=to+ zMyA^5!pc3>gh>IUS`rx-!KV-@VR6r%=^tpGlV?6R@2GiyD_=TPN^e)G(hU?KcnmJ9 zxd@R}mjA}q75|zZ&T$|AM5l5$|IY1W49-g2eW z&;}XTx_1%zj^D2ppAIfWkzvQfm~tYAMQjeUw-JaH$Op}qQWHMT3%G5b6+Z8^Th-sv zW|RG+<@Nr$K1-EpVTt1Nrt5~7y!u}ESq0R!eG{hy(2&|uNlX>Z4G4veJS3PIKgUq> zzOF!hZdei2-6_XeA59>H0^}&@M5olroHe*MBMzL3zDaQ@7!9y55cZ&M1WRSh3@p?B z^!@PwP-LT}Hh$PG!EhHN{m;_A=^~%3_nAzCQIE_|)}KXg!j+6Y+A8**!i44+unhTqMM)2BXvoQhx)DT|!Ei zbNX1&?o0Q*$46GFwi$?>Nv>qpyFg_J@A)hm1E1gt+nnSu(Z&J)veX}6W!$cK}~Jd9Z(lR(W8|~ zQYHEksD(vb`X@ZV8 z11{atueTvAT0~`v4I&UM_-R0qQg{z3BERsIkOcnGD;&G zfWD#BCY~I>op5B1A6Sp8p)V^`nqPff1dgrK8t4O#aIj0vPk;uD>)t`OvbDPIS+S~j zMCK@D0U$aRNt*)Hb{jwkByU26O{AHN0{)X)T>{ zim>C5Ex_4P$v`N5<~F6;5sgFFSXSO?e*-rJK#nx} z^aP(nONIJ9tY$+uHNgeY1|y#JJ2}F!U5MVKgHNmhMlLw*TPgxkt#6jfJFl3>>w)q* ziog1$Cr={hNX46JM5$E!-I*hv};=J+dXMZpx6*eD6!gg;Cc!Uus1w$S~XXp5-! zDZXm-p`<){rVIP!7*?@u&7pSKF_b-<16;xH(gO`K888d)VV z{ADrFB$mk6gRN2pZ7tWr_fYd_8-P041r;(CQfmzUg2p&C5*ud{*kg+R=?myTg0z-fdp7n)2by&pS4<-J( z{yDQ#*dz=!1y!Ygj6LxHGfJEL%&H%rNRZw*sY=qe{{7Y1_WjQhOGD#80lt%jUuybA zjqw8?G%4-=^jbXg(Ll5l1BIi|lCZpMo^BS*?!V%WemaP!&DjW0kA6j=W zbqYxj*iLotTA01r=9}K`&BP{`*(%D%Zc-~A{Dipue;op^gh3DCbEQ3qrVHEtsj{p=Qm(u5Z{R(z5*0=oX|MNfvbz z5illpjXEN#hj|DVQ8noah1bn!BDdrvAoX#n!OUPHACq; zU(y#S?pf}2re(?V(23cQlHO)L8x5-yP%HhMH?Jhh+{PcK3T$pXbmUQpjA_ZWhhZC7 zYr^o0O*U6_oXxYZA(qNb5pQh$KUG)TlnW+38=c;_(u7Cb^BUFr#O0=cTz+h8DH+oN z{%=}&`9+^h+eI`VPT=y8>BE^_DJaxBXl01Mk6yhbV>s#n@R)(T+9A>(?h2{`V|3&%cN~fU_N;Wv z+cZ$m*t}!4`j$u;!I+8Sj@}AK1EHjf$cn}oUXPK-de!O|WWFjFmMsUd9O92cf5GzZ zc4Y=M=nPipoAI0^j!Oumna&YEf~i?H96T~Z0F|{2;~!4S14U*@4WO~8F%+1uGD?}Y zw+afuq{FTyWNODzSmV%&*o}qc*L8@eX$e{jo3S4)rxWU;W-w)Gvuy4Qb||R>6n2gs=t;8!y9g^LgBmu1O+rd%V#;CDtSVCdP#FLc z!5^F?+mOYPpfrMe)Ct=z54v`N_BUYG0nrScs02K*hmGzq2?3)TZpQyUTp(ThBjihB zy~*MipoxTc`Aasyug3ir&9ABl_u$XnVVGsl5FRXnwubjA7$W>&ZI3NH{4q4=T^_<5 zf)>tS7=DBko?^bQZsR=#uOym=-)GXtu_+uo1;GBF>Aw=!l;4vPI+J3IJJ9e$N|=sd z)<)y#x7g#bcPKr8d*|d&65#X%(J_AnZo!tKxKrZJf27jp6@csi78qZ~9tJc56b0$d zz(MzO2lra%!JhXPi2@D(4(BuBIN*wWgfV1Ho?G5;@!G)g^EeFwdG_67rEu2O+8|B% zc1)x#nvDbQRzAP^=VkOyw~#{rU$`?wP+zsIJvoo}62lSai%jF34!C~45S}wJh zyC|DP;YkaM>aB8iNP~$cfgA4~vBAc^M##(q+E3t}DbuzCPD9!r9p|cN&~RX(NrWHC zR}i3N4qHMRM=Jwg##~PZF|ZR8X2!2f4r4Nqfqa0Q6@u z02BhoKu7u?p&jlS$gz_r)ziINI|X6{Wdl`|2&%kD22_MyGCb~|U21y!4`v7$Zq;YgK_<2e!{p$Bs42^%2PMh;yCfzQ> za@@N=SYxe}|Cnp#zOfA(OI$ztoE09|nu)JZndUT5<};kgyqO3nXsqW)z3DR?;7^<$pQSM9Yo<$BG4Xb#qK0_Llz1p$l@d=1NO z^WmA49fPdgic%8@=fFE*EdajiVgKtScnyOtFb0$Ywb6f8had8QN=|Mkcr^Yfo!3!K2%>UuM3$t>3}K9>OeHMpFd%6M z$LI3F55eIF$B5ka0CMwH#^-QO2+PfsX{HMC3zt7cTO<8<4NQgoudes;0uqKQ)yu1q zD&(orBt-5k@WYc34xh}Yh=f1$z~39^;&c>F`?6uud?Fzv2Z*X9>SaqpP2XAe`Ah%~ zgOe;vSxkB!6$>ZEH6iv9A%!&VDi8Zp0n0ukfM)WSr5k*DkT&lF%b;0M6d5zP72FWQ zr21x#=Cc|hl>%A8?yQ&gZCCq?Cvwd_D;Rc1*~n}%#v=HYpNtg`4^ssaqDc+-@z0ri zIh6?pfJ%du!~Qtj1Un{!IKM|*AH`UlfC71-g(Xq^5`OWUGNDV@VM$jcN%>pbQrtOF zXw556d3YcB7(mF{&9pTU>lEgLW(hiwx6HXUX@$&;8lw!N?J z&BA#tVjf1R{(SJ$(3^M&bw+;ZO6xH@#oAhLhqY2@QJ*BP7bidLAj1H|{b!bek)TpxMtm|C5hYus;$bJFMS6<>^nfk`S0pt; zfWzkyR^6+fSQXoDp-=-1r=D}#`^%Q;x)L~APnO1$fS(4%h93JU+!Uzhc%I-LqcfOS zyN|;!@#sqwQ-ktI5P>m87(w(|uW*FLn^dco2`Ll4_r3yFx;7&hQ5B^uc4~qlDWWR- z3_MgR*bD|p0(~gZ$GPFRa@!&PLqqpm3^@y^jV6cv{*vFsP5mV_+8Cid`pM2t-66Pjvo+j-CRq=p==4;yxq??QXR=9V>tZ1_Hz z+surO^`Y)0LA=x?PKO3s1XiB_0p&LA1tc`}W~o>QUpCkBlsaCrbdC!AOq>cmqIuZw zn2YD$D;|gjDk4wD$h7p2%ub0@A$h|869iT&Rt_#iXRw| z1WdoG&cgxeomJ?~mV#l!DqeP@m$LL*VG7zqL*x74rR2j0yhT9f^f!p-MdE4SP5-fi z(QbTvWAK$#Ely1J2s57bFb&g)vqsgu`IwMIu_>@n04OAp{uYVO(>vrE^ZbOdfgFcT zbojJkxQBd|aMrgbhw$SV$Ug+RS#Cmgu;3`(_vMZ{SopV9<-=&?!t=TEG=!Qs@C# z@Z@(?sPU2x`=9tl6hOa;)bpWm|00g3oYZYlrQH(TWE1zVW>^-!uaEoO&r z@(lc#TQK(*9%Szc6`>1Z5lPT@yK)?4!9D_o%{x5aH~J20NCr( zwjp08GJ})%u&s~t_tFg8j7}$JZLEWOj{mqm7T=U{L67#^W+b=hFi^45pDgKepr0PrK1)AQ^&POer^)3I5$fb*2+wR(x z30s+F#L-p{#mEq@-xZL#|9IlrVM90O!Z+3V$@9Z^C-J>v`gawNN+b-ux!b|AI)ZlR z@lLr->)m6SgrW2Gms+?bnF`St7|2PVits%2ey5FZ1Rs8<)1I>nzS-2AA8xtR#xlE? zd_zLw`pYY8=|(Jk4;0E18HD2ZvhjZ>W}bVHdX$Bwgo0J4k3N|XvboT~4f){ZmEfeq zmvq)hnegCu30{Q7&m>$GAwFQz^#nv4B#D^KufN{dzMzX56YXihPrfj=BS{1!+MZox z5J@c0s8q086tbJ;!0U|C(XxbujaMKGN^2qwi8NJ0c2D3eZDPY@`srYQBBmoyx_^fD z33pzQ`YaGhFhdU?dD&zWxyh$Vz!||DQrra@8J)cD;-5K{sgd*`R#PY4m_5o2#|oVO zW~mEPCVhlmf|DuTrb>Xp9_@kR^GE_X+H1Eq`+G-PIr+V-oJqDlIRZk5j>iiaE+yUs zp9PTT7ErB)&AGNWE?-POY(X~`hy)(r3kD6ie8DIysdZd(3FH(qgL5G!?}}w9mSK~( z2nt;4br1ga&1^mV5Yv1KJ*A9;X*3KBqysQ{@lmfGezF7_e0YAZjn6yeJn8uh0k5*v z>T&!Akfr3q*3U*8pfcL|wLkm>h7SM>kCk-)n?~MQDNJ6WhW7xFG){Y|JcvJ+xeT^` zpiFlv6k0gzA+4Fpr_i#SiS5q?(fBb3HDGwobRDEU0900{$0FvpmQ6X@sqygeY7^Oh z|9^AkyX3=J5iqx#kj06b46#A{PJ^0e#k@p5Y}GjN(yizsFPH@|$|sSuKNk$vW2(?y zDAW+VoBE)ETqF_LuC#D-d-gO236xyw&n-%&W@6y9c2T~sm zvp%HYx53hw<2WEO;!1NjB2PHqf(M2B%*ONu7r@;6lczQpEXeeS`QFe&eBqmD@#6Dl zf+985}HrQYi#tP2kGkKPmQsAENs@jy~41@0KT9W zDghEB%hKb8k4f-nnUB?@`5Xr@))$}sJ$l}@L+DOw5@jN3wa^SqY z)kAw;VCN3FaMR+$%`ao&TRCEn?so^Rv2>E=DN0-_w!Q#-9IECGZw6pkE7~_5Zk@A1 zQyUg=0%NFQm;{aTye@IwB5GY_u|FM7WiiYP@?haFX2gx`2Eh_)FAzG(&r~jXWdc?) z>csT*r9Pj52cZ>0;1rBWfERcP2t>Z;;T63F-i|Bd`86^{sb#BM^`+c7HKh(ViSe0ATH;yPR zrKCtIf+*cBC8B^zgQRqa^aeK49R?i&3eqLr4bmbFo9@_j$A4|~oJY@dp7(v;>wBN; z`~KI#x$kw)S~Ig|elu&X!@f6rm=&jU!slz0xlm87jq}s}{c}scI5HlJs$N=R$cZZc zb_}L)#ZcBu0h*w>{l0bvckY4MZ{o>f^`Vw`3j?edzCRbKX4iJp)J?LUxwj4GeP8)Z zB}RH6$V@0q_7#k?!8nbiyr)Lt#6^ueljMmXKSL|BkCwqEzmsb!*@Ox!=&@WC*DQ&nkSy{rzGTrdG-lf&T1&?-joU9+&Q9RC>z%X zwx0}k;i`Ktkvd(z^HbsBH#F_~ta^3+*D83rNr^&2Vb}(Q^CK8Rub(BE(lwrPFgI_X zch#V0$79O!AhB({#eB7Pg`w6NC$=6=M>y>!w+RVmPf$oki)*lef2vpGpU6XshvKX8 z`=X9B6Ap|VD#0h7i*A@8~sYbM?3EfdcrI*Q&d56m6+Q@&;_0m?mgx>R~b()+hx ze=0eX=n&*r2y3bA!OEs&=v;u}zv`Byon6R)$K&lcux}}m!48OD$G}OjH28(T`#ja% zRN5Iw>?Ff0@T$c-%Jy^OP~9f)S@h{B{-Y@J4BxN+^3+jMgGLMcHrI0zw;pIS-OpNb7f{8vU$70%XN2Bf{C<=Mn15x3nuT43xYQK~~A0>YE8Uzff zqReQrItbH#y)lb5w$`-@;n`roTj;_l8qCD&j?emJUze3nUyykq(J-v9;A_VrWgF zq_>)}LjbJphD;>0BW3ghlksXJzDIQP9=(Pr_ZWx0gjN*&7GymF8Bw0l4_~h61?E>aIl`6R)z@ipS>XWWsjo5DTu}q!Ou632yGf7EBN*;n;>#aq$D@vV~5QcZf z%V^DYsORzX4^Rd?&J57vz<$fl5apmrSO<;8nyX?ri866uAHXP6S1f_bQ#%>irgWTm?Mu{?zyi)h#>O`H?n2{E6#DIE-?+@y(gN}ddJnGVtkk*4~${{>fuuA z;r{B+gW+dBi>-wDrFGojzQlEQplr%Y=CqgPzzK7q-m`R0p#>{`hfa|G;1JT!%33kz% z%BURdC38N9#3ll~ci)sdH}z2u4=?TIrUAx*|H1u-ah&LOvjNi60n)PpCIVULuq(H7 zTE%ldH+y1MVmwk0=d9wpuEj7DaI-8K_=Lzk;>{Z$iHFi53HQETB3N4-8-Ul!# z$E2q4du;yq3Q{Qz5O`%eKxVX-c>YaR9e)e9)JoWIy?qbpM~I_&TbfKSO4o(r1h<_H zST0>E!z)Yv{1DCX^HBU^{554g8fAqU2wWUE0o$!JhAG_N(#u*Rsn)ST%!r8c^}IbGy{*v*t?JtcJNCLL;-uES=#DM zU7%mgWGo8$eb~#38%k)Cj+2RRo8B;5_7GJ{cAvYERsQReraz2 zD6jfWewZCMbggd@j+6lwD`D7S?ew#zmcbUgako+Pirkv&Rf+*&hZf({?G@j&U7?IL zx1+n2tEEuK$`kn7hRqpNtX|8Pak)VAY`1iMePCuuD_?Hkx555UQbAcT_}F~>%=K{N zXn);yOt7>}uYiz{xHY2?^=^{4&zBCzr1fAfY0mgE2Ky)rXp@Cum4W*acYyz}PlM#y1?FmVw3g?&=jCr^_>6YedPWwP^>WeSwQz=1`Youdpkn^foN5!Vw)aZ-y zWdSQ9SqjDFc~oMKL34Hq;RLYVvPXFyFYp<6t_WSK#(1G}|9u4UHR(R2Pdt~3D^7*5 zF_w)Y>PGyW0_)5(KDyztS$|Ny?pv=7k< zZu)#kfB&hq@SEmc?uP$;B;3uTyHP$utv zx+x?g!V#46gt>PiJ%-Q}LufV`8wp!arI#RG=iw2L7rn*w$9wcR&wS*WrbLYMzcVq` zogZm6sVnYmIliAnj&~*anl7n!?Y5W*yCUv7^56#~r|qp#Zsx=k@GoA-&HCuTw~y|r zEG5*^iPtNZCpf?>x8`hipIKPEM(})jx3BxeQMK{>WL#4C^dOxQ{gAWwynmtF&1rMB zpP2Ies8b%-MPt$eAC`m>ZsZ&H!8O6%qM0RU_T#cf`<_YySUkSw%(68dG;L(MpzTJtVdPpsTa>q|wLMC(_-wbqo95Lh3RP#zCh zOnptF~iI!H=I`rw`sH zAF)F=7X2c1eWSgHj;eGdzjN>M_sNd5T~uEC@G!h6CoeeOeAFfv1%2FsioI2R0O~|N z!ybkc3xN*);2TT3$dgq#d2Dj^%d5Hw_{R!q@x+ z&O&~~xzFusH|Vc8m=XbUR7ajUl4G_&iQ8CP+Z&v=uNk$DaXcGhHjBkE=t6$$ zzN8&c>@r96=;r>@M?2Lft*Dyi)v;f$b3fpo<>1ATnHbn)!Nd{h+f>NqqZloSUvo52 zjOb){?Yci!lUFfZ>uDQW>%*o|o)Z(BIe+J%o144P<}l+^nTc_Z+KmaxA+2xUq{~T+ ztnOT=V24W?gg}no^!>TQa!s2qK%f3IJ%92mW)8bnF^;PPw^cW)>{W% zsP~u~@>JV#UU3-ZLPpjHByW{0eq!#IVDqu8ACpvr8&kdye)}+=?UUa?1FC0&O2SM^ zy$NUM9=TG5-`jw8MT7g?Td)d8V~*5#N2!IiXj?sFR$kQr*=3RJauw`neud6GzLyx) z?~pobEW^n=Xn5w(-{Gx)Du0%q4shlF?>UsZ_!GEDlO) zwi5e`3LQz9`mETa$T)h^ zYwkv`JtZ8mMNsHc=1Ztrj!HUt+Z#S|O4IiX1&4jeqfA%9D?rn46QAJi_<9J_S1pJO zUt_s5{k0=toVLZw&K6sJ00MD;iEbw^v&E)uWjNDa)y@8yZ0XKI;>h8UUP6gr)M`e= znMc*5PtSI+UWjy7>_;bNcvF zhfZ_hooS|@Q*Z5u5np@s>`mV#vZarvipC{!H8G7k*>z<17%X`7N z+M#PL-5rk2y2(#v+JYo$Oc@-5;{1cJ*0YDpR|oedI;4|Qr6@%$L}AFj{6fch^zP*7 zi9)8}t&)8&`pZ;~ z$L~1aCKGwbAmz{oco@t=%99Ayc=%~9ZP`5vu^e9aUk|Rl)>e4i>Enniy+3B1qPgD7 z7R4X|stlPt$H{53r@MHLrHSvwcPE-}8Bke=y%&$x7QKO~juv4`do%K5Y<_)^#qIt+ zOm(?pcw-LH7ufp3djhju?}+){e5vH%gk4!k|Ko3HTM1-)0Vrx~kuS11)v+T|f`U(m zFy5f!RMNajV=>uTt8hiZnZb*VpVC=OD=fJNCm$4siZGIN?$!h{uj6jcayQPP-WQ9&c&KytgPjZ)Fk#=cM^PJ(iF{8I!7~32AG{<{921h5j_l{6& z4ZQMS#Iv0<$mYe?Pgbxo_7k(BPxhF*;#Y^A+@ozqHV99h}Nzw(;Er z4gD;tU#IAGX26dE+Q2KoKOSD9}$82K*k(7G6_1ihmEKxLG zGnd4Yd@?RAnA+rI>K|oT{m4cZkme>8lQW+gONYgi`6;F5b;dW`yy6kwMO=e!sn-tD ze!E#I+GoBl94c!Pp;!*um_aIY|TyHjbklm>fV zPhre^nPgoDKTRP38o%vNj=X86EZ>B-)O}5TNd*85p zMbpBjxbdV;s>k&qhUtcv-N_TGLr@t0xhH?Rk&}6u2MOug9b_bepLM}V$3|aI-qyz0 z!tkOze2+H|C6kQ!RKuKiPF><2AAV`nrmDcCd9T)_BsDu;j;tV+tb!8tLneKo5m7p| zYC*>NkV~Rg@%|^h*tP{0&uA$n(sAq(%Q(m_*=GH?7o_3QT4(LPu~NHk99lt!eYrR| z!spW;Zph>s49+Y))gnJRURg+tr&I`>vvL-U>qt$>#aVwC=m|YMf}Vvk69?++gAc7J zqgh6_JDl(AEKM)3EgF;_xa?VQ6h&|s9(Gz8pYxqBElrQRa8znmk_Sg{zfF_Wa=zO;lKd~W^4;A~~%^mBO}rCfb=Fx8k+0 zNo;8^d7TBr6*`~BI)>-1&)B+=XP4p91*+Oru*kNn?)Dk+#f*A~ZVDuJMs81i=PRW+ z^~kFvttrcFw#-P-UaRKjkfC2}HS$7Sq$XEtqP zXv%Uu^H&!~LSyz=vZ|(J=jqCpzRb4l^D&R&?IKE9J1h1C7!%Hbkwm>R_x^L-nh$vi zPXbE{NBs>`(I^$sp5icYQ@Xr7j~m79xHIIIwd>ETYPh{T;B!MPV@_v$-*$Z8Y}|I^ zn;RyYRIQS4X58w2!y%8&xI9ha${F`uwB{+-{=hf48+VmXsi748l=He3%`-&`!UwWQ za5UXl935t-pDNl`(>D99dJaQqk>v6H!H$KZ^Tgx$cI~u#hESyM5*RV9PntVl1=-BD` z>CJ6U@>6wk?rFnykq+WnU9D8GyQc1~E?x4(RG zfK?JDY6iJO>eBodq*qGrq~Lc`SS-XVQQU7wH;V}M-VXOWmKCe$t!ylta9A4`)21gp ziS%X0O@waiT;02+BTTe+T}PO3k6nin{kSYo>%-}z4L;|#$`DPq+?2?Ul||a^zYd8i zLr`*c>sC}Y_?^siCpqydQ9TA9Y=DOg9)o3*c1(`(Sbw?op0uNO)IirH_89!ft@0u~ zzDMgztZdS_E#_LPyb*W2XvGr2h)i0K1s}>Df_0W0@8o?(lkgis7TO_R>$tZ=y!kuX zNUAY1)J&@J`<=Mso=WgiP z3mbs?|A^C2Dp%lIji-jilvpSJd5M_E(RsLDr|Lt@J?lqLX7-P}%?vejYJz?zUZDTr z-?ll`7x<0PR<1CQMn|qN&-_lNG@!#>mFiH^?%xOo{HWc2e(tE<@i+3saZsz6oq15J z`FB!ZaaIuTRCdOe@Ef@X+l^f7Xy1+8{F4C09602I2ywZ689nH=n2|(;>*rt_8393d z=85w;o{si?gi$W%h{gL*49X)cfR6t&ocw2_1<-w_VaDfePbPekP+)5ywGfyDN!E!q z^k1QTZXtK^$m{Io%>)Fnw_Ok!xB&9)|B(c1yv58P>&9Dt*qbP*M2NI1^r?jU_9M5at98USgyrz8`LX33?+P{Kb{&nL|e8 zP0}->*OMQhf}v(FO);Ftn5f&432*DEe(>`Tdt)E>D(^JNkM~ zP$c3ylefP?FUe*yN-oyGb`mijI5`%xcz;hb8yK?nIX)QZ5 zKRwe%M?2S7d`q-`uXv~7hh^a5C_S;`ygu0+m}Qo7bF=t4(<)*PO2S|GekH*+I)<8n ze<9-+zGS8OJ1n3n*yimvukynmPr--_RdjjD^ z-GeZjh{c*)M{hjUZNl1%sB&{6`*vS@*)fW%u+|^Z->eYw%gd2C=-WN;;ly6UDa|FCd8HH?YvbIxnj9;JlcMKmb*K+q}eq;<6XtQd6wrDwc|)QUNZgs zK{2JU;qhN;yCk)7+!;L;sMf-mt)TvfB7?GenBoo!y&J)sjWc>=z@qfl6WHEL3H$L7 zl*mxgYp_sJP=yblKLXWR7_$v5m81qG^o0KQ)G7V#|C@_iR~ih@A{-&aJGO_L=G%jN zIE#k|Eia(4r@Jl(Z)-M=O?Ear2WzUQ-OMb#v_jV6hm;G4$28T}nf)}!hM#NOXE4-V&2nzgicJm52?1a%o4)CCpgwvs*mzWL(y~HmB z7qCDtfd>UA!>^?FLYVi#Ezk!2LM{t6Qi3+9krK2)zmg5=GtdT6pMf^$SK^MlDGA!3 zO-axO{X)=O{DeUp}7 zQ4EQlAdbHiM4R*rxkQQB+8nOPw_S|Q79IgDV8X&7LSZ)$KlxuR`qdQ|p83!DLsAnu z5qkiovp6n1J>VUE>UF9x)a~U;wYpI6_S&8pdLwOO&yXMd#^nrw=+Q)gXv<@E&`um& zhn;T$j?Jba=xBZ+;01AEfaySC5aeIUl*S37qd7rzG`|oG_;fdL({wjTi(kl7M`9@G zXo#U8XMQF16$gc&qdB-R;UDBWtSJ$6G))Nm{y`?BcgV-?ZU}!Jwy4Cjtn9J)?WdNa zJP2rpzI$~OL4mMC$~go+C3&aBB3~;nvLTvcHbhhW3z-y)L_|9h5$#{dB}#-a!tx*h z>3@aeg7SzDyu1yqOR{{)Jo?vLyvTwj~8X{*`PbwIllZc0@n_3)zr# z0Y(NBkI2+q?Cr?ge#YCrkNFE3a~@DIej)5k^P#|YKn=pyY4{Hl{&%#y<7zwvX`}(f z|4L91HvR6i3m5(m95>rZI#&nO^fx{mn&0x`|CD<%_d*#S?8yy))t_>I z%)L-n4~zu}qs9Km+zZ3R9GQ)Wx_}M8%ms$k^lwO;brz00Qo|gR#((>HEeK-CrS*3p z_|Js_Ao+g@zr|Mp^Z+Wq!~#@;je*THW38pO8*yuD0~A#({huP{f6vr^k!pYEvT zi36abpRtdIDhFQmnu{$aweQhqFM zd?9rUw2Hq<`6umvNC75*dREG*Q*wi;iO4;Vj5$d6Z;I=$rSPIM{u7>bbGh-lD?_Sa zNEc;e(0`B&6gfIgOR5B?cyv(hNPIzs{7YRF(E3>g|1K(^82vAlAONTi$$2K@!1JC# zvBptnKSX7Hf!m8XLRJJo%^d>g0OAfbyO$6iXGB6Y%P3SEh|1k;`2vZA?$-)_QPBSu zTVSt97iE7%;iOtLk`-q`2b?#&xMDv}my3ht%=On(;^NTwi%b4IFaB0XQv2U|YKvhU zxiotG;Mi7@a=HS;92WJW9IdA+?VF7Iy5O8AQumZiOBzA3^#t1l4F^O%Cp=pJ`>Cc{NT0s1dS);WnxFEIsuuCYgn;!@n*8KN>kfI>U~ zvFuUr{}>vDpY?ixHv%7{{y@!5aavCbk4Y*9Qh+hE0HD<8TA(zhpd-RQ6+OAdUa|XZ zcXt-4mHt~@Aq=Tt&Gkmqr_V38dp7`E7LV+N+YelBAP^7r{BO65(1hN6%f)tBevw)M zQ;^G#6p;ww$q0rV$IqR6N&*hTQ(*FM?z^!1cV}Kq`TGTkU2i-B*(b6gaIydHls6&( zI6nu3Ao0-OgHXIAlmRy6U$|UFLLRuJReZhIQ*ymm*Ap(I?Fs+e>jSY1KHyPBK@gVC zQy{`yCW(mjAItxL$db;RiuUH7X=|i-=Ez<~uB8lt`1Xc4n>$A6NLCe>*YiWgz1r4K zoWeEi$Z$hljsnRkHlKl>_%_k~P;b!wO4+K#g#2fBx5 zE+(!>&x+y{HM(;Z0}zv|+}p6C*h}^2(A$@4aW?~quF{mi%~h80{BuZ1;qhTG6QRzT zP_R;y5c|)eqT@d#?`-@}6`eMJFPUgaPy|3llz5Q+S1w9ENDol!e9@!O<8dh3h z@-Gy?ZgPq{l?A~6q8$7KIGVyF7ZpvG~PN^5&w_wqqh!RT6W`2KpD{c3?L8YZ*U z&mtEJito>}uJP(ca)ZD}IsHrSzpR|UR)?RC`>j^|Q>p!L7qHa%oQAJdENvLLC^l6T zSS+N(Lm#A^E@1e9enO zliwdC&d=d(1nlFz0M3i9J3Fr3zVYYqSAC09MQ@G%qF(Aka+2?$EJ(GTksrfb9<=7EKuk(I~d)bIHI34%!z`dH*FQ{%^qeUnPp~ zC<8co5gBZUcY$l1mxyz25RuqDVc>)Sy&Dz!yw*jP|AnUZ{QbcLGWLIVQvJslNN;$@ zTd3Dqp4S(@tuq-F&@Kwr%Ns$(1)ssYnN?hLS!t9UEz^A2y+ z1e>m#6|i5uCY4Z%#X>w**M1n@Kab2Fki|tD_k6>>@+oTcp>-?qiJUv}3H>aV8+9#~ z+tn?UnyZs2!pO!?n5ycS7p-jSGM7DY(uk7|LA6C2ynmCb#*TN<>P;O#xz@p|RZRG> zq3`wJ4k7+H6FqyrcV;`rFyg%%_}9e0j9`gB!s|83#i14v&#dC`x`Lm5@Y>2ygw#h# zSLDzekal9VU=&6zBTk}sszybF@y|4q2!#jt>Q%z1lKX#<$*m>>H}iHZw|kvfZu)`p zNlb@!jLZk-9LxubjLdO39aJ@J8z?mvOp8{|Q(H|MTc-2CT9PJvzBs*77uJ}GnVW@T z?ZjwPgEOe)U7YIGt2=kHuAQ(%WH zyQjzl(O+`4vJ8DE)U|HG)-Y?_bZENfoFmdS8p}TN2)XIB9Qf3HJg`XPftH_LIxLT$ zF4btP+a#fAnXwPpUUv4MvE~nMS);)TY1!bRD9LR(T>0~NFB#|T2_Y6f?VJ76?P=|~ zH7?~O(9=)nmWR8A4U`rO!odR_lDP(N+xQNirc52%ZBTpGP%`Jja#{{*8WME~gmK{m z*}3PU#s^2twyav`D9p4E9lh~2b-V^ACP}L6SY14IYteIA>hJk&=m}MxeRQ)PJFunh z0H2B)*ci9vJu((jA34@Kvvm+G$!dLDdd@|r$(%7&;Jnq8wwK6RgCwRT>{JHZNBjT6md&mT2N6S}&^g^Jx+xrypm0m1+|>mCszIoWceoLB zGD76Xl4sm(G9_AEQ-={BpaI`}HC;b?w?Bd0-+2#>fhDvwL2&x(t{=nTt*qyrn7c`; zNkRh75}X;TcaaA^ORA*A5VkzvT<*P>@w_uY*B$-KB&BN7&I^Cznn`X62Ca=)n)i$c zyY#Wjo{F}GjswIesW7ETca8nxql$^*lFoMfil8N;!r)5Vb{ZA4{kP8;`PS)5)NIEL zW5O$UN_fb-kJaX5Xx=lwk_rDBQRe)vvwe)g`B*XcEI&YmtS(In@t+#%Z_LAqIVrsQyCM|N_F)_jcf3z;Th zP7HK(uh>b-B$9RfWwGjfxjz2M;&0~kvJEl;uWWaE=vJy)b#P;aSZ}XHSyJEZWAxIk z^ww57m>JEo!kQwnq>g$|Gx_u3&CBDWJk2lA4VqY=d0kHkz8)9+4;ll8*oDZrh4p4} zlV*rj7gxd-_rYt1Ggk~7vTCQ_8O{(G&iqN=8GvC!mKANsV*x8JS!=G2$M`?40lFVX zP1AVD47|||1;`9}$o@e&5JLm+VU~NFwZl9O;41O+8uHp;<|>efr&C+VT02a#VRqGu z3sr#Za!l~0E+17LAReee1*<=y^N?Kz)=rZcU5vfa7X-)_c*y=iIS|7?wY2=yg192I z+(c-Z@-Uo1Hk|pBdKiFVLlz5}0WAd&8Szgwh-(vTkC{5~iJc&_d3)U6p0A7i$1UMm zfTmMwtQ?|kHqb3aN74lQtsej#C5)4{o091~EnZq9jLyk@@r=KF;) zg&lV7GzYzKx+DPWrxrzvrQIAU`Z+aCOO+)E0slvkoS3%l9YtW;CE7GVp}3slm+YP{a51!=x#g5QlE*)_usw%$;RGk6m9z6q~ABT zO_&ijTzqd#w042j!*PIB+n9I7MsTF$aPgOxMzXaZ6Ho=93 zOjJgP5CuM+;T>C<>a55YY-sPk+Mh5wYC^wXctGM~Bb*B%|2lV{Vti~vgwwA0Glw;7h^2J5&)C_Ka zV7612u-}2U37ZXlmw=SBmA-0v%-ZF9SXp_*IY^n{8kLXU7T|DY^|;)s?)!SVi;FEe zUHV=am+Xx}ol|KwxaZ0%A_(Qpr>2#~FQ;lgXC8-+HwDrTP-ZZnp4y_fM&^pu8hqVX zR<&Vr4mm2S@@;@U@7d^jJ+U=ZJlY?#c4m%N0k*!!d%Y9|HPx@gxUz6|z>7dFeQ37;aMQc7E)@sa^B7Xy%ge zdFRB)neXnca9^&55l{3lqyrQYN8q->17@HCQ7In1YKj~9DpqGr2g8CrOYr^|bDtvL zxgDupHkjV=#pgCxEV(s|g*2h;OO{nnxwsQ8EQChK1ct_3s>=?OVU>g9Z%6J~Q`qc( zY)P^m7c^#nH$DC~bWnGHVpTc(kW0Q(~G349J`xT>t>Dcqu zYY96nrQ;Vg+u`X*Rjql0fuwvbxQ{`$sDa3Zs_ekp)<;QX#&clf)spb)(SH8X7j_lK zhRGT)?fgqm*QF}HkCcY?Fq9k(*BiapI$pZ*DywwGP;&b1eVsIi6+Q}zD-Hs#*KV)U z;J7BwK5~(}vq~W8Qs1=6L$QewS$mxs&|BbNULX(R32~_BAYjiua;c|X<)Apfjpf4K zxVZ!PVsX0R!a8Zh_xw++1%l~-JdMPQCpiJ4z#HHIR)V)KdF> z?fuKEGwUM2Upwm}f%&Ve7j%7H#GEB`WnBc%Rif!95Y|*XmAZvhckx1M8=@MQ${wDmx86c@Ov9`fZ zi16^b{f*F8N+3r3>`FrOt*r%x*{4GiH^Br-gp4~thLvkQ4x&j#xI9F1wmZ5tF|QBI z=Sf)4@rs}JJK??VkXX+&J-G`+TW=g89$d&RJ)U)}1R+7Cf!5<}Q`nP)jxHSmOOjUD z@xX+DTLXV6cJx0X^*h0+@bd(5{2>D|{xfbk)?Fa16AaU|TMO#HY-Vsl6pW^hyvUnp>~H+sWFi&Q3++vB620rdxg z#g}r{5?0;ZT~`ynzgZMqjW!Mz>A!7U5lovGxsTczZE%Kf)cP?wS>iut63!sY*K_*P-;{5Lja<`I9swt z#4ExPCM{QSMYSka?SlfK2p7C+v9eq>&K<#}0GGK`k^_rHw$Q2?yhY@CBL_k{{(a44 z*X;t!@B5X;Ei#IJKv@~SCTFU<3j^7IH|fRPpj&zKO~|``$eOM+u4>gj&%2y{NNf^; zGF*nz0W9|F=V3t(xxEVbK(5m+5BS5f3I2BwX-FQ!^3XYNCG)+;o!vx=AP<+I0`^2^1?s+}!CUS;kB z=RCz2XQh+@f886IlxZrXngilgMN=96T! zY}gABtqYTKoO3~Kyl{#`KLmuV+}UzpVhp<<0!m}%KFD)rIEWSH*1G0HZo3M#s)-bb zi8T}bBE^zelQnz)e%k51eh4UxDpe&Q$saE&9Tp{m(~ClXSM%6*T}%lMYLDqI%z(bB zAJPXt!(8bMHM^{y33Cvx70TFGyC!I~3wwE=KNDdRumBXEOoUS^GGP#su>l|&x61M} zB19Th+$dn-UQno&;E)yjqJj~Cn6h5nEKSkFH)BxsS@uUCTBd*hp4iDWOIeRa&8OtCdxPU8|^SlpepJ$^E#0SgBK ze)|x}a#IP@j|qe6p&Z5zg~hxwBjYNjz`m-Yf&5pMPNT{(9ISAA$l7pHjma@ybw>>L z1{>VWy+j()@Cnn-iC$ELBFEQRD1kX5v2%Vf#c6kY<8-mG*EiD|rkn}um{(3QDg6k6 zu5qI{4Bwh?AJY%LKNRa+89g49`ovoGc(i$R1+Tbfy-Euu!Ow8h&iLq)-sKayf=h0; zo7BdHm{8lLOG(qQO#}>N+6u!|qEm8s6O5^!sK}@kT%H6ze2>kNVTPAvrLZZ;cterv z!RG_f>%k0U-%Db(vmr#3x^hWYsC}0o5>D(VJsW%v?q1+RxK3ZUb$Lrqs)7O$(0{=x-`I`!TD2xY?4%yjWo9iSEr# zqE+)OiLcGtd_f!6W-PfS1VM6a)K|8sXG?vlZQsvO_~f06XDP%Mk%tO?bO@y2PX(kR z)gimx_Ys`Jr-!o&LL%C-lVcvSN?rA0XNVO+IIB!Ggv6cqS-f(V#vAbXQXR~Fjd7R8 zfdT}{S<(OszEuDPG6)&0Ri?4>kVkMLL3?Qgk%6m4;)cTnuO^uyWP~hfjP{O-IhQQv z>mrD$^I*A)-_E)Yx<(&DhBSPHYmwqxg+wTMA0Xi2z?|4e2VAkm7=#R6=Rq#k{V*7# z^J)}=#K4M}C}|L84|`OVp$)B%p@B_yO@ou2EE)7<;#RF<@4)K`#F7ZOexgS&nu-&A*h;mwcDmtI+`v*p< zP4gNk^^2P65Vcu0TSZy#X30Oy(395RmD7!u-kTbIYGf}{$UT>Pc`RO@92IMh<;w@z zLG{SQiawrZclh0tEQAZ%Xy0h_CO;BvRa|TL0xpo;i*h)+i4nBYG5*Q{yf^;OZ;o;# zVZ8abT)_U%E_i+60y=Lwk2!TwszI((Bt^}38iWfz9Ud>M#EOO@T(GtTN%&4o6ykq> z)$TH8Tbhtu-iBMns^$ZLg7J6g00mRu&AHd^$;z7ew?wHbUZ8+7SVwqzRV6J*p)Ks| z>c{45()MTT$T4Dl0>;*7iSGgsMlLJEZCOQFOOK0Sa0!T;L=Y?i`jm z@*aT#&KC=Gr}!AsgE39p>)>l^{@DdQ`NG)AAP2r*K|-SYkq1`btyx=r8+mcQOxc(iN&7)JCe&YvVU0 z^>5xTXiOe8#cd8sAhGY>d+W)sl%BJ4q(kO7{*rB%$u2PU>QHS7tIu4Pgo(_T@6n07 zcJ`8^B4YfZtK~Ke&TI2?F@4@Lg6|(YK{o_El^c?b?(*w5h)VnW6_WO`*K$@ss3`-g z4}~vDXDt%!b=RcRSBk-`YBqZ67-2N~klLAW_2~L6!NH(Q0ZydzIjOrlk5CS|gv9d$ zm3B9n+b13Jc^Yt93WDk%42JJ2zJFsk1#hEyd3WwrT>;?>{gL~3R8I~yhzdQgb{iZh zKfua2zK+@L0D}0>VcvHZg*Jf@Uj^Tt@b8704H4#5<)@*e;snq(i{VdMA0!(wsBbgf zv`-Qhq#|tTV$h_`mx?oKqLrTUXD4gX4Q?65CZ2?mDTlaRu12OzakyP-lO3_&oIg`O zO!HM3!%ivW6m~M-38~pPuy001#dzcbLm`GnT3x!y@mT2V0t*sW4a#GOsi6}Q?8`kP z6Oc8Gn>G4cP)Lsl(TU9q3ZDZZ6TvErnd2o+I?t<-cGcB$48 zFYfsSd8vbTO(UPpTaH2UaQAMx99dr6mQb$*M(yw9{HH?F*OD9`Y9(9~=#|Fu*R~`G zy3g&-e%ND(zpv0r7{vKRG*vWD|0a899a-|QU!tuGl&axzvqd`U{kj~&7_TJh(o5yw zTYax{(7tJv;n+RIO4t9WQr>#C@%i+d8Esp9k>-roQC%U|dPV63+G}-8jBP1=^yBvC zbIgw)cS&@3+I=nQ9W-H zh1Rz9MQPRbklFix5ap0}#-I!g^L+;K4|5TM~o zlat|>GcBVz?@_^rNQ5%82bbl3zN<$m|Jl6Vvi7l^mUeSKU(ZX)ulgNDmnWqXN|emdPaT)UcMBe4?m8_?+!c z>8s7Rkd|2d(z{Wcrxtj&l122=eyLbaJy@pRvAsdNWvMiDPtqPe{V+80l?|V^&*c1z zY6SjQcZTFjr^`@ew~h|`Kwhp&MfUaD^^Mm9evj&p-uP5YCtn@>`lVW_by%vo^G$=)OnF$HOj{3Y?fFWw9}Htx_8z9bb;R0ZaoFjJhAQ8KU(%cL%OmTNS>Rh{hT~qzo~aL3 zA9!Y5!4wJp#QeF@(Se4{=5XvN7hEc9VL+0-iA@tDRsw(V>v&z%mL>^4%7wn*VVzt~9LnZX64HA-@!I*s+z ziY=$(nu>dA4$!qzoWHAtN}>20AO1%N9{XPoyt!*M&0m|Jk=&zp5JzEX!txRIdLSku zCMx!_73JO0na6o!qp-HIj*gD8jJ}SPuO+;;*4l%zFghOmH$GfaX#SSWSKX1q(yYx?Ce&r7q{ zWn32j-wa*EL}M1cd;j6Pr$Oi>{*@ZGKE1mxhh+0EkI=YXseSwP_bItIBTq+h@ZIKJ z9=7({I)U2}QA*1U+jNe;G}#%{YW<>D?aREMSNFcsXOnADP}BXnkJ;ue)9)z@-UMm1 z@zuOu9DR4Ilcwa_f@cr zXsJs!_A3&s*Geh;(o{NkE8x+rS9R}ZWvz_-VDB%i`Do3yUCOiPHCETC$n!Tm7yg>U z)cq^S_?U-Jtej(D;lEx>&a%J|{{KR4zWm+XZzhJHG;P?p^4j7FL9bu2F}5m)1?>|v ziQN#IcJ`6Fc6H_Sg0ea9j`p18@Yw(Q*?orxz*G1ztGmY^m`_dxR)i~o7+B+hj_FHI z%t?06NX*OwHRWvj9Jvk|2)KT4D(Bd|eWjj@il?}!{{nW2OB*>=CQssAwB20WT;5Lp z-tV+uPnO&ZQ5D-(AmbKrWS`E&aPITR{}wQ+@>U)UnW0nTnNak5?#CH_WDGXFViDtB zxb^L-tv?(jQ#GUuFp?qWpql{p9?jRFEGO7O^mDEMNdC8QGv_ zQmpr31Bur6tpA-))=uwVn6vP;Lu%DShYgD=#3z@>#!jB5a_jB=*>ySRG~>2CpVM9( zH|fmwT|IUOcP%n9c5!EMO-NbFHTnF7;B6i18bxsus;5pJ;CXvsVP#d_v=g&VpE}gM zHfzH^265I&g)!HRw|v|8Ou~96o9-PA3m<{-saFrR`_FzHb)xqKqp_3TMmGH^ADFfu z*kLDdu_5GB!y5aXn~YPA1T?WdmR+XYwSTYNnzDK}tEVSca_?V#c-g{thS4YEY<6s4 zXCX0rnWX9Cb#5>GKc4>dZ{ut!@nw6bvP@C)D#~>HacWuq`>8iG5`}8MY_?6%oD<&` zy`C!|eD{}YPI7lUW7GfYz8B`-W*`@GibK_K=CPbvhNn)p7=N4fKykZytK8i;`*>Dp z@I3tcX74APefv&|Wjydr@-jYVkvXxkd{Tb|MM;0N^R;9taJRiBe#OfWA`O{ z`QTry*ivTIwu3(o0+Zc6V4q3=Ib|jm6pSWJL}r{59GHFEK%h?kjeSK`{*yIJdlXjp z>`-oA!|Qv?R?OG#_@YfIOS(J1zgEAgQh4p+#=Up%me>4xw_AAk&FfZ~2P;#3fz|31 zm4qd_Q*Nd`Dg6BOk+7!?S1?B|Z^{y8|GXc+%X6OQF!PE2PzjKjKap$W%)nQvtXn@! zW|-YD<=Ryy=U3aVOj|l>LiEnn2NnL#Sax0H8^^MSM~f_lCN&mbd-Q*jSeRSwzs$>~ zjt1%TXS-=@8u*;tulaJ#c2%|Q)ts{~8lGs{WqM+6@QsgCE*74;7L+lAJt>asZR5q@ zMqLM&%VAEI=Oeo}i>X9SulQK#)bUHB~3G5wE8O}O3Oc}u2eT3ib3y?FWfll{OrgcQh(OuE1$rC^7@w%z(t-Udwg zQ`jJfzapX<#EN##2X>qDO5#H*3sQ??K{+A78`XfVp$5udfJ%LUWjZ&C?)|{L1Q~P! z5450bTrDC!H4dnR33v)E=x{s)cmi|_uyzBDT_xq`XJfPV%U5=5VW6`kf&D)zgiatU zp9`!RVllE2SRD~*Y;&Ol=!h(!E(sKK4)MSp0Uba?44t8S<=usA*#VXe4BvJ!qM6bF ztf`@1K{f?E{Df}G)!$M*oM#vqj{adoGlk6yt0~|S9CTCAPxD21%2kXJ(G5f&Uqcuu9D~O|#AqA3f#{=E2m{4p!3Ls@Rbd^wLN^qBYy@HG-#B6n1&@@V z8;ah|Kp4uNLX4r{P6xW7=*?P$p>I;bhN3ib(RHJ?C=q%Y7}lpTGGMeX(Y2#i`^efo dGm*4I8vy~{tiX~9R89&r*Z`Xm4mqHPDge{K!o&ao literal 0 HcmV?d00001 From a47078f86929d69127d5a995df4e0d5a6b6e8df1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 13:45:49 -0700 Subject: [PATCH 086/377] FlexSub: T matrix built for cantilever and rigid assemblies --- modules/subdyn/src/SD_FEM.f90 | 310 ++++++++++++++++++++++--- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Tests.f90 | 104 ++++++++- modules/subdyn/src/SubDyn_Types.f90 | 143 ++++++++++++ 4 files changed, 518 insertions(+), 40 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 3ad6127bd..907476ea3 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -224,28 +224,28 @@ LOGICAL FUNCTION ElementsConnected(p, ie1, ie2, iWhichNode_e1, iWhichNode_e2) END FUNCTION ElementsConnected !> Loop through a list of elements and returns a list of unique joints -TYPE(IList) FUNCTION JointsList(p, Elements) +TYPE(IList) FUNCTION NodesList(p, Elements) use IntegerList, only: init_list, append, find, sort use IntegerList, only: print_list TYPE(SD_ParameterType), INTENT(IN) :: p integer(IntKi), dimension(:), INTENT(IN) :: Elements integer(IntKi) :: ie, ei, j1, j2 INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 - call init_list(JointsList, 0, 0, ErrStat2, ErrMsg2) + call init_list(NodesList, 0, 0, ErrStat2, ErrMsg2) do ie = 1, size(Elements) ei = Elements(ie) ! Element index j1 = p%Elems(ei,2) ! Joint 1 j2 = p%Elems(ei,3) ! Joint 2 ! Append joints indices if not in list already - if (find(JointsList, j1, ErrStat2, ErrMsg2)<=0) call append(JointsList, j1, ErrStat2, ErrMsg2) - if (find(JointsList, j2, ErrStat2, ErrMsg2)<=0) call append(JointsList, j2, ErrStat2, ErrMsg2) + if (find(NodesList, j1, ErrStat2, ErrMsg2)<=0) call append(NodesList, j1, ErrStat2, ErrMsg2) + if (find(NodesList, j2, ErrStat2, ErrMsg2)<=0) call append(NodesList, j2, ErrStat2, ErrMsg2) ! Sorting required by find function - call sort(JointsList, ErrStat2, ErrMsg2) + call sort(NodesList, ErrStat2, ErrMsg2) enddo - call print_list(JointsList, 'Joint list') -END FUNCTION JointsList + call print_list(NodesList, 'Joint list') +END FUNCTION NodesList !---------------------------------------------------------------------------- @@ -263,9 +263,9 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) ! local variable INTEGER :: I, n, iMem, iNode, JointID INTEGER(IntKi) :: mType !< Member Type - CHARACTER(1024) :: sType !< String for element type + CHARACTER(1255) :: sType !< String for element type INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" @@ -386,7 +386,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) LOGICAL :: found, CreateNewProp INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" @@ -708,7 +708,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) INTEGER(IntKi) :: eType !< Member type REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ErrMsg = "" ErrStat = ErrID_None @@ -834,7 +834,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 integer(IntKi), dimension(6) :: DOFNode_Old integer(IntKi) :: ErrStat2 - character(1024) :: ErrMsg2 + character(ErrMsgLen) :: ErrMsg2 ErrMsg = "" ErrStat = ErrID_None @@ -959,7 +959,7 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) REAL(ReKi) :: FCe(12) ! Pretension force from cable element INTEGER, DIMENSION(2) :: nn ! node number in element INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system ErrMsg = "" @@ -1047,23 +1047,27 @@ END SUBROUTINE AssembleKM SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m + TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! Varaibles for rigid assembly type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA - integer(IntKi) :: nDOF + + ErrStat = ErrID_None ErrMsg = "" call RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat2, ErrMsg2); if(Failed()) return - nDOF = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', nDOF + + call BuildTMatrix(); if (Failed()) return + + deallocate(RAm1) deallocate(RA) deallocate(njRA) @@ -1077,13 +1081,124 @@ END FUNCTION Failed !SUBROUTINE Fatal(ErrMsg_in) ! character(len=*), intent(in) :: ErrMsg_in - ! CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); - ! CALL CleanUp_AssembleKM() + ! CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'DirectElimination'); + ! CALL CleanUp_DirectElimination() !END SUBROUTINE Fatal - !SUBROUTINE CleanUp_AssembleKM() + !SUBROUTINE CleanUp_DirectElimination() !pass - !END SUBROUTINE CleanUp_AssembleKM + !END SUBROUTINE CleanUp_DirectElimination + + SUBROUTINE BuildTMatrix() + ! Variables for Building T + use IntegerList, only: init_list, find, pop, destroy_list, len + use IntegerList, only: print_list + real(ReKi), dimension(:,:), allocatable :: T + real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 + integer(IntKi), dimension(:), allocatable :: Elements !< List of elements + real(ReKi), dimension(:,:), allocatable :: Tc + integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements + integer(IntKi), dimension(:), allocatable :: IDOFOld !< + integer(IntKi), dimension(:), pointer :: IDOFNew !< + integer(IntKi) :: iPrev + type(IList) :: IRA + integer(IntKi) :: nDOF + integer(IntKi) :: aID, ia ! assembly ID, and index in IRA + integer(IntKi) :: iNode + integer(IntKi) :: I + integer(IntKi) :: nc !< Number of DOF after constraints applied + integer(IntKi) :: nj + + ! --- Misc inits + nullify(IDOFNew) + I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) + + + allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2) ! Indices of DOF for each joint, in reduced system + + + nDOF = nDOF_ConstraintReduced() + print*,'nDOF constraint elim', nDOF + allocate(T(1:Init%TDOF, 1:nDOF)) + T=0 + iPrev =0 + call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); + IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) + call print_list(IRA, 'List of RA indices') + print*,'------------------ BUILD T ----------------------------------' + + ! --- For each node: + ! - create list of indices I in the assembled vector of DOF + ! - create list of indices Itilde in the reduced vector of DOF + do iNode = 1, Init%NNode + nc=0 + if (allocated(Tc)) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + + if (Init%Nodes(iNode,iJointType) == idJointPin ) then + print*,'TODO T Build' + STOP + + elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then + print*,'TODO T Build' + STOP + + elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then + print*,'TODO T Build' + STOP + + elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p)) then + ! This joint is involved in a rigid link assembly, we skip it (accounted for above) + aID = RAm1(iNode) + ia = find(IRA, aID, ErrStat2, ErrMsg2) + print*,'Node',iNode, 'is involved in RA', aID, ia + if ( ia <= 0) then + ! This rigid assembly has already been processed, pass to next node + cycle + else + call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2) + aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed + nj = size(INodesID) + allocate(IDOFOld(1:6*nj)) + do I=1, nj + IDOFOld( (I-1)*6+1 : I*6 ) = m%NodesDOF(INodesID(I))%List(1:6) + enddo + endif + else + ! That's a regular Cantilever joint + allocate(Tc(1:6,1:6)) + allocate(IDOFOld(1:6)) + Tc=I6 + IDOFOld = m%NodesDOF(iNode)%List(1:6) + endif + else + ErrMsg2='Wrong joint type'; ErrStat2=ErrID_Fatal + endif + if (allocated(Tc)) then + nc=size(Tc,2) + call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) + m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) + IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations + !print*,'N',iNode,'I ',IDOFOld + !print*,'N',iNode,'It',IDOFNew + T(IDOFOld, IDOFNew) = Tc + iPrev = iPrev + nc + else + print*,'Error, Tc not allocated, TODO' + STOP + endif + enddo + deallocate(T) + nullify(IDOFNew) + ! --- Safety checks + if (len(IRA)>0) then + ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal + endif + + call destroy_list(IRA, ErrStat2, ErrMsg2) + + END SUBROUTINE BuildTMatrix !> Returns number of DOF after constraint reduction (via the matrix T) INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() @@ -1175,6 +1290,128 @@ LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) enddo END FUNCTION NodeHasRigidElem +!------------------------------------------------------------------------------------------------------ +!> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. +SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) + REAL(ReKi), INTENT(IN ) :: Pj(3) ! (x,y,z) positions of leader node + REAL(ReKi), INTENT(IN ) :: Pk(3) ! (x,y,z) positions of follower node + REAL(ReKi), INTENT( OUT) :: TRigid(6,6) ! Transformation matrix such that xk = T.xj + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local + !REAL(ReKi) :: L ! length of element + !REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrix + !REAL(ReKi) :: R0(3,3) + integer(IntKi) :: I + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Formulation using Delta of Global coordinates + Trigid=0; do I = 1,6; Trigid(I,I) = 1; enddo + Trigid ( 1, 5 ) = (Pk(3) - Pj(3)) + Trigid ( 1, 6 ) = -(Pk(2) - Pj(2)) + Trigid ( 2, 4 ) = -(Pk(3) - Pj(3)) + Trigid ( 2, 6 ) = (Pk(1) - Pj(1)) + Trigid ( 3, 4 ) = (Pk(2) - Pj(2)) + Trigid ( 3, 5 ) = -(Pk(1) - Pj(1)) + + ! --- Formulation bty transforming the "local" matrix into a global one + !call GetDirCos(Pj, Pk, R0, L, ErrStat, ErrMsg) + !TRigid = 0 ; do I = 1,6; TRigid(I,I) = 1; enddo + !TRigid (1, 5) = L + !TRigid (2, 4) = -L + !TRigid(1:3,4:6) = matmul( R0 , matmul(TRigid(1:3,4:6), transpose(R0)) ) + + ! --- Formulation using L and Rotation matrix + !TRigid = 0; do I = 1,6; TRigid(I,I) = 1; enddo + !TRigid ( 1, 5 ) = L*R0(3,3) + !TRigid ( 1, 6 ) = -L*R0(2,3) + !TRigid ( 2, 4 ) = -L*R0(3,3) + !TRigid ( 2, 6 ) = L*R0(1,3) + !TRigid ( 3, 4 ) = L*R0(2,3) + !TRigid ( 3, 5 ) = -L*R0(1,3) +END SUBROUTINE GetRigidTransformation + +!------------------------------------------------------------------------------------------------------ +!> Returns constrains matrix for a rigid assembly (RA) formed by a set of elements. +!! +SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements + real(ReKi), dimension(:,:), allocatable :: Tc + integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + type(IList) :: LNodesID !< List of nodes id involved in element + type(IList) :: INodesInterf !< List of indices for Nodes involved in interface + integer(IntKi) :: NodeID !< NodeID + integer(IntKi) :: iTmp !< Temporary index + integer(IntKi) :: iNodeID !< Loop index on node ID list + integer(IntKi) :: iMainNode !< Index of main node selected for rigid assembly within INodesID list + integer(IntKi) :: nNodes !< Number of Nodes involved in RA + integer(IntKi) :: iFound !< Loop index on node ID list + integer(IntKi) :: i !< Loop index + real(ReKi) :: TRigid(6,6) ! Transformation matrix such that xi = T.x1 + real(ReKi) :: P1(3), Pi(3) ! Nodal points + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! --- List of nodes stored first in LINodes than moved to INodes + LNodesID = NodesList(p, Elements) + call move_alloc(LNodesID%List, INodesID) + call destroy_list(LNodesID, ErrStat2, ErrMsg2) + print*,'Nodes involved in assembly (befr) ',INodesID + + !--- Look for potential interface node + call init_list(INodesInterf, 0, 0, ErrStat2, ErrMsg2); + do iNodeID = 1, size(INodesID) + NodeID = INodesID(iNodeID) + iFound = FINDLOCI( Init%Interf(:,1), NodeID) + if (iFound>0) then + call append(INodesInterf, iNodeID, ErrStat2, ErrMsg2) + ! This node is an interface node + print*,'Node',NodeID, 'is an interface node, selecting it for the rigid assembly' + endif + enddo + + ! --- Decide which node will be the main node of the rigid assembly + if (len(INodesInterf)==0) then + iMainNode = 1 ! By default we select the first node + else if (len(INodesInterf)==1) then + iMainNode = pop(INodesInterf, ErrStat2, ErrMsg2) + else + ErrStat=ErrID_Fatal + ErrMsg='Cannot have several interface nodes linked within a same rigid assembly' + return + endif + call destroy_list(INodesInterf, ErrStat2, ErrMsg2) + + ! --- Order list of joints with main node first (swapping iMainNode with INodes(1)) + iTmp = INodesID(1) + INodesID(1) = iMainNode + INodesID(iMainNode) = iTmp + print*,'Nodes involved in assembly (after)',INodesID + + ! --- Building Transformation matrix + nNodes =size(INodesID) + allocate(Tc(6*nNodes,6)) + Tc(:,:)=0 + ! I6 for first node + do i = 1,6 ; Tc(i,i)=1_ReKi; enddo ! I6 = eye(6) + ! Rigid transformation matrix for the other nodes + P1 = Init%Nodes(INodesID(1), 2:4) ! reference node coordinates + do i = 2, nNodes + Pi = Init%Nodes(INodesID(i), 2:4) ! follower node coordinates + call GetRigidTransformation(P1, Pi, TRigid, ErrStat2, ErrMsg2) + Tc( ((i-1)*6)+1:6*i, 1:6) = TRigid(1:6,1:6) + enddo +END SUBROUTINE RAElimination + !------------------------------------------------------------------------------------------------------ !> Setup a list of rigid link assemblies (RA) SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) @@ -1193,8 +1430,8 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) integer(IntKi) :: ie !< Index on elements integer(IntKi) :: ia !< Index on assemblies integer(IntKi) :: e0 !< Index of an element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(1024) :: ErrMsg2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" allocate(RAm1(1:Init%NElem)) @@ -1238,8 +1475,8 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) ! --- Counting unique joints involved in Rigid assembly allocate(njRA(1:nRA)) do ia = 1, nRA - ! Getting list of joints involved in RA(ia) - Er = JointsList(p, RA(ia)%List) + ! Getting list of nodes involved in RA(ia) + Er = NodesList(p, RA(ia)%List) njRA(ia) = len(Er) call destroy_list(Er, ErrStat2, ErrMsg2) enddo @@ -1285,17 +1522,18 @@ END SUBROUTINE RigidLinkAssemblies !------------------------------------------------------------------------------------------------------ !> Computes directional cosine matrix DirCos -!! rrd: This should be from local to global +!! Transforms from element to global coordinates: xg = DC.xe, Kg = DC.Ke.DC^t +!! Assumes that the element main direction is along ze. +!! !! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix -!! in the FAST framework. It seems to be used consistantly in the code (i.e., the transpose -!! of this matrix is used later). +!! in the FAST framework. SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) - REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) positions of two nodes making up an element - REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix - REAL(ReKi) , INTENT( OUT) :: L ! length of element - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: Dx,Dy,Dz, Dxy ! distances between nodes + REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element + REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix + REAL(ReKi) , INTENT( OUT) :: L ! length of element + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi) :: Dx, Dy, Dz, Dxy ! distances between nodes ErrMsg = "" ErrStat = ErrID_None diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index f1f0f941a..f37970bcc 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -153,6 +153,7 @@ typedef ^ ^ ReKi SDWrOutput {:} - - typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 86df3cf26..a0b7d9aab 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -12,6 +12,10 @@ module SubDyn_Tests test_equal_i1, & test_equal_i0 end interface + interface test_almost_equal; module procedure & + test_almost_equal_1, & + test_almost_equal_2 + end interface contains ! -------------------------------------------------------------------------------- @@ -109,13 +113,74 @@ subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) endif end subroutine + subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), dimension(:), intent(in) :: VecRef !< + real(ReKi), dimension(:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + real(ReKi) :: delta + real(ReKi) :: delta_cum + ! + cpt=0 + delta_cum=0.0_ReKi + do i=1,size(VecRef,1) + delta=abs(VecRef(i)-VecTry(i)) + delta_cum=delta_cum+delta + if(delta>MINNORM) then + cpt=cpt+1 + endif + enddo + delta_cum=delta_cum/size(VecRef) + if(cpt>0) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum,' - Failed:',cpt + call test_fail(InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum + call test_success(InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=(cpt==0) + endif + end subroutine + subroutine test_almost_equal_2(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), dimension(:,:), intent(in) :: VecRef !< + real(ReKi), dimension(:,:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + real(ReKi), dimension(:),allocatable :: VecRef2 !< + real(ReKi), dimension(:),allocatable :: VecTry2 !< + integer :: p, i,j,n1,n2,nCPs + ! + n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 + allocate ( VecRef2 (n1*n2) ) ; allocate ( VecTry2 (n1*n2) ) + p=0 + do j=1,n2; do i=1,n1 + p=p+1 + VecRef2(p)=VecRef(i,j) + VecTry2(p)=VecTry(i,j) + enddo; enddo; + call test_almost_equal(Var,VecRef2,VecTry2,MINNORM,bStop,bPrint,bPassed) + end subroutine - ! --------------------------------------------------------------------------------} - ! --- Specific SubDyn tests - ! --------------------------------------------------------------------------------{ - subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg,Init,p) + + ! --------------------------------------------------------------------------------} + ! --- Specific SubDyn tests + ! --------------------------------------------------------------------------------{ + subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg, Init, p) TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters INTEGER(IntKi) :: DOFTP, DOFM @@ -162,7 +227,37 @@ subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMs IF ( ErrStat /= 0 ) RETURN end subroutine Test_CB_Results + !> Transformation matrices tests + subroutine Test_Transformations(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + + real(ReKi), dimension(3) :: P1, P2 + real(ReKi), dimension(3,3) :: DirCos, A, R0, Ref + real(ReKi), dimension(6,6) :: T, Tref + real(ReKi) :: L + integer(IntKi) :: I + + ! --- DirCos + P1=(/0,0,0/) + P2=(/2,0,0/) + call GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) + Ref = reshape( (/0_ReKi,-1_ReKi,0_ReKi, 0_ReKi, 0_ReKi, -1_ReKi, 1_ReKi, 0_ReKi, 0_ReKi/) , (/3,3/)) + call test_almost_equal('DirCos',Ref,DirCos,1e-8,.true.,.true.) + + ! --- Rigid Transo + P1=(/1,2,-1/) + P2=(/2,5,5/) + call GetRigidTransformation(P1, P2, T, ErrStat, ErrMsg) + Tref = 0; do I=1,6; Tref(I,I) =1_ReKi; enddo + Tref(1,5) = 6._ReKi; Tref(1,6) =-3._ReKi; + Tref(2,4) =-6._ReKi; Tref(2,6) = 1._ReKi; + Tref(3,4) = 3._ReKi; Tref(3,5) =-1._ReKi; + call test_almost_equal('TRigid',Tref,T,1e-8,.true.,.true.) + + end subroutine Test_Transformations + !> Series of tests for integer lists subroutine Test_lists(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg @@ -221,6 +316,7 @@ subroutine SD_Tests(ErrStat,ErrMsg) ErrMsg = "" call Test_lists(ErrStat2, ErrMsg2) + call Test_Transformations(ErrStat2, ErrMsg2) end subroutine SD_Tests diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 9f37d8f2c..b8bebc0ab 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -197,6 +197,7 @@ MODULE SubDyn_Types REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] END TYPE SD_MiscVarType ! ======================= @@ -5453,6 +5454,22 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF +IF (ALLOCATED(SrcMiscData%NodesDOFtilde)) THEN + i1_l = LBOUND(SrcMiscData%NodesDOFtilde,1) + i1_u = UBOUND(SrcMiscData%NodesDOFtilde,1) + IF (.NOT. ALLOCATED(DstMiscData%NodesDOFtilde)) THEN + ALLOCATE(DstMiscData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%NodesDOFtilde,1), UBOUND(SrcMiscData%NodesDOFtilde,1) + CALL SD_Copyilist( SrcMiscData%NodesDOFtilde(i1), DstMiscData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF IF (ALLOCATED(SrcMiscData%ElemsDOF)) THEN i1_l = LBOUND(SrcMiscData%ElemsDOF,1) i1_u = UBOUND(SrcMiscData%ElemsDOF,1) @@ -5511,6 +5528,12 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(MiscData%NodesDOF) ENDIF +IF (ALLOCATED(MiscData%NodesDOFtilde)) THEN +DO i1 = LBOUND(MiscData%NodesDOFtilde,1), UBOUND(MiscData%NodesDOFtilde,1) + CALL SD_Destroyilist( MiscData%NodesDOFtilde(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%NodesDOFtilde) +ENDIF IF (ALLOCATED(MiscData%ElemsDOF)) THEN DEALLOCATE(MiscData%ElemsDOF) ENDIF @@ -5625,6 +5648,29 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no + IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no IF ( ALLOCATED(InData%ElemsDOF) ) THEN Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension @@ -5825,6 +5871,47 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz ENDIF END DO END IF + IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6177,6 +6264,62 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) + ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE From 9236bcafaac4f802027ecda2709b251e34fbebeb Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 13:53:39 -0700 Subject: [PATCH 087/377] FlexSub: starting FEM, standalone tools for FEM --- modules/subdyn/src/{SD_FEM.f90 => FEM.f90} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/subdyn/src/{SD_FEM.f90 => FEM.f90} (100%) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/FEM.f90 similarity index 100% rename from modules/subdyn/src/SD_FEM.f90 rename to modules/subdyn/src/FEM.f90 From 767be0559c2e8a53826574514f060aa7213c8499 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 13:56:19 -0700 Subject: [PATCH 088/377] FlexSub: temp copy --- modules/subdyn/src/{SD_FEM.f90 => copy.f90} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/subdyn/src/{SD_FEM.f90 => copy.f90} (100%) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/copy.f90 similarity index 100% rename from modules/subdyn/src/SD_FEM.f90 rename to modules/subdyn/src/copy.f90 From b4a0c8fdb4a001e452daa8888346d6bf7f4d35cf Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 23 Dec 2019 14:18:23 -0700 Subject: [PATCH 089/377] [BugFix] WAMITmesh not used for trpd test case The Offshore_FixedBottom_OC3Tripod standalone HD test case was failing when the WAMITmesh was committed without actually having a WAMIT body. This is probably from the modification of the names used. --- modules/hydrodyn/src/HydroDyn.f90 | 118 +++++++++++++++--------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 2fdec3ecb..71cf5d6af 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1468,68 +1468,72 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I u%PRPMesh%RemapFlag = .TRUE. - ! Create the input mesh associated with kinematics of the various WAMIT bodies - CALL MeshCreate( BlankMesh = u%WAMITMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = p%NBody & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - do iBody = 1, p%NBody - theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) - orientation = EulerConstruct(theta) - - CALL MeshPositionNode (u%WAMITMesh & - , iBody & - , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & - , ErrStat2 & - , ErrMsg2 & - , orientation ) + ! Create the input mesh associated with kinematics of the various WAMIT bodies + IF (p%PotMod >= 1) THEN + CALL MeshCreate( BlankMesh = u%WAMITMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NBody & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL MeshConstructElement ( u%WAMITMesh & - , ELEMENT_POINT & - , ErrStat2 & - , ErrMsg2 & - , iBody ) + do iBody = 1, p%NBody + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitLocal%PtfmRefztRot(iBody)/) + orientation = EulerConstruct(theta) + + CALL MeshPositionNode (u%WAMITMesh & + , iBody & + , (/InitLocal%PtfmRefxt(iBody), InitLocal%PtfmRefyt(iBody), InitLocal%PtfmRefzt(iBody)/) & + , ErrStat2 & + , ErrMsg2 & + , orientation ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + CALL MeshConstructElement ( u%WAMITMesh & + , ELEMENT_POINT & + , ErrStat2 & + , ErrMsg2 & + , iBody ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end do + + CALL MeshCommit ( u%WAMITMesh & + , ErrStat2 & + , ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - end do - - CALL MeshCommit ( u%WAMITMesh & - , ErrStat2 & - , ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - - ! Output mesh for loads at each WAMIT body - CALL MeshCopy ( SrcMesh = u%WAMITMesh & - ,DestMesh = y%WAMITMesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat2 & - ,ErrMess = ErrMsg2 & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - u%WAMITMesh%RemapFlag = .TRUE. - y%WAMITMesh%RemapFlag = .TRUE. - + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + + ! Output mesh for loads at each WAMIT body + CALL MeshCopy ( SrcMesh = u%WAMITMesh & + ,DestMesh = y%WAMITMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat2 & + ,ErrMess = ErrMsg2 & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:y%WAMITMesh') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + u%WAMITMesh%RemapFlag = .TRUE. + y%WAMITMesh%RemapFlag = .TRUE. + ENDIF ! PotMod > 1 + + ! Create helper mesh to map all Hydrodynamics loads to the platform reference point to (0,0,0) CALL MeshCreate ( BlankMesh = m%AllHdroOrigin & ,IOS = COMPONENT_OUTPUT & From 392c85a08f32362f97a0c6aa29a9c96cc5d62877 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 23 Dec 2019 14:29:05 -0700 Subject: [PATCH 090/377] Update reg_test Offshore_FixedBottom_OC3Tripod standalone --- reg_tests/CMakeLists.txt | 5 ++++- reg_tests/CTestList.cmake | 12 ++++++++++++ reg_tests/r-test | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/reg_tests/CMakeLists.txt b/reg_tests/CMakeLists.txt index d29d5b5bc..6541d028a 100644 --- a/reg_tests/CMakeLists.txt +++ b/reg_tests/CMakeLists.txt @@ -40,6 +40,9 @@ set(CTEST_OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast" # Set the BeamDyn executable configuration option and default set(CTEST_BEAMDYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/beamdyn/beamdyn_driver" CACHE FILEPATH "Specify the BeamDyn driver executable to use in testing.") +# Set the BeamDyn executable configuration option and default +set(CTEST_HYDRODYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/hydrodyn/hydrodyn_driver" CACHE FILEPATH "Specify the HydroDyn driver executable to use in testing.") + # Set the python executable configuration option and default if(NOT EXISTS ${PYTHON_EXECUTABLE}) find_program(PYTHON_EXECUTABLE NAMES python3 python py) @@ -61,7 +64,7 @@ add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/r-test") # build and seed the test directories with the data they need to run the tests file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}) -foreach(regTest glue-codes/openfast modules/beamdyn) +foreach(regTest glue-codes/openfast modules/beamdyn modules/hydrodyn) file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}/${regTest}) endforeach() diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index b60068525..0662edb9c 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -83,6 +83,15 @@ function(bd_regression TESTNAME LABEL) regression(${TEST_SCRIPT} ${BEAMDYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") endfunction(bd_regression) +# hydrodyn +function(hd_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeHydrodynRegressionCase.py") + set(HYDRODYN_EXECUTABLE "${CTEST_HYDRODYN_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/modules/hydrodyn") + regression(${TEST_SCRIPT} ${HYDRODYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(hd_regression) + #=============================================================================== # Regression tests #=============================================================================== @@ -129,3 +138,6 @@ bd_regression("bd_curved_beam" "beamdyn;static") bd_regression("bd_isotropic_rollup" "beamdyn;static") bd_regression("bd_static_cantilever_beam" "beamdyn;static") bd_regression("bd_static_twisted_with_k1" "beamdyn;static") + +# HydroDyn regression tests +hd_regression("Offshore_FixedBottom_OC3Tripod" "hydrodyn;offshore;standalone") diff --git a/reg_tests/r-test b/reg_tests/r-test index ed4e66186..0c1567c56 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit ed4e6618670108527a6071c6a91d8fe504d37b18 +Subproject commit 0c1567c56c3a90fa260ee430df4496ab60597587 From 2885b138a66b60b88f76eae1e1f23bec8949a5f2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 13:57:15 -0700 Subject: [PATCH 091/377] FlexSub: copied history of SD_FEM to FEM --- modules/subdyn/CMakeLists.txt | 1 + modules/subdyn/src/FEM.f90 | 1441 +------------------ modules/subdyn/src/{copy.f90 => SD_FEM.f90} | 600 +------- 3 files changed, 41 insertions(+), 2001 deletions(-) rename modules/subdyn/src/{copy.f90 => SD_FEM.f90} (76%) diff --git a/modules/subdyn/CMakeLists.txt b/modules/subdyn/CMakeLists.txt index 61afff133..0f88349d3 100644 --- a/modules/subdyn/CMakeLists.txt +++ b/modules/subdyn/CMakeLists.txt @@ -20,6 +20,7 @@ endif() set(SUBDYN_SOURCES src/SubDyn.f90 + src/FEM.f90 src/SD_FEM.f90 src/SubDyn_Output.f90 src/SubDyn_Output_Params.f90 diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 907476ea3..c1e6cfeee 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -16,58 +16,14 @@ ! See the License for the specific language governing permissions and ! limitations under the License. !********************************************************************************************************************************** -MODULE SD_FEM +!> Standalone tools for beam-based finite element method (FEM) +!! No dependency with SubDyn types and representation +MODULE FEM USE NWTC_Library - USE SubDyn_Types IMPLICIT NONE INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors - INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint - INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in - INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) - - ! values of these parameters are ordered by their place in SubDyn input file: - INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) - INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction dof array (JointID,RctTDxss,RctTDYss,RctTDZss,RctRDXss,RctRDYss,RctRDZss) - INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) - INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) - INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) - INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs - INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) - INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) - INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) - INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) - INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) - ! Indices in Members table - INTEGER(IntKi), PARAMETER :: iMType= 6 ! Index in Members table where the type is stored - INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored - - ! Indices in Joints table - INTEGER(IntKi), PARAMETER :: iJointType= 5 ! Index in Joints where the joint type is stored - INTEGER(IntKi), PARAMETER :: iJointDir= 6 ! Index in Joints where the joint-direction are stored - INTEGER(IntKi), PARAMETER :: iJointStiff= 9 ! Index in Joints where the joint-stiffness is stored - INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored - - ! ID for joint types - INTEGER(IntKi), PARAMETER :: idJointCantilever = 1 - INTEGER(IntKi), PARAMETER :: idJointUniversal = 2 - INTEGER(IntKi), PARAMETER :: idJointPin = 3 - INTEGER(IntKi), PARAMETER :: idJointBall = 4 - - ! ID for member types - INTEGER(IntKi), PARAMETER :: idMemberBeam = 1 - INTEGER(IntKi), PARAMETER :: idMemberCable = 2 - INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 - - INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) - - INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic - MODULE PROCEDURE FINDLOCI_ReKi - MODULE PROCEDURE FINDLOCI_IntKi - END INTERFACE - - CONTAINS !------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) @@ -141,461 +97,7 @@ SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) endif enddo END SUBROUTINE InsertDOFrows - !------------------------------------------------------------------------------------------------------ -!> Maps nodes to elements -!! allocate NodesConnE and NodesConnN -SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) - USE qsort_c_module ,only: QsortC - TYPE(SD_InitType), INTENT( INOUT ) :: Init - TYPE(SD_ParameterType), INTENT( IN ) :: p - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements - INTEGER(IntKi) :: I,J,K !counter - - ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) - CALL AllocAry(Init%NodesConnE, Init%NNode, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; - CALL AllocAry(Init%NodesConnN, Init%NNode, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; - Init%NodesConnE = 0 - Init%NodesConnN = -99999 ! Not Used - - ! find the node connectivity, nodes/elements that connect to a common node - DO I = 1, Init%NNode - !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array - k = 0 - DO J = 1, Init%NElem !This should be vectorized - IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element - k = k + 1 - if (k > MaxMemJnt+1) then - CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); - endif - Init%NodesConnE(I, k + 1) = p%Elems(J, 1) - !if ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) then - ! Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element - !else - ! Init%NodesConnN(I, k + 1) = p%Elems(J, 3) - !endif - ENDIF - ENDDO - - !IF( k>1 )THEN ! sort the nodes ascendingly - ! SortA(1:k, 1) = Init%NodesConnN(I, 3:(k+2)) - ! CALL QsortC( SortA(1:k, 1:1) ) - ! Init%NodesConnN(I, 3:(k+2)) = SortA(1:k, 1) - !ENDIF - - Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column - !Init%NodesConnN(I, 2) = k - !print*,'ConnE',I,'val',Init%NodesConnE(I, 1:5) - ENDDO - -END SUBROUTINE NodeCon - -!---------------------------------------------------------------------------- -!> Check if two elements are connected -!! returns true if they are, and return which node (1 or 2) of each element is involved -LOGICAL FUNCTION ElementsConnected(p, ie1, ie2, iWhichNode_e1, iWhichNode_e2) - TYPE(SD_ParameterType), INTENT(IN) :: p - INTEGER(IntKi), INTENT(IN) :: ie1, ie2 ! Indices of elements - INTEGER(IntKi), INTENT(OUT) :: iWhichNode_e1, iWhichNode_e2 ! 1 or 2 if node 1 or node 2 - if ((p%Elems(ie1, 2) == p%Elems(ie2, 2))) then ! node 1 connected to node 1 - iWhichNode_e1=1 - iWhichNode_e2=1 - ElementsConnected=.True. - else if((p%Elems(ie1, 2) == p%Elems(ie2, 3))) then ! node 1 connected to node 2 - iWhichNode_e1=1 - iWhichNode_e2=2 - ElementsConnected=.True. - else if((p%Elems(ie1, 3) == p%Elems(ie2, 2))) then ! node 2 connected to node 1 - iWhichNode_e1=2 - iWhichNode_e2=1 - ElementsConnected=.True. - else if((p%Elems(ie1, 3) == p%Elems(ie2, 3))) then ! node 2 connected to node 2 - iWhichNode_e1=2 - iWhichNode_e2=2 - ElementsConnected=.True. - else - ElementsConnected=.False. - iWhichNode_e1=-1 - iWhichNode_e2=-1 - endif -END FUNCTION ElementsConnected - -!> Loop through a list of elements and returns a list of unique joints -TYPE(IList) FUNCTION NodesList(p, Elements) - use IntegerList, only: init_list, append, find, sort - use IntegerList, only: print_list - TYPE(SD_ParameterType), INTENT(IN) :: p - integer(IntKi), dimension(:), INTENT(IN) :: Elements - integer(IntKi) :: ie, ei, j1, j2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - call init_list(NodesList, 0, 0, ErrStat2, ErrMsg2) - do ie = 1, size(Elements) - ei = Elements(ie) ! Element index - j1 = p%Elems(ei,2) ! Joint 1 - j2 = p%Elems(ei,3) ! Joint 2 - ! Append joints indices if not in list already - if (find(NodesList, j1, ErrStat2, ErrMsg2)<=0) call append(NodesList, j1, ErrStat2, ErrMsg2) - if (find(NodesList, j2, ErrStat2, ErrMsg2)<=0) call append(NodesList, j2, ErrStat2, ErrMsg2) - ! Sorting required by find function - call sort(NodesList, ErrStat2, ErrMsg2) - enddo - call print_list(NodesList, 'Joint list') -END FUNCTION NodesList - - -!---------------------------------------------------------------------------- -!> -! - Removes the notion of "ID" and use Index instead -! - Creates Nodes (use indices instead of ID), similar to Joints array -! - Creates Elems (use indices instead of ID) similar to Members array -! - Updates Reacts (use indices instead of ID) -! - Updates Interf (use indices instead of ID) -SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) ::Init - TYPE(SD_ParameterType), INTENT(INOUT) ::p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable - INTEGER :: I, n, iMem, iNode, JointID - INTEGER(IntKi) :: mType !< Member Type - CHARACTER(1255) :: sType !< String for element type - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! TODO See if Elems is actually used elsewhere - - CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Initialize Nodes - Init%Nodes = -999999 ! Init to unphysical values - do I = 1,Init%NJoints - Init%Nodes(I, 1) = I ! JointID replaced by index I - Init%Nodes(I, 2:JointsCol) = Init%Joints(I, 2:JointsCol) ! All the rest is copied - enddo - - ! --- Re-Initialize Reactions, pointing to index instead of JointID - do I = 1, p%NReact - JointID=p%Reacts(I,1) - p%Reacts(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index - if (p%Reacts(I,1)<=0) then - CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - ! --- Re-Initialize interface joints, pointing to index instead of JointID - do I = 1, Init%NInterf - JointID=Init%Interf(I,1) - Init%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (Init%Interf(I,1)<=0) then - CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - ! Change numbering in concentrated mass matrix - do I = 1, Init%NCMass - JointID = Init%CMass(I,1) - Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (Init%Interf(I,1)<=0) then - CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - - ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) - p%Elems = 0 - ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables - DO iMem = 1, p%NMembers - ! Column 1 : member index (instead of MemberID) - p%Elems(iMem, 1) = iMem - mType = Init%Members(iMem, iMType) ! - ! Column 2-3: Joint index (instead of JointIDs) - p%Elems(iMem, 1) = iMem ! NOTE: element/member number (not MemberID) - do iNode=2,3 - p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) - if (p%Elems(iMem,iNode)<=0) then - CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list!') - return - endif - enddo - ! Column 4-5: PropIndex 1-2 (instead of PropSetID1&2) - ! NOTE: this index has different meaning depending on the member type ! - DO n=iMProp,iMProp+1 - - if (mType==idMemberBeam) then - sType='Member x-section property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) - else if (mType==idMemberCable) then - sType='Cable property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) - else if (mType==idMemberRigid) then - sType='Rigid property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) - else - ! Should not happen - print*,'Element type unknown',mType - STOP - end if - - if (p%Elems(iMem,n)<=0) then - CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') - endif - END DO !n, loop through property ids - ! Column 6: member type - p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! - END DO !iMem, loop through members - - ! TODO in theory, we shouldn't need these anymore - ! deallocate(Init%Members) - ! deallocate(Init%Joints) -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - SUBROUTINE Fatal(ErrMsg_in) - CHARACTER(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems'); - END SUBROUTINE Fatal -END SUBROUTINE SD_ReIndex_CreateNodesAndElems - -!---------------------------------------------------------------------------- -SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) ::Init - TYPE(SD_ParameterType), INTENT(INOUT) ::p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable - INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 - INTEGER :: NNE ! number of nodes per element - INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempProps(:, :) - INTEGER, ALLOCATABLE :: TempMembers(:, :) - INTEGER :: knode, kelem, kprop, nprop - REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 - LOGICAL :: found, CreateNewProp - INTEGER(IntKi) :: eType !< Element Type - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! number of nodes per element - IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN - NNE = 2 - ELSE - CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') - RETURN - ENDIF - - ! Total number of element - Init%NElem = p%NMembers*Init%NDiv ! TODO TODO TODO: THIS IS A MAX SINCE CABLE AND RIGID CANNOT BE SUBDIVIDED - ! Total number of nodes - Depends on division and number of nodes per element - Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. - - ! check the number of interior modes - IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) - RETURN - ENDIF - - CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different - - ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays - ! NOTE: need NNode and NElem - CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - - - Init%MemberNodes = 0 - ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) - if (Init%NDiv==1) then - ! NDiv = 1 - Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) - Init%NPropB = Init%NPropSetsB - - else if (Init%NDiv > 1) then - - ! Discretize structure according to NDiv - ! - Elems is fully reinitialized, connectivity needs to be done again using SetNewElem - ! - Nodes are not reinitialized, but appended to NNodes - ! - - ! Initialize Temp arrays that will contain user inputs + input from the subdivided members - ! We don't know how many properties will be needed, so allocated to size MaxNProp - MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) - CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempProps, MaxNProp, PropSetsBCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return - TempProps = -9999. - TempMembers = p%Elems(1:p%NMembers,:) - TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB - - kelem = 0 - knode = Init%NJoints - kprop = Init%NPropSetsB - DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information - ! Member data - Node1 = TempMembers(I, 2) - Node2 = TempMembers(I, 3) - Prop1 = TempMembers(I, iMProp ) - Prop2 = TempMembers(I, iMProp+1) - eType = TempMembers(I, iMType ) - - IF ( Node1==Node2 ) THEN - CALL Fatal(' Same starting and ending node in the member.') - RETURN - ENDIF - - if (eType/=idMemberBeam) then - ! --- Cables and rigid links are not subdivided - ! No need to create new properties or new nodes - print*,'Member',I, 'not subdivided since it is not a beam. Looping through.' - Init%MemberNodes(I, 1) = Node1 - Init%MemberNodes(I, 2) = Node2 - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p) - - continue - endif - - ! --- Subdivision of beams - Init%MemberNodes(I, 1) = Node1 - Init%MemberNodes(I, Init%NDiv+1) = Node2 - - IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN - - CALL Fatal(' Material E,G and rho in a member must be the same') - RETURN - ENDIF - - x1 = Init%Nodes(Node1, 2) - y1 = Init%Nodes(Node1, 3) - z1 = Init%Nodes(Node1, 4) - - x2 = Init%Nodes(Node2, 2) - y2 = Init%Nodes(Node2, 3) - z2 = Init%Nodes(Node2, 4) - - dx = ( x2 - x1 )/Init%NDiv - dy = ( y2 - y1 )/Init%NDiv - dz = ( z2 - z1 )/Init%NDiv - - d1 = TempProps(Prop1, 5) - t1 = TempProps(Prop1, 6) - - d2 = TempProps(Prop2, 5) - t2 = TempProps(Prop2, 6) - - dd = ( d2 - d1 )/Init%NDiv - dt = ( t2 - t1 )/Init%NDiv - - ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node - CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) - - ! node connect to Node1 - knode = knode + 1 - Init%MemberNodes(I, 2) = knode - CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) ! Set Init%Nodes(knode,:) - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) - nprop = Prop1 - ENDIF - - ! interior nodes - DO J = 2, (Init%NDiv-1) - knode = knode + 1 - Init%MemberNodes(I, J+1) = knode - - CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) ! Set Init%Nodes(knode,:) - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) - ENDIF - ENDDO - - ! the element connect to Node2 - kelem = kelem + 1 - CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) - ENDDO ! loop over all members - ! - Init%NPropB = kprop - Init%NElem = kelem ! TODO since not all members might have been divided - Init%NNode = knode ! TODO since not all members might have been divided - - ENDIF ! if NDiv is greater than 1 - - ! set the props in Init - CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return - - if (Init%NDiv==1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) - else if (Init%NDiv>1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempProps(1:Init%NPropB, 1:PropSetsBCol) - endif - - ! --- Cables and rigid link properties (these cannot be subdivided, so direct copy of inputs) - Init%NPropC = Init%NPropSetsC - Init%NPropR = Init%NPropSetsR - CALL AllocAry(Init%PropsC, Init%NPropC, PropSetsCCol, 'Init%PropsCable', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%PropsR, Init%NPropR, PropSetsRCol, 'Init%PropsRigid', ErrStat2, ErrMsg2); if(Failed()) return - Init%PropsC(1:Init%NPropC, 1:PropSetsCCol) = Init%PropSetsC(1:Init%NPropC, 1:PropSetsCCol) - Init%PropsR(1:Init%NPropR, 1:PropSetsRCol) = Init%PropSetsR(1:Init%NPropR, 1:PropSetsRCol) - - CALL CleanUp_Discrt() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') - Failed = ErrStat >= AbortErrLev - if (Failed) CALL CleanUp_Discrt() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - CHARACTER(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); - CALL CleanUp_Discrt() - END SUBROUTINE Fatal - - SUBROUTINE CleanUp_Discrt() - ! deallocate temp matrices - IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) - IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) - END SUBROUTINE CleanUp_Discrt - -END SUBROUTINE SD_Discrt - - !> Returns index of val in Array (val is an integer!) ! NOTE: in the future use intrinsinc function findloc FUNCTION FINDLOCI_ReKi(Array, Val) result(i) @@ -630,666 +132,6 @@ FUNCTION FINDLOCI_IntKi(Array, Val) result(i) enddo i=-1 END FUNCTION - - -!------------------------------------------------------------------------------------------------------ -!> Set properties of node k -SUBROUTINE SetNewNode(k, x, y, z, Init) - TYPE(SD_InitType), INTENT(INOUT) :: Init - INTEGER, INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: x, y, z - - Init%Nodes(k, 1) = k - Init%Nodes(k, 2) = x - Init%Nodes(k, 3) = y - Init%Nodes(k, 4) = z - Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever - ! Properties below are for non-cantilever joints - Init%Nodes(k, iJointDir:iJointDir+2) = -99999 - Init%Nodes(k, iJointStiff) = -99999 - Init%Nodes(k, iJointDamp) = -99999 - -END SUBROUTINE SetNewNode - -!------------------------------------------------------------------------------------------------------ -!> Set properties of element k -SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) - INTEGER, INTENT(IN ) :: k - INTEGER, INTENT(IN ) :: n1 - INTEGER, INTENT(IN ) :: n2 - INTEGER, INTENT(IN ) :: eType - INTEGER, INTENT(IN ) :: p1 - INTEGER, INTENT(IN ) :: p2 - TYPE(SD_ParameterType), INTENT(INOUT) :: p - - p%Elems(k, 1) = k - p%Elems(k, 2) = n1 - p%Elems(k, 3) = n2 - p%Elems(k, iMProp ) = p1 - p%Elems(k, iMProp+1) = p2 - p%Elems(k, iMType) = eType - -END SUBROUTINE SetNewElem - -!------------------------------------------------------------------------------------------------------ -!> Set material properties of element k -!! NOTE: this is only for a beam -SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) - INTEGER , INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: E, G, rho, d, t - REAL(ReKi), INTENT(INOUT):: TempProps(:, :) - - TempProps(k, 1) = k - TempProps(k, 2) = E - TempProps(k, 3) = G - TempProps(k, 4) = rho - TempProps(k, 5) = d - TempProps(k, 6) = t - -END SUBROUTINE SetNewProp - -!------------------------------------------------------------------------------------------------------ -!> Set Element properties p%ElemProps, different properties are set depening on element type.. -SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I, J, K, iTmp - INTEGER :: N1, N2 ! starting node and ending node in the element - INTEGER :: P1, P2 ! property set numbers for starting and ending nodes - REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section - REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices - REAL(ReKi) :: L ! length of the element - REAL(ReKi) :: T0 ! pretension force in cable [N] - REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer - LOGICAL :: shear - INTEGER(IntKi) :: eType !< Member type - REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrMsg = "" - ErrStat = ErrID_None - - ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2); ErrMsg2='Error allocating p%ElemProps' - if(Failed()) return - - ! Loop over all elements and set ElementProperties - do I = 1, Init%NElem - N1 = p%Elems(I, 2) - N2 = p%Elems(I, 3) - - P1 = p%Elems(I, iMProp ) - P2 = p%Elems(I, iMProp+1) - eType = p%Elems(I, iMType) - - ! --- Properties common to all element types: L, DirCos (and Area and rho) - Point1 = Init%Nodes(N1,2:4) - Point2 = Init%Nodes(N2,2:4) - CALL GetDirCos(Point1, Point2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos - p%ElemProps(i)%eType = eType - p%ElemProps(i)%Length = L - p%ElemProps(i)%DirCos = DirCos - - ! Init to excessive values to detect any issue - p%ElemProps(i)%Ixx = -9.99e+36 - p%ElemProps(i)%Iyy = -9.99e+36 - p%ElemProps(i)%Jzz = -9.99e+36 - p%ElemProps(i)%Kappa = -9.99e+36 - p%ElemProps(i)%YoungE = -9.99e+36 - p%ElemProps(i)%ShearG = -9.99e+36 - p%ElemProps(i)%Area = -9.99e+36 - p%ElemProps(i)%Rho = -9.99e+36 - p%ElemProps(i)%T0 = -9.99e+36 - - ! --- Properties that are specific to some elements - if (eType==idMemberBeam) then - E = Init%PropsB(P1, 2) - G = Init%PropsB(P1, 3) - rho = Init%PropsB(P1, 4) - D1 = Init%PropsB(P1, 5) - t1 = Init%PropsB(P1, 6) - D2 = Init%PropsB(P2, 5) - t2 = Init%PropsB(P2, 6) - r1 = 0.25*(D1 + D2) - t = 0.5*(t1+t2) - if ( EqualRealNos(t, 0.0_ReKi) ) then - r2 = 0 - else - r2 = r1 - t - endif - A = Pi_D*(r1*r1-r2*r2) - Ixx = 0.25*Pi_D*(r1**4-r2**4) - Iyy = Ixx - Jzz = 2.0*Ixx - - if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli - Shear = .false. - kappa = 0 - elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko - Shear = .true. - ! kappa = 0.53 - ! equation 13 (Steinboeck et al) in SubDyn Theory Manual - nu = E / (2.0_ReKi*G) - 1.0_ReKi - D_outer = 2.0_ReKi * r1 ! average (outer) diameter - D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter - ratioSq = ( D_inner / D_outer)**2 - kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & - / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) - endif - ! Storing Beam specific properties - p%ElemProps(i)%Ixx = Ixx - p%ElemProps(i)%Iyy = Iyy - p%ElemProps(i)%Jzz = Jzz - p%ElemProps(i)%Shear = Shear - p%ElemProps(i)%kappa = kappa - p%ElemProps(i)%YoungE = E - p%ElemProps(i)%ShearG = G - p%ElemProps(i)%Area = A - p%ElemProps(i)%Rho = rho - - else if (eType==idMemberCable) then - print*,'Member',I,'eType',eType,'Ps',P1,P2 - p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 - p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] - p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] - p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] - - else if (eType==idMemberRigid) then - print*,'Member',I,'eType',eType,'Ps',P1,P2 - p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 - p%ElemProps(i)%Rho = Init%PropsR(P1, 2) - - else - ! Should not happen - print*,'Element type unknown',eType - STOP - end if - enddo ! I end loop over elements -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed -END SUBROUTINE SetElementProperties - - -!> Distribute global DOF indices corresponding to Nodes, Elements, BCs, Reactions -!! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs -!! For other joint type -> Condensation of the 3 translational DOF -!! -> Keeping 3 rotational DOF for each memeber connected to the joint -SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) - use IntegerList, only: init_list, len - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer(IntKi) :: iNode, k - integer(IntKi) :: iPrev ! Cumulative counter over the global DOF - integer(IntKi) :: iElem ! - integer(IntKi) :: idElem - integer(IntKi) :: nRot ! Number of rotational DOFs (multiple of 3) to be used at the joint - integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 - integer(IntKi), dimension(6) :: DOFNode_Old - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - ErrMsg = "" - ErrStat = ErrID_None - - allocate(m%NodesDOF(1:Init%NNode), stat=ErrStat2) - ErrMsg2="Error allocating NodesDOF" - if(Failed()) return - - call AllocAry(m%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; - m%ElemsDOF=-9999 - - iPrev =0 - do iNode = 1, Init%NNode - ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) - if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then - nRot=3 - else - nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint - endif - call init_list(m%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) - m%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) - - ! --- Distribute to members - do iElem = 1, Init%NodesConnE(iNode,1) ! members connected to joint iJ - idElem = Init%NodesConnE(iNode,iElem+1) - if (iNode == p%Elems(idElem, 2)) then ! Current joint is Elem node 1 - iOff = 0 - else ! Current joint is Elem node 2 - iOff = 6 - endif - m%ElemsDOF(iOff+1:iOff+3, idElem) = m%NodesDOF(iNode)%List(1:3) - if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then - m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(4:6) - else - m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) - endif - enddo ! iElem, loop on members connect to joint - iPrev = iPrev + len(m%NodesDOF(iNode)) - enddo ! iNode, loop on joints - - ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return - CALL InitBCs(Init, p) - - ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return - CALL InitIntFc(Init, p) - - ! --- Safety check - if (any(m%ElemsDOF<0)) then - ErrStat=ErrID_Fatal - ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" - endif - - ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) - if (Init%NNode == count( Init%Nodes(:, iJointType) == idJointCantilever)) then - do idElem = 1, Init%NElem - iNode = p%Elems(idElem, 2) - DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) - if ( any( (m%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then - ErrStat=ErrID_Fatal - ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iElem="//trim(Num2LStr(idElem)) - return - endif - enddo - else - print*,'Not performing safety check' ! remove me in the future - STOP - endif - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - - !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have - !! NOTE: need p%Reacts to have an updated first column that uses indices and not JointIDs - SUBROUTINE InitBCs(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - Init%BCs = 0 - DO I = 1, p%NReact - iNode = p%Reacts(I,1) ! Node index - DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) - Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); - ENDDO - ENDDO - END SUBROUTINE InitBCs - - !> Sets a list of DOF indices and the value these DOF should have - !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs - SUBROUTINE InitIntFc(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - Init%IntFc = 0 - DO I = 1, Init%NInterf - iNode = Init%Interf(I,1) ! Node index - DO J = 1, 6 - Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) - Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); - ENDDO - ENDDO - END SUBROUTINE InitIntFc - -END SUBROUTINE DistributeDOF - -!------------------------------------------------------------------------------------------------------ -!> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I, J, K, jn, kn - INTEGER :: iGlob - REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector - REAL(ReKi) :: FCe(12) ! Pretension force from cable element - INTEGER, DIMENSION(2) :: nn ! node number in element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system - integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system - ErrMsg = "" - ErrStat = ErrID_None - - ! total unconstrained degrees of freedom of the system - Init%TDOF = nDOF_Unconstrained() - print*,'nDOF_unconstrained',Init%TDOF, 6*Init%NNode - - CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - Init%K = 0.0_ReKi - Init%M = 0.0_ReKi - Init%FG = 0.0_ReKi - - ! loop over all elements, compute element matrices and assemble into global matrices - DO i = 1, Init%NElem - ! --- Element Me,Ke,Fg, Fce - CALL ElemM(p%ElemProps(i), Me) - CALL ElemK(p%ElemProps(i), Ke) - CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) - - ! --- Assembly in global unconstrained system - IDOF = m%ElemsDOF(1:12, i) - Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) - Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) - Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) - ENDDO ! end loop over elements , i - - ! add concentrated mass - DO I = 1, Init%NCMass - DO J = 1, 3 - iGlob = m%NodesDOF(i)%List(J) ! ux, uy, uz - Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) - ENDDO - DO J = 4, 6 - iGlob = m%NodesDOF(i)%List(J) ! theta_x, theta_y, theta_z - Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) - ENDDO - ENDDO ! Loop on concentrated mass - - ! add concentrated mass induced gravity force - DO I = 1, Init%NCMass - iGlob = m%NodesDOF(i)%List(3) ! uz - Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g - ENDDO ! I concentrated mass induced gravity - - CALL CleanUp_AssembleKM() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM') - Failed = ErrStat >= AbortErrLev - if (Failed) call Cleanup_AssembleKM() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); - CALL CleanUp_AssembleKM() - END SUBROUTINE Fatal - - SUBROUTINE CleanUp_AssembleKM() - !pass - END SUBROUTINE CleanUp_AssembleKM - - INTEGER(IntKi) FUNCTION nDOF_Unconstrained() - integer(IntKi) :: i - integer(IntKi) :: m - nDOF_Unconstrained=0 - do i = 1,Init%NNode - if (Init%Nodes(i,iJointType) == idJointCantilever ) then - nDOF_Unconstrained = nDOF_Unconstrained + 6 - else - m = Init%NodesConnE(i,1) ! Col1: number of elements connected to this joint - nDOF_Unconstrained = nDOF_Unconstrained + 3 + 3*m - endif - end do - END FUNCTION - -END SUBROUTINE AssembleKM -!------------------------------------------------------------------------------------------------------ -!> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ! Varaibles for rigid assembly - type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA - - - ErrStat = ErrID_None - ErrMsg = "" - - call RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat2, ErrMsg2); if(Failed()) return - - - call BuildTMatrix(); if (Failed()) return - - - deallocate(RAm1) - deallocate(RA) - deallocate(njRA) - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'DirectElimination') - Failed = ErrStat >= AbortErrLev - !if (Failed) call Cleanup_AssembleKM() - END FUNCTION Failed - - !SUBROUTINE Fatal(ErrMsg_in) - ! character(len=*), intent(in) :: ErrMsg_in - ! CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'DirectElimination'); - ! CALL CleanUp_DirectElimination() - !END SUBROUTINE Fatal - - !SUBROUTINE CleanUp_DirectElimination() - !pass - !END SUBROUTINE CleanUp_DirectElimination - - SUBROUTINE BuildTMatrix() - ! Variables for Building T - use IntegerList, only: init_list, find, pop, destroy_list, len - use IntegerList, only: print_list - real(ReKi), dimension(:,:), allocatable :: T - real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 - integer(IntKi), dimension(:), allocatable :: Elements !< List of elements - real(ReKi), dimension(:,:), allocatable :: Tc - integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - integer(IntKi), dimension(:), allocatable :: IDOFOld !< - integer(IntKi), dimension(:), pointer :: IDOFNew !< - integer(IntKi) :: iPrev - type(IList) :: IRA - integer(IntKi) :: nDOF - integer(IntKi) :: aID, ia ! assembly ID, and index in IRA - integer(IntKi) :: iNode - integer(IntKi) :: I - integer(IntKi) :: nc !< Number of DOF after constraints applied - integer(IntKi) :: nj - - ! --- Misc inits - nullify(IDOFNew) - I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - - - allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2) ! Indices of DOF for each joint, in reduced system - - - nDOF = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', nDOF - allocate(T(1:Init%TDOF, 1:nDOF)) - T=0 - iPrev =0 - call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); - IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) - call print_list(IRA, 'List of RA indices') - print*,'------------------ BUILD T ----------------------------------' - - ! --- For each node: - ! - create list of indices I in the assembled vector of DOF - ! - create list of indices Itilde in the reduced vector of DOF - do iNode = 1, Init%NNode - nc=0 - if (allocated(Tc)) deallocate(Tc) - if (allocated(IDOFOld)) deallocate(IDOFOld) - - if (Init%Nodes(iNode,iJointType) == idJointPin ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then - ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - aID = RAm1(iNode) - ia = find(IRA, aID, ErrStat2, ErrMsg2) - print*,'Node',iNode, 'is involved in RA', aID, ia - if ( ia <= 0) then - ! This rigid assembly has already been processed, pass to next node - cycle - else - call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2) - aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed - nj = size(INodesID) - allocate(IDOFOld(1:6*nj)) - do I=1, nj - IDOFOld( (I-1)*6+1 : I*6 ) = m%NodesDOF(INodesID(I))%List(1:6) - enddo - endif - else - ! That's a regular Cantilever joint - allocate(Tc(1:6,1:6)) - allocate(IDOFOld(1:6)) - Tc=I6 - IDOFOld = m%NodesDOF(iNode)%List(1:6) - endif - else - ErrMsg2='Wrong joint type'; ErrStat2=ErrID_Fatal - endif - if (allocated(Tc)) then - nc=size(Tc,2) - call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) - m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) - IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - !print*,'N',iNode,'I ',IDOFOld - !print*,'N',iNode,'It',IDOFNew - T(IDOFOld, IDOFNew) = Tc - iPrev = iPrev + nc - else - print*,'Error, Tc not allocated, TODO' - STOP - endif - enddo - deallocate(T) - nullify(IDOFNew) - ! --- Safety checks - if (len(IRA)>0) then - ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal - endif - - call destroy_list(IRA, ErrStat2, ErrMsg2) - - END SUBROUTINE BuildTMatrix - - !> Returns number of DOF after constraint reduction (via the matrix T) - INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() - integer(IntKi) :: iNode - integer(IntKi) :: ia ! Index on rigid link assembly - integer(IntKi) :: m ! Number of elements connected to a joint - nDOF_ConstraintReduced = 0 - - ! Rigid assemblies contribution - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) - - ! Contribution from all the other joints - do iNode = 1, Init%NNode - m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint - - if (Init%Nodes(iNode,iJointType) == idJointPin ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m - print*,'Node',iNode, 'is a pin joint' - - elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m - print*,'Node',iNode, 'is an universal joint' - - elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 3*m - print*,'Node',iNode, 'is a ball joint' - - elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then - ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - print*,'Node',iNode, 'is involved in a RA' - else - ! That's a regular Cantilever joint - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 - !print*,'Node',iNode, 'is a regular cantilever' - endif - else - ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal - endif - end do - END FUNCTION nDOF_ConstraintReduced -END SUBROUTINE DirectElimination - - -!------------------------------------------------------------------------------------------------------ -!> Returns list of rigid link elements (Er) -TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, append - use IntegerList, only: print_list - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - integer(IntKi) :: ie !< Index on elements - ErrStat = ErrID_None - ErrMsg = "" - ! --- Establish a list of rigid link elements - call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); - - do ie = 1, Init%NElem - if (p%ElemProps(ie)%eType == idMemberRigid) then - call append(RigidLinkElements, ie, ErrStat, ErrMsg); - endif - end do - call print_list(RigidLinkElements,'Rigid element list') -END FUNCTION RigidLinkElements - -!------------------------------------------------------------------------------------------------------ -!> Returns true if one of the element connected to the node is a rigid link -LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) - INTEGER(IntKi), INTENT(IN ) :: iJoint - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - ! Local variables - integer(IntKi) :: ie !< Loop index on elements - integer(IntKi) :: ei !< Element index - integer(IntKi) :: m ! Number of elements connected to a joint - - NodeHasRigidElem = .False. ! default return value - - ! Loop through elements connected to node J - do ie = 1, Init%NodesConnE(iJoint, 1) - ei = Init%NodesConnE(iJoint, ie+1) - if (p%ElemProps(ei)%eType == idMemberRigid) then - NodeHasRigidElem = .True. - return ! we exit as soon as one rigid member is found - endif - enddo -END FUNCTION NodeHasRigidElem - !------------------------------------------------------------------------------------------------------ !> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) @@ -1331,195 +173,6 @@ SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) !TRigid ( 3, 4 ) = L*R0(2,3) !TRigid ( 3, 5 ) = -L*R0(1,3) END SUBROUTINE GetRigidTransformation - -!------------------------------------------------------------------------------------------------------ -!> Returns constrains matrix for a rigid assembly (RA) formed by a set of elements. -!! -SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get - integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements - real(ReKi), dimension(:,:), allocatable :: Tc - integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Local variables - type(IList) :: LNodesID !< List of nodes id involved in element - type(IList) :: INodesInterf !< List of indices for Nodes involved in interface - integer(IntKi) :: NodeID !< NodeID - integer(IntKi) :: iTmp !< Temporary index - integer(IntKi) :: iNodeID !< Loop index on node ID list - integer(IntKi) :: iMainNode !< Index of main node selected for rigid assembly within INodesID list - integer(IntKi) :: nNodes !< Number of Nodes involved in RA - integer(IntKi) :: iFound !< Loop index on node ID list - integer(IntKi) :: i !< Loop index - real(ReKi) :: TRigid(6,6) ! Transformation matrix such that xi = T.x1 - real(ReKi) :: P1(3), Pi(3) ! Nodal points - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! --- List of nodes stored first in LINodes than moved to INodes - LNodesID = NodesList(p, Elements) - call move_alloc(LNodesID%List, INodesID) - call destroy_list(LNodesID, ErrStat2, ErrMsg2) - print*,'Nodes involved in assembly (befr) ',INodesID - - !--- Look for potential interface node - call init_list(INodesInterf, 0, 0, ErrStat2, ErrMsg2); - do iNodeID = 1, size(INodesID) - NodeID = INodesID(iNodeID) - iFound = FINDLOCI( Init%Interf(:,1), NodeID) - if (iFound>0) then - call append(INodesInterf, iNodeID, ErrStat2, ErrMsg2) - ! This node is an interface node - print*,'Node',NodeID, 'is an interface node, selecting it for the rigid assembly' - endif - enddo - - ! --- Decide which node will be the main node of the rigid assembly - if (len(INodesInterf)==0) then - iMainNode = 1 ! By default we select the first node - else if (len(INodesInterf)==1) then - iMainNode = pop(INodesInterf, ErrStat2, ErrMsg2) - else - ErrStat=ErrID_Fatal - ErrMsg='Cannot have several interface nodes linked within a same rigid assembly' - return - endif - call destroy_list(INodesInterf, ErrStat2, ErrMsg2) - - ! --- Order list of joints with main node first (swapping iMainNode with INodes(1)) - iTmp = INodesID(1) - INodesID(1) = iMainNode - INodesID(iMainNode) = iTmp - print*,'Nodes involved in assembly (after)',INodesID - - ! --- Building Transformation matrix - nNodes =size(INodesID) - allocate(Tc(6*nNodes,6)) - Tc(:,:)=0 - ! I6 for first node - do i = 1,6 ; Tc(i,i)=1_ReKi; enddo ! I6 = eye(6) - ! Rigid transformation matrix for the other nodes - P1 = Init%Nodes(INodesID(1), 2:4) ! reference node coordinates - do i = 2, nNodes - Pi = Init%Nodes(INodesID(i), 2:4) ! follower node coordinates - call GetRigidTransformation(P1, Pi, TRigid, ErrStat2, ErrMsg2) - Tc( ((i-1)*6)+1:6*i, 1:6) = TRigid(1:6,1:6) - enddo -END SUBROUTINE RAElimination - -!------------------------------------------------------------------------------------------------------ -!> Setup a list of rigid link assemblies (RA) -SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA - integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - ! Local variables - type(IList) :: Er !< List of rigid elements - type(IList) :: Ea !< List of elements in a rigid assembly - integer(IntKi) :: nRA !< Number of rigid assemblies - integer(IntKi) :: ie !< Index on elements - integer(IntKi) :: ia !< Index on assemblies - integer(IntKi) :: e0 !< Index of an element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - allocate(RAm1(1:Init%NElem)) - RAm1(1:Init%NElem) = -1 - - ! --- Establish a list of rigid link elements - Er = RigidLinkElements(Init, p, ErrStat2, ErrMsg2) - nRA=0 - do while (len(Er)>0) - nRA=nRA+1 - ! Creating List Ea of elements of a given assembly - call init_list(Ea, 0, 0, ErrStat2, ErrMsg2); - e0 = pop(Er, ErrStat2, ErrMsg2); - call append(Ea, e0, ErrStat2, ErrMsg2); - call AddNeighbors(e0, Er, Ea) - call print_list(Ea,'Rigid assembly') - do ie = 1, len(Ea) - e0 = get(Ea, ie, ErrStat2, ErrMsg2) - RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to - enddo - call destroy_list(Ea, ErrStat2, ErrMsg2) - enddo - call destroy_list(Er, ErrStat2, ErrMsg2) - - ! --- Creating RA, array of lists of assembly elements. - ! Note: exactly the same as all the Ea created above, but we didn't know the total number of RA - allocate(RA(1:nRA)) - do ia = 1, nRA - call init_list(RA(ia), 0, 0, ErrStat2, ErrMsg2) - enddo - do ie = 1, Init%NElem - ia = RAm1(ie) ! Index of the assembly the element belongs to: RA^{-1}(ie) = ia - if (ia>0) then - call append(RA(ia), ie, ErrStat2, ErrMsg2) - endif - enddo - do ia = 1, nRA - call print_list(RA(ia),'Rigid assembly') - enddo - - ! --- Counting unique joints involved in Rigid assembly - allocate(njRA(1:nRA)) - do ia = 1, nRA - ! Getting list of nodes involved in RA(ia) - Er = NodesList(p, RA(ia)%List) - njRA(ia) = len(Er) - call destroy_list(Er, ErrStat2, ErrMsg2) - enddo - print*,'njRA',njRA -CONTAINS - !> The neighbors of e0 (that are found within the list Er) are added to the list Ea - RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) - integer(IntKi), intent(in) :: e0 !< Index of an element - type(IList), intent(inout) :: Er !< List of rigid elements - type(IList), intent(inout) :: Ea !< List of elements in a rigid assembly - type(IList) :: En !< List of neighbors of e0 - integer (IntKi) :: ik - integer (IntKi) :: ek, ek2 - integer (IntKi) :: iWhichNode_e0, iWhichNode_ek - call init_list(En, 0, 0, ErrStat2, ErrMsg2) - ! Loop through all elements, setup list of e0-neighbors, add them to Ea, remove them from Er - ik=0 - do while (ik< len(Er)) - ik=ik+1 - ek = Er%List(ik) - if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then - print*,'Element ',ek,'is connected to ',e0,'via its node',iWhichNode_ek - ! Remove element from Er (a rigid element can belong to only one assembly) - ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before - ik=ik-1 - if (ek/=ek2) then - print*,'Problem in popping',ek,ek2 - endif - call append(En, ek, ErrStat2, ErrMsg2) - call append(Ea, ek, ErrStat2, ErrMsg2) - endif - enddo - ! Loop through neighbors and recursively add neighbors of neighbors - do ik = 1, len(En) - ek = En%List(ik) - call AddNeighbors(ek, Er, Ea) - enddo - call destroy_list(En, ErrStat2, ErrMsg2) - END SUBROUTINE AddNeighbors - - -END SUBROUTINE RigidLinkAssemblies - !------------------------------------------------------------------------------------------------------ !> Computes directional cosine matrix DirCos !! Transforms from element to global coordinates: xg = DC.xe, Kg = DC.Ke.DC^t @@ -1575,61 +228,6 @@ SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) ENDIF END SUBROUTINE GetDirCos - - -SUBROUTINE ElemM(ep, Me) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Me(12, 12) - if (ep%eType==idMemberBeam) then - !Calculate Ke, Me to be used for output - CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) - - else if (ep%eType==idMemberCable) then - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) - - else if (ep%eType==idMemberRigid) then - if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then - Me=0.0_ReKi - else - print*,'SD_FEM: Mass matrix for rigid members rho/=0 TODO' - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) - !CALL ElemM_(A, L, rho, DirCos, Me) - endif - endif -END SUBROUTINE ElemM - -SUBROUTINE ElemK(ep, Ke) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Ke(12, 12) - - if (ep%eType==idMemberBeam) then - CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) - - else if (ep%eType==idMemberCable) then - CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) - - else if (ep%eType==idMemberRigid) then - Ke = 0.0_ReKi - endif -END SUBROUTINE ElemK - -SUBROUTINE ElemF(ep, gravity, Fg, Fo) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity - REAL(ReKi), INTENT(OUT) :: Fg(12) - REAL(ReKi), INTENT(OUT) :: Fo(12) - if (ep%eType==idMemberBeam) then - Fo(1:12)=0 - else if (ep%eType==idMemberCable) then - CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) - else if (ep%eType==idMemberRigid) then - Fo(1:12)=0 - endif - CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) -END SUBROUTINE ElemF - - - !------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for classical beam elements !! shear is true -- non-tapered Timoshenko beam @@ -1819,7 +417,7 @@ SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed END SUBROUTINE ElemM_Beam - +!------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for pretension cable SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) REAL(ReKi), INTENT( IN) :: A, L, rho @@ -1857,30 +455,6 @@ SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed END SUBROUTINE ElemM_Cable - - -!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices -SUBROUTINE ApplyConstr(Init,p) - TYPE(SD_InitType ),INTENT(INOUT):: Init - TYPE(SD_ParameterType),INTENT(IN ):: p - - INTEGER :: I !, J, k - INTEGER :: row_n !bgn_j, end_j, - - DO I = 1, p%NReact*6 - row_n = Init%BCs(I, 1) - IF (Init%BCs(I, 2) == 1) THEN - Init%K(row_n,: )= 0 - Init%K(: ,row_n)= 0 - Init%K(row_n,row_n)= 1 - - Init%M(row_n,: )= 0 - Init%M(: ,row_n)= 0 - Init%M(row_n,row_n)= 0 - ENDIF - ENDDO ! I, loop on reaction nodes -END SUBROUTINE ApplyConstr - !------------------------------------------------------------------------------------------------------ !> calculates the lumped forces and moments due to gravity on a given element: !! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: @@ -1916,7 +490,7 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) !F(12) is 0 for g along z alone END SUBROUTINE ElemG - +!------------------------------------------------------------------------------------------------------ !> SUBROUTINE ElemF_Cable(T0, DirCos, F) REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] @@ -1938,9 +512,6 @@ SUBROUTINE ElemF_Cable(T0, DirCos, F) F = MATMUL(DC, F)! TODO: change me if DirCos convention is transposed END SUBROUTINE ElemF_Cable - - - !------------------------------------------------------------------------------------------------------ !> Calculates the lumped gravity forces at the nodes given the element geometry !! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 @@ -1986,4 +557,4 @@ SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) !F(12) is 0 for g along z alone END SUBROUTINE LumpForces -END MODULE SD_FEM +END MODULE FEM diff --git a/modules/subdyn/src/copy.f90 b/modules/subdyn/src/SD_FEM.f90 similarity index 76% rename from modules/subdyn/src/copy.f90 rename to modules/subdyn/src/SD_FEM.f90 index 907476ea3..34fa87072 100644 --- a/modules/subdyn/src/copy.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -19,9 +19,9 @@ MODULE SD_FEM USE NWTC_Library USE SubDyn_Types + USE FEM IMPLICIT NONE - INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in @@ -69,79 +69,6 @@ MODULE SD_FEM CONTAINS -!------------------------------------------------------------------------------------------------------ -!> Remove degrees of freedom from a matrix (lines and rows) -SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) - REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix - logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER :: I, J ! counters into full matrix - INTEGER :: Ir, Jr ! counters into reduced matrix - INTEGER :: nr ! number of reduced DOF - ErrStat = ErrID_None - ErrMsg = '' - - nr= count(bDOF) - CALL AllocAry(Ared, nr, nr, 'Ared', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return - - ! Remove rows and columns from A when bDOF is - Jr=0 - do J = 1, size(A,1) - if (bDOF(J)) then - Jr=Jr+1 - Ir=0 - do I = 1, size(A,1) - if (bDOF(I)) then - Ir=Ir+1 - Ared(Ir, Jr) = REAL( A(I, J), LAKi ) - end if - end do - endif - end do -END SUBROUTINE RemoveDOF - -!> Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) -SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) - REAL(LAKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix - logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(ReKi), INTENT(IN ) :: DefaultVal ! Default value to fill the - REAL(ReKi) , INTENT(INOUT) :: A(:,:) ! Full matrix - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER :: I ! counter into full matrix - INTEGER :: Ir ! counter into reduced matrix - INTEGER :: n ! number of DOF (fullsystem) - ErrStat = ErrID_None - ErrMsg = '' - n= size(bDOF) - IF ( size(Ared,1) > n) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'InsertDOFrows: Number of reduced rows needs to be lower than full system rows' - RETURN - END IF - IF ( size(Ared,2) /= size(A,2) ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'InsertDOFrows: Inconsistent number of columns between A and Ared' - RETURN - END IF - !CALL AllocAry(A, n, size(Ared,2), 'A', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return - - ! Use rows from Ared when bDOF is true, use default value otherwise - ir=0 ! initialize - do i=1,n - if (bDOF(i)) then - ir =ir +1 - A(i,:)=real( Ared(ir,:), ReKi ) - else - A(i,:)=DefaultVal - endif - enddo -END SUBROUTINE InsertDOFrows - !------------------------------------------------------------------------------------------------------ !> Maps nodes to elements !! allocate NodesConnE and NodesConnN @@ -595,43 +522,6 @@ END SUBROUTINE CleanUp_Discrt END SUBROUTINE SD_Discrt - -!> Returns index of val in Array (val is an integer!) -! NOTE: in the future use intrinsinc function findloc -FUNCTION FINDLOCI_ReKi(Array, Val) result(i) - real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == NINT(Array(i)) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 -END FUNCTION -!> Returns index of val in Array (val is an integer!) -! NOTE: in the future use intrinsinc function findloc -FUNCTION FINDLOCI_IntKi(Array, Val) result(i) - integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == Array(i) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 -END FUNCTION - - !------------------------------------------------------------------------------------------------------ !> Set properties of node k SUBROUTINE SetNewNode(k, x, y, z, Init) @@ -1057,6 +947,10 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA + ! + real(ReKi), dimension(:,:), allocatable :: T + real(ReKi), dimension(:,:), allocatable :: MM, KK + integer(IntKi) :: nDOF ErrStat = ErrID_None @@ -1067,6 +961,15 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call BuildTMatrix(); if (Failed()) return + ! --- DOF elimination for system matrices and RHS vector + ! Temporary backup of M and K of full system + !call move_alloc(Init%M, Init%M) + !call move_alloc(Init%K, Init%K) + !! Reallocating + !nDOF = size(T,2) + !CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + !CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + !CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector deallocate(RAm1) deallocate(RA) @@ -1093,7 +996,7 @@ SUBROUTINE BuildTMatrix() ! Variables for Building T use IntegerList, only: init_list, find, pop, destroy_list, len use IntegerList, only: print_list - real(ReKi), dimension(:,:), allocatable :: T + !real(ReKi), dimension(:,:), allocatable :: T real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 integer(IntKi), dimension(:), allocatable :: Elements !< List of elements real(ReKi), dimension(:,:), allocatable :: Tc @@ -1289,49 +1192,6 @@ LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) endif enddo END FUNCTION NodeHasRigidElem - -!------------------------------------------------------------------------------------------------------ -!> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. -SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) - REAL(ReKi), INTENT(IN ) :: Pj(3) ! (x,y,z) positions of leader node - REAL(ReKi), INTENT(IN ) :: Pk(3) ! (x,y,z) positions of follower node - REAL(ReKi), INTENT( OUT) :: TRigid(6,6) ! Transformation matrix such that xk = T.xj - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local - !REAL(ReKi) :: L ! length of element - !REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrix - !REAL(ReKi) :: R0(3,3) - integer(IntKi) :: I - ErrStat = ErrID_None - ErrMsg = "" - - ! --- Formulation using Delta of Global coordinates - Trigid=0; do I = 1,6; Trigid(I,I) = 1; enddo - Trigid ( 1, 5 ) = (Pk(3) - Pj(3)) - Trigid ( 1, 6 ) = -(Pk(2) - Pj(2)) - Trigid ( 2, 4 ) = -(Pk(3) - Pj(3)) - Trigid ( 2, 6 ) = (Pk(1) - Pj(1)) - Trigid ( 3, 4 ) = (Pk(2) - Pj(2)) - Trigid ( 3, 5 ) = -(Pk(1) - Pj(1)) - - ! --- Formulation bty transforming the "local" matrix into a global one - !call GetDirCos(Pj, Pk, R0, L, ErrStat, ErrMsg) - !TRigid = 0 ; do I = 1,6; TRigid(I,I) = 1; enddo - !TRigid (1, 5) = L - !TRigid (2, 4) = -L - !TRigid(1:3,4:6) = matmul( R0 , matmul(TRigid(1:3,4:6), transpose(R0)) ) - - ! --- Formulation using L and Rotation matrix - !TRigid = 0; do I = 1,6; TRigid(I,I) = 1; enddo - !TRigid ( 1, 5 ) = L*R0(3,3) - !TRigid ( 1, 6 ) = -L*R0(2,3) - !TRigid ( 2, 4 ) = -L*R0(3,3) - !TRigid ( 2, 6 ) = L*R0(1,3) - !TRigid ( 3, 4 ) = L*R0(2,3) - !TRigid ( 3, 5 ) = -L*R0(1,3) -END SUBROUTINE GetRigidTransformation - !------------------------------------------------------------------------------------------------------ !> Returns constrains matrix for a rigid assembly (RA) formed by a set of elements. !! @@ -1520,61 +1380,27 @@ END SUBROUTINE AddNeighbors END SUBROUTINE RigidLinkAssemblies -!------------------------------------------------------------------------------------------------------ -!> Computes directional cosine matrix DirCos -!! Transforms from element to global coordinates: xg = DC.xe, Kg = DC.Ke.DC^t -!! Assumes that the element main direction is along ze. -!! -!! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix -!! in the FAST framework. -SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) - REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element - REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix - REAL(ReKi) , INTENT( OUT) :: L ! length of element - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: Dx, Dy, Dz, Dxy ! distances between nodes - ErrMsg = "" - ErrStat = ErrID_None - - Dx=P2(1)-P1(1) - Dy=P2(2)-P1(2) - Dz=P2(3)-P1(3) - Dxy = sqrt( Dx**2 + Dy**2 ) - L = sqrt( Dx**2 + Dy**2 + Dz**2) +!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices +SUBROUTINE ApplyConstr(Init,p) + TYPE(SD_InitType ),INTENT(INOUT):: Init + TYPE(SD_ParameterType),INTENT(IN ):: p - IF ( EqualRealNos(L, 0.0_ReKi) ) THEN - ErrMsg = ' Same starting and ending location in the element.' - ErrStat = ErrID_Fatal - RETURN - ENDIF + INTEGER :: I !, J, k + INTEGER :: row_n !bgn_j, end_j, - IF ( EqualRealNos(Dxy, 0.0_ReKi) ) THEN - DirCos=0.0_ReKi ! whole matrix set to 0 - IF ( Dz < 0) THEN !x is kept along global x - DirCos(1, 1) = 1.0_ReKi - DirCos(2, 2) = -1.0_ReKi - DirCos(3, 3) = -1.0_ReKi - ELSE - DirCos(1, 1) = 1.0_ReKi - DirCos(2, 2) = 1.0_ReKi - DirCos(3, 3) = 1.0_ReKi - ENDIF - ELSE - DirCos(1, 1) = Dy/Dxy - DirCos(1, 2) = +Dx*Dz/(L*Dxy) - DirCos(1, 3) = Dx/L - - DirCos(2, 1) = -Dx/Dxy - DirCos(2, 2) = +Dz*Dy/(L*Dxy) - DirCos(2, 3) = Dy/L - - DirCos(3, 1) = 0.0_ReKi - DirCos(3, 2) = -Dxy/L - DirCos(3, 3) = +Dz/L - ENDIF + DO I = 1, p%NReact*6 + row_n = Init%BCs(I, 1) + IF (Init%BCs(I, 2) == 1) THEN + Init%K(row_n,: )= 0 + Init%K(: ,row_n)= 0 + Init%K(row_n,row_n)= 1 -END SUBROUTINE GetDirCos + Init%M(row_n,: )= 0 + Init%M(: ,row_n)= 0 + Init%M(row_n,row_n)= 0 + ENDIF + ENDDO ! I, loop on reaction nodes +END SUBROUTINE ApplyConstr SUBROUTINE ElemM(ep, Me) @@ -1591,7 +1417,7 @@ SUBROUTINE ElemM(ep, Me) if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then Me=0.0_ReKi else - print*,'SD_FEM: Mass matrix for rigid members rho/=0 TODO' + print*,'FEM: Mass matrix for rigid members rho/=0 TODO' CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) !CALL ElemM_(A, L, rho, DirCos, Me) endif @@ -1628,362 +1454,4 @@ SUBROUTINE ElemF(ep, gravity, Fg, Fo) CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) END SUBROUTINE ElemF - - -!------------------------------------------------------------------------------------------------------ -!> Element stiffness matrix for classical beam elements -!! shear is true -- non-tapered Timoshenko beam -!! shear is false -- non-tapered Euler-Bernoulli beam -SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - LOGICAL , INTENT( IN) :: Shear - REAL(ReKi), INTENT(OUT) :: K(12, 12) - ! Local variables - REAL(ReKi) :: Ax, Ay, Kx, Ky - REAL(ReKi) :: DC(12, 12) - - Ax = kappa*A - Ay = kappa*A - - K(1:12,1:12) = 0 - - IF (Shear) THEN - Kx = 12.0*E*Iyy / (G*Ax*L*L) - Ky = 12.0*E*Ixx / (G*Ay*L*L) - ELSE - Kx = 0.0 - Ky = 0.0 - ENDIF - - K( 9, 9) = E*A/L - K( 7, 7) = 12.0*E*Iyy/( L*L*L*(1.0 + Kx) ) - K( 8, 8) = 12.0*E*Ixx/( L*L*L*(1.0 + Ky) ) - K(12, 12) = G*Jzz/L - K(10, 10) = (4.0 + Ky)*E*Ixx / ( L*(1.0+Ky) ) - K(11, 11) = (4.0 + Kx)*E*Iyy / ( L*(1.0+Kx) ) - K( 2, 4) = -6.*E*Ixx / ( L*L*(1.0+Ky) ) - K( 1, 5) = 6.*E*Iyy / ( L*L*(1.0+Kx) ) - K( 4, 10) = (2.0-Ky)*E*Ixx / ( L*(1.0+Ky) ) - K( 5, 11) = (2.0-Kx)*E*Iyy / ( L*(1.0+Kx) ) - - K( 3, 3) = K(9,9) - K( 1, 1) = K(7,7) - K( 2, 2) = K(8,8) - K( 6, 6) = K(12,12) - K( 4, 4) = K(10,10) - K(5,5) = K(11,11) - K(4,2) = K(2,4) - K(5,1) = K(1,5) - K(10,4) = K(4,10) - K(11,5) = K(5,11) - K(12,6)= -K(6,6) - K(10,2)= K(4,2) - K(11,1)= K(5,1) - K(9,3) = -K(3,3) - K(7,1) = -K(1,1) - K(8,2) = -K(2,2) - K(6, 12) = -K(6,6) - K(2, 10) = K(4,2) - K(1, 11) = K(5,1) - K(3, 9) = -K(3,3) - K(1, 7) = -K(1,1) - K(2, 8) = -K(2,2) - K(11,7) = -K(5,1) - K(10,8) = -K(4,2) - K(7,11) = -K(5,1) - K(8,10) = -K(4,2) - K(7,5) = -K(5,1) - K(5,7) = -K(5,1) - K(8,4) = -K(4,2) - K(4,8) = -K(4,2) - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed - -END SUBROUTINE ElemK_Beam -!------------------------------------------------------------------------------------------------------ -!> Element stiffness matrix for pretension cable -!! Element coordinate system: z along the cable! -SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) - REAL(ReKi), INTENT( IN) :: A, L, E - REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - REAL(ReKi), INTENT(OUT) :: K(12, 12) - ! Local variables - REAL(ReKi) :: L0, Eps0, EAL0, EE - REAL(ReKi) :: DC(12, 12) - - Eps0 = T0/(E*A) - L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 - EAL0 = E*A*L0 - EE = EAL0* Eps0/(1+Eps0) - - K(1:12,1:12)=0 - - ! Note: only translatoinal DOF involved (1-3, 7-9) - K(1,1)= EE - K(2,2)= EE - K(3,3)= EAL0 - - K(1,7)= -EE - K(2,8)= -EE - K(3,9)= -EAL0 - - K(7,1)= -EE - K(8,2)= -EE - K(9,3)= -EAL0 - - K(7,7)= EE - K(8,8)= EE - K(9,9)= EAL0 - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed -END SUBROUTINE ElemK_Cable -!------------------------------------------------------------------------------------------------------ -!> Element mass matrix for classical beam elements -SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - REAL(ReKi), INTENT(OUT) :: M(12, 12) - - REAL(ReKi) :: t, rx, ry, po - REAL(ReKi) :: DC(12, 12) - - t = rho*A*L; - rx = rho*Ixx; - ry = rho*Iyy; - po = rho*Jzz*L; - - M(1:12,1:12) = 0 - - M( 9, 9) = t/3.0 - M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) - M( 8, 8) = 13.0*t/35.0 + 6.0*rx/(5.0*L) - M(12, 12) = po/3.0 - M(10, 10) = t*L*L/105.0 + 2.0*L*rx/15.0 - M(11, 11) = t*L*L/105.0 + 2.0*L*ry/15.0 - M( 2, 4) = -11.0*t*L/210.0 - rx/10.0 - M( 1, 5) = 11.0*t*L/210.0 + ry/10.0 - M( 3, 9) = t/6.0 - M( 5, 7) = 13.*t*L/420. - ry/10. - M( 4, 8) = -13.*t*L/420. + rx/10. - M( 6, 12) = po/6. - M( 2, 10) = 13.*t*L/420. - rx/10. - M( 1, 11) = -13.*t*L/420. + ry/10. - M( 8, 10) = 11.*t*L/210. + rx/10. - M( 7, 11) = -11.*t*L/210. - ry/10. - M( 1, 7) = 9.*t/70. - 6.*ry/(5.*L) - M( 2, 8) = 9.*t/70. - 6.*rx/(5.*L) - M( 4, 10) = -L*L*t/140. - rx*L/30. - M( 5, 11) = -L*L*t/140. - ry*L/30. - - M( 3, 3) = M( 9, 9) - M( 1, 1) = M( 7, 7) - M( 2, 2) = M( 8, 8) - M( 6, 6) = M(12, 12) - M( 4, 4) = M(10, 10) - M( 5, 5) = M(11, 11) - M( 4, 2) = M( 2, 4) - M( 5, 1) = M( 1, 5) - M( 9, 3) = M( 3, 9) - M( 7, 5) = M( 5, 7) - M( 8, 4) = M( 4, 8) - M(12, 6) = M( 6, 12) - M(10, 2) = M( 2, 10) - M(11, 1) = M( 1, 11) - M(10, 8) = M( 8, 10) - M(11, 7) = M( 7, 11) - M( 7, 1) = M( 1, 7) - M( 8, 2) = M( 2, 8) - M(10, 4) = M( 4, 10) - M(11, 5) = M( 5, 11) - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed - -END SUBROUTINE ElemM_Beam - -!> Element stiffness matrix for pretension cable -SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) - REAL(ReKi), INTENT( IN) :: A, L, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) - REAL(ReKi), INTENT(OUT) :: M(12, 12) - ! Local variables - REAL(ReKi) :: DC(12, 12) - REAL(ReKi) :: t - - t = rho*A*L; - - M(1:12,1:12) = 0 - - M( 1, 1) = 13._ReKi/35._ReKi * t - M( 2, 2) = 13._ReKi/35._ReKi * t - M( 3, 3) = t/3.0_ReKi - - M( 7, 7) = 13._ReKi/35._ReKi * t - M( 8, 8) = 13._ReKi/35._ReKi * t - M( 9, 9) = t/3.0_ReKi - - M( 1, 7) = 9._ReKi/70._ReKi * t - M( 2, 8) = 9._ReKi/70._ReKi * t - M( 3, 9) = t/6.0_ReKi - - M( 7, 1) = 9._ReKi/70._ReKi * t - M( 8, 2) = 9._ReKi/70._ReKi * t - M( 9, 3) = t/6.0_ReKi - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed -END SUBROUTINE ElemM_Cable - - -!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices -SUBROUTINE ApplyConstr(Init,p) - TYPE(SD_InitType ),INTENT(INOUT):: Init - TYPE(SD_ParameterType),INTENT(IN ):: p - - INTEGER :: I !, J, k - INTEGER :: row_n !bgn_j, end_j, - - DO I = 1, p%NReact*6 - row_n = Init%BCs(I, 1) - IF (Init%BCs(I, 2) == 1) THEN - Init%K(row_n,: )= 0 - Init%K(: ,row_n)= 0 - Init%K(row_n,row_n)= 1 - - Init%M(row_n,: )= 0 - Init%M(: ,row_n)= 0 - Init%M(row_n,row_n)= 0 - ENDIF - ENDDO ! I, loop on reaction nodes -END SUBROUTINE ApplyConstr - -!------------------------------------------------------------------------------------------------------ -!> calculates the lumped forces and moments due to gravity on a given element: -!! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: -!! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, -!! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 -SUBROUTINE ElemG(A, L, rho, DirCos, F, g) - REAL(ReKi), INTENT( IN ) :: A !< area - REAL(ReKi), INTENT( IN ) :: L !< element length - REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix (for determining distance between nodes 1 and 2) - REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1; 7-12 are loads for node 2. - REAL(ReKi) :: TempCoeff - REAL(ReKi) :: w ! weight per unit length - - F = 0 ! initialize whole array to zero, then set the non-zero portions - w = rho*A*g ! weight per unit length - - ! lumped forces on both nodes (z component only): - F(3) = -0.5*L*w - F(9) = F(3) - - ! lumped moments on node 1 (x and y components only): - ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary - ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. - TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice - F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12. !bjj: DirCos(2,3) = Dy/L - F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12. !bjj: DirCos(1,3) = Dx/L - - ! lumped moments on node 2: (note the opposite sign of node 1 moment) - F(10) = -F(4) - F(11) = -F(5) - !F(12) is 0 for g along z alone - -END SUBROUTINE ElemG - -!> -SUBROUTINE ElemF_Cable(T0, DirCos, F) - REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. - ! Local variables - REAL(ReKi) :: DC(12, 12) - - F(1:12) = 0 ! init - F(3) = +T0 - F(9) = -T0 - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - F = MATMUL(DC, F)! TODO: change me if DirCos convention is transposed - -END SUBROUTINE ElemF_Cable - - - -!------------------------------------------------------------------------------------------------------ -!> Calculates the lumped gravity forces at the nodes given the element geometry -!! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 -!! bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. -SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) - REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !< X-sectional areas at node 1 and node 2, t2/t1 thickness ratio - REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( IN ) :: L !< Length of element - REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< Direction cosine matrix - REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces - !LOCALS - REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force - - !Calculate quadratic polynomial coefficients - a0 = a1 - print*,'Error: the function lumpforces is not ready to use' - STOP - - !Calculate quadratic polynomial coefficients - a0 = -99999 ! TODO: this is wrong - a2 = ( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. ! *x**2 - a1 = (Area2-Area1)/L -a2*L ! *x - - !Now calculate the Lumped Forces - F = 0 - F(3) = -(a0*L/2. +a1*L**2/6. +a2*L**3/12. )*rho*g !Forces along z (must be negative on earth) - F(9) = -(a0*L/2. +a1*L**2/3. +a2*L**3/4. )*rho*g !Forces along z (must be negative on earth) - - !Now calculate the Lumped Moments - !HERE TO BE COMPLETED FOR THE BELOW - TempCoeff = 1.0/12.0*g*L*L*rho*Area2 !RRD : I am changing this to >0 sign 6/10/13 - - !F(4) = TempCoeff*( DirCos(1, 3)*DirCos(2, 1) - DirCos(1, 1)*DirCos(2, 3) ) !These do not work if convnetion on z2>z1, x2>x1, y2>y1 are not followed as I have discovered 7/23 - !F(5) = TempCoeff*( DirCos(1, 3)*DirCos(2, 2) - DirCos(1, 2)*DirCos(2, 3) ) - - !RRD attempt at new dircos which keeps x in the X-Y plane - F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent - F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent - !RRD ends - F(10) = -F(4) - F(11) = -F(5) - !F(12) is 0 for g along z alone -END SUBROUTINE LumpForces - END MODULE SD_FEM From 6a3fdfaf1415cb0facab4878c454a17d7b191ddc Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 14:58:00 -0700 Subject: [PATCH 092/377] FlexSub: small reorganizing of SD_FEM --- modules/subdyn/src/SD_FEM.f90 | 198 ++++++++++++++++------------------ 1 file changed, 95 insertions(+), 103 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 34fa87072..7c4facec5 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -70,6 +70,8 @@ MODULE SD_FEM CONTAINS !------------------------------------------------------------------------------------------------------ +! --- Helper functions +!------------------------------------------------------------------------------------------------------ !> Maps nodes to elements !! allocate NodesConnE and NodesConnN SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) @@ -173,9 +175,56 @@ TYPE(IList) FUNCTION NodesList(p, Elements) enddo call print_list(NodesList, 'Joint list') END FUNCTION NodesList +!------------------------------------------------------------------------------------------------------ +!> Returns list of rigid link elements (Er) +TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, append + use IntegerList, only: print_list + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: ie !< Index on elements + ErrStat = ErrID_None + ErrMsg = "" + ! --- Establish a list of rigid link elements + call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); + do ie = 1, Init%NElem + if (p%ElemProps(ie)%eType == idMemberRigid) then + call append(RigidLinkElements, ie, ErrStat, ErrMsg); + endif + end do + call print_list(RigidLinkElements,'Rigid element list') +END FUNCTION RigidLinkElements -!---------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------------ +!> Returns true if one of the element connected to the node is a rigid link +LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) + INTEGER(IntKi), INTENT(IN ) :: iJoint + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + ! Local variables + integer(IntKi) :: ie !< Loop index on elements + integer(IntKi) :: ei !< Element index + integer(IntKi) :: m ! Number of elements connected to a joint + + NodeHasRigidElem = .False. ! default return value + + ! Loop through elements connected to node J + do ie = 1, Init%NodesConnE(iJoint, 1) + ei = Init%NodesConnE(iJoint, ie+1) + if (p%ElemProps(ei)%eType == idMemberRigid) then + NodeHasRigidElem = .True. + return ! we exit as soon as one rigid member is found + endif + enddo +END FUNCTION NodeHasRigidElem + +!------------------------------------------------------------------------------------------------------ +! --- Main routines, more or less listed in order in which they are called +!------------------------------------------------------------------------------------------------------ !> ! - Removes the notion of "ID" and use Index instead ! - Creates Nodes (use indices instead of ID), similar to Joints array @@ -520,63 +569,53 @@ SUBROUTINE CleanUp_Discrt() IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) END SUBROUTINE CleanUp_Discrt -END SUBROUTINE SD_Discrt - -!------------------------------------------------------------------------------------------------------ -!> Set properties of node k -SUBROUTINE SetNewNode(k, x, y, z, Init) - TYPE(SD_InitType), INTENT(INOUT) :: Init - INTEGER, INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: x, y, z + !> Set properties of node k + SUBROUTINE SetNewNode(k, x, y, z, Init) + TYPE(SD_InitType), INTENT(INOUT) :: Init + INTEGER, INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: x, y, z + Init%Nodes(k, 1) = k + Init%Nodes(k, 2) = x + Init%Nodes(k, 3) = y + Init%Nodes(k, 4) = z + Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever + ! Properties below are for non-cantilever joints + Init%Nodes(k, iJointDir:iJointDir+2) = -99999 + Init%Nodes(k, iJointStiff) = -99999 + Init%Nodes(k, iJointDamp) = -99999 + END SUBROUTINE SetNewNode - Init%Nodes(k, 1) = k - Init%Nodes(k, 2) = x - Init%Nodes(k, 3) = y - Init%Nodes(k, 4) = z - Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever - ! Properties below are for non-cantilever joints - Init%Nodes(k, iJointDir:iJointDir+2) = -99999 - Init%Nodes(k, iJointStiff) = -99999 - Init%Nodes(k, iJointDamp) = -99999 - -END SUBROUTINE SetNewNode + !> Set properties of element k + SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) + INTEGER, INTENT(IN ) :: k + INTEGER, INTENT(IN ) :: n1 + INTEGER, INTENT(IN ) :: n2 + INTEGER, INTENT(IN ) :: eType + INTEGER, INTENT(IN ) :: p1 + INTEGER, INTENT(IN ) :: p2 + TYPE(SD_ParameterType), INTENT(INOUT) :: p + p%Elems(k, 1) = k + p%Elems(k, 2) = n1 + p%Elems(k, 3) = n2 + p%Elems(k, iMProp ) = p1 + p%Elems(k, iMProp+1) = p2 + p%Elems(k, iMType) = eType + END SUBROUTINE SetNewElem + + !> Set material properties of element k, NOTE: this is only for a beam + SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) + INTEGER , INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: E, G, rho, d, t + REAL(ReKi), INTENT(INOUT):: TempProps(:, :) + TempProps(k, 1) = k + TempProps(k, 2) = E + TempProps(k, 3) = G + TempProps(k, 4) = rho + TempProps(k, 5) = d + TempProps(k, 6) = t + END SUBROUTINE SetNewProp -!------------------------------------------------------------------------------------------------------ -!> Set properties of element k -SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) - INTEGER, INTENT(IN ) :: k - INTEGER, INTENT(IN ) :: n1 - INTEGER, INTENT(IN ) :: n2 - INTEGER, INTENT(IN ) :: eType - INTEGER, INTENT(IN ) :: p1 - INTEGER, INTENT(IN ) :: p2 - TYPE(SD_ParameterType), INTENT(INOUT) :: p - - p%Elems(k, 1) = k - p%Elems(k, 2) = n1 - p%Elems(k, 3) = n2 - p%Elems(k, iMProp ) = p1 - p%Elems(k, iMProp+1) = p2 - p%Elems(k, iMType) = eType - -END SUBROUTINE SetNewElem - -!------------------------------------------------------------------------------------------------------ -!> Set material properties of element k -!! NOTE: this is only for a beam -SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) - INTEGER , INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: E, G, rho, d, t - REAL(ReKi), INTENT(INOUT):: TempProps(:, :) - - TempProps(k, 1) = k - TempProps(k, 2) = E - TempProps(k, 3) = G - TempProps(k, 4) = rho - TempProps(k, 5) = d - TempProps(k, 6) = t - -END SUBROUTINE SetNewProp +END SUBROUTINE SD_Discrt !------------------------------------------------------------------------------------------------------ !> Set Element properties p%ElemProps, different properties are set depening on element type.. @@ -1145,53 +1184,6 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() END FUNCTION nDOF_ConstraintReduced END SUBROUTINE DirectElimination - -!------------------------------------------------------------------------------------------------------ -!> Returns list of rigid link elements (Er) -TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, append - use IntegerList, only: print_list - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - integer(IntKi) :: ie !< Index on elements - ErrStat = ErrID_None - ErrMsg = "" - ! --- Establish a list of rigid link elements - call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); - - do ie = 1, Init%NElem - if (p%ElemProps(ie)%eType == idMemberRigid) then - call append(RigidLinkElements, ie, ErrStat, ErrMsg); - endif - end do - call print_list(RigidLinkElements,'Rigid element list') -END FUNCTION RigidLinkElements - -!------------------------------------------------------------------------------------------------------ -!> Returns true if one of the element connected to the node is a rigid link -LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) - INTEGER(IntKi), INTENT(IN ) :: iJoint - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - ! Local variables - integer(IntKi) :: ie !< Loop index on elements - integer(IntKi) :: ei !< Element index - integer(IntKi) :: m ! Number of elements connected to a joint - - NodeHasRigidElem = .False. ! default return value - - ! Loop through elements connected to node J - do ie = 1, Init%NodesConnE(iJoint, 1) - ei = Init%NodesConnE(iJoint, ie+1) - if (p%ElemProps(ei)%eType == idMemberRigid) then - NodeHasRigidElem = .True. - return ! we exit as soon as one rigid member is found - endif - enddo -END FUNCTION NodeHasRigidElem !------------------------------------------------------------------------------------------------------ !> Returns constrains matrix for a rigid assembly (RA) formed by a set of elements. !! From 2a3e9ce82667b7e87fe855049453e583fed32452 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 23 Dec 2019 15:18:35 -0700 Subject: [PATCH 093/377] FlexSub: system reduction implemented (only for full cantilever..) --- modules/subdyn/src/SD_FEM.f90 | 97 ++++++++++++-------------- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 65 +++++++++++++++++ 3 files changed, 112 insertions(+), 51 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 7c4facec5..b497a6114 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -985,65 +985,69 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) ! Varaibles for rigid assembly type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA ! - real(ReKi), dimension(:,:), allocatable :: T real(ReKi), dimension(:,:), allocatable :: MM, KK + real(ReKi), dimension(:), allocatable :: FF integer(IntKi) :: nDOF - - ErrStat = ErrID_None ErrMsg = "" - call RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat2, ErrMsg2); if(Failed()) return + call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - - call BuildTMatrix(); if (Failed()) return + call BuildTMatrix(m%Tred); if (Failed()) return ! --- DOF elimination for system matrices and RHS vector ! Temporary backup of M and K of full system - !call move_alloc(Init%M, Init%M) - !call move_alloc(Init%K, Init%K) - !! Reallocating - !nDOF = size(T,2) - !CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - !CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - !CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - - deallocate(RAm1) - deallocate(RA) - deallocate(njRA) + call move_alloc(Init%M, MM) + call move_alloc(Init%K, KK) + call move_alloc(Init%FG, FF) + ! Reallocating + nDOF = size(m%Tred,2) + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + ! Elimination + Init%M = matmul(transpose(m%Tred), matmul(MM, m%Tred)) + Init%K = matmul(transpose(m%Tred), matmul(KK, m%Tred)) + Init%FG = matmul(transpose(m%Tred), FF) + + call CleanUp_DirectElimination() CONTAINS LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'DirectElimination') Failed = ErrStat >= AbortErrLev - !if (Failed) call Cleanup_AssembleKM() + if (Failed) call CleanUp_DirectElimination() END FUNCTION Failed !SUBROUTINE Fatal(ErrMsg_in) ! character(len=*), intent(in) :: ErrMsg_in - ! CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'DirectElimination'); - ! CALL CleanUp_DirectElimination() + ! call SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'DirectElimination'); + ! call CleanUp_DirectElimination() !END SUBROUTINE Fatal - !SUBROUTINE CleanUp_DirectElimination() - !pass - !END SUBROUTINE CleanUp_DirectElimination - - SUBROUTINE BuildTMatrix() + SUBROUTINE CleanUp_DirectElimination() + ! Cleaning up memory + if (allocated(MM )) deallocate(MM ) + if (allocated(KK )) deallocate(KK ) + if (allocated(FF )) deallocate(FF ) + if (allocated(RA )) deallocate(RA ) + if (allocated(RAm1)) deallocate(RAm1) + if (allocated(RA )) deallocate(RA ) + END SUBROUTINE CleanUp_DirectElimination + + SUBROUTINE BuildTMatrix(Tred) ! Variables for Building T use IntegerList, only: init_list, find, pop, destroy_list, len use IntegerList, only: print_list - !real(ReKi), dimension(:,:), allocatable :: T - real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 - integer(IntKi), dimension(:), allocatable :: Elements !< List of elements + real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination real(ReKi), dimension(:,:), allocatable :: Tc integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements integer(IntKi), dimension(:), allocatable :: IDOFOld !< integer(IntKi), dimension(:), pointer :: IDOFNew !< + real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 integer(IntKi) :: iPrev - type(IList) :: IRA + type(IList) :: IRA !< list of rigid assembly indices to process integer(IntKi) :: nDOF integer(IntKi) :: aID, ia ! assembly ID, and index in IRA integer(IntKi) :: iNode @@ -1055,23 +1059,21 @@ SUBROUTINE BuildTMatrix() nullify(IDOFNew) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2) ! Indices of DOF for each joint, in reduced system - nDOF = nDOF_ConstraintReduced() print*,'nDOF constraint elim', nDOF - allocate(T(1:Init%TDOF, 1:nDOF)) - T=0 - iPrev =0 + CALL AllocAry( m%Tred, nDOF, nDOF, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + Tred=0 call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) call print_list(IRA, 'List of RA indices') - print*,'------------------ BUILD T ----------------------------------' ! --- For each node: ! - create list of indices I in the assembled vector of DOF ! - create list of indices Itilde in the reduced vector of DOF + ! - increment iPrev by the number of DOF of Itilde + iPrev =0 do iNode = 1, Init%NNode nc=0 if (allocated(Tc)) deallocate(Tc) @@ -1124,21 +1126,24 @@ SUBROUTINE BuildTMatrix() IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations !print*,'N',iNode,'I ',IDOFOld !print*,'N',iNode,'It',IDOFNew - T(IDOFOld, IDOFNew) = Tc + Tred(IDOFOld, IDOFNew) = Tc iPrev = iPrev + nc else print*,'Error, Tc not allocated, TODO' STOP endif enddo - deallocate(T) - nullify(IDOFNew) ! --- Safety checks if (len(IRA)>0) then ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal endif + ! --- Cleanup + nullify(IDOFNew) call destroy_list(IRA, ErrStat2, ErrMsg2) + if (allocated(Tc) ) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + if (allocated(INodesID)) deallocate(INodesID) END SUBROUTINE BuildTMatrix @@ -1215,6 +1220,7 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) ! --- List of nodes stored first in LINodes than moved to INodes LNodesID = NodesList(p, Elements) + if (allocated(INodesID)) deallocate(INodesID) call move_alloc(LNodesID%List, INodesID) call destroy_list(LNodesID, ErrStat2, ErrMsg2) print*,'Nodes involved in assembly (befr) ',INodesID @@ -1266,14 +1272,13 @@ END SUBROUTINE RAElimination !------------------------------------------------------------------------------------------------------ !> Setup a list of rigid link assemblies (RA) -SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) +SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), allocatable :: njRA !< Number of joints per RA integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly ! Local variables type(IList) :: Er !< List of rigid elements @@ -1323,16 +1328,6 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, njRA, ErrStat, ErrMsg) do ia = 1, nRA call print_list(RA(ia),'Rigid assembly') enddo - - ! --- Counting unique joints involved in Rigid assembly - allocate(njRA(1:nRA)) - do ia = 1, nRA - ! Getting list of nodes involved in RA(ia) - Er = NodesList(p, RA(ia)%List) - njRA(ia) = len(Er) - call destroy_list(Er, ErrStat2, ErrMsg2) - enddo - print*,'njRA',njRA CONTAINS !> The neighbors of e0 (that are found within the list Er) are added to the list Ea RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index f37970bcc..b32c192ab 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -155,6 +155,7 @@ typedef ^ ^ IntKi Decimat - - - typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" +typedef ^ ^ ReKi Tred {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index b8bebc0ab..6361d103e 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -199,6 +199,7 @@ MODULE SubDyn_Types TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Tred !< Transformation matrix performing the constraint reduction x = T. xtilde [-] END TYPE SD_MiscVarType ! ======================= ! ========= SD_ParameterType ======= @@ -5483,6 +5484,20 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF END IF DstMiscData%ElemsDOF = SrcMiscData%ElemsDOF +ENDIF +IF (ALLOCATED(SrcMiscData%Tred)) THEN + i1_l = LBOUND(SrcMiscData%Tred,1) + i1_u = UBOUND(SrcMiscData%Tred,1) + i2_l = LBOUND(SrcMiscData%Tred,2) + i2_u = UBOUND(SrcMiscData%Tred,2) + IF (.NOT. ALLOCATED(DstMiscData%Tred)) THEN + ALLOCATE(DstMiscData%Tred(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Tred.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Tred = SrcMiscData%Tred ENDIF END SUBROUTINE SD_CopyMisc @@ -5536,6 +5551,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDIF IF (ALLOCATED(MiscData%ElemsDOF)) THEN DEALLOCATE(MiscData%ElemsDOF) +ENDIF +IF (ALLOCATED(MiscData%Tred)) THEN + DEALLOCATE(MiscData%Tred) ENDIF END SUBROUTINE SD_DestroyMisc @@ -5676,6 +5694,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF END IF + Int_BufSz = Int_BufSz + 1 ! Tred allocated yes/no + IF ( ALLOCATED(InData%Tred) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Tred upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Tred) ! Tred + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5928,6 +5951,22 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) END IF + IF ( .NOT. ALLOCATED(InData%Tred) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Tred,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tred,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Tred,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tred,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Tred)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Tred))-1 ) = PACK(InData%Tred,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Tred) + END IF END SUBROUTINE SD_PackMisc SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -6346,6 +6385,32 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Tred not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Tred)) DEALLOCATE(OutData%Tred) + ALLOCATE(OutData%Tred(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Tred.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Tred)>0) OutData%Tred = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Tred))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Tred) + DEALLOCATE(mask2) + END IF END SUBROUTINE SD_UnPackMisc SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) From f1b0f6210036c2ccced66d3da31abf22c0e0d70c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 23 Dec 2019 16:44:49 -0700 Subject: [PATCH 094/377] TCF: move WAMIT2 outputs to HD glue code --- modules/hydrodyn/src/HydroDyn.f90 | 14 +- .../src/HydroDynOutListParameters.xlsx | Bin 94610 -> 96983 bytes modules/hydrodyn/src/HydroDyn_Output.f90 | 487 +++++++++++------- 3 files changed, 292 insertions(+), 209 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 71cf5d6af..5001826bd 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1933,6 +1933,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, #endif REAL(ReKi) :: WaveElev (p%NWaveElev) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi) :: WaveElev1(p%NWaveElev) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi) :: WaveElev2(p%NWaveElev) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi) :: q(6*p%NBody), qdot(6*p%NBody), qdotsq(6*p%NBody), qdotdot(6*p%NBody) REAL(ReKi) :: rotdisp(3) ! small angle rotational displacements @@ -2006,7 +2007,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, end if m%F_Waves = 0.0_ReKi - + if ( m%u_WAMIT(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then @@ -2105,6 +2106,8 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Compute the wave elevations at the requested output locations for this time. Note that p%WaveElev has the second order added to it already. DO I=1,p%NWaveElev + WaveElev2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%Waves2%WaveElev2(:,I), & + m%LastIndWave, p%NStepWave + 1 ) WaveElev1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev1(:,I), & m%LastIndWave, p%NStepWave + 1 ) WaveElev(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev(:,I), & @@ -2125,7 +2128,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Map calculated results into the AllOuts Array - CALL HDOut_MapOutputs( Time, p, y, m%WAMIT, p%NWaveElev, WaveElev, WaveElev1, m%F_PtfmAdd, m%F_Waves, m%F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat2, ErrMsg2 ) + CALL HDOut_MapOutputs( Time, p, y, m%WAMIT, m%WAMIT2, p%NWaveElev, WaveElev, WaveElev1, WaveElev2, m%F_PtfmAdd, m%F_Waves, m%F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) DO I = 1,p%NumOuts @@ -2145,13 +2148,6 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, END DO END IF - IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN - DO I=1, p%WAMIT2%NumOuts - y%WriteOutput(J) = y%WAMIT2%WriteOutput(I) - J = J + 1 - END DO - END IF - IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN DO I=1, p%Morison%NumOuts y%WriteOutput(J) = y%Morison%WriteOutput(I) diff --git a/modules/hydrodyn/src/HydroDynOutListParameters.xlsx b/modules/hydrodyn/src/HydroDynOutListParameters.xlsx index d7aa4b51625f42283cb62fdb059689f7ed0b4967..dee38a4d297bfa73dc9c585e4410956b0d2b51b1 100644 GIT binary patch literal 96983 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 z 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 diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index d5858add0..24a472d0a 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -34,7 +34,7 @@ MODULE HydroDyn_Output ! using the parameters listed in the "HydroDynOutListParameters.xlsx" Excel file. Any changes to these ! lines should be modified in the Matlab script and/or Excel worksheet as necessary. ! =================================================================================================== -! This code was generated by Write_ChckOutLst.m at 22-Sep-2019 15:01:11. +! This code was generated by Write_ChckOutLst.m at 23-Dec-2019 15:23:54. ! Parameters related to output length (number of characters allowed in the output data headers): @@ -500,35 +500,99 @@ MODULE HydroDyn_Output INTEGER(IntKi), PARAMETER :: B9RdtMxi = 436 INTEGER(IntKi), PARAMETER :: B9RdtMyi = 437 INTEGER(IntKi), PARAMETER :: B9RdtMzi = 438 + INTEGER(IntKi), PARAMETER :: B1WvsF2xi = 439 + INTEGER(IntKi), PARAMETER :: B1WvsF2yi = 440 + INTEGER(IntKi), PARAMETER :: B1WvsF2zi = 441 + INTEGER(IntKi), PARAMETER :: B1WvsM2xi = 442 + INTEGER(IntKi), PARAMETER :: B1WvsM2yi = 443 + INTEGER(IntKi), PARAMETER :: B1WvsM2zi = 444 + INTEGER(IntKi), PARAMETER :: B2WvsF2xi = 445 + INTEGER(IntKi), PARAMETER :: B2WvsF2yi = 446 + INTEGER(IntKi), PARAMETER :: B2WvsF2zi = 447 + INTEGER(IntKi), PARAMETER :: B2WvsM2xi = 448 + INTEGER(IntKi), PARAMETER :: B2WvsM2yi = 449 + INTEGER(IntKi), PARAMETER :: B2WvsM2zi = 450 + INTEGER(IntKi), PARAMETER :: B3WvsF2xi = 451 + INTEGER(IntKi), PARAMETER :: B3WvsF2yi = 452 + INTEGER(IntKi), PARAMETER :: B3WvsF2zi = 453 + INTEGER(IntKi), PARAMETER :: B3WvsM2xi = 454 + INTEGER(IntKi), PARAMETER :: B3WvsM2yi = 455 + INTEGER(IntKi), PARAMETER :: B3WvsM2zi = 456 + INTEGER(IntKi), PARAMETER :: B4WvsF2xi = 457 + INTEGER(IntKi), PARAMETER :: B4WvsF2yi = 458 + INTEGER(IntKi), PARAMETER :: B4WvsF2zi = 459 + INTEGER(IntKi), PARAMETER :: B4WvsM2xi = 460 + INTEGER(IntKi), PARAMETER :: B4WvsM2yi = 461 + INTEGER(IntKi), PARAMETER :: B4WvsM2zi = 462 + INTEGER(IntKi), PARAMETER :: B5WvsF2xi = 463 + INTEGER(IntKi), PARAMETER :: B5WvsF2yi = 464 + INTEGER(IntKi), PARAMETER :: B5WvsF2zi = 465 + INTEGER(IntKi), PARAMETER :: B5WvsM2xi = 466 + INTEGER(IntKi), PARAMETER :: B5WvsM2yi = 467 + INTEGER(IntKi), PARAMETER :: B5WvsM2zi = 468 + INTEGER(IntKi), PARAMETER :: B6WvsF2xi = 469 + INTEGER(IntKi), PARAMETER :: B6WvsF2yi = 470 + INTEGER(IntKi), PARAMETER :: B6WvsF2zi = 471 + INTEGER(IntKi), PARAMETER :: B6WvsM2xi = 472 + INTEGER(IntKi), PARAMETER :: B6WvsM2yi = 473 + INTEGER(IntKi), PARAMETER :: B6WvsM2zi = 474 + INTEGER(IntKi), PARAMETER :: B7WvsF2xi = 475 + INTEGER(IntKi), PARAMETER :: B7WvsF2yi = 476 + INTEGER(IntKi), PARAMETER :: B7WvsF2zi = 477 + INTEGER(IntKi), PARAMETER :: B7WvsM2xi = 478 + INTEGER(IntKi), PARAMETER :: B7WvsM2yi = 479 + INTEGER(IntKi), PARAMETER :: B7WvsM2zi = 480 + INTEGER(IntKi), PARAMETER :: B8WvsF2xi = 481 + INTEGER(IntKi), PARAMETER :: B8WvsF2yi = 482 + INTEGER(IntKi), PARAMETER :: B8WvsF2zi = 483 + INTEGER(IntKi), PARAMETER :: B8WvsM2xi = 484 + INTEGER(IntKi), PARAMETER :: B8WvsM2yi = 485 + INTEGER(IntKi), PARAMETER :: B8WvsM2zi = 486 + INTEGER(IntKi), PARAMETER :: B9WvsF2xi = 487 + INTEGER(IntKi), PARAMETER :: B9WvsF2yi = 488 + INTEGER(IntKi), PARAMETER :: B9WvsF2zi = 489 + INTEGER(IntKi), PARAMETER :: B9WvsM2xi = 490 + INTEGER(IntKi), PARAMETER :: B9WvsM2yi = 491 + INTEGER(IntKi), PARAMETER :: B9WvsM2zi = 492 ! Wave Elevations: - INTEGER(IntKi), PARAMETER :: Wave1Elev = 439 - INTEGER(IntKi), PARAMETER :: Wave2Elev = 440 - INTEGER(IntKi), PARAMETER :: Wave3Elev = 441 - INTEGER(IntKi), PARAMETER :: Wave4Elev = 442 - INTEGER(IntKi), PARAMETER :: Wave5Elev = 443 - INTEGER(IntKi), PARAMETER :: Wave6Elev = 444 - INTEGER(IntKi), PARAMETER :: Wave7Elev = 445 - INTEGER(IntKi), PARAMETER :: Wave8Elev = 446 - INTEGER(IntKi), PARAMETER :: Wave9Elev = 447 - INTEGER(IntKi), PARAMETER :: Wave1Elv1 = 448 - INTEGER(IntKi), PARAMETER :: Wave2Elv1 = 449 - INTEGER(IntKi), PARAMETER :: Wave3Elv1 = 450 - INTEGER(IntKi), PARAMETER :: Wave4Elv1 = 451 - INTEGER(IntKi), PARAMETER :: Wave5Elv1 = 452 - INTEGER(IntKi), PARAMETER :: Wave6Elv1 = 453 - INTEGER(IntKi), PARAMETER :: Wave7Elv1 = 454 - INTEGER(IntKi), PARAMETER :: Wave8Elv1 = 455 - INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 456 - - + INTEGER(IntKi), PARAMETER :: Wave1Elev = 493 + INTEGER(IntKi), PARAMETER :: Wave2Elev = 494 + INTEGER(IntKi), PARAMETER :: Wave3Elev = 495 + INTEGER(IntKi), PARAMETER :: Wave4Elev = 496 + INTEGER(IntKi), PARAMETER :: Wave5Elev = 497 + INTEGER(IntKi), PARAMETER :: Wave6Elev = 498 + INTEGER(IntKi), PARAMETER :: Wave7Elev = 499 + INTEGER(IntKi), PARAMETER :: Wave8Elev = 500 + INTEGER(IntKi), PARAMETER :: Wave9Elev = 501 + INTEGER(IntKi), PARAMETER :: Wave1Elv1 = 502 + INTEGER(IntKi), PARAMETER :: Wave2Elv1 = 503 + INTEGER(IntKi), PARAMETER :: Wave3Elv1 = 504 + INTEGER(IntKi), PARAMETER :: Wave4Elv1 = 505 + INTEGER(IntKi), PARAMETER :: Wave5Elv1 = 506 + INTEGER(IntKi), PARAMETER :: Wave6Elv1 = 507 + INTEGER(IntKi), PARAMETER :: Wave7Elv1 = 508 + INTEGER(IntKi), PARAMETER :: Wave8Elv1 = 509 + INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 510 + INTEGER(IntKi), PARAMETER :: Wave1Elv2 = 511 + INTEGER(IntKi), PARAMETER :: Wave2Elv2 = 512 + INTEGER(IntKi), PARAMETER :: Wave3Elv2 = 513 + INTEGER(IntKi), PARAMETER :: Wave4Elv2 = 514 + INTEGER(IntKi), PARAMETER :: Wave5Elv2 = 515 + INTEGER(IntKi), PARAMETER :: Wave6Elv2 = 516 + INTEGER(IntKi), PARAMETER :: Wave7Elv2 = 517 + INTEGER(IntKi), PARAMETER :: Wave8Elv2 = 518 + INTEGER(IntKi), PARAMETER :: Wave9Elv2 = 519 + + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi), PARAMETER :: MaxOutPts = 519 !End of code generated by Matlab script ! =================================================================================================== - REAL(ReKi) :: AllOuts(MaxHDOutputs) ! Array of all possible outputs @@ -550,6 +614,13 @@ MODULE HydroDyn_Output B1WvsM1yi,B2WvsM1yi,B3WvsM1yi,B4WvsM1yi,B5WvsM1yi,B6WvsM1yi,B7WvsM1yi,B8WvsM1yi,B9WvsM1yi, & B1WvsM1zi,B2WvsM1zi,B3WvsM1zi,B4WvsM1zi,B5WvsM1zi,B6WvsM1zi,B7WvsM1zi,B8WvsM1zi,B9WvsM1zi/), & (/9,6/))) + INTEGER, PARAMETER :: FWaves2(6,9) = transpose(reshape((/B1WvsF2xi,B2WvsF2xi,B3WvsF2xi,B4WvsF2xi,B5WvsF2xi,B6WvsF2xi,B7WvsF2xi,B8WvsF2xi,B9WvsF2xi, & + B1WvsF2yi,B2WvsF2yi,B3WvsF2yi,B4WvsF2yi,B5WvsF2yi,B6WvsF2yi,B7WvsF2yi,B8WvsF2yi,B9WvsF2yi, & + B1WvsF2zi,B2WvsF2zi,B3WvsF2zi,B4WvsF2zi,B5WvsF2zi,B6WvsF2zi,B7WvsF2zi,B8WvsF2zi,B9WvsF2zi, & + B1WvsM2xi,B2WvsM2xi,B3WvsM2xi,B4WvsM2xi,B5WvsM2xi,B6WvsM2xi,B7WvsM2xi,B8WvsM2xi,B9WvsM2xi, & + B1WvsM2yi,B2WvsM2yi,B3WvsM2yi,B4WvsM2yi,B5WvsM2yi,B6WvsM2yi,B7WvsM2yi,B8WvsM2yi,B9WvsM2yi, & + B1WvsM2zi,B2WvsM2zi,B3WvsM2zi,B4WvsM2zi,B5WvsM2zi,B6WvsM2zi,B7WvsM2zi,B8WvsM2zi,B9WvsM2zi/), & + (/9,6/))) INTEGER, PARAMETER :: FWavesTot(6,9)= transpose(reshape((/B1WvsFxi,B2WvsFxi,B3WvsFxi,B4WvsFxi,B5WvsFxi,B6WvsFxi,B7WvsFxi,B8WvsFxi,B9WvsFxi, & B1WvsFyi,B2WvsFyi,B3WvsFyi,B4WvsFyi,B5WvsFyi,B6WvsFyi,B7WvsFyi,B8WvsFyi,B9WvsFyi, & B1WvsFzi,B2WvsFzi,B3WvsFzi,B4WvsFzi,B5WvsFzi,B6WvsFzi,B7WvsFzi,B8WvsFzi,B9WvsFzi, & @@ -598,207 +669,235 @@ MODULE HydroDyn_Output INTEGER, PARAMETER :: WaveElevi(9) = (/Wave1Elev,Wave2Elev,Wave3Elev,Wave4Elev,Wave5Elev,Wave6Elev,Wave7Elev,Wave8Elev,Wave9Elev/) INTEGER, PARAMETER :: WaveElevi1(9) = (/Wave1Elv1,Wave2Elv1,Wave3Elv1,Wave4Elv1,Wave5Elv1,Wave6Elv1,Wave7Elv1,Wave8Elv1,Wave9Elv1/) + INTEGER, PARAMETER :: WaveElevi2(9) = (/Wave1Elv2,Wave2Elv2,Wave3Elv2,Wave4Elv2,Wave5Elv2,Wave6Elv2,Wave7Elv2,Wave8Elv2,Wave9Elv2/) - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(456) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(519) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically "B1ADDFXI ","B1ADDFYI ","B1ADDFZI ","B1ADDMXI ","B1ADDMYI ","B1ADDMZI ","B1HDSFXI ", & "B1HDSFYI ","B1HDSFZI ","B1HDSMXI ","B1HDSMYI ","B1HDSMZI ","B1HEAVE ","B1PITCH ", & "B1RAXI ","B1RAYI ","B1RAZI ","B1RDTFXI ","B1RDTFYI ","B1RDTFZI ","B1RDTMXI ", & "B1RDTMYI ","B1RDTMZI ","B1ROLL ","B1RVXI ","B1RVYI ","B1RVZI ","B1SURGE ", & "B1SWAY ","B1TAXI ","B1TAYI ","B1TAZI ","B1TVXI ","B1TVYI ","B1TVZI ", & - "B1WVSF1XI","B1WVSF1YI","B1WVSF1ZI","B1WVSFXI ","B1WVSFYI ","B1WVSFZI ","B1WVSM1XI", & - "B1WVSM1YI","B1WVSM1ZI","B1WVSMXI ","B1WVSMYI ","B1WVSMZI ","B1YAW ","B2ADDFXI ", & - "B2ADDFYI ","B2ADDFZI ","B2ADDMXI ","B2ADDMYI ","B2ADDMZI ","B2HDSFXI ","B2HDSFYI ", & - "B2HDSFZI ","B2HDSMXI ","B2HDSMYI ","B2HDSMZI ","B2HEAVE ","B2PITCH ","B2RAXI ", & - "B2RAYI ","B2RAZI ","B2RDTFXI ","B2RDTFYI ","B2RDTFZI ","B2RDTMXI ","B2RDTMYI ", & - "B2RDTMZI ","B2ROLL ","B2RVXI ","B2RVYI ","B2RVZI ","B2SURGE ","B2SWAY ", & - "B2TAXI ","B2TAYI ","B2TAZI ","B2TVXI ","B2TVYI ","B2TVZI ","B2WVSF1XI", & - "B2WVSF1YI","B2WVSF1ZI","B2WVSFXI ","B2WVSFYI ","B2WVSFZI ","B2WVSM1XI","B2WVSM1YI", & - "B2WVSM1ZI","B2WVSMXI ","B2WVSMYI ","B2WVSMZI ","B2YAW ","B3ADDFXI ","B3ADDFYI ", & - "B3ADDFZI ","B3ADDMXI ","B3ADDMYI ","B3ADDMZI ","B3HDSFXI ","B3HDSFYI ","B3HDSFZI ", & - "B3HDSMXI ","B3HDSMYI ","B3HDSMZI ","B3HEAVE ","B3PITCH ","B3RAXI ","B3RAYI ", & - "B3RAZI ","B3RDTFXI ","B3RDTFYI ","B3RDTFZI ","B3RDTMXI ","B3RDTMYI ","B3RDTMZI ", & - "B3ROLL ","B3RVXI ","B3RVYI ","B3RVZI ","B3SURGE ","B3SWAY ","B3TAXI ", & - "B3TAYI ","B3TAZI ","B3TVXI ","B3TVYI ","B3TVZI ","B3WVSF1XI","B3WVSF1YI", & - "B3WVSF1ZI","B3WVSFXI ","B3WVSFYI ","B3WVSFZI ","B3WVSM1XI","B3WVSM1YI","B3WVSM1ZI", & - "B3WVSMXI ","B3WVSMYI ","B3WVSMZI ","B3YAW ","B4ADDFXI ","B4ADDFYI ","B4ADDFZI ", & - "B4ADDMXI ","B4ADDMYI ","B4ADDMZI ","B4HDSFXI ","B4HDSFYI ","B4HDSFZI ","B4HDSMXI ", & - "B4HDSMYI ","B4HDSMZI ","B4HEAVE ","B4PITCH ","B4RAXI ","B4RAYI ","B4RAZI ", & - "B4RDTFXI ","B4RDTFYI ","B4RDTFZI ","B4RDTMXI ","B4RDTMYI ","B4RDTMZI ","B4ROLL ", & - "B4RVXI ","B4RVYI ","B4RVZI ","B4SURGE ","B4SWAY ","B4TAXI ","B4TAYI ", & - "B4TAZI ","B4TVXI ","B4TVYI ","B4TVZI ","B4WVSF1XI","B4WVSF1YI","B4WVSF1ZI", & - "B4WVSFXI ","B4WVSFYI ","B4WVSFZI ","B4WVSM1XI","B4WVSM1YI","B4WVSM1ZI","B4WVSMXI ", & - "B4WVSMYI ","B4WVSMZI ","B4YAW ","B5ADDFXI ","B5ADDFYI ","B5ADDFZI ","B5ADDMXI ", & - "B5ADDMYI ","B5ADDMZI ","B5HDSFXI ","B5HDSFYI ","B5HDSFZI ","B5HDSMXI ","B5HDSMYI ", & - "B5HDSMZI ","B5HEAVE ","B5PITCH ","B5RAXI ","B5RAYI ","B5RAZI ","B5RDTFXI ", & - "B5RDTFYI ","B5RDTFZI ","B5RDTMXI ","B5RDTMYI ","B5RDTMZI ","B5ROLL ","B5RVXI ", & - "B5RVYI ","B5RVZI ","B5SURGE ","B5SWAY ","B5TAXI ","B5TAYI ","B5TAZI ", & - "B5TVXI ","B5TVYI ","B5TVZI ","B5WVSF1XI","B5WVSF1YI","B5WVSF1ZI","B5WVSFXI ", & - "B5WVSFYI ","B5WVSFZI ","B5WVSM1XI","B5WVSM1YI","B5WVSM1ZI","B5WVSMXI ","B5WVSMYI ", & - "B5WVSMZI ","B5YAW ","B6ADDFXI ","B6ADDFYI ","B6ADDFZI ","B6ADDMXI ","B6ADDMYI ", & - "B6ADDMZI ","B6HDSFXI ","B6HDSFYI ","B6HDSFZI ","B6HDSMXI ","B6HDSMYI ","B6HDSMZI ", & - "B6HEAVE ","B6PITCH ","B6RAXI ","B6RAYI ","B6RAZI ","B6RDTFXI ","B6RDTFYI ", & - "B6RDTFZI ","B6RDTMXI ","B6RDTMYI ","B6RDTMZI ","B6ROLL ","B6RVXI ","B6RVYI ", & - "B6RVZI ","B6SURGE ","B6SWAY ","B6TAXI ","B6TAYI ","B6TAZI ","B6TVXI ", & - "B6TVYI ","B6TVZI ","B6WVSF1XI","B6WVSF1YI","B6WVSF1ZI","B6WVSFXI ","B6WVSFYI ", & - "B6WVSFZI ","B6WVSM1XI","B6WVSM1YI","B6WVSM1ZI","B6WVSMXI ","B6WVSMYI ","B6WVSMZI ", & - "B6YAW ","B7ADDFXI ","B7ADDFYI ","B7ADDFZI ","B7ADDMXI ","B7ADDMYI ","B7ADDMZI ", & - "B7HDSFXI ","B7HDSFYI ","B7HDSFZI ","B7HDSMXI ","B7HDSMYI ","B7HDSMZI ","B7HEAVE ", & - "B7PITCH ","B7RAXI ","B7RAYI ","B7RAZI ","B7RDTFXI ","B7RDTFYI ","B7RDTFZI ", & - "B7RDTMXI ","B7RDTMYI ","B7RDTMZI ","B7ROLL ","B7RVXI ","B7RVYI ","B7RVZI ", & - "B7SURGE ","B7SWAY ","B7TAXI ","B7TAYI ","B7TAZI ","B7TVXI ","B7TVYI ", & - "B7TVZI ","B7WVSF1XI","B7WVSF1YI","B7WVSF1ZI","B7WVSFXI ","B7WVSFYI ","B7WVSFZI ", & - "B7WVSM1XI","B7WVSM1YI","B7WVSM1ZI","B7WVSMXI ","B7WVSMYI ","B7WVSMZI ","B7YAW ", & + "B1WVSF1XI","B1WVSF1YI","B1WVSF1ZI","B1WVSF2XI","B1WVSF2YI","B1WVSF2ZI","B1WVSFXI ", & + "B1WVSFYI ","B1WVSFZI ","B1WVSM1XI","B1WVSM1YI","B1WVSM1ZI","B1WVSM2XI","B1WVSM2YI", & + "B1WVSM2ZI","B1WVSMXI ","B1WVSMYI ","B1WVSMZI ","B1YAW ","B2ADDFXI ","B2ADDFYI ", & + "B2ADDFZI ","B2ADDMXI ","B2ADDMYI ","B2ADDMZI ","B2HDSFXI ","B2HDSFYI ","B2HDSFZI ", & + "B2HDSMXI ","B2HDSMYI ","B2HDSMZI ","B2HEAVE ","B2PITCH ","B2RAXI ","B2RAYI ", & + "B2RAZI ","B2RDTFXI ","B2RDTFYI ","B2RDTFZI ","B2RDTMXI ","B2RDTMYI ","B2RDTMZI ", & + "B2ROLL ","B2RVXI ","B2RVYI ","B2RVZI ","B2SURGE ","B2SWAY ","B2TAXI ", & + "B2TAYI ","B2TAZI ","B2TVXI ","B2TVYI ","B2TVZI ","B2WVSF1XI","B2WVSF1YI", & + "B2WVSF1ZI","B2WVSF2XI","B2WVSF2YI","B2WVSF2ZI","B2WVSFXI ","B2WVSFYI ","B2WVSFZI ", & + "B2WVSM1XI","B2WVSM1YI","B2WVSM1ZI","B2WVSM2XI","B2WVSM2YI","B2WVSM2ZI","B2WVSMXI ", & + "B2WVSMYI ","B2WVSMZI ","B2YAW ","B3ADDFXI ","B3ADDFYI ","B3ADDFZI ","B3ADDMXI ", & + "B3ADDMYI ","B3ADDMZI ","B3HDSFXI ","B3HDSFYI ","B3HDSFZI ","B3HDSMXI ","B3HDSMYI ", & + "B3HDSMZI ","B3HEAVE ","B3PITCH ","B3RAXI ","B3RAYI ","B3RAZI ","B3RDTFXI ", & + "B3RDTFYI ","B3RDTFZI ","B3RDTMXI ","B3RDTMYI ","B3RDTMZI ","B3ROLL ","B3RVXI ", & + "B3RVYI ","B3RVZI ","B3SURGE ","B3SWAY ","B3TAXI ","B3TAYI ","B3TAZI ", & + "B3TVXI ","B3TVYI ","B3TVZI ","B3WVSF1XI","B3WVSF1YI","B3WVSF1ZI","B3WVSF2XI", & + "B3WVSF2YI","B3WVSF2ZI","B3WVSFXI ","B3WVSFYI ","B3WVSFZI ","B3WVSM1XI","B3WVSM1YI", & + "B3WVSM1ZI","B3WVSM2XI","B3WVSM2YI","B3WVSM2ZI","B3WVSMXI ","B3WVSMYI ","B3WVSMZI ", & + "B3YAW ","B4ADDFXI ","B4ADDFYI ","B4ADDFZI ","B4ADDMXI ","B4ADDMYI ","B4ADDMZI ", & + "B4HDSFXI ","B4HDSFYI ","B4HDSFZI ","B4HDSMXI ","B4HDSMYI ","B4HDSMZI ","B4HEAVE ", & + "B4PITCH ","B4RAXI ","B4RAYI ","B4RAZI ","B4RDTFXI ","B4RDTFYI ","B4RDTFZI ", & + "B4RDTMXI ","B4RDTMYI ","B4RDTMZI ","B4ROLL ","B4RVXI ","B4RVYI ","B4RVZI ", & + "B4SURGE ","B4SWAY ","B4TAXI ","B4TAYI ","B4TAZI ","B4TVXI ","B4TVYI ", & + "B4TVZI ","B4WVSF1XI","B4WVSF1YI","B4WVSF1ZI","B4WVSF2XI","B4WVSF2YI","B4WVSF2ZI", & + "B4WVSFXI ","B4WVSFYI ","B4WVSFZI ","B4WVSM1XI","B4WVSM1YI","B4WVSM1ZI","B4WVSM2XI", & + "B4WVSM2YI","B4WVSM2ZI","B4WVSMXI ","B4WVSMYI ","B4WVSMZI ","B4YAW ","B5ADDFXI ", & + "B5ADDFYI ","B5ADDFZI ","B5ADDMXI ","B5ADDMYI ","B5ADDMZI ","B5HDSFXI ","B5HDSFYI ", & + "B5HDSFZI ","B5HDSMXI ","B5HDSMYI ","B5HDSMZI ","B5HEAVE ","B5PITCH ","B5RAXI ", & + "B5RAYI ","B5RAZI ","B5RDTFXI ","B5RDTFYI ","B5RDTFZI ","B5RDTMXI ","B5RDTMYI ", & + "B5RDTMZI ","B5ROLL ","B5RVXI ","B5RVYI ","B5RVZI ","B5SURGE ","B5SWAY ", & + "B5TAXI ","B5TAYI ","B5TAZI ","B5TVXI ","B5TVYI ","B5TVZI ","B5WVSF1XI", & + "B5WVSF1YI","B5WVSF1ZI","B5WVSF2XI","B5WVSF2YI","B5WVSF2ZI","B5WVSFXI ","B5WVSFYI ", & + "B5WVSFZI ","B5WVSM1XI","B5WVSM1YI","B5WVSM1ZI","B5WVSM2XI","B5WVSM2YI","B5WVSM2ZI", & + "B5WVSMXI ","B5WVSMYI ","B5WVSMZI ","B5YAW ","B6ADDFXI ","B6ADDFYI ","B6ADDFZI ", & + "B6ADDMXI ","B6ADDMYI ","B6ADDMZI ","B6HDSFXI ","B6HDSFYI ","B6HDSFZI ","B6HDSMXI ", & + "B6HDSMYI ","B6HDSMZI ","B6HEAVE ","B6PITCH ","B6RAXI ","B6RAYI ","B6RAZI ", & + "B6RDTFXI ","B6RDTFYI ","B6RDTFZI ","B6RDTMXI ","B6RDTMYI ","B6RDTMZI ","B6ROLL ", & + "B6RVXI ","B6RVYI ","B6RVZI ","B6SURGE ","B6SWAY ","B6TAXI ","B6TAYI ", & + "B6TAZI ","B6TVXI ","B6TVYI ","B6TVZI ","B6WVSF1XI","B6WVSF1YI","B6WVSF1ZI", & + "B6WVSF2XI","B6WVSF2YI","B6WVSF2ZI","B6WVSFXI ","B6WVSFYI ","B6WVSFZI ","B6WVSM1XI", & + "B6WVSM1YI","B6WVSM1ZI","B6WVSM2XI","B6WVSM2YI","B6WVSM2ZI","B6WVSMXI ","B6WVSMYI ", & + "B6WVSMZI ","B6YAW ","B7ADDFXI ","B7ADDFYI ","B7ADDFZI ","B7ADDMXI ","B7ADDMYI ", & + "B7ADDMZI ","B7HDSFXI ","B7HDSFYI ","B7HDSFZI ","B7HDSMXI ","B7HDSMYI ","B7HDSMZI ", & + "B7HEAVE ","B7PITCH ","B7RAXI ","B7RAYI ","B7RAZI ","B7RDTFXI ","B7RDTFYI ", & + "B7RDTFZI ","B7RDTMXI ","B7RDTMYI ","B7RDTMZI ","B7ROLL ","B7RVXI ","B7RVYI ", & + "B7RVZI ","B7SURGE ","B7SWAY ","B7TAXI ","B7TAYI ","B7TAZI ","B7TVXI ", & + "B7TVYI ","B7TVZI ","B7WVSF1XI","B7WVSF1YI","B7WVSF1ZI","B7WVSF2XI","B7WVSF2YI", & + "B7WVSF2ZI","B7WVSFXI ","B7WVSFYI ","B7WVSFZI ","B7WVSM1XI","B7WVSM1YI","B7WVSM1ZI", & + "B7WVSM2XI","B7WVSM2YI","B7WVSM2ZI","B7WVSMXI ","B7WVSMYI ","B7WVSMZI ","B7YAW ", & "B8ADDFXI ","B8ADDFYI ","B8ADDFZI ","B8ADDMXI ","B8ADDMYI ","B8ADDMZI ","B8HDSFXI ", & "B8HDSFYI ","B8HDSFZI ","B8HDSMXI ","B8HDSMYI ","B8HDSMZI ","B8HEAVE ","B8PITCH ", & "B8RAXI ","B8RAYI ","B8RAZI ","B8RDTFXI ","B8RDTFYI ","B8RDTFZI ","B8RDTMXI ", & "B8RDTMYI ","B8RDTMZI ","B8ROLL ","B8RVXI ","B8RVYI ","B8RVZI ","B8SURGE ", & "B8SWAY ","B8TAXI ","B8TAYI ","B8TAZI ","B8TVXI ","B8TVYI ","B8TVZI ", & - "B8WVSF1XI","B8WVSF1YI","B8WVSF1ZI","B8WVSFXI ","B8WVSFYI ","B8WVSFZI ","B8WVSM1XI", & - "B8WVSM1YI","B8WVSM1ZI","B8WVSMXI ","B8WVSMYI ","B8WVSMZI ","B8YAW ","B9ADDFXI ", & - "B9ADDFYI ","B9ADDFZI ","B9ADDMXI ","B9ADDMYI ","B9ADDMZI ","B9HDSFXI ","B9HDSFYI ", & - "B9HDSFZI ","B9HDSMXI ","B9HDSMYI ","B9HDSMZI ","B9HEAVE ","B9PITCH ","B9RAXI ", & - "B9RAYI ","B9RAZI ","B9RDTFXI ","B9RDTFYI ","B9RDTFZI ","B9RDTMXI ","B9RDTMYI ", & - "B9RDTMZI ","B9ROLL ","B9RVXI ","B9RVYI ","B9RVZI ","B9SURGE ","B9SWAY ", & - "B9TAXI ","B9TAYI ","B9TAZI ","B9TVXI ","B9TVYI ","B9TVZI ","B9WVSF1XI", & - "B9WVSF1YI","B9WVSF1ZI","B9WVSFXI ","B9WVSFYI ","B9WVSFZI ","B9WVSM1XI","B9WVSM1YI", & - "B9WVSM1ZI","B9WVSMXI ","B9WVSMYI ","B9WVSMZI ","B9YAW ","HYDROFXI ","HYDROFYI ", & - "HYDROFZI ","HYDROMXI ","HYDROMYI ","HYDROMZI ","WAVE1ELEV","WAVE1ELV1","WAVE2ELEV", & - "WAVE2ELV1","WAVE3ELEV","WAVE3ELV1","WAVE4ELEV","WAVE4ELV1","WAVE5ELEV","WAVE5ELV1", & - "WAVE6ELEV","WAVE6ELV1","WAVE7ELEV","WAVE7ELV1","WAVE8ELEV","WAVE8ELV1","WAVE9ELEV", & - "WAVE9ELV1"/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(456) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + "B8WVSF1XI","B8WVSF1YI","B8WVSF1ZI","B8WVSF2XI","B8WVSF2YI","B8WVSF2ZI","B8WVSFXI ", & + "B8WVSFYI ","B8WVSFZI ","B8WVSM1XI","B8WVSM1YI","B8WVSM1ZI","B8WVSM2XI","B8WVSM2YI", & + "B8WVSM2ZI","B8WVSMXI ","B8WVSMYI ","B8WVSMZI ","B8YAW ","B9ADDFXI ","B9ADDFYI ", & + "B9ADDFZI ","B9ADDMXI ","B9ADDMYI ","B9ADDMZI ","B9HDSFXI ","B9HDSFYI ","B9HDSFZI ", & + "B9HDSMXI ","B9HDSMYI ","B9HDSMZI ","B9HEAVE ","B9PITCH ","B9RAXI ","B9RAYI ", & + "B9RAZI ","B9RDTFXI ","B9RDTFYI ","B9RDTFZI ","B9RDTMXI ","B9RDTMYI ","B9RDTMZI ", & + "B9ROLL ","B9RVXI ","B9RVYI ","B9RVZI ","B9SURGE ","B9SWAY ","B9TAXI ", & + "B9TAYI ","B9TAZI ","B9TVXI ","B9TVYI ","B9TVZI ","B9WVSF1XI","B9WVSF1YI", & + "B9WVSF1ZI","B9WVSF2XI","B9WVSF2YI","B9WVSF2ZI","B9WVSFXI ","B9WVSFYI ","B9WVSFZI ", & + "B9WVSM1XI","B9WVSM1YI","B9WVSM1ZI","B9WVSM2XI","B9WVSM2YI","B9WVSM2ZI","B9WVSMXI ", & + "B9WVSMYI ","B9WVSMZI ","B9YAW ","HYDROFXI ","HYDROFYI ","HYDROFZI ","HYDROMXI ", & + "HYDROMYI ","HYDROMZI ","WAVE1ELEV","WAVE1ELV1","WAVE1ELV2","WAVE2ELEV","WAVE2ELV1", & + "WAVE2ELV2","WAVE3ELEV","WAVE3ELV1","WAVE3ELV2","WAVE4ELEV","WAVE4ELV1","WAVE4ELV2", & + "WAVE5ELEV","WAVE5ELV1","WAVE5ELV2","WAVE6ELEV","WAVE6ELV1","WAVE6ELV2","WAVE7ELEV", & + "WAVE7ELV1","WAVE7ELV2","WAVE8ELEV","WAVE8ELV1","WAVE8ELV2","WAVE9ELEV","WAVE9ELV1", & + "WAVE9ELV2"/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(519) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) B1AddFxi , B1AddFyi , B1AddFzi , B1AddMxi , B1AddMyi , B1AddMzi , B1HdSFxi , & B1HdSFyi , B1HdSFzi , B1HdSMxi , B1HdSMyi , B1HdSMzi , B1Heave , B1Pitch , & B1RAxi , B1RAyi , B1RAzi , B1RdtFxi , B1RdtFyi , B1RdtFzi , B1RdtMxi , & B1RdtMyi , B1RdtMzi , B1Roll , B1RVxi , B1RVyi , B1RVzi , B1Surge , & B1Sway , B1TAxi , B1TAyi , B1TAzi , B1TVxi , B1TVyi , B1TVzi , & - B1WvsF1xi , B1WvsF1yi , B1WvsF1zi , B1WvsFxi , B1WvsFyi , B1WvsFzi , B1WvsM1xi , & - B1WvsM1yi , B1WvsM1zi , B1WvsMxi , B1WvsMyi , B1WvsMzi , B1Yaw , B2AddFxi , & - B2AddFyi , B2AddFzi , B2AddMxi , B2AddMyi , B2AddMzi , B2HdSFxi , B2HdSFyi , & - B2HdSFzi , B2HdSMxi , B2HdSMyi , B2HdSMzi , B2Heave , B2Pitch , B2RAxi , & - B2RAyi , B2RAzi , B2RdtFxi , B2RdtFyi , B2RdtFzi , B2RdtMxi , B2RdtMyi , & - B2RdtMzi , B2Roll , B2RVxi , B2RVyi , B2RVzi , B2Surge , B2Sway , & - B2TAxi , B2TAyi , B2TAzi , B2TVxi , B2TVyi , B2TVzi , B2WvsF1xi , & - B2WvsF1yi , B2WvsF1zi , B2WvsFxi , B2WvsFyi , B2WvsFzi , B2WvsM1xi , B2WvsM1yi , & - B2WvsM1zi , B2WvsMxi , B2WvsMyi , B2WvsMzi , B2Yaw , B3AddFxi , B3AddFyi , & - B3AddFzi , B3AddMxi , B3AddMyi , B3AddMzi , B3HdSFxi , B3HdSFyi , B3HdSFzi , & - B3HdSMxi , B3HdSMyi , B3HdSMzi , B3Heave , B3Pitch , B3RAxi , B3RAyi , & - B3RAzi , B3RdtFxi , B3RdtFyi , B3RdtFzi , B3RdtMxi , B3RdtMyi , B3RdtMzi , & - B3Roll , B3RVxi , B3RVyi , B3RVzi , B3Surge , B3Sway , B3TAxi , & - B3TAyi , B3TAzi , B3TVxi , B3TVyi , B3TVzi , B3WvsF1xi , B3WvsF1yi , & - B3WvsF1zi , B3WvsFxi , B3WvsFyi , B3WvsFzi , B3WvsM1xi , B3WvsM1yi , B3WvsM1zi , & - B3WvsMxi , B3WvsMyi , B3WvsMzi , B3Yaw , B4AddFxi , B4AddFyi , B4AddFzi , & - B4AddMxi , B4AddMyi , B4AddMzi , B4HdSFxi , B4HdSFyi , B4HdSFzi , B4HdSMxi , & - B4HdSMyi , B4HdSMzi , B4Heave , B4Pitch , B4RAxi , B4RAyi , B4RAzi , & - B4RdtFxi , B4RdtFyi , B4RdtFzi , B4RdtMxi , B4RdtMyi , B4RdtMzi , B4Roll , & - B4RVxi , B4RVyi , B4RVzi , B4Surge , B4Sway , B4TAxi , B4TAyi , & - B4TAzi , B4TVxi , B4TVyi , B4TVzi , B4WvsF1xi , B4WvsF1yi , B4WvsF1zi , & - B4WvsFxi , B4WvsFyi , B4WvsFzi , B4WvsM1xi , B4WvsM1yi , B4WvsM1zi , B4WvsMxi , & - B4WvsMyi , B4WvsMzi , B4Yaw , B5AddFxi , B5AddFyi , B5AddFzi , B5AddMxi , & - B5AddMyi , B5AddMzi , B5HdSFxi , B5HdSFyi , B5HdSFzi , B5HdSMxi , B5HdSMyi , & - B5HdSMzi , B5Heave , B5Pitch , B5RAxi , B5RAyi , B5RAzi , B5RdtFxi , & - B5RdtFyi , B5RdtFzi , B5RdtMxi , B5RdtMyi , B5RdtMzi , B5Roll , B5RVxi , & - B5RVyi , B5RVzi , B5Surge , B5Sway , B5TAxi , B5TAyi , B5TAzi , & - B5TVxi , B5TVyi , B5TVzi , B5WvsF1xi , B5WvsF1yi , B5WvsF1zi , B5WvsFxi , & - B5WvsFyi , B5WvsFzi , B5WvsM1xi , B5WvsM1yi , B5WvsM1zi , B5WvsMxi , B5WvsMyi , & - B5WvsMzi , B5Yaw , B6AddFxi , B6AddFyi , B6AddFzi , B6AddMxi , B6AddMyi , & - B6AddMzi , B6HdSFxi , B6HdSFyi , B6HdSFzi , B6HdSMxi , B6HdSMyi , B6HdSMzi , & - B6Heave , B6Pitch , B6RAxi , B6RAyi , B6RAzi , B6RdtFxi , B6RdtFyi , & - B6RdtFzi , B6RdtMxi , B6RdtMyi , B6RdtMzi , B6Roll , B6RVxi , B6RVyi , & - B6RVzi , B6Surge , B6Sway , B6TAxi , B6TAyi , B6TAzi , B6TVxi , & - B6TVyi , B6TVzi , B6WvsF1xi , B6WvsF1yi , B6WvsF1zi , B6WvsFxi , B6WvsFyi , & - B6WvsFzi , B6WvsM1xi , B6WvsM1yi , B6WvsM1zi , B6WvsMxi , B6WvsMyi , B6WvsMzi , & - B6Yaw , B7AddFxi , B7AddFyi , B7AddFzi , B7AddMxi , B7AddMyi , B7AddMzi , & - B7HdSFxi , B7HdSFyi , B7HdSFzi , B7HdSMxi , B7HdSMyi , B7HdSMzi , B7Heave , & - B7Pitch , B7RAxi , B7RAyi , B7RAzi , B7RdtFxi , B7RdtFyi , B7RdtFzi , & - B7RdtMxi , B7RdtMyi , B7RdtMzi , B7Roll , B7RVxi , B7RVyi , B7RVzi , & - B7Surge , B7Sway , B7TAxi , B7TAyi , B7TAzi , B7TVxi , B7TVyi , & - B7TVzi , B7WvsF1xi , B7WvsF1yi , B7WvsF1zi , B7WvsFxi , B7WvsFyi , B7WvsFzi , & - B7WvsM1xi , B7WvsM1yi , B7WvsM1zi , B7WvsMxi , B7WvsMyi , B7WvsMzi , B7Yaw , & + B1WvsF1xi , B1WvsF1yi , B1WvsF1zi , B1WvsF2xi , B1WvsF2yi , B1WvsF2zi , B1WvsFxi , & + B1WvsFyi , B1WvsFzi , B1WvsM1xi , B1WvsM1yi , B1WvsM1zi , B1WvsM2xi , B1WvsM2yi , & + B1WvsM2zi , B1WvsMxi , B1WvsMyi , B1WvsMzi , B1Yaw , B2AddFxi , B2AddFyi , & + B2AddFzi , B2AddMxi , B2AddMyi , B2AddMzi , B2HdSFxi , B2HdSFyi , B2HdSFzi , & + B2HdSMxi , B2HdSMyi , B2HdSMzi , B2Heave , B2Pitch , B2RAxi , B2RAyi , & + B2RAzi , B2RdtFxi , B2RdtFyi , B2RdtFzi , B2RdtMxi , B2RdtMyi , B2RdtMzi , & + B2Roll , B2RVxi , B2RVyi , B2RVzi , B2Surge , B2Sway , B2TAxi , & + B2TAyi , B2TAzi , B2TVxi , B2TVyi , B2TVzi , B2WvsF1xi , B2WvsF1yi , & + B2WvsF1zi , B2WvsF2xi , B2WvsF2yi , B2WvsF2zi , B2WvsFxi , B2WvsFyi , B2WvsFzi , & + B2WvsM1xi , B2WvsM1yi , B2WvsM1zi , B2WvsM2xi , B2WvsM2yi , B2WvsM2zi , B2WvsMxi , & + B2WvsMyi , B2WvsMzi , B2Yaw , B3AddFxi , B3AddFyi , B3AddFzi , B3AddMxi , & + B3AddMyi , B3AddMzi , B3HdSFxi , B3HdSFyi , B3HdSFzi , B3HdSMxi , B3HdSMyi , & + B3HdSMzi , B3Heave , B3Pitch , B3RAxi , B3RAyi , B3RAzi , B3RdtFxi , & + B3RdtFyi , B3RdtFzi , B3RdtMxi , B3RdtMyi , B3RdtMzi , B3Roll , B3RVxi , & + B3RVyi , B3RVzi , B3Surge , B3Sway , B3TAxi , B3TAyi , B3TAzi , & + B3TVxi , B3TVyi , B3TVzi , B3WvsF1xi , B3WvsF1yi , B3WvsF1zi , B3WvsF2xi , & + B3WvsF2yi , B3WvsF2zi , B3WvsFxi , B3WvsFyi , B3WvsFzi , B3WvsM1xi , B3WvsM1yi , & + B3WvsM1zi , B3WvsM2xi , B3WvsM2yi , B3WvsM2zi , B3WvsMxi , B3WvsMyi , B3WvsMzi , & + B3Yaw , B4AddFxi , B4AddFyi , B4AddFzi , B4AddMxi , B4AddMyi , B4AddMzi , & + B4HdSFxi , B4HdSFyi , B4HdSFzi , B4HdSMxi , B4HdSMyi , B4HdSMzi , B4Heave , & + B4Pitch , B4RAxi , B4RAyi , B4RAzi , B4RdtFxi , B4RdtFyi , B4RdtFzi , & + B4RdtMxi , B4RdtMyi , B4RdtMzi , B4Roll , B4RVxi , B4RVyi , B4RVzi , & + B4Surge , B4Sway , B4TAxi , B4TAyi , B4TAzi , B4TVxi , B4TVyi , & + B4TVzi , B4WvsF1xi , B4WvsF1yi , B4WvsF1zi , B4WvsF2xi , B4WvsF2yi , B4WvsF2zi , & + B4WvsFxi , B4WvsFyi , B4WvsFzi , B4WvsM1xi , B4WvsM1yi , B4WvsM1zi , B4WvsM2xi , & + B4WvsM2yi , B4WvsM2zi , B4WvsMxi , B4WvsMyi , B4WvsMzi , B4Yaw , B5AddFxi , & + B5AddFyi , B5AddFzi , B5AddMxi , B5AddMyi , B5AddMzi , B5HdSFxi , B5HdSFyi , & + B5HdSFzi , B5HdSMxi , B5HdSMyi , B5HdSMzi , B5Heave , B5Pitch , B5RAxi , & + B5RAyi , B5RAzi , B5RdtFxi , B5RdtFyi , B5RdtFzi , B5RdtMxi , B5RdtMyi , & + B5RdtMzi , B5Roll , B5RVxi , B5RVyi , B5RVzi , B5Surge , B5Sway , & + B5TAxi , B5TAyi , B5TAzi , B5TVxi , B5TVyi , B5TVzi , B5WvsF1xi , & + B5WvsF1yi , B5WvsF1zi , B5WvsF2xi , B5WvsF2yi , B5WvsF2zi , B5WvsFxi , B5WvsFyi , & + B5WvsFzi , B5WvsM1xi , B5WvsM1yi , B5WvsM1zi , B5WvsM2xi , B5WvsM2yi , B5WvsM2zi , & + B5WvsMxi , B5WvsMyi , B5WvsMzi , B5Yaw , B6AddFxi , B6AddFyi , B6AddFzi , & + B6AddMxi , B6AddMyi , B6AddMzi , B6HdSFxi , B6HdSFyi , B6HdSFzi , B6HdSMxi , & + B6HdSMyi , B6HdSMzi , B6Heave , B6Pitch , B6RAxi , B6RAyi , B6RAzi , & + B6RdtFxi , B6RdtFyi , B6RdtFzi , B6RdtMxi , B6RdtMyi , B6RdtMzi , B6Roll , & + B6RVxi , B6RVyi , B6RVzi , B6Surge , B6Sway , B6TAxi , B6TAyi , & + B6TAzi , B6TVxi , B6TVyi , B6TVzi , B6WvsF1xi , B6WvsF1yi , B6WvsF1zi , & + B6WvsF2xi , B6WvsF2yi , B6WvsF2zi , B6WvsFxi , B6WvsFyi , B6WvsFzi , B6WvsM1xi , & + B6WvsM1yi , B6WvsM1zi , B6WvsM2xi , B6WvsM2yi , B6WvsM2zi , B6WvsMxi , B6WvsMyi , & + B6WvsMzi , B6Yaw , B7AddFxi , B7AddFyi , B7AddFzi , B7AddMxi , B7AddMyi , & + B7AddMzi , B7HdSFxi , B7HdSFyi , B7HdSFzi , B7HdSMxi , B7HdSMyi , B7HdSMzi , & + B7Heave , B7Pitch , B7RAxi , B7RAyi , B7RAzi , B7RdtFxi , B7RdtFyi , & + B7RdtFzi , B7RdtMxi , B7RdtMyi , B7RdtMzi , B7Roll , B7RVxi , B7RVyi , & + B7RVzi , B7Surge , B7Sway , B7TAxi , B7TAyi , B7TAzi , B7TVxi , & + B7TVyi , B7TVzi , B7WvsF1xi , B7WvsF1yi , B7WvsF1zi , B7WvsF2xi , B7WvsF2yi , & + B7WvsF2zi , B7WvsFxi , B7WvsFyi , B7WvsFzi , B7WvsM1xi , B7WvsM1yi , B7WvsM1zi , & + B7WvsM2xi , B7WvsM2yi , B7WvsM2zi , B7WvsMxi , B7WvsMyi , B7WvsMzi , B7Yaw , & B8AddFxi , B8AddFyi , B8AddFzi , B8AddMxi , B8AddMyi , B8AddMzi , B8HdSFxi , & B8HdSFyi , B8HdSFzi , B8HdSMxi , B8HdSMyi , B8HdSMzi , B8Heave , B8Pitch , & B8RAxi , B8RAyi , B8RAzi , B8RdtFxi , B8RdtFyi , B8RdtFzi , B8RdtMxi , & B8RdtMyi , B8RdtMzi , B8Roll , B8RVxi , B8RVyi , B8RVzi , B8Surge , & B8Sway , B8TAxi , B8TAyi , B8TAzi , B8TVxi , B8TVyi , B8TVzi , & - B8WvsF1xi , B8WvsF1yi , B8WvsF1zi , B8WvsFxi , B8WvsFyi , B8WvsFzi , B8WvsM1xi , & - B8WvsM1yi , B8WvsM1zi , B8WvsMxi , B8WvsMyi , B8WvsMzi , B8Yaw , B9AddFxi , & - B9AddFyi , B9AddFzi , B9AddMxi , B9AddMyi , B9AddMzi , B9HdSFxi , B9HdSFyi , & - B9HdSFzi , B9HdSMxi , B9HdSMyi , B9HdSMzi , B9Heave , B9Pitch , B9RAxi , & - B9RAyi , B9RAzi , B9RdtFxi , B9RdtFyi , B9RdtFzi , B9RdtMxi , B9RdtMyi , & - B9RdtMzi , B9Roll , B9RVxi , B9RVyi , B9RVzi , B9Surge , B9Sway , & - B9TAxi , B9TAyi , B9TAzi , B9TVxi , B9TVyi , B9TVzi , B9WvsF1xi , & - B9WvsF1yi , B9WvsF1zi , B9WvsFxi , B9WvsFyi , B9WvsFzi , B9WvsM1xi , B9WvsM1yi , & - B9WvsM1zi , B9WvsMxi , B9WvsMyi , B9WvsMzi , B9Yaw , HydroFxi , HydroFyi , & - HydroFzi , HydroMxi , HydroMyi , HydroMzi , Wave1Elev , Wave1Elv1 , Wave2Elev , & - Wave2Elv1 , Wave3Elev , Wave3Elv1 , Wave4Elev , Wave4Elv1 , Wave5Elev , Wave5Elv1 , & - Wave6Elev , Wave6Elv1 , Wave7Elev , Wave7Elv1 , Wave8Elev , Wave8Elv1 , Wave9Elev , & - Wave9Elv1 /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(456) = (/ & ! This lists the units corresponding to the allowed parameters + B8WvsF1xi , B8WvsF1yi , B8WvsF1zi , B8WvsF2xi , B8WvsF2yi , B8WvsF2zi , B8WvsFxi , & + B8WvsFyi , B8WvsFzi , B8WvsM1xi , B8WvsM1yi , B8WvsM1zi , B8WvsM2xi , B8WvsM2yi , & + B8WvsM2zi , B8WvsMxi , B8WvsMyi , B8WvsMzi , B8Yaw , B9AddFxi , B9AddFyi , & + B9AddFzi , B9AddMxi , B9AddMyi , B9AddMzi , B9HdSFxi , B9HdSFyi , B9HdSFzi , & + B9HdSMxi , B9HdSMyi , B9HdSMzi , B9Heave , B9Pitch , B9RAxi , B9RAyi , & + B9RAzi , B9RdtFxi , B9RdtFyi , B9RdtFzi , B9RdtMxi , B9RdtMyi , B9RdtMzi , & + B9Roll , B9RVxi , B9RVyi , B9RVzi , B9Surge , B9Sway , B9TAxi , & + B9TAyi , B9TAzi , B9TVxi , B9TVyi , B9TVzi , B9WvsF1xi , B9WvsF1yi , & + B9WvsF1zi , B9WvsF2xi , B9WvsF2yi , B9WvsF2zi , B9WvsFxi , B9WvsFyi , B9WvsFzi , & + B9WvsM1xi , B9WvsM1yi , B9WvsM1zi , B9WvsM2xi , B9WvsM2yi , B9WvsM2zi , B9WvsMxi , & + B9WvsMyi , B9WvsMzi , B9Yaw , HydroFxi , HydroFyi , HydroFzi , HydroMxi , & + HydroMyi , HydroMzi , Wave1Elev , Wave1Elv1 , Wave1Elv2 , Wave2Elev , Wave2Elv1 , & + Wave2Elv2 , Wave3Elev , Wave3Elv1 , Wave3Elv2 , Wave4Elev , Wave4Elv1 , Wave4Elv2 , & + Wave5Elev , Wave5Elv1 , Wave5Elv2 , Wave6Elev , Wave6Elv1 , Wave6Elv2 , Wave7Elev , & + Wave7Elv1 , Wave7Elv2 , Wave8Elev , Wave8Elv1 , Wave8Elv2 , Wave9Elev , Wave9Elv1 , & + Wave9Elv2 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(519) = (/ & ! This lists the units corresponding to the allowed parameters "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ", & "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ", & "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ", & "(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ", & - "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ", & - "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ", & - "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & - "(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ", & "(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ", & "(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & "(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & "(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & - "(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ", & - "(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ","(N·m) ", & - "(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & - "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & "(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ", & "(N·m) ","(N·m) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & "(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ", & "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ", & "(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & - "(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & - "(N·m) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & - "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ", & - "(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ", & - "(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & - "(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & "(rad) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ", & "(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ", & "(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ", & "(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & "(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & - "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ", & - "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ", & - "(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & - "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ", & "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ", & "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ", & "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & "(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & + "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ", & + "(N·m) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ", & + "(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ", & + "(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & + "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(rad) ","(N) ","(N) ", & - "(N) ","(N·m) ","(N·m) ","(N·m) ","(m) ","(m) ","(m) ", & + "(N) ","(N·m) ","(N·m) ","(N·m) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(N) ","(N) ","(N) ","(N·m) ","(N·m) ","(N·m) ", & + "(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ","(N·m) ", & + "(N·m) ","(N·m) ","(rad) ","(N) ","(N) ","(N) ","(N·m) ", & + "(N·m) ","(N·m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) "/) @@ -1021,7 +1120,7 @@ SUBROUTINE HDOut_WriteWvKinFiles( Rootname, HD_Prog, NStepWave, NNodes, NWaveEle END SUBROUTINE HDOut_WriteWvKinFiles !==================================================================================================== -SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, WaveElev1, F_Add, F_Waves, F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat, ErrMsg ) +SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, m_WAMIT2, NWaveElev, WaveElev, WaveElev1, WaveElev2, F_Add, F_Waves, F_Hydro, q, qdot, qdotdot, AllOuts, ErrStat, ErrMsg ) ! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput ! This is called by HydroDyn_CalcOutput() at each time step. !---------------------------------------------------------------------------------------------------- @@ -1029,9 +1128,11 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, Wa TYPE(HydroDyn_ParameterType), INTENT( IN ) :: p ! HydroDyn's parameter data TYPE(HydroDyn_OutputType), INTENT( INOUT ) :: y ! HydroDyn's output data type(WAMIT_MiscVarType), intent( in ) :: m_WAMIT(:) ! WAMIT object's MiscVar data + type(WAMIT2_MiscVarType), intent( in ) :: m_WAMIT2(:) ! WAMIT2 object's MiscVar data INTEGER, INTENT( IN ) :: NWaveElev ! Number of wave elevation locations to output REAL(ReKi), INTENT( IN ) :: WaveElev(:) ! Instantaneous total elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi), INTENT( IN ) :: WaveElev1(:) ! Instantaneous first order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) + REAL(ReKi), INTENT( IN ) :: WaveElev2(:) ! Instantaneous second order elevation of incident waves at each of the NWaveElev points where the incident wave elevations can be output (meters) REAL(ReKi), INTENT( IN ) :: F_Add(:) REAL(ReKi), INTENT( IN ) :: F_Waves(:) REAL(ReKi), INTENT( IN ) :: F_Hydro(:) ! All hydrodynamic loads integrated at (0,0,0) in the global coordinate system @@ -1059,7 +1160,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, Wa AllOuts(FWaves1 (:,iBody)) = m_WAMIT(1)%F_Waves1(startIndx:endIndx) AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(1)%F_HS(startIndx:endIndx) AllOuts(FRdtn (:,iBody)) = m_WAMIT(1)%F_Rdtn(startIndx:endIndx) + m_WAMIT(1)%F_PtfmAM(startIndx:endIndx) - ! AllOuts(FWaves2 (iBody)) = F_Waves2(startIndx:endIndx) ! These are reported by the WAMIT2 module + AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(1)%F_Waves2(startIndx:endIndx) ! These are reported by the WAMIT2 module AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) @@ -1077,7 +1178,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, Wa AllOuts(FWaves1 (:,iBody)) = m_WAMIT(iBody)%F_Waves1 AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(iBody)%F_HS AllOuts(FRdtn (:,iBody)) = m_WAMIT(iBody)%F_Rdtn + m_WAMIT(iBody)%F_PtfmAM - !AllOuts(FWaves2 (:,iBody)) = F_Waves2 + AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(iBody)%F_Waves2 AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) @@ -1093,6 +1194,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, NWaveElev, WaveElev, Wa DO I=1,NWaveElev AllOuts(WaveElevi(I)) = WaveElev(I) AllOuts(WaveElevi1(I))= WaveElev1(I) + AllOuts(WaveElevi2(I))= WaveElev2(I) END DO @@ -1122,7 +1224,7 @@ SUBROUTINE HDOut_WriteOutputs( Time, y, p, Decimate, ErrStat, ErrMsg ) ! Initialize ErrStat and determine if it makes any sense to write output !TODO: We should not have this check here, once per timestep! This should be resolved during initialization. GJH 7/7/2014 - IF ( ( (.NOT. ALLOCATED( p%OutParam )) .AND. (.NOT. ALLOCATED( p%WAMIT(1)%OutParam ) ) .AND. (.NOT. ALLOCATED( p%WAMIT2%OutParam ) )& + IF ( ( (.NOT. ALLOCATED( p%OutParam )) .AND. (.NOT. ALLOCATED( p%WAMIT(1)%OutParam ) ) .AND. (.NOT. ALLOCATED( p%WAMIT2(1)%OutParam ) )& .AND. (.NOT. ALLOCATED( p%Waves2%OutParam ) ) .AND. ( .NOT. ALLOCATED( p%Morison%OutParam ) ) ) ) THEN ErrStat = ErrID_Warn ErrMsg = ' Cannot write output to file because there are not a valid output list.' @@ -1207,7 +1309,16 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E ErrStat = ErrID_None ErrMsg = "" - + ! Sanity check that we didn't have an issue during the programing of this module. The auto + ! generated outlist at the top of this file sets the MaxOutPts value, but HD does not use + ! that value, but rather has the maximum outputs hard coded in the HD registry file. This + ! next test will hopefully help the developer catch any issues. + if ( MaxOutPts /= MaxHDOutputs ) then + call SetErrStat(ErrID_Fatal, ' HD outputs: the number of outputs given by the Write_ChckOutList.m '// & + 'script using the xlsx file does not match the number of outputs given by the HydroDyn.txt registry '// & + 'file.', ErrStat, ErrMsg, 'HDOUT_Init') + return + endif !------------------------------------------------------------------------------------------------- @@ -1228,10 +1339,6 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E m%Decimate = 0 p%OutDec = 1 !TODO: Remove this once the parameter has been added to the HD input file GJH 7/8/2014 - IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN - hasWAMIT2Outs = .TRUE. - p%NumTotalOuts = p%NumTotalOuts + p%WAMIT2%NumOuts - END IF IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN hasWaves2Outs = .TRUE. p%NumTotalOuts = p%NumTotalOuts + p%Waves2%NumOuts @@ -1285,14 +1392,6 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, InitInp, y, p, m, InitOut, ErrStat, E END DO END IF - IF ( hasWAMIT2Outs ) THEN - DO I=1, p%WAMIT2%NumOuts - InitOut%WriteOutputHdr(J) = InitOut%WAMIT2%WriteOutputHdr(I) - InitOut%WriteOutputUnt(J) = InitOut%WAMIT2%WriteOutputUnt(I) - J = J + 1 - END DO - END IF - IF ( hasMorisonOuts ) THEN DO I=1, p%Morison%NumOuts InitOut%WriteOutputHdr(J) = InitOut%Morison%WriteOutputHdr(I) @@ -1349,8 +1448,6 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta !------------------------------------------------------------------------------------------------- p%UnOutFile = -1 IF ( (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) .OR. & - (ALLOCATED( p%WAMIT(1)%OutParam ) .AND. p%WAMIT(1)%NumOuts > 0 ) .OR. & - (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0 ) .OR. & (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0 ) .OR. & (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0 ) ) THEN ! Output has been requested so let's open an output file @@ -1376,11 +1473,6 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputHdr(I) ), I=1,p%WAMIT2%NumOuts ) - END IF - IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN Frmt = '('//TRIM(Int2LStr(p%Waves2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Waves2%WriteOutputHdr(I) ), I=1,p%Waves2%NumOuts ) @@ -1406,11 +1498,6 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%WAMIT2%OutParam ) .AND. p%WAMIT2%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%WAMIT2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WAMIT2%WriteOutputUnt(I) ), I=1,p%WAMIT2%NumOuts ) - END IF - IF (ALLOCATED( p%Waves2%OutParam ) .AND. p%Waves2%NumOuts > 0) THEN Frmt = '('//TRIM(Int2LStr(p%Waves2%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Waves2%WriteOutputUnt(I) ), I=1,p%Waves2%NumOuts ) @@ -1563,7 +1650,7 @@ SUBROUTINE HDOut_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) LOGICAL :: InvalidOutput(MaxHDOutputs) ! This array determines if the output channel is valid for this configuration LOGICAL :: CheckOutListAgain - !------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------------------------- ! Allocate and set index, name, and units for the output channels ! If a selected output channel is not available in this module, set error flag. !------------------------------------------------------------------------------------------------- From 4d8fe631ff00f1e0b580268105a1a16c005e5c8c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 23 Dec 2019 16:46:39 -0700 Subject: [PATCH 095/377] TCF: Change WAMIT2 to arrayed in HD code --- modules/hydrodyn/src/HydroDyn.f90 | 70 ++-- modules/hydrodyn/src/HydroDyn.txt | 18 +- modules/hydrodyn/src/HydroDyn_Types.f90 | 534 +++++++++++++++++++++--- 3 files changed, 538 insertions(+), 84 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 5001826bd..41f848e88 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1054,8 +1054,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I return end if - CALL WAMIT2_Init(InitLocal%WAMIT2, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, z%WAMIT2, OtherState%WAMIT2, & - y%WAMIT2, m%WAMIT2, Interval, InitOut%WAMIT2, ErrStat2, ErrMsg2 ) + CALL WAMIT2_Init(InitLocal%WAMIT2, m%u_WAMIT2(1), p%WAMIT2(1), x%WAMIT2(1), xd%WAMIT2(1), z%WAMIT2, OtherState%WAMIT2(1), & + y%WAMIT2(1), m%WAMIT2(1), Interval, InitOut%WAMIT2(1), ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() @@ -2050,6 +2050,50 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, end do end if end if + + ! Second order + if ( m%u_WAMIT2(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh + + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + ! Copy the inputs from the HD mesh into the WAMIT mesh + call MeshCopy( u%WAMITMesh, m%u_WAMIT2(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + if ( ErrStat >= AbortErrLev ) return + + call WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2(1), p%WAMIT2(1), x%WAMIT2(1), xd%WAMIT2(1), & + z%WAMIT2, OtherState%WAMIT2(1), y%WAMIT2(1), m%WAMIT2(1), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + do iBody=1,p%NBody + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT2(1)%Mesh%Force (:,iBody) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(1)%Mesh%Moment(:,iBody) + end do +!FIXME: check how we should deal with m%F_Waves + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + m%F_Waves = m%F_Waves + m%WAMIT2(1)%F_Waves2 + else + do iBody=1,p%NBody + + ! We need to copy the iWAMIT2-th node data from the Inputs(I)%WAMIT2Mesh onto the 1st node of the Inputs_WAMIT2(I)%Mesh + m%u_WAMIT2(iBody)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iBody) + m%u_WAMIT2(iBody)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iBody) + m%u_WAMIT2(iBody)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iBody) + m%u_WAMIT2(iBody)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iBody) + m%u_WAMIT2(iBody)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iBody) + m%u_WAMIT2(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) + + call WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2(iBody), p%WAMIT2(iBody), x%WAMIT2(iBody), xd%WAMIT2(iBody), & + z%WAMIT2, OtherState%WAMIT2(iBody), y%WAMIT2(iBody), m%WAMIT2(iBody), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT2(iBody)%Mesh%Force (:,1) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(iBody)%Mesh%Moment(:,1) + + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + m%F_Waves(indxStart:indxEnd) = m%F_Waves(indxStart:indxEnd) + m%WAMIT2(iBody)%F_Waves2 + end do + end if + end if #ifdef USE_FIT ELSE IF ( p%PotMod ==2 ) THEN !FIT @@ -2068,28 +2112,6 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, END IF - IF ( m%u_WAMIT2%Mesh%Committed ) THEN ! Make sure we are using WAMIT2 / there is a valid mesh - - ! Copy the inputs from the HD mesh into the WAMIT2 mesh - CALL MeshCopy( u%WAMITMesh, m%u_WAMIT2%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2, p%WAMIT2, x%WAMIT2, xd%WAMIT2, & - z%WAMIT2, OtherState%WAMIT2, y%WAMIT2, m%WAMIT2, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - - ! Add WAMIT2 forces to the HydroDyn output mesh - y%WAMITMesh%Force (:,1) = y%WAMITMesh%Force (:,1) + y%WAMIT2%Mesh%Force (:,1) - y%WAMITMesh%Moment(:,1) = y%WAMITMesh%Moment(:,1) + y%WAMIT2%Mesh%Moment(:,1) - - ! Add the second order WAMIT forces to the first order WAMIT forces for the total (this is just to make the mesh match this misc var) - m%F_Waves = m%F_Waves + m%WAMIT2%F_Waves2 - - END IF - - IF ( u%Morison%LumpedMesh%Committed ) THEN ! Make sure we are using Morison / there is a valid mesh CALL Morison_CalcOutput( Time, u%Morison, p%Morison, x%Morison, xd%Morison, & diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 93f3c0120..69ca90036 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -23,7 +23,7 @@ usefrom WAMIT.txt usefrom WAMIT2.txt usefrom Morison.txt #usefrom FIT.txt -param HydroDyn/HydroDyn unused INTEGER MaxHDOutputs - 456 - "The maximum number of output channels supported by this module" - +param HydroDyn/HydroDyn unused INTEGER MaxHDOutputs - 519 - "The maximum number of output channels supported by this module" - typedef HydroDyn/HydroDyn InitInputType CHARACTER(1024) InputFile - - - "Supplied by Driver: full path and filename for the HydroDyn module" - typedef ^ ^ LOGICAL UseInputFile - - - "Supplied by Driver: .TRUE. if using a input file, .FALSE. if all inputs are being passed in by the caller" - typedef ^ ^ CHARACTER(1024) OutRootName - - - "Supplied by Driver: The name of the root file (without extension) including the full path" - @@ -76,7 +76,7 @@ typedef ^ ^ CHARACTER(2 # Define outputs from the initialization routine here: # typedef ^ InitOutputType WAMIT_InitOutputType WAMIT {:} - - "Initialization output from the WAMIT module" - -typedef ^ InitOutputType WAMIT2_InitOutputType WAMIT2 - - - "Initialization output from the WAMIT2 module" - +typedef ^ InitOutputType WAMIT2_InitOutputType WAMIT2 {:} - - "Initialization output from the WAMIT2 module" - typedef ^ InitOutputType Waves2_InitOutputType Waves2 - - - "Initialization output from the Waves2 module" - typedef ^ ^ Morison_InitOutputType Morison - - - "Initialization output from the Morison module" - typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "The is the list of all HD-related output channel header strings (includes all sub-module channels)" - @@ -105,7 +105,7 @@ typedef ^ HD_ModuleMapType MeshMapType # Define continuous (differentiable) states here: # typedef ^ ContinuousStateType WAMIT_ContinuousStateType WAMIT {:} - - "continuous states from the wamit module" - -typedef ^ ContinuousStateType WAMIT2_ContinuousStateType WAMIT2 - - - "continuous states from the wamit2 module" - +typedef ^ ContinuousStateType WAMIT2_ContinuousStateType WAMIT2 {:} - - "continuous states from the wamit2 module" - typedef ^ ContinuousStateType Waves2_ContinuousStateType Waves2 - - - "continuous states from the waves2 module" - typedef ^ ContinuousStateType Morison_ContinuousStateType Morison - - - "continuous states from the Morison module" - # @@ -113,7 +113,7 @@ typedef ^ ContinuousStateType Morison_Con # Define discrete (nondifferentiable) states here: # typedef ^ DiscreteStateType WAMIT_DiscreteStateType WAMIT {:} - - "discrete states from the wamit module" - -typedef ^ DiscreteStateType WAMIT2_DiscreteStateType WAMIT2 - - - "discrete states from the wamit2 module" - +typedef ^ DiscreteStateType WAMIT2_DiscreteStateType WAMIT2 {:} - - "discrete states from the wamit2 module" - #typedef ^ DiscreteStateType FIT_DiscreteStateType FIT - - - "discrete states from the FIT module" - typedef ^ DiscreteStateType Waves2_DiscreteStateType Waves2 - - - "discrete states from the waves2 module" - typedef ^ DiscreteStateType Morison_DiscreteStateType Morison - - - "discrete states from the Morison module" - @@ -130,7 +130,7 @@ typedef ^ ConstraintStateType Morison_Con # Define any other states here: # typedef ^ OtherStateType WAMIT_OtherStateType WAMIT {:} - - "OtherState information from the WAMIT module" - -typedef ^ OtherStateType WAMIT2_OtherStateType WAMIT2 - - - "OtherState information from the WAMIT2 module" - +typedef ^ OtherStateType WAMIT2_OtherStateType WAMIT2 {:} - - "OtherState information from the WAMIT2 module" - #typedef ^ OtherStateType FIT_OtherStateType FIT - - - "OtherState information from the FIT module" - typedef ^ OtherStateType Waves2_OtherStateType Waves2 - - - "OtherState information from the Waves2 module" - typedef ^ ^ Morison_OtherStateType Morison - - - "OtherState information from the Morison module" - @@ -149,11 +149,11 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi F_Hydro {6} - - "The total hydrodynamic forces and moments integrated about the (0,0,0) platform reference point" - typedef ^ ^ ReKi F_Waves {:} - - "The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules)" - typedef ^ ^ WAMIT_MiscVarType WAMIT {:} - - "misc var information from the WAMIT module" - -typedef ^ ^ WAMIT2_MiscVarType WAMIT2 - - - "misc var information from the WAMIT2 module" - +typedef ^ ^ WAMIT2_MiscVarType WAMIT2 {:} - - "misc var information from the WAMIT2 module" - typedef ^ ^ Waves2_MiscVarType Waves2 - - - "misc var information from the Waves2 module" - typedef ^ ^ Morison_MiscVarType Morison - - - "misc var information from the Morison module" - typedef ^ ^ WAMIT_InputType u_WAMIT {:} - - "WAMIT module inputs" - -typedef ^ ^ WAMIT2_InputType u_WAMIT2 - - - "WAMIT2 module inputs" - +typedef ^ ^ WAMIT2_InputType u_WAMIT2 {:} - - "WAMIT2 module inputs" - typedef ^ ^ Waves2_InputType u_Waves2 - - - "Waves2 module inputs" - typedef ^ ^ Logical IgnoreMod - - - "whether to ignore the modulo in ED outputs (necessary for linearization perturbations)" - # ..... Parameters ................................................................................................................ @@ -163,7 +163,7 @@ typedef ^ ^ Logical typedef ^ ParameterType INTEGER nWAMITObj - - - "number of WAMIT input files and matrices. If NBodyMod = 1 then nPotFiles will be 1 even if NBody > 1" - typedef ^ ^ INTEGER vecMultiplier - - - "multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1" - typedef ^ ^ WAMIT_ParameterType WAMIT {:} - - "Parameter data for the WAMIT module" - -typedef ^ ^ WAMIT2_ParameterType WAMIT2 - - - "Parameter data for the WAMIT2 module" - +typedef ^ ^ WAMIT2_ParameterType WAMIT2 {:} - - "Parameter data for the WAMIT2 module" - #typedef ^ ^ FIT_ParameterType FIT - - - "Parameter data for the FIT module" - typedef ^ ^ Waves2_ParameterType Waves2 - - - "Parameter data for the Waves2 module" - typedef ^ ^ Morison_ParameterType Morison - - - "Parameter data for the Morison module" - @@ -207,7 +207,7 @@ typedef ^ InputType MeshType # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: typedef ^ OutputType WAMIT_OutputType WAMIT {:} - - "WAMIT module outputs" - -typedef ^ OutputType WAMIT2_OutputType WAMIT2 - - - "WAMIT2 module outputs" - +typedef ^ OutputType WAMIT2_OutputType WAMIT2 {:} - - "WAMIT2 module outputs" - typedef ^ OutputType Waves2_OutputType Waves2 - - - "Waves2 module outputs" - typedef ^ ^ Morison_OutputType Morison - - - "Morison module outputs" - typedef ^ OutputType MeshType WAMITMesh - - - "Point Loads at the WAMIT reference point(s) in the inertial frame" - diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 77acaa408..4b85d2f2d 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -42,7 +42,7 @@ MODULE HydroDyn_Types USE Morison_Types USE NWTC_Library IMPLICIT NONE - INTEGER(IntKi), PUBLIC, PARAMETER :: MaxHDOutputs = 456 ! The maximum number of output channels supported by this module [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxHDOutputs = 519 ! The maximum number of output channels supported by this module [-] ! ========= HydroDyn_InitInputType ======= TYPE, PUBLIC :: HydroDyn_InitInputType CHARACTER(1024) :: InputFile !< Supplied by Driver: full path and filename for the HydroDyn module [-] @@ -97,7 +97,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_InitOutputType ======= TYPE, PUBLIC :: HydroDyn_InitOutputType TYPE(WAMIT_InitOutputType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< Initialization output from the WAMIT module [-] - TYPE(WAMIT2_InitOutputType) :: WAMIT2 !< Initialization output from the WAMIT2 module [-] + TYPE(WAMIT2_InitOutputType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< Initialization output from the WAMIT2 module [-] TYPE(Waves2_InitOutputType) :: Waves2 !< Initialization output from the Waves2 module [-] TYPE(Morison_InitOutputType) :: Morison !< Initialization output from the Morison module [-] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all HD-related output channel header strings (includes all sub-module channels) [-] @@ -125,7 +125,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_ContinuousStateType ======= TYPE, PUBLIC :: HydroDyn_ContinuousStateType TYPE(WAMIT_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< continuous states from the wamit module [-] - TYPE(WAMIT2_ContinuousStateType) :: WAMIT2 !< continuous states from the wamit2 module [-] + TYPE(WAMIT2_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< continuous states from the wamit2 module [-] TYPE(Waves2_ContinuousStateType) :: Waves2 !< continuous states from the waves2 module [-] TYPE(Morison_ContinuousStateType) :: Morison !< continuous states from the Morison module [-] END TYPE HydroDyn_ContinuousStateType @@ -133,7 +133,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_DiscreteStateType ======= TYPE, PUBLIC :: HydroDyn_DiscreteStateType TYPE(WAMIT_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< discrete states from the wamit module [-] - TYPE(WAMIT2_DiscreteStateType) :: WAMIT2 !< discrete states from the wamit2 module [-] + TYPE(WAMIT2_DiscreteStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< discrete states from the wamit2 module [-] TYPE(Waves2_DiscreteStateType) :: Waves2 !< discrete states from the waves2 module [-] TYPE(Morison_DiscreteStateType) :: Morison !< discrete states from the Morison module [-] END TYPE HydroDyn_DiscreteStateType @@ -149,7 +149,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_OtherStateType ======= TYPE, PUBLIC :: HydroDyn_OtherStateType TYPE(WAMIT_OtherStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< OtherState information from the WAMIT module [-] - TYPE(WAMIT2_OtherStateType) :: WAMIT2 !< OtherState information from the WAMIT2 module [-] + TYPE(WAMIT2_OtherStateType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< OtherState information from the WAMIT2 module [-] TYPE(Waves2_OtherStateType) :: Waves2 !< OtherState information from the Waves2 module [-] TYPE(Morison_OtherStateType) :: Morison !< OtherState information from the Morison module [-] END TYPE HydroDyn_OtherStateType @@ -167,11 +167,11 @@ MODULE HydroDyn_Types REAL(ReKi) , DIMENSION(1:6) :: F_Hydro !< The total hydrodynamic forces and moments integrated about the (0,0,0) platform reference point [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F_Waves !< The total waves forces on a WAMIT body calculated by first and second order methods (WAMIT and WAMIT2 modules) [-] TYPE(WAMIT_MiscVarType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< misc var information from the WAMIT module [-] - TYPE(WAMIT2_MiscVarType) :: WAMIT2 !< misc var information from the WAMIT2 module [-] + TYPE(WAMIT2_MiscVarType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< misc var information from the WAMIT2 module [-] TYPE(Waves2_MiscVarType) :: Waves2 !< misc var information from the Waves2 module [-] TYPE(Morison_MiscVarType) :: Morison !< misc var information from the Morison module [-] TYPE(WAMIT_InputType) , DIMENSION(:), ALLOCATABLE :: u_WAMIT !< WAMIT module inputs [-] - TYPE(WAMIT2_InputType) :: u_WAMIT2 !< WAMIT2 module inputs [-] + TYPE(WAMIT2_InputType) , DIMENSION(:), ALLOCATABLE :: u_WAMIT2 !< WAMIT2 module inputs [-] TYPE(Waves2_InputType) :: u_Waves2 !< Waves2 module inputs [-] LOGICAL :: IgnoreMod !< whether to ignore the modulo in ED outputs (necessary for linearization perturbations) [-] END TYPE HydroDyn_MiscVarType @@ -181,7 +181,7 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: nWAMITObj !< number of WAMIT input files and matrices. If NBodyMod = 1 then nPotFiles will be 1 even if NBody > 1 [-] INTEGER(IntKi) :: vecMultiplier !< multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1 [-] TYPE(WAMIT_ParameterType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< Parameter data for the WAMIT module [-] - TYPE(WAMIT2_ParameterType) :: WAMIT2 !< Parameter data for the WAMIT2 module [-] + TYPE(WAMIT2_ParameterType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< Parameter data for the WAMIT2 module [-] TYPE(Waves2_ParameterType) :: Waves2 !< Parameter data for the Waves2 module [-] TYPE(Morison_ParameterType) :: Morison !< Parameter data for the Morison module [-] INTEGER(IntKi) :: PotMod !< 1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model [-] @@ -223,7 +223,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_OutputType ======= TYPE, PUBLIC :: HydroDyn_OutputType TYPE(WAMIT_OutputType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< WAMIT module outputs [-] - TYPE(WAMIT2_OutputType) :: WAMIT2 !< WAMIT2 module outputs [-] + TYPE(WAMIT2_OutputType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< WAMIT2 module outputs [-] TYPE(Waves2_OutputType) :: Waves2 !< Waves2 module outputs [-] TYPE(Morison_OutputType) :: Morison !< Morison module outputs [-] TYPE(MeshType) :: WAMITMesh !< Point Loads at the WAMIT reference point(s) in the inertial frame [-] @@ -2079,9 +2079,22 @@ SUBROUTINE HydroDyn_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCo IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyInitOutput( SrcInitOutputData%WAMIT2, DstInitOutputData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcInitOutputData%WAMIT2)) THEN + i1_l = LBOUND(SrcInitOutputData%WAMIT2,1) + i1_u = UBOUND(SrcInitOutputData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WAMIT2)) THEN + ALLOCATE(DstInitOutputData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcInitOutputData%WAMIT2,1), UBOUND(SrcInitOutputData%WAMIT2,1) + CALL WAMIT2_CopyInitOutput( SrcInitOutputData%WAMIT2(i1), DstInitOutputData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyInitOutput( SrcInitOutputData%Waves2, DstInitOutputData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -2209,7 +2222,12 @@ SUBROUTINE HydroDyn_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(InitOutputData%WAMIT) ENDIF - CALL WAMIT2_DestroyInitOutput( InitOutputData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%WAMIT2)) THEN +DO i1 = LBOUND(InitOutputData%WAMIT2,1), UBOUND(InitOutputData%WAMIT2,1) + CALL WAMIT2_DestroyInitOutput( InitOutputData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(InitOutputData%WAMIT2) +ENDIF CALL Waves2_DestroyInitOutput( InitOutputData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyInitOutput( InitOutputData%Morison, ErrStat, ErrMsg ) IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN @@ -2298,8 +2316,12 @@ SUBROUTINE HydroDyn_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2315,6 +2337,8 @@ SUBROUTINE HydroDyn_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2477,7 +2501,18 @@ SUBROUTINE HydroDyn_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ENDIF END DO END IF - CALL WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2505,6 +2540,8 @@ SUBROUTINE HydroDyn_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackInitOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2814,6 +2851,20 @@ SUBROUTINE HydroDyn_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -2847,13 +2898,15 @@ SUBROUTINE HydroDyn_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackInitOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -3702,9 +3755,22 @@ SUBROUTINE HydroDyn_CopyContState( SrcContStateData, DstContStateData, CtrlCode, IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyContState( SrcContStateData%WAMIT2, DstContStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcContStateData%WAMIT2)) THEN + i1_l = LBOUND(SrcContStateData%WAMIT2,1) + i1_u = UBOUND(SrcContStateData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstContStateData%WAMIT2)) THEN + ALLOCATE(DstContStateData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcContStateData%WAMIT2,1), UBOUND(SrcContStateData%WAMIT2,1) + CALL WAMIT2_CopyContState( SrcContStateData%WAMIT2(i1), DstContStateData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyContState( SrcContStateData%Waves2, DstContStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -3728,7 +3794,12 @@ SUBROUTINE HydroDyn_DestroyContState( ContStateData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ContStateData%WAMIT) ENDIF - CALL WAMIT2_DestroyContState( ContStateData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(ContStateData%WAMIT2)) THEN +DO i1 = LBOUND(ContStateData%WAMIT2,1), UBOUND(ContStateData%WAMIT2,1) + CALL WAMIT2_DestroyContState( ContStateData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ContStateData%WAMIT2) +ENDIF CALL Waves2_DestroyContState( ContStateData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyContState( ContStateData%Morison, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyContState @@ -3792,8 +3863,12 @@ SUBROUTINE HydroDyn_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3809,6 +3884,8 @@ SUBROUTINE HydroDyn_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -3911,7 +3988,18 @@ SUBROUTINE HydroDyn_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ENDIF END DO END IF - CALL WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3939,6 +4027,8 @@ SUBROUTINE HydroDyn_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4086,6 +4176,20 @@ SUBROUTINE HydroDyn_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -4119,13 +4223,15 @@ SUBROUTINE HydroDyn_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -4239,9 +4345,22 @@ SUBROUTINE HydroDyn_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyDiscState( SrcDiscStateData%WAMIT2, DstDiscStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcDiscStateData%WAMIT2)) THEN + i1_l = LBOUND(SrcDiscStateData%WAMIT2,1) + i1_u = UBOUND(SrcDiscStateData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstDiscStateData%WAMIT2)) THEN + ALLOCATE(DstDiscStateData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstDiscStateData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcDiscStateData%WAMIT2,1), UBOUND(SrcDiscStateData%WAMIT2,1) + CALL WAMIT2_CopyDiscState( SrcDiscStateData%WAMIT2(i1), DstDiscStateData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyDiscState( SrcDiscStateData%Waves2, DstDiscStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -4265,7 +4384,12 @@ SUBROUTINE HydroDyn_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(DiscStateData%WAMIT) ENDIF - CALL WAMIT2_DestroyDiscState( DiscStateData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(DiscStateData%WAMIT2)) THEN +DO i1 = LBOUND(DiscStateData%WAMIT2,1), UBOUND(DiscStateData%WAMIT2,1) + CALL WAMIT2_DestroyDiscState( DiscStateData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(DiscStateData%WAMIT2) +ENDIF CALL Waves2_DestroyDiscState( DiscStateData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyDiscState( DiscStateData%Morison, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyDiscState @@ -4329,8 +4453,12 @@ SUBROUTINE HydroDyn_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4346,6 +4474,8 @@ SUBROUTINE HydroDyn_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -4448,7 +4578,18 @@ SUBROUTINE HydroDyn_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ENDIF END DO END IF - CALL WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4476,6 +4617,8 @@ SUBROUTINE HydroDyn_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackDiscState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4623,6 +4766,20 @@ SUBROUTINE HydroDyn_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -4656,13 +4813,15 @@ SUBROUTINE HydroDyn_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackDiscState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -5258,9 +5417,22 @@ SUBROUTINE HydroDyn_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCo IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyOtherState( SrcOtherStateData%WAMIT2, DstOtherStateData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcOtherStateData%WAMIT2)) THEN + i1_l = LBOUND(SrcOtherStateData%WAMIT2,1) + i1_u = UBOUND(SrcOtherStateData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstOtherStateData%WAMIT2)) THEN + ALLOCATE(DstOtherStateData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOtherStateData%WAMIT2,1), UBOUND(SrcOtherStateData%WAMIT2,1) + CALL WAMIT2_CopyOtherState( SrcOtherStateData%WAMIT2(i1), DstOtherStateData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyOtherState( SrcOtherStateData%Waves2, DstOtherStateData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -5284,7 +5456,12 @@ SUBROUTINE HydroDyn_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(OtherStateData%WAMIT) ENDIF - CALL WAMIT2_DestroyOtherState( OtherStateData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(OtherStateData%WAMIT2)) THEN +DO i1 = LBOUND(OtherStateData%WAMIT2,1), UBOUND(OtherStateData%WAMIT2,1) + CALL WAMIT2_DestroyOtherState( OtherStateData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OtherStateData%WAMIT2) +ENDIF CALL Waves2_DestroyOtherState( OtherStateData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyOtherState( OtherStateData%Morison, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyOtherState @@ -5348,8 +5525,12 @@ SUBROUTINE HydroDyn_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5365,6 +5546,8 @@ SUBROUTINE HydroDyn_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -5467,7 +5650,18 @@ SUBROUTINE HydroDyn_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ENDIF END DO END IF - CALL WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5495,6 +5689,8 @@ SUBROUTINE HydroDyn_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackOtherState( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5642,6 +5838,20 @@ SUBROUTINE HydroDyn_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -5675,13 +5885,15 @@ SUBROUTINE HydroDyn_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackOtherState( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -5835,9 +6047,22 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyMisc( SrcMiscData%WAMIT2, DstMiscData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcMiscData%WAMIT2)) THEN + i1_l = LBOUND(SrcMiscData%WAMIT2,1) + i1_u = UBOUND(SrcMiscData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstMiscData%WAMIT2)) THEN + ALLOCATE(DstMiscData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%WAMIT2,1), UBOUND(SrcMiscData%WAMIT2,1) + CALL WAMIT2_CopyMisc( SrcMiscData%WAMIT2(i1), DstMiscData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyMisc( SrcMiscData%Waves2, DstMiscData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -5860,9 +6085,22 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyInput( SrcMiscData%u_WAMIT2, DstMiscData%u_WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcMiscData%u_WAMIT2)) THEN + i1_l = LBOUND(SrcMiscData%u_WAMIT2,1) + i1_u = UBOUND(SrcMiscData%u_WAMIT2,1) + IF (.NOT. ALLOCATED(DstMiscData%u_WAMIT2)) THEN + ALLOCATE(DstMiscData%u_WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%u_WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%u_WAMIT2,1), UBOUND(SrcMiscData%u_WAMIT2,1) + CALL WAMIT2_CopyInput( SrcMiscData%u_WAMIT2(i1), DstMiscData%u_WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyInput( SrcMiscData%u_Waves2, DstMiscData%u_Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -5894,7 +6132,12 @@ SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(MiscData%WAMIT) ENDIF - CALL WAMIT2_DestroyMisc( MiscData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%WAMIT2)) THEN +DO i1 = LBOUND(MiscData%WAMIT2,1), UBOUND(MiscData%WAMIT2,1) + CALL WAMIT2_DestroyMisc( MiscData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%WAMIT2) +ENDIF CALL Waves2_DestroyMisc( MiscData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyMisc( MiscData%Morison, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%u_WAMIT)) THEN @@ -5903,7 +6146,12 @@ SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(MiscData%u_WAMIT) ENDIF - CALL WAMIT2_DestroyInput( MiscData%u_WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(MiscData%u_WAMIT2)) THEN +DO i1 = LBOUND(MiscData%u_WAMIT2,1), UBOUND(MiscData%u_WAMIT2,1) + CALL WAMIT2_DestroyInput( MiscData%u_WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%u_WAMIT2) +ENDIF CALL Waves2_DestroyInput( MiscData%u_Waves2, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyMisc @@ -6048,8 +6296,12 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6065,6 +6317,8 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -6122,8 +6376,12 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! u_WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%u_WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! u_WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%u_WAMIT2,1), UBOUND(InData%u_WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! u_WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! u_WAMIT2 + CALL WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! u_WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6139,6 +6397,8 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! u_Waves2: size of buffers for each call to pack subtype CALL Waves2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! u_Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -6371,7 +6631,18 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ENDIF END DO END IF - CALL WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6399,6 +6670,8 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6496,7 +6769,18 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ENDIF END DO END IF - CALL WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! u_WAMIT2 + IF ( .NOT. ALLOCATED(InData%u_WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%u_WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%u_WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%u_WAMIT2,1), UBOUND(InData%u_WAMIT2,1) + CALL WAMIT2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! u_WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6524,6 +6808,8 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Waves2, ErrStat2, ErrMsg2, OnlySize ) ! u_Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6868,6 +7154,20 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -6901,13 +7201,15 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -7044,6 +7346,20 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! u_WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%u_WAMIT2)) DEALLOCATE(OutData%u_WAMIT2) + ALLOCATE(OutData%u_WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%u_WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%u_WAMIT2,1), UBOUND(OutData%u_WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -7077,13 +7393,15 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_WAMIT2, ErrStat2, ErrMsg2 ) ! u_WAMIT2 + CALL WAMIT2_UnpackInput( Re_Buf, Db_Buf, Int_Buf, OutData%u_WAMIT2(i1), ErrStat2, ErrMsg2 ) ! u_WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -7163,9 +7481,22 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyParam( SrcParamData%WAMIT2, DstParamData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcParamData%WAMIT2)) THEN + i1_l = LBOUND(SrcParamData%WAMIT2,1) + i1_u = UBOUND(SrcParamData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstParamData%WAMIT2)) THEN + ALLOCATE(DstParamData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%WAMIT2,1), UBOUND(SrcParamData%WAMIT2,1) + CALL WAMIT2_CopyParam( SrcParamData%WAMIT2(i1), DstParamData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyParam( SrcParamData%Waves2, DstParamData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -7361,7 +7692,12 @@ SUBROUTINE HydroDyn_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%WAMIT) ENDIF - CALL WAMIT2_DestroyParam( ParamData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%WAMIT2)) THEN +DO i1 = LBOUND(ParamData%WAMIT2,1), UBOUND(ParamData%WAMIT2,1) + CALL WAMIT2_DestroyParam( ParamData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%WAMIT2) +ENDIF CALL Waves2_DestroyParam( ParamData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyParam( ParamData%Morison, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%WaveTime)) THEN @@ -7463,8 +7799,12 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -7480,6 +7820,8 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -7675,7 +8017,18 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ENDIF END DO END IF - CALL WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -7703,6 +8056,8 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -8095,6 +8450,20 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -8128,13 +8497,15 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -8995,9 +9366,22 @@ SUBROUTINE HydroDyn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - CALL WAMIT2_CopyOutput( SrcOutputData%WAMIT2, DstOutputData%WAMIT2, CtrlCode, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(SrcOutputData%WAMIT2)) THEN + i1_l = LBOUND(SrcOutputData%WAMIT2,1) + i1_u = UBOUND(SrcOutputData%WAMIT2,1) + IF (.NOT. ALLOCATED(DstOutputData%WAMIT2)) THEN + ALLOCATE(DstOutputData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOutputData%WAMIT2,1), UBOUND(SrcOutputData%WAMIT2,1) + CALL WAMIT2_CopyOutput( SrcOutputData%WAMIT2(i1), DstOutputData%WAMIT2(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF CALL Waves2_CopyOutput( SrcOutputData%Waves2, DstOutputData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -9036,7 +9420,12 @@ SUBROUTINE HydroDyn_DestroyOutput( OutputData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(OutputData%WAMIT) ENDIF - CALL WAMIT2_DestroyOutput( OutputData%WAMIT2, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WAMIT2)) THEN +DO i1 = LBOUND(OutputData%WAMIT2,1), UBOUND(OutputData%WAMIT2,1) + CALL WAMIT2_DestroyOutput( OutputData%WAMIT2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OutputData%WAMIT2) +ENDIF CALL Waves2_DestroyOutput( OutputData%Waves2, ErrStat, ErrMsg ) CALL Morison_DestroyOutput( OutputData%Morison, ErrStat, ErrMsg ) CALL MeshDestroy( OutputData%WAMITMesh, ErrStat, ErrMsg ) @@ -9104,8 +9493,12 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2 allocated yes/no + IF ( ALLOCATED(InData%WAMIT2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WAMIT2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) Int_BufSz = Int_BufSz + 3 ! WAMIT2: size of buffers for each call to pack subtype - CALL WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 + CALL WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9121,6 +9514,8 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + END DO + END IF Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -9245,7 +9640,18 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err ENDIF END DO END IF - CALL WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 + IF ( .NOT. ALLOCATED(InData%WAMIT2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT2,1), UBOUND(InData%WAMIT2,1) + CALL WAMIT2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT2(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9273,6 +9679,8 @@ SUBROUTINE HydroDyn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + END DO + END IF CALL Waves2_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9461,6 +9869,20 @@ SUBROUTINE HydroDyn_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT2)) DEALLOCATE(OutData%WAMIT2) + ALLOCATE(OutData%WAMIT2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT2,1), UBOUND(OutData%WAMIT2,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -9494,13 +9916,15 @@ SUBROUTINE HydroDyn_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL WAMIT2_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2, ErrStat2, ErrMsg2 ) ! WAMIT2 + CALL WAMIT2_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%WAMIT2(i1), ErrStat2, ErrMsg2 ) ! WAMIT2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -9903,8 +10327,12 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, E CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated - CALL WAMIT2_Output_ExtrapInterp1( y1%WAMIT2, y2%WAMIT2, tin, y_out%WAMIT2, tin_out, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(y_out%WAMIT2) .AND. ALLOCATED(y1%WAMIT2)) THEN + DO i01 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) + CALL WAMIT2_Output_ExtrapInterp1( y1%WAMIT2(i01), y2%WAMIT2(i01), tin, y_out%WAMIT2(i01), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated CALL Waves2_Output_ExtrapInterp1( y1%Waves2, y2%Waves2, tin, y_out%Waves2, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL Morison_Output_ExtrapInterp1( y1%Morison, y2%Morison, tin, y_out%Morison, tin_out, ErrStat2, ErrMsg2 ) @@ -9980,8 +10408,12 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSta CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated - CALL WAMIT2_Output_ExtrapInterp2( y1%WAMIT2, y2%WAMIT2, y3%WAMIT2, tin, y_out%WAMIT2, tin_out, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(y_out%WAMIT2) .AND. ALLOCATED(y1%WAMIT2)) THEN + DO i01 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) + CALL WAMIT2_Output_ExtrapInterp2( y1%WAMIT2(i01), y2%WAMIT2(i01), y3%WAMIT2(i01), tin, y_out%WAMIT2(i01), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ENDDO +END IF ! check if allocated CALL Waves2_Output_ExtrapInterp2( y1%Waves2, y2%Waves2, y3%Waves2, tin, y_out%Waves2, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL Morison_Output_ExtrapInterp2( y1%Morison, y2%Morison, y3%Morison, tin, y_out%Morison, tin_out, ErrStat2, ErrMsg2 ) From 9c031bdae14c61f38fa68cdd887ef5ed7466d8fd Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 23 Dec 2019 17:44:53 -0700 Subject: [PATCH 096/377] TCF: remove the WAMIT2_Output.f90, and cleanup --- modules/hydrodyn/CMakeLists.txt | 1 - modules/hydrodyn/src/HydroDyn.f90 | 9 +- modules/hydrodyn/src/HydroDyn_Input.f90 | 103 +---- modules/hydrodyn/src/WAMIT.txt | 8 +- modules/hydrodyn/src/WAMIT2.f90 | 24 - modules/hydrodyn/src/WAMIT2.txt | 5 +- modules/hydrodyn/src/WAMIT2_Output.f90 | 561 ------------------------ modules/hydrodyn/src/WAMIT2_Types.f90 | 219 +-------- modules/hydrodyn/src/WAMIT_Types.f90 | 219 +-------- 9 files changed, 23 insertions(+), 1126 deletions(-) delete mode 100644 modules/hydrodyn/src/WAMIT2_Output.f90 diff --git a/modules/hydrodyn/CMakeLists.txt b/modules/hydrodyn/CMakeLists.txt index e23123863..3c1021325 100644 --- a/modules/hydrodyn/CMakeLists.txt +++ b/modules/hydrodyn/CMakeLists.txt @@ -40,7 +40,6 @@ set(HYDRODYN_SOURCES src/UserWaves.f90 src/WAMIT.f90 src/WAMIT2.f90 - src/WAMIT2_Output.f90 src/WAMIT_Interp.f90 src/Waves.f90 src/Waves2.f90 diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 41f848e88..b58bd24a4 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1077,10 +1077,6 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I RETURN END IF - ELSE - - p%WAMIT2%NumOuts = 0 !This doesn't get initialized if we don't call WAMIT2_Init - ENDIF #ifdef USE_FIT @@ -1873,7 +1869,7 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt ! Determine the rotational angles from the direction-cosine matrix rotdisp = GetSmllRotAngs ( Inputs(I)%WAMITMesh%Orientation(:,:,1), ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_UpdateStates' ) Inputs_FIT(I)%roll = rotdisp(1) Inputs_FIT(I)%pitch = rotdisp(2) Inputs_FIT(I)%yaw = rotdisp(3) @@ -2067,8 +2063,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT2(1)%Mesh%Force (:,iBody) y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(1)%Mesh%Moment(:,iBody) end do -!FIXME: check how we should deal with m%F_Waves - ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + ! Add F_Waves2 to m%F_Waves m%F_Waves = m%F_Waves + m%WAMIT2(1)%F_Waves2 else do iBody=1,p%NBody diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index afb8859e6..7128fc5f9 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -26,7 +26,6 @@ MODULE HydroDyn_Input USE HydroDyn_Output USE Waves USE Morison - USE WAMIT2_Output USE Waves2_Output USE Morison_Output IMPLICIT NONE @@ -1131,100 +1130,6 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) -! !------------------------------------------------------------------------------------------------- -! ! Data section for Floating platform force flags -! !------------------------------------------------------------------------------------------------- -! -! ! Header -! -! CALL ReadCom( UnIn, FileName, 'Floating platform force flags header', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! -! ! PtfmSgFChr - Platform horizontal surge translation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmSgFChr, 'PtfmSgFChr', 'Platform horizontal surge translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmSgFChr ) ! Convert Line to upper case. -! -! -! ! PtfmSwFChr - Platform horizontal sway translation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmSwFChr, 'PtfmSwFChr', 'Platform horizontal sway translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmSwFChr ) ! Convert Line to upper case. -! -! -! ! PtfmHvFChr - Platform vertical heave translation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmHvFChr, 'PtfmHvFChr', 'Platform vertical heave translation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmHvFChr ) ! Convert Line to upper case. -! -! -! ! PtfmRFChr - Platform roll tilt rotation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmRFChr, 'PtfmRFChr', 'Platform roll tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmRFChr ) ! Convert Line to upper case. -! -! -! ! PtfmPFChr - Platform pitch tilt rotation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmPFChr, 'PtfmPFChr', 'Platform pitch tilt rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmPFChr ) ! Convert Line to upper case. -! -! -! ! PtfmYFChr - Platform yaw rotation force flag -! -! CALL ReadVar ( UnIn, FileName, InitInp%PtfmYFChr, 'PtfmYFChr', 'Platform yaw rotation force flag', ErrStat2, ErrMsg2, UnEchoLocal ) -! -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) -! IF (ErrStat >= AbortErrLev) THEN -! CALL CleanUp() -! RETURN -! END IF -! -! CALL Conv2UC( InitInp%PtfmYFChr ) ! Convert Line to upper case. - - - !------------------------------------------------------------------------------------------------- ! Floating Platform Additional Stiffness and Damping Section !------------------------------------------------------------------------------------------------- @@ -2370,7 +2275,7 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) ! OutList - list of requested parameters to output to a file - ALLOCATE( InitInp%UserOutputs(4526), Stat=ErrStat2) ! Total possible number of output channels: Waves2 = 18 + SS_Excitation = 7 + SS_Radiation = 7 + WAMIT2 = 6 + Morison= 4032 + HydroDyn=456 = 4526 + ALLOCATE( InitInp%UserOutputs(4583), Stat=ErrStat2) ! Total possible number of output channels: Waves2 = 18 + SS_Excitation = 7 + SS_Radiation = 7 + Morison= 4032 + HydroDyn=519 = 4583 IF (ErrStat2 /= 0) THEN CALL SetErrStat( ErrID_Fatal, 'Error allocating UserOutputs.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL CleanUp() @@ -4190,9 +4095,9 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! Extract Waves2 list InitInp%Waves2%NumOuts = GetWaves2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Waves2%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! Extract WAMIT2 list - InitInp%WAMIT2%NumOuts = GetWAMIT2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT2%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - +! ! Extract WAMIT2 list +! InitInp%WAMIT2%NumOuts = GetWAMIT2Channels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%WAMIT2%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) +! ! Extract Morison list !foundMask = .FALSE. InitInp%Morison%NumOuts = GetMorisonChannels ( InitInp%NUserOutputs, InitInp%UserOutputs, InitInp%Morison%OutList, foundMask, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index 723de28e0..e141365ec 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -43,7 +43,7 @@ typedef ^ ^ ReKi typedef ^ ^ INTEGER NStepWave - - - "" - typedef ^ ^ INTEGER NStepWave2 - - - "" - typedef ^ ^ ReKi WaveDOmega - - - "" - -typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin (needed for SS_Excitation module)" m +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin (needed for SS_Excitation module)" m typedef ^ ^ SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) typedef ^ ^ SiKi WaveTime {:} - - "" - typedef ^ ^ INTEGER WaveMod - - - "" - @@ -57,10 +57,7 @@ typedef ^ ^ INTEGER # # # Define outputs from the initialization routine here: -# -#typedef ^ InitOutputType MeshType OutputMesh - - - "" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "" - -typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "" - +typedef ^ InitOutputType ReKi NULLVAL - - - "" - # # # ..... States .................................................................................................................... @@ -145,4 +142,3 @@ typedef ^ InputType MeshType # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: typedef ^ OutputType MeshType Mesh - - - "Loads at the WAMIT reference point in the inertial frame" - -typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index ceeb7f4e6..d5cb9fd26 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -54,7 +54,6 @@ MODULE WAMIT2 USE WAMIT2_Types USE WAMIT_Interp - USE WAMIT2_Output USE NWTC_Library USE NWTC_FFTPACK @@ -706,17 +705,6 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini y%Mesh%RemapFlag = .TRUE. - - ! Initialize the outputs - CALL WMT2OUT_Init( InitInp, y, p, InitOut, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp - RETURN - END IF - - - !---------------------------------------------------------------------- !> 6. Set zero values for unused outputs. This is mostly so that the !! compiler does not complain. @@ -5482,18 +5470,6 @@ SUBROUTINE WAMIT2_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, END DO - - ! Map the calculated results into the AllOuts Array - CALL WMT2Out_MapOutputs(Time, y, m%F_Waves2, AllOuts, ErrStat, ErrMsg) - - - - ! Put the output data in the OutData array - DO I = 1,p%NumOuts - y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) - END DO - - END SUBROUTINE WAMIT2_CalcOutput diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index d479a39af..1b7a21e5c 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -67,9 +67,7 @@ typedef ^ ^ ReKi WvHiCOffS # Define outputs from the initialization routine here: # -#typedef ^ InitOutputType MeshType OutputMesh - - - "" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "" - -typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "" - +typedef ^ InitOutputType ReKi NULLVAL - - - "" - # ..... States .................................................................................................................... @@ -142,4 +140,3 @@ typedef ^ InputType MeshType Mesh # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: typedef ^ OutputType MeshType Mesh - - - "Loads at the platform reference point in the inertial frame" - -typedef ^ ^ ReKi WriteOutput {:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT2_Output.f90 b/modules/hydrodyn/src/WAMIT2_Output.f90 deleted file mode 100644 index 1ca00ee50..000000000 --- a/modules/hydrodyn/src/WAMIT2_Output.f90 +++ /dev/null @@ -1,561 +0,0 @@ -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2013-2015 National Renewable Energy Laboratory -! -! This file is part of HydroDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -MODULE WAMIT2_Output - - ! This MODULE stores variables used for output. - - USE NWTC_Library - USE WAMIT2_Types - !USE HydroDyn_Output_Types -! USE Waves - IMPLICIT NONE - - PRIVATE - - ! Indices for computing output channels: - ! NOTES: - ! (1) These parameters are in the order stored in "OutListParameters.xlsx" - ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter - - INTEGER(IntKi), PARAMETER :: OutStrLenM1 = ChanLen - - ! WAMIT2 Body Forces: - - INTEGER(IntKi), PARAMETER :: WavesF2xi = 1 - INTEGER(IntKi), PARAMETER :: WavesF2yi = 2 - INTEGER(IntKi), PARAMETER :: WavesF2zi = 3 - INTEGER(IntKi), PARAMETER :: WavesM2xi = 4 - INTEGER(IntKi), PARAMETER :: WavesM2yi = 5 - INTEGER(IntKi), PARAMETER :: WavesM2zi = 6 - - - -!End of code generated by Matlab script - - - INTEGER, PARAMETER :: FWaves2(6) = (/WavesF2xi,WavesF2yi,WavesF2zi,WavesM2xi,WavesM2yi,WavesM2zi/) - - - -! This code was generated by hand. - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(6) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "WAVESF2XI ","WAVESF2YI ","WAVESF2ZI ","WAVESM2XI ","WAVESM2YI ","WAVESM2ZI "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(6) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - WavesF2xi , WavesF2yi , WavesF2zi , WavesM2xi , WavesM2yi , WavesM2zi /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(6) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) "/) - - - REAL(ReKi) :: AllOuts(MaxWAMIT2Outputs) ! Array of all possible outputs - - ! ..... Public Subroutines ................................................................................................... - PUBLIC :: WMT2OUT_MapOutputs - PUBLIC :: WMT2OUT_WriteOutputNames - PUBLIC :: WMT2OUT_WriteOutputUnits - PUBLIC :: WMT2OUT_WriteOutputs - PUBLIC :: WMT2OUT_Init - PUBLIC :: WMT2OUT_DestroyParam - PUBLIC :: GetWAMIT2Channels - -CONTAINS - - - - -!==================================================================================================== -SUBROUTINE WMT2OUT_MapOutputs( CurrentTime, y, F_Waves2, AllOuts, ErrStat, ErrMsg ) -! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput -! This is called by WAMIT2_CalcOutput() at each time step. -!---------------------------------------------------------------------------------------------------- - REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds - TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! WAMIT2's output data - REAL(ReKi), INTENT( IN ) :: F_Waves2(6) - REAL(ReKi), INTENT( OUT ) :: AllOuts(MaxWAMIT2Outputs) - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I - - ErrStat = ErrID_None - ErrMsg = "" - - - ! TODO: use y%mesh for the forces instead of individual parameters - - AllOuts(FWaves2) = F_Waves2 - - - - - -END SUBROUTINE WMT2OUT_MapOutputs - - -!==================================================================================================== - -SUBROUTINE WMT2OUT_WriteOutputNames( UnOutFile, p, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file - TYPE(WAMIT2_ParameterType), INTENT( IN ) :: p ! WAMIT2 module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnOutFile,Frmt) 'Time', ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts ) - -END SUBROUTINE WMT2OUT_WriteOutputNames - -!==================================================================================================== - - -SUBROUTINE WMT2OUT_WriteOutputUnits( UnOutFile, p, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: UnOutFile ! file unit for the output file - TYPE(WAMIT2_ParameterType), INTENT( IN ) :: p ! WAMIT2 module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnOutFile,Frmt) '(sec)', ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts ) - -END SUBROUTINE WMT2OUT_WriteOutputUnits - -!==================================================================================================== -SUBROUTINE WMT2OUT_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) -! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file -! opened in WMT2OUT_Init() -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - INTEGER , INTENT( IN ) :: UnOutFile - REAL(DbKi), INTENT( IN ) :: Time ! Time for this output - TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! WAMIT2's output data - TYPE(WAMIT2_ParameterType),INTENT( IN ) :: p ! WAMIT2 parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables -! REAL(ReKi) :: OutData (0:p%NumOuts) ! an output array - INTEGER :: I ! Generic loop counter - CHARACTER(200) :: Frmt ! a string to hold a format statement - - - - ! Initialize ErrStat and determine if it makes any sense to write output - - IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnOutFile < 0 ) THEN - ErrMsg = ' No WAMIT2 outputs written. The OutParam array must be allocated and there must be a valid output file identifier before we can write outputs.' - ErrStat = ErrID_Warn - RETURN - ELSE - ErrStat = ErrID_None - ErrMsg = '' - END IF - - - - - - ! Write the output parameters to the file - - Frmt = '(F8.3,'//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - !Frmt = '('//TRIM( p%OutFmt )//','//TRIM(Int2LStr(p%NumOuts))//'(:,A,'//TRIM( p%OutFmt )//'))' - - WRITE(UnOutFile,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) - - - RETURN - - -END SUBROUTINE WMT2OUT_WriteOutputs - - - -!==================================================================================================== -SUBROUTINE WMT2OUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) -! This subroutine initialized the output module, checking if the output parameter list (OutList) -! contains valid names, and opening the output file if there are any requested outputs -!---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - - - TYPE(WAMIT2_InitInputType ), INTENT( IN ) :: InitInp ! data needed to initialize the output module - TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! This module's internal data - TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p - TYPE(WAMIT2_InitOutputType), INTENT( OUT ) :: InitOut - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables - INTEGER :: I ! Generic loop counter -! INTEGER :: J ! Generic loop counter -! INTEGER :: Indx ! Counts the current index into the WaveKinNd array -! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. -! CHARACTER(200) :: Frmt ! a string to hold a format statement - - !------------------------------------------------------------------------------------------------- - ! Initialize local variables - !------------------------------------------------------------------------------------------------- - - - ErrStat = ErrID_None - ErrMsg = "" - - - - - !------------------------------------------------------------------------------------------------- - ! Check that the variables in OutList are valid - !------------------------------------------------------------------------------------------------- - - - CALL WMT2OUT_ChkOutLst( InitInp%OutList(1:p%NumOuts), y, p, ErrStat, ErrMsg ) - IF ( ErrStat /= 0 ) RETURN - - - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file - - ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutput array.' - ErrStat = ErrID_Fatal - RETURN - END IF - y%WriteOutput = 0.0_ReKi - - ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WriteOutputHdr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - DO I = 1,p%NumOuts - - InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) - - END DO - - END IF ! there are any requested outputs - - RETURN - -END SUBROUTINE WMT2OUT_Init - - -!==================================================================================================== -FUNCTION GetWAMIT2Channels ( NUserOutputs, UserOutputs, OutList, foundMask, ErrStat, ErrMsg ) -! This routine checks the names of inputted output channels, checks to see if they -! below to the list of available WAMIT2 channels. - -!---------------------------------------------------------------------------------------------------- - INTEGER, INTENT( IN ) :: NUserOutputs ! Number of user-specified output channels - CHARACTER(10), INTENT( IN ) :: UserOutputs (:) ! An array holding the names of the requested output channels. - CHARACTER(10), INTENT( OUT ) :: OutList (:) ! An array holding the names of the matched WAMIT2 output channels. - LOGICAL, INTENT( INOUT ) :: foundMask (:) ! A mask indicating whether a user requested channel belongs to a module's output channels. - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER GetWAMIT2Channels ! The number of channels found in this module - - ! Local variables. - - INTEGER :: I ! Generic loop-counting index. - INTEGER :: count ! Generic loop-counting index. - INTEGER :: INDX ! Index for valid arrays - - CHARACTER(10) :: OutListTmp ! A string to temporarily hold OutList(I). - CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. -! LOGICAL :: InvalidOutput(MaxWAMIT2Outputs) ! This array determines if the output channel is valid for this configuration - LOGICAL :: CheckOutListAgain - - LOGICAL :: newFoundMask (NUserOutputs) ! A Mask indicating whether a user requested channel belongs to a modules output channels. - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - GetWAMIT2Channels = 0 - - newFoundMask = .FALSE. - - - DO I = 1,NUserOutputs - IF (.NOT. foundMask(I) ) THEN - OutListTmp = UserOutputs(I) - - CheckOutListAgain = .FALSE. - - ! Reverse the sign (+/-) of the output channel if the user prefixed the - ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". - - - - IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN - - OutListTmp = OutListTmp(2:) - ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) - CheckOutListAgain = .TRUE. - - END IF - - CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case - - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - - IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again - ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - END IF - - IF ( Indx > 0 ) THEN - newFoundMask(I) = .TRUE. - foundMask(I) = .TRUE. - GetWAMIT2Channels = GetWAMIT2Channels + 1 - - !ELSE - ! foundMask(I) = .FALSE. - END IF - END IF -END DO - - -IF ( GetWAMIT2Channels > 0 ) THEN - - count = 1 - ! Test that num channels does not exceed max possible channels due to size of OutList - !ALLOCATE ( OutList(GetWAMITChannels) , STAT=ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating memory for the OutList array in the GetWAMIT2Channels function.' - ErrStat = ErrID_Fatal - RETURN - END IF - - DO I = 1,NUserOutputs - IF ( newFoundMask(I) ) THEN - OutList(count) = UserOutputs(I) - count = count + 1 - END IF - - END DO - -END IF - - -END FUNCTION GetWAMIT2Channels - - -!==================================================================================================== -SUBROUTINE WMT2OUT_ChkOutLst( OutList, y, p, ErrStat, ErrMsg ) -! This routine checks the names of inputted output channels, checks to see if any of them are ill- -! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, -! name, and units of the output channels). -! Note that the Wamit module must be initialized prior to calling this function (if it -! is being used) so that it can correctly determine if the Lines outputs are valid. -!---------------------------------------------------------------------------------------------------- - - - - ! Passed variables - - TYPE(WAMIT2_OutputType), INTENT( INOUT ) :: y ! This module's internal data - TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT2 platform module - CHARACTER(10), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables. - - INTEGER :: I ! Generic loop-counting index. -! INTEGER :: J ! Generic loop-counting index. - INTEGER :: INDX ! Index for valid arrays - - CHARACTER(10) :: OutListTmp ! A string to temporarily hold OutList(I). - CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. - - - ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" -! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these -! lines should be modified in the Matlab script and/or Excel worksheet as necessary. -! This code was generated by Write_ChckOutLst.m at 09-Jan-2013 14:53:03. - - LOGICAL :: InvalidOutput(MaxWAMIT2Outputs) ! This array determines if the output channel is valid for this configuration - - LOGICAL :: CheckOutListAgain - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - InvalidOutput = .FALSE. - -!End of code generated by Matlab script - - !------------------------------------------------------------------------------------------------- - ! ALLOCATE the OutParam array - !------------------------------------------------------------------------------------------------- - ALLOCATE ( p%OutParam(p%NumOuts) , STAT=ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating memory for the OutParam array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - - - DO I = 1,p%NumOuts - - p%OutParam(I)%Name = OutList(I) - OutListTmp = OutList(I) - - - ! Reverse the sign (+/-) of the output channel if the user prefixed the - ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". - - CheckOutListAgain = .FALSE. - - IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN - p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) - CheckOutListAgain = .TRUE. - p%OutParam(I)%SignM = 1 - ELSE - p%OutParam(I)%SignM = 1 - END IF - - CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case - - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - - IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again - p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - END IF - - IF ( Indx > 0 ) THEN - p%OutParam(I)%Indx = ParamIndxAry(Indx) - IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%Indx = 1 - p%OutParam(I)%SignM = 0 - ELSE - p%OutParam(I)%Units = ParamUnitsAry(Indx) - END IF - ELSE - ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' - ErrStat = ErrID_Fatal -! RETURN - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%Indx = 1 - p%OutParam(I)%SignM = 0 ! this will print all zeros - END IF - - END DO - - - RETURN -END SUBROUTINE WMT2OUT_ChkOutLst - - -!==================================================================================================== -SUBROUTINE WMT2OUT_DestroyParam ( p, ErrStat, ErrMsg ) -! This function cleans up after running the WAMIT2 output module. It closes the output file, -! releases memory, and resets the number of outputs requested to 0. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - TYPE(WAMIT2_ParameterType), INTENT( INOUT ) :: p ! parameter data for this instance of the WAMIT2 module - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - -! ! Internal variables - LOGICAL :: Err - - - !------------------------------------------------------------------------------------------------- - ! Initialize error information - !------------------------------------------------------------------------------------------------- - ErrStat = ErrID_None - ErrMsg = "" - Err = .FALSE. - - - - !------------------------------------------------------------------------------------------------- - ! Deallocate arrays - !------------------------------------------------------------------------------------------------- - IF ( ALLOCATED( p%OutParam ) ) DEALLOCATE ( p%OutParam, STAT=ErrStat ) - IF ( ErrStat /= 0 ) Err = .TRUE. - - !------------------------------------------------------------------------------------------------- - ! Reset number of outputs - !------------------------------------------------------------------------------------------------- - p%NumOuts = 0 - p%UnOutFile = -1 - - !p%WaveKinNd = -1 ! set this array to "invalid" - - !------------------------------------------------------------------------------------------------- - ! Make sure ErrStat is non-zero if an error occurred - !------------------------------------------------------------------------------------------------- - IF ( Err ) ErrStat = ErrID_Fatal - - RETURN - -END SUBROUTINE WMT2OUT_DestroyParam -!==================================================================================================== - - -END MODULE WAMIT2_Output diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index d2248e64f..e956ab5d6 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -81,8 +81,7 @@ MODULE WAMIT2_Types ! ======================= ! ========= WAMIT2_InitOutputType ======= TYPE, PUBLIC :: WAMIT2_InitOutputType - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + REAL(ReKi) :: NULLVAL !< [-] END TYPE WAMIT2_InitOutputType ! ======================= ! ========= WAMIT2_ContinuousStateType ======= @@ -144,7 +143,6 @@ MODULE WAMIT2_Types ! ========= WAMIT2_OutputType ======= TYPE, PUBLIC :: WAMIT2_OutputType TYPE(MeshType) :: Mesh !< Loads at the platform reference point in the inertial frame [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] END TYPE WAMIT2_OutputType ! ======================= CONTAINS @@ -910,37 +908,13 @@ SUBROUTINE WAMIT2_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_CopyInitOutput' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN - ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr -ENDIF -IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN - ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt -ENDIF + DstInitOutputData%NULLVAL = SrcInitOutputData%NULLVAL END SUBROUTINE WAMIT2_CopyInitOutput SUBROUTINE WAMIT2_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -952,12 +926,6 @@ SUBROUTINE WAMIT2_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN - DEALLOCATE(InitOutputData%WriteOutputHdr) -ENDIF -IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN - DEALLOCATE(InitOutputData%WriteOutputUnt) -ENDIF END SUBROUTINE WAMIT2_DestroyInitOutput SUBROUTINE WAMIT2_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -995,16 +963,7 @@ SUBROUTINE WAMIT2_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no - IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr - END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no - IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt - END IF + Re_BufSz = Re_BufSz + 1 ! NULLVAL IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1032,40 +991,8 @@ SUBROUTINE WAMIT2_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%NULLVAL + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT2_PackInitOutput SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1087,7 +1014,6 @@ SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_UnPackInitOutput' @@ -1101,60 +1027,8 @@ SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF + OutData%NULLVAL = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT2_UnPackInitOutput SUBROUTINE WAMIT2_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -2600,7 +2474,6 @@ SUBROUTINE WAMIT2_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, E CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_CopyOutput' @@ -2610,18 +2483,6 @@ SUBROUTINE WAMIT2_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, E CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN - i1_l = LBOUND(SrcOutputData%WriteOutput,1) - i1_u = UBOUND(SrcOutputData%WriteOutput,1) - IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN - ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstOutputData%WriteOutput = SrcOutputData%WriteOutput -ENDIF END SUBROUTINE WAMIT2_CopyOutput SUBROUTINE WAMIT2_DestroyOutput( OutputData, ErrStat, ErrMsg ) @@ -2634,9 +2495,6 @@ SUBROUTINE WAMIT2_DestroyOutput( OutputData, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) -IF (ALLOCATED(OutputData%WriteOutput)) THEN - DEALLOCATE(OutputData%WriteOutput) -ENDIF END SUBROUTINE WAMIT2_DestroyOutput SUBROUTINE WAMIT2_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -2692,11 +2550,6 @@ SUBROUTINE WAMIT2_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no - IF ( ALLOCATED(InData%WriteOutput) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput - END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2752,19 +2605,6 @@ SUBROUTINE WAMIT2_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) - END IF END SUBROUTINE WAMIT2_PackOutput SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2786,7 +2626,6 @@ SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_UnPackOutput' @@ -2840,29 +2679,6 @@ SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) - ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) - DEALLOCATE(mask1) - END IF END SUBROUTINE WAMIT2_UnPackOutput @@ -3091,8 +2907,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp1' REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors ! Initialize ErrStat @@ -3109,14 +2923,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err END IF CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated END SUBROUTINE WAMIT2_Output_ExtrapInterp1 @@ -3148,8 +2954,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, INTEGER(IntKi) :: order ! order of polynomial fit (max 2) REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp2' @@ -3173,15 +2977,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, END IF CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) - c1 = ( (t(2)-t(3))*y1%WriteOutput + t(3)*y2%WriteOutput - t(2)*y3%WriteOutput ) / (t(2)*t(3)*(t(2) - t(3))) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated END SUBROUTINE WAMIT2_Output_ExtrapInterp2 END MODULE WAMIT2_Types diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index 29a0695a3..3f41d1a22 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -78,8 +78,7 @@ MODULE WAMIT_Types ! ======================= ! ========= WAMIT_InitOutputType ======= TYPE, PUBLIC :: WAMIT_InitOutputType - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + REAL(ReKi) :: NULLVAL !< [-] END TYPE WAMIT_InitOutputType ! ======================= ! ========= WAMIT_ContinuousStateType ======= @@ -160,7 +159,6 @@ MODULE WAMIT_Types ! ========= WAMIT_OutputType ======= TYPE, PUBLIC :: WAMIT_OutputType TYPE(MeshType) :: Mesh !< Loads at the WAMIT reference point in the inertial frame [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] END TYPE WAMIT_OutputType ! ======================= CONTAINS @@ -1168,37 +1166,13 @@ SUBROUTINE WAMIT_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_CopyInitOutput' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN - ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr -ENDIF -IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN - ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt -ENDIF + DstInitOutputData%NULLVAL = SrcInitOutputData%NULLVAL END SUBROUTINE WAMIT_CopyInitOutput SUBROUTINE WAMIT_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -1210,12 +1184,6 @@ SUBROUTINE WAMIT_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN - DEALLOCATE(InitOutputData%WriteOutputHdr) -ENDIF -IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN - DEALLOCATE(InitOutputData%WriteOutputUnt) -ENDIF END SUBROUTINE WAMIT_DestroyInitOutput SUBROUTINE WAMIT_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1253,16 +1221,7 @@ SUBROUTINE WAMIT_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no - IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr - END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no - IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt - END IF + Re_BufSz = Re_BufSz + 1 ! NULLVAL IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1290,40 +1249,8 @@ SUBROUTINE WAMIT_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%NULLVAL + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT_PackInitOutput SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1345,7 +1272,6 @@ SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_UnPackInitOutput' @@ -1359,60 +1285,8 @@ SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF + OutData%NULLVAL = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT_UnPackInitOutput SUBROUTINE WAMIT_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -5248,7 +5122,6 @@ SUBROUTINE WAMIT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, Er CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_CopyOutput' @@ -5258,18 +5131,6 @@ SUBROUTINE WAMIT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, Er CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN - i1_l = LBOUND(SrcOutputData%WriteOutput,1) - i1_u = UBOUND(SrcOutputData%WriteOutput,1) - IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN - ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstOutputData%WriteOutput = SrcOutputData%WriteOutput -ENDIF END SUBROUTINE WAMIT_CopyOutput SUBROUTINE WAMIT_DestroyOutput( OutputData, ErrStat, ErrMsg ) @@ -5282,9 +5143,6 @@ SUBROUTINE WAMIT_DestroyOutput( OutputData, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) -IF (ALLOCATED(OutputData%WriteOutput)) THEN - DEALLOCATE(OutputData%WriteOutput) -ENDIF END SUBROUTINE WAMIT_DestroyOutput SUBROUTINE WAMIT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -5340,11 +5198,6 @@ SUBROUTINE WAMIT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no - IF ( ALLOCATED(InData%WriteOutput) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput - END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5400,19 +5253,6 @@ SUBROUTINE WAMIT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) - END IF END SUBROUTINE WAMIT_PackOutput SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -5434,7 +5274,6 @@ SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_UnPackOutput' @@ -5488,29 +5327,6 @@ SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) - ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) - DEALLOCATE(mask1) - END IF END SUBROUTINE WAMIT_UnPackOutput @@ -5739,8 +5555,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp1' REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors ! Initialize ErrStat @@ -5757,14 +5571,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM END IF CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated END SUBROUTINE WAMIT_Output_ExtrapInterp1 @@ -5796,8 +5602,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, INTEGER(IntKi) :: order ! order of polynomial fit (max 2) REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp2' @@ -5821,15 +5625,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, END IF CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) - c1 = ( (t(2)-t(3))*y1%WriteOutput + t(3)*y2%WriteOutput - t(2)*y3%WriteOutput ) / (t(2)*t(3)*(t(2) - t(3))) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated END SUBROUTINE WAMIT_Output_ExtrapInterp2 END MODULE WAMIT_Types From f792a4b41a283f11d01a88e3622d3cb8384c161d Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 24 Dec 2019 12:32:09 -0700 Subject: [PATCH 097/377] TCF: fixed errors in 2nd order WAMIT arrays of types. Added a flag to track when the WAMIT2 submodule is actually used. If it was not in use, the array p%WAMIT2 was never allocated, which caused all sorts of weird errors and seg faults in the output handling (hard to track seg faults). --- modules/hydrodyn/src/HydroDyn.f90 | 220 +++++++++++++++-------- modules/hydrodyn/src/HydroDyn.txt | 2 + modules/hydrodyn/src/HydroDyn_Output.f90 | 6 +- modules/hydrodyn/src/HydroDyn_Types.f90 | 72 ++++++++ 4 files changed, 222 insertions(+), 78 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index b58bd24a4..981664c39 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -773,6 +773,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I +!FIXME: why is this called again? I'm either not remembering something, or I don't undestand the wave stretching above. -- ADP CALL Waves2_Init(InitLocal%Waves2, m%u_Waves2, p%Waves2, x%Waves2, xd%Waves2, z%Waves2, OtherState%Waves2, & y%Waves2, m%Waves2, Interval, InitOut%Waves2, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -827,6 +828,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I p%WaveElev(I,J) = p%Waves2%WaveElev2(I,J) + p%WaveElev(I,J) ENDDO ENDDO + CALL MOVE_ALLOC(p%Waves2%WaveElev2,p%WaveElev2) ENDIF ENDIF @@ -1007,14 +1009,22 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL MOVE_ALLOC(InitLocal%WAMIT%WaveElevC0, Waves_InitOut%WaveElevC0) CALL MOVE_ALLOC(InitLocal%WAMIT%WaveDirArr, Waves_InitOut%WaveDirArr) - + !----------------------------------------- ! Initialize the WAMIT2 Calculations !----------------------------------------- - + ! Only call the WAMIT2_Init if one of the flags is set for a calculation IF ( InitLocal%WAMIT2%MnDriftF .OR. InitLocal%WAMIT2%NewmanAppF .OR. InitLocal%WAMIT2%DiffQTFF .OR. InitLocal%WAMIT2%SumQTFF ) THEN + ! Flag required for indicating when to try using arrays that are allocated + p%WAMIT2used = .TRUE. + + ! Temporarily move arrays to init input for WAMIT2 (save some space) + CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT2%WaveTime) + CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT2%WaveElevC0) + CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT2%WaveDirArr) + ! Copy Waves initialization output into the initialization input type for the WAMIT module InitLocal%WAMIT2%RhoXg = Waves_InitOut%RhoXg InitLocal%WAMIT2%NStepWave = Waves_InitOut%NStepWave @@ -1022,12 +1032,10 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitLocal%WAMIT2%WaveDirMin = Waves_InitOut%WaveDirMin InitLocal%WAMIT2%WaveDirMax = Waves_InitOut%WaveDirMax InitLocal%WAMIT2%WaveDOmega = Waves_InitOut%WaveDOmega - InitLocal%WAMIT2%NBodyMod = InitLocal%NBodyMod ! There are restrictions in WAMIT2 on which files may be used for MnDriftF or NewmanAppF for BodyMod > 1 - ! Temporarily move arrays to init input for WAMIT2 (save some space) - CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT2%WaveTime) - CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%WAMIT2%WaveElevC0) - CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%WAMIT2%WaveDirArr) + ! Set values for all NBodyMods + InitLocal%WAMIT2%NBodyMod = InitLocal%NBodyMod ! There are restrictions in WAMIT2 on which files may be used for MnDriftF or NewmanAppF for BodyMod > 1 + InitLocal%WAMIT2%WAMITULEN = InitLocal%WAMITULEN(1) ! Determine how many WAMIT2 modules we need based on NBody and NBodyMod if (p%NBodyMod == 1) then @@ -1038,6 +1046,19 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I call AllocAry( InitLocal%WAMIT2%PtfmRefyt , InitLocal%NBody, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) call AllocAry( InitLocal%WAMIT2%PtfmRefzt , InitLocal%NBody, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) call AllocAry( InitLocal%WAMIT2%PtfmRefztRot, InitLocal%NBody, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + allocate( p%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array p%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( x%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array x%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( xd%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array xd%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( OtherState%WAMIT2(1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( y%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( m%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( m%u_WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%u_WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( InitOut%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + InitLocal%WAMIT2%PtfmRefxt (1) = InitLocal%PtfmRefxt (1) + InitLocal%WAMIT2%PtfmRefyt (1) = InitLocal%PtfmRefyt (1) + InitLocal%WAMIT2%PtfmRefzt (1) = InitLocal%PtfmRefzt (1) + InitLocal%WAMIT2%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(1) + else InitLocal%WAMIT2%NBody = 1_IntKi ! The WAMIT2 object will contain all NBody WAMIT2 bodies @@ -1046,6 +1067,18 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I call AllocAry( InitLocal%WAMIT2%PtfmRefyt , 1, "PtfmRefyt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) call AllocAry( InitLocal%WAMIT2%PtfmRefzt , 1, "PtfmRefzt" , ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) call AllocAry( InitLocal%WAMIT2%PtfmRefztRot, 1, "PtfmRefztRot", ErrStat2, ErrMsg2 ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + allocate( p%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array p%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( x%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array x%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( xd%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array xd%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( OtherState%WAMIT2(InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array OtherState%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( y%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array y%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( m%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( m%u_WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%u_WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( InitOut%WAMIT2( InitLocal%NBody), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + InitLocal%WAMIT2%PtfmRefxt (1) = InitLocal%PtfmRefxt (1) + InitLocal%WAMIT2%PtfmRefyt (1) = InitLocal%PtfmRefyt (1) + InitLocal%WAMIT2%PtfmRefzt (1) = InitLocal%PtfmRefzt (1) + InitLocal%WAMIT2%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(1) endif @@ -1061,13 +1094,32 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL CleanUp() RETURN END IF - + + ! For NBodyMod > 1 and NBody > 1, set the body info and init the WAMIT2 body + do i = 2, p%nWAMITObj + InitLocal%WAMIT2%WAMITFile = InitLocal%PotFile (i) + InitLocal%WAMIT2%WAMITULEN = InitLocal%WAMITULEN (i) + InitLocal%WAMIT2%PtfmRefxt (1) = InitLocal%PtfmRefxt (i) + InitLocal%WAMIT2%PtfmRefyt (1) = InitLocal%PtfmRefyt (i) + InitLocal%WAMIT2%PtfmRefzt (1) = InitLocal%PtfmRefzt (i) + InitLocal%WAMIT2%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(i) + + CALL WAMIT2_Init(InitLocal%WAMIT2, m%u_WAMIT2(i), p%WAMIT2(i), x%WAMIT2(i), xd%WAMIT2(i), z%WAMIT2, OtherState%WAMIT2(i), & + y%WAMIT2(i), m%WAMIT2(i), Interval, InitOut%WAMIT2(i), ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + end do + + ! move arrays back - CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveTime, p%WaveTime ) - CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveElevC0, Waves_InitOut%WaveElevC0) - CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveDirArr, Waves_InitOut%WaveDirArr) - - + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveTime, p%WaveTime ) + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveElevC0, Waves_InitOut%WaveElevC0) + CALL MOVE_ALLOC(InitLocal%WAMIT2%WaveDirArr, Waves_InitOut%WaveDirArr) + + ! Verify that WAMIT2_Init() did not request a different Interval! IF ( p%DT /= Interval ) THEN @@ -1076,7 +1128,16 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL CleanUp() RETURN END IF - + + ELSE + ! Flag used in output handling to indicate when to ignore WAMIT2 outputs. + p%WAMIT2used = .FALSE. + allocate( p%WAMIT2(1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array p%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + allocate( m%WAMIT2(1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT2.', ErrStat, ErrMsg, RoutineName ) + p%WAMIT2%MnDriftF = .FALSE. + p%WAMIT2%NewmanAppF = .FALSE. + p%WAMIT2%DiffQTFF = .FALSE. + p%WAMIT2%SumQTFF = .FALSE. ENDIF #ifdef USE_FIT @@ -1939,7 +2000,9 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = "" + ErrMsg = "" + WaveElev1 = 0.0_ReKi + WaveElev2 = 0.0_ReKi ! In case we don't use 2nd order waves ! Compute outputs here: @@ -2004,92 +2067,95 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, m%F_Waves = 0.0_ReKi - if ( m%u_WAMIT(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh - - if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then - ! Copy the inputs from the HD mesh into the WAMIT mesh - call MeshCopy( u%WAMITMesh, m%u_WAMIT(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - if ( ErrStat >= AbortErrLev ) return - - call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(1), p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), & - z%WAMIT, OtherState%WAMIT(1), y%WAMIT(1), m%WAMIT(1), ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - do iBody=1,p%NBody - y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(1)%Mesh%Force (:,iBody) - y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(1)%Mesh%Moment(:,iBody) - - end do - ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order - m%F_Waves = m%F_Waves + m%WAMIT(1)%F_Waves1 - else - do iBody=1,p%NBody - - ! We need to copy the iWAMIT-th node data from the Inputs(I)%WAMITMesh onto the 1st node of the Inputs_WAMIT(I)%Mesh - m%u_WAMIT(iBody)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iBody) - m%u_WAMIT(iBody)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iBody) - m%u_WAMIT(iBody)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iBody) - m%u_WAMIT(iBody)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iBody) - m%u_WAMIT(iBody)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iBody) - m%u_WAMIT(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) - - call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(iBody), p%WAMIT(iBody), x%WAMIT(iBody), xd%WAMIT(iBody), & - z%WAMIT, OtherState%WAMIT(iBody), y%WAMIT(iBody), m%WAMIT(iBody), ErrStat2, ErrMsg2 ) + if (allocated(m%u_WAMIT)) then ! Check that we allocated u_WAMIT, otherwise there is an error checking the mesh + if ( m%u_WAMIT(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh + + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + ! Copy the inputs from the HD mesh into the WAMIT mesh + call MeshCopy( u%WAMITMesh, m%u_WAMIT(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(iBody)%Mesh%Force (:,1) - y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(iBody)%Mesh%Moment(:,1) - + if ( ErrStat >= AbortErrLev ) return + + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(1), p%WAMIT(1), x%WAMIT(1), xd%WAMIT(1), & + z%WAMIT, OtherState%WAMIT(1), y%WAMIT(1), m%WAMIT(1), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + do iBody=1,p%NBody + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(1)%Mesh%Force (:,iBody) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(1)%Mesh%Moment(:,iBody) + + end do ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order - indxStart = (iBody-1)*6+1 - indxEnd = indxStart+5 - m%F_Waves(indxStart:indxEnd) = m%F_Waves(indxStart:indxEnd) + m%WAMIT(iBody)%F_Waves1 - end do - end if - end if + m%F_Waves = m%F_Waves + m%WAMIT(1)%F_Waves1 + else + do iBody=1,p%NBody + + ! We need to copy the iWAMIT-th node data from the Inputs(I)%WAMITMesh onto the 1st node of the Inputs_WAMIT(I)%Mesh + m%u_WAMIT(iBody)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iBody) + m%u_WAMIT(iBody)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iBody) + m%u_WAMIT(iBody)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iBody) + m%u_WAMIT(iBody)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iBody) + m%u_WAMIT(iBody)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iBody) + m%u_WAMIT(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) + + call WAMIT_CalcOutput( Time, p%WaveTime, m%u_WAMIT(iBody), p%WAMIT(iBody), x%WAMIT(iBody), xd%WAMIT(iBody), & + z%WAMIT, OtherState%WAMIT(iBody), y%WAMIT(iBody), m%WAMIT(iBody), ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT(iBody)%Mesh%Force (:,1) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT(iBody)%Mesh%Moment(:,1) + + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order + indxStart = (iBody-1)*6+1 + indxEnd = indxStart+5 + m%F_Waves(indxStart:indxEnd) = m%F_Waves(indxStart:indxEnd) + m%WAMIT(iBody)%F_Waves1 + end do + end if + end if ! m%u_WAMIT(1)%Mesh%Committed + end if ! m%u_WAMIT is allocated + + ! Second order - if ( m%u_WAMIT2(1)%Mesh%Committed ) then ! Make sure we are using WAMIT / there is a valid mesh - - if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then + if (p%WAMIT2used) then + + if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then ! Copy the inputs from the HD mesh into the WAMIT mesh - call MeshCopy( u%WAMITMesh, m%u_WAMIT2(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) - if ( ErrStat >= AbortErrLev ) return - + call MeshCopy( u%WAMITMesh, m%u_WAMIT2(1)%Mesh, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + if ( ErrStat >= AbortErrLev ) return call WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2(1), p%WAMIT2(1), x%WAMIT2(1), xd%WAMIT2(1), & z%WAMIT2, OtherState%WAMIT2(1), y%WAMIT2(1), m%WAMIT2(1), ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) do iBody=1,p%NBody y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT2(1)%Mesh%Force (:,iBody) - y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(1)%Mesh%Moment(:,iBody) + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(1)%Mesh%Moment(:,iBody) end do ! Add F_Waves2 to m%F_Waves m%F_Waves = m%F_Waves + m%WAMIT2(1)%F_Waves2 else do iBody=1,p%NBody - + ! We need to copy the iWAMIT2-th node data from the Inputs(I)%WAMIT2Mesh onto the 1st node of the Inputs_WAMIT2(I)%Mesh m%u_WAMIT2(iBody)%Mesh%TranslationDisp(:,1) = u%WAMITMesh%TranslationDisp(:,iBody) m%u_WAMIT2(iBody)%Mesh%Orientation (:,:,1)= u%WAMITMesh%Orientation (:,:,iBody) m%u_WAMIT2(iBody)%Mesh%TranslationVel (:,1) = u%WAMITMesh%TranslationVel (:,iBody) m%u_WAMIT2(iBody)%Mesh%RotationVel (:,1) = u%WAMITMesh%RotationVel (:,iBody) m%u_WAMIT2(iBody)%Mesh%TranslationAcc (:,1) = u%WAMITMesh%TranslationAcc (:,iBody) - m%u_WAMIT2(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) - + m%u_WAMIT2(iBody)%Mesh%RotationAcc (:,1) = u%WAMITMesh%RotationAcc (:,iBody) + call WAMIT2_CalcOutput( Time, p%WaveTime, m%u_WAMIT2(iBody), p%WAMIT2(iBody), x%WAMIT2(iBody), xd%WAMIT2(iBody), & z%WAMIT2, OtherState%WAMIT2(iBody), y%WAMIT2(iBody), m%WAMIT2(iBody), ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) y%WAMITMesh%Force (:,iBody) = y%WAMITMesh%Force (:,iBody) + y%WAMIT2(iBody)%Mesh%Force (:,1) - y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(iBody)%Mesh%Moment(:,1) - + y%WAMITMesh%Moment(:,iBody) = y%WAMITMesh%Moment(:,iBody) + y%WAMIT2(iBody)%Mesh%Moment(:,1) + ! Copy the F_Waves1 information to the HydroDyn level so we can combine it with the 2nd order indxStart = (iBody-1)*6+1 indxEnd = indxStart+5 m%F_Waves(indxStart:indxEnd) = m%F_Waves(indxStart:indxEnd) + m%WAMIT2(iBody)%F_Waves2 end do end if - end if - + end if ! p%WAMIT2used + #ifdef USE_FIT ELSE IF ( p%PotMod ==2 ) THEN !FIT Inputs_FIT%roll = rotdisp(1) @@ -2122,9 +2188,15 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Compute the wave elevations at the requested output locations for this time. Note that p%WaveElev has the second order added to it already. - DO I=1,p%NWaveElev - WaveElev2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%Waves2%WaveElev2(:,I), & - m%LastIndWave, p%NStepWave + 1 ) + ! Second order wave elevation, if calculated (This array is split out for speed because of the if) + if (allocated(p%WaveElev2)) then + DO I=1,p%NWaveElev + WaveElev2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev2(:,I), & + m%LastIndWave, p%NStepWave + 1 ) + END DO + endif + + DO I=1,p%NWaveElev WaveElev1(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev1(:,I), & m%LastIndWave, p%NStepWave + 1 ) WaveElev(I) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveElev(:,I), & diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 69ca90036..526a342ad 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -164,6 +164,7 @@ typedef ^ ParameterType INTEGER typedef ^ ^ INTEGER vecMultiplier - - - "multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1" - typedef ^ ^ WAMIT_ParameterType WAMIT {:} - - "Parameter data for the WAMIT module" - typedef ^ ^ WAMIT2_ParameterType WAMIT2 {:} - - "Parameter data for the WAMIT2 module" - +typedef ^ ^ LOGICAL WAMIT2used - .FALSE. - "Indicates when WAMIT2 is used. Shortcuts some calculations" - #typedef ^ ^ FIT_ParameterType FIT - - - "Parameter data for the FIT module" - typedef ^ ^ Waves2_ParameterType Waves2 - - - "Parameter data for the Waves2 module" - typedef ^ ^ Morison_ParameterType Morison - - - "Parameter data for the Morison module" - @@ -175,6 +176,7 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER NWaveElev - - - "Number of wave elevation outputs" - typedef ^ ^ SiKi WaveElev {:}{:} - - "Total wave elevation" - typedef ^ ^ SiKi WaveElev1 {:}{:} - - "First order wave elevation" - +typedef ^ ^ SiKi WaveElev2 {:}{:} - - "Second order wave elevation" - typedef ^ ^ ReKi WtrDpth - - - "Water depth" (m) typedef ^ ^ ReKi AddF0 {:}{:} - - "Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m)" - typedef ^ ^ ReKi AddCLin {:}{:}{:} - - "Additional stiffness matrix" - diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index 24a472d0a..3429ce12e 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -1148,8 +1148,6 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, m_WAMIT2, NWaveElev, Wa ErrStat = ErrID_None ErrMsg = "" - - ! Need to use individual components of force for output reporting, the y%mesh data has total forces from all contributions if ( p%potMod == 1 ) then @@ -1160,7 +1158,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, m_WAMIT2, NWaveElev, Wa AllOuts(FWaves1 (:,iBody)) = m_WAMIT(1)%F_Waves1(startIndx:endIndx) AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(1)%F_HS(startIndx:endIndx) AllOuts(FRdtn (:,iBody)) = m_WAMIT(1)%F_Rdtn(startIndx:endIndx) + m_WAMIT(1)%F_PtfmAM(startIndx:endIndx) - AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(1)%F_Waves2(startIndx:endIndx) ! These are reported by the WAMIT2 module + if (p%WAMIT2used) AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(1)%F_Waves2(startIndx:endIndx) ! These are reported by the WAMIT2 module AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) @@ -1178,7 +1176,7 @@ SUBROUTINE HDOut_MapOutputs( CurrentTime, p, y, m_WAMIT, m_WAMIT2, NWaveElev, Wa AllOuts(FWaves1 (:,iBody)) = m_WAMIT(iBody)%F_Waves1 AllOuts(FHdrSttc (:,iBody)) = m_WAMIT(iBody)%F_HS AllOuts(FRdtn (:,iBody)) = m_WAMIT(iBody)%F_Rdtn + m_WAMIT(iBody)%F_PtfmAM - AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(iBody)%F_Waves2 + if (p%WAMIT2used) AllOuts(FWaves2 (:,iBody)) = m_WAMIT2(iBody)%F_Waves2 AllOuts(FAdd (:,iBody)) = F_Add(startIndx:endIndx) AllOuts(FWavesTot(:,iBody)) = F_Waves(startIndx:endIndx) AllOuts(WBMotions(:,iBody)) = q(startIndx:endIndx) diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 4b85d2f2d..f2016a6bb 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -182,6 +182,7 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: vecMultiplier !< multiplier for the WAMIT vectors and matrices. If NBodyMod=1 then this = NBody, else 1 [-] TYPE(WAMIT_ParameterType) , DIMENSION(:), ALLOCATABLE :: WAMIT !< Parameter data for the WAMIT module [-] TYPE(WAMIT2_ParameterType) , DIMENSION(:), ALLOCATABLE :: WAMIT2 !< Parameter data for the WAMIT2 module [-] + LOGICAL :: WAMIT2used = .FALSE. !< Indicates when WAMIT2 is used. Shortcuts some calculations [-] TYPE(Waves2_ParameterType) :: Waves2 !< Parameter data for the Waves2 module [-] TYPE(Morison_ParameterType) :: Morison !< Parameter data for the Morison module [-] INTEGER(IntKi) :: PotMod !< 1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model [-] @@ -192,6 +193,7 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: NWaveElev !< Number of wave elevation outputs [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< Total wave elevation [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev1 !< First order wave elevation [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev2 !< Second order wave elevation [-] REAL(ReKi) :: WtrDpth !< Water depth [(m)] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddCLin !< Additional stiffness matrix [-] @@ -7497,6 +7499,7 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF + DstParamData%WAMIT2used = SrcParamData%WAMIT2used CALL Waves2_CopyParam( SrcParamData%Waves2, DstParamData%Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -7547,6 +7550,20 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er END IF END IF DstParamData%WaveElev1 = SrcParamData%WaveElev1 +ENDIF +IF (ALLOCATED(SrcParamData%WaveElev2)) THEN + i1_l = LBOUND(SrcParamData%WaveElev2,1) + i1_u = UBOUND(SrcParamData%WaveElev2,1) + i2_l = LBOUND(SrcParamData%WaveElev2,2) + i2_u = UBOUND(SrcParamData%WaveElev2,2) + IF (.NOT. ALLOCATED(DstParamData%WaveElev2)) THEN + ALLOCATE(DstParamData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev2 = SrcParamData%WaveElev2 ENDIF DstParamData%WtrDpth = SrcParamData%WtrDpth IF (ALLOCATED(SrcParamData%AddF0)) THEN @@ -7709,6 +7726,9 @@ SUBROUTINE HydroDyn_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%WaveElev1)) THEN DEALLOCATE(ParamData%WaveElev1) ENDIF +IF (ALLOCATED(ParamData%WaveElev2)) THEN + DEALLOCATE(ParamData%WaveElev2) +ENDIF IF (ALLOCATED(ParamData%AddF0)) THEN DEALLOCATE(ParamData%AddF0) ENDIF @@ -7822,6 +7842,7 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! WAMIT2used Int_BufSz = Int_BufSz + 3 ! Waves2: size of buffers for each call to pack subtype CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, .TRUE. ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -7875,6 +7896,11 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM IF ( ALLOCATED(InData%WaveElev1) ) THEN Int_BufSz = Int_BufSz + 2*2 ! WaveElev1 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WaveElev1) ! WaveElev1 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev2 allocated yes/no + IF ( ALLOCATED(InData%WaveElev2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev2) ! WaveElev2 END IF Re_BufSz = Re_BufSz + 1 ! WtrDpth Int_BufSz = Int_BufSz + 1 ! AddF0 allocated yes/no @@ -8058,6 +8084,8 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ENDIF END DO END IF + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%WAMIT2used , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -8168,6 +8196,22 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM IF (SIZE(InData%WaveElev1)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WaveElev1))-1 ) = PACK(InData%WaveElev1,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%WaveElev1) + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%WaveElev2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WaveElev2))-1 ) = PACK(InData%WaveElev2,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%WaveElev2) END IF ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth Re_Xferred = Re_Xferred + 1 @@ -8506,6 +8550,8 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + OutData%WAMIT2used = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -8670,6 +8716,32 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF (SIZE(OutData%WaveElev1)>0) OutData%WaveElev1 = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WaveElev1))-1 ), mask2, 0.0_ReKi ), SiKi) Re_Xferred = Re_Xferred + SIZE(OutData%WaveElev1) DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WaveElev2)) DEALLOCATE(OutData%WaveElev2) + ALLOCATE(OutData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%WaveElev2)>0) OutData%WaveElev2 = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WaveElev2))-1 ), mask2, 0.0_ReKi ), SiKi) + Re_Xferred = Re_Xferred + SIZE(OutData%WaveElev2) + DEALLOCATE(mask2) END IF OutData%WtrDpth = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 From e8db2fd7b6b4ca29a93391ab1819ab52255d43cf Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 24 Dec 2019 12:51:34 -0700 Subject: [PATCH 098/377] update of r-test pointer --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index 0c1567c56..4069ab44a 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 0c1567c56c3a90fa260ee430df4496ab60597587 +Subproject commit 4069ab44a8b1cad19a6c387ad3893e9a11016450 From e828a7874bac050ceeb0e9665323aa92a7ee3995 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 27 Dec 2019 07:45:44 -0700 Subject: [PATCH 099/377] FlexSub: implemented ball joint elimination --- modules/subdyn/src/SD_FEM.f90 | 127 +++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 33 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index b497a6114..d3ddc71b5 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -777,7 +777,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) iPrev =0 do iNode = 1, Init%NNode ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) - if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then + if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then nRot=3 else nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint @@ -794,7 +794,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) iOff = 6 endif m%ElemsDOF(iOff+1:iOff+3, idElem) = m%NodesDOF(iNode)%List(1:3) - if (Init%Nodes(iNode,iJointType) == idJointCantilever ) then + if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(4:6) else m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) @@ -829,8 +829,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) endif enddo else - print*,'Not performing safety check' ! remove me in the future - STOP + ! Safety check does not apply if some joints are non-cantilever endif CONTAINS @@ -896,7 +895,7 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) ! total unconstrained degrees of freedom of the system Init%TDOF = nDOF_Unconstrained() - print*,'nDOF_unconstrained',Init%TDOF, 6*Init%NNode + print*,'nDOF_unconstrained:',Init%TDOF, ' (if all Cantilever, it would be: ',6*Init%NNode,')' CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix @@ -961,7 +960,7 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() integer(IntKi) :: m nDOF_Unconstrained=0 do i = 1,Init%NNode - if (Init%Nodes(i,iJointType) == idJointCantilever ) then + if (int(Init%Nodes(i,iJointType)) == idJointCantilever ) then nDOF_Unconstrained = nDOF_Unconstrained + 6 else m = Init%NodesConnE(i,1) ! Col1: number of elements connected to this joint @@ -1051,9 +1050,11 @@ SUBROUTINE BuildTMatrix(Tred) integer(IntKi) :: nDOF integer(IntKi) :: aID, ia ! assembly ID, and index in IRA integer(IntKi) :: iNode + integer(IntKi) :: JType integer(IntKi) :: I integer(IntKi) :: nc !< Number of DOF after constraints applied integer(IntKi) :: nj + real(ReKi) :: phat(3) !< Directional vector of the joint ! --- Misc inits nullify(IDOFNew) @@ -1078,20 +1079,8 @@ SUBROUTINE BuildTMatrix(Tred) nc=0 if (allocated(Tc)) deallocate(Tc) if (allocated(IDOFOld)) deallocate(IDOFOld) - - if (Init%Nodes(iNode,iJointType) == idJointPin ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then - print*,'TODO T Build' - STOP - - elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then + JType = int(Init%Nodes(iNode,iJointType)) + if(JType == idJointCantilever ) then if ( NodeHasRigidElem(iNode, Init, p)) then ! This joint is involved in a rigid link assembly, we skip it (accounted for above) aID = RAm1(iNode) @@ -1117,15 +1106,18 @@ SUBROUTINE BuildTMatrix(Tred) IDOFOld = m%NodesDOF(iNode)%List(1:6) endif else - ErrMsg2='Wrong joint type'; ErrStat2=ErrID_Fatal + allocate(IDOFOld(1:len(m%NodesDOF(iNode)))) + IDOFOld(:) = m%NodesDOF(iNode)%List(:) + phat = Init%Nodes(iNode, iJointDir:iJointDir+2) + call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Tc, Init, p, ErrStat2, ErrMsg2) endif if (allocated(Tc)) then nc=size(Tc,2) call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - !print*,'N',iNode,'I ',IDOFOld - !print*,'N',iNode,'It',IDOFNew + print*,'N',iNode,'I ',IDOFOld + print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc iPrev = iPrev + nc else @@ -1152,6 +1144,7 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() integer(IntKi) :: iNode integer(IntKi) :: ia ! Index on rigid link assembly integer(IntKi) :: m ! Number of elements connected to a joint + integer(IntKi) :: NodeType nDOF_ConstraintReduced = 0 ! Rigid assemblies contribution @@ -1160,20 +1153,21 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() ! Contribution from all the other joints do iNode = 1, Init%NNode m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + NodeType = Init%Nodes(iNode,iJointType) - if (Init%Nodes(iNode,iJointType) == idJointPin ) then + if (NodeType == idJointPin ) then nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m - print*,'Node',iNode, 'is a pin joint' + print*,'Node',iNode, 'is a pin joint, number of members involved: ', m - elseif(Init%Nodes(iNode,iJointType) == idJointUniversal ) then + elseif(NodeType == idJointUniversal ) then nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m - print*,'Node',iNode, 'is an universal joint' + print*,'Node',iNode, 'is an universal joint, number of members involved: ', m - elseif(Init%Nodes(iNode,iJointType) == idJointBall ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 3*m - print*,'Node',iNode, 'is a ball joint' + elseif(NodeType == idJointBall ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 3 + 3*m + print*,'Node',iNode, 'is a ball joint, number of members involved: ', m - elseif(Init%Nodes(iNode,iJointType) == idJointCantilever ) then + elseif(NodeType == idJointCantilever ) then if ( NodeHasRigidElem(iNode, Init, p)) then ! This joint is involved in a rigid link assembly, we skip it (accounted for above) print*,'Node',iNode, 'is involved in a RA' @@ -1190,8 +1184,9 @@ END FUNCTION nDOF_ConstraintReduced END SUBROUTINE DirectElimination !------------------------------------------------------------------------------------------------------ -!> Returns constrains matrix for a rigid assembly (RA) formed by a set of elements. -!! +!> Returns constraint matrix Tc for a rigid assembly (RA) formed by a set of elements. +!! x_c = Tc.x_c_tilde +!! where x_c are all the DOF of the rigid assembly, and x_c_tilde are the 6 reduced DOF (leader DOF) SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements @@ -1269,6 +1264,72 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) Tc( ((i-1)*6)+1:6*i, 1:6) = TRigid(1:6,1:6) enddo END SUBROUTINE RAElimination +!------------------------------------------------------------------------------------------------------ +!> Returns constraint matrix Tc for a joint involving several Elements +!! x_c = Tc.x_c_tilde +!! where +! x_c are all the DOF of the joint (3 translation + 3*m, m the number of elements) +! x_c_tilde are the nc reduced DOF +SUBROUTINE JointElimination(Elements, JType, phat, Tc, Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements involved at a joint + integer(IntKi), INTENT(IN ) :: JType !< Joint type + real(ReKi), INTENT(IN ) :: phat(3) !< Directional vector of the joint + real(ReKi), dimension(:,:), allocatable :: Tc !< Transformation matrix from eliminated to full + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + !type(IList) :: I !< List of indices for Nodes involved in interface + integer(IntKi) :: i, ie, ne !< Loop index + integer(IntKi) :: nDOFr !< Number of reduced DOF + integer(IntKi) :: nDOFt !< Number of total DOF *nreduced) + !real(ReKi) :: P1(3), Pi(3) ! Nodal points + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ne = Elements(1) ! TODO TODO + nDOFt = 3 + 3*ne + + ! The elements already share the same translational DOF + + if (JType == idJointPin ) then + nDOFr = 5 + 1*ne + allocate(Tc(nDOFt, nDOFr)); + Tc(:,:)=0 + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + ! + print*,'TODO pin' + STOP + + elseif(JType == idJointUniversal ) then + nDOFr = 4 + 2*ne + allocate(Tc(nDOFt, nDOFr)); + Tc(:,:)=0 + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + ! + print*,'TODO univ' + STOP + + elseif(JType == idJointBall ) then + print*,'Elements',Elements + nDOFr = 3 + 3*ne + allocate(Tc(nDOFt, nDOFr)); + Tc(:,:)=0 + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + do i = 3,nDOFr; Tc(i,i)=1_ReKi; enddo ! Identity for other DOF as well + + else + ErrMsg='JointElimination: Wrong joint type'; ErrStat=ErrID_Fatal + endif + !do i=1,nDOFt + ! print*,'Tc',Tc(i,:) + !enddo + +END SUBROUTINE JointElimination !------------------------------------------------------------------------------------------------------ !> Setup a list of rigid link assemblies (RA) From 8a6eb26e72b169944c81413d2dc274d428415ac8 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 2 Jan 2020 10:33:02 -0700 Subject: [PATCH 100/377] FlexSub: pseudo inverse implemented --- modules/subdyn/src/FEM.f90 | 71 +++++++++++++++++++++++ modules/subdyn/src/SubDyn_Tests.f90 | 90 ++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index c1e6cfeee..125cce082 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -557,4 +557,75 @@ SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) !F(12) is 0 for g along z alone END SUBROUTINE LumpForces +!------------------------------------------------------------------------------------------------------ +!> +!! Method 1: pinv_A = A \ eye(m) (matlab) +!! call _GELSS to solve A.X=B +!! pinv(A) = B(1:n,1:m) +!! Method 2: [U,S,V] = svd(A); pinv_A = ( V / S ) * U'; (matlab) +! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' +SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) + use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM + real(LaKi), dimension(:,:), intent(inout) :: A + real(LaKi), dimension(:,:), allocatable :: Ainv + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! < Error message if ErrStat / = ErrID_None + ! + real(LaKi), dimension(:), allocatable :: S + real(LaKi), dimension(:,:), allocatable :: U + real(LaKi), dimension(:,:), allocatable :: Vt + real(LaKi), dimension(:), allocatable :: WORK + integer :: i, j ! Loop indices + integer :: M !< The number of rows of the input matrix A + integer :: N !< The number of columns of the input matrix A + integer :: K !< + integer :: L !< + integer :: LWORK !< + INTEGER :: INFO + M = size(A,1) + N = size(A,2) + K = min(M,N) + L = max(M,N) + LWORK = MAX(1,3*K +L,5*K) + allocate(S(K)); S = 0; + !! LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths + allocate(Work(LWORK)); Work=0 + allocate(U (M,K) ); U=0; + allocate(Vt(K,N) ); Vt=0; + allocate(Ainv(N,M)); Ainv=0; + + ! --- Compute the SVD of A + ! [U,S,V] = svd(A) + !call DGESVD ('S', 'S', M, N, A, M, S, U, M , Vt , K, WORK, LWORK, INFO) + call LAPACK_DGESVD('S', 'S', M, N, A, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) + + !--- Compute PINV = V**T * SIGMA * U**T in two steps + ! SIGMA = S^(-1)=1/S(j), S is diagonal + do j = 1, K + U(:,j) = U(:,j)/S(j) + end do + ! Compute Ainv = 1.0*V^t * U^t + 0.0*Ainv V*(inv(S))*U' + !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) + call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) + ! --- Compute rank + ! tol=maxval(shape(A))*epsilon(maxval(S)) + !r=0 + !do i=1,K + ! if(S(i) .gt. tol)then + ! r=r+1 + ! end if + !end do + ! --- Scale + !do j = 1, K + ! do i = 1, K + ! if (i .eq. j .and. i .le. r)then + ! s_inv(i,j)=1.0_reki/s(i) + ! else + ! s_inv(i,j)=0.0_reki + ! end if + ! end do + !end do + ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),V(1:r,:))) + END SUBROUTINE PseudoInverse + END MODULE FEM diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index a0b7d9aab..c5bfdd19b 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -13,6 +13,7 @@ module SubDyn_Tests test_equal_i0 end interface interface test_almost_equal; module procedure & + test_almost_equal_0, & test_almost_equal_1, & test_almost_equal_2 end interface @@ -113,6 +114,32 @@ subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) endif end subroutine + subroutine test_almost_equal_0(Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), intent(in) :: Ref !< + real(ReKi), intent(in) :: Try !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + real(ReKi) :: delta + ! + cpt=0 + delta=abs(Ref-Try) + if(delta>MINNORM) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta,' - Failed:',cpt + call test_fail(InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta + call test_success(InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=delta>MINNORM + endif + end subroutine subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) ! Arguments character(len=*), intent(in) :: Var @@ -232,7 +259,7 @@ subroutine Test_Transformations(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg - real(ReKi), dimension(3) :: P1, P2 + real(ReKi), dimension(3) :: P1, P2, e1, e2, e3 real(ReKi), dimension(3,3) :: DirCos, A, R0, Ref real(ReKi), dimension(6,6) :: T, Tref real(ReKi) :: L @@ -255,8 +282,68 @@ subroutine Test_Transformations(ErrStat,ErrMsg) Tref(3,4) = 3._ReKi; Tref(3,5) =-1._ReKi; call test_almost_equal('TRigid',Tref,T,1e-8,.true.,.true.) + + ! --- Orthogonal vectors + e1 = (/10,0,0/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi,-1._ReKi/),1e-8,.true.,.true.) + call test_almost_equal('orth',e3,(/0._ReKi,1._ReKi, 0._ReKi/),1e-8,.true.,.true.) + e1 = (/0,10,0/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi, 1._ReKi/),1e-8,.true.,.true.) + call test_almost_equal('orth',e3,(/1._ReKi,0._ReKi, 0._ReKi/),1e-8,.true.,.true.) + e1 = (/1,2,4/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e2), 1e-8, .true., .true.) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e3), 1e-8, .true., .true.) end subroutine Test_Transformations + + !> Linear algebra tests + subroutine Test_Linalg(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref + integer(IntKi) :: I, J + + ! --- Inverse of a 3x3 matrix + allocate(A(3,3)); allocate(Aref(3,3)) + A(1,1) = 7 ; A(1,2) = 2 ; A(1,3) = 1 ; + A(2,1) = 0 ; A(2,2) = 3 ; A(2,3) = -1 ; + A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; + Aref(1,1) =-2 ; Aref(1,2) = 8 ; Aref(1,3) = -5 ; + Aref(2,1) = 3 ; Aref(2,2) =-11; Aref(2,3) = 7 ; + Aref(3,1) = 9 ; Aref(3,2) =-34; Aref(3,3) = 21; + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8, .true., .true.) + deallocate(A ) + deallocate(Ainv) + deallocate(Aref) + + ! --- Inverse of a 3x6 matrix + allocate(A(3,6)) + allocate(Aref(6,3)) + A(1,:) = (/ 0, 1, 2, 0, 1, 2 /) + A(2,:) = (/ -1, 1, 2, -0, 0, 0 /) + A(3,:) = (/ -0, 0, 0, -1, 1, 2 /) + Aref(:,:) = transpose(reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /))) + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + call test_almost_equal('Inverse of 3x6 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6, .true., .true.) + deallocate(A ) + deallocate(Ainv) + deallocate(Aref) + + ! --- Inverse of a 6x3 matrix + allocate(A(6,3)) + allocate(Aref(3,6)) + A(:,1) = (/ 0, 1, 2, 0, 1, 2 /) + A(:,2) = (/ -1, 1, 2, -0, 0, 0 /) + A(:,3) = (/ -0, 0, 0, -1, 1, 2 /) + Aref(:,:) = reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /)) + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + call test_almost_equal('Inverse of 6x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6, .true., .true.) + end subroutine Test_Linalg + !> Series of tests for integer lists subroutine Test_lists(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat @@ -317,6 +404,7 @@ subroutine SD_Tests(ErrStat,ErrMsg) call Test_lists(ErrStat2, ErrMsg2) call Test_Transformations(ErrStat2, ErrMsg2) + call Test_Linalg(ErrStat2, ErrMsg2) end subroutine SD_Tests From 6583d6c6a80843c0b020a722c87125c6a9d6dede Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 4 Jan 2020 08:30:32 -0700 Subject: [PATCH 101/377] FlexSub: T-matrix implemented --- modules/subdyn/src/FEM.f90 | 71 ++++-- modules/subdyn/src/SD_FEM.f90 | 397 ++++++++++++++++++++-------------- 2 files changed, 283 insertions(+), 185 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 125cce082..db0ba1ce0 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -229,6 +229,40 @@ SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) END SUBROUTINE GetDirCos !------------------------------------------------------------------------------------------------------ +!> Returns two vectors orthonormal to the input vector +SUBROUTINE GetOrthVectors(e1, e2, e3, ErrStat, ErrMsg) + real(ReKi) , intent(in ) :: e1(3) !< + real(ReKi) , intent( out) :: e2(3) !< + real(ReKi) , intent( out) :: e3(3) !< + integer(IntKi), intent( out) :: ErrStat ! error status of the operation + character(*), intent( out) :: ErrMsg ! error message if errstat /= errid_none + real(ReKi) :: min_norm + real(ReKi) :: e2_norm + real(ReKi) :: e1b(3) + ErrMsg = "" + ErrStat = ErrID_None + + min_norm = min( abs(e1(1)), abs(e1(2)), abs(e1(3)) ) + ! Finding a good candidate for orthogonality + if (min_norm == abs(e1(1))) then; e2 = (/ 0._ReKi, -e1(3), e1(2) /) + else if (min_norm == abs(e1(2))) then; e2 = (/ e1(3) , 0._ReKi, -e1(1) /) + else if (min_norm == abs(e1(3))) then; e2 = (/-e1(2) , e1(1), 0._ReKi /) + endif + ! Normalizing + e2_norm=sqrt(e2(1)**2 + e2(2)**2 + e2(3)**2) + if (abs(e2_norm)<1e-8) then + ErrStat=ErrID_Fatal + ErrMsg='Failed to determine orthogonal vector' + e2=-99999._ReKi + e3=-99999._ReKi + return + endif + e2 = e2/e2_norm + e1b= e1/sqrt(e1(1)**2 + e1(2)**2 + e1(3)**2) + ! Third + e3 = cross_product(e1b,e2) +END SUBROUTINE GetOrthVectors +!------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for classical beam elements !! shear is true -- non-tapered Timoshenko beam !! shear is false -- non-tapered Euler-Bernoulli beam @@ -566,7 +600,7 @@ END SUBROUTINE LumpForces ! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM - real(LaKi), dimension(:,:), intent(inout) :: A + real(LaKi), dimension(:,:), intent(in) :: A real(LaKi), dimension(:,:), allocatable :: Ainv INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! < Error message if ErrStat / = ErrID_None @@ -575,13 +609,16 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) real(LaKi), dimension(:,:), allocatable :: U real(LaKi), dimension(:,:), allocatable :: Vt real(LaKi), dimension(:), allocatable :: WORK + real(LaKi), dimension(:,:), allocatable :: Acopy integer :: i, j ! Loop indices integer :: M !< The number of rows of the input matrix A integer :: N !< The number of columns of the input matrix A integer :: K !< integer :: L !< integer :: LWORK !< - INTEGER :: INFO + integer :: INFO + integer :: rank + real(ReKi) :: tol M = size(A,1) N = size(A,2) K = min(M,N) @@ -593,11 +630,12 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) allocate(U (M,K) ); U=0; allocate(Vt(K,N) ); Vt=0; allocate(Ainv(N,M)); Ainv=0; + allocate(Acopy(M,N)); Acopy=A; ! --- Compute the SVD of A ! [U,S,V] = svd(A) !call DGESVD ('S', 'S', M, N, A, M, S, U, M , Vt , K, WORK, LWORK, INFO) - call LAPACK_DGESVD('S', 'S', M, N, A, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) + call LAPACK_DGESVD('S', 'S', M, N, Acopy, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) !--- Compute PINV = V**T * SIGMA * U**T in two steps ! SIGMA = S^(-1)=1/S(j), S is diagonal @@ -608,24 +646,15 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) ! --- Compute rank - ! tol=maxval(shape(A))*epsilon(maxval(S)) - !r=0 - !do i=1,K - ! if(S(i) .gt. tol)then - ! r=r+1 - ! end if - !end do - ! --- Scale - !do j = 1, K - ! do i = 1, K - ! if (i .eq. j .and. i .le. r)then - ! s_inv(i,j)=1.0_reki/s(i) - ! else - ! s_inv(i,j)=0.0_reki - ! end if - ! end do - !end do - ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),V(1:r,:))) + tol=maxval(shape(A))*epsilon(maxval(S)) + rank=0 + do i=1,K + if(S(i) .gt. tol)then + rank=rank+1 + end if + end do + print*,'Rank',rank + ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),Vt(1:r,:))) END SUBROUTINE PseudoInverse END MODULE FEM diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d3ddc71b5..280bca594 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -202,9 +202,9 @@ END FUNCTION RigidLinkElements !------------------------------------------------------------------------------------------------------ !> Returns true if one of the element connected to the node is a rigid link LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) - INTEGER(IntKi), INTENT(IN ) :: iJoint - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT(IN) :: iJoint + TYPE(SD_InitType), INTENT(IN) :: Init + TYPE(SD_ParameterType), INTENT(IN) :: p ! Local variables integer(IntKi) :: ie !< Loop index on elements integer(IntKi) :: ei !< Element index @@ -913,7 +913,7 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) ! --- Assembly in global unconstrained system IDOF = m%ElemsDOF(1:12, i) - Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) + Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) ENDDO ! end loop over elements , i @@ -970,6 +970,172 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END FUNCTION END SUBROUTINE AssembleKM + +!------------------------------------------------------------------------------------------------------ +!> Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF +SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) + use IntegerList, only: init_list, find, pop, destroy_list, len + use IntegerList, only: print_list + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p + type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination + ! Local + real(ReKi), dimension(:,:), allocatable :: Tc + integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements + integer(IntKi), dimension(:), allocatable :: IDOFOld !< + integer(IntKi), dimension(:), pointer :: IDOFNew !< + real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 + integer(IntKi) :: iPrev + type(IList) :: IRA !< list of rigid assembly indices to process + integer(IntKi) :: nDOF + integer(IntKi) :: aID, ia ! assembly ID, and index in IRA + integer(IntKi) :: iNode + integer(IntKi) :: JType + integer(IntKi) :: I + integer(IntKi) :: nc !< Number of DOF after constraints applied + integer(IntKi) :: nj + real(ReKi) :: phat(3) !< Directional vector of the joint + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Misc inits + nullify(IDOFNew) + I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) + allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + + nDOF = nDOF_ConstraintReduced() + print*,'nDOF constraint elim', nDOF , '/' , Init%TDOF + CALL AllocAry( m%Tred, Init%TDOF, nDOF, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + Tred=0 + call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; + IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) + call print_list(IRA, 'List of RA indices') + + ! --- For each node: + ! - create list of indices I in the assembled vector of DOF + ! - create list of indices Itilde in the reduced vector of DOF + ! - increment iPrev by the number of DOF of Itilde + iPrev =0 + do iNode = 1, Init%NNode + if (allocated(Tc)) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + JType = int(Init%Nodes(iNode,iJointType)) + if(JType == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p)) then + ! --- Joint involved in a rigid link assembly + aID = RAm1(iNode) + ia = find(IRA, aID, ErrStat2, ErrMsg2) + print*,'Node',iNode, 'is involved in RA', aID, ia + if ( ia <= 0) then + ! This rigid assembly has already been processed, pass to next node + cycle + else + call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; + aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed + nj = size(INodesID) + allocate(IDOFOld(1:6*nj)) + do I=1, nj + IDOFOld( (I-1)*6+1 : I*6 ) = m%NodesDOF(INodesID(I))%List(1:6) + enddo + endif + else + ! --- Regular cantilever joint + allocate(Tc(1:6,1:6)) + allocate(IDOFOld(1:6)) + Tc=I6 + IDOFOld = m%NodesDOF(iNode)%List(1:6) + endif + else + ! --- Ball/Pin/Universal joint + allocate(IDOFOld(1:len(m%NodesDOF(iNode)))) + IDOFOld(:) = m%NodesDOF(iNode)%List(:) + phat = Init%Nodes(iNode, iJointDir:iJointDir+2) + call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return + endif + nc=size(Tc,2) + call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) + m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) + IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations + print*,'N',iNode,'I ',IDOFOld + print*,'N',iNode,'It',IDOFNew + Tred(IDOFOld, IDOFNew) = Tc + iPrev = iPrev + nc + enddo + ! --- Safety checks + if (len(IRA)>0) then + ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal + if(Failed()) return + endif + if (iPrev /= nDOF) then + ErrMsg2='Inconsistency in number of reduced DOF'; ErrStat2=ErrID_Fatal + if(Failed()) return + endif + call CleanUp_BuildTMatrix() +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'BuildTMatrix') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp_BuildTMatrix() + END FUNCTION Failed + + SUBROUTINE CleanUp_BuildTMatrix() + nullify(IDOFNew) + call destroy_list(IRA, ErrStat2, ErrMsg2) + if (allocated(Tc) ) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + if (allocated(INodesID)) deallocate(INodesID) + END SUBROUTINE CleanUp_BuildTMatrix + + !> Returns number of DOF after constraint reduction (via the matrix T) + INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() + integer(IntKi) :: iNode + integer(IntKi) :: ia ! Index on rigid link assembly + integer(IntKi) :: m ! Number of elements connected to a joint + integer(IntKi) :: NodeType + nDOF_ConstraintReduced = 0 + + ! Rigid assemblies contribution + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) + + ! Contribution from all the other joints + do iNode = 1, Init%NNode + m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + NodeType = Init%Nodes(iNode,iJointType) + + if (NodeType == idJointPin ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m + print*,'Node',iNode, 'is a pin joint, number of members involved: ', m + + elseif(NodeType == idJointUniversal ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m + print*,'Node',iNode, 'is an universal joint, number of members involved: ', m + + elseif(NodeType == idJointBall ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 3 + 3*m + print*,'Node',iNode, 'is a ball joint, number of members involved: ', m + + elseif(NodeType == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p)) then + ! This joint is involved in a rigid link assembly, we skip it (accounted for above) + print*,'Node',iNode, 'is involved in a RA' + else + ! That's a regular Cantilever joint + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 + !print*,'Node',iNode, 'is a regular cantilever' + endif + else + ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal + endif + end do + END FUNCTION nDOF_ConstraintReduced +END SUBROUTINE BuildTMatrix !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) @@ -984,7 +1150,6 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) ! Varaibles for rigid assembly type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - ! real(ReKi), dimension(:,:), allocatable :: MM, KK real(ReKi), dimension(:), allocatable :: FF integer(IntKi) :: nDOF @@ -993,7 +1158,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - call BuildTMatrix(m%Tred); if (Failed()) return + call BuildTMatrix(Init, p, RA, RAm1, m, m%Tred, ErrStat2, ErrMsg2); if (Failed()) return ! --- DOF elimination for system matrices and RHS vector ! Temporary backup of M and K of full system @@ -1035,152 +1200,7 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(RA )) deallocate(RA ) END SUBROUTINE CleanUp_DirectElimination - SUBROUTINE BuildTMatrix(Tred) - ! Variables for Building T - use IntegerList, only: init_list, find, pop, destroy_list, len - use IntegerList, only: print_list - real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination - real(ReKi), dimension(:,:), allocatable :: Tc - integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - integer(IntKi), dimension(:), allocatable :: IDOFOld !< - integer(IntKi), dimension(:), pointer :: IDOFNew !< - real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 - integer(IntKi) :: iPrev - type(IList) :: IRA !< list of rigid assembly indices to process - integer(IntKi) :: nDOF - integer(IntKi) :: aID, ia ! assembly ID, and index in IRA - integer(IntKi) :: iNode - integer(IntKi) :: JType - integer(IntKi) :: I - integer(IntKi) :: nc !< Number of DOF after constraints applied - integer(IntKi) :: nj - real(ReKi) :: phat(3) !< Directional vector of the joint - ! --- Misc inits - nullify(IDOFNew) - I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - - allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2) ! Indices of DOF for each joint, in reduced system - - nDOF = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', nDOF - CALL AllocAry( m%Tred, nDOF, nDOF, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - Tred=0 - call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); - IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) - call print_list(IRA, 'List of RA indices') - - ! --- For each node: - ! - create list of indices I in the assembled vector of DOF - ! - create list of indices Itilde in the reduced vector of DOF - ! - increment iPrev by the number of DOF of Itilde - iPrev =0 - do iNode = 1, Init%NNode - nc=0 - if (allocated(Tc)) deallocate(Tc) - if (allocated(IDOFOld)) deallocate(IDOFOld) - JType = int(Init%Nodes(iNode,iJointType)) - if(JType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then - ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - aID = RAm1(iNode) - ia = find(IRA, aID, ErrStat2, ErrMsg2) - print*,'Node',iNode, 'is involved in RA', aID, ia - if ( ia <= 0) then - ! This rigid assembly has already been processed, pass to next node - cycle - else - call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2) - aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed - nj = size(INodesID) - allocate(IDOFOld(1:6*nj)) - do I=1, nj - IDOFOld( (I-1)*6+1 : I*6 ) = m%NodesDOF(INodesID(I))%List(1:6) - enddo - endif - else - ! That's a regular Cantilever joint - allocate(Tc(1:6,1:6)) - allocate(IDOFOld(1:6)) - Tc=I6 - IDOFOld = m%NodesDOF(iNode)%List(1:6) - endif - else - allocate(IDOFOld(1:len(m%NodesDOF(iNode)))) - IDOFOld(:) = m%NodesDOF(iNode)%List(:) - phat = Init%Nodes(iNode, iJointDir:iJointDir+2) - call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Tc, Init, p, ErrStat2, ErrMsg2) - endif - if (allocated(Tc)) then - nc=size(Tc,2) - call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) - m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) - IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - print*,'N',iNode,'I ',IDOFOld - print*,'N',iNode,'It',IDOFNew - Tred(IDOFOld, IDOFNew) = Tc - iPrev = iPrev + nc - else - print*,'Error, Tc not allocated, TODO' - STOP - endif - enddo - ! --- Safety checks - if (len(IRA)>0) then - ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal - endif - - ! --- Cleanup - nullify(IDOFNew) - call destroy_list(IRA, ErrStat2, ErrMsg2) - if (allocated(Tc) ) deallocate(Tc) - if (allocated(IDOFOld)) deallocate(IDOFOld) - if (allocated(INodesID)) deallocate(INodesID) - - END SUBROUTINE BuildTMatrix - - !> Returns number of DOF after constraint reduction (via the matrix T) - INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() - integer(IntKi) :: iNode - integer(IntKi) :: ia ! Index on rigid link assembly - integer(IntKi) :: m ! Number of elements connected to a joint - integer(IntKi) :: NodeType - nDOF_ConstraintReduced = 0 - - ! Rigid assemblies contribution - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) - - ! Contribution from all the other joints - do iNode = 1, Init%NNode - m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint - NodeType = Init%Nodes(iNode,iJointType) - - if (NodeType == idJointPin ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m - print*,'Node',iNode, 'is a pin joint, number of members involved: ', m - - elseif(NodeType == idJointUniversal ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m - print*,'Node',iNode, 'is an universal joint, number of members involved: ', m - - elseif(NodeType == idJointBall ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 3 + 3*m - print*,'Node',iNode, 'is a ball joint, number of members involved: ', m - - elseif(NodeType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then - ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - print*,'Node',iNode, 'is involved in a RA' - else - ! That's a regular Cantilever joint - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 - !print*,'Node',iNode, 'is a regular cantilever' - endif - else - ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal - endif - end do - END FUNCTION nDOF_ConstraintReduced END SUBROUTINE DirectElimination !------------------------------------------------------------------------------------------------------ @@ -1192,8 +1212,8 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements real(ReKi), dimension(:,:), allocatable :: Tc integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables @@ -1270,24 +1290,27 @@ END SUBROUTINE RAElimination !! where ! x_c are all the DOF of the joint (3 translation + 3*m, m the number of elements) ! x_c_tilde are the nc reduced DOF -SUBROUTINE JointElimination(Elements, JType, phat, Tc, Init, p, ErrStat, ErrMsg) +SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements involved at a joint integer(IntKi), INTENT(IN ) :: JType !< Joint type real(ReKi), INTENT(IN ) :: phat(3) !< Directional vector of the joint + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p real(ReKi), dimension(:,:), allocatable :: Tc !< Transformation matrix from eliminated to full - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables !type(IList) :: I !< List of indices for Nodes involved in interface - integer(IntKi) :: i, ie, ne !< Loop index + integer(IntKi) :: i, j, ie, ne !< Loop index integer(IntKi) :: nDOFr !< Number of reduced DOF integer(IntKi) :: nDOFt !< Number of total DOF *nreduced) - !real(ReKi) :: P1(3), Pi(3) ! Nodal points - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 + real(ReKi) :: e1(3), e2(3), e3(3) ! forming orthonormal basis with phat + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + real(LaKi), dimension(:,:), allocatable :: Tc_rot !< Part of Tc just for rotational DOF + real(LaKi), dimension(:,:), allocatable :: Tc_rot_m1 !< Inverse of Tc_rot + real(ReKi) :: ColMean ErrStat = ErrID_None ErrMsg = "" @@ -1298,12 +1321,48 @@ SUBROUTINE JointElimination(Elements, JType, phat, Tc, Init, p, ErrStat, ErrMsg) if (JType == idJointPin ) then nDOFr = 5 + 1*ne - allocate(Tc(nDOFt, nDOFr)); + allocate(Tc (nDOFt, nDOFr)); + allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); Tc(:,:)=0 + Tc_rot_m1(:,:)=0 + + ! Normalizing + e3= phat/sqrt(phat(1)**2 + phat(2)**2 + phat(3)**2) + call GetOrthVectors(e3, e1, e2, ErrStat2, ErrMsg2); + print*,'e1',e1 + print*,'e2',e2 + print*,'e3',e3 + print*,'shape',shape(Tc_rot_m1) + print*,'ne',ne + print*,'nDOF',nDOFr, nDOFt + + ! Forming Tcm1, inverse of Tc + do ie=1,ne + Tc_rot_m1(1 , (ie-1)*3+1:ie*3 ) = e1(1:3)/ne + Tc_rot_m1(2 , (ie-1)*3+1:ie*3 ) = e2(1:3)/ne + Tc_rot_m1(ie+2, (ie-1)*3+1:ie*3 ) = e3(1:3) + enddo + ! Pseudo inverse: + call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) + !allocate(Tc_rot (nDOFt-3, nDOFr-3)); + !print*,'Tc_rm1',Tc_rot_m1(1,:) + !print*,'Tc_rm1',Tc_rot_m1(2,:) + !print*,'Tc_rm1',Tc_rot_m1(3,:) + !print*,'Tc_rot',Tc_rot(1,:) + !print*,'Tc_rot',Tc_rot(2,:) + !print*,'Tc_rot',Tc_rot(3,:) + !print*,'Tc_rot',Tc_rot(4,:) + !print*,'Tc_rot',Tc_rot(5,:) + !print*,'Tc_rot',Tc_rot(6,:) + !print*,'Tc_rot',Tc_rot(7,:) + !print*,'Tc_rot',Tc_rot(8,:) + !print*,'Tc_rot',Tc_rot(9,:) + + ! --- Forming Tc do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF - ! - print*,'TODO pin' - STOP + Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) + deallocate(Tc_rot) + deallocate(Tc_rot_m1) elseif(JType == idJointUniversal ) then nDOFr = 4 + 2*ne @@ -1329,6 +1388,16 @@ SUBROUTINE JointElimination(Elements, JType, phat, Tc, Init, p, ErrStat, ErrMsg) ! print*,'Tc',Tc(i,:) !enddo + ! --- Safety check + do j =1, size(Tc,2) + ColMean=0; do i=1,size(Tc,1) ; ColMean = ColMean + abs(Tc(i,j)); enddo + ColMean = ColMean/size(Tc,1) + if (ColMean<1e-6) then + ErrMsg='JointElimination: a reduced degree of freedom has a singular mapping.'; ErrStat=ErrID_Fatal + return + endif + enddo + END SUBROUTINE JointElimination !------------------------------------------------------------------------------------------------------ From 156bcad32ab96b767d95d6c49fdf464ebac9eaaf Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 4 Jan 2020 09:59:57 -0700 Subject: [PATCH 102/377] FlexSub: BugFix: index of concentrated mass --- modules/subdyn/src/SD_FEM.f90 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 280bca594..1a1ee67e4 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -281,7 +281,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) do I = 1, Init%NCMass JointID = Init%CMass(I,1) Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (Init%Interf(I,1)<=0) then + if (Init%CMass(I,1)<=0) then CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') return endif @@ -920,12 +920,18 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) ! add concentrated mass DO I = 1, Init%NCMass + iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added + ! Safety + if (Init%Nodes(iNode,iJointType) /= idJointCantilever) then + ErrMsg2='Concentrated mass is only for cantilever joints. Problematic node: '//trim(Num2LStr(iNode)); ErrStat2=ErrID_Fatal; + if(Failed()) return + endif DO J = 1, 3 - iGlob = m%NodesDOF(i)%List(J) ! ux, uy, uz + iGlob = m%NodesDOF(iNode)%List(J) ! ux, uy, uz Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) ENDDO DO J = 4, 6 - iGlob = m%NodesDOF(i)%List(J) ! theta_x, theta_y, theta_z + iGlob = m%NodesDOF(iNode)%List(J) ! theta_x, theta_y, theta_z Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) ENDDO ENDDO ! Loop on concentrated mass From 0a221e6e4b701f73f571d712e5eeaed3d37bdba0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 4 Jan 2020 10:06:41 -0700 Subject: [PATCH 103/377] FlexSub: additional damping and stiffness implemented --- modules/subdyn/src/SD_FEM.f90 | 64 ++++++++++++++++++++----- modules/subdyn/src/SubDyn.f90 | 9 ++-- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 65 ++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 14 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 1a1ee67e4..ae2fcc40f 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -881,13 +881,13 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, jn, kn + INTEGER :: I, J, K INTEGER :: iGlob REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector REAL(ReKi) :: FCe(12) ! Pretension force from cable element - INTEGER, DIMENSION(2) :: nn ! node number in element INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: iNode !< Node index integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system ErrMsg = "" @@ -1173,6 +1173,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call move_alloc(Init%FG, FF) ! Reallocating nDOF = size(m%Tred,2) + CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D', ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector @@ -1180,6 +1181,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) Init%M = matmul(transpose(m%Tred), matmul(MM, m%Tred)) Init%K = matmul(transpose(m%Tred), matmul(KK, m%Tred)) Init%FG = matmul(transpose(m%Tred), FF) + Init%D = 0 !< Used for additional stiffness call CleanUp_DirectElimination() @@ -1189,13 +1191,6 @@ LOGICAL FUNCTION Failed() Failed = ErrStat >= AbortErrLev if (Failed) call CleanUp_DirectElimination() END FUNCTION Failed - - !SUBROUTINE Fatal(ErrMsg_in) - ! character(len=*), intent(in) :: ErrMsg_in - ! call SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'DirectElimination'); - ! call CleanUp_DirectElimination() - !END SUBROUTINE Fatal - SUBROUTINE CleanUp_DirectElimination() ! Cleaning up memory if (allocated(MM )) deallocate(MM ) @@ -1205,8 +1200,6 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(RAm1)) deallocate(RAm1) if (allocated(RA )) deallocate(RA ) END SUBROUTINE CleanUp_DirectElimination - - END SUBROUTINE DirectElimination !------------------------------------------------------------------------------------------------------ @@ -1503,6 +1496,55 @@ END SUBROUTINE AddNeighbors END SUBROUTINE RigidLinkAssemblies + +!------------------------------------------------------------------------------------------------------ +!> Add stiffness and damping to some joints +SUBROUTINE InsertJointStiffDamp(p, m, Init, ErrStat, ErrMsg) + TYPE(SD_ParameterType), INTENT(IN ) :: p + TYPE(SD_MiscVarType),target, INTENT(IN ) :: m + TYPE(SD_InitType), INTENT(INOUT) :: Init + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: iNode, JType, iStart + real(ReKi) :: StifAdd, DampAdd + integer(IntKi), dimension(:), pointer :: Ifreerot + ErrStat = ErrID_None + ErrMsg = "" + do iNode = 1, Init%NNode + JType = int(Init%Nodes(iNode,iJointType)) + StifAdd = Init%Nodes(iNode, iJointStiff) + DampAdd = Init%Nodes(iNode, iJointDamp ) + if(JType == idJointCantilever ) then + ! Cantilever joints should not have damping or stiffness + if(StifAdd>0) then + ErrMsg='InsertJointStiffDamp: Additional stiffness should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; + return + endif + if(DampAdd>0) then + ErrMsg='InsertJointStiffDamp: Additional damping should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; + return + endif + else + ! Ball/Univ/Pin joints have damping/stiffness inserted at indices of "free rotation" + if ( JType == idJointBall ) then; iStart=4; + else if ( JType == idJointUniversal ) then; iStart=5; + else if ( JType == idJointPin ) then; iStart=6; + endif + Ifreerot=>m%NodesDOFtilde(iNode)%List(iStart:) + ! Ball/Pin/Universal joints + if(StifAdd>0) then + print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot + Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd + endif + if(DampAdd>0) then + print*,'DampAdd, Node',iNode,DampAdd, Ifreerot + Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd + endif + endif + enddo +END SUBROUTINE InsertJointStiffDamp + !> Apply constraint (Boundary conditions) on Mass and Stiffness matrices SUBROUTINE ApplyConstr(Init,p) TYPE(SD_InitType ),INTENT(INOUT):: Init diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 62ffff708..139ae2ba6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -317,7 +317,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO !Store mapping between nodes and elements CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return - ! --- Allocated DOF indices to joints and members + ! --- Allocate DOF indices to joints and members call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; ! Assemble Stiffness and mass matrix @@ -332,9 +332,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return - ! --- Elimination + ! --- Elimination of constraints (reset M, K, D) CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return - + + ! --- Additional Damping and stiffness at pin/ball/universal joints + CALL InsertJointStiffDamp(p, m, Init, ErrStat2, ErrMsg2); if(Failed()) return ! --- Craig-Bampton reduction (sets many parameters) CALL Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -1664,6 +1666,7 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) CALL CBApplyConstr(p%DOFI, p%DOFR, CBparams%DOFM, p%DOFL, & CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) + ! TODO TODO TODO Transform new damping matrix as well !................................ ! set values needed to calculate outputs and update states: !................................ diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index b32c192ab..f47bf1228 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -110,6 +110,7 @@ typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" +typedef ^ ^ ReKi D {:}{:} - - "System damping matrix" typedef ^ ^ ReKi F {:} - - "System force vector" N typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 6361d103e..4061391ca 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -147,6 +147,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D !< System damping matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] @@ -2939,6 +2940,20 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%M = SrcInitTypeData%M ENDIF +IF (ALLOCATED(SrcInitTypeData%D)) THEN + i1_l = LBOUND(SrcInitTypeData%D,1) + i1_u = UBOUND(SrcInitTypeData%D,1) + i2_l = LBOUND(SrcInitTypeData%D,2) + i2_u = UBOUND(SrcInitTypeData%D,2) + IF (.NOT. ALLOCATED(DstInitTypeData%D)) THEN + ALLOCATE(DstInitTypeData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%D = SrcInitTypeData%D +ENDIF IF (ALLOCATED(SrcInitTypeData%F)) THEN i1_l = LBOUND(SrcInitTypeData%F,1) i1_u = UBOUND(SrcInitTypeData%F,1) @@ -3110,6 +3125,9 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%M)) THEN DEALLOCATE(InitTypeData%M) ENDIF +IF (ALLOCATED(InitTypeData%D)) THEN + DEALLOCATE(InitTypeData%D) +ENDIF IF (ALLOCATED(InitTypeData%F)) THEN DEALLOCATE(InitTypeData%F) ENDIF @@ -3280,6 +3298,11 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%M) ! M END IF + Int_BufSz = Int_BufSz + 1 ! D allocated yes/no + IF ( ALLOCATED(InData%D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D) ! D + END IF Int_BufSz = Int_BufSz + 1 ! F allocated yes/no IF ( ALLOCATED(InData%F) ) THEN Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension @@ -3668,6 +3691,22 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%M) END IF + IF ( .NOT. ALLOCATED(InData%D) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D))-1 ) = PACK(InData%D,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D) + END IF IF ( .NOT. ALLOCATED(InData%F) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4327,6 +4366,32 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%M) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D)) DEALLOCATE(OutData%D) + ALLOCATE(OutData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D)>0) OutData%D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated Int_Xferred = Int_Xferred + 1 ELSE From b2bd51171498b4e8c0477ce1ccb3443da70e2b34 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 6 Jan 2020 10:27:52 -0700 Subject: [PATCH 104/377] FlexSub: universal joints --- modules/subdyn/src/FEM.f90 | 28 ++++++++++----------- modules/subdyn/src/SD_FEM.f90 | 46 +++++++++++++++-------------------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index db0ba1ce0..a3c15411a 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -268,7 +268,7 @@ END SUBROUTINE GetOrthVectors !! shear is false -- non-tapered Euler-Bernoulli beam SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa - REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t LOGICAL , INTENT( IN) :: Shear REAL(ReKi), INTENT(OUT) :: K(12, 12) ! Local variables @@ -345,7 +345,7 @@ END SUBROUTINE ElemK_Beam SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) REAL(ReKi), INTENT( IN) :: A, L, E REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t REAL(ReKi), INTENT(OUT) :: K(12, 12) ! Local variables REAL(ReKi) :: L0, Eps0, EAL0, EE @@ -387,7 +387,7 @@ END SUBROUTINE ElemK_Cable !> Element mass matrix for classical beam elements SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t REAL(ReKi), INTENT(OUT) :: M(12, 12) REAL(ReKi) :: t, rx, ry, po @@ -455,7 +455,7 @@ END SUBROUTINE ElemM_Beam !> Element stiffness matrix for pretension cable SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) REAL(ReKi), INTENT( IN) :: A, L, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t REAL(ReKi), INTENT(OUT) :: M(12, 12) ! Local variables REAL(ReKi) :: DC(12, 12) @@ -495,12 +495,12 @@ END SUBROUTINE ElemM_Cable !! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, !! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 SUBROUTINE ElemG(A, L, rho, DirCos, F, g) - REAL(ReKi), INTENT( IN ) :: A !< area - REAL(ReKi), INTENT( IN ) :: L !< element length - REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix (for determining distance between nodes 1 and 2) - REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1; 7-12 are loads for node 2. + REAL(ReKi), INTENT( IN ) :: A !< area + REAL(ReKi), INTENT( IN ) :: L !< element length + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1 ; 7-12 are loads for node 2. REAL(ReKi) :: TempCoeff REAL(ReKi) :: w ! weight per unit length @@ -527,9 +527,9 @@ END SUBROUTINE ElemG !------------------------------------------------------------------------------------------------------ !> SUBROUTINE ElemF_Cable(T0, DirCos, F) - REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< direction cosine matrix - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. + REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. ! Local variables REAL(ReKi) :: DC(12, 12) @@ -555,7 +555,7 @@ SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) REAL(ReKi), INTENT( IN ) :: g !< gravity REAL(ReKi), INTENT( IN ) :: L !< Length of element REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN ) :: DirCos(3, 3) !< Direction cosine matrix + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces !LOCALS REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ae2fcc40f..41009367a 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1328,13 +1328,6 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) ! Normalizing e3= phat/sqrt(phat(1)**2 + phat(2)**2 + phat(3)**2) call GetOrthVectors(e3, e1, e2, ErrStat2, ErrMsg2); - print*,'e1',e1 - print*,'e2',e2 - print*,'e3',e3 - print*,'shape',shape(Tc_rot_m1) - print*,'ne',ne - print*,'nDOF',nDOFr, nDOFt - ! Forming Tcm1, inverse of Tc do ie=1,ne Tc_rot_m1(1 , (ie-1)*3+1:ie*3 ) = e1(1:3)/ne @@ -1343,20 +1336,6 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) enddo ! Pseudo inverse: call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) - !allocate(Tc_rot (nDOFt-3, nDOFr-3)); - !print*,'Tc_rm1',Tc_rot_m1(1,:) - !print*,'Tc_rm1',Tc_rot_m1(2,:) - !print*,'Tc_rm1',Tc_rot_m1(3,:) - !print*,'Tc_rot',Tc_rot(1,:) - !print*,'Tc_rot',Tc_rot(2,:) - !print*,'Tc_rot',Tc_rot(3,:) - !print*,'Tc_rot',Tc_rot(4,:) - !print*,'Tc_rot',Tc_rot(5,:) - !print*,'Tc_rot',Tc_rot(6,:) - !print*,'Tc_rot',Tc_rot(7,:) - !print*,'Tc_rot',Tc_rot(8,:) - !print*,'Tc_rot',Tc_rot(9,:) - ! --- Forming Tc do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) @@ -1364,16 +1343,31 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) deallocate(Tc_rot_m1) elseif(JType == idJointUniversal ) then + if (ne/=2) then + ErrMsg='JointElimination: universal joints should only connect two elements.'; ErrStat=ErrID_Fatal + return + endif nDOFr = 4 + 2*ne allocate(Tc(nDOFt, nDOFr)); + allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); Tc(:,:)=0 + Tc_rot_m1(:,:)=0 ! Important init + ! Forming the inverse of Tc_rot + Tc_rot_m1(1,1:3) = p%ElemProps(Elements(1))%DirCos(:,3)/2._ReKi + Tc_rot_m1(1,4:6) = p%ElemProps(Elements(2))%DirCos(:,3)/2._ReKi + Tc_rot_m1(2,1:3) = p%ElemProps(Elements(1))%DirCos(:,1) + Tc_rot_m1(3,1:3) = p%ElemProps(Elements(1))%DirCos(:,2) + Tc_rot_m1(4,4:6) = p%ElemProps(Elements(2))%DirCos(:,1) + Tc_rot_m1(5,4:6) = p%ElemProps(Elements(2))%DirCos(:,2) + ! Pseudo inverse + call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) + ! --- Forming Tc do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF - ! - print*,'TODO univ' - STOP + Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) + deallocate(Tc_rot) + deallocate(Tc_rot_m1) elseif(JType == idJointBall ) then - print*,'Elements',Elements nDOFr = 3 + 3*ne allocate(Tc(nDOFt, nDOFr)); Tc(:,:)=0 @@ -1386,7 +1380,7 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) !do i=1,nDOFt ! print*,'Tc',Tc(i,:) !enddo - + STOP ! --- Safety check do j =1, size(Tc,2) ColMean=0; do i=1,size(Tc,1) ; ColMean = ColMean + abs(Tc(i,j)); enddo From f6d7956ca0b12ebb1fdb736761dfafc41d11cf2b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 6 Jan 2020 14:34:42 -0700 Subject: [PATCH 105/377] TCF: cleanup comments --- modules/hydrodyn/src/HydroDyn.f90 | 6 +--- modules/hydrodyn/src/HydroDyn_Input.f90 | 1 - modules/hydrodyn/src/WAMIT2.txt | 4 --- modules/hydrodyn/src/WAMIT2_Types.f90 | 45 ------------------------- 4 files changed, 1 insertion(+), 55 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 981664c39..f3c0a4742 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -663,9 +663,6 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL MOVE_ALLOC(Waves_InitOut%WaveElevC0, InitLocal%Waves2%WaveElevC0) CALL MOVE_ALLOC(Waves_InitOut%WaveDirArr, InitLocal%Waves2%WaveDirArr) - !bjj: note that this doesn't get called if .not. (InitLocal%Waves2%WvDiffQTFF .OR. InitLocal%Waves2%WvSumQTFF), so p%waves2%* never get set - ! however, they get queried later in the code!!!! I've set these parameters in an "else" statement, below - !========================================================================== ! Initialize Wave Stretching data for 2nd Order Waves !========================================================================== @@ -841,7 +838,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I p%Waves2%WvSumQTFF = .FALSE. p%Waves2%NumOuts = 0 - ENDIF + ENDIF ! InitLocal%Waves2%WvDiffQTFF .OR. InitLocal%Waves2%WvSumQTFF @@ -2012,7 +2009,6 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Additional stiffness, damping forces. These need to be placed on a point mesh which is located at the WAMIT reference point (WRP). ! This mesh will need to get mapped by the glue code for use by either ElastoDyn or SubDyn. !------------------------------------------------------------------- -!bjj: if these are false in the input file, the parameter verions of these variables don't get set: ! Deal with any output from the Waves2 module.... IF (p%Waves2%WvDiffQTFF .OR. p%Waves2%WvSumQTFF ) THEN diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 7128fc5f9..3c14f3d09 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -4180,7 +4180,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! WAMIT2 InitInp%WAMIT2%WtrDens = InitInp%Waves%WtrDens InitInp%WAMIT2%WaveMod = InitInp%Waves%WaveMod - InitInp%WAMIT2%OutAll = InitInp%OutAll InitInp%WAMIT2%HasWAMIT = InitInp%PotMod == 1 ! Morison InitInp%Morison%UnSum = InitInp%UnSum diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index 1b7a21e5c..d642f5167 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -42,10 +42,6 @@ typedef ^ ^ SiKi WaveDirMin typedef ^ ^ SiKi WaveDirMax - - - "Maximum wave direction from Waves module" - typedef ^ ^ SiKi WaveTime {:} - - "Simulation times at which the instantaneous second order loads associated with the incident waves are determined" sec -typedef ^ ^ CHARACTER(10) OutList {27} - - "This should really be dimensioned with MaxOutPts" - -typedef ^ ^ LOGICAL OutAll - - - "" - -typedef ^ ^ INTEGER NumOuts - - - "" - -typedef ^ ^ INTEGER NumOutAll - - - "" - typedef ^ ^ INTEGER WaveMod - - - "The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here." - #[note: only one of MnDriff / NewmanApp / DiffQTF can be non-zero diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index e956ab5d6..c9d0de30a 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -58,10 +58,6 @@ MODULE WAMIT2_Types REAL(SiKi) :: WaveDirMin !< Minimum wave direction from Waves module [-] REAL(SiKi) :: WaveDirMax !< Maximum wave direction from Waves module [-] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] - CHARACTER(10) , DIMENSION(1:27) :: OutList !< This should really be dimensioned with MaxOutPts [-] - LOGICAL :: OutAll !< [-] - INTEGER(IntKi) :: NumOuts !< [-] - INTEGER(IntKi) :: NumOutAll !< [-] INTEGER(IntKi) :: WaveMod !< The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here. [-] INTEGER(IntKi) :: MnDrift !< Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] INTEGER(IntKi) :: NewmanApp !< Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] @@ -263,10 +259,6 @@ SUBROUTINE WAMIT2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E END IF DstInitInputData%WaveTime = SrcInitInputData%WaveTime ENDIF - DstInitInputData%OutList = SrcInitInputData%OutList - DstInitInputData%OutAll = SrcInitInputData%OutAll - DstInitInputData%NumOuts = SrcInitInputData%NumOuts - DstInitInputData%NumOutAll = SrcInitInputData%NumOutAll DstInitInputData%WaveMod = SrcInitInputData%WaveMod DstInitInputData%MnDrift = SrcInitInputData%MnDrift DstInitInputData%NewmanApp = SrcInitInputData%NewmanApp @@ -401,10 +393,6 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime END IF - Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList - Int_BufSz = Int_BufSz + 1 ! OutAll - Int_BufSz = Int_BufSz + 1 ! NumOuts - Int_BufSz = Int_BufSz + 1 ! NumOutAll Int_BufSz = Int_BufSz + 1 ! WaveMod Int_BufSz = Int_BufSz + 1 ! MnDrift Int_BufSz = Int_BufSz + 1 ! NewmanApp @@ -573,18 +561,6 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IF (SIZE(InData%WaveTime)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WaveTime))-1 ) = PACK(InData%WaveTime,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%WaveTime) END IF - DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) - DO I = 1, LEN(InData%OutList) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutAll , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOutAll - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%WaveMod Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MnDrift @@ -847,27 +823,6 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + SIZE(OutData%WaveTime) DEALLOCATE(mask1) END IF - i1_l = LBOUND(OutData%OutList,1) - i1_u = UBOUND(OutData%OutList,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) - DO I = 1, LEN(OutData%OutList) - OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - OutData%OutAll = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%NumOuts = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NumOutAll = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 OutData%WaveMod = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%MnDrift = IntKiBuf( Int_Xferred ) From ddf726a84ab0999a2e67efac91c89e4782af26ae Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 6 Jan 2020 14:38:49 -0700 Subject: [PATCH 106/377] TCF: change array sizes to 6*p%NBody for forces --- modules/hydrodyn/src/WAMIT2.f90 | 106 ++++++++++++++------------ modules/hydrodyn/src/WAMIT2.txt | 2 +- modules/hydrodyn/src/WAMIT2_Types.f90 | 62 +++++++++++++-- 3 files changed, 116 insertions(+), 54 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index d5cb9fd26..83a4b4d88 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -242,7 +242,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini TYPE(W2_SumData_Type) :: SumQTFData !< Data storage for the full sum QTF method ! Force arrays - REAL(SiKi) :: MnDriftForce(6) !< MnDrift force array. Constant for all time. First index is force component + REAL(SiKi) :: MnDriftForce(:) !< MnDrift force array. Constant for all time. First index is force component REAL(SiKi), ALLOCATABLE :: NewmanAppForce(:,:) !< NewmanApp force array. Index 1: Time, Index 2: force component REAL(SiKi), ALLOCATABLE :: DiffQTFForce(:,:) !< DiffQTF force array. Index 1: Time, Index 2: force component REAL(SiKi), ALLOCATABLE :: SumQTFForce(:,:) !< SumQTF force array. Index 1: Time, Index 2: force component @@ -523,6 +523,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini +!FIXME: does this actually need to be passed in? All body iterations occur within each init routine +ThisBodyNum=1 !> If the MnDrift method will be used, call the subroutine to calculate the force time series IF ( p%MnDriftF ) THEN @@ -594,7 +596,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%MnDriftF ) THEN - DO I=1,6 ! Loop through load components. Set ones that are calculated. + DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. IF ( p%MnDriftDims(I) ) THEN p%WaveExctn2(:,I) = MnDriftForce(I) ENDIF @@ -602,7 +604,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ELSE IF ( p%NewmanAppF ) THEN - DO I=1,6 ! Loop through load components. Set ones that are calculated. + DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. IF ( p%NewmanAppDims(I) ) THEN p%WaveExctn2(:,I) = NewmanAppForce(:,I) ENDIF @@ -610,7 +612,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ELSE IF ( p%DiffQTFF ) THEN - DO I=1,6 ! Loop through load components. Set ones that are calculated. + DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. IF ( p%DiffQTFDims(I) ) THEN p%WaveExctn2(:,I) = DiffQTFForce(:,I) ENDIF @@ -622,7 +624,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Summation method IF ( p%SumQTFF ) THEN - DO I=1,6 ! Loop through load components. Set ones that are calculated. + DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. IF ( p%SumQTFDims(I) ) THEN ! Add the sum force to the difference force calculated above (if there was one). Loop through all timesteps. DO J=1,InitInp%NStepWave @@ -642,7 +644,6 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini - !---------------------------------------------------------------------- !> 5. Create the mesh used for exporting the 2nd order forces from the !! WAMIT2_CalcOuput routine at each timestep. Also set the outputs @@ -671,7 +672,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini DO ThisBodyNum = 1,p%NBody ! Set orientation and position for each body in mesh - theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(ThisBodyNum)/) + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(ThisBodyNum)/) ! angle in radians orientation = EulerConstruct(theta) XYZloc = (/InitInp%PtfmRefxt(ThisBodyNum), InitInp%PtfmRefyt(ThisBodyNum), InitInp%PtfmRefzt(ThisBodyNum)/) @@ -712,6 +713,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini x%DummyContState = 0.0_SiKi xd%DummyDiscState = 0.0_SiKi z%DummyConstrState = 0.0_SiKi + CALL AllocAry( m%LastIndWave, p%NBody, 'm%LastIndWave', ErrStatTmp, ErrMsgTmp) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) m%LastIndWave = 1_IntKi OtherState%DummyOtherState = 0 @@ -783,7 +786,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: MnDriftData !< Data storage for the MnDrift method. Set to INOUT in case we need to convert 4D to 3D - REAL(SiKi), INTENT( OUT) :: MnDriftForce(6) !< Force data. Index 1 is the force component. Constant for all time. + REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: MnDriftForce(:) !< Force data. Index 1 is the force component. Constant for all time. CHARACTER(*), INTENT( OUT) :: ErrMsg INTEGER(IntKi), INTENT( OUT) :: ErrStat @@ -820,6 +823,14 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ErrMsgTmp = '' ErrStat = ErrID_None ErrStatTmp = ErrID_None + + ! Initialize resulting forces + ALLOCATE( MnDriftForce(6*p%NBody), STAT=ErrStatTmp ) + IF (ErrStatTmp /= 0) THEN + CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the resulting mean drift force '// & + 'of the 2nd order force.',ErrStat, ErrMsg, RoutineName) + RETURN + ENDIF MnDriftForce = 0.0_SiKi @@ -1087,7 +1098,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ! Now loop through all the dimensions and perform the calculation - DO I=1,6 + DO I=1,6*p%NBody ! Set the MnDrift force to 0.0 (Even ones we don't calculate) MnDriftForce(I) = 0.0_SiKi @@ -1175,8 +1186,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ! Now put it all together... note the frequency stepsize is multiplied after the summation MnDriftForce(I) = MnDriftForce(I) + REAL(QTF_Value * aWaveElevC * CONJG(aWaveElevC)) !bjj: put QTF_Value first so that if it's zero, the rest gets set to zero (to hopefully avoid overflow issues) - ENDDO - + ENDDO ! NStepWave2 ENDIF ! Load component to calculate @@ -1562,7 +1572,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ALLOCATE( NewmanTerm2C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & 'approximation in the frequency domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( NewmanAppForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + ALLOCATE( NewmanAppForce( 0:InitInp%NStepWave, 6*p%NBody), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the resulting Newmans '// & 'approximation of the 2nd order force.',ErrStat, ErrMsg, RoutineName) @@ -2009,7 +2019,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ALLOCATE( TmpComplexArr( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( DiffQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + ALLOCATE( DiffQTFForce( 0:InitInp%NStepWave, 6*p%NBody), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) @@ -2073,7 +2083,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ! Now loop through all the dimensions and perform the calculation - DO I=1,6 + DO I=1,6*p%NBody ! Only on the dimensions we requested, and it exists in the dataset IF ( p%DiffQTFDims(I) .AND. DiffQTFData%Data4D%LoadComponents(I) ) THEN @@ -2454,7 +2464,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er ALLOCATE( Term2Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & 'QTF 2nd order force in the time domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( SumQTFForce( 0:InitInp%NStepWave, 6), STAT=ErrStatTmp ) + ALLOCATE( SumQTFForce( 0:InitInp%NStepWave, 6*p%NBody), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the full difference '// & 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) @@ -2485,7 +2495,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er ! Now loop through all the dimensions and perform the calculation - DO I=1,6 + DO I=1,6*p%NBody ! Only on the dimensions we requested, and if it is present in the data IF ( p%SumQTFDims(I) .AND. SumQTFData%Data4D%LoadComponents(I) ) THEN @@ -3063,6 +3073,13 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff p%NBody = InitInp%NBody ! Number of bodies WAMIT2 sees p%NBodyMod = InitInp%NBodyMod ! How multiple bodys are treated + ! This module's implementation requires that if NBodyMod = 2 or 3, then there is one instance of a WAMIT module for each body, therefore, HydroDyn may have NBody > 1, but this WAMIT module will have NBody = 1 + if ( (p%NBodyMod > 1) .and. (p%NBody > 1) ) then + CALL SetErrStat( ErrID_Fatal, "DEVELOPER ERROR: If NBodyMod = 2 or 3, then NBody for the a WAMIT2 object must be equal to 1", ErrStat, ErrMsg, RoutineName) + CALL CleanUp + return + end if + !-------------------------------------------------------------------------------- !> ### Flags indicating forces to calculate for with each method @@ -3102,10 +3119,6 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ELSE p%MnDriftDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something ENDIF - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp - RETURN - ENDIF @@ -3125,10 +3138,6 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ELSE p%NewmanAppDims(:) = .FALSE. ! Set all dimensions to false unless we are actually calculating something ENDIF - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp - RETURN - ENDIF @@ -3176,18 +3185,18 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff !-------------------------------------------------------------------------------- ! Allocate array for the WaveExtcn2. - ALLOCATE( p%WaveExctn2(0:InitInp%NStepWave,6), STAT=ErrStatTmp) + ALLOCATE( p%WaveExctn2(0:InitInp%NStepWave,6*p%NBody), STAT=ErrStatTmp) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,'Cannot allocate array p%WaveExctn2 to store '// & 'the 2nd order force data.', ErrStat,ErrMsg,'CheckInitInp') IF (ErrStat >= AbortErrLev ) RETURN - - !-------------------------------------------------------------------------------- - !> FAST channel output - !-------------------------------------------------------------------------------- - - p%NumOuts = InitInp%NumOuts - p%NumOutAll = InitInp%NumOutAll +! +! !-------------------------------------------------------------------------------- +! !> FAST channel output +! !-------------------------------------------------------------------------------- +! +! p%NumOuts = InitInp%NumOuts +! p%NumOutAll = InitInp%NumOutAll END SUBROUTINE CheckInitInput @@ -5429,10 +5438,9 @@ SUBROUTINE WAMIT2_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, ! Local Variables: - INTEGER(IntKi) :: I ! Generic index -! INTEGER(IntKi) :: J ! Generic index -! INTEGER(IntKi) :: K ! Generic index - REAL(ReKi) :: AllOuts(MaxWAMIT2Outputs) + INTEGER(IntKi) :: I ! Generic index + INTEGER(IntKi) :: IBody ! Index to body number + INTEGER(IntKi) :: indxStart ! Starting index ! Initialize ErrStat @@ -5451,23 +5459,27 @@ SUBROUTINE WAMIT2_CalcOutput( Time, WaveTime, u, p, x, xd, z, OtherState, y, m, END IF - ! Compute the 2nd order load contribution from incident waves: - DO I = 1,6 ! Loop through all wave excitation forces and moments - m%F_Waves2(I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn2(:,I), & - m%LastIndWave, p%NStepWave + 1 ) - END DO ! I - All wave excitation forces and moments + do iBody = 1, p%NBody + indxStart = (iBody-1)*6 + + DO I = 1,6 ! Loop through all wave excitation forces and moments + m%F_Waves2(indxStart+I) = InterpWrappedStpReal ( REAL(Time, SiKi), WaveTime(:), p%WaveExctn2(:,indxStart+I), & + m%LastIndWave(IBody), p%NStepWave + 1 ) + END DO ! I - All wave excitation forces and moments ! Copy results to the output point mesh - DO I=1,3 - y%Mesh%Force(I,1) = m%F_Waves2(I) - END DO - DO I=1,3 - y%Mesh%Moment(I,1) = m%F_Waves2(I+3) - END DO + DO I=1,3 + y%Mesh%Force(I,IBody) = m%F_Waves2(indxStart+I) + END DO + DO I=1,3 + y%Mesh%Moment(I,IBody) = m%F_Waves2(indxStart+I+3) + END DO + + enddo END SUBROUTINE WAMIT2_CalcOutput diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index d642f5167..c9f840e7b 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -86,7 +86,7 @@ typedef ^ OtherStateType IntKi DummyOtherS # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType INTEGER LastIndWave - - - "Index for last interpolation step of 2nd order forces" - +typedef ^ MiscVarType INTEGER LastIndWave : - - "Index for last interpolation step of 2nd order forces" - typedef ^ ^ ReKi F_Waves2 {6} - - "2nd order force from this timestep" - diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index c9d0de30a..e99849f12 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -102,7 +102,7 @@ MODULE WAMIT2_Types ! ======================= ! ========= WAMIT2_MiscVarType ======= TYPE, PUBLIC :: WAMIT2_MiscVarType - INTEGER(IntKi) :: LastIndWave !< Index for last interpolation step of 2nd order forces [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: LastIndWave !< Index for last interpolation step of 2nd order forces [-] REAL(ReKi) , DIMENSION(1:6) :: F_Waves2 !< 2nd order force from this timestep [-] END TYPE WAMIT2_MiscVarType ! ======================= @@ -1525,7 +1525,18 @@ SUBROUTINE WAMIT2_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcMiscData%LastIndWave)) THEN + i1_l = LBOUND(SrcMiscData%LastIndWave,1) + i1_u = UBOUND(SrcMiscData%LastIndWave,1) + IF (.NOT. ALLOCATED(DstMiscData%LastIndWave)) THEN + ALLOCATE(DstMiscData%LastIndWave(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%LastIndWave.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstMiscData%LastIndWave = SrcMiscData%LastIndWave +ENDIF DstMiscData%F_Waves2 = SrcMiscData%F_Waves2 END SUBROUTINE WAMIT2_CopyMisc @@ -1538,6 +1549,9 @@ SUBROUTINE WAMIT2_DestroyMisc( MiscData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(MiscData%LastIndWave)) THEN + DEALLOCATE(MiscData%LastIndWave) +ENDIF END SUBROUTINE WAMIT2_DestroyMisc SUBROUTINE WAMIT2_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1575,7 +1589,11 @@ SUBROUTINE WAMIT2_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! LastIndWave + Int_BufSz = Int_BufSz + 1 ! LastIndWave allocated yes/no + IF ( ALLOCATED(InData%LastIndWave) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LastIndWave upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LastIndWave) ! LastIndWave + END IF Re_BufSz = Re_BufSz + SIZE(InData%F_Waves2) ! F_Waves2 IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -1604,8 +1622,19 @@ SUBROUTINE WAMIT2_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%LastIndWave - Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%LastIndWave) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LastIndWave,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LastIndWave,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%LastIndWave)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%LastIndWave))-1 ) = PACK(InData%LastIndWave,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%LastIndWave) + END IF ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_Waves2))-1 ) = PACK(InData%F_Waves2,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%F_Waves2) END SUBROUTINE WAMIT2_PackMisc @@ -1643,8 +1672,29 @@ SUBROUTINE WAMIT2_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%LastIndWave = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LastIndWave not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LastIndWave)) DEALLOCATE(OutData%LastIndWave) + ALLOCATE(OutData%LastIndWave(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LastIndWave.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%LastIndWave)>0) OutData%LastIndWave = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%LastIndWave))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%LastIndWave) + DEALLOCATE(mask1) + END IF i1_l = LBOUND(OutData%F_Waves2,1) i1_u = UBOUND(OutData%F_Waves2,1) ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) From e2e949f86b3bae8bd1561e189b17ea77f8597067 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 7 Jan 2020 04:04:42 -0700 Subject: [PATCH 107/377] FlexSub: using rest length for cable mass --- modules/subdyn/src/SD_FEM.f90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 41009367a..8136fb5ce 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1380,7 +1380,6 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) !do i=1,nDOFt ! print*,'Tc',Tc(i,:) !enddo - STOP ! --- Safety check do j =1, size(Tc,2) ColMean=0; do i=1,size(Tc,1) ; ColMean = ColMean + abs(Tc(i,j)); enddo @@ -1565,12 +1564,15 @@ END SUBROUTINE ApplyConstr SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(ReKi), INTENT(OUT) :: Me(12, 12) + REAL(ReKi) :: L0, Eps0 if (ep%eType==idMemberBeam) then !Calculate Ke, Me to be used for output CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) else if (ep%eType==idMemberCable) then - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) + Eps0 = ep%T0/(ep%YoungE*ep%Area) + L0 = ep%Length/(1+Eps0) ! "rest length" for which pretension would be 0 + CALL ElemM_Cable(ep%Area, L0, ep%rho, ep%DirCos, Me) else if (ep%eType==idMemberRigid) then if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then From c5978e8195da48aefe0f3e367bdc0ebf39c5c30c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 7 Jan 2020 07:22:20 -0700 Subject: [PATCH 108/377] FlexSub: starting reindexing --- modules/subdyn/src/SD_FEM.f90 | 54 +++++++++++++++---- modules/subdyn/src/SubDyn.f90 | 73 +++++++++++++++++++------- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 7 +++ 4 files changed, 104 insertions(+), 31 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 8136fb5ce..83a77163c 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -840,6 +840,7 @@ END FUNCTION Failed !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have !! NOTE: need p%Reacts to have an updated first column that uses indices and not JointIDs + !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" SUBROUTINE InitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p @@ -848,14 +849,15 @@ SUBROUTINE InitBCs(Init, p) DO I = 1, p%NReact iNode = p%Reacts(I,1) ! Node index DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) - Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); + Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); ! 0 or 1 if fixed reaction or not ENDDO ENDDO END SUBROUTINE InitBCs !> Sets a list of DOF indices and the value these DOF should have !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs + !! TODO remove me and merge me with CraigBampton SUBROUTINE InitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p @@ -863,9 +865,9 @@ SUBROUTINE InitIntFc(Init, p) Init%IntFc = 0 DO I = 1, Init%NInterf iNode = Init%Interf(I,1) ! Node index - DO J = 1, 6 - Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) - Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); + DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); ! 0 or 1 if fixed to interface ENDDO ENDDO END SUBROUTINE InitIntFc @@ -982,7 +984,7 @@ END SUBROUTINE AssembleKM SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) use IntegerList, only: init_list, find, pop, destroy_list, len use IntegerList, only: print_list - TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(IN ) :: p type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly @@ -998,7 +1000,6 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 integer(IntKi) :: iPrev type(IList) :: IRA !< list of rigid assembly indices to process - integer(IntKi) :: nDOF integer(IntKi) :: aID, ia ! assembly ID, and index in IRA integer(IntKi) :: iNode integer(IntKi) :: JType @@ -1016,9 +1017,9 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system - nDOF = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', nDOF , '/' , Init%TDOF - CALL AllocAry( m%Tred, Init%TDOF, nDOF, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + Init%nDOFRed = nDOF_ConstraintReduced() + print*,'nDOF constraint elim', Init%nDOFRed , '/' , Init%TDOF + CALL AllocAry( m%Tred, Init%TDOF, Init%nDOFRed, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix Tred=0 call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) @@ -1079,7 +1080,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal if(Failed()) return endif - if (iPrev /= nDOF) then + if (iPrev /= Init%nDOFRed) then ErrMsg2='Inconsistency in number of reduced DOF'; ErrStat2=ErrID_Fatal if(Failed()) return endif @@ -1183,6 +1184,10 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) Init%FG = matmul(transpose(m%Tred), FF) Init%D = 0 !< Used for additional stiffness + ! --- Triggers for storage of DOF indices, replacing with indices in constrained system + CALL ReInitBCs(Init, p) + CALL ReInitIntFc(Init, p) + call CleanUp_DirectElimination() CONTAINS @@ -1200,6 +1205,33 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(RAm1)) deallocate(RAm1) if (allocated(RA )) deallocate(RA ) END SUBROUTINE CleanUp_DirectElimination + + !> Reset DOF indices after elimination + SUBROUTINE ReInitBCs(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + DO I = 1, p%NReact + iNode = p%Reacts(I,1) ! Node index + DO J = 1, 6 + Init%BCs( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) + ENDDO + ENDDO + END SUBROUTINE ReInitBCs + + !> Reset DOF indices after elimination + SUBROUTINE ReInitIntFc(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + Init%IntFc = 0 + DO I = 1, Init%NInterf + iNode = Init%Interf(I,1) ! Node index + DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + Init%IntFc( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) + ENDDO + ENDDO + END SUBROUTINE ReInitIntFc END SUBROUTINE DirectElimination !------------------------------------------------------------------------------------------------------ diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 139ae2ba6..9698d3c4b 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -19,7 +19,7 @@ !********************************************************************************************************************************** !> SubDyn is a time-domain structural-dynamics module for multi-member fixed-bottom substructures. !! SubDyn relies on two main engineering schematizations: (1) a linear frame finite-element beam model (LFEB), and -!! (2) a dynamics system reduction via Craig-Bampton�s (C-B) method, together with a Static-Improvement method, greatly reducing +!! (2) a dynamics system reduction via Craig-Bampton's (C-B) method, together with a Static-Improvement method, greatly reducing !! the number of modes needed to obtain an accurate solution. Module SubDyn @@ -332,14 +332,14 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return - ! --- Elimination of constraints (reset M, K, D) + ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return ! --- Additional Damping and stiffness at pin/ball/universal joints CALL InsertJointStiffDamp(p, m, Init, ErrStat2, ErrMsg2); if(Failed()) return ! --- Craig-Bampton reduction (sets many parameters) - CALL Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + CALL Craig_Bampton(Init, p, m, CBparams, ErrStat2, ErrMsg2); if(Failed()) return ! --- Initial system states IF ( p%qmL > 0 ) THEN @@ -1538,9 +1538,11 @@ END SUBROUTINE SD_AM2 !------------------------------------------------------------------------------------------------------ !> Perform Craig Bampton reduction -SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) +SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) + use IntegerList, only: len TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine TYPE(SD_ParameterType),INTENT(INOUT) :: p ! Parameters + TYPE(SD_MiscVarType), INTENT(IN ) :: m TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -1569,22 +1571,18 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) p%NNodes_I = Init%NInterf ! Number of interface nodes p%NNodes_L = Init%NNode - p%NReact - p%NNodes_I ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I - !DOFS of interface - !BJJ: TODO: are these 6's actually TPdofL? - p%DOFI = p%NNodes_I*6 - p%DOFC = p%NReact*6 - p%DOFR = (p%NReact+p%NNodes_I)*6 ! = p%DOFC + p%DOFI - p%DOFL = p%NNodes_L*6 ! = Init%TDOF - p%DOFR - - + ! --- Counting DOFs: + ! DOFR (retained) = DOFI (interface), DOFC (reaction), + ! DOFL (internal) + ! DOFM (CB modes) + call CountDOFs(); if(Failed()) return IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes IF(p%Nmodes > p%DOFL) THEN - CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than maximum. ',ErrStat,ErrMsg,'Craig_Bampton') + CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than number of internal DOFs. ',ErrStat,ErrMsg,'Craig_Bampton') CALL CleanupCB() RETURN ENDIF - ELSE ! full FEM p%Nmodes = p%DOFL !Jdampings need to be reallocated here because DOFL not known during Init @@ -1593,15 +1591,12 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) DEALLOCATE(Init%JDampings) CALL AllocAry( Init%JDampings, p%DOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return Init%JDampings = JDamping1 ! set default values for all modes - ENDIF - CBparams%DOFM = p%Nmodes ! retained modes (all if no C-B reduction) ! matrix dimension paramters - p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) - p%URbarL = p%DOFI !=p%NNodes_I*6 ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED - + p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) + p%URbarL = p%DOFI ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); ; if (Failed()) return @@ -1676,6 +1671,43 @@ SUBROUTINE Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) CALL CleanUpCB() contains + SUBROUTINE CountDOFs() + INTEGER(IntKi) :: iNode, iiNode + ErrStat2 = ErrID_None + ErrMsg2 = "" + ! Interface DOFS + p%DOFI =0 + do iiNode= 1,Init%NInterf + iNode = Init%Interf(iiNode,1) + p%DOFI = p%DOFI + len(m%NodesDOFtilde(iNode)) + enddo + if (p%DOFI /= p%NNodes_I*6) then + ErrMsg2='Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'; ErrStat2=ErrID_Fatal + return + endif + ! Reaction DOFs + do iiNode= 1,p%NReact + iNode = p%Reacts(iiNode,1) + p%DOFC = p%DOFC + len(m%NodesDOFtilde(iNode)) + enddo + if (p%DOFC /= p%NReact*6) then + ErrMsg2='Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'; ErrStat2=ErrID_Fatal + return + endif + p%DOFR = p%DOFC + p%DOFI + p%DOFL = Init%nDOFRed - p%DOFR ! TODO + print*,'Number of DOFs: "interface" (I)',p%DOFI + print*,'Number of DOFs: "reactions" (C)',p%DOFC + print*,'Number of DOFs: interface (R)',p%DOFR + print*,'Number of DOFs: internal (L)',p%DOFL + print*,'Number of DOFs: total (R+L)',Init%nDOFRed + END SUBROUTINE + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'Craig_Bampton'); + CALL CleanUp() + END SUBROUTINE Fatal logical function Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') @@ -2436,7 +2468,8 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) ErrMsg = "" ! Index IDI for interface DOFs - p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs in global uneliminated system + p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs (indices updated after DirectElimination) + print*,'IDI',p%IDI ! Index IDC for constraint DOFs p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs in global uneliminated system diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index f47bf1228..bfcd3a5f9 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -104,6 +104,7 @@ typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" typedef ^ ^ INTEGER TDOF - - - "Total degree of freedom" +typedef ^ ^ INTEGER nDOFRed - - - "Total degree of freedom after constraint reduction" typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4061391ca..a3b66418d 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -141,6 +141,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] INTEGER(IntKi) :: TDOF !< Total degree of freedom [-] + INTEGER(IntKi) :: nDOFRed !< Total degree of freedom after constraint reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] @@ -2856,6 +2857,7 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%NPropC = SrcInitTypeData%NPropC DstInitTypeData%NPropR = SrcInitTypeData%NPropR DstInitTypeData%TDOF = SrcInitTypeData%TDOF + DstInitTypeData%nDOFRed = SrcInitTypeData%nDOFRed IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN i1_l = LBOUND(SrcInitTypeData%Nodes,1) i1_u = UBOUND(SrcInitTypeData%Nodes,1) @@ -3268,6 +3270,7 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! NPropC Int_BufSz = Int_BufSz + 1 ! NPropR Int_BufSz = Int_BufSz + 1 ! TDOF + Int_BufSz = Int_BufSz + 1 ! nDOFRed Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no IF ( ALLOCATED(InData%Nodes) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension @@ -3595,6 +3598,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%TDOF Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFRed + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4210,6 +4215,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%TDOF = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + OutData%nDOFRed = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated Int_Xferred = Int_Xferred + 1 ELSE From 5b1bce548da5e16835d1f3f55cea429544ce8391 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 7 Jan 2020 12:13:20 -0700 Subject: [PATCH 109/377] TCF: cleanup of WAMIT2 --- modules/hydrodyn/src/WAMIT2.f90 | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 83a4b4d88..ca9402c4f 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -23,7 +23,7 @@ ! distributed under the License is distributed on an "AS IS" BASIS, ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ! See the License for the specific language governing permissions and -! +! !********************************************************************************************************************************** MODULE WAMIT2 @@ -300,7 +300,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !------------------------------------------------------------------------------------------------------------- !> 1. Check the data file related values (_MnDrift_, _MnDriftF_ etc). Also copy over important things from _InitInp_ to _p_ and _InitOut_. - CALL CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStatTmp, ErrMsgTmp ) + CALL CheckInitInput( InitInp, Interval, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -527,7 +527,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ThisBodyNum=1 !> If the MnDrift method will be used, call the subroutine to calculate the force time series IF ( p%MnDriftF ) THEN - + ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order mean drift force.' ) @@ -679,12 +679,12 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Create the node on the mesh CALL MeshPositionNode (u%Mesh, ThisBodyNum, XYZloc, ErrStatTmp, ErrMsgTmp, orientation ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) - + ! Create the mesh element CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, ThisBodyNum ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ENDDO - + CALL MeshCommit ( u%Mesh, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN @@ -718,7 +718,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini m%LastIndWave = 1_IntKi OtherState%DummyOtherState = 0 - + ! Cleanup remaining stuff CALL CleanUp @@ -1043,7 +1043,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, IF (ErrStat >= AbortErrLev) RETURN MnDriftData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. - + ENDIF @@ -1276,7 +1276,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using CHARACTER(*), PARAMETER :: RoutineName = 'NewmanApp_InitCalc' - + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -1507,7 +1507,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp IF (ErrStat >= AbortErrLev) RETURN NewmanAppData%DataIs3D = .TRUE. ! Set flag to indicate we now have the 3D data. - + ENDIF @@ -1856,7 +1856,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using CHARACTER(*), PARAMETER :: RoutineName = 'DiffQTF_InitCalc' - + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -2294,7 +2294,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using. For the first term in the equation. CHARACTER(*), PARAMETER :: RoutineName = 'SumQTF_InitCalc' - + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -3666,7 +3666,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) Data3D%WvFreq1( 1 ) = 0.0_SiKi Data3D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing ENDIF - + ! add the two points for step-change after last entered frequency Data3D%WvFreq1( Data3D%NumWvFreq1-1 ) = Data3D%WvFreq1(Data3D%NumWvFreq1-2) + 10.0_SiKi*EPSILON(0.0_SiKi) Data3D%WvFreq1( Data3D%NumWvFreq1 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant @@ -4487,7 +4487,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) Data4D%WvFreq1( 1 ) = 0.0_SiKi Data4D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing ENDIF - + ! add the two points for step-change after last entered frequency Data4D%WvFreq1( Data4D%NumWvFreq1-1 ) = Data4D%WvFreq1(Data4D%NumWvFreq1-2) + 10.0_SiKi*EPSILON(0.0_SiKi) Data4D%WvFreq1( Data4D%NumWvFreq1 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant @@ -4502,7 +4502,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) Data4D%WvFreq2( 1 ) = 0.0_SiKi Data4D%WvFreq2( 2 ) = MAX( TmpWvFreq2(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing ENDIF - + ! add the two points for step-change after last entered frequency Data4D%WvFreq2( Data4D%NumWvFreq2-1 ) = Data4D%WvFreq2(Data4D%NumWvFreq2-2) + 10.0_SiKi*EPSILON(0.0_SiKi) Data4D%WvFreq2( Data4D%NumWvFreq2 ) = HUGE(1.0_SiKi)/5 ! floating overflow occurs later with arithmetic so I divided by a small constant From 4a4cab0d154f96c25eb712f19975850810ce9c0e Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 7 Jan 2020 12:21:00 -0700 Subject: [PATCH 110/377] TCF: more cleanup of WAMIT2.f90 -- data[34]d routines --- modules/hydrodyn/src/WAMIT2.f90 | 81 +++++++++++++++++---------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index ca9402c4f..305e625f2 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -316,11 +316,11 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> If the MnDrift method will be used, read in the data for it. IF ( p%MnDriftF ) THEN IF ( MnDriftData%DataIs3D ) THEN - CALL Read_DataFile3D( TRIM(MnDriftData%Filename), MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile3D( InitInp, TRIM(MnDriftData%Filename), MnDriftData%Data3D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSEIF ( MnDriftData%DataIs4D ) THEN MnDriftData%Data4D%IsSumForce = .FALSE. - CALL Read_DataFile4D( TRIM(MnDriftData%Filename), MnDriftData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile4D( InitInp, TRIM(MnDriftData%Filename), MnDriftData%Data4D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift method flags incorrectly set by '// & @@ -336,11 +336,11 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> If the NewmanApp method will be used, read in the data for it. IF ( p%NewmanAppF ) THEN IF ( NewmanAppData%DataIs3D ) THEN - CALL Read_DataFile3D( TRIM(NewmanAppData%Filename), NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile3D( InitInp, TRIM(NewmanAppData%Filename), NewmanAppData%Data3D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSEIF ( NewmanAppData%DataIs4D ) THEN NewmanAppData%Data4D%IsSumForce = .FALSE. - CALL Read_DataFile4D( TRIM(NewmanAppData%Filename), NewmanAppData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile4D( InitInp, TRIM(NewmanAppData%Filename), NewmanAppData%Data4D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp method flags incorrectly set by '// & @@ -362,7 +362,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini 'CheckInitInput subroutine. 3D data cannot be used in the DiffQTF method.', ErrStat, ErrMsg, RoutineName ) ELSEIF ( DiffQTFData%DataIs4D ) THEN DiffQTFData%Data4D%IsSumForce = .FALSE. - CALL Read_DataFile4D( TRIM(DiffQTFData%Filename), DiffQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile4D( InitInp, TRIM(DiffQTFData%Filename), DiffQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF method flags incorrectly set by '// & @@ -379,7 +379,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini IF ( p%SumQTFF ) THEN IF ( SumQTFData%DataIs4D ) THEN SumQTFData%Data4D%IsSumForce = .TRUE. - CALL Read_DataFile4D( TRIM(SumQTFData%Filename), SumQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) + CALL Read_DataFile4D( InitInp, TRIM(SumQTFData%Filename), SumQTFData%Data4D, ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF method flags incorrectly set by '// & @@ -745,7 +745,6 @@ END SUBROUTINE CleanUp - !------------------------------------------------------------------------------------------------------------------------------- !> This subroutine calculates the force time series using the MnDrift calculation. !! The data is stored in either 3D or 4D arrays depending on the file type used. @@ -800,7 +799,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter CHARACTER(*), PARAMETER :: RoutineName = 'MnDrift_InitCalc' - + ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF @@ -835,7 +834,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, !> 1. Check the data to see if low cutoff on the difference frequency is 0. If it is above zero, that implies no mean drift - !! term since \f$ \omega_1=\omega_2 \f$ + !! term since \f$ \omega_1=\omega_2 \f$ IF ( InitInp%WvLowCOffD > 0.0_SiKi ) THEN CALL SetErrStat( ErrID_Warn, ' WvLowCOffD > 0.0, so no mean drift term is calculated (the mean drift uses only the equal '//& @@ -2720,12 +2719,13 @@ END SUBROUTINE SumQTF_InitCalc !! !! This subroutine also populates the InitOut and creates the filenames for each of the calculation types. !! - SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStat, ErrMsg ) + SUBROUTINE CheckInitInput( InitInp, Interval, InitOut, p, MnDriftData, NewmanAppData, DiffQTFData, SumQTFData, ErrStat, ErrMsg ) IMPLICIT NONE ! Passed variables. TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine + REAL(DbKi), INTENT(IN ) :: Interval !< Coupling interval in seconds: don't change it from the glue code provided value. TYPE(WAMIT2_InitOutputType), INTENT(INOUT) :: InitOut !< The output from the init routine TYPE(WAMIT2_ParameterType), INTENT( OUT) :: p !< The parameters @@ -2745,7 +2745,7 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the local error status CHARACTER(2048) :: ErrMsgTmp !< Temporary error message variable CHARACTER(*), PARAMETER :: RoutineName = 'CheckInitInput' - + !> ## Subroutine contents !-------------------------------------------------------------------------------- @@ -3076,9 +3076,9 @@ SUBROUTINE CheckInitInput( InitInp, InitOut, p, MnDriftData, NewmanAppData, Diff ! This module's implementation requires that if NBodyMod = 2 or 3, then there is one instance of a WAMIT module for each body, therefore, HydroDyn may have NBody > 1, but this WAMIT module will have NBody = 1 if ( (p%NBodyMod > 1) .and. (p%NBody > 1) ) then CALL SetErrStat( ErrID_Fatal, "DEVELOPER ERROR: If NBodyMod = 2 or 3, then NBody for the a WAMIT2 object must be equal to 1", ErrStat, ErrMsg, RoutineName) - CALL CleanUp + CALL CleanUp return - end if + end if !-------------------------------------------------------------------------------- @@ -3221,11 +3221,12 @@ END SUBROUTINE CheckInitInput !! !! At the end of all this, we check the data for completeness and set the flags accordingly. !! - SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) + SUBROUTINE Read_DataFile3D( InitInp, Filename3D, Data3D, ErrStat, Errmsg ) IMPLICIT NONE ! Passed variables. + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine CHARACTER(*), INTENT(IN ) :: Filename3D !< Name of the file containing the 3D data TYPE(W2_InitData3D_Type), INTENT(INOUT) :: Data3D !< 3D QTF data INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error value @@ -3629,9 +3630,9 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) ! Now we need to figure out if the zero frequency was given in the file. If so, we change NumWvFreq1 to - ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and + ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and ! zero out all values not in the input frequency range. The inifinite frequency value will be set to HUGE - ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step + ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step ! change for zeroing the values outside the input frequency range. IF (HaveZeroFreq1) THEN Data3D%NumWvFreq1 = Data3D%NumWvFreq1+2 @@ -3661,7 +3662,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) ! Populate the wave frequencies with what we read in Data3D%WvFreq1( WvFreq1LoIdx:WvFreq1HiIdx ) = TmpWvFreq1 - ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency IF ( .NOT. HaveZeroFreq1) THEN Data3D%WvFreq1( 1 ) = 0.0_SiKi Data3D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing @@ -3852,7 +3853,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) !! to be performed only when \f$ \omega_1 = \omega_2 \f$. ! Loop over the wave components, but only perform calculations on the ones that have values - DO L=1,6 + DO L=1,6*Data3D%NumBodies IF (Data3D%LoadComponents(L)) THEN ! Only do this for the load components that exist DO I=1,Data3D%NumWvFreq1 ! Frequencies @@ -3892,19 +3893,19 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) !---------------------------------------------------------------------------------- - !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, + !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, !! and added two frequencies for the infinite frequency term on the end of the array, - !! to create step changes outside the entered frequency ranges. We need to populate + !! to create step changes outside the entered frequency ranges. We need to populate !! the these new terms (set to zero). !---------------------------------------------------------------------------------- IF (.NOT. HaveZeroFreq1) THEN Data3D%DataSet( 1:2,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values to zero for everything before entered frequency range Data3D%DataMask(1:2,:,:,:) = .TRUE. ! Set the mask for these first two frequencies - ENDIF + ENDIF Data3D%DataSet( Data3D%NumWvFreq1-1:Data3D%NumWvFreq1,:,:,:) = CMPLX(0.0_SiKi,0.0_SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) - Data3D%DataMask(Data3D%NumWvFreq1-1:Data3D%NumWvFreq1,:,:,:) = .TRUE. ! Set the mask for the last two frequencies - + Data3D%DataMask(Data3D%NumWvFreq1-1:Data3D%NumWvFreq1,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + !---------------------------------------------------------------------------------- !> Find out if the data is sparse or full. Verification that the requested component @@ -3913,7 +3914,7 @@ SUBROUTINE Read_DataFile3D( Filename3D, Data3D, ErrStat, Errmsg ) !! for only the values of k that have data in them. !---------------------------------------------------------------------------------- - DO L=1,6 ! Loop over force component directions + DO L=1,6*Data3D%NumBodies ! Loop over force component directions TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found IF (Data3D%LoadComponents(L)) THEN ! Only if we found data for that component DO I=1,Data3D%NumWvFreq1 @@ -3970,11 +3971,12 @@ END SUBROUTINE Read_DataFile3D !! !! At the end of all this, we check the data for completeness and set the flags accordingly. !! - SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) + SUBROUTINE Read_DataFile4D( InitInp, Filename4D, Data4D, ErrStat, Errmsg ) IMPLICIT NONE ! Passed variables. + TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine CHARACTER(*), INTENT(IN ) :: Filename4D !< Name of the file containing the 4D data TYPE(W2_InitData4D_Type), INTENT(INOUT) :: Data4D !< 4D QTF data INTEGER(IntKi), INTENT( OUT) :: ErrStat !< The error value @@ -4419,9 +4421,9 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ! Now we need to figure out if the zero frequency was given in the file. If so, we change NumWvFreq1 to - ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and + ! NumWvFreq1+2. If not, change to NumWvFreq1+4. We will add on the inifinite frequency value and ! zero out all values not in the input frequency range. The inifinite frequency value will be set to HUGE - ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step + ! and we'll add/subtract epsilon to the first non-zero frequency entered so that we can achieve a step ! change for zeroing the values outside the input frequency range. IF (HaveZeroFreq1) THEN Data4D%NumWvFreq1 = Data4D%NumWvFreq1+2 @@ -4482,7 +4484,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ! Populate the wave frequencies with what we read in Data4D%WvFreq1( WvFreq1LoIdx:WvFreq1HiIdx ) = TmpWvFreq1 - ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency IF ( .NOT. HaveZeroFreq1) THEN Data4D%WvFreq1( 1 ) = 0.0_SiKi Data4D%WvFreq1( 2 ) = MAX( TmpWvFreq1(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing @@ -4497,7 +4499,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) ! Populate the wave frequencies with what we read in Data4D%WvFreq2( WvFreq2LoIdx:WvFreq2HiIdx ) = TmpWvFreq2 - ! If no zero frequency was supplied, add the two points for step-change before first entered frequency + ! If no zero frequency was supplied, add the two points for step-change before first entered frequency IF ( .NOT. HaveZeroFreq2) THEN Data4D%WvFreq2( 1 ) = 0.0_SiKi Data4D%WvFreq2( 2 ) = MAX( TmpWvFreq2(1) - 10.0_SiKi*EPSILON(0.0_SiKi), 0.0_SiKi ) ! make sure the Frequencies are still monotonically increasing @@ -4778,26 +4780,26 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) !---------------------------------------------------------------------------------- - !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, + !> We added two frequencies for the \f$ omega = 0 \f$ term if it did not exist, !! and added two frequencies for the infinite frequency term on the end of the array, - !! to create step changes outside the entered frequency ranges. We need to populate + !! to create step changes outside the entered frequency ranges. We need to populate !! the these new terms (set to zero). !---------------------------------------------------------------------------------- IF (.NOT. HaveZeroFreq1) THEN Data4D%DataSet( 1:2,:,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values to zero for everything before entered frequency range Data4D%DataMask(1:2,:,:,:,:) = .TRUE. ! Set the mask for these first two frequencies - ENDIF + ENDIF Data4D%DataSet( Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) - Data4D%DataMask(Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + Data4D%DataMask(Data4D%NumWvFreq1-1:Data4D%NumWvFreq1,:,:,:,:) = .TRUE. ! Set the mask for the last two frequencies IF (.NOT. HaveZeroFreq2) THEN Data4D%DataSet( :,1:2,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values to zero for everything before entered frequency range Data4D%DataMask(:,1:2,:,:,:) = .TRUE. ! Set the mask for these first two frequencies - ENDIF + ENDIF Data4D%DataSet( :,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = CMPLX(0.0,0.0,SiKi) ! Set the values for the last two frequencies to zero (everything higher than the last non-infinite frequency) - Data4D%DataMask(:,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = .TRUE. ! Set the mask for the last two frequencies - + Data4D%DataMask(:,Data4D%NumWvFreq2-1:Data4D%NumWvFreq2,:,:,:) = .TRUE. ! Set the mask for the last two frequencies + !---------------------------------------------------------------------------------- !> Find out if the data is sparse or full. Verification that the requested component @@ -4806,7 +4808,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) !! for only the values of k that have data in them. !---------------------------------------------------------------------------------- - DO M=1,6 ! Loop over force component directions + DO M=1,6*Data4D%NumBodies ! Loop over force component directions TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found IF (Data4D%LoadComponents(M)) THEN ! Only if we found data for that component DO I=1,Data4D%NumWvFreq1 @@ -4861,7 +4863,7 @@ SUBROUTINE Read_DataFile4D( Filename4D, Data4D, ErrStat, Errmsg ) IF (Data4D%NumWvFreq1 /= Data4D%NumWvFreq2) THEN TmpDiagComplete = .FALSE. ELSE ! Same number of frequencies, so we can proceed. - DO M=1,6 ! Loop over force component directions + DO M=1,6*Data4D%NumBodies ! Loop over force component directions ! If we have data for this component, and it is sparse, proceed to check it. IF (Data4D%LoadComponents(M) .AND. Data4D%DataIsSparse(M)) THEN @@ -5214,6 +5216,7 @@ SUBROUTINE ReadRealNumberFromString(StringToParse, ValueRead, StrRead, IsRealNum CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message including message from ReadNum INTEGER(IntKi), INTENT( OUT) :: IOErrStat !< Error status from the internal read. Useful for diagnostics. + CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for holding the error message returned from a CALL statement ! Initialize some things @@ -5717,7 +5720,7 @@ SUBROUTINE Copy_InitData4Dto3D( Data4D, Data3D, ErrStat, ErrMsg ) !! for only the values of k that have data in them. !---------------------------------------------------------------------------------- - DO L=1,6 ! Loop over force component directions + DO L=1,6*Data3D%NumBodies ! Loop over force component directions TmpSparseFlag = .FALSE. ! Change this to true if any empty values are found IF (Data3D%LoadComponents(L)) THEN ! Only if we found data for that component DO I=1,Data3D%NumWvFreq1 From 23813889b72c7e3d91306436d545313af5f7330f Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 7 Jan 2020 12:25:22 -0700 Subject: [PATCH 111/377] TCF: Correct dimension checks in WAMIT2, and add MnDrift updates Updated MnDrift_Init to handle the rotated platform NOTE: some checks are missing, and the Newman's approx, DiffQTF and SumQTF are not complete. --- modules/hydrodyn/src/WAMIT2.f90 | 1024 +++++++++++++++++-------------- 1 file changed, 565 insertions(+), 459 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 305e625f2..572975b84 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -227,8 +227,10 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Local Variables - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: IBody !< Counter for current body + INTEGER(IntKi) :: ThisDim !< Counter to currrent dimension INTEGER(IntKi) :: J !< Generic counter + INTEGER(IntKi) :: Idx !< Generic counter INTEGER(IntKi) :: ThisBodyNum !< Current body number REAL(R8Ki) :: theta(3) !< rotation about z for ThisBodyNum (0 about x,y) REAL(R8Ki) :: orientation(3,3) !< Orientation matrix for orientation of ThisBodyNum @@ -242,7 +244,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini TYPE(W2_SumData_Type) :: SumQTFData !< Data storage for the full sum QTF method ! Force arrays - REAL(SiKi) :: MnDriftForce(:) !< MnDrift force array. Constant for all time. First index is force component + REAL(SiKi), ALLOCATABLE :: MnDriftForce(:) !< MnDrift force array. Constant for all time. First index is force component REAL(SiKi), ALLOCATABLE :: NewmanAppForce(:,:) !< NewmanApp force array. Index 1: Time, Index 2: force component REAL(SiKi), ALLOCATABLE :: DiffQTFForce(:,:) !< DiffQTF force array. Index 1: Time, Index 2: force component REAL(SiKi), ALLOCATABLE :: SumQTFForce(:,:) !< SumQTF force array. Index 1: Time, Index 2: force component @@ -397,24 +399,29 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> 3. Now check the data to ensure that all the dimensions that were requested acually exist in the file. At !! this point, the MnDriftData and NewmanApp data will be either 3D or 4D, but not both. !! - !> Check the MnDrift data: check both in case we have already copied 4D data into the 3D. Will decide later which is used. IF ( p%MnDriftF ) THEN IF ( MnDriftData%DataIs3D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,MnDriftData%Data3D%NumBodies - IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data3D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,MnDriftData%Data3D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%MnDriftDims(ThisDim) .AND. ( .NOT. MnDriftData%Data3D%LoadComponents(Idx) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the MnDrift method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE IF ( MnDriftData%DataIs4D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,MnDriftData%Data4D%NumBodies - IF ( p%MnDriftDims(I) .AND. ( .NOT. MnDriftData%Data4D%LoadComponents(I) ) )& - CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the MnDrift method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,MnDriftData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%MnDriftDims(ThisDim) .AND. ( .NOT. MnDriftData%Data4D%LoadComponents(Idx) ) )& + CALL SetErrStat( ErrID_Warn, ' '//TRIM(MnDriftData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the MnDrift method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE ! We didn't find any data to use... CALL SetErrStat( ErrID_Fatal, ' Programming error. MnDrift flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) @@ -429,20 +436,26 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> Check the NewmanApp data: check both in case we have already copied 4D data into the 3D. Will decide later which is used. IF ( p%NewmanAppF ) THEN IF ( NewmanAppData%DataIs3D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,NewmanAppData%Data3D%NumBodies - IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data3D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,NewmanAppData%Data3D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%NewmanAppDims(ThisDim) .AND. ( .NOT. NewmanAppData%Data3D%LoadComponents(Idx) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the NewmanApp method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE IF ( NewmanAppData%DataIs4D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,NewmanAppData%Data4D%NumBodies - IF ( p%NewmanAppDims(I) .AND. ( .NOT. NewmanAppData%Data4D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the NewmanApp method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,NewmanAppData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%NewmanAppDims(ThisDim) .AND. ( .NOT. NewmanAppData%Data4D%LoadComponents(Idx) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(NewmanAppData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the NewmanApp method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. NewmanApp flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) @@ -457,12 +470,15 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> Check the DiffQTF data: Don't check the 3D data. We may have copied 4D into it for the MnDrift term. IF ( p%DiffQTFF ) THEN IF ( DiffQTFData%DataIs4D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,DiffQTFData%Data4D%NumBodies - IF ( p%DiffQTFDims(I) .AND. ( .NOT. DiffQTFData%Data4D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Warn, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the DiffQTF method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,DiffQTFData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%DiffQTFDims(ThisDim) .AND. ( .NOT. DiffQTFData%Data4D%LoadComponents(Idx) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(DiffQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the DiffQTF method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. DiffQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) @@ -477,12 +493,15 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !> Check the SumQTF data IF ( p%SumQTFF ) THEN IF ( SumQTFData%DataIs4D ) THEN - ! Check the dimensions used. The LoadComponents(I) flag will be set to .TRUE. if data was found in the file - DO I=1,SumQTFData%Data4D%NumBodies - IF ( p%SumQTFDims(I) .AND. ( .NOT. SumQTFData%Data4D%LoadComponents(I) ) ) & - CALL SetErrStat( ErrID_Warn, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & - TRIM(Num2LStr(I))//' force component for the SumQTF method. Setting this component to zero.', & - ErrStat,ErrMsg,RoutineName) + ! Check the dimensions used. The LoadComponents(Idx) flag will be set to .TRUE. if data was found in the file + DO IBody=1,SumQTFData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%SumQTFDims(ThisDim) .AND. ( .NOT. SumQTFData%Data4D%LoadComponents(Idx) ) ) & + CALL SetErrStat( ErrID_Warn, ' '//TRIM(SumQTFData%Filename)//' does not contain information for the '// & + TRIM(Num2LStr(ThisDim))//' force component for the SumQTF method. Setting this component to zero.', & + ErrStat,ErrMsg,RoutineName) + ENDDO ENDDO ELSE CALL SetErrStat( ErrID_Fatal, ' Programming error. SumQTF flag is set, but no data has been read in.',ErrStat,ErrMsg, RoutineName) @@ -593,29 +612,37 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Difference method data. Only one difference method can be calculated at a time. - IF ( p%MnDriftF ) THEN - DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. - IF ( p%MnDriftDims(I) ) THEN - p%WaveExctn2(:,I) = MnDriftForce(I) - ENDIF + DO IBody=1,p%NBody ! Loop through load components. Set ones that are calculated. + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%MnDriftDims(ThisDim) ) THEN + p%WaveExctn2(:,Idx) = MnDriftForce(Idx) + ENDIF + ENDDO ENDDO ELSE IF ( p%NewmanAppF ) THEN - DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. - IF ( p%NewmanAppDims(I) ) THEN - p%WaveExctn2(:,I) = NewmanAppForce(:,I) - ENDIF + DO IBody=1,p%NBody ! Loop through load components. Set ones that are calculated. + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%NewmanAppDims(ThisDim) ) THEN + p%WaveExctn2(:,Idx) = NewmanAppForce(:,Idx) + ENDIF + ENDDO ENDDO ELSE IF ( p%DiffQTFF ) THEN - DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. - IF ( p%DiffQTFDims(I) ) THEN - p%WaveExctn2(:,I) = DiffQTFForce(:,I) - ENDIF + DO IBody=1,p%NBody ! Loop through load components. Set ones that are calculated. + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%DiffQTFDims(ThisDim) ) THEN + p%WaveExctn2(:,Idx) = DiffQTFForce(:,Idx) + ENDIF + ENDDO ENDDO ENDIF @@ -624,13 +651,13 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Summation method IF ( p%SumQTFF ) THEN - DO I=1,6*p%NBody ! Loop through load components. Set ones that are calculated. - IF ( p%SumQTFDims(I) ) THEN - ! Add the sum force to the difference force calculated above (if there was one). Loop through all timesteps. - DO J=1,InitInp%NStepWave - p%WaveExctn2(J,I) = p%WaveExctn2(J,I) + SumQTFForce(J,I) - ENDDO - ENDIF + DO IBody=1,p%NBody ! Loop through load components. Set ones that are calculated. + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%SumQTFDims(ThisDim) ) THEN + p%WaveExctn2(:,Idx) = p%WaveExctn2(:,Idx) + SumQTFForce(:,Idx) + ENDIF + ENDDO ENDDO ENDIF @@ -769,11 +796,15 @@ END SUBROUTINE CleanUp !! !! where \f$ k \f$ indicates the index to the load component, \f$ {F_{{ex}~k}^{{-}(2)}} \f$ is the resulting time !! independent mean drift force, and \f$ a_m \f$ and \f$ a_m^* \f$ are the complex wave amplitude and its complex conjugate for - !! the \f$ m^{th} \f$ frequency. Note the lack of time dependence in this equation: the mean drift is the average drift + !! the \f$ m^{th} \f$ frequency. _Note the lack of time dependence in this equation:_ the mean drift is the average drift !! force over the entire simulation. Note also that \f$ F_k^{-} (\omega_m, \beta_m) \f$ is the dimensionalized real valued !! diagonal of the QTF read from the WAMIT file and interpolated for the \f$ m^{th} \f$ wave frequency. Note that this is !! is a numerical integral, so the \f$ \Delta\omega \f$ term is necessary. !! + !! @note The mean drift is a static value representing the mean drift force for the entire simulation. Therefore, any offset + !! in the body location can be ignored since it cancels out (it is in the complex part that is ignored in the summation). + !! The orientation of the platform is therefore handled after the summation. + !! !! Since the frequency range of the QTF has not yet been checked, we will do that now. !! !------------------------------------------------------------------------------------------------------------------------------- @@ -795,7 +826,9 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, REAL(SiKi) :: TmpReal1 !< Temporary real REAL(SiKi) :: TmpReal2 !< Temporary real LOGICAL :: TmpFlag !< Temporary logical flag - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: ThisDim !< Generic counter for dimension + INTEGER(IntKi) :: IBody !< Index to which body we are on + INTEGER(IntKi) :: Idx !< Index to the full set of 6*NBody INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter CHARACTER(*), PARAMETER :: RoutineName = 'MnDrift_InitCalc' @@ -809,8 +842,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms - REAL(SiKi) :: RotateZ !< The rotation to apply to the body - REAL(SiKi) :: OffsetXY(2) !< The phase shift offset to apply to the body + REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset COMPLEX(SiKi),ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) @@ -1030,10 +1062,13 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, IF ( .NOT. MnDriftData%DataIs3D .AND. MnDriftData%Data4D%WvFreqDiagComplete ) THEN TmpFlag = .FALSE. ! if this goes true, then we need to convert to 3D data - DO I=1,MnDriftData%Data4D%NumBodies - IF ( p%MnDriftDims(I) ) THEN ! Flag indicating which dimension we are calculating for - IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) ) TmpFlag = .TRUE. - ENDIF + DO IBody=1,MnDriftData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%MnDriftDims(IBody) ) THEN ! Flag indicating which dimension we are calculating for + IF ( MnDriftData%Data4D%DataIsSparse(Idx) .AND. MnDriftData%Data4D%LoadComponents(Idx) ) TmpFlag = .TRUE. + ENDIF + ENDDO ENDDO ! If we need to create the 3D data set, then @@ -1054,12 +1089,18 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. TmpFlag = .FALSE. IF ( MnDriftData%DataIs3D ) THEN - DO I=1,MnDriftData%Data3D%NumBodies - IF ( MnDriftData%Data3D%DataIsSparse(I) .AND. MnDriftData%Data3D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. + DO IBody=1,MnDriftData%Data3D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( MnDriftData%Data3D%DataIsSparse(Idx) .AND. MnDriftData%Data3D%LoadComponents(Idx) .AND. p%MnDriftDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO ELSE ! must be 4D -- we checked that we had something at the start of this routine. - DO I=1,MnDriftData%Data4D%NumBodies - IF ( MnDriftData%Data4D%DataIsSparse(I) .AND. MnDriftData%Data4D%LoadComponents(I) .AND. p%MnDriftDims(I) ) TmpFlag = .TRUE. + DO IBody=1,MnDriftData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( MnDriftData%Data4D%DataIsSparse(Idx) .AND. MnDriftData%Data4D%LoadComponents(Idx) .AND. p%MnDriftDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO ENDIF IF (TmpFlag) THEN @@ -1097,99 +1138,124 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ! Now loop through all the dimensions and perform the calculation - DO I=1,6*p%NBody - - ! Set the MnDrift force to 0.0 (Even ones we don't calculate) - MnDriftForce(I) = 0.0_SiKi - - IF (MnDriftData%DataIs3D) THEN - TmpFlag = MnDriftData%Data3D%LoadComponents(I) - ELSE - TmpFlag = MnDriftData%Data4D%LoadComponents(I) - END IF + DO IBody=1,p%NBody + DO ThisDim=1,6 - ! Only on the dimensions we requested, and if it is present in the data - IF ( p%MnDriftDims(I) .AND. TmpFlag ) THEN + Idx = (IBody-1)*6 + ThisDim - ! Set an initial search index for the 3D and 4D array interpolation - LastIndex3 = (/0,0,0/) - LastIndex4 = (/0,0,0,0/) + ! Set the MnDrift force to 0.0 (Even ones we don't calculate) + MnDriftForce(Idx) = 0.0_SiKi - ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays IF (MnDriftData%DataIs3D) THEN - TmpData3D = MnDriftData%Data3D%DataSet(:,:,:,I) + TmpFlag = MnDriftData%Data3D%LoadComponents(Idx) ELSE - TmpData4D = MnDriftData%Data4D%DataSet(:,:,:,:,I) + TmpFlag = MnDriftData%Data4D%LoadComponents(Idx) END IF - - DO J=1,InitInp%NStepWave2 + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%MnDriftDims(ThisDim) .AND. TmpFlag ) THEN - ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or - ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. - aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 + ! Set an initial search index for the 3D and 4D array interpolation + LastIndex3 = (/0,0,0/) + LastIndex4 = (/0,0,0,0/) - ! Calculate the frequency - Omega1 = J * InitInp%WaveDOmega + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + IF (MnDriftData%DataIs3D) THEN + TmpData3D = MnDriftData%Data3D%DataSet(:,:,:,Idx) + ELSE + TmpData4D = MnDriftData%Data4D%DataSet(:,:,:,:,Idx) + END IF - ! Only get a QTF value if within the range of frequencies we have wave amplitudes for (first order cutoffs). This - ! is done only for efficiency. - IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN + DO J=1,InitInp%NStepWave2 - ! Now get the QTF value that corresponds to this frequency and wavedirection pair. - IF ( MnDriftData%DataIs3D ) THEN + ! NOTE: since the Mean Drift only returns a static time independent average value for the drift force, we do not + ! need to account for any offset in the location of the WAMIT body (this term vanishes). + ! First get the wave amplitude -- must be reconstructed from the WaveElevC0 array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 to remove the built in normalization in WaveElevC0. + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 - ! Set the (omega1,beta1,beta2) point we are looking for. - Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Calculate the frequency + Omega1 = J * InitInp%WaveDOmega - ! get the interpolated value for F(omega1,beta1,beta2) - CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, MnDriftData%Data3D%WvFreq1, & - MnDriftData%Data3D%WvDir1, MnDriftData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) - ELSE + ! Only get a QTF value if within the range of frequencies we have wave amplitudes for (first order cutoffs). This + ! is done only for efficiency. + IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN - ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Now get the QTF value that corresponds to this frequency and wavedirection pair. + IF ( MnDriftData%DataIs3D ) THEN - ! get the interpolated value for F(omega1,omega2,beta1,beta2) - CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, MnDriftData%Data4D%WvFreq1, MnDriftData%Data4D%WvFreq2, & - MnDriftData%Data4D%WvDir1, MnDriftData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + ! Set the (omega1,beta1,beta2) point we are looking for. (angles in degrees here) + Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord3(2) = Coord3(2) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord3(3) = Coord3(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - ENDIF !QTF value find + ! get the interpolated value for F(omega1,beta1,beta2) + CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, MnDriftData%Data3D%WvFreq1, & + MnDriftData%Data3D%WvDir1, MnDriftData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) + ELSE - ELSE ! outside the frequency range + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. (angles in degrees here) + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) - QTF_Value = CMPLX(0.0,0.0,SiKi) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord4(3) = Coord4(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord4(4) = Coord4(4) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - ENDIF ! frequency check + ! get the interpolated value for F(omega1,omega2,beta1,beta2) + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, MnDriftData%Data4D%WvFreq1, MnDriftData%Data4D%WvFreq2, & + MnDriftData%Data4D%WvDir1, MnDriftData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - ! Check and make sure nothing bombed in the interpolation that we need to be aware of - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - ENDIF + ENDIF !QTF value find - ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the mean drift. - ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So - ! we throw the complex part out. - QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) + ELSE ! outside the frequency range + QTF_Value = CMPLX(0.0,0.0,SiKi) - ! Now put it all together... note the frequency stepsize is multiplied after the summation - MnDriftForce(I) = MnDriftForce(I) + REAL(QTF_Value * aWaveElevC * CONJG(aWaveElevC)) !bjj: put QTF_Value first so that if it's zero, the rest gets set to zero (to hopefully avoid overflow issues) + ENDIF ! frequency check - ENDDO ! NStepWave2 - ENDIF ! Load component to calculate + ! Check and make sure nothing bombed in the interpolation that we need to be aware of + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF - ENDDO + + ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the mean drift. + ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So + ! we throw the complex part out. + QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) + + ! NOTE: any offset in platform location vanishes when the only the REAL part is kept (the offset resides in the + ! phase shift, which is in the imaginary part) + ! Now put it all together... note the frequency stepsize is multiplied after the summation + MnDriftForce(Idx) = MnDriftForce(Idx) + REAL(QTF_Value * aWaveElevC * CONJG(aWaveElevC)) !bjj: put QTF_Value first so that if it's zero, the rest gets set to zero (to hopefully avoid overflow issues) + + ENDDO ! NStepWave2 + + ENDIF ! Load component to calculate + + + ! Now rotate the force components with platform orientation + ! NOTE: RotateZMatrixT is the rotation from local to global. + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(ThisBodyNum)), -sin(InitInp%PtfmRefztRot(ThisBodyNum)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(ThisBodyNum)), cos(InitInp%PtfmRefztRot(ThisBodyNum)) /) + + + MnDriftForce(1:2) = MATMUL( RotateZMatrixT, MnDriftForce(1:2) ) ! Fx and Fy, rotation about z + MnDriftForce(4:5) = MATMUL( RotateZMatrixT, MnDriftForce(4:5) ) ! Mx and My, rotation about z + + ENDDO ! ThisDim -- Load Component on body + ENDDO ! IBody @@ -1270,7 +1336,9 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp REAL(SiKi) :: TmpReal1 !< Temporary real REAL(SiKi) :: TmpReal2 !< Temporary real LOGICAL :: TmpFlag !< Temporary logical flag - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: ThisDim !< Generic counter for dimension + INTEGER(IntKi) :: IBody !< Index to which body we are on + INTEGER(IntKi) :: Idx !< Index to the full set of 6*NBody INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using @@ -1291,6 +1359,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset + REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) + REAL(SiKi) :: OffsetXY(2) !< The phase shift offset to apply to the body COMPLEX(SiKi), ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) COMPLEX(SiKi), ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) @@ -1494,10 +1564,13 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp IF ( .NOT. NewmanAppData%DataIs3D .AND. NewmanAppData%Data4D%WvFreqDiagComplete ) THEN TmpFlag = .FALSE. ! if this goes true, then we need to convert to 3D data - DO I=1,6 - IF ( p%NewmanAppDims(I) ) THEN ! Flag indicating which dimension we are calculating for - IF ( NewmanAppData%Data4D%DataIsSparse(I) .AND. NewmanAppData%Data4D%LoadComponents(I) ) TmpFlag = .TRUE. - ENDIF + DO IBody=1,NewmanAppData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( p%NewmanAppDims(ThisDim) ) THEN ! Flag indicating which dimension we are calculating for + IF ( NewmanAppData%Data4D%DataIsSparse(Idx) .AND. NewmanAppData%Data4D%LoadComponents(Idx) ) TmpFlag = .TRUE. + ENDIF + ENDDO ENDDO ! If we need to create the 3D data set, then @@ -1518,12 +1591,18 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. TmpFlag = .FALSE. IF ( NewmanAppData%DataIs3D ) THEN - DO I=1,6 - IF ( NewmanAppData%Data3D%DataIsSparse(I) .AND. NewmanAppData%Data3D%LoadComponents(I) .AND. p%NewmanAppDims(I) ) TmpFlag = .TRUE. + DO IBody=1,NewmanAppData%Data3D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( NewmanAppData%Data3D%DataIsSparse(Idx) .AND. NewmanAppData%Data3D%LoadComponents(Idx) .AND. p%NewmanAppDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO ELSE ! must be 4D -- we checked that we had something at the start of this routine. - DO I=1,6 - IF ( NewmanAppData%Data4D%DataIsSparse(I) .AND. NewmanAppData%Data4D%LoadComponents(I) .AND. p%NewmanAppDims(I) ) TmpFlag = .TRUE. + DO IBody=1,NewmanAppData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( NewmanAppData%Data4D%DataIsSparse(Idx) .AND. NewmanAppData%Data4D%LoadComponents(Idx) .AND. p%NewmanAppDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO ENDIF IF (TmpFlag) THEN @@ -1611,159 +1690,169 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ! Now loop through all the dimensions and perform the calculation - DO I=1,6 + DO IBody=1,p%NBody + DO ThisDim=1,6 - ! set zero frequency term to zero - NewmanTerm1C(0) = CMPLX(0.0, 0.0, SiKi) - NewmanTerm2C(0) = CMPLX(0.0, 0.0, SiKi) + Idx= (IBody-1)*6+ThisDim - IF (NewmanAppData%DataIs3D) THEN - TmpFlag = NewmanAppData%Data3D%LoadComponents(I) - ELSE - TmpFlag = NewmanAppData%Data4D%LoadComponents(I) - END IF - - ! Only on the dimensions we requested, and if it is present in the data - IF ( p%NewmanAppDims(I) .AND. TmpFlag ) THEN - - ! Set an initial search index for the 3D and 4D array interpolation - LastIndex3 = (/0,0,0/) - LastIndex4 = (/0,0,0,0/) + ! set zero frequency term to zero + NewmanTerm1C(0) = CMPLX(0.0, 0.0, SiKi) + NewmanTerm2C(0) = CMPLX(0.0, 0.0, SiKi) - ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays IF (NewmanAppData%DataIs3D) THEN - TmpData3D = NewmanAppData%Data3D%DataSet(:,:,:,I) + TmpFlag = NewmanAppData%Data3D%LoadComponents(Idx) ELSE - TmpData4D = NewmanAppData%Data4D%DataSet(:,:,:,:,I) + TmpFlag = NewmanAppData%Data4D%LoadComponents(Idx) END IF - - DO J=1,InitInp%NStepWave2 + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%NewmanAppDims(ThisDim) .AND. TmpFlag ) THEN - ! First get the wave amplitude -- must be reconstructed from the WaveElevC array. First index is the real (1) or - ! imaginary (2) part. Divide by NStepWave2 so that the wave amplitude is of the same form as the paper. - aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 - ! Calculate the frequency - Omega1 = J * InitInp%WaveDOmega + ! Set an initial search index for the 3D and 4D array interpolation + LastIndex3 = (/0,0,0/) + LastIndex4 = (/0,0,0,0/) + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + IF (NewmanAppData%DataIs3D) THEN + TmpData3D = NewmanAppData%Data3D%DataSet(:,:,:,Idx) + ELSE + TmpData4D = NewmanAppData%Data4D%DataSet(:,:,:,:,Idx) + END IF - ! Only get a QTF value if within the range of frequencies between the cutoffs for the difference frequency - IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN - ! Now get the QTF value that corresponds to this frequency and wavedirection pair. - IF ( NewmanAppData%DataIs3D ) THEN + DO J=1,InitInp%NStepWave2 - ! Set the (omega1,beta1,beta2) point we are looking for. - Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! First get the wave amplitude -- must be reconstructed from the WaveElevC array. First index is the real (1) or + ! imaginary (2) part. Divide by NStepWave2 so that the wave amplitude is of the same form as the paper. + aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 + ! Calculate the frequency + Omega1 = J * InitInp%WaveDOmega - ! get the interpolated value for F(omega1,beta1,beta2) - CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, NewmanAppData%Data3D%WvFreq1, & - NewmanAppData%Data3D%WvDir1, NewmanAppData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) - ELSE + ! Only get a QTF value if within the range of frequencies between the cutoffs for the difference frequency + IF ( (Omega1 >= InitInp%WvLowCOff) .AND. (Omega1 <= InitInp%WvHiCOff) ) THEN - ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Now get the QTF value that corresponds to this frequency and wavedirection pair. + IF ( NewmanAppData%DataIs3D ) THEN - ! get the interpolated value for F(omega1,omega2,beta1,beta2) - CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, NewmanAppData%Data4D%WvFreq1, NewmanAppData%Data4D%WvFreq2, & - NewmanAppData%Data4D%WvDir1, NewmanAppData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + ! Set the (omega1,beta1,beta2) point we are looking for. + Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord3(2) = Coord3(2) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord3(3) = Coord3(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - ENDIF !QTF value find + ! get the interpolated value for F(omega1,beta1,beta2) + CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, NewmanAppData%Data3D%WvFreq1, & + NewmanAppData%Data3D%WvDir1, NewmanAppData%Data3D%WvDir2, LastIndex3, QTF_Value, ErrStatTmp, ErrMsgTmp ) + ELSE - ELSE ! outside the frequency range + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) - QTF_Value = CMPLX(0.0,0.0,SiKi) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord4(3) = Coord4(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord4(4) = Coord4(4) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - ENDIF ! frequency check + ! get the interpolated value for F(omega1,omega2,beta1,beta2) + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, NewmanAppData%Data4D%WvFreq1, NewmanAppData%Data4D%WvFreq2, & + NewmanAppData%Data4D%WvDir1, NewmanAppData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + ENDIF !QTF value find - ! Check and make sure nothing bombed in the interpolation that we need to be aware of - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) - RETURN - ENDIF + ELSE ! outside the frequency range + QTF_Value = CMPLX(0.0,0.0,SiKi) - ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. - ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So - ! we throw the complex part out. - QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) + ENDIF ! frequency check - ! Now we place these results into the arrays - IF (REAL(QTF_Value) > 0.0_SiKi) THEN - NewmanTerm1C(J) = aWaveElevC * (QTF_Value)**0.5_SiKi - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + ! Check and make sure nothing bombed in the interpolation that we need to be aware of + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF - ELSE IF (REAL(QTF_Value) < 0.0_SiKi) THEN - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) - NewmanTerm2C(J) = aWaveElevC * (-QTF_Value)**0.5_SiKi - ELSE ! at 0 + ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. + ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So + ! we throw the complex part out. + QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) - ENDIF + ! Now we place these results into the arrays + IF (REAL(QTF_Value) > 0.0_SiKi) THEN + NewmanTerm1C(J) = aWaveElevC * (QTF_Value)**0.5_SiKi + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + ELSE IF (REAL(QTF_Value) < 0.0_SiKi) THEN - ENDDO + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm2C(J) = aWaveElevC * (-QTF_Value)**0.5_SiKi - ! Now we apply the FFT to the first piece. - CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) - RETURN - END IF + ELSE ! at 0 - ! Now we apply the FFT to the second piece. - CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) - RETURN - ENDIF + NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + ENDIF - ! Now square the real part of the resulting time domain pieces and add them together to get the final force time series. - DO J=0,InitInp%NStepWave-1 - NewmanAppForce(J,I) = (abs(NewmanTerm1t(J)))**2 - (abs(NewmanTerm2t(J)))**2 - ENDDO + ENDDO ! J=1,InitInp%NStepWave2 + + ! Now we apply the FFT to the first piece. + CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + END IF + + ! Now we apply the FFT to the second piece. + CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF - ! Copy the last first term to the last so that it is cyclic - NewmanAppForce(InitInp%NStepWave,I) = NewmanAppForce(0,I) - ENDIF ! Load component to calculate + ! Now square the real part of the resulting time domain pieces and add them together to get the final force time series. + DO J=0,InitInp%NStepWave-1 + NewmanAppForce(J,Idx) = (abs(NewmanTerm1t(J)))**2 - (abs(NewmanTerm2t(J)))**2 + ENDDO - ENDDO + ! Copy the last first term to the last so that it is cyclic + NewmanAppForce(InitInp%NStepWave,Idx) = NewmanAppForce(0,Idx) + + ENDIF ! Load component to calculate + + ENDDO ! ThisDim -- index to current dimension + ENDDO ! IBody -- current body ! Done with the FFT library routines, so end them. @@ -1850,7 +1939,9 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, REAL(SiKi) :: TmpReal1 !< Temporary real REAL(SiKi) :: TmpReal2 !< Temporary real LOGICAL :: TmpFlag !< Temporary logical flag - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: ThisDim !< Generic counter for dimension + INTEGER(IntKi) :: IBody !< Index to which body we are on + INTEGER(IntKi) :: Idx !< Index to the full set of 6*NBody INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using @@ -1867,7 +1958,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, REAL(SiKi), ALLOCATABLE :: TmpDiffQTFForce(:) !< The resulting diffQTF force for this load component REAL(ReKi) :: Omega1 !< First wave frequency REAL(ReKi) :: Omega2 !< Second wave frequency - REAL(SiKi) :: MnDriftForce(6) !< Mean drift force (first term). MnDrift_InitCalc routine will return this. + REAL(SiKi), ALLOCATABLE :: MnDriftForce(:) !< Mean drift force (first term). MnDrift_InitCalc routine will return this. ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq @@ -1990,8 +2081,11 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, !! and set the TmpFlag to true if there is a sparse matrix for one of them. !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implemented. TmpFlag = .FALSE. - DO I=1,6 - IF ( DiffQTFData%Data4D%DataIsSparse(I) .AND. DiffQTFData%Data4D%LoadComponents(I) .AND. p%DiffQTFDims(I) ) TmpFlag = .TRUE. + DO IBody=1,DiffQTFData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( DiffQTFData%Data4D%DataIsSparse(Idx) .AND. DiffQTFData%Data4D%LoadComponents(Idx) .AND. p%DiffQTFDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(DiffQTFData%Filename)//' is too sparse '// & @@ -2065,8 +2159,8 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ! Make sure we have a value for the mean drift for each of the dimensions we were requested to calculate. To ! find out we will just check the status of the flags for each dimension in the MnDriftDims against the ones ! for the DiffQTFDims - DO I=1,6 - IF ( p%DiffQTFDims(I) .AND. (.NOT. p%MnDriftDims(I)) ) & + DO ThisDim=1,6 + IF ( p%DiffQTFDims(ThisDim) .AND. (.NOT. p%MnDriftDims(ThisDim)) ) & CALL SetErrStat( ErrID_Fatal,' The DiffQTF method requires the use of the MnDrift method for the first term. '// & 'Something went wrong and the MnDrift method returned a different number of load components.', & ErrStat,ErrMsg,RoutineName) @@ -2082,105 +2176,108 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ! Now loop through all the dimensions and perform the calculation - DO I=1,6*p%NBody + DO IBody=1,p%NBody + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim - ! Only on the dimensions we requested, and it exists in the dataset - IF ( p%DiffQTFDims(I) .AND. DiffQTFData%Data4D%LoadComponents(I) ) THEN + ! Only on the dimensions we requested, and it exists in the dataset + IF ( p%DiffQTFDims(ThisDim) .AND. DiffQTFData%Data4D%LoadComponents(Idx) ) THEN - ! Set an initial search index for the 4D array interpolation - LastIndex4 = (/0,0,0,0/) + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) - ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays - TmpData4D = DiffQTFData%Data4D%DataSet(:,:,:,:,I) + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + TmpData4D = DiffQTFData%Data4D%DataSet(:,:,:,:,Idx) - ! Initialize the temporary array to zero. - TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + ! Initialize the temporary array to zero. + TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ! Outer loop to create the TmpComplexArr - DO J=1,InitInp%NStepWave2-1 + ! Outer loop to create the TmpComplexArr + DO J=1,InitInp%NStepWave2-1 - ! Calculate the frequency -- This is the difference frequency. - OmegaDiff = J * InitInp%WaveDOmega + ! Calculate the frequency -- This is the difference frequency. + OmegaDiff = J * InitInp%WaveDOmega - ! Only perform calculations if the difference frequency is in the right range - IF ( (OmegaDiff >= InitInp%WvLowCOffD) .AND. (OmegaDiff <= InitInp%WvHiCOffD) ) THEN + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaDiff >= InitInp%WvLowCOffD) .AND. (OmegaDiff <= InitInp%WvHiCOffD) ) THEN - ! Set the \f$ H^- \f$ term to zero before we start - TmpHMinusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + ! Set the \f$ H^- \f$ term to zero before we start + TmpHMinusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ! Do the sum over H^- - DO K=1,InitInp%NStepWave2-J ! note the funny upper limit. This is because we are doing a summation on a triangular area. + ! Do the sum over H^- + DO K=1,InitInp%NStepWave2-J ! note the funny upper limit. This is because we are doing a summation on a triangular area. - ! set the two frequencies that the difference frequency comes from - Omega1 = (J + K) * InitInp%WaveDOmega ! the mth frequency -- \mu^- + n = m - Omega2 = K * InitInp%WaveDOmega ! the nth frequency + ! set the two frequencies that the difference frequency comes from + Omega1 = (J + K) * InitInp%WaveDOmega ! the mth frequency -- \mu^- + n = m + Omega2 = K * InitInp%WaveDOmega ! the nth frequency - ! Find the Wave amplitudes 1 and 2 - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K), SiKi) / InitInp%NStepWave2 - aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K), SiKi) / InitInp%NStepWave2 + ! Find the Wave amplitudes 1 and 2 + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K), SiKi) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K), SiKi) / InitInp%NStepWave2 - ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) - ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value - CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & - DiffQTFData%Data4D%WvDir1, DiffQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) - RETURN - ENDIF + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & + DiffQTFData%Data4D%WvDir1, DiffQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + ENDIF - ! Calculate this value and add it to what we have so far. - TmpHMinusC = TmpHMinusC + aWaveElevC1 * CONJG(aWaveElevC2) * QTF_Value + ! Calculate this value and add it to what we have so far. + TmpHMinusC = TmpHMinusC + aWaveElevC1 * CONJG(aWaveElevC2) * QTF_Value - ENDDO + ENDDO - ! Copy this value difference frequency information over to the array we will take the IFFT. Divide - ! by two for the single sided FFT given in the documentation. - TmpComplexArr(J) = TmpHMinusC / 2.0_SiKi + ! Copy this value difference frequency information over to the array we will take the IFFT. Divide + ! by two for the single sided FFT given in the documentation. + TmpComplexArr(J) = TmpHMinusC / 2.0_SiKi - ELSE ! outside the frequency range, so + ELSE ! outside the frequency range, so - TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ENDIF ! frequency check + ENDIF ! frequency check - ENDDO + ENDDO - ! Now we apply the FFT to the result of the sum - CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) - RETURN - END IF + ! Now we apply the FFT to the result of the sum + CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + END IF - ! Now we multiply the result by 2 and save it to the DiffQTFForce array and add the MnDrift term - DO K=0,InitInp%NStepWave-1 ! bjj: added the "-1" here because TmpDiffQTFForce(InitInp%NStepWave) is not set and DiffQTFForce(InitInp%NStepWave,I) gets overwritten next, anyway - DiffQTFForce(K,I) = 2.0_SiKi * TmpDiffQTFForce(K) + MnDriftForce(I) - ENDDO + ! Now we multiply the result by 2 and save it to the DiffQTFForce array and add the MnDrift term + DO K=0,InitInp%NStepWave-1 ! bjj: added the "-1" here because TmpDiffQTFForce(InitInp%NStepWave) is not set and DiffQTFForce(InitInp%NStepWave,Idx) gets overwritten next, anyway + DiffQTFForce(K,Idx) = 2.0_SiKi * TmpDiffQTFForce(K) + MnDriftForce(Idx) + ENDDO - ! Copy the last first term to the last so that it is cyclic - DiffQTFForce(InitInp%NStepWave,I) = DiffQTFForce(0,I) + ! Copy the last first term to the first so that it is cyclic + DiffQTFForce(InitInp%NStepWave,Idx) = DiffQTFForce(0,Idx) - ENDIF ! Load component to calculate + ENDIF ! Load component to calculate - ENDDO + ENDDO ! ThisDim -- The current dimension + ENDDO ! IBody -- This WAMIT body @@ -2288,7 +2385,9 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er CHARACTER(2048) :: ErrMsgTmp !< Temporary error message for calls INTEGER(IntKi) :: ErrStatTmp !< Temporary error status for calls LOGICAL :: TmpFlag !< Temporary logical flag - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: ThisDim !< Generic counter for dimension + INTEGER(IntKi) :: IBody !< Index to which body we are on + INTEGER(IntKi) :: Idx !< Index to the full set of 6*NBody INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: K !< Generic counter TYPE(FFT_DataType) :: FFT_Data !< Temporary array for the FFT module we're using. For the first term in the equation. @@ -2429,8 +2528,11 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er !! and set the TmpFlag to true if there is a sparse matrix for one of them. !! FIXME: remove this check and warning once the sparse matrix interpolation routines are implimented. TmpFlag = .FALSE. - DO I=1,6 - IF ( SumQTFData%Data4D%DataIsSparse(I) .AND. SumQTFData%Data4D%LoadComponents(I) .AND. p%SumQTFDims(I) ) TmpFlag = .TRUE. + DO IBody=1,SumQTFData%Data4D%NumBodies + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + IF ( SumQTFData%Data4D%DataIsSparse(Idx) .AND. SumQTFData%Data4D%LoadComponents(Idx) .AND. p%SumQTFDims(ThisDim) ) TmpFlag = .TRUE. + ENDDO ENDDO IF (TmpFlag) THEN CALL SetErrStat(ErrID_Fatal,' The second order WAMIT data in '//TRIM(SumQTFData%Filename)//' is too sparse '// & @@ -2494,198 +2596,202 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, Er ! Now loop through all the dimensions and perform the calculation - DO I=1,6*p%NBody + DO IBody=1,p%NBody + DO ThisDim=1,6 - ! Only on the dimensions we requested, and if it is present in the data - IF ( p%SumQTFDims(I) .AND. SumQTFData%Data4D%LoadComponents(I) ) THEN + Idx = (IBody-1)*6+ThisDim + ! Only on the dimensions we requested, and if it is present in the data + IF ( p%SumQTFDims(ThisDim) .AND. SumQTFData%Data4D%LoadComponents(Idx) ) THEN - ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays - TmpData4D = SumQTFData%Data4D%DataSet(:,:,:,:,I) + ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays + TmpData4D = SumQTFData%Data4D%DataSet(:,:,:,:,Idx) - !--------------------------------------------------------------------------------- - ! Calculate the first term - ! This term is only the FFT over the diagonal elements where omega_1 = omega_2 - ! note that the sum frequency is 2*omega. The index for the sum frequency is - ! therefore 2*J. Since we are placing the calculated value for the A_m * A_m * - ! F_k^+ term in the 2*omega location, we will only run through the first half of - ! the frequencies (the sum frequency will exceed the bounds of the frequencies - ! used in the FFT otherwise). - ! The IFFT will be calculated later. - ! Set an initial search index for the 4D array interpolation - LastIndex4 = (/0,0,0,0/) + !--------------------------------------------------------------------------------- + ! Calculate the first term + ! This term is only the FFT over the diagonal elements where omega_1 = omega_2 + ! note that the sum frequency is 2*omega. The index for the sum frequency is + ! therefore 2*J. Since we are placing the calculated value for the A_m * A_m * + ! F_k^+ term in the 2*omega location, we will only run through the first half of + ! the frequencies (the sum frequency will exceed the bounds of the frequencies + ! used in the FFT otherwise). + ! The IFFT will be calculated later. - ! Initialize the array to zero - Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) + ! Initialize the array to zero + Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ! The limits look a little funny. But remember we are placing the value in the 2*J location, - ! so we cannot overun the end of the array, and the highest frequency must be zero. The - ! floor function is just in case (NStepWave2 - 1) is an odd number - DO J=1,FLOOR(REAL(InitInp%NStepWave2-1)/2.0_SiKi) - ! The frequency - Omega1 = REAL(J,ReKi) * InitInp%WaveDOmega - OmegaSum = 2.0_SiKi * Omega1 ! the sum frequency + ! The limits look a little funny. But remember we are placing the value in the 2*J location, + ! so we cannot overun the end of the array, and the highest frequency must be zero. The + ! floor function is just in case (NStepWave2 - 1) is an odd number + DO J=1,FLOOR(REAL(InitInp%NStepWave2-1)/2.0_SiKi) - ! Only perform calculations if the difference frequency is in the right range - IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN + ! The frequency + Omega1 = REAL(J,ReKi) * InitInp%WaveDOmega + OmegaSum = 2.0_SiKi * Omega1 ! the sum frequency + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN - ! Find the wave amplitude at frequency omega - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi ) / InitInp%NStepWave2 - ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Find the wave amplitude at frequency omega + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi ) / InitInp%NStepWave2 - ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value - CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & - SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - ENDIF + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) - ! Set the value of the first term in the frequency domain - Term1ArrayC(2*J) = aWaveElevC1 * aWaveElevC1 * QTF_Value + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & + SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + ! Set the value of the first term in the frequency domain + Term1ArrayC(2*J) = aWaveElevC1 * aWaveElevC1 * QTF_Value - ENDIF ! Check on the limits - ENDDO ! First term calculation + ENDIF ! Check on the limits + ENDDO ! First term calculation - !--------------------------------------------------------------------------------- - ! Calculate the second term. - ! In this term, we are are now stepping through the sum frequencies. The inner - ! sum essentially covers all the off diagonal terms (omega_m /= omega_n). The limits - ! on the outer integral that is the FFT run through the full frequency range that - ! we are using + !--------------------------------------------------------------------------------- + ! Calculate the second term. + ! In this term, we are are now stepping through the sum frequencies. The inner + ! sum essentially covers all the off diagonal terms (omega_m /= omega_n). The limits + ! on the outer integral that is the FFT run through the full frequency range that + ! we are using - ! Set an initial search index for the 4D array interpolation - LastIndex4 = (/0,0,0,0/) - ! Initialize the temporary arrays for each term to zero. - Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + ! Set an initial search index for the 4D array interpolation + LastIndex4 = (/0,0,0,0/) + ! Initialize the temporary arrays for each term to zero. + Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ! Check the limits for the high frequency cutoff. If WvHiCOffS is less than the - ! maximum frequency possible with the value of WaveDT (omega_max = pi/WaveDT = NStepWave2*WaveDOmega), - ! then we are good. If the WvHiCOff > 1/2 omega_max, then we will be potentially - ! throwing away information. However, remember the following: - ! WaveDT Omega_max wavelength - ! (s) (rad/s) (m) - ! .25 4 Pi < 1 - ! 0.5 2 Pi 1 - ! 1.0 Pi 10 - ! so, we don't need a really small WaveDT - !This section has been removed since it is kind of annoying. - ! IF ( InitInp%WvHiCOffS > InitInp%NStepWave2*InitInp%WaveDOmega ) THEN - ! CALL SetErrStat( ErrID_Warn,' The high frequency cutoff for second order wave forces, WvHiCOffS, '// & - ! 'is larger than the Nyquist frequency for the given time step of WaveDT. The Nyquist frequency '// & - ! '(highest frequency) that can be computed is OmegaMax = PI/WaveDT = '// & - ! TRIM(Num2LStr(InitInp%NStepWave2*InitInp%WaveDOmega))// & - ! ' radians/second. If you need those frequencies, decrease WaveDT. For reference, 2*PI '// & - ! 'radians/second corresponds to a wavelength of ~1 meter.',& - ! ErrStat,ErrMsg,RoutineName) - ! ENDIF + ! Check the limits for the high frequency cutoff. If WvHiCOffS is less than the + ! maximum frequency possible with the value of WaveDT (omega_max = pi/WaveDT = NStepWave2*WaveDOmega), + ! then we are good. If the WvHiCOff > 1/2 omega_max, then we will be potentially + ! throwing away information. However, remember the following: + ! WaveDT Omega_max wavelength + ! (s) (rad/s) (m) + ! .25 4 Pi < 1 + ! 0.5 2 Pi 1 + ! 1.0 Pi 10 + ! so, we don't need a really small WaveDT + !This section has been removed since it is kind of annoying. + ! IF ( InitInp%WvHiCOffS > InitInp%NStepWave2*InitInp%WaveDOmega ) THEN + ! CALL SetErrStat( ErrID_Warn,' The high frequency cutoff for second order wave forces, WvHiCOffS, '// & + ! 'is larger than the Nyquist frequency for the given time step of WaveDT. The Nyquist frequency '// & + ! '(highest frequency) that can be computed is OmegaMax = PI/WaveDT = '// & + ! TRIM(Num2LStr(InitInp%NStepWave2*InitInp%WaveDOmega))// & + ! ' radians/second. If you need those frequencies, decrease WaveDT. For reference, 2*PI '// & + ! 'radians/second corresponds to a wavelength of ~1 meter.',& + ! ErrStat,ErrMsg,RoutineName) + ! ENDIF - ! Outer loop to create the Term2ArrayC. This is stepwise through the sum frequencies. - DO J=1,InitInp%NStepWave2 - ! Calculate the frequency -- This is the sum frequency. - OmegaSum = J * InitInp%WaveDOmega + ! Outer loop to create the Term2ArrayC. This is stepwise through the sum frequencies. + DO J=1,InitInp%NStepWave2 + ! Calculate the frequency -- This is the sum frequency. + OmegaSum = J * InitInp%WaveDOmega - ! Set the \f$ H^+ \f$ term to zero before we start - TmpHPlusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + ! Set the \f$ H^+ \f$ term to zero before we start + TmpHPlusC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - ! Only perform calculations if the difference frequency is in the right range - IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN - !> Now do the inner sum. We are going to perform a sum up to the maximum frequency that we - !! can support (Nyquist frequency) for the given WaveDOmega and NStepWave2 (WaveOmegaMax = - !! NStepWave2 * WaveDOmega = Pi / WaveDT rad/second). Note that this means the largest diagonal - !! frequency we use is \f$ \omega = \Delta\omega * \f$ _NStepwave_/4. - !! So, we essentially end up running into the sampling limit. If we want higher frequency - !! terms, we need to use a smaller stepsize. + ! Only perform calculations if the difference frequency is in the right range + IF ( (OmegaSum >= InitInp%WvLowCOffS) .AND. (OmegaSum <= InitInp%WvHiCOffS) ) THEN - DO K=0,FLOOR(Real(J-1)/2.0_SiKi) + !> Now do the inner sum. We are going to perform a sum up to the maximum frequency that we + !! can support (Nyquist frequency) for the given WaveDOmega and NStepWave2 (WaveOmegaMax = + !! NStepWave2 * WaveDOmega = Pi / WaveDT rad/second). Note that this means the largest diagonal + !! frequency we use is \f$ \omega = \Delta\omega * \f$ _NStepwave_/4. + !! So, we essentially end up running into the sampling limit. If we want higher frequency + !! terms, we need to use a smaller stepsize. - ! Calculate the frequency pair - Omega1 = K * InitInp%WaveDOmega - Omega2 = (J-K) * InitInp%WaveDOmega + DO K=0,FLOOR(Real(J-1)/2.0_SiKi) - ! Find the wave amplitude at frequency omega. Remove the NStepWave2 normalization built into WaveElevC0 from Waves module - aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1, K), InitInp%WaveElevC0(2, K), SiKi ) / InitInp%NStepWave2 - aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,J-K), InitInp%WaveElevC0(2,J-K), SiKi ) / InitInp%NStepWave2 + ! Calculate the frequency pair + Omega1 = K * InitInp%WaveDOmega + Omega2 = (J-K) * InitInp%WaveDOmega - ! Set the (omega1,omega2,beta1,beta2) point we are looking for. - Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) + ! Find the wave amplitude at frequency omega. Remove the NStepWave2 normalization built into WaveElevC0 from Waves module + aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1, K), InitInp%WaveElevC0(2, K), SiKi ) / InitInp%NStepWave2 + aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,J-K), InitInp%WaveElevC0(2,J-K), SiKi ) / InitInp%NStepWave2 - ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value - CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & - SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - ENDIF + ! Set the (omega1,omega2,beta1,beta2) point we are looking for. + Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) - ! Set the value of the first term in the frequency domain. - TmpHPlusC = TmpHPlusC + aWaveElevC1 * aWaveElevC2 * QTF_Value + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value + CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & + SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF - ENDDO + ! Set the value of the first term in the frequency domain. + TmpHPlusC = TmpHPlusC + aWaveElevC1 * aWaveElevC2 * QTF_Value - ! Save the value from the summation. - Term2ArrayC(J) = TmpHPlusC + ENDDO + ! Save the value from the summation. + Term2ArrayC(J) = TmpHPlusC - ENDIF ! Check on the limits - ENDDO ! Second term calculation -- frequency step on the sum frequency + ENDIF ! Check on the limits + ENDDO ! Second term calculation -- frequency step on the sum frequency - ! Now we apply the FFT to the result of the sum. - CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - END IF - ! Now we apply the FFT to the result of the sum. - CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - ENDIF + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + END IF - ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. - DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,I) gets overwritten later, so I'm setting the array bounds to be -1. - SumQTFForce(J,I) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J), SiKi)) - ENDDO + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF - ! Copy the last first term to the last so that it is cyclic - SumQTFForce(InitInp%NStepWave,I) = SumQTFForce(0,I) + ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. + DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,Idx) gets overwritten later, so Idx'm setting the array bounds to be -1. + SumQTFForce(J,Idx) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J), SiKi)) + ENDDO - ENDIF ! Load component to calculate + ! Copy the last first term to the first so that it is cyclic + SumQTFForce(InitInp%NStepWave,Idx) = SumQTFForce(0,Idx) - ENDDO + ENDIF ! Load component to calculate + + ENDDO ! ThisDim -- current dimension + ENDDO ! IBody -- current WAMIT body From cd9da379aa50901de52ac1f1ad33ac9bcdc4fd67 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 7 Jan 2020 14:10:29 -0700 Subject: [PATCH 112/377] FlexSub: introducing DOFtilde2Nodes for convenience --- modules/subdyn/src/FEM.f90 | 21 ++++ modules/subdyn/src/SD_FEM.f90 | 18 ++- modules/subdyn/src/SubDyn.f90 | 163 ++++++++++++------------- modules/subdyn/src/SubDyn_Registry.txt | 3 +- modules/subdyn/src/SubDyn_Types.f90 | 67 +++++++++- 5 files changed, 181 insertions(+), 91 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index a3c15411a..11f69d4dc 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -133,6 +133,27 @@ FUNCTION FINDLOCI_IntKi(Array, Val) result(i) i=-1 END FUNCTION !------------------------------------------------------------------------------------------------------ +SUBROUTINE RigidTransformationLine(dx,dy,dz,iLine,Line) + real(ReKi), INTENT(IN) :: dx,dy,dz + integer(IntKi) , INTENT(IN) :: iLine + Real(ReKi), dimension(6), INTENT(OUT) :: Line + SELECT CASE (iLine) + CASE (1); Line = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); Line = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); Line = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (6); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + CASE DEFAULT + Line=-99999999_ReKi + print*,'Error in RigidTransformationLine' + STOP +! ErrStat = ErrID_Fatal +! ErrMsg = 'Error calculating transformation matrix TI ' +! return + END SELECT +END SUBROUTINE +!------------------------------------------------------------------------------------------------------ !> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) REAL(ReKi), INTENT(IN ) :: Pj(3) ! (x,y,z) positions of leader node diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 83a77163c..287e4202f 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1146,6 +1146,7 @@ END SUBROUTINE BuildTMatrix !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) + use IntegerList, only: len TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m @@ -1159,7 +1160,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly real(ReKi), dimension(:,:), allocatable :: MM, KK real(ReKi), dimension(:), allocatable :: FF - integer(IntKi) :: nDOF + integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF ErrStat = ErrID_None ErrMsg = "" @@ -1173,7 +1174,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call move_alloc(Init%K, KK) call move_alloc(Init%FG, FF) ! Reallocating - nDOF = size(m%Tred,2) + nDOF = Init%nDOFRed CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D', ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix @@ -1188,6 +1189,19 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) CALL ReInitBCs(Init, p) CALL ReInitIntFc(Init, p) + ! --- Creating a convenient Map from DOF to Nodes + call AllocAry(m%DOFtilde2Nodes, Init%nDOFRed, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; + m%DOFtilde2Nodes=-999 + do iNode=1,Init%NNode + nDOFPerNode = len(m%NodesDOFtilde(iNode)) + do iiDOF = 1, nDOFPerNode + iDOF = m%NodesDOFtilde(iNode)%List(iiDOF) + m%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index + m%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node + m%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node + enddo + enddo + call CleanUp_DirectElimination() CONTAINS diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 9698d3c4b..ef21e90ad 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -126,7 +126,7 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, !--------------------------------------------------------------------- DO I = 1,NNodes_I ! Create the node on the mesh - nodeIndx = IDI(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID + nodeIndx = IDI(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID CALL MeshPositionNode ( inputMesh & , I & , Nodes(nodeIndx,2:4) & ! position @@ -147,7 +147,7 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, !--------------------------------------------------------------------- DO I = 1,NNodes_L ! Create the node on the mesh - nodeIndx = IDL(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes + nodeIndx = IDL(I*6) / 6 !TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes CALL MeshPositionNode ( inputMesh & , I + NNodes_I & , Nodes(nodeIndx,2:4) & @@ -168,7 +168,7 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, !--------------------------------------------------------------------- DO I = 1,NNodes_C ! Create the node on the mesh - nodeIndx = IDC(I*6) / 6 !integer division gives me the actual node index, is it true? Yes it is not the nodeID + nodeIndx = IDC(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID CALL MeshPositionNode ( inputMesh & , I + NNodes_I + NNodes_L & , Nodes(nodeIndx,2:4) & @@ -221,21 +221,21 @@ SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh ) ! Interface nodes (IDI) DO I = 1,SIZE(p%IDI,1)/6 y2Node = y2Node + 1 - SDnode = p%IDI(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDnode = p%IDI(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO ! Interior nodes (IDL) DO I = 1,SIZE(p%IDL,1)/6 y2Node = y2Node + 1 - SDnode = p%IDL(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDnode = p%IDL(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO ! Base Reaction nodes (IDC) DO I = 1,SIZE(p%IDC,1)/6 y2Node = y2Node + 1 - SDnode = p%IDC(I*6) / 6 !integer division gives me the actual node index; it is not the nodeID + SDnode = p%IDC(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO @@ -1539,7 +1539,6 @@ END SUBROUTINE SD_AM2 !------------------------------------------------------------------------------------------------------ !> Perform Craig Bampton reduction SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) - use IntegerList, only: len TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine TYPE(SD_ParameterType),INTENT(INOUT) :: p ! Parameters TYPE(SD_MiscVarType), INTENT(IN ) :: m @@ -1625,7 +1624,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) ! Set p%TI and CBparams%TI2 - CALL TrnsfTI(Init, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + CALL TrnsfTI(Init, m, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1672,6 +1671,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) contains SUBROUTINE CountDOFs() + use IntegerList, only: len INTEGER(IntKi) :: iNode, iiNode ErrStat2 = ErrID_None ErrMsg2 = "" @@ -1734,7 +1734,10 @@ end subroutine CleanUpCB END SUBROUTINE Craig_Bampton !------------------------------------------------------------------------------------------------------ -!> +!> Partition matrices and vectors into Boundary (R) and internal (L) nodes +!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FGR = FG(IDR) +!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FGL = FG(IDL) +!! MRL = M(IDR, IDL), KRR = K(IDR, IDL) SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(IN ) :: p @@ -1749,6 +1752,8 @@ SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) ! local variables INTEGER(IntKi) :: I, J, II, JJ + !MRR = Init%M(p%IDR,p%IDR) + !KRR = Init%K(p%IDR,p%IDR) DO I = 1, p%DOFR !Boundary DOFs II = p%IDR(I) FGR(I) = Init%FG(II) @@ -1918,8 +1923,9 @@ END SUBROUTINE CBMatrix !------------------------------------------------------------------------------------------------------ !> -SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) +SUBROUTINE TrnsfTI(Init, m, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_MiscVarType), INTENT(IN ) :: m INTEGER(IntKi), INTENT(IN ) :: DOFI ! # of DOFS of interface nodes INTEGER(IntKi), INTENT(IN ) :: DOFR ! # of DOFS of restrained nodes (restraints and interface) INTEGER(IntKi), INTENT(IN ) :: IDI(DOFI) @@ -1929,60 +1935,59 @@ SUBROUTINE TrnsfTI(Init, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - INTEGER :: I, di - INTEGER :: rmndr, n + INTEGER :: I, J, K, iDOF, iiDOF, iNode, nDOFPerNode REAL(ReKi) :: dx, dy, dz + REAL(ReKi), dimension(6) :: Line ErrStat = ErrID_None ErrMsg = "" - - TI(:,:) = 0. !Initialize + + ! --- TI: Transformation matrix from interface points to ref point + TI(:,:)=0 DO I = 1, DOFI - di = IDI(I) - rmndr = MOD(di, 6) - n = CEILING(di/6.0) - - dx = Init%Nodes(n, 2) - Init%TP_RefPoint(1) - dy = Init%Nodes(n, 3) - Init%TP_RefPoint(2) - dz = Init%Nodes(n, 4) - Init%TP_RefPoint(3) - - SELECT CASE (rmndr) - CASE (1); TI(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) - CASE (2); TI(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) - CASE (3); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) - CASE (4); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - CASE (5); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - CASE (0); TI(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) - CASE DEFAULT - ErrStat = ErrID_Fatal - ErrMsg = 'Error calculating transformation matrix TI ' - RETURN - END SELECT + iDOF = IDI(I) ! DOF index in constrained system + iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + + if ((iiDOF<1) .or. (iiDOF>6)) then + ErrMsg = 'TransfTI, interface node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + return + endif + if (nDOFPerNode/=6) then + ErrMsg = 'TransfTI, interface node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + return + endif + dx = Init%Nodes(iNode, 2) - Init%TP_RefPoint(1) + dy = Init%Nodes(iNode, 3) - Init%TP_RefPoint(2) + dz = Init%Nodes(iNode, 4) - Init%TP_RefPoint(3) + + CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line + TI(I, 1:6) = Line ENDDO - - !Augment with TI2 + ! --- TI2: Transformation matrix from reaction points to origin TI2(:,:) = 0. !Initialize DO I = 1, DOFR - di = IDR(I) - rmndr = MOD(di, 6) - n = CEILING(di/6.0) + iDOF = IDR(I) ! DOF index in constrained system + iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + + if ((iiDOF<1) .or. (iiDOF>6)) then + ErrMsg = 'TransfTI, reaction node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + return + endif + if (nDOFPerNode/=6) then + ErrMsg = 'TransfTI, reaction node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + return + endif - dx = Init%Nodes(n, 2) - dy = Init%Nodes(n, 3) - dz = Init%Nodes(n, 4) - SELECT CASE (rmndr) - CASE (1); TI2(I, 1:6) = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) - CASE (2); TI2(I, 1:6) = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) - CASE (3); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) - CASE (4); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - CASE (5); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - CASE (0); TI2(I, 1:6) = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) - CASE DEFAULT - ErrStat = ErrID_Fatal - ErrMsg = 'Error calculating transformation matrix TI2 ' - RETURN - END SELECT + dx = Init%Nodes(iNode, 2) + dy = Init%Nodes(iNode, 3) + dz = Init%Nodes(iNode, 4) + CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) ! returns Line + TI2(I, 1:6) = Line ENDDO END SUBROUTINE TrnsfTI @@ -2461,48 +2466,51 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - INTEGER(IntKi) :: TempIDY(p%DOFC+p%DOFI+p%DOFL, 2) - INTEGER(IntKi) :: IDT(Init%TDOF) + INTEGER(IntKi), allocatable :: TempIDY(:,:) + INTEGER(IntKi), allocatable :: IDT(:) INTEGER(IntKi) :: I, K ! counters ErrStat = ErrID_None ErrMsg = "" - ! Index IDI for interface DOFs + ! Indices IDI for interface DOFs p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs (indices updated after DirectElimination) - print*,'IDI',p%IDI - ! Index IDC for constraint DOFs - p%IDC = Init%BCs(1:p%DOFC, 1) !Constraint DOFs in global uneliminated system + ! Indices IDC for constraint DOFs + p%IDC = Init%BCs(1:p%DOFC, 1) ! Reaction DOFs (indices updated after DirectElimination) - ! Index IDR for IDR DOFs + ! Indices IDR = [IDC, IDI], "retained interface DOFS" p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again p%IDR(p%DOFC+1:p%DOFR) = p%IDI ! IDR contains DOFs ofboundaries, constraints first then interface - ! --- Index IDL for IDL DOFs - ! first set the total DOFs: - DO I = 1, Init%TDOF !Total DOFs + ! --- Indices IDL for internal DOFs = AllDOF - IDR + ! First set the all DOFs indices IDT = 1:nDOFRed + allocate(IDT(1:Init%nDOFRed)) + DO I = 1, Init%nDOFRed !Total DOFs IDT(I) = I ENDDO - ! remove DOFs on the boundaries: + ! Then, remove DOFs on the boundaries: DO I = 1, p%DOFR !Boundary DOFs (Interface + Constraints) IDT(p%IDR(I)) = 0 !Set 0 wherever DOFs belong to boundaries ENDDO ! That leaves the internal DOFs: K = 0 - DO I = 1, Init%TDOF + DO I = 1, Init%nDOFRed IF ( IDT(I) .NE. 0 ) THEN K = K+1 p%IDL(K) = IDT(I) !Internal DOFs ENDIF ENDDO + deallocate(IDT) IF ( K /= p%DOFL ) THEN ErrStat = ErrID_Fatal ErrMsg = "SetIndexArrays: IDL or p%DOFL are the incorrect size." RETURN END IF - ! --- Index IDY for all DOFs: + ! --- Index [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] ! set the second column of the temp array + allocate(TempIDY(p%DOFI+p%DOFL+p%DOFC, 2)) + print*,SIZE(TempIDY),Init%nDOFRed DO I = 1, SIZE(TempIDY,1) TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) ENDDO @@ -2514,26 +2522,7 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) CALL QsortC( TempIDY ) ! the second column is the key: p%IDY = TempIDY(:, 2) - - -! do I = 1, p%DOFI !Total DOFs -! print*,'IDI ',I, p%IDI(I) -! enddo -! do I = 1, p%DOFC !Total DOFs -! print*,'IDR_c',I, p%IDR(I) -! enddo -! do I = p%DOFC+1,p%DOFR -! print*,'IDR_c',I, p%IDR(I) -! enddo -! do I = 1, p%DOFL !Total DOFs -! print*,'IDL ',I, p%IDL(I) -! enddo -! do I = 1, p%DOFC !Total DOFs -! print*,'IDC ',I, p%IDC(I) -! enddo -! do I = 1, size(p%IDY) -! print*,'IDY ',I, p%IDY(I) -! enddo + deallocate(TempIDY) END SUBROUTINE SetIndexArrays diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index bfcd3a5f9..dbb8adb8e 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -155,8 +155,9 @@ typedef ^ ^ ReKi SDWrOutput {:} - - typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" -typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" +typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" typedef ^ ^ ReKi Tred {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a3b66418d..4cac560aa 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -199,8 +199,9 @@ MODULE SubDyn_Types REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in unconstrained assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Tred !< Transformation matrix performing the constraint reduction x = T. xtilde [-] END TYPE SD_MiscVarType ! ======================= @@ -5557,6 +5558,20 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%ElemsDOF = SrcMiscData%ElemsDOF ENDIF +IF (ALLOCATED(SrcMiscData%DOFtilde2Nodes)) THEN + i1_l = LBOUND(SrcMiscData%DOFtilde2Nodes,1) + i1_u = UBOUND(SrcMiscData%DOFtilde2Nodes,1) + i2_l = LBOUND(SrcMiscData%DOFtilde2Nodes,2) + i2_u = UBOUND(SrcMiscData%DOFtilde2Nodes,2) + IF (.NOT. ALLOCATED(DstMiscData%DOFtilde2Nodes)) THEN + ALLOCATE(DstMiscData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DOFtilde2Nodes = SrcMiscData%DOFtilde2Nodes +ENDIF IF (ALLOCATED(SrcMiscData%Tred)) THEN i1_l = LBOUND(SrcMiscData%Tred,1) i1_u = UBOUND(SrcMiscData%Tred,1) @@ -5624,6 +5639,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%ElemsDOF)) THEN DEALLOCATE(MiscData%ElemsDOF) ENDIF +IF (ALLOCATED(MiscData%DOFtilde2Nodes)) THEN + DEALLOCATE(MiscData%DOFtilde2Nodes) +ENDIF IF (ALLOCATED(MiscData%Tred)) THEN DEALLOCATE(MiscData%Tred) ENDIF @@ -5766,6 +5784,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF END IF + Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no + IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes + END IF Int_BufSz = Int_BufSz + 1 ! Tred allocated yes/no IF ( ALLOCATED(InData%Tred) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Tred upper/lower bounds for each dimension @@ -6023,6 +6046,22 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) END IF + IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) + END IF IF ( .NOT. ALLOCATED(InData%Tred) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6457,6 +6496,32 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) + ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Tred not allocated Int_Xferred = Int_Xferred + 1 ELSE From 09b74613d45c8274a0da7c84fe2cb863f0a9182a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jan 2020 03:43:01 -0700 Subject: [PATCH 113/377] FlexSub: fixing init and reinit of BC and Intf --- modules/subdyn/src/SD_FEM.f90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 287e4202f..d174396a3 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -845,7 +845,7 @@ SUBROUTINE InitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - Init%BCs = 0 + Init%BCs = -9999 DO I = 1, p%NReact iNode = p%Reacts(I,1) ! Node index DO J = 1, 6 @@ -862,7 +862,7 @@ SUBROUTINE InitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - Init%IntFc = 0 + Init%IntFc = -9999 DO I = 1, Init%NInterf iNode = Init%Interf(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss @@ -1238,7 +1238,6 @@ SUBROUTINE ReInitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - Init%IntFc = 0 DO I = 1, Init%NInterf iNode = Init%Interf(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss From 09a5d7927810db98893eb098a53f86eda9bc9eda Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jan 2020 03:54:14 -0700 Subject: [PATCH 114/377] FlexSub: isolating generic part of eigensolver --- modules/subdyn/src/FEM.f90 | 90 ++++++++++++++++++++++++++++ modules/subdyn/src/SubDyn.f90 | 109 +++++++++------------------------- 2 files changed, 119 insertions(+), 80 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 11f69d4dc..478186e15 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -25,6 +25,96 @@ MODULE FEM INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors CONTAINS +!------------------------------------------------------------------------------------------------------ +!> Return eigenvalues, Omega, and eigenvectors +SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) + USE NWTC_LAPACK, only: LAPACK_ggev + USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT + INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K + REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix + REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix + REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors + REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! LOCALS + REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables + INTEGER :: i + INTEGER :: LWORK !variables for the eigensolver + INTEGER, ALLOCATABLE :: KEY(:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = '' + + ! allocate working arrays and return arrays for the eigensolver + LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine + !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out + CALL AllocAry( Work, LWORK, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAR, N, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAI, N, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( BETA, N, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( VL, N, N, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( KEY, N, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! --- Eigenvalue analysis + ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. + ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 + ! bjj: This comes from the LAPACK documentation: + ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). + ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted + CALL LAPACK_ggev('N','V',N ,K, M, ALPHAR, ALPHAI, BETA, VL, EigVect, WORK, LWORK, ErrStat2, ErrMsg2) + if(Failed()) return + + ! --- Determinign and sorting eigen frequencies + DO I=1,N !Initialize the key and calculate Omega + KEY(I)=I + IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN + Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + ELSE + Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) + END IF + ENDDO + ! Sorting + CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return + + ! --- Sorting eigen vectors + ! KEEP ME: scaling of the eigenvectors using generalized mass =identity criterion + ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) + ! result1 = matmul(M,EigVect) + ! result2 = matmul(transpose(EigVect),result1) + ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors + ! normcoeff=sqrt(matmul(transpose(EigVect),matmul(M,EigVect))) !This should be a diagonal matrix which contains the normalization factors + VL=EigVect !temporary storage for sorting EigVect + DO I=1,N + !EigVect(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized + EigVect(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one + ENDDO + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + CALL CleanupEigen() + RETURN + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + + SUBROUTINE CleanupEigen() + IF (ALLOCATED(Work) ) DEALLOCATE(Work) + IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) + IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) + IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) + IF (ALLOCATED(VL) ) DEALLOCATE(VL) + IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) + END SUBROUTINE CleanupEigen + +END SUBROUTINE EigenSolve + !------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ef21e90ad..de6f263fd 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -330,7 +330,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL EigenSolve( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL EigenSolveWrap( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return @@ -1794,8 +1794,8 @@ END SUBROUTINE BreakSysMtrx !................................ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) - TYPE(SD_InitType), INTENT(IN) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_InitType), INTENT(IN) :: Init ! TODO remove me + TYPE(SD_ParameterType), INTENT(INOUT) :: p ! TODO remove m INTEGER(IntKi), INTENT( in) :: DOFM REAL(ReKi), INTENT( IN) :: MRR( p%DOFR, p%DOFR) REAL(ReKi), INTENT( IN) :: MLL( p%DOFL, p%DOFL) @@ -1839,7 +1839,7 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & ! Set OmegaL and PhiL from Eq. 2 !.................................................... IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - CALL EigenSolve(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + CALL EigenSolveWrap(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL ! bjj: break up this equation to avoid as many tenporary variables on the stack @@ -1878,7 +1878,7 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & ! Set PhiR from Eq. 3: !.................................................... ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) - ! ** note this must be done after EigenSolve() because it modifies KLL ** + ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** CALL LAPACK_getrf( p%DOFL, p%DOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) @@ -1993,8 +1993,10 @@ SUBROUTINE TrnsfTI(Init, m, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ -!> Return eigenvalues, Omega, and eigenvectors, Phi, -SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega, ErrStat, ErrMsg ) +!> Warpper funciton for eigen value analyses, for two cases: +!! Case1: K and M are taken "as is" (bRemoveConstraints=false), This is used for the "LL" part of the matrix +!! Case2: K and M constain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system +SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega, ErrStat, ErrMsg ) USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix @@ -2008,14 +2010,9 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omeg INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! LOCALS - REAL(LAKi), ALLOCATABLE :: Omega2(:) !RRD: Eigen-values new system -! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. -! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 REAL(LAKi), ALLOCATABLE :: Kred(:,:), Mred(:,:) - REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), VR(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables - INTEGER :: i - INTEGER :: N, LWORK !variables for the eigensolver - INTEGER, ALLOCATABLE :: KEY(:) + REAL(LAKi), ALLOCATABLE :: EigVect(:,:), Omega2_LaKi(:) + INTEGER :: N INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) @@ -2023,14 +2020,13 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omeg ErrStat = ErrID_None ErrMsg = '' - !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + ! --- Special handling if constraint are present, and type conversion IF (bRemoveConstraints) THEN - ! Removing constrained nodes DOFs - ! This is actually done when we are printing out the 'full' set of eigenvalues - ! Mred = M[bDOF,bDOF], Kred = K[bDOF,bDOF] + ! Removing constrained nodes DOFs, only done for printing out the 'full' set of eigenvalues + ! Mred = M[bDOF,bDOF], Kred = K[bDOF,bDOF] call SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat2, ErrMsg2); if(Failed()) return call RemoveDOF(M, bDOF, Mred, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(M, bDOF, Kred, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, Kred, ErrStat2, ErrMsg2); if(Failed()) return N=SIZE(Kred,1) ELSE ! This is actually done whe we are generating the CB-reduced set of eigenvalues @@ -2042,64 +2038,23 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omeg ENDIF ! Note: NOmega must be <= N, which is the length of Omega2, Phi! IF ( NOmega > N ) THEN - CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolve') + CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') CALL CleanupEigen() RETURN END IF - ! allocate working arrays and return arrays for the eigensolver - LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine - !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out - CALL AllocAry( Work, lwork, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( Omega2, n, 'Omega2', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAR, n, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAI, n, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( BETA, n, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( VR, n, n, 'VR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( VL, n, n, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( KEY, n, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return - - CALL LAPACK_ggev('N','V',N ,Kred, Mred, ALPHAR, ALPHAI, BETA, VL, VR, work, lwork, ErrStat2, ErrMsg2) - if(Failed()) return - !if (.not. reduced) call wrmatrix(REAL(VR,ReKi),77,'ES15.8e2') - ! bjj: This comes from the LAPACK documentation: - ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. - ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less - ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). - ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted - DO I=1,N !Initialize the key and calculate Omega2 - KEY(I)=I - IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN - Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? - ELSE - Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) - END IF - ENDDO - CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return - - !we need to rearrange eigenvectors based on sorting of Omega2 - !Now rearrange VR based on the new key, also I might have to scale the eigenvectors following generalized mass =idnetity criterion, also if i reduced the matrix I will need to re-expand the eigenvector - ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) - ! result1 = matmul(Mred2,VR) - ! result2 = matmul(transpose(VR),result1) - ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors - !normcoeff=sqrt(matmul(transpose(VR),matmul(Mred2,VR))) !This should be a diagonal matrix which contains the normalization factors - VL=VR !temporary storage for sorting VR - DO I=1,N - !VR(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized - VR(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one - ENDDO - !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + ! --- Eigenvalue analysis + CALL AllocAry( Omega2_LaKi, N, 'Omega', ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL AllocAry( EigVect , N, N, 'EigVect', ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL EigenSolve(Kred, Mred, N, EigVect, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; - ! --- Finish EigenSolve - ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - Omega=SQRT( Omega2(1:NOmega) ) !Assign my new Omega and below my new Phi (eigenvectors) [eigenvalues are actually the square of omega] + ! --- Setting up Phi, and type conversion + Omega=sqrt(Omega2_LaKi(1:NOmega) ) IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: !Need to expand eigenvectors for removed DOFs, setting Phi - CALL InsertDOFrows(VR(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return - ELSE ! For the time being Phi gets updated only when CB eigensolver is requested. I need to fix it for the other case (full fem) and then get rid of the other eigensolver, this implies "unreducing" the VR - ! This is done as part of the CB-reduced eigensolve - Phi=REAL( VR(:,1:NOmega), ReKi ) ! eigenvectors + CALL InsertDOFrows(EigVect(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return + ELSE + Phi=REAL( EigVect(:,1:NOmega), ReKi ) ! eigenvectors ENDIF CALL CleanupEigen() @@ -2107,26 +2062,20 @@ SUBROUTINE EigenSolve(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omeg CONTAINS LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') Failed = ErrStat >= AbortErrLev if (Failed) call CleanUpEigen() END FUNCTION Failed SUBROUTINE CleanupEigen() - IF (ALLOCATED(Work) ) DEALLOCATE(Work) - IF (ALLOCATED(Omega2)) DEALLOCATE(Omega2) !bjj: break in Debug_Doub - IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) - IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) - IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) - IF (ALLOCATED(VR) ) DEALLOCATE(VR) - IF (ALLOCATED(VL) ) DEALLOCATE(VL) - IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) + IF (ALLOCATED(Omega2_LaKi)) DEALLOCATE(Omega2_LaKi) + IF (ALLOCATED(EigVect) ) DEALLOCATE(EigVect) IF (ALLOCATED(Kred) ) DEALLOCATE(Kred) IF (ALLOCATED(Mred) ) DEALLOCATE(Mred) IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) END SUBROUTINE CleanupEigen -END SUBROUTINE EigenSolve +END SUBROUTINE EigenSolveWrap !> Returns a list of boolean which are true if a DOF is not part of a BC constraint SUBROUTINE SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat, ErrMsg ) From 73cffd057b4f87a61e65f5f6bd76da69c6967513 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 8 Jan 2020 10:33:43 -0700 Subject: [PATCH 115/377] TCF: fix mistake in WAMIT2 setup in hydrodyn.f90 --- modules/hydrodyn/src/HydroDyn.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index f3c0a4742..db9aa71a7 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1051,10 +1051,10 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I allocate( m%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%WAMIT2.', ErrStat, ErrMsg, RoutineName ) allocate( m%u_WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array m%u_WAMIT2.', ErrStat, ErrMsg, RoutineName ) allocate( InitOut%WAMIT2( 1), stat = ErrStat2 ); if (ErrStat2 /=0) call SetErrStat( ErrID_Fatal, 'Failed to allocate array InitOut%WAMIT2.', ErrStat, ErrMsg, RoutineName ) - InitLocal%WAMIT2%PtfmRefxt (1) = InitLocal%PtfmRefxt (1) - InitLocal%WAMIT2%PtfmRefyt (1) = InitLocal%PtfmRefyt (1) - InitLocal%WAMIT2%PtfmRefzt (1) = InitLocal%PtfmRefzt (1) - InitLocal%WAMIT2%PtfmRefztRot(1) = InitLocal%PtfmRefztRot(1) + InitLocal%WAMIT2%PtfmRefxt = InitLocal%PtfmRefxt + InitLocal%WAMIT2%PtfmRefyt = InitLocal%PtfmRefyt + InitLocal%WAMIT2%PtfmRefzt = InitLocal%PtfmRefzt + InitLocal%WAMIT2%PtfmRefztRot = InitLocal%PtfmRefztRot else InitLocal%WAMIT2%NBody = 1_IntKi ! The WAMIT2 object will contain all NBody WAMIT2 bodies From a6c015891b399be7258df8f206bc177ec087c257 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 8 Jan 2020 15:35:04 -0700 Subject: [PATCH 116/377] TCF: pass gravity and waterdepth to WAMIT2 for wavenumber calcs --- modules/hydrodyn/src/HydroDyn.f90 | 2 ++ modules/hydrodyn/src/WAMIT2.txt | 2 ++ modules/hydrodyn/src/WAMIT2_Types.f90 | 14 ++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index db9aa71a7..fbe6deb71 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1029,6 +1029,8 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitLocal%WAMIT2%WaveDirMin = Waves_InitOut%WaveDirMin InitLocal%WAMIT2%WaveDirMax = Waves_InitOut%WaveDirMax InitLocal%WAMIT2%WaveDOmega = Waves_InitOut%WaveDOmega + InitLocal%WAMIT2%Gravity = InitLocal%Gravity + InitLocal%WAMIT2%WtrDpth = InitLocal%Morison%WtrDpth ! The data in InitLocal%Morison%WtrDpth was directly placed there when we parsed the HydroDyn input file ! Set values for all NBodyMods InitLocal%WAMIT2%NBodyMod = InitLocal%NBodyMod ! There are restrictions in WAMIT2 on which files may be used for MnDriftF or NewmanAppF for BodyMod > 1 diff --git a/modules/hydrodyn/src/WAMIT2.txt b/modules/hydrodyn/src/WAMIT2.txt index c9f840e7b..6fedc15d3 100644 --- a/modules/hydrodyn/src/WAMIT2.txt +++ b/modules/hydrodyn/src/WAMIT2.txt @@ -33,6 +33,8 @@ typedef ^ ^ INTEGER NStepWave typedef ^ ^ INTEGER NStepWave2 - - - "NStepWave / 2" - typedef ^ ^ ReKi WaveDOmega - - - "Frequency step for incident wave calculations" (rad/s) typedef ^ ^ ReKi WtrDens - - - "Water density" (kg/m^3) +typedef ^ ^ ReKi Gravity - - - "Supplied by Driver: Gravitational acceleration" (m/s^2) +typedef ^ ^ SiKi WtrDpth - - - "Water depth (positive-valued)" (m) typedef ^ ^ SiKi WaveElevC0 {:}{:} - - "Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part" (meters) typedef ^ ^ SiKi WaveDir - - - "Mean incident wave propagation heading direction" (degrees) diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index e99849f12..985857fd3 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -51,6 +51,8 @@ MODULE WAMIT2_Types INTEGER(IntKi) :: NStepWave2 !< NStepWave / 2 [-] REAL(ReKi) :: WaveDOmega !< Frequency step for incident wave calculations [(rad/s)] REAL(ReKi) :: WtrDens !< Water density [(kg/m^3)] + REAL(ReKi) :: Gravity !< Supplied by Driver: Gravitational acceleration [(m/s^2)] + REAL(SiKi) :: WtrDpth !< Water depth (positive-valued) [(m)] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevC0 !< Discrete Fourier transform of the instantaneous elevation of incident waves at the platform reference point. First column is real part, second column is imaginary part [(meters)] REAL(SiKi) :: WaveDir !< Mean incident wave propagation heading direction [(degrees)] LOGICAL :: WaveMultiDir !< Indicates the waves are multidirectional -- set by HydroDyn_Input [-] @@ -217,6 +219,8 @@ SUBROUTINE WAMIT2_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%NStepWave2 = SrcInitInputData%NStepWave2 DstInitInputData%WaveDOmega = SrcInitInputData%WaveDOmega DstInitInputData%WtrDens = SrcInitInputData%WtrDens + DstInitInputData%Gravity = SrcInitInputData%Gravity + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth IF (ALLOCATED(SrcInitInputData%WaveElevC0)) THEN i1_l = LBOUND(SrcInitInputData%WaveElevC0,1) i1_u = UBOUND(SrcInitInputData%WaveElevC0,1) @@ -374,6 +378,8 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! NStepWave2 Re_BufSz = Re_BufSz + 1 ! WaveDOmega Re_BufSz = Re_BufSz + 1 ! WtrDens + Re_BufSz = Re_BufSz + 1 ! Gravity + Re_BufSz = Re_BufSz + 1 ! WtrDpth Int_BufSz = Int_BufSz + 1 ! WaveElevC0 allocated yes/no IF ( ALLOCATED(InData%WaveElevC0) ) THEN Int_BufSz = Int_BufSz + 2*2 ! WaveElevC0 upper/lower bounds for each dimension @@ -511,6 +517,10 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDens Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveElevC0) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -743,6 +753,10 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%WtrDens = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = REAL( ReKiBuf( Re_Xferred ), SiKi) + Re_Xferred = Re_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 not allocated Int_Xferred = Int_Xferred + 1 ELSE From c0b122c16d617fb8450e09f64336c9c1d4797823 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 8 Jan 2020 15:37:27 -0700 Subject: [PATCH 117/377] TCF: add phase shift due to body location to WAMIT2 --- modules/hydrodyn/src/WAMIT2.f90 | 184 +++++++++++++++++++++----------- 1 file changed, 122 insertions(+), 62 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 572975b84..2e3ef4261 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -51,7 +51,7 @@ MODULE WAMIT2 !! - + USE Waves, ONLY: WaveNumber USE WAMIT2_Types USE WAMIT_Interp USE NWTC_Library @@ -1347,8 +1347,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF - COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1C(:) !< First term in the newman calculation, complex frequency space. Current load dimension. - COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2C(:) !< Second term in the newman calculation, complex frequency space. Current load dimension. + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1C(:,:) !< First term in the newman calculation, complex frequency space. All dimensions, this body. + COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2C(:,:) !< Second term in the newman calculation, complex frequency space. All dimensions, this body. COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm1t(:) !< First term in the newman calculation, time domain. Current load dimension. COMPLEX(SiKi), ALLOCATABLE :: NewmanTerm2t(:) !< Second term in the newman calculation, time domain. Current load dimension. COMPLEX(SiKi) :: aWaveElevC !< Wave elevation of current frequency component. NStepWave2 factor removed. @@ -1360,7 +1360,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) - REAL(SiKi) :: OffsetXY(2) !< The phase shift offset to apply to the body + COMPLEX(SiKi) :: PhaseShiftXY !< The phase shift offset to apply to the body + REAL(SiKi) :: WaveNmbr1 !< Wavenumber for this frequency COMPLEX(SiKi), ALLOCATABLE :: TmpData3D(:,:,:) !< Temporary 3D array we put the 3D data into (minus the load component indice) COMPLEX(SiKi), ALLOCATABLE :: TmpData4D(:,:,:,:) !< Temporary 4D array we put the 4D data into (minus the load component indice) @@ -1644,10 +1645,10 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ALLOCATE( NewmanTerm2t( 0:InitInp%NStepWave ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & 'approximation in the time domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( NewmanTerm1C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) + ALLOCATE( NewmanTerm1C( 0:InitInp%NStepWave2, 6 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the first term of the Newmans '// & 'approximation in the frequency domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( NewmanTerm2C( 0:InitInp%NStepWave2 ), STAT=ErrStatTmp ) + ALLOCATE( NewmanTerm2C( 0:InitInp%NStepWave2, 6 ), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for calculating the second term of the Newmans '// & 'approximation in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( NewmanAppForce( 0:InitInp%NStepWave, 6*p%NBody), STAT=ErrStatTmp ) @@ -1688,17 +1689,21 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp END IF - - ! Now loop through all the dimensions and perform the calculation + ! Loop through all bodies DO IBody=1,p%NBody + + ! set all frequency terms to zero to start + NewmanTerm1C(:,:) = CMPLX(0.0, 0.0, SiKi) + NewmanTerm2C(:,:) = CMPLX(0.0, 0.0, SiKi) + + !---------------------------------------------------- + ! Populate the frequency terms for this body + !---------------------------------------------------- + DO ThisDim=1,6 Idx= (IBody-1)*6+ThisDim - ! set zero frequency term to zero - NewmanTerm1C(0) = CMPLX(0.0, 0.0, SiKi) - NewmanTerm2C(0) = CMPLX(0.0, 0.0, SiKi) - IF (NewmanAppData%DataIs3D) THEN TmpFlag = NewmanAppData%Data3D%LoadComponents(Idx) ELSE @@ -1725,6 +1730,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ! First get the wave amplitude -- must be reconstructed from the WaveElevC array. First index is the real (1) or ! imaginary (2) part. Divide by NStepWave2 so that the wave amplitude is of the same form as the paper. aWaveElevC = CMPLX( InitInp%WaveElevC0(1,J), InitInp%WaveElevC0(2,J), SiKi) / InitInp%NStepWave2 + ! Calculate the frequency Omega1 = J * InitInp%WaveDOmega @@ -1762,6 +1768,11 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ENDIF !QTF value find + ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. + ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So + ! we throw the complex part out. NOTE: the phase shift due to location will be added before the FFT. + QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) + ELSE ! outside the frequency range @@ -1769,8 +1780,6 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ENDIF ! frequency check - - ! Check and make sure nothing bombed in the interpolation that we need to be aware of CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN @@ -1784,74 +1793,125 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp RETURN ENDIF - - - ! Now we have the value of the QTF. These values should only be real for the omega1=omega2 case of the approximation. - ! However if the value came from the 4D interpolation routine, it might have some residual complex part to it. So - ! we throw the complex part out. - QTF_Value = CMPLX(REAL(QTF_Value,SiKi),0.0,SiKi) - - - ! Now we place these results into the arrays + ! Now calculate the Newman terms IF (REAL(QTF_Value) > 0.0_SiKi) THEN - NewmanTerm1C(J) = aWaveElevC * (QTF_Value)**0.5_SiKi - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm1C(J,ThisDim) = aWaveElevC * (QTF_Value)**0.5_SiKi + NewmanTerm2C(J,ThisDim) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ELSE IF (REAL(QTF_Value) < 0.0_SiKi) THEN - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) - NewmanTerm2C(J) = aWaveElevC * (-QTF_Value)**0.5_SiKi + NewmanTerm1C(J,ThisDim) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm2C(J,ThisDim) = aWaveElevC * (-QTF_Value)**0.5_SiKi ELSE ! at 0 - NewmanTerm1C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) - NewmanTerm2C(J) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm1C(J,ThisDim) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) + NewmanTerm2C(J,ThisDim) = CMPLX(0.0_SiKi, 0.0_SiKi, SiKi) ENDIF + ENDDO ! J=1,InitInp%NStepWave2 - ! Now we apply the FFT to the first piece. - CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) - RETURN - END IF + ENDIF ! Load component to calculate - ! Now we apply the FFT to the second piece. - CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) - IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) - RETURN - ENDIF + ENDDO ! ThisDim -- index to current dimension - ! Now square the real part of the resulting time domain pieces and add them together to get the final force time series. - DO J=0,InitInp%NStepWave-1 - NewmanAppForce(J,Idx) = (abs(NewmanTerm1t(J)))**2 - (abs(NewmanTerm2t(J)))**2 - ENDDO + !---------------------------------------------------- + ! Rotate back to global frame and phase shift and set the terms for the summation + !---------------------------------------------------- - ! Copy the last first term to the last so that it is cyclic - NewmanAppForce(InitInp%NStepWave,Idx) = NewmanAppForce(0,Idx) + ! Set rotation + ! NOTE: RotateZMatrixT is the rotation from local to global. + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(ThisBodyNum)), -sin(InitInp%PtfmRefztRot(ThisBodyNum)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(ThisBodyNum)), cos(InitInp%PtfmRefztRot(ThisBodyNum)) /) - ENDIF ! Load component to calculate + ! Loop through all the frequencies + DO J=1,InitInp%NStepWave2 + + ! Frequency + Omega1 = J * InitInp%WaveDOmega + + !> Phase shift due to offset in location + !! The phase shift due to an (x,y) offset is of the form + !! \f$ exp(-\imath k(\omega) ( X cos(\Beta(w)) + Y sin(\beta(w)) )) \f$ + ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead + ! of above is mathematically equivalent, but only because each frequency has only one wave + ! direction associated with it through the equal energy approach used in multidirectional waves. + + WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J)*D2R) ) + PhaseShiftXY = CMPLX( cos(TmpReal1), -sin(TmpReal1) ) + + + ! Apply the phase shift + DO ThisDim=1,6 + NewmanTerm1C(J,ThisDim) = NewmanTerm1C(J,ThisDim)*PhaseShiftXY ! Newman term 1 + NewmanTerm2C(J,ThisDim) = NewmanTerm2C(J,ThisDim)*PhaseShiftXY ! Newman term 2 + ENDDO + + + ! Apply the rotation to get back to global frame -- Term 1 + NewmanTerm1C(J,1:2) = MATMUL(RotateZMatrixT, NewmanTerm1C(J,1:2)) + NewmanTerm1C(J,4:5) = MATMUL(RotateZMatrixT, NewmanTerm1C(J,4:5)) + + ! Apply the rotation to get back to global frame -- Term 2 + NewmanTerm2C(J,1:2) = MATMUL(RotateZMatrixT, NewmanTerm2C(J,1:2)) + NewmanTerm2C(J,4:5) = MATMUL(RotateZMatrixT, NewmanTerm2C(J,4:5)) + + ENDDO ! J=1,InitInp%NStepWave2 + + + + !---------------------------------------------------- + ! Apply the FFT to get time domain results + !---------------------------------------------------- + + DO ThisDim=1,6 ! Loop through all dimensions + + Idx= (IBody-1)*6+ThisDim + + ! Now we apply the FFT to the first piece. + CALL ApplyCFFT( NewmanTerm1t(:), NewmanTerm1C(:,ThisDim), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + END IF + + ! Now we apply the FFT to the second piece. + CALL ApplyCFFT( NewmanTerm2t(:), NewmanTerm2C(:,ThisDim), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData3D)) DEALLOCATE(TmpData3D,STAT=ErrStatTmp) + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1t)) DEALLOCATE(NewmanTerm1t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2t)) DEALLOCATE(NewmanTerm2t,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm1C)) DEALLOCATE(NewmanTerm1C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanTerm2C)) DEALLOCATE(NewmanTerm2C,STAT=ErrStatTmp) + IF (ALLOCATED(NewmanAppForce)) DEALLOCATE(NewmanAppForce,STAT=ErrStatTmp) + RETURN + ENDIF + + + ! Now square the real part of the resulting time domain pieces and add them together to get the final force time series. + DO J=0,InitInp%NStepWave-1 + NewmanAppForce(J,Idx) = (abs(NewmanTerm1t(J)))**2 - (abs(NewmanTerm2t(J)))**2 + ENDDO + + ! Copy the last first term to the last so that it is cyclic + NewmanAppForce(InitInp%NStepWave,Idx) = NewmanAppForce(0,Idx) ENDDO ! ThisDim -- index to current dimension + ENDDO ! IBody -- current body From 919a63ab5a085a5496855b053cbd49c0ecbf46fb Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 8 Jan 2020 16:13:10 -0700 Subject: [PATCH 118/377] TCF: WAMIT2 -- remove useless variable --- modules/hydrodyn/src/WAMIT2.f90 | 47 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 2e3ef4261..fd45ce50e 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -231,9 +231,8 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini INTEGER(IntKi) :: ThisDim !< Counter to currrent dimension INTEGER(IntKi) :: J !< Generic counter INTEGER(IntKi) :: Idx !< Generic counter - INTEGER(IntKi) :: ThisBodyNum !< Current body number - REAL(R8Ki) :: theta(3) !< rotation about z for ThisBodyNum (0 about x,y) - REAL(R8Ki) :: orientation(3,3) !< Orientation matrix for orientation of ThisBodyNum + REAL(R8Ki) :: theta(3) !< rotation about z for the current body (0 about x,y) + REAL(R8Ki) :: orientation(3,3) !< Orientation matrix for orientation of the current body REAL(ReKi) :: XYZloc(3) !< Starting position of this WAMIT2 body @@ -542,15 +541,13 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini -!FIXME: does this actually need to be passed in? All body iterations occur within each init routine -ThisBodyNum=1 !> If the MnDrift method will be used, call the subroutine to calculate the force time series IF ( p%MnDriftF ) THEN ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order mean drift force.' ) - CALL MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -564,7 +561,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( " Calculating second order difference-frequency force using the Newman's approximation." ) - CALL NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanAppForce, ErrMsgTmp, ErrStatTmp ) + CALL NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -580,7 +577,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order difference-frequency force using the full quadratic transfer function.' ) - CALL DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -594,7 +591,7 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Tell our nice users what is about to happen that may take a while: CALL WrScr ( ' Calculating second order sum-frequency force using the full quadratic transfer function.' ) - CALL SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, ErrMsgTmp, ErrStatTmp ) + CALL SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp @@ -696,19 +693,19 @@ SUBROUTINE WAMIT2_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini RETURN END IF - DO ThisBodyNum = 1,p%NBody + DO IBody = 1,p%NBody ! Set orientation and position for each body in mesh - theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(ThisBodyNum)/) ! angle in radians + theta = (/ 0.0_R8Ki, 0.0_R8Ki, InitInp%PtfmRefztRot(IBody)/) ! angle in radians orientation = EulerConstruct(theta) - XYZloc = (/InitInp%PtfmRefxt(ThisBodyNum), InitInp%PtfmRefyt(ThisBodyNum), InitInp%PtfmRefzt(ThisBodyNum)/) + XYZloc = (/InitInp%PtfmRefxt(IBody), InitInp%PtfmRefyt(IBody), InitInp%PtfmRefzt(IBody)/) ! Create the node on the mesh - CALL MeshPositionNode (u%Mesh, ThisBodyNum, XYZloc, ErrStatTmp, ErrMsgTmp, orientation ) + CALL MeshPositionNode (u%Mesh, IBody, XYZloc, ErrStatTmp, ErrMsgTmp, orientation ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ! Create the mesh element - CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, ThisBodyNum ) + CALL MeshConstructElement ( u%Mesh, ELEMENT_POINT, ErrStatTmp, ErrMsgTmp, IBody ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) ENDDO @@ -808,13 +805,12 @@ END SUBROUTINE CleanUp !! Since the frequency range of the QTF has not yet been checked, we will do that now. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ErrMsg, ErrStat ) + SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: MnDriftData !< Data storage for the MnDrift method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: MnDriftForce(:) !< Force data. Index 1 is the force component. Constant for all time. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1247,8 +1243,8 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, ThisBodyNum, MnDriftData, MnDriftForce, ! Now rotate the force components with platform orientation ! NOTE: RotateZMatrixT is the rotation from local to global. - RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(ThisBodyNum)), -sin(InitInp%PtfmRefztRot(ThisBodyNum)) /) - RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(ThisBodyNum)), cos(InitInp%PtfmRefztRot(ThisBodyNum)) /) + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) MnDriftForce(1:2) = MATMUL( RotateZMatrixT, MnDriftForce(1:2) ) ! Fx and Fy, rotation about z @@ -1318,13 +1314,12 @@ END SUBROUTINE MnDrift_InitCalc !! Since the frequency range of the QTF has not yet been checked, we will do that now. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanAppForce, ErrMsg, ErrStat ) + SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: NewmanAppData !< Data storage for the NewmanApp method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: NewmanAppForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1825,8 +1820,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, ThisBodyNum, NewmanAppData, NewmanApp ! Set rotation ! NOTE: RotateZMatrixT is the rotation from local to global. - RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(ThisBodyNum)), -sin(InitInp%PtfmRefztRot(ThisBodyNum)) /) - RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(ThisBodyNum)), cos(InitInp%PtfmRefztRot(ThisBodyNum)) /) + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) ! Loop through all the frequencies DO J=1,InitInp%NStepWave2 @@ -1981,13 +1976,12 @@ END SUBROUTINE NewmanApp_InitCalc !! Since the frequency range of the QTF has not yet been checked, we will do that now as well. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ErrMsg, ErrStat ) + SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_DiffData_Type), INTENT(INOUT) :: DiffQTFData !< Data storage for the DiffQTF method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: DiffQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2206,7 +2200,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, DiffQTFForce, ! Before we continue, we will get the MnDriftForce results. ! --> Note that we can pass the DiffQTFData directly since we are using the same type for both - CALL MnDrift_InitCalc( InitInp, p, ThisBodyNum, DiffQTFData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) + CALL MnDrift_InitCalc( InitInp, p, DiffQTFData, MnDriftForce, ErrMsgTmp, ErrStatTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) @@ -2429,13 +2423,12 @@ END SUBROUTINE DiffQTF_InitCalc !! if the cutoff for the highest sum frequency, _WvHiCOffS_ is above the Nyquist frequency. !! !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE SumQTF_InitCalc( InitInp, p, ThisBodyNum, SumQTFData, SumQTFForce, ErrMsg, ErrStat ) + SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ) IMPLICIT NONE TYPE(WAMIT2_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine TYPE(WAMIT2_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT(IN ) :: ThisBodyNum !< Which body are we on TYPE(W2_SumData_Type), INTENT(INOUT) :: SumQTFData !< Data storage for the SumQTF method. Set to INOUT in case we need to convert 4D to 3D REAL(SiKi), ALLOCATABLE, INTENT( OUT) :: SumQTFForce(:,:) !< Force data. Index 1 is the timestep, index 2 is the load component. CHARACTER(*), INTENT( OUT) :: ErrMsg From 79fe2e647574fc8f722d7a1dcbacd102dfa1ff4b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 8 Jan 2020 16:15:40 -0700 Subject: [PATCH 119/377] TCF: WAMIT2 fix heading corrections in MnDrift and Newman approx --- modules/hydrodyn/src/WAMIT2.f90 | 47 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index fd45ce50e..645884e33 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -838,6 +838,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex3(3) !< Last used index for searching in the interpolation algorithms INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms + REAL(SiKi) :: RotateZdegOffset !< Offset to wave heading (NBodyMod==2 only) REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset @@ -1135,6 +1136,15 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ! Now loop through all the dimensions and perform the calculation DO IBody=1,p%NBody + + ! Heading correction, only applies to NBodyMod == 2 + if (p%NBodyMod==2) then + RotateZdegOffset = InitInp%PtfmRefztRot(IBody)*R2D + else + RotateZdegOffset = 0.0_SiKi + endif + + DO ThisDim=1,6 Idx = (IBody-1)*6 + ThisDim @@ -1186,8 +1196,8 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame - Coord3(2) = Coord3(2) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - Coord3(3) = Coord3(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord3(2) = Coord3(2) - RotateZdegOffset + Coord3(3) = Coord3(3) - RotateZdegOffset ! get the interpolated value for F(omega1,beta1,beta2) CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, MnDriftData%Data3D%WvFreq1, & @@ -1199,8 +1209,8 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame - Coord4(3) = Coord4(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - Coord4(4) = Coord4(4) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord4(3) = Coord4(3) - RotateZdegOffset + Coord4(4) = Coord4(4) - RotateZdegOffset ! get the interpolated value for F(omega1,omega2,beta1,beta2) CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, MnDriftData%Data4D%WvFreq1, MnDriftData%Data4D%WvFreq2, & @@ -1354,6 +1364,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms REAL(SiKi) :: Coord3(3) !< The (omega1,beta1,beta2) coordinate we want in the 3D dataset REAL(SiKi) :: Coord4(4) !< The (omega1,omega2,beta1,beta2) coordinate we want in the 4D dataset + REAL(SiKi) :: RotateZdegOffset !< Offset to wave heading (NBodyMod==2 only) REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) COMPLEX(SiKi) :: PhaseShiftXY !< The phase shift offset to apply to the body REAL(SiKi) :: WaveNmbr1 !< Wavenumber for this frequency @@ -1691,6 +1702,14 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg NewmanTerm1C(:,:) = CMPLX(0.0, 0.0, SiKi) NewmanTerm2C(:,:) = CMPLX(0.0, 0.0, SiKi) + + ! Heading correction, only applies to NBodyMod == 2 + if (p%NBodyMod==2) then + RotateZdegOffset = InitInp%PtfmRefztRot(IBody)*R2D + else + RotateZdegOffset = 0.0_SiKi + endif + !---------------------------------------------------- ! Populate the frequency terms for this body !---------------------------------------------------- @@ -1740,8 +1759,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg Coord3 = (/ REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame - Coord3(2) = Coord3(2) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - Coord3(3) = Coord3(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord3(2) = Coord3(2) - RotateZdegOffset + Coord3(3) = Coord3(3) - RotateZdegOffset ! get the interpolated value for F(omega1,beta1,beta2) CALL WAMIT_Interp3D_Cplx( Coord3, TmpData3D, NewmanAppData%Data3D%WvFreq1, & @@ -1753,8 +1772,8 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame - Coord4(3) = Coord4(3) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D - Coord4(4) = Coord4(4) - InitInp%PtfmRefztRot(ThisBodyNum)*R2D + Coord4(3) = Coord4(3) - RotateZdegOffset + Coord4(4) = Coord4(4) - RotateZdegOffset ! get the interpolated value for F(omega1,omega2,beta1,beta2) CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, NewmanAppData%Data4D%WvFreq1, NewmanAppData%Data4D%WvFreq2, & @@ -1841,11 +1860,13 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg PhaseShiftXY = CMPLX( cos(TmpReal1), -sin(TmpReal1) ) - ! Apply the phase shift - DO ThisDim=1,6 - NewmanTerm1C(J,ThisDim) = NewmanTerm1C(J,ThisDim)*PhaseShiftXY ! Newman term 1 - NewmanTerm2C(J,ThisDim) = NewmanTerm2C(J,ThisDim)*PhaseShiftXY ! Newman term 2 - ENDDO + ! Apply the phase shift, but only to the NBodyMod=2 case + if (p%NBodyMod == 2) then + DO ThisDim=1,6 + NewmanTerm1C(J,ThisDim) = NewmanTerm1C(J,ThisDim)*PhaseShiftXY ! Newman term 1 + NewmanTerm2C(J,ThisDim) = NewmanTerm2C(J,ThisDim)*PhaseShiftXY ! Newman term 2 + ENDDO + endif ! Apply the rotation to get back to global frame -- Term 1 From 31df59ab6329c05cfc10dcdcc5de747742564a87 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 9 Jan 2020 15:03:41 -0700 Subject: [PATCH 120/377] FlexSub: cleaning up partitioning, starting list of interior nodes --- modules/subdyn/src/IntegerList.f90 | 92 +++++++- modules/subdyn/src/SD_FEM.f90 | 26 +-- modules/subdyn/src/SubDyn.f90 | 308 ++++++++++++------------- modules/subdyn/src/SubDyn_Registry.txt | 11 +- modules/subdyn/src/SubDyn_Types.f90 | 247 ++++++++++++-------- 5 files changed, 408 insertions(+), 276 deletions(-) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index b2dfcb7a1..e8530eedd 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -21,10 +21,54 @@ module IntegerList module procedure pop_last module procedure pop_item end interface + interface init_list + module procedure init_list_n_def + module procedure init_list_vect + end interface + interface find + module procedure find_list + module procedure find_raw + end interface contains + !> Concatenate lists: I3=[I1,I2] + subroutine concatenate_lists(I1,I2,I3, ErrStat, ErrMsg) + integer(intki), intent(in) :: i1(:), i2(:) + integer(intki), intent(out) :: i3(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + I3(1:size(I1)) = I1 + I3(size(I1)+1:size(I1)+size(I2)) = I2 + endsubroutine + + !> Set difference: I3=I1-I2 (assumes I1 is biggger than I2), elements of I1 not in I2 + subroutine lists_difference(I1, I2, I3, ErrStat, ErrMsg) + integer(IntKi), intent(in) :: I1(:), I2(:) + integer(IntKi), intent(out) :: I3(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: I + logical, dimension(:), allocatable :: bUnique + ErrStat = ErrID_None + ErrMsg = "" + allocate(bUnique(1:size(I1))) + ! Then, remove DOFs on the boundaries: + DO i = 1, size(I1) !Boundary DOFs (Interface + Constraints) + if (find(I2,I1(i))>0) then + bUnique(I) = .false. + else + bUnique(I) = .true. + endif + ENDDO + if (count(bUnique) /= size(I3)) then + ErrStat=ErrID_Fatal; ErrMsg='Storage for list difference is of wrong size'; return + endif + I3 = pack(I1, bUnique) + deallocate(bUnique) + endsubroutine + !> Initialize an integer list - subroutine init_list(L,n,default_val,ErrStat,ErrMsg) + subroutine init_list_n_def(L,n,default_val,ErrStat,ErrMsg) type(IList), intent(inout) :: L !< List integer(IntKi), intent(in) :: n !< number of initial values integer(IntKi), intent(in) :: default_val !< default values @@ -32,12 +76,22 @@ subroutine init_list(L,n,default_val,ErrStat,ErrMsg) character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ErrStat = ErrID_None ErrMsg = "" - call AllocAry(L%List, n, 'L%List', ErrStat, ErrMsg) if (ErrStat/=ErrID_None) return L%List(1:n) = default_val + end subroutine init_list_n_def - end subroutine init_list + subroutine init_list_vect(L,vect,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), dimension(:), intent(in) :: vect !< number of initial values + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + call AllocAry(L%List, size(vect), 'L%List', ErrStat, ErrMsg) + if (ErrStat/=ErrID_None) return + L%List = vect + end subroutine init_list_vect !> Deallocate list subroutine destroy_list(L,ErrStat,ErrMsg) @@ -160,7 +214,7 @@ end subroutine reverse !> Returns index of element e in L, returns 0 if not found !! NOTE: list but be sorted to call this function - integer(IntKi) function find(L, e, ErrStat, ErrMsg) + integer(IntKi) function find_list(L, e, ErrStat, ErrMsg) type(IList), intent(inout) :: L integer(IntKi), intent(in ) :: e integer(IntKi), intent( out) :: ErrStat !< Error status of the operation @@ -168,16 +222,34 @@ integer(IntKi) function find(L, e, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" if (len(L)>0) then - find = binary_search(L%List, e) ! Binary search returns index for inequality List(i)<=e - if (find>0) then - if (L%List(find)/=e) then - find=-1 + find_list = binary_search(L%List, e) ! Binary search returns index for inequality List(i)<=e + if (find_list>0) then + if (L%List(find_list)/=e) then + find_list=-1 endif endif else - find=-1 + find_list=-1 endif - end function find + end function find_list + + !> Returns index of val in Array (val is an integer!) + ! NOTE: in the future use intrinsinc function findloc + function find_raw(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 + end function !> Print subroutine print_list(L, varname, u_opt) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d174396a3..a9ae30003 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -268,10 +268,10 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) enddo ! --- Re-Initialize interface joints, pointing to index instead of JointID - do I = 1, Init%NInterf - JointID=Init%Interf(I,1) - Init%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (Init%Interf(I,1)<=0) then + do I = 1, p%NInterf + JointID=p%Interf(I,1) + p%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (p%Interf(I,1)<=0) then CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') return endif @@ -381,8 +381,8 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. ! check the number of interior modes - IF ( p%Nmodes > 6*(Init%NNode - Init%NInterf - p%NReact) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - Init%NInterf - p%NReact) ))) + IF ( p%Nmodes > 6*(Init%NNode - p%NInterf - p%NReact) ) THEN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - p%NInterf - p%NReact) ))) RETURN ENDIF @@ -808,7 +808,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) CALL InitBCs(Init, p) ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%IntFc, 6*Init%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%IntFc, 6*p%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return CALL InitIntFc(Init, p) ! --- Safety check @@ -863,11 +863,11 @@ SUBROUTINE InitIntFc(Init, p) TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode Init%IntFc = -9999 - DO I = 1, Init%NInterf - iNode = Init%Interf(I,1) ! Node index + DO I = 1, p%NInterf + iNode = p%Interf(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%IntFc( (I-1)*6+J, 2) = Init%Interf(I, J+1); ! 0 or 1 if fixed to interface + Init%IntFc( (I-1)*6+J, 2) = p%Interf(I, J+1); ! 0 or 1 if fixed to interface ENDDO ENDDO END SUBROUTINE InitIntFc @@ -1238,8 +1238,8 @@ SUBROUTINE ReInitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - DO I = 1, Init%NInterf - iNode = Init%Interf(I,1) ! Node index + DO I = 1, p%NInterf + iNode = p%Interf(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) ENDDO @@ -1288,7 +1288,7 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) call init_list(INodesInterf, 0, 0, ErrStat2, ErrMsg2); do iNodeID = 1, size(INodesID) NodeID = INodesID(iNodeID) - iFound = FINDLOCI( Init%Interf(:,1), NodeID) + iFound = FINDLOCI( p%Interf(:,1), NodeID) if (iFound>0) then call append(INodesInterf, iNodeID, ErrStat2, ErrMsg2) ! This node is an interface node diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index de6f263fd..a0de4d4e5 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -111,7 +111,8 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I ! generic counter variable + REAL(ReKi), dimension(3) :: Point + INTEGER :: I, iOffset ! generic counter variable INTEGER :: nodeIndx CALL MeshCreate( BlankMesh = inputMesh & @@ -121,67 +122,41 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, ,ErrMess = ErrMsg & ,Force = .TRUE. & ,Moment = .TRUE. ) - !--------------------------------------------------------------------- - ! Interface nodes - !--------------------------------------------------------------------- + ! --- Interface nodes + print*,'NNodes_I',NNodes_I + iOffset = 0 DO I = 1,NNodes_I - ! Create the node on the mesh + ! Create the node and mesh element nodeIndx = IDI(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID - CALL MeshPositionNode ( inputMesh & - , I & - , Nodes(nodeIndx,2:4) & ! position - , ErrStat & - , ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - ! Create the mesh element - CALL MeshConstructElement ( inputMesh & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , I ) + print*,'I',I,'IDI',IDI(I*6), 'nodeIndx',nodeIndx + !iDOF = IDI(I) ! DOF index in constrained system + !iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node + !nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + !iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + Point = Nodes(nodeIndx, 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) END DO - !--------------------------------------------------------------------- - ! Interior nodes - !--------------------------------------------------------------------- + ! --- Interior nodes + iOffset = NNodes_I DO I = 1,NNodes_L - ! Create the node on the mesh + ! Create the node and mesh element nodeIndx = IDL(I*6) / 6 !TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes - CALL MeshPositionNode ( inputMesh & - , I + NNodes_I & - , Nodes(nodeIndx,2:4) & - , ErrStat & - , ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - ! Create the mesh element - CALL MeshConstructElement ( inputMesh & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , I + NNodes_I ) + Point = Nodes(nodeIndx, 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) END DO - !--------------------------------------------------------------------- - ! Base Reaction nodes - !--------------------------------------------------------------------- + ! --- Base Reaction nodes + iOffset = NNodes_I + NNodes_L DO I = 1,NNodes_C - ! Create the node on the mesh + ! Create the node and mesh element nodeIndx = IDC(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID - CALL MeshPositionNode ( inputMesh & - , I + NNodes_I + NNodes_L & - , Nodes(nodeIndx,2:4) & - , ErrStat & - , ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - ! Create the mesh element - CALL MeshConstructElement ( inputMesh & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , I + NNodes_I + NNodes_L ) + print*,'I',I,'IDC',IDC(I*6), 'nodeIndx',nodeIndx + Point = Nodes(nodeIndx, 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) END DO CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN @@ -323,10 +298,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Assemble Stiffness and mass matrix CALL AssembleKM(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Calculate values for FEMparams (for summary file output only - ! Solve dynamics problem + ! --- Eigen values of full system (for summary file output only) + ! True below is to remove the constraints ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - ! The results, Phi is not used in the remainder of this Init subroutine, Omega goes to outsummary. FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -382,7 +356,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction - CALL CreateY2Meshes( Init%NNode, Init%Nodes, Init%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Initialize the outputs & Store mapping between nodes and elements CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return @@ -936,16 +910,16 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- ! Joints with reaction forces, joint number and locked/free dof -CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%Interf, Init%NInterf, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return -DO I = 1, Init%NInterf +CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(p%Interf, p%NInterf, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, p%NInterf CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - Init%Interf(I,:) = Dummy_IntAry(1:InterfCol) + p%Interf(I,:) = Dummy_IntAry(1:InterfCol) ENDDO -IF (Check( ( Init%NInterf < 0 ) .OR. (Init%NInterf > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN +IF (Check( ( p%NInterf < 0 ) .OR. (p%NInterf > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN !----------------------------------- MEMBERS -------------------------------------- ! One day we will need to take care of COSMIDs for non-circular members @@ -1566,15 +1540,13 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - ! number of nodes: - p%NNodes_I = Init%NInterf ! Number of interface nodes - p%NNodes_L = Init%NNode - p%NReact - p%NNodes_I ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I - ! --- Counting DOFs: - ! DOFR (retained) = DOFI (interface), DOFC (reaction), - ! DOFL (internal) - ! DOFM (CB modes) - call CountDOFs(); if(Failed()) return + ! --- Partitioon DOFs and Nodes into sets: I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior + !! Partition Nodes into: Nodes_I (Interf), Nodes_C (React), Nodes_L + !! Partitions the DOF index arrays into IDR=[IDC, ICI] and IDL (interior) + !! Sets the DOF mapping [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] + call PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return + IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes IF(p%Nmodes > p%DOFL) THEN @@ -1616,8 +1588,6 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return - ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. - CALL SetIndexArrays(Init, p, ErrStat2, ErrMsg2) ; if(Failed()) return ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on ! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: @@ -1670,38 +1640,6 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL CleanUpCB() contains - SUBROUTINE CountDOFs() - use IntegerList, only: len - INTEGER(IntKi) :: iNode, iiNode - ErrStat2 = ErrID_None - ErrMsg2 = "" - ! Interface DOFS - p%DOFI =0 - do iiNode= 1,Init%NInterf - iNode = Init%Interf(iiNode,1) - p%DOFI = p%DOFI + len(m%NodesDOFtilde(iNode)) - enddo - if (p%DOFI /= p%NNodes_I*6) then - ErrMsg2='Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'; ErrStat2=ErrID_Fatal - return - endif - ! Reaction DOFs - do iiNode= 1,p%NReact - iNode = p%Reacts(iiNode,1) - p%DOFC = p%DOFC + len(m%NodesDOFtilde(iNode)) - enddo - if (p%DOFC /= p%NReact*6) then - ErrMsg2='Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'; ErrStat2=ErrID_Fatal - return - endif - p%DOFR = p%DOFC + p%DOFI - p%DOFL = Init%nDOFRed - p%DOFR ! TODO - print*,'Number of DOFs: "interface" (I)',p%DOFI - print*,'Number of DOFs: "reactions" (C)',p%DOFC - print*,'Number of DOFs: interface (R)',p%DOFR - print*,'Number of DOFs: internal (L)',p%DOFL - print*,'Number of DOFs: total (R+L)',Init%nDOFRed - END SUBROUTINE SUBROUTINE Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in @@ -2365,12 +2303,6 @@ SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) CALL AllocAry( p%D2_64, p%DOFL, p%DOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 CALL AllocAry( p%F2_61, p%DOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 end if - - CALL AllocAry( p%IDI, p%DOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%IDR, p%DOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%IDL, p%DOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%IDC, p%DOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%IDY, p%DOFC+p%DOFI+p%DOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') if ( p%SttcSolve ) THEN CALL AllocAry( p%PhiL_T, p%DOFL, p%DOFL, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2406,55 +2338,89 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) END SUBROUTINE AllocMiscVars !------------------------------------------------------------------------------------------------------ -!> Set the index arrays IDI, IDR, IDL, IDC, and IDY. -SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) - USE qsort_c_module, only: QsortC - - TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +!> Partition DOFs and Nodes into sets: I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior +!! Partition Nodes into: Nodes_I (Interf), Nodes_C (React), Nodes_L +!! Partition the DOF index arrays into IDR=[IDC, ICI] and IDL (interior) +!! Sets the DOF mapping [_,IDY] =sort([IDI, IDL, IDC]), Y is in the continuous order [I,L,C] +SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) + use qsort_c_module, only: QsortC + use IntegerList, only: len, concatenate_lists, lists_difference + type(SD_Inittype), intent( in) :: Init !< Input data for initialization routine + type(SD_MiscVartype), intent( in) :: m !< Misc + type(SD_Parametertype), intent(inout) :: p !< Parameters + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables - INTEGER(IntKi), allocatable :: TempIDY(:,:) - INTEGER(IntKi), allocatable :: IDT(:) - INTEGER(IntKi) :: I, K ! counters + integer(IntKi), allocatable :: TempIDY(:,:) + integer(IntKi), allocatable :: IDT(:) + integer(IntKi) :: I ! counters + integer(IntKi) :: iNode, iiNode + integer(IntKi) :: NNodes_R + integer(IntKi), allocatable :: INodesAll(:) + integer(IntKi), allocatable :: Nodes_R(:) + integer(IntKi) :: ErrStat2 ! < Error status of the operation + character(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" - + ! --- Count nodes per types + p%NNodes_I = p%NInterf ! Number of interface nodes + NNodes_R = p%NReact+p%NInterf ! Number of retained nodes + p%NNodes_L = Init%NNode - NNodes_R ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I + + CALL AllocAry( p%Nodes_L, p%NNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( Nodes_R , NNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + + ! --- Partition Nodes + ! Nodes_L = IAll - NodesR + allocate(INodesAll(1:Init%NNode)); + do iNode=1,Init%NNode + INodesAll(iNode)=iNode + enddo + call concatenate_lists(p%Reacts(:,1), p%Interf(:,1), Nodes_R, ErrStat2, ErrMsg2); if(Failed()) return + call lists_difference(INodesAll, Nodes_R, p%Nodes_L(:,1), ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Count DOFs + ! Interface DOFS + p%DOFI =0 + do iiNode= 1,p%NInterf + iNode = p%Interf(iiNode,1) + p%DOFI = p%DOFI + len(m%NodesDOFtilde(iNode)) + enddo + ! Reaction DOFs + do iiNode= 1,p%NReact + iNode = p%Reacts(iiNode,1) + p%DOFC = p%DOFC + len(m%NodesDOFtilde(iNode)) + enddo + p%DOFR = p%DOFC + p%DOFI + p%DOFL = Init%nDOFRed - p%DOFR ! TODO + ! --- Safety checks + if (p%DOFC /= p%NReact*6) then + call Fatal('Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'); return + endif + if (p%DOFI /= p%NNodes_I*6) then + call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'); return + endif + + ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. + CALL AllocAry( p%IDI, p%DOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDC, p%DOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDR, p%DOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDL, p%DOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDY, p%DOFC+p%DOFI+p%DOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + if(Failed()) return + ! Indices IDI for interface DOFs p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs (indices updated after DirectElimination) - ! Indices IDC for constraint DOFs p%IDC = Init%BCs(1:p%DOFC, 1) ! Reaction DOFs (indices updated after DirectElimination) - ! Indices IDR = [IDC, IDI], "retained interface DOFS" - p%IDR( 1:p%DOFC ) = p%IDC ! Constraint DOFs again - p%IDR(p%DOFC+1:p%DOFR) = p%IDI ! IDR contains DOFs ofboundaries, constraints first then interface + call concatenate_lists(p%IDC, p%IDI, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return ! --- Indices IDL for internal DOFs = AllDOF - IDR ! First set the all DOFs indices IDT = 1:nDOFRed allocate(IDT(1:Init%nDOFRed)) - DO I = 1, Init%nDOFRed !Total DOFs - IDT(I) = I - ENDDO - ! Then, remove DOFs on the boundaries: - DO I = 1, p%DOFR !Boundary DOFs (Interface + Constraints) - IDT(p%IDR(I)) = 0 !Set 0 wherever DOFs belong to boundaries - ENDDO - ! That leaves the internal DOFs: - K = 0 - DO I = 1, Init%nDOFRed - IF ( IDT(I) .NE. 0 ) THEN - K = K+1 - p%IDL(K) = IDT(I) !Internal DOFs - ENDIF - ENDDO - deallocate(IDT) - IF ( K /= p%DOFL ) THEN - ErrStat = ErrID_Fatal - ErrMsg = "SetIndexArrays: IDL or p%DOFL are the incorrect size." - RETURN - END IF + DO I = 1, Init%nDOFRed; IDT(I) = I; ENDDO + call lists_difference(IDT, p%IDR, p%IDL, ErrStat2, ErrMsg2); if(Failed()) return ! --- Index [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] ! set the second column of the temp array @@ -2467,13 +2433,41 @@ SUBROUTINE SetIndexArrays(Init, p, ErrStat, ErrMsg) TempIDY(1:p%DOFI, 1) = p%IDI TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL TempIDY(p%DOFI+p%DOFL+1: p%DOFI+p%DOFL+p%DOFC, 1) = p%IDC - ! sort based on the first column - CALL QsortC( TempIDY ) - ! the second column is the key: - p%IDY = TempIDY(:, 2) - deallocate(TempIDY) + CALL QsortC( TempIDY ) ! sort based on the first column + p%IDY = TempIDY(:, 2) ! the second column is the key: + ! + call CleanUp() + + print*,'Nodes_I',p%Interf(:,1) + print*,'Nodes_C',p%Reacts(:,1) + print*,'Nodes_L',p%Nodes_L + print*,'Number of DOFs: "interface" (I)',p%DOFI + print*,'Number of DOFs: "reactions" (C)',p%DOFC + print*,'Number of DOFs: interface (R)',p%DOFR + print*,'Number of DOFs: internal (L)',p%DOFL + print*,'Number of DOFs: total (R+L)',Init%nDOFRed + print*,'Number of Nodes: "interface" (I)',p%NNodes_I + print*,'Number of Nodes: "reactions" (C)',p%NReact + print*,'Number of Nodes: internal (L)',p%NNodes_L + print*,'Number of Nodes: total (R+L)',Init%NNode +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L'); + CALL CleanUp() + END SUBROUTINE Fatal + SUBROUTINE CleanUp() + if(allocated(TempIDY)) deallocate(TempIDY) + if(allocated(IDT)) deallocate(IDT) + if(allocated(INodesAll)) deallocate(INodesAll) + END SUBROUTINE CleanUp -END SUBROUTINE SetIndexArrays +END SUBROUTINE PartitionDOFNodes_I_C_R_L !------------------------------------------------------------------------------------------------------ !> Take the input u LMesh and constructs the appropriate corresponding UFL vector @@ -2566,12 +2560,12 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%NReact*6 WRITE(UnSum, '(A, A6)') 'Reaction DOF_ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%NReact*6) + WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%NReact*6)! TODO TODO TODO might have been updated WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%DOFI WRITE(UnSum, '(A,A6)') 'Interface DOF ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%DOFI) + WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%DOFI) ! TODO TODO TODO might have been updated WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of concentrated masses (NCMass):',Init%NCMass diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index dbb8adb8e..6cac3cb3b 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -78,7 +78,6 @@ typedef ^ ^ INTEGER NPropSetsX - - - "Number of extended property sets" typedef ^ ^ INTEGER NPropSetsB - - - "Number of property sets for beams" typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" -typedef ^ ^ INTEGER NInterf - - - "Number of joints attached to transition piece" typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" @@ -93,7 +92,6 @@ typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" -typedef ^ ^ INTEGER Interf {:}{:} - - "Interface degree of freedoms" typedef ^ ^ CHARACTER(10) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" @@ -195,12 +193,15 @@ typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B met typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType IntKi qmL - - - "Length of state array" typedef ^ ParameterType IntKi DofL - - - "Internal nodes # of DOFs" -typedef ^ ParameterType IntKi NNodes_I - - - "Number of Interface nodes" -typedef ^ ParameterType IntKi NNodes_L - - - "Number of Internal nodes" -typedef ^ ParameterType IntKi NNodes_RbarL - - - "Number of Interface + Internal nodes" typedef ^ ParameterType IntKi DofI - - - "Interface nodes # of DOFs" typedef ^ ParameterType IntKi DofR - - - "Interface and restrained nodes # of DOFs" typedef ^ ParameterType IntKi DofC - - - "Contrained nodes # of DOFs" +typedef ^ ParameterType IntKi NNodes_RbarL - - - "Number of Interface + Internal nodes" +typedef ^ ParameterType IntKi NNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" +typedef ^ ParameterType IntKi NNodes_I - - - "Number of Interface nodes" +typedef ^ ParameterType IntKi NInterf - - - "Number of joints attached to transition piece" +typedef ^ ParameterType IntKi Interf {:}{:} - - "Interface degree of freedoms" typedef ^ ParameterType IntKi NReact - - - "Number of joints with reactions" typedef ^ ParameterType IntKi Reacts {:}{:} - - "React degree of freedoms" typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4cac560aa..12c9e7fd7 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -116,7 +116,6 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NPropSetsB !< Number of property sets for beams [-] INTEGER(IntKi) :: NPropSetsC !< Number of property sets for cables [-] INTEGER(IntKi) :: NPropSetsR !< Number of property sets for rigid links [-] - INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] INTEGER(IntKi) :: FEMMod !< FEM switch: element model in the FEM [-] @@ -131,7 +130,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Interf !< Interface degree of freedoms [-] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] @@ -239,12 +237,15 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] INTEGER(IntKi) :: qmL !< Length of state array [-] INTEGER(IntKi) :: DofL !< Internal nodes of DOFs [-] - INTEGER(IntKi) :: NNodes_I !< Number of Interface nodes [-] - INTEGER(IntKi) :: NNodes_L !< Number of Internal nodes [-] - INTEGER(IntKi) :: NNodes_RbarL !< Number of Interface + Internal nodes [-] INTEGER(IntKi) :: DofI !< Interface nodes of DOFs [-] INTEGER(IntKi) :: DofR !< Interface and restrained nodes of DOFs [-] INTEGER(IntKi) :: DofC !< Contrained nodes of DOFs [-] + INTEGER(IntKi) :: NNodes_RbarL !< Number of Interface + Internal nodes [-] + INTEGER(IntKi) :: NNodes_L !< Number of Internal nodes [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] + INTEGER(IntKi) :: NNodes_I !< Number of Interface nodes [-] + INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Interf !< Interface degree of freedoms [-] INTEGER(IntKi) :: NReact !< Number of joints with reactions [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Reacts !< React degree of freedoms [-] INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] @@ -2694,7 +2695,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%NPropSetsB = SrcInitTypeData%NPropSetsB DstInitTypeData%NPropSetsC = SrcInitTypeData%NPropSetsC DstInitTypeData%NPropSetsR = SrcInitTypeData%NPropSetsR - DstInitTypeData%NInterf = SrcInitTypeData%NInterf DstInitTypeData%NCMass = SrcInitTypeData%NCMass DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs DstInitTypeData%FEMMod = SrcInitTypeData%FEMMod @@ -2824,20 +2824,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%Members = SrcInitTypeData%Members ENDIF -IF (ALLOCATED(SrcInitTypeData%Interf)) THEN - i1_l = LBOUND(SrcInitTypeData%Interf,1) - i1_u = UBOUND(SrcInitTypeData%Interf,1) - i2_l = LBOUND(SrcInitTypeData%Interf,2) - i2_u = UBOUND(SrcInitTypeData%Interf,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Interf)) THEN - ALLOCATE(DstInitTypeData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Interf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Interf = SrcInitTypeData%Interf -ENDIF IF (ALLOCATED(SrcInitTypeData%SSOutList)) THEN i1_l = LBOUND(SrcInitTypeData%SSOutList,1) i1_u = UBOUND(SrcInitTypeData%SSOutList,1) @@ -3104,9 +3090,6 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%Members)) THEN DEALLOCATE(InitTypeData%Members) ENDIF -IF (ALLOCATED(InitTypeData%Interf)) THEN - DEALLOCATE(InitTypeData%Interf) -ENDIF IF (ALLOCATED(InitTypeData%SSOutList)) THEN DEALLOCATE(InitTypeData%SSOutList) ENDIF @@ -3202,7 +3185,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! NPropSetsB Int_BufSz = Int_BufSz + 1 ! NPropSetsC Int_BufSz = Int_BufSz + 1 ! NPropSetsR - Int_BufSz = Int_BufSz + 1 ! NInterf Int_BufSz = Int_BufSz + 1 ! NCMass Int_BufSz = Int_BufSz + 1 ! NCOSMs Int_BufSz = Int_BufSz + 1 ! FEMMod @@ -3253,11 +3235,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! Members upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%Members) ! Members END IF - Int_BufSz = Int_BufSz + 1 ! Interf allocated yes/no - IF ( ALLOCATED(InData%Interf) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Interf upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Interf) ! Interf - END IF Int_BufSz = Int_BufSz + 1 ! SSOutList allocated yes/no IF ( ALLOCATED(InData%SSOutList) ) THEN Int_BufSz = Int_BufSz + 2*1 ! SSOutList upper/lower bounds for each dimension @@ -3397,8 +3374,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsR Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCMass Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCOSMs @@ -3550,22 +3525,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%Members)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Members))-1 ) = PACK(InData%Members,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%Members) END IF - IF ( .NOT. ALLOCATED(InData%Interf) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Interf)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Interf))-1 ) = PACK(InData%Interf,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Interf) - END IF IF ( .NOT. ALLOCATED(InData%SSOutList) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3904,8 +3863,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%NPropSetsR = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NInterf = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 OutData%NCMass = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NCOSMs = IntKiBuf( Int_Xferred ) @@ -4147,32 +4104,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + SIZE(OutData%Members) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Interf not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Interf)) DEALLOCATE(OutData%Interf) - ALLOCATE(OutData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Interf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Interf)>0) OutData%Interf = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Interf))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Interf) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSOutList not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6935,12 +6866,41 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstParamData%qmL = SrcParamData%qmL DstParamData%DofL = SrcParamData%DofL - DstParamData%NNodes_I = SrcParamData%NNodes_I - DstParamData%NNodes_L = SrcParamData%NNodes_L - DstParamData%NNodes_RbarL = SrcParamData%NNodes_RbarL DstParamData%DofI = SrcParamData%DofI DstParamData%DofR = SrcParamData%DofR DstParamData%DofC = SrcParamData%DofC + DstParamData%NNodes_RbarL = SrcParamData%NNodes_RbarL + DstParamData%NNodes_L = SrcParamData%NNodes_L +IF (ALLOCATED(SrcParamData%Nodes_L)) THEN + i1_l = LBOUND(SrcParamData%Nodes_L,1) + i1_u = UBOUND(SrcParamData%Nodes_L,1) + i2_l = LBOUND(SrcParamData%Nodes_L,2) + i2_u = UBOUND(SrcParamData%Nodes_L,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_L)) THEN + ALLOCATE(DstParamData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Nodes_L = SrcParamData%Nodes_L +ENDIF + DstParamData%NNodes_I = SrcParamData%NNodes_I + DstParamData%NInterf = SrcParamData%NInterf +IF (ALLOCATED(SrcParamData%Interf)) THEN + i1_l = LBOUND(SrcParamData%Interf,1) + i1_u = UBOUND(SrcParamData%Interf,1) + i2_l = LBOUND(SrcParamData%Interf,2) + i2_u = UBOUND(SrcParamData%Interf,2) + IF (.NOT. ALLOCATED(DstParamData%Interf)) THEN + ALLOCATE(DstParamData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Interf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Interf = SrcParamData%Interf +ENDIF DstParamData%NReact = SrcParamData%NReact IF (ALLOCATED(SrcParamData%Reacts)) THEN i1_l = LBOUND(SrcParamData%Reacts,1) @@ -7204,6 +7164,12 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%Elems)) THEN DEALLOCATE(ParamData%Elems) ENDIF +IF (ALLOCATED(ParamData%Nodes_L)) THEN + DEALLOCATE(ParamData%Nodes_L) +ENDIF +IF (ALLOCATED(ParamData%Interf)) THEN + DEALLOCATE(ParamData%Interf) +ENDIF IF (ALLOCATED(ParamData%Reacts)) THEN DEALLOCATE(ParamData%Reacts) ENDIF @@ -7429,12 +7395,23 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF Int_BufSz = Int_BufSz + 1 ! qmL Int_BufSz = Int_BufSz + 1 ! DofL - Int_BufSz = Int_BufSz + 1 ! NNodes_I - Int_BufSz = Int_BufSz + 1 ! NNodes_L - Int_BufSz = Int_BufSz + 1 ! NNodes_RbarL Int_BufSz = Int_BufSz + 1 ! DofI Int_BufSz = Int_BufSz + 1 ! DofR Int_BufSz = Int_BufSz + 1 ! DofC + Int_BufSz = Int_BufSz + 1 ! NNodes_RbarL + Int_BufSz = Int_BufSz + 1 ! NNodes_L + Int_BufSz = Int_BufSz + 1 ! Nodes_L allocated yes/no + IF ( ALLOCATED(InData%Nodes_L) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_L) ! Nodes_L + END IF + Int_BufSz = Int_BufSz + 1 ! NNodes_I + Int_BufSz = Int_BufSz + 1 ! NInterf + Int_BufSz = Int_BufSz + 1 ! Interf allocated yes/no + IF ( ALLOCATED(InData%Interf) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Interf upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Interf) ! Interf + END IF Int_BufSz = Int_BufSz + 1 ! NReact Int_BufSz = Int_BufSz + 1 ! Reacts allocated yes/no IF ( ALLOCATED(InData%Reacts) ) THEN @@ -8046,18 +8023,52 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofL Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_I + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofI Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_L + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofR + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofC Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_RbarL Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofI + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_L Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofR + IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_I Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofC + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Interf) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Interf)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Interf))-1 ) = PACK(InData%Interf,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Interf) + END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NReact Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Reacts) ) THEN @@ -9111,18 +9122,72 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%DofL = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NNodes_I = IntKiBuf( Int_Xferred ) + OutData%DofI = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NNodes_L = IntKiBuf( Int_Xferred ) + OutData%DofR = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%DofC = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NNodes_RbarL = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%DofI = IntKiBuf( Int_Xferred ) + OutData%NNodes_L = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%DofR = IntKiBuf( Int_Xferred ) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes_L)) DEALLOCATE(OutData%Nodes_L) + ALLOCATE(OutData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Nodes_L)>0) OutData%Nodes_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_L))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) + DEALLOCATE(mask2) + END IF + OutData%NNodes_I = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%DofC = IntKiBuf( Int_Xferred ) + OutData%NInterf = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Interf not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Interf)) DEALLOCATE(OutData%Interf) + ALLOCATE(OutData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Interf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Interf)>0) OutData%Interf = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Interf))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Interf) + DEALLOCATE(mask2) + END IF OutData%NReact = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Reacts not allocated From f02f25387385f6734f52cad87ac0b2f3955c2e5e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 9 Jan 2020 15:59:25 -0700 Subject: [PATCH 121/377] FlexSub: y2mesh creation using Nodes indices and not DOF indices --- modules/subdyn/src/SubDyn.f90 | 130 +++++++++---------------- modules/subdyn/src/SubDyn_Registry.txt | 6 +- modules/subdyn/src/SubDyn_Types.f90 | 30 +++--- 3 files changed, 66 insertions(+), 100 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a0de4d4e5..3b4c6d4e2 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -68,23 +68,10 @@ SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) ,RotationVel = .TRUE. & ,TranslationAcc = .TRUE. & ,RotationAcc = .TRUE. ) - - ! Create the node on the mesh - CALL MeshPositionNode ( inputMesh & - , 1 & - , TP_RefPoint & - , ErrStat & - , ErrMsg ) !note: assumes identiy matrix as reference orientation - IF ( ErrStat >= AbortErrLev ) RETURN - - ! Create the mesh element - CALL MeshConstructElement ( inputMesh & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , 1 ) - CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN + ! Create the node and mesh element, note: assumes identiy matrix as reference orientation + CALL MeshPositionNode (inputMesh, 1, TP_RefPoint, ErrStat, ErrMsg); IF(ErrStat>=AbortErrLev) return + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1) + CALL MeshCommit( inputMesh, ErrStat, ErrMsg); if(ErrStat >= AbortErrLev) return ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh CALL MeshCopy ( SrcMesh = inputMesh & @@ -97,69 +84,50 @@ SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) ,Moment = .TRUE. ) END SUBROUTINE CreateTPMeshes -SUBROUTINE CreateY2Meshes( NNode, Nodes, NNodes_I, IDI, NNodes_L, IDL, NNodes_C, IDC, inputMesh, outputMesh, ErrStat, ErrMsg ) +SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh, outputMesh, ErrStat, ErrMsg ) INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) - INTEGER(IntKi), INTENT( IN ) :: NNodes_I ! number interface nodes i.e. Y2 stuff at the beginning - INTEGER(IntKi), INTENT( IN ) :: IDI(NNodes_I*6) - INTEGER(IntKi), INTENT( IN ) :: NNodes_L ! number interior nodes (no constraints) i.e. Y2 stuff after interface stuff - INTEGER(IntKi), INTENT( IN ) :: IDL(NNodes_L*6) - INTEGER(IntKi), INTENT( IN ) :: NNodes_C ! number base reaction nodes i.e. Y2 stuff after interior stuff - INTEGER(IntKi), INTENT( IN ) :: IDC(NNodes_C*6) + INTEGER(IntKi), INTENT( IN ) :: INodes_I(:) !< Indices of interface nodes + INTEGER(IntKi), INTENT( IN ) :: INodes_L(:) !< Indices of interior nodes + INTEGER(IntKi), INTENT( IN ) :: INodes_C(:) !< Indices of reaction nodes TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%LMesh TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y2Mesh INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables REAL(ReKi), dimension(3) :: Point - INTEGER :: I, iOffset ! generic counter variable + INTEGER :: I, iOffset, iNode ! generic counter variable INTEGER :: nodeIndx CALL MeshCreate( BlankMesh = inputMesh & ,IOS = COMPONENT_INPUT & - ,Nnodes = NNodes_I + NNodes_L + NNodes_C & + ,Nnodes = size(INodes_I) + size(INodes_L) + size(INodes_C) & ,ErrStat = ErrStat & ,ErrMess = ErrMsg & ,Force = .TRUE. & ,Moment = .TRUE. ) ! --- Interface nodes - print*,'NNodes_I',NNodes_I iOffset = 0 - DO I = 1,NNodes_I - ! Create the node and mesh element - nodeIndx = IDI(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID - print*,'I',I,'IDI',IDI(I*6), 'nodeIndx',nodeIndx - !iDOF = IDI(I) ! DOF index in constrained system - !iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node - !nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - !iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) - Point = Nodes(nodeIndx, 2:4) + DO I = 1,size(INodes_I) + Point = Nodes(INodes_I(I), 2:4) CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - END DO - + ENDDO ! --- Interior nodes - iOffset = NNodes_I - DO I = 1,NNodes_L - ! Create the node and mesh element - nodeIndx = IDL(I*6) / 6 !TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID of the input file that may not be sequential, but the renumbered list of nodes - Point = Nodes(nodeIndx, 2:4) + iOffset = size(INodes_I) + DO I = 1,size(INodes_L) + Point = Nodes(INodes_L(I), 2:4) CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) END DO - - ! --- Base Reaction nodes - iOffset = NNodes_I + NNodes_L - DO I = 1,NNodes_C - ! Create the node and mesh element - nodeIndx = IDC(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index, is it true? Yes it is not the nodeID - print*,'I',I,'IDC',IDC(I*6), 'nodeIndx',nodeIndx - Point = Nodes(nodeIndx, 2:4) + ! --- Base Reaction nodes + iOffset = size(INodes_I) + size(INodes_L) + DO I = 1,size(INodes_C) + Point = Nodes(INodes_C(I), 2:4) CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) END DO - CALL MeshCommit ( inputMesh, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN ! Create the Interior Points output mesh as a sibling copy of the input mesh CALL MeshCopy ( SrcMesh = inputMesh & @@ -356,7 +324,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction - CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%NInterf, p%IDI, p%NNodes_L, p%IDL, p%NReact, p%IDC, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%Interf(:,1), p%Nodes_L(:,1), p%Reacts(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Initialize the outputs & Store mapping between nodes and elements CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return @@ -448,8 +416,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: ULS(p%DOFL), UL0m(p%DOFL), FLt(p%DOFL) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) INTEGER(IntKi) :: startDOF - REAL(ReKi) :: DCM(3,3),junk(6,p%NNodes_L) - REAL(ReKi) :: HydroForces(6*p%NNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) + REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) + REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None @@ -503,7 +471,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --------------------------------------------------------------------------------- ! Place the outputs onto interface node portion of Y2 output mesh ! --------------------------------------------------------------------------------- - DO I = 1, p%NNodes_I + DO I = 1, p%nNodes_I startDOF = (I-1)*6 + 1 ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%UR_bar(startDOF + 3), m%UR_bar(startDOF + 4), m%UR_bar(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) @@ -521,12 +489,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --------------------------------------------------------------------------------- ! Place the outputs onto interior node portion of Y2 output mesh ! --------------------------------------------------------------------------------- - DO I = 1, p%NNodes_L !Only interior nodes here + DO I = 1, p%nNodes_L !Only interior nodes here ! starting index in the master arrays for the current node startDOF = (I-1)*6 + 1 ! index into the Y2Mesh - J = p%NNodes_I + I + J = p%nNodes_I + I ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UL input angles', m%UL(startDOF + 3), m%UL(startDOF + 4), m%UL(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) @@ -541,17 +509,17 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END DO !Repeat for the acceleration, there should be a way to combine into 1 loop - L1 = p%NNodes_I+1 - L2 = p%NNodes_I+p%NNodes_L - junk= RESHAPE(m%UL_dotdot,(/6 ,p%NNodes_L/)) + L1 = p%nNodes_I+1 + L2 = p%nNodes_I+p%nNodes_L + junk= RESHAPE(m%UL_dotdot,(/6 ,p%nNodes_L/)) y%Y2mesh%TranslationAcc ( :,L1:L2) = junk(1:3,:) y%Y2mesh%RotationAcc ( :,L1:L2) = junk(4:6,:) ! --------------------------------------------------------------------------------- ! Base reaction nodes ! --------------------------------------------------------------------------------- - L1 = p%NNodes_I+p%NNodes_L+1 - L2 = p%NNodes_I+p%NNodes_L+p%NReact + L1 = p%nNodes_I+p%nNodes_L+1 + L2 = p%nNodes_I+p%nNodes_L+p%NReact y%Y2mesh%TranslationDisp( :,L1:L2) = 0.0 CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return @@ -571,7 +539,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES !Aggregate the forces and moments at the interface nodes to the reference point !TODO: where are these HydroTP, HydroForces documented? - DO I = 1, p%NNodes_I + DO I = 1, p%nNodes_I startDOF = (I-1)*6 + 1 !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5 ) = (/u%LMesh%Force(:,I),u%LMesh%Moment(:,I)/) !(6,NNODES_I) @@ -2355,7 +2323,7 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) integer(IntKi), allocatable :: IDT(:) integer(IntKi) :: I ! counters integer(IntKi) :: iNode, iiNode - integer(IntKi) :: NNodes_R + integer(IntKi) :: nNodes_R integer(IntKi), allocatable :: INodesAll(:) integer(IntKi), allocatable :: Nodes_R(:) integer(IntKi) :: ErrStat2 ! < Error status of the operation @@ -2363,12 +2331,12 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" ! --- Count nodes per types - p%NNodes_I = p%NInterf ! Number of interface nodes - NNodes_R = p%NReact+p%NInterf ! Number of retained nodes - p%NNodes_L = Init%NNode - NNodes_R ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%NNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%NNodes_I + p%nNodes_I = p%NInterf ! Number of interface nodes + nNodes_R = p%NReact+p%NInterf ! Number of retained nodes + p%nNodes_L = Init%NNode - nNodes_R ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%nNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%nNodes_I - CALL AllocAry( p%Nodes_L, p%NNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( Nodes_R , NNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') ! --- Partition Nodes ! Nodes_L = IAll - NodesR @@ -2383,13 +2351,11 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ! Interface DOFS p%DOFI =0 do iiNode= 1,p%NInterf - iNode = p%Interf(iiNode,1) - p%DOFI = p%DOFI + len(m%NodesDOFtilde(iNode)) + p%DOFI = p%DOFI + len(m%NodesDOFtilde( p%Interf(iiNode,1) )) enddo ! Reaction DOFs do iiNode= 1,p%NReact - iNode = p%Reacts(iiNode,1) - p%DOFC = p%DOFC + len(m%NodesDOFtilde(iNode)) + p%DOFC = p%DOFC + len(m%NodesDOFtilde( p%Reacts(iiNode,1) )) enddo p%DOFR = p%DOFC + p%DOFI p%DOFL = Init%nDOFRed - p%DOFR ! TODO @@ -2397,7 +2363,7 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) if (p%DOFC /= p%NReact*6) then call Fatal('Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'); return endif - if (p%DOFI /= p%NNodes_I*6) then + if (p%DOFI /= p%nNodes_I*6) then call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'); return endif @@ -2446,9 +2412,9 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) print*,'Number of DOFs: interface (R)',p%DOFR print*,'Number of DOFs: internal (L)',p%DOFL print*,'Number of DOFs: total (R+L)',Init%nDOFRed - print*,'Number of Nodes: "interface" (I)',p%NNodes_I + print*,'Number of Nodes: "interface" (I)',p%nNodes_I print*,'Number of Nodes: "reactions" (C)',p%NReact - print*,'Number of Nodes: internal (L)',p%NNodes_L + print*,'Number of Nodes: internal (L)',p%nNodes_L print*,'Number of Nodes: total (R+L)',Init%NNode contains LOGICAL FUNCTION Failed() @@ -2477,12 +2443,12 @@ SUBROUTINE ConstructUFL( u, p, UFL ) REAL(ReKi) :: UFL(p%DOFL) INTEGER :: I, J, StartDOF ! integers for indexing into mesh and UFL - ! note that p%DOFL = p%NNodes_L*6 - DO I = 1, p%NNodes_L !Only interior nodes here + ! note that p%DOFL = p%nNodes_L*6 + DO I = 1, p%nNodes_L !Only interior nodes here ! starting index in the master arrays for the current node startDOF = (I-1)*6 + 1 ! TODO ! index into the Y2Mesh - J = p%NNodes_I + I + J = p%nNodes_I + I ! Construct UFL array from the Force and Moment fields of the input mesh UFL ( startDOF : startDOF + 2 ) = u%LMesh%Force (:,J) UFL ( startDOF+3 : startDOF + 5 ) = u%LMesh%Moment(:,J) @@ -2540,7 +2506,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of nodes (NNodes):',Init%NNode + WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',Init%NNode WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') '--------', '-----------', '---------------', '---------------', '---------------' ! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, Init%NNode) !do not group the format or it won't work 3(E15.6) does not work !bjj??? diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 6cac3cb3b..4e8224c2b 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -196,10 +196,10 @@ typedef ^ ParameterType IntKi DofL - - - "Internal nodes # of DOFs" typedef ^ ParameterType IntKi DofI - - - "Interface nodes # of DOFs" typedef ^ ParameterType IntKi DofR - - - "Interface and restrained nodes # of DOFs" typedef ^ ParameterType IntKi DofC - - - "Contrained nodes # of DOFs" -typedef ^ ParameterType IntKi NNodes_RbarL - - - "Number of Interface + Internal nodes" -typedef ^ ParameterType IntKi NNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi nNodes_RbarL - - - "Number of Interface + Internal nodes" +typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" -typedef ^ ParameterType IntKi NNodes_I - - - "Number of Interface nodes" +typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" typedef ^ ParameterType IntKi NInterf - - - "Number of joints attached to transition piece" typedef ^ ParameterType IntKi Interf {:}{:} - - "Interface degree of freedoms" typedef ^ ParameterType IntKi NReact - - - "Number of joints with reactions" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 12c9e7fd7..181f766fd 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -240,10 +240,10 @@ MODULE SubDyn_Types INTEGER(IntKi) :: DofI !< Interface nodes of DOFs [-] INTEGER(IntKi) :: DofR !< Interface and restrained nodes of DOFs [-] INTEGER(IntKi) :: DofC !< Contrained nodes of DOFs [-] - INTEGER(IntKi) :: NNodes_RbarL !< Number of Interface + Internal nodes [-] - INTEGER(IntKi) :: NNodes_L !< Number of Internal nodes [-] + INTEGER(IntKi) :: nNodes_RbarL !< Number of Interface + Internal nodes [-] + INTEGER(IntKi) :: nNodes_L !< Number of Internal nodes [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] - INTEGER(IntKi) :: NNodes_I !< Number of Interface nodes [-] + INTEGER(IntKi) :: nNodes_I !< Number of Interface nodes [-] INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Interf !< Interface degree of freedoms [-] INTEGER(IntKi) :: NReact !< Number of joints with reactions [-] @@ -6869,8 +6869,8 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%DofI = SrcParamData%DofI DstParamData%DofR = SrcParamData%DofR DstParamData%DofC = SrcParamData%DofC - DstParamData%NNodes_RbarL = SrcParamData%NNodes_RbarL - DstParamData%NNodes_L = SrcParamData%NNodes_L + DstParamData%nNodes_RbarL = SrcParamData%nNodes_RbarL + DstParamData%nNodes_L = SrcParamData%nNodes_L IF (ALLOCATED(SrcParamData%Nodes_L)) THEN i1_l = LBOUND(SrcParamData%Nodes_L,1) i1_u = UBOUND(SrcParamData%Nodes_L,1) @@ -6885,7 +6885,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%Nodes_L = SrcParamData%Nodes_L ENDIF - DstParamData%NNodes_I = SrcParamData%NNodes_I + DstParamData%nNodes_I = SrcParamData%nNodes_I DstParamData%NInterf = SrcParamData%NInterf IF (ALLOCATED(SrcParamData%Interf)) THEN i1_l = LBOUND(SrcParamData%Interf,1) @@ -7398,14 +7398,14 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! DofI Int_BufSz = Int_BufSz + 1 ! DofR Int_BufSz = Int_BufSz + 1 ! DofC - Int_BufSz = Int_BufSz + 1 ! NNodes_RbarL - Int_BufSz = Int_BufSz + 1 ! NNodes_L + Int_BufSz = Int_BufSz + 1 ! nNodes_RbarL + Int_BufSz = Int_BufSz + 1 ! nNodes_L Int_BufSz = Int_BufSz + 1 ! Nodes_L allocated yes/no IF ( ALLOCATED(InData%Nodes_L) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Nodes_L upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%Nodes_L) ! Nodes_L END IF - Int_BufSz = Int_BufSz + 1 ! NNodes_I + Int_BufSz = Int_BufSz + 1 ! nNodes_I Int_BufSz = Int_BufSz + 1 ! NInterf Int_BufSz = Int_BufSz + 1 ! Interf allocated yes/no IF ( ALLOCATED(InData%Interf) ) THEN @@ -8029,9 +8029,9 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofC Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_RbarL + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_RbarL Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_L + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8049,7 +8049,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes_I + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf Int_Xferred = Int_Xferred + 1 @@ -9128,9 +9128,9 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%DofC = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NNodes_RbarL = IntKiBuf( Int_Xferred ) + OutData%nNodes_RbarL = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NNodes_L = IntKiBuf( Int_Xferred ) + OutData%nNodes_L = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated Int_Xferred = Int_Xferred + 1 @@ -9158,7 +9158,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) DEALLOCATE(mask2) END IF - OutData%NNodes_I = IntKiBuf( Int_Xferred ) + OutData%nNodes_I = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NInterf = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 From 4ddeaaea8c483daed6b5c8d1cb35f49edb3eb3c6 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 9 Jan 2020 17:21:22 -0700 Subject: [PATCH 122/377] FlexSub: y2map using nodes indices --- modules/subdyn/src/SubDyn.f90 | 90 +++++++++++++++++------------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 3b4c6d4e2..d8c05b8af 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -148,41 +148,6 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) END SUBROUTINE CreateY2Meshes -!------------------------------------------------------------------------------------------------------ -!> Set the index array that maps SD internal nodes to the Y2Mesh nodes. -!! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, -!! so this routine could easily have segmentation faults if any errors exist. -SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh ) - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh - ! locals - INTEGER(IntKi) :: i - INTEGER(IntKi) :: SDnode - INTEGER(IntKi) :: y2Node - - y2Node = 0 - ! Interface nodes (IDI) - DO I = 1,SIZE(p%IDI,1)/6 - y2Node = y2Node + 1 - SDnode = p%IDI(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - - ! Interior nodes (IDL) - DO I = 1,SIZE(p%IDL,1)/6 - y2Node = y2Node + 1 - SDnode = p%IDL(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - - ! Base Reaction nodes (IDC) - DO I = 1,SIZE(p%IDC,1)/6 - y2Node = y2Node + 1 - SDnode = p%IDC(I*6) / 6 ! TODO TODO TODO integer division gives me the actual node index; it is not the nodeID - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - -END SUBROUTINE SD_Y2Mesh_Mapping !--------------------------------------------------------------------------- @@ -2472,9 +2437,10 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders INTEGER(IntKi) :: mType ! Member Type + Real(ReKi) :: mMass, mLength ! Member mass and length INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix - REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3), mlength !temporary arrays, member i-th direction cosine matrix (global to local) and member length + REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices @@ -2515,7 +2481,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem - WRITE(UnSum, '(A10,5(A10))') 'Elem No.', 'Node_I', 'Node_J', 'Type', 'Prop_I', 'Prop_J' + WRITE(UnSum, '(A10,5(A10))') 'Elem No.','Node_I','Node_J','Prop_I','Prop_J','Type' WRITE(UnSum, '(6(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) WRITE(UnSum, '()') @@ -2541,20 +2507,20 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers WRITE(UnSum, '(A,I6)') 'Number of nodes per member:', Init%Ndiv+1 - WRITE(UnSum, '(A9,A10,A10,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID', 'Mass', 'Node IDs...' - !WRITE(UnSum, '('//Num2LStr(Init%NDiv + 1 )//'(I6))') ((Init%MemberNodes(i, j), j = 1, Init%NDiv+1), i = 1, p%NMembers) + WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS - propids=p%Elems(i,iMProp:iMProp+1) - mlength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) + propids=p%Elems(i,iMProp:iMProp+1) ! TODO use member + mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length IF (ErrStat .EQ. ErrID_None) THEN mType = Init%Members(I, iMType) ! if (mType==idMemberBeam) then - WRITE(UnSum, '(I9,I10,I10, E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3), & - MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & - Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mlength, .TRUE.), & - ' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + mMass= MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & + Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mLength, .TRUE.) + + WRITE(UnSum, '(I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& + mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) else WRITE(UnSum, '(A)') 'TODO, member mass for non-beam elements' endif @@ -2580,7 +2546,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) XYZ2=Init%Nodes(Init%Members(i,3),2:4) ENDIF ENDDO - CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mlength, ErrStat, ErrMsg) + CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) DirCos=TRANSPOSE(DirCos) !This is now global to local WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO @@ -2719,6 +2685,38 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) #endif CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) +contains + !------------------------------------------------------------------------------------------------------ + !> Set the index array that maps SD internal nodes to the Y2Mesh nodes. + !! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, + !! so this routine could easily have segmentation faults if any errors exist. + SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh + ! locals + INTEGER(IntKi) :: i + INTEGER(IntKi) :: SDnode + INTEGER(IntKi) :: y2Node + y2Node = 0 + ! Interface nodes (IDI) + DO I = 1,SIZE(p%Interf,1) + y2Node = y2Node + 1 + SDnode = p%Interf(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Interior nodes (IDL) + DO I = 1,SIZE(p%Nodes_L,1) + y2Node = y2Node + 1 + SDnode = p%Nodes_L(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Base Reaction nodes (IDC) + DO I = 1,SIZE(p%Reacts,1) + y2Node = y2Node + 1 + SDnode = p%Reacts(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + END SUBROUTINE SD_Y2Mesh_Mapping END SUBROUTINE OutSummary From 63718d2a716427c107fe07287075d1ad661e0a46 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 9 Jan 2020 18:46:19 -0700 Subject: [PATCH 123/377] FlexSub: reduction of forces using Tred and full force vector --- modules/subdyn/src/SD_FEM.f90 | 14 +- modules/subdyn/src/SubDyn.f90 | 136 ++++++++++++-------- modules/subdyn/src/SubDyn_Registry.txt | 3 + modules/subdyn/src/SubDyn_Types.f90 | 171 +++++++++++++++++++++++++ 4 files changed, 264 insertions(+), 60 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index a9ae30003..75dfcac97 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1019,7 +1019,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) Init%nDOFRed = nDOF_ConstraintReduced() print*,'nDOF constraint elim', Init%nDOFRed , '/' , Init%TDOF - CALL AllocAry( m%Tred, Init%TDOF, Init%nDOFRed, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Tred, Init%TDOF, Init%nDOFRed, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix Tred=0 call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) @@ -1175,15 +1175,17 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call move_alloc(Init%FG, FF) ! Reallocating nDOF = Init%nDOFRed - CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D', ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix - CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( m%Fext, Init%TDOF , 'm%Fext ', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force + CALL AllocAry( m%Fext_red, Init%nDOFRed, 'm%Fext_red', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force, reduced by Tred ! Elimination Init%M = matmul(transpose(m%Tred), matmul(MM, m%Tred)) Init%K = matmul(transpose(m%Tred), matmul(KK, m%Tred)) Init%FG = matmul(transpose(m%Tred), FF) - Init%D = 0 !< Used for additional stiffness + Init%D = 0 !< Used for additional stiffness ! --- Triggers for storage of DOF indices, replacing with indices in constrained system CALL ReInitBCs(Init, p) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index d8c05b8af..abc770576 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -290,6 +290,8 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%Interf(:,1), p%Nodes_L(:,1), p%Reacts(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(m%INodes_Mesh_to_SD, Init%NNode, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); if(Failed()) return + call Y2Mesh_SD_Mapping(p, m%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices ! Initialize the outputs & Store mapping between nodes and elements CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return @@ -399,7 +401,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) ! Inputs on interior nodes: - CALL ConstructUFL( u, p, m%UFL ) + CALL ConstructUFL( u, p, m, m%UFL ) !________________________________________ ! Set motion outputs on y%Y2mesh @@ -613,7 +615,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! form u(4) in Eq. 10: - CALL ConstructUFL( u, p, m%UFL ) + CALL ConstructUFL( u, p, m, m%UFL ) !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot @@ -1410,12 +1412,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, m%UFL ) + CALL ConstructUFL( u_interp, p, m, m%UFL ) ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, UFL2 ) + CALL ConstructUFL( u_interp, p, m, UFL2 ) ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -1538,6 +1540,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) !................................ CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%DOFM, Init, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) + ! TODO TODO TODO DAMPING MATRIX if(Failed()) return ! to use a little less space, let's deallocate these arrays that we don't need anymore, then allocate the next set of temporary arrays: @@ -2299,6 +2302,7 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) p%nNodes_I = p%NInterf ! Number of interface nodes nNodes_R = p%NReact+p%NInterf ! Number of retained nodes p%nNodes_L = Init%NNode - nNodes_R ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%nNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%nNodes_I + ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') @@ -2401,23 +2405,40 @@ END SUBROUTINE CleanUp END SUBROUTINE PartitionDOFNodes_I_C_R_L !------------------------------------------------------------------------------------------------------ -!> Take the input u LMesh and constructs the appropriate corresponding UFL vector -SUBROUTINE ConstructUFL( u, p, UFL ) - TYPE(SD_InputType), INTENT(IN ) :: u ! Inputs - TYPE(SD_ParameterType), INTENT(IN ) :: p ! Parameters - REAL(ReKi) :: UFL(p%DOFL) - INTEGER :: I, J, StartDOF ! integers for indexing into mesh and UFL - - ! note that p%DOFL = p%nNodes_L*6 - DO I = 1, p%nNodes_L !Only interior nodes here - ! starting index in the master arrays for the current node - startDOF = (I-1)*6 + 1 ! TODO - ! index into the Y2Mesh - J = p%nNodes_I + I - ! Construct UFL array from the Force and Moment fields of the input mesh - UFL ( startDOF : startDOF + 2 ) = u%LMesh%Force (:,J) - UFL ( startDOF+3 : startDOF + 5 ) = u%LMesh%Moment(:,J) - END DO +!> Construct force vector on internal DOF (L) from the values on the input mesh +!! First, the full vector of external forces is built on the non-reduced DOF +!! Then, the vector is reduced using the Tred matrix +SUBROUTINE ConstructUFL( u, p, m, UFL ) + type(SD_InputType), intent(in ) :: u ! Inputs + type(SD_ParameterType), intent(in ) :: p ! Parameters + type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red + real(ReKi) , intent(out) :: UFL(p%DOFL) + integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes + integer :: nMembers + real(ReKi), parameter :: myNaN = -9999998.989_ReKi + ! TODO to save time, perform Tred multiplication only if Tred is not identity + + ! --- Build vector of external force + m%Fext= myNaN + DO iMeshNode = 1,size(m%INodes_Mesh_to_SD) + iSDNode = m%INodes_Mesh_to_SD(iMeshNode) + nMembers = (size(m%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's DOFlist + ! Force - All nodes have only 3 translational DOFs + m%Fext( m%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) + ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + m%Fext( m%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers + m%Fext( m%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers + m%Fext( m%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers + enddo + ! TODO: remove test below in the future + if (any(m%Fext == myNaN)) then + print*,'Error in setting up Fext' + STOP + endif + ! --- Reduced vector of external force + m%Fext_red = matmul(transpose(m%Tred), m%Fext) + UFL=0 + UFL= m%Fext_red(p%IDL) END SUBROUTINE @@ -2685,41 +2706,48 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) #endif CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) -contains - !------------------------------------------------------------------------------------------------------ - !> Set the index array that maps SD internal nodes to the Y2Mesh nodes. - !! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, - !! so this routine could easily have segmentation faults if any errors exist. - SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh - ! locals - INTEGER(IntKi) :: i - INTEGER(IntKi) :: SDnode - INTEGER(IntKi) :: y2Node - y2Node = 0 - ! Interface nodes (IDI) - DO I = 1,SIZE(p%Interf,1) - y2Node = y2Node + 1 - SDnode = p%Interf(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Interior nodes (IDL) - DO I = 1,SIZE(p%Nodes_L,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_L(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Base Reaction nodes (IDC) - DO I = 1,SIZE(p%Reacts,1) - y2Node = y2Node + 1 - SDnode = p%Reacts(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - END SUBROUTINE SD_Y2Mesh_Mapping - END SUBROUTINE OutSummary +!------------------------------------------------------------------------------------------------------ +!> Set the index array that maps SD internal nodes to the Y2Mesh nodes. +!! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, +!! so this routine could easily have segmentation faults if any errors exist. +SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh + ! locals + INTEGER(IntKi) :: i + INTEGER(IntKi) :: SDnode + INTEGER(IntKi) :: y2Node + y2Node = 0 + ! Interface nodes (IDI) + DO I = 1,SIZE(p%Interf,1) + y2Node = y2Node + 1 + SDnode = p%Interf(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Interior nodes (IDL) + DO I = 1,SIZE(p%Nodes_L,1) + y2Node = y2Node + 1 + SDnode = p%Nodes_L(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Base Reaction nodes (IDC) + DO I = 1,SIZE(p%Reacts,1) + y2Node = y2Node + 1 + SDnode = p%Reacts(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO +END SUBROUTINE SD_Y2Mesh_Mapping +!> +SUBROUTINE Y2Mesh_SD_Mapping(p, MeshtoSD) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + INTEGER(IntKi), INTENT( OUT) :: MeshtoSD(:) !< index/mapping of mesh nodes with SD mesh + MeshtoSD( 1:p%nNodes_I) = p%Interf(:,1) + MeshtoSD(p%nNodes_I+ 1:p%nNodes_I+p%nNodes_L) = p%Nodes_L(:,1) + MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nReact) = p%Reacts(:,1) +END SUBROUTINE Y2Mesh_SD_Mapping + !------------------------------------------------------------------------------------------------------ !> This function calculates the length of a member FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 4e8224c2b..e376d459f 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -154,9 +154,12 @@ typedef ^ ^ DbKi LastOutTime - - - typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" +typedef ^ ^ IntKi INodes_Mesh_to_SD {:} - - "Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" typedef ^ ^ ReKi Tred {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" +typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 181f766fd..452176e55 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -198,9 +198,12 @@ MODULE SubDyn_Types INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_Mesh_to_SD !< Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Tred !< Transformation matrix performing the constraint reduction x = T. xtilde [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads on unconstrained DOFs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext_red !< External loads on constrained DOFs, Fext_red= T^t Fext [-] END TYPE SD_MiscVarType ! ======================= ! ========= SD_ParameterType ======= @@ -5475,6 +5478,18 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF +IF (ALLOCATED(SrcMiscData%INodes_Mesh_to_SD)) THEN + i1_l = LBOUND(SrcMiscData%INodes_Mesh_to_SD,1) + i1_u = UBOUND(SrcMiscData%INodes_Mesh_to_SD,1) + IF (.NOT. ALLOCATED(DstMiscData%INodes_Mesh_to_SD)) THEN + ALLOCATE(DstMiscData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%INodes_Mesh_to_SD = SrcMiscData%INodes_Mesh_to_SD +ENDIF IF (ALLOCATED(SrcMiscData%ElemsDOF)) THEN i1_l = LBOUND(SrcMiscData%ElemsDOF,1) i1_u = UBOUND(SrcMiscData%ElemsDOF,1) @@ -5516,6 +5531,30 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF END IF DstMiscData%Tred = SrcMiscData%Tred +ENDIF +IF (ALLOCATED(SrcMiscData%Fext)) THEN + i1_l = LBOUND(SrcMiscData%Fext,1) + i1_u = UBOUND(SrcMiscData%Fext,1) + IF (.NOT. ALLOCATED(DstMiscData%Fext)) THEN + ALLOCATE(DstMiscData%Fext(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Fext = SrcMiscData%Fext +ENDIF +IF (ALLOCATED(SrcMiscData%Fext_red)) THEN + i1_l = LBOUND(SrcMiscData%Fext_red,1) + i1_u = UBOUND(SrcMiscData%Fext_red,1) + IF (.NOT. ALLOCATED(DstMiscData%Fext_red)) THEN + ALLOCATE(DstMiscData%Fext_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Fext_red = SrcMiscData%Fext_red ENDIF END SUBROUTINE SD_CopyMisc @@ -5567,6 +5606,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(MiscData%NodesDOFtilde) ENDIF +IF (ALLOCATED(MiscData%INodes_Mesh_to_SD)) THEN + DEALLOCATE(MiscData%INodes_Mesh_to_SD) +ENDIF IF (ALLOCATED(MiscData%ElemsDOF)) THEN DEALLOCATE(MiscData%ElemsDOF) ENDIF @@ -5575,6 +5617,12 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) ENDIF IF (ALLOCATED(MiscData%Tred)) THEN DEALLOCATE(MiscData%Tred) +ENDIF +IF (ALLOCATED(MiscData%Fext)) THEN + DEALLOCATE(MiscData%Fext) +ENDIF +IF (ALLOCATED(MiscData%Fext_red)) THEN + DEALLOCATE(MiscData%Fext_red) ENDIF END SUBROUTINE SD_DestroyMisc @@ -5710,6 +5758,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! INodes_Mesh_to_SD allocated yes/no + IF ( ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! INodes_Mesh_to_SD upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%INodes_Mesh_to_SD) ! INodes_Mesh_to_SD + END IF Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no IF ( ALLOCATED(InData%ElemsDOF) ) THEN Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension @@ -5725,6 +5778,16 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*2 ! Tred upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%Tred) ! Tred END IF + Int_BufSz = Int_BufSz + 1 ! Fext allocated yes/no + IF ( ALLOCATED(InData%Fext) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fext upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fext) ! Fext + END IF + Int_BufSz = Int_BufSz + 1 ! Fext_red allocated yes/no + IF ( ALLOCATED(InData%Fext_red) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fext_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fext_red) ! Fext_red + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5961,6 +6024,19 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz ENDIF END DO END IF + IF ( .NOT. ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_Mesh_to_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_Mesh_to_SD,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%INodes_Mesh_to_SD)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_Mesh_to_SD))-1 ) = PACK(InData%INodes_Mesh_to_SD,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%INodes_Mesh_to_SD) + END IF IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6009,6 +6085,32 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%Tred)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Tred))-1 ) = PACK(InData%Tred,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%Tred) END IF + IF ( .NOT. ALLOCATED(InData%Fext) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext) + END IF + IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) + END IF END SUBROUTINE SD_PackMisc SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -6401,6 +6503,29 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_Mesh_to_SD not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%INodes_Mesh_to_SD)) DEALLOCATE(OutData%INodes_Mesh_to_SD) + ALLOCATE(OutData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%INodes_Mesh_to_SD)>0) OutData%INodes_Mesh_to_SD = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_Mesh_to_SD))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%INodes_Mesh_to_SD) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6479,6 +6604,52 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + SIZE(OutData%Tred) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fext)) DEALLOCATE(OutData%Fext) + ALLOCATE(OutData%Fext(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Fext)>0) OutData%Fext = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Fext) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fext_red)) DEALLOCATE(OutData%Fext_red) + ALLOCATE(OutData%Fext_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Fext_red)>0) OutData%Fext_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext_red))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Fext_red) + DEALLOCATE(mask1) + END IF END SUBROUTINE SD_UnPackMisc SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) From c38bc49c5f14ed1de34bab65a64d352ea3255257 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 9 Jan 2020 19:26:33 -0700 Subject: [PATCH 124/377] FlexSub: storing mapping SD to mesh, revert if not needed --- modules/subdyn/src/SubDyn.f90 | 52 +++++++++++------------ modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 57 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index abc770576..ef6698538 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -274,15 +274,6 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Write the summary file - IF ( Init%SSSum ) THEN - ! note p%KBB/MBB are KBBt/MBBt - ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return - IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) - IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) - ENDIF ! --- Initialize Inputs and Outputs ! Create the input and output meshes associated with Transition Piece reference point @@ -290,8 +281,19 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%Interf(:,1), p%Nodes_L(:,1), p%Reacts(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry(m%INodes_Mesh_to_SD, Init%NNode, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); if(Failed()) return + call AllocAry(m%INodes_Mesh_to_SD, Init%NNode, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); if(Failed()) return ! TODO move to AllocMiscVars, when Nnode in p + call AllocAry(m%INodes_SD_to_Mesh, Init%NNode, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); if(Failed()) return call Y2Mesh_SD_Mapping(p, m%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices + call SD_Y2Mesh_Mapping(p, m%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices + + ! --- Write the summary file + IF ( Init%SSSum ) THEN + ! note p%KBB/MBB are KBBt/MBBt + ! Write a summary of the SubDyn Initialization + CALL OutSummary(Init,p,m%INodes_SD_to_Mesh,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return + IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) + IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) + ENDIF ! Initialize the outputs & Store mapping between nodes and elements CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return @@ -388,7 +390,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None - ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -438,8 +439,10 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --------------------------------------------------------------------------------- ! Place the outputs onto interface node portion of Y2 output mesh ! --------------------------------------------------------------------------------- + ! TODO TODO TODO UL is constrained, need to multiply by T to get full DOFs DO I = 1, p%nNodes_I - startDOF = (I-1)*6 + 1 + startDOF = (I-1)*6 + 1 ! OK since interface Nodes are limited to 6 DOFs for now + ! TODO: code below might need to change if not all DOF fixed at interface ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%UR_bar(startDOF + 3), m%UR_bar(startDOF + 4), m%UR_bar(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') @@ -456,6 +459,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --------------------------------------------------------------------------------- ! Place the outputs onto interior node portion of Y2 output mesh ! --------------------------------------------------------------------------------- + ! TODO TODO TODO UL is constrained, need to multiply by T to get full DOFs DO I = 1, p%nNodes_L !Only interior nodes here ! starting index in the master arrays for the current node startDOF = (I-1)*6 + 1 @@ -476,6 +480,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END DO !Repeat for the acceleration, there should be a way to combine into 1 loop + ! TODO TODO TODO UL is constrained L1 = p%nNodes_I+1 L2 = p%nNodes_I+p%nNodes_L junk= RESHAPE(m%UL_dotdot,(/6 ,p%nNodes_L/)) @@ -483,18 +488,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%RotationAcc ( :,L1:L2) = junk(4:6,:) ! --------------------------------------------------------------------------------- - ! Base reaction nodes + ! Base reaction nodes have zero disp vel and acc ! --------------------------------------------------------------------------------- - L1 = p%nNodes_I+p%nNodes_L+1 + L1 = p%nNodes_I+p%nNodes_L+1 L2 = p%nNodes_I+p%nNodes_L+p%NReact - - y%Y2mesh%TranslationDisp( :,L1:L2) = 0.0 + y%Y2mesh%TranslationDisp(:,L1:L2) = 0.0 CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return - - y%Y2mesh%TranslationVel ( :,L1:L2) = 0.0 - y%Y2mesh%RotationVel ( :,L1:L2) = 0.0 - y%Y2mesh%TranslationAcc ( :,L1:L2) = 0.0 - y%Y2mesh%RotationAcc ( :,L1:L2) = 0.0 + y%Y2mesh%TranslationVel (:,L1:L2) = 0.0 + y%Y2mesh%RotationVel (:,L1:L2) = 0.0 + y%Y2mesh%TranslationAcc (:,L1:L2) = 0.0 + y%Y2mesh%RotationAcc (:,L1:L2) = 0.0 !________________________________________ ! Set loads outputs on y%Y1Mesh @@ -2444,9 +2447,10 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) !------------------------------------------------------------------------------------------------------ !> Output the summary file -SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) +SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file + INTEGER(IntKi) , INTENT(IN) :: SDtoMeshIndx(:) ! SD to mesh mapping TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use TYPE(FEM_MatArrays), INTENT(IN) :: FEMparams ! FEM parameters that will be passed in for summary file use INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation @@ -2459,17 +2463,13 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders INTEGER(IntKi) :: mType ! Member Type Real(ReKi) :: mMass, mLength ! Member mass and length - INTEGER(IntKi) :: SDtoMeshIndx(Init%NNode) REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices - ErrStat = ErrID_None ErrMsg = "" - - CALL SD_Y2Mesh_Mapping(p, SDtoMeshIndx ) !------------------------------------------------------------------------------------------------------------- ! open txt file diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index e376d459f..f7230fd6e 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -155,6 +155,7 @@ typedef ^ ^ IntKi Decimat - - - typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi INodes_Mesh_to_SD {:} - - "Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) " "-" +typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" typedef ^ ^ ReKi Tred {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 452176e55..64566097d 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -199,6 +199,7 @@ MODULE SubDyn_Types TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_Mesh_to_SD !< Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Tred !< Transformation matrix performing the constraint reduction x = T. xtilde [-] @@ -5490,6 +5491,18 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%INodes_Mesh_to_SD = SrcMiscData%INodes_Mesh_to_SD ENDIF +IF (ALLOCATED(SrcMiscData%INodes_SD_to_Mesh)) THEN + i1_l = LBOUND(SrcMiscData%INodes_SD_to_Mesh,1) + i1_u = UBOUND(SrcMiscData%INodes_SD_to_Mesh,1) + IF (.NOT. ALLOCATED(DstMiscData%INodes_SD_to_Mesh)) THEN + ALLOCATE(DstMiscData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%INodes_SD_to_Mesh = SrcMiscData%INodes_SD_to_Mesh +ENDIF IF (ALLOCATED(SrcMiscData%ElemsDOF)) THEN i1_l = LBOUND(SrcMiscData%ElemsDOF,1) i1_u = UBOUND(SrcMiscData%ElemsDOF,1) @@ -5609,6 +5622,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%INodes_Mesh_to_SD)) THEN DEALLOCATE(MiscData%INodes_Mesh_to_SD) ENDIF +IF (ALLOCATED(MiscData%INodes_SD_to_Mesh)) THEN + DEALLOCATE(MiscData%INodes_SD_to_Mesh) +ENDIF IF (ALLOCATED(MiscData%ElemsDOF)) THEN DEALLOCATE(MiscData%ElemsDOF) ENDIF @@ -5763,6 +5779,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! INodes_Mesh_to_SD upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%INodes_Mesh_to_SD) ! INodes_Mesh_to_SD END IF + Int_BufSz = Int_BufSz + 1 ! INodes_SD_to_Mesh allocated yes/no + IF ( ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! INodes_SD_to_Mesh upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%INodes_SD_to_Mesh) ! INodes_SD_to_Mesh + END IF Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no IF ( ALLOCATED(InData%ElemsDOF) ) THEN Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension @@ -6037,6 +6058,19 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%INodes_Mesh_to_SD)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_Mesh_to_SD))-1 ) = PACK(InData%INodes_Mesh_to_SD,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%INodes_Mesh_to_SD) END IF + IF ( .NOT. ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_SD_to_Mesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_SD_to_Mesh,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%INodes_SD_to_Mesh)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_SD_to_Mesh))-1 ) = PACK(InData%INodes_SD_to_Mesh,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%INodes_SD_to_Mesh) + END IF IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6526,6 +6560,29 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + SIZE(OutData%INodes_Mesh_to_SD) DEALLOCATE(mask1) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_SD_to_Mesh not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%INodes_SD_to_Mesh)) DEALLOCATE(OutData%INodes_SD_to_Mesh) + ALLOCATE(OutData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%INodes_SD_to_Mesh)>0) OutData%INodes_SD_to_Mesh = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_SD_to_Mesh))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%INodes_SD_to_Mesh) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE From 732b0c89d2f98117c478a56d508544d7748eaceb Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 07:58:30 -0700 Subject: [PATCH 125/377] FlexSub: variable renaming to highlight ILC partitioning --- modules/subdyn/src/SD_FEM.f90 | 128 +- modules/subdyn/src/SubDyn.f90 | 512 ++++---- modules/subdyn/src/SubDyn_Output.f90 | 34 +- modules/subdyn/src/SubDyn_Registry.txt | 64 +- modules/subdyn/src/SubDyn_Types.f90 | 1532 ++++++++++++++---------- 5 files changed, 1315 insertions(+), 955 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 75dfcac97..f1c55ab25 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -25,7 +25,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in - INTEGER(IntKi), PARAMETER :: TPdofL = 6 ! 6 degrees of freedom (length of u subarray [UTP]) + INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 ! 6 degrees of freedom (length of u subarray [UTP]) ! values of these parameters are ordered by their place in SubDyn input file: INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) @@ -85,13 +85,13 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) INTEGER(IntKi) :: I,J,K !counter ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) - CALL AllocAry(Init%NodesConnE, Init%NNode, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; - CALL AllocAry(Init%NodesConnN, Init%NNode, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnE, p%nNodes, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnN, p%nNodes, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; Init%NodesConnE = 0 Init%NodesConnN = -99999 ! Not Used ! find the node connectivity, nodes/elements that connect to a common node - DO I = 1, Init%NNode + DO I = 1, p%nNodes !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array k = 0 DO J = 1, Init%NElem !This should be vectorized @@ -248,7 +248,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) ! TODO See if Elems is actually used elsewhere CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%Nodes, Init%NNode, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%Nodes, p%nNodes, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return ! --- Initialize Nodes Init%Nodes = -999999 ! Init to unphysical values @@ -258,20 +258,20 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) enddo ! --- Re-Initialize Reactions, pointing to index instead of JointID - do I = 1, p%NReact - JointID=p%Reacts(I,1) - p%Reacts(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index - if (p%Reacts(I,1)<=0) then + do I = 1, p%nNodes_C + JointID=p%Nodes_C(I,1) + p%Nodes_C(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index + if (p%Nodes_C(I,1)<=0) then CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') return endif enddo ! --- Re-Initialize interface joints, pointing to index instead of JointID - do I = 1, p%NInterf - JointID=p%Interf(I,1) - p%Interf(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (p%Interf(I,1)<=0) then + do I = 1, p%nNodes_I + JointID=p%Nodes_I(I,1) + p%Nodes_I(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (p%Nodes_I(I,1)<=0) then CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') return endif @@ -377,12 +377,12 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! Total number of element Init%NElem = p%NMembers*Init%NDiv ! TODO TODO TODO: THIS IS A MAX SINCE CABLE AND RIGID CANNOT BE SUBDIVIDED ! Total number of nodes - Depends on division and number of nodes per element - Init%NNode = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - Init%NNode = Init%NNode + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. + p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers + p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. ! check the number of interior modes - IF ( p%Nmodes > 6*(Init%NNode - p%NInterf - p%NReact) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(Init%NNode - p%NInterf - p%NReact) ))) + IF ( p%Nmodes > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))) RETURN ENDIF @@ -527,7 +527,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! Init%NPropB = kprop Init%NElem = kelem ! TODO since not all members might have been divided - Init%NNode = knode ! TODO since not all members might have been divided + p%nNodes = knode ! TODO since not all members might have been divided ENDIF ! if NDiv is greater than 1 @@ -767,7 +767,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) ErrMsg = "" ErrStat = ErrID_None - allocate(m%NodesDOF(1:Init%NNode), stat=ErrStat2) + allocate(m%NodesDOF(1:p%nNodes), stat=ErrStat2) ErrMsg2="Error allocating NodesDOF" if(Failed()) return @@ -775,7 +775,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) m%ElemsDOF=-9999 iPrev =0 - do iNode = 1, Init%NNode + do iNode = 1, p%nNodes ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then nRot=3 @@ -804,11 +804,11 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) enddo ! iNode, loop on joints ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%BCs, 6*p%NReact, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%BCs, 6*p%nNodes_C, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return CALL InitBCs(Init, p) ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%IntFc, 6*p%NInterf,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%IntFc, 6*p%nNodes_I,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return CALL InitIntFc(Init, p) ! --- Safety check @@ -818,7 +818,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) endif ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) - if (Init%NNode == count( Init%Nodes(:, iJointType) == idJointCantilever)) then + if (p%nNodes == count( Init%Nodes(:, iJointType) == idJointCantilever)) then do idElem = 1, Init%NElem iNode = p%Elems(idElem, 2) DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) @@ -839,18 +839,18 @@ LOGICAL FUNCTION Failed() END FUNCTION Failed !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have - !! NOTE: need p%Reacts to have an updated first column that uses indices and not JointIDs + !! NOTE: need p%Nodes_C to have an updated first column that uses indices and not JointIDs !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" SUBROUTINE InitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode Init%BCs = -9999 - DO I = 1, p%NReact - iNode = p%Reacts(I,1) ! Node index + DO I = 1, p%nNodes_C + iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%BCs( (I-1)*6+J, 2) = p%Reacts(I, J+1); ! 0 or 1 if fixed reaction or not + Init%BCs( (I-1)*6+J, 2) = p%Nodes_C(I, J+1); ! 0 or 1 if fixed reaction or not ENDDO ENDDO END SUBROUTINE InitBCs @@ -863,11 +863,11 @@ SUBROUTINE InitIntFc(Init, p) TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode Init%IntFc = -9999 - DO I = 1, p%NInterf - iNode = p%Interf(I,1) ! Node index + DO I = 1, p%nNodes_I + iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%IntFc( (I-1)*6+J, 2) = p%Interf(I, J+1); ! 0 or 1 if fixed to interface + Init%IntFc( (I-1)*6+J, 2) = p%Nodes_I(I, J+1); ! 0 or 1 if fixed to interface ENDDO ENDDO END SUBROUTINE InitIntFc @@ -896,12 +896,12 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) ErrStat = ErrID_None ! total unconstrained degrees of freedom of the system - Init%TDOF = nDOF_Unconstrained() - print*,'nDOF_unconstrained:',Init%TDOF, ' (if all Cantilever, it would be: ',6*Init%NNode,')' + p%nDOF = nDOF_Unconstrained() + print*,'nDOF_unconstrained:',p%nDOF, ' (if all Cantilever, it would be: ',6*p%nNodes,')' - CALL AllocAry( Init%K, Init%TDOF, Init%TDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, Init%TDOF, Init%TDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,Init%TDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector Init%K = 0.0_ReKi Init%M = 0.0_ReKi Init%FG = 0.0_ReKi @@ -967,7 +967,7 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() integer(IntKi) :: i integer(IntKi) :: m nDOF_Unconstrained=0 - do i = 1,Init%NNode + do i = 1,p%nNodes if (int(Init%Nodes(i,iJointType)) == idJointCantilever ) then nDOF_Unconstrained = nDOF_Unconstrained + 6 else @@ -985,7 +985,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) use IntegerList, only: init_list, find, pop, destroy_list, len use IntegerList, only: print_list TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p + TYPE(SD_ParameterType), INTENT(INOUT) :: p type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m @@ -1015,11 +1015,11 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) ! --- Misc inits nullify(IDOFNew) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - allocate(m%NodesDOFtilde(1:Init%NNode), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + allocate(m%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system - Init%nDOFRed = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', Init%nDOFRed , '/' , Init%TDOF - CALL AllocAry( Tred, Init%TDOF, Init%nDOFRed, 'm%Tred', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + p%nDOF_red = nDOF_ConstraintReduced() + print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF + CALL AllocAry( Tred, p%nDOF, p%nDOF_red, 'p%T_red', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix Tred=0 call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) @@ -1030,7 +1030,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) ! - create list of indices Itilde in the reduced vector of DOF ! - increment iPrev by the number of DOF of Itilde iPrev =0 - do iNode = 1, Init%NNode + do iNode = 1, p%nNodes if (allocated(Tc)) deallocate(Tc) if (allocated(IDOFOld)) deallocate(IDOFOld) JType = int(Init%Nodes(iNode,iJointType)) @@ -1080,7 +1080,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal if(Failed()) return endif - if (iPrev /= Init%nDOFRed) then + if (iPrev /= p%nDOF_red) then ErrMsg2='Inconsistency in number of reduced DOF'; ErrStat2=ErrID_Fatal if(Failed()) return endif @@ -1112,7 +1112,7 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) ! Contribution from all the other joints - do iNode = 1, Init%NNode + do iNode = 1, p%nNodes m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint NodeType = Init%Nodes(iNode,iJointType) @@ -1166,7 +1166,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - call BuildTMatrix(Init, p, RA, RAm1, m, m%Tred, ErrStat2, ErrMsg2); if (Failed()) return + call BuildTMatrix(Init, p, RA, RAm1, m, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return ! --- DOF elimination for system matrices and RHS vector ! Temporary backup of M and K of full system @@ -1174,17 +1174,17 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call move_alloc(Init%K, KK) call move_alloc(Init%FG, FF) ! Reallocating - nDOF = Init%nDOFRed - CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix - CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - CALL AllocAry( m%Fext, Init%TDOF , 'm%Fext ', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force - CALL AllocAry( m%Fext_red, Init%nDOFRed, 'm%Fext_red', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force, reduced by Tred + nDOF = p%nDOF_red + CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( m%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force + CALL AllocAry( m%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force, reduced by Tred ! Elimination - Init%M = matmul(transpose(m%Tred), matmul(MM, m%Tred)) - Init%K = matmul(transpose(m%Tred), matmul(KK, m%Tred)) - Init%FG = matmul(transpose(m%Tred), FF) + Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) + Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) + Init%FG = matmul(transpose(p%T_red), FF) Init%D = 0 !< Used for additional stiffness ! --- Triggers for storage of DOF indices, replacing with indices in constrained system @@ -1192,9 +1192,9 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) CALL ReInitIntFc(Init, p) ! --- Creating a convenient Map from DOF to Nodes - call AllocAry(m%DOFtilde2Nodes, Init%nDOFRed, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; + call AllocAry(m%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; m%DOFtilde2Nodes=-999 - do iNode=1,Init%NNode + do iNode=1,p%nNodes nDOFPerNode = len(m%NodesDOFtilde(iNode)) do iiDOF = 1, nDOFPerNode iDOF = m%NodesDOFtilde(iNode)%List(iiDOF) @@ -1227,8 +1227,8 @@ SUBROUTINE ReInitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%NReact - iNode = p%Reacts(I,1) ! Node index + DO I = 1, p%nNodes_C + iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 Init%BCs( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) ENDDO @@ -1240,8 +1240,8 @@ SUBROUTINE ReInitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%NInterf - iNode = p%Interf(I,1) ! Node index + DO I = 1, p%nNodes_I + iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) ENDDO @@ -1290,7 +1290,7 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) call init_list(INodesInterf, 0, 0, ErrStat2, ErrMsg2); do iNodeID = 1, size(INodesID) NodeID = INodesID(iNodeID) - iFound = FINDLOCI( p%Interf(:,1), NodeID) + iFound = FINDLOCI( p%Nodes_I(:,1), NodeID) if (iFound>0) then call append(INodesInterf, iNodeID, ErrStat2, ErrMsg2) ! This node is an interface node @@ -1551,7 +1551,7 @@ SUBROUTINE InsertJointStiffDamp(p, m, Init, ErrStat, ErrMsg) integer(IntKi), dimension(:), pointer :: Ifreerot ErrStat = ErrID_None ErrMsg = "" - do iNode = 1, Init%NNode + do iNode = 1, p%nNodes JType = int(Init%Nodes(iNode,iJointType)) StifAdd = Init%Nodes(iNode, iJointStiff) DampAdd = Init%Nodes(iNode, iJointDamp ) @@ -1593,7 +1593,7 @@ SUBROUTINE ApplyConstr(Init,p) INTEGER :: I !, J, k INTEGER :: row_n !bgn_j, end_j, - DO I = 1, p%NReact*6 + DO I = 1, p%nNodes_C*6 row_n = Init%BCs(I, 1) IF (Init%BCs(I, 2) == 1) THEN Init%K(row_n,: )= 0 diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ef6698538..88d6abb88 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -216,7 +216,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! Discretize the structure according to the division size - ! sets Init%NNode, Init%NElm + ! sets p%nNodes, Init%NElm CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2); if(Failed()) return ! Set element properties (p%ElemProps) @@ -234,10 +234,10 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! --- Eigen values of full system (for summary file output only) ! True below is to remove the constraints ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - FEMparams%NOmega = Init%TDOF - p%Nreact*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change + FEMparams%NOmega = p%nDOF - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(FEMparams%Modes, Init%TDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL EigenSolveWrap( Init%K, Init%M, Init%TDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(FEMparams%Modes, p%nDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL EigenSolveWrap( Init%K, Init%M, p%nDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return @@ -280,9 +280,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction - CALL CreateY2Meshes( Init%NNode, Init%Nodes, p%Interf(:,1), p%Nodes_L(:,1), p%Reacts(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry(m%INodes_Mesh_to_SD, Init%NNode, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); if(Failed()) return ! TODO move to AllocMiscVars, when Nnode in p - call AllocAry(m%INodes_SD_to_Mesh, Init%NNode, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); if(Failed()) return + CALL CreateY2Meshes( p%nNodes, Init%Nodes, p%Nodes_I(:,1), p%Nodes_L(:,1), p%Nodes_C(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return call Y2Mesh_SD_Mapping(p, m%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices call SD_Y2Mesh_Mapping(p, m%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices @@ -382,7 +380,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) INTEGER(IntKi) :: I,J ! Counters REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) - REAL(ReKi) :: ULS(p%DOFL), UL0m(p%DOFL), FLt(p%DOFL) ! Temporary values in static improvement method + REAL(ReKi) :: ULS(p%nDOFL), UL0m(p%nDOFL), FLt(p%nDOFL) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) INTEGER(IntKi) :: startDOF REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) @@ -435,6 +433,20 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = m%UL - UL0M END IF ENDIF + ! --- Build original DOF vectors (DOF before the CB reduction) + !m%U_red (p%IDI) = m%UR_bar + !m%U_red (p%IDC) = 0 !!! TODO, might not be generic + !m%U_red (p%IDL) = m%UL + !m%U_red_dot (p%IDI) = m%UR_bar_dot + !m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic + !m%U_red_dot (p%IDL) = m%UL_dot + !m%U_red_dotdot(p%IDI) = m%UR_bar_dotdot + !m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic + !m%U_red_dotdot(p%IDL) = m%UL_dotdot + + !m%U_full = matmul(p%T_red, m%U_red) + !m%U_full_dot = matmul(p%T_red, m%U_red_dot) + !m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) ! --------------------------------------------------------------------------------- ! Place the outputs onto interface node portion of Y2 output mesh @@ -491,7 +503,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Base reaction nodes have zero disp vel and acc ! --------------------------------------------------------------------------------- L1 = p%nNodes_I+p%nNodes_L+1 - L2 = p%nNodes_I+p%nNodes_L+p%NReact + L2 = p%nNodes_I+p%nNodes_L+p%nNodes_C y%Y2mesh%TranslationDisp(:,L1:L2) = 0.0 CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return y%Y2mesh%TranslationVel (:,L1:L2) = 0.0 @@ -769,7 +781,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) END IF ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet - !note at this stage I do not know DOFL yet; Nmodes will be updated later for the FULL FEM CASE. + !note at this stage I do not know nDOFL yet; Nmodes will be updated later for the FULL FEM CASE. p%Nmodes = -1 !Ignore next line CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -836,28 +848,28 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) !------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- ! The joints should be all clamped for now CALL ReadCom ( UnIn, SDInputFile, 'BASE REACTION JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, p%NReact, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_C, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Reacts, p%NReact, ReactCol, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return -DO I = 1, p%NReact +CALL AllocAry(p%Nodes_C, p%nNodes_C, ReactCol, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +DO I = 1, p%nNodes_C CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return - p%Reacts(I,:) = Dummy_IntAry(1:ReactCol) + p%Nodes_C(I,:) = Dummy_IntAry(1:ReactCol) ENDDO -IF (Check ( ( p%NReact < 1 ) .OR. (p%NReact > Init%NJoints) , 'NReact must be greater than 0 and less than number of joints')) return +IF (Check ( ( p%nNodes_C < 1 ) .OR. (p%nNodes_C > Init%NJoints) , 'NReact must be greater than 0 and less than number of joints')) return !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- ! Joints with reaction forces, joint number and locked/free dof CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, p%NInterf, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_I, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Interf, p%NInterf, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return -DO I = 1, p%NInterf +CALL AllocAry(p%Nodes_I, p%nNodes_I, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, p%nNodes_I CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - p%Interf(I,:) = Dummy_IntAry(1:InterfCol) + p%Nodes_I(I,:) = Dummy_IntAry(1:InterfCol) ENDDO -IF (Check( ( p%NInterf < 0 ) .OR. (p%NInterf > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN +IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN !----------------------------------- MEMBERS -------------------------------------- ! One day we will need to take care of COSMIDs for non-circular members @@ -1401,7 +1413,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_InputType) :: u_interp ! interpolated value of inputs REAL(ReKi) :: junk2(2*p%qml) !temporary states (qm and qmdot only) REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP - REAL(ReKi) :: UFL2(p%DOFL) ! temporary copy of UFL + REAL(ReKi) :: UFL2(p%nDOFL) ! temporary copy of UFL INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -1487,44 +1499,44 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes - IF(p%Nmodes > p%DOFL) THEN + IF(p%Nmodes > p%nDOFL) THEN CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than number of internal DOFs. ',ErrStat,ErrMsg,'Craig_Bampton') CALL CleanupCB() RETURN ENDIF ELSE ! full FEM - p%Nmodes = p%DOFL - !Jdampings need to be reallocated here because DOFL not known during Init + p%Nmodes = p%nDOFL + !Jdampings need to be reallocated here because nDOFL not known during Init !So assign value to one temporary variable JDamping1=Init%Jdampings(1) DEALLOCATE(Init%JDampings) - CALL AllocAry( Init%JDampings, p%DOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return + CALL AllocAry( Init%JDampings, p%nDOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return Init%JDampings = JDamping1 ! set default values for all modes ENDIF - CBparams%DOFM = p%Nmodes ! retained modes (all if no C-B reduction) + CBparams%nDOFM = p%Nmodes ! retained modes (all if no C-B reduction) ! matrix dimension paramters p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) - p%URbarL = p%DOFI ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED + p%URbarL = p%nDOFI ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED - CALL AllocParameters(p, CBparams%DOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - - CALL AllocAry( MRR, p%DOFR, p%DOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MLL, p%DOFL, p%DOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MRL, p%DOFR, p%DOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRR, p%DOFR, p%DOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KLL, p%DOFL, p%DOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRL, p%DOFR, p%DOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGL, p%DOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGR, p%DOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocParameters(p, CBparams%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + + CALL AllocAry( MRR, p%nDOFR, p%nDOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MLL, p%nDOFL, p%nDOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, p%nDOFR, p%nDOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, p%nDOFR, p%nDOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KLL, p%nDOFL, p%nDOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, p%nDOFR, p%nDOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGL, p%nDOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, p%nDOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBB, p%DOFR, p%DOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBM, p%DOFR, CBparams%DOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%KBB, p%DOFR, p%DOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiL, p%DOFL, p%DOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%DOFL, p%DOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%OmegaL, p%DOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%TI2, p%DOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( CBparams%MBB, p%nDOFR, p%nDOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, p%nDOFR, CBparams%nDOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, p%nDOFR, p%nDOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%TI2, p%nDOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on @@ -1532,7 +1544,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) ! Set p%TI and CBparams%TI2 - CALL TrnsfTI(Init, m, p%TI, p%DOFI, p%IDI, CBparams%TI2, p%DOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + CALL TrnsfTI(Init, m, p%TI, p%nDOFI, p%IDI, CBparams%TI2, p%nDOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1541,7 +1553,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! CBparams%PhiR from Eq. 3 ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. !................................ - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%DOFM, Init, & ! < inputs + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%nDOFM, Init, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) ! TODO TODO TODO DAMPING MATRIX if(Failed()) return @@ -1555,18 +1567,18 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) ! "b" stands for "bar"; "t" stands for "tilde" - CALL AllocAry( MBBb, p%DOFI, p%DOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MBmb, p%DOFI, CBparams%DOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KBBb, p%DOFI, p%DOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( PhiRb, p%DOFL, p%DOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGRb, p%DOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBBb, p%nDOFI, p%nDOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBmb, p%nDOFI, CBparams%nDOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KBBb, p%nDOFI, p%nDOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( PhiRb, p%nDOFL, p%nDOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGRb, p%nDOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return !................................ ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to ! MBBb, MBMb, KBBb, PHiRb, FGRb ! (throw out rows/columns of first matrices to create second matrices) !................................ - CALL CBApplyConstr(p%DOFI, p%DOFR, CBparams%DOFM, p%DOFL, & + CALL CBApplyConstr(p%nDOFI, p%nDOFR, CBparams%nDOFM, p%nDOFL, & CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) ! TODO TODO TODO Transform new damping matrix as well @@ -1618,42 +1630,42 @@ END SUBROUTINE Craig_Bampton SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT( OUT) :: MRR(p%DOFR, p%DOFR) - REAL(ReKi), INTENT( OUT) :: MLL(p%DOFL, p%DOFL) - REAL(ReKi), INTENT( OUT) :: MRL(p%DOFR, p%DOFL) - REAL(ReKi), INTENT( OUT) :: KRR(p%DOFR, p%DOFR) - REAL(ReKi), INTENT( OUT) :: KLL(p%DOFL, p%DOFL) - REAL(ReKi), INTENT( OUT) :: KRL(p%DOFR, p%DOFL) - REAL(ReKi), INTENT( OUT) :: FGR(p%DOFR) - REAL(ReKi), INTENT( OUT) :: FGL(p%DOFL) + REAL(ReKi), INTENT( OUT) :: MRR(p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT( OUT) :: MLL(p%nDOFL, p%nDOFL) + REAL(ReKi), INTENT( OUT) :: MRL(p%nDOFR, p%nDOFL) + REAL(ReKi), INTENT( OUT) :: KRR(p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT( OUT) :: KLL(p%nDOFL, p%nDOFL) + REAL(ReKi), INTENT( OUT) :: KRL(p%nDOFR, p%nDOFL) + REAL(ReKi), INTENT( OUT) :: FGR(p%nDOFR) + REAL(ReKi), INTENT( OUT) :: FGL(p%nDOFL) ! local variables INTEGER(IntKi) :: I, J, II, JJ !MRR = Init%M(p%IDR,p%IDR) !KRR = Init%K(p%IDR,p%IDR) - DO I = 1, p%DOFR !Boundary DOFs + DO I = 1, p%nDOFR !Boundary DOFs II = p%IDR(I) FGR(I) = Init%FG(II) - DO J = 1, p%DOFR + DO J = 1, p%nDOFR JJ = p%IDR(J) MRR(I, J) = Init%M(II, JJ) KRR(I, J) = Init%K(II, JJ) ENDDO ENDDO - DO I = 1, p%DOFL + DO I = 1, p%nDOFL II = p%IDL(I) FGL(I) = Init%FG(II) - DO J = 1, p%DOFL + DO J = 1, p%nDOFL JJ = p%IDL(J) MLL(I, J) = Init%M(II, JJ) KLL(I, J) = Init%K(II, JJ) ENDDO ENDDO - DO I = 1, p%DOFR + DO I = 1, p%nDOFR II = p%IDR(I) - DO J = 1, p%DOFL + DO J = 1, p%nDOFL JJ = p%IDL(J) MRL(I, J) = Init%M(II, JJ) KRL(I, J) = Init%K(II, JJ) !Note KRL and MRL are getting data from a constraint-applied formatted M and K (i.e. Mbar and Kbar) this may not be legit!! RRD @@ -1669,32 +1681,32 @@ END SUBROUTINE BreakSysMtrx ! PhiR from Eq. 3 ! MBB, MBM, and KBB from Eq. 4. !................................ -SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & +SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) TYPE(SD_InitType), INTENT(IN) :: Init ! TODO remove me TYPE(SD_ParameterType), INTENT(INOUT) :: p ! TODO remove m - INTEGER(IntKi), INTENT( in) :: DOFM - REAL(ReKi), INTENT( IN) :: MRR( p%DOFR, p%DOFR) - REAL(ReKi), INTENT( IN) :: MLL( p%DOFL, p%DOFL) - REAL(ReKi), INTENT( IN) :: MRL( p%DOFR, p%DOFL) - REAL(ReKi), INTENT( IN) :: KRR( p%DOFR, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: KLL( p%DOFL, p%DOFL) ! on exit, it has been factored (otherwise not changed) - REAL(ReKi), INTENT( IN) :: KRL( p%DOFR, p%DOFL) - REAL(ReKi), INTENT(INOUT) :: MBB( p%DOFR, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: MBM( p%DOFR, DOFM) - REAL(ReKi), INTENT(INOUT) :: KBB( p%DOFR, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: PhiR(p%DOFL, p%DOFR) - REAL(ReKi), INTENT(INOUT) :: PhiL(p%DOFL, p%DOFL) !used to be PhiM(DOFL,DOFM), now it is more generic - REAL(ReKi), INTENT(INOUT) :: OmegaL(p%DOFL) !used to be omegaM only ! Eigenvalues + INTEGER(IntKi), INTENT( in) :: nDOFM + REAL(ReKi), INTENT( IN) :: MRR( p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT( IN) :: MLL( p%nDOFL, p%nDOFL) + REAL(ReKi), INTENT( IN) :: MRL( p%nDOFR, p%nDOFL) + REAL(ReKi), INTENT( IN) :: KRR( p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT(INOUT) :: KLL( p%nDOFL, p%nDOFL) ! on exit, it has been factored (otherwise not changed) + REAL(ReKi), INTENT( IN) :: KRL( p%nDOFR, p%nDOFL) + REAL(ReKi), INTENT(INOUT) :: MBB( p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT(INOUT) :: MBM( p%nDOFR, nDOFM) + REAL(ReKi), INTENT(INOUT) :: KBB( p%nDOFR, p%nDOFR) + REAL(ReKi), INTENT(INOUT) :: PhiR(p%nDOFL, p%nDOFR) + REAL(ReKi), INTENT(INOUT) :: PhiL(p%nDOFL, p%nDOFL) !used to be PhiM(nDOFL,nDOFM), now it is more generic + REAL(ReKi), INTENT(INOUT) :: OmegaL(p%nDOFL) !used to be omegaM only ! Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! LOCAL VARIABLES - REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%DOFL, p%DOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%DOFR,p%DOFL) = transpose of PhiR * MLL (temporary storage) + REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%nDOFR,p%nDOFL) = transpose of PhiR * MLL (temporary storage) INTEGER :: I !, lwork !counter, and varibales for inversion routines INTEGER :: DOFvar !placeholder used to get both PhiL or PhiM into 1 process - INTEGER :: ipiv(p%DOFL) !the integer vector ipvt of length min(m,n), containing the pivot indices. + INTEGER :: ipiv(p%nDOFL) !the integer vector ipvt of length min(m,n), containing the pivot indices. !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. INTEGER(IntKi) :: ErrStat2 @@ -1707,22 +1719,22 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & CALL WrScr(' Calculating Internal Modal Eigenvectors') IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT - DOFvar=p%DOFL + DOFvar=p%nDOFL ELSE - DOFvar=DOFM !Initialize for normal cases, dynamic only + DOFvar=nDOFM !Initialize for normal cases, dynamic only ENDIF !.................................................... ! Set OmegaL and PhiL from Eq. 2 !.................................................... IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - CALL EigenSolveWrap(KLL, MLL, p%DOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL ! bjj: break up this equation to avoid as many tenporary variables on the stack ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) - CALL AllocAry( Temp , p%DOFL , p%DOFL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return - CALL AllocAry( MU , p%DOFL , p%DOFL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( Temp , p%nDOFL , p%nDOFL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , p%nDOFL , p%nDOFL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL) Temp = MATMUL( MU, MLL ) MU = MATMUL( Temp, PhiL ) @@ -1731,7 +1743,7 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & DO I = 1, DOFvar PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) ENDDO - DO I=DOFvar+1, p%DOFL !loop done only if .not. p%SttcSolve .and. DOFM < p%DOFL (and actually, in that case, these values aren't used anywhere anyway) + DO I=DOFvar+1, p%nDOFL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) PhiL(:,I) = 0.0_ReKi OmegaL(I) = 0.0_ReKi END DO @@ -1742,12 +1754,12 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & !.................................................... IF (p%SttcSolve) THEN p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement - DO I = 1, p%DOFL + DO I = 1, p%nDOFL p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) ENDDO END IF - ! ELSE .not. p%SttcSolve .and. DOFM < p%DOFL (in this case, PhiL, OmegaL aren't used) + ! ELSE .not. p%SttcSolve .and. nDOFM < p%nDOFL (in this case, PhiL, OmegaL aren't used) END IF @@ -1756,15 +1768,15 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & !.................................................... ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** - CALL LAPACK_getrf( p%DOFL, p%DOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return + CALL LAPACK_getrf( p%nDOFL, p%nDOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N',N=p%DOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return + CALL LAPACK_getrs( TRANS='N',N=p%nDOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return !.................................................... ! Set MBB, MBM, and KBB from Eq. 4: !.................................................... - CALL AllocAry( PhiR_T_MLL, p%DOFR, p%DOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry( PhiR_T_MLL, p%nDOFR, p%nDOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return PhiR_T_MLL = TRANSPOSE(PhiR) PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) @@ -1772,11 +1784,11 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, DOFM, Init, & MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) - IF ( DOFM .EQ. 0) THEN + IF ( nDOFM .EQ. 0) THEN MBM = 0.0_ReKi ELSE - MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:DOFM)) ! last half of operation - MBM = MATMUL( MRL, PhiL(:,1:DOFM) ) + MBM !This had PhiM + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nDOFM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:nDOFM) ) + MBM !This had PhiM ENDIF DEALLOCATE( PhiR_T_MLL ) @@ -1800,15 +1812,15 @@ END SUBROUTINE CBMatrix !------------------------------------------------------------------------------------------------------ !> -SUBROUTINE TrnsfTI(Init, m, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) +SUBROUTINE TrnsfTI(Init, m, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_MiscVarType), INTENT(IN ) :: m - INTEGER(IntKi), INTENT(IN ) :: DOFI ! # of DOFS of interface nodes - INTEGER(IntKi), INTENT(IN ) :: DOFR ! # of DOFS of restrained nodes (restraints and interface) - INTEGER(IntKi), INTENT(IN ) :: IDI(DOFI) - INTEGER(IntKi), INTENT(IN ) :: IDR(DOFR) - REAL(ReKi), INTENT(INOUT) :: TI( DOFI,6) ! matrix TI that relates the reduced matrix to the TP, - REAL(ReKi), INTENT(INOUT) :: TI2(DOFR,6) ! matrix TI2 that relates to (0,0,0) the overall substructure mass + INTEGER(IntKi), INTENT(IN ) :: nDOFI ! # of DOFS of interface nodes + INTEGER(IntKi), INTENT(IN ) :: nDOFR ! # of DOFS of restrained nodes (restraints and interface) + INTEGER(IntKi), INTENT(IN ) :: IDI(nDOFI) + INTEGER(IntKi), INTENT(IN ) :: IDR(nDOFR) + REAL(ReKi), INTENT(INOUT) :: TI( nDOFI,6) ! matrix TI that relates the reduced matrix to the TP, + REAL(ReKi), INTENT(INOUT) :: TI2(nDOFR,6) ! matrix TI2 that relates to (0,0,0) the overall substructure mass INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -1821,7 +1833,7 @@ SUBROUTINE TrnsfTI(Init, m, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) ! --- TI: Transformation matrix from interface points to ref point TI(:,:)=0 - DO I = 1, DOFI + DO I = 1, nDOFI iDOF = IDI(I) ! DOF index in constrained system iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node @@ -1845,7 +1857,7 @@ SUBROUTINE TrnsfTI(Init, m, TI, DOFI, IDI, TI2, DOFR, IDR, ErrStat, ErrMsg) ENDDO ! --- TI2: Transformation matrix from reaction points to origin TI2(:,:) = 0. !Initialize - DO I = 1, DOFR + DO I = 1, nDOFR iDOF = IDR(I) ! DOF index in constrained system iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node @@ -1929,7 +1941,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega=sqrt(Omega2_LaKi(1:NOmega) ) IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: !Need to expand eigenvectors for removed DOFs, setting Phi - CALL InsertDOFrows(EigVect(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL InsertDOFRows(EigVect(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return ELSE Phi=REAL( EigVect(:,1:NOmega), ReKi ) ! eigenvectors ENDIF @@ -1968,7 +1980,7 @@ SUBROUTINE SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = '' - NReactDOFs = p%NReact*6 !p%DOFC + NReactDOFs = p%nNodes_C*6 !p%nDOFC IF (NReactDOFs > nDOF) THEN ErrStat = ErrID_Fatal ErrMsg = 'SelectNonBCConstraintsDOF: invalid matrix sizes.' @@ -2006,10 +2018,10 @@ SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = '' - ALLOCATE(idx(p%NReact*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints + ALLOCATE(idx(p%nNodes_C*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints idx=0 !initialize L=0 !initialize - DO I = 1, p%NReact*6 !Cycle on reaction DOFs + DO I = 1, p%nNodes_C*6 !Cycle on reaction DOFs IF (Init%BCs(I, 2) == 1) THEN idx(I)=Init%BCs(I, 1) !row/col index that was originally eliminated when applying restraints L=L+1 !number of DOFs to eliminate @@ -2029,28 +2041,28 @@ SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) END SUBROUTINE UnReduceVRdofs !------------------------------------------------------------------------------------------------------ -SUBROUTINE CBApplyConstr(DOFI, DOFR, DOFM, DOFL, & +SUBROUTINE CBApplyConstr(nDOFI, nDOFR, nDOFM, nDOFL, & MBB , MBM , KBB , PHiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) - INTEGER(IntKi), INTENT(IN ) :: DOFR, DOFI, DOFM, DOFL - REAL(ReKi), INTENT(IN ) :: FGR(DOFR) - REAL(ReKi), INTENT(IN ) :: MBB(DOFR, DOFR) - REAL(ReKi), INTENT(IN ) :: MBM(DOFR, DOFM) - REAL(ReKi), INTENT(IN ) :: KBB(DOFR, DOFR) - REAL(ReKi), INTENT(IN ) :: PhiR(DOFL, DOFR) - REAL(ReKi), INTENT( OUT) :: MBBb(DOFI, DOFI) - REAL(ReKi), INTENT( OUT) :: KBBb(DOFI, DOFI) - REAL(ReKi), INTENT( OUT) :: MBMb(DOFI, DOFM) - REAL(ReKi), INTENT( OUT) :: FGRb(DOFI) - REAL(ReKi), INTENT( OUT) :: PhiRb(DOFL, DOFI) + INTEGER(IntKi), INTENT(IN ) :: nDOFR, nDOFI, nDOFM, nDOFL + REAL(ReKi), INTENT(IN ) :: FGR(nDOFR) + REAL(ReKi), INTENT(IN ) :: MBB(nDOFR, nDOFR) + REAL(ReKi), INTENT(IN ) :: MBM(nDOFR, nDOFM) + REAL(ReKi), INTENT(IN ) :: KBB(nDOFR, nDOFR) + REAL(ReKi), INTENT(IN ) :: PhiR(nDOFL, nDOFR) + REAL(ReKi), INTENT( OUT) :: MBBb(nDOFI, nDOFI) + REAL(ReKi), INTENT( OUT) :: KBBb(nDOFI, nDOFI) + REAL(ReKi), INTENT( OUT) :: MBMb(nDOFI, nDOFM) + REAL(ReKi), INTENT( OUT) :: FGRb(nDOFI) + REAL(ReKi), INTENT( OUT) :: PhiRb(nDOFL, nDOFI) - MBBb = MBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) - KBBb = KBB(DOFR-DOFI+1:DOFR, DOFR-DOFI+1:DOFR) -IF (DOFM > 0) THEN - MBMb = MBM(DOFR-DOFI+1:DOFR, : ) + MBBb = MBB(nDOFR-nDOFI+1:nDOFR, nDOFR-nDOFI+1:nDOFR) + KBBb = KBB(nDOFR-nDOFI+1:nDOFR, nDOFR-nDOFI+1:nDOFR) +IF (nDOFM > 0) THEN + MBMb = MBM(nDOFR-nDOFI+1:nDOFR, : ) END IF - FGRb = FGR(DOFR-DOFI+1:DOFR ) - PhiRb = PhiR( :, DOFR-DOFI+1:DOFR) + FGRb = FGR(nDOFR-nDOFI+1:nDOFR ) + PhiRb = PhiR( :, nDOFR-nDOFI+1:nDOFR) END SUBROUTINE CBApplyConstr @@ -2058,18 +2070,18 @@ END SUBROUTINE CBApplyConstr SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%DOFI, p%DOFI) - REAL(ReKi), INTENT(IN ) :: MBMb( p%DOFI, p%Nmodes) - REAL(ReKi), INTENT(IN ) :: KBBb( p%DOFI, p%DOFI) - REAL(ReKi), INTENT(IN ) :: PhiL ( p%DOFL, p%DOFL) - REAL(ReKi), INTENT(IN ) :: PhiRb( p%DOFL, p%DOFI) - REAL(ReKi), INTENT(IN ) :: OmegaL(p%DOFL) - REAL(ReKi), INTENT(IN ) :: FGRb(p%DOFI) - REAL(ReKi), INTENT(IN ) :: FGL(p%DOFL) + REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOFI, p%nDOFI) + REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOFI, p%Nmodes) + REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOFI, p%nDOFI) + REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOFL, p%nDOFL) + REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOFL, p%nDOFI) + REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOFL) + REAL(ReKi), INTENT(IN ) :: FGRb(p%nDOFI) + REAL(ReKi), INTENT(IN ) :: FGL(p%nDOFL) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(ReKi) :: TI_transpose(TPdofL,p%DOFI) !bjj: added this so we don't have to take the transpose 5+ times + REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI) !bjj: added this so we don't have to take the transpose 5+ times INTEGER(IntKi) :: I integer(IntKi) :: n ! size of jacobian in AM2 calculation INTEGER(IntKi) :: ErrStat2 @@ -2096,7 +2108,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt !p%D1_15=-TI_transpose !this is 6x6NIN - IF ( p%NModes > 0 ) THEN ! These values don't exist for DOFM=0; i.e., p%NModes == 0 + IF ( p%NModes > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%NModes == 0 ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') @@ -2116,7 +2128,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%FX = MATMUL( FGL, p%PhiM ) != MATMUL( TRANSPOSE(PhiM), FGL ) because FGL is 1-D ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) - DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped + DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=nDOFM == 0), this loop is skipped p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) ENDDO @@ -2140,7 +2152,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! C2_21, C2_42 ! C2_61, C2_62 - DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=DOFM == 0), this loop is skipped + DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=nDOFM == 0), this loop is skipped p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) ENDDO @@ -2205,9 +2217,9 @@ END SUBROUTINE SetParameters !------------------------------------------------------------------------------------------------------ !> Allocate parameter arrays, based on the dimensions already set in the parameter data type. -SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) +SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - INTEGER(IntKi), INTENT( in) :: DOFM + INTEGER(IntKi), INTENT( in) :: nDOFM INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -2219,34 +2231,34 @@ SUBROUTINE AllocParameters(p, DOFM, ErrStat, ErrMsg) ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( p%KBB, TPdofL, TPdofL, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%MBB, TPdofL, TPdofL, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%TI, p%DOFI, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, TPdofL, p%DOFL, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FY, TPdofL, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiRb_TI, p%DOFL, TPdofL, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%TI, p%nDOFI, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOFL, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiRb_TI, p%nDOFL, nDOFL_TP, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') if (p%Nmodes > 0 ) THEN - CALL AllocAry( p%MBM, TPdofL, DOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%MMB, DOFM, TPdofL, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%NOmegaM2, DOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%N2OmegaMJDamp, DOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FX, DOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C1_11, TPdofL, DOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C1_12, TPdofL, DOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiM, p%DOFL, DOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_61, p%DOFL, DOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_62, p%DOFL, DOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_13, TPdofL, TPdofL, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%NModes == 0 - CALL AllocAry( p%D2_63, p%DOFL, TPdofL, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%NModes == 0 - CALL AllocAry( p%D2_64, p%DOFL, p%DOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 - CALL AllocAry( p%F2_61, p%DOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 + CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%NOmegaM2, nDOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%N2OmegaMJDamp, nDOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiM, p%nDOFL, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_61, p%nDOFL, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_62, p%nDOFL, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%NModes == 0 + CALL AllocAry( p%D2_63, p%nDOFL, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%NModes == 0 + CALL AllocAry( p%D2_64, p%nDOFL, p%nDOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 + CALL AllocAry( p%F2_61, p%nDOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 end if if ( p%SttcSolve ) THEN - CALL AllocAry( p%PhiL_T, p%DOFL, p%DOFL, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiLInvOmgL2, p%DOFL, p%DOFL, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FGL, p%DOFL, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiL_T, p%nDOFL, p%nDOFL, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiLInvOmgL2, p%nDOFL, p%nDOFL, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FGL, p%nDOFL, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') end if END SUBROUTINE AllocParameters @@ -2266,13 +2278,22 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) ErrMsg = "" ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( Misc%UFL, p%DOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UFL, p%nDOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar, p%URbarL, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar_dot, p%URbarL, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar_dotdot,p%URbarL, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL, p%DOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dot, p%DOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dotdot, p%DOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL, p%nDOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dot, p%nDOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dotdot, p%nDOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + + call AllocAry( Misc%INodes_Mesh_to_SD, p%nNodes, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + call AllocAry( Misc%INodes_SD_to_Mesh, p%nNodes, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') END SUBROUTINE AllocMiscVars @@ -2302,92 +2323,93 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" ! --- Count nodes per types - p%nNodes_I = p%NInterf ! Number of interface nodes - nNodes_R = p%NReact+p%NInterf ! Number of retained nodes - p%nNodes_L = Init%NNode - nNodes_R ! Number of Interior nodes =(TDOF-DOFC-DOFI)/6 = (6*Init%NNode - (p%NReact+p%nNodes_I)*6 ) / 6 = Init%NNode - p%NReact -p%nNodes_I + p%nNodes_I = p%nNodes_I ! Number of interface nodes + nNodes_R = p%nNodes_C+p%nNodes_I ! Number of retained nodes + p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes =(TDOF-nDOFC-nDOFI)/6 = (6*p%nNodes - (p%nNodes_C+p%nNodes_I)*6 ) / 6 = p%nNodes - p%nNodes_C -p%nNodes_I ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - ! --- Partition Nodes - ! Nodes_L = IAll - NodesR - allocate(INodesAll(1:Init%NNode)); - do iNode=1,Init%NNode + ! --- Partition Nodes: Nodes_L = IAll - NodesR + allocate(INodesAll(1:p%nNodes)); + do iNode=1,p%nNodes INodesAll(iNode)=iNode enddo - call concatenate_lists(p%Reacts(:,1), p%Interf(:,1), Nodes_R, ErrStat2, ErrMsg2); if(Failed()) return + ! Nodes_R = [Nodes_C Nodes_I] + call concatenate_lists(p%Nodes_C(:,1), p%Nodes_I(:,1), Nodes_R, ErrStat2, ErrMsg2); if(Failed()) return + ! Nodes_L = IAll - Nodes_R call lists_difference(INodesAll, Nodes_R, p%Nodes_L(:,1), ErrStat2, ErrMsg2); if(Failed()) return ! --- Count DOFs ! Interface DOFS - p%DOFI =0 - do iiNode= 1,p%NInterf - p%DOFI = p%DOFI + len(m%NodesDOFtilde( p%Interf(iiNode,1) )) + p%nDOFI =0 + do iiNode= 1,p%nNodes_I + p%nDOFI = p%nDOFI + len(m%NodesDOFtilde( p%Nodes_I(iiNode,1) )) enddo ! Reaction DOFs - do iiNode= 1,p%NReact - p%DOFC = p%DOFC + len(m%NodesDOFtilde( p%Reacts(iiNode,1) )) + do iiNode= 1,p%nNodes_C + p%nDOFC = p%nDOFC + len(m%NodesDOFtilde( p%Nodes_C(iiNode,1) )) enddo - p%DOFR = p%DOFC + p%DOFI - p%DOFL = Init%nDOFRed - p%DOFR ! TODO + p%nDOFR = p%nDOFC + p%nDOFI + p%nDOFL = p%nDOF_red - p%nDOFR ! TODO ! --- Safety checks - if (p%DOFC /= p%NReact*6) then + if (p%nDOFC /= p%nNodes_C*6) then call Fatal('Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'); return endif - if (p%DOFI /= p%nNodes_I*6) then + if (p%nDOFI /= p%nNodes_I*6) then call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'); return endif ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. - CALL AllocAry( p%IDI, p%DOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDC, p%DOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDR, p%DOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDL, p%DOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDY, p%DOFC+p%DOFI+p%DOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDI, p%nDOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDC, p%nDOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDR, p%nDOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDL, p%nDOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%IDY, p%nDOFC+p%nDOFI+p%nDOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') if(Failed()) return ! Indices IDI for interface DOFs - p%IDI = Init%IntFc(1:p%DOFI, 1) ! Interface DOFs (indices updated after DirectElimination) + p%IDI = Init%IntFc(1:p%nDOFI, 1) ! Interface DOFs (indices updated after DirectElimination) ! Indices IDC for constraint DOFs - p%IDC = Init%BCs(1:p%DOFC, 1) ! Reaction DOFs (indices updated after DirectElimination) + p%IDC = Init%BCs(1:p%nDOFC, 1) ! Reaction DOFs (indices updated after DirectElimination) ! Indices IDR = [IDC, IDI], "retained interface DOFS" call concatenate_lists(p%IDC, p%IDI, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return ! --- Indices IDL for internal DOFs = AllDOF - IDR - ! First set the all DOFs indices IDT = 1:nDOFRed - allocate(IDT(1:Init%nDOFRed)) - DO I = 1, Init%nDOFRed; IDT(I) = I; ENDDO + ! First set the all DOFs indices IDT = 1:nnDOFRed + allocate(IDT(1:p%nDOF_red)) + DO I = 1, p%nDOF_red; IDT(I) = I; ENDDO call lists_difference(IDT, p%IDR, p%IDL, ErrStat2, ErrMsg2); if(Failed()) return ! --- Index [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] ! set the second column of the temp array - allocate(TempIDY(p%DOFI+p%DOFL+p%DOFC, 2)) - print*,SIZE(TempIDY),Init%nDOFRed + allocate(TempIDY(p%nDOFI+p%nDOFL+p%nDOFC, 2)) + print*,SIZE(TempIDY),p%nDOF_red DO I = 1, SIZE(TempIDY,1) TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) ENDDO ! set the first column of the temp array - TempIDY(1:p%DOFI, 1) = p%IDI - TempIDY(p%DOFI+1 : p%DOFI+p%DOFL, 1) = p%IDL - TempIDY(p%DOFI+p%DOFL+1: p%DOFI+p%DOFL+p%DOFC, 1) = p%IDC + TempIDY(1:p%nDOFI, 1) = p%IDI + TempIDY(p%nDOFI+1 : p%nDOFI+p%nDOFL, 1) = p%IDL + TempIDY(p%nDOFI+p%nDOFL+1: p%nDOFI+p%nDOFL+p%nDOFC, 1) = p%IDC CALL QsortC( TempIDY ) ! sort based on the first column p%IDY = TempIDY(:, 2) ! the second column is the key: ! call CleanUp() - print*,'Nodes_I',p%Interf(:,1) - print*,'Nodes_C',p%Reacts(:,1) + print*,'Nodes_I',p%Nodes_I(:,1) + print*,'Nodes_C',p%Nodes_C(:,1) print*,'Nodes_L',p%Nodes_L - print*,'Number of DOFs: "interface" (I)',p%DOFI - print*,'Number of DOFs: "reactions" (C)',p%DOFC - print*,'Number of DOFs: interface (R)',p%DOFR - print*,'Number of DOFs: internal (L)',p%DOFL - print*,'Number of DOFs: total (R+L)',Init%nDOFRed + print*,'Number of DOFs: "interface" (I)',p%nDOFI + print*,'Number of DOFs: "reactions" (C)',p%nDOFC + print*,'Number of DOFs: interface (R)',p%nDOFR + print*,'Number of DOFs: internal (L)',p%nDOFL + print*,'Number of DOFs: total (R+L)',p%nDOF_red print*,'Number of Nodes: "interface" (I)',p%nNodes_I - print*,'Number of Nodes: "reactions" (C)',p%NReact + print*,'Number of Nodes: "reactions" (C)',p%nNodes_C print*,'Number of Nodes: internal (L)',p%nNodes_L - print*,'Number of Nodes: total (R+L)',Init%NNode + print*,'Number of Nodes: total (R+L)',p%nNodes contains LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') @@ -2415,7 +2437,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%DOFL) + real(ReKi) , intent(out) :: UFL(p%nDOFL) integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes integer :: nMembers real(ReKi), parameter :: myNaN = -9999998.989_ReKi @@ -2425,7 +2447,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) m%Fext= myNaN DO iMeshNode = 1,size(m%INodes_Mesh_to_SD) iSDNode = m%INodes_Mesh_to_SD(iMeshNode) - nMembers = (size(m%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's DOFlist + nMembers = (size(m%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs m%Fext( m%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs @@ -2439,11 +2461,11 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) STOP endif ! --- Reduced vector of external force - m%Fext_red = matmul(transpose(m%Tred), m%Fext) + m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL=0 UFL= m%Fext_red(p%IDL) -END SUBROUTINE +END SUBROUTINE ConstructUFL !------------------------------------------------------------------------------------------------------ !> Output the summary file @@ -2493,12 +2515,12 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',Init%NNode + WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',p%nNodes WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') '--------', '-----------', '---------------', '---------------', '---------------' -! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, Init%NNode) !do not group the format or it won't work 3(E15.6) does not work !bjj??? - WRITE(UnSum, '('//Num2LStr(Init%NNode)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & - (NINT(Init%Nodes(i, 1)), SDtoMeshIndx(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, Init%NNode) +! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) !do not group the format or it won't work 3(E15.6) does not work !bjj??? + WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & + (NINT(Init%Nodes(i, 1)), SDtoMeshIndx(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem @@ -2511,14 +2533,14 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%NReact*6 + WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%nNodes_C*6 WRITE(UnSum, '(A, A6)') 'Reaction DOF_ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%NReact*6)! TODO TODO TODO might have been updated + WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%nNodes_C*6)! TODO TODO TODO might have been updated WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%DOFI + WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%nDOFI WRITE(UnSum, '(A,A6)') 'Interface DOF ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%DOFI) ! TODO TODO TODO might have been updated + WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%nDOFI) ! TODO TODO TODO might have been updated WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of concentrated masses (NCMass):',Init%NCMass @@ -2560,7 +2582,7 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) !The alternative would be to get an element that belongs to the member and use it with dircos !BJJ:TODO: DIDN'T we already calculate DirCos for each element? can't we use that here? - DO j=1,Init%NNode + DO j=1,p%nNodes IF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,2) )THEN XYZ1=Init%Nodes(Init%Members(i,2),2:4) ELSEIF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,3) ) THEN @@ -2582,17 +2604,17 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(I6, e15.6)') ( i, FEMparams%Omega(i)/2.0/pi, i = 1, FEMparams%NOmega ) WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", CBparams%DOFM - WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, CBparams%DOFM ) + WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", CBparams%nDOFM + WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, CBparams%nDOFM ) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full SYstem !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(Init%TDOF))//' x '//TRIM(Num2LStr(FEMparams%NOmega))//& + WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF))//' x '//TRIM(Num2LStr(FEMparams%NOmega))//& ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), FEMparams%NOmega WRITE(UnSum, '(6x,'//Num2LStr(FEMparams%NOmega)//'(I15))') (i, i = 1, FEMparams%NOmega )!HEADERS - WRITE(UnSum, '(I6,'//Num2LStr(FEMparams%NOmega)//'e15.6)') ( i, (FEMparams%Modes(i,j), j = 1, FEMparams%NOmega ),i = 1, Init%TDOF) + WRITE(UnSum, '(I6,'//Num2LStr(FEMparams%NOmega)//'e15.6)') ( i, (FEMparams%Modes(i,j), j = 1, FEMparams%NOmega ),i = 1, p%nDOF) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices @@ -2601,10 +2623,10 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (no constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide - IF (CBparams%DOFM > 0) THEN - CALL WrMatrix( CBparams%PhiL(:,1:CBparams%DOFM ), UnSum, 'e15.6', 'PhiM' ) + IF (CBparams%nDOFM > 0) THEN + CALL WrMatrix( CBparams%PhiL(:,1:CBparams%nDOFM ), UnSum, 'e15.6', 'PhiM' ) ELSE - WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%DOFL)), '0' + WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%nDOFL)), '0' END IF WRITE(UnSum, '(A)') SubSectionDivide @@ -2653,18 +2675,18 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) ! write assembed K M to a txt file !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') 'FULL FEM K and M matrices. TOTAL FEM TDOFs:', Init%TDOF + WRITE(UnSum, '(A, I6)') 'FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF WRITE(UnSum, '(A)') ('Stiffness matrix K' ) - WRITE(UnSum, '(15x,'//TRIM(Num2LStr(Init%TDOF))//'(I15))') (i, i = 1, Init%TDOF ) - DO i=1,Init%TDOF - WRITE(UnSum, '(I15, '//TRIM(Num2LStr(Init%TDOF))//'(e15.6))') i, (Init%K(i, j), j = 1, Init%TDOF) + WRITE(UnSum, '(15x,'//TRIM(Num2LStr(p%nDOF))//'(I15))') (i, i = 1, p%nDOF ) + DO i=1,p%nDOF + WRITE(UnSum, '(I15, '//TRIM(Num2LStr(p%nDOF))//'(e15.6))') i, (Init%K(i, j), j = 1, p%nDOF) ENDDO WRITE(UnSum, '(A)') SubSectionDivide WRITE(UnSum, '(A)') ('Mass matrix M' ) - WRITE(UnSum, '(15x,'//TRIM(Num2LStr(Init%TDOF))//'(I15))') (i, i = 1, Init%TDOF ) - DO i=1,Init%TDOF - WRITE(UnSum, '(I15, '//TRIM(Num2LStr(Init%TDOF))//'(e15.6))') i, (Init%M(i, j), j = 1, Init%TDOF) + WRITE(UnSum, '(15x,'//TRIM(Num2LStr(p%nDOF))//'(I15))') (i, i = 1, p%nDOF ) + DO i=1,p%nDOF + WRITE(UnSum, '(I15, '//TRIM(Num2LStr(p%nDOF))//'(e15.6))') i, (Init%M(i, j), j = 1, p%nDOF) ENDDO !------------------------------------------------------------------------------------------------------------- @@ -2672,7 +2694,7 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') 'Gravity force vector FG applied at each node of the full system' - WRITE(UnSum, '(I6, e15.6)') (i, Init%FG(i), i = 1, Init%TDOF) + WRITE(UnSum, '(I6, e15.6)') (i, Init%FG(i), i = 1, p%nDOF) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices @@ -2684,7 +2706,7 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) CALL WrMatrix( CBparams%MBB, UnSum, 'e15.6', 'MBB' ) WRITE(UnSum, '(A)') SubSectionDivide - IF ( CBparams%DOFM > 0 ) THEN + IF ( CBparams%nDOFM > 0 ) THEN CALL WrMatrix( CBparams%MBM, UnSum, 'e15.6', 'MBM' ) ELSE WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "MBM", '6', '0' @@ -2721,9 +2743,9 @@ SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) INTEGER(IntKi) :: y2Node y2Node = 0 ! Interface nodes (IDI) - DO I = 1,SIZE(p%Interf,1) + DO I = 1,SIZE(p%Nodes_I,1) y2Node = y2Node + 1 - SDnode = p%Interf(I,1) + SDnode = p%Nodes_I(I,1) SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO ! Interior nodes (IDL) @@ -2733,9 +2755,9 @@ SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO ! Base Reaction nodes (IDC) - DO I = 1,SIZE(p%Reacts,1) + DO I = 1,SIZE(p%Nodes_C,1) y2Node = y2Node + 1 - SDnode = p%Reacts(I,1) + SDnode = p%Nodes_C(I,1) SDtoMesh( SDnode ) = y2Node ! TODO add safety check END DO END SUBROUTINE SD_Y2Mesh_Mapping @@ -2743,9 +2765,9 @@ END SUBROUTINE SD_Y2Mesh_Mapping SUBROUTINE Y2Mesh_SD_Mapping(p, MeshtoSD) TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters INTEGER(IntKi), INTENT( OUT) :: MeshtoSD(:) !< index/mapping of mesh nodes with SD mesh - MeshtoSD( 1:p%nNodes_I) = p%Interf(:,1) + MeshtoSD( 1:p%nNodes_I) = p%Nodes_I(:,1) MeshtoSD(p%nNodes_I+ 1:p%nNodes_I+p%nNodes_L) = p%Nodes_L(:,1) - MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nReact) = p%Reacts(:,1) + MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nNodes_C) = p%Nodes_C(:,1) END SUBROUTINE Y2Mesh_SD_Mapping !------------------------------------------------------------------------------------------------------ diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index d6d7c5afe..fa3cdf9a0 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -187,13 +187,13 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being - ALLOCATE ( p%MOutLst3(p%NReact), STAT = ErrStat2) !this list contains different arrays for each of its elements + ALLOCATE ( p%MOutLst3(p%nNodes_C), STAT = ErrStat2) !this list contains different arrays for each of its elements ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init' if(Failed()) return - DO I=1,p%NReact !For all constrained node + DO I=1,p%nNodes_C !For all constrained node pLst => p%MOutLst3(I) - pLst%Noutcnt=p%Reacts(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array + pLst%Noutcnt=p%Nodes_C(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array NconEls=Init%NodesConnE(pLst%Noutcnt,1) !Number of elements connecting to the joint ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other MOutLst ! Me: has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) @@ -258,7 +258,7 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) ErrStat=ErrID_None ErrMsg="" - DOFC = p%NReact*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure + DOFC = p%nNodes_C*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure CALL AllocAry(p%TIreact, 6, DOFC, 'p%TIReact', ErrStat, ErrMsg ) if ( ErrStat /= ErrID_None ) return @@ -271,7 +271,7 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) !Other rows done per column actually DO I = 1, DOFC - nodeID = p%Reacts(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Reacts) + nodeID = p%Nodes_C(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Nodes_C) x = Init%Nodes(nodeID, 2) y = Init%Nodes(nodeID, 3) @@ -321,8 +321,8 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL - Real(ReKi), DIMENSION( p%URbarL+p%DOFL+6*p%Nreact) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs - Real(ReKi), DIMENSION(p%URbarL+p%DOFL+6*p%Nreact) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs + Real(ReKi), DIMENSION(p%URbarL+p%nDOFL+6*p%nNodes_C) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs + Real(ReKi), DIMENSION(p%URbarL+p%nDOFL+6*p%nNodes_C) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs Integer(IntKi) ::sgn !+1/-1 for node force calculations type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities ErrStat = ErrID_None @@ -332,13 +332,13 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array yout =0 !Initialize and populate with Y2 data - yout(1: p%UrbarL ) = m%UR_bar - yout(p%URbarL+1:p%URbarL+p%DOFL) = m%UL + yout(1: p%UrbarL ) = m%UR_bar + yout(p%URbarL+1:p%URbarL+p%nDOFL) = m%UL !Same for a variable that deals with Udotdot uddout =0 !Initialize and populate with Udotdot data - uddout(1 : p%URbarL ) = m%UR_bar_dotdot - uddout(p%URbarL+1 : p%URbarL+p%DOFL ) = m%UL_dotdot + uddout(1 : p%URbarL ) = m%UR_bar_dotdot + uddout(p%URbarL+1 : p%URbarL+p%nDOFL ) = m%UL_dotdot ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency @@ -434,11 +434,11 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ENDIF !Assign interface forces and moments - AllOuts(IntfSS(1:TPdofL))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign + AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign !Assign interface translations and rotations at the TP ref point - AllOuts(IntfTRss(1:TPdofL))=m%u_TP + AllOuts(IntfTRss(1:nDOFL_TP))=m%u_TP !Assign interface translations and rotations accelerations - AllOuts(IntfTRAss(1:TPdofL))= m%udotdot_TP + AllOuts(IntfTRAss(1:nDOFL_TP))= m%udotdot_TP ! Assign all SSqm, SSqmdot, SSqmdotdot ! We only have space for the first 99 values @@ -453,7 +453,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Need to Calculate Reaction Forces Now, but only if requested IF (p%OutReact) THEN - ALLOCATE ( ReactNs(6*p%NReact), STAT = ErrStat ) + ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating space for ReactNs array.' ErrStat = ErrID_Fatal @@ -462,7 +462,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ReactNs = 0.0 !Initialize - DO I=1,p%NReact !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh + DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh FK_elm2=0. !Initialize for cumulative force FM_elm2=0. !Initialize pLst => p%MOutLst3(I) @@ -492,7 +492,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ! TODO TODO TODO assumed DOF order maybe ENDDO ! Store into AllOuts - AllOuts( ReactSS(1:TPdofL) ) = matmul(p%TIreact,ReactNs) + AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) ENDIF if (allocated(ReactNs)) deallocate(ReactNs) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index f7230fd6e..accb3b486 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -38,14 +38,14 @@ typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connect typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" # CB_MatArrays: Matrices and arrays for CB summary -typedef SubDyn/SD CB_MatArrays INTEGER DOFM - - - "retained degrees of freedom (modes)" +typedef SubDyn/SD CB_MatArrays INTEGER nDOFM - - - "retained degrees of freedom (modes)" typedef ^ CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(DOFL,DOFL), or PhiL(DOFL,DOFM)" +typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" -typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (DOFL or DOFM)" +typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" # FEM_MatArrays: Matrices and arrays for FEM summary typedef SubDyn/SD FEM_MatArrays ReKi Omega {:} - - "Eigenvalues of full FEM model, we calculate them all" typedef ^ FEM_MatArrays INTEGER NOmega - - - "Number of full FEM Eigenvalues (for now TDOF-6*Nreact)" @@ -96,13 +96,10 @@ typedef ^ ^ CHARACTER(10) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -typedef ^ ^ INTEGER NNode - - - "Total number of nodes" typedef ^ ^ INTEGER NElem - - - "Total number of elements" typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" -typedef ^ ^ INTEGER TDOF - - - "Total degree of freedom" -typedef ^ ^ INTEGER nDOFRed - - - "Total degree of freedom after constraint reduction" typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" @@ -148,6 +145,12 @@ typedef ^ ^ ReKi UR_bar_dotdot {:} typedef ^ ^ ReKi UL {:} - - typedef ^ ^ ReKi UL_dot {:} - - typedef ^ ^ ReKi UL_dotdot {:} - - +typedef ^ ^ ReKi U_full {:} - - +typedef ^ ^ ReKi U_full_dot {:} - - +typedef ^ ^ ReKi U_full_dotdot {:} - - +typedef ^ ^ ReKi U_red {:} - - +typedef ^ ^ ReKi U_red_dot {:} - - +typedef ^ ^ ReKi U_red_dotdot {:} - - ### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" @@ -158,15 +161,27 @@ typedef ^ ^ IntKi INodes_Mesh_to_SD {:} typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" -typedef ^ ^ ReKi Tred {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" # ============================== Parameters ============================================================================================================================================ +# --- Algo typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds +typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" +# --- FEM +typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" +typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" +typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" +typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" +typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +# --- Constraints reduction +typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +# --- CB reduction typedef ^ ParameterType Logical SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B method" +typedef ^ ParameterType IntKi qmL - - - "Length of state array" typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" @@ -188,35 +203,31 @@ typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" -typedef ^ ParameterType ReKi FGL {:} - - "Internal node DOFL, gravity loads" typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" -typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B method" -typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" -typedef ^ ParameterType IntKi qmL - - - "Length of state array" -typedef ^ ParameterType IntKi DofL - - - "Internal nodes # of DOFs" -typedef ^ ParameterType IntKi DofI - - - "Interface nodes # of DOFs" -typedef ^ ParameterType IntKi DofR - - - "Interface and restrained nodes # of DOFs" -typedef ^ ParameterType IntKi DofC - - - "Contrained nodes # of DOFs" -typedef ^ ParameterType IntKi nNodes_RbarL - - - "Number of Interface + Internal nodes" +# --- Partitioning I L C Y, R=[C I] +typedef ^ ParameterType IntKi nNodes - - - "Total number of nodes" +typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" +typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" -typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" -typedef ^ ParameterType IntKi NInterf - - - "Number of joints attached to transition piece" -typedef ^ ParameterType IntKi Interf {:}{:} - - "Interface degree of freedoms" -typedef ^ ParameterType IntKi NReact - - - "Number of joints with reactions" -typedef ^ ParameterType IntKi Reacts {:}{:} - - "React degree of freedoms" -typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" -typedef ^ ParameterType IntKi URbarL - - - "Length of URbar, subarray of y2 array (DOFRb)" -typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" -typedef ^ ParameterType IntKi NAvgEls - 2 - "Max number of elements that should be averaged when calculating outputs at nodes" +typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" +typedef ^ ParameterType IntKi nDOFI - - - "Interface nodes # of DOFs" +typedef ^ ParameterType IntKi nDOFL - - - "Internal nodes # of DOFs" +typedef ^ ParameterType IntKi nDOFC - - - "Contrained nodes # of DOFs" +typedef ^ ParameterType IntKi nDOFR - - - "Interface and restrained nodes # of DOFs" typedef ^ ParameterType IntKi IDI {:} - - "Index array of the interface(nodes connect to TP) dofs" -typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and restraint dofs" typedef ^ ParameterType IntKi IDL {:} - - "Index array of the internal dofs" typedef ^ ParameterType IntKi IDC {:} - - "Index array of the contraint dofs" +typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and restraint dofs" typedef ^ ParameterType IntKi IDY {:} - - "Index array of the all dofs in Y2" +typedef ^ ParameterType IntKi URbarL - - - "Length of URbar, subarray of y2 array (DOFRb)" +typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" +# --- Outputs +typedef ^ ParameterType IntKi NAvgEls - 2 - "Max number of elements that should be averaged when calculating outputs at nodes" typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" @@ -227,7 +238,6 @@ typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" -typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 64566097d..705a03b4d 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -70,14 +70,14 @@ MODULE SubDyn_Types ! ======================= ! ========= CB_MatArrays ======= TYPE, PUBLIC :: CB_MatArrays - INTEGER(IntKi) :: DOFM !< retained degrees of freedom (modes) [-] + INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI2 !< TI2 matrix to refer to total mass to (0,0,0) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(DOFL,DOFL), or PhiL(DOFL,DOFM) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (DOFL or DOFM) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] END TYPE CB_MatArrays ! ======================= ! ========= FEM_MatArrays ======= @@ -133,13 +133,10 @@ MODULE SubDyn_Types CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] - INTEGER(IntKi) :: NNode !< Total number of nodes [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] - INTEGER(IntKi) :: TDOF !< Total degree of freedom [-] - INTEGER(IntKi) :: nDOFRed !< Total degree of freedom after constraint reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] @@ -193,6 +190,12 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] @@ -202,7 +205,6 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Tred !< Transformation matrix performing the constraint reduction x = T. xtilde [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads on unconstrained DOFs [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext_red !< External loads on constrained DOFs, Fext_red= T^t Fext [-] END TYPE SD_MiscVarType @@ -210,7 +212,16 @@ MODULE SubDyn_Types ! ========= SD_ParameterType ======= TYPE, PUBLIC :: SD_ParameterType REAL(DbKi) :: SDDeltaT !< Time step (for integration of continuous states) [seconds] + INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] + INTEGER(IntKi) :: nDOF !< Total degree of freedom [-] + INTEGER(IntKi) :: nDOF_red !< Total degree of freedom after constraint reduction [-] + INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] + TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] LOGICAL :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] + INTEGER(IntKi) :: NModes !< Number of modes to retain in C-B method [-] + INTEGER(IntKi) :: qmL !< Length of state array [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -232,35 +243,29 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node DOFL, gravity loads [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AM2Jac !< Jacobian (factored) for Adams-Boulton 2nd order Integration [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AM2JacPiv !< Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI !< Matrix to calculate TP reference point reaction at top of structure [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIreact !< Matrix to calculate single point reaction at base of structure [-] - INTEGER(IntKi) :: NModes !< Number of modes to retain in C-B method [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] - INTEGER(IntKi) :: qmL !< Length of state array [-] - INTEGER(IntKi) :: DofL !< Internal nodes of DOFs [-] - INTEGER(IntKi) :: DofI !< Interface nodes of DOFs [-] - INTEGER(IntKi) :: DofR !< Interface and restrained nodes of DOFs [-] - INTEGER(IntKi) :: DofC !< Contrained nodes of DOFs [-] - INTEGER(IntKi) :: nNodes_RbarL !< Number of Interface + Internal nodes [-] + INTEGER(IntKi) :: nNodes !< Total number of nodes [-] + INTEGER(IntKi) :: nNodes_I !< Number of Interface nodes [-] INTEGER(IntKi) :: nNodes_L !< Number of Internal nodes [-] + INTEGER(IntKi) :: nNodes_C !< Number of joints with reactions [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_I !< Interface degree of freedoms [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] - INTEGER(IntKi) :: nNodes_I !< Number of Interface nodes [-] - INTEGER(IntKi) :: NInterf !< Number of joints attached to transition piece [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Interf !< Interface degree of freedoms [-] - INTEGER(IntKi) :: NReact !< Number of joints with reactions [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Reacts !< React degree of freedoms [-] - INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] - INTEGER(IntKi) :: URbarL !< Length of URbar, subarray of y2 array (DOFRb) [-] - INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] - INTEGER(IntKi) :: NAvgEls = 2 !< Max number of elements that should be averaged when calculating outputs at nodes [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_C !< React degree of freedoms [-] + INTEGER(IntKi) :: nDOFI !< Interface nodes of DOFs [-] + INTEGER(IntKi) :: nDOFL !< Internal nodes of DOFs [-] + INTEGER(IntKi) :: nDOFC !< Contrained nodes of DOFs [-] + INTEGER(IntKi) :: nDOFR !< Interface and restrained nodes of DOFs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI !< Index array of the interface(nodes connect to TP) dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL !< Index array of the internal dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC !< Index array of the contraint dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDY !< Index array of the all dofs in Y2 [-] + INTEGER(IntKi) :: URbarL !< Length of URbar, subarray of y2 array (DOFRb) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] + INTEGER(IntKi) :: NAvgEls = 2 !< Max number of elements that should be averaged when calculating outputs at nodes [-] INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] @@ -271,7 +276,6 @@ MODULE SubDyn_Types TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst !< List of user requested members and nodes [-] TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst2 !< List of all member joint nodes and elements for output [-] TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst3 !< List of all member joint nodes and elements for output [-] - TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< An array holding names, units, and indices of all of the selected output channels. logical [-] LOGICAL :: OutAll !< Flag to output or not all joint forces [-] LOGICAL :: OutReact !< Flag to check whether reactions are requested [-] @@ -1641,7 +1645,7 @@ SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCo ! ErrStat = ErrID_None ErrMsg = "" - DstCB_MatArraysData%DOFM = SrcCB_MatArraysData%DOFM + DstCB_MatArraysData%nDOFM = SrcCB_MatArraysData%nDOFM IF (ALLOCATED(SrcCB_MatArraysData%TI2)) THEN i1_l = LBOUND(SrcCB_MatArraysData%TI2,1) i1_u = UBOUND(SrcCB_MatArraysData%TI2,1) @@ -1807,7 +1811,7 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! DOFM + Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! TI2 allocated yes/no IF ( ALLOCATED(InData%TI2) ) THEN Int_BufSz = Int_BufSz + 2*2 ! TI2 upper/lower bounds for each dimension @@ -1870,7 +1874,7 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DOFM + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%TI2) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2017,7 +2021,7 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%DOFM = IntKiBuf( Int_Xferred ) + OutData%nDOFM = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI2 not allocated Int_Xferred = Int_Xferred + 1 @@ -2842,13 +2846,10 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ENDIF DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim - DstInitTypeData%NNode = SrcInitTypeData%NNode DstInitTypeData%NElem = SrcInitTypeData%NElem DstInitTypeData%NPropB = SrcInitTypeData%NPropB DstInitTypeData%NPropC = SrcInitTypeData%NPropC DstInitTypeData%NPropR = SrcInitTypeData%NPropR - DstInitTypeData%TDOF = SrcInitTypeData%TDOF - DstInitTypeData%nDOFRed = SrcInitTypeData%nDOFRed IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN i1_l = LBOUND(SrcInitTypeData%Nodes,1) i1_u = UBOUND(SrcInitTypeData%Nodes,1) @@ -3246,13 +3247,10 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END IF Int_BufSz = Int_BufSz + 1 ! OutCOSM Int_BufSz = Int_BufSz + 1 ! TabDelim - Int_BufSz = Int_BufSz + 1 ! NNode Int_BufSz = Int_BufSz + 1 ! NElem Int_BufSz = Int_BufSz + 1 ! NPropB Int_BufSz = Int_BufSz + 1 ! NPropC Int_BufSz = Int_BufSz + 1 ! NPropR - Int_BufSz = Int_BufSz + 1 ! TDOF - Int_BufSz = Int_BufSz + 1 ! nDOFRed Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no IF ( ALLOCATED(InData%Nodes) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension @@ -3550,8 +3548,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNode - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB @@ -3560,10 +3556,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropR Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%TDOF - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFRed - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4139,8 +4131,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 - OutData%NNode = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 OutData%NElem = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NPropB = IntKiBuf( Int_Xferred ) @@ -4149,10 +4139,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%NPropR = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%TDOF = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFRed = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -5433,6 +5419,78 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%UL_dotdot = SrcMiscData%UL_dotdot ENDIF +IF (ALLOCATED(SrcMiscData%U_full)) THEN + i1_l = LBOUND(SrcMiscData%U_full,1) + i1_u = UBOUND(SrcMiscData%U_full,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full)) THEN + ALLOCATE(DstMiscData%U_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full = SrcMiscData%U_full +ENDIF +IF (ALLOCATED(SrcMiscData%U_full_dot)) THEN + i1_l = LBOUND(SrcMiscData%U_full_dot,1) + i1_u = UBOUND(SrcMiscData%U_full_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_dot)) THEN + ALLOCATE(DstMiscData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_dot = SrcMiscData%U_full_dot +ENDIF +IF (ALLOCATED(SrcMiscData%U_full_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%U_full_dotdot,1) + i1_u = UBOUND(SrcMiscData%U_full_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_dotdot)) THEN + ALLOCATE(DstMiscData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_dotdot = SrcMiscData%U_full_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%U_red)) THEN + i1_l = LBOUND(SrcMiscData%U_red,1) + i1_u = UBOUND(SrcMiscData%U_red,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red)) THEN + ALLOCATE(DstMiscData%U_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red = SrcMiscData%U_red +ENDIF +IF (ALLOCATED(SrcMiscData%U_red_dot)) THEN + i1_l = LBOUND(SrcMiscData%U_red_dot,1) + i1_u = UBOUND(SrcMiscData%U_red_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red_dot)) THEN + ALLOCATE(DstMiscData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red_dot = SrcMiscData%U_red_dot +ENDIF +IF (ALLOCATED(SrcMiscData%U_red_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%U_red_dotdot,1) + i1_u = UBOUND(SrcMiscData%U_red_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red_dotdot)) THEN + ALLOCATE(DstMiscData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot +ENDIF IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN i1_l = LBOUND(SrcMiscData%SDWrOutput,1) i1_u = UBOUND(SrcMiscData%SDWrOutput,1) @@ -5531,20 +5589,6 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%DOFtilde2Nodes = SrcMiscData%DOFtilde2Nodes ENDIF -IF (ALLOCATED(SrcMiscData%Tred)) THEN - i1_l = LBOUND(SrcMiscData%Tred,1) - i1_u = UBOUND(SrcMiscData%Tred,1) - i2_l = LBOUND(SrcMiscData%Tred,2) - i2_u = UBOUND(SrcMiscData%Tred,2) - IF (.NOT. ALLOCATED(DstMiscData%Tred)) THEN - ALLOCATE(DstMiscData%Tred(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Tred.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%Tred = SrcMiscData%Tred -ENDIF IF (ALLOCATED(SrcMiscData%Fext)) THEN i1_l = LBOUND(SrcMiscData%Fext,1) i1_u = UBOUND(SrcMiscData%Fext,1) @@ -5604,6 +5648,24 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%UL_dotdot)) THEN DEALLOCATE(MiscData%UL_dotdot) ENDIF +IF (ALLOCATED(MiscData%U_full)) THEN + DEALLOCATE(MiscData%U_full) +ENDIF +IF (ALLOCATED(MiscData%U_full_dot)) THEN + DEALLOCATE(MiscData%U_full_dot) +ENDIF +IF (ALLOCATED(MiscData%U_full_dotdot)) THEN + DEALLOCATE(MiscData%U_full_dotdot) +ENDIF +IF (ALLOCATED(MiscData%U_red)) THEN + DEALLOCATE(MiscData%U_red) +ENDIF +IF (ALLOCATED(MiscData%U_red_dot)) THEN + DEALLOCATE(MiscData%U_red_dot) +ENDIF +IF (ALLOCATED(MiscData%U_red_dotdot)) THEN + DEALLOCATE(MiscData%U_red_dotdot) +ENDIF IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) ENDIF @@ -5631,9 +5693,6 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%DOFtilde2Nodes)) THEN DEALLOCATE(MiscData%DOFtilde2Nodes) ENDIF -IF (ALLOCATED(MiscData%Tred)) THEN - DEALLOCATE(MiscData%Tred) -ENDIF IF (ALLOCATED(MiscData%Fext)) THEN DEALLOCATE(MiscData%Fext) ENDIF @@ -5720,6 +5779,36 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! UL_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%UL_dotdot) ! UL_dotdot END IF + Int_BufSz = Int_BufSz + 1 ! U_full allocated yes/no + IF ( ALLOCATED(InData%U_full) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full) ! U_full + END IF + Int_BufSz = Int_BufSz + 1 ! U_full_dot allocated yes/no + IF ( ALLOCATED(InData%U_full_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_dot) ! U_full_dot + END IF + Int_BufSz = Int_BufSz + 1 ! U_full_dotdot allocated yes/no + IF ( ALLOCATED(InData%U_full_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_dotdot) ! U_full_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! U_red allocated yes/no + IF ( ALLOCATED(InData%U_red) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red) ! U_red + END IF + Int_BufSz = Int_BufSz + 1 ! U_red_dot allocated yes/no + IF ( ALLOCATED(InData%U_red_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red_dot) ! U_red_dot + END IF + Int_BufSz = Int_BufSz + 1 ! U_red_dotdot allocated yes/no + IF ( ALLOCATED(InData%U_red_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot + END IF Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no IF ( ALLOCATED(InData%SDWrOutput) ) THEN Int_BufSz = Int_BufSz + 2*1 ! SDWrOutput upper/lower bounds for each dimension @@ -5794,11 +5883,6 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes END IF - Int_BufSz = Int_BufSz + 1 ! Tred allocated yes/no - IF ( ALLOCATED(InData%Tred) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Tred upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Tred) ! Tred - END IF Int_BufSz = Int_BufSz + 1 ! Fext allocated yes/no IF ( ALLOCATED(InData%Fext) ) THEN Int_BufSz = Int_BufSz + 2*1 ! Fext upper/lower bounds for each dimension @@ -5946,6 +6030,84 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%UL_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_dotdot))-1 ) = PACK(InData%UL_dotdot,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%UL_dotdot) END IF + IF ( .NOT. ALLOCATED(InData%U_full) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full))-1 ) = PACK(InData%U_full,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full) + END IF + IF ( .NOT. ALLOCATED(InData%U_full_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dot))-1 ) = PACK(InData%U_full_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full_dot) + END IF + IF ( .NOT. ALLOCATED(InData%U_full_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dotdot))-1 ) = PACK(InData%U_full_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full_dotdot) + END IF + IF ( .NOT. ALLOCATED(InData%U_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red))-1 ) = PACK(InData%U_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red) + END IF + IF ( .NOT. ALLOCATED(InData%U_red_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dot))-1 ) = PACK(InData%U_red_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red_dot) + END IF + IF ( .NOT. ALLOCATED(InData%U_red_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dotdot))-1 ) = PACK(InData%U_red_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red_dotdot) + END IF IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6103,22 +6265,6 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) END IF - IF ( .NOT. ALLOCATED(InData%Tred) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Tred,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tred,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Tred,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Tred,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Tred)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Tred))-1 ) = PACK(InData%Tred,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Tred) - END IF IF ( .NOT. ALLOCATED(InData%Fext) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6398,6 +6544,144 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + SIZE(OutData%UL_dotdot) DEALLOCATE(mask1) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full)) DEALLOCATE(OutData%U_full) + ALLOCATE(OutData%U_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full)>0) OutData%U_full = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_dot)) DEALLOCATE(OutData%U_full_dot) + ALLOCATE(OutData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full_dot)>0) OutData%U_full_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_dotdot)) DEALLOCATE(OutData%U_full_dotdot) + ALLOCATE(OutData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full_dotdot)>0) OutData%U_full_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dotdot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red)) DEALLOCATE(OutData%U_red) + ALLOCATE(OutData%U_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red)>0) OutData%U_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red_dot)) DEALLOCATE(OutData%U_red_dot) + ALLOCATE(OutData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red_dot)>0) OutData%U_red_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red_dotdot)) DEALLOCATE(OutData%U_red_dotdot) + ALLOCATE(OutData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red_dotdot)>0) OutData%U_red_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dotdot) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6635,32 +6919,6 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Tred not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Tred)) DEALLOCATE(OutData%Tred) - ALLOCATE(OutData%Tred(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Tred.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Tred)>0) OutData%Tred = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Tred))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Tred) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6726,8 +6984,58 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" DstParamData%SDDeltaT = SrcParamData%SDDeltaT - DstParamData%SttcSolve = SrcParamData%SttcSolve -IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN + DstParamData%IntMethod = SrcParamData%IntMethod + DstParamData%nDOF = SrcParamData%nDOF + DstParamData%nDOF_red = SrcParamData%nDOF_red + DstParamData%Nmembers = SrcParamData%Nmembers +IF (ALLOCATED(SrcParamData%Elems)) THEN + i1_l = LBOUND(SrcParamData%Elems,1) + i1_u = UBOUND(SrcParamData%Elems,1) + i2_l = LBOUND(SrcParamData%Elems,2) + i2_u = UBOUND(SrcParamData%Elems,2) + IF (.NOT. ALLOCATED(DstParamData%Elems)) THEN + ALLOCATE(DstParamData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Elems = SrcParamData%Elems +ENDIF +IF (ALLOCATED(SrcParamData%ElemProps)) THEN + i1_l = LBOUND(SrcParamData%ElemProps,1) + i1_u = UBOUND(SrcParamData%ElemProps,1) + IF (.NOT. ALLOCATED(DstParamData%ElemProps)) THEN + ALLOCATE(DstParamData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) + CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%T_red)) THEN + i1_l = LBOUND(SrcParamData%T_red,1) + i1_u = UBOUND(SrcParamData%T_red,1) + i2_l = LBOUND(SrcParamData%T_red,2) + i2_u = UBOUND(SrcParamData%T_red,2) + IF (.NOT. ALLOCATED(DstParamData%T_red)) THEN + ALLOCATE(DstParamData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%T_red = SrcParamData%T_red +ENDIF + DstParamData%SttcSolve = SrcParamData%SttcSolve + DstParamData%NModes = SrcParamData%NModes + DstParamData%qmL = SrcParamData%qmL +IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN i1_l = LBOUND(SrcParamData%NOmegaM2,1) i1_u = UBOUND(SrcParamData%NOmegaM2,1) IF (.NOT. ALLOCATED(DstParamData%NOmegaM2)) THEN @@ -7011,18 +7319,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%PhiLInvOmgL2 = SrcParamData%PhiLInvOmgL2 ENDIF -IF (ALLOCATED(SrcParamData%FGL)) THEN - i1_l = LBOUND(SrcParamData%FGL,1) - i1_u = UBOUND(SrcParamData%FGL,1) - IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN - ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FGL = SrcParamData%FGL -ENDIF IF (ALLOCATED(SrcParamData%AM2Jac)) THEN i1_l = LBOUND(SrcParamData%AM2Jac,1) i1_u = UBOUND(SrcParamData%AM2Jac,1) @@ -7077,28 +7373,24 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%TIreact = SrcParamData%TIreact ENDIF - DstParamData%NModes = SrcParamData%NModes -IF (ALLOCATED(SrcParamData%Elems)) THEN - i1_l = LBOUND(SrcParamData%Elems,1) - i1_u = UBOUND(SrcParamData%Elems,1) - i2_l = LBOUND(SrcParamData%Elems,2) - i2_u = UBOUND(SrcParamData%Elems,2) - IF (.NOT. ALLOCATED(DstParamData%Elems)) THEN - ALLOCATE(DstParamData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elems.', ErrStat, ErrMsg,RoutineName) + DstParamData%nNodes = SrcParamData%nNodes + DstParamData%nNodes_I = SrcParamData%nNodes_I + DstParamData%nNodes_L = SrcParamData%nNodes_L + DstParamData%nNodes_C = SrcParamData%nNodes_C +IF (ALLOCATED(SrcParamData%Nodes_I)) THEN + i1_l = LBOUND(SrcParamData%Nodes_I,1) + i1_u = UBOUND(SrcParamData%Nodes_I,1) + i2_l = LBOUND(SrcParamData%Nodes_I,2) + i2_u = UBOUND(SrcParamData%Nodes_I,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_I)) THEN + ALLOCATE(DstParamData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_I.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%Elems = SrcParamData%Elems + DstParamData%Nodes_I = SrcParamData%Nodes_I ENDIF - DstParamData%qmL = SrcParamData%qmL - DstParamData%DofL = SrcParamData%DofL - DstParamData%DofI = SrcParamData%DofI - DstParamData%DofR = SrcParamData%DofR - DstParamData%DofC = SrcParamData%DofC - DstParamData%nNodes_RbarL = SrcParamData%nNodes_RbarL - DstParamData%nNodes_L = SrcParamData%nNodes_L IF (ALLOCATED(SrcParamData%Nodes_L)) THEN i1_l = LBOUND(SrcParamData%Nodes_L,1) i1_u = UBOUND(SrcParamData%Nodes_L,1) @@ -7113,41 +7405,24 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%Nodes_L = SrcParamData%Nodes_L ENDIF - DstParamData%nNodes_I = SrcParamData%nNodes_I - DstParamData%NInterf = SrcParamData%NInterf -IF (ALLOCATED(SrcParamData%Interf)) THEN - i1_l = LBOUND(SrcParamData%Interf,1) - i1_u = UBOUND(SrcParamData%Interf,1) - i2_l = LBOUND(SrcParamData%Interf,2) - i2_u = UBOUND(SrcParamData%Interf,2) - IF (.NOT. ALLOCATED(DstParamData%Interf)) THEN - ALLOCATE(DstParamData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Interf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Interf = SrcParamData%Interf -ENDIF - DstParamData%NReact = SrcParamData%NReact -IF (ALLOCATED(SrcParamData%Reacts)) THEN - i1_l = LBOUND(SrcParamData%Reacts,1) - i1_u = UBOUND(SrcParamData%Reacts,1) - i2_l = LBOUND(SrcParamData%Reacts,2) - i2_u = UBOUND(SrcParamData%Reacts,2) - IF (.NOT. ALLOCATED(DstParamData%Reacts)) THEN - ALLOCATE(DstParamData%Reacts(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%Nodes_C)) THEN + i1_l = LBOUND(SrcParamData%Nodes_C,1) + i1_u = UBOUND(SrcParamData%Nodes_C,1) + i2_l = LBOUND(SrcParamData%Nodes_C,2) + i2_u = UBOUND(SrcParamData%Nodes_C,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_C)) THEN + ALLOCATE(DstParamData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Reacts.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_C.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%Reacts = SrcParamData%Reacts + DstParamData%Nodes_C = SrcParamData%Nodes_C ENDIF - DstParamData%Nmembers = SrcParamData%Nmembers - DstParamData%URbarL = SrcParamData%URbarL - DstParamData%IntMethod = SrcParamData%IntMethod - DstParamData%NAvgEls = SrcParamData%NAvgEls + DstParamData%nDOFI = SrcParamData%nDOFI + DstParamData%nDOFL = SrcParamData%nDOFL + DstParamData%nDOFC = SrcParamData%nDOFC + DstParamData%nDOFR = SrcParamData%nDOFR IF (ALLOCATED(SrcParamData%IDI)) THEN i1_l = LBOUND(SrcParamData%IDI,1) i1_u = UBOUND(SrcParamData%IDI,1) @@ -7160,18 +7435,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%IDI = SrcParamData%IDI ENDIF -IF (ALLOCATED(SrcParamData%IDR)) THEN - i1_l = LBOUND(SrcParamData%IDR,1) - i1_u = UBOUND(SrcParamData%IDR,1) - IF (.NOT. ALLOCATED(DstParamData%IDR)) THEN - ALLOCATE(DstParamData%IDR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDR = SrcParamData%IDR -ENDIF IF (ALLOCATED(SrcParamData%IDL)) THEN i1_l = LBOUND(SrcParamData%IDL,1) i1_u = UBOUND(SrcParamData%IDL,1) @@ -7196,6 +7459,18 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%IDC = SrcParamData%IDC ENDIF +IF (ALLOCATED(SrcParamData%IDR)) THEN + i1_l = LBOUND(SrcParamData%IDR,1) + i1_u = UBOUND(SrcParamData%IDR,1) + IF (.NOT. ALLOCATED(DstParamData%IDR)) THEN + ALLOCATE(DstParamData%IDR(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDR = SrcParamData%IDR +ENDIF IF (ALLOCATED(SrcParamData%IDY)) THEN i1_l = LBOUND(SrcParamData%IDY,1) i1_u = UBOUND(SrcParamData%IDY,1) @@ -7208,6 +7483,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%IDY = SrcParamData%IDY ENDIF + DstParamData%URbarL = SrcParamData%URbarL +IF (ALLOCATED(SrcParamData%FGL)) THEN + i1_l = LBOUND(SrcParamData%FGL,1) + i1_u = UBOUND(SrcParamData%FGL,1) + IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN + ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FGL = SrcParamData%FGL +ENDIF + DstParamData%NAvgEls = SrcParamData%NAvgEls DstParamData%NMOutputs = SrcParamData%NMOutputs DstParamData%NumOuts = SrcParamData%NumOuts DstParamData%OutSwtch = SrcParamData%OutSwtch @@ -7263,22 +7552,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF -IF (ALLOCATED(SrcParamData%ElemProps)) THEN - i1_l = LBOUND(SrcParamData%ElemProps,1) - i1_u = UBOUND(SrcParamData%ElemProps,1) - IF (.NOT. ALLOCATED(DstParamData%ElemProps)) THEN - ALLOCATE(DstParamData%ElemProps(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) - CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF IF (ALLOCATED(SrcParamData%OutParam)) THEN i1_l = LBOUND(SrcParamData%OutParam,1) i1_u = UBOUND(SrcParamData%OutParam,1) @@ -7311,6 +7584,18 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(ParamData%Elems)) THEN + DEALLOCATE(ParamData%Elems) +ENDIF +IF (ALLOCATED(ParamData%ElemProps)) THEN +DO i1 = LBOUND(ParamData%ElemProps,1), UBOUND(ParamData%ElemProps,1) + CALL SD_Destroyelemproptype( ParamData%ElemProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%ElemProps) +ENDIF +IF (ALLOCATED(ParamData%T_red)) THEN + DEALLOCATE(ParamData%T_red) +ENDIF IF (ALLOCATED(ParamData%NOmegaM2)) THEN DEALLOCATE(ParamData%NOmegaM2) ENDIF @@ -7374,9 +7659,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%PhiLInvOmgL2)) THEN DEALLOCATE(ParamData%PhiLInvOmgL2) ENDIF -IF (ALLOCATED(ParamData%FGL)) THEN - DEALLOCATE(ParamData%FGL) -ENDIF IF (ALLOCATED(ParamData%AM2Jac)) THEN DEALLOCATE(ParamData%AM2Jac) ENDIF @@ -7389,33 +7671,33 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%TIreact)) THEN DEALLOCATE(ParamData%TIreact) ENDIF -IF (ALLOCATED(ParamData%Elems)) THEN - DEALLOCATE(ParamData%Elems) +IF (ALLOCATED(ParamData%Nodes_I)) THEN + DEALLOCATE(ParamData%Nodes_I) ENDIF IF (ALLOCATED(ParamData%Nodes_L)) THEN DEALLOCATE(ParamData%Nodes_L) ENDIF -IF (ALLOCATED(ParamData%Interf)) THEN - DEALLOCATE(ParamData%Interf) -ENDIF -IF (ALLOCATED(ParamData%Reacts)) THEN - DEALLOCATE(ParamData%Reacts) +IF (ALLOCATED(ParamData%Nodes_C)) THEN + DEALLOCATE(ParamData%Nodes_C) ENDIF IF (ALLOCATED(ParamData%IDI)) THEN DEALLOCATE(ParamData%IDI) ENDIF -IF (ALLOCATED(ParamData%IDR)) THEN - DEALLOCATE(ParamData%IDR) -ENDIF IF (ALLOCATED(ParamData%IDL)) THEN DEALLOCATE(ParamData%IDL) ENDIF IF (ALLOCATED(ParamData%IDC)) THEN DEALLOCATE(ParamData%IDC) ENDIF +IF (ALLOCATED(ParamData%IDR)) THEN + DEALLOCATE(ParamData%IDR) +ENDIF IF (ALLOCATED(ParamData%IDY)) THEN DEALLOCATE(ParamData%IDY) ENDIF +IF (ALLOCATED(ParamData%FGL)) THEN + DEALLOCATE(ParamData%FGL) +ENDIF IF (ALLOCATED(ParamData%MoutLst)) THEN DO i1 = LBOUND(ParamData%MoutLst,1), UBOUND(ParamData%MoutLst,1) CALL SD_Destroymeshauxdatatype( ParamData%MoutLst(i1), ErrStat, ErrMsg ) @@ -7434,12 +7716,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%MoutLst3) ENDIF -IF (ALLOCATED(ParamData%ElemProps)) THEN -DO i1 = LBOUND(ParamData%ElemProps,1), UBOUND(ParamData%ElemProps,1) - CALL SD_Destroyelemproptype( ParamData%ElemProps(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%ElemProps) -ENDIF IF (ALLOCATED(ParamData%OutParam)) THEN DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) @@ -7484,7 +7760,47 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Db_BufSz = 0 Int_BufSz = 0 Db_BufSz = Db_BufSz + 1 ! SDDeltaT + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! nDOF + Int_BufSz = Int_BufSz + 1 ! nDOF_red + Int_BufSz = Int_BufSz + 1 ! Nmembers + Int_BufSz = Int_BufSz + 1 ! Elems allocated yes/no + IF ( ALLOCATED(InData%Elems) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Elems upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Elems) ! Elems + END IF + Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no + IF ( ALLOCATED(InData%ElemProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElemProps upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + Int_BufSz = Int_BufSz + 3 ! ElemProps: size of buffers for each call to pack subtype + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ElemProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ElemProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ElemProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no + IF ( ALLOCATED(InData%T_red) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%T_red) ! T_red + END IF Int_BufSz = Int_BufSz + 1 ! SttcSolve + Int_BufSz = Int_BufSz + 1 ! NModes + Int_BufSz = Int_BufSz + 1 ! qmL Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no IF ( ALLOCATED(InData%NOmegaM2) ) THEN Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension @@ -7590,11 +7906,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! PhiLInvOmgL2 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%PhiLInvOmgL2) ! PhiLInvOmgL2 END IF - Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no - IF ( ALLOCATED(InData%FGL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL - END IF Int_BufSz = Int_BufSz + 1 ! AM2Jac allocated yes/no IF ( ALLOCATED(InData%AM2Jac) ) THEN Int_BufSz = Int_BufSz + 2*2 ! AM2Jac upper/lower bounds for each dimension @@ -7615,51 +7926,34 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! TIreact upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%TIreact) ! TIreact END IF - Int_BufSz = Int_BufSz + 1 ! NModes - Int_BufSz = Int_BufSz + 1 ! Elems allocated yes/no - IF ( ALLOCATED(InData%Elems) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Elems upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Elems) ! Elems - END IF - Int_BufSz = Int_BufSz + 1 ! qmL - Int_BufSz = Int_BufSz + 1 ! DofL - Int_BufSz = Int_BufSz + 1 ! DofI - Int_BufSz = Int_BufSz + 1 ! DofR - Int_BufSz = Int_BufSz + 1 ! DofC - Int_BufSz = Int_BufSz + 1 ! nNodes_RbarL + Int_BufSz = Int_BufSz + 1 ! nNodes + Int_BufSz = Int_BufSz + 1 ! nNodes_I Int_BufSz = Int_BufSz + 1 ! nNodes_L + Int_BufSz = Int_BufSz + 1 ! nNodes_C + Int_BufSz = Int_BufSz + 1 ! Nodes_I allocated yes/no + IF ( ALLOCATED(InData%Nodes_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_I upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_I) ! Nodes_I + END IF Int_BufSz = Int_BufSz + 1 ! Nodes_L allocated yes/no IF ( ALLOCATED(InData%Nodes_L) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Nodes_L upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%Nodes_L) ! Nodes_L END IF - Int_BufSz = Int_BufSz + 1 ! nNodes_I - Int_BufSz = Int_BufSz + 1 ! NInterf - Int_BufSz = Int_BufSz + 1 ! Interf allocated yes/no - IF ( ALLOCATED(InData%Interf) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Interf upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Interf) ! Interf - END IF - Int_BufSz = Int_BufSz + 1 ! NReact - Int_BufSz = Int_BufSz + 1 ! Reacts allocated yes/no - IF ( ALLOCATED(InData%Reacts) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Reacts upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Reacts) ! Reacts + Int_BufSz = Int_BufSz + 1 ! Nodes_C allocated yes/no + IF ( ALLOCATED(InData%Nodes_C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_C upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_C) ! Nodes_C END IF - Int_BufSz = Int_BufSz + 1 ! Nmembers - Int_BufSz = Int_BufSz + 1 ! URbarL - Int_BufSz = Int_BufSz + 1 ! IntMethod - Int_BufSz = Int_BufSz + 1 ! NAvgEls + Int_BufSz = Int_BufSz + 1 ! nDOFI + Int_BufSz = Int_BufSz + 1 ! nDOFL + Int_BufSz = Int_BufSz + 1 ! nDOFC + Int_BufSz = Int_BufSz + 1 ! nDOFR Int_BufSz = Int_BufSz + 1 ! IDI allocated yes/no IF ( ALLOCATED(InData%IDI) ) THEN Int_BufSz = Int_BufSz + 2*1 ! IDI upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%IDI) ! IDI END IF - Int_BufSz = Int_BufSz + 1 ! IDR allocated yes/no - IF ( ALLOCATED(InData%IDR) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDR upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDR) ! IDR - END IF Int_BufSz = Int_BufSz + 1 ! IDL allocated yes/no IF ( ALLOCATED(InData%IDL) ) THEN Int_BufSz = Int_BufSz + 2*1 ! IDL upper/lower bounds for each dimension @@ -7670,11 +7964,23 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*1 ! IDC upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%IDC) ! IDC END IF + Int_BufSz = Int_BufSz + 1 ! IDR allocated yes/no + IF ( ALLOCATED(InData%IDR) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDR upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDR) ! IDR + END IF Int_BufSz = Int_BufSz + 1 ! IDY allocated yes/no IF ( ALLOCATED(InData%IDY) ) THEN Int_BufSz = Int_BufSz + 2*1 ! IDY upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%IDY) ! IDY END IF + Int_BufSz = Int_BufSz + 1 ! URbarL + Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no + IF ( ALLOCATED(InData%FGL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL + END IF + Int_BufSz = Int_BufSz + 1 ! NAvgEls Int_BufSz = Int_BufSz + 1 ! NMOutputs Int_BufSz = Int_BufSz + 1 ! NumOuts Int_BufSz = Int_BufSz + 1 ! OutSwtch @@ -7685,7 +7991,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! MoutLst allocated yes/no IF ( ALLOCATED(InData%MoutLst) ) THEN Int_BufSz = Int_BufSz + 2*1 ! MoutLst upper/lower bounds for each dimension - ! Allocate buffers for subtypes, if any (we'll get sizes from these) DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) Int_BufSz = Int_BufSz + 3 ! MoutLst: size of buffers for each call to pack subtype CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst @@ -7752,29 +8057,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no - IF ( ALLOCATED(InData%ElemProps) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! ElemProps upper/lower bounds for each dimension - DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) - Int_BufSz = Int_BufSz + 3 ! ElemProps: size of buffers for each call to pack subtype - CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! ElemProps - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! ElemProps - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! ElemProps - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no IF ( ALLOCATED(InData%OutParam) ) THEN Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension @@ -7832,8 +8114,93 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%SDDeltaT Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF_red + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Nmembers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Elems) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Elems)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Elems))-1 ) = PACK(InData%Elems,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Elems) + END IF + IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%T_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%T_red) + END IF IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SttcSolve , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NModes + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%qmL + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8155,19 +8522,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%PhiLInvOmgL2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiLInvOmgL2))-1 ) = PACK(InData%PhiLInvOmgL2,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%PhiLInvOmgL2) END IF - IF ( .NOT. ALLOCATED(InData%FGL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FGL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FGL) - END IF IF ( .NOT. ALLOCATED(InData%AM2Jac) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8229,38 +8583,30 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%TIreact)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TIreact))-1 ) = PACK(InData%TIreact,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%TIreact) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NModes + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Elems) ) THEN + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_C + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nodes_I) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Elems)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Elems))-1 ) = PACK(InData%Elems,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Elems) + IF (SIZE(InData%Nodes_I)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_I))-1 ) = PACK(InData%Nodes_I,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_I) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%qmL - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofL - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofI - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofR - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%DofC - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_RbarL - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8277,51 +8623,29 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NInterf - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Interf) ) THEN + IF ( .NOT. ALLOCATED(InData%Nodes_C) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Interf,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Interf,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Interf)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Interf))-1 ) = PACK(InData%Interf,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Interf) + IF (SIZE(InData%Nodes_C)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_C))-1 ) = PACK(InData%Nodes_C,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_C) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NReact + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Reacts) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Reacts,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Reacts,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Reacts,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Reacts,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Reacts)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Reacts))-1 ) = PACK(InData%Reacts,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Reacts) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Nmembers + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%URbarL + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%IntMethod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NAvgEls + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%IDI) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8336,19 +8660,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%IDI)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI))-1 ) = PACK(InData%IDI,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%IDI) END IF - IF ( .NOT. ALLOCATED(InData%IDR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDR)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR))-1 ) = PACK(InData%IDR,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDR) - END IF IF ( .NOT. ALLOCATED(InData%IDL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8375,6 +8686,19 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%IDC)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC))-1 ) = PACK(InData%IDC,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%IDC) END IF + IF ( .NOT. ALLOCATED(InData%IDR) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDR)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR))-1 ) = PACK(InData%IDR,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDR) + END IF IF ( .NOT. ALLOCATED(InData%IDY) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8388,6 +8712,23 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%IDY)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDY))-1 ) = PACK(InData%IDY,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%IDY) END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%URbarL + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%FGL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FGL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FGL) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NAvgEls + Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMOutputs Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts @@ -8531,47 +8872,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) - CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8625,44 +8925,164 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackParam - SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%SDDeltaT = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 + SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_ParameterType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackParam' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%SDDeltaT = DbKiBuf( Db_Xferred ) + Db_Xferred = Db_Xferred + 1 + OutData%IntMethod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF_red = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%Nmembers = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Elems)) DEALLOCATE(OutData%Elems) + ALLOCATE(OutData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Elems)>0) OutData%Elems = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Elems))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Elems) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) + ALLOCATE(OutData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackelemproptype( Re_Buf, Db_Buf, Int_Buf, OutData%ElemProps(i1), ErrStat2, ErrMsg2 ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%T_red)) DEALLOCATE(OutData%T_red) + ALLOCATE(OutData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%T_red) + DEALLOCATE(mask2) + END IF OutData%SttcSolve = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 + OutData%NModes = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%qmL = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9194,29 +9614,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%PhiLInvOmgL2) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FGL)) DEALLOCATE(OutData%FGL) - ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FGL)>0) OutData%FGL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FGL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FGL) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9318,9 +9715,15 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%TIreact) DEALLOCATE(mask2) END IF - OutData%NModes = IntKiBuf( Int_Xferred ) + OutData%nNodes = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems not allocated + OutData%nNodes_I = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_C = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9330,10 +9733,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Elems)) DEALLOCATE(OutData%Elems) - ALLOCATE(OutData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%Nodes_I)) DEALLOCATE(OutData%Nodes_I) + ALLOCATE(OutData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9342,24 +9745,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%Elems)>0) OutData%Elems = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Elems))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Elems) + IF (SIZE(OutData%Nodes_I)>0) OutData%Nodes_I = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_I))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_I) DEALLOCATE(mask2) END IF - OutData%qmL = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%DofL = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%DofI = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%DofR = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%DofC = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_RbarL = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9386,39 +9775,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) DEALLOCATE(mask2) END IF - OutData%nNodes_I = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NInterf = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Interf not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Interf)) DEALLOCATE(OutData%Interf) - ALLOCATE(OutData%Interf(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Interf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Interf)>0) OutData%Interf = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Interf))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Interf) - DEALLOCATE(mask2) - END IF - OutData%NReact = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Reacts not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_C not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9428,10 +9785,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Reacts)) DEALLOCATE(OutData%Reacts) - ALLOCATE(OutData%Reacts(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%Nodes_C)) DEALLOCATE(OutData%Nodes_C) + ALLOCATE(OutData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Reacts.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_C.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9440,17 +9797,17 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%Reacts)>0) OutData%Reacts = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Reacts))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Reacts) + IF (SIZE(OutData%Nodes_C)>0) OutData%Nodes_C = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_C))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_C) DEALLOCATE(mask2) END IF - OutData%Nmembers = IntKiBuf( Int_Xferred ) + OutData%nDOFI = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%URbarL = IntKiBuf( Int_Xferred ) + OutData%nDOFL = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%IntMethod = IntKiBuf( Int_Xferred ) + OutData%nDOFC = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NAvgEls = IntKiBuf( Int_Xferred ) + OutData%nDOFR = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI not allocated Int_Xferred = Int_Xferred + 1 @@ -9475,17 +9832,17 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%IDI) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDR)) DEALLOCATE(OutData%IDR) - ALLOCATE(OutData%IDR(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IDL)) DEALLOCATE(OutData%IDL) + ALLOCATE(OutData%IDL(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9494,21 +9851,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDR)>0) OutData%IDR = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDR) + IF (SIZE(OutData%IDL)>0) OutData%IDL = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDL) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDL)) DEALLOCATE(OutData%IDL) - ALLOCATE(OutData%IDL(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IDC)) DEALLOCATE(OutData%IDC) + ALLOCATE(OutData%IDC(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9517,21 +9874,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDL)>0) OutData%IDL = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDL) + IF (SIZE(OutData%IDC)>0) OutData%IDC = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC)) DEALLOCATE(OutData%IDC) - ALLOCATE(OutData%IDC(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IDR)) DEALLOCATE(OutData%IDR) + ALLOCATE(OutData%IDR(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9540,8 +9897,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDC)>0) OutData%IDC = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC) + IF (SIZE(OutData%IDR)>0) OutData%IDR = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDR) DEALLOCATE(mask1) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDY not allocated @@ -9567,6 +9924,33 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%IDY) DEALLOCATE(mask1) END IF + OutData%URbarL = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FGL)) DEALLOCATE(OutData%FGL) + ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FGL)>0) OutData%FGL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FGL))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FGL) + DEALLOCATE(mask1) + END IF + OutData%NAvgEls = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 OutData%NMOutputs = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NumOuts = IntKiBuf( Int_Xferred ) @@ -9755,62 +10139,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) - ALLOCATE(OutData%ElemProps(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackelemproptype( Re_Buf, Db_Buf, Int_Buf, OutData%ElemProps(i1), ErrStat2, ErrMsg2 ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated Int_Xferred = Int_Xferred + 1 ELSE From 503f49295c0b695a132ddec9f5289d24480004b3 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 08:25:42 -0700 Subject: [PATCH 126/377] FlexSub: transfer of motion using full vector of DOF with proper mapping and Tred transform --- modules/subdyn/src/SubDyn.f90 | 108 ++++++++++------------------------ 1 file changed, 31 insertions(+), 77 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 88d6abb88..bea92dc94 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -372,16 +372,18 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t TYPE(SD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- !! nectivity information does not have to be recalculated) - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(SD_MiscVarType), target, INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None !locals INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays - INTEGER(IntKi) :: I,J ! Counters + INTEGER(IntKi) :: I,J ! Counters + INTEGER(IntKi) :: iSDNode, iY2Node REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOFL), UL0m(p%nDOFL), FLt(p%nDOFL) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) + INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) @@ -434,83 +436,35 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END IF ENDIF ! --- Build original DOF vectors (DOF before the CB reduction) - !m%U_red (p%IDI) = m%UR_bar - !m%U_red (p%IDC) = 0 !!! TODO, might not be generic - !m%U_red (p%IDL) = m%UL - !m%U_red_dot (p%IDI) = m%UR_bar_dot - !m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic - !m%U_red_dot (p%IDL) = m%UL_dot - !m%U_red_dotdot(p%IDI) = m%UR_bar_dotdot - !m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic - !m%U_red_dotdot(p%IDL) = m%UL_dotdot - - !m%U_full = matmul(p%T_red, m%U_red) - !m%U_full_dot = matmul(p%T_red, m%U_red_dot) - !m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) + m%U_red (p%IDI) = m%UR_bar + m%U_red (p%IDC) = 0 !!! TODO, might not be generic + m%U_red (p%IDL) = m%UL + m%U_red_dot (p%IDI) = m%UR_bar_dot + m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic + m%U_red_dot (p%IDL) = m%UL_dot + m%U_red_dotdot(p%IDI) = m%UR_bar_dotdot + m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic + m%U_red_dotdot(p%IDL) = m%UL_dotdot + + m%U_full = matmul(p%T_red, m%U_red) + m%U_full_dot = matmul(p%T_red, m%U_red_dot) + m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) - ! --------------------------------------------------------------------------------- - ! Place the outputs onto interface node portion of Y2 output mesh - ! --------------------------------------------------------------------------------- - ! TODO TODO TODO UL is constrained, need to multiply by T to get full DOFs - DO I = 1, p%nNodes_I - startDOF = (I-1)*6 + 1 ! OK since interface Nodes are limited to 6 DOFs for now - ! TODO: code below might need to change if not all DOF fixed at interface + ! --- Place displacement/velocity/acceleration into Y2 output mesh + DO iSDNode = 1,p%nNodes + iY2Node = m%INodes_SD_to_Mesh(iSDNode) + DOFList => m%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles - CALL SmllRotTrans( 'UR_bar input angles', m%UR_bar(startDOF + 3), m%UR_bar(startDOF + 4), m%UR_bar(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) + CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - - y%Y2mesh%TranslationDisp (:,I) = m%UR_bar ( startDOF : startDOF + 2 ) - y%Y2mesh%Orientation (:,:,I) = DCM - y%Y2mesh%TranslationVel (:,I) = m%UR_bar_dot ( startDOF : startDOF + 2 ) - y%Y2mesh%RotationVel (:,I) = m%UR_bar_dot ( startDOF + 3 : startDOF + 5 ) - y%Y2mesh%TranslationAcc (:,I) = m%UR_bar_dotdot ( startDOF : startDOF + 2 ) - y%Y2mesh%RotationAcc (:,I) = m%UR_bar_dotdot ( startDOF + 3 : startDOF + 5 ) - - ENDDO - - ! --------------------------------------------------------------------------------- - ! Place the outputs onto interior node portion of Y2 output mesh - ! --------------------------------------------------------------------------------- - ! TODO TODO TODO UL is constrained, need to multiply by T to get full DOFs - DO I = 1, p%nNodes_L !Only interior nodes here - ! starting index in the master arrays for the current node - startDOF = (I-1)*6 + 1 - - ! index into the Y2Mesh - J = p%nNodes_I + I - - ! Construct the direction cosine matrix given the output angles - CALL SmllRotTrans( 'UL input angles', m%UL(startDOF + 3), m%UL(startDOF + 4), m%UL(startDOF + 5), DCM, '', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - - ! Y2 = Interior node displacements and velocities for use as inputs to HydroDyn - y%Y2mesh%TranslationDisp (:,J) = m%UL ( startDOF : startDOF + 2 ) - y%Y2mesh%Orientation (:,:,J) = DCM - y%Y2mesh%TranslationVel (:,J) = m%UL_dot ( startDOF : startDOF + 2 ) - y%Y2mesh%RotationVel (:,J) = m%UL_dot ( startDOF + 3 : startDOF + 5 ) - - END DO - - !Repeat for the acceleration, there should be a way to combine into 1 loop - ! TODO TODO TODO UL is constrained - L1 = p%nNodes_I+1 - L2 = p%nNodes_I+p%nNodes_L - junk= RESHAPE(m%UL_dotdot,(/6 ,p%nNodes_L/)) - y%Y2mesh%TranslationAcc ( :,L1:L2) = junk(1:3,:) - y%Y2mesh%RotationAcc ( :,L1:L2) = junk(4:6,:) - - ! --------------------------------------------------------------------------------- - ! Base reaction nodes have zero disp vel and acc - ! --------------------------------------------------------------------------------- - L1 = p%nNodes_I+p%nNodes_L+1 - L2 = p%nNodes_I+p%nNodes_L+p%nNodes_C - y%Y2mesh%TranslationDisp(:,L1:L2) = 0.0 - CALL Eye( y%Y2mesh%Orientation(:,:,L1:L2), ErrStat2, ErrMsg2 ) ; if(Failed()) return - y%Y2mesh%TranslationVel (:,L1:L2) = 0.0 - y%Y2mesh%RotationVel (:,L1:L2) = 0.0 - y%Y2mesh%TranslationAcc (:,L1:L2) = 0.0 - y%Y2mesh%RotationAcc (:,L1:L2) = 0.0 - + y%Y2mesh%Orientation (:,:,iY2Node) = DCM + y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + enddo !________________________________________ ! Set loads outputs on y%Y1Mesh !________________________________________ @@ -522,7 +476,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !Aggregate the forces and moments at the interface nodes to the reference point !TODO: where are these HydroTP, HydroForces documented? DO I = 1, p%nNodes_I - startDOF = (I-1)*6 + 1 + startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5 ) = (/u%LMesh%Force(:,I),u%LMesh%Moment(:,I)/) !(6,NNODES_I) ENDDO From 0865a590f5aacc378465cd8c655d1ef74741dbe0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 08:54:38 -0700 Subject: [PATCH 127/377] FlexSub: moved variables from misc to parameters --- modules/subdyn/src/SD_FEM.f90 | 97 +- modules/subdyn/src/SubDyn.f90 | 87 +- modules/subdyn/src/SubDyn_Output.f90 | 18 +- modules/subdyn/src/SubDyn_Registry.txt | 14 +- modules/subdyn/src/SubDyn_Types.f90 | 1259 ++++++++++++------------ 5 files changed, 739 insertions(+), 736 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index f1c55ab25..5b6699d02 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -748,11 +748,10 @@ END SUBROUTINE SetElementProperties !! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs !! For other joint type -> Condensation of the 3 translational DOF !! -> Keeping 3 rotational DOF for each memeber connected to the joint -SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) +SUBROUTINE DistributeDOF(Init, p, ErrStat, ErrMsg) use IntegerList, only: init_list, len TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m + TYPE(SD_ParameterType), INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None integer(IntKi) :: iNode, k @@ -767,12 +766,12 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) ErrMsg = "" ErrStat = ErrID_None - allocate(m%NodesDOF(1:p%nNodes), stat=ErrStat2) + allocate(p%NodesDOF(1:p%nNodes), stat=ErrStat2) ErrMsg2="Error allocating NodesDOF" if(Failed()) return - call AllocAry(m%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; - m%ElemsDOF=-9999 + call AllocAry(p%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; + p%ElemsDOF=-9999 iPrev =0 do iNode = 1, p%nNodes @@ -782,8 +781,8 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) else nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint endif - call init_list(m%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) - m%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) + call init_list(p%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) + p%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) ! --- Distribute to members do iElem = 1, Init%NodesConnE(iNode,1) ! members connected to joint iJ @@ -793,14 +792,14 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) else ! Current joint is Elem node 2 iOff = 6 endif - m%ElemsDOF(iOff+1:iOff+3, idElem) = m%NodesDOF(iNode)%List(1:3) + p%ElemsDOF(iOff+1:iOff+3, idElem) = p%NodesDOF(iNode)%List(1:3) if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then - m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(4:6) + p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(4:6) else - m%ElemsDOF(iOff+4:iOff+6, idElem) = m%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) + p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) endif enddo ! iElem, loop on members connect to joint - iPrev = iPrev + len(m%NodesDOF(iNode)) + iPrev = iPrev + len(p%NodesDOF(iNode)) enddo ! iNode, loop on joints ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first @@ -812,7 +811,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) CALL InitIntFc(Init, p) ! --- Safety check - if (any(m%ElemsDOF<0)) then + if (any(p%ElemsDOF<0)) then ErrStat=ErrID_Fatal ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" endif @@ -822,7 +821,7 @@ SUBROUTINE DistributeDOF(Init, p, m, ErrStat, ErrMsg) do idElem = 1, Init%NElem iNode = p%Elems(idElem, 2) DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) - if ( any( (m%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then + if ( any( (p%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then ErrStat=ErrID_Fatal ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iElem="//trim(Num2LStr(idElem)) return @@ -849,7 +848,7 @@ SUBROUTINE InitBCs(Init, p) DO I = 1, p%nNodes_C iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) Init%BCs( (I-1)*6+J, 2) = p%Nodes_C(I, J+1); ! 0 or 1 if fixed reaction or not ENDDO ENDDO @@ -866,7 +865,7 @@ SUBROUTINE InitIntFc(Init, p) DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = m%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) Init%IntFc( (I-1)*6+J, 2) = p%Nodes_I(I, J+1); ! 0 or 1 if fixed to interface ENDDO ENDDO @@ -876,10 +875,9 @@ END SUBROUTINE DistributeDOF !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) +SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType), INTENT(INOUT) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables @@ -914,7 +912,7 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) ! --- Assembly in global unconstrained system - IDOF = m%ElemsDOF(1:12, i) + IDOF = p%ElemsDOF(1:12, i) Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) @@ -929,18 +927,18 @@ SUBROUTINE AssembleKM(Init, p, m, ErrStat, ErrMsg) if(Failed()) return endif DO J = 1, 3 - iGlob = m%NodesDOF(iNode)%List(J) ! ux, uy, uz + iGlob = p%NodesDOF(iNode)%List(J) ! ux, uy, uz Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) ENDDO DO J = 4, 6 - iGlob = m%NodesDOF(iNode)%List(J) ! theta_x, theta_y, theta_z + iGlob = p%NodesDOF(iNode)%List(J) ! theta_x, theta_y, theta_z Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) ENDDO ENDDO ! Loop on concentrated mass ! add concentrated mass induced gravity force DO I = 1, Init%NCMass - iGlob = m%NodesDOF(i)%List(3) ! uz + iGlob = p%NodesDOF(i)%List(3) ! uz Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO ! I concentrated mass induced gravity @@ -981,14 +979,13 @@ END SUBROUTINE AssembleKM !------------------------------------------------------------------------------------------------------ !> Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF -SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) +SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) use IntegerList, only: init_list, find, pop, destroy_list, len use IntegerList, only: print_list TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p + TYPE(SD_ParameterType),target,INTENT(INOUT) :: p type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination @@ -1015,7 +1012,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) ! --- Misc inits nullify(IDOFNew) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - allocate(m%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + allocate(p%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system p%nDOF_red = nDOF_ConstraintReduced() print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF @@ -1049,7 +1046,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) nj = size(INodesID) allocate(IDOFOld(1:6*nj)) do I=1, nj - IDOFOld( (I-1)*6+1 : I*6 ) = m%NodesDOF(INodesID(I))%List(1:6) + IDOFOld( (I-1)*6+1 : I*6 ) = p%NodesDOF(INodesID(I))%List(1:6) enddo endif else @@ -1057,19 +1054,19 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, m, Tred, ErrStat, ErrMsg) allocate(Tc(1:6,1:6)) allocate(IDOFOld(1:6)) Tc=I6 - IDOFOld = m%NodesDOF(iNode)%List(1:6) + IDOFOld = p%NodesDOF(iNode)%List(1:6) endif else ! --- Ball/Pin/Universal joint - allocate(IDOFOld(1:len(m%NodesDOF(iNode)))) - IDOFOld(:) = m%NodesDOF(iNode)%List(:) + allocate(IDOFOld(1:len(p%NodesDOF(iNode)))) + IDOFOld(:) = p%NodesDOF(iNode)%List(:) phat = Init%Nodes(iNode, iJointDir:iJointDir+2) call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return endif nc=size(Tc,2) - call init_list(m%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) - m%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) - IDOFNew => m%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations + call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) + p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) + IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations print*,'N',iNode,'I ',IDOFOld print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc @@ -1145,11 +1142,10 @@ END FUNCTION nDOF_ConstraintReduced END SUBROUTINE BuildTMatrix !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) +SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) use IntegerList, only: len TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - TYPE(SD_MiscVarType),target, INTENT(INOUT) :: m + TYPE(SD_ParameterType),target,INTENT(INOUT) :: p INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables @@ -1166,7 +1162,7 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - call BuildTMatrix(Init, p, RA, RAm1, m, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return + call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return ! --- DOF elimination for system matrices and RHS vector ! Temporary backup of M and K of full system @@ -1179,8 +1175,6 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - CALL AllocAry( m%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force - CALL AllocAry( m%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 ); if(Failed()) return ! external force, reduced by Tred ! Elimination Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) @@ -1192,15 +1186,15 @@ SUBROUTINE DirectElimination(Init, p, m, ErrStat, ErrMsg) CALL ReInitIntFc(Init, p) ! --- Creating a convenient Map from DOF to Nodes - call AllocAry(m%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; - m%DOFtilde2Nodes=-999 + call AllocAry(p%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; + p%DOFtilde2Nodes=-999 do iNode=1,p%nNodes - nDOFPerNode = len(m%NodesDOFtilde(iNode)) + nDOFPerNode = len(p%NodesDOFtilde(iNode)) do iiDOF = 1, nDOFPerNode - iDOF = m%NodesDOFtilde(iNode)%List(iiDOF) - m%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index - m%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node - m%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node + iDOF = p%NodesDOFtilde(iNode)%List(iiDOF) + p%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index + p%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node + p%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node enddo enddo @@ -1230,7 +1224,7 @@ SUBROUTINE ReInitBCs(Init, p) DO I = 1, p%nNodes_C iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) + Init%BCs( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) ENDDO ENDDO END SUBROUTINE ReInitBCs @@ -1243,7 +1237,7 @@ SUBROUTINE ReInitIntFc(Init, p) DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = m%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) + Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) ENDDO ENDDO END SUBROUTINE ReInitIntFc @@ -1539,9 +1533,8 @@ END SUBROUTINE RigidLinkAssemblies !------------------------------------------------------------------------------------------------------ !> Add stiffness and damping to some joints -SUBROUTINE InsertJointStiffDamp(p, m, Init, ErrStat, ErrMsg) - TYPE(SD_ParameterType), INTENT(IN ) :: p - TYPE(SD_MiscVarType),target, INTENT(IN ) :: m +SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) + TYPE(SD_ParameterType),target,INTENT(IN ) :: p TYPE(SD_InitType), INTENT(INOUT) :: Init INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -1571,7 +1564,7 @@ SUBROUTINE InsertJointStiffDamp(p, m, Init, ErrStat, ErrMsg) else if ( JType == idJointUniversal ) then; iStart=5; else if ( JType == idJointPin ) then; iStart=6; endif - Ifreerot=>m%NodesDOFtilde(iNode)%List(iStart:) + Ifreerot=>p%NodesDOFtilde(iNode)%List(iStart:) ! Ball/Pin/Universal joints if(StifAdd>0) then print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index bea92dc94..7d35ee934 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -192,7 +192,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL DispNVD( SD_ProgDesc ) InitOut%Ver = SD_ProgDesc - ! --- Test + ! --- Test TODO remove me in the future CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return ! transfer glue-code information to data structure for SubDyn initialization: @@ -214,22 +214,25 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - + + ! -------------------------------------------------------------------------------- + ! --- Manipulation of Init and parameters + ! -------------------------------------------------------------------------------- ! Discretize the structure according to the division size ! sets p%nNodes, Init%NElm - CALL SD_Discrt(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + CALL SD_Discrt(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! Set element properties (p%ElemProps) - CALL SetElementProperties(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + CALL SetElementProperties(Init, p, ErrStat2, ErrMsg2); if(Failed()) return !Store mapping between nodes and elements - CALL NodeCon(Init,p,ErrStat2, ErrMsg2); if(Failed()) return + CALL NodeCon(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! --- Allocate DOF indices to joints and members - call DistributeDOF(Init, p ,m ,ErrStat2, ErrMsg2); if(Failed()) return; + call DistributeDOF(Init, p ,ErrStat2, ErrMsg2); if(Failed()) return; ! Assemble Stiffness and mass matrix - CALL AssembleKM(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return + CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! --- Eigen values of full system (for summary file output only) ! True below is to remove the constraints @@ -240,11 +243,14 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL EigenSolveWrap( Init%K, Init%M, p%nDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) - CALL DirectElimination(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return + CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! --- Additional Damping and stiffness at pin/ball/universal joints - CALL InsertJointStiffDamp(p, m, Init, ErrStat2, ErrMsg2); if(Failed()) return + CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return + ! -------------------------------------------------------------------------------- + ! --- CB, Misc + ! -------------------------------------------------------------------------------- ! --- Craig-Bampton reduction (sets many parameters) CALL Craig_Bampton(Init, p, m, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -275,20 +281,24 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return + ! -------------------------------------------------------------------------------- ! --- Initialize Inputs and Outputs + ! -------------------------------------------------------------------------------- ! Create the input and output meshes associated with Transition Piece reference point CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction CALL CreateY2Meshes( p%nNodes, Init%Nodes, p%Nodes_I(:,1), p%Nodes_L(:,1), p%Nodes_C(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - call Y2Mesh_SD_Mapping(p, m%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices - call SD_Y2Mesh_Mapping(p, m%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices + call AllocAry( p%INodes_Mesh_to_SD, p%nNodes, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + call AllocAry( p%INodes_SD_to_Mesh, p%nNodes, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + call Y2Mesh_SD_Mapping(p, p%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices + call SD_Y2Mesh_Mapping(p, p%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices ! --- Write the summary file IF ( Init%SSSum ) THEN ! note p%KBB/MBB are KBBt/MBBt ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init,p,m%INodes_SD_to_Mesh,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return + CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) ENDIF @@ -365,14 +375,14 @@ END SUBROUTINE SD_UpdateStates SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t TYPE(SD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- !! nectivity information does not have to be recalculated) - TYPE(SD_MiscVarType), target, INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None !locals @@ -452,8 +462,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Place displacement/velocity/acceleration into Y2 output mesh DO iSDNode = 1,p%nNodes - iY2Node = m%INodes_SD_to_Mesh(iSDNode) - DOFList => m%NodesDOF(iSDNode)%List ! Alias to shorten notations + iY2Node = p%INodes_SD_to_Mesh(iSDNode) + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) @@ -1498,7 +1508,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) ! Set p%TI and CBparams%TI2 - CALL TrnsfTI(Init, m, p%TI, p%nDOFI, p%IDI, CBparams%TI2, p%nDOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + CALL TrnsfTI(Init, p, p%TI, p%nDOFI, p%IDI, CBparams%TI2, p%nDOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1766,9 +1776,9 @@ END SUBROUTINE CBMatrix !------------------------------------------------------------------------------------------------------ !> -SUBROUTINE TrnsfTI(Init, m, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) +SUBROUTINE TrnsfTI(Init, p, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine - TYPE(SD_MiscVarType), INTENT(IN ) :: m + TYPE(SD_ParameterType), INTENT(IN ) :: p INTEGER(IntKi), INTENT(IN ) :: nDOFI ! # of DOFS of interface nodes INTEGER(IntKi), INTENT(IN ) :: nDOFR ! # of DOFS of restrained nodes (restraints and interface) INTEGER(IntKi), INTENT(IN ) :: IDI(nDOFI) @@ -1789,9 +1799,9 @@ SUBROUTINE TrnsfTI(Init, m, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) TI(:,:)=0 DO I = 1, nDOFI iDOF = IDI(I) ! DOF index in constrained system - iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) if ((iiDOF<1) .or. (iiDOF>6)) then ErrMsg = 'TransfTI, interface node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal @@ -1813,9 +1823,9 @@ SUBROUTINE TrnsfTI(Init, m, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) TI2(:,:) = 0. !Initialize DO I = 1, nDOFR iDOF = IDR(I) ! DOF index in constrained system - iNode = m%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = m%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = m%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) if ((iiDOF<1) .or. (iiDOF>6)) then ErrMsg = 'TransfTI, reaction node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal @@ -2246,8 +2256,8 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - call AllocAry( Misc%INodes_Mesh_to_SD, p%nNodes, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - call AllocAry( Misc%INodes_SD_to_Mesh, p%nNodes, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') END SUBROUTINE AllocMiscVars @@ -2299,11 +2309,11 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ! Interface DOFS p%nDOFI =0 do iiNode= 1,p%nNodes_I - p%nDOFI = p%nDOFI + len(m%NodesDOFtilde( p%Nodes_I(iiNode,1) )) + p%nDOFI = p%nDOFI + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) enddo ! Reaction DOFs do iiNode= 1,p%nNodes_C - p%nDOFC = p%nDOFC + len(m%NodesDOFtilde( p%Nodes_C(iiNode,1) )) + p%nDOFC = p%nDOFC + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) enddo p%nDOFR = p%nDOFC + p%nDOFI p%nDOFL = p%nDOF_red - p%nDOFR ! TODO @@ -2399,15 +2409,15 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) ! --- Build vector of external force m%Fext= myNaN - DO iMeshNode = 1,size(m%INodes_Mesh_to_SD) - iSDNode = m%INodes_Mesh_to_SD(iMeshNode) - nMembers = (size(m%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + DO iMeshNode = 1,size(p%INodes_Mesh_to_SD) + iSDNode = p%INodes_Mesh_to_SD(iMeshNode) + nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs - m%Fext( m%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) + m%Fext( p%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs - m%Fext( m%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers - m%Fext( m%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers - m%Fext( m%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers enddo ! TODO: remove test below in the future if (any(m%Fext == myNaN)) then @@ -2423,10 +2433,9 @@ END SUBROUTINE ConstructUFL !------------------------------------------------------------------------------------------------------ !> Output the summary file -SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) +SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file - INTEGER(IntKi) , INTENT(IN) :: SDtoMeshIndx(:) ! SD to mesh mapping TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use TYPE(FEM_MatArrays), INTENT(IN) :: FEMparams ! FEM parameters that will be passed in for summary file use INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation @@ -2474,7 +2483,7 @@ SUBROUTINE OutSummary(Init, p, SDtoMeshIndx, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') '--------', '-----------', '---------------', '---------------', '---------------' ! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) !do not group the format or it won't work 3(E15.6) does not work !bjj??? WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & - (NINT(Init%Nodes(i, 1)), SDtoMeshIndx(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) + (NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index fa3cdf9a0..b3a81b9a5 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -254,7 +254,9 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) INTEGER :: rmndr !type-column index INTEGER :: nodeID !node ID INTEGER(IntKi) :: DOFC ! DOFC = Init%NReact*6 - REAL(ReKi) :: x, y, z !coordinates + INTEGER(IntKi) :: iiDOF, iNode, nDOFPerNode ! + REAL(ReKi) :: dx, dy, dz ! distances from reaction points to subdyn origin (mudline) + REAL(ReKi), dimension(6) :: Line ErrStat=ErrID_None ErrMsg="" @@ -273,15 +275,15 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) DO I = 1, DOFC nodeID = p%Nodes_C(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Nodes_C) - x = Init%Nodes(nodeID, 2) - y = Init%Nodes(nodeID, 3) - z = Init%Nodes(nodeID, 4) + WtrDpth + dx = Init%Nodes(nodeID, 2) + dy = Init%Nodes(nodeID, 3) + dz = Init%Nodes(nodeID, 4) + WtrDpth rmndr = MOD(I, 6) !It gives me the column index among the 6 different kinds SELECT CASE (rmndr) - CASE (1); p%TIreact(4:6, I) = (/0.0_ReKi , z , -y/) - CASE (2); p%TIreact(4:6, I) = (/-z , 0.0_ReKi , x/) - CASE (3); p%TIreact(4:6, I) = (/y , -x , 0.0_ReKi/) + CASE (1); p%TIreact(4:6, I) = (/0.0_ReKi , dz , -dy/) + CASE (2); p%TIreact(4:6, I) = (/-dz , 0.0_ReKi , dx/) + CASE (3); p%TIreact(4:6, I) = (/dy , -dx , 0.0_ReKi/) CASE (4); p%TIreact(4:6, I) = (/1.0_ReKi , 0.0_ReKi , 0.0_ReKi/) CASE (5); p%TIreact(4:6, I) = (/0.0_ReKi , 1.0_ReKi , 0.0_ReKi/) CASE (0); p%TIreact(4:6, I) = (/0.0_ReKi , 0.0_ReKi , 1.0_ReKi/) @@ -290,7 +292,9 @@ SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) ErrMsg = 'Error calculating transformation matrix TIreact, wrong column index ' RETURN END SELECT + !print*,'TIr',p%TIreact(:, I) ENDDO + END SUBROUTINE ReactMatx !==================================================================================================== diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index accb3b486..74dcb983e 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -155,12 +155,6 @@ typedef ^ ^ ReKi U_red_dotdot {:} typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" -typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" -typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" -typedef ^ ^ IntKi INodes_Mesh_to_SD {:} - - "Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) " "-" -typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) " "-" -typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" -typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" @@ -177,7 +171,13 @@ typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub struc typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" # --- Constraints reduction -typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" +typedef ^ ^ IntKi INodes_Mesh_to_SD {:} - - "Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) " "-" +typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) " "-" +typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" +typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" # --- CB reduction typedef ^ ParameterType Logical SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B method" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 705a03b4d..d9a7c9e5d 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -199,12 +199,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_Mesh_to_SD !< Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads on unconstrained DOFs [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext_red !< External loads on constrained DOFs, Fext_red= T^t Fext [-] END TYPE SD_MiscVarType @@ -219,6 +213,12 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_Mesh_to_SD !< Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] LOGICAL :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] INTEGER(IntKi) :: NModes !< Number of modes to retain in C-B method [-] INTEGER(IntKi) :: qmL !< Length of state array [-] @@ -5313,7 +5313,6 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMisc' @@ -5505,90 +5504,6 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstMiscData%LastOutTime = SrcMiscData%LastOutTime DstMiscData%Decimat = SrcMiscData%Decimat -IF (ALLOCATED(SrcMiscData%NodesDOF)) THEN - i1_l = LBOUND(SrcMiscData%NodesDOF,1) - i1_u = UBOUND(SrcMiscData%NodesDOF,1) - IF (.NOT. ALLOCATED(DstMiscData%NodesDOF)) THEN - ALLOCATE(DstMiscData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%NodesDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcMiscData%NodesDOF,1), UBOUND(SrcMiscData%NodesDOF,1) - CALL SD_Copyilist( SrcMiscData%NodesDOF(i1), DstMiscData%NodesDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcMiscData%NodesDOFtilde)) THEN - i1_l = LBOUND(SrcMiscData%NodesDOFtilde,1) - i1_u = UBOUND(SrcMiscData%NodesDOFtilde,1) - IF (.NOT. ALLOCATED(DstMiscData%NodesDOFtilde)) THEN - ALLOCATE(DstMiscData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcMiscData%NodesDOFtilde,1), UBOUND(SrcMiscData%NodesDOFtilde,1) - CALL SD_Copyilist( SrcMiscData%NodesDOFtilde(i1), DstMiscData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcMiscData%INodes_Mesh_to_SD)) THEN - i1_l = LBOUND(SrcMiscData%INodes_Mesh_to_SD,1) - i1_u = UBOUND(SrcMiscData%INodes_Mesh_to_SD,1) - IF (.NOT. ALLOCATED(DstMiscData%INodes_Mesh_to_SD)) THEN - ALLOCATE(DstMiscData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%INodes_Mesh_to_SD = SrcMiscData%INodes_Mesh_to_SD -ENDIF -IF (ALLOCATED(SrcMiscData%INodes_SD_to_Mesh)) THEN - i1_l = LBOUND(SrcMiscData%INodes_SD_to_Mesh,1) - i1_u = UBOUND(SrcMiscData%INodes_SD_to_Mesh,1) - IF (.NOT. ALLOCATED(DstMiscData%INodes_SD_to_Mesh)) THEN - ALLOCATE(DstMiscData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%INodes_SD_to_Mesh = SrcMiscData%INodes_SD_to_Mesh -ENDIF -IF (ALLOCATED(SrcMiscData%ElemsDOF)) THEN - i1_l = LBOUND(SrcMiscData%ElemsDOF,1) - i1_u = UBOUND(SrcMiscData%ElemsDOF,1) - i2_l = LBOUND(SrcMiscData%ElemsDOF,2) - i2_u = UBOUND(SrcMiscData%ElemsDOF,2) - IF (.NOT. ALLOCATED(DstMiscData%ElemsDOF)) THEN - ALLOCATE(DstMiscData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%ElemsDOF = SrcMiscData%ElemsDOF -ENDIF -IF (ALLOCATED(SrcMiscData%DOFtilde2Nodes)) THEN - i1_l = LBOUND(SrcMiscData%DOFtilde2Nodes,1) - i1_u = UBOUND(SrcMiscData%DOFtilde2Nodes,1) - i2_l = LBOUND(SrcMiscData%DOFtilde2Nodes,2) - i2_u = UBOUND(SrcMiscData%DOFtilde2Nodes,2) - IF (.NOT. ALLOCATED(DstMiscData%DOFtilde2Nodes)) THEN - ALLOCATE(DstMiscData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%DOFtilde2Nodes = SrcMiscData%DOFtilde2Nodes -ENDIF IF (ALLOCATED(SrcMiscData%Fext)) THEN i1_l = LBOUND(SrcMiscData%Fext,1) i1_u = UBOUND(SrcMiscData%Fext,1) @@ -5669,30 +5584,6 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) ENDIF -IF (ALLOCATED(MiscData%NodesDOF)) THEN -DO i1 = LBOUND(MiscData%NodesDOF,1), UBOUND(MiscData%NodesDOF,1) - CALL SD_Destroyilist( MiscData%NodesDOF(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(MiscData%NodesDOF) -ENDIF -IF (ALLOCATED(MiscData%NodesDOFtilde)) THEN -DO i1 = LBOUND(MiscData%NodesDOFtilde,1), UBOUND(MiscData%NodesDOFtilde,1) - CALL SD_Destroyilist( MiscData%NodesDOFtilde(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(MiscData%NodesDOFtilde) -ENDIF -IF (ALLOCATED(MiscData%INodes_Mesh_to_SD)) THEN - DEALLOCATE(MiscData%INodes_Mesh_to_SD) -ENDIF -IF (ALLOCATED(MiscData%INodes_SD_to_Mesh)) THEN - DEALLOCATE(MiscData%INodes_SD_to_Mesh) -ENDIF -IF (ALLOCATED(MiscData%ElemsDOF)) THEN - DEALLOCATE(MiscData%ElemsDOF) -ENDIF -IF (ALLOCATED(MiscData%DOFtilde2Nodes)) THEN - DEALLOCATE(MiscData%DOFtilde2Nodes) -ENDIF IF (ALLOCATED(MiscData%Fext)) THEN DEALLOCATE(MiscData%Fext) ENDIF @@ -5816,73 +5707,6 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz END IF Db_BufSz = Db_BufSz + 1 ! LastOutTime Int_BufSz = Int_BufSz + 1 ! Decimat - Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no - IF ( ALLOCATED(InData%NodesDOF) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) - Int_BufSz = Int_BufSz + 3 ! NodesDOF: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! NodesDOF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! NodesDOF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! NodesDOF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no - IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! INodes_Mesh_to_SD allocated yes/no - IF ( ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! INodes_Mesh_to_SD upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%INodes_Mesh_to_SD) ! INodes_Mesh_to_SD - END IF - Int_BufSz = Int_BufSz + 1 ! INodes_SD_to_Mesh allocated yes/no - IF ( ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! INodes_SD_to_Mesh upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%INodes_SD_to_Mesh) ! INodes_SD_to_Mesh - END IF - Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no - IF ( ALLOCATED(InData%ElemsDOF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF - END IF - Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no - IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes - END IF Int_BufSz = Int_BufSz + 1 ! Fext allocated yes/no IF ( ALLOCATED(InData%Fext) ) THEN Int_BufSz = Int_BufSz + 2*1 ! Fext upper/lower bounds for each dimension @@ -6125,214 +5949,73 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Db_Xferred = Db_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN + IF ( .NOT. ALLOCATED(InData%Fext) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOF,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO + IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext) END IF - IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN + IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO + IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) END IF - IF ( .NOT. ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_Mesh_to_SD,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_Mesh_to_SD,1) - Int_Xferred = Int_Xferred + 2 + END SUBROUTINE SD_PackMisc - IF (SIZE(InData%INodes_Mesh_to_SD)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_Mesh_to_SD))-1 ) = PACK(InData%INodes_Mesh_to_SD,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%INodes_Mesh_to_SD) - END IF - IF ( .NOT. ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN - IntKiBuf( Int_Xferred ) = 0 + SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_MiscVarType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMisc' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdotdot not allocated Int_Xferred = Int_Xferred + 1 ELSE - IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_SD_to_Mesh,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_SD_to_Mesh,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%INodes_SD_to_Mesh)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_SD_to_Mesh))-1 ) = PACK(InData%INodes_SD_to_Mesh,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%INodes_SD_to_Mesh) - END IF - IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) - END IF - IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) - END IF - IF ( .NOT. ALLOCATED(InData%Fext) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext) - END IF - IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) - END IF - END SUBROUTINE SD_PackMisc - - SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 IF (ALLOCATED(OutData%qmdotdot)) DEALLOCATE(OutData%qmdotdot) ALLOCATE(OutData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) @@ -6709,216 +6392,6 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Db_Xferred = Db_Xferred + 1 OutData%Decimat = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesDOF)) DEALLOCATE(OutData%NodesDOF) - ALLOCATE(OutData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%NodesDOF,1), UBOUND(OutData%NodesDOF,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOF(i1), ErrStat2, ErrMsg2 ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) - ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_Mesh_to_SD not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%INodes_Mesh_to_SD)) DEALLOCATE(OutData%INodes_Mesh_to_SD) - ALLOCATE(OutData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%INodes_Mesh_to_SD)>0) OutData%INodes_Mesh_to_SD = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_Mesh_to_SD))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%INodes_Mesh_to_SD) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_SD_to_Mesh not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%INodes_SD_to_Mesh)) DEALLOCATE(OutData%INodes_SD_to_Mesh) - ALLOCATE(OutData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%INodes_SD_to_Mesh)>0) OutData%INodes_SD_to_Mesh = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_SD_to_Mesh))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%INodes_SD_to_Mesh) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElemsDOF)) DEALLOCATE(OutData%ElemsDOF) - ALLOCATE(OutData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) - ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7012,25 +6485,109 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) RETURN END IF END IF - DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) - CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO + DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) + CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%T_red)) THEN + i1_l = LBOUND(SrcParamData%T_red,1) + i1_u = UBOUND(SrcParamData%T_red,1) + i2_l = LBOUND(SrcParamData%T_red,2) + i2_u = UBOUND(SrcParamData%T_red,2) + IF (.NOT. ALLOCATED(DstParamData%T_red)) THEN + ALLOCATE(DstParamData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%T_red = SrcParamData%T_red +ENDIF +IF (ALLOCATED(SrcParamData%NodesDOF)) THEN + i1_l = LBOUND(SrcParamData%NodesDOF,1) + i1_u = UBOUND(SrcParamData%NodesDOF,1) + IF (.NOT. ALLOCATED(DstParamData%NodesDOF)) THEN + ALLOCATE(DstParamData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%NodesDOF,1), UBOUND(SrcParamData%NodesDOF,1) + CALL SD_Copyilist( SrcParamData%NodesDOF(i1), DstParamData%NodesDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%NodesDOFtilde)) THEN + i1_l = LBOUND(SrcParamData%NodesDOFtilde,1) + i1_u = UBOUND(SrcParamData%NodesDOFtilde,1) + IF (.NOT. ALLOCATED(DstParamData%NodesDOFtilde)) THEN + ALLOCATE(DstParamData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%NodesDOFtilde,1), UBOUND(SrcParamData%NodesDOFtilde,1) + CALL SD_Copyilist( SrcParamData%NodesDOFtilde(i1), DstParamData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%INodes_Mesh_to_SD)) THEN + i1_l = LBOUND(SrcParamData%INodes_Mesh_to_SD,1) + i1_u = UBOUND(SrcParamData%INodes_Mesh_to_SD,1) + IF (.NOT. ALLOCATED(DstParamData%INodes_Mesh_to_SD)) THEN + ALLOCATE(DstParamData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%INodes_Mesh_to_SD = SrcParamData%INodes_Mesh_to_SD +ENDIF +IF (ALLOCATED(SrcParamData%INodes_SD_to_Mesh)) THEN + i1_l = LBOUND(SrcParamData%INodes_SD_to_Mesh,1) + i1_u = UBOUND(SrcParamData%INodes_SD_to_Mesh,1) + IF (.NOT. ALLOCATED(DstParamData%INodes_SD_to_Mesh)) THEN + ALLOCATE(DstParamData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%INodes_SD_to_Mesh = SrcParamData%INodes_SD_to_Mesh +ENDIF +IF (ALLOCATED(SrcParamData%ElemsDOF)) THEN + i1_l = LBOUND(SrcParamData%ElemsDOF,1) + i1_u = UBOUND(SrcParamData%ElemsDOF,1) + i2_l = LBOUND(SrcParamData%ElemsDOF,2) + i2_u = UBOUND(SrcParamData%ElemsDOF,2) + IF (.NOT. ALLOCATED(DstParamData%ElemsDOF)) THEN + ALLOCATE(DstParamData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ElemsDOF = SrcParamData%ElemsDOF ENDIF -IF (ALLOCATED(SrcParamData%T_red)) THEN - i1_l = LBOUND(SrcParamData%T_red,1) - i1_u = UBOUND(SrcParamData%T_red,1) - i2_l = LBOUND(SrcParamData%T_red,2) - i2_u = UBOUND(SrcParamData%T_red,2) - IF (.NOT. ALLOCATED(DstParamData%T_red)) THEN - ALLOCATE(DstParamData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%DOFtilde2Nodes)) THEN + i1_l = LBOUND(SrcParamData%DOFtilde2Nodes,1) + i1_u = UBOUND(SrcParamData%DOFtilde2Nodes,1) + i2_l = LBOUND(SrcParamData%DOFtilde2Nodes,2) + i2_u = UBOUND(SrcParamData%DOFtilde2Nodes,2) + IF (.NOT. ALLOCATED(DstParamData%DOFtilde2Nodes)) THEN + ALLOCATE(DstParamData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%T_red = SrcParamData%T_red + DstParamData%DOFtilde2Nodes = SrcParamData%DOFtilde2Nodes ENDIF DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%NModes = SrcParamData%NModes @@ -7596,6 +7153,30 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%T_red)) THEN DEALLOCATE(ParamData%T_red) ENDIF +IF (ALLOCATED(ParamData%NodesDOF)) THEN +DO i1 = LBOUND(ParamData%NodesDOF,1), UBOUND(ParamData%NodesDOF,1) + CALL SD_Destroyilist( ParamData%NodesDOF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%NodesDOF) +ENDIF +IF (ALLOCATED(ParamData%NodesDOFtilde)) THEN +DO i1 = LBOUND(ParamData%NodesDOFtilde,1), UBOUND(ParamData%NodesDOFtilde,1) + CALL SD_Destroyilist( ParamData%NodesDOFtilde(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%NodesDOFtilde) +ENDIF +IF (ALLOCATED(ParamData%INodes_Mesh_to_SD)) THEN + DEALLOCATE(ParamData%INodes_Mesh_to_SD) +ENDIF +IF (ALLOCATED(ParamData%INodes_SD_to_Mesh)) THEN + DEALLOCATE(ParamData%INodes_SD_to_Mesh) +ENDIF +IF (ALLOCATED(ParamData%ElemsDOF)) THEN + DEALLOCATE(ParamData%ElemsDOF) +ENDIF +IF (ALLOCATED(ParamData%DOFtilde2Nodes)) THEN + DEALLOCATE(ParamData%DOFtilde2Nodes) +ENDIF IF (ALLOCATED(ParamData%NOmegaM2)) THEN DEALLOCATE(ParamData%NOmegaM2) ENDIF @@ -7797,6 +7378,72 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF ( ALLOCATED(InData%T_red) ) THEN Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%T_red) ! T_red + END IF + Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no + IF ( ALLOCATED(InData%NodesDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOF: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no + IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! INodes_Mesh_to_SD allocated yes/no + IF ( ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! INodes_Mesh_to_SD upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%INodes_Mesh_to_SD) ! INodes_Mesh_to_SD + END IF + Int_BufSz = Int_BufSz + 1 ! INodes_SD_to_Mesh allocated yes/no + IF ( ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! INodes_SD_to_Mesh upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%INodes_SD_to_Mesh) ! INodes_SD_to_Mesh + END IF + Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no + IF ( ALLOCATED(InData%ElemsDOF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF + END IF + Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no + IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes END IF Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! NModes @@ -8148,52 +7795,192 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) - CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%T_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%T_red) + END IF + IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_Mesh_to_SD,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_Mesh_to_SD,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%INodes_Mesh_to_SD)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_Mesh_to_SD))-1 ) = PACK(InData%INodes_Mesh_to_SD,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%INodes_Mesh_to_SD) + END IF + IF ( .NOT. ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_SD_to_Mesh,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_SD_to_Mesh,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%INodes_SD_to_Mesh)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_SD_to_Mesh))-1 ) = PACK(InData%INodes_SD_to_Mesh,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%INodes_SD_to_Mesh) + END IF + IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) END IF - IF ( .NOT. ALLOCATED(InData%T_red) ) THEN + IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%T_red) + IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) END IF IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SttcSolve , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 @@ -9076,6 +8863,216 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%T_red) DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesDOF)) DEALLOCATE(OutData%NodesDOF) + ALLOCATE(OutData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodesDOF,1), UBOUND(OutData%NodesDOF,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOF(i1), ErrStat2, ErrMsg2 ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) + ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_Mesh_to_SD not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%INodes_Mesh_to_SD)) DEALLOCATE(OutData%INodes_Mesh_to_SD) + ALLOCATE(OutData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%INodes_Mesh_to_SD)>0) OutData%INodes_Mesh_to_SD = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_Mesh_to_SD))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%INodes_Mesh_to_SD) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_SD_to_Mesh not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%INodes_SD_to_Mesh)) DEALLOCATE(OutData%INodes_SD_to_Mesh) + ALLOCATE(OutData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%INodes_SD_to_Mesh)>0) OutData%INodes_SD_to_Mesh = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_SD_to_Mesh))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%INodes_SD_to_Mesh) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElemsDOF)) DEALLOCATE(OutData%ElemsDOF) + ALLOCATE(OutData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) + ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) + DEALLOCATE(mask2) END IF OutData%SttcSolve = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 From c8a1858b9c9fca1db30cdc4083da2e2a6c6a4ab1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 09:08:52 -0700 Subject: [PATCH 128/377] FlexSub: using proper DOF indexing for transfer matrix to reaction point --- modules/subdyn/src/SubDyn_Output.f90 | 132 ++++++++++++--------------- 1 file changed, 60 insertions(+), 72 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index b3a81b9a5..558e3a9d6 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -219,7 +219,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ENDDO ENDDO !Store the matrix that will let me calculate single point reaction at the base of structure - CALL ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) + CALL ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) ENDIF ! These variables are to help follow the framework template, but the data in them is simply a copy of data @@ -243,57 +243,45 @@ END SUBROUTINE SDOut_Init !------------------------------------------------------------------------------------------------------ !>This subroutine allocates and calculated TIreact, Matrix to go from local reactions at constrained nodes to single point reactions -SUBROUTINE ReactMatx(Init, p, WtrDpth, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT( IN) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT( INOUT) :: p ! Parameter data - REAL(ReKi), INTENT(IN) :: WtrDpth - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +SUBROUTINE ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init !< Input data for initialization routine + REAL(ReKi), INTENT(IN ) :: WtrDpth !< Water depth + TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameter data + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables - INTEGER :: I !counter - INTEGER :: rmndr !type-column index - INTEGER :: nodeID !node ID - INTEGER(IntKi) :: DOFC ! DOFC = Init%NReact*6 - INTEGER(IntKi) :: iiDOF, iNode, nDOFPerNode ! - REAL(ReKi) :: dx, dy, dz ! distances from reaction points to subdyn origin (mudline) - REAL(ReKi), dimension(6) :: Line + INTEGER :: I !counter + INTEGER(IntKi) :: iDOF, iiDOF, iNode, nDOFPerNode ! + REAL(ReKi) :: dx, dy, dz ! distances from reaction points to subdyn origin (mudline) + REAL(ReKi), dimension(6) :: Line ErrStat=ErrID_None ErrMsg="" - DOFC = p%nNodes_C*6 ! bjj, this is p%DOFC !Total DOFs at the base of structure + CALL AllocAry(p%TIreact, 6, p%nDOFC, 'TIReact', ErrStat, ErrMsg); if ( ErrStat /= ErrID_None ) return - CALL AllocAry(p%TIreact, 6, DOFC, 'p%TIReact', ErrStat, ErrMsg ) - if ( ErrStat /= ErrID_None ) return - - p%TIreact=0 !Initialize - - DO I=1,3 !Take care of first three rows - p%TIreact(I,I:DOFC:6)=1 - ENDDO - - !Other rows done per column actually - DO I = 1, DOFC - nodeID = p%Nodes_C(ceiling(I/6.0),1) !Constrained Node ID (this works in the reordered/renumbered p%Nodes_C) + ! --- TI: Transformation matrix from interface points to ref point + p%TIreact(1:6,:)=0 !Initialize + DO I = 1, p%nDOFC + iDOF = p%IDC(I) ! DOF index in constrained system + iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + if ((iiDOF<1) .or. (iiDOF>6)) then + ErrMsg = 'ReactMatx, interface node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + return + endif + if (nDOFPerNode/=6) then + ErrMsg = 'ReactMatx, interface node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + return + endif - dx = Init%Nodes(nodeID, 2) - dy = Init%Nodes(nodeID, 3) - dz = Init%Nodes(nodeID, 4) + WtrDpth - - rmndr = MOD(I, 6) !It gives me the column index among the 6 different kinds - SELECT CASE (rmndr) - CASE (1); p%TIreact(4:6, I) = (/0.0_ReKi , dz , -dy/) - CASE (2); p%TIreact(4:6, I) = (/-dz , 0.0_ReKi , dx/) - CASE (3); p%TIreact(4:6, I) = (/dy , -dx , 0.0_ReKi/) - CASE (4); p%TIreact(4:6, I) = (/1.0_ReKi , 0.0_ReKi , 0.0_ReKi/) - CASE (5); p%TIreact(4:6, I) = (/0.0_ReKi , 1.0_ReKi , 0.0_ReKi/) - CASE (0); p%TIreact(4:6, I) = (/0.0_ReKi , 0.0_ReKi , 1.0_ReKi/) - CASE DEFAULT - ErrStat = ErrID_Fatal - ErrMsg = 'Error calculating transformation matrix TIreact, wrong column index ' - RETURN - END SELECT - !print*,'TIr',p%TIreact(:, I) - ENDDO + dx = Init%Nodes(iNode, 2) + dy = Init%Nodes(iNode, 3) + dz = Init%Nodes(iNode, 4) + WtrDpth + + CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line + p%TIreact(1:6, I) = Line + enddo END SUBROUTINE ReactMatx @@ -336,12 +324,12 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array yout =0 !Initialize and populate with Y2 data - yout(1: p%UrbarL ) = m%UR_bar + yout(1: p%UrbarL ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red yout(p%URbarL+1:p%URbarL+p%nDOFL) = m%UL !Same for a variable that deals with Udotdot uddout =0 !Initialize and populate with Udotdot data - uddout(1 : p%URbarL ) = m%UR_bar_dotdot + uddout(1 : p%URbarL ) = m%UR_bar_dotdot ! TODO TODO TODO look at U_full_dotdot U_red_dotdot uddout(p%URbarL+1 : p%URbarL+p%nDOFL ) = m%UL_dotdot ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency @@ -503,31 +491,31 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg END SUBROUTINE SDOut_MapOutputs !==================================================================================================== - SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, K2,FM_nod,FK_nod) - !This function calculates for the given element the static and dynamic forces, given K and M of the element, and - !output quantities Udotdot and Y2 containing the - !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked +!> Calculates static and dynamic forces for a given element, using K and M of the element, and +!output quantities Udotdot and Y2 containing the +!and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked !---------------------------------------------------------------------------------------------------- - Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) - Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces - Integer(IntKi), INTENT(IN) :: K2 !1 or 2 depending on node of interest - REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments - !Locals - INTEGER(IntKi) :: L !counter - REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage - - FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE - FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE - FF_glb = FF_glb - Fg ! GLOBAL REFERENCE - DO L=1,4 ! Transforming coordinates 3 at a time - FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) - FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) - ENDDO - FM_nod=FM_elm(6*(k2-1)+1:k2*6) ! k2=1, 1:6, k2=2 7:12 - FK_nod=FF_elm(6*(k2-1)+1:k2*6) - - END SUBROUTINE CALC_NODE_FORCES +SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, K2,FM_nod,FK_nod) + Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) + Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces + Integer(IntKi), INTENT(IN) :: K2 !1 or 2 depending on node of interest + REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments + !Locals + INTEGER(IntKi) :: L !counter + REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage + + FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE + FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE + FF_glb = FF_glb - Fg ! GLOBAL REFERENCE + DO L=1,4 ! Transforming coordinates 3 at a time + FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) + FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) + ENDDO + FM_nod=FM_elm(6*(k2-1)+1:k2*6) ! k2=1, 1:6, k2=2 7:12 + FK_nod=FF_elm(6*(k2-1)+1:k2*6) + +END SUBROUTINE CALC_NODE_FORCES !==================================================================================================== SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) From d1a7ac0e845a991a35fdef8d890db63e39e94556 Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Fri, 10 Jan 2020 12:41:46 -0700 Subject: [PATCH 129/377] Negligible edits prior to committing Morison changes. --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 6 ++++-- modules/hydrodyn/src/Morison.f90 | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 81815118e..01251802f 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -258,6 +258,8 @@ PROGRAM HydroDynDriver STOP END IF + PRINT *, 'NBody is '//trim(Num2LStr(NBody))//' and planning to read in '//trim(Num2LStr(7+6*NBODY))//' columns from the input file' + DO n = 1,drvrInitInp%NSteps READ (UnWAMITInp,*,IOSTAT=ErrStat) (WAMITin (n,J), J=1,7+6*NBODY) @@ -503,7 +505,7 @@ PROGRAM HydroDynDriver CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'PRP orientation', ErrStat, ErrMsg ) u(1)%PRPMesh%Orientation(:,:,1) = dcm DO I=1, NBody - CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,6*I+5),ReKi), REAL(WAMITin(n,6*I+6),ReKi), REAL(WAMITin(n,6*I+7),ReKi), dcm, 'body '//I//' orientation', ErrStat, ErrMsg ) + CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,6*I+5),ReKi), REAL(WAMITin(n,6*I+6),ReKi), REAL(WAMITin(n,6*I+7),ReKi), dcm, 'body orientation', ErrStat, ErrMsg ) u(1)%PRPMesh%Orientation(:,:,1) = dcm END DO @@ -550,7 +552,7 @@ PROGRAM HydroDynDriver u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - 2*WAMITin(n, 6*I+5:6*I+7) + WAMITin(n-1, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) END DO - END + END IF END IF !@mhall: end of addition diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 6a7a06efd..88e205672 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2157,7 +2157,7 @@ SUBROUTINE SetSplitNodeProperties( numNodes, nodes, numElements, elements, ErrSt nodes(element%Node2Indx)%MGdensity = 0.0 END IF - !@mhall: if this node is Node 1 of the element in question... ? + !@mhall: if this node is Node I of the element in question... ? IF ( element%Node1Indx == I ) THEN IF ( nodes(I)%tMG > 0 ) THEN From 962f6af5399f1e9edb90751dc58fc721a8d89413 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 13:32:26 -0700 Subject: [PATCH 130/377] FlexSub: fix missing init in nDOFC --- modules/subdyn/src/SubDyn.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 7d35ee934..140a3b71f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2312,6 +2312,7 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) p%nDOFI = p%nDOFI + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) enddo ! Reaction DOFs + p%nDOFC =0 do iiNode= 1,p%nNodes_C p%nDOFC = p%nDOFC + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) enddo From 54c1ecd5ede7cff6b989c897e0edd394896332ee Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 15:22:47 -0700 Subject: [PATCH 131/377] FlexSub: fix summary file mass --- modules/subdyn/src/SubDyn.f90 | 131 ++++++++++++++-------------------- 1 file changed, 55 insertions(+), 76 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 140a3b71f..339c95aa4 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2446,7 +2446,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file - INTEGER(IntKi) :: i, j, k, propids(2) !counter and temporary holders + INTEGER(IntKi) :: i, j, k, propIDs(2), Iprop(2) !counter and temporary holders INTEGER(IntKi) :: mType ! Member Type Real(ReKi) :: mMass, mLength ! Member mass and length REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix @@ -2515,16 +2515,24 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers WRITE(UnSum, '(A,I6)') 'Number of nodes per member:', Init%Ndiv+1 WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' + DO i=1,size(Init%PropSetsB,1) + print*,'psb',Init%PropSetsB(i,:) + enddo + DO i=1,size(Init%PropsB,1) + print*,'pb ',Init%PropsB(i,:) + enddo DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS - propids=p%Elems(i,iMProp:iMProp+1) ! TODO use member + propIDs=Init%Members(i,iMProp:iMProp+1) mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length IF (ErrStat .EQ. ErrID_None) THEN mType = Init%Members(I, iMType) ! if (mType==idMemberBeam) then - mMass= MemberMass(Init%PropSetsB(propids(1),4),Init%PropSetsB(propids(1),5),Init%PropSetsB(propids(1),6), & - Init%PropSetsB(propids(2),4),Init%PropSetsB(propids(2),5),Init%PropSetsB(propids(2),6), mLength, .TRUE.) + iProp(1) = FINDLOCI(Init%PropSetsB(:,1), propIDs(1)) + iProp(2) = FINDLOCI(Init%PropSetsB(:,1), propIDs(2)) + mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & + Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, .TRUE.) WRITE(UnSum, '(I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) @@ -2735,7 +2743,8 @@ SUBROUTINE Y2Mesh_SD_Mapping(p, MeshtoSD) END SUBROUTINE Y2Mesh_SD_Mapping !------------------------------------------------------------------------------------------------------ -!> This function calculates the length of a member +!> Calculate length of a member as given in input file +!! Joints and Members ID have not been reindexed (Elems and Nodes have) FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) TYPE(SD_InitType), INTENT(IN) :: Init !< Input data for initialization routine, this structure contains many variables needed for summary file INTEGER(IntKi), INTENT(IN) :: MemberID !< Member ID # @@ -2743,87 +2752,57 @@ FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None !Locals - REAL(Reki) :: xyz1(3),xyz2(3) ! Coordinates of joints in GLOBAL REF SYS - INTEGER(IntKi) :: i ! Counter - INTEGER(IntKi) :: Joint1,Joint2 ! JointID - CHARACTER(*), PARAMETER :: RoutineName = 'MemberLength' + REAL(Reki) :: xyz1(3),xyz2(3) ! Coordinates of joints in GLOBAL REF SYS + integer(IntKi) :: iMember !< Member index in Init%Members list + INTEGER(IntKi) :: Joint1,Joint2 ! JointID + CHARACTER(*), PARAMETER :: RoutineName = 'MemberLength' ErrStat = ErrID_None ErrMsg = '' MemberLength=0.0 !Find the MemberID in the list - DO i=1,SIZE(Init%Members, DIM=1) - IF (Init%Members(i,1) .EQ. MemberID) THEN - ! Find joints ID for this member - Joint1 = FindNode(i,1); if (Joint1<0) return - Joint2 = FindNode(i,2); if (Joint2<0) return - xyz1= Init%Joints(Joint1,2:4) - xyz2= Init%Joints(Joint2,2:4) - MemberLength=SQRT( SUM((xyz2-xyz1)**2.) ) - if ( EqualRealNos(MemberLength, 0.0_ReKi) ) then - call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' has zero length!', ErrStat,ErrMsg,RoutineName); - return - endif - return - ENDIF - ENDDO - call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' not found in member list!', ErrStat,ErrMsg,RoutineName); - -contains - !> Find JointID for node `iNode` (1 or 2) or member `iMember` - integer(IntKi) function FindNode(iMember,iNode) result(j) - integer(IntKi), intent(in) :: iMember !< Member index in Init%Members list - integer(IntKi), intent(in) :: iNode !< Node index, 1 or 2 for the member iMember - logical :: found - found = .false. - j=1 - do while ( .not. found .and. j <= Init%NJoints ) - if (Init%Members(iMember, iNode+1) == nint(Init%Joints(j,1))) then ! Columns 2/3 for iNode 1/2 - found = .true. - exit - endif - j = j + 1 - enddo - if (.not.found) then - j=-1 - call SetErrStat(ErrID_Fatal,' Member '//trim(Num2LStr(iMember))//' has JointID'//trim(Num2LStr(iNode))//' = '//& - trim(Num2LStr(Init%Members(iMember,iNode+1)))//' which is not in the node list !', ErrStat,ErrMsg,RoutineName) - endif - end function - + iMember = FINDLOCI(Init%Members(:,1), MemberID) + if (iMember<=0) then + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' not found in member list!', ErrStat,ErrMsg,RoutineName); + return + endif + ! Find joints ID for this member + Joint1 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,2)) + Joint2 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,3)) + xyz1= Init%Joints(Joint1,2:4) + xyz2= Init%Joints(Joint2,2:4) + MemberLength=SQRT( SUM((xyz2-xyz1)**2.) ) + if ( EqualRealNos(MemberLength, 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' has zero length!', ErrStat,ErrMsg,RoutineName); + return + endif END FUNCTION MemberLength !------------------------------------------------------------------------------------------------------ !> Calculate member mass, given properties at the ends, keep units consistent !! For now it works only for circular pipes or for a linearly varying area -FUNCTION MemberMass(rho1,D1,t1,rho2,D2,t2,L,ctube) - REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member - ! IF ctube=.FALSE. then D1/2=Area at end1/2, t1 and t2 are ignored - REAL(ReKi) :: MemberMass !mass - LOGICAL, INTENT(IN) :: ctube ! =TRUE for circular pipes, false elseshape - !LOCALS - REAL(ReKi) ::a0,a1,a2,b0,b1,dd,dt !temporary coefficients - - !Density allowed to vary linearly only - b0=rho1 - b1=(rho2-rho1)/L - !Here we will need to figure out what element it is for now circular pipes - IF (ctube) THEN !circular tube - a0=pi * (D1*t1-t1**2.) - dt=t2-t1 !thickness variation - dd=D2-D1 !OD variation - a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L - a2=pi * ( dd*dt-dt**2.)/L**2. - - ELSE !linearly varying area - a0=D1 !This is an area - a1=(D2-D1)/L !Delta area - a2=0. - - ENDIF - MemberMass= b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz - -END FUNCTION MemberMass +FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,ctube) + REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member + LOGICAL, INTENT(IN) :: ctube ! =TRUE for circular pipes, false elseshape + REAL(ReKi) :: BeamMass !mass + REAL(ReKi) :: a0,a1,a2,b0,b1,dd,dt !temporary coefficients + !Density allowed to vary linearly only + b0=rho1 + b1=(rho2-rho1)/L + !Here we will need to figure out what element it is for now circular pipes + IF (ctube) THEN !circular tube + a0=pi * (D1*t1-t1**2.) + dt=t2-t1 !thickness variation + dd=D2-D1 !OD variation + a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L + a2=pi * ( dd*dt-dt**2.)/L**2. + ELSE !linearly varying area + a0=D1 !This is an area + a1=(D2-D1)/L !Delta area + a2=0. + ENDIF + BeamMass= b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz +END FUNCTION BeamMass !------------------------------------------------------------------------------------------------------ !> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR From 26aed9e4fcd9e64fe9badcd7fd859e9c6f9a02b1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 15:58:41 -0700 Subject: [PATCH 132/377] FlexSub: removed some duplicate variables --- modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src/SubDyn.f90 | 182 ++++++++++++------------- modules/subdyn/src/SubDyn_Output.f90 | 71 +++++----- modules/subdyn/src/SubDyn_Registry.txt | 7 +- modules/subdyn/src/SubDyn_Types.f90 | 35 +---- 5 files changed, 130 insertions(+), 167 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 5b6699d02..36c4de4fe 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -381,7 +381,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. ! check the number of interior modes - IF ( p%Nmodes > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN + IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))) RETURN ENDIF diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 339c95aa4..20073b6a0 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -83,7 +83,9 @@ SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) ,Force = .TRUE. & ,Moment = .TRUE. ) END SUBROUTINE CreateTPMeshes - +!--------------------------------------------------------------------------- +!> Create output (Y2, for motion) and input (u, for forces)meshes, based on SubDyn nodes +!! Ordering of nodes is: I (interface), L (internal), C (bottom) SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh, outputMesh, ErrStat, ErrMsg ) INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) @@ -148,8 +150,6 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) END SUBROUTINE CreateY2Meshes - - !--------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -255,10 +255,10 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL Craig_Bampton(Init, p, m, CBparams, ErrStat2, ErrMsg2); if(Failed()) return ! --- Initial system states - IF ( p%qmL > 0 ) THEN - CALL AllocAry(x%qm, p%qmL, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(x%qmdot, p%qmL, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(m%qmdotdot, p%qmL, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return + IF ( p%nDOFM > 0 ) THEN + CALL AllocAry(x%qm, p%nDOFM, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(x%qmdot, p%nDOFM, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(m%qmdotdot, p%nDOFM, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return x%qm = 0.0_ReKi x%qmdot = 0.0_ReKi m%qmdotdot= 0.0_ReKi @@ -355,7 +355,7 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m ErrStat = ErrID_None ! no error has occurred ErrMsg = "" - IF ( p%qml == 0) RETURN ! no retained modes = no states + IF ( p%nDOFM == 0) RETURN ! no retained modes = no states IF (p%IntMethod .eq. 1) THEN CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) @@ -422,13 +422,13 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] - IF ( p%qml > 0) THEN + IF ( p%nDOFM > 0) THEN m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? + p%F2_61 ! + F2(6) ] - ELSE ! There are no states when p%qml=0 (i.e., no retained modes: p%Nmodes=0), so we omit those portions of the equations + ELSE ! There are no states when p%nDOFM=0 (i.e., no retained modes: p%nDOFM=0), so we omit those portions of the equations m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] @@ -440,8 +440,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? m%UL = m%UL + ULS - IF ( p%qml > 0) THEN - UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%qmL), FLt(1:p%qmL) ) + IF ( p%nDOFM > 0) THEN + UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) m%UL = m%UL - UL0M END IF ENDIF @@ -493,7 +493,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D - IF ( p%qml > 0) THEN + IF ( p%nDOFM > 0) THEN Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) @@ -517,7 +517,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) IF ( p%OutSwtch > 0 ) THEN ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file !find xdot at t - IF ( p%NModes > 0 ) THEN + IF ( p%nDOFM > 0 ) THEN ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear @@ -584,11 +584,11 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ErrMsg = "" ! INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here - CALL AllocAry(dxdt%qm, p%qmL, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) - CALL AllocAry(dxdt%qmdot, p%qmL, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + CALL AllocAry(dxdt%qm, p%nDOFM, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + CALL AllocAry(dxdt%qmdot, p%nDOFM, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) IF ( ErrStat >= AbortErrLev ) RETURN - IF ( p%qmL == 0 ) RETURN + IF ( p%nDOFM == 0 ) RETURN ! form u(3) in Eq. 10: m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) @@ -706,16 +706,16 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) IF (Init%CBMod) THEN ! Nmodes - Number of interal modes to retain. - CALL ReadIVar ( UnIn, SDInputFile, p%Nmodes, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, p%nDOFM, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - IF (Check( p%Nmodes < 0 , 'Nmodes must be a non-negative integer.')) return + IF (Check( p%nDOFM < 0 , 'Nmodes must be a non-negative integer.')) return - if ( p%Nmodes > 0 ) THEN + if ( p%nDOFM > 0 ) THEN ! Damping ratios for retained modes - CALL AllocAry(Init%JDampings, p%Nmodes, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + CALL AllocAry(Init%JDampings, p%nDOFM, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return Init%JDampings=WrongNo !Initialize - CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%Nmodes, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); + CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%nDOFM, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the ! last entry to fill in remaining values. !Check 1st value, we need at least one good value from user or throw error @@ -723,12 +723,12 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL Fatal('Damping ratio should be larger than 0 and less than 100') return ELSE - DO I = 2, p%Nmodes + DO I = 2, p%nDOFM IF ( Init%JDampings(I) .EQ. WrongNo ) THEN - Init%Jdampings(I:p%Nmodes)=Init%JDampings(I-1) + Init%Jdampings(I:p%nDOFM)=Init%JDampings(I-1) IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) ErrStat = ErrID_Info - ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%Nmodes))//'.' + ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%nDOFM))//'.' END IF EXIT ELSEIF ( ( Init%JDampings(I) < 0 ) .OR.( Init%JDampings(I) >= 100.0 ) ) THEN @@ -738,7 +738,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ENDDO ENDIF IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings - WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%Nmodes,NWTC_MaxAryLen)) + WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%nDOFM,NWTC_MaxAryLen)) END IF ELSE CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -746,7 +746,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet !note at this stage I do not know nDOFL yet; Nmodes will be updated later for the FULL FEM CASE. - p%Nmodes = -1 + p%nDOFM = -1 !Ignore next line CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !Read 1 damping value for all modes @@ -758,7 +758,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ENDIF ENDIF -IF ((p%Nmodes > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%Nmodes is undefined, but if Nmodes=0 then JDampings does not exist +IF ((p%nDOFM > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%nDOFM is undefined, but if Nmodes=0 then JDampings does not exist Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings END IF @@ -1375,7 +1375,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables TYPE(SD_InputType) :: u_interp ! interpolated value of inputs - REAL(ReKi) :: junk2(2*p%qml) !temporary states (qm and qmdot only) + REAL(ReKi) :: junk2(2*p%nDOFM) !temporary states (qm and qmdot only) REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP REAL(ReKi) :: UFL2(p%nDOFL) ! temporary copy of UFL INTEGER(IntKi) :: ErrStat2 @@ -1403,8 +1403,8 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - junk2( 1: p%qml)=p%SDDeltaT * x%qmdot !upper portion of array - junk2(1+p%qml:2*p%qml)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array + junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D !.................................................... @@ -1416,8 +1416,8 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg !IF ( ErrStat >= AbortErrLev ) RETURN ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: - x%qm = x%qm - junk2( 1: p%qml) - x%qmdot = x%qmdot - junk2(p%qml+1:2*p%qml) + x%qm = x%qm - junk2( 1: p%nDOFM) + x%qmdot = x%qmdot - junk2(p%nDOFM+1:2*p%nDOFM) ! clean up temporary variable(s) CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) @@ -1450,11 +1450,8 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None ErrMsg = "" - - ! --- Partitioon DOFs and Nodes into sets: I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior !! Partition Nodes into: Nodes_I (Interf), Nodes_C (React), Nodes_L !! Partitions the DOF index arrays into IDR=[IDC, ICI] and IDL (interior) @@ -1463,13 +1460,13 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes - IF(p%Nmodes > p%nDOFL) THEN + IF(p%nDOFM > p%nDOFL) THEN CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than number of internal DOFs. ',ErrStat,ErrMsg,'Craig_Bampton') CALL CleanupCB() RETURN ENDIF ELSE ! full FEM - p%Nmodes = p%nDOFL + p%nDOFM = p%nDOFL !Jdampings need to be reallocated here because nDOFL not known during Init !So assign value to one temporary variable JDamping1=Init%Jdampings(1) @@ -1477,30 +1474,25 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL AllocAry( Init%JDampings, p%nDOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return Init%JDampings = JDamping1 ! set default values for all modes ENDIF - CBparams%nDOFM = p%Nmodes ! retained modes (all if no C-B reduction) - - ! matrix dimension paramters - p%qmL = p%Nmodes ! Length of 1/2 x array, x1 that is (note, do this after check if CBMod is true [Nmodes modified if CMBod is false]) - p%URbarL = p%nDOFI ! Length of URbar array, subarray of Y2 : THIS MAY CHANGE IF SOME DOFS ARE NOT CONSTRAINED - CALL AllocParameters(p, CBparams%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - - CALL AllocAry( MRR, p%nDOFR, p%nDOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MLL, p%nDOFL, p%nDOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MRL, p%nDOFR, p%nDOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRR, p%nDOFR, p%nDOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KLL, p%nDOFL, p%nDOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRL, p%nDOFR, p%nDOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGL, p%nDOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGR, p%nDOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + + CALL AllocAry( MRR, p%nDOFR, p%nDOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MLL, p%nDOFL, p%nDOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, p%nDOFR, p%nDOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, p%nDOFR, p%nDOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KLL, p%nDOFL, p%nDOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, p%nDOFR, p%nDOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGL, p%nDOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, p%nDOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBB, p%nDOFR, p%nDOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBM, p%nDOFR, CBparams%nDOFM,'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%KBB, p%nDOFR, p%nDOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%TI2, p%nDOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( CBparams%MBB, p%nDOFR, p%nDOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, p%nDOFR, p%nDOFM, 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, p%nDOFR, p%nDOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%TI2, p%nDOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on @@ -1517,7 +1509,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! CBparams%PhiR from Eq. 3 ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. !................................ - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, CBparams%nDOFM, Init, & ! < inputs + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFM, Init, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) ! TODO TODO TODO DAMPING MATRIX if(Failed()) return @@ -1531,18 +1523,18 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) ! "b" stands for "bar"; "t" stands for "tilde" - CALL AllocAry( MBBb, p%nDOFI, p%nDOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MBmb, p%nDOFI, CBparams%nDOFM,'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KBBb, p%nDOFI, p%nDOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( PhiRb, p%nDOFL, p%nDOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGRb, p%nDOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBBb, p%nDOFI, p%nDOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBmb, p%nDOFI, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KBBb, p%nDOFI, p%nDOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( PhiRb, p%nDOFL, p%nDOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGRb, p%nDOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return !................................ ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to ! MBBb, MBMb, KBBb, PHiRb, FGRb ! (throw out rows/columns of first matrices to create second matrices) !................................ - CALL CBApplyConstr(p%nDOFI, p%nDOFR, CBparams%nDOFM, p%nDOFL, & + CALL CBApplyConstr(p%nDOFI, p%nDOFR, p%nDOFM, p%nDOFL, & CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & MBBb, MBMb, KBBb, PHiRb, FGRb) ! TODO TODO TODO Transform new damping matrix as well @@ -2035,7 +2027,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOFI, p%nDOFI) - REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOFI, p%Nmodes) + REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOFI, p%nDOFM) REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOFI, p%nDOFI) REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOFL, p%nDOFL) REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOFL, p%nDOFI) @@ -2072,17 +2064,17 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt !p%D1_15=-TI_transpose !this is 6x6NIN - IF ( p%NModes > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%NModes == 0 + IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') p%MMB = TRANSPOSE( p%MBM ) != MMBt - p%PhiM = PhiL(:,1:p%Nmodes) + p%PhiM = PhiL(:,1:p%nDOFM) ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) - p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%Nmodes) * OmegaL(1:p%Nmodes) ! OmegaM is a one-dimensional array - p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%Nmodes) * Init%JDampings(1:p%Nmodes) ! Init%JDampings is also a one-dimensional array + p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array + p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array ! B_23, B_24 !p%PhiM_T = TRANSPOSE( p%PhiM ) @@ -2092,7 +2084,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%FX = MATMUL( FGL, p%PhiM ) != MATMUL( TRANSPOSE(PhiM), FGL ) because FGL is 1-D ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) - DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=nDOFM == 0), this loop is skipped + DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) ENDDO @@ -2116,7 +2108,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! C2_21, C2_42 ! C2_61, C2_62 - DO I = 1, p%Nmodes ! if (p%NModes=p%qmL=nDOFM == 0), this loop is skipped + DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) ENDDO @@ -2133,23 +2125,23 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%F2_61 = MATMUL( p%D2_64, FGL ) !Now calculate a Jacobian used when AM2 is called and store in parameters - IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%qmL > 0) - n=2*p%qmL + IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%nDOFM > 0) + n=2*p%nDOFM CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ); if(Failed()) return ! First we calculate the Jacobian: ! (note the Jacobian is first stored as p%AM2InvJac) p%AM2Jac=0. - DO i=1,p%qmL - p%AM2Jac(i+p%qmL,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 - p%AM2Jac(i+p%qmL,i+p%qmL)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize + DO i=1,p%nDOFM + p%AM2Jac(i+p%nDOFM,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 + p%AM2Jac(i+p%nDOFM,i+p%nDOFM)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize END DO - DO I=1,p%qmL + DO I=1,p%nDOFM p%AM2Jac(I,I)=-1. !J11 - p%AM2Jac(I,p%qmL+I)=p%SDdeltaT/2. !J12 - p%AM2Jac(p%qmL+I,p%qmL+I)=p%AM2Jac(p%qmL+I,p%qmL+I)-1 !J22 complete + p%AM2Jac(I,p%nDOFM+I)=p%SDdeltaT/2. !J12 + p%AM2Jac(p%nDOFM+I,p%nDOFM+I)=p%AM2Jac(p%nDOFM+I,p%nDOFM+I)-1 !J22 complete ENDDO ! Now need to factor it: !I think it could be improved and made more efficient if we can say the matrix is positive definite @@ -2202,7 +2194,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOFL, nDOFL_TP, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') -if (p%Nmodes > 0 ) THEN +if (p%nDOFM > 0 ) THEN CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%NOmegaM2, nDOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2213,10 +2205,10 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%PhiM, p%nDOFL, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_61, p%nDOFL, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_62, p%nDOFL, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%NModes == 0 - CALL AllocAry( p%D2_63, p%nDOFL, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%NModes == 0 - CALL AllocAry( p%D2_64, p%nDOFL, p%nDOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 - CALL AllocAry( p%F2_61, p%nDOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%NModes == 0 + CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D2_63, p%nDOFL, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 + CALL AllocAry( p%D2_64, p%nDOFL, p%nDOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%F2_61, p%nDOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if if ( p%SttcSolve ) THEN @@ -2243,9 +2235,9 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. CALL AllocAry( Misc%UFL, p%nDOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar, p%URbarL, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar_dot, p%URbarL, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar_dotdot,p%URbarL, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar, p%nDOFI, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar_dot, p%nDOFI, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL, p%nDOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dot, p%nDOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dotdot, p%nDOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') @@ -2576,8 +2568,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(I6, e15.6)') ( i, FEMparams%Omega(i)/2.0/pi, i = 1, FEMparams%NOmega ) WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", CBparams%nDOFM - WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, CBparams%nDOFM ) + WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM + WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, p%nDOFM ) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full SYstem @@ -2595,8 +2587,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (no constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide - IF (CBparams%nDOFM > 0) THEN - CALL WrMatrix( CBparams%PhiL(:,1:CBparams%nDOFM ), UnSum, 'e15.6', 'PhiM' ) + IF (p%nDOFM > 0) THEN + CALL WrMatrix( CBparams%PhiL(:,1:p%nDOFM ), UnSum, 'e15.6', 'PhiM' ) ELSE WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%nDOFL)), '0' END IF @@ -2678,7 +2670,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CALL WrMatrix( CBparams%MBB, UnSum, 'e15.6', 'MBB' ) WRITE(UnSum, '(A)') SubSectionDivide - IF ( CBparams%nDOFM > 0 ) THEN + IF ( p%nDOFM > 0 ) THEN CALL WrMatrix( CBparams%MBM, UnSum, 'e15.6', 'MBM' ) ELSE WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "MBM", '6', '0' diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 558e3a9d6..3ec98f2aa 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -286,13 +286,13 @@ SUBROUTINE ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) END SUBROUTINE ReactMatx !==================================================================================================== -SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) -! This subroutine writes the data stored in the y variable to the correct indexed postions in WriteOutput -! This is called by SD_CalcOutput() at each time step. -! This routine does fill Allouts -! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling -! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) +!> Writes the data stored in the y variable to the correct indexed postions in WriteOutput +!! This is called by SD_CalcOutput() at each time step. +!! This routine does fill Allouts +!! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling +!! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) !---------------------------------------------------------------------------------------------------- +SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds TYPE(SD_InputType), INTENT( IN ) :: u ! SubDyn module's input data TYPE(SD_ContinuousStateType), INTENT( IN ) :: x ! SubDyn module's states data @@ -302,19 +302,17 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg REAL(ReKi), INTENT( OUT ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER(IntKi) ::I,J,K,K2,L,L2 ! Counters - INTEGER(IntKi), DIMENSION(2) ::K3 ! It stores Node IDs for element under consideration (may not be consecutive numbers) - INTEGER(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%Nmodes - REAL(ReKi), DIMENSION (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments - REAL(ReKi), DIMENSION (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments - Real(ReKi), DIMENSION (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions - REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL - - Real(ReKi), DIMENSION(p%URbarL+p%nDOFL+6*p%nNodes_C) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs - Real(ReKi), DIMENSION(p%URbarL+p%nDOFL+6*p%nNodes_C) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs + INTEGER(IntKi) :: I,J,K,K2,L,L2 ! Counters + INTEGER(IntKi), DIMENSION(2) :: K3 ! It stores Node IDs for element under consideration (may not be consecutive numbers) + INTEGER(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM + REAL(ReKi), DIMENSION (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments + REAL(ReKi), DIMENSION (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments + Real(ReKi), DIMENSION (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions + REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL + Real(ReKi), DIMENSION(p%nDOFI+p%nDOFL+p%nDOFC) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs + Real(ReKi), DIMENSION(p%nDOFI+p%nDOFL+p%nDOFC) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs Integer(IntKi) ::sgn !+1/-1 for node force calculations type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities ErrStat = ErrID_None @@ -324,26 +322,26 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array yout =0 !Initialize and populate with Y2 data - yout(1: p%UrbarL ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red - yout(p%URbarL+1:p%URbarL+p%nDOFL) = m%UL + yout(1: p%nDOFI ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red + yout(p%nDOFI+1:p%nDOFI+p%nDOFL) = m%UL !Same for a variable that deals with Udotdot uddout =0 !Initialize and populate with Udotdot data - uddout(1 : p%URbarL ) = m%UR_bar_dotdot ! TODO TODO TODO look at U_full_dotdot U_red_dotdot - uddout(p%URbarL+1 : p%URbarL+p%nDOFL ) = m%UL_dotdot + uddout(1 : p%nDOFI ) = m%UR_bar_dotdot ! TODO TODO TODO look at U_full_dotdot U_red_dotdot + uddout(p%nDOFI+1 : p%nDOFI+p%nDOFL ) = m%UL_dotdot - ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency + ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency - ! Only generate member-based outputs for the number of user-requested member outputs - !Now store and identify needed output as requested by user - !p%MOutLst has the mapping for the member, node, elements per node, to be used - !MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) - !Inertial Load for the elements that are needed - if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 - DO I=1,p%NMOutputs - !I know el # and whether it is 1st node or second node - pLst=>p%MOutLst(I) - DO J=1,pLst%NOutCnt !Iterate on requested nodes for that member + ! Only generate member-based outputs for the number of user-requested member outputs + !Now store and identify needed output as requested by user + !p%MOutLst has the mapping for the member, node, elements per node, to be used + !MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) + !Inertial Load for the elements that are needed + if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 + DO I=1,p%NMOutputs + !I know el # and whether it is 1st node or second node + pLst=>p%MOutLst(I) + DO J=1,pLst%NOutCnt !Iterate on requested nodes for that member !I need to average across potentially up to 2 elements !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second K = pLst%ElmIDs(J,1) !element number @@ -383,7 +381,6 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average ENDIF - ! Store in AllOuts !Forces and moments AllOuts(MNfmKe (:,J,I)) = FK_elm2 !static forces and moments (6) Local Ref @@ -396,9 +393,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations AllOuts(MNTRAe (1:3,J,I)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref AllOuts(MNTRAe (4:6,J,I)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref - ENDDO ! J, Loop on requested nodes for that member - ENDDO ! I, Loop on member outputs END IF @@ -434,7 +429,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ! Assign all SSqm, SSqmdot, SSqmdotdot ! We only have space for the first 99 values - maxOutModes = min(p%Nmodes,99) + maxOutModes = min(p%nDOFM,99) IF ( maxOutModes > 0 ) THEN !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) Allouts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) @@ -736,7 +731,7 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) InvalidOutput = .FALSE. ! mark invalid output channels: - DO k=p%Nmodes+1,99 + DO k=p%nDOFM+1,99 InvalidOutput(SSqm01 +k-1) = .true. InvalidOutput(SSqmd01 +k-1) = .true. InvalidOutput(SSqmdd01+k-1) = .true. diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 74dcb983e..6b36d03f2 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -38,8 +38,7 @@ typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connect typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" # CB_MatArrays: Matrices and arrays for CB summary -typedef SubDyn/SD CB_MatArrays INTEGER nDOFM - - - "retained degrees of freedom (modes)" -typedef ^ CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" +typedef SubDyn/SD CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" @@ -179,9 +178,8 @@ typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indice typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" # --- CB reduction +typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType Logical SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" -typedef ^ ParameterType IntKi NModes - - - "Number of modes to retain in C-B method" -typedef ^ ParameterType IntKi qmL - - - "Length of state array" typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" @@ -224,7 +222,6 @@ typedef ^ ParameterType IntKi IDL {:} - - "Index array of the internal dofs" typedef ^ ParameterType IntKi IDC {:} - - "Index array of the contraint dofs" typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and restraint dofs" typedef ^ ParameterType IntKi IDY {:} - - "Index array of the all dofs in Y2" -typedef ^ ParameterType IntKi URbarL - - - "Length of URbar, subarray of y2 array (DOFRb)" typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" # --- Outputs typedef ^ ParameterType IntKi NAvgEls - 2 - "Max number of elements that should be averaged when calculating outputs at nodes" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index d9a7c9e5d..882073256 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -70,7 +70,6 @@ MODULE SubDyn_Types ! ======================= ! ========= CB_MatArrays ======= TYPE, PUBLIC :: CB_MatArrays - INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI2 !< TI2 matrix to refer to total mass to (0,0,0) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] @@ -219,9 +218,8 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] + INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] LOGICAL :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] - INTEGER(IntKi) :: NModes !< Number of modes to retain in C-B method [-] - INTEGER(IntKi) :: qmL !< Length of state array [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -263,7 +261,6 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC !< Index array of the contraint dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDY !< Index array of the all dofs in Y2 [-] - INTEGER(IntKi) :: URbarL !< Length of URbar, subarray of y2 array (DOFRb) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] INTEGER(IntKi) :: NAvgEls = 2 !< Max number of elements that should be averaged when calculating outputs at nodes [-] INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] @@ -1645,7 +1642,6 @@ SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCo ! ErrStat = ErrID_None ErrMsg = "" - DstCB_MatArraysData%nDOFM = SrcCB_MatArraysData%nDOFM IF (ALLOCATED(SrcCB_MatArraysData%TI2)) THEN i1_l = LBOUND(SrcCB_MatArraysData%TI2,1) i1_u = UBOUND(SrcCB_MatArraysData%TI2,1) @@ -1811,7 +1807,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! TI2 allocated yes/no IF ( ALLOCATED(InData%TI2) ) THEN Int_BufSz = Int_BufSz + 2*2 ! TI2 upper/lower bounds for each dimension @@ -1874,8 +1869,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%TI2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2021,8 +2014,6 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%nDOFM = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI2 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6589,9 +6580,8 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%DOFtilde2Nodes = SrcParamData%DOFtilde2Nodes ENDIF + DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve - DstParamData%NModes = SrcParamData%NModes - DstParamData%qmL = SrcParamData%qmL IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN i1_l = LBOUND(SrcParamData%NOmegaM2,1) i1_u = UBOUND(SrcParamData%NOmegaM2,1) @@ -7040,7 +7030,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%IDY = SrcParamData%IDY ENDIF - DstParamData%URbarL = SrcParamData%URbarL IF (ALLOCATED(SrcParamData%FGL)) THEN i1_l = LBOUND(SrcParamData%FGL,1) i1_u = UBOUND(SrcParamData%FGL,1) @@ -7445,9 +7434,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes END IF + Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve - Int_BufSz = Int_BufSz + 1 ! NModes - Int_BufSz = Int_BufSz + 1 ! qmL Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no IF ( ALLOCATED(InData%NOmegaM2) ) THEN Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension @@ -7621,7 +7609,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*1 ! IDY upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%IDY) ! IDY END IF - Int_BufSz = Int_BufSz + 1 ! URbarL Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no IF ( ALLOCATED(InData%FGL) ) THEN Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension @@ -7982,11 +7969,9 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SttcSolve , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NModes + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%qmL + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SttcSolve , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8499,8 +8484,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%IDY)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDY))-1 ) = PACK(InData%IDY,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%IDY) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%URbarL - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%FGL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9074,11 +9057,9 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) DEALLOCATE(mask2) END IF - OutData%SttcSolve = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%NModes = IntKiBuf( Int_Xferred ) + OutData%nDOFM = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%qmL = IntKiBuf( Int_Xferred ) + OutData%SttcSolve = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated Int_Xferred = Int_Xferred + 1 @@ -9921,8 +9902,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%IDY) DEALLOCATE(mask1) END IF - OutData%URbarL = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated Int_Xferred = Int_Xferred + 1 ELSE From ad3b5a5ead7590907c3889cafddf325302a994d6 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 16:48:57 -0700 Subject: [PATCH 133/377] FlexSub: explicit index names in sdout mapping --- modules/subdyn/src/SubDyn.f90 | 10 +- modules/subdyn/src/SubDyn_Output.f90 | 291 +++++++++++++-------------- 2 files changed, 149 insertions(+), 152 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 20073b6a0..1845aebe4 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -447,14 +447,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ENDIF ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI) = m%UR_bar - m%U_red (p%IDC) = 0 !!! TODO, might not be generic m%U_red (p%IDL) = m%UL + m%U_red (p%IDC) = 0 !!! TODO, might not be generic m%U_red_dot (p%IDI) = m%UR_bar_dot - m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic m%U_red_dot (p%IDL) = m%UL_dot + m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic m%U_red_dotdot(p%IDI) = m%UR_bar_dotdot - m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic m%U_red_dotdot(p%IDL) = m%UL_dotdot + m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic m%U_full = matmul(p%T_red, m%U_red) m%U_full_dot = matmul(p%T_red, m%U_red_dot) @@ -537,7 +537,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END IF ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations - CALL SDOut_MapOutputs(t, u,p,x,y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return + CALL SDOut_MapOutputs(t, u, p, x, y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return ! Put the output data in the WriteOutput array DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims @@ -2280,7 +2280,7 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ErrMsg = "" ! --- Count nodes per types p%nNodes_I = p%nNodes_I ! Number of interface nodes - nNodes_R = p%nNodes_C+p%nNodes_I ! Number of retained nodes + nNodes_R = p%nNodes_I+p%nNodes_C ! Number of retained nodes p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes =(TDOF-nDOFC-nDOFI)/6 = (6*p%nNodes - (p%nNodes_C+p%nNodes_I)*6 ) / 6 = p%nNodes - p%nNodes_C -p%nNodes_I ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 3ec98f2aa..48e3d34e6 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -92,6 +92,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + ! NOTE: MemberNodes >2 if nDiv>1 pLst%NodeIDs=Init%MemberNodes(pLst%MemberID,pLst%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting pLst%ElmIDs=0 !Initialize to 0 pLst%ElmNds=0 !Initialize to 0 @@ -106,7 +107,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number M = p%Elems(L,2:3) !1st and 2nd node of the k-th element !Select only the other node, not the one where elements connect to - IF (M(1) .EQ. pLst%NodeIDs(J)) then + IF (M(1) .EQ. pLst%NodeIDs(J)) then Junk=M(2) else Junk=M(1) @@ -293,37 +294,38 @@ END SUBROUTINE ReactMatx !! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) !---------------------------------------------------------------------------------------------------- SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) - REAL(DbKi), INTENT( IN ) :: CurrentTime ! Current simulation time in seconds - TYPE(SD_InputType), INTENT( IN ) :: u ! SubDyn module's input data - TYPE(SD_ContinuousStateType), INTENT( IN ) :: x ! SubDyn module's states data - TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), target,INTENT( IN ) :: p ! SubDyn module's parameter data - TYPE(SD_MiscVarType), INTENT( INOUT ) :: m ! Misc/optimization variables - REAL(ReKi), INTENT( OUT ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(DbKi), intent( in ) :: CurrentTime ! Current simulation time in seconds + type(SD_InputType), intent( in ) :: u ! SubDyn module's input data + type(SD_ContinuousStateType), intent( in ) :: x ! SubDyn module's states data + type(SD_OutputType), intent( inout ) :: y ! SubDyn module's output data + type(SD_ParameterType), target,intent( in ) :: p ! SubDyn module's parameter data + type(SD_MiscVarType), intent( inout ) :: m ! Misc/optimization variables + real(ReKi), intent( out ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs + integer(IntKi), intent( out ) :: ErrStat ! Error status of the operation + character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals - INTEGER(IntKi) :: I,J,K,K2,L,L2 ! Counters - INTEGER(IntKi), DIMENSION(2) :: K3 ! It stores Node IDs for element under consideration (may not be consecutive numbers) - INTEGER(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM - REAL(ReKi), DIMENSION (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments - REAL(ReKi), DIMENSION (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments - Real(ReKi), DIMENSION (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), ALLOCATABLE :: ReactNs(:) !6*Nreact reactions - REAL(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL - Real(ReKi), DIMENSION(p%nDOFI+p%nDOFL+p%nDOFC) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs - Real(ReKi), DIMENSION(p%nDOFI+p%nDOFL+p%nDOFC) ::uddout ! modifications to Y2 and Udotdot to include constrained node DOFs - Integer(IntKi) ::sgn !+1/-1 for node force calculations + integer(IntKi) :: iMemberOutput, iiNode, iElem, FirstOrSecond, I, J, K2,L,L2 ! Counters + integer(IntKi), dimension(2) :: ElemNodes ! It stores Node IDs for element under consideration (may not be consecutive numbers) + integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM + real(ReKi), dimension (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments + real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments + real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions + real(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL + real(ReKi), dimension(p%nDOFI+p%nDOFL+p%nDOFC) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs + real(ReKi), dimension(p%nDOFI+p%nDOFL+p%nDOFC) :: uddout ! modifications to Y2 and Udotdot to include constrained node DOFs + integer(IntKi) ::sgn !+1/-1 for node force calculations type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities + real(ReKi), dimension(2),parameter :: NodeNumber_To_Sign = (/-1, +1/) ErrStat = ErrID_None ErrMsg = "" AllOuts = 0.0_ReKi ! initialize for those outputs that aren't valid (and thus aren't set in this routine) !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array - yout =0 !Initialize and populate with Y2 data - yout(1: p%nDOFI ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red - yout(p%nDOFI+1:p%nDOFI+p%nDOFL) = m%UL + yout( 1:p%nDOFI ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red + yout( p%nDOFI+1:p%nDOFI+p%nDOFL) = m%UL + yout(p%NDOFL+p%nDOFI+1:p%nDOFI+p%nDOFL+p%nDOFC) = 0 !Same for a variable that deals with Udotdot uddout =0 !Initialize and populate with Udotdot data @@ -338,87 +340,85 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) !Inertial Load for the elements that are needed if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 - DO I=1,p%NMOutputs - !I know el # and whether it is 1st node or second node - pLst=>p%MOutLst(I) - DO J=1,pLst%NOutCnt !Iterate on requested nodes for that member - !I need to average across potentially up to 2 elements - !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second - K = pLst%ElmIDs(J,1) !element number - K2= pLst%ElmNds(J,1) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node - sgn=-1 - IF (K2 .EQ. 2) sgn= +1 - K3=p%Elems(K,2:3) !first and second node ID associated with element K - L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout - L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local dir-cosine matrix - !I need to find the Udotdot() for the two nodes of the element of interest - !I need to move the displacements to the local ref system - ! bjj: added these temporary storage variables so that the CALC_NODE_FORCES call doesn't created - ! new temporary *every time* it's called - Tmp_Udotdot(1: 6) = uddout( L : L+5 ) - Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) - Tmp_y2(1: 6) = yout( L : L+5 ) - Tmp_y2(7:12) = yout( L2 : L2+5 ) - CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,J,1),pLst%Ke(:,:,J,1),Tmp_Udotdot, Tmp_y2,pLst%Fg(:,J,1), K2,FM_elm,FK_elm) - - FM_elm2=sgn*FM_elm - FK_elm2=sgn*FK_elm - - IF (p%MOutLst(I)%ElmIDs(J,p%NavgEls) .NE. 0) THEN !element number - K = pLst%ElmIDs(J,p%NavgEls) !element number - K2 = pLst%ElmNds(J,p%NavgEls) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node - sgn=-1 - IF (K2 .EQ. 2) sgn= +1 - K3=p%Elems(K,2:3) !first and second node ID associated with element K - L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order - L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - CALL CALC_NODE_FORCES(DIRCOS,pLst%Me(:,:,J,p%NavgEls),pLst%Ke(:,:,J,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,J,p%NavgEls), K2,FM_elm,FK_elm ) - - FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average - FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average - ENDIF - ! Store in AllOuts - !Forces and moments - AllOuts(MNfmKe (:,J,I)) = FK_elm2 !static forces and moments (6) Local Ref - AllOuts(MNfmMe (:,J,I)) = FM_elm2 !dynamic forces and moments (6) Local Ref - !Displacement- Translational -no need for averaging since it is a node translation - In global reference SS - L=p%IDY( (p%MOutLst(I)%NodeIDs(J)-1)*6 +1 )! starting index for nodeID(J) within yout - AllOuts(MNTDss (:,J,I)) = yout(L:L+2) - !Displacement- Rotational - I need to get the direction cosine matrix to tranform rotations - In Local reference Element Ref Sys - AllOuts(MNRDe (:,J,I)) = matmul(DIRCOS,yout(L+3:L+5) ) !local ref - !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations - AllOuts(MNTRAe (1:3,J,I)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref - AllOuts(MNTRAe (4:6,J,I)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref - ENDDO ! J, Loop on requested nodes for that member - ENDDO ! I, Loop on member outputs + ! Loop over member-outputs requested + DO iMemberOutput=1,p%NMOutputs + pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output + DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member + !I need to average across potentially up to 2 elements + !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second + iElem = pLst%ElmIDs(iiNode,1) ! element number + FirstOrSecond = pLst%ElmNds(iiNode,1) ! first or second node of the element to be considered + sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node + ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element K + L =p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout + L2=p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout + + DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local dir-cosine matrix + !I need to find the Udotdot() for the two nodes of the element of interest + !I need to move the displacements to the local ref system + ! bjj: added these temporary storage variables so that the CALC_NODE_FORCES call doesn't created + ! new temporary *every time* it's called + Tmp_Udotdot(1: 6) = uddout( L : L+5 ) + Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) + Tmp_y2(1: 6) = yout( L : L+5 ) + Tmp_y2(7:12) = yout( L2 : L2+5 ) + !print*,'Tmp_y2',Tmp_y2(1:6) + !print*,'Tmp_y2',m%U_full( p%NodesDOF(ElemNodes(1)%List(1:6)) ) + CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,iiNode,1),pLst%Ke(:,:,iiNode,1),Tmp_Udotdot, Tmp_y2,pLst%Fg(:,iiNode,1), FirstOrSecond, FM_elm, FK_elm) + + FM_elm2=sgn*FM_elm + FK_elm2=sgn*FK_elm + + IF (pLst%ElmIDs(iiNode,p%NavgEls) .NE. 0) THEN !element number + iElem = pLst%ElmIDs(iiNode,p%NavgEls) !element index/number + FirstOrSecond = pLst%ElmNds(iiNode,p%NavgEls) !first or second node of the element to be considered + sgn=NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node + ElemNodes=p%Elems(iElem,2:3) !first and second node ID associated with element K + L = p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order + L2 = p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout + CALL CALC_NODE_FORCES(DIRCOS,pLst%Me(:,:,iiNode,p%NavgEls),pLst%Ke(:,:,iiNode,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,iiNode,p%NavgEls), FirstOrSecond, FM_elm, FK_elm ) + + FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average + FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average + ENDIF + ! Store in AllOuts + !Forces and moments + AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref + AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref + !Displacement- Translational -no need for averaging since it is a node translation - In global reference SS + L=p%IDY( (pLst%NodeIDs(iiNode)-1)*6 +1 )! starting index for nodeID(iiNode) within yout + !print*,'NodeIDs',pLst%NodeIDs(iiNode), 'L',L + AllOuts(MNTDss (:,iiNode,iMemberOutput)) = yout(L:L+2) + !Displacement- Rotational - I need to get the direction cosine matrix to tranform rotations - In Local reference Element Ref Sys + AllOuts(MNRDe (:,iiNode,iMemberOutput)) = matmul(DIRCOS,yout(L+3:L+5) ) !local ref + !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations + AllOuts(MNTRAe (1:3,iiNode,iMemberOutput)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref + AllOuts(MNTRAe (4:6,iiNode,iMemberOutput)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref + ENDDO ! iiNode, Loop on requested nodes for that member + ENDDO ! iMemberOutput, Loop on member outputs END IF IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES - DO I=1,p%NMembers !Cycle on all members - pLst=>p%MOutLst2(I) - DO J=1,2 !Iterate on requested nodes for that member (first and last) - K =pLst%ElmIDs(J,1) !element number - K2=pLst%ElmNds(J,1) !first or second node of the element to be considered - !Assign the sign depending on whether it is the 1st or second node - sgn=-1 - IF (K2 .EQ. 2) sgn= +1 - K3=p%Elems(K,2:3) !first and second node ID associated with element K - L =p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order - L2=p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,J,1),pLst%Ke(:,:,J,1),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,J,1), K2,FM_elm,FK_elm) - ! Store in All Outs - L=MaxOutPts+(I-1)*24+(J-1)*12+1!start index - L2=L+11 - AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) - ENDDO !J, nodes 1 and 2 - ENDDO ! I, Loop on members - ENDIF + DO iMemberOutput=1,p%NMembers !Cycle on all members + pLst=>p%MOutLst2(iMemberOutput) + DO iiNode=1,2 !Iterate on requested nodes for that member (first and last) + iElem = pLst%ElmIDs(iiNode,1) !element number + FirstOrSecond = pLst%ElmNds(iiNode,1) !first or second node of the element to be considered + sgn=NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node + ElemNodes=p%Elems(iElem,2:3) !first and second node ID associated with element iElem + L =p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order + L2=p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout + DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local + CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,1),pLst%Ke(:,:,iiNode,1),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,iiNode,1), FirstOrSecond, FM_elm, FK_elm) + ! Store in All Outs + L=MaxOutPts+(iMemberOutput-1)*24+(iiNode-1)*12+1!start index + L2=L+11 + AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) + ENDDO !iiNode, nodes 1 and 2 + ENDDO ! iMemberOutput, Loop on members + ENDIF !Assign interface forces and moments AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign @@ -439,47 +439,44 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg !Need to Calculate Reaction Forces Now, but only if requested IF (p%OutReact) THEN - - ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for ReactNs array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ReactNs = 0.0 !Initialize - - DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh - FK_elm2=0. !Initialize for cumulative force - FM_elm2=0. !Initialize - pLst => p%MOutLst3(I) - !Find the joint forces - DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) - K = pLst%ElmIDs(1,J) ! element number - K2 = pLst%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered - K3 = p%Elems(K,2:3) !first and second node ID associated with element K - L = p%IDY((K3(1)-1)*6+1)! starting index for node K3(1) within yout ! TODO different DOF order - L2 = p%IDY((K3(2)-1)*6+1)! starting index for node K3(2) within yout - DIRCOS=transpose(p%elemprops(K)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,1,J),pLst%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,1,J), K2,FM_elm,FK_elm) - !transform back to global, need to do 3 at a time since cosine matrix is 3x3 - DO L=1,2 - FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF - FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(p%elemprops(K)%DirCos,FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; - ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 - ENDDO - ENDDO - !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise - !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES - ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt - !The index in Y2mesh is? - !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: - junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) - ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ! TODO TODO TODO assumed DOF order maybe - ENDDO - ! Store into AllOuts - AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) + ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for ReactNs array.' + ErrStat = ErrID_Fatal + RETURN + END IF + ReactNs = 0.0 !Initialize + DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh + FK_elm2=0. !Initialize for cumulative force + FM_elm2=0. !Initialize + pLst => p%MOutLst3(I) + !Find the joint forces + DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) + iElem = pLst%ElmIDs(1,J) ! element number + FirstOrSecond = pLst%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered + ElemNodes = p%Elems(iElem,2:3) !first and second node ID associated with element iElem + L = p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order + L2 = p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout + DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local + CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,1,J),pLst%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & + (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,1,J), FirstOrSecond, FM_elm,FK_elm) + !transform back to global, need to do 3 at a time since cosine matrix is 3x3 + DO L=1,2 + FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%ElemProps(iElem)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF + FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(p%ElemProps(iElem)%DirCos,FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; + ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 + ENDDO + ENDDO + !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise + !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES + ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt + !The index in Y2mesh is? + !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: + junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) + ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ! TODO TODO TODO assumed DOF order maybe + ENDDO + ! Store into AllOuts + AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) ENDIF if (allocated(ReactNs)) deallocate(ReactNs) @@ -490,11 +487,11 @@ END SUBROUTINE SDOut_MapOutputs !output quantities Udotdot and Y2 containing the !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked !---------------------------------------------------------------------------------------------------- -SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, K2,FM_nod,FK_nod) +SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces - Integer(IntKi), INTENT(IN) :: K2 !1 or 2 depending on node of interest + Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments !Locals INTEGER(IntKi) :: L !counter @@ -507,8 +504,8 @@ SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, K2,FM_nod,FK_nod) FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) ENDDO - FM_nod=FM_elm(6*(k2-1)+1:k2*6) ! k2=1, 1:6, k2=2 7:12 - FK_nod=FF_elm(6*(k2-1)+1:k2*6) + FM_nod = FM_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) ! k2=1, 1:6, k2=2 7:12 + FK_nod = FF_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) END SUBROUTINE CALC_NODE_FORCES From 700ce52566578502c371445ff5ed5202abe93f70 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 10 Jan 2020 18:17:53 -0700 Subject: [PATCH 134/377] FlexSub: force calculation: using un-reduced vectors, DOF indices, and simplified --- modules/subdyn/src/SubDyn.f90 | 8 +- modules/subdyn/src/SubDyn_Output.f90 | 345 +++++++++++++-------------- 2 files changed, 171 insertions(+), 182 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 1845aebe4..d72a7bc47 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2402,7 +2402,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) ! --- Build vector of external force m%Fext= myNaN - DO iMeshNode = 1,size(p%INodes_Mesh_to_SD) + DO iMeshNode = 1,p%nNodes iSDNode = p%INodes_Mesh_to_SD(iMeshNode) nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs @@ -2507,12 +2507,6 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers WRITE(UnSum, '(A,I6)') 'Number of nodes per member:', Init%Ndiv+1 WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' - DO i=1,size(Init%PropSetsB,1) - print*,'psb',Init%PropSetsB(i,:) - enddo - DO i=1,size(Init%PropsB,1) - print*,'pb ',Init%PropsB(i,:) - enddo DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 48e3d34e6..2902bdef5 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -219,7 +219,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) pLst%Fg(:,1,K) = pLst%Fg(:,1,K) + FCe(1:12) ! Adding cable element force ENDDO ENDDO - !Store the matrix that will let me calculate single point reaction at the base of structure + ! Compute p%TIreact, matrix to calculate single point reaction at the base of structure CALL ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) ENDIF @@ -304,210 +304,205 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg integer(IntKi), intent( out ) :: ErrStat ! Error status of the operation character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals - integer(IntKi) :: iMemberOutput, iiNode, iElem, FirstOrSecond, I, J, K2,L,L2 ! Counters - integer(IntKi), dimension(2) :: ElemNodes ! It stores Node IDs for element under consideration (may not be consecutive numbers) - integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM - real(ReKi), dimension (6) :: FM_elm, FK_elm, junk !output static and dynamic forces and moments - real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments - real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) - real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions - real(ReKi) :: Tmp_Udotdot(12), Tmp_y2(12) !temporary storage for calls to CALC_LOCAL - real(ReKi), dimension(p%nDOFI+p%nDOFL+p%nDOFC) :: yout ! modifications to Y2 and Udotdot to include constrained node DOFs - real(ReKi), dimension(p%nDOFI+p%nDOFL+p%nDOFC) :: uddout ! modifications to Y2 and Udotdot to include constrained node DOFs - integer(IntKi) ::sgn !+1/-1 for node force calculations - type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities - real(ReKi), dimension(2),parameter :: NodeNumber_To_Sign = (/-1, +1/) + integer(IntKi) :: iMemberOutput, iiNode, iSDNode, iMeshNode, I, J, L, L2 ! Counters + integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM + real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments + real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments + real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions + integer(IntKi) :: sgn !+1/-1 for node force calculations + type(MeshAuxDataType), pointer :: pLst !< Info for a given member-output (Alias to shorten notation) + integer(IntKi), pointer :: DOFList(:) !< List of DOF indices for a given Nodes (Alias to shorten notation) ErrStat = ErrID_None ErrMsg = "" AllOuts = 0.0_ReKi ! initialize for those outputs that aren't valid (and thus aren't set in this routine) - - !Create a variable that lists Y2 and adds removed constrained nodes' dofs; we will be using it to carry out other calculations with a special indexing array - yout( 1:p%nDOFI ) = m%UR_bar ! TODO TODO TODO Look at U_full/U_red - yout( p%nDOFI+1:p%nDOFI+p%nDOFL) = m%UL - yout(p%NDOFL+p%nDOFI+1:p%nDOFI+p%nDOFL+p%nDOFC) = 0 - - !Same for a variable that deals with Udotdot - uddout =0 !Initialize and populate with Udotdot data - uddout(1 : p%nDOFI ) = m%UR_bar_dotdot ! TODO TODO TODO look at U_full_dotdot U_red_dotdot - uddout(p%nDOFI+1 : p%nDOFI+p%nDOFL ) = m%UL_dotdot - - ! TODO TODO TODO, there is a lot of similarity between the three outputs sections with some code redundency - ! Only generate member-based outputs for the number of user-requested member outputs - !Now store and identify needed output as requested by user - !p%MOutLst has the mapping for the member, node, elements per node, to be used - !MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) - !Inertial Load for the elements that are needed + ! -------------------------------------------------------------------------------- + ! --- Requested member-outputs (Node kinematics and loads) + ! -------------------------------------------------------------------------------- + ! p%MOutLst has the mapping for the member, node, elements per node, to be used + ! MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 ! Loop over member-outputs requested DO iMemberOutput=1,p%NMOutputs pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member - !I need to average across potentially up to 2 elements - !Calculate forces on 1st stored element, and if 2nd exists do averaging with the second - iElem = pLst%ElmIDs(iiNode,1) ! element number - FirstOrSecond = pLst%ElmNds(iiNode,1) ! first or second node of the element to be considered - sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node - ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element K - L =p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout - L2=p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout - - DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local dir-cosine matrix - !I need to find the Udotdot() for the two nodes of the element of interest - !I need to move the displacements to the local ref system - ! bjj: added these temporary storage variables so that the CALC_NODE_FORCES call doesn't created - ! new temporary *every time* it's called - Tmp_Udotdot(1: 6) = uddout( L : L+5 ) - Tmp_Udotdot(7:12) = uddout( L2 : L2+5 ) - Tmp_y2(1: 6) = yout( L : L+5 ) - Tmp_y2(7:12) = yout( L2 : L2+5 ) - !print*,'Tmp_y2',Tmp_y2(1:6) - !print*,'Tmp_y2',m%U_full( p%NodesDOF(ElemNodes(1)%List(1:6)) ) - CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,iiNode,1),pLst%Ke(:,:,iiNode,1),Tmp_Udotdot, Tmp_y2,pLst%Fg(:,iiNode,1), FirstOrSecond, FM_elm, FK_elm) - + ! --- Forces (potentially averaged on 2 elements) + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) FM_elm2=sgn*FM_elm FK_elm2=sgn*FK_elm - - IF (pLst%ElmIDs(iiNode,p%NavgEls) .NE. 0) THEN !element number - iElem = pLst%ElmIDs(iiNode,p%NavgEls) !element index/number - FirstOrSecond = pLst%ElmNds(iiNode,p%NavgEls) !first or second node of the element to be considered - sgn=NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node - ElemNodes=p%Elems(iElem,2:3) !first and second node ID associated with element K - L = p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order - L2 = p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout - CALL CALC_NODE_FORCES(DIRCOS,pLst%Me(:,:,iiNode,p%NavgEls),pLst%Ke(:,:,iiNode,p%NavgEls),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,iiNode,p%NavgEls), FirstOrSecond, FM_elm, FK_elm ) - - FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) !Now Average - FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) !Now Average + IF (pLst%ElmIDs(iiNode,p%NavgEls) .NE. 0) THEN ! Second element exist + ! NOTE: forces are computed in the coordinate system of the first element for averaging + call ElementForce(pLst, iiNode, p%NavgEls, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above + FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average + FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average ENDIF - ! Store in AllOuts - !Forces and moments - AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref - AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref - !Displacement- Translational -no need for averaging since it is a node translation - In global reference SS - L=p%IDY( (pLst%NodeIDs(iiNode)-1)*6 +1 )! starting index for nodeID(iiNode) within yout - !print*,'NodeIDs',pLst%NodeIDs(iiNode), 'L',L - AllOuts(MNTDss (:,iiNode,iMemberOutput)) = yout(L:L+2) - !Displacement- Rotational - I need to get the direction cosine matrix to tranform rotations - In Local reference Element Ref Sys - AllOuts(MNRDe (:,iiNode,iMemberOutput)) = matmul(DIRCOS,yout(L+3:L+5) ) !local ref - !Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations - AllOuts(MNTRAe (1:3,iiNode,iMemberOutput)) = matmul(DIRCOS,uddout(L:L+2) ) !translational accel local ref - AllOuts(MNTRAe (4:6,iiNode,iMemberOutput)) = matmul(DIRCOS,uddout(L+3:L+5) ) !rotational accel local ref + ! Static (elastic) component of reaction forces and moments at MαNβ along local member coordinate system + ! "MαNβFKxe, MαNβFKye, MαNβFKze, MαNβMKxe, MαNβMKye, MαNβMKze" + AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref + ! Dynamic (inertial) component of reaction forces and moments at MαNβ along local member coordinate system + ! "MαNβFMxe, MαNβFMye, MαNβFMze, MαNβMMxe, MαNβMMye, MαNβMMze" + AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref + + ! --- Displacements and acceleration + DOFList => p%NodesDOF(pLst%NodeIDs(iiNode))%List + ! Displacement- Translational -no need for averaging since it is a node translation - In global reference SS + ! "MαNβTDxss, MαNβTDyss, MαNβTDzss" + AllOuts(MNTDss (:,iiNode,iMemberOutput)) = m%U_full(DOFList(1:3)) + ! Displacement- Rotational - need direction cosine matrix to tranform rotations - In Local reference Element Ref Sys + ! "MαNβRDxss, MαNβRDye, MαNβRDze" + AllOuts(MNRDe (:,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full(DOFList(4:6))) !local ref + ! Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations + ! "MαNβTAxe, MαNβTAye, MαNβTAze" + ! "MαNβRAxe, MαNβRAye, MαNβRAze" + AllOuts(MNTRAe (1:3,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(1:3))) ! translational accel local ref + AllOuts(MNTRAe (4:6,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(4:6))) ! rotational accel local ref ENDDO ! iiNode, Loop on requested nodes for that member ENDDO ! iMemberOutput, Loop on member outputs END IF - IF (p%OutAll) THEN !NEED TO CALCULATE TOTAL FORCES + ! -------------------------------------------------------------------------------- + ! --- All nodal loads from stiffness and mass matrix + ! -------------------------------------------------------------------------------- + ! "MaaaJbFKxe, MaaaJbMKxe MaaaJbFMxe, MaaaJbMMxe for member aaa and node b." + IF (p%OutAll) THEN DO iMemberOutput=1,p%NMembers !Cycle on all members pLst=>p%MOutLst2(iMemberOutput) DO iiNode=1,2 !Iterate on requested nodes for that member (first and last) - iElem = pLst%ElmIDs(iiNode,1) !element number - FirstOrSecond = pLst%ElmNds(iiNode,1) !first or second node of the element to be considered - sgn=NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node - ElemNodes=p%Elems(iElem,2:3) !first and second node ID associated with element iElem - L =p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order - L2=p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout - DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,1),pLst%Ke(:,:,iiNode,1),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,iiNode,1), FirstOrSecond, FM_elm, FK_elm) + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) ! Store in All Outs - L=MaxOutPts+(iMemberOutput-1)*24+(iiNode-1)*12+1!start index - L2=L+11 + L = MaxOutPts+(iMemberOutput-1)*24+(iiNode-1)*12+1 + L2 = L+11 AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) ENDDO !iiNode, nodes 1 and 2 ENDDO ! iMemberOutput, Loop on members ENDIF - !Assign interface forces and moments - AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign - !Assign interface translations and rotations at the TP ref point - AllOuts(IntfTRss(1:nDOFL_TP))=m%u_TP - !Assign interface translations and rotations accelerations - AllOuts(IntfTRAss(1:nDOFL_TP))= m%udotdot_TP - - ! Assign all SSqm, SSqmdot, SSqmdotdot - ! We only have space for the first 99 values - maxOutModes = min(p%nDOFM,99) - IF ( maxOutModes > 0 ) THEN - !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) - Allouts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) - Allouts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) - Allouts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) - END IF + ! -------------------------------------------------------------------------------- + ! --- Interface kinematics and loads (TP/platform reference point) + ! -------------------------------------------------------------------------------- + ! Total interface reaction forces and moments in SS coordinate system + ! "IntfFXss, IntfFYss, IntfFZss, IntfMXss, IntfMYss, IntfMZss," + AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign + ! Interface translations and rotations in SS coordinate system + ! "IntfTDXss, IntfTDYss, IntfTDZss, IntfRDXss, IntfRDYss IntfRDZss" + AllOuts(IntfTRss(1:nDOFL_TP))=m%u_TP + ! Interface Translational and rotational accelerations in SS coordinate system + ! "IntfTAXss, IntfTAYss, IntfTAZss, IntfRAXss, IntfRAYss IntfRAZss" + AllOuts(IntfTRAss(1:nDOFL_TP))= m%udotdot_TP + + ! -------------------------------------------------------------------------------- + ! --- Modal parameters "SSqmXX, SSqmdotXX, SSqmddXX" amplitude, speed and acceleration + ! -------------------------------------------------------------------------------- + maxOutModes = min(p%nDOFM,99) ! We only have space for the first 99 values + IF ( maxOutModes > 0 ) THEN + !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) + AllOuts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) + AllOuts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) + AllOuts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) + END IF - !Need to Calculate Reaction Forces Now, but only if requested - IF (p%OutReact) THEN - ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for ReactNs array.' - ErrStat = ErrID_Fatal - RETURN - END IF - ReactNs = 0.0 !Initialize - DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh - FK_elm2=0. !Initialize for cumulative force - FM_elm2=0. !Initialize - pLst => p%MOutLst3(I) - !Find the joint forces - DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) - iElem = pLst%ElmIDs(1,J) ! element number - FirstOrSecond = pLst%ElmNds(1,J) ! 1=first, 2=second node of the element to be considered - ElemNodes = p%Elems(iElem,2:3) !first and second node ID associated with element iElem - L = p%IDY((ElemNodes(1)-1)*6+1)! starting index for node ElemNodes(1) within yout ! TODO different DOF order - L2 = p%IDY((ElemNodes(2)-1)*6+1)! starting index for node ElemNodes(2) within yout - DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local - CALL CALC_NODE_FORCES( DIRCOS,pLst%Me(:,:,1,J),pLst%Ke(:,:,1,J),(/uddout( L : L+5 ),uddout( L2 : L2+5 )/), & - (/yout( L : L+5 ), yout( L2 : L2+5 )/), pLst%Fg(:,1,J), FirstOrSecond, FM_elm,FK_elm) - !transform back to global, need to do 3 at a time since cosine matrix is 3x3 - DO L=1,2 - FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(p%ElemProps(iElem)%DirCos,FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF - FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(p%ElemProps(iElem)%DirCos,FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; - ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 - ENDDO - ENDDO - !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise - !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES - ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt - !The index in Y2mesh is? - !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: - junk = (/u%LMesh%Force(:,p%NNodes_I+p%NNodes_L+I),u%LMesh%Moment(:,p%NNodes_I+p%NNodes_L+I)/) - ReactNs((I-1)*6+1:6*I)=FK_elm2 - junk !Accumulate reactions from all nodes in GLOBAL COORDINATES ! TODO TODO TODO assumed DOF order maybe - ENDDO - ! Store into AllOuts - AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) - ENDIF - if (allocated(ReactNs)) deallocate(ReactNs) + ! --------------------------------------------------------------------------------} + ! --- Base reaction loads + ! --------------------------------------------------------------------------------{ + ! Total base reaction forces and moments at the (0.,0.,-WtrDpth) location in SS coordinate system + ! "ReactFXss, ReactFYss, ReactFZss, ReactMXss, ReactMYss, ReactMZss" + IF (p%OutReact) THEN + ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for ReactNs array.' + ErrStat = ErrID_Fatal + RETURN + END IF + ReactNs = 0.0 !Initialize + DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh + FK_elm2=0. !Initialize for cumulative force + FM_elm2=0. !Initialize + pLst => p%MOutLst3(I) + !Find the joint forces + DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) + iiNode = 1 + call ElementForce(pLst, iiNode, J, FM_elm, FK_elm, sgn, DIRCOS, .false.) + !transform back to global, need to do 3 at a time since cosine matrix is 3x3 + DO L=1,2 + FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF + FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; + ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 + ENDDO + ENDDO + !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise + !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES + ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt + !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: + iSDNode = p%Nodes_C(I,1) + iMeshNode = p%INodes_SD_to_Mesh(iSDNode) + Fext = (/ u%LMesh%Force(:,iMeshNode), u%LMesh%Moment(:,iMeshNode) /) + ReactNs((I-1)*6+1:6*I) = FK_elm2 - Fext !Accumulate reactions from all nodes in GLOBAL COORDINATES + ENDDO + ! Store into AllOuts + AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) + ENDIF + if (allocated(ReactNs)) deallocate(ReactNs) +contains + + subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInputDirCos) + type(MeshAuxDataType), intent(in) :: pLst !< Info for one member output + integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given number + integer(IntKi) , intent(in) :: JJ !< TODO: interpretation: index over other member connected to the current member (for averaging) + real(ReKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(ReKi), dimension (6), intent(out) :: FM_elm, FK_elm !output static and dynamic forces and moments + integer(IntKi), intent(out) :: sgn !+1/-1 for node force calculations + logical, intent(in) :: bUseInputDirCos !< If True, use DIRCOS from input, otherwise, use element DirCos + ! Local + integer(IntKi) :: iElem !< Element index/number + integer(IntKi) :: FirstOrSecond !< 1 or 2 if first node or second node + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + real(ReKi) , dimension(12) :: X_e, Xdd_e ! Displacement and acceleration for an element + integer(IntKi), dimension(2), parameter :: NodeNumber_To_Sign = (/-1, +1/) + + iElem = pLst%ElmIDs(iiNode,JJ) ! element number + FirstOrSecond = pLst%ElmNds(iiNode,JJ) ! first or second node of the element to be considered + sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node + ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element iElem + X_e(1:6) = m%U_full (p%NodesDOF(ElemNodes(1))%List(1:6)) + X_e(7:12) = m%U_full (p%NodesDOF(ElemNodes(2))%List(1:6)) + Xdd_e(1:6) = m%U_full_dotdot(p%NodesDOF(ElemNodes(1))%List(1:6)) + Xdd_e(7:12) = m%U_full_dotdot(p%NodesDOF(ElemNodes(2))%List(1:6)) + if (.not. bUseInputDirCos) then + DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local + endif + CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,JJ),pLst%Ke(:,:,iiNode,JJ), Xdd_e, X_e, pLst%Fg(:,iiNode,JJ), FirstOrSecond, FM_elm, FK_elm) + end subroutine ElementForce + + !==================================================================================================== + !> Calculates static and dynamic forces for a given element, using K and M of the element, and + !output quantities Udotdot and Y2 containing the + !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked + !---------------------------------------------------------------------------------------------------- + SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) + Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) + Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces + Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest + REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments + !Locals + INTEGER(IntKi) :: L !counter + REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage + + FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE + FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE + FF_glb = FF_glb - Fg ! GLOBAL REFERENCE + DO L=1,4 ! Transforming coordinates 3 at a time + FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) + FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) + ENDDO + FM_nod = FM_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) ! k2=1, 1:6, k2=2 7:12 + FK_nod = FF_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) + END SUBROUTINE CALC_NODE_FORCES END SUBROUTINE SDOut_MapOutputs -!==================================================================================================== -!> Calculates static and dynamic forces for a given element, using K and M of the element, and -!output quantities Udotdot and Y2 containing the -!and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked -!---------------------------------------------------------------------------------------------------- -SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) - Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) - Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces - Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest - REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments - !Locals - INTEGER(IntKi) :: L !counter - REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage - - FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE - FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE - FF_glb = FF_glb - Fg ! GLOBAL REFERENCE - DO L=1,4 ! Transforming coordinates 3 at a time - FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) - FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) - ENDDO - FM_nod = FM_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) ! k2=1, 1:6, k2=2 7:12 - FK_nod = FF_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) - -END SUBROUTINE CALC_NODE_FORCES !==================================================================================================== SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) From 3cfa650a5fc1795083e82cb7959aebb12c55fb62 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 13 Jan 2020 11:29:34 -0700 Subject: [PATCH 135/377] TCF: loop rearrange on NewmanApp WAMIT2 --- modules/hydrodyn/src/WAMIT2.f90 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 645884e33..f4973a442 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -1848,20 +1848,20 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg ! Frequency Omega1 = J * InitInp%WaveDOmega - !> Phase shift due to offset in location - !! The phase shift due to an (x,y) offset is of the form - !! \f$ exp(-\imath k(\omega) ( X cos(\Beta(w)) + Y sin(\beta(w)) )) \f$ - ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead - ! of above is mathematically equivalent, but only because each frequency has only one wave - ! direction associated with it through the equal energy approach used in multidirectional waves. + !> Phase shift due to offset in location, only for NBodyMod==2 + if (p%NBodyMod == 2) then - WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned - TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J)*D2R) ) - PhaseShiftXY = CMPLX( cos(TmpReal1), -sin(TmpReal1) ) + !> The phase shift due to an (x,y) offset is of the form + !! \f$ exp(-\imath k(\omega) ( X cos(\Beta(w)) + Y sin(\beta(w)) )) \f$ + ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead + ! of above is mathematically equivalent, but only because each frequency has only one wave + ! direction associated with it through the equal energy approach used in multidirectional waves. + WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J)*D2R) ) + PhaseShiftXY = CMPLX( cos(TmpReal1), -sin(TmpReal1) ) - ! Apply the phase shift, but only to the NBodyMod=2 case - if (p%NBodyMod == 2) then + ! Apply the phase shift DO ThisDim=1,6 NewmanTerm1C(J,ThisDim) = NewmanTerm1C(J,ThisDim)*PhaseShiftXY ! Newman term 1 NewmanTerm2C(J,ThisDim) = NewmanTerm2C(J,ThisDim)*PhaseShiftXY ! Newman term 2 From 1fa3412757410780abca2a47cdd390079d6ab93d Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 13 Jan 2020 11:31:05 -0700 Subject: [PATCH 136/377] TCF: DiffQTF updated for phase shift in NBodyMod == 2 --- modules/hydrodyn/src/WAMIT2.f90 | 128 +++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index f4973a442..5917e1dba 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -2025,7 +2025,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF - COMPLEX(SiKi), ALLOCATABLE :: TmpComplexArr(:) !< Temporary complex array for frequency domain of one complete load component + COMPLEX(SiKi), ALLOCATABLE :: TmpComplexArr(:,:) !< Temporary complex array for frequency domain of one complete load component COMPLEX(SiKi) :: TmpHMinusC !< Temporary variable for holding the current value of \f$ H^- \f$ COMPLEX(SiKi) :: aWaveElevC1 !< Wave elevation of the first frequency component. NStepWave2 factor removed. COMPLEX(SiKi) :: aWaveElevC2 !< Wave elevation of the second frequency component. NStepWave2 factor removed. @@ -2034,6 +2034,11 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS REAL(ReKi) :: Omega1 !< First wave frequency REAL(ReKi) :: Omega2 !< Second wave frequency REAL(SiKi), ALLOCATABLE :: MnDriftForce(:) !< Mean drift force (first term). MnDrift_InitCalc routine will return this. + REAL(SiKi) :: RotateZdegOffset !< Offset to wave heading (NBodyMod==2 only) + REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) + COMPLEX(SiKi) :: PhaseShiftXY !< The phase shift offset to apply to the body + REAL(SiKi) :: WaveNmbr1 !< Wavenumber for this frequency + REAL(SiKi) :: WaveNmbr2 !< Wavenumber for this frequency ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq @@ -2184,7 +2189,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ALLOCATE( TmpDiffQTFForce( 0:InitInp%NStepWave), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & 'QTF 2nd order force time series.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( TmpComplexArr( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + ALLOCATE( TmpComplexArr( 0:InitInp%NStepWave2, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for one load component of the full difference '// & 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( DiffQTFForce( 0:InitInp%NStepWave, 6*p%NBody), STAT=ErrStatTmp ) @@ -2252,6 +2257,22 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Now loop through all the dimensions and perform the calculation DO IBody=1,p%NBody + + ! Initialize the temporary array to zero. + TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + + ! Heading correction, only applies to NBodyMod == 2 + if (p%NBodyMod==2) then + RotateZdegOffset = InitInp%PtfmRefztRot(IBody)*R2D + else + RotateZdegOffset = 0.0_SiKi + endif + + !---------------------------------------------------- + ! Populate the frequency terms for this body + ! -- with phase shift for NBodyMod == 2 + !---------------------------------------------------- + DO ThisDim=1,6 Idx = (IBody-1)*6+ThisDim @@ -2265,10 +2286,6 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays TmpData4D = DiffQTFData%Data4D%DataSet(:,:,:,:,Idx) - ! Initialize the temporary array to zero. - TmpComplexArr = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - - ! Outer loop to create the TmpComplexArr DO J=1,InitInp%NStepWave2-1 @@ -2290,7 +2307,6 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS Omega1 = (J + K) * InitInp%WaveDOmega ! the mth frequency -- \mu^- + n = m Omega2 = K * InitInp%WaveDOmega ! the nth frequency - ! Find the Wave amplitudes 1 and 2 aWaveElevC1 = CMPLX( InitInp%WaveElevC0(1,J+K), InitInp%WaveElevC0(2,J+K), SiKi) / InitInp%NStepWave2 aWaveElevC2 = CMPLX( InitInp%WaveElevC0(1,K), InitInp%WaveElevC0(2,K), SiKi) / InitInp%NStepWave2 @@ -2298,6 +2314,10 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Set the (omega1,omega2,beta1,beta2) point we are looking for. Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(J+K), InitInp%WaveDirArr(K) /) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord4(3) = Coord4(3) - RotateZdegOffset + Coord4(4) = Coord4(4) - RotateZdegOffset + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, DiffQTFData%Data4D%WvFreq1, DiffQTFData%Data4D%WvFreq2, & DiffQTFData%Data4D%WvDir1, DiffQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) @@ -2310,6 +2330,30 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS RETURN ENDIF + !-------------------------- + ! Phase shift due to offset + !-------------------------- + if (p%NBodyMod == 2) then + !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) + !! - k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ + ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead + ! of above is mathematically equivalent, but only because each frequency has only one wave + ! direction associated with it through the equal energy approach used in multidirectional waves. + + WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + WaveNmbr2 = WaveNumber ( REAL(Omega2,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J+K)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J+K)*D2R) ) + TmpReal2 = WaveNmbr2 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(K)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(K)*D2R) ) + + ! Set the phase shift for the set of difference frequencies + PhaseShiftXY = CMPLX( cos(TmpReal1 - TmpReal2), -sin(TmpReal1 - TmpReal2) ) + + ! For similicity, apply to the QTF_Value (mathematically equivalent to applying to the wave elevations) + QTF_Value = QTF_Value*PhaseShiftXY + + endif ! Phaseshift for NBodyMod==2 + ! Calculate this value and add it to what we have so far. TmpHMinusC = TmpHMinusC + aWaveElevC1 * CONJG(aWaveElevC2) * QTF_Value @@ -2317,39 +2361,69 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS ! Copy this value difference frequency information over to the array we will take the IFFT. Divide ! by two for the single sided FFT given in the documentation. - TmpComplexArr(J) = TmpHMinusC / 2.0_SiKi + TmpComplexArr(J,ThisDim) = TmpHMinusC / 2.0_SiKi ELSE ! outside the frequency range, so - TmpComplexArr(J) = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + TmpComplexArr(J,ThisDim) = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) ENDIF ! frequency check ENDDO + ENDIF ! Load component to calculate + ENDDO ! ThisDim -- The current dimension - ! Now we apply the FFT to the result of the sum - CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) - IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) - RETURN - END IF + !---------------------------------------------------- + ! Rotate back to global frame + !---------------------------------------------------- - ! Now we multiply the result by 2 and save it to the DiffQTFForce array and add the MnDrift term - DO K=0,InitInp%NStepWave-1 ! bjj: added the "-1" here because TmpDiffQTFForce(InitInp%NStepWave) is not set and DiffQTFForce(InitInp%NStepWave,Idx) gets overwritten next, anyway - DiffQTFForce(K,Idx) = 2.0_SiKi * TmpDiffQTFForce(K) + MnDriftForce(Idx) - ENDDO + ! Set rotation + ! NOTE: RotateZMatrixT is the rotation from local to global. + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) - ! Copy the last first term to the first so that it is cyclic - DiffQTFForce(InitInp%NStepWave,Idx) = DiffQTFForce(0,Idx) + ! Loop through all the frequencies + DO J=1,InitInp%NStepWave2 - ENDIF ! Load component to calculate + ! Apply the rotation to get back to global frame + TmpComplexArr(J,1:2) = MATMUL(RotateZMatrixT, TmpComplexArr(J,1:2)) + TmpComplexArr(J,4:5) = MATMUL(RotateZMatrixT, TmpComplexArr(J,4:5)) + + ENDDO ! J=1,InitInp%NStepWave2 + + + + !---------------------------------------------------- + ! Apply the FFT to get time domain results + !---------------------------------------------------- + + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + + ! Now we apply the FFT to the result of the sum + CALL ApplyFFT_cx( TmpDiffQTFForce(:), TmpComplexArr(:,ThisDim), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the difference QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + IF (ALLOCATED(DiffQTFForce)) DEALLOCATE(DiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpDiffQTFForce)) DEALLOCATE(TmpDiffQTFForce,STAT=ErrStatTmp) + IF (ALLOCATED(TmpComplexArr)) DEALLOCATE(TmpComplexArr,STAT=ErrStatTmp) + RETURN + END IF + + + ! Now we multiply the result by 2 and save it to the DiffQTFForce array and add the MnDrift term + ! NOTE: phase shift and orientations on the MnDriftForce term have already been applied + ! NOTE: the "-1" since TmpDiffQTFForce(InitInp%NStepWave) is not set and DiffQTFForce(InitInp%NStepWave,Idx) gets overwritten + DO K=0,InitInp%NStepWave-1 + DiffQTFForce(K,Idx) = 2.0_SiKi * TmpDiffQTFForce(K) + MnDriftForce(Idx) + ENDDO + + ! Copy the last first term to the first so that it is cyclic + DiffQTFForce(InitInp%NStepWave,Idx) = DiffQTFForce(0,Idx) ENDDO ! ThisDim -- The current dimension ENDDO ! IBody -- This WAMIT body From 9ead8d6f1c8d9ff8675276d83f1cdfa7dcbe5705 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 13 Jan 2020 13:34:41 -0700 Subject: [PATCH 137/377] TCF: SumQTF updated for phase shift in NBodyMod == 2 --- modules/hydrodyn/src/WAMIT2.f90 | 180 ++++++++++++++++++++++++-------- 1 file changed, 138 insertions(+), 42 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 5917e1dba..c449ca2be 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -2544,8 +2544,8 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Wave information and QTF temporary COMPLEX(SiKi) :: QTF_Value !< Temporary complex number for QTF - COMPLEX(SiKi), ALLOCATABLE :: Term1ArrayC(:) !< Temporary complex array for frequency domain of one load component. For first term. - COMPLEX(SiKi), ALLOCATABLE :: Term2ArrayC(:) !< Temporary complex array for frequency domain of one load component. For second term. + COMPLEX(SiKi), ALLOCATABLE :: Term1ArrayC(:,:) !< Temporary complex array for frequency domain of one load component. For first term. + COMPLEX(SiKi), ALLOCATABLE :: Term2ArrayC(:,:) !< Temporary complex array for frequency domain of one load component. For second term. REAL(SiKi), ALLOCATABLE :: Term1Array(:) !< Temporary complex array for time domain of one load component. For first term. REAL(SiKi), ALLOCATABLE :: Term2Array(:) !< Temporary complex array for time domain of one load component. For second term. COMPLEX(SiKi) :: TmpHPlusC !< Temporary variable for holding the current value of \f$ H^+ \f$ @@ -2554,6 +2554,13 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat REAL(ReKi) :: OmegaSum !< Wave difference frequency REAL(ReKi) :: Omega1 !< First wave frequency REAL(ReKi) :: Omega2 !< Second wave frequency + REAL(SiKi) :: RotateZdegOffset !< Offset to wave heading (NBodyMod==2 only) + REAL(SiKi) :: RotateZMatrixT(2,2) !< The transpose of rotation in matrix form for rotation about z (from global to local) + COMPLEX(SiKi) :: PhaseShiftXY !< The phase shift offset to apply to the body + REAL(SiKi) :: WaveNmbr1 !< Wavenumber for this frequency + REAL(SiKi) :: WaveNmbr2 !< Wavenumber for this frequency + REAL(SiKi) :: TmpReal1 !< Temporary real + REAL(SiKi) :: TmpReal2 !< Temporary real ! Interpolation routine indices and value to search for, and smaller array to pass INTEGER(IntKi) :: LastIndex4(4) !< Last used index for searching in the interpolation algorithms. First wave freq @@ -2701,10 +2708,10 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Setup the arrays holding the SumQTF terms, both the complex frequency domain and real time domain pieces - ALLOCATE( Term1ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + ALLOCATE( Term1ArrayC( 0:InitInp%NStepWave2, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the first term of one load component of the full sum '// & 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) - ALLOCATE( Term2ArrayC( 0:InitInp%NStepWave2), STAT=ErrStatTmp ) + ALLOCATE( Term2ArrayC( 0:InitInp%NStepWave2, 6), STAT=ErrStatTmp ) IF (ErrStatTmp /= 0) CALL SetErrStat(ErrID_Fatal,' Cannot allocate array for the second term of one load component of the full sum '// & 'QTF 2nd order force in the frequency domain.',ErrStat, ErrMsg, RoutineName) ALLOCATE( Term1Array( 0:InitInp%NStepWave), STAT=ErrStatTmp ) @@ -2745,8 +2752,24 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Now loop through all the dimensions and perform the calculation DO IBody=1,p%NBody - DO ThisDim=1,6 + ! Initialize the temporary array to zero. + Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) + + ! Heading correction, only applies to NBodyMod == 2 + if (p%NBodyMod==2) then + RotateZdegOffset = InitInp%PtfmRefztRot(IBody)*R2D + else + RotateZdegOffset = 0.0_SiKi + endif + + !---------------------------------------------------- + ! Populate the frequency terms for this body + ! -- with phase shift for NBodyMod == 2 + !---------------------------------------------------- + + DO ThisDim=1,6 Idx = (IBody-1)*6+ThisDim ! Only on the dimensions we requested, and if it is present in the data @@ -2756,8 +2779,6 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! To make things run slightly quicker, copy the data we will be interpolating over into the temporary arrays TmpData4D = SumQTFData%Data4D%DataSet(:,:,:,:,Idx) - - !--------------------------------------------------------------------------------- ! Calculate the first term ! This term is only the FFT over the diagonal elements where omega_1 = omega_2 @@ -2771,10 +2792,6 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Set an initial search index for the 4D array interpolation LastIndex4 = (/0,0,0,0/) - ! Initialize the array to zero - Term1ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - - ! The limits look a little funny. But remember we are placing the value in the 2*J location, ! so we cannot overun the end of the array, and the highest frequency must be zero. The ! floor function is just in case (NStepWave2 - 1) is an odd number @@ -2794,6 +2811,10 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Set the (omega1,omega2,beta1,beta2) point we are looking for. Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega1,SiKi), InitInp%WaveDirArr(J), InitInp%WaveDirArr(J) /) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord4(3) = Coord4(3) - RotateZdegOffset + Coord4(4) = Coord4(4) - RotateZdegOffset + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) @@ -2803,15 +2824,37 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat RETURN ENDIF + !-------------------------- + ! Phase shift due to offset + !-------------------------- + if (p%NBodyMod == 2) then + !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) + !! 1 k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$. + !! For the first term, \f$ \omega_1 = \omega_2 \$f. + ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead + ! of above is mathematically equivalent, but only because each frequency has only one wave + ! direction associated with it through the equal energy approach used in multidirectional waves. + + WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J)*D2R) ) + + ! Set the phase shift for the set of sum frequencies + PhaseShiftXY = CMPLX( cos(TmpReal1 + TmpReal1), -sin(TmpReal1 + TmpReal1) ) + + ! For similicity, apply to the QTF_Value (mathematically equivalent to applying to the wave elevations) + QTF_Value = QTF_Value*PhaseShiftXY + + endif ! Phaseshift for NBodyMod==2 + ! Set the value of the first term in the frequency domain - Term1ArrayC(2*J) = aWaveElevC1 * aWaveElevC1 * QTF_Value + Term1ArrayC(2*J,ThisDim) = aWaveElevC1 * aWaveElevC1 * QTF_Value ENDIF ! Check on the limits ENDDO ! First term calculation - !--------------------------------------------------------------------------------- ! Calculate the second term. ! In this term, we are are now stepping through the sum frequencies. The inner @@ -2823,10 +2866,6 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Set an initial search index for the 4D array interpolation LastIndex4 = (/0,0,0,0/) - ! Initialize the temporary arrays for each term to zero. - Term2ArrayC = CMPLX(0.0_SiKi,0.0_SiKi,SiKi) - - ! Check the limits for the high frequency cutoff. If WvHiCOffS is less than the ! maximum frequency possible with the value of WaveDT (omega_max = pi/WaveDT = NStepWave2*WaveDOmega), ! then we are good. If the WvHiCOff > 1/2 omega_max, then we will be potentially @@ -2886,6 +2925,10 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat ! Set the (omega1,omega2,beta1,beta2) point we are looking for. Coord4 = (/ REAL(Omega1,SiKi), REAL(Omega2,SiKi), InitInp%WaveDirArr(K), InitInp%WaveDirArr(J-K) /) + ! Apply local Z rotation to heading angle (degrees) to put wave direction into the local (rotated) body frame + Coord4(3) = Coord4(3) - RotateZdegOffset + Coord4(4) = Coord4(4) - RotateZdegOffset + ! get the interpolated value for F(omega1,omega2,beta1,beta2) --> QTF_Value CALL WAMIT_Interp4D_Cplx( Coord4, TmpData4D, SumQTFData%Data4D%WvFreq1, SumQTFData%Data4D%WvFreq2, & SumQTFData%Data4D%WvDir1, SumQTFData%Data4D%WvDir2, LastIndex4, QTF_Value, ErrStatTmp, ErrMsgTmp ) @@ -2895,48 +2938,101 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat RETURN ENDIF + !-------------------------- + ! Phase shift due to offset + !-------------------------- + if (p%NBodyMod == 2) then + !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) + !! - k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ + ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead + ! of above is mathematically equivalent, but only because each frequency has only one wave + ! direction associated with it through the equal energy approach used in multidirectional waves. + + WaveNmbr1 = WaveNumber ( REAL(Omega1,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + WaveNmbr2 = WaveNumber ( REAL(Omega2,SiKi), InitInp%Gravity, InitInp%WtrDpth ) ! SiKi returned + TmpReal1 = WaveNmbr1 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(K)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(K)*D2R) ) + TmpReal2 = WaveNmbr2 * ( InitInp%PtfmRefxt(1)*cos(InitInp%WaveDirArr(J-K)*D2R) + InitInp%PtfmRefyt(1)*sin(InitInp%WaveDirArr(J-K)*D2R) ) + + ! Set the phase shift for the set of sum frequencies + PhaseShiftXY = CMPLX( cos(TmpReal1 + TmpReal2), -sin(TmpReal1 + TmpReal2) ) + + QTF_Value = QTF_Value*PhaseShiftXY + + endif ! Phaseshift for NBodyMod==2 + ! Set the value of the first term in the frequency domain. TmpHPlusC = TmpHPlusC + aWaveElevC1 * aWaveElevC2 * QTF_Value ENDDO ! Save the value from the summation. - Term2ArrayC(J) = TmpHPlusC - + Term2ArrayC(J,ThisDim) = TmpHPlusC ENDIF ! Check on the limits ENDDO ! Second term calculation -- frequency step on the sum frequency + ENDIF ! Load component to calculate + ENDDO ! ThisDim -- current dimension + !---------------------------------------------------- + ! Rotate back to global frame + !---------------------------------------------------- - ! Now we apply the FFT to the result of the sum. - CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - END IF + ! Set rotation + ! NOTE: RotateZMatrixT is the rotation from local to global. + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) - ! Now we apply the FFT to the result of the sum. - CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:), FFT_Data, ErrStatTmp ) - CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & - ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) - RETURN - ENDIF + ! Loop through all the frequencies + DO J=1,InitInp%NStepWave2 - ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. - DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,Idx) gets overwritten later, so Idx'm setting the array bounds to be -1. - SumQTFForce(J,Idx) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J), SiKi)) - ENDDO + ! Apply the rotation to get back to global frame -- term 1 + Term1ArrayC(J,1:2) = MATMUL(RotateZMatrixT, Term1ArrayC(J,1:2)) + Term1ArrayC(J,4:5) = MATMUL(RotateZMatrixT, Term1ArrayC(J,4:5)) - ! Copy the last first term to the first so that it is cyclic - SumQTFForce(InitInp%NStepWave,Idx) = SumQTFForce(0,Idx) + ! Apply the rotation to get back to global frame -- term 2 + Term2ArrayC(J,1:2) = MATMUL(RotateZMatrixT, Term2ArrayC(J,1:2)) + Term2ArrayC(J,4:5) = MATMUL(RotateZMatrixT, Term2ArrayC(J,4:5)) + + ENDDO ! J=1,InitInp%NStepWave2 + + + + !---------------------------------------------------- + ! Apply the FFT to get time domain results + !---------------------------------------------------- + + DO ThisDim=1,6 + Idx = (IBody-1)*6+ThisDim + + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term1Array(:), Term1ArrayC(:,ThisDim), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the first term of the Sum QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + END IF + + ! Now we apply the FFT to the result of the sum. + CALL ApplyFFT_cx( Term2Array(:), Term2ArrayC(:,ThisDim), FFT_Data, ErrStatTmp ) + CALL SetErrStat(ErrStatTmp,'Error occured while applying the FFT to the second term of the Sum QTF.', & + ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + IF (ALLOCATED(TmpData4D)) DEALLOCATE(TmpData4D,STAT=ErrStatTmp) + RETURN + ENDIF + + ! Now we add the two terms together. The 0.5 multiplier on is because the double sided FFT was used. + DO J=0,InitInp%NStepWave-1 !bjj: Term1Array and Term2Array don't set the last element, so we can get over-flow errors here. SumQTFForce(InitInp%NStepWave,Idx) gets overwritten later, so Idx'm setting the array bounds to be -1. + SumQTFForce(J,Idx) = 0.5_SiKi*(REAL(Term1Array(J) + 2*Term2Array(J), SiKi)) + ENDDO + + ! Copy the last first term to the first so that it is cyclic + SumQTFForce(InitInp%NStepWave,Idx) = SumQTFForce(0,Idx) - ENDIF ! Load component to calculate ENDDO ! ThisDim -- current dimension ENDDO ! IBody -- current WAMIT body From c59f672a730dae18a9a27a06ad0584fe452f9e39 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jan 2020 13:39:08 -0700 Subject: [PATCH 138/377] FlexSub: fixed member indexing in SDout (see #378) --- modules/subdyn/src/SubDyn_Output.f90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 2902bdef5..214810acf 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -60,6 +60,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters INTEGER(IntKi) :: Junk !Temporary Holders + INTEGER(IntKi) :: iMember ! Member index (not member ID) INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities REAL(ReKi) :: FCe(12) ! Pretension force from cable element @@ -93,7 +94,8 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return ! NOTE: MemberNodes >2 if nDiv>1 - pLst%NodeIDs=Init%MemberNodes(pLst%MemberID,pLst%NodeCnt) !We are storing the actual node numbers corresponding to what the user ordinal number is requesting + iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers + pLst%NodeIDs=Init%MemberNodes(iMember,pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting pLst%ElmIDs=0 !Initialize to 0 pLst%ElmNds=0 !Initialize to 0 @@ -112,7 +114,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) else Junk=M(1) endif - IF (ANY(Init%MemberNodes(pLst%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + IF (ANY(Init%MemberNodes(iMember,:) .EQ. Junk)) THEN !This means we are in the selected member IF (K2 .EQ. 2) EXIT K2=K2+1 pLst%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 @@ -146,7 +148,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - pLst%MemberID=I !Assign memberID for all members + pLst%MemberID=Init%Members(I,1) pLst%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member !Now I need to find out which elements are attached to those nodes and still belong to the member I !ElmIDs could contain the same element twice if Ndiv=1 @@ -162,7 +164,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) !Select only the other node, not the one where elements connect to Junk=M(1) IF (M(1) .EQ. pLst%NodeIDs(J)) Junk=M(2) - IF (ANY(Init%MemberNodes(pLst%MemberID,:) .EQ. Junk)) THEN !This means we are in the selected member + IF (ANY(Init%MemberNodes(I,:) .EQ. Junk)) THEN !This means we are in the selected member pLst%ElmIDs(K2,1)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for pLst%ElmNds(K2,1)=1 !store whether first or second node of element IF (M(2) .EQ. pLst%NodeIDs(J) ) pLst%ElmNds(K2,1)=2 !store whether first or second node of element From b736f5b5ce2e44282e7dde3700f1182352499839 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 13 Jan 2020 14:22:18 -0700 Subject: [PATCH 139/377] [BugFix] WAMIT2 multidirectional angle issue #9 --- modules/hydrodyn/src/WAMIT2.f90 | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index c449ca2be..006308dfd 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -966,7 +966,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(MnDriftData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -980,7 +980,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data3D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(MnDriftData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1023,7 +1023,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(MnDriftData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1037,7 +1037,7 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(MnDriftData%Data4D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(MnDriftData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(MnDriftData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1478,7 +1478,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(NewmanAppData%Data3D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1492,7 +1492,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data3D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(NewmanAppData%Data3D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1535,7 +1535,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(NewmanAppData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -1549,7 +1549,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(NewmanAppData%Data4D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(NewmanAppData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(NewmanAppData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -2129,7 +2129,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(DiffQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -2143,7 +2143,7 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(DiffQTFData%Data4D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(DiffQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(DiffQTFData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -2651,7 +2651,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir1) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(SumQTFData%Data4D%WvDir1) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the first wave direction.', & ErrStat, ErrMsg, RoutineName) @@ -2665,7 +2665,7 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) ENDIF - IF ( InitInp%WaveDirMax < MAXVAL(SumQTFData%Data4D%WvDir2) ) THEN + IF ( InitInp%WaveDirMax > MAXVAL(SumQTFData%Data4D%WvDir2) ) THEN CALL SetErrStat( ErrID_Fatal,' Maximum wave direction required of '//TRIM(Num2LStr(InitInp%WaveDirMax))//' is not'//& 'found in the WAMIT data file '//TRIM(SumQTFData%Filename)//' for the second wave direction.', & ErrStat, ErrMsg, RoutineName) From 3514a4c3a6e0f8d9db5442ace399a450233c3f14 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jan 2020 16:01:10 -0700 Subject: [PATCH 140/377] FlexSub: allowing number of base reactions to be 0 --- modules/subdyn/src/SubDyn.f90 | 45 +---------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index d72a7bc47..0812b879f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -820,7 +820,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return p%Nodes_C(I,:) = Dummy_IntAry(1:ReactCol) ENDDO -IF (Check ( ( p%nNodes_C < 1 ) .OR. (p%nNodes_C > Init%NJoints) , 'NReact must be greater than 0 and less than number of joints')) return +IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- ! Joints with reaction forces, joint number and locked/free dof @@ -1953,49 +1953,6 @@ SUBROUTINE SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat, ErrMsg ) end if end do END SUBROUTINE - - - -!------------------------------------------------------------------------------------------------------ -!> Augments VRred to VR for the constrained DOFs, somehow reversing what RemoveBCConstraints did for matrices -!Note it works for constrained nodes, still to see how to make it work for interface nodes if needed -SUBROUTINE UnReduceVRdofs(VRred,VR,rDOF,rModes, Init,p, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT(in ) :: Init - TYPE(SD_ParameterType), INTENT(in ) :: p - INTEGER, INTENT(IN ) :: rDOF ,RModes !retained DOFs after removing restrained DOFs and retained modes - REAL(LAKi), INTENT(IN ) :: VRred(rDOF, rModes) !eigenvector matrix with restrained DOFs removed - REAL(ReKi), INTENT(INOUT) :: VR(:,:) !eigenvalues including the previously removed DOFs - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER, ALLOCATABLE :: idx(:) - INTEGER :: I, I2, L !counters; I,I2 should be long, L short - - ErrStat = ErrID_None - ErrMsg = '' - - ALLOCATE(idx(p%nNodes_C*6), STAT = ErrStat ) !it contains row/col index that was originally eliminated when applying restraints - idx=0 !initialize - L=0 !initialize - DO I = 1, p%nNodes_C*6 !Cycle on reaction DOFs - IF (Init%BCs(I, 2) == 1) THEN - idx(I)=Init%BCs(I, 1) !row/col index that was originally eliminated when applying restraints - L=L+1 !number of DOFs to eliminate - ENDIF - ENDDO -! PRINT *, ' rDOF+L=',rDOF+L, 'SIZE(Phi2)=',SIZE(VR,1) -! ALLOCATE(VR(rDOF+L,rModes), STAT = ErrStat ) !Restored eigenvectors with restrained node DOFs included - VR=0.!Initialize - - I2=1 !Initialize - DO I=1,rDOF+L !This loop inserts Vred in VR in all but the removed DOFs - IF (ALL((idx-I).NE.0)) THEN - VR(I,:)=REAL( VRred(I2,:), ReKi ) ! potentially change of precision - I2=I2+1 !Note this counter gets updated only if we insert Vred rows into VR - ENDIF - ENDDO -END SUBROUTINE UnReduceVRdofs - !------------------------------------------------------------------------------------------------------ SUBROUTINE CBApplyConstr(nDOFI, nDOFR, nDOFM, nDOFL, & MBB , MBM , KBB , PHiR , FGR , & From aa897e181d73bdb414028cca9d1b5c582588b068 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jan 2020 16:36:46 -0700 Subject: [PATCH 141/377] FlexSub: simplifying output init --- modules/subdyn/src/SubDyn.f90 | 6 +- modules/subdyn/src/SubDyn_Output.f90 | 300 +++++++++++++------------ modules/subdyn/src/SubDyn_Registry.txt | 1 - modules/subdyn/src/SubDyn_Types.f90 | 7 - 4 files changed, 152 insertions(+), 162 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 0812b879f..18b5c97cb 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -199,7 +199,6 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO Init%g = InitInput%g Init%TP_RefPoint = InitInput%TP_RefPoint Init%SubRotateZ = InitInput%SubRotateZ - p%NAvgEls = 2 !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) @@ -1023,10 +1022,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat2) If (Check( ErrStat2 /= ErrID_None ,'Error allocating SSOutList arrays')) return - -CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, & - 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ) -if(Failed()) return +CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL CleanUp() CONTAINS diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 214810acf..b4e4ad3df 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -56,14 +56,15 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - INTEGER(IntKi) :: I,J,K,K2,L,NconEls !Counters - INTEGER(IntKi) :: Junk !Temporary Holders - INTEGER(IntKi) :: iMember ! Member index (not member ID) - INTEGER(IntKi), Dimension(2) :: M !counter for two nodes at a time - type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities - REAL(ReKi) :: FCe(12) ! Pretension force from cable element + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: I,J,K2 !Counters + INTEGER(IntKi) :: iMember ! Member index (not member ID) + INTEGER(IntKi) :: iElem ! Index of element in Element List + INTEGER(IntKi) :: iNode ! Index of node in Node list + INTEGER(IntKi) :: iiElem ! Loop counter on element index + INTEGER(IntKi) :: nElemPerNode ! Number of elements connecting to a node + type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities ErrStat = 0 ErrMsg="" @@ -72,114 +73,90 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ! Check that the variables in OutList are valid CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat2, ErrMsg2 ); if(Failed()) return - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested + ! --- Allocation (size 0 if not outputs) + !IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested ! Allocate SDWrOuput which is used to store a time step's worth of output channels, prior to writing to a file. - CALL AllocAry(misc%SDWrOutput, p%NumOuts +p%OutAllInt*p%OutAllDims, 'SDWrOutupt', ErrStat2, ErrMsg2) ; if(Failed()) return + CALL AllocAry(misc%SDWrOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'SDWrOutupt' , ErrStat2, ErrMsg2) ; if(Failed()) return + ! Allocate WriteOuput + CALL AllocAry(y%WriteOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return + ! Header, and Units, copy of data already available in the OutParam data structure ! TODO TODO TODO remove copy + CALL AllocAry(InitOut%WriteOutputHdr, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputHdr', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(InitOut%WriteOutputUnt, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputUnt', ErrStat2, ErrMsg2); if(Failed()) return misc%SDWrOutput = 0.0_ReKi misc%LastOutTime = 0.0_DbKi misc%Decimat = 0 - - !Allocate WriteOuput - CALL AllocAry(y%WriteOutput, p%NumOuts +p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return y%WriteOutput = 0 - - - DO I=1,p%NMOutputs - pLst => p%MOutLst(I) - CALL AllocAry(pLst%NodeIDs, pLst%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmIDs, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, p%NAvgEls, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - ! NOTE: MemberNodes >2 if nDiv>1 - iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers - pLst%NodeIDs=Init%MemberNodes(iMember,pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting - pLst%ElmIDs=0 !Initialize to 0 - pLst%ElmNds=0 !Initialize to 0 - - DO J=1,pLst%NoutCnt !Iterate on requested nodes for that member - !I need to get at most 2 elements that belong to the same MOutLst(I)%MemberID - !make use of MemberNodes and NodesConnE - NconEls=Init%NodesConnE(pLst%NodeIDs(J),1)!Number of elements connecting to the j-th node - - K2=0 !Initialize counter - DO K=1, NconEls - L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number - M = p%Elems(L,2:3) !1st and 2nd node of the k-th element - !Select only the other node, not the one where elements connect to - IF (M(1) .EQ. pLst%NodeIDs(J)) then - Junk=M(2) - else - Junk=M(1) - endif - IF (ANY(Init%MemberNodes(iMember,:) .EQ. Junk)) THEN !This means we are in the selected member - IF (K2 .EQ. 2) EXIT - K2=K2+1 - pLst%ElmIDs(J,K2)=L !This array has for each node requested NODEID(J), for each memberMOutLst(I)%MemberID, the 2 elements to average from, it may have 1 if one of the numbers is 0 - IF (M(2) .EQ. pLst%NodeIDs(J) )then - pLst%ElmNds(J,K2)=2 !store whether first or second node of element - else - pLst%ElmNds(J,K2)=1 !store whether first or second node of element - endif - ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), pLst%Me(:,:,J,K2)) - CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,J,K2)) - CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,J,K2), FCe) - pLst%Fg(:,J,K2) = pLst%Fg(:,J,K2) + FCe(1:12) ! Adding cable element force - END IF - ENDDO ! K, NconEls - ENDDO !J, Noutcnt + DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + END DO + + !_________________________________ OUTPUT FOR REQUESTED MEMBERS _______________________________ + DO I=1,p%NMOutputs + pLst => p%MOutLst(I) ! Alias to shorten notations + CALL AllocAry(pLst%NodeIDs, pLst%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, pLst%NoutCnt, 2, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, pLst%NoutCnt, 2, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + + ! NOTE: len(MemberNodes) >2 if nDiv>1 + iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers + pLst%NodeIDs=Init%MemberNodes(iMember,pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting + pLst%ElmIDs=0 !Initialize to 0 + pLst%ElmNds=0 !Initialize to 0 + + DO J=1,pLst%NoutCnt ! loop on requested nodes for that member + iNode = pLst%NodeIDs(J) ! Index of requested node in node list + nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the j-th node + ! Finding 1 or max 2 elements that belong to the member and connect to the node + K2=0 ! Counter so that max 2 elements are included: NOTE: I belive more than 2 should be an error + DO iiElem = 1, nElemPerNode + iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number + IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN + IF (K2 == 2) EXIT ! we found both elements already, error... + K2=K2+1 + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=J, iStore=K2, NodeID2=iNode) + END IF + ENDDO ! iiElem, nElemPerNode + ENDDO !J, Noutcnt ENDDO !I, NMOutputs - - END IF ! there are any requested outputs + !_________________________________ OUTPUT FOR ALL MEMBERS __________________________________ IF (p%OutAll) THEN !I need to store all member end forces and moments - - ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat2 ) !this list contains different arrays for each of its elements - ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init' - - DO I=1,p%NMembers - pLst => p%MOutLst2(I) - CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - pLst%MemberID=Init%Members(I,1) - pLst%NodeIDs=Init%MemberNodes(I,1:Init%Ndiv+1) !We are storing the actual node numbers in the member - !Now I need to find out which elements are attached to those nodes and still belong to the member I - !ElmIDs could contain the same element twice if Ndiv=1 - pLst%ElmIDs=0 !Initialize to 0 - DO J=1,Init%Ndiv+1,Init%Ndiv !Iterate on requested nodes for that member (first and last) - !I need to get at most 2 elements that belong to the same I Member - !make use of MemberNodes and NodesConnE - NconEls=Init%NodesConnE(pLst%NodeIDs(J),1) !Number of elements connecting to the 1st or last node of the member - K2= J/(Init%Ndiv+1)+1 !store this quantity used later, basically 1 or 2 depending on J - DO K=1, NconEls - L=Init%NodesConnE(pLst%NodeIDs(J),k+1) !k-th Element Number in the set of elements attached to the selected node - M=p%Elems(L,2:3) !1st and 2nd node of the k-th element - !Select only the other node, not the one where elements connect to - Junk=M(1) - IF (M(1) .EQ. pLst%NodeIDs(J)) Junk=M(2) - IF (ANY(Init%MemberNodes(I,:) .EQ. Junk)) THEN !This means we are in the selected member - pLst%ElmIDs(K2,1)=L !This array has for each node requested NODEID(J), for each member I, the element to get results for - pLst%ElmNds(K2,1)=1 !store whether first or second node of element - IF (M(2) .EQ. pLst%NodeIDs(J) ) pLst%ElmNds(K2,1)=2 !store whether first or second node of element - ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), pLst%Me(:,:,K2, 1)) - CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,K2, 1)) - CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,K2,1), FCe) - pLst%Fg(:,K2,1) = pLst%Fg(:,K2,1) + FCe(1:12) ! Adding cable element force + + ! MOutLst2: nodal output info by members, for all members, First and Last Node + ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat2 ); ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init'; if(Failed()) return + + DO iMember=1,p%NMembers + pLst => p%MOutLst2(iMember) ! Alias + CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + pLst%MemberID = Init%Members(iMember,1) + pLst%NodeIDs = Init%MemberNodes(iMember,1:Init%Ndiv+1) ! We are storing the actual node numbers in the member + !ElmIDs could contain the same element twice if Ndiv=1 + pLst%ElmIDs=0 !Initialize to 0 + DO J=1,Init%Ndiv+1,Init%Ndiv ! loop on first and last node of member + iNode = pLst%NodeIDs(J) ! Index of requested node in node list + nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the 1st or last node of the member + K2= J/(Init%Ndiv+1)+1 ! 1 (first node) or 2 (last node) depending on J + DO iiElem=1, nElemPerNode + iElem = Init%NodesConnE(iNode,iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node + IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=K2, iStore=1, NodeID2=iNode) EXIT !We found the element for that node, exit loop on elements - ENDIF - ENDDO - ENDDO - ENDDO - ENDIF + ENDIF + ENDDO + ENDDO ! Loop on divisions + ENDDO ! Loop on members + ENDIF ! OutAll !_____________________________________REACTIONS_____________________________________________ + ! --- Check if reaction requested by user p%OutReact = .FALSE. DO I=1,p%NumOuts if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" @@ -187,61 +164,86 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) EXIT ENDIF ENDDO - IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being - - ALLOCATE ( p%MOutLst3(p%nNodes_C), STAT = ErrStat2) !this list contains different arrays for each of its elements - ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init' - if(Failed()) return + ! MOutLst3: nodal output info by members, for the members involved in reaction + ALLOCATE(p%MOutLst3(p%nNodes_C), STAT = ErrStat2); ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init'; if(Failed()) return DO I=1,p%nNodes_C !For all constrained node pLst => p%MOutLst3(I) - pLst%Noutcnt=p%Nodes_C(I,1) !Assign nodeID for list I, I am using Noutcnt as a temporary holder for it, since nodeID is n array - NconEls=Init%NodesConnE(pLst%Noutcnt,1) !Number of elements connecting to the joint - ! ElmIDs: element IDs connecting to the joint; (1,NconEls) and not (NconEls) as the same meshauxtype is used with other MOutLst - ! Me: has for each selected joint, and for each element attached to that node, a 12x12 matrix (extra dimension redundant) - ! Ke: has for each selected joint, and for each element attached to that node a 12x12 matrix - CALL AllocAry(pLst%ElmIDs, 1, NconEls, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, 1, NconEls, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12 , 1, NconEls, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12 , 1, NconEls, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - DO K=1, NconEls - L=Init%NodesConnE(pLst%Noutcnt,k+1) !k-th Element Number in the set of elements attached to the selected node - pLst%ElmIDs(1,K)=L !This array has for each joint requested the elements' ID to get results for - M=p%Elems(L,2:3) !1st and 2nd node of the k-th element - !Select whether the joint is the 1st or second node of the element - pLst%ElmNds(1,K)=1 !store whether first or second node of element - IF (M(2) .EQ. pLst%Noutcnt ) pLst%ElmNds(1,K)=2 !store whether first or second node of element - ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(L), pLst%Me(:,:,1,K)) - CALL ElemK(p%ElemProps(L), pLst%Ke(:,:,1,K)) - CALL ElemF(p%ElemProps(L), Init%g, pLst%Fg(:,1,K), FCe) - pLst%Fg(:,1,K) = pLst%Fg(:,1,K) + FCe(1:12) ! Adding cable element force + iNode = p%Nodes_C(I,1) ! Note: Nodes_C has been reindexed + nElemPerNode = Init%NodesConnE(iNode,1) ! Number of elements connecting to the joint + CALL AllocAry(pLst%ElmIDs, 1, nElemPerNode, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 1, nElemPerNode, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + DO iiElem = 1, nElemPerNode + iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=1, iStore=iiElem, NodeID2=iNode) ENDDO ENDDO ! Compute p%TIreact, matrix to calculate single point reaction at the base of structure CALL ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) ENDIF - - ! These variables are to help follow the framework template, but the data in them is simply a copy of data - ! already available in the OutParam data structure - CALL AllocAry(InitOut%WriteOutputHdr, p%NumOuts+p%OutAllint*p%OutAllDims, 'WriteOutputHdr', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(InitOut%WriteOutputUnt, p%NumOuts+p%OutAllint*p%OutAllDims, 'WriteOutputUnt', ErrStat2, ErrMsg2); if(Failed()) return - DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims - InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) - END DO - RETURN CONTAINS LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SDOut_Init') Failed = ErrStat >= AbortErrLev -! if (Failed) call CleanUp() END FUNCTION Failed + + !> Returns true if an element is connected to node iNode, and along member iMember + LOGICAL FUNCTION ThisElementIsAlongMember(iElem, iNode, iMember) + integer(IntKi), intent(in) :: iElem !< Element index + integer(IntKi), intent(in) :: iNode !< Node index + integer(IntKi), intent(in) :: iMember !< Member index + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + integer(IntKi) :: iOtherNode ! Other node than iNode for element iElem + ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the element + ! Check that the other node belongs to the member + IF (ElemNodes(1) == iNode) then + iOtherNode=ElemNodes(2) + else if (ElemNodes(2) == iNode) then + iOtherNode=ElemNodes(1) + else + ThisElementIsAlongMember=.false. ! Not along member since nodes don't match + return + endif + ! Being along the member means the second node of the element is in the node list of the member + ThisElementIsAlongMember= ANY(Init%MemberNodes(iMember,:) == iOtherNode) + END FUNCTION + + !> Set different "data" for a given output node, and possibly store more than one "data" per node: + !! The "data" is: + !! - Mass, stiffness matrices and constant element force (gravity and cable) + !! - A flag whether the node is the 1st or second node of an element + !! The "data" is stored at the index (iiNode,iStore): + !! - iiNode: node index within the list of nodes that are to be used for output for this member + !! - iStore: index over the number of "data" stored per node. E.g. Member1 and 2 connecting to a node + SUBROUTINE ConfigOutputNode_MKF_ID(pLst, iElem, iiNode, iStore, NodeID2) + type(MeshAuxDataType), intent(inout) :: pLst !< Info for one member output + integer(IntKi) , intent(in) :: iElem !< Element index to which the node belong + integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) + integer(IntKi) , intent(in) :: iStore !< Storage index, used several informations are stored per node + integer(IntKi) , intent(in) :: NodeID2 !< If ElemNode(2) == NodeID2, then it's the second node + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + pLst%ElmIDs(iiNode,iStore) = iElem ! This array has for each joint requested the elements' ID to get results for + ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the k-th element + if (ElemNodes(2) == NodeID2) then + pLst%ElmNds(iiNode,iStore) = 2 ! store whether first or second node of element + else + pLst%ElmNds(iiNode,iStore) = 1 ! store whether first or second node of element + endif + ! --- Element Me, Ke, Fg, Fce + CALL ElemM(p%ElemProps(iElem), pLst%Me(:,:,iiNode,iStore)) + CALL ElemK(p%ElemProps(iElem), pLst%Ke(:,:,iiNode,iStore)) + CALL ElemF(p%ElemProps(iElem), Init%g, pLst%Fg(:,iiNode,iStore), FCe) + pLst%Fg(:,iiNode,iStore) = pLst%Fg(:,iiNode,iStore) + FCe(1:12) ! Adding cable element force + END SUBROUTINE ConfigOutputNode_MKF_ID + + END SUBROUTINE SDOut_Init !------------------------------------------------------------------------------------------------------ @@ -334,9 +336,9 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) FM_elm2=sgn*FM_elm FK_elm2=sgn*FK_elm - IF (pLst%ElmIDs(iiNode,p%NavgEls) .NE. 0) THEN ! Second element exist + IF (pLst%ElmIDs(iiNode,2) .NE. 0) THEN ! Second element exist ! NOTE: forces are computed in the coordinate system of the first element for averaging - call ElementForce(pLst, iiNode, p%NavgEls, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above + call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average ENDIF @@ -433,7 +435,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 ENDDO ENDDO - !junk= FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise + ! FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: @@ -450,7 +452,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInputDirCos) type(MeshAuxDataType), intent(in) :: pLst !< Info for one member output - integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given number + integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) integer(IntKi) , intent(in) :: JJ !< TODO: interpretation: index over other member connected to the current member (for averaging) real(ReKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) real(ReKi), dimension (6), intent(out) :: FM_elm, FK_elm !output static and dynamic forces and moments diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 6b36d03f2..7feb2a6e6 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -224,7 +224,6 @@ typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and rest typedef ^ ParameterType IntKi IDY {:} - - "Index array of the all dofs in Y2" typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" # --- Outputs -typedef ^ ParameterType IntKi NAvgEls - 2 - "Max number of elements that should be averaged when calculating outputs at nodes" typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 882073256..6f0788f45 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -262,7 +262,6 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDY !< Index array of the all dofs in Y2 [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] - INTEGER(IntKi) :: NAvgEls = 2 !< Max number of elements that should be averaged when calculating outputs at nodes [-] INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] @@ -7042,7 +7041,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%FGL = SrcParamData%FGL ENDIF - DstParamData%NAvgEls = SrcParamData%NAvgEls DstParamData%NMOutputs = SrcParamData%NMOutputs DstParamData%NumOuts = SrcParamData%NumOuts DstParamData%OutSwtch = SrcParamData%OutSwtch @@ -7614,7 +7612,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL END IF - Int_BufSz = Int_BufSz + 1 ! NAvgEls Int_BufSz = Int_BufSz + 1 ! NMOutputs Int_BufSz = Int_BufSz + 1 ! NumOuts Int_BufSz = Int_BufSz + 1 ! OutSwtch @@ -8497,8 +8494,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%FGL) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NAvgEls - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMOutputs Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts @@ -9925,8 +9920,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%FGL) DEALLOCATE(mask1) END IF - OutData%NAvgEls = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 OutData%NMOutputs = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NumOuts = IntKiBuf( Int_Xferred ) From 93db96f72a8e1285a3aff3f3e790bcd1118a09b9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jan 2020 21:12:22 -0700 Subject: [PATCH 142/377] FlexSub: fixed rigid assemblies issues (unique nodes list, storing DOFtilde for RA, using RAm1(ie)), more todo --- modules/subdyn/src/FEM.f90 | 17 ++- modules/subdyn/src/IntegerList.f90 | 107 +++++++++++++++--- modules/subdyn/src/SD_FEM.f90 | 165 +++++++++++++++------------- modules/subdyn/src/SubDyn.f90 | 15 ++- modules/subdyn/src/SubDyn_Tests.f90 | 19 +++- 5 files changed, 214 insertions(+), 109 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 478186e15..82605b77f 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -728,7 +728,6 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) integer :: L !< integer :: LWORK !< integer :: INFO - integer :: rank real(ReKi) :: tol M = size(A,1) N = size(A,2) @@ -757,14 +756,14 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) ! --- Compute rank - tol=maxval(shape(A))*epsilon(maxval(S)) - rank=0 - do i=1,K - if(S(i) .gt. tol)then - rank=rank+1 - end if - end do - print*,'Rank',rank + !tol=maxval(shape(A))*epsilon(maxval(S)) + !rank=0 + !do i=1,K + ! if(S(i) .gt. tol)then + ! rank=rank+1 + ! end if + !end do + !print*,'Rank',rank ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),Vt(1:r,:))) END SUBROUTINE PseudoInverse diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index e8530eedd..9ad8c7298 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -27,7 +27,12 @@ module IntegerList end interface interface find module procedure find_list - module procedure find_raw + module procedure find_intarray + end interface + interface unique + module procedure unique_list + module procedure unique_intarray + module procedure unique_intarray_in_place end interface contains @@ -233,23 +238,17 @@ integer(IntKi) function find_list(L, e, ErrStat, ErrMsg) endif end function find_list - !> Returns index of val in Array (val is an integer!) - ! NOTE: in the future use intrinsinc function findloc - function find_raw(Array, Val) result(i) - integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == Array(i) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 - end function + !> Unique, in place + subroutine unique_list(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (len(L)>0) then + call unique_intarray_in_place(L%List) + endif + end subroutine !> Print subroutine print_list(L, varname, u_opt) @@ -329,6 +328,78 @@ Integer(IntKi) function binary_search(x, x0) result(i_inf) end do end function binary_search + !> Returns index of val in Array (val is an integer!) + ! NOTE: in the future use intrinsinc function findloc + function find_intarray(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 + end function + + !> return in res the unique values of v + subroutine unique_intarray(v,res) + ! Arguments + integer(IntKi),dimension(:),intent(in) :: v + integer(IntKi),dimension(:),allocatable::res + ! + integer(IntKi),dimension(:),pointer::tmp + integer :: k !< number of unique elements + integer :: i, j + if (allocated(res)) deallocate(res) + allocate(tmp(1:size(v))) + k = 1 + tmp(1) = v(1) + outer: do i=2,size(v) + do j=1,k + if (tmp(j) == v(i)) then + ! Found a match so start looking again + cycle outer + end if + end do + ! No match found so add it to the output + k = k + 1 + tmp(k) = v(i) + end do outer + allocate(res(1:k)) + res(1:k)=tmp(1:k) + deallocate(tmp) + end subroutine + + subroutine unique_intarray_in_place(v) + integer(IntKi),dimension(:),allocatable :: v + integer(IntKi),dimension(:),allocatable::res + integer :: k !< number of unique elements + integer :: i, j + allocate(res(1:size(v))) + k = 1 + res(1) = v(1) + outer: do i=2,size(v) + do j=1,k + if (res(j) == v(i)) then + ! Found a match so start looking again + cycle outer + end if + end do + ! No match found so add it to the output + k = k + 1 + res(k) = v(i) + end do outer + deallocate(v) + allocate(v(1:k)) + v(1:k)=res(1:k) + deallocate(res) + end subroutine + !> Resize integer array of dimension 1 subroutine resize_array(array,nNewSize,default_val) integer(IntKi),dimension(:),allocatable,intent(inout) :: array diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 36c4de4fe..72d0337e7 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -75,21 +75,20 @@ MODULE SD_FEM !> Maps nodes to elements !! allocate NodesConnE and NodesConnN SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) - USE qsort_c_module ,only: QsortC - TYPE(SD_InitType), INTENT( INOUT ) :: Init - TYPE(SD_ParameterType), INTENT( IN ) :: p - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements - INTEGER(IntKi) :: I,J,K !counter - - ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) - CALL AllocAry(Init%NodesConnE, p%nNodes, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; - CALL AllocAry(Init%NodesConnN, p%nNodes, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; - Init%NodesConnE = 0 - Init%NodesConnN = -99999 ! Not Used - + TYPE(SD_InitType), INTENT( INOUT ) :: Init + TYPE(SD_ParameterType), INTENT( IN ) :: p + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements + INTEGER(IntKi) :: I,J,K !counter + + ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) + CALL AllocAry(Init%NodesConnE, p%nNodes, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnN, p%nNodes, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; + Init%NodesConnE = 0 + Init%NodesConnN = -99999 ! Not Used + ! find the node connectivity, nodes/elements that connect to a common node DO I = 1, p%nNodes !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array @@ -101,23 +100,9 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); endif Init%NodesConnE(I, k + 1) = p%Elems(J, 1) - !if ( NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) then - ! Init%NodesConnN(I, k + 1) = p%Elems(J, 2) !If nodeID matches 2nd node of element - !else - ! Init%NodesConnN(I, k + 1) = p%Elems(J, 3) - !endif ENDIF ENDDO - - !IF( k>1 )THEN ! sort the nodes ascendingly - ! SortA(1:k, 1) = Init%NodesConnN(I, 3:(k+2)) - ! CALL QsortC( SortA(1:k, 1:1) ) - ! Init%NodesConnN(I, 3:(k+2)) = SortA(1:k, 1) - !ENDIF - Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column - !Init%NodesConnN(I, 2) = k - !print*,'ConnE',I,'val',Init%NodesConnE(I, 1:5) ENDDO END SUBROUTINE NodeCon @@ -201,17 +186,16 @@ END FUNCTION RigidLinkElements !------------------------------------------------------------------------------------------------------ !> Returns true if one of the element connected to the node is a rigid link -LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) - INTEGER(IntKi), INTENT(IN) :: iJoint - TYPE(SD_InitType), INTENT(IN) :: Init - TYPE(SD_ParameterType), INTENT(IN) :: p +LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p, ei) + integer(IntKi), intent(in) :: iJoint + type(SD_InitType), intent(in) :: Init + type(SD_ParameterType), intent(in) :: p + integer(IntKi), intent( out) :: ei !< Element index that connects do iJoint rigidly ! Local variables integer(IntKi) :: ie !< Loop index on elements - integer(IntKi) :: ei !< Element index integer(IntKi) :: m ! Number of elements connected to a joint NodeHasRigidElem = .False. ! default return value - ! Loop through elements connected to node J do ie = 1, Init%NodesConnE(iJoint, 1) ei = Init%NodesConnE(iJoint, ie+1) @@ -220,6 +204,7 @@ LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p) return ! we exit as soon as one rigid member is found endif enddo + ei=-1 END FUNCTION NodeHasRigidElem !------------------------------------------------------------------------------------------------------ @@ -370,20 +355,18 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN NNE = 2 ELSE - CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.') - RETURN + CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.'); return ENDIF ! Total number of element - Init%NElem = p%NMembers*Init%NDiv ! TODO TODO TODO: THIS IS A MAX SINCE CABLE AND RIGID CANNOT BE SUBDIVIDED + Init%NElem = p%NMembers*Init%NDiv ! Note: This is a max since cable and rigid cannot be subdivided ! Total number of nodes - Depends on division and number of nodes per element p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! TODO TODO TODO Same as above. + p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! Note: Same as above. Can be improved by counting R&C ! check the number of interior modes IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))) - RETURN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))); return ENDIF CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different @@ -435,13 +418,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) if (eType/=idMemberBeam) then ! --- Cables and rigid links are not subdivided ! No need to create new properties or new nodes - print*,'Member',I, 'not subdivided since it is not a beam. Looping through.' Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, 2) = Node2 kelem = kelem + 1 CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p) - - continue + cycle endif ! --- Subdivision of beams @@ -999,11 +980,13 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) type(IList) :: IRA !< list of rigid assembly indices to process integer(IntKi) :: aID, ia ! assembly ID, and index in IRA integer(IntKi) :: iNode + integer(IntKi) :: er !< Index of one rigid element belong to a rigid assembly integer(IntKi) :: JType integer(IntKi) :: I integer(IntKi) :: nc !< Number of DOF after constraints applied integer(IntKi) :: nj real(ReKi) :: phat(3) !< Directional vector of the joint + type(IList), dimension(:), allocatable :: RA_DOFtilde ! DOF indices for each rigid assembly, in reduced system INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None @@ -1013,6 +996,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) nullify(IDOFNew) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) allocate(p%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + allocate(RA_DOFtilde(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system p%nDOF_red = nDOF_ConstraintReduced() print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF @@ -1032,14 +1016,22 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) if (allocated(IDOFOld)) deallocate(IDOFOld) JType = int(Init%Nodes(iNode,iJointType)) if(JType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then + if ( NodeHasRigidElem(iNode, Init, p, er)) then ! --- Joint involved in a rigid link assembly - aID = RAm1(iNode) - ia = find(IRA, aID, ErrStat2, ErrMsg2) + aID = RAm1(er) + if (aID<0) then + call Fatal('No rigid assembly attributed to node'//trim(Num2LStr(iNode))//'. RAm1 wrong'); return + endif + ia = find(IRA, aID, ErrStat2, ErrMsg2); if(Failed()) return print*,'Node',iNode, 'is involved in RA', aID, ia if ( ia <= 0) then - ! This rigid assembly has already been processed, pass to next node - cycle + ! This rigid assembly has already been processed + ! The DOF list is taken from the stored RA DOF list + call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) + print*,'The RA',aID,', has already been processed!' + print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) + print*,'N',iNode,'It',p%NodesDOFtilde(iNode)%List + cycle ! We pass to the next joint else call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed @@ -1048,6 +1040,11 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) do I=1, nj IDOFOld( (I-1)*6+1 : I*6 ) = p%NodesDOF(INodesID(I))%List(1:6) enddo + + ! Storing DOF list for this RA (Note: same as NodesDOFtilde below) + nc=size(Tc,2) + call init_list(RA_DOFtilde(aID), (/ (iprev + i, i=1,nc) /), ErrStat2, ErrMsg2); + endif else ! --- Regular cantilever joint @@ -1074,12 +1071,10 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) enddo ! --- Safety checks if (len(IRA)>0) then - ErrMsg2='Not all rigid assemblies were processed'; ErrStat2=ErrID_Fatal - if(Failed()) return + call Fatal('Not all rigid assemblies were processed'); return endif if (iPrev /= p%nDOF_red) then - ErrMsg2='Inconsistency in number of reduced DOF'; ErrStat2=ErrID_Fatal - if(Failed()) return + call Fatal('Inconsistency in number of reduced DOF'); return endif call CleanUp_BuildTMatrix() contains @@ -1089,6 +1084,11 @@ LOGICAL FUNCTION Failed() if (Failed) call CleanUp_BuildTMatrix() END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'BuildTMatrix'); + END SUBROUTINE Fatal + SUBROUTINE CleanUp_BuildTMatrix() nullify(IDOFNew) call destroy_list(IRA, ErrStat2, ErrMsg2) @@ -1126,7 +1126,7 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() print*,'Node',iNode, 'is a ball joint, number of members involved: ', m elseif(NodeType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p)) then + if ( NodeHasRigidElem(iNode, Init, p, er)) then ! This joint is involved in a rigid link assembly, we skip it (accounted for above) print*,'Node',iNode, 'is involved in a RA' else @@ -1236,6 +1236,7 @@ SUBROUTINE ReInitIntFc(Init, p) INTEGER(IntKi) :: I, J, iNode DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index + print*,'iNode',iNode DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) ENDDO @@ -1248,7 +1249,7 @@ END SUBROUTINE DirectElimination !! x_c = Tc.x_c_tilde !! where x_c are all the DOF of the rigid assembly, and x_c_tilde are the 6 reduced DOF (leader DOF) SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get, unique, find integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements real(ReKi), dimension(:,:), allocatable :: Tc integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements @@ -1258,11 +1259,12 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables type(IList) :: LNodesID !< List of nodes id involved in element - type(IList) :: INodesInterf !< List of indices for Nodes involved in interface + type(IList) :: LNodesInterf !< List of nodes id involved in interface integer(IntKi) :: NodeID !< NodeID integer(IntKi) :: iTmp !< Temporary index integer(IntKi) :: iNodeID !< Loop index on node ID list - integer(IntKi) :: iMainNode !< Index of main node selected for rigid assembly within INodesID list + integer(IntKi) :: iiMainNode !< Index of main node selected for rigid assembly within INodesID list + integer(IntKi) :: iMainNode !< Main node index integer(IntKi) :: nNodes !< Number of Nodes involved in RA integer(IntKi) :: iFound !< Loop index on node ID list integer(IntKi) :: i !< Loop index @@ -1275,39 +1277,45 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) ! --- List of nodes stored first in LINodes than moved to INodes LNodesID = NodesList(p, Elements) - if (allocated(INodesID)) deallocate(INodesID) - call move_alloc(LNodesID%List, INodesID) - call destroy_list(LNodesID, ErrStat2, ErrMsg2) - print*,'Nodes involved in assembly (befr) ',INodesID + print*,'Nodes involved in assembly (bfr1) ',LNodesID%List + call unique(LNodesID, ErrStat2, ErrMsg2); + print*,'Nodes involved in assembly (bfr2) ',LNodesID%List !--- Look for potential interface node - call init_list(INodesInterf, 0, 0, ErrStat2, ErrMsg2); - do iNodeID = 1, size(INodesID) - NodeID = INodesID(iNodeID) + call init_list(LNodesInterf, 0, 0, ErrStat2, ErrMsg2); + do iNodeID = 1, len(LNodesID) + NodeID = LNodesID%List(iNodeID) iFound = FINDLOCI( p%Nodes_I(:,1), NodeID) if (iFound>0) then - call append(INodesInterf, iNodeID, ErrStat2, ErrMsg2) + call append(LNodesInterf, NodeID, ErrStat2, ErrMsg2) ! This node is an interface node print*,'Node',NodeID, 'is an interface node, selecting it for the rigid assembly' endif enddo ! --- Decide which node will be the main node of the rigid assembly - if (len(INodesInterf)==0) then - iMainNode = 1 ! By default we select the first node - else if (len(INodesInterf)==1) then - iMainNode = pop(INodesInterf, ErrStat2, ErrMsg2) + if (len(LNodesInterf)==0) then + iiMainNode = 1 ! By default we select the first node + else if (len(LNodesInterf)==1) then + ! Finding the index of the interface node + iMainNode = pop(LNodesInterf, ErrStat2, ErrMsg2) + iiMainNode = find(LNodesID, iMainNode, ErrStat2, ErrMsg2); else ErrStat=ErrID_Fatal ErrMsg='Cannot have several interface nodes linked within a same rigid assembly' return endif - call destroy_list(INodesInterf, ErrStat2, ErrMsg2) + call destroy_list(LNodesInterf, ErrStat2, ErrMsg2) + + ! --- Extracting index array from list + if (allocated(INodesID)) deallocate(INodesID) + call move_alloc(LNodesID%List, INodesID) + call destroy_list(LNodesID, ErrStat2, ErrMsg2) ! --- Order list of joints with main node first (swapping iMainNode with INodes(1)) - iTmp = INodesID(1) - INodesID(1) = iMainNode - INodesID(iMainNode) = iTmp + iTmp = INodesID(1) + INodesID(1) = INodesID(iiMainNode) + INodesID(iiMainNode) = iTmp print*,'Nodes involved in assembly (after)',INodesID ! --- Building Transformation matrix @@ -1435,6 +1443,7 @@ END SUBROUTINE JointElimination !------------------------------------------------------------------------------------------------------ !> Setup a list of rigid link assemblies (RA) +!! RA(a) = [e1,..,en] : list of elements that form the rigid assembly of index "a" SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get TYPE(SD_InitType), INTENT(INOUT) :: Init @@ -1467,7 +1476,7 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) e0 = pop(Er, ErrStat2, ErrMsg2); call append(Ea, e0, ErrStat2, ErrMsg2); call AddNeighbors(e0, Er, Ea) - call print_list(Ea,'Rigid assembly') + call print_list(Ea,'Rigid assembly (loop 1)') do ie = 1, len(Ea) e0 = get(Ea, ie, ErrStat2, ErrMsg2) RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to @@ -1489,10 +1498,10 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) endif enddo do ia = 1, nRA - call print_list(RA(ia),'Rigid assembly') + call print_list(RA(ia),'Rigid assembly (loop 2)') enddo CONTAINS - !> The neighbors of e0 (that are found within the list Er) are added to the list Ea + !> The neighbor-elements of element e0 (that are found within the list Er) are added to the list Ea RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) integer(IntKi), intent(in) :: e0 !< Index of an element type(IList), intent(inout) :: Er !< List of rigid elements @@ -1508,12 +1517,13 @@ RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) ik=ik+1 ek = Er%List(ik) if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then - print*,'Element ',ek,'is connected to ',e0,'via its node',iWhichNode_ek + print*,'Element ',ek,'is connected to element',e0,'via its node',iWhichNode_ek ! Remove element from Er (a rigid element can belong to only one assembly) ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before ik=ik-1 if (ek/=ek2) then print*,'Problem in popping',ek,ek2 + STOP endif call append(En, ek, ErrStat2, ErrMsg2) call append(Ea, ek, ErrStat2, ErrMsg2) @@ -1527,7 +1537,6 @@ RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) call destroy_list(En, ErrStat2, ErrMsg2) END SUBROUTINE AddNeighbors - END SUBROUTINE RigidLinkAssemblies diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 18b5c97cb..80e1319bb 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1830,7 +1830,6 @@ SUBROUTINE TrnsfTI(Init, p, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) ! returns Line TI2(I, 1:6) = Line ENDDO - END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ @@ -2423,6 +2422,20 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') 'Unless specified, units are consistent with Input units, [SI] system is advised.' WRITE(UnSum, '(A)') SectionDivide + !write(UnSum,'(A)')'Nodes_I',p%Nodes_I(:,1) + !write(UnSum,'(A)')'Nodes_C',p%Nodes_C(:,1) + !write(UnSum,'(A)')'Nodes_L',p%Nodes_L + write(UnSum,'(A,I0)')'Number of DOFs: "interface" (I): ',p%nDOFI + write(UnSum,'(A,I0)')'Number of DOFs: "reactions" (C): ',p%nDOFC + write(UnSum,'(A,I0)')'Number of DOFs: interface (R): ',p%nDOFR + write(UnSum,'(A,I0)')'Number of DOFs: internal (L): ',p%nDOFL + write(UnSum,'(A,I0)')'Number of DOFs: total (R+L): ',p%nDOF_red + write(UnSum,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I + write(UnSum,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C + write(UnSum,'(A,I0)')'Number of Nodes: internal (L): ',p%nNodes_L + write(UnSum,'(A,I0)')'Number of Nodes: total (R+L): ',p%nNodes + + WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',p%nNodes WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index c5bfdd19b..7507981ce 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -1,9 +1,11 @@ module SubDyn_Tests use NWTC_Library - USE SubDyn_Types - USE SD_FEM + use SubDyn_Types + use SD_FEM use IntegerList + implicit none + public :: SD_Tests private @@ -126,6 +128,7 @@ subroutine test_almost_equal_0(Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) ! Variables character(len=255) :: InfoAbs real(ReKi) :: delta + integer :: cpt ! cpt=0 delta=abs(Ref-Try) @@ -264,6 +267,7 @@ subroutine Test_Transformations(ErrStat,ErrMsg) real(ReKi), dimension(6,6) :: T, Tref real(ReKi) :: L integer(IntKi) :: I + testname='Transf' ! --- DirCos P1=(/0,0,0/) @@ -305,6 +309,7 @@ subroutine Test_Linalg(ErrStat,ErrMsg) character(ErrMsgLen), intent(out) :: ErrMsg real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref integer(IntKi) :: I, J + testname='Linalg' ! --- Inverse of a 3x3 matrix allocate(A(3,3)); allocate(Aref(3,3)) @@ -390,8 +395,16 @@ subroutine Test_lists(ErrStat,ErrMsg) call test_equal('pop ',e , 3) e = pop(L1, ErrStat, ErrMsg) call test_equal('pop ',e , 5) + call destroy_list(L1, ErrStat, ErrMsg) + + ! test unique + call init_list(L1,(/5,3,2,3,8/),ErrStat, ErrMsg) + call unique(L1, ErrStat, ErrMsg) + call test_equal('uniq ',L1%List, (/5,3,2,8/) , .true. , .false.) - end subroutine + call destroy_list(L1, ErrStat, ErrMsg) + call destroy_list(L2, ErrStat, ErrMsg) + end subroutine Test_lists subroutine SD_Tests(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation From a71e70cacc8af7ee84ff740d2ae75a8542ce47c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jan 2020 22:06:55 -0700 Subject: [PATCH 143/377] FlexSub: FE of full system done only if summary file requested, fixed cosine matrix --- modules/subdyn/src/SD_FEM.f90 | 1 - modules/subdyn/src/SubDyn.f90 | 90 +++++---- modules/subdyn/src/SubDyn_Registry.txt | 5 - modules/subdyn/src/SubDyn_Types.f90 | 262 ------------------------- 4 files changed, 47 insertions(+), 311 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 72d0337e7..ac63a0218 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1236,7 +1236,6 @@ SUBROUTINE ReInitIntFc(Init, p) INTEGER(IntKi) :: I, J, iNode DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index - print*,'iNode',iNode DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) ENDDO diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 80e1319bb..84ae4a19e 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -177,7 +177,6 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! local variables TYPE(SD_InitType) :: Init TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file - TYPE(FEM_MatArrays) :: FEMparams ! FEM parameters to be stored and written to summary file INTEGER(IntKi) :: ErrStat2 ! Error status of the operation CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None @@ -233,17 +232,10 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Assemble Stiffness and mass matrix CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Eigen values of full system (for summary file output only) - ! True below is to remove the constraints - ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - FEMparams%NOmega = p%nDOF - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change - CALL AllocAry(FEMparams%Omega, FEMparams%NOmega, 'FEMparams%Omega', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(FEMparams%Modes, p%nDOF, FEMparams%NOmega, 'FEMparams%Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL EigenSolveWrap( Init%K, Init%M, p%nDOF, FEMparams%NOmega, .True., Init, p, FEMparams%Modes, FEMparams%Omega, ErrStat2, ErrMsg2 ); if(Failed()) return - ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! --- Additional Damping and stiffness at pin/ball/universal joints CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return @@ -297,9 +289,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO IF ( Init%SSSum ) THEN ! note p%KBB/MBB are KBBt/MBBt ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init,p,FEMparams,CBparams, ErrStat2, ErrMsg2); if(Failed()) return - IF( ALLOCATED(Init%K) ) DEALLOCATE(Init%K) - IF( ALLOCATED(Init%M) ) DEALLOCATE(Init%M) + CALL OutSummary(Init, p, InitInput, CBparams, ErrStat2, ErrMsg2); if(Failed()) return ENDIF ! Initialize the outputs & Store mapping between nodes and elements @@ -325,7 +315,6 @@ END FUNCTION Failed SUBROUTINE CleanUp() CALL SD_DestroyInitType(Init, ErrStat2, ErrMsg2) CALL SD_DestroyCB_MatArrays( CBparams, ErrStat2, ErrMsg2 ) ! local variables - CALL SD_DestroyFEM_MatArrays( FEMparams, ErrStat2, ErrMsg2 ) ! local variables END SUBROUTINE CleanUp END SUBROUTINE SD_Init @@ -2378,11 +2367,11 @@ END SUBROUTINE ConstructUFL !------------------------------------------------------------------------------------------------------ !> Output the summary file -SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) +SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file + TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use - TYPE(FEM_MatArrays), INTENT(IN) :: FEMparams ! FEM parameters that will be passed in for summary file use INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None !LOCALS @@ -2391,6 +2380,7 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file INTEGER(IntKi) :: i, j, k, propIDs(2), Iprop(2) !counter and temporary holders + INTEGER(IntKi) :: iNode1, iNode2 ! Node indices INTEGER(IntKi) :: mType ! Member Type Real(ReKi) :: mMass, mLength ! Member mass and length REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix @@ -2398,21 +2388,29 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices + ! Variables for Eigenvalue analysis + integer(IntKi) :: nOmega + real(ReKi), dimension(:,:), allocatable :: Modes + real(ReKi), dimension(:) , allocatable :: Omega + ! ErrStat = ErrID_None ErrMsg = "" + ! --- Eigen values of full system (for summary file output only) + ! True below is to remove the constraints + ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + nOmega = p%nDOF_red - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change + CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL EigenSolveWrap( Init%K, Init%M, p%nDOF_red, nOmega, .True., Init, p, Modes, Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + !------------------------------------------------------------------------------------------------------------- ! open txt file !------------------------------------------------------------------------------------------------------------- SummaryName = TRIM(Init%RootName)//'.sum' UnSum = -1 ! we haven't opened the summary file, yet. - CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ) - CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init' ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE(UnSum) - RETURN - END IF + CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ); if(Failed()) return !------------------------------------------------------------------------------------------------------------- ! write discretized data to a txt file @@ -2434,6 +2432,8 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) write(UnSum,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C write(UnSum,'(A,I0)')'Number of Nodes: internal (L): ',p%nNodes_L write(UnSum,'(A,I0)')'Number of Nodes: total (R+L): ',p%nNodes + write(UnSum,'(A,3(E15.6))')'TP reference point:',InitInput%TP_RefPoint(1:3) + WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') @@ -2502,20 +2502,13 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A, I6)') 'Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers WRITE(UnSum, '(A9,9(A15))') 'Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' DO i=1,p%NMembers - !Find the right index in the Nodes array for the selected JointID. This is horrible, but I do not know how to implement this search in a more efficient way - !The alternative would be to get an element that belongs to the member and use it with dircos - -!BJJ:TODO: DIDN'T we already calculate DirCos for each element? can't we use that here? - DO j=1,p%nNodes - IF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,2) )THEN - XYZ1=Init%Nodes(Init%Members(i,2),2:4) - ELSEIF ( NINT(Init%Nodes(j,1)) .EQ. Init%Members(i,3) ) THEN - XYZ2=Init%Nodes(Init%Members(i,3),2:4) - ENDIF - ENDDO - CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) - DirCos=TRANSPOSE(DirCos) !This is now global to local - WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + iNode1 = FINDLOCI(Init%Joints(:,1), Init%Members(i,2)) ! index of joint 1 of member i + iNode2 = FINDLOCI(Init%Joints(:,1), Init%Members(i,3)) ! index of joint 2 of member i + XYZ1 = Init%Joints(iNode1,2:4) + XYZ2 = Init%Joints(iNode2,2:4) + CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) + DirCos=TRANSPOSE(DirCos) !This is now global to local + WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO !------------------------------------------------------------------------------------------------------------- @@ -2524,21 +2517,21 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') 'Eigenvalues' WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A, I6)') "FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", FEMparams%NOmega - WRITE(UnSum, '(I6, e15.6)') ( i, FEMparams%Omega(i)/2.0/pi, i = 1, FEMparams%NOmega ) + WRITE(UnSum, '(A, I6)') "FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega + WRITE(UnSum, '(I6, e15.6)') ( i, Omega(i)/2.0/pi, i = 1, nOmega ) WRITE(UnSum, '(A)') SubSectionDivide WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, p%nDOFM ) !------------------------------------------------------------------------------------------------------------- - ! write Eigenvectors of full SYstem + ! write Eigenvectors of full System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF))//' x '//TRIM(Num2LStr(FEMparams%NOmega))//& - ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), FEMparams%NOmega - WRITE(UnSum, '(6x,'//Num2LStr(FEMparams%NOmega)//'(I15))') (i, i = 1, FEMparams%NOmega )!HEADERS - WRITE(UnSum, '(I6,'//Num2LStr(FEMparams%NOmega)//'e15.6)') ( i, (FEMparams%Modes(i,j), j = 1, FEMparams%NOmega ),i = 1, p%nDOF) + WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& + ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega + WRITE(UnSum, '(6x,'//Num2LStr(nOmega)//'(I15))') (i, i = 1, nOmega )!HEADERS + WRITE(UnSum, '(I6,'//Num2LStr(nOmega)//'e15.6)') ( i, (Modes(i,j), j = 1, nOmega ),i = 1, p%nDOF_red) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices @@ -2650,8 +2643,19 @@ SUBROUTINE OutSummary(Init, p, FEMparams,CBparams, ErrStat,ErrMsg) CALL WrMatrix( p%TI, UnSum, 'e15.6', 'TI' ) #endif + call CleanUp() - CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'OutSummary') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE CleanUp() + if(allocated(Omega)) deallocate(Omega) + if(allocated(Modes)) deallocate(Modes) + CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + END SUBROUTINE CleanUp END SUBROUTINE OutSummary !------------------------------------------------------------------------------------------------------ diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 7feb2a6e6..6e6d365a2 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -45,11 +45,6 @@ typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" -# FEM_MatArrays: Matrices and arrays for FEM summary -typedef SubDyn/SD FEM_MatArrays ReKi Omega {:} - - "Eigenvalues of full FEM model, we calculate them all" -typedef ^ FEM_MatArrays INTEGER NOmega - - - "Number of full FEM Eigenvalues (for now TDOF-6*Nreact)" -typedef ^ FEM_MatArrays ReKi Modes {:}{:} - - "Eigenmodes of full FEM model, we calculate them all" - # typedef ^ ElemPropType IntKi eType - - - "Element Type" typedef ^ ^ ReKi Length - - - "Length of an element" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 6f0788f45..7fab8ba69 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -79,13 +79,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] END TYPE CB_MatArrays ! ======================= -! ========= FEM_MatArrays ======= - TYPE, PUBLIC :: FEM_MatArrays - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Omega !< Eigenvalues of full FEM model, we calculate them all [-] - INTEGER(IntKi) :: NOmega !< Number of full FEM Eigenvalues (for now TDOF-6*Nreact) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Modes !< Eigenmodes of full FEM model, we calculate them all [-] - END TYPE FEM_MatArrays -! ======================= ! ========= ElemPropType ======= TYPE, PUBLIC :: ElemPropType INTEGER(IntKi) :: eType !< Element Type [-] @@ -2194,261 +2187,6 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END IF END SUBROUTINE SD_UnPackCB_MatArrays - SUBROUTINE SD_CopyFEM_MatArrays( SrcFEM_MatArraysData, DstFEM_MatArraysData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FEM_MatArrays), INTENT(IN) :: SrcFEM_MatArraysData - TYPE(FEM_MatArrays), INTENT(INOUT) :: DstFEM_MatArraysData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyFEM_MatArrays' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcFEM_MatArraysData%Omega)) THEN - i1_l = LBOUND(SrcFEM_MatArraysData%Omega,1) - i1_u = UBOUND(SrcFEM_MatArraysData%Omega,1) - IF (.NOT. ALLOCATED(DstFEM_MatArraysData%Omega)) THEN - ALLOCATE(DstFEM_MatArraysData%Omega(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEM_MatArraysData%Omega.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstFEM_MatArraysData%Omega = SrcFEM_MatArraysData%Omega -ENDIF - DstFEM_MatArraysData%NOmega = SrcFEM_MatArraysData%NOmega -IF (ALLOCATED(SrcFEM_MatArraysData%Modes)) THEN - i1_l = LBOUND(SrcFEM_MatArraysData%Modes,1) - i1_u = UBOUND(SrcFEM_MatArraysData%Modes,1) - i2_l = LBOUND(SrcFEM_MatArraysData%Modes,2) - i2_u = UBOUND(SrcFEM_MatArraysData%Modes,2) - IF (.NOT. ALLOCATED(DstFEM_MatArraysData%Modes)) THEN - ALLOCATE(DstFEM_MatArraysData%Modes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstFEM_MatArraysData%Modes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstFEM_MatArraysData%Modes = SrcFEM_MatArraysData%Modes -ENDIF - END SUBROUTINE SD_CopyFEM_MatArrays - - SUBROUTINE SD_DestroyFEM_MatArrays( FEM_MatArraysData, ErrStat, ErrMsg ) - TYPE(FEM_MatArrays), INTENT(INOUT) :: FEM_MatArraysData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyFEM_MatArrays' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(FEM_MatArraysData%Omega)) THEN - DEALLOCATE(FEM_MatArraysData%Omega) -ENDIF -IF (ALLOCATED(FEM_MatArraysData%Modes)) THEN - DEALLOCATE(FEM_MatArraysData%Modes) -ENDIF - END SUBROUTINE SD_DestroyFEM_MatArrays - - SUBROUTINE SD_PackFEM_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FEM_MatArrays), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackFEM_MatArrays' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Omega allocated yes/no - IF ( ALLOCATED(InData%Omega) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Omega upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Omega) ! Omega - END IF - Int_BufSz = Int_BufSz + 1 ! NOmega - Int_BufSz = Int_BufSz + 1 ! Modes allocated yes/no - IF ( ALLOCATED(InData%Modes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Modes upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Modes) ! Modes - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%Omega) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Omega,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Omega,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Omega)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Omega))-1 ) = PACK(InData%Omega,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Omega) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NOmega - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Modes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Modes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Modes,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Modes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Modes,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Modes)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Modes))-1 ) = PACK(InData%Modes,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Modes) - END IF - END SUBROUTINE SD_PackFEM_MatArrays - - SUBROUTINE SD_UnPackFEM_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FEM_MatArrays), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackFEM_MatArrays' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Omega not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Omega)) DEALLOCATE(OutData%Omega) - ALLOCATE(OutData%Omega(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Omega.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Omega)>0) OutData%Omega = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Omega))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Omega) - DEALLOCATE(mask1) - END IF - OutData%NOmega = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Modes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Modes)) DEALLOCATE(OutData%Modes) - ALLOCATE(OutData%Modes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Modes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Modes)>0) OutData%Modes = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Modes))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Modes) - DEALLOCATE(mask2) - END IF - END SUBROUTINE SD_UnPackFEM_MatArrays - SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData From 5ab0e24ea5aedc764c866b413b5bec43f4760b0e Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 14 Jan 2020 11:29:43 -0700 Subject: [PATCH 144/377] [BugFix] TCF: error in coordinate transform on WAMIT2 --- modules/hydrodyn/src/WAMIT2.f90 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 006308dfd..08e9e8792 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -1144,6 +1144,10 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS RotateZdegOffset = 0.0_SiKi endif + ! NOTE: RotateZMatrixT is the rotation from local to global. + RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) + RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) + DO ThisDim=1,6 @@ -1251,16 +1255,13 @@ SUBROUTINE MnDrift_InitCalc( InitInp, p, MnDriftData, MnDriftForce, ErrMsg, ErrS ENDIF ! Load component to calculate - ! Now rotate the force components with platform orientation - ! NOTE: RotateZMatrixT is the rotation from local to global. - RotateZMatrixT(:,1) = (/ cos(InitInp%PtfmRefztRot(IBody)), -sin(InitInp%PtfmRefztRot(IBody)) /) - RotateZMatrixT(:,2) = (/ sin(InitInp%PtfmRefztRot(IBody)), cos(InitInp%PtfmRefztRot(IBody)) /) + ENDDO ! ThisDim -- Load Component on body - MnDriftForce(1:2) = MATMUL( RotateZMatrixT, MnDriftForce(1:2) ) ! Fx and Fy, rotation about z - MnDriftForce(4:5) = MATMUL( RotateZMatrixT, MnDriftForce(4:5) ) ! Mx and My, rotation about z + ! Now rotate the force components with platform orientation + MnDriftForce(1:2) = MATMUL( RotateZMatrixT, MnDriftForce(1:2) ) ! Fx and Fy, rotation about z + MnDriftForce(4:5) = MATMUL( RotateZMatrixT, MnDriftForce(4:5) ) ! Mx and My, rotation about z - ENDDO ! ThisDim -- Load Component on body ENDDO ! IBody From 5fa827410c057252d6fbb1737e981a0dbb277d46 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 14 Jan 2020 11:44:51 -0700 Subject: [PATCH 145/377] TCF: typos in WAMIT2 doxygen contents --- modules/hydrodyn/src/WAMIT2.f90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 08e9e8792..593cc60b9 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -1853,7 +1853,7 @@ SUBROUTINE NewmanApp_InitCalc( InitInp, p, NewmanAppData, NewmanAppForce, ErrMsg if (p%NBodyMod == 2) then !> The phase shift due to an (x,y) offset is of the form - !! \f$ exp(-\imath k(\omega) ( X cos(\Beta(w)) + Y sin(\beta(w)) )) \f$ + !! \f$ exp[-\imath k(\omega) ( X cos(\beta(w)) + Y sin(\beta(w)) )] \f$ ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead ! of above is mathematically equivalent, but only because each frequency has only one wave ! direction associated with it through the equal energy approach used in multidirectional waves. @@ -2336,8 +2336,8 @@ SUBROUTINE DiffQTF_InitCalc( InitInp, p, DiffQTFData, DiffQTFForce, ErrMsg, ErrS !-------------------------- if (p%NBodyMod == 2) then !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form - !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) - !! - k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\beta(w_1)) + Y sin(\beta(w_1)) ) + !! - k(\omega_2) ( X cos(\beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead ! of above is mathematically equivalent, but only because each frequency has only one wave ! direction associated with it through the equal energy approach used in multidirectional waves. @@ -2830,8 +2830,8 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat !-------------------------- if (p%NBodyMod == 2) then !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form - !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) - !! 1 k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$. + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\beta(w_1)) + Y sin(\beta(w_1)) ) + !! 1 k(\omega_2) ( X cos(\beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$. !! For the first term, \f$ \omega_1 = \omega_2 \$f. ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead ! of above is mathematically equivalent, but only because each frequency has only one wave @@ -2944,8 +2944,8 @@ SUBROUTINE SumQTF_InitCalc( InitInp, p, SumQTFData, SumQTFForce, ErrMsg, ErrStat !-------------------------- if (p%NBodyMod == 2) then !> The phase shift due to an (x,y) offset for second order difference frequencies is of the form - !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\Beta(w_1)) + Y sin(\beta(w_1)) ) - !! - k(\omega_2) ( X cos(\Beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ + !! \f$ exp[-\imath ( k(\omega_1) ( X cos(\beta(w_1)) + Y sin(\beta(w_1)) ) + !! - k(\omega_2) ( X cos(\beta(w_2)) + Y sin(\beta(w_2)) ) ) ]\f$ ! NOTE: the phase shift applies to the aWaveElevC of the incoming wave. Including it here instead ! of above is mathematically equivalent, but only because each frequency has only one wave ! direction associated with it through the equal energy approach used in multidirectional waves. From 44417ef01db67e3f16188dc3ddb436c384cab561 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 16 Jan 2020 09:44:37 -0700 Subject: [PATCH 146/377] Adding NBody > 1 to SS modules- draft --- modules/hydrodyn/src/SS_Excitation.txt | 64 ++++---- modules/hydrodyn/src/SS_Radiation.f90 | 194 ++++++++++++++++--------- modules/hydrodyn/src/SS_Radiation.txt | 40 ++--- modules/hydrodyn/src/WAMIT.f90 | 19 ++- 4 files changed, 194 insertions(+), 123 deletions(-) diff --git a/modules/hydrodyn/src/SS_Excitation.txt b/modules/hydrodyn/src/SS_Excitation.txt index 6a9dbd814..aca06ade3 100644 --- a/modules/hydrodyn/src/SS_Excitation.txt +++ b/modules/hydrodyn/src/SS_Excitation.txt @@ -15,56 +15,58 @@ # URL: $HeadURL$ ################################################################################################################################### -typedef SS_Excitation/SS_Exc InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - -typedef ^ ^ ReKi WaveDir - - - "Wave direction" rad -typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - -typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m -typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s - -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {7} - - "Header of the output" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {7} - - "Units of the output" - - -typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - - -typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - - -# Define constraint states here: -typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - +typedef SS_Excitation/SS_Exc InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - +typedef ^ ^ ReKi WaveDir - - - "Wave direction" rad +typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m +typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s + +typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {7} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {7} - - "Units of the output" - + +typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - + +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - + +# Define constraint states here: +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - # Define any data that are other states, including integer or logical states here: -typedef ^ OtherStateType IntKi n - - - "Current Time step" - -typedef ^ ^ SS_Exc_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - +typedef ^ OtherStateType IntKi n - - - "Current Time step" - +typedef ^ ^ SS_Exc_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType INTEGER LastIndWave - 1 - "last used index in the WaveTime array" - +typedef ^ MiscVarType INTEGER LastIndWave - 1 - "last used index in the WaveTime array" - # ..... Parameters ......................... # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType DbKi DT - - - "Time step" s -typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - -typedef ^ ^ IntKi spDOF {6} - - "States per DOF" - -typedef ^ ^ ReKi A {:}{:} - - "A matrix" - -typedef ^ ^ ReKi B {:} - - "B matrix" - -typedef ^ ^ ReKi C {:}{:} - - "C matrix" - -typedef ^ ^ INTEGER N - - - "Number of states" - -typedef ^ ^ DbKi Tc - - - "Time shift" s -typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m -typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s +typedef ^ ParameterType DbKi DT - - - "Time step" s +typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - +typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - +typedef ^ ^ IntKi spDOF {6} - - "States per DOF" - +typedef ^ ^ ReKi A {:}{:} - - "A matrix" - +typedef ^ ^ ReKi B {:} - - "B matrix" - +typedef ^ ^ ReKi C {:}{:} - - "C matrix" - +typedef ^ ^ INTEGER N - - - "Number of states" - +typedef ^ ^ DbKi Tc - - - "Time shift" s +typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m +typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s # ..... Inputs ............................. # Define inputs that are contained on the mesh here: -typedef ^ InputType ReKi DummyInput - - - "Remove this variable if you have input variables" - +typedef ^ InputType ReKi DummyInput - - - "Remove this variable if you have input variables" - # ..... Outputs ............................ -typedef ^ OutputType ReKi y {6} - - "Force/Moments" - -typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - +typedef ^ OutputType ReKi y {6} - - "Force/Moments" - +typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - diff --git a/modules/hydrodyn/src/SS_Radiation.f90 b/modules/hydrodyn/src/SS_Radiation.f90 index 4e25a2abd..0404d61e8 100644 --- a/modules/hydrodyn/src/SS_Radiation.f90 +++ b/modules/hydrodyn/src/SS_Radiation.f90 @@ -45,7 +45,45 @@ MODULE SS_Radiation PUBLIC :: SS_Rad_UpdateDiscState ! Tight coupling routine for updating discrete states -CONTAINS + CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transforms the State Space input file data from a local (heading-angle, based) coordinate system to the global system. +!> NOTE: This routine ONLY works if all the DOFs are enabled!!!!!!!!!! +subroutine TransformStateSpaceMatrices( NBody, RotZ, B, C ) +!.................................................................................................................................. + integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) + real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) + real(SiKi), intent( inout ) :: B(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(SiKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + + integer(IntKi) :: i,j,indx + real(R8Ki) :: R(3,3) + real(R8Ki) :: Rt(3,3) + + !do j = 1, NBody + ! Rj(1,:) = (/ cos(RotZ(j)), sin(RotZ(j)), 0.0_R8Ki/) + ! Rj(2,:) = (/-sin(RotZ(j)), cos(RotZ(j)), 0.0_R8Ki/) + ! Rj(3,:) = (/ 0.0_R8Ki , 0.0_R8Ki , 1.0_R8Ki/) + do i = 1, NBody + if ( .not. EqualRealNos(RotZ(i), 0.0_R8Ki) ) then + R(1,:) = (/ cos(RotZ(i)), sin(RotZ(i)), 0.0_R8Ki/) + R(2,:) = (/-sin(RotZ(i)), cos(RotZ(i)), 0.0_R8Ki/) + R(3,:) = (/ 0.0_R8Ki , 0.0_R8Ki , 1.0_R8Ki/) + Rt = transpose(R) + do j = 1,2 ! Need to do this twice, since a single R (3x3) matrix is used to transform all 6 DOFs associated with the ith Body data + indx = (i-1)*6 + (j-1)*3 + 1 + ! Create sub matrix which is all rows of B but only necessary columns for transformation work, NOTE: B is numStates X (6*NBody) + B(:,indx:indx+2) = matmul( B(:,indx:indx+2), R ) + ! Create sub matrix which is all columns of C but only necessary rows for transformation work, NOTE: c is (6*NBody) X numStates + C(indx:indx+2,:) = matmul( Rt, C(indx:indx+2,:) ) + end do + end if + end do + + ! end do +end subroutine TransformWAMITMatrices + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -80,14 +118,13 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini REAL(ReKi), ALLOCATABLE :: Rad_C (:,:) ! C matrix of the radiation state-space system on the input file ss INTEGER :: I ! Generic index -! INTEGER :: J ! Generic index - INTEGER :: xx (1,6) ! Active DOF's on the input file .ss - INTEGER :: DOFs ! Number of DOFS - INTEGER :: N ! Number of states + INTEGER, allocatable :: xx (:) ! Active DOF's on the input file .ss + INTEGER :: numDOFs ! Number of DOFS + INTEGER :: numStates ! Number of states + int(IntKi) :: N ! Counter INTEGER :: Nlines ! Number of lines in the input file, used to determine N INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. INTEGER :: Sttus ! Error in reading .ss file - !CHARACTER :: Line ! Temp line of file integer :: ErrStat2 character(1024) :: ErrMsg2 @@ -98,7 +135,9 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini UnSS = -1 N = 0 - + numStates = 0 + p%NBody = InitInp%NBody ! Number of WAMIT bodies: =1 if WAMIT is using NBodyMod > 1, >=1 if NBodyMod=1 + ! Open the .ss input file! CALL GetNewUnit( UnSS ) CALL OpenFInpFile ( UnSS, TRIM(InitInp%InputFile)//'.ss', ErrStat2, ErrMsg2 ) ! Open file. @@ -112,12 +151,14 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini Nlines = 1 CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Header',ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', xx(1,:), 6, 'xx', 'xx vector containing the enabled dofs',ErrStat2, ErrMsg2) ! Reads in the second line, containing the active dofs vector + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + call AllocAry( xx, 6*p%NBody, 'xx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', xx(:), 6*p%NBody, 'xx', 'xx vector containing the enabled dofs',ErrStat2, ErrMsg2) ! Reads in the second line, containing the active dofs vector CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ss', N, 'N', 'Number of Dofs',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ss', numStates, 'numStates', 'Number of States',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', p%spdof, 6, 'spdof', 'spdof vector containing the number of states per dofs',ErrStat2, ErrMsg2) ! Reads in the forth line, containing the state per dofs vector + call AllocAry( p%spdof, 6*p%NBody, 'p%spdof', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', p%spdof, 6*p%NBody, 'spdof', 'spdof vector containing the number of states per dofs',ErrStat2, ErrMsg2) ! Reads in the forth line, containing the state per dofs vector CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() @@ -133,22 +174,22 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini END IF END DO - ! The input file contains the matrices A [NxN], B [Nx6] and C [6xN], so - !p%N = ( Nlines - 6 ) / 2 ! this is the number of states + ! The input file contains the matrices A [NxN], B [N x 6*NBody] and C [6*NBody x N], so + !p%numStates = ( Nlines - 6*p%NBody ) / 2 ! this is the number of states !Verifications on the input file - IF ( ( Nlines - 6 ) / 2 /= N) THEN + IF ( ( Nlines - 6*p%NBody ) / 2 /= numStates) THEN CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Rad_Init') END IF - IF ( N /= SUM(p%spdof)) THEN + IF ( numStates /= SUM(p%spdof)) THEN CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Rad_Init') END IF !Verify if the DOFs active in the input file correspond to the ones active by FAST in this run - DO I=1,6 !Loop through all 6 DOFs - IF ( InitInp%DOFs (1,I) == 1) THEN ! True when the current DOF is active in FAST - IF ( xx (1,I) /= 1) THEN ! True if a DOF enabled by FAST is not available in the INPUT File + DO I=1,6*p%NBody !Loop through all 6 DOFs + IF ( InitInp%enabledDOFs (I) == 1) THEN ! True when the current DOF is active in FAST + IF ( xx (I) /= 1) THEN ! True if a DOF enabled by FAST is not available in the INPUT File CALL SetErrStat(ErrID_Severe,'Error in the input file .ss: The enabled DOFs in the current FAST Simulation don`t match the ones on the input file .ss!',ErrStat,ErrMsg,'SS_Rad_Init') END IF END IF @@ -163,9 +204,9 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Now we can allocate the temporary matrices A, B and C - CALL AllocAry( Rad_A, N, N, 'Rad_A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( Rad_B, N, DOFs, 'Rad_B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( Rad_C, DOFs, N, 'Rad_C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_A, numStates, numStates, 'Rad_A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_B, numStates, DOFs, 'Rad_B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_C, DOFs, numStates, 'Rad_C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() @@ -178,41 +219,45 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Skip the first 4 lines: (NOTE: no error handling here because we would have caught it the first time through) CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Header', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'Enabled dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) - CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'N', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) - CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'N per dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'numStates', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) + CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ss', 'numStates per dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) - DO I = 1,N !Read A MatriX - CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', Rad_A(I,:), N, 'Rad_A', 'A_Matrix',ErrStat2, ErrMsg2) + DO I = 1,numStates !Read A MatriX + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ss', Rad_A(I,:), numStates, 'Rad_A', 'A_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') END DO - DO I = 1,N !Read B Matrix - CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_B(I,:), 6, 'Rad_B', 'B_Matrix',ErrStat2, ErrMsg2) + DO I = 1,numStates !Read B Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_B(I,:), 6*p%NBody, 'Rad_B', 'B_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') END DO - DO I = 1,6 !Read C Matrix - CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_C(I,:), N, 'Rad_C', 'C_Matrix',ErrStat2, ErrMsg2) + DO I = 1,6*p%NBody !Read C Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ss', Rad_C(I,:), numStates, 'Rad_C', 'C_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') END DO CLOSE ( UnSS ) !Close .ss input file UnSS = -1 ! Indicate the file is closed + ! Transform the SS matrices using the heading angles + ! NOTE: This transformation routine ONLY works if all the DOFs are enabled so we will do it on Rad_B and Rad_C which have all DOFs !!!!!!!!!! + call TransformStateSpaceMatrices( p%NBody, InitInp%PtfmRefztRot, Rad_B, Rad_C ) + !Now we are ready to reduce the matrices to the correspondent active dofs in FAST - p%N=0 - DO I=1,6 !For each state - IF ( InitInp%DOFs (1,I) == 1) THEN ! True when the current DOF is active in FAST - p%N = p%N + p%spdof(I) !Add the correspondent number of states to the vector + p%numStates=0 + DO I=1,6*p%NBody !For each state + IF ( InitInp%enabledDOFs (I) == 1) THEN ! True when the current DOF is active in FAST + p%numStates = p%numStates + p%spdof(I) !Add the correspondent number of states to the vector END IF END DO - CALL WrScr1 ( 'Using SS_Radiation Module, with '//TRIM( Num2LStr(p%N ))//' of '//TRIM( Num2LStr(N ))// ' radiation states' ) + CALL WrScr1 ( 'Using SS_Radiation Module, with '//TRIM( Num2LStr(p%numStates ))//' of '//TRIM( Num2LStr(numStates ))// ' radiation states' ) !Now we can allocate the final size of the SS matrices - CALL AllocAry( p%A, p%N, p%N, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( p%B, p%N, 6, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( p%c, 6, p%N, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( p%A, p%numStates, p%numStates, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( p%B, p%numStates, 6*p%NBody, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( p%C, 6*p%NBody, p%numStates, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') ! if these arrays weren't allocated, return before a seg fault occurs: IF (ErrStat >= AbortErrLev) THEN @@ -223,12 +268,12 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini !Finaly we write the ss matrices, based on the ones on the input file and on the active dofs - IF ( p%N == N ) THEN !The matrices are the same + IF ( p%numStates == numStates ) THEN !The matrices are the same p%A = Rad_A p%B = Rad_B p%C = Rad_C - + ELSE !We need to cut some of the lines and columns p%A = 0 @@ -238,8 +283,8 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini N=1 !Use as number of active states introduced - DO I=1,6 !For each dof... - IF ( InitInp%DOFs (1,I) == 1 .AND. sum(p%spdof(1:I))= AbortErrLev) THEN CALL CleanUp() RETURN END IF - x%x = 0 + x%x = 0 - xd%DummyDiscState = 0 !TD: SS doesn't have disc states - z%DummyConstrState = 0 !TD: SS doesn't have constr states + xd%DummyDiscState = 0 !TD: SS doesn't have disc states + z%DummyConstrState = 0 !TD: SS doesn't have constr states - ! Define other States: - DO I=1,SIZE(OtherState%xdot) - CALL SS_Rad_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - END DO - OtherState%n = -1 - - ! misc vars: - m%DummyMiscVar = 0 + ! Define other States: + DO I=1,SIZE(OtherState%xdot) + CALL SS_Rad_CopyContState( x, OtherState%xdot(i), MESH_NEWCOPY, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + END DO + OtherState%n = -1 + +! misc vars: + m%DummyMiscVar = 0 - !Inputs - u%dq = 0 !6 DoF's velocities - - ! Define system output initializations (set up mesh) here: - - y%y = 0 - y%WriteOutput = 0 + !Inputs + call AllocAry( u%dq, 6*p%NBody, 'u%dq', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + u%dq = 0 !All DoF's velocities + + ! Define system output initializations (set up mesh) here: + call AllocAry( y%y, 6*p%NBody+1, 'y%y', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + call AllocAry( y%WriteOutput, 6*p%NBody+1, 'y%WriteOutput', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + y%y = 0 + y%WriteOutput = 0 - ! Define initialization-routine output here: - - InitOut%WriteOutputHdr = (/ 'Time', 'F1 ' , 'F2 ' , 'F3 ' , 'F4 ' , 'F5 ' , 'F6 ' /) - InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + ! Define initialization-routine output here: + ! This output channels are only used by the stand-alone driver program and not by the OpenFAST coupled version. + ! For OpenFAST, these outputs are attached (via HydroDyn) to the Radiation Force/Moment channels within HydroDyn + ! Define system output initializations (set up mesh) here: + call AllocAry( InitOut%WriteOutputHdr, 6*p%NBody+1, 'InitOut%WriteOutputHdr', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + call AllocAry( InitOut%WriteOutputUnt, 6*p%NBody+1, 'InitOut%WriteOutputUnt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') +!TODO: Create actual NBody ouput headers +! InitOut%WriteOutputHdr = (/ 'Time', 'F1 ' , 'F2 ' , 'F3 ' , 'F4 ' , 'F5 ' , 'F6 ' /) +! InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) - ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which - ! this module must be called here: + ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which + ! this module must be called here: - !p%DT=Interval - + !p%DT=Interval + CALL CleanUp() ! deallocate local arrays CONTAINS @@ -443,7 +495,7 @@ SUBROUTINE SS_Rad_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, E ! Compute outputs here: y%WriteOutput(1) = REAL(Time,ReKi) - y%WriteOutput(2:7) = y%y + y%WriteOutput(2:6*p%NBody+1) = y%y END SUBROUTINE SS_Rad_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- @@ -468,8 +520,8 @@ SUBROUTINE SS_Rad_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat = ErrID_None ErrMsg = "" - - CALL AllocAry( dxdt%x, p%N, 'SS_Rad_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) + + CALL AllocAry( dxdt%x, p%numStates, 'SS_Rad_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) IF ( ErrStat >= AbortErrLev) RETURN ! Compute the first time derivatives of the continuous states here: diff --git a/modules/hydrodyn/src/SS_Radiation.txt b/modules/hydrodyn/src/SS_Radiation.txt index 5b8ebe35e..2b73981dd 100644 --- a/modules/hydrodyn/src/SS_Radiation.txt +++ b/modules/hydrodyn/src/SS_Radiation.txt @@ -11,23 +11,24 @@ # column 10: Units ################################################################################################################################### -typedef SS_Radiation/SS_Rad InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - -typedef ^ ^ ReKi DOFs {1}{6} - - "Vector with enable platf. DOFs" "m/s or rad/s" +typedef SS_Radiation/SS_Rad InitInputType CHARACTER(1024) InputFile - - - "Name of the input file" - +typedef ^ ^ ReKi enabledDOFs {:} - - "Vector with enable platf. DOFs" (m/s or rad/s) +typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - +typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {7} - - "Header of the output" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {7} - - "Units of the output" - +typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {:} - - "Units of the output" - -typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - +typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - - -typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - # Define constraint states here: -typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "" - # Define any data that are other states, including integer or logical states here: -typedef ^ OtherStateType IntKi n - - - "Current Time step" - -typedef ^ ^ SS_Rad_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - +typedef ^ OtherStateType IntKi n - - - "Current Time step" - +typedef ^ ^ SS_Rad_ContinuousStateType xdot {4} - - "Old Values of dxdt to used by the solver (multistep method)" - # ..... Misc/Optimization variables................................................................................................. @@ -40,21 +41,22 @@ typedef ^ MiscVarType SiKi DummyMiscVar - - - "Rem # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType DbKi DT - - - "Time step" seconds -typedef ^ ^ ReKi A {:}{:} - - "A matrix" - -typedef ^ ^ ReKi B {:}{:} - - "B matrix" - -typedef ^ ^ ReKi C {:}{:} - - "C matrix" - -typedef ^ ^ INTEGER N - - - "Number of states" - -typedef ^ ^ INTEGER spdof {6} - - "States per dof" - +typedef ^ ParameterType DbKi DT - - - "Time step" (s) +typedef ^ ^ ReKi A {:}{:} - - "A matrix" - +typedef ^ ^ ReKi B {:}{:} - - "B matrix" - +typedef ^ ^ ReKi C {:}{:} - - "C matrix" - +typedef ^ ^ INTEGER numStates - - - "Number of states" - +typedef ^ ^ INTEGER spdof {:} - - "States per dof" - +typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - # ..... Inputs ............................. # Define inputs that are contained on the mesh here: -typedef ^ InputType ReKi dq {6} - - "Body velocities" - +typedef ^ InputType ReKi dq {:} - - "Body velocities" - # ..... Outputs ............................ -typedef ^ OutputType ReKi y {6} - - "Force" - -typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - +typedef ^ OutputType ReKi y {:} - - "Force" - +typedef ^ ^ ReKi WriteOutput {:} - - "output Data" (kN) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 26b760893..40df68749 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -1151,6 +1151,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init SS_Exctn_InitInp%InputFile = InitInp%WAMITFile SS_Exctn_InitInp%WaveDir = InitInp%WaveDir SS_Exctn_InitInp%NStepWave = p%NStepWave + SS_Exctn_InitInp%NBody = InitInp%NBody ! No other modules need this WaveElev0 array so we will simply move the allocation over to the SS_Exctn module IF (ALLOCATED(InitInp%WaveElev0)) CALL MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) @@ -1223,8 +1224,21 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ELSE IF ( InitInp%RdtnMod == 2 ) THEN SS_Rdtn_InitInp%InputFile = InitInp%WAMITFile - SS_Rdtn_InitInp%DOFs = 1 + + call AllocAry(SS_Rdtn_InitInp%enabledDOFs, 6*p%NBody, 'SS_Rdtn_InitInp%enabledDOFs', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + SS_Rdtn_InitInp%enabledDOFs = 1 ! Set to 1 (True) for all DOFs, meaning each DOF is to be used in the analysis. Interval_Sub = InitInp%Conv_Rdtn%RdtnDT + SS_Rdtn_InitInp%NBody = InitInp%NBody + call AllocAry(SS_Rdtn_InitInp%PtfmRefztRot, p%NBody, 'SS_Rdtn_InitInp%PtfmRefztRot', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + SS_Rdtn_InitInp%PtfmRefztRot = InitInp%PtfmRefztRot CALL SS_Rad_Init(SS_Rdtn_InitInp, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, & m%SS_Rdtn_y, m%SS_Rdtn, Interval_Sub, SS_Rdtn_InitOut, ErrStat2, ErrMsg2) @@ -1751,7 +1765,8 @@ SUBROUTINE WAMIT_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, m%SS_Rdtn_u%dq(indxStart:indxStart+2) = u%Mesh%TranslationVel(:,iBody) m%SS_Rdtn_u%dq(indxStart+3:indxStart+5) = u%Mesh%RotationVel(:,iBody) end do - CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) + + CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) ! NOTE: The input below (0.0) will only work as part of a linearization Get_OP call! If this routine (WAMIT_CalcContStateDeriv) is called in another context, then the following ! input needs to be implemented generically. From 02f98e3150305ace65d15bd9bae606014c656c8b Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Fri, 17 Jan 2020 14:24:44 -0700 Subject: [PATCH 147/377] Major changes for new Morison approach with nonlinear buoyancy and all loads lumped. Most of restructuring done, but not complete. Not ready to compile yet. --- modules/hydrodyn/src/Morison.f90 | 3625 ++++++++++++------------------ modules/hydrodyn/src/Morison.txt | 130 +- 2 files changed, 1453 insertions(+), 2302 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 88e205672..32b329b4a 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -737,38 +737,6 @@ SUBROUTINE LumpBuoyancy( sgn, densWater, R, tMG, Z, C, g, F_B ) END SUBROUTINE LumpBuoyancy - -SUBROUTINE LumpFloodedBuoyancy( sgn, densFill, R, tM, FillFS, Z, C, g, F_BF ) - - REAL(ReKi), INTENT ( IN ) :: sgn - REAL(ReKi), INTENT ( IN ) :: densFill - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tM - REAL(ReKi), INTENT ( IN ) :: FillFS - REAL(ReKi), INTENT ( IN ) :: Z - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_BF(6) - - - REAL(ReKi) :: f, f1, f2 !, f3 - - f = -densFill*g*sgn - - f1 = -(Z - FillFS)*Pi* (R-tM)*(R-tM) - f2 = 0.25*Pi*(R-tM)*(R-tM)*(R-tM)*(R-tM) - - - F_BF(1) = C(1,3)*f1*f - F_BF(2) = C(2,3)*f1*f - F_BF(3) = C(3,3)*f1*f - F_BF(4) = (-C(1,1)*C(3,2) + C(1,2)*C(3,1))*f*f2 ! TODO: We flipped the signs of the moments because 1 member tapered integrated moments were not zero. GJH 10/1/13 Jason is verifying. - F_BF(5) = (-C(2,1)*C(3,2) + C(2,2)*C(3,1))*f*f2 - F_BF(6) = (-C(3,1)*C(3,2) + C(3,2)*C(3,1))*f*f2 - - -END SUBROUTINE LumpFloodedBuoyancy - LOGICAL FUNCTION IsThisSplitValueUsed(nSplits, splits, checkVal) INTEGER, INTENT ( IN ) :: nSplits @@ -1581,32 +1549,25 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen END SUBROUTINE WriteSummaryFile + !==================================================================================================== -SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, numElements, node1, node2, originalElement, newNode, newElement, ErrStat, ErrMsg ) +SUBROUTINE SplitElementOnZBoundary( axis, boundary, numNodes, node1, node2, newNode, ErrStat, ErrMsg ) !@mhall: This splits an element at a given global x, y, or z location? - INTEGER, INTENT ( IN ) :: axis !@mhall: which axis to work with in calculating positions along element (global x,y, or z)? - REAL(ReKi), INTENT ( IN ) :: boundary !@mhall: [axis] coordinate of boundary? - INTEGER, INTENT ( IN ) :: iCurrentElement + INTEGER, INTENT ( IN ) :: axis ! which axis to work with in calculating positions along element (global x,y, or z)? + REAL(ReKi), INTENT ( IN ) :: boundary ! [axis] coordinate of boundary? INTEGER, INTENT ( INOUT ) :: numNodes - TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 !@mhall: element end nodes? - INTEGER, INTENT ( INOUT ) :: numElements - TYPE(Morison_MemberType), INTENT ( INOUT ) :: originalElement + TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 TYPE(Morison_NodeType), INTENT ( OUT ) :: newNode - TYPE(Morison_MemberType), INTENT ( OUT ) :: newElement INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None INTEGER :: I, J - REAL(ReKi) :: s - INTEGER :: newNodeIndx, newElementIndx + REAL(ReKi) :: s ! interpolation factor ErrStat = ErrID_None ErrMsg = "" - ! Create new node and element indices - newNodeIndx = numNodes + 1 - newElementIndx = numElements + 1 ! find normalized distance from 1nd node to the boundary CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) @@ -1621,326 +1582,57 @@ SUBROUTINE SplitElementOnZBoundary( axis, boundary, iCurrentElement, numNodes, n END DO newNode%R_LToG = node1%R_LToG - ! Create the new node information. - ! Note that the caller will determine if this is an interior node (subdivide) or an endnode (split due to MG, MSL, seabed, filled free surface) - newNode%JointOvrlp = 0 - newNode%NConnections = 2 - newNode%ConnectionList(1) = iCurrentElement - newNode%ConnectionList(2) = newElementIndx - - - - ! Update node2 connectivity - DO I = 1,10 ! 10 is the maximum number of connecting elements for a node, this should probably be a parameter !! TODO - IF ( node2%ConnectionList(I) == iCurrentElement ) THEN - node2%ConnectionList(I) = newElementIndx - EXIT - END IF - END DO - - - ! Create the new element properties by first copying all the properties from the existing element - newElement = originalElement - ! Linearly interpolate the coef values based on depth - originalElement%R2 = originalElement%R1 * (1-s) + originalElement%R2*s - newElement%R1 = originalElement%R2 - originalElement%t2 = originalElement%t1 * (1-s) + originalElement%t2*s - originalElement%InpMbrDist2 = originalElement%InpMbrDist1 * (1-s) + originalElement%InpMbrDist2*s - newElement%t1 = originalElement%t2 - newElement%InpMbrDist1 = originalElement%InpMbrDist2 - - ! The end point of the new element is set to the original end point of the existing element, then - ! the starting point of the new element and the ending point of the existing element are set to the - ! newly created node - newElement%Node2Indx = originalElement%Node2Indx - originalElement%Node2Indx = newNodeIndx - newElement%Node1Indx = newNodeIndx END SUBROUTINE SplitElementOnZBoundary -!==================================================================================================== -!SUBROUTINE SplitElementsForMG(MGTop, MGBottom, numNodes, nodes, numElements, elements, ErrStat, ErrMsg) -! -! REAL(ReKi), INTENT ( IN ) :: MGTop -! REAL(ReKi), INTENT ( IN ) :: MGBottom -! INTEGER, INTENT ( INOUT ) :: numNodes -! TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) -! INTEGER, INTENT ( INOUT ) :: numElements -! TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) -! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs -! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! -! INTEGER :: I, J, K -! INTEGER :: node1Indx, node2Indx -! TYPE(Morison_NodeType) :: node1, node2, newNode, newNode2 -! TYPE(Morison_MemberType) :: element, newElement, newElement2 -! REAL(ReKi) :: zBoundary -! INTEGER :: origNumElements -! -! origNumElements = numElements -! -! DO I=1,origNumElements -! -! IF ( elements(I)%MGSplitState > 0 ) THEN -! -! node1Indx = elements(I)%Node1Indx -! node1 = nodes(node1Indx) -! node2Indx = elements(I)%Node2Indx -! node2 = nodes(node2Indx) -! element = elements(I) -! -! ! Intersects top boundary -! IF ( elements(I)%MGSplitState == 1 ) THEN -! zBoundary = MGTop -! ELSE ! Intersects the bottom boundary -! zBoundary = MGBottom -! END IF -! -! -! CALL SplitElementOnZBoundary( zBoundary, I, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) -! newNode%NodeType = 1 ! end node -! ! Update the number of nodes and elements by one each -! numNodes = numNodes + 1 -! newNode%JointIndx = numNodes -! numElements = numElements + 1 -! -! ! Copy the altered nodes and elements into the master arrays -! nodes(node1Indx) = node1 -! nodes(node2Indx) = node2 -! nodes(numNodes) = newNode -! elements(I) = element -! elements(numElements) = newElement -! -! ! If the original element spanned both marine growth boundaries, then we need to make an additional split -! IF ( elements(I)%MGSplitState == 3 ) THEN -! -! CALL SplitElementOnZBoundary( MGTop, numElements, numNodes, numElements, newNode, node2, newElement, newNode2, newElement2, ErrStat, ErrMsg ) -! newNode2%NodeType = 1 ! end node -! newNode2%JointIndx = numNodes + 1 -! ! Copy the altered nodes and elements into the master arrays -! nodes(numNodes) = newNode -! nodes(node2Indx) = node2 -! nodes(numNodes+1) = newNode2 -! elements(numElements) = newElement -! elements(numElements+1) = newElement2 -! -! ! Update the number of nodes and elements by one each -! numNodes = numNodes + 1 -! -! numElements = numElements + 1 -! -! END IF -! END IF -! END DO -!END SUBROUTINE SplitElementsForMG - -SUBROUTINE SplitElements(numNodes, nodes, numElements, elements, ErrStat, ErrMsg) - ! This splits all of the Morison elements according to already defined split locations, - ! adding resuling new nodes and elements to the respective master arrays. - - INTEGER, INTENT ( INOUT ) :: numNodes - TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) - INTEGER, INTENT ( INOUT ) :: numElements - TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I, J, iCurrent, nSplits !, K - REAL(ReKi) :: splits(5) - INTEGER :: node1Indx, node2Indx - TYPE(Morison_NodeType) :: node1, node2, newNode !, newNode2 - TYPE(Morison_MemberType) :: element, newElement !, newElement2 - REAL(ReKi) :: zBoundary - INTEGER :: origNumElements - - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - origNumElements = numElements - - DO I=1,origNumElements - - IF ( elements(I)%NumSplits > 0 ) THEN - - - ! The splits are presorted from smallest Z to largest Z - nSplits = elements(I)%NumSplits - splits = elements(I)%Splits - iCurrent = I - - DO J=1,nSplits - - node1Indx = elements(iCurrent)%Node1Indx - node1 = nodes(node1Indx) - node2Indx = elements(iCurrent)%Node2Indx - node2 = nodes(node2Indx) - element = elements(iCurrent) - - CALL SplitElementOnZBoundary( 3, splits(J), iCurrent, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) - - ! Was this split due to the location of an elements free surface location crossing through the element? - IF ( element%MmbrFilledIDIndx /= -1 ) THEN - IF ( EqualRealNos(element%FillFSLoc, splits(J)) ) THEN - newElement%MmbrFilledIDIndx = -1 - END IF - END IF - - newNode%NodeType = 1 ! end node - ! Update the number of nodes and elements by one each - numNodes = numNodes + 1 - newNode%JointIndx = numNodes - numElements = numElements + 1 - - ! Copy the altered nodes and elements into the master arrays - !nodes(node1Indx) = node1 - nodes(node2Indx) = node2 - nodes(numNodes) = newNode - elements(iCurrent) = element - elements(numElements) = newElement - - - - ! now make element = newElement by setting iCurrent to numElements - iCurrent = numElements - - - END DO - - END IF - END DO -END SUBROUTINE SplitElements -!==================================================================================================== -!SUBROUTINE SplitElementsForWtr(MSL2SWL, Zseabed, numNodes, nodes, numElements, elements, ErrStat, ErrMsg) -! -! REAL(ReKi), INTENT ( IN ) :: MSL2SWL -! REAL(ReKi), INTENT ( IN ) :: Zseabed -! INTEGER, INTENT ( INOUT ) :: numNodes -! TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) -! INTEGER, INTENT ( INOUT ) :: numElements -! TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) -! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs -! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! -! INTEGER :: I, J, K -! INTEGER :: node1Indx, node2Indx -! TYPE(Morison_NodeType) :: node1, node2, newNode, newNode2 -! TYPE(Morison_MemberType) :: element, newElement, newElement2 -! REAL(ReKi) :: zBoundary -! INTEGER :: origNumElements -! -! origNumElements = numElements -! -! DO I=1,origNumElements -! -! IF ( elements(I)%WtrSplitState > 0 ) THEN -! -! node1Indx = elements(I)%Node1Indx -! node1 = nodes(node1Indx) -! node2Indx = elements(I)%Node2Indx -! node2 = nodes(node2Indx) -! element = elements(I) -! -! ! Intersects top boundary -! IF ( elements(I)%WtrSplitState == 1 ) THEN -! zBoundary = MSL2SWL -! ELSE ! Intersects the bottom boundary -! zBoundary = Zseabed -! END IF -! -! -! CALL SplitElementOnZBoundary( zBoundary, I, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) -! newNode%NodeType = 1 ! end node -! ! Update the number of nodes and elements by one each -! numNodes = numNodes + 1 -! newNode%JointIndx = numNodes -! numElements = numElements + 1 -! -! ! Copy the altered nodes and elements into the master arrays -! nodes(node1Indx) = node1 -! nodes(node2Indx) = node2 -! nodes(numNodes) = newNode -! elements(I) = element -! elements(numElements) = newElement -! -! ! If the original element spanned both marine growth boundaries, then we need to make an additional split -! IF ( elements(I)%WtrSplitState == 3 ) THEN -! -! CALL SplitElementOnZBoundary( MSL2SWL, numElements, numNodes, numElements, newNode, node2, newElement, newNode2, newElement2, ErrStat, ErrMsg ) -! newNode2%NodeType = 1 ! end node -! newNode2%JointIndx = numNodes + 1 -! ! Copy the altered nodes and elements into the master arrays -! nodes(numNodes) = newNode -! nodes(node2Indx) = node2 -! nodes(numNodes+1) = newNode2 -! elements(numElements) = newElement -! elements(numElements+1) = newElement2 -! -! ! Update the number of nodes and elements by one each -! numNodes = numNodes + 1 -! -! numElements = numElements + 1 -! -! END IF -! END IF -! END DO -!END SUBROUTINE SplitElementsForWtr -!==================================================================================================== -SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, ErrMsg ) - ! This subdivides all of the (already-split) Morison elements according to each element's maximum desired - ! element length (MDivSize), adding resuling new nodes and elements to the respective master arrays. + +SUBROUTINE DiscretizeMember( numNodes, nodes, member, propSet1, propSet2, numMGDepths, MGDepths, ErrStat, ErrMsg ) + ! This subdivides a Morison member according to its maximum desired + ! element length (MDivSize), allocating the member's arrays, and + ! adding resuling new nodes to the master node array. - INTEGER, INTENT ( INOUT ) :: numNodes - TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) - INTEGER, INTENT ( INOUT ) :: numElements - TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) + INTEGER, INTENT ( INOUT ) :: numNodes ! the current number of nodes being used in the model + TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) ! the array of nodes (maximum size for now) + TYPE(Morison_MemberType), INTENT ( INOUT ) :: member ! the morison member to discretize + TYPE(Morison_MemberPropType) INTENT( IN ) :: propSet1 ! property set of node 1 + TYPE(Morison_MemberPropType) INTENT( IN ) :: propSet2 ! property set of node N+1 + INTEGER, INTENT( IN ) :: numMGDepths + TYPE(Morison_MGDepthsType), INTENT( IN ) :: MGDepths(:) INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None TYPE(Morison_NodeType) :: node1, node2, newNode - TYPE(Morison_MemberType) :: element, newElement + !TYPE(Morison_MemberType) :: element, newElement INTEGER :: numDiv REAL(ReKi) :: divSize(3) INTEGER :: I, J, K - REAL(ReKi) :: memLen ! Length of member [m] INTEGER :: origNumElements - INTEGER :: node1Indx, node2Indx, elementIndx, axis + INTEGER :: node1Indx, node2Indx, axis REAL(ReKi) :: start, Loc + REAL(ReKi) :: s ! interpolation factor ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - - origNumElements = numElements - - DO I=1,origNumElements - - CALL Morison_CopyMemberType( elements(I), element, MESH_NEWCOPY, ErrStat, ErrMsg ) ! element = elements(I); bjj: I'm replacing the "equals" here with the copy routine, - ! though at this point there are no allocatable/pointer fields in this type so no harm done. - ! mostly for me to remember that when Inspector complains about uninitialized values, it's - ! because not all *fields* have been initialized. - node1Indx = element%Node1Indx + + ! some copying for convenience + node1Indx = member%Node1Indx CALL Morison_CopyNodeType( nodes(node1Indx), node1, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node1 = nodes(node1Indx); bjj: note that not all fields have been initialized, but maybe that's okay. - node2Indx = element%Node2Indx ! We need this index for the last sub-element + node2Indx = member%Node2Indx ! We need this index for the last sub-element CALL Morison_CopyNodeType( nodes(node2Indx), node2, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node2 = nodes(node2Indx); bjj: note that not all fields have been initialized, but maybe that's okay. - elementIndx = I - - CALL GetDistance(node1%JointPos, node2%JointPos, memLen) ! Calculate member length. + ! calculate and save member length + CALL GetDistance(node1%JointPos, node2%JointPos, member%Len) ! Calculate member length. - ! If the requested division size is less then the member length, we will subdivide the member - - IF ( element%MDivSize < memLen ) THEN + ! If the requested division size is less then the member length, create nodes along the member + IF ( member%MDivSize < member%Len ) THEN ! Ensure a safe choice of x/y/z axis to use for splitting. IF ( .NOT. ( EqualRealNos( node2%JointPos(3) , node1%JointPos(3) ) ) ) THEN @@ -1954,91 +1646,134 @@ SUBROUTINE SubdivideMembers( numNodes, nodes, numElements, elements, ErrStat, Er END IF start = node1%JointPos(axis) - numDiv = CEILING( memLen / element%MDivSize ) + numDiv = CEILING( memLen / member%MDivSize ) + + ! set number of elements in member and element size + member%NElements = numDiv + member%dl = member%Len/numDiv + + ! allocate member arrays + CALL AllocateMemberVariables(member, ErrStat2, ErrMsg2) + + ! now that the arrays are allocated, fill in values for the ends of the member + member%R( 1) = propSet1%PropD / 2.0 + member%RMG(1) = propSet1%PropD / 2.0 + node1%tMG + member%Rin(1) = propSet1%PropD / 2.0 - propSet1%PropThck + member%R( N+1) = propSet2%PropD / 2.0 + member%RMG(N+1) = propSet2%PropD / 2.0 + node2%tMG + member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck + + member%NodeIndx( 1) = node1Indx + member%NodeIndx(N+1) = node2Indx + + ! get the division size along each axis DO K=1,3 divSize(K) = (node2%JointPos(K) - node1%JointPos(K)) / numDiv END DO + + ! loop through the new node locations along the member and add a node at each DO J=1,numDiv - 1 loc = start + divSize(axis)*J - CALL SplitElementOnZBoundary( axis, loc, elementIndx, numNodes, numElements, node1, node2, element, newNode, newElement, ErrStat, ErrMsg ) + + ! below was previously CALL SplitElementOnZBoundary( axis, loc, numNodes, node1, node2, newNode, ErrStat, ErrMsg ) + + ! find normalized distance from 1nd node to the boundary + CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) + newNode = node1 ! copy all base node properties + + newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] + + ! Set properties of new node based on interpolation of original end node coordinates + + !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates + DO I=axis,axis+1 + K = MOD(I,3) + 1 + newNode%JointPos(K) = node1%JointPos(K)*(1-s) + node2%JointPos(K)*s + END DO + + newNode%R_LToG = node1%R_LToG + newNode%NodeType = 2 ! interior node newNode%JointIndx = -1 - ! Copy updated node and element information to the nodes and elements arrays - nodes(node1Indx) = node1 ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - nodes(node2Indx) = node2 ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - numNodes = numNodes + 1 - numElements = numElements + 1 - nodes(numNodes) = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - elements(elementIndx) = element ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - elements(numElements) = newElement ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - - node1 = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - element = newElement ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - node1Indx = numNodes - elementIndx = numElements + ! Set the marine growth thickness and density information for the new node + CALL SetNodeMG( numMGDepths, MGDepths, newNode ) + ! Copy new node into the nodes array (this now just appends the new node to the list, the variables node1 and node2 don't need to change) + numNodes = numNodes + 1 + nodes(numNodes) = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers + ! Now fill in properties of the member at the new node location + I = J+1 ! the node index along the member, from 1 to N+1 + member%R( I) = member%R( 1)*(1-s) + member%R( N+1)*s + member%Rin(I) = member%Rin(1)*(1-s) + member%Rin(N+1)*s + member%RMG(I) = member%R(I) + newNode%tMG + ! record the node index in the member's node index list + member%NodeIndx(I) = node1Indx + J - ! Create a new node - !newNode = node2 - ! - !DO K=1,3 - ! newNode%JointPos = node1%JointPos(K) + divSize(K)*J - !END DO - ! - !numNodes = numNodes + 1 - !element%Node2Indx = numNodes - !nodes(numNodes) = newNode - ! - ! ! Create a new element - !newElement = element - !newElement%Node1Indx = numNodes - !element = newElement - !numElements = numElements + 1 END DO - !element%Node2Indx = node2Indx + + ELSE ! if the member will only be one element long, record that and allocate its arrays + + ! set number of elements in member and element size + member%NElements = 1 + member%dl = member%Len - END IF - - END DO + ! allocate member arrays + CALL AllocateMemberVariables(member, ErrStat2, ErrMsg2) + ! now that the arrays are allocated, fill in values for the ends of the member + member%R( 1) = propSet1%PropD / 2.0 + member%RMG(1) = propSet1%PropD / 2.0 + node1%tMG + member%Rin(1) = propSet1%PropD / 2.0 - propSet1%PropThck + member%R( N+1) = propSet2%PropD / 2.0 + member%RMG(N+1) = propSet2%PropD / 2.0 + node2%tMG + member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck -END SUBROUTINE SubdivideMembers - -SUBROUTINE CreateSuperMembers( ) - - + member%NodeIndx( 1) = node1Indx + member%NodeIndx(N+1) = node2Indx - ! Determine if any of the joints flagged for overlap elimination (super member creation) satisfy the necessary requirements - !IF ( InitInp%NJoints > 0 ) THEN - ! - ! DO I = 1,InitInp%NJoints - ! - ! ! Check #1 are there more than 2 members connected to the joint? - ! IF ( InitInp%InpJoints(I)%JointOvrlp == 1 .AND. InitInp%InpJoints(I)%NConnections > 2) THEN - ! ! Check #2 are there two members whose local z-axis are the same? - ! CALL Get180Members(joint, InitInp%Joints, InitInp%Members, member1, member2) - ! - ! !zVect1 - ! !zVect2 - ! !dot(zVect1, zVect2) - ! - ! END IF - ! - ! - ! END DO - ! - ! - !END IF + END IF + +END SUBROUTINE DiscretizeMember + +SUBROUTINE AllocateMemberVariables(member, ErrStat, ErrMsg) + + TYPE(Morison_MemberType), INTENT ( INOUT ) :: member ! the morison member to discretize + INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + INTEGER :: N + + + N = member%NElements + + !@mhall: I'm hoping the arrays for each member can be allocated like this + + ALLOCATE ( member%NodeIndx(N+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the member node index array.' + ErrStat = ErrID_Fatal + RETURN + END IF -END SUBROUTINE CreateSuperMembers + ALLOCATE ( member%R(N+1), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the member node radius array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + !@mhall: etc. + + +END SUBROUTINE AllocateMemberVariables !==================================================================================================== @@ -2108,130 +1843,6 @@ SUBROUTINE SetDepthBasedCoefs( z, NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, END SUBROUTINE SetDepthBasedCoefs -!==================================================================================================== -SUBROUTINE SetSplitNodeProperties( numNodes, nodes, numElements, elements, ErrStat, ErrMsg ) -! This private subroutine generates the properties of nodes after the mesh has been split -! the input data. -!---------------------------------------------------------------------------------------------------- - - INTEGER, INTENT ( IN ) :: numNodes - INTEGER, INTENT ( IN ) :: numElements - TYPE(Morison_MemberType), INTENT ( INOUT ) :: elements(:) - TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - INTEGER :: I - TYPE(Morison_MemberType) :: element - REAL(ReKi) :: dR, dz -! REAL(ReKi) :: DirCos(3,3) - - ErrStat = ErrID_None - ErrMsg = "" - - - DO I=1,numNodes - - IF ( nodes(I)%NodeType /= 3 ) THEN - - ! End point or internal member node - ! Super member nodes already have their properties set - - - !element = elements(nodes(I)%ConnectionList(1)) - - ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array - - ! CALL Morison_DirCosMtrx( nodes(element%Node1Indx)%JointPos, nodes(element%Node2Indx)%JointPos, elements(nodes(I)%ConnectionList(1))%R_LToG ) - - element = elements(nodes(I)%ConnectionList(1)) - - nodes(I)%R_LToG = element%R_LToG - - nodes(I)%InpMbrIndx = element%InpMbrIndx - IF ( .NOT. ( ( nodes(element%Node1Indx)%tMG > 0 ) .AND. ( nodes(element%Node2Indx)%tMG > 0 ) .AND. (.NOT. element%PropPot) ) ) THEN - nodes(element%Node1Indx)%tMG = 0.0 - nodes(element%Node2Indx)%tMG = 0.0 - nodes(element%Node1Indx)%MGdensity = 0.0 - nodes(element%Node2Indx)%MGdensity = 0.0 - END IF - - !@mhall: if this node is Node I of the element in question... ? - IF ( element%Node1Indx == I ) THEN - - IF ( nodes(I)%tMG > 0 ) THEN - nodes(I)%Cd = element%CdMG1 - nodes(I)%Ca = element%CaMG1 - nodes(I)%Cp = element%CpMG1 - nodes(I)%AxCa = element%AxCaMG1 - nodes(I)%AxCp = element%AxCpMG1 - ELSE - nodes(I)%Cd = element%Cd1 - nodes(I)%Ca = element%Ca1 - nodes(I)%Cp = element%Cp1 - nodes(I)%AxCa = element%AxCa1 - nodes(I)%AxCp = element%AxCp1 - END IF - - nodes(I)%R = element%R1 - nodes(I)%t = element%t1 - nodes(I)%InpMbrDist = element%InpMbrDist1 - - !@mhall: otherwise this must be Node 2 of the element in question? - ELSE - - IF ( nodes(I)%tMG > 0 ) THEN - nodes(I)%Cd = element%CdMG2 - nodes(I)%Ca = element%CaMG2 - nodes(I)%Cp = element%CpMG2 - nodes(I)%AxCa = element%AxCaMG2 - nodes(I)%AxCp = element%AxCpMG2 - ELSE - nodes(I)%Cd = element%Cd2 - nodes(I)%Ca = element%Ca2 - nodes(I)%Cp = element%Cp2 - nodes(I)%AxCa = element%AxCa2 - nodes(I)%AxCp = element%AxCp2 - END IF - - nodes(I)%R = element%R2 - nodes(I)%t = element%t2 - nodes(I)%InpMbrDist = element%InpMbrDist2 - END IF - - CALL GetDistance( nodes(element%Node1Indx)%JointPos, nodes(element%Node2Indx)%JointPos, dz ) - dR = ( element%R2 + nodes(element%Node2Indx)%tMG ) - ( element%R1 + nodes(element%Node1Indx)%tMG ) - IF ( EqualRealNos(dR, 0.0_ReKi) ) dR = 0.0 - IF ( EqualRealNos(dz, 0.0_ReKi) ) THEN - nodes(I)%dRdz = 0.0 - ELSE - nodes(I)%dRdz = dR / dz - END IF - - nodes(I)%PropPot = element%PropPot - - IF ( element%MmbrFilledIDIndx /= -1 ) THEN - nodes(I)%FillFlag = .TRUE. - nodes(I)%FillFSLoc = element%FillFSLoc ! This is relative to the MSL. - nodes(I)%FillDensity = element%FillDens - - ELSE - nodes(I)%FillFSLoc = 0.0 ! This is the MSL. - nodes(I)%FillDensity = 0.0 - elements(nodes(I)%ConnectionList(1))%FillDens = 0.0 - elements(nodes(I)%ConnectionList(1))%FillFSLoc = 0.0 - END IF - - - - - END IF - -END DO - -END SUBROUTINE SetSplitNodeProperties - !==================================================================================================== !SUBROUTINE SetMemberCoefs( SimplCd, SimplCdMG, SimplCa, SimplCaMG, CoefMembers, NCoefDpth, CoefDpths, element, node1, node2 ) @@ -2387,12 +1998,11 @@ SUBROUTINE SetAxialCoefs( NJoints, NAxCoefs, AxialCoefs, numNodes, nodes, numEle END SUBROUTINE SetAxialCoefs -SUBROUTINE SetNodeMG( numMGDepths, MGDepths, numNodes, nodes ) - +SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node ) + ! sets the margine growth thickness of a single node (previously all nodes) INTEGER, INTENT( IN ) :: numMGDepths TYPE(Morison_MGDepthsType), INTENT( IN ) :: MGDepths(:) - INTEGER, INTENT( IN ) :: numNodes - TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) + TYPE(Morison_NodeType), INTENT( INOUT ) :: node INTEGER :: I, J REAL(ReKi) :: z @@ -2400,12 +2010,11 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, numNodes, nodes ) REAL(ReKi) :: dd, s LOGICAL :: foundLess = .FALSE. - DO I=1,numNodes !Find the table entry(ies) which match the node's depth value ! The assumption here is that the depth table is stored from largest ! to smallest in depth - z = nodes(I)%JointPos(3) + z = node%JointPos(3) foundLess = .FALSE. indx1 = 0 indx2 = 0 @@ -2422,8 +2031,8 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, numNodes, nodes ) END DO IF ( indx2 == 0 .OR. .NOT. foundLess ) THEN !Not at a marine growth depth - nodes(I)%tMG = 0.0 - nodes(I)%MGdensity = 0.0 + node%tMG = 0.0 + node%MGdensity = 0.0 ELSE ! Linearly interpolate the coef values based on depth !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) @@ -2434,1402 +2043,66 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, numNodes, nodes ) ELSE s = ( MGDepths(indx1)%MGDpth - z ) / dd END IF - nodes(I)%tMG = MGDepths(indx1)%MGThck*(1-s) + MGDepths(indx2)%MGThck*s - nodes(I)%MGdensity = MGDepths(indx1)%MGDens*(1-s) + MGDepths(indx2)%MGDens*s + node%tMG = MGDepths(indx1)%MGThck*(1-s) + MGDepths(indx2)%MGThck*s + node%MGdensity = MGDepths(indx1)%MGDens*(1-s) + MGDepths(indx2)%MGDens*s END IF - END DO - END SUBROUTINE SetNodeMG + -SUBROUTINE SetElementFillProps( numFillGroups, filledGroups, numElements, elements ) +!==================================================================================================== +SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) +! This public subroutine process the input geometry and parameters and eliminates joint overlaps, +! sub-divides members, sets joint-level properties, etc. It is called by HydroDyn before Morison_Init +! so that the node positions are available beforehand for other parts of HydroDyn. +!---------------------------------------------------------------------------------------------------- - INTEGER, INTENT( IN ) :: numFillGroups - TYPE(Morison_FilledGroupType), INTENT( IN ) :: filledGroups(:) - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) - - INTEGER :: I !, J - - DO I=1,numElements - - - IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN - - elements(I)%FillDens = filledGroups(elements(I)%MmbrFilledIDIndx)%FillDens - elements(I)%FillFSLoc = filledGroups(elements(I)%MmbrFilledIDIndx)%FillFSLoc - ELSE - elements(I)%FillDens = 0.0 - elements(I)%FillFSLoc = 0.0 - END IF - - - - END DO - + ! Passed variables -END SUBROUTINE SetElementFillProps - -!SUBROUTINE CreateLumpedMarkers( numNodes, nodes, numElements, elements, numLumpedMarkers, lumpedMarkers, ErrStat, ErrMsg ) -! -! INTEGER, INTENT( IN ) :: numNodes -! INTEGER, INTENT( IN ) :: numElements -! TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) -! TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) -! INTEGER, INTENT( OUT ) :: numLumpedMarkers -! TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: lumpedMarkers(:) -! INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs -! CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! -! INTEGER :: I, J, count -! TYPE(Morison_MemberType) :: element -! -! numLumpedMarkers = 0 -! -! ! Count how many distributed markers we need to create by looping over the nodes -! DO I=1,numNodes -! IF ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) THEN -! ! end of a member that was not a part of super member creation -! numLumpedMarkers = numLumpedMarkers + 1 -! END IF -! END DO -! -! ! Allocate the array for the distributed markers -! ALLOCATE ( lumpedMarkers(numLumpedMarkers), STAT = ErrStat ) -! IF ( ErrStat /= ErrID_None ) THEN -! ErrMsg = ' Error allocating space for the lumped load markers array.' -! ErrStat = ErrID_Fatal -! RETURN -! END IF -! count = 1 -! DO I=1,numNodes -! -! IF ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0) THEN -! -! element = elements(nodes(I)%ConnectionList(1)) -! -! IF ( element%Node1Indx == I ) THEN -! lumpedMarkers(count)%Cd = element%Cd1 -! lumpedMarkers(count)%CdMG = element%CdMG1 -! lumpedMarkers(count)%Ca = element%Ca1 -! lumpedMarkers(count)%CaMG = element%CaMG1 -! lumpedMarkers(count)%R = element%R1 -! lumpedMarkers(count)%t = element%t1 -! ELSE -! lumpedMarkers(count)%Cd = element%Cd2 -! lumpedMarkers(count)%CdMG = element%CdMG2 -! lumpedMarkers(count)%Ca = element%Ca2 -! lumpedMarkers(count)%CaMG = element%CaMG2 -! lumpedMarkers(count)%R = element%R2 -! lumpedMarkers(count)%t = element%t2 -! END IF -! -! lumpedMarkers(count)%PropPot = element%PropPot -! lumpedMarkers(count)%tMG = nodes(I)%tMG -! lumpedMarkers(count)%MGdensity = nodes(I)%MGdensity -! -! -! ! Compute all initialization forces now so we have access to the element information -! -! !IF ( element%PropPot == .FALSE. ) THEN -! ! -! ! ! Member is not modeled with WAMIT -! ! CALL LumpedBuoyancy( ) -! ! CALL LumpedMGLoads( ) -! ! CALL LumpedDynPressure( ) -! ! CALL LumpedAddedMass( ) -! ! CALL LumpedAddedMassMG( ) -! ! CALL LumpedAddedMassFlood( ) ! Do we actually compute this??? TODO -! ! -! !END IF -! ! -! ! ! These are the only two loads we compute at initialization if the member is modeled with WAMIT -! !CALL LumpedDragConst( ) -! !CALL LumpedFloodedBuoyancy( ) -! -! -! count = count + 1 -! -! END IF -! -! END DO -! -!END SUBROUTINE CreateLumpedMarkers - - -SUBROUTINE SplitMeshNodes( numNodes, nodes, numElements, elements, numSplitNodes, splitNodes, ErrStat, ErrMsg ) + TYPE(Morison_InitInputType), INTENT( INOUT ) :: InitInp ! the Morison initialization data + !TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! tge Morison parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - INTEGER, INTENT( IN ) :: numNodes - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) - TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) - INTEGER, INTENT( OUT ) :: numSplitNodes - TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: splitNodes(:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I, J, splitNodeIndx -! TYPE(Morison_MemberType) :: element - TYPE(Morison_NodeType) :: node1, node2, newNode - + + ! Local variables + + INTEGER :: I, J !, j1, j2, tempINT ! generic integer for counting +! TYPE(Morison_JointType) :: joint1, joint2 +! Real(ReKi) :: z1 +! Real(ReKi) :: z2 + Real(ReKi) :: d + INTEGER :: temp + INTEGER :: prop1Indx, prop2Indx, node1Indx, node2Indx + INTEGER :: maxNodes = 0 + INTEGER :: maxElements = 0 + INTEGER :: maxSuperMembers = 0 + ! TYPE(Morison_NodeType) :: node1, node2, tempNode + INTEGER :: numSplitNodes + INTEGER :: Node1Indx, Node2Indx ! indices of joint nodes at member ends + TYPE(Morison_NodeType),ALLOCATABLE :: splitNodes(:) + LOGICAL :: doSwap ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - numSplitNodes = 0 - - ! Count how many distributed markers we need to create by looping over the nodes - DO I=1,numNodes - IF ( nodes(I)%NodeType == 1 ) THEN - ! Nodes at the end of members get one node for each connecting member - numSplitNodes = numSplitNodes + nodes(I)%NConnections - ELSE - ! Internal nodes and super member nodes only get one node - numSplitNodes = numSplitNodes + 1 - END IF - END DO - - ! Allocate the array for the distributed markers - ALLOCATE ( splitNodes(numSplitNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for split nodes array.' - ErrStat = ErrID_Fatal - RETURN - END IF - splitNodes(1:numNodes) = nodes(1:numNodes) - - IF ( numSplitNodes > numNodes ) THEN + IF ( InitInp%NMembers > 0 ) THEN - splitNodeIndx = numNodes + 1 - - DO I=1,numElements - ! Loop over elements in the processed mesh and create additional nodes/markers at the end of elements if that node connects to other elements - node1 = splitnodes(elements(I)%Node1Indx) - node2 = splitnodes(elements(I)%Node2Indx) - IF (node1%NodeType == 1 ) THEN ! end node - IF ( node1%NConnections > 1 ) THEN - !create new node by copying the old one - newNode = node1 - newNode%NConnections = 1 - splitnodes(splitNodeIndx) = newNode - splitnodes(elements(I)%Node1Indx)%NConnections = node1%NConnections - 1 - !set the new node as the first node of this element - elements(I)%Node1Indx = splitNodeIndx - splitNodeIndx = splitNodeIndx + 1 - !NOTE: the node connection list entries are now bogus!!!! - END IF - - END IF - - IF (node2%NodeType == 1 ) THEN ! end node - IF ( node2%NConnections > 1 ) THEN - !create new node by copying the old one - newNode = node2 - newNode%NConnections = 1 - splitnodes(splitNodeIndx) = newNode - splitnodes(elements(I)%Node2Indx)%NConnections = node2%NConnections - 1 - !set the new node as the first node of this element - elements(I)%Node2Indx = splitNodeIndx - splitNodeIndx = splitNodeIndx + 1 - !NOTE: the node connection list entries are now bogus!!!! - END IF - - END IF - - END DO - - ! Fix connections - DO J = 1,numSplitNodes - splitnodes(J)%NConnections = 0 - END DO - - DO I = 1,numElements - - - DO J = 1,numSplitNodes - IF ( elements(I)%Node1Indx == J ) THEN - splitnodes(J)%NConnections = splitnodes(J)%NConnections + 1 - splitnodes(J)%ConnectionList(splitnodes(J)%NConnections) = I - END IF - IF ( elements(I)%Node2Indx == J ) THEN - splitnodes(J)%NConnections = splitnodes(J)%NConnections + 1 - splitnodes(J)%ConnectionList(splitnodes(J)%NConnections) = I - END IF - END DO - END DO - - END IF - -END SUBROUTINE SplitMeshNodes - - - -SUBROUTINE GenerateLumpedLoads( nodeIndx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: nodeIndx - REAL(ReKi), INTENT( IN ) :: sgn - TYPE(Morison_NodeType), INTENT( IN ) :: node - REAL(ReKi), INTENT( IN ) :: gravity - REAL(ReKi), INTENT( IN ) :: MSL2SWL - REAL(ReKi), INTENT( IN ) :: densWater - INTEGER, INTENT( IN ) :: NStepWave - REAL(SiKi), INTENT( IN ) :: WaveDynP(:,:) ! TODO: Verify it is ok to use (:,:) for the zero-based first array index GJH 2/5/14 - REAL(ReKi),ALLOCATABLE, INTENT( OUT ) :: F_DP(:,:) - REAL(ReKi), INTENT( OUT ) :: F_B(6) - REAL(ReKi), INTENT( OUT ) :: dragConst - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - REAL(ReKi) :: k(3) - - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - IF (.NOT. node%PropPot ) THEN - - k = sgn * node%R_LToG(:,3) - - CALL LumpDynPressure( nodeIndx, node%JAxCp, k, node%R, node%tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg) - - ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. - ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) - CALL LumpBuoyancy( sgn, densWater, node%R, node%tMG, node%JointPos(3) - MSL2SWL, node%R_LToG, gravity, F_B ) - - - ! This one is tricky because we need to calculate a signed volume which is the signed sum of all connecting elements and then split the - ! result across all the connecting nodes. - !CALL LumpAddedMass() - - ELSE - - ALLOCATE ( F_DP(0:NStepWave, 6), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating distributed dynamic pressure loads array.' - ErrStat = ErrID_Fatal - RETURN - END IF - F_DP = 0.0 - F_B = 0.0 - END IF - - - CALL LumpDragConst( densWater, node%Cd, node%R, node%tMG, dragConst ) - - - - -END SUBROUTINE GenerateLumpedLoads - - - -SUBROUTINE CreateLumpedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWave, WaveDynP, WaveAcc, numNodes, nodes, numElements, elements, & - numLumpedMarkers, lumpedMeshIn, lumpedMeshOut, lumpedToNodeIndx, L_An, & - L_F_B, L_F_I, L_F_BF, L_AM_M, L_dragConst, & - ErrStat, ErrMsg ) - - REAL(ReKi), INTENT( IN ) :: densWater - REAL(ReKi), INTENT( IN ) :: gravity - REAL(ReKi), INTENT( IN ) :: MSL2SWL - REAL(ReKi), INTENT( IN ) :: wtrDpth - INTEGER, INTENT( IN ) :: NStepWave - REAL(SiKi), INTENT( IN ) :: WaveDynP(0:,:) - REAL(SiKi), INTENT( IN ) :: WaveAcc(0:,:,:) - INTEGER, INTENT( IN ) :: numNodes - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) - TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) - INTEGER, INTENT( OUT ) :: numLumpedMarkers - !TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: lumpedMarkers(:) - TYPE(MeshType), INTENT( OUT ) :: lumpedMeshIn - TYPE(MeshType), INTENT( OUT ) :: lumpedMeshOut - INTEGER, ALLOCATABLE, INTENT( OUT ) :: lumpedToNodeIndx(:) - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_An(:,:) ! The signed/summed end cap Area x k of all connected members at a common joint - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_B(:,:) ! Buoyancy force associated with the member - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_I(:,:,:) ! Inertial force. TODO: Eventually the dynamic pressure will be included in this force! GJH 4/15/14 - !REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_DP(:,:,:) ! Dynamic pressure force - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_F_BF(:,:) ! Flooded buoyancy force - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_AM_M(:,:,:) ! Added mass of member - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: L_dragConst(:) ! - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - INTEGER :: I, J, M, count - TYPE(Morison_MemberType) :: element - TYPE(Morison_NodeType) :: node, node1, node2 - REAL(ReKi) :: L, sgn -! REAL(ReKi) :: k(3) - REAL(ReKi) :: z0 - REAL(ReKi),ALLOCATABLE :: F_DP(:,:) - REAL(ReKi) :: F_B(6) - REAL(ReKi) :: F_BF(6) - REAL(ReKi) :: Vmat(3,1), F_I(6), AM_M(6,6) !AM(6,6), - REAL(ReKi) :: dragConst - - - INTEGER, ALLOCATABLE :: nodeToLumpedIndx(:) - INTEGER, ALLOCATABLE :: commonNodeLst(:) - LOGICAL, ALLOCATABLE :: usedJointList(:) - INTEGER :: nCommon -! REAL(ReKi) :: CA - REAL(ReKi) :: AMfactor - REAL(ReKi) :: An(3), Vn(3), af(3) -! REAL(ReKi) :: AM11, AM22, AM33 - REAL(ReKi) :: f1, VnDotAf, Vmag !f2, - - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - numLumpedMarkers = 0 - z0 = -(wtrDpth) ! The total sea depth is the still water depth of the seabed - - - - ! Count how many lumped markers we need to create by looping over the nodes - - DO I=1,numNodes - - IF ( (nodes(I)%NodeType == 3) .OR. ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) ) THEN - - numLumpedMarkers = numLumpedMarkers + 1 - - END IF - - END DO - - - ! Create the input and output meshes associated with lumped loads - - CALL MeshCreate( BlankMesh = lumpedMeshIn & - ,IOS = COMPONENT_INPUT & - ,Nnodes = numLumpedMarkers & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. ) - - - - - ! ! Allocate the array for the lumped markers - ! - !ALLOCATE ( lumpedMarkers(numLumpedMarkers), STAT = ErrStat ) - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for the lumped load markers array.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - - ALLOCATE ( commonNodeLst(10), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the commonNodeLst array.' - ErrStat = ErrID_Fatal - RETURN - END IF - commonNodeLst = -1 - - ALLOCATE ( usedJointList(numNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the UsedJointList array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - usedJointList = .FALSE. - - ALLOCATE ( lumpedToNodeIndx(numLumpedMarkers), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( nodeToLumpedIndx(numNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - - ALLOCATE ( L_F_B( 6, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped buoyancy forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_F_B = 0.0 - - ALLOCATE ( L_An( 3, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the L_An array.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_An = 0.0 - - ! This is - ALLOCATE ( L_F_I( 0:NStepWave, 6, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped inertial forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_F_I = 0.0 - - !ALLOCATE ( L_F_DP( 0:NStepWave, 6, numLumpedMarkers ), STAT = ErrStat ) - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for the lumped dynamic pressure forces/moments array.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - ! L_F_DP = 0.0 - - ALLOCATE ( L_F_BF( 6, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped buoyancy due to flooding forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_F_BF = 0.0 - - ALLOCATE ( L_AM_M( 6, 6, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped member added mass.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_AM_M = 0.0 - - ALLOCATE ( L_dragConst( numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped drag constants.' - ErrStat = ErrID_Fatal - RETURN - END IF - L_dragConst = 0.0 - - ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads - ! For the buoyancy loads, loop over the elements and then apply one half of the resulting value - ! to each of the interior element nodes but the full value to an end node. This means that an internal member node will receive 1/2 of its - ! load from element A and 1/2 from element B. If it is the end of a member it will simply receive - ! the element A load. - - count = 1 - - DO I=1,numNodes - - ! exclude internal member nodes and end nodes which were connected to a joint made into a super member - - IF ( (nodes(I)%NodeType == 3) .OR. ( nodes(I)%NodeType == 1 .AND. nodes(I)%JointOvrlp == 0 ) ) THEN - - lumpedToNodeIndx(count) = I - nodeToLumpedIndx(I) = count - - ! If this is a super member node, then generate the lumped loads now, otherwise save it for the loop over elements - - IF ( nodes(I)%NodeType == 3 ) THEN - - END IF - - - - - ! Create the node on the mesh - - CALL MeshPositionNode (lumpedMeshIn & - , count & - , nodes(I)%JointPos & ! this info comes from FAST - , ErrStat & - , ErrMsg & - ) !, transpose(nodes(I)%R_LToG) ) - IF ( ErrStat /= 0 ) THEN - RETURN - END IF - - ! Create the mesh element - - CALL MeshConstructElement ( lumpedMeshIn & - , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , count & - ) - count = count + 1 - - - END IF - - END DO - - - - - ! CA is the added mass coefficient for three dimensional bodies in infinite fluid (far from boundaries) The default value is 2/Pi - - - AMfactor = 2.0 * densWater * Pi / 3.0 - - ! Loop over nodes again in order to create lumped axial drag. - - usedJointList = .FALSE. - commonNodeLst = -1 - - DO I=1,numNodes - - - - ! Determine bounds checking based on what load we are calculating, - ! This is for L_An - IF ( nodes(I)%JointPos(3) >= z0 ) THEN - - ! exclude internal member nodes and end nodes which were connected to a joint made into a super member - - - - ! If this is a super member node, then generate the lumped loads now, otherwise save it for the loop over elements - - IF ( nodes(I)%NodeType == 3 ) THEN - - ELSE - - IF ( nodes(I)%JointIndx /= -1 ) THEN ! TODO: MAYBE THIS SHOULD CHECK JointOvrlp value instead!! - - ! Have we already set the added mass for this node? - IF ( .NOT. usedJointList(nodes(I)%JointIndx) ) THEN - - nCommon = 0 - An = 0.0 - Vn = 0.0 - - DO J=1,numNodes - - ! must match joint index but also cannot be modeled using WAMIT - IF ( nodes(I)%JointIndx == nodes(J)%JointIndx ) THEN - - nCommon = nCommon + 1 - commonNodeLst(nCommon) = J - - ! Compute the signed area*outward facing normal of this member - sgn = 1.0 - - element = elements(nodes(J)%ConnectionList(1)) - - IF ( element%Node1Indx == J ) THEN - sgn = -1.0 ! Local coord sys points into element at starting node, so flip sign of local z vector - ELSE IF ( element%Node2Indx == J ) THEN - sgn = 1.0 ! Local coord sys points out of element at ending node, so leave sign of local z vector - ELSE - ErrMsg = 'Internal Error in CreateLumpedMesh: could not find element node index match.' - ErrStat = ErrID_FATAL - RETURN - END IF - ! Compute the signed volume of this member - f1 = (nodes(J)%R+nodes(J)%tMG)*(nodes(J)%R+nodes(J)%tMG)*(nodes(J)%R+nodes(J)%tMG) - Vn = Vn + sgn*f1*nodes(J)%R_LToG(:,3) - An = An + sgn*nodes(J)%R_LtoG(:,3)*Pi*(nodes(J)%R+nodes(J)%tMG)**2 - - END IF - - END DO - - nodes(I)%NConnectPreSplit = nCommon - - ! Divide the directed area equally across all connected markers - Vmag = sqrt(Dot_Product(Vn,Vn)) - - - - AM_M = 0.0 - IF ( (Vmag > 0.0) .AND. (.NOT. nodes(I)%PropPot) ) THEN - Vmat = RESHAPE(Vn,(/3,1/)) - AM_M(1:3,1:3) = (nodes(I)%JAxCa*AMfactor/(REAL( nCommon, ReKi)*Vmag) )*MatMul(Vmat,TRANSPOSE(Vmat)) - END IF - - DO J=1,nCommon - - IF ( nodes(I)%JointPos(3) >= z0 ) THEN - - L_An (:, nodeToLumpedIndx(commonNodeLst(J))) = An / nCommon - L_AM_M(:,:,nodeToLumpedIndx(commonNodeLst(J))) = AM_M - - DO M=0,NStepWave - ! The WaveAcc array has indices of (timeIndx, nodeIndx, vectorIndx), the nodeIndx needs to correspond to the total list of nodes for which - ! the wave kinematics were generated. We can use the nodeToLumpedIndx however for L_F_I and it's indices are (timeIndx, nodeIndx, vectorIndx) - - - F_I = 0.0 - IF ( (Vmag > 0.0) .AND. (.NOT. nodes(I)%PropPot) ) THEN - af = WaveAcc(M,commonNodeLst(J),:) - VnDotAf = Dot_Product(Vn,af) - F_I(1:3) = ( nodes(I)%JAxCa*AMfactor*VnDotAf / ( REAL( nCommon, ReKi ) * Vmag ) ) * Vn - END IF - L_F_I(M, :,nodeToLumpedIndx(commonNodeLst(J))) = F_I - END DO - - ELSE - ! Should we ever land in here? - L_An(:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 - L_AM_M(:,:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 - L_F_I(:,:,nodeToLumpedIndx(commonNodeLst(J))) = 0.0 - END IF - - END DO - - usedJointList(nodes(I)%JointIndx) = .TRUE. - END IF !IF ( .NOT. usedJointList(nodes(I)%JointIndx) ) - - END IF ! IF ( nodes(I)%JointIndx /= -1 ) - - END IF ! IF ( nodes(I)%NodeType == 3 ) THEN - - - - END IF ! ( nodes(I)%JointPos(3) >= z0 ) - - - - END DO ! I=1,numNodes - - - ! Loop over elements and identify those end nodes which have a JointOvrlp option of 0. - - DO I=1,numElements - - element = elements(I) - node1 = nodes(element%Node1Indx) - node2 = nodes(element%Node2Indx) - - CALL GetDistance( node1%JointPos, node2%JointPos, L ) - - IF ( node1%NodeType == 1 .AND. node1%JointOvrlp == 0 ) THEN - - !Process Lumped loads for this node - node = node1 - sgn = 1.0 - IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) )THEN - CALL GenerateLumpedLoads( element%Node1Indx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) - L_F_I(:, :, nodeToLumpedIndx(element%Node1Indx)) = L_F_I(:, :, nodeToLumpedIndx(element%Node1Indx)) + F_DP - ! L_F_DP(:, :, nodeToLumpedIndx(element%Node1Indx)) = F_DP - - L_dragConst(nodeToLumpedIndx(element%Node1Indx)) = dragConst - IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) )THEN - L_F_B (:, nodeToLumpedIndx(element%Node1Indx)) = F_B - END IF - - ELSE - F_BF = 0.0 - !L_F_DP(:, :, nodeToLumpedIndx(element%Node1Indx)) = 0.0 - L_F_B (:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 - L_dragConst(nodeToLumpedIndx(element%Node1Indx)) = 0.0 - - END IF - IF ( node%FillFlag ) THEN - IF ( (node%JointPos(3) <= (node%FillFSLoc)) .AND. (node%JointPos(3) >= z0) ) THEN - CALL LumpFloodedBuoyancy( sgn, node%FillDensity, node%R, node%t, node%FillFSLoc, node%JointPos(3) , node%R_LToG, gravity, F_BF ) - - L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = F_BF - ELSE - L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 - END IF - ELSE - L_F_BF(:, nodeToLumpedIndx(element%Node1Indx)) = 0.0 - END IF - - - ENDIF - - - IF ( node2%NodeType == 1 .AND. node2%JointOvrlp == 0 ) THEN - - !Process Lumped loads for this node - node = node2 - sgn = -1.0 - - ! Generate the loads regardless of node location, and then make the bounds check per load type because the range is different - CALL GenerateLumpedLoads( element%Node2Indx, sgn, node, gravity, MSL2SWL, densWater, NStepWave, WaveDynP, dragConst, F_DP, F_B, ErrStat, ErrMsg ) - IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) ) THEN - L_F_I(:, :, nodeToLumpedIndx(element%Node2Indx)) = L_F_I(:, :, nodeToLumpedIndx(element%Node2Indx)) + F_DP - !L_F_DP(:, :, nodeToLumpedIndx(element%Node2Indx)) = F_DP - - L_dragConst(nodeToLumpedIndx(element%Node2Indx)) = dragConst - - IF ( ( node%JointPos(3) >= z0 ) .AND. (.NOT. node%PropPot) ) THEN - L_F_B (:, nodeToLumpedIndx(element%Node2Indx)) = F_B - END IF - - ELSE - F_BF = 0.0 - !L_F_DP(:, :, nodeToLumpedIndx(element%Node2Indx)) = 0.0 - L_F_B (:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 - L_dragConst(nodeToLumpedIndx(element%Node2Indx)) = 0.0 - - END IF - IF ( node%FillFlag ) THEN - IF ( (node%JointPos(3) <= (node%FillFSLoc)) .AND. (node%JointPos(3) >= z0) ) THEN - CALL LumpFloodedBuoyancy( sgn, node%FillDensity, node%R, node%t, node%FillFSLoc, node%JointPos(3), node%R_LToG, gravity, F_BF ) - L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = F_BF - ELSE - L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 - END IF - ELSE - L_F_BF(:, nodeToLumpedIndx(element%Node2Indx)) = 0.0 - END IF - ENDIF - - - - - IF ( ErrStat /= 0 ) THEN - RETURN - END IF - - - END DO - - - CALL MeshCommit ( lumpedMeshIn & - , ErrStat & - , ErrMsg ) - - IF ( ErrStat /= 0 ) THEN - RETURN - END IF - - ! Initialize the inputs - DO I=1,lumpedMeshIn%Nnodes - lumpedMeshIn%Orientation(:,:,I) = lumpedMeshIn%RefOrientation(:,:,I) - END DO - lumpedMeshIn%TranslationDisp = 0.0 - lumpedMeshIn%TranslationVel = 0.0 - lumpedMeshIn%RotationVel = 0.0 - lumpedMeshIn%TranslationAcc = 0.0 - lumpedMeshIn%RotationAcc = 0.0 - - CALL MeshCopy ( SrcMesh = lumpedMeshIn & - ,DestMesh = lumpedMeshOut & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - lumpedMeshIn%RemapFlag = .TRUE. - lumpedMeshOut%RemapFlag = .TRUE. - - -END SUBROUTINE CreateLumpedMesh - -!subroutine ComputeDistributedLoadsAtNode( elementWaterState, densWater, JointZPos, & -! PropPot, R, dRdz, t, tMG, MGdensity, & -! R_LToG, Ca, Cp, AxCa, AxCp, Cd, WaveAcc, WaveDynP, D_dragConst_in, & -! D_AM_M, D_dragConst, D_F_I, ErrStat, ErrMsg ) -! -! INTEGER, INTENT( IN ) :: elementWaterState -! REAL(ReKi), INTENT( IN ) :: densWater -! REAL(ReKi), INTENT( IN ) :: JointZPos -! LOGICAL, INTENT( IN ) :: PropPot -! REAL(ReKi), INTENT( IN ) :: R -! REAL(ReKi), INTENT( IN ) :: dRdz -! REAL(ReKi), INTENT( IN ) :: t -! REAL(ReKi), INTENT( IN ) :: tMG -! REAL(ReKi), INTENT( IN ) :: MGdensity -! REAL(ReKi), INTENT( IN ) :: R_LToG(3,3) -! REAL(ReKi), INTENT( IN ) :: Ca -! REAL(ReKi), INTENT( IN ) :: Cp -! REAL(ReKi), INTENT( IN ) :: AxCa -! REAL(ReKi), INTENT( IN ) :: AxCp -! REAL(ReKi), INTENT( IN ) :: Cd -! REAL(ReKi), INTENT( IN ) :: WaveAcc(3) -! REAL(ReKi), INTENT( IN ) :: WaveDynP -! REAL(ReKi), INTENT( IN ) :: D_dragConst_in ! -! REAL(ReKi), INTENT( OUT ) :: D_AM_M(6,6) ! Added mass of member -! -! REAL(ReKi), INTENT( OUT ) :: D_dragConst ! -! REAL(ReKi), INTENT( OUT ) :: D_F_I(3) ! Inertial force associated with the member -! INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs -! CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! REAL(ReKi) :: k(3) -! -! -! IF ( .NOT. PropPot ) THEN ! Member is not modeled with WAMIT -! -! -! ! node is in the water, what about the entire element? -! IF ( elementWaterState == 1 ) THEN -! -! ! Element is in the water -! -! -! ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. -! ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) -! k = R_LToG(:,3) -! CALL DistrInertialLoads( densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, WaveAcc, WaveDynP, D_F_I, ErrStat, ErrMsg ) -! CALL DistrAddedMass( densWater, Ca, AxCa, R_LToG, R, tMG, dRdZ, D_AM_M ) -! -! ELSE -! ! Element is out of the water -! D_F_I (:) = 0.0 -! D_AM_M(:,:) = 0.0 ! This is not time-dependent -! END IF -! -! -! END IF ! IF ( .NOT. nodes(I)%PropPot ) -! -! ! These are the only two loads we compute at initialization if the member is modeled with WAMIT, they are also computed when Morison is used. -! IF ( elementWaterState == 1 )THEN -! ! element is in the water -! D_dragConst = D_dragConst_in -! ELSE -! D_dragConst = 0.0 -! END IF -! -!end subroutine ComputeDistributedLoadsAtNode - - -SUBROUTINE CreateDistributedMesh( densWater, gravity, MSL2SWL, wtrDpth, NStepWave, WaveAcc, WaveDynP, numNodes, nodes, nodeInWater, numElements, elements, & - numDistribMarkers, distribMeshIn, distribMeshOut, distribToNodeIndx, D_F_I, & - D_F_B, D_F_DP, D_F_MG, D_F_BF, D_AM_M, D_AM_MG, D_AM_F, D_dragConst, elementWaterStateArr, & - Morison_Rad, ErrStat, ErrMsg ) - - REAL(ReKi), INTENT( IN ) :: densWater - REAL(ReKi), INTENT( IN ) :: gravity - REAL(ReKi), INTENT( IN ) :: MSL2SWL - REAL(ReKi), INTENT( IN ) :: wtrDpth - INTEGER, INTENT( IN ) :: NStepWave - REAL(SiKi), INTENT( IN ) :: WaveAcc(0:,:,:) - REAL(SiKi), INTENT( IN ) :: WaveDynP(0:,:) - INTEGER, INTENT( IN ) :: numNodes - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( IN ) :: elements(:) - TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) - INTEGER(IntKi), INTENT( IN ) :: nodeInWater(0:,:) ! Flag indicating whether or not a node is in the water at a given wave time - INTEGER, INTENT( OUT ) :: numDistribMarkers - !TYPE(Morison_NodeType), ALLOCATABLE, INTENT( OUT ) :: distribMarkers(:) - TYPE(MeshType), INTENT( OUT ) :: distribMeshIn - TYPE(MeshType), INTENT( OUT ) :: distribMeshOut - INTEGER, ALLOCATABLE, INTENT( OUT ) :: distribToNodeIndx(:) - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_I(:,:,:) - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_B(:,:) ! Buoyancy force associated with the member - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_DP(:,:,:) ! Dynamic pressure force - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_MG(:,:) ! Marine growth weight - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_F_BF(:,:) ! Flooded buoyancy force - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_M(:,:,:) ! Added mass of member - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_MG(:) ! Added mass of marine growth - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_AM_F(:) ! Added mass of flooded fluid - REAL(ReKi),ALLOCATABLE, INTENT( OUT) :: D_dragConst(:) ! - INTEGER,ALLOCATABLE, INTENT( OUT) :: elementWaterStateArr(:,:) - REAL(SiKi), ALLOCATABLE, INTENT( OUT ) :: Morison_Rad(:) ! radius of each node (for FAST visualization) - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - - INTEGER :: I, J, count, node2Indx - INTEGER :: secondNodeWaterState - TYPE(Morison_MemberType) :: element - TYPE(Morison_NodeType) :: node1, node2 - REAL(ReKi) :: L - REAL(ReKi) :: k(3) - REAL(R8Ki) :: orientation(3,3) - - ! REAL(ReKi),ALLOCATABLE :: F_DP(:,:) - REAL(ReKi) :: F_B(6) - REAL(ReKi) :: F_BF(6) - REAL(ReKi),ALLOCATABLE :: F_I(:,:) - REAL(ReKi) :: z0 - INTEGER, ALLOCATABLE :: nodeToDistribIndx(:) - - numDistribMarkers = 0 - z0 = -(wtrDpth) ! The total sea depth is the still water depth of the seabed - - ! Count how many distributed markers we need to create by looping over the nodes - - DO I=1,numNodes - - IF ( nodes(I)%NodeType /= 3 ) THEN ! exclude super member nodes - - numDistribMarkers = numDistribMarkers + 1 - - END IF - - END DO - - - ! Create the input and output meshes associated with distributed loads - - CALL MeshCreate( BlankMesh = distribMeshIn & - ,IOS = COMPONENT_INPUT & - ,Nnodes = numDistribMarkers & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. ) - - IF ( ErrStat >= AbortErrLev ) RETURN - - CALL AllocAry( Morison_Rad, numDistribMarkers, 'Morison_Rad', ErrStat, ErrMsg) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Allocate the array for the distributed markers - - !ALLOCATE ( distribMarkers(numDistribMarkers), STAT = ErrStat ) - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for the distributed load markers array.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - - ALLOCATE ( distribToNodeIndx(numDistribMarkers), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( nodeToDistribIndx(numNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - - ALLOCATE ( elementWaterStateArr( 0:NStepWave, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the elementWaterStateArr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - elementWaterStateArr = 0 ! out of the water - - ALLOCATE ( D_F_I( 0:NStepWave, 6, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed inertial forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_F_I = 0.0 - - ALLOCATE ( D_F_B( 6, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed buoyancy forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_F_B = 0.0 - - ALLOCATE ( D_F_DP( 0:NStepWave, 6, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed dynamic pressure forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_F_DP = 0.0 - - ALLOCATE ( D_F_MG( 6, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed marine growth weight forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_F_MG = 0.0 - - ALLOCATE ( D_F_BF( 6, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed buoyancy due to flooding forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_F_BF = 0.0 - - - ALLOCATE ( D_AM_M( 3, 3, numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed added mass of flooded fluid.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_AM_M = 0.0 - - ALLOCATE ( D_AM_MG( numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed added mass of marine growth.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_AM_MG = 0.0 - - ALLOCATE ( D_AM_F( numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed added mass of flooded fluid.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_AM_F = 0.0 - - ALLOCATE ( D_dragConst( numDistribMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the distributed drag constants.' - ErrStat = ErrID_Fatal - RETURN - END IF - D_dragConst = 0.0 - - ! Loop over nodes to create all loads on the resulting markers except for the buoyancy loads <---@mhall: what does "create all loads" mean? - ! For the buoyancy loads, loop over the elements and then apply one half of the resulting value - ! to each of the interior element nodes but the full value to an end node. This means that an internal member node will receive 1/2 of its - ! load from element A and 1/2 from element B. If it is the end of a member it will simply receive - ! the element A load. <---@mhall: shouldn't end nodes only receive half too? - - count = 1 - - DO I=1,numNodes - - IF ( nodes(I)%NodeType /= 3 ) THEN - - ! End point or internal member node - - ! Find the node index for the other end of this element - !IF ( nodes(I)%NodeType == 1 ) THEN - ! element = elements(nodes(I)%ConnectionList(1)) - ! IF ( element%Node1Indx == I ) THEN - ! node2Indx = element%Node2Indx - ! ELSE - ! node2Indx = element%Node1Indx - ! END IF - !ELSE - ! node2Indx = -1 - !END IF - ! - ! ! Need to see if this node is connected to an element which goes above MSL2SWL or below Seabed. - !IF ( node2Indx > 0 ) THEN - ! IF ( nodes(node2Indx)%JointPos(3) > MSL2SWL ) THEN - ! secondNodeWaterState = 1 - ! ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN - ! secondNodeWaterState = 2 - ! ELSE - ! secondNodeWaterState = 0 - ! END IF - !ELSE - ! secondNodeWaterState = 0 - !END IF - - !CALL GetDistance( element - ! ! Compute all initialization forces now so we have access to the element information - ! - IF ( .NOT. nodes(I)%PropPot .AND. nodes(I)%JointPos(3) >= z0 ) THEN - - ! Member is not modeled with WAMIT - - k = nodes(I)%R_LToG(:,3) - - ! IF ( nodes(I)%JointPos(3) <= MSL2SWL .AND. nodes(I)%JointPos(3) >= z0 ) THEN - - - CALL DistrAddedMass( densWater, nodes(I)%Ca, nodes(I)%AxCa, nodes(I)%R_LToG, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdZ, D_AM_M(:,:,count) ) - ! IF ( secondNodeWaterState == 0 ) THEN - ! Element is in the water - - - !CALL DistrDynPressure( I, nodes(I)%AxCa,nodes(I)%AxCp, nodes(I)%R_LToG, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdz, NStepWave, WaveDynP, WaveAcc, F_DP, ErrStat, ErrMsg) - ! D_F_DP(:,:,count) = 0.0 !F_DP - ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. - ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) - CALL DistrBuoyancy( densWater, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdz, nodes(I)%JointPos(3) - MSL2SWL, nodes(I)%R_LToG, gravity, F_B ) - D_F_B(:,count) = F_B - ! ! Compute all initialization forces now so we have access to the element information - ! - ! IF ( ( .NOT. nodes(J)%PropPot ) .AND. ( nodes(J)%JointPos(3) >= z0 ) ) THEN - ! k = nodes(J)%R_LToG(:,3) - CALL DistrInertialLoads( I, densWater, nodes(I)%Ca, nodes(I)%Cp, nodes(I)%AxCa, nodes(I)%AxCp, nodes(I)%R, nodes(I)%tMG, nodes(I)%dRdZ, k, NStepWave, WaveAcc, WaveDynP, F_I, ErrStat, ErrMsg ) - D_F_I(:,:,count) = F_I - - ! END IF - - ! ELSE - ! Element is out of the water - ! D_F_DP(:,:,count) = 0.0 - ! D_F_B(:,count) = 0.0 - - ! END IF - - ! ELSE - ! NOTE: Everything was initialized to zero so this isn't really necessary. GJH 9/24/13 - - ! D_F_DP(:,:,count) = 0.0 - - ! D_F_B(:,count) = 0.0 - ! END IF - - ! IF ( ( nodes(I)%JointPos(3) >= z0 ) .AND. (secondNodeWaterState /= 2 ) ) THEN - ! if the node is at or above the seabed then the element is in the water - CALL DistrMGLoads( nodes(I)%MGdensity, gravity, nodes(I)%R, nodes(I)%tMG, D_F_MG(:,count) ) - CALL DistrAddedMassMG( nodes(I)%MGdensity, nodes(I)%R, nodes(I)%tMG, D_AM_MG(count) ) - ! ELSE - ! D_F_MG(:,count) = 0.0 - ! D_AM_MG(count)= 0.0 - ! END IF - - END IF ! IF ( .NOT. nodes(I)%PropPot ) - - ! This is always computed, but may be zereod out for any given timestep during the CalcOutput work <---@mhall: what is this? - CALL DistrDragConst( densWater, nodes(I)%Cd, nodes(I)%R, nodes(I)%tMG, D_dragConst(count) ) - - IF ( nodes(I)%FillFlag ) THEN - IF ( nodes(I)%JointPos(3) <= nodes(I)%FillFSLoc .AND. nodes(I)%JointPos(3) >= z0 ) THEN - - ! Find the node index for the other end of this element - IF ( nodes(I)%NodeType == 1 ) THEN - element = elements(nodes(I)%ConnectionList(1)) - IF ( element%Node1Indx == I ) THEN - node2Indx = element%Node2Indx - ELSE - node2Indx = element%Node1Indx - END IF - ELSE - node2Indx = -1 - END IF - - ! different check for filled element, based on free-surface location - IF ( node2Indx > 0 ) THEN - IF ( nodes(node2Indx)%JointPos(3) > nodes(I)%FillFSLoc ) THEN - secondNodeWaterState = 0 - ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN - secondNodeWaterState = 2 - ELSE - secondNodeWaterState = 1 - END IF - ELSE - secondNodeWaterState = 1 - END IF - - IF (secondNodeWaterState == 1 ) THEN - CALL DistrAddedMassFlood( nodes(I)%FillDensity, nodes(I)%R, nodes(I)%t, D_AM_F(count) ) - ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. - ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) - CALL DistrFloodedBuoyancy( nodes(I)%FillDensity, nodes(I)%FillFSLoc, nodes(I)%R, nodes(I)%t, nodes(I)%dRdZ, nodes(I)%JointPos(3) - MSL2SWL, nodes(I)%R_LToG, gravity, F_BF ) - D_F_BF(:,count ) = F_BF - ELSE - D_AM_F(count) = 0.0 - D_F_BF(:,count ) = 0.0 - END IF - - ELSE - ! NOTE: Everything was initialized to zero so this isn't really necessary. GJH 9/24/13 - D_AM_F(count) = 0.0 - D_F_BF(:,count ) = 0.0 - END IF - ELSE - D_AM_F(count) = 0.0 - D_F_BF(:,count ) = 0.0 - END IF - - - - ! Create the node on the mesh - - orientation = transpose(nodes(I)%R_LToG ) - CALL MeshPositionNode (distribMeshIn & - , count & - , nodes(I)%JointPos & ! this info comes from FAST - , ErrStat & - , ErrMsg & ! , orient = orientation & ! bjj: I need this orientation set for visualization. but, will it mess up calculations (because loads are in different positions?) - ) !, transpose(nodes(I)%R_LToG ) ) - IF ( ErrStat >= AbortErrLev ) RETURN - - Morison_Rad(count) = nodes(I)%R ! set this for FAST visualization - - !@mhall: what is happening in these lines? - distribToNodeIndx(count) = I - nodeToDistribIndx(I) = count - count = count + 1 - - END IF - - END DO - - ! Now for time-varying values - - DO count=1,numDistribMarkers - J = distribToNodeIndx(count) - DO I=0,NStepWave - IF ( nodes(J)%NodeType /= 3 ) THEN - - ! End point or internal member node - - ! Find the node index for the other end of this element - IF ( nodes(J)%NodeType == 1 ) THEN - element = elements(nodes(J)%ConnectionList(1)) - IF ( element%Node1Indx == J ) THEN - node2Indx = element%Node2Indx - ELSE - node2Indx = element%Node1Indx - END IF - ELSE - node2Indx = -1 - END IF - - ! Need to see if this node is connected to an element which goes above MSL2SWL or below Seabed. - IF ( node2Indx > 0 ) THEN - IF ( ( nodeInWater(I,node2Indx) == 0 ) .AND. ( nodes(node2Indx)%JointPos(3) >= z0 ) ) THEN - secondNodeWaterState = 0 - ELSE IF ( nodes(node2Indx)%JointPos(3) < z0 ) THEN - secondNodeWaterState = 2 - ELSE - secondNodeWaterState = 1 - END IF - ELSE - secondNodeWaterState = 1 - END IF - - - - - IF ( (nodeInWater(I,J) == 1) .AND. nodes(J)%JointPos(3) >= z0 ) THEN - IF ( secondNodeWaterState == 1 ) THEN - ! Element is in the water - elementWaterStateArr(I,count) = 1 - END IF - END IF - - END IF - - END DO ! DO I=0,NStepWave - END DO ! DO count=1,numDistribMarkers - - - ! End of time-varying values - - - DO I=1,numElements - - - ! Create the mesh element - - CALL MeshConstructElement ( distribMeshIn & - , ELEMENT_LINE2 & - , ErrStat & - , ErrMsg & - , nodeToDistribIndx(elements(I)%Node1Indx) & - , nodeToDistribIndx(elements(I)%Node2Indx) ) - - IF ( ErrStat /= 0 ) RETURN - - - END DO - - - CALL MeshCommit ( distribMeshIn & - , ErrStat & - , ErrMsg ) - - IF ( ErrStat /= 0 ) THEN - RETURN - END IF - - ! Initialize the inputs - DO I=1,distribMeshIn%Nnodes - distribMeshIn%Orientation(:,:,I) = distribMeshIn%RefOrientation(:,:,I) - END DO - distribMeshIn%TranslationDisp = 0.0 - distribMeshIn%TranslationVel = 0.0 - distribMeshIn%RotationVel = 0.0 - distribMeshIn%TranslationAcc = 0.0 - distribMeshIn%RotationAcc = 0.0 - - CALL MeshCopy ( SrcMesh = distribMeshIn & - ,DestMesh = distribMeshOut & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - distribMeshIn%RemapFlag = .TRUE. - distribMeshOut%RemapFlag = .TRUE. - -END SUBROUTINE CreateDistributedMesh - - - -!==================================================================================================== -SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) -! This public subroutine process the input geometry and parameters and eliminates joint overlaps, -! sub-divides members, sets joint-level properties, etc. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - TYPE(Morison_InitInputType), INTENT( INOUT ) :: InitInp ! the Morison initialization data - !TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! tge Morison parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - ! Local variables - - INTEGER :: I, J !, j1, j2, tempINT ! generic integer for counting -! TYPE(Morison_JointType) :: joint1, joint2 -! Real(ReKi) :: z1 -! Real(ReKi) :: z2 - Real(ReKi) :: d - INTEGER :: temp - INTEGER :: prop1Indx, prop2Indx, node1Indx, node2Indx - INTEGER :: maxNodes = 0 - INTEGER :: maxElements = 0 - INTEGER :: maxSuperMembers = 0 - ! TYPE(Morison_NodeType) :: node1, node2, tempNode - TYPE(Morison_MemberPropType) :: propSet - INTEGER :: numSplitNodes - TYPE(Morison_NodeType),ALLOCATABLE :: splitNodes(:) - LOGICAL :: doSwap - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - IF ( InitInp%NMembers > 0 ) THEN - - - ! Determine the maximum number of nodes, elements, and super members which might be generated for the simulation mesh - CALL GetMaxSimQuantities( InitInp%NMGDepths, InitInp%MGTop, InitInp%MGBottom, InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%FilledGroups, InitInp%NJoints, InitInp%InpJoints, InitInp%NMembers, InitInp%InpMembers, maxNodes, maxElements, maxSuperMembers ) - - - ! Create a worse case size for the number of nodes and number of elements that will be generated for the simulation - ! marine growth split + super member split + member subdivision all creates new nodes - - ! marine growth split + member subdivision creates new elements + ! Determine the maximum number of nodes, elements, and super members which might be generated for the simulation mesh + CALL GetMaxSimQuantities( InitInp%NMGDepths, InitInp%MGTop, InitInp%MGBottom, InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%FilledGroups, InitInp%NJoints, InitInp%InpJoints, InitInp%NMembers, InitInp%InpMembers, maxNodes, maxElements, maxSuperMembers ) + + + ! Create a worse case size for the number of nodes and number of elements that will be generated for the simulation + ! marine growth split + super member split + member subdivision all creates new nodes + + ! marine growth split + member subdivision creates new elements ! Create a worse case size for the number of super members @@ -3862,29 +2135,33 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) InitInp%Nodes(I)%FillFlag = .FALSE. InitInp%Nodes(I)%FillDensity = 0.0 - + ! Set the marine growth thickness and density information for each joint node + CALL SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%Nodes(I) ) END DO + + ! Allocate memory for Members arrays InitInp%NElements = InitInp%NMembers - ALLOCATE ( InitInp%Elements(maxElements), STAT = ErrStat ) + ALLOCATE ( InitInp%Members(maxElements), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Elements array.' + ErrMsg = ' Error allocating space for Members array.' ErrStat = ErrID_Fatal RETURN END IF + ! loop through members, assign each its nodes, etc. DO I = 1,InitInp%NMembers - InitInp%Elements(I)%Node1Indx = InitInp%InpMembers(I)%MJointID1Indx ! Index of the first node in the Morison_NodeType array - InitInp%Elements(I)%Node2Indx = InitInp%InpMembers(I)%MJointID2Indx ! Index of the second node in the Morison_NodeType array - node1Indx = InitInp%Elements(I)%Node1Indx - node2Indx = InitInp%Elements(I)%Node2Indx + InitInp%Members(I)%Node1Indx = InitInp%InpMembers(I)%MJointID1Indx ! Index of the first node in the Morison_NodeType array + InitInp%Members(I)%Node2Indx = InitInp%InpMembers(I)%MJointID2Indx ! Index of the second node in the Morison_NodeType array + node1Indx = InitInp%Members(I)%Node1Indx + node2Indx = InitInp%Members(I)%Node2Indx prop1Indx = InitInp%InpMembers(I)%MPropSetID1Indx prop2Indx = InitInp%InpMembers(I)%MPropSetID2Indx @@ -3893,8 +2170,8 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! than the second node. ! The local element coordinate system requires that Z1 <= Z2, and if Z1=Z2 then X1 <= X2, and if Z1=Z2, X1=X2 then Y10) THEN @@ -3943,108 +2219,60 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) END IF - propSet = InitInp%MPropSets(prop1Indx) - InitInp%Elements(I)%R1 = propSet%PropD / 2.0 - InitInp%Elements(I)%t1 = propSet%PropThck - propSet = InitInp%MPropSets(prop2Indx) - InitInp%Elements(I)%R2 = propSet%PropD / 2.0 - InitInp%Elements(I)%t2 = propSet%PropThck + ! assign member to its joints' lists of connected members + Node1Indx = InitInp%Members(I)%Node1Indx + Node2Indx = InitInp%Members(I)%Node2Indx + InitInp%Nodes(Node1Indx)%Nconnections = InitInp%Nodes(Node1Indx)%Nconnections + 1 ! increment the joint's number of connections + InitInp%Nodes(Node2Indx)%Nconnections = InitInp%Nodes(Node2Indx)%Nconnections + 1 ! increment the joint's number of connections + InitInp%Nodes(Node1Indx)%ConnectionList(InitInp%Nodes(Node1Indx)%Nconnections) = I ! assign the member ID to the joint's connection list (positive since end 1) + InitInp%Nodes(Node2Indx)%ConnectionList(InitInp%Nodes(Node2Indx)%Nconnections) =-I ! assign the member ID to the joint's connection list (negative since end 2) - InitInp%Elements(I)%NumSplits = InitInp%InpMembers(I)%NumSplits - InitInp%Elements(I)%Splits = InitInp%InpMembers(I)%Splits - !InitInp%Elements(I)%MGSplitState = InitInp%InpMembers(I)%MGSplitState - !InitInp%Elements(I)%WtrSplitState = InitInp%InpMembers(I)%WtrSplitState - InitInp%Elements(I)%MDivSize = InitInp%InpMembers(I)%MDivSize - InitInp%Elements(I)%MCoefMod = InitInp%InpMembers(I)%MCoefMod - InitInp%Elements(I)%MmbrCoefIDIndx = InitInp%InpMembers(I)%MmbrCoefIDIndx - InitInp%Elements(I)%MmbrFilledIDIndx = InitInp%InpMembers(I)%MmbrFilledIDIndx + ! assign member some input quantities + InitInp%Members(I)%InpMbrIndx = I + InitInp%Members(I)%MDivSize = InitInp%InpMembers(I)%MDivSize + InitInp%Members(I)%MCoefMod = InitInp%InpMembers(I)%MCoefMod + InitInp%Members(I)%MmbrCoefIDIndx = InitInp%InpMembers(I)%MmbrCoefIDIndx + InitInp%Members(I)%MmbrFilledIDIndx = InitInp%InpMembers(I)%MmbrFilledIDIndx + ! assign member length CALL GetDistance( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, d) + InitInp%Members(I)%InpMbrLen = d - InitInp%Elements(I)%InpMbrLen = d - InitInp%Elements(I)%InpMbrIndx = I - - ! Direction cosines matrix which transforms a point in member coordinates to the global inertial system - !CALL Morison_DirCosMtrx( node1%JointPos, node2%JointPos, InitInp%Elements(I)%R_LToG ) - + ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array + CALL Morison_DirCosMtrx( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, InitInp%Members(I)%R_LToG ) - InitInp%Elements(I)%PropPot = InitInp%InpMembers(I)%PropPot ! Flag specifying whether member is modelled in WAMIT [true = modelled in WAMIT, false = not modelled in WAMIT] - + InitInp%Members(I)%PropPot = InitInp%InpMembers(I)%PropPot ! Flag specifying whether member is modelled in WAMIT [true = modelled in WAMIT, false = not modelled in WAMIT] + ! InitInp%Nodes(node1Indx)%R_LToG = InitInp%Members(I)%R_LToG + ! InitInp%Nodes(node2Indx)%R_LToG = InitInp%Members(I)%R_LToG + !@mhall: no longer any need to split or subdivide members. + ! Instead, we need to discretize a member and create node points along it. + + DO I = 1, InitInp%NMembers + ! discretize a member and create node points along it. This will be done in Morison_Init + CALL DiscretizeMember( InitInp%NNodes, InitInp%Nodes, InitInp%Members(I), InitInp%MPropSets(prop1Indx), InitInp%MPropSets(prop2Indx), InitInp%NMGDepths, InitInp%MGDepths, ErrStat, ErrMsg ) + !@mhall: hoping passing one entry of Members is okay - otherwise can pass all and put for loop inside DiscretizeMember - ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array - - CALL Morison_DirCosMtrx( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, InitInp%Elements(I)%R_LToG ) - ! InitInp%Nodes(node1Indx)%R_LToG = InitInp%Elements(I)%R_LToG - ! InitInp%Nodes(node2Indx)%R_LToG = InitInp%Elements(I)%R_LToG - END DO - - - - ! Set the fill properties onto the elements - - CALL SetElementFillProps( InitInp%NFillGroups, InitInp%FilledGroups, InitInp%NElements, InitInp%Elements ) - - ! Split the elements at certain depths according to still water line, internal filled free surface, marine growth transition depths, seabed dpeth, etc. as applicable. - CALL SplitElements(InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) - - ! Split element due to MSL2SWL location and seabed location - !CALL SplitElementsForWtr(InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) - - ! Split elements if they cross the marine growth boundary. - - !CALL SplitElementsForMG(InitInp%MGTop, InitInp%MGBottom, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg) - - - ! Create any Super Members - !CALL CreateSuperMembers( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) - - ! Subdivide the members based on user-requested maximum division sizes (MDivSize) + END DO - CALL SubdivideMembers( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) - - + ! Set the fill properties onto the elements + !@mthall: This is now done in member setup loop in Morison_Init. CALL SetElementFillProps( InitInp%NFillGroups, InitInp%FilledGroups, InitInp%NElements, InitInp%Members ) + + + !@mhall: The below should be changed to operate on each member m%Members(I) and the arrays within it, or each joint. + ! The hydro coefficients should be set for each node along a member. + ! Set the element Cd, Ca, and Cp coefs - - CALL SetElementCoefs( InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, InitInp%SimplCpMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG,InitInp%CoefMembers, InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements ) - + CALL SetElementCoefs( InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, InitInp%SimplCpMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG,InitInp%CoefMembers, InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members ) ! Set the axial coefs AxCd and AxCa - CALL SetAxialCoefs( InitInp%NJoints, InitInp%NAxCoefs, InitInp%AxialCoefs, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements ) - - ! Set the marine growth thickness and density information onto the nodes (this is not a per-element quantity, but a per-node quantity - - CALL SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%NNodes, InitInp%Nodes ) - - - ! Create duplicate nodes at the ends of elements so that only one element is connected to any given end node - - CALL SplitMeshNodes( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, numSplitNodes, splitNodes, ErrStat, ErrMsg ) - - IF (numSplitNodes > InitInp%NNodes ) THEN - - InitInp%NNodes = numSplitNodes - !Reallocate the Nodes array - DEALLOCATE ( InitInp%Nodes ) - ALLOCATE ( InitInp%Nodes(numSplitNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Nodes array.' - ErrStat = ErrID_Fatal - RETURN - END IF - InitInp%Nodes = splitNodes - DEALLOCATE ( splitNodes ) - - END IF - + CALL SetAxialCoefs( InitInp%NJoints, InitInp%NAxCoefs, InitInp%AxialCoefs, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members ) - ! Now that the nodes are split, we can push the element properties down to the individual nodes without an issue - - CALL SetSplitNodeProperties( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, ErrStat, ErrMsg ) + !@mhall: duplicate nodes at member ends no longer needed @@ -4054,6 +2282,10 @@ SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) ! NOTE: since we need to mantain the input geometry, the altered members are now part of the simulation mesh and ! we will generate a mapping between the input and simulation meshes which is needed to generate user-requested outputs. + + + END DO !I = 1,InitInp%NMembers + ELSE @@ -4080,6 +2312,7 @@ END SUBROUTINE Morison_ProcessMorisonGeometry !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. !! The initial states and initial guess for the input are defined. +!! A lot of the model setup has been done previously in Morison_ProcessMorisonGeometry, and stored in InitInp. SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) !.................................................................................................................................. @@ -4089,7 +2322,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In TYPE(Morison_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states TYPE(Morison_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states TYPE(Morison_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states - TYPE(Morison_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(Morison_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (this contains the Members array) TYPE(Morison_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; !! only the output mesh is initialized) TYPE(Morison_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables @@ -4103,6 +2336,20 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(Morison_MemberType) :: mem ! the current member + INTEGER :: N + REAL(ReKi) :: dl + REAL(ReKi) :: vec(3) + REAL(ReKi) :: phi ! member tilt angle + REAL(ReKi) :: beta ! member tilt heading + REAL(ReKi) :: cosPhi + REAL(ReKi) :: sinPhi + REAL(ReKi) :: tanPhi + REAL(ReKi) :: sinBeta + REAL(ReKi) :: cosBeta + REAL(ReKi) :: Za + REAL(ReKi) :: Zb + ! TYPE(Morison_InitInputType) :: InitLocal ! Local version of the input data for the geometry processing routine ! INTEGER, ALLOCATABLE :: distribToNodeIndx(:) @@ -4110,270 +2357,560 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - - ! Initialize the NWTC Subroutine Library + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + + CALL NWTC_Init( ) + + + ! InitLocal = InitInp + p%WtrDens = InitInp%WtrDens + p%NumOuts = InitInp%NumOuts + p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] + p%OutSwtch = InitInp%OutSwtch + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for MOutLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF +IF (ALLOCATED(InitInp%MOutLst) ) & + p%MOutLst = InitInp%MOutLst ! Member output data + + p%NJOutputs = InitInp%NJOutputs ! Number of joints to output [ >=0 and <10] + + ALLOCATE ( p%JOutLst(p%NJOutputs), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for JOutLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF +IF (ALLOCATED(InitInp%JOutLst) ) & + p%JOutLst = InitInp%JOutLst ! Joint output data + + + + ! ----------------------- set up the members ----------------------- + + ! allocate and copy in the Members array + + ALLOCATE ( m%Members(p%NMembers), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the members array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + m%Members = InitInp%Members + + + ! ----------------------- set up the nodes ----------------------- + + ! allocate and copy in the nodes list + + p%NNodes = InitInp%NNodes + + ALLOCATE ( p%Nodes(p%NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for Nodes array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + p%Nodes = InitInp%Nodes + + + ! allocate and copy in hydrodynamic arrays for the nodes + + p%NStepWave= InitInp%NStepWave + + ALLOCATE ( p%WaveVel(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave velocities array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveVel = InitInp%WaveVel + + ALLOCATE ( p%WaveAcc(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave accelerations array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveAcc = InitInp%WaveAcc + + ALLOCATE ( p%WaveDynP(0:p%NStepWave, p%NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave dynamic pressure array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveDynP = InitInp%WaveDynP + + ALLOCATE ( p%WaveTime(0:p%NStepWave), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for wave time array.' + ErrStat = ErrID_Fatal + RETURN + END IF + p%WaveTime = InitInp%WaveTime + + + CALL MOVE_ALLOC( InitInp%nodeInWater, p%nodeInWater ) + + + ! allocate and initialize some wave-related arrays + + ALLOCATE ( elementWaterStateArr( 0:NStepWave, p%NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the elementWaterStateArr array.' + ErrStat = ErrID_Fatal + RETURN + END IF + elementWaterStateArr = 0 ! out of the water + + + + ALLOCATE ( m%F_I( 0:NStepWave, 6, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the inertial forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_I = 0.0 + + ALLOCATE ( m%F_DP( 0:NStepWave, 6, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the dynamic pressure forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_DP = 0.0 + + + + ! allocate and initialize joint-specific arrays + + ALLOCATE ( commonNodeLst(10), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the commonNodeLst array.' + ErrStat = ErrID_Fatal + RETURN + END IF + commonNodeLst = -1 + + ALLOCATE ( usedJointList(numNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the UsedJointList array.' + ErrStat = ErrID_Fatal + RETURN + END IF + usedJointList = .FALSE. + + ALLOCATE ( lumpedToNodeIndx(numLumpedMarkers), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( nodeToLumpedIndx(numNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the lumped index array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + ALLOCATE ( L_An( 3, numLumpedMarkers ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the joint directional area array.' + ErrStat = ErrID_Fatal + RETURN + END IF + L_An = 0.0 + + + + ! initialize load arrays for all nodes + + CALL AllocateNodeLoadVariables(m, p%NNodes, ErrStat, ErrMsg) + + ! a few additional loads that + + + + + ! Create the input and output meshes associated with loads at the nodes + + CALL MeshCreate( BlankMesh = u%Mesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = p%NNodes & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL AllocAry( Morison_Rad, numDistribMarkers, 'Morison_Rad', ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) RETURN + + + DO I=1,p%NNodes + + IF ( p%Nodes(I)%NodeType == 3 ) THEN - CALL NWTC_Init( ) - - - ! InitLocal = InitInp - p%WtrDens = InitInp%WtrDens - p%NumOuts = InitInp%NumOuts - p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] - p%OutSwtch = InitInp%OutSwtch - ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for MOutLst array.' - ErrStat = ErrID_Fatal - RETURN - END IF -IF (ALLOCATED(InitInp%MOutLst) ) & - p%MOutLst = InitInp%MOutLst ! Member output data - - p%NJOutputs = InitInp%NJOutputs ! Number of joints to output [ >=0 and <10] - - ALLOCATE ( p%JOutLst(p%NJOutputs), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for JOutLst array.' - ErrStat = ErrID_Fatal - RETURN END IF -IF (ALLOCATED(InitInp%JOutLst) ) & - p%JOutLst = InitInp%JOutLst ! Joint output data - + ! Create the node on the mesh + !orientation = transpose(p%Nodes(I)%R_LToG ) - - p%NNodes = InitInp%NNodes + CALL MeshPositionNode (u%Mesh & + , count & + , p%Nodes(I)%JointPos & ! this info comes from FAST + , ErrStat & + , ErrMsg & + ) !, transpose(p%Nodes(I)%R_LToG) ) + IF ( ErrStat /= 0 ) RETURN + + + Morison_Rad(count) = p%Nodes(I)%R ! set this for FAST visualization - ALLOCATE ( p%Nodes(p%NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Nodes array.' - ErrStat = ErrID_Fatal + !@mhall: what is happening in these lines? + distribToNodeIndx(count) = I + nodeToDistribIndx(I) = count + + ! Create the mesh element + + CALL MeshConstructElement (u%Mesh & + , ELEMENT_POINT & + , ErrStat & + , ErrMsg & + , count & + ) + count = count + 1 + + END DO + + + + CALL MeshCommit ( u%Mesh & + , ErrStat & + , ErrMsg ) + + IF ( ErrStat /= 0 ) THEN RETURN - END IF + END IF + + ! Initialize the inputs + DO I=1,u%Mesh%Nnodes + u%Mesh%Orientation(:,:,I) = u%Mesh%RefOrientation(:,:,I) + END DO + + u%Mesh%TranslationDisp = 0.0 + u%Mesh%TranslationVel = 0.0 + u%Mesh%RotationVel = 0.0 + u%Mesh%TranslationAcc = 0.0 + u%Mesh%RotationAcc = 0.0 + + + ! Duplicate the input mesh to create the output mesh + + CALL MeshCopy ( SrcMesh = u%Mesh & + ,DestMesh = y%Mesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + u%Mesh%RemapFlag = .TRUE. + y%Mesh%RemapFlag = .TRUE. + - p%Nodes = InitInp%Nodes + !--------------- - p%NStepWave= InitInp%NStepWave + ! Define parameters here: + + + p%DT = Interval + + + ! Define initial system states here: + + x%DummyContState = 0 + xd%DummyDiscState = 0 + z%DummyConstrState = 0 + OtherState%DummyOtherState = 0 + m%LastIndWave = 1 + + ! IF ( p%OutSwtch > 0 ) THEN @mhall: I think the below need to be allocated in all cases + + + - ALLOCATE ( p%WaveVel(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave velocities array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveVel = InitInp%WaveVel - ALLOCATE ( p%WaveAcc(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave accelerations array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveAcc = InitInp%WaveAcc - ALLOCATE ( p%WaveDynP(0:p%NStepWave, p%NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave dynamic pressure array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveDynP = InitInp%WaveDynP + ! loop through elements of each member and precalculate the required quantities + DO im = 1, p%NMembers + + + mem = m%Members(im) + + N = mem%NElements + dl = mem%dl + + ! find fill location of member (previously in SetElementFillProps) + IF ( mem%MmbrFilledIDIndx > 0 ) THEN + mem%FillDens = InitInp%FilledGroups(elements(I)%MmbrFilledIDIndx)%FillDens + mem%FillFSLoc = InitInp%FilledGroups(elements(I)%MmbrFilledIDIndx)%FillFSLoc + ELSE + mem%FillDens = 0.0 + mem%FillFSLoc = 0.0 + END IF + + + ! calculate instantaneous incline angle and heading, and related trig values + vec = p%Nodes(mem%NodeIndx(N+1))%JointPos - p%Nodes(mem%NodeIndx(1))%JointPos + + phi = arccos(vec(3)/SQRT(Dot_Product(vec,vec))) ! incline angle +! beta = arctan2(vec(2), vec(1)) ! heading of incline + + sinPhi = sin(phi) + cosPhi = cos(phi) +! tanPhi = tan(phi) + +! sinBeta = sin(beta) +! cosBeta = cos(beta) + + + + ! calculate l_fill or z_overfill for the member + mem%l_fill = (mem%FillFSLoc - )/cosPhi ! fill length along cylinder axis + + if mem%l_fill > mem%Len then + mem%z_overfill = mem%FillFSLoc - Zb + else + mem%z_overfill = 0.0 + end if + + + ! calculate h_floor if seabed-piercing + if (Za < -WtrDepth) then + do i=2,N+1 + if (Za > -WtrDepth) then ! find the lowest node above the seabed + mem%h_floor = (-WtrDepth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) + mem%i_floor = i-1 ! record the number of the element that pierces the seabed + break + end if + end do + end if + + + ! calculate element-level values + DO i = 1,N + mem%m_mg(i) = (mem%RMG(i+1) - mem%RMG(i))/dl + mem%m_in(i) = (mem%Rin(i+1) - mem%Rin(i))/dl + mem%alpha( i) = GetAlpha(mem%RMG(i), mem%RMG(i+1)) + mem%alpha_fb(i) = GetAlpha(mem%Rin(i), mem%Rin(i+1)) - ALLOCATE ( p%WaveTime(0:p%NStepWave), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave time array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveTime = InitInp%WaveTime + END DO + + + ! force-related constants for each element + DO i = 1,N + + Za = p%Nodes(mem%NodeIndx( i))%JointPos(3) ! z location of node i + Zb = p%Nodes(mem%NodeIndx(i+1))%JointPos(3) ! z location of node i+1 + + ! ------------------ marine growth weight and inertia, and flooded ballast inertia-------------------- + + if (i > mem%i_floor) then + ! full marine growth: get the properties for each half-element lumped to the appropriate node + + Rmid = 0.5*(mem%R( i)+mem%R( i+1)) ! radius at middle of segment, where division occurs + RmidMG = 0.5*(mem%RMG(i)+mem%RMG(i+1)) ! radius with marine growth at middle of segment, where division occurs + Rmidin = 0.5*(mem%Rin(i)+mem%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs + Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment + + CALL MarineGrowthPartSegment(mem%R(i ), Rmid, mem%RMG(i ),RmidMG, Lmid, rhoMG, mem%m_mg_l(i), mem%h_cmg_l(i), mem%I_lmg_l(i), mem%I_rmg_l(i)) ! get precomupted quantities for lower half-segment + CALL MarineGrowthPartSegment(mem%R(i+1), Rmid, mem%RMG(i+1),RmidMG,-Lmid, rhoMG, mem%m_mg_u(i), mem%h_cmg_u(i), mem%I_lmg_u(i), mem%I_rmg_u(i)) ! get precomupted quantities for upper half-segment + CALL FloodedBallastPartSegment(mem%Rin(i ), mem%Rmidin, Lmid, FillDens, mem%m_fb_l(i), mem%h_cfb_l(i), mem%I_lfb_l(i), mem%I_rfb_l(i)) ! get precomupted quantities for lower half-segment + CALL FloodedBallastPartSegment(mem%Rin(i+1), mem%Rmidin, -Lmid, FillDens, mem%m_fb_u(i), mem%h_cfb_u(i), mem%I_lfb_u(i), mem%I_rfb_u(i)) ! get precomupted quantities for upper half-segment + + else if (i == mem%ifloor) then + ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node + Rmid = (-mem%h_floor*mem%R( i) +(dl+mem%h_floor)*mem%R( i+1))/dl + RmidMG = (-mem%h_floor*mem%RMG(i) +(dl+mem%h_floor)*mem%RMG(i+1))/dl + Rmidin = (-mem%h_floor*mem%Rin(i) +(dl+mem%h_floor)*mem%Rin(i+1))/dl + Lmid = -mem%h_floor + + CALL MarineGrowthPartSegment(mem%R(i+1), Rmid, mem%RMG(i+1),RmidMG, -Lmid, rhoMG, mem%m_mg_u(i), mem%h_cmg_u(i), mem%I_lmg_u(i), mem%I_rmg_u(i)) ! get precomupted quantities for upper half-segment + CALL FloodedBallastPartSegment(mem%Rin(i+1), Rmidin, -Lmid, FillDens, mem%m_fb_u(i), mem%h_cfb_u(i), mem%I_lfb_u(i), mem%I_rfb_u(i)) ! get precomupted quantities for upper half-segment - CALL MOVE_ALLOC( InitInp%nodeInWater, p%nodeInWater ) + end if + + ! ------------------ flooded ballast weight (done) -------------------- + + ! fully buried element + if (Zb < -WtrDepth) then + mem%floodstatus(i) = 0 + ! fully filled elements + if (mem%FillFSLoc > Zb) then + mem%floodstatus(i) = 1 - ! Use the processed geometry information to create the distributed load mesh and associated marker parameters + ! depth-adjusted force distribution constant + mem%alpha_fb_star(i) = mem%alpha_fb(i)*( Zb - mem%FillFSLoc )^3 / ( ( (1-mem%alpha_fb(i))*(Za - mem%FillFSLoc))^3 + mem%alpha_fb(i)*(Zb - mem%FillFSLoc)^3 ) - ! We are storing the parameters in the DistribMarkers data structure instead of trying to hold this information within the DistribMesh. But these two data structures - ! must always be in sync. For example, the 5th element of the DistribMarkers array must correspond to the 5th node in the DistribMesh data structure. - - CALL CreateDistributedMesh( InitInp%WtrDens, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NStepWave, InitInp%WaveAcc, InitInp%WaveDynP, & - p%NNodes, p%Nodes, p%nodeInWater, InitInp%NElements, InitInp%Elements, & - p%NDistribMarkers, u%DistribMesh, y%DistribMesh, p%distribToNodeIndx, p%D_F_I, & - p%D_F_B, p%D_F_DP, p%D_F_MG, p%D_F_BF, p%D_AM_M, p%D_AM_MG, p%D_AM_F, p%D_dragConst, p%elementWaterState, & ! - InitOut%Morison_Rad, ErrStat, ErrMsg ) - - - !@mhall: D_F_BF must become a variable rather than a parameter! <<<< - - - IF ( ErrStat > ErrID_None ) RETURN - + ! force and moment magnitude constants + mem%Cfl_fb(i) = TwoPi * m * mem%FillDens * g * dl *( (li - mem%lfill)*Rin(i) + 0.5*((li - mem%lfill)*m_in + mem%Rin(i))*dl + 1/3*m_in*dl^2 ) + mem%Cfr_fb(i) = Pi * mem%FillDens * g * dl *( mem%Rin(i)^2 + m_in_in*Rin(i)*dl +1/3 m_in^2 *dl^2 ) + mem%CM0_fb(i) = TwoPi * mem%FillDens * g * dl *( 0.25*dl^3*m_in^4 + 0.25*dl^3*m_in^2 + dl^2*m_in^3*Rin(i) + 2/3*dl^2*m_in*mem%Rin(i) + 1.5*dl*m_in^2*mem%Rin(i)^2 + 0.5*dl*mem%Rin(i)^2 + m_in*mem%Rin(i)^3 ) - CALL CreateLumpedMesh( InitInp%WtrDens, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NStepWave, InitInp%WaveDynP, InitInp%WaveAcc,p%NNodes, p%Nodes, InitInp%NElements, InitInp%Elements, & - p%NLumpedMarkers, u%LumpedMesh, y%LumpedMesh, p%lumpedToNodeIndx, p%L_An, & - p%L_F_B, p%L_F_I, p%L_F_BF, p%L_AM_M, p%L_dragConst, & - ErrStat, ErrMsg ) - IF ( ErrStat > ErrID_None ) RETURN - + + ! partially filled element + else if ((mem%FillFSLoc > Za) .AND. (mem%FillFSLoc < Zb)) then + mem%floodstatus(i) = 2 + ! length along axis from node i to fill level + mem%h_fill = mem%l_fill - (i-1)*dl - ! CALL CreateSuperMesh( InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, p%NSuperMarkers, p%SuperMarkers, InitOut%LumpedMesh, ErrStat, ErrMsg ) + ! depth-adjusted force distribution constant + mem%alpha_fb_star(i) = (1 - mem%alpha_fb(i))*( Za - mem%FillFSLoc )^3 / ( ( (1-mem%alpha_fb(i))*(Za - mem%FillFSLoc))^3 - mem%alpha_fb(i)*(Zb - mem%FillFSLoc)^3 ) + + ! force and moment magnitude constants + mem%Cfl_fb(i) = TwoPi * m * mem%FillDens * g * mem%h_fill *( (li - mem%lfill)*mem%Rin(i) + 0.5*((li - mem%lfill)*m_in + mem%Rin(i))*mem%h_fill + 1/3*m_in*mem%h_fill^2 ) + mem%Cfr_fb(i) = Pi * mem%FillDens * g * mem%h_fill *( mem%Rin(i)^2 + m_in_in*mem%Rin(i)*mem%h_fill +1/3 m_in^2 *mem%h_fill^2 ) + mem%CM0_fb(i) = TwoPi * mem%FillDens * g * mem%h_fill *( 0.25*mem%h_fill^3*m_in^4 + 0.25*mem%h_fill^3*m_in^2 + mem%h_fill^2*m_in^3*mem%Rin(i) + 2/3*mem%h_fill^2*m_in*mem%Rin(i) + 1.5*mem%h_fill*m_in^2*mem%Rin(i)^2 + 0.5*mem%h_fill*mem%Rin(i)^2 + m_in*mem%Rin(i)^3 ) - - + ! unflooded element + else + mem%floodstatus(i) = 0 + end if - ! Define parameters here: - - - p%DT = Interval + end do ! end looping through elements + +end do ! looping through members + - ! Define initial system states here: + +! loop through joints to calculate joint quantities (the joints are the first NJoints nodes) - x%DummyContState = 0 - xd%DummyDiscState = 0 - z%DummyConstrState = 0 - OtherState%DummyOtherState = 0 - m%LastIndWave = 1 - IF ( p%OutSwtch > 0 ) THEN - ALLOCATE ( m%D_F_D(3,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_D array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_D = 0.0_ReKi - ALLOCATE ( m%D_F_I(3,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_I array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_I = 0.0_ReKi - ALLOCATE ( m%D_F_B(6,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_B array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_B = 0.0_ReKi - ALLOCATE ( m%D_F_AM(6,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_AM = 0.0_ReKi - ALLOCATE ( m%D_F_AM_M(6,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM_M array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_AM_M = 0.0_ReKi - ALLOCATE ( m%D_F_AM_MG(6,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM_MG array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_AM_MG = 0.0_ReKi - ALLOCATE ( m%D_F_AM_F(6,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM_F array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_F_AM_F = 0.0_ReKi - ALLOCATE ( m%D_FV(3,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FV array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_FV = 0.0_ReKi - ALLOCATE ( m%D_FA(3,y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FA array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_FA = 0.0_ReKi - ALLOCATE ( m%D_FDynP(y%DistribMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FDynP array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%D_FDynP = 0.0_ReKi + ! CA is the added mass coefficient for three dimensional bodies in infinite fluid (far from boundaries) The default value is 2/Pi + AMfactor = 2.0 * densWater * Pi / 3.0 + + usedJointList = .FALSE. + commonNodeLst = -1 + +DO I = 1,p%NJoints + + An = 0.0 + Vn = 0.0 + I_n = 0.0 + + IF ( p%Nodes(I)%JointPos(3) >= z0 ) THEN + + ! loop through each member attached to the joint, getting the radius of its appropriate end + DO J = 1, p%Nodes(I)%NConnections + + ! identify attached member and which end to us + IF (p%Nodes(I)%ConnectionList(J) > 0) THEN ! set up for end node 1 + member = p%Members(p%Nodes(I)%ConnectionList(J)) + MemberEndIndx = 1 + ELSE ! set up for end node N+1 + member = p%Members(-p%Nodes(I)%ConnectionList(J)) + MemberEndIndx = member%NElements + 1 + END IF + + ! attached member cannot be modeled using WAMIT if we're to count it + IF (.NOT. member%PropPot) THEN + + ! Compute the signed area*outward facing normal of this member + sgn = 1.0 + + IF ( MemberEndIndx == 1 ) THEN + sgn = -1.0 ! Local coord sys points into member at starting node, so flip sign of local z vector + ELSE + sgn = 1.0 ! Local coord sys points out of member at ending node, so leave sign of local z vector + END IF + + ! Compute the signed quantities for this member end, and add them to the joint values + An = An + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector + Vn = Vn + sgn* member%k* (member%RMG(MemberEndIndx))**3 ! r^3-weighted normal vector used for mass + I_n=I_n + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**4 ! r^4-weighted normal vector used for moments of inertia + + END IF + + END DO !J = 1, p%Nodes(I)%NConnections + + ! magnitudes of normal-weighted values + Amag = sqrt(Dot_Product(An ,An)) + Vmag = sqrt(Dot_Product(Vn ,Vn)) + Imag = sqrt(Dot_Product(I_n,I_n)) + + + ! marine growth mass/inertia magnitudes + p%Nodes(I)%m_MG = p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Amag ! marine growth mass at joint + Ir_MG_end = 0.25* p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Imag ! radial moment of inertia magnitude + Il_MG_end = 0.5* p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Imag ! axial moment of inertia magnitude + + ! get rotation matrix for moment of inertia orientations + RodrigMat(I_n, R_I, ErrStat, ErrMsg) + + ! globally-oreinted moment of inertia matrix for joint + Irl_mat = 0 + Irl_mat(1,1) = Ir_MG_end + Irl_mat(2,2) = Ir_MG_end + Irl_mat(3,3) = Il_MG_end + + p%Nodes(I)%I_MG = MatMul( MatMul(R_I, Irl_mat), Transpose(R_I) ) ! final moment of inertia matrix for node + + + + ! pre-compute wave inertia loads on joint + DO M=0,NStepWave + ! The WaveAcc array has indices of (timeIndx, nodeIndx, vectorIndx), the nodeIndx needs to correspond to the total list of nodes for which + ! the wave kinematics were generated. We can use the nodeToLumpedIndx however for L_F_I and it's indices are (timeIndx, nodeIndx, vectorIndx) + + F_I = 0.0 + IF ( (Vmag > 0.0) .AND. (.NOT. p%Nodes(I)%PropPot) ) THEN + af = p%WaveAcc(M, i,:) + VnDotAf = Dot_Product(Vn,af) + F_I(1:3) = ( p%Nodes(I)%JAxCa*AMfactor*VnDotAf / ( REAL( nCommon, ReKi ) * Vmag ) ) * Vn + END IF + m%L_F_I(M, :, i) = F_I + END DO + + ELSE ! if joint is below seabed + + p%Nodes(I)%m_MG = 0.0 + p%Nodes(I)%I_MG = 0.0 + m%L_F_I(:,:, i) = 0.0 + + END IF ! nodes(I)%JointPos(3) >= z0 + +END DO ! looping through nodes that are joints + - ALLOCATE ( m%L_F_B(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_F_B array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_F_B = 0.0_ReKi - ALLOCATE ( m%L_F_D(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_F_D array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_F_D = 0.0_ReKi - ALLOCATE ( m%L_F_I(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_F_I array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_F_I = 0.0_ReKi - !ALLOCATE ( m%L_F_DP(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Error allocating space for L_F_DP array.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - ALLOCATE ( m%L_FV(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_FV array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_FV = 0.0_ReKi - ALLOCATE ( m%L_FA(3,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_FA array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_FA = 0.0_ReKi - ALLOCATE ( m%L_FDynP(y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_FDynP array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_FDynP = 0.0_ReKi - ALLOCATE ( m%L_F_AM(6,y%LumpedMesh%Nnodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for L_F_AM array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%L_F_AM = 0.0_ReKi ! Define initial guess for the system inputs here: @@ -4387,6 +2924,8 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ! Initialize the outputs + IF ( p%OutSwtch > 0) then !@mhall: moved this "if" to after allocations + CALL MrsnOUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) IF ( ErrStat > ErrID_None ) RETURN @@ -4402,7 +2941,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ! Write Summary information now that everything has been initialized. - CALL WriteSummaryFile( InitInp%UnSum, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Elements, p%NumOuts, p%OutParam, p%NMOutputs, p%MOutLst, p%distribToNodeIndx, p%NJOutputs, p%JOutLst, u%LumpedMesh, y%LumpedMesh,u%DistribMesh, y%DistribMesh, p%L_F_B, p%L_F_BF, p%D_F_B, p%D_F_BF, p%D_F_MG, InitInp%Gravity, ErrStat, ErrMsg ) !p%NDistribMarkers, distribMarkers, p%NLumpedMarkers, lumpedMarkers, + CALL WriteSummaryFile( InitInp%UnSum, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members, p%NumOuts, p%OutParam, p%NMOutputs, p%MOutLst, p%distribToNodeIndx, p%NJOutputs, p%JOutLst, u%LumpedMesh, y%LumpedMesh,u%DistribMesh, y%DistribMesh, p%L_F_B, p%L_F_BF, p%D_F_B, p%D_F_BF, p%D_F_MG, InitInp%Gravity, ErrStat, ErrMsg ) !p%NDistribMarkers, distribMarkers, p%NLumpedMarkers, lumpedMarkers, IF ( ErrStat > ErrID_None ) RETURN ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which @@ -4417,6 +2956,192 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In END SUBROUTINE Morison_Init +SUBROUTINE RodrigMat(a, R, ErrStat, ErrMsg) + ! calculates rotation matrix R to rotate unit vertical vector to direction of input vector a + + REAL(ReKi), INTENT ( IN ) :: a(3) ! input vector + REAL(ReKi), INTENT ( INOUT ) :: R(3,3) ! rotation matrix from Rodrigues's rotation formula + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + REAL(ReKi) :: vec(3) ! scaled and adjusted input vector + REAL(ReKi) :: factor ! denomenator used for scaling + + + IF ((a(1) == 0) .AND. (a(2)==0)) THEN ! return identity if vertical + CALL EYE(R, ErrStat,ErrMsg) + IF (a(3) < 0) THEN + R = -R + END IF + + ELSE + vec = a/SQRT(Dot_Product(a,a)) + vec(3) = vec(3) + 1 + + factor = 2.0/Dot_Product(vec, vec) + + R(1,1) = factor*vec(1)*vec(1) - 1 + R(1,2) = factor*vec(1)*vec(2) + R(1,3) = factor*vec(1)*vec(3) + R(2,1) = factor*vec(2)*vec(1) + R(2,2) = factor*vec(2)*vec(2) - 1 + R(2,3) = factor*vec(2)*vec(3) + R(3,1) = factor*vec(3)*vec(1) + R(3,2) = factor*vec(3)*vec(2) + R(3,3) = factor*vec(3)*vec(3) - 1 + END IF + +END SUBROUTINE RodrigMat + + +FUNCTION GetAlpha(R1,R2) + ! calculates relative center of volume location for a (tapered) cylindrical element + + REAL(ReKi), INTENT ( IN ) :: R1 ! interior radius of element at node point + REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element + + + REAL(ReKi) :: alpha ! relative location of volumentric centroid between radius 1 and 2 (0= at radius 1, 1= at radius 2) + + alpha = (R1*R1 + 2*R1*R2 + 3*R2*R2)/4/(R1*R1 + R1*R2 + R2*R2) + + return alpha + +END FUNCTION GetAlpha + + +SUBROUTINE AllocateNodeLoadVariables(m, NNodes, ErrStat, ErrMsg ) + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT(IN ) :: NNodes ! number of nodes in node list + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = "" + + + ALLOCATE ( m%F_D(3,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_D array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_D = 0.0_ReKi + + ALLOCATE ( m%F_B( 6, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the buoyancy forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_B = 0.0 + + + ALLOCATE ( m%F_MG( 6, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the marine growth weight forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_MG = 0.0 + + ALLOCATE ( m%F_BF( 6, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the buoyancy due to flooding forces/moments array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_BF = 0.0 + + + ALLOCATE ( m%AM_M( 3, 3, NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the added mass of flooded fluid.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%AM_M = 0.0 + + ALLOCATE ( m%AM_MG( NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the added mass of marine growth.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%AM_MG = 0.0 + + ALLOCATE ( m%AM_F( NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the added mass of flooded fluid.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%AM_F = 0.0 + + ALLOCATE ( m%F_AM(6,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_AM = 0.0_ReKi + + ALLOCATE ( m%F_AM_M(6,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM_M array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_AM_M = 0.0_ReKi + + ALLOCATE ( m%F_AM_MG(6,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_F_AM_MG array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%F_AM_MG = 0.0_ReKi + + ALLOCATE ( m%dragConst( NNodes ), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for the drag constants.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%dragConst = 0.0 + + + ALLOCATE ( m%FV(3,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FV array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%FV = 0.0_ReKi + + ALLOCATE ( m%FA(3,NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FA array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%FA = 0.0_ReKi + + ALLOCATE ( m%FDynP(NNodes), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for D_FDynP array.' + ErrStat = ErrID_Fatal + RETURN + END IF + m%FDynP = 0.0_ReKi + + +END SUBROUTINE AllocateNodeLoadVariables + + + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the end of the simulation. SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) @@ -4551,6 +3276,55 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, REAL(ReKi) :: D_AM_M(6,6) REAL(ReKi) :: nodeInWater REAL(ReKi) :: D_dragConst ! The distributed drag factor + + + TYPE(Morison_MemberType) :: mem ! the current member + INTEGER :: N + REAL(ReKi) :: dl + REAL(ReKi) :: vec(3) + REAL(ReKi) :: phi ! member tilt angle + REAL(ReKi) :: beta ! member tilt heading + REAL(ReKi) :: cosPhi + REAL(ReKi) :: sinPhi + REAL(ReKi) :: tanPhi + REAL(ReKi) :: sinBeta + REAL(ReKi) :: cosBeta + REAL(ReKi) :: z1 + REAL(ReKi) :: z2 + REAL(ReKi) :: r1 + REAL(ReKi) :: r2 + REAL(ReKi) :: m ! shorthand for taper including marine growth of segment i + REAL(ReKi) :: Rmid + REAL(ReKi) :: RmidMG + REAL(ReKi) :: Rmidin + REAL(ReKi) :: Lmid + REAL(ReKi) :: Imat + REAL(ReKi) :: Fl ! various element axial force + REAL(ReKi) :: Fr ! various element radial force + REAL(ReKi) :: M ! various element radial moment + REAL(ReKi) :: h0 ! distances along cylinder centerline from point 1 to the waterplane + REAL(ReKi) :: rh ! radius of cylinder at point where its centerline crosses the waterplane + REAL(ReKi) :: l1 ! distance from cone end to bottom node + REAL(ReKi) :: Vs ! segment submerged volume + REAL(ReKi) :: a0 ! waterplane ellipse shape + REAL(ReKi) :: b0 + REAL(ReKi) :: cr ! centroid of segment submerged volume relative to its lower node + REAL(ReKi) :: cl + REAL(ReKi) :: cx + REAL(ReKi) :: cz + REAL(ReKi) :: pwr ! exponent for buoyancy node distribution smoothing + REAL(ReKi) :: alpha ! final load distribution factor for element + REAL(ReKi) :: Fb !buoyant force + REAL(ReKi) :: Fr !radial component of buoyant force + REAL(ReKi) :: Fl !axial component of buoyant force + REAL(ReKi) :: M !moment induced about the center of the cylinder's bottom face + REAL(ReKi) :: BuoyF(3) ! buoyancy force vector aligned with an element + REAL(ReKi) :: BuoyM(3) ! buoyancy moment vector aligned with an element + + + + + ! Initialize ErrStat ErrStat = ErrID_None @@ -4563,7 +3337,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! allocate their data storage at each time step! If we could make them static local variables (like in C) then we could avoid adding them to the OtherState datatype. ! The same is true for the lumped drag (L_F_D) and the lumped dynamic pressure (L_F_DP) - DO J = 1, y%DistribMesh%Nnodes + DO J = 1, y%Mesh%Nnodes ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers nodeIndx = p%distribToNodeIndx(J) @@ -4625,7 +3399,314 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, - ENDDO + ENDDO + + + + + !!! below from GenerateLumpedLoads - need to make sure nothing is forgotten <<<<<< + IF (.NOT. node%PropPot ) THEN + k = sgn * node%R_LToG(:,3) + CALL LumpDynPressure( nodeIndx, node%JAxCp, k, node%R, node%tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg) + + ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. + ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) + ! CALL LumpBuoyancy( sgn, densWater, node%R, node%tMG, node%JointPos(3) - MSL2SWL, node%R_LToG, gravity, F_B ) + ELSE + ALLOCATE ( F_DP(0:NStepWave, 6), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating distributed dynamic pressure loads array.' + ErrStat = ErrID_Fatal + RETURN + END IF + F_DP = 0.0 + F_B = 0.0 + END IF + CALL LumpDragConst( densWater, node%Cd, node%R, node%tMG, dragConst ) + + +<<<<< most of above likely not used anymore!!! + + + ! Clear saved loads on each node since these are accumulated + !@mhall: Faster way to do this? Is this list right? + DO i = 1, p%NNodes + DO J=1,6 + F_D (i,J) = 0.0 + F_I (i,J) = 0.0 + F_B (i,J) = 0.0 + F_FB (i,J) = 0.0 + F_FBI (i,J) = 0.0 + F_MG (i,J) = 0.0 + F_MGI (i,J) = 0.0 + F_AM (i,J) = 0.0 + F_AM_M (i,J) = 0.0 + F_AM_MG(i,J) = 0.0 + F_AM_F (i,J) = 0.0 + END DO + END DO + + + + + + ! ============================================================================================== + ! Calculate instantaneous loads on each member except for the hydrodynamic loads on member ends. + ! This covers aspects of the load calculations previously in CreateDistributedMesh. + + + ! Loop through each member + DO im = 1, p%NMembers + + N = m%Members(im)%NElements + + mem = m%Members(im) !@mhall: does this have much overhead? + + + ! calculate isntantaneous incline angle and heading, and related trig values + vec = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) - u%Mesh%TranslationDisp(:, mem%NodeIndx(1 )) + + phi = arccos(vec(3)/SQRT(Dot_Product(vec,vec))) ! incline angle + beta = arctan2(vec(2), vec(1)) ! heading of incline + + sinPhi = sin(phi) + cosPhi = cos(phi) + tanPhi = tan(phi) + + sinBeta = sin(beta) + cosBeta = cos(beta) + + + + + DO i =1,N ! loop through member elements + + ! save some commonly used variables + + dl = mem%dl + + z1 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i )) ! get node z locations from input mesh + z2 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i+1)) + r1 = m%Members(im)%RMG(i ) + r2 = m%Members(im)%RMG(i+1) + + m = mem%m_mg(i) + + ! should i_floor theshold be applied to below calculations to avoid wasting time on computing zero-valued things? <<<<< + ! should lumped half-element coefficients get combined at initialization? <<< + + ! ------------------ marine growth -------------------- + + ! lower node + m%F_MG(mem%NodeIndx(i ), 3) = m%F_MG(mem%NodeIndx(i ), 3) + mem%m_mg_l(i)*g ! weight force + m%F_MG(mem%NodeIndx(i ), 4) = m%F_MG(mem%NodeIndx(i ), 4) - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force + m%F_MG(mem%NodeIndx(i ), 5) = m%F_MG(mem%NodeIndx(i ), 5) + mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force + ! upper node + m%F_MG(mem%NodeIndx(i+1), 3) = m%F_MG(mem%NodeIndx(i+1), 3) + mem%m_mg_u(i)*g ! weight force + m%F_MG(mem%NodeIndx(i+1), 4) = m%F_MG(mem%NodeIndx(i+1), 4) - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force + m%F_MG(mem%NodeIndx(i+1), 5) = m%F_MG(mem%NodeIndx(i+1), 5) + mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force + + ! lower node + Imat = diag(mem%I_rmg_l(i), mem%I_rmg_l(i), mem%I_lmg_l(i)) + m%F_MGI(mem%NodeIndx(i ), 1:3) = m%F_MGI(mem%NodeIndx(i ), 1:3) - a_struct * mem%m_mg_l(i) + m%F_MGI(mem%NodeIndx(i ), 4:6) = m%F_MGI(mem%NodeIndx(i ), 4:6) - cross (a_struct * mem%m_mg_l(i), mem%h_cmg_l(i) * mem%k) + C * Imat * Ctrans + ! upper node + Imat = diag(mem%I_rmg_u(i), mem%I_rmg_u(i), mem%I_lmg_u(i)) + m%F_MGI(mem%NodeIndx(i+1), 1:3) = m%F_MGI(mem%NodeIndx(i+1), 1:3) - a_struct * mem%m_mg_u(i) + m%F_MGI(mem%NodeIndx(i+1), 4:6) = m%F_MGI(mem%NodeIndx(i+1), 4:6) - cross (a_struct * mem%m_mg_u(i), mem%h_cmg_u(i) * mem%k) + C * Imat * Ctrans + + + ! ------------------ flooded ballast inertia --------------------- + + ! lower node + Imat = diag(mem%I_rfb_l(i), mem%I_rfb_l(i), mem%I_lfb_l(i)) + m%F_FBI(mem%NodeIndx(i ), 1:3) = m%F_FBI(mem%NodeIndx(i ), 1:3) - a_struct * mem%m_fb_l(i) + m%F_FBI(mem%NodeIndx(i ), 4:6) = m%F_FBI(mem%NodeIndx(i ), 4:6) - cross (a_struct * mem%m_fb_l(i), mem%h_cfb_l(i) * mem%k) + C * Imat * Ctrans + ! upper node + Imat = diag(mem%I_rfb_u(i), mem%I_rfb_u(i), mem%I_lfb_u(i)) + m%F_FBI(mem%NodeIndx(i+1), 1:3) = m%F_FBI(mem%NodeIndx(i+1), 1:3) - a_struct * mem%m_fb_u(i) + m%F_FBI(mem%NodeIndx(i+1), 4:6) = m%F_FBI(mem%NodeIndx(i+1), 4:6) - cross (a_struct * mem%m_fb_u(i), mem%h_cfb_u(i) * mem%k) + C * Imat * Ctrans + + + ! ------------------ flooded ballast weight --------------------- + + ! fully filled elements + if (floodstatus(i) == 1) then + + ! forces and moment in tilted coordinates about node i + Fl = mem%Cfl_fb(i)*cosPhi + Fr = mem%Cfr_fb(i)*sinPhi + M = mem%CM0_fb(i)*sinPhi - Fr(i)*alpha_fb_star(i)*dl + + ! calculate full vector and distribute to nodes + DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, (1-mem%alpha_fb_star(i)), m%F_FB(mem%NodeIndx(i), :), m%F_FB(mem%NodeIndx(i+1), :)) + + + ! partially filled element + else if (floodstatus(i) == 2) then + + ! forces and moment in tilted coordinates about node i + Fl = mem%Cfl_fb(i)*cosPhi + Fr = mem%Cfr_fb(i)*sinPhi + M = mem%CM0_fb(i)*sinPhi + Fr(i)*(1 - alpha_fb_star(i))*dl + + ! calculate full vector and distribute to nodes + DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, mem%alpha_fb_star(i), m%F_FB(mem%NodeIndx(i), :), m%F_FB(mem%NodeIndx(i-1), :)) + + + ! no load for unflooded element or element fully below seabed + + end if + + + ! ------------------- buoyancy loads... ------------------------ + + if (z1 <= 0) then ! if segment is at least partially submerged ... + + + if (z1*z2 <= 0) then ! special calculation if the slice is partially submerged + + h0 = -z1/cosPhi ! distances along element centerline from point 1 to the waterplane + rh = r1 + h0*m ! radius of element at point where its centerline crosses the waterplane + + if (abs(m) < 0.0001) then ! untapered cylinder case + + Vs = Pi*r1*r1*h0 ! volume of total submerged portion + + cr = 0.25*r1*r1*tanPhi/h0 + cl = 0.5*h0 + 0.125*r1*r1*tanPhi*tanPhi/h0 + + cx = cr*cosPhi + cl*sinPhi + cz = cl*cosPhi - cr*sinPhi + + !alpha0 = 0.5*h0/dl ! force distribution between end nodes + + else ! inclined tapered cylinder case (note I've renamed r0 to rh here!!) + + l1 = r1/m ! distance from cone end to bottom node + + ! waterplane ellipse shape + b0 = rh/sqrt(1 - m^2 * tanPhi**2) + a0 = rh/((1 - m^2*tanPhi**2)*cosPhi) ! simplified from what's in ConicalCalcs.ipynb + + ! segment submerged volume + Vs = pi*(a0*b0*rh*cosPhi - l1^3*m^3)/(3*m) + + ! centroid of segment submerged volume (relative to bottom node) + cx = -0.25*(3*a0*b0*rh*rh*(m**2 + 1)*cosPhi + 3.0*l1**4*m**4*(m**2*tanPhi**2 - 1) + 4*l1*m*(m**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - 1.0*l1**3*m**3))*sin(phi)/(m*(m**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - l1**3*m**3)) + cz = 0.25*(-4.0*a0*b0*l1*m*rh*cosPhi + 3.0*a0*b0*rh*rh*cosPhi + 1.0*l1**4*m**4)*cosPhi/(m*(a0*b0*rh*cosPhi - l1**3*m**3)) + + !alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) ! this can be precomputed + + end if + + pwr = 1 + alpha = (1-mem%alpha(i))*z1**pwr/(-mem%alpha(i)*z2**pwr + (1-mem%alpha(i))*z1**pwr) + + Fb = Vs*rho*g !buoyant force + Fr = -Fb*sinPhi !radial component of buoyant force + Fl = Fb*cosPhi !axial component of buoyant force + M = -Fb*cx !moment induced about the center of the cylinder's bottom face + + ! calculate (imaginary) bottom plate forces/moment to subtract from displacement-based values + Fl = Fl + rho*g*z1* Pi *r1*r1 + M0 = M + rho*g* sinPhi * Pi/4*r1**4 + + + ! reduce taper-based moment to remove (not double count) radial force distribution to each node + M = M0 - Fr*alpha*dl + Fr*dl + + BuoyF(1) = Fr*cosBeta + BuoyF(2) = Fr*sinBeta + BuoyF(3) = Fl + BuoyM(1) = -M*sinBeta + BuoyM(2) = M*cosBeta + BuoyM(3) = 0 + + ! distribute force and moment to each adjacent node of the element BELOW THIS ONE + m%F_B(mem%NodeIndx(i-1), 1:3) = MatMul(C, BuoyF )*(1-alpha) + m%F_B(mem%NodeIndx(i-1), 4:6) = Matmul(C, BuoyMT)*(1-alpha) + + m%F_B(mem%NodeIndx(i ), 1:3) = MatMul(C, BuoyF )*alpha + m%F_B(mem%NodeIndx(i ), 4:6) = Matmul(C, BuoyMT)*alpha + + + else ! normal, fully submerged case + + Fl = -2.0*Pi*m*rho*g*dl*( z1*r1 + 0.5*(z1*m + r1*cosPhi)*dl + 1/3*m*cosPhi*dl*dl ) ! from CylinderCalculationsR1.ipynb + + Fr = -Pi*rho*g*dl*(r1*r1 + m*r1*dl + 1/3*m**2*dl**2)*sinPhi ! from CylinderCalculationsR1.ipynb + + M0 = -Pi*dl*g*rho*(3*dl**3*m**4 + 3*dl**3*m**2 + 12*dl**2*m**3*r1 + 8*dl**2*m*r1 + 18*dl*m**2*r1*r1 + 6*dl*r1*r1 + 12*m*r1**3)*sin(phi)/12 ! latest from CylinderCalculationsR1.ipynb + + ! precomputed as mem%alpha(i) ... alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) + + z1d = -min(0,z1) + z2d = -min(0,z2) + + alpha = mem%alpha(i)*z2d/(mem%alpha(i)*z2d+(1-mem%alpha(i))*z1d) + + + ! reduce moment to remove (not double count) radial force distribution to each node + M = M0 - Fr*alpha*dl + + BuoyF(1) = Fr*cosBeta + BuoyF(2) = Fr*sinBeta + BuoyF(3) = Fl + BuoyM(1) = -M*sinBeta + BuoyM(2) = M*cosBeta + BuoyM(3) = 0 + + ! distribute force and moment to each adjacent node + m%F_B(mem%NodeIndx(i ), 1:3) = MatMul(C, BuoyF)*(1-alpha) + m%F_B(mem%NodeIndx(i ), 4:6) = Matmul(C, BuoyM)*(1-alpha) + + m%F_B(mem%NodeIndx(i+1), 1:3) = MatMul(C, BuoyF)*alpha + m%F_B(mem%NodeIndx(i+1), 4:6) = Matmul(C, BuoyM)*alpha + + end if ! submergence cases + + end if ! element at least partially submerged + + END DO ! i =1,N ! loop through member elements + + + ! Any end plate loads that are modeled on a per-member basis + + ! reassign convenience variables to correspond to member ends + z1 = u%Mesh%TranslationDisp(3, m%Members(im)%NodeIndx(1 )) + z2 = u%Mesh%TranslationDisp(3, m%Members(im)%NodeIndx(N+1)) + + ! Water ballast buoyancy + if (z1 >= -wtrDpth) then ! end load only if end is above seabed + + ! if member is fully flooded + if (mem%z_overfill > 0) then + Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0)) + M = -mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi + AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB( 1,:)) + + Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0)) + M = mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi + AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB(N+1,:)) + + ! if member is partially flooded + else if (l_fill > 0) then + Fl = -mem%FillDens * g * pi *Rin(1)**2*l_fill*cosPhi + M = -mem%FillDens * g * pi *0.25*Rin(1)**4*sinPhi + AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB(1,:)) + + ! no load if member is not flooded at all + end if + ! no load if end is below seabed + end if + + ! --- no inertia loads from water ballast modeled on ends + + end do ! im - looping through members + + + !@mhall: hydrodynamic loads not yet implemented, below not yet adjusted ! NOTE: All wave kinematics have already been zeroed out above the SWL or instantaneous wave height (for WaveStMod > 0), so loads derived from the kinematics will be correct @@ -4722,6 +3803,60 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, END SUBROUTINE Morison_CalcOutput + +! Takes loads on node i in element tilted frame and converts to 6DOF loads at node i and adjacent node +SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, alpha, Fi, F2) + + REAL(ReKi), INTENT ( IN ) :: Fl ! (N) axial load about node i + REAL(ReKi), INTENT ( IN ) :: Fr ! (N) radial load about node i in direction of tilt + REAL(ReKi), INTENT ( IN ) :: M ! (N-m) radial moment about node i, positive in direction of tilt angle + REAL(ReKi), INTENT ( IN ) :: sinPhi ! trig functions of tilt angle + REAL(ReKi), INTENT ( IN ) :: cosPhi + REAL(ReKi), INTENT ( IN ) :: sinBeta ! trig functions of heading of tilt + REAL(ReKi), INTENT ( IN ) :: cosBeta + REAL(ReKi), INTENT ( IN ) :: alpha ! fraction of load staying with node i (1-alpha goes to other node) + + REAL(ReKi), INTENT ( OUT ) :: Fi(6) ! (N, Nm) force/moment vector for node i + REAL(ReKi), INTENT ( OUT ) :: F2(6) ! (N, Nm) force/moment vector for the other node (whether i+1, or i-1) + + + Fi(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + Fi(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + Fi(3) = (Fl*cosPhi + Fr*sinPhi)*alpha + Fi(4) = sinBeta * M *alpha + Fi(5) = cosBeta * M *alpha + Fi(6) = 0.0 + + Fi(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + Fi(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + Fi(3) = (Fl*cosPhi + Fr*sinPhi)*(1-alpha) + Fi(4) = sinBeta * M *(1-alpha) + Fi(5) = cosBeta * M *(1-alpha) + Fi(6) = 0.0 + +END SUBROUTINE DistributeElementLoads + + +! Takes loads on end node i and converts to 6DOF loads, adding to the nodes existing loads +SUBROUTINE AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, Fi) + + REAL(ReKi), INTENT ( IN ) :: Fl ! (N) axial load about node i + REAL(ReKi), INTENT ( IN ) :: M ! (N-m) radial moment about node i, positive in direction of tilt angle + REAL(ReKi), INTENT ( IN ) :: sinPhi ! trig functions of tilt angle + REAL(ReKi), INTENT ( IN ) :: cosPhi + REAL(ReKi), INTENT ( IN ) :: sinBeta ! trig functions of heading of tilt + REAL(ReKi), INTENT ( IN ) :: cosBeta + REAL(ReKi), INTENT ( INOUT ) :: Fi(6) ! (N, Nm) force/moment vector for end node i + + Fi(1) = Fi(1) + Fl*sinPhi*cosBeta + Fi(2) = Fi(2) + Fl*sinPhi*sinBeta + Fi(3) = Fi(3) + Fl*cosPhi + Fi(4) = Fi(4) + M*sinBeta + Fi(5) = Fi(5) - M*cosBeta + +END SUBROUTINE AddEndLoad + + !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for computing derivatives of continuous states SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 27fb926eb..2b403ae68 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -71,7 +71,7 @@ typedef ^ ^ ReKi typedef ^ ^ INTEGER JointOvrlp - - - "" - typedef ^ ^ INTEGER JointAxIDIndx - - - "" - typedef ^ ^ INTEGER NConnections - - - "Number of elements connecting to this node" - -typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the elements connected to this node" - +typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the members connected to this node (positive if end 1, negative if end 2)" - typedef ^ ^ INTEGER NConnectPreSplit - - - "In code, but unused: should be removed" - typedef ^ ^ ReKi Cd - - - "Nodal Cd" - typedef ^ ^ ReKi CdMG - - - "Nodal Cd with marine growth" - @@ -91,6 +91,8 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth (of member at node location)" m typedef ^ ^ ReKi dRdz - - - "Nodal rate of change in member radius with respect to member axial direction" typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 +typedef ^ ^ ReKi m_MG - - - "marine growth mass at a joint" kg +typedef ^ ^ ReKi I_MG {3}{3} - - "marine growth inertia matrix at a joint" kg-m^2 typedef ^ ^ ReKi FillFSLoc - - - "Nodal fill free surface location (of connected chamber to this node)" m typedef ^ ^ LOGICAL FillFlag - - - "Is this node filled? T/F" - typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 @@ -98,41 +100,59 @@ typedef ^ ^ INTEGER typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - typedef ^ ^ LOGICAL PropPot - - - "Is this node modeled with potential flow theory? T/F" - typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from node local to global coordinates" - -typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "Index of member's node 1 in the master node list" - -typedef ^ ^ INTEGER Node2Indx - - - "Index of member's node 2 in the master node list" - -typedef ^ ^ ReKi R1 - - - "Radius of node 1" m -typedef ^ ^ ReKi t1 - - - "Member thickness at node 1" m -typedef ^ ^ ReKi R2 - - - "Radius of node 2" m -typedef ^ ^ ReKi t2 - - - "Member thickness at node 2" m -typedef ^ ^ ReKi Cd1 - - - "Member Cd at node 1" - -typedef ^ ^ ReKi CdMG1 - - - "Member Cd at node 1 with marine growth" - -typedef ^ ^ ReKi Ca1 - - - "Member Ca at node 1" - -typedef ^ ^ ReKi CaMG1 - - - "Member Ca at node 1 with marine growth" - -typedef ^ ^ ReKi Cp1 - - - "Member Cp at node 1" - -typedef ^ ^ ReKi CpMG1 - - - "Member Cp at node 1 with marine growth" - -typedef ^ ^ ReKi AxCa1 - - - "Member axial Ca at node 1" - -typedef ^ ^ ReKi AxCaMG1 - - - "Member axial Ca at node 1 with marine growth" - -typedef ^ ^ ReKi AxCp1 - - - "Member axial Cp at node 1" - -typedef ^ ^ ReKi AxCpMG1 - - - "Member axial Cp at node 1 with marine growth" - -typedef ^ ^ ReKi Cd2 - - - "Member Cd at node 2" - -typedef ^ ^ ReKi CdMG2 - - - "Member Cd at node 2 with marine growth" - -typedef ^ ^ ReKi Ca2 - - - "Member Ca at node 2" - -typedef ^ ^ ReKi CaMG2 - - - "Member Ca at node 2 with marine growth" - -typedef ^ ^ ReKi Cp2 - - - "Member Cp at node 2" - -typedef ^ ^ ReKi CpMG2 - - - "Member Cp at node 2 with marine growth" - -typedef ^ ^ ReKi AxCa2 - - - "Member axial Ca at node 2" - -typedef ^ ^ ReKi AxCaMG2 - - - "Member axial Ca at node 2 with marine growth" - -typedef ^ ^ ReKi AxCp2 - - - "Member axial Cp at node 2" - -typedef ^ ^ ReKi AxCpMG2 - - - "Member axial Cp at node 2 with marine growth" - +typedef Morison/Morison Morison_MemberType INTEGER NodeIndx {:} - - "Index of each of the member's nodes in the master node list" - +typedef ^ ^ INTEGER NElements - - - "number of elements in this member" - +typedef ^ ^ ReKi Len - - - "the reference total length for this member" m +typedef ^ ^ ReKi dl - - - "the reference element length for this member (may be less than MDivSize to achieve uniform element lengths)" m +typedef ^ ^ ReKi k {3} - - "unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn)" m +typedef ^ ^ ReKi R {:} - - "outer member radius at each node" m +typedef ^ ^ ReKi RMG {:} - - "radius at each node including marine growth" m +typedef ^ ^ ReKi Rin {:} - - "inner member radius at node, equivalent to radius of water ballast at this node if filled" m +typedef ^ ^ ReKi m_mg {:} - - "taper dr/dl of outer surface including marine growth of each element" - +typedef ^ ^ ReKi m_in {:} - - "taper dr/dl of interior surface of each element" - +typedef ^ ^ ReKi l_fill - - - "fill length along member axis from start node 1" m +typedef ^ ^ ReKi h_fill - - - "fill length of partially flooded element" m +typedef ^ ^ ReKi z_overfill - - - "if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled." m +typedef ^ ^ ReKi h_floor - - - "the distance from the node to the seabed along the member axis (negative value)" m +typedef ^ ^ INTEGER i_floor - - - "the number of the element that pierces the seabed (zero if the member doesn't pierce it)" - +typedef ^ ^ INTEGER floodstatus {:} - - "flooded status for each element: 0 unflooded or fully below seabed, 1 fully flooded, 2 partially flooded" - +typedef ^ ^ ReKi alpha {:} - - "relative volume centroid of each element including marine growth, from node i to node i+1" - +typedef ^ ^ ReKi alpha_fb {:} - - "relative volume centroid of each element's flooded ballast, from node i to node i+1" - +typedef ^ ^ ReKi alpha_fb_star {:} - - "load distribution factor for each element after adjusting alpha_fb for node reference depths" - +typedef ^ ^ ReKi Cd {:} - - "Member Cd at each node" - +typedef ^ ^ ReKi CdMG {:} - - "Member Cd at each node with marine growth" - +typedef ^ ^ ReKi Ca {:} - - "Member Ca at each node" - +typedef ^ ^ ReKi CaMG {:} - - "Member Ca at each node with marine growth" - +typedef ^ ^ ReKi Cp {:} - - "Member Cp at each node" - +typedef ^ ^ ReKi CpMG {:} - - "Member Cp at each node with marine growth" - +typedef ^ ^ ReKi AxCa {:} - - "Member axial Ca at each node" - +typedef ^ ^ ReKi AxCaMG {:} - - "Member axial Ca at each node with marine growth" - +typedef ^ ^ ReKi AxCp {:} - - "Member axial Cp at each node" - +typedef ^ ^ ReKi AxCpMG {:} - - "Member axial Cp at each node with marine growth" - +typedef ^ ^ ReKi m_fb_l {:} - - "mass of flooded ballast in lower portion of each element" kg +typedef ^ ^ ReKi m_fb_u {:} - - "mass of flooded ballast in upper portion of each element" kg +typedef ^ ^ ReKi h_cfb_l {:} - - "distance to flooded ballast centroid from node point in lower portion of each element" m +typedef ^ ^ ReKi h_cfb_u {:} - - "distance to flooded ballast centroid from node point in upper portion of each element" m +typedef ^ ^ ReKi I_lfb_l {:} - - "axial moment of inertia of flooded ballast in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_lfb_u {:} - - "axial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi I_rfb_l {:} - - "radial moment of inertia of flooded ballast in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_rfb_u {:} - - "radial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi m_mg_l {:} - - "mass of marine growth in lower portion of each element" kg +typedef ^ ^ ReKi m_mg_u {:} - - "mass of marine growth in upper portion of each element" kg +typedef ^ ^ ReKi h_cmg_l {:} - - "distance to marine growth centroid from node point in lower portion of each element" m +typedef ^ ^ ReKi h_cmg_u {:} - - "distance to marine growth centroid from node point in upper portion of each element" m +typedef ^ ^ ReKi I_lmg_l {:} - - "axial moment of inertia of marine growth in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_lmg_u {:} - - "axial moment of inertia of marine growth in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi I_rmg_l {:} - - "radial moment of inertia of marine growth in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_rmg_u {:} - - "radial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi Cfl_fb {:} - - "axial force constant due to flooded ballast, for each element" N +typedef ^ ^ ReKi Cfr_fb {:} - - "radial force constant due to flooded ballast, for each element" N +typedef ^ ^ ReKi CM0_fb {:} - - "moment constant due to flooded ballast, for each element about lower node" Nm typedef ^ ^ ReKi InpMbrDist1 - - - "Normalized distance of node 1 from the user-specified corresponding member in the input file" - typedef ^ ^ ReKi InpMbrDist2 - - - "Normalized distance of node 2 from the user-specified corresponding member in the input file" - typedef ^ ^ ReKi InpMbrLen - - - "Length of the user-specified member this is a part of" - typedef ^ ^ INTEGER InpMbrIndx - - - "Index of the user-specified member this is a part of" - typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from member local to global coordinates" - -#typedef ^ ^ INTEGER MGSplitState - - - "Unused" - -#typedef ^ ^ INTEGER WtrSplitState - - - "Unused" - -typedef ^ ^ INTEGER NumSplits - - - "How many splits need to be created in the member/element" - -typedef ^ ^ ReKi Splits {5} - - "Locations of the splits in the Z coordinate" m typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - @@ -191,8 +211,8 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "Unused: For super member calculations" - typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - -typedef ^ ^ INTEGER NElements - - - "Number of elements in the discretized model" - -typedef ^ ^ Morison_MemberType Elements {:} - - "Array of elements which were derived from the user-specified members" - +typedef ^ ^ INTEGER NMembers - - - "Number of elements in the discretized model" - +typedef ^ ^ Morison_MemberType Members {:} - - "Array of elements which were derived from the user-specified members" - typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - @@ -270,25 +290,22 @@ typedef ^ OtherStateType IntKi # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi D_F_D {:}{:} - - "Distributed viscous drag loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - -typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_B was computed)" - -#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Unused: Distributed dynamic pressure loads" - -typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_B {:}{:} - - "" - -typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ MiscVarType ReKi F_D {:}{:} - - "Nodal viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_I {:}{:} - - "Nodal inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - +typedef ^ ^ ReKi F_B {:}{:} - - "Nodal bounancy loads" - +typedef ^ ^ ReKi F_FB {:}{:} - - "Nodal flooded ballast weight/buoyancy loads" - +typedef ^ ^ ReKi F_FBI {:}{:} - - "Nodal flooded ballast inertia loads" - +typedef ^ ^ ReKi F_MG {:}{:} - - "Nodal marine growth weight loads" - +typedef ^ ^ ReKi F_MGI {:}{:} - - "Nodal marine growth inertia loads" - +typedef ^ ^ ReKi F_AM {:}{:} - - "Nodal total added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_AM_M {:}{:} - - "Nodal member added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_AM_MG {:}{:} - - "Nodal marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_AM_F {:}{:} - - "Nodal added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ Morison_MemberType Members {:} - - "Array of Morison members used during simulation" - typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - # ..... Parameters ................................................................................................................ @@ -297,12 +314,13 @@ typedef ^ ^ INTEGER # typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 +typedef ^ ^ INTEGER NMembers - - - "number of members" - typedef ^ ^ INTEGER NNodes - - - "" - typedef ^ ^ Morison_NodeType Nodes {:} - - "" - typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - typedef ^ ^ ReKi D_dragConst {:} - - "" - -typedef ^ ^ ReKi L_An {:}{:} - - "" - +typedef ^ ^ ReKi L_An {:}{:} - - "directional area vector of each joint" m^2 typedef ^ ^ ReKi L_F_B {:}{:} - - "" - typedef ^ ^ ReKi L_F_I {:}{:}{:} - - "" - typedef ^ ^ ReKi L_F_DP {:}{:}{:} - - "" - @@ -345,12 +363,10 @@ typedef ^ ^ CHARACTER(1 # ..... Inputs .................................................................................................................... # Define inputs that are contained on the mesh here: # -typedef ^ InputType MeshType DistribMesh - - - "Distributed Loads Meshed input data" - -typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed input data" - +typedef ^ InputType MeshType Mesh - - - "Kinematics of each node input mesh" - # # # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: -typedef ^ OutputType MeshType DistribMesh - - - "Distributed Loads Meshed output data" - -typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed output data" - +typedef ^ OutputType MeshType Mesh - - - "Loads on each node output mesh" - typedef ^ ^ ReKi WriteOutput {:} - - "" - From 42095ced5659970e7eda780826e6b9f962151d06 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 11 Feb 2020 12:50:35 -0700 Subject: [PATCH 148/377] -Added PtfmRefztRot as InitInput for rotation of SS C matrix -Changed length of y and WriteOutput related arrays for NBody > 1 cases (and NBodMod=1) -Changed name of N Parameter to numStates --- modules/hydrodyn/src/SS_Excitation.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/SS_Excitation.txt b/modules/hydrodyn/src/SS_Excitation.txt index aca06ade3..6efd072bc 100644 --- a/modules/hydrodyn/src/SS_Excitation.txt +++ b/modules/hydrodyn/src/SS_Excitation.txt @@ -19,11 +19,12 @@ typedef SS_Excitation/SS_Exc InitInputType CHARACTER(1024) typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - typedef ^ ^ ReKi WaveDir - - - "Wave direction" rad typedef ^ ^ INTEGER NStepWave - - - "Number of timesteps in the WaveTime array" - +typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {7} - - "Header of the output" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {7} - - "Units of the output" - +typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {:} - - "Units of the output" - typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - @@ -54,7 +55,7 @@ typedef ^ ^ IntKi typedef ^ ^ ReKi A {:}{:} - - "A matrix" - typedef ^ ^ ReKi B {:} - - "B matrix" - typedef ^ ^ ReKi C {:}{:} - - "C matrix" - -typedef ^ ^ INTEGER N - - - "Number of states" - +typedef ^ ^ INTEGER numStates - - - "Number of states" - typedef ^ ^ DbKi Tc - - - "Time shift" s typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s @@ -65,8 +66,8 @@ typedef ^ InputType ReKi # ..... Outputs ............................ -typedef ^ OutputType ReKi y {6} - - "Force/Moments" - -typedef ^ ^ ReKi WriteOutput {7} - - "output Data" "kN" - +typedef ^ OutputType ReKi y {:} - - "Force/Moments" - +typedef ^ ^ ReKi WriteOutput {:} - - "output Data" "kN" - From 1ae63edcec245b7f0c5fb9c896af64990d897f31 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 08:14:56 -0700 Subject: [PATCH 149/377] Updated to phase shift Wave Elevations for NBodyMod=2 and using SS_Exctn --- modules/hydrodyn/src/WAMIT.f90 | 87 ++++++++++++++++++++++++---- modules/hydrodyn/src/WAMIT.txt | 4 +- modules/hydrodyn/src/WAMIT_Types.f90 | 4 +- 3 files changed, 81 insertions(+), 14 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 24d062b15..6b50e557e 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -154,6 +154,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init REAL(ReKi) :: TmpPer ! A temporary period read in from a WAMIT file (sec ) REAL(ReKi) :: TmpRe ! A temporary real value read in from a WAMIT file (- ) REAL(SiKi) :: TmpCoord(2) ! A temporary real array to hold the (Omega,WaveDir) pair for interpolation + COMPLEX(SiKi),ALLOCATABLE :: tmpComplexArr(:) ! A temporary array (0:NStepWave2-1) for FFT use. REAL(ReKi), ALLOCATABLE :: WAMITFreq (:) ! Frequency components as ordered in the WAMIT output files (rad/s ) REAL(ReKi), ALLOCATABLE :: WAMITPer (:) ! Period components as ordered in the WAMIT output files (sec ) REAL(ReKi), ALLOCATABLE :: WAMITWvDir(:) ! Wave direction components as ordered in the WAMIT output files (degrees) @@ -909,7 +910,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Initialize the variables associated with the incident wave: SELECT CASE ( InitInp%WaveMod ) ! Which incident wave kinematics model are we using? - CASE ( 0 ) + CASE ( 0 ) ! No waves if ( p%ExctnMod == 1 ) then ! Initialize everything to zero: @@ -928,10 +929,15 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init SS_Exctn_InitInp%InputFile = InitInp%WAMITFile SS_Exctn_InitInp%WaveDir = InitInp%WaveDir SS_Exctn_InitInp%NStepWave = p%NStepWave + SS_Exctn_InitInp%NBody = InitInp%NBody + SS_Exctn_InitInp%PtfmRefztRot = InitInp%PtfmRefztRot + ! No other modules need this WaveElev0 array so we will simply move the allocation over to the SS_Exctn module IF (ALLOCATED(InitInp%WaveElev0)) CALL MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) +!TODO: Verify what happens within SS_Exctn when we have no waves. + ! We need the WaveTime array to stay intact for use in other modules, so we will make a copy instead of moving the allocation ALLOCATE ( SS_Exctn_InitInp%WaveTime (0:InitInp%NStepWave) , STAT=ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN @@ -1152,18 +1158,79 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init SS_Exctn_InitInp%WaveDir = InitInp%WaveDir SS_Exctn_InitInp%NStepWave = p%NStepWave SS_Exctn_InitInp%NBody = InitInp%NBody + SS_Exctn_InitInp%PtfmRefztRot = InitInp%PtfmRefztRot + + + + if (allocated(InitInp%WaveElev0)) then + ! No other modules need this WaveElev0 array so we will simply move the allocation over to the SS_Exctn module - IF (ALLOCATED(InitInp%WaveElev0)) CALL MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) + call MOVE_ALLOC(InitInp%WaveElev0, SS_Exctn_InitInp%WaveElev0) - ! We need the WaveTime array to stay intact for use in other modules, so we will make a copy instead of moving the allocation - ALLOCATE ( SS_Exctn_InitInp%WaveTime (0:InitInp%NStepWave) , STAT=ErrStat2 ) - IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the SS_Exctn_InitInp%WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') - CALL Cleanup() - RETURN - END IF - SS_Exctn_InitInp%WaveTime = InitInp%WaveTime + + ! Handle special case when NBodyMod=2 and (PtfmRefxt /= 0 or PtfmRefyt /= 0) : Need to phase shift the wave elevation data for the offset body + if ( p%NBodyMod==2 .and. (InitInp%PtfmRefxt(1) /= 0 .or. InitInp%PtfmRefyt(1) /= 0) ) then + + ! Need to start with the DFT of the Wave Elevation data at the Platform reference point: InitInp%WaveElevC0 + + ! Now apply the phase shift in the frequency space + + do J = 1, NInpWvDir + do I = 0,InitInp%NStepWave2 ! Loop through the positive frequency components (including zero) of the discrete Fourier transform + + ! Compute the frequency of this component: + + Omega = I*InitInp%WaveDOmega + ! Fxy = exp(-j * k(w) * ( X*cos(Beta(w)) + Y*sin(Beta(w)) ) + WaveNmbr = WaveNumber ( Omega, InitInp%Gravity, InitInp%WtrDpth ) + tmpAngle = WaveNmbr * ( InitInp%PtfmRefxt(1)*cos(HdroWvDir(J)*D2R) + InitInp%PtfmRefyt(1)*sin(HdroWvDir(J)*D2R) ) + TmpRe = cos(tmpAngle) + TmpIm = -sin(tmpAngle) + Fxy = CMPLX( TmpRe, TmpIm ) + + tmpComplexArr(I) = Fxy*CMPLX(InitInp%WaveElevC0(1,I), InitInp%WaveElevC0(2,I)) + + + end do + end do + + ! Compute the inverse discrete Fourier transforms to find the time-domain + ! representations of the wave kinematics without stretcing: + + CALL InitFFT ( InitInp%NStepWave, FFT_Data, .TRUE., ErrStat2 ) + CALL SetErrStat(ErrStat2,'Error occured while initializing the FFT.',ErrStat,ErrMsg,'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + ! We'll need the following for wave stretching once we implement it. + CALL ApplyFFT_cx ( SS_Exctn_InitInp%WaveElev0(0:InitInp%NStepWave-1), tmpComplexArr(: ), FFT_Data, ErrStat2 ) + CALL SetErrStat(ErrStat2,'Error occured while applying the FFT to WaveElev0.',ErrStat,ErrMsg,'WAMIT_Init') + IF ( ErrStat >= AbortErrLev ) THEN + CALL CleanUp() + RETURN + END IF + + CALL ExitFFT(FFT_Data, ErrStat2) + CALL SetErrStat( ErrStat2, 'Error in call to ExitFFT.', ErrStat, ErrMsg, 'WAMIT_Init') + IF ( ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + + end if + ! We need the WaveTime array to stay intact for use in other modules, so we will make a copy instead of moving the allocation + ALLOCATE ( SS_Exctn_InitInp%WaveTime (0:InitInp%NStepWave) , STAT=ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating memory for the SS_Exctn_InitInp%WaveTime array.', ErrStat, ErrMsg, 'WAMIT_Init') + CALL Cleanup() + RETURN + END IF + SS_Exctn_InitInp%WaveTime = InitInp%WaveTime + + end if call SS_Exc_Init(SS_Exctn_InitInp, m%SS_Exctn_u, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, & m%SS_Exctn_y, m%SS_Exctn, Interval_Sub, SS_Exctn_InitOut, ErrStat2, ErrMsg2) diff --git a/modules/hydrodyn/src/WAMIT.txt b/modules/hydrodyn/src/WAMIT.txt index e141365ec..acbedb1d0 100644 --- a/modules/hydrodyn/src/WAMIT.txt +++ b/modules/hydrodyn/src/WAMIT.txt @@ -25,8 +25,8 @@ typedef ^ ^ SiKi typedef ^ ^ ReKi PtfmVol0 {:} - - "" - typedef ^ ^ LOGICAL HasWAMIT - - - ".TRUE. if using WAMIT model, .FALSE. otherwise" - typedef ^ ^ ReKi WAMITULEN - - - "" - -typedef ^ ^ ReKi PtfmRefxt {:} - - "The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) -typedef ^ ^ ReKi PtfmRefyt {:} - - "The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) +typedef ^ ^ ReKi PtfmRefxt {:} - - "The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ]" (m) +typedef ^ ^ ReKi PtfmRefyt {:} - - "The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ]" (m) typedef ^ ^ ReKi PtfmRefzt {:} - - "The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ]" (m) typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians typedef ^ ^ ReKi PtfmCOBxt {:} - - "" - diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index 3f41d1a22..630ae52ce 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -47,8 +47,8 @@ MODULE WAMIT_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmVol0 !< [-] LOGICAL :: HasWAMIT !< .TRUE. if using WAMIT model, .FALSE. otherwise [-] REAL(ReKi) :: WAMITULEN !< [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefxt !< The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefyt !< The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefxt !< The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefyt !< The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefzt !< The zt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1; must be 0.0 if NBodyMod=2 ] [(m)] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmCOBxt !< [-] From 314c451a6953d65dba9ed60d545163a381962509 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 08:17:16 -0700 Subject: [PATCH 150/377] Augmented for NBody>1 and body rotation --- modules/hydrodyn/src/SS_Excitation.f90 | 113 +++-- modules/hydrodyn/src/SS_Excitation_Types.f90 | 423 +++++++++++++++++-- 2 files changed, 464 insertions(+), 72 deletions(-) diff --git a/modules/hydrodyn/src/SS_Excitation.f90 b/modules/hydrodyn/src/SS_Excitation.f90 index 0610f7d62..55d38d838 100644 --- a/modules/hydrodyn/src/SS_Excitation.f90 +++ b/modules/hydrodyn/src/SS_Excitation.f90 @@ -46,6 +46,38 @@ MODULE SS_Excitation CONTAINS + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine transforms the State Space input file data from a local (heading-angle, based) coordinate system to the global system. +!> NOTE: This routine ONLY works if all the DOFs are enabled!!!!!!!!!! +subroutine TransformStateSpaceMatrices( NBody, RotZ, C ) +!.................................................................................................................................. + integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) + real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) + real(SiKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + + integer(IntKi) :: i,j,indx + real(R8Ki) :: R(3,3) + real(R8Ki) :: Rt(3,3) + + do i = 1, NBody + if ( .not. EqualRealNos(RotZ(i), 0.0_R8Ki) ) then + R(1,:) = (/ cos(RotZ(i)), sin(RotZ(i)), 0.0_R8Ki/) + R(2,:) = (/-sin(RotZ(i)), cos(RotZ(i)), 0.0_R8Ki/) + R(3,:) = (/ 0.0_R8Ki , 0.0_R8Ki , 1.0_R8Ki/) + Rt = transpose(R) + + do j = 1,2 ! Need to do this twice, since a single R (3x3) matrix is used to transform all 6 DOFs associated with the ith Body data + indx = (i-1)*6 + (j-1)*3 + 1 + + ! Create sub matrix which is all columns of C but only necessary rows for transformation work, NOTE: c is (6*NBody) X numStates + C(indx:indx+2,:) = matmul( Rt, C(indx:indx+2,:) ) + end do + end if + end do + +end subroutine TransformStateSpaceMatrices + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -76,12 +108,9 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Local Variables: INTEGER :: I ! Generic index -! INTEGER :: J ! Generic index - INTEGER :: xx (1,6) ! Active DOF's on the input file .ss INTEGER :: Nlines ! Number of lines in the input file, used to determine N INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. INTEGER :: Sttus ! Error in reading .ssexctn file - !CHARACTER :: Line ! Temp line of file real(ReKi) :: WaveDir ! Temp wave direction angle (deg) integer :: ErrStat2 character(1024) :: ErrMsg2 @@ -93,8 +122,9 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini u%DummyInput = 0.0_ReKi UnSS = -1 - p%N = 0 - + p%numStates = 0 + p%NBody = InitInp%NBody ! Number of WAMIT bodies: =1 if WAMIT is using NBodyMod > 1, >=1 if NBodyMod=1 + ! Open the .ss input file! CALL GetNewUnit( UnSS ) CALL OpenFInpFile ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', ErrStat2, ErrMsg2 ) ! Open file. @@ -119,10 +149,10 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%Tc, 'p%Tc', 'Time offset (s)',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') - CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%N, 'p%N', 'Number of states',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states + CALL ReadVar( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%numStates, 'p%numStates', 'Number of states',ErrStat2, ErrMsg2) ! Reads in the third line, containing the number of states CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') - CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%spDOF, 6, 'p%spDOF', 'States per DOF',ErrStat2, ErrMsg2) + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%spDOF, 6*p%NBody, 'p%spDOF', 'States per DOF',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') IF (ErrStat >= AbortErrLev) THEN @@ -139,11 +169,10 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini END IF END DO - ! The input file contains the matrices A [NxN], B [Nx1] and C [6xN], so - !p%N = ( Nlines - 1 ) / 2 ! this is the number of states + ! The input file contains the matrices A [NxN], B [Nx1] and C [6*NBodyxN], so !Verifications on the input file - IF ( ( Nlines - 6 ) / 2 /= p%N) THEN + IF ( ( Nlines - 6*p%NBody ) / 2 /= p%numStates) THEN CALL SetErrStat(ErrID_Severe,'Error in the input file .ssexctn: The size of the matrices does not correspond to the number of states!',ErrStat,ErrMsg,'SS_Exc_Init') END IF @@ -155,9 +184,9 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Now we can allocate the temporary matrices A, B and C - CALL AllocAry( p%A, p%N, p%N, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') - CALL AllocAry( p%B, p%N, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') - CALL AllocAry( p%C, 6, p%N, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( p%A, p%numStates, p%numStates, 'p%A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( p%B, p%numStates, 'p%B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( p%C, 6*p%NBody, p%numStates, 'p%C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() @@ -174,25 +203,27 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Number of Excitation States', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) CALL ReadCom ( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', 'Number of states per dofs', ErrStat2, ErrMsg2 )! Reads the first entire line (Title header) - DO I = 1,p%N !Read A MatriX - CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%A(I,:), p%N, 'p%A', 'A_Matrix',ErrStat2, ErrMsg2) + DO I = 1,p%numStates !Read A MatriX + CALL ReadAry( UnSS,TRIM(InitInp%InputFile)//'.ssexctn', p%A(I,:), p%numStates, 'p%A', 'A_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') END DO - DO I = 1,p%N !Read B Matrix + DO I = 1,p%numStates !Read B Matrix CALL ReadVar( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', p%B(I), 'p%B', 'B_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') END DO - DO I = 1,6 !Read C Matrix - CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', p%C(I,:), p%N, 'p%C', 'C_Matrix',ErrStat2, ErrMsg2) + DO I = 1,6*p%NBody !Read C Matrix + CALL ReadAry( UnSS, TRIM(InitInp%InputFile)//'.ssexctn', p%C(I,:), p%numStates, 'p%C', 'C_Matrix',ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') END DO - CLOSE ( UnSS ) !Close .ss input file - UnSS = -1 ! Indicate the file is closed + CLOSE ( UnSS ) !Close .ss input file + UnSS = -1 ! Indicate the file is closed - - CALL WrScr1 ( 'Using SS_Excitation Module, with '//TRIM( Num2LStr(p%N ))//' excitation states' ) + ! Transform the SS c matriX using the heading angles + call TransformStateSpaceMatrices( p%NBody, InitInp%PtfmRefztRot, p%C ) + + CALL WrScr1 ( 'Using SS_Excitation Module, with '//TRIM( Num2LStr(p%numStates ))//' excitation states' ) ! Define parameters here: @@ -207,11 +238,13 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini CALL CleanUp() RETURN END IF - p%WaveTime = InitInp%WaveTime + + p%WaveTime = InitInp%WaveTime p%WaveElev0 = InitInp%WaveElev0 - + + ! Define initial system states here: - CALL AllocAry( x%x, p%N, 'x%x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + CALL AllocAry( x%x, p%numStates, 'x%x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() RETURN @@ -231,19 +264,22 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! misc vars: - ! Inputs - ! no inputs + ! Inputs + ! no inputs - ! Define system output initializations (set up mesh) here: - - y%y = 0 - y%WriteOutput = 0 + ! Define system output initializations (set up mesh) here: + call AllocAry( y%y, p%NBody*6+1, 'y%y', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + y%y = 0 + y%WriteOutput = 0 - ! Define initialization-routine output here: - - InitOut%WriteOutputHdr = (/ 'Time', 'FX ' , 'FY ' , 'FZ ' , 'MX ' , 'MY ' , 'MZ ' /) - InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + ! Define initialization-routine output here: + ! For OpenFAST, these outputs are attached (via HydroDyn) to the Radiation Force/Moment channels within HydroDyn + call AllocAry( InitOut%WriteOutputHdr, 6*p%NBody+1, 'InitOut%WriteOutputHdr', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + call AllocAry( InitOut%WriteOutputUnt, 6*p%NBody+1, 'InitOut%WriteOutputUnt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + !TODO: Create actual NBody ouput headers + !InitOut%WriteOutputHdr = (/ 'Time', 'FX ' , 'FY ' , 'FZ ' , 'MX ' , 'MY ' , 'MZ ' /) + !InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) CALL CleanUp() ! deallocate local arrays @@ -377,8 +413,7 @@ SUBROUTINE SS_Exc_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, E TYPE(SS_Exc_MiscVarType), INTENT(INOUT) :: m !< Initial misc/optimization variables INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None -! REAL(DbKi) :: test(6,1) - + ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -391,7 +426,7 @@ SUBROUTINE SS_Exc_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, E ! Compute outputs here: y%WriteOutput(1) = REAL(Time,ReKi) - y%WriteOutput(2:7) = y%y + y%WriteOutput(2:6*p%NBody+1) = y%y END SUBROUTINE SS_Exc_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- @@ -417,7 +452,7 @@ SUBROUTINE SS_Exc_CalcContStateDeriv( Time, waveElev0, p, x, xd, z, OtherState, ErrMsg = "" - CALL AllocAry( dxdt%x, p%N, 'SS_Exc_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) + CALL AllocAry( dxdt%x, p%numStates, 'SS_Exc_CalcContStateDeriv:dxdt%x', ErrStat, ErrMsg) IF ( ErrStat >= AbortErrLev) RETURN ! Compute the first time derivatives of the continuous states here: diff --git a/modules/hydrodyn/src/SS_Excitation_Types.f90 b/modules/hydrodyn/src/SS_Excitation_Types.f90 index b58afc6fc..9bf1a2d95 100644 --- a/modules/hydrodyn/src/SS_Excitation_Types.f90 +++ b/modules/hydrodyn/src/SS_Excitation_Types.f90 @@ -36,16 +36,20 @@ MODULE SS_Excitation_Types ! ========= SS_Exc_InitInputType ======= TYPE, PUBLIC :: SS_Exc_InitInputType CHARACTER(1024) :: InputFile !< Name of the input file [-] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] REAL(ReKi) :: WaveDir !< Wave direction [rad] INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefxt !< The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefyt !< The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] END TYPE SS_Exc_InitInputType ! ======================= ! ========= SS_Exc_InitOutputType ======= TYPE, PUBLIC :: SS_Exc_InitOutputType - CHARACTER(10) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] - CHARACTER(10) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Header of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output [-] END TYPE SS_Exc_InitOutputType ! ======================= ! ========= SS_Exc_ContinuousStateType ======= @@ -77,12 +81,13 @@ MODULE SS_Excitation_Types ! ========= SS_Exc_ParameterType ======= TYPE, PUBLIC :: SS_Exc_ParameterType REAL(DbKi) :: DT !< Time step [s] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] INTEGER(IntKi) , DIMENSION(1:6) :: spDOF !< States per DOF [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: N !< Number of states [-] + INTEGER(IntKi) :: numStates !< Number of states [-] REAL(DbKi) :: Tc !< Time shift [s] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] @@ -95,8 +100,8 @@ MODULE SS_Excitation_Types ! ======================= ! ========= SS_Exc_OutputType ======= TYPE, PUBLIC :: SS_Exc_OutputType - REAL(ReKi) , DIMENSION(1:6) :: y !< Force/Moments [-] - REAL(ReKi) , DIMENSION(1:7) :: WriteOutput !< output Data [kN] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: y !< Force/Moments [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< output Data [kN] END TYPE SS_Exc_OutputType ! ======================= CONTAINS @@ -117,8 +122,45 @@ SUBROUTINE SS_Exc_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E ErrStat = ErrID_None ErrMsg = "" DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%NBody = SrcInitInputData%NBody DstInitInputData%WaveDir = SrcInitInputData%WaveDir DstInitInputData%NStepWave = SrcInitInputData%NStepWave +IF (ALLOCATED(SrcInitInputData%PtfmRefxt)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefxt,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefxt,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefxt)) THEN + ALLOCATE(DstInitInputData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefxt = SrcInitInputData%PtfmRefxt +ENDIF +IF (ALLOCATED(SrcInitInputData%PtfmRefyt)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefyt,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefyt,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefyt)) THEN + ALLOCATE(DstInitInputData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefyt = SrcInitInputData%PtfmRefyt +ENDIF +IF (ALLOCATED(SrcInitInputData%PtfmRefztRot)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefztRot,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefztRot,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefztRot)) THEN + ALLOCATE(DstInitInputData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefztRot = SrcInitInputData%PtfmRefztRot +ENDIF IF (ALLOCATED(SrcInitInputData%WaveElev0)) THEN i1_l = LBOUND(SrcInitInputData%WaveElev0,1) i1_u = UBOUND(SrcInitInputData%WaveElev0,1) @@ -154,6 +196,15 @@ SUBROUTINE SS_Exc_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitInputData%PtfmRefxt)) THEN + DEALLOCATE(InitInputData%PtfmRefxt) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefyt)) THEN + DEALLOCATE(InitInputData%PtfmRefyt) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefztRot)) THEN + DEALLOCATE(InitInputData%PtfmRefztRot) +ENDIF IF (ALLOCATED(InitInputData%WaveElev0)) THEN DEALLOCATE(InitInputData%WaveElev0) ENDIF @@ -198,8 +249,24 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1*LEN(InData%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! NBody Re_BufSz = Re_BufSz + 1 ! WaveDir Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! PtfmRefxt allocated yes/no + IF ( ALLOCATED(InData%PtfmRefxt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefxt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefxt) ! PtfmRefxt + END IF + Int_BufSz = Int_BufSz + 1 ! PtfmRefyt allocated yes/no + IF ( ALLOCATED(InData%PtfmRefyt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefyt upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefyt) ! PtfmRefyt + END IF + Int_BufSz = Int_BufSz + 1 ! PtfmRefztRot allocated yes/no + IF ( ALLOCATED(InData%PtfmRefztRot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefztRot upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PtfmRefztRot) ! PtfmRefztRot + END IF Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no IF ( ALLOCATED(InData%WaveElev0) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension @@ -241,10 +308,51 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WaveDir Re_Xferred = Re_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NStepWave Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefxt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefxt))-1 ) = PACK(InData%PtfmRefxt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefxt) + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefyt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefyt))-1 ) = PACK(InData%PtfmRefyt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefyt) + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefztRot)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%PtfmRefztRot))-1 ) = PACK(InData%PtfmRefztRot,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%PtfmRefztRot) + END IF IF ( .NOT. ALLOCATED(InData%WaveElev0) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -311,10 +419,81 @@ SUBROUTINE SS_Exc_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 OutData%WaveDir = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%NStepWave = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) + ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefxt)>0) OutData%PtfmRefxt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefxt))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefxt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) + ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefyt)>0) OutData%PtfmRefyt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefyt))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefyt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefztRot)>0) OutData%PtfmRefztRot = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%PtfmRefztRot))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%PtfmRefztRot) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -378,8 +557,30 @@ SUBROUTINE SS_Exc_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF END SUBROUTINE SS_Exc_CopyInitOutput SUBROUTINE SS_Exc_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -391,6 +592,12 @@ SUBROUTINE SS_Exc_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF END SUBROUTINE SS_Exc_DestroyInitOutput SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -428,8 +635,16 @@ SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -457,18 +672,40 @@ SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) DO I = 1, LEN(InData%WriteOutputHdr) IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) DO I = 1, LEN(InData%WriteOutputUnt) IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I END DO !i1 + END IF END SUBROUTINE SS_Exc_PackInitOutput SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -504,8 +741,19 @@ SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%WriteOutputHdr,1) - i1_u = UBOUND(OutData%WriteOutputHdr,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) @@ -519,8 +767,20 @@ SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END DO ! I END DO !i1 DEALLOCATE(mask1) - i1_l = LBOUND(OutData%WriteOutputUnt,1) - i1_u = UBOUND(OutData%WriteOutputUnt,1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) @@ -534,6 +794,7 @@ SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END DO ! I END DO !i1 DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Exc_UnPackInitOutput SUBROUTINE SS_Exc_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -1364,6 +1625,7 @@ SUBROUTINE SS_Exc_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM ErrStat = ErrID_None ErrMsg = "" DstParamData%DT = SrcParamData%DT + DstParamData%NBody = SrcParamData%NBody DstParamData%NStepWave = SrcParamData%NStepWave DstParamData%spDOF = SrcParamData%spDOF IF (ALLOCATED(SrcParamData%A)) THEN @@ -1406,7 +1668,7 @@ SUBROUTINE SS_Exc_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM END IF DstParamData%C = SrcParamData%C ENDIF - DstParamData%N = SrcParamData%N + DstParamData%numStates = SrcParamData%numStates DstParamData%Tc = SrcParamData%Tc IF (ALLOCATED(SrcParamData%WaveElev0)) THEN i1_l = LBOUND(SrcParamData%WaveElev0,1) @@ -1496,6 +1758,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_BufSz = 0 Int_BufSz = 0 Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NBody Int_BufSz = Int_BufSz + 1 ! NStepWave Int_BufSz = Int_BufSz + SIZE(InData%spDOF) ! spDOF Int_BufSz = Int_BufSz + 1 ! A allocated yes/no @@ -1513,7 +1776,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C) ! C END IF - Int_BufSz = Int_BufSz + 1 ! N + Int_BufSz = Int_BufSz + 1 ! numStates Db_BufSz = Db_BufSz + 1 ! Tc Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no IF ( ALLOCATED(InData%WaveElev0) ) THEN @@ -1554,6 +1817,8 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NStepWave Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%spDOF))-1 ) = PACK(InData%spDOF,.TRUE.) @@ -1603,7 +1868,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IF (SIZE(InData%C)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C))-1 ) = PACK(InData%C,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%C) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%N + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%numStates Int_Xferred = Int_Xferred + 1 DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%Tc Db_Xferred = Db_Xferred + 1 @@ -1671,6 +1936,8 @@ SUBROUTINE SS_Exc_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Int_Xferred = 1 OutData%DT = DbKiBuf( Db_Xferred ) Db_Xferred = Db_Xferred + 1 + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 OutData%NStepWave = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%spDOF,1) @@ -1759,7 +2026,7 @@ SUBROUTINE SS_Exc_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = Re_Xferred + SIZE(OutData%C) DEALLOCATE(mask2) END IF - OutData%N = IntKiBuf( Int_Xferred ) + OutData%numStates = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%Tc = DbKiBuf( Db_Xferred ) Db_Xferred = Db_Xferred + 1 @@ -1957,8 +2224,30 @@ SUBROUTINE SS_Exc_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, E ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcOutputData%y)) THEN + i1_l = LBOUND(SrcOutputData%y,1) + i1_u = UBOUND(SrcOutputData%y,1) + IF (.NOT. ALLOCATED(DstOutputData%y)) THEN + ALLOCATE(DstOutputData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%y = SrcOutputData%y +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF END SUBROUTINE SS_Exc_CopyOutput SUBROUTINE SS_Exc_DestroyOutput( OutputData, ErrStat, ErrMsg ) @@ -1970,6 +2259,12 @@ SUBROUTINE SS_Exc_DestroyOutput( OutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(OutputData%y)) THEN + DEALLOCATE(OutputData%y) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF END SUBROUTINE SS_Exc_DestroyOutput SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -2007,8 +2302,16 @@ SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ALLOCATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2036,10 +2339,32 @@ SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%y))-1 ) = PACK(InData%y,.TRUE.) + IF ( .NOT. ALLOCATED(InData%y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%y)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%y))-1 ) = PACK(InData%y,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%y) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) + END IF END SUBROUTINE SS_Exc_PackOutput SUBROUTINE SS_Exc_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2075,28 +2400,52 @@ SUBROUTINE SS_Exc_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%y,1) - i1_u = UBOUND(OutData%y,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%y = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%y))-1 ), mask1, 0.0_ReKi ) + IF (SIZE(OutData%y)>0) OutData%y = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%y))-1 ), mask1, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%y) DEALLOCATE(mask1) - i1_l = LBOUND(OutData%WriteOutput,1) - i1_u = UBOUND(OutData%WriteOutput,1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) + IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Exc_UnPackOutput @@ -2116,7 +2465,7 @@ SUBROUTINE SS_Exc_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Exc_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2163,8 +2512,8 @@ SUBROUTINE SS_Exc_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(SS_Exc_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(SS_Exc_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2209,9 +2558,9 @@ SUBROUTINE SS_Exc_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Exc_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(SS_Exc_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(SS_Exc_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(SS_Exc_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(SS_Exc_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2266,7 +2615,7 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Exc_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2313,8 +2662,8 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(SS_Exc_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(SS_Exc_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2342,18 +2691,22 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN ALLOCATE(b1(SIZE(y_out%y,1))) ALLOCATE(c1(SIZE(y_out%y,1))) b1 = -(y1%y - y2%y)/t(2) y_out%y = y1%y + b1 * t_out DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) y_out%WriteOutput = y1%WriteOutput + b1 * t_out DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Exc_Output_ExtrapInterp1 @@ -2371,9 +2724,9 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Exc_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(SS_Exc_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(SS_Exc_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(SS_Exc_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2408,6 +2761,7 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN ALLOCATE(b1(SIZE(y_out%y,1))) ALLOCATE(c1(SIZE(y_out%y,1))) b1 = (t(3)**2*(y1%y - y2%y) + t(2)**2*(-y1%y + y3%y))/(t(2)*t(3)*(t(2) - t(3))) @@ -2415,6 +2769,8 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, y_out%y = y1%y + b1 * t_out + c1 * t_out**2 DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) @@ -2422,6 +2778,7 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Exc_Output_ExtrapInterp2 END MODULE SS_Excitation_Types From 2b16387f7ea29a1aad203e1bd761dfd1db6a941f Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 08:18:29 -0700 Subject: [PATCH 151/377] Bug fixes for changes in var name numDOFs --- modules/hydrodyn/src/SS_Radiation.f90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/SS_Radiation.f90 b/modules/hydrodyn/src/SS_Radiation.f90 index 0404d61e8..046651219 100644 --- a/modules/hydrodyn/src/SS_Radiation.f90 +++ b/modules/hydrodyn/src/SS_Radiation.f90 @@ -82,7 +82,7 @@ subroutine TransformStateSpaceMatrices( NBody, RotZ, B, C ) end do ! end do -end subroutine TransformWAMITMatrices +end subroutine TransformStateSpaceMatrices !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. @@ -121,7 +121,7 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini INTEGER, allocatable :: xx (:) ! Active DOF's on the input file .ss INTEGER :: numDOFs ! Number of DOFS INTEGER :: numStates ! Number of states - int(IntKi) :: N ! Counter + integer(IntKi) :: N ! Counter INTEGER :: Nlines ! Number of lines in the input file, used to determine N INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. INTEGER :: Sttus ! Error in reading .ss file @@ -195,7 +195,7 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini END IF END DO - DOFs = SUM (xx) !Number of DOFS in the input file + numDOFs = SUM (xx) !Number of DOFS in the input file IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() @@ -205,8 +205,8 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Now we can allocate the temporary matrices A, B and C CALL AllocAry( Rad_A, numStates, numStates, 'Rad_A', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( Rad_B, numStates, DOFs, 'Rad_B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - CALL AllocAry( Rad_C, DOFs, numStates, 'Rad_C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_B, numStates, numDOFs, 'Rad_B', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + CALL AllocAry( Rad_C, numDOFs, numStates, 'Rad_C', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() From 4919c83e5acd59a512901d5254df5acc34cb5232 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 08:20:05 -0700 Subject: [PATCH 152/377] Replaced N with numStates --- modules/hydrodyn/src/Conv_Radiation_Types.f90 | 24 +- modules/hydrodyn/src/Current_Types.f90 | 24 +- modules/hydrodyn/src/HydroDyn.f90 | 52 +- modules/hydrodyn/src/SS_Radiation_Types.f90 | 486 +++++++++++++++--- modules/hydrodyn/src/Waves2_Types.f90 | 24 +- modules/hydrodyn/src/Waves_Types.f90 | 24 +- 6 files changed, 501 insertions(+), 133 deletions(-) diff --git a/modules/hydrodyn/src/Conv_Radiation_Types.f90 b/modules/hydrodyn/src/Conv_Radiation_Types.f90 index b27b4d4e1..98a9b9f1b 100644 --- a/modules/hydrodyn/src/Conv_Radiation_Types.f90 +++ b/modules/hydrodyn/src/Conv_Radiation_Types.f90 @@ -1957,7 +1957,7 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2004,8 +2004,8 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, E ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2058,9 +2058,9 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrSta ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2123,7 +2123,7 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2170,8 +2170,8 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2224,9 +2224,9 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSt ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to diff --git a/modules/hydrodyn/src/Current_Types.f90 b/modules/hydrodyn/src/Current_Types.f90 index a6e140585..e56b124c4 100644 --- a/modules/hydrodyn/src/Current_Types.f90 +++ b/modules/hydrodyn/src/Current_Types.f90 @@ -1678,7 +1678,7 @@ SUBROUTINE Current_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Current_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1725,8 +1725,8 @@ SUBROUTINE Current_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(Current_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Current_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1771,9 +1771,9 @@ SUBROUTINE Current_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(Current_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(Current_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Current_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Current_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1828,7 +1828,7 @@ SUBROUTINE Current_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Current_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1875,8 +1875,8 @@ SUBROUTINE Current_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Er ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(Current_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Current_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1921,9 +1921,9 @@ SUBROUTINE Current_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(Current_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(Current_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Current_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Current_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index fbe6deb71..e197640f5 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -2455,7 +2455,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM m%IgnoreMod = .true. ! to compute perturbations, we need to ignore the modulo function ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid - NN = p%WAMIT(1)%SS_Rdtn%N + p%WAMIT(1)%SS_Exctn%N + NN = p%WAMIT(1)%SS_Rdtn%numStates + p%WAMIT(1)%SS_Exctn%numStates ! make a copy of the inputs to perturb call HydroDyn_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2551,15 +2551,15 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM dXdu = 0.0_R8Ki - do i = 1,p%WAMIT(1)%SS_Exctn%N + do i = 1,p%WAMIT(1)%SS_Exctn%numStates dXdu(offsetI+i,size(p%Jac_u_indx,1)+1) = p%WAMIT(1)%SS_Exctn%B(i) end do - offsetI = NN - p%WAMIT(1)%SS_Rdtn%N + offsetI = NN - p%WAMIT(1)%SS_Rdtn%numStates offsetJ = size(p%Jac_u_indx,1)+1 - 13 do j = 1, 6 - do i = 1,p%WAMIT(1)%SS_Rdtn%N + do i = 1,p%WAMIT(1)%SS_Rdtn%numStates dXdu(offsetI+i,offsetJ+j) = p%WAMIT(1)%SS_Rdtn%B(i,j) end do end do @@ -2643,7 +2643,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: - NN = p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N + NN = p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates ! make a copy of the continuous states to perturb call HydroDyn_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2729,17 +2729,17 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, dXdx = 0.0_R8Ki ! Analytical Jacobians from State-space models - if ( p%WAMIT(1)%SS_Exctn%N > 0 ) then - do j=1,p%WAMIT(1)%SS_Exctn%N - do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all active (enabled) DOFs + if ( p%WAMIT(1)%SS_Exctn%numStates > 0 ) then + do j=1,p%WAMIT(1)%SS_Exctn%numStates + do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all active (enabled) DOFs dXdx(i, j) = p%WAMIT(1)%SS_Exctn%A(i,j) end do end do end if - if ( p%WAMIT(1)%SS_Rdtn%N > 0 ) then - do j=1,p%WAMIT(1)%SS_Rdtn%N - do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all active (enabled) DOFs - dXdx(i+p%WAMIT(1)%SS_Exctn%N, j+p%WAMIT(1)%SS_Exctn%N) = p%WAMIT(1)%SS_Rdtn%A(i,j) + if ( p%WAMIT(1)%SS_Rdtn%numStates > 0 ) then + do j=1,p%WAMIT(1)%SS_Rdtn%numStates + do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all active (enabled) DOFs + dXdx(i+p%WAMIT(1)%SS_Exctn%numStates, j+p%WAMIT(1)%SS_Exctn%numStates) = p%WAMIT(1)%SS_Rdtn%A(i,j) end do end do end if @@ -3007,7 +3007,7 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" indx = 1 - NN = p%WAMIT(1)%SS_Rdtn%N + p%WAMIT(1)%SS_Exctn%N + NN = p%WAMIT(1)%SS_Rdtn%numStates + p%WAMIT(1)%SS_Exctn%numStates if ( NN == 0 ) return ! allocate space for the row/column names and for perturbation sizes call allocAry(p%dx, NN, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -3020,12 +3020,12 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) ! set perturbation sizes: p%dx - do i = 1, p%WAMIT(1)%SS_Exctn%N + do i = 1, p%WAMIT(1)%SS_Exctn%numStates p%dx(i) = 20000.0_R8Ki * D2R_D end do - do i = 1, p%WAMIT(1)%SS_Rdtn%N - p%dx(i+p%WAMIT(1)%SS_Exctn%N) = 2.0_R8Ki * D2R_D + do i = 1, p%WAMIT(1)%SS_Rdtn%numStates + p%dx(i+p%WAMIT(1)%SS_Exctn%numStates) = 2.0_R8Ki * D2R_D end do modLabels = (/'Exctn ','Rdtn '/) @@ -3375,8 +3375,8 @@ SUBROUTINE HD_Perturb_x( p, n, perturb_sign, x, dx ) dx = p%dx(n) - if (n > p%WAMIT(1)%SS_Exctn%N) then - indx = n - p%WAMIT(1)%SS_Exctn%N + if (n > p%WAMIT(1)%SS_Exctn%numStates) then + indx = n - p%WAMIT(1)%SS_Exctn%numStates x%WAMIT(1)%SS_Rdtn%x( indx ) = x%WAMIT(1)%SS_Rdtn%x( indx ) + dx * perturb_sign else indx = n @@ -3539,16 +3539,16 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, IF ( PRESENT( x_op ) ) THEN if (.not. allocated(x_op)) then - call AllocAry(x_op, p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N,'x_op',ErrStat2,ErrMsg2) + call AllocAry(x_op, p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates,'x_op',ErrStat2,ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) return end if - do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all DOFs + do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all DOFs x_op(i) = x%WAMIT(1)%SS_Exctn%x(i) end do - do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all DOFs - x_op(i+p%WAMIT(1)%SS_Exctn%N) = x%WAMIT(1)%SS_Rdtn%x(i) + do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all DOFs + x_op(i+p%WAMIT(1)%SS_Exctn%numStates) = x%WAMIT(1)%SS_Rdtn%x(i) end do END IF @@ -3557,7 +3557,7 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, IF ( PRESENT( dx_op ) ) THEN if (.not. allocated(dx_op)) then - call AllocAry(dx_op, p%WAMIT(1)%SS_Exctn%N+p%WAMIT(1)%SS_Rdtn%N,'dx_op',ErrStat2,ErrMsg2) + call AllocAry(dx_op, p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates,'dx_op',ErrStat2,ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) return end if @@ -3569,11 +3569,11 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, return end if - do i=1,p%WAMIT(1)%SS_Exctn%N ! Loop through all DOFs + do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all DOFs dx_op(i) = dx%WAMIT(1)%SS_Exctn%x(i) end do - do i=1,p%WAMIT(1)%SS_Rdtn%N ! Loop through all DOFs - dx_op(i+p%WAMIT(1)%SS_Exctn%N) = dx%WAMIT(1)%SS_Rdtn%x(i) + do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all DOFs + dx_op(i+p%WAMIT(1)%SS_Exctn%numStates) = dx%WAMIT(1)%SS_Rdtn%x(i) end do call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) diff --git a/modules/hydrodyn/src/SS_Radiation_Types.f90 b/modules/hydrodyn/src/SS_Radiation_Types.f90 index 597349c03..dc26ccc81 100644 --- a/modules/hydrodyn/src/SS_Radiation_Types.f90 +++ b/modules/hydrodyn/src/SS_Radiation_Types.f90 @@ -36,13 +36,15 @@ MODULE SS_Radiation_Types ! ========= SS_Rad_InitInputType ======= TYPE, PUBLIC :: SS_Rad_InitInputType CHARACTER(1024) :: InputFile !< Name of the input file [-] - REAL(ReKi) , DIMENSION(1:1,1:6) :: DOFs !< Vector with enable platf. DOFs [m/s or rad/s] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: enabledDOFs !< Vector with enable platf. DOFs [(m/s] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] END TYPE SS_Rad_InitInputType ! ======================= ! ========= SS_Rad_InitOutputType ======= TYPE, PUBLIC :: SS_Rad_InitOutputType - CHARACTER(10) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] - CHARACTER(10) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Header of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output [-] END TYPE SS_Rad_InitOutputType ! ======================= ! ========= SS_Rad_ContinuousStateType ======= @@ -73,23 +75,24 @@ MODULE SS_Radiation_Types ! ======================= ! ========= SS_Rad_ParameterType ======= TYPE, PUBLIC :: SS_Rad_ParameterType - REAL(DbKi) :: DT !< Time step [seconds] + REAL(DbKi) :: DT !< Time step [(s)] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: N !< Number of states [-] - INTEGER(IntKi) , DIMENSION(1:6) :: spdof !< States per dof [-] + INTEGER(IntKi) :: numStates !< Number of states [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: spdof !< States per dof [-] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] END TYPE SS_Rad_ParameterType ! ======================= ! ========= SS_Rad_InputType ======= TYPE, PUBLIC :: SS_Rad_InputType - REAL(ReKi) , DIMENSION(1:6) :: dq !< Body velocities [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dq !< Body velocities [-] END TYPE SS_Rad_InputType ! ======================= ! ========= SS_Rad_OutputType ======= TYPE, PUBLIC :: SS_Rad_OutputType - REAL(ReKi) , DIMENSION(1:6) :: y !< Force [-] - REAL(ReKi) , DIMENSION(1:7) :: WriteOutput !< output Data [kN] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: y !< Force [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< output Data [(kN)] END TYPE SS_Rad_OutputType ! ======================= CONTAINS @@ -110,7 +113,31 @@ SUBROUTINE SS_Rad_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E ErrStat = ErrID_None ErrMsg = "" DstInitInputData%InputFile = SrcInitInputData%InputFile - DstInitInputData%DOFs = SrcInitInputData%DOFs +IF (ALLOCATED(SrcInitInputData%enabledDOFs)) THEN + i1_l = LBOUND(SrcInitInputData%enabledDOFs,1) + i1_u = UBOUND(SrcInitInputData%enabledDOFs,1) + IF (.NOT. ALLOCATED(DstInitInputData%enabledDOFs)) THEN + ALLOCATE(DstInitInputData%enabledDOFs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%enabledDOFs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%enabledDOFs = SrcInitInputData%enabledDOFs +ENDIF + DstInitInputData%NBody = SrcInitInputData%NBody +IF (ALLOCATED(SrcInitInputData%PtfmRefztRot)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefztRot,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefztRot,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefztRot)) THEN + ALLOCATE(DstInitInputData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefztRot = SrcInitInputData%PtfmRefztRot +ENDIF END SUBROUTINE SS_Rad_CopyInitInput SUBROUTINE SS_Rad_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) @@ -122,6 +149,12 @@ SUBROUTINE SS_Rad_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitInputData%enabledDOFs)) THEN + DEALLOCATE(InitInputData%enabledDOFs) +ENDIF +IF (ALLOCATED(InitInputData%PtfmRefztRot)) THEN + DEALLOCATE(InitInputData%PtfmRefztRot) +ENDIF END SUBROUTINE SS_Rad_DestroyInitInput SUBROUTINE SS_Rad_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -160,7 +193,17 @@ SUBROUTINE SS_Rad_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1*LEN(InData%InputFile) ! InputFile - Re_BufSz = Re_BufSz + SIZE(InData%DOFs) ! DOFs + Int_BufSz = Int_BufSz + 1 ! enabledDOFs allocated yes/no + IF ( ALLOCATED(InData%enabledDOFs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! enabledDOFs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%enabledDOFs) ! enabledDOFs + END IF + Int_BufSz = Int_BufSz + 1 ! NBody + Int_BufSz = Int_BufSz + 1 ! PtfmRefztRot allocated yes/no + IF ( ALLOCATED(InData%PtfmRefztRot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefztRot upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PtfmRefztRot) ! PtfmRefztRot + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -192,8 +235,34 @@ SUBROUTINE SS_Rad_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DOFs))-1 ) = PACK(InData%DOFs,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DOFs) + IF ( .NOT. ALLOCATED(InData%enabledDOFs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%enabledDOFs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%enabledDOFs,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%enabledDOFs)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%enabledDOFs))-1 ) = PACK(InData%enabledDOFs,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%enabledDOFs) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PtfmRefztRot)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%PtfmRefztRot))-1 ) = PACK(InData%PtfmRefztRot,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%PtfmRefztRot) + END IF END SUBROUTINE SS_Rad_PackInitInput SUBROUTINE SS_Rad_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -234,19 +303,54 @@ SUBROUTINE SS_Rad_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I - i1_l = LBOUND(OutData%DOFs,1) - i1_u = UBOUND(OutData%DOFs,1) - i2_l = LBOUND(OutData%DOFs,2) - i2_u = UBOUND(OutData%DOFs,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! enabledDOFs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%enabledDOFs)) DEALLOCATE(OutData%enabledDOFs) + ALLOCATE(OutData%enabledDOFs(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%enabledDOFs.', ErrStat, ErrMsg,RoutineName) RETURN END IF - mask2 = .TRUE. - OutData%DOFs = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DOFs))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%DOFs) - DEALLOCATE(mask2) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%enabledDOFs)>0) OutData%enabledDOFs = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%enabledDOFs))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%enabledDOFs) + DEALLOCATE(mask1) + END IF + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%PtfmRefztRot)>0) OutData%PtfmRefztRot = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%PtfmRefztRot))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%PtfmRefztRot) + DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Rad_UnPackInitInput SUBROUTINE SS_Rad_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -264,8 +368,30 @@ SUBROUTINE SS_Rad_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF END SUBROUTINE SS_Rad_CopyInitOutput SUBROUTINE SS_Rad_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -277,6 +403,12 @@ SUBROUTINE SS_Rad_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF END SUBROUTINE SS_Rad_DestroyInitOutput SUBROUTINE SS_Rad_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -314,8 +446,16 @@ SUBROUTINE SS_Rad_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -343,18 +483,40 @@ SUBROUTINE SS_Rad_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) DO I = 1, LEN(InData%WriteOutputHdr) IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) DO I = 1, LEN(InData%WriteOutputUnt) IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I END DO !i1 + END IF END SUBROUTINE SS_Rad_PackInitOutput SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -390,8 +552,19 @@ SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%WriteOutputHdr,1) - i1_u = UBOUND(OutData%WriteOutputHdr,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) @@ -405,8 +578,20 @@ SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END DO ! I END DO !i1 DEALLOCATE(mask1) - i1_l = LBOUND(OutData%WriteOutputUnt,1) - i1_u = UBOUND(OutData%WriteOutputUnt,1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) @@ -420,6 +605,7 @@ SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END DO ! I END DO !i1 DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Rad_UnPackInitOutput SUBROUTINE SS_Rad_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -1292,8 +1478,20 @@ SUBROUTINE SS_Rad_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM END IF DstParamData%C = SrcParamData%C ENDIF - DstParamData%N = SrcParamData%N + DstParamData%numStates = SrcParamData%numStates +IF (ALLOCATED(SrcParamData%spdof)) THEN + i1_l = LBOUND(SrcParamData%spdof,1) + i1_u = UBOUND(SrcParamData%spdof,1) + IF (.NOT. ALLOCATED(DstParamData%spdof)) THEN + ALLOCATE(DstParamData%spdof(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%spdof.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstParamData%spdof = SrcParamData%spdof +ENDIF + DstParamData%NBody = SrcParamData%NBody END SUBROUTINE SS_Rad_CopyParam SUBROUTINE SS_Rad_DestroyParam( ParamData, ErrStat, ErrMsg ) @@ -1313,6 +1511,9 @@ SUBROUTINE SS_Rad_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDIF IF (ALLOCATED(ParamData%C)) THEN DEALLOCATE(ParamData%C) +ENDIF +IF (ALLOCATED(ParamData%spdof)) THEN + DEALLOCATE(ParamData%spdof) ENDIF END SUBROUTINE SS_Rad_DestroyParam @@ -1367,8 +1568,13 @@ SUBROUTINE SS_Rad_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C) ! C END IF - Int_BufSz = Int_BufSz + 1 ! N + Int_BufSz = Int_BufSz + 1 ! numStates + Int_BufSz = Int_BufSz + 1 ! spdof allocated yes/no + IF ( ALLOCATED(InData%spdof) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! spdof upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%spdof) ! spdof + END IF + Int_BufSz = Int_BufSz + 1 ! NBody IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1446,10 +1652,23 @@ SUBROUTINE SS_Rad_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IF (SIZE(InData%C)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C))-1 ) = PACK(InData%C,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%C) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%N + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%numStates Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%spdof))-1 ) = PACK(InData%spdof,.TRUE.) + IF ( .NOT. ALLOCATED(InData%spdof) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%spdof,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%spdof,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%spdof)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%spdof))-1 ) = PACK(InData%spdof,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%spdof) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NBody + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SS_Rad_PackParam SUBROUTINE SS_Rad_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1566,19 +1785,33 @@ SUBROUTINE SS_Rad_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = Re_Xferred + SIZE(OutData%C) DEALLOCATE(mask2) END IF - OutData%N = IntKiBuf( Int_Xferred ) + OutData%numStates = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%spdof,1) - i1_u = UBOUND(OutData%spdof,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! spdof not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%spdof)) DEALLOCATE(OutData%spdof) + ALLOCATE(OutData%spdof(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%spdof.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%spdof = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%spdof))-1 ), mask1, 0_IntKi ) + IF (SIZE(OutData%spdof)>0) OutData%spdof = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%spdof))-1 ), mask1, 0_IntKi ) Int_Xferred = Int_Xferred + SIZE(OutData%spdof) DEALLOCATE(mask1) + END IF + OutData%NBody = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SS_Rad_UnPackParam SUBROUTINE SS_Rad_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) @@ -1596,7 +1829,18 @@ SUBROUTINE SS_Rad_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrM ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcInputData%dq)) THEN + i1_l = LBOUND(SrcInputData%dq,1) + i1_u = UBOUND(SrcInputData%dq,1) + IF (.NOT. ALLOCATED(DstInputData%dq)) THEN + ALLOCATE(DstInputData%dq(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%dq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInputData%dq = SrcInputData%dq +ENDIF END SUBROUTINE SS_Rad_CopyInput SUBROUTINE SS_Rad_DestroyInput( InputData, ErrStat, ErrMsg ) @@ -1608,6 +1852,9 @@ SUBROUTINE SS_Rad_DestroyInput( InputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InputData%dq)) THEN + DEALLOCATE(InputData%dq) +ENDIF END SUBROUTINE SS_Rad_DestroyInput SUBROUTINE SS_Rad_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1645,7 +1892,11 @@ SUBROUTINE SS_Rad_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! dq allocated yes/no + IF ( ALLOCATED(InData%dq) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dq upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%dq) ! dq + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1673,8 +1924,19 @@ SUBROUTINE SS_Rad_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%dq))-1 ) = PACK(InData%dq,.TRUE.) + IF ( .NOT. ALLOCATED(InData%dq) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dq,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%dq)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%dq))-1 ) = PACK(InData%dq,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%dq) + END IF END SUBROUTINE SS_Rad_PackInput SUBROUTINE SS_Rad_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1710,17 +1972,29 @@ SUBROUTINE SS_Rad_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%dq,1) - i1_u = UBOUND(OutData%dq,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dq not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dq)) DEALLOCATE(OutData%dq) + ALLOCATE(OutData%dq(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%dq = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%dq))-1 ), mask1, 0.0_ReKi ) + IF (SIZE(OutData%dq)>0) OutData%dq = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%dq))-1 ), mask1, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%dq) DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Rad_UnPackInput SUBROUTINE SS_Rad_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -1738,8 +2012,30 @@ SUBROUTINE SS_Rad_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, E ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcOutputData%y)) THEN + i1_l = LBOUND(SrcOutputData%y,1) + i1_u = UBOUND(SrcOutputData%y,1) + IF (.NOT. ALLOCATED(DstOutputData%y)) THEN + ALLOCATE(DstOutputData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%y = SrcOutputData%y +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF END SUBROUTINE SS_Rad_CopyOutput SUBROUTINE SS_Rad_DestroyOutput( OutputData, ErrStat, ErrMsg ) @@ -1751,6 +2047,12 @@ SUBROUTINE SS_Rad_DestroyOutput( OutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(OutputData%y)) THEN + DEALLOCATE(OutputData%y) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF END SUBROUTINE SS_Rad_DestroyOutput SUBROUTINE SS_Rad_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1788,8 +2090,16 @@ SUBROUTINE SS_Rad_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ALLOCATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1817,10 +2127,32 @@ SUBROUTINE SS_Rad_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%y))-1 ) = PACK(InData%y,.TRUE.) + IF ( .NOT. ALLOCATED(InData%y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%y)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%y))-1 ) = PACK(InData%y,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%y) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) + END IF END SUBROUTINE SS_Rad_PackOutput SUBROUTINE SS_Rad_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1856,28 +2188,52 @@ SUBROUTINE SS_Rad_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%y,1) - i1_u = UBOUND(OutData%y,1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%y = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%y))-1 ), mask1, 0.0_ReKi ) + IF (SIZE(OutData%y)>0) OutData%y = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%y))-1 ), mask1, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%y) DEALLOCATE(mask1) - i1_l = LBOUND(OutData%WriteOutput,1) - i1_u = UBOUND(OutData%WriteOutput,1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) + IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) DEALLOCATE(mask1) + END IF END SUBROUTINE SS_Rad_UnPackOutput @@ -1897,7 +2253,7 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1944,8 +2300,8 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1973,12 +2329,14 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(u_out%dq) .AND. ALLOCATED(u1%dq)) THEN ALLOCATE(b1(SIZE(u_out%dq,1))) ALLOCATE(c1(SIZE(u_out%dq,1))) b1 = -(u1%dq - u2%dq)/t(2) u_out%dq = u1%dq + b1 * t_out DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Rad_Input_ExtrapInterp1 @@ -1996,9 +2354,9 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(SS_Rad_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(SS_Rad_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2033,6 +2391,7 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(u_out%dq) .AND. ALLOCATED(u1%dq)) THEN ALLOCATE(b1(SIZE(u_out%dq,1))) ALLOCATE(c1(SIZE(u_out%dq,1))) b1 = (t(3)**2*(u1%dq - u2%dq) + t(2)**2*(-u1%dq + u3%dq))/(t(2)*t(3)*(t(2) - t(3))) @@ -2040,6 +2399,7 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, u_out%dq = u1%dq + b1 * t_out + c1 * t_out**2 DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Rad_Input_ExtrapInterp2 @@ -2059,7 +2419,7 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2106,8 +2466,8 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2135,18 +2495,22 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN ALLOCATE(b1(SIZE(y_out%y,1))) ALLOCATE(c1(SIZE(y_out%y,1))) b1 = -(y1%y - y2%y)/t(2) y_out%y = y1%y + b1 * t_out DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) y_out%WriteOutput = y1%WriteOutput + b1 * t_out DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Rad_Output_ExtrapInterp1 @@ -2164,9 +2528,9 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(SS_Rad_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2201,6 +2565,7 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN ALLOCATE(b1(SIZE(y_out%y,1))) ALLOCATE(c1(SIZE(y_out%y,1))) b1 = (t(3)**2*(y1%y - y2%y) + t(2)**2*(-y1%y + y3%y))/(t(2)*t(3)*(t(2) - t(3))) @@ -2208,6 +2573,8 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, y_out%y = y1%y + b1 * t_out + c1 * t_out**2 DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) @@ -2215,6 +2582,7 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 DEALLOCATE(b1) DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SS_Rad_Output_ExtrapInterp2 END MODULE SS_Radiation_Types diff --git a/modules/hydrodyn/src/Waves2_Types.f90 b/modules/hydrodyn/src/Waves2_Types.f90 index 66297b84b..e3ea16b2b 100644 --- a/modules/hydrodyn/src/Waves2_Types.f90 +++ b/modules/hydrodyn/src/Waves2_Types.f90 @@ -3553,7 +3553,7 @@ SUBROUTINE Waves2_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Waves2_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3600,8 +3600,8 @@ SUBROUTINE Waves2_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(Waves2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Waves2_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3646,9 +3646,9 @@ SUBROUTINE Waves2_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(Waves2_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(Waves2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves2_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Waves2_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3703,7 +3703,7 @@ SUBROUTINE Waves2_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3750,8 +3750,8 @@ SUBROUTINE Waves2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3804,9 +3804,9 @@ SUBROUTINE Waves2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(Waves2_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Waves2_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to diff --git a/modules/hydrodyn/src/Waves_Types.f90 b/modules/hydrodyn/src/Waves_Types.f90 index e5ecef1ea..e4cd16058 100644 --- a/modules/hydrodyn/src/Waves_Types.f90 +++ b/modules/hydrodyn/src/Waves_Types.f90 @@ -3141,7 +3141,7 @@ SUBROUTINE Waves_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Waves_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3188,8 +3188,8 @@ SUBROUTINE Waves_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMs ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 - TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 + TYPE(Waves_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(Waves_InputType), INTENT(INOUT) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3234,9 +3234,9 @@ SUBROUTINE Waves_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, E ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 - TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 - TYPE(Waves_InputType), INTENT(IN) :: u3 ! Input at t3 + TYPE(Waves_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(Waves_InputType), INTENT(INOUT) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3291,7 +3291,7 @@ SUBROUTINE Waves_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Waves_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3338,8 +3338,8 @@ SUBROUTINE Waves_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 - TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 + TYPE(Waves_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(Waves_OutputType), INTENT(INOUT) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3384,9 +3384,9 @@ SUBROUTINE Waves_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 - TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 - TYPE(Waves_OutputType), INTENT(IN) :: y3 ! Output at t3 + TYPE(Waves_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(Waves_OutputType), INTENT(INOUT) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to From b6df68a83c00d8421d405eff671926d4b65b3953 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 14:38:09 -0700 Subject: [PATCH 153/377] Update types for NBody mods --- modules/hydrodyn/src/SS_Excitation_Types.f90 | 114 ------------------- 1 file changed, 114 deletions(-) diff --git a/modules/hydrodyn/src/SS_Excitation_Types.f90 b/modules/hydrodyn/src/SS_Excitation_Types.f90 index 9bf1a2d95..99b87296a 100644 --- a/modules/hydrodyn/src/SS_Excitation_Types.f90 +++ b/modules/hydrodyn/src/SS_Excitation_Types.f90 @@ -39,8 +39,6 @@ MODULE SS_Excitation_Types INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] REAL(ReKi) :: WaveDir !< Wave direction [rad] INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefxt !< The xt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: PtfmRefyt !< The yt offset of the body reference point(s) from (0,0,0) [1 to NBody; only used when PotMod=1 ] [(m)] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] @@ -125,30 +123,6 @@ SUBROUTINE SS_Exc_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%NBody = SrcInitInputData%NBody DstInitInputData%WaveDir = SrcInitInputData%WaveDir DstInitInputData%NStepWave = SrcInitInputData%NStepWave -IF (ALLOCATED(SrcInitInputData%PtfmRefxt)) THEN - i1_l = LBOUND(SrcInitInputData%PtfmRefxt,1) - i1_u = UBOUND(SrcInitInputData%PtfmRefxt,1) - IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefxt)) THEN - ALLOCATE(DstInitInputData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitInputData%PtfmRefxt = SrcInitInputData%PtfmRefxt -ENDIF -IF (ALLOCATED(SrcInitInputData%PtfmRefyt)) THEN - i1_l = LBOUND(SrcInitInputData%PtfmRefyt,1) - i1_u = UBOUND(SrcInitInputData%PtfmRefyt,1) - IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefyt)) THEN - ALLOCATE(DstInitInputData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitInputData%PtfmRefyt = SrcInitInputData%PtfmRefyt -ENDIF IF (ALLOCATED(SrcInitInputData%PtfmRefztRot)) THEN i1_l = LBOUND(SrcInitInputData%PtfmRefztRot,1) i1_u = UBOUND(SrcInitInputData%PtfmRefztRot,1) @@ -196,12 +170,6 @@ SUBROUTINE SS_Exc_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(InitInputData%PtfmRefxt)) THEN - DEALLOCATE(InitInputData%PtfmRefxt) -ENDIF -IF (ALLOCATED(InitInputData%PtfmRefyt)) THEN - DEALLOCATE(InitInputData%PtfmRefyt) -ENDIF IF (ALLOCATED(InitInputData%PtfmRefztRot)) THEN DEALLOCATE(InitInputData%PtfmRefztRot) ENDIF @@ -252,16 +220,6 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! NBody Re_BufSz = Re_BufSz + 1 ! WaveDir Int_BufSz = Int_BufSz + 1 ! NStepWave - Int_BufSz = Int_BufSz + 1 ! PtfmRefxt allocated yes/no - IF ( ALLOCATED(InData%PtfmRefxt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! PtfmRefxt upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefxt) ! PtfmRefxt - END IF - Int_BufSz = Int_BufSz + 1 ! PtfmRefyt allocated yes/no - IF ( ALLOCATED(InData%PtfmRefyt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! PtfmRefyt upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PtfmRefyt) ! PtfmRefyt - END IF Int_BufSz = Int_BufSz + 1 ! PtfmRefztRot allocated yes/no IF ( ALLOCATED(InData%PtfmRefztRot) ) THEN Int_BufSz = Int_BufSz + 2*1 ! PtfmRefztRot upper/lower bounds for each dimension @@ -314,32 +272,6 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NStepWave Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PtfmRefxt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefxt))-1 ) = PACK(InData%PtfmRefxt,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefxt) - END IF - IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PtfmRefyt)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PtfmRefyt))-1 ) = PACK(InData%PtfmRefyt,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PtfmRefyt) - END IF IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -425,52 +357,6 @@ SUBROUTINE SS_Exc_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%NStepWave = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) - ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%PtfmRefxt)>0) OutData%PtfmRefxt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefxt))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefxt) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) - ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%PtfmRefyt)>0) OutData%PtfmRefyt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PtfmRefyt))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PtfmRefyt) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated Int_Xferred = Int_Xferred + 1 ELSE From 4462460766c93271e2ee4c1ea39bc335a567617d Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 14:38:53 -0700 Subject: [PATCH 154/377] Removed WAMIT2_Output from source files --- vs-build/HydroDyn/HydroDynDriver.vfproj | 37 ++++++++++++------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/vs-build/HydroDyn/HydroDynDriver.vfproj b/vs-build/HydroDyn/HydroDynDriver.vfproj index a8d0c8ebe..efab18895 100644 --- a/vs-build/HydroDyn/HydroDynDriver.vfproj +++ b/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -53,11 +53,11 @@ + + - - @@ -65,11 +65,11 @@ - + - + @@ -77,11 +77,11 @@ - + - + @@ -89,11 +89,11 @@ - + - + @@ -111,11 +111,11 @@ - + - + @@ -123,20 +123,20 @@ - + - + - + - + @@ -147,20 +147,20 @@ - + - + - + - + @@ -181,7 +181,6 @@ - From 16b34d78a646492215c98b04c1f2ea9dcb4de592 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Feb 2020 14:48:43 -0700 Subject: [PATCH 155/377] update r-test commit per Andy's removal of platform force flags --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index 4069ab44a..0d7bc558c 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 4069ab44a8b1cad19a6c387ad3893e9a11016450 +Subproject commit 0d7bc558c9b5cd08d5350412b0dd06e2bdaad0f3 From caff156b9279b8ec8d209b041c1c4d9fa5e62642 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 13 Feb 2020 13:28:10 -0700 Subject: [PATCH 156/377] FlexSub: adding singularity test based on eigenvalues --- modules/subdyn/src/FEM.f90 | 69 ++++++++++++++++++++++++++++- modules/subdyn/src/SubDyn.f90 | 8 ++-- modules/subdyn/src/SubDyn_Tests.f90 | 18 +++++++- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 82605b77f..065353701 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -72,8 +72,25 @@ SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) ! --- Determinign and sorting eigen frequencies DO I=1,N !Initialize the key and calculate Omega KEY(I)=I - IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN - Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + IF ( AlphaR(I)<0.0_LAKi ) THEN + !print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + !ELSE IF ( .not.EqualRealNos(AlphaI(I),0.0_LAKi )) THEN + ! print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) + ! ErrStat2=ErrID_Fatal + ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' + ! if(Failed()) return + ELSE IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN +! Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + ErrStat2=ErrID_Fatal + ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + ELSE IF ( EqualRealNos(ALPHAR(I),0.0_LAKi) ) THEN + ErrStat2=ErrID_Fatal + ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' + if(Failed()) return ELSE Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) END IF @@ -115,6 +132,54 @@ END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolve +!> Compute the determinant of a real matrix using an LU factorization +FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) + use NWTC_LAPACK, only: LAPACK_GETRF + REAL(LaKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(DbKi) :: det !< May easily overflow + integer(IntKi) :: i + integer :: n + integer, allocatable :: ipiv(:) + real(LaKi), allocatable :: PLU(:,:) + real(LaKi) :: ScaleVal + + n = size(A(1,:)) + allocate(PLU(n,n)) + allocate(ipiv(n)) + ScaleVal= 1.0_LaKi + PLU = A/ScaleVal + ! general matrix factorization: Factor matrix into A=PLU. + call LAPACK_GETRF( n, n, PLU, ipiv, ErrStat, ErrMsg ) !call dgetrf(n, n, PLU, n, ipiv, info) + if (ErrStat==ErrID_Fatal) then + print*,'Error in getrf' + det = 0 + deallocate(PLU) + deallocate(ipiv) + return + endif + ! PLU now contains the LU of the factorization A = PLU + ! As L has unit diagonal entries, the determinant can be computed + ! from the product of U's diagonal entries. Additional sign changes + ! stemming from the permutations P have to be taken into account as well. + det = 1.0_LaKi + do i = 1,n + if(ipiv(i) /= i) then ! additional sign change + det = -det*PLU(i,i) + else + det = det*PLU(i,i) + endif + end do + deallocate(PLU) + deallocate(ipiv) + IF ( EqualRealNos(det, 0.0_LaKi) ) THEN + print*,'Det is zero' + return + else + det = det*(ScaleVal**n) + endif +END FUNCTION Determinant !------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 84ae4a19e..52eb6ff6e 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1822,7 +1822,7 @@ SUBROUTINE TrnsfTI(Init, p, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ -!> Warpper funciton for eigen value analyses, for two cases: +!> Wrapper function for eigen value analyses, for two cases: !! Case1: K and M are taken "as is" (bRemoveConstraints=false), This is used for the "LL" part of the matrix !! Case2: K and M constain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega, ErrStat, ErrMsg ) @@ -2399,6 +2399,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! --- Eigen values of full system (for summary file output only) ! True below is to remove the constraints ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + CALL WrScr(' Calculating Full System Modes (for summary file output)') + nOmega = p%nDOF_red - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -2796,12 +2798,12 @@ END SUBROUTINE SymMatDebug FUNCTION is_numeric(string, x) IMPLICIT NONE CHARACTER(len=*), INTENT(IN) :: string - REAL(SiKi), INTENT(OUT) :: x + REAL(ReKi), INTENT(OUT) :: x LOGICAL :: is_numeric INTEGER :: e,n CHARACTER(len=12) :: fmt - x = 0.0_SiKi + x = 0.0_ReKi n=LEN_TRIM(string) WRITE(fmt,'("(F",I0,".0)")') n READ(string,fmt,IOSTAT=e) x diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 7507981ce..b74f177af 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -308,10 +308,20 @@ subroutine Test_Linalg(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref + real(DbKi) :: det integer(IntKi) :: I, J testname='Linalg' - ! --- Inverse of a 3x3 matrix + ! --- Determinant of a singular matrix + allocate(A(3,3)); + A(1,1) = 0 ; A(1,2) = 0 ; A(1,3) = 1 ; + A(2,1) = 0 ; A(2,2) = 0 ; A(2,3) = -1 ; + A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; + det = Determinant(A,ErrStat, ErrMsg) + call test_almost_equal('Det of singular 3x3 matrix', real(det,ReKi), 0.0, 1e-8, .true. , .true.) + deallocate(A ) + + ! --- Inverse and determinant of a 3x3 matrix allocate(A(3,3)); allocate(Aref(3,3)) A(1,1) = 7 ; A(1,2) = 2 ; A(1,3) = 1 ; A(2,1) = 0 ; A(2,2) = 3 ; A(2,3) = -1 ; @@ -320,6 +330,12 @@ subroutine Test_Linalg(ErrStat,ErrMsg) Aref(2,1) = 3 ; Aref(2,2) =-11; Aref(2,3) = 7 ; Aref(3,1) = 9 ; Aref(3,2) =-34; Aref(3,3) = 21; call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + ! Determinant test + det = Determinant(A,ErrStat, ErrMsg) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0, 1e-8, .true. , .true.) + det = Determinant(Ainv,ErrStat, ErrMsg) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0, 1e-8, .true. , .true.) + ! Inverse test call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8, .true., .true.) deallocate(A ) deallocate(Ainv) From d3214fe5bcce66025eb8a21b5aeecfba29379aca Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 13 Feb 2020 14:23:31 -0700 Subject: [PATCH 157/377] FlexSub: removing DOF selections for interface and reactions --- modules/subdyn/src/SD_FEM.f90 | 7 +++---- modules/subdyn/src/SubDyn.f90 | 16 +++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ac63a0218..76eb201cd 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -29,7 +29,6 @@ MODULE SD_FEM ! values of these parameters are ordered by their place in SubDyn input file: INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) - INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction dof array (JointID,RctTDxss,RctTDYss,RctTDZss,RctRDXss,RctRDYss,RctRDZss) INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) @@ -60,7 +59,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idMemberCable = 2 INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 - INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,ReactCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) + INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi @@ -830,7 +829,7 @@ SUBROUTINE InitBCs(Init, p) iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%BCs( (I-1)*6+J, 2) = p%Nodes_C(I, J+1); ! 0 or 1 if fixed reaction or not + Init%BCs( (I-1)*6+J, 2) = 1 ! NOTE: Always selected now p%Nodes_C(I, J+1); ! 0 or 1 if fixed reaction or not ENDDO ENDDO END SUBROUTINE InitBCs @@ -847,7 +846,7 @@ SUBROUTINE InitIntFc(Init, p) iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%IntFc( (I-1)*6+J, 2) = p%Nodes_I(I, J+1); ! 0 or 1 if fixed to interface + Init%IntFc( (I-1)*6+J, 2) = 1 ! NOTE: Always selected now p%Nodes_I(I, J+1); ! 0 or 1 if fixed to interface ENDDO ENDDO END SUBROUTINE InitIntFc diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 52eb6ff6e..7d27a96a2 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -616,7 +616,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings -INTEGER(IntKi) :: I, J, flg, K +INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) INTEGER(IntKi) :: ErrStat2 @@ -779,9 +779,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 + nColsReactInterf=InterfCol else ! New format LegacyFormat=.False. + nColsReactInterf=1 endif ! Extract fields from first line DO I = 1, nColumns @@ -803,10 +805,10 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_C, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Nodes_C, p%nNodes_C, ReactCol, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL AllocAry(p%Nodes_C, p%nNodes_C, nColsReactInterf, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return DO I = 1, p%nNodes_C - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, ReactCol, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return - p%Nodes_C(I,:) = Dummy_IntAry(1:ReactCol) + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColsReactInterf, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return + p%Nodes_C(I,:) = Dummy_IntAry(1:nColsReactInterf) ENDDO IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return @@ -816,10 +818,10 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_I, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Nodes_I, p%nNodes_I, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +CALL AllocAry(p%Nodes_I, p%nNodes_I, nColsReactInterf, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return DO I = 1, p%nNodes_I - CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, InterfCol, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - p%Nodes_I(I,:) = Dummy_IntAry(1:InterfCol) + CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, nColsReactInterf, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + p%Nodes_I(I,:) = Dummy_IntAry(1:nColsReactInterf) ENDDO IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN From 6892dceb19eb0faf221c6c306ce392fbc693984c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Mar 2020 16:21:56 -0700 Subject: [PATCH 158/377] FlexSub: small fix, errstat2 should be used in cleanup --- modules/subdyn/src/SubDyn.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 7d27a96a2..bf875bd5b 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2658,7 +2658,7 @@ END FUNCTION Failed SUBROUTINE CleanUp() if(allocated(Omega)) deallocate(Omega) if(allocated(Modes)) deallocate(Modes) - CALL SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + CALL SDOut_CloseSum( UnSum, ErrStat2, ErrMsg2 ) END SUBROUTINE CleanUp END SUBROUTINE OutSummary From a8573842cb11ba92c2e1694be7b8c05538d4048c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 5 Mar 2020 16:22:28 -0700 Subject: [PATCH 159/377] FlexSub: summary EVA does not check for singularities (e.g. spar) --- modules/subdyn/src/FEM.f90 | 29 ++++++++++++++++++----------- modules/subdyn/src/SubDyn.f90 | 16 +++++++++------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 065353701..ab566f1e1 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -27,12 +27,13 @@ MODULE FEM CONTAINS !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors -SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) +SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix + LOGICAL, INTENT(IN ) :: bCheckSingularity !< If True, check for singularities REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation @@ -74,23 +75,29 @@ SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) KEY(I)=I IF ( AlphaR(I)<0.0_LAKi ) THEN !print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif !ELSE IF ( .not.EqualRealNos(AlphaI(I),0.0_LAKi )) THEN ! print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) ! ErrStat2=ErrID_Fatal ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' ! if(Failed()) return ELSE IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN -! Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? - ErrStat2=ErrID_Fatal - ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return + Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif ELSE IF ( EqualRealNos(ALPHAR(I),0.0_LAKi) ) THEN - ErrStat2=ErrID_Fatal - ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' - if(Failed()) return + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' + if(Failed()) return + endif ELSE Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) END IF diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index bf875bd5b..f75f788d7 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1671,7 +1671,7 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & ! Set OmegaL and PhiL from Eq. 2 !.................................................... IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .False.,Init,p, PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .False.,Init,p, .True., PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL ! bjj: break up this equation to avoid as many tenporary variables on the stack @@ -1827,17 +1827,18 @@ END SUBROUTINE TrnsfTI !> Wrapper function for eigen value analyses, for two cases: !! Case1: K and M are taken "as is" (bRemoveConstraints=false), This is used for the "LL" part of the matrix !! Case2: K and M constain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system -SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, Omega, ErrStat, ErrMsg ) +SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, bCheckSingularity, Phi, Omega, ErrStat, ErrMsg ) USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix - INTEGER, INTENT(IN ) :: NOmega ! RRD: no. of requested eigenvalues + INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues LOGICAL, INTENT(IN ) :: bRemoveConstraints ! Whether or not to reduce matrices, this will be removed altogether later, when reduction will be done apriori TYPE(SD_InitType), INTENT(IN ) :: Init TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT( OUT) :: Phi(nDOF, NOmega) ! RRD: Returned Eigenvectors - REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! RRD: Returned Eigenvalues + LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present + REAL(ReKi), INTENT( OUT) :: Phi(nDOF, NOmega) ! Returned Eigenvectors + REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! LOCALS @@ -1877,7 +1878,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, Phi, ! --- Eigenvalue analysis CALL AllocAry( Omega2_LaKi, N, 'Omega', ErrStat2, ErrMsg2 ); if (Failed()) return; CALL AllocAry( EigVect , N, N, 'EigVect', ErrStat2, ErrMsg2 ); if (Failed()) return; - CALL EigenSolve(Kred, Mred, N, EigVect, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL EigenSolve(Kred, Mred, N, bCheckSingularity, EigVect, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion Omega=sqrt(Omega2_LaKi(1:NOmega) ) @@ -2401,12 +2402,13 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! --- Eigen values of full system (for summary file output only) ! True below is to remove the constraints ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! NOTE: we don't check for singularities/rigig body modes here CALL WrScr(' Calculating Full System Modes (for summary file output)') nOmega = p%nDOF_red - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL EigenSolveWrap( Init%K, Init%M, p%nDOF_red, nOmega, .True., Init, p, Modes, Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL EigenSolveWrap( Init%K, Init%M, p%nDOF_red, nOmega, .True., Init, p, .False., Modes, Omega, ErrStat2, ErrMsg2 ); if(Failed()) return !------------------------------------------------------------------------------------------------------------- ! open txt file From 419005024c31d955e449bc35623f33fc3f7c9121 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 12 Mar 2020 10:44:59 -0600 Subject: [PATCH 160/377] FlexSub: Update from Visual Studio --- modules/subdyn/src/FEM.f90 | 6 +++--- modules/subdyn/src/SubDyn.f90 | 2 +- vs-build/FASTlib/FASTlib.vfproj | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index ab566f1e1..a47b57e55 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -85,14 +85,14 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM ! ErrStat2=ErrID_Fatal ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' ! if(Failed()) return - ELSE IF ( EqualRealNos(Beta(I),0.0_LAKi) ) THEN + ELSE IF ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) THEN Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? if (bCheckSingularity) then ErrStat2=ErrID_Fatal ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' if(Failed()) return endif - ELSE IF ( EqualRealNos(ALPHAR(I),0.0_LAKi) ) THEN + ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_Ki) ) THEN if (bCheckSingularity) then ErrStat2=ErrID_Fatal ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' @@ -180,7 +180,7 @@ FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) end do deallocate(PLU) deallocate(ipiv) - IF ( EqualRealNos(det, 0.0_LaKi) ) THEN + IF ( EqualRealNos(real(det, ReKi), 0.0_ReKi) ) THEN print*,'Det is zero' return else diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f75f788d7..8ac1406ac 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1538,7 +1538,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) SUBROUTINE Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'Craig_Bampton'); - CALL CleanUp() + CALL CleanUpCB() END SUBROUTINE Fatal logical function Failed() diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index b6c338a88..93424cd08 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -1392,8 +1392,12 @@ + + + + From 6c2526c57b75ba275c60400516376f532da7df7d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 12 Mar 2020 11:51:53 -0600 Subject: [PATCH 161/377] FlexSub: correct typo --- modules/subdyn/src/FEM.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index a47b57e55..298ca2c5c 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -92,7 +92,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' if(Failed()) return endif - ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_Ki) ) THEN + ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_ReKi) ) THEN if (bCheckSingularity) then ErrStat2=ErrID_Fatal ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' From d302f923b5aeb5edb07fd77175f9f5914bee03e1 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Mar 2020 17:01:12 -0600 Subject: [PATCH 162/377] SD: fix for type so double precision compiles --- modules/subdyn/src/FEM.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 065353701..4f390bf6f 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -138,7 +138,7 @@ FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) REAL(LaKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - real(DbKi) :: det !< May easily overflow + real(LaKi) :: det !< May easily overflow integer(IntKi) :: i integer :: n integer, allocatable :: ipiv(:) From fb2acefb6198d2899112992f9080840df1b2722f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 21:51:41 -0600 Subject: [PATCH 163/377] FlexSub: small hint to help intel compiler in debug --- modules/subdyn/src/SubDyn_Output.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index b4e4ad3df..46e15c2f4 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -103,7 +103,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) ! NOTE: len(MemberNodes) >2 if nDiv>1 iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers - pLst%NodeIDs=Init%MemberNodes(iMember,pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting + pLst%NodeIDs(1:pLst%NoutCnt)=Init%MemberNodes(iMember, pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting pLst%ElmIDs=0 !Initialize to 0 pLst%ElmNds=0 !Initialize to 0 From 7289571722de5b125b6a96d92f5ba5a17b151749 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 21:52:04 -0600 Subject: [PATCH 164/377] FlexSub: updating VS solution for SubDyn driver --- vs-build/SubDyn/SubDyn.vfproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vs-build/SubDyn/SubDyn.vfproj b/vs-build/SubDyn/SubDyn.vfproj index 5f0256521..0af119b82 100644 --- a/vs-build/SubDyn/SubDyn.vfproj +++ b/vs-build/SubDyn/SubDyn.vfproj @@ -174,10 +174,14 @@ + + - + + + From 4b373c998c5d63277acbdd4fcff0dfa6ac9eec10 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 23:04:20 -0600 Subject: [PATCH 165/377] FlexSub: modifications to run with VS double solution --- modules/subdyn/src/IntegerList.f90 | 4 ++- modules/subdyn/src/SubDyn_Driver.f90 | 2 +- modules/subdyn/src/SubDyn_Tests.f90 | 44 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index 9ad8c7298..d988c523c 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -42,6 +42,8 @@ subroutine concatenate_lists(I1,I2,I3, ErrStat, ErrMsg) integer(intki), intent(out) :: i3(:) integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat=ErrID_None + ErrMsg='' I3(1:size(I1)) = I1 I3(size(I1)+1:size(I1)+size(I2)) = I2 endsubroutine @@ -213,7 +215,7 @@ subroutine swap(i,j) tmp=L%List(i) L%List(i) = L%List(j) L%List(j) = tmp - end + end subroutine end subroutine reverse diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index cc6c4026e..f5dd61b82 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -90,7 +90,7 @@ PROGRAM TestSubDyn REAL(DbKi) :: TMax REAL(DbKi) :: OutTime ! Used to determine if output should be generated at this simulation time REAL(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds - REAL :: UsrTime1 ! User CPU time for simulation initialization + REAL(ReKi) :: UsrTime1 ! User CPU time for simulation initialization INTEGER :: StrtTime (8) ! Start time of simulation CHARACTER(200) :: git_commit ! String containing the current git commit hash TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'SubDyn Driver', '', '' ) ! The version number of this program. diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index b74f177af..b80f476e3 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -66,8 +66,7 @@ subroutine test_equal_i0(Var,iTry,iRef) if(iRef/=iTry) then write(InfoAbs,'(A,I0,A,I0)') trim(Var),iRef,'/',iTry call test_fail(InfoAbs) - STOP -1 !OTHER-COMPILER - STOP ! COMPAQ-COMPILER + STOP else write(InfoAbs,'(A,A,I0)') trim(Var),' ok ',iRef call test_success(InfoAbs) @@ -274,7 +273,7 @@ subroutine Test_Transformations(ErrStat,ErrMsg) P2=(/2,0,0/) call GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) Ref = reshape( (/0_ReKi,-1_ReKi,0_ReKi, 0_ReKi, 0_ReKi, -1_ReKi, 1_ReKi, 0_ReKi, 0_ReKi/) , (/3,3/)) - call test_almost_equal('DirCos',Ref,DirCos,1e-8,.true.,.true.) + call test_almost_equal('DirCos',Ref,DirCos,1e-8_ReKi,.true.,.true.) ! --- Rigid Transo P1=(/1,2,-1/) @@ -284,22 +283,22 @@ subroutine Test_Transformations(ErrStat,ErrMsg) Tref(1,5) = 6._ReKi; Tref(1,6) =-3._ReKi; Tref(2,4) =-6._ReKi; Tref(2,6) = 1._ReKi; Tref(3,4) = 3._ReKi; Tref(3,5) =-1._ReKi; - call test_almost_equal('TRigid',Tref,T,1e-8,.true.,.true.) + call test_almost_equal('TRigid',Tref,T,1e-8_ReKi,.true.,.true.) ! --- Orthogonal vectors e1 = (/10,0,0/) call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi,-1._ReKi/),1e-8,.true.,.true.) - call test_almost_equal('orth',e3,(/0._ReKi,1._ReKi, 0._ReKi/),1e-8,.true.,.true.) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi,-1._ReKi/),1e-8_ReKi,.true.,.true.) + call test_almost_equal('orth',e3,(/0._ReKi,1._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) e1 = (/0,10,0/) call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi, 1._ReKi/),1e-8,.true.,.true.) - call test_almost_equal('orth',e3,(/1._ReKi,0._ReKi, 0._ReKi/),1e-8,.true.,.true.) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi, 1._ReKi/),1e-8_ReKi,.true.,.true.) + call test_almost_equal('orth',e3,(/1._ReKi,0._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) e1 = (/1,2,4/) call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('dot', 0._ReKi, dot_product(e1,e2), 1e-8, .true., .true.) - call test_almost_equal('dot', 0._ReKi, dot_product(e1,e3), 1e-8, .true., .true.) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e2), 1e-8_ReKi, .true., .true.) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e3), 1e-8_ReKi, .true., .true.) end subroutine Test_Transformations @@ -313,13 +312,14 @@ subroutine Test_Linalg(ErrStat,ErrMsg) testname='Linalg' ! --- Determinant of a singular matrix - allocate(A(3,3)); - A(1,1) = 0 ; A(1,2) = 0 ; A(1,3) = 1 ; - A(2,1) = 0 ; A(2,2) = 0 ; A(2,3) = -1 ; - A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; - det = Determinant(A,ErrStat, ErrMsg) - call test_almost_equal('Det of singular 3x3 matrix', real(det,ReKi), 0.0, 1e-8, .true. , .true.) - deallocate(A ) + ! Commented since might lead to floating invalid + !allocate(A(3,3)); + !A(1,1) = 0 ; A(1,2) = 0 ; A(1,3) = 1 ; + !A(2,1) = 0 ; A(2,2) = 0 ; A(2,3) = -1 ; + !A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; + !det = Determinant(A,ErrStat, ErrMsg) + !call test_almost_equal('Det of singular 3x3 matrix', real(det,ReKi), 0.0_ReKi, 1e-8_ReKi, .true. , .true.) + !deallocate(A ) ! --- Inverse and determinant of a 3x3 matrix allocate(A(3,3)); allocate(Aref(3,3)) @@ -332,11 +332,11 @@ subroutine Test_Linalg(ErrStat,ErrMsg) call PseudoInverse(A, Ainv, ErrStat, ErrMsg) ! Determinant test det = Determinant(A,ErrStat, ErrMsg) - call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0, 1e-8, .true. , .true.) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) det = Determinant(Ainv,ErrStat, ErrMsg) - call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0, 1e-8, .true. , .true.) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) ! Inverse test - call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8, .true., .true.) + call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8_ReKi, .true., .true.) deallocate(A ) deallocate(Ainv) deallocate(Aref) @@ -349,7 +349,7 @@ subroutine Test_Linalg(ErrStat,ErrMsg) A(3,:) = (/ -0, 0, 0, -1, 1, 2 /) Aref(:,:) = transpose(reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /))) call PseudoInverse(A, Ainv, ErrStat, ErrMsg) - call test_almost_equal('Inverse of 3x6 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6, .true., .true.) + call test_almost_equal('Inverse of 3x6 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) deallocate(A ) deallocate(Ainv) deallocate(Aref) @@ -362,7 +362,7 @@ subroutine Test_Linalg(ErrStat,ErrMsg) A(:,3) = (/ -0, 0, 0, -1, 1, 2 /) Aref(:,:) = reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /)) call PseudoInverse(A, Ainv, ErrStat, ErrMsg) - call test_almost_equal('Inverse of 6x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6, .true., .true.) + call test_almost_equal('Inverse of 6x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) end subroutine Test_Linalg !> Series of tests for integer lists From 53d552485a404b31188b504b1e37d9be3e4372cd Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 23:04:43 -0600 Subject: [PATCH 166/377] FlexSub: attempt to add multiple configurations for VS solution --- vs-build/SubDyn/SubDyn.vfproj | 207 +++++++++++++++++----------------- 1 file changed, 103 insertions(+), 104 deletions(-) diff --git a/vs-build/SubDyn/SubDyn.vfproj b/vs-build/SubDyn/SubDyn.vfproj index 0af119b82..1be5887b8 100644 --- a/vs-build/SubDyn/SubDyn.vfproj +++ b/vs-build/SubDyn/SubDyn.vfproj @@ -5,7 +5,7 @@ - + @@ -15,7 +15,7 @@ - + @@ -25,8 +25,8 @@ - - + + @@ -35,145 +35,143 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + - + + + - - - + + + + + - - - - - - - - - - - + + + - + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + - - - - - - - - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - + @@ -181,6 +179,7 @@ + From ce7db79b68c6760d2d913a89b93bda28b514fdd5 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 23:54:22 -0600 Subject: [PATCH 167/377] FlexSub: printing wrong eigenfrequencies to sceen --- modules/subdyn/src/SubDyn.f90 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 8ac1406ac..254012fc0 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1844,7 +1844,8 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, bChec ! LOCALS REAL(LAKi), ALLOCATABLE :: Kred(:,:), Mred(:,:) REAL(LAKi), ALLOCATABLE :: EigVect(:,:), Omega2_LaKi(:) - INTEGER :: N + REAL(ReKi) :: Om2 + INTEGER(IntKi) :: N, i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) @@ -1881,7 +1882,15 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, bChec CALL EigenSolve(Kred, Mred, N, bCheckSingularity, EigVect, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion - Omega=sqrt(Omega2_LaKi(1:NOmega) ) + do i = 1, NOmega + Om2 = real(Omega2_LaKi(i), ReKi) + if (Om2>0) then + Omega(i)=sqrt(Om2) ! was getting floating invalid + else + print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 + Omega(i)= 0.0_ReKi + endif + enddo IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: !Need to expand eigenvectors for removed DOFs, setting Phi CALL InsertDOFRows(EigVect(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return From cd636bd60e7e996efdfe1c37d2ffc0990978d16d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 26 Mar 2020 23:55:59 -0600 Subject: [PATCH 168/377] FlexSub: update of VS project and solution --- vs-build/SubDyn/SubDyn.sln | 16 ++++++++++++++-- vs-build/SubDyn/SubDyn.vfproj | 16 ++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/vs-build/SubDyn/SubDyn.sln b/vs-build/SubDyn/SubDyn.sln index 981a6bac1..84fbc238d 100644 --- a/vs-build/SubDyn/SubDyn.sln +++ b/vs-build/SubDyn/SubDyn.sln @@ -1,22 +1,34 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "SubDyn", "SubDyn.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release_Double|Win32 = Release_Double|Win32 + Release_Double|x64 = Release_Double|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.Build.0 = Debug_Double|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.ActiveCfg = Debug|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.Build.0 = Debug|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.ActiveCfg = Debug|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.Build.0 = Debug|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|Win32.ActiveCfg = Release_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|Win32.Build.0 = Release_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|x64.ActiveCfg = Release_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Release_Double|x64.Build.0 = Release_Double|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.ActiveCfg = Release|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.Build.0 = Release|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.ActiveCfg = Release|x64 diff --git a/vs-build/SubDyn/SubDyn.vfproj b/vs-build/SubDyn/SubDyn.vfproj index 1be5887b8..4cb323d69 100644 --- a/vs-build/SubDyn/SubDyn.vfproj +++ b/vs-build/SubDyn/SubDyn.vfproj @@ -5,7 +5,7 @@ - + @@ -25,8 +25,8 @@ - - + + @@ -36,7 +36,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -55,8 +55,8 @@ - - + + @@ -76,7 +76,7 @@ - + From 90a3350bb19a009507791396442f74efeae5e9c1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 31 Mar 2020 22:15:21 -0600 Subject: [PATCH 169/377] FlexSub: fix index in gravity force for concentrated mass --- modules/subdyn/src/SD_FEM.f90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 76eb201cd..5a74455e9 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -918,7 +918,8 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) ! add concentrated mass induced gravity force DO I = 1, Init%NCMass - iGlob = p%NodesDOF(i)%List(3) ! uz + iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added + iGlob = p%NodesDOF(iNode)%List(3) ! uz Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO ! I concentrated mass induced gravity From 8558f1b65c6d96125a612d46a6e87939eb67745e Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 16 Apr 2020 11:50:09 -0600 Subject: [PATCH 170/377] Massive code overhaul with new Morison implementation Sorry, this massive commit will basically make Morison.f90 and related files new entries in the repo. --- modules/hydrodyn/src/HydroDyn.f90 | 220 +- modules/hydrodyn/src/HydroDyn.txt | 4 +- .../src/HydroDynOutListParameters.xlsx | Bin 96983 -> 154011 bytes modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 66 +- modules/hydrodyn/src/HydroDyn_Input.f90 | 72 +- modules/hydrodyn/src/HydroDyn_Types.f90 | 200 +- modules/hydrodyn/src/Morison.f90 | 4675 +++++------ modules/hydrodyn/src/Morison.txt | 159 +- .../src/MorisonOutListParameters.xlsx | Bin 0 -> 113539 bytes modules/hydrodyn/src/Morison_Output.f90 | 6956 ++++++++++------- modules/hydrodyn/src/Morison_Types.f90 | 5669 ++++++++++---- modules/hydrodyn/src/SS_Excitation.f90 | 29 +- modules/hydrodyn/src/SS_Radiation.f90 | 19 +- modules/hydrodyn/src/WAMIT.f90 | 7 +- vs-build/HydroDyn/HydroDynDriver.vfproj | 2 +- 15 files changed, 10420 insertions(+), 7658 deletions(-) create mode 100644 modules/hydrodyn/src/MorisonOutListParameters.xlsx diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index e197640f5..457b95687 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -27,6 +27,7 @@ MODULE HydroDyn USE HydroDyn_Types USE NWTC_Library + use Morison USE WAMIT USE WAMIT2 USE HydroDyn_Input @@ -1375,43 +1376,25 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I CALL MOVE_ALLOC( InitLocal%Morison%WaveTime, p%WaveTime ) - IF ( u%Morison%DistribMesh%Committed ) THEN + IF ( u%Morison%Mesh%Committed ) THEN ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = u%Morison%DistribMesh & - , DestMesh = m%MrsnDistribMesh_position & + CALL MeshCopy ( SrcMesh = u%Morison%Mesh & + , DestMesh = m%MrsnMesh_position & , CtrlCode = MESH_NEWCOPY & , IOS = COMPONENT_INPUT & , TranslationDisp = .TRUE. & , ErrStat = ErrStat2 & , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%MrsnDistribMesh_position') + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%MrsnMesh_position') IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() RETURN END IF - m%MrsnDistribMesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. + m%MrsnMesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. END IF - IF ( u%Morison%LumpedMesh%Committed ) THEN - ! we need the translation displacement mesh for loads transfer: - CALL MeshCopy ( SrcMesh = u%Morison%LumpedMesh & - , DestMesh = m%MrsnLumpedMesh_position & - , CtrlCode = MESH_NEWCOPY & - , IOS = COMPONENT_INPUT & - , TranslationDisp = .TRUE. & - , ErrStat = ErrStat2 & - , ErrMess = ErrMsg2 ) ! automatically sets DestMesh%RemapFlag = .TRUE. - - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDyn_Init:m%MrsnLumpedMesh_position') - IF ( ErrStat >= AbortErrLev ) THEN - CALL CleanUp() - RETURN - END IF - m%MrsnLumpedMesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. - - END IF ! Verify that Morison_Init() did not request a different Interval! IF ( p%DT /= Interval ) THEN @@ -1642,13 +1625,11 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I END IF if ( y%WAMITMesh%Committed ) then - call MeshMapCreate( y%WAMITMesh, m%AllHdroOrigin, m%HD_MeshMap%W_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call MeshMapCreate( y%WAMITMesh, m%AllHdroOrigin, m%HD_MeshMap%W_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF ( y%Morison%LumpedMesh%Committed ) THEN - CALL MeshMapCreate( y%Morison%LumpedMesh, m%AllHdroOrigin, m%HD_MeshMap%M_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ENDIF - IF ( y%Morison%DistribMesh%Committed ) THEN - CALL MeshMapCreate( y%Morison%DistribMesh, m%AllHdroOrigin, m%HD_MeshMap%M_L_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + IF ( y%Morison%Mesh%Committed ) THEN + CALL MeshMapCreate( y%Morison%Mesh, m%AllHdroOrigin, m%HD_MeshMap%M_P_2_PRP_P, ErrStat2, ErrMsg2 );CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ENDIF IF ( ErrStat >= AbortErrLev ) THEN @@ -2172,7 +2153,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, - IF ( u%Morison%LumpedMesh%Committed ) THEN ! Make sure we are using Morison / there is a valid mesh + IF ( u%Morison%Mesh%Committed ) THEN ! Make sure we are using Morison / there is a valid mesh CALL Morison_CalcOutput( Time, u%Morison, p%Morison, x%Morison, xd%Morison, & z%Morison, OtherState%Morison, y%Morison, m%Morison, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) @@ -2180,7 +2161,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Integrate all the mesh loads onto the platfrom reference Point (PRP) at (0,0,0) - m%F_Hydro = CalcLoadsAtWRP( y, u, m%AllHdroOrigin, u%PRPMesh, m%MrsnLumpedMesh_position, m%MrsnDistribMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) + m%F_Hydro = CalcLoadsAtWRP( y, u, m%AllHdroOrigin, u%PRPMesh, m%MrsnMesh_position, m%HD_MeshMap, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDyn_CalcOutput' ) @@ -2344,14 +2325,13 @@ END SUBROUTINE HydroDyn_CalcConstrStateResidual !---------------------------------------------------------------------------------------------------------------------------------- -function CalcLoadsAtWRP( y, u, AllHdroOrigin, PRP_Position, MrsnLumpedMesh_Postion, MrsnDistribMesh_Position, MeshMapData, ErrStat, ErrMsg ) +function CalcLoadsAtWRP( y, u, AllHdroOrigin, PRP_Position, MrsnMesh_Position, MeshMapData, ErrStat, ErrMsg ) type(HydroDyn_OutputType), intent(inout) :: y ! Hydrodyn outputs type(HydroDyn_InputType), intent(in ) :: u ! Hydrodyn inputs type(MeshType), intent(inout) :: AllHdroOrigin ! This is the mesh which data is mapped onto. We pass it in to avoid allocating it at each call type(MeshType), intent(inout) :: PRP_Position ! These are the kinematics associated the PRP at (0,0,0). We pass it in to avoid allocating it at each call - type(MeshType), intent(in ) :: MrsnLumpedMesh_Postion ! These are the kinematics associated with the Morison lumped loads mesh. We pass it in to avoid allocating it at each call - type(MeshType), intent(in ) :: MrsnDistribMesh_Position ! These are the kinematics associated with the Morison distributed loads mesh. We pass it in to avoid allocating it at each call + type(MeshType), intent(in ) :: MrsnMesh_Position ! These are the kinematics associated with the Morison loads mesh. We pass it in to avoid allocating it at each call type(HD_ModuleMapType), intent(inout) :: MeshMapData ! Mesh mapping data structures integer(IntKi), intent( out) :: ErrStat ! Error status of the operation character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -2375,22 +2355,10 @@ function CalcLoadsAtWRP( y, u, AllHdroOrigin, PRP_Position, MrsnLumpedMesh_Posti end if - if ( y%Morison%LumpedMesh%Committed ) then - - ! This is viscous drag associate with the WAMIT body and/or filled/flooded forces of the WAMIT body - - call Transfer_Point_to_Point( y%Morison%LumpedMesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnLumpedMesh_Postion, PRP_Position ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') - if (ErrStat >= AbortErrLev) return - - CalcLoadsAtWRP(1:3) = CalcLoadsAtWRP(1:3) + AllHdroOrigin%Force(:,1) - CalcLoadsAtWRP(4:6) = CalcLoadsAtWRP(4:6) + AllHdroOrigin%Moment(:,1) - - end if - if ( y%Morison%DistribMesh%Committed ) then + if ( y%Morison%Mesh%Committed ) then - call Transfer_Line2_to_Point( y%Morison%DistribMesh, AllHdroOrigin, MeshMapData%M_L_2_PRP_P, ErrStat2, ErrMsg2, MrsnDistribMesh_Position, PRP_Position ) + call Transfer_Point_to_Point( y%Morison%Mesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnMesh_Position, PRP_Position ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') if (ErrStat >= AbortErrLev) return @@ -2939,9 +2907,8 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) ! determine how many outputs there are in the Jacobians p%Jac_ny = 0 - if ( y%Morison%DistribMesh%Committed ) then - p%Jac_ny = p%Jac_ny + y%Morison%DistribMesh%NNodes * 6 ! 3 Force, Moment, at each node on the distributed loads mesh - p%Jac_ny = p%Jac_ny + y%Morison%LumpedMesh%NNodes * 6 ! 3 Force, Moment, at each node on the lumped loads mesh + if ( y%Morison%Mesh%Committed ) then + p%Jac_ny = p%Jac_ny + y%Morison%Mesh%NNodes * 6 ! 3 Force, Moment, at each node on the distributed loads mesh end if p%Jac_ny = p%Jac_ny + y%WAMITMesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point @@ -2962,11 +2929,9 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) index_next = 1 - if ( y%Morison%DistribMesh%Committed ) then - index_last = index_next - call PackLoadMesh_Names(y%Morison%DistribMesh, 'DistribLoads', InitOut%LinNames_y, index_next) + if ( y%Morison%Mesh%Committed ) then index_last = index_next - call PackLoadMesh_Names(y%Morison%LumpedMesh, 'LumpedLoads', InitOut%LinNames_y, index_next) + call PackLoadMesh_Names(y%Morison%Mesh, 'MorisonLoads', InitOut%LinNames_y, index_next) end if @@ -3089,9 +3054,8 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) ! determine how many inputs there are in the Jacobians nu = 0; - if ( u%Morison%DistribMesh%Committed ) then - nu = nu + u%Morison%DistribMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node - nu = nu + u%Morison%LumpedMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + if ( u%Morison%Mesh%Committed ) then + nu = nu + u%Morison%Mesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node end if nu = nu + u%WAMITMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node @@ -3118,18 +3082,18 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) index = 1 meshFieldCount = 0 - if ( u%Morison%DistribMesh%Committed ) then - !Module/Mesh/Field: u%Morison%DistribMesh%TranslationDisp = 1; - !Module/Mesh/Field: u%Morison%DistribMesh%Orientation = 2; - !Module/Mesh/Field: u%Morison%DistribMesh%TranslationVel = 3; - !Module/Mesh/Field: u%Morison%DistribMesh%RotationVel = 4; - !Module/Mesh/Field: u%Morison%DistribMesh%TranslationAcc = 5; - !Module/Mesh/Field: u%Morison%DistribMesh%RotationAcc = 6; + if ( u%Morison%Mesh%Committed ) then + !Module/Mesh/Field: u%Morison%Mesh%TranslationDisp = 1; + !Module/Mesh/Field: u%Morison%Mesh%Orientation = 2; + !Module/Mesh/Field: u%Morison%Mesh%TranslationVel = 3; + !Module/Mesh/Field: u%Morison%Mesh%RotationVel = 4; + !Module/Mesh/Field: u%Morison%Mesh%TranslationAcc = 5; + !Module/Mesh/Field: u%Morison%Mesh%RotationAcc = 6; do i_meshField = 1,6 - do i=1,u%Morison%DistribMesh%NNodes + do i=1,u%Morison%Mesh%NNodes do j=1,3 - p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%Morison%DistribMesh%{TranslationDisp/Orientation/TranslationVel/RotationVel/TranslationAcc/RotationAcc} = m + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%Morison%Mesh%{TranslationDisp/Orientation/TranslationVel/RotationVel/TranslationAcc/RotationAcc} = m p%Jac_u_indx(index,2) = j !index: j p%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3145,18 +3109,6 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationAcc = 11; !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12; - do i_meshField = 1,6 - do i=1,u%Morison%LumpedMesh%NNodes - do j=1,3 - p%Jac_u_indx(index,1) = meshFieldCount + i_meshField !if this mesh is allocated, then the previous DistribMesh would have been allocated - p%Jac_u_indx(index,2) = j !index: j - p%Jac_u_indx(index,3) = i !Node: i - index = index + 1 - end do !j - end do !i - - end do !i_meshField - meshFieldCount = meshFieldCount + 6 end if !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 or 1; @@ -3181,8 +3133,8 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) !................ ! input perturbations, du: !................ - if ( u%Morison%DistribMesh%Committed ) then - call AllocAry(p%du, 18, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) + if ( u%Morison%Mesh%Committed ) then + call AllocAry(p%du, 12, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return else @@ -3196,21 +3148,14 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) perturb = 2*D2R ! rotational input scaling index = 0 - if ( u%Morison%DistribMesh%Committed ) then - p%du(1) = perturb_t ! u%Morison%DistribMesh%TranslationDisp - p%du(2) = perturb ! u%Morison%DistribMesh%Orientation - p%du(3) = perturb_t ! u%Morison%DistribMesh%TranslationVel - p%du(4) = perturb ! u%Morison%DistribMesh%RotationVel - p%du(5) = perturb_t ! u%Morison%DistribMesh%TranslationAcc - p%du(6) = perturb ! u%Morison%DistribMesh%RotationAcc + if ( u%Morison%Mesh%Committed ) then + p%du(1) = perturb_t ! u%Morison%Mesh%TranslationDisp + p%du(2) = perturb ! u%Morison%Mesh%Orientation + p%du(3) = perturb_t ! u%Morison%Mesh%TranslationVel + p%du(4) = perturb ! u%Morison%Mesh%RotationVel + p%du(5) = perturb_t ! u%Morison%Mesh%TranslationAcc + p%du(6) = perturb ! u%Morison%Mesh%RotationAcc index = 6 - p%du(index + 1) = perturb_t ! u%Morison%LumpedMesh%TranslationDisp - p%du(index + 2) = perturb ! u%Morison%LumpedMesh%Orientation - p%du(index + 3) = perturb_t ! u%Morison%LumpedMesh%TranslationVel - p%du(index + 4) = perturb ! u%Morison%LumpedMesh%RotationVel - p%du(index + 5) = perturb_t ! u%Morison%LumpedMesh%TranslationAcc - p%du(index + 6) = perturb ! u%Morison%LumpedMesh%RotationAcc - index = index + 6 end if @@ -3237,7 +3182,7 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) InitOut%IsLoad_u = .false. ! HD's inputs are NOT loads index = 1 - if ( u%Morison%DistribMesh%Committed ) then + if ( u%Morison%Mesh%Committed ) then FieldMask = .false. FieldMask(MASKID_TRANSLATIONDISP) = .true. FieldMask(MASKID_Orientation) = .true. @@ -3245,16 +3190,8 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) FieldMask(MASKID_ROTATIONVEL) = .true. FieldMask(MASKID_TRANSLATIONACC) = .true. FieldMask(MASKID_ROTATIONACC) = .true. - call PackMotionMesh_Names(u%Morison%DistribMesh, 'Morison-Distrib', InitOut%LinNames_u, index, FieldMask=FieldMask) + call PackMotionMesh_Names(u%Morison%Mesh, 'Morison', InitOut%LinNames_u, index, FieldMask=FieldMask) - FieldMask = .false. - FieldMask(MASKID_TRANSLATIONDISP) = .true. - FieldMask(MASKID_Orientation) = .true. - FieldMask(MASKID_TRANSLATIONVel) = .true. - FieldMask(MASKID_ROTATIONVel) = .true. - FieldMask(MASKID_TRANSLATIONACC) = .true. - FieldMask(MASKID_ROTATIONACC) = .true. - call PackMotionMesh_Names(u%Morison%LumpedMesh, 'Morison-Lumped', InitOut%LinNames_u, index, FieldMask=FieldMask) end if FieldMask = .false. @@ -3294,46 +3231,33 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) ! determine which mesh we're trying to perturb and perturb the input: ! If we do not have Morison meshes, then the following select cases will vary - if ( u%Morison%DistribMesh%Committed ) then + if ( u%Morison%Mesh%Committed ) then SELECT CASE( p%Jac_u_indx(n,1) ) - CASE ( 1) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationDisp = 1 - u%Morison%DistribMesh%TranslationDisp (fieldIndx,node) = u%Morison%DistribMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE ( 2) !Module/Mesh/Field: u%Morison%DistribMesh%Orientation = 2 - CALL PerturbOrientationMatrix( u%Morison%DistribMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE ( 3) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationVel = 3 - u%Morison%DistribMesh%TranslationVel( fieldIndx,node) = u%Morison%DistribMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE ( 4) !Module/Mesh/Field: u%Morison%DistribMesh%RotationVel = 4 - u%Morison%DistribMesh%RotationVel (fieldIndx,node) = u%Morison%DistribMesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE ( 5) !Module/Mesh/Field: u%Morison%DistribMesh%TranslationAcc = 5 - u%Morison%DistribMesh%TranslationAcc( fieldIndx,node) = u%Morison%DistribMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE ( 6) !Module/Mesh/Field: u%Morison%DistribMesh%RotationAcc = 6 - u%Morison%DistribMesh%RotationAcc(fieldIndx,node) = u%Morison%DistribMesh%RotationAcc(fieldIndx,node) + du * perturb_sign - - CASE ( 7) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationDisp = 7 - u%Morison%LumpedMesh%TranslationDisp (fieldIndx,node) = u%Morison%LumpedMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE ( 8) !Module/Mesh/Field: u%Morison%LumpedMesh%Orientation = 8 - CALL PerturbOrientationMatrix( u%Morison%LumpedMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE ( 9) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationVel = 9 - u%Morison%LumpedMesh%TranslationVel( fieldIndx,node) = u%Morison%LumpedMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (10) !Module/Mesh/Field: u%Morison%LumpedMesh%RotationVel = 10 - u%Morison%LumpedMesh%RotationVel (fieldIndx,node) = u%Morison%LumpedMesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (11) !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationAcc = 11 - u%Morison%LumpedMesh%TranslationAcc( fieldIndx,node) = u%Morison%LumpedMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (12) !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12 - u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) = u%Morison%LumpedMesh%RotationAcc(fieldIndx,node) + du * perturb_sign - - CASE (13) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 + CASE ( 1) !Module/Mesh/Field: u%Morison%Mesh%TranslationDisp = 1 + u%Morison%Mesh%TranslationDisp (fieldIndx,node) = u%Morison%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%Morison%Mesh%Orientation = 2 + CALL PerturbOrientationMatrix( u%Morison%Mesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%Morison%Mesh%TranslationVel = 3 + u%Morison%Mesh%TranslationVel( fieldIndx,node) = u%Morison%Mesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%Morison%Mesh%RotationVel = 4 + u%Morison%Mesh%RotationVel (fieldIndx,node) = u%Morison%Mesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%Morison%Mesh%TranslationAcc = 5 + u%Morison%Mesh%TranslationAcc( fieldIndx,node) = u%Morison%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%Morison%Mesh%RotationAcc = 6 + u%Morison%Mesh%RotationAcc(fieldIndx,node) = u%Morison%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign + + CASE ( 7) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE (14) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 + CASE ( 8) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE (15) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 + CASE ( 9) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (16) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + CASE (10) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (17) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 + CASE (11) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (18) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 + CASE (12) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign @@ -3406,9 +3330,8 @@ SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) indx_first = 1 - if ( y_p%Morison%DistribMesh%Committed ) then - call PackLoadMesh_dY(y_p%Morison%DistribMesh, y_m%Morison%DistribMesh, dY, indx_first) - call PackLoadMesh_dY(y_p%Morison%LumpedMesh , y_m%Morison%LumpedMesh , dY, indx_first) + if ( y_p%Morison%Mesh%Committed ) then + call PackLoadMesh_dY(y_p%Morison%Mesh, y_m%Morison%Mesh, dY, indx_first) end if call PackLoadMesh_dY(y_p%WAMITMesh, y_m%WAMITMesh, dY, indx_first) @@ -3471,9 +3394,8 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, nu = size(p%Jac_u_indx,1) ! our operating point includes DCM (orientation) matrices, not just small angles like the perturbation matrices do - if ( u%Morison%DistribMesh%Committed ) then - nu = nu + u%Morison%DistribMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node - + u%Morison%LumpedMesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + if ( u%Morison%Mesh%Committed ) then + nu = nu + u%Morison%Mesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node nu = nu + 1 ! Extended input else @@ -3496,9 +3418,8 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, Mask(MASKID_ROTATIONACC) = .true. index = 1 - if ( u%Morison%DistribMesh%Committed ) then - call PackMotionMesh(u%Morison%DistribMesh, u_op, index, FieldMask=Mask) - call PackMotionMesh(u%Morison%LumpedMesh , u_op, index, FieldMask=Mask) + if ( u%Morison%Mesh%Committed ) then + call PackMotionMesh(u%Morison%Mesh, u_op, index, FieldMask=Mask) end if call PackMotionMesh(u%WAMITMesh, u_op, index, FieldMask=Mask) @@ -3519,9 +3440,8 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, end if index = 1 - if ( y%Morison%DistribMesh%Committed ) then - call PackLoadMesh(y%Morison%DistribMesh, y_op, index) - call PackLoadMesh(y%Morison%LumpedMesh , y_op, index) + if ( y%Morison%Mesh%Committed ) then + call PackLoadMesh(y%Morison%Mesh, y_op, index) end if call PackLoadMesh(y%WAMITMesh, y_op, index) diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 526a342ad..a3410ceca 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -97,7 +97,6 @@ typedef ^ ^ LOGICAL typedef ^ HD_ModuleMapType MeshMapType uW_P_2_PRP_P - - - "Mesh mapping data: WAMIT body kinematics to PRP node at (0,0,0)" - typedef ^ HD_ModuleMapType MeshMapType W_P_2_PRP_P - - - "Mesh mapping data: WAMIT loads to PRP node at (0,0,0)" - typedef ^ HD_ModuleMapType MeshMapType M_P_2_PRP_P - - - "Mesh mapping data: lumped Morison loads to PRP node at (0,0,0)" - -typedef ^ HD_ModuleMapType MeshMapType M_L_2_PRP_P - - - "Mesh mapping data: distributed Morison loads to PRP node at (0,0,0)" - # # @@ -139,8 +138,7 @@ typedef ^ ^ Morison_Oth # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. typedef ^ MiscVarType MeshType AllHdroOrigin - - - "An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - -typedef ^ ^ MeshType MrsnLumpedMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - -typedef ^ ^ MeshType MrsnDistribMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - +typedef ^ ^ MeshType MrsnMesh_position - - - "A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh" - typedef ^ ^ HD_ModuleMapType HD_MeshMap - - - typedef ^ ^ INTEGER Decimate - - - "The output decimation counter" - typedef ^ ^ DbKi LastOutTime - - - "Last time step which was written to the output file (sec)" - diff --git a/modules/hydrodyn/src/HydroDynOutListParameters.xlsx b/modules/hydrodyn/src/HydroDynOutListParameters.xlsx index dee38a4d297bfa73dc9c585e4410956b0d2b51b1..c9c2501e403038abb1c6af586b1b910f72dfbf36 100644 GIT binary patch literal 154011 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

ld_t3r#{em1=rvefhW`vVk=g_ zzCdq2K9pb1<6^0;Mt{$OsqKpc{0;R1*<%nMMAa3^BC*2=3NZP79eGK)xS=T_4D>lp z8ByHFgQ`GZLHp^H0aAlbN*EGKvGyR$QAXMZ4YJ`yBf6rKyO^>Y@B0=&P^PY9Sd`=Z z4#>4^N;gd~IEADs*Uo{;fj75y3qmfPaCXu%>Uq+7QkTeylBcQ6(U4J?+DW9RNw$Ww zEMrq*dII!u0I!OFG^Mtb+8`*djLlso9Vo14s9{93OlmDBB5D}sWfA1i-D?jBCTqNxkxtZpjG8LZwYWJdV| zxfa5w6#y*U3);$JmAC8upv)ftCk^tccqvb#rIh=^i!FJRTb)5B&KfZO5WA4s!a-kC zj{(*i+^JMF$|Fv=z>J{o1P)HxD(BiRzEQSZl83Pu| z@Q_88f0eJYlpC+?6M&BJYrrZ*F+EJMkZJ8^u%#4SVAeZg1T7&W70Xd~)G1-ybXFBr zHJX0#;OA-ot_e9L13#&X=+=|&SOyXn5pL8uF81{Gu;E_+h6lV1xnwFqTLK5uO z>|r5hz;&#&lrvN2Nwoj#tA#Vg6MW2U#X@-BKPRY)T&fr`*5M4jxy&avkH~3pR*;ig zAh7KQpMymE<7xmshpoR+Zu<(GX#e+VQ`8C~${(dC+6I6?L8SZ8cZJ%LwSh1cRM`y` zJs@SSSvX-j=hv1|kkT-Uan11=dF+exf#a5k=m2e`&;_nc@c>-K{U|WJ%pyui9zYgd z1#dMJ93WZ2mO#BtA%imVI3OiBkH6fgMi__hfP^R(>;>qBhiZ2IkY!OogoThRFY)KWRY_J!UINKq)Eq!6`U#l|v-_TM^$Sf!7Vjg13%a z4!;DxWH)phxHk9h9|(g|#`>6(xvM1NV#au~!kN-5E#Bi!uL!7-Ax?6PxcjJsC1gQ~4lR`iT2hGG%@XzpGxMF)S;*iHFS zAGqsKNEd4n1uD>#(sL3Z;Y`XKTp@npSqCqCUmlVCe=H?pY9j`vhx$EuFgu~Xl1lHs zwutw+@5|ens^-UnN7+NPhp{KP4YD|&V5d30Ks^dLFpgp=Q|Zy$p1Lvr52*d2wcJ&6 z+le4imRMUPRGa7dYUffrlw%Ab)CK@^zkpKAIOq1|wi#bU0Ue?9aS_-Z6~Bm4`*%u^ zTp=I>4;ZaTEA95`iK|Y3(RXr`;q|*EMJoaoMJe@;Yb6)1s`f<1mjsp36FC>EhY)L; zIaErQal;mi6W`fJ@NQRzzfMHsm&t&nbBlg5=(Q1^JZZiCQ1Rhqei1vDdk?La6`x!V z{&??J96L(HQsJ|CLH>z79mW`S6f`!rnm24d?>LJwV0D%7A$J~Kx6`7j(GQ)lIvUfi zNpsGzUuGK(L{CnV8HRe~T5yLxB6|=+!gZ}$L97Uqx33&4ZU>b`CB>MaUm!woLaa%c z8H@)%Qaq5VxDlIBH<~_m@e0)&TZ;r#q86<)%w<^1>$v3D-@I{!4GR#NCqKpdq?DAo zRl|o^e6ZfDc(qNcI8fP7J6>@=O>DJ^-0t%bC3_hNW5;rWK4J-1jU*UmSE9qI`#d&c zma?P7K^=jzDttN6e%=k3#fsz7NkdjSb4H|xVA>PuvTA?<5z-1K712i}390$g{tUzd zpa=ex*G+SR9_Dz_kB92lYe?T!@f-DRVjo(2q|>pqOgPNovegCo9hvp_P|>PZGuY*q z=;ixqM+>$<$vvLy$w0Ilc)3*ZdQyuX`}g2E`ZT*O5l1J1n~s|$>YF2aGcaAx^|7z$ ztSvOje=c>1gh4tTFZ#oEspd^z!GO*i@nUbzBz(G5;FXhAtNNz8H0s74c3H3YR&aD- z3tzto6V<`-ZR(6R{xzf^THs;7rRyLQPXgh{t#Z!%>zoOD(}ugY3WY6%9s|N-#!g9A z=-UlAy<_q$x-t2ApMT)kSF`J#-IDvXp))p<(UyG@*0cnM&~MviOTXEW5f02CRKCuo z!9ajir7O;`-Rc zJh1F5@G3_o!=NIDtF>c~o0UoYGxu^`*~ZAWqVketqYzlX?NFt&OuJ0_^S&p|5EHf} zI)Q#M4#6VIqmrB+lCuUNtfB4VS&@`JpxXlJ%2m_oiXyGtEuOAWsALwNeG+y?9ppP+ z2r|P`YuC_{3jVQZ_iiY+mJ&U<{c@w-7HziAuvQA8zV7gM(di^Z zG-)8K0m#ZMlqhIOEW%RhS*_9hMray_$WI;7&=%0KFAsZuhe}} zy;{_F@>PfG2cDvdce%#l+G&N2VM*Is)#DBc258V)+v<2D$F=GWLkhfru3^8qK!0qP z-8MPoarlg)?Yo1av^}}mcG>cSjt+qv3cmGz%QUa5Q+?Bl;NbJBP1y#&8EJ^*CyKRQ zI8+yRN=PN@n^XngVtlD+O#Wub{#bznDSBL~gD}d_y%G%+OG?0c za12K2Gd^qpz*+D<6f0s!ruC82@&3?$&D|*Hj zh%+SL8O&(A;G*9br?_{u(o%*+iwtr*z~p@H)}%dE*^+jZ_g*&>-yicjm`U8I-0j)e z$+EP4F@gGgOs{^hB8(yMO^Hy~rFb4hf=uf;U6^lH=$c-$9eJQzla_~MA?sxR>LTC+ z`%aiFYAx_-9-2kY^9=V%XV*r&U_sF4S|oBWut~?GLExyp6brQ zzI@J6+c~V~;fccVE}kXx@DtLPuOB-0>Fu`QL+q$;Ey@M&6Q-jI7g-Kh?`H&#?FJ3~ zf(P5%O#~gxL1Bs>i={P;sx5`i;rscJynA5{XoH(3^N#(!@M{@;o?%$*&i({gNA29^ z9Rx`00=e<%Q3Ct0Xq5kfYy2Uw-ahEeBlxxVKVfy|5_UeRnIx#L!3ZH`6oAYy?oC4x2Ejm<|@iX-c7 zk5xXBi}RER<28)Ef}9jZ5`hqwg0d?h03kO3<@vrQ))t1t|Vy6JdA+&{^7G_Dt&|Ift-u&E?A0VR(x!7b-6&2Dulth7_bD$54601{E%w^L<5DC)GEPQ)k2_YNR5&lXa;muEev^rsP}yV^$7sa2Z@2O zpis1{qFS{edZM*amBQos{i0+9fJ;yjL&A*0F;vKxKdcd*WnVBj3s(XpctY!k3a@n^ z((eltvgXOnyj$4S)b=Uh^{Z7Pm_O}G6NCpV%C!x%y z|H%KQ!Tr!$umMOd0ZZk04gpE6B7qL%nH|yz6j=wEfV)r*l$HzXhGa*Ujz=sN!KB=B zF02dged2Fpn!cneay=JX9Wk07Vnh*2w zHRy3m-(^0Ugg#2}$4Cwx-Xo^_v}lshL`b`za7tZm$A%Cq|1L|cTuZg(GJxF6^CjUI zz`4~^hd`AlV?Qy^M=YlYM_yTEYytY^o(J_EjgEzT?lvYsr#I!c8ZNrCOm`hFiiTMN zSOeCM^g~!=0bk@q8U+BIsC~fXklkB??FJEJ1DqcDp}Szui}{fZxN>Y4R*94>m5d6- ztt)x^c^fr)-thdXq}J3GFXodYwHgni|JVVYI$V-!UYG)bo zUtk#F+ckxb#+dKcezR$6*|uy5P2V2|ZO{K+GHh52z2j~{csuYybLLlRg@wS6QBPl* ztdCEJ&Ka~?hX^B$-^=?y7eYo(zCSDwFb=d~Y))NcTKAcKRkb6{^UIA_Kc!S@s}J-m zT}9Pvi`$8A?ijWks2)+j6 zLB04=F5L8T!ByX27npChF8wD*G06#;=7?(H>o6(ou6rJ#uz-)RAm<3Gj|@vuS4k>w zPkfjF15fDeBl0TBt=Fv#LVhV!g7z>(cBqlJcx_}Fr@XyiwSl5acLWQ#R_KV#zU}^g zgtn~zKtmWwy($^MU$;6OvD|Cima!vz6hau8beeW!S~>G&-#q#F&}J~atq*&Vmn9~Y z6w8a_6Q=ShAba;&ZSGu`^|PBaO=#RuLR_2Pj@xYBFyp!|8F%8gBFuM(Dp84@)0;5A zzl(=F3eSMP_MKU5U3f`DG-_^kCU(}!JYE?T=&Tpkn|CRH4QB)*vC}Twm%||?ZWhh% zuozc-MVqIzZ>e9%ox8FAL4vm;8m~Tx9#V&~(T(wnfJPnHu%Vr0z2TyZg}7D0hbnFB zsNrZBq}PYE##;v+rw_mMgZ4<%SZD)uexcjm`Oh7t4(GHG9A&Wnd3$O6wP$i31xI=n zR<=Sr{E;Z>B^OLwjjwvvg|t&H)0%G0hO@S{ngd+N&`vtizHJ)Jmt*swG=#7&$uh0G zy@Gkc|3*U|(gBzwK*I@k3D>j}wP@7FEZbZN>F4$u0La!w3jNd!#H)P;iR4RnW5xSv z&IH6ZDeCJn|Sj`}U<&1;%|CTSH84BP-B4wgwvR0Rq=Fde3&HsxQb zBQrwF0S3GnJ6SFIRRH-r5Fd@S$k1D6OE6Kzk%IQYqlaXnUH*CV4DB?w`0K5~1ztsc z*006{v}bh#8|ZZJ$6mcJ=;o1Mh-9JC#Li(HQmMiKw<=AnxGlEsos8%fMPNlALadx( z|Di;+plTqF=fS2`1!v3gBq~W>QFtC83LM=pv%{MHxUP;4h(+-f_h^mXRjlAhu!n^5 z|GDue9|Z*?eE{jK4(6}!V8kHvS2(5D^KWr5mODRq zzfumrp%`W!IXe6&54N&lu`V#V$oFM<^w2}3@RJlA;8dcwU4kr>9Y2Hwt@~Z7aoQqI z_=&j{9`@KF8&*o9G!ivR4R9gBSuNz6YI_3n^6HcY(EOz+RM9Bs(q!|`gF<dS1LmIq1v^1?bgo#AJPKs(k^XdW#u1p!>fej*iR-OBLbOlNB88>sdp)1Z3EA(s5w@AM-d@a zQ0HYBFvPEC5mh2AS~d$tGtQJ2O7$k2;j6EvHNmYQWV5< zLh8Ttm}d&TrDgE0?~fAy&x6*c39QqAGa}hfy`bgbd>NDol;3(jU~Sd__@KJ9&JT9@fleK0em5AjvQmcY7B2N#1 zz+iRII@27NapKw5`_Cy@CAWa9PK}N z59yXRnDVA=cr396q>#qJUkedP@=UR7tJImd3vmv@Ye{8D6uCS@boQVzD2m_>;(*(Y zdvQ5(WB^i-4d}M+sxDtCcN&94B=FP5vAFr-$IOmihd;xB-PwnvH=L5(CrCkYCTG>u zU@1sZkMlxh9=L8Yb#;~=Fi^c8_K$M}zo7`_$NgP>dBBpK{9TennBmX8#{z7+!R9o*&J1H4p%7qvbNM$&HTT6ao+_{qs9 zloKobd?xVMYBSNOqd8UM<3{8|c6z|w<1nLMkjL862UqYD3JCSCXMt;cALOU9*k8V{deH!Cs;dk` zcspC9<18u@Ag;@48VxpE3}x4miO-&o%gTjZ3oT*(uy)S7pH=7Xx?z1*p0X<(3A58D zuPwkfEFwk=3V?RW8eGL45ts?%>Ud%xXAB2+C`JlA2wHa8C&Qo0LHrz5NnQo(QV533zS&79UUF%6jH_nb$_rHh_3AuZhBRl(PiLL3mtu|FCC zCB(uPkKplVTLL%1=No|W$4z>SL?TX2aY?9v|Gcj7Fq{lEQ9KEH5a>A4luMlac)&r@ zA^W(C?joqN;FCl%HP#-DsKs|lfHwhq`&}LA77Bw>>I&3L1M!++UIQvPvL;O~c7h5H z#Ra-;@%22@Zk*I@nj8d528{>@9l`Bac$fg)<4)0qNbcmI9TSLmNAmqG*MChefeYCG z_Wo>qexi&*qn$q8=hTzLWs0y>xzlljlo#D*@Jo)qf_C_TB7nTJ@uiqGXgAv(Nb0d+ph2fr$cf zI6sT<0s`ihW2c5S{TN5$KaG0`7LpmTDIv&&dj2}-2~*KUfy$Ge-U?93I2wD(&lv>k zSY^c{`_IjYMrb+TXCy-l2S5(IS3tVLwF>Yq&6Zle4lkLCPor8M&~r9pM`a4vxazm> zFfJrn{{j6jW*FaJNrr*8fMWwZ5t=CWHm^(E)Twt(cBxuwCmyz9eyNW3(O@FTH$@cE zkVgy4{j-hTnxmMlcJ6z1y9O^!n`Xe7ZuSEg7&#<^)e`CK8dO8+;SG(03s5fVkpZkx zH;ldzs>FToIl^CSwptznQJTyvs_-4^f=}v0c>lyC2jcJ*9{4D4L73^lM98mjVJz>W zT4N1=)ewu|k42kV(38jNnbF+y;oFuWt@__G#=h0L4g8_AOVuCAnpJO(CJM-_@)5Tp zw@kMhZsfedV_!;*jeaD|E@5pTH>vSaPd+LNW28U zmtE+{1L2)X-HY+D6~7VT5WyJKbT0Z3 z+6b1Ba8tH8>TdIxpYM(NRAPVG2UQhKjt2)^>IrHCG8x8?@*t>D7wR*yUWa}oZX{Ki zVE#v>bV!C=N7X)Df&*MSbe&wsn>jM1$o=cS86|wo+deAu}&x;+@D&2wT(@rs=!x(_~;YChZerSEUnNo zH1t4p*FrkH&ORAb(4)=6T&?DU4bB~(7aY5~5nHJ8KW zc-X=WE>Qw@XgP1J5Ho}URf}ZNoEa>@ z&yYtONm0WkE4ja?UjCAl*Lh^VmMEk~Dt$4+V+3~03!cx8in z7QE*)puNJNjFi@~6R;uHw-8FQnXm%c2FpNb;1w zVW)qzuS1j8ZVwy;H3px0Vc5jrZLFf=;X_>i^^HE#s={wzyF`1thj0-AD*1DAFy`UDAqz zpfqf{kx*%*q#FSdQA%1RBm_ZFIs_y(-F4?$;B%hyp7-7l_me-SbB;OkKVq!~XE+Zg zS#@w{1HI)4jiZLIirBgLHa2a9J;=2BK)(t4T+c-=fY)tA0Iwl#SlWD$0cQO0Yv-`U zU!@ot0Mqa%WGiP+K>UO-;VcDSH%d)rU=XQW`E*d-T@odU89E{QE?^n{tOr7j59c58 zz~87sLG;gn_xIZ~GgtpJK%M9YRk6#$w^Rl&89wWzJr2h$-Q_}wub=%U=k5FOH#tz4 zjhubcgrefQQV<880EH3L3I6j<7CgEJ-eQLtG=Jzq2$TgLm!B<43H|sxlm{Y(HXC{aPI{f7y-ugC)5?n5yHp3{K}2j-L!ehCAfV%n)bZBqlk7OrX1 zqx9#vksK8YO1bbFJc@_jrWgE}CesXya~G6*poP|ugdWsH(u`kT&H{6AcpTnq4n8x2 zSM$O1cE1r&aXJvc0#87*ra*=ci==t^6M7FBd{1ir(h~UK;~$4(%kKP=pGrQ;vqH=P z9L%11D*Vpj@C2Hz?9QaHLGNCJ*C@|XrWNWYB4k|8p0+6dec;L?VwVKHrw2jv**CM8 zGvLif=sVxDPg8Nb7n`W)gupBlOO&-4`U*)4d&}&N%3SGJ%O`BR#*Qj>?7bsX?liJUJwh} zS0>-n{Id=}eo!e7nCcTywkJ)PBK?e04`-*#kD=3`gu9Rq&^{6T&Jz$Kk?=nJoBZyk zXAnMr!>B=?mWo~+nhCV-gJ0D$WrqelsIlv?BpLc8ufSdrM4q;AgZV5Q&0gqCd%#!5 z(4em^v#&IPTJT?EMX(8)hnv99diK}9Q$8-TbNY1Li+p#wcWA$Ec5>=>I+Jm_&)|15 z?|0mG`i$6Sedu(Lf9H)Y@#dbH8QoCNe#1s%y=B$JNiP^#cq2~zPj~z#PDi%bXl~J$ z(oJP$^jcsFE_f-Rja9RB@qS^bxtDmdRj%Y8nc6Qm-MC0TY`Cl>5ROb2U`GB6O7T6ta{DiO(|P?zvqv4Oytpe0@=A`4+vy3(uSs zZf9P73oFfRD+MSis47U8x2uJ`4(ah{9bJWW*gOrYBgy6ij9O{c8dj1&125%iMNen)f;|IMX0$Zvd<#fKdsHAsvN3vpcH?yn*5kqy@v zM4ZvR=7nF?nDLg>ZxYRYbA*13zHbWs_@e*p$1O>}n)00tA%Os~O8$_Vc{vam!jN%|4=&i}0GSiZyN>lldcj_wpNJE}k#69g1Io_j&;C^Xm41n%@qdG9z`tfWN+dbMG%q$$ybxzYBF@9Skv7*OhD z`EjW+meCvWe&JT2qpU=7aWGO_8}NQHyC=$Py=v^TdZeK(xk73Gd4rB}ZPbIe7Af)N zNru9B@uVp4LXEca&Wz`qZN7V`G>s1p>35$osB-a8&W+=5FHFhsQTh}bWekOQJS+&@ zavt=0!$8n)MLCyzteGrP|21Yv#jgx^!S~L)Dzc59#oT)BrLi2+;CH;^Hmx+gnMtBQ zLL`vBg+#zg;}H!oGut(rvVFVDKnq1FhXeha3mxXi&ysr6bn<;{RQJ(q8T96jj$P-? zf_K!eUW$5__ro~JivyvTaTl9@g%n~-5%Im?B@$O?%*g_krbFOkSBvz$5|ZA?0{-hp zPr)Ti+&`l!gquDb2)>Ne^q-OxeCp2YdI_U@ks7)iMQj7j?8v$4($Q+5RJGC<5)$z= zz0MFN1#g=^XXEI~Ifyl>y#brK>V4}P{@!JseJ`72C*wzz5GM&+>6n*R4ukP(8JuQI z^>+O@MT5q!crxNOD#hb6mMi_b#4POSkICU45TX)`=(DT5{AuYsP2Avz*VBJ$kM{?! zvyEskt#1vb{Y+a3e;sJPj@BgghD{yk4)(hgC~o2iDR zZYWm86vE-hTZHQEo5^1%Xe;+lE=2xJCis~4GZc%a47e)SJ?w5qLveHEBUx{d=S6$(;%VdsD`bvy) z?N26fCpQNqvXR$6RhY|UP%2USYKwa)Z>oJ!yVNycJCk28AQh90uow^LbT|EFoI=V9*sFrOMv(Z%|>^>FNWQy&-0b7i*FaOf{}QExi6#1iz08tShF z8s5J>ecPAGlS3L!AN$>x$LNUVp0ogT6|th=6=%dk8sP==H_)+N1UMF3-`RjSVET}E zxP~0;&DwO6q@1paTXSw;cEEhXYF93bX_c5v=!W`Ka_vnzcWKx{+J#K+L^LihLu18| zg|z3-xec&8FV!0D9s-&zh5Oy;KPh98I4`fh;~TEoB%4sUlk=w!MNuCoZSx!YX;eyn zfiW$K@OB2Gq;mGggM_imcV(?~%8_n7S+k$-u_3_iXr`~7w9+a-Jt7{W0;|c*>qDoCZ?Gdox~x{Ps)VN_*bRnEmcTS*|V{__cGFDnShO z7`!_Dslj|yTewK!wD?{Y z(y@v;i_`Ho_NE%o`2F0GHFJ5Hs;TD$ZYVL%OWv;tJ49t^z>hmUzFOFOg)*L2B*y^) zTtJ0O3rU|4hSo=^n$0LtqTVzz{n_`o-q+Fo=&LgSoqE&mfS03kvAYYqZdGurCq%FQ zIF8GcW2xClO=*E1S+G&s{`Fo2cMD4NEuJckP(3rVzU6anE(4RNpNWi>XCt1k$(;CL zUAY8Yj453dpKsRw>mEC!qx>c6VfJ*={-htelZoLWI3LCY$V9$B)Va7?(vJ8kWA)24 z#2sa6tSMjCe(7${4)7&b@q7A+8fK#fwvpEtd((3FU%ze=3J76;TMzlr?ofnrOiXnj z#GCEX-5Boc;oR3_xNX+QE`Ma!|1^!`%;Y5hh5D`DY=pt+9iYiz%8jw`aZbR<-7I$F zXO8lSnrtAe(2cEI-G%1k;l?qF#xWstd6yBhqlSRc%-lR=ncSR9!v8aSW2kaM=LUe^sswXd(lEjUh=B&`~0TwlTNh?$>|Vv&^zJg90J; z#_hcv;1iJJRTi__0)9TKByFYsnm*jbe)!^Tb=7>!*WhrjB;>sx1~fv4&)t*xHL>@5 zOt0CNyhzp0`hCU2@Y;qbfF~ZiO6C-#r{T41jCWrk5845KA8`#K^|t($j^p|fzv|}v z_Q!_(t;&XshSJ^L)RoPjGcNOk+7pe=_P^{=45p`Exm!z9n{>>exG@Ggkl@Skd@GFj& zHruv$egtK(pUz9#*}duAHM5tb<$7;=G`8Z`Xx*@ni-vZ3iixJ7jEO~ohJ%KOhK9z3 zHr;WFlyDRc?M5^%8WmV^f6Rxpcd~W1e(=D>nGgO)kk|dm<5y{8k+cf2d8?GeNJe+Q zx6^Gb*Rd5bi-ZS7n@o9jc2iUn?#eyOekos6cWoGH##hDlGBmB1!Va_Rx#vLW%TW5u zzWuGO5~l}dC+jEkl#LTUAN_Wx675aZ%*H=@JMMlRA(8xe`1{So$0M`T&7Egozf$gI zj2~^Zre;VUIqi0T^&1~+JW8}b-Sj&+SY?nnSve`Ft5fH*2{A)8dhCBMP;d0zUK~6g z$v}-a)|_s%zCkt)oX)k8FibS=>zqzR`T4k>F16JONmfd3oy_ZRc6aYA9;YH3KUNZ$ z`Op@vPqi^j)Yp3*Pp#OmuKMm<%1ewNAI)iR`<;HTGh59luJ;qwLLH|@`5mqd@s0bs zpW0qsPee*K9&YvOZT)_>Yu|WK)p)WoHIv$SWPCb)n)E}+-t1`R{&7al$?C?|wUvpl z9QA&?J2Rn&B$B=d6?(o8(zo9Lu6(xVR_2usb{V(?O5cD>Pf$}B5{W6N_h063)ciOy ze!Nd|X+(n3i>fTj?05$iYHxaS_$0X#IrMwy*=l2>_vvSm2_7@!Q&+==y_4;gkKVgu zOH19}`+j_l#|NRvZ34-oQd94bhwG_{6RKv%9t}N0d}cm}u7?E2t4O3@ibIi_=p^hlwN%Cp&AQr=^{Ci@0M| zl3Q!i_T#>uyN7AV0YjT2lHR+g_J=Nqr;7@W2S-1T{d_kZM;ca6S7x3upnSbIM|v|( zwx;G!H&LPLl0KUo2fr)FA3J;OZzFa7w?Lx>J`!RCCu?N_)S$)2*rFob^8%rNkDmclhIX*1sS8&Wm@gTi&)`H?Ti# zrCz%K;-I&UdgSQ0cahn%n-a1&7OieDY-dE>c)9UgB=PvV`15s*7b|aXAJ5Nc#gh%r zPJSC`ba|(9x^GZ6>RqEQG?Yh^yzaDJXGQ60#M{fVeRN}yZ-@IZw(`x~l2FFD_u+OM ziJzb5e4OXCRX?9ieo=KZU9;_sZCmrip@w4BmWld_x-|b=uU@5%*$=0xH&)+uQX2U|&r`iFiaPf`NUa%Cj}6TPe^Jm=YB2DY1VnFB64akAt%Lx!*p9I+L1)ElUykLVbfet zuC7>(;+3etSE*Wt{R1d=M++xH>dVr1qR1@AwrCkPTi^7?)fp6=bk8ficE27N&1gbQ z*BI1Gdi|b8!D+Wuy9+%tBPUx}^&jEew=dXWJ(f_o`#Fv@n3YqyYw-8pch&3Wi$8lGbRRk}zVZN&;3C1Y6BmJ~=5i0whV>I1+wRWR$Hm&6J|MXZK5 zFv=tpA;s)Hnd4CVy?-B zWdwzJh>GS&G=HF_<#zPL{!+6 z`mQ9|dFT4yq3s{{xyZ?e;8b0CQ_)LtFPmPqoL}(K)&#b;c82e*m3w#7pkK${I{f|<1So~Iz z&q5rdfp=(I4lRVF^Oqsb`X&5T4) zoe`&OkN^BvZ7HzYuq&i|?+4wX)k?GKgA_|Ik~iwL@O@gF1f2W9sXPlrKXy`nC>HA zdbWmKfY|{H_5bHW_uqvxLD?1~Yx1w>71hh`u2%u}qB%9ax^6)H(jBOv$J`25;cWJr zf-m~38#bHh^CPfrz=_bmCkmWl5*E+8RJn8(BR`(VERQdK5Kh$@XMLnJz@c6BQ{csQ zb|lNs`d`Ph8)A10wT5}LtA082T71^Z-K;=}pP0DtaGC{1CfAOoJL9Xji4#>Wx!}~ff>fR1 zq|piS{ue(Z(qFL6st(9&S4}wI$5;PSo9j-ktovsSGnxE-|G?F~SIX`p>^{eOTaS5| zklDT|N~#?-!GkJ^ROv)9ZFRrY?-$i%-^c$+zCEl`N+>Z!R-s^Y zs&IEnn*8Q3l~M$}aCoY4uq3UWZI@cKRL*chUlfrAbG zxy!Ghd^sN>?TR6K>OTc#JKx6yqQy0eTzn4g*gGGPRCcO&Vp096Dab!8#I#a!8`D7$plGZ-@#hZqBNd zJ^(!Z5O2XR&$i-a^2#oI#W@si?}Yq}eMyQ-@y_CxsJqVj#-a@!^~x5#7hGnw^T@X6 zsaW|PKQnn@(U{BkmfaG&|18BN-}rt*$FV_YtyQK_23JC%wpFL=eClW&1x2@1kc2Lm zW?jz!^&+`G?GJI2m9}8oh5jlMH|_{=jE32REe`9JjM`u7ytqGrd~z>DwaW}AW=|rN zcP?x#feT$%RZ1Iuk0NA6Pgph3xjmhtWb?{{tZeAE@DroOWiFkw&YNBvo_>J1@M1r1 z61!v}S=oK=lIw;_>6pZ|m*ptZFaD4l^^RuSr5A0Fav00(;8{08&bAyb;+b#E-PkcE z&RdDD1vIm;$ET^^J5akyejgmD{S~$OTS~dnr#y8qrzgGkZF-#-qgSx#nefifYP}Zc zJbT#0oXPj#D-Ol!*e0u=cD>)#U-*F9#S8G)*{ILGbV`hvG@je>$_(%$yU;B7ZB9L< z{JWLSll>VaiOafr3v+okhdwP(-H4S<{XTx;T9>Lnmfltu+xB<4I;~P^NywQBvB2Mm zlLWD~E%2WAI9R!zUYgvX@7-HS2*3Ov#TgFxX*XIpAdM7NvHwcwBt>JlUd_PLlHy7W zFKlFQqEHdO;NM{qi5!!U!WWjp$ONu|k>bRI7Uz|SF+X=PrfO-B-w`U{>8YpSv(`4FzPLJEt`ItD?WJk;>Vd&do@ESf&$(DnJLVqerCG4_ zDJjH^pJ)>O4!IkSYH6zEl-9d~^cH4)W8LfI=(ib{iBs;5__gG*f8n9UF#qYIVf9ZH7K*l>7ng%M>Yhk>G5Z-a`v&NcLRQ zR}0BT#MBzd_tAS}WAT9X5 z46H5ui05^O7~~T7dpl%E*N|A;&#fjd+PBDqOPPd5%dhUF z)PiQ}58UBhp7H@J-`Q|I6hhZoIAU zkkkl9D4u0(lW;UJbHhm{A6fcCVldrQ!K_B_k6)umzm0pRI@mQzgC-w+7VXh=jyp9I zI8&j}PV^nk&0mmBEQ$k{J_(JBpRhha=en6po@ct{8oN6SHtQEa`Q1m-YyJ#LQrg)) zIkngsseDXc4?S4!p-G!FEI-WNb59@jB|*b^$Rw9o(yF}^j4f%u-pE7Ted8CXCELC}QrP~5>8O;Ka_q~;f;Ae_{Za5EG(ga_6YK4rM$%{P^7 zq+sLjB)pbR<3OS`95V0?eTFwcke^UH3$>JCMRJW0?4+&CL=7(~=~olv#)3G2>G39^ zDQT!X?0QjPE?^W>&~FI*p2TKH3TP_WxgVJlPZAbti4%+OAzoopsi1KbhK_tSAYR^; z%Bu#vTuVaJ;79&B6nu%xUT`r0U)?#ijCHiZ{&6ytFVT4q8~T;@fB$e zhv-yIIs>>5ZZMZW-3!0*2uKBt3Be<@)N8Eer{47Lwb7bzB0$cAKnOWkYvfJtxDrat zL+)h;A#n=O{Kv(s#(H;}WcKR$nfEe6r z$KrkAvjef{EQ$n)4%SK8Elc%* z5FMeazlwvk$o>A>OqYZ3qfs!bd%hL@Fqg&hTGN zJkfQb)i|1z{jX-IlSXSO4ls%a*eumu#=pS}bz6txxmt+>6XXxnVZz%$|L0p!-^AvB zh^wO7`Wx}>~HVNEv3^And6i-^K4;j6)AV8uRYEdZo9!>!=T(a zAzR|{Vl7oMUmh)yTMin=olh& z8TP}v>ARfEGAYi+m~n@73Ka#wGlA)(&zXjeXV6EUsPX6-FvC+uDqohCSzjJDFPv%| z9dNKXb)@EP@bMW3P}c0>153cmCs?+y0j85xa4eotujA$gqI9TWEeDkYC%2pbLPjQg zaHVA7r-4@96)z{_pjyhZpEH+9-(={xj-PCGe?3f`@I5}PswKk98@;~TyXDAcqgyOG zS%V&m>x>awp52D7pE!U;@!6W#mml+o`K4$qV0p2mXT*{z&TBv%qpn6?HK3|zISXjH z!nl(BHAv2D1Z$X%_$lSOk9wL(AP<_6MWZQH_BT-|RdOcwHFsLox>t!1ukn&1r++Fq zKZ(nZ%;00h*P%0$KNNV>qL+70CyE69ai%^keV6<{=UzILF8oA zPcoPN-v^<>@bAhWqXZ2$BngOxVjX0YwlMKpkh~O`-qx}gsCwUXbqntWfI3iV2kl6z z?3Oj)pcXToT3PB652ON)`}hfenPO1xphu%wFlfowa53+H6~q8VLo`tB+~*9#(Fup3 z4-%t*j0`Z%NDYc^@Ba~hH#WsTyDe0BulYiIAYi#LmYW!oY>;kk6fyM40ILr!GXX%D z_mAGfo)IQKm#hl{4X{RqHN%T;SdNzs(6E|yPkOjGK8Rs}$l0T$9xoeR_rwc7VOlSb z_Q)K^vY8oX%Lc>K?t!>}CoC}PE&GVPL1>MpJeVGrTe z0mTLf=AVq3EOISpR`Kv2Qur5o}3I9$&&zHq$?^{503WIdT!C8#0-<@%oV*n_8UTsj6m2v02RPJbngK`8v#Ul}Ni4!kQd@!CEoyo)}Q33mEKx1Q2OZTSWEmp#F z&^|sRhE|0^%s^0Sbzc$WO#I{^1|C(EgqajsVeH#nWJ%7TA+ayemMeR0dz|zceUp4o ziA_Qm@R7}aB9Hhp#$enSuRJYvXPma#C1))Y^<~s{clNd5-UVl5|H>QWUfqu zPi6*GundCoM%F!F@hP(L{-Ilf34!aam^B) z(fzaG!I(hPjZ7s#1jNs_Z4TTb`ztj<4FUuR;=*Ok7+`n~`2APSZtvP~R@MX4K=t)Mh5$8- z8xv$y2cjSH5VsPbZbQN=-|%3nUt+6qhOG6u&WuF>^)Dbni10sxwfxZa>}LB%|9!Jd zJIspoSmR*woqzLEjy43F7xogE6%b;7eFE-x{y)Vjh05H#jxiNhxT*(G_CwrN_U1bU z3#V0(@BnlurmQvP-hc{yBuI%dN+vctpewh9gAm?Pn>*gm==B3~qwzemUC>woy+w<| zJLa|i@@lC*7TrB2o&+`k?+g(A95t}HS2D&)rhXsa{@ybPc1fP4@kT)&|k)=U*Y2U{e41Dk9cj(9y?mO8AECKaG(cLw{NTLWA$40XJ~yT|~(0Z;afB4h~!)2MHvKL7+*Pj!Kk0^@Pz&XkHfQ4?L>Ttc95U}L zumS!KnPXEo|62dTVC9<4uxCgo$R+~ul>d+!I6R&GQ3u<%vd<7I*us17HFG`3)9OHk zDoq)l8OCq7eewBuq%5bELI_%~ypIrrpbg9m?m}FNCbonzCYU<5r}KU$wwHtS3pH*Q za-bumwP)}ih)2~VIVUe(Ej_GCnSu63f-8eJAMkql8NC6pd}zBKpknRUS`Y-j?964-=Sl<_F$4@C)KT>248W1V#{Y~PEE=s| zq}PD(v4z6llB95!9#<8NGJu!d$3Jf>-v+y??;04a#{dra>UpfBMR3ak|DHlXWnydTU;P2SPx-Z)YqByBVg3oQ9}L+VZ)U%X zhW*)&y%ydEC5SWk`4qU#T&D$)^3YuJWit&a%zgzt8kt3*??{8uz~a-#(5Sc$KDiup zY;YSNq_u%#qa?luW0+jYeBrhiU728`jE#Yw^bD<_frdeVZ8;1GV4#s*UyxSmGAcnN@>0d6%;E~i(e$X7=qJ$MDOkC^k)5B4_N-m|r_RNpA|cYoVrnu?-* zvM_9rKtPvLLYx2q6OQVPaLYy**r5T@U@{HpX;7+-1>C+p&hJRvev+TF3O9W3q)_zJ z)N<$HFN6VsFYLu|vn)`ojaVef4#;7B>w0 z_w66B_p}x3=NYBmN(B4*@Xk&e6lqo66s`r}u9r;;jf9+bHS+A9OdHQtgj!?$l^e`f zAdDF8m5UWGT~L$>1VQ_#`#)LAKLJ>9QO}BtDZoGj9_@UAREi`5U{@V3C%~r8A+RV%Xo1 z5lLeG0SMlZSc5EqrO?<_f1s!P&)f)k+f|Peo*SKuQ6j~2<*z}&v>c>kjJKIx6{yRT z)EarEMyb`S5A4P;KLuX@3MKOLz=yzB6cT}xDG3G|f{f_&S^Ax;E%`jCiP6iXNe@~G z&NSi+Wp<3AOvoD0s4ZKl9abZOKupQm(B-f4E395FqaOr7IB_;D!iMOajkXk?IwRFl z;zEn4r1O4L4d^Qsa*Fy+&TFx zeJ1JS6QRDPZB1Q;rSC#~t7g83+p80(1D;DZD<_5v85uT%UMtR}{p<9ReyOyl=GZpP z`Hg8(*b?FX-$)r=^%^Uoqg#A8Q_p11Sd(xYej9(Ealk~U=DX1GF&5VbzWwJAab;lw znK1?Ij158po!Pj9fNZ&L$BT<J%WJQ8xGHM1em|OB2 z^QGh^iiEBh_`RehZ=P+N$WJ{=XHGa^)%_#lNaCU6q=Oabm2skYy$IZdi|y0k`dV;P zuxoa_z^pee!dr%3zJPPEyZ@DXJB!6#!@ik`r`}po8s)@Sg>MFS9J?QgF(dYKh295^ z@(7CrcGRn9C;*0{6*PskJJv~6P(EiHs^ASW(1yke4sb$@V7_;Nx>ztbaQDy94mdJ! zm13EG@WuDhV`5{vDI>$a%|p74D~mQ<$)$FsSKDkk65&5}ZvAi-XW?7xWH zy6TWRdKfQ;VTZ9FEEaL_N-6Rccod|aqz}tZ7cy0iYJW?hWFX?Gm6J@ns#%y2wXWX zp^%0Q0TEx~L?W`qY^;OVJ?QTcq<+g=j9mHVBPTAeNq-|(x`ku;0=`)>8V5wIaOQfo z2WOQ8hFS}Ia1jRAhN6#rp9pW8cA;p+!7;@bilQbCQbhJiL2XA$N}_*Ixog^J)Fv5F z3E-Gmd+cHNe(-S)N~kBUH%rWh!RJ+d3w>d2U&`*pXBX z`RMFRRF;dt)!ls}ProU%W4naQg zw7B}q=q}*;@WrM}<7-IJ7uoX>!YwlBZY}HsoLVvJ?Ky=k#j{j|?8qULYVBN%45@op zG}U!FG%o>{>^#7`LI}G~1eb6RE2K6)$z97y&`pII9O611hNOk_HErReLJx!9~>qP!@lqP?|do`>H1@6fKAhf(CsbA zadh)SUzCVS>58}oZ6Gr|5;4~relgj$Vgjv4^Q>JuB{c#B?X2bi zr>@g7Hi+U_g(g!*NUv{nI{GLfNl!GnJw^Nii{-|&wy_fj#7G8$Rg-k|wnjNzn{l3J zNBjYX6C>kFK#1=u*5BznxYA~RMM{4-SXrLyz*kF1YwKfK^TjV2LFl3ub&-Pwx6Ux6dJt-6b5Ym{YW@oLF(SHNdB3eN5QHKItl1vg6V5^as$G;PCPhqbsma) zI=O+X9N(x~#*6x!@ZH7=-YgC+GJHRnThW(1+T0#H9;q{1e6}KF_M>2B!gs7}VV8YZ z;(-sAAP(?GMRdP97qO>I8EYTasC4zVTud>TW!)pR|AbwTm6-BK(Lp>g64G%|SlIR2xM_@04*J&>yxEOBCJbJdpnu zL-*8M=BDDjQl2{a+Ev{^Q=ZN|&w}cUp9T7Ri^LuTx2NxzMO%^R{?M3fulnB8FXZWC zU^klv@e7XSTVOLt2=8UE8(PcKxN`%S)a=6)8u6ThLpu`(Vq#6rbpq5qWyS7h-5hAy z>m+HvQ0Ib4sRgec$VcahQJ4!X|EiJU+E)A&hN^6z@fnD|Ff)UX6>8FRpAW?4z*`FO zpWQL^1kviP9pL8SZb^0Mvv3KvY1Q2JWv5xD90>8 zrzV@h_h2n}r+@wTod$AgW|6*P!9AH4j*^5~Z#Qnw126n)lBr}pHU$^{8fQk1${eLP zqNH@SciUF2g7}_CalECTeZEtBD&jOIjYzlEty0o%TnZb^gw(U18<}T)(nU%~@RqvL zIRtP9#Mu{6aJlly#^8515710|PT9*t-#NEeVT0dXpNLCHGa>d^vt=seUXH>SULga!5QqT2E4EcyAwuFVxKt0{c7lEo7xe}Ze zV?YJmZSJEp6`Q>OeU>*W*BM)PI!?#6cY3qKJ9K^2Ne&l4L_-`Itm8n}HgI3k=;2lx zcOh(s646DyN2uD?O%Y+lSVa1>+|G46#8rK$@ltzf&q4!dGhfm(U5ncpj@?UV;lB#YNCT3NeuDj&?rmqYOheY zFOZ<%YNhL}Euyc14f$(l4sD+WCP6DN;7Th)&LvEw=>u(F^Xy5jGCgS@I_wJy!r8J9 zbXr^!LFusv((m~eUooF~f?`N@XH2Ff0tI(>e?XOI7i^LZfWUz%`HCHHis&@E!+aV= zEw3+hDyvMy8cjhAy;*BVfe+&)aO_J#+-8|qJaK`e;kuzPMs9FH;Uo?o= zxT4@vxNMLnnFnNBj0+>~3pYS)f=n4U$e6~hx3zVM|9+8Jt~}CqEoA*L%z&uBM(gKW z%wB{d!p&c|%hpcJ!iN>w=q(0x;9ge!JB*lpcQ?k*G?Z)47hJh!?D&ud# zu})GtE`%OkyWwJC|B{+q=t6u+gommL@>~t|D2>-BZ7h#?7LmtN7Q>K?{OM5Kz5zVl z%;aD0uL%T+$%Dex|A}yRP{;8{R*!**bTj0+W`(a%Eul0gitRd{X;$ zQ-oQ>|DP?e5r9g*9aE&GzlT*j!`ZtOwtxnC++7B+LUWPM?T@iEa3@qj>Xj%bxlp1j z0LjWS0s7!R`G&4{?M=~ytCU4`yWtW@J}0aqa>$ld$CJkfA?p*H&^o>(O(FQ}^jd>- zVUxQ6CRn{~o*K`7+@Wtq)>Qx}`|A;=v!7hG`hfeXYSKeDYf$kz&53}J?_&af z3vB|mPDc)K8VL;DVe}6k*{ufp3CGt~hq`yc1LDv!u0KWvcLfgyN-6RlN1ke2uBeD; za1pPFs=M{c?^|8u9!X!#T?9dD%9DUohZuoxK!sJowF%kr-Rle=*pU;&!q{m#E@MST zoJv1wPc1M{TJutwGRh9`RFMr9yVo!xoQ^_?l86%Ro_cTKuik0eB~M4mo9F_HhrTkN z9fk|Ql@1lhlr%eU>a@CdV*H$9F37U~E~lF{Y?loh|U5W_^?t zBK`Gy*P~FTj1;Cs#q<=?Q|VO}4P6dox7efxDyiv23TSRBVbaqFc@(ZS?2vQ19 zIJ2B!KIf>XqyPP|%@1V6%TDXWc2zLn_Mr+jKi3&RMx^i9Pp65dTd0+#2jUr>Z;T=D z2MTlVADPm$b2|zp%}_qgF%qjyg+gEOG7)QfNuP;eghpK~Bp!hlOlm$Dx(bA*#d zk4+cT--}69G0g>?q~q$2>L%m}>pU$P2NE(OK<&yczZ414#(-&qZmyK#_d`s+=kx4; z*^cp`*Fo@6b}QG2VZgf*1Vy15e7U%@kM<@bzj1J^6jv<@I;a^r2i)3$L6JUyz?-bw zA`0Lu;Hv4ID{xtFvy)&b(JdmNxMPh!CLV_1y=IDokIH##kU=DT^tqq~ZtPyf?o%tO9u}z8KcYUfHLTTuCWjcn zGZL-1?yiZnSEe1l@fB|Ol*jV;q_rgwBx1YXhT)xJC|#H#zdR$juncL@%^7PT(i zV{wvV;BE9iPTpm=e&{~%>zYuvYw$bHU92lEJ6OuVBVDTsEbtmjl?YA$>Zzf$_=r=3 zj<T@jsDt_R+97^X- zL}`JDCh(Ri?XUmi{3_9DIn=X^z!>@S^W}Sz8l~m0ZF=7_sG#1|m1u=s%-R$yT>P^v z4Y45#^U8=YLAK}E;SQVZf^PV5imN0r4Ud#Ry?kU~1x+*qfW=O$t^u|vDRUEqGOxeW z9$MgIzGH#lRzG4s)7<<|A6MpdsmU2ISwb@cp>Xm4F2C85K1i)5ODng#K$4T zBgT6A8Xz9_P?|OIzlix@b>VI(T0x);Fs~5>V32^#f&pX`D2YMz57*4~1(3u02(TkiE1bfO!`e^Uy zLU-es-q{p* zg0t8^*F%v8VV&qVTAoHg;7 z= zt}geK(bA|0Glm$@cNcv)L#G~&kG&d4n=?(^IIZ51*E&JTq3n0q}lmO8R z;07>V%t6sz_LBS*k$!k|8lPqqJKO%&vg&$2%|gpNX1SE(!Irv^K&wu6rPKMZWF`9H-hzdulFxlxFdX9++eIQEVo%K7X_bp)3n!ye7jO^3IEm8 z0u8d-g^}&xyYLdkn_aJ(*&%rnNo9JpLfJnj;d{w97H)?B9;wN>UFmJsTT@ni(u>nr zWfeD6d$L_ri`2dP`a($7y{+EBnRwgRp2mWqe@4WvGMoyN5&DNQW(<_g-n$tjIeU|`Ql*cf;W?et#BuQ_^j4c4)?OZoD%6FHKrqB&S3z`Uk3s1R<36&JH z*IFiC3*!qwxb*EN8dcZN|0<@xe3bQjX7^4cr@yQJHrAk{m*AR@-@~;~YBbCV7U6vV z2=A5^@gY53a+B;{I&cFG)ds>0BwPotUZU5YmTN%s8Fla-MJ62|)wIY>Dz<}X28b@~ z*Q5))nK{#_vC$w)kYuH|F?bLlCHKu!t1ebF9lj)If+YX})robnU%Q`u=g(O6cXc0c ziq6QWV<*}Nav;UJCrL>BCB?Ay0C*_A39TFL0t-zd=L;)JDEE|R1{<^s%Ye8>fVu`< zSt*cIZio%+c~EFe>65yu@%4l5pj=`X2W^2}6u;R-4(Fci>7S_s56s_wy}P6*YfB%B zsnK#W>dZmBXNbYYNcD-p1#C8U{sxBR%spXLjj{BxNK@%b+GUoi2u%7=^_VOK~2QHs#1~ZeA?ZpZo z-yfX0$A@+MhJ0tCTt7u$*6B{Qyot+0xzH4J7G>SrY;jVzCp>Hnoqi@W(b?c#xSXJY zartsyIvaAYJ&E`R_S5H)e3a48pUZI7%oV3B#riDWP+ZJOG)T!7*_xo=E%fjz$ElOM z9q>uxHd|tTIq`87ZjPO`uBuzd^TqlP*SUmH`PE=iA?K;cUVAn1)l<{D=be~ooaLAZ z(b3`Jl$F@hD{OHW$!ix!EHO@69lgZXkMAVL(9tJ)8*56lM_*{z)>y6<&!BpK`^}s< z+DiG+#fKOj?N_#WYb-m5iAl^w<24o8qhmB}Or1L7o9XENpIpg_Rnd0A<$7qPFMhpN z_UnTvrR%CwbcIPz-gz3cKHWD{N3$zLBv__Qivkhea50e@|h zx|II%WY+JEKIQAGr1XVJE0vy>!J#joX)5M(e!@h&!z`h{JPnXW(}E-Vxy1j&*PF*v z^?m>2WJ;z`#tc!?WDI4*2wkM z439WfUZ(dx+hNIN6RNPmK`N^8@?QQM1`n?M94-2aMm~4t%3fi(z&>UYa`cOI-fnc| zW!!f?^M!@fH9hL;L0?S7p0D|^qW|3Gw$KcH<};4PXUDG_9%w2o*VndJ%N7;a>osS~DYKr#cWZfbL~GL4@K!tSd=&Tg z`Oc^cQPH3i76D6lp0l&NSrT_h!Tw1YO9R}~QO5w=?=3YYsvYW=MlbInvN8h6d(Dl( z()4SxZKC%}PcPZqpYASe+|nf)u(kArc_jOtb18aG8Y$}(noz+_{Fb& z?Qf-z6$UC9(zx)R*xmdT4>N2HW3ds75qr5$9A;Q1b<0q2s++zeOaVV-_f;d<$5Gv@ zm(SVp+(k3?QZ829rx%cBDQ~y`ouRm7>c>xC-x&(dq=deXGTo+Vlq;6jdfLz9$9&kS zHvztMk5eWI0V%~%96{QFj?=ys{OM>UPn9;A%qt5fH=O!YZ`myo6kuvP-kzf{SIIES zH9_p;fbPbwu;?FRqAvoG`k|+N`FedlgO)m0**rX;Wx-8?W?|6e{ACMY`tc{?38=p!jGw>u%XvAQQS(OnPqrh z9upVzr}G%AuPZuZN4^*ndCU5oJecX;TQ>|k*oA)3HRuj4pYMNoxJT0Ie8NdHN$0yC zlt#sC(pKd@$l;zZ4EykOuqr)H=~81%t-dC+;M?)kb8X@rdfPs+c>z1?iRY$HUJCBsA6w(e($D2q?+VSH`7Hh1%8jS6x7kil$q#nN zu0MU`>dQJ!mBDo87CXJ~7rp$(^176V;OgGO8`H-}$zQlPio_yb?R*>yz?oM zobpt!#ctzn{Y@1Lo=sC5chB$XZI~gCa&Nx1Qsl-ZyC-))j@n6#$Ni8zD5F!<#6_>0gbt%dM_gh(2GKwE5`eprL>9)#K89^bkot*!ZU!#ehWXH2N)GpgyxhNFKaBJPU9Z0oi zZ-h6n^Za1kwId5z3dV#F>6ernMVaz+1z{In?f^WMHSTr&C3O6T;C(xuJus_Tdx<^g z2S1!4-M$!8`|Y3W$Cs_pe$A=Ek`ej|cKq#{dl$230(N%0-5LCl{zy5_v?O6&8eIA; zeLL<@QnRA&&L?N*`rV6WTjGviUa9@s1+Lld1n7v6HH>1HF%G)9)lIy3q+DOoVn^DSrI?Z4sS2;zU>%e|jGdA!Lb z!ExugA31ZrpdIv*pdD{LL*DuyX=E2L&4(Mmk+6``pz!c@R-5Ic_7Zll zhMve}I>s3CA3Y{_aPzCcxrM1D_~)_aqOY~SHthEN+r&5pyB$|68zalkjKAtQWxWG2_O4_-tPws;2s)nuY*uz$NnN%OQRM7OX z*xSosCwNB`?W->eUDDmS!DkHgX*D4sy(fptCWzmWW}n;#m5 zi{%qpx9s9|^k9P|K298Ox}89lR(D9x5i5u1U0i5SHJxJK0aGa6I%>~j$N2V3?T+fD zDyuT2I`Jk|!;VZ&Nw1c?GyFO@oL+u$|M@8HaB;~y;;Ad|Pp$(fR`~ay>We$0xYtOg zdZ^S-9M@2^+fiFpdqZ3jwgW`5b{~x1y>;CFI+_MptM|cQcP9S)EOq6D($m?-gK?|D z#da597oK_Y)rpz1^wau}3txFuBn{PNi|72l_KJaFf;qpcTgq!JVYo>r7QE$!gg`eZ z^Q!}I3%01o9CUkqq;T%xQr`K(@<4U0*yk^S7m(Ff-Wdy;KJ=mH&ri>en~KInJMc*3 z6}ca4UcQnz&w9P$vW|S$!)R`)J3C@6&ZBvOAV~ngXzm&t;Erpi;DY~i$L_aZMGdZ= zzog=Sa7T=VUfwHBXYr^*uMyS>r{cZ66?xcgf!;D0;UOSoH9#%WN96Gr>>j7K)oJSJ zZ3@1U7N@ljD!bjXRzKrVy#&IS)Kgxne%jO4tuR5@7;Sk zzp?X$g7!n{bGwo`r#9V-PRKRenW`2nJO7J`H;NICe0sVw&N1t5u|r&bqzM zH;X?U*qJ&tcleCFS}z~EM?daj)?HK2=i|q`)y>d7;Wsa}Z4eU4M7P|@GzlX;GOF3( z`uv`-lz@rkz{=%DIqOSa4b}%P7K&v*%=maTnA_$U_ls8Z!+OsYSK(dxd=#L};bzuzL`_N~02 zf?PWASX1**$)WNCk181@f4w@nanatp_t(VCSgK`$jbPy2^bh+otPI-FSE%{fVK)9| zQ+lyBj42k3IzQ591L}3Qwa-q-^GdhpGv2ibhSUvwLq` zEarINxB?zTv20;5ACRjETAjOT$vxO13rnZRd8{$=>uVU-#%irMfy1F*?o}sC-i;L0 zhKWD4Ec|(--KO_J_h3DIS^iFig7QwYhm5>inFc)US66gUvNs4x3D9rgqu&pYrC2%@ z<~ihCF*TLye;cE!R7@ z_S_z?sbVfZY_{cDxbOGZlwT#Y8N=r-i^BWQyxC4-z2FDun9}h*F5xA0v-i%tNq6*R zW*FY#%J4jVscMNQ_nUw9;sxAJ+N}zoscIB7)Z$Ci&Hor<&%4Ri@+RwUxpS7uoNyLb zvE>mo{w}TXZ{`bQ2U=D%!d$8hZaoi=mEXL*m%Bnl@Z7=V2y?y~k?dO(+czfOO5!=M zVIzz4_SuEEB#9kpma=$LkT&4S?B^70)VMk4_RxB?48|f0CJ)%e1y#0hE=Md^a`0Xe z=g-iRL1y9<-1a#yGETSq&ILv*CQqb2=Cy4Lc}U(BGR;=ApIZ10xeoX$nY5jj+{@1D zO~2{E?2|z;7S@7gqf5LTV?GtS1lyCt73f(DK7VR0Gxr{rk+_-voHS8Y$;fc`b>8QL zZDr(lojcE;Ea;-xa+*#uF{JN|YwEMvHx6@NT+n!;;UJcOQ3nq9wqgoGvvi_MW^ebI zln;}J59${zW9$KI$c)KN{cL=Z>wJiwyy!Q z4><_3=SmZ_Hy`<8*r;?kFyN4--wX0DAv2NBbFE*dWcwZKgUOsLGBib{L>m;H>?bsG z*4MlltmoS3H@HriN4Cdhzt^s3907~LoCjh)7Zh?$D>UoHU3k_0Wol%FD?_b_Tam@1 z%03cf2ObUCj@yUzRj$j+rnMWc!teH&s%-CF|8_*W{Ta5;G}E*oZqu1`wG)Z=%jEoo z-n9xV9cLU?bwg_@JNGTZs=XqILt#PBEKIST8KkgumBl;dyl7QJxn$>$$_*{o{6%ZkntbMHzh8&weg?DcHC^3pM0 ztqzb%2K`O74m!}bJ8g7HrtMlFm!rxcmpNCPNF_nX9@|~l?}Qfa>|#jJakbf|b}mhMM~ma ztTE?Q(pA^S2KAWeZ#1BAbWvg|RB9MIygC>~slQWApx;`$X9L$q1dypg^p`h)MW9E0_fypY1;n6xb{^gRsD|T*)aBX5tczNP1 z+5Y{Fm#$BK6mh&%6i8OS+;pE+`NG#E)>ubh0W-*tIoZFgexGB$(BP)60?Xv-NnL zo8Uck!SxI?I^~aX3@)Ul!odT?h5HNg!i9pFspOaKQwa?{;Hdyg*EA?qz) zwqvCAywm|w-{(2HI1x86!P1L6MqAHIPo=BnIy?#_ueF#k(~pcfsQLNp^7KO-0*&`V zT($Bll}pVstl_Lems@={)>A_@*U2iSW`#T8iedjrF@^-vo@Hxb0TXYW;Sxnp@r-pz z3Aneti?IedX9_pKNe2bB)~~X$ujJ6kh}>w9(_G7M_|66$iKxz!4?n#paR`o&PN{2> zFnnIROF?Ze^D@Z+?y5nDh!o|0)a-p{wDfasv=7@hPaM+b<^%SlxlsH9VM+IC{?(I9!6$d~akA zmUY3wooTQJ$!qF0~H~(n?@PBE&qn%}xLJA;8m#Q$NS5~YqDuFWD13r^sRq-pgKfo(At%e)vO<+FY&58^a5JU{q+i=Q z(N`WwSJvjrDkz#IrmG$2c`wy~UtIfaemjqX`axMZjVoy490?Rf%A%S$SNuitN7~+!3KvFRjgRV89r5D2FX`my zeM5zkCc4n`h3xG|);O&3@)aDj_kg`LUSh3-8XP96jJBK%Tb>l8K-r~Fx-@+hZS8d9 z8TpL*y53l^{qOc1%kbNG^j|n=X6hGHI?mKuR(CDu2QPeD_R$N$wywtu72Q@Vnd20XvL3J3YvWQmvCz91s{I*$l|JK zjwE!F6Fk5uF23YlFqmP}jbU+T-sS1=52y}MIsXWSZ%LsFT zQvqEHA2KJY?1cHw_mwXuP@WVh2m^Y*H!Ww_QlSNbUDPzGFn)QoYls07HVoP2&LG|Q zd#OGm=Qx5lf;T9=q-#(;=Llz?sb~gq1S4=7FZh%X08cDGu@$847Hk#AQSWl=u(|o? zvJqJR`U*;%t6jj{nJZTFJ^h_K(fSMN)m2X2=op9$V}%0~;eZ*WvEcefwsVwo=!913 zut&n#(f2CB?Y9q=hOe%)T}_-ce9cnYr{lA~khwBpp3!i8%@(%$Iu}A$H4kwR=LWw_ z5Gx=QnjcOBKE=+pp>JL3=GB#{6UWSXT_U=*ztQYD9M1o(lUGmcH~~5kQ1OxxG&h?) z(jM+n=%Sb_rsgGG1pABbZuII3TXIv)CEu#<$})frmjj{tEs1d8D^eb}kWqG62~1ik z+-bm*4Sq_X#Swf;adv*t3^*Nw>QN*;#nx4oAvH+og3$<-C^e(~B_mT{DL4Kg$F@+G zXn5Ff6YLcb-9Majqtl7Bzlh^YaU0ArTP>I43;Q3qAr^wHE6%jLhBiYBq*p9&qPk5L zAACJ_#900wL%gSN;sr)P95kW%A`Wy25a_#{T3Z%L&%QkfpIclqJnKsLEu!6axVuoB zu=|a0e%zD1SEI0$KU)Ha6o+)`J-)h8csmOrJ0>_UNi}&WJci%dwk+WZ$*`gc9pHy? z)r#rQ_TmdkApngR@Dt&T$Znat?%t*1LT>?7;Xu8*yYZ^)msj>oww{>_zTf}{)Pbxl zKoo1#D0U#em7z=2S=!Owtka?Ap}=hxZFr$yoRZ;0yv93gL&My?*#t$|Xa`CIf_6~= zdin5BaAX$v+*!x#1bF>r4tOhhaco9 z+%JgrDWLK1VY4?)M7AjcT&4-`dy+>Rc8|A}PN@E1l?FbJ3VBLrv{$Ab1#t8t_yLCe zHNW+%eF~1vE*Wm`V*Y=wA@c?|pqQ!y2N5CN;Uzs{_>@=ys)11!U+Et5qu%4m|6_91 z>_qy0q^<5B7!Eu~Rzt&kB}L@^;h-ZbCfgRHAE84tVW-HjZncmma#{m*-1C+L zK?TSkno~DrejpfN)RhDIqd*CCP^BXvdx!NaB|G0Iv{NeKLVqlAVfP|BRC6M-Sg}Ujpl3J@@-KX`x7tqJD#I5ZObM>~;?bRQAo#`fwPTwmUbc7+{o|(qX?c3J^L@OpFQVK%B zNdS(N9P#Q}Ct3}TOGrTz{N@B3vmDoO`ug|JmKDhd_DMh~FS+ zq#M&h;f`@7JRTSm;;^%sD$4P#b^)2UsK=P;1h?Oyi{X`w;WbNg ztj8$d3WO!q8a`oa^;2{4*HBma{B%`U;J?ZcxA|ojTL_Phe9U|`nl^Eb5t$n36W-=q z(Qs()R+g+y^6G$j#3m|LAk2HGQksQun>Kp@vlg)NT%O9*X8p-ca0cg^ShP!ESN8Tq zqyio%xA&MU;{iA&_2bFG8mBEN*6_=OxBw28cPeh8tk@QdbbBJ$am_~X9_GGhRjWq( zH5dI4z*VeMlduSgw%r+!b0oA3FP#X%3PK?g42Sp*p)|xd&IGU%O9JRe{~bx{{;~eW zw*L1!*}0IwL79L1BBVqRA;K}1%5X?EP1n(XznFR9sx@z`?4}!9wVOTipx8fh5E*O@ z!5aX|Zw_ZfS~Zo_@aSl5^P3C|8R?zDp8P>H2=VPP_$qdH?;J=1L=kQ@wmeMnU3L zLLl*({wAAYcII!K)KydWHlRYh;;+5UE*Xhb5(kgh%y##h3xlsuZj4o7MaLK z7Vnu*f`gYuTgIH--y3a?#3u+@0HLiWbRvg2zHEy{)()GCWDJJzpPR6Zkp|x>XxmH` zyLtXT-Yt(hWaB%*?V2S;)k^2lQbGw$l5IXmAG1e%D zus$@dOhxklqjjpuuK89FFUZo)$OTWx2rd|#o|iCrt-wt+_bbgrP;sf-v^I;>r<$D7 zaeN)I9eEsEu;C9slRpTtZ`XtJSTT%CMGmWx0x2t~OC@y9lnWb*^;qo+Y!a_~VD9hi zJv*(toi%;x)cK_g^#_V)Yg5But1bXA*J|#b+)B6yhF(4l%t!6Nla&u~YohHtr0$Nu z@t8T>EfOkMk z3IW!TIbiHK0Lc=7b&s-L00h|hh)HDSE*;>2z$t{4W$nO^YA*tp(0(5q9z-~WBd+L< zq4$xb3D>o-1{6ME*&qmm6czEu)J0+QfJBOiOuxI}+VqbHZCNN}ro5i{^_lWOvrOAt z(~twHjdGCN$Fu52a(2FH5W=>;g?U48o0%ykprHO@Qymqhtr5mCtCk1_LDu3*jlbCi zMROpxCq2#wn`KbeAA%5kbtMBCyBV+?gmP3PRRI40x|1bVH_*QOUZsWsD=AV5eg%PM ziu=ZEppe0*^96lQz~BDY>)3eyfjE}c`;%fTQ{&P-g>WQedB>uC%xCNKvI3xnMF7IW zS}IPC>1dW831jK z1xSFETon+Vx;3l$m>FG$jQ&Pv0W!-I_DJg8cL1gQ_yLbyUi7AM*PLP24Q0thVIndP z;hb$Xa4vCFH$7xk0iW(vF{rynHA-m-Sx~k8NUvfnsS8SW5VCPbIoI za0lQZkeh;~y@0Yq8+DVYKY!e~%rY;jmZzyiSR z+JmTM21l}RElAu!TKvBo=k4*M{(>iDDC`h3|Fz*Ic?j!~Jdj4f8srSd2wDV2dg_1& zM`rW+Cuj$j2BAo65aOa`)B<;j7K-y0tZV)s6(}_F(uiIz>0!=yXSG?$K z4?&k4A|Kh2GTWTm1Y1{5ewSF0+yUMOPqYn=!mS={hz7Swodh9EP!nuGgmA%td_?A> z=;PqrCKTNx#ZgeVv4_Q!t>VUGf8;mhg=N|B@sRfrH=$64*la*FLg3c-`mT8vIRFAZ z4~GG$Q__5#Up*T1+ru&R>%}#dUPKBe_xv@oSqP2tIGFjpm?3;}V;B&db${Be>|Z_F zN>^eEK##Qr#f1McPik_~DgzkJ$ROehQO4Cc@W=uxFn^`=y9z{WLcE>>`rhpbFCMrb1SV<;Jji4i`xJeU(L0;yH}iDSYX1b zonQDC;-c~VW_s+s-IL zYRjR4v_LY7$6M*%=Tb(^rTaaQ{`kFMj}sG?*Yx(?xFSw0CvUXFrLb@pG5-7{AGuGN zP9$qnHBhtQcYukZXigL|DrkDzYfpwl{y3d$J@bQ&+5G}44ghmCV^0A686oCa7L=F@ z7eZ9d5TkDmE-`AFFg_~Q&kk*leJm?r zxM*3NWI&9`PMsCHpkTlr**^4Q#7Bg9Fg328>K$pM=$|JqMzx)*%ca!hNQz|RbfNu! zBEun?XR;7OtTXbkz7$}6CbCR$43K|97@tf}DJ--(%%Vqgp=ePEmvF$@>@~~)dLuv}@<1lz*4NoQd;g;DGOPA@;x2}4M zW9&!~J2ZEfSiqlODGrckzzNNJ8qxEIi4E$Z~RRC{26oU@1v?Xlm?F-!OrEs@usIE9}nd?BJU}5ofe$vid~F=D7b92WFUo+ zED2(b_7pVea88}u--6usTjvQmm#PGE>HmPWGbE&z*$`O}Dlg!b5W&j!3a#G%S?X|I zSC8`25ebP(+Z*qm`6EUV!Wq1U2fRO&UWB?P&h;u_`kW0{zqO8UBbdRr#AG0tqA`Vk ziws5FggO1+N-!4Y&j~KY8=xEf4ko8)LWim1zu$>X${YhIKUar*1kOSGhLpRaP!hE+ zv?|v*_*}%EWyoV=Gdv+o0j8i2>k3V_5$&}zNh-a6ZwYd0)KqIoveGuMEo-r~V!W8M zd$i@}BjNbY@d5d&xn#}3gwFJ789xcuO_2lJo0iAf28<^ymg!ZIx|TuM+I0TF;?`-# zEjtjuKHN&NN`Y8Aezba%OUR?bkw+aGnqh+{tLM_B)D<#TFHtS|c#hIaao&J$da-F$ z2>#ifq@J2k2MCj2$U8<%n`-#~bT9Agb5uU-!)+m2%UYGZtyh0y{G26r5BqsVT^Ts8 zZR=%;F74~f$s?YZDT;>z`oV0UHQ%!8xgzT~nt=vndCi%6t`v_}sVh;_rbfO`ki7!` z;R6w{AB6Ywu{Iv;@wNdb#XUIy8k*jA0Ua_u&?*6`Qpbr_6qq-i*KgN?L*;MUh^uk> z32~w;ETnFMEg+neQz_m(_ct2K*___A4lkzZ!^0FCkk})cXJDW=EuUXgshaCYts%gG zI;Gc=CB|%90D(Y=V&u>19PKuC0nePhC7Y|ZaTY8%c=0*CZ{&x9SD{mCn_R`k?h~I$ zx&DVsV4u{gQHGAyQTHes0+`PpbJs&{k&0%cq5|^j@2nAu02a|qa3c{X;z$-{rD|}G zmEWh9J5At9w?Hu91;GGZ+#_OPgh6_;^EDU^Z)K1AxZY=k4kCq4J^Y&tA<4h367{-8 zIaY#Y#AJBu5K6QGaJRab4{6rDLv%b1H+q`BOtvr7QVs=kR}#EzqJU`MP~rS7OIP+( zS%I545zrPOh;`wsW;iLsvHc$Q$bBs4H*hkG@1hRa zQu7XS(^6wqk!(mzK<8|P`(HS{?}o@3I3QqqjePB>_Cuu7-mr?o+F!5=1377*B+nUt z;r;up$NdT>Y^AR(tqcs6k$?y z^sV*aHd7cr?eWfdPy&I4%-y@JrNFkrO}A|HiL~lAxYmsjG9L;Cbu7voUu6hGLD2+O zYLFvIOl^a=EYgw^c*`$?)nN9iRjXc zI2M9xYt#N){uOj3xwkJ%QA$S2q4WqfhX~}XEiF%T>Zu;I)bj6Gm&oZidF&)3suc8P zIZRLJ_R>MPHEkP_>WgZmP`|a_0ZuZWsH3iega;BAD%CYaT{S!tn44)JLID1>VNV** zBQ4VYfU1mJgJ3%^ORa%XIURj!$BJTCy=@A5XM<+N+k!|C6rFOy2B4dMJ6aZ`ko7a8NUw zvXAPN69|Dq)Z>7X^oDFrgi>#OGk0?6~g>Fmy1oa-qJT%7C^3tar3(CM^Q zXYvALjQ)J;mmA57!m*%BlYGa)HB1?NJ0+7pW3?ns%!Y4R^%JS^%#kgJERFIMGRoIN z9E~cnSq8`EbihT}oQ6DwLlUCjm)8326z@YW5nsG{bJQUl550zOO-+P7CIg>)fMci2 zwc)<%@R=eZlf~HQJAvirv^kv_E>Qr*;gmz)>cz?z=lkHFjD@N4#i_;lY5n=G#p$lV zxq^?gciZ^cEky0jjVr6?8eHihsy0uwPqDn3_IpyrafuXj+mAZ=Gszj`f%!vr0YS)u z5H+8w+9JkZC)o5x&-m*YC2H$s48mueDeJ@ORbQP zfdf37>;m?Gpm$+FHz8Y}R8_;Ng4qZ9IF#0f4ddDaR%I6kf=+?yBf2Ivp3~8Of*oc3 zIQXaHi4h_luro=7h*;@p7$Uc+*{&bD1iCYzO0WgE24}{r%~wd*DNSWwZrUuULU$5l z|C%dGHeHN$T?vSWXOEKnoV+NT zhmd}CoAP?&-2pZXQBThSh^%)2Y4$gdfrK^xE5pFA_Mb36%nqm#6hhg)5JdAtp;jN5 z6vVP@YZkl&7thLFMa!JGU5w@^RF}P|m*YTR0v%jfw$xBqUrFRelNJoA@5fgIdA*YS zI;i9}Ts=r7f~XuW%+Ha^LQq>f(jG7NBw6cw50&YWdl-BI?7@`8M<_uoypF(za}{IWL4q{fO&di77Zxv zA)Glwvamg^=!CmuoPa-0c0ffB0C|*eQ00gVJzyY4jFufsDgoYro6(pwk)K7%!_S#GUJy*i}EVU!!;Hy{(iO*cF}6hs7wk9ExarE8s`DLX&INc zb=T|-?p(h5v6uqU%7B71iKReK9(O;Dy99`Nq57=m+6vsFk@L_X=fC%O4_^Nja05^j z6?Qehu{T4p6w`LFg{YqT{F^m2O?qjSGG<5xqw48oj1Qpi=;S=WSt~O(v@fa|&%fPE z9mIV%@H;EZAh*nLbmP=UHfXB(OY!%_UML(1EK;;EBBM5DVx}4YdruR<{Se3vm12=i zjj}yJon`Nc1l~ao{JfDIU^prhAb!loKNvMk7}Q3t6*W8jTLASg1epyUrnY845T1y^2}OptUyOoLDgqxX97HzuRwJ_aZ!!{y+i1;VbN$t% zgsTGY2FqvN&P;C$Xk18dCySVRU6>izlVPkAscixkUJp`x$L9C(TW-Bp%uyc@V>+_y zssg4bRv$5nVyko75pDTPCmmYC;_8%369Hc*@~pqGJu(d?b(4Xzc!w*tY`=fS_gxTI z6TTH}hk0~(J*jhZAPTP;^e@z_H&sKRp@>Tf1ID{i^%&6ivjijnN+Hw-$jpD0LUl>am_Ry;ZtLx$dD>KF}UKp~{-=D<*+MK?dmtMAK=4 zrzVP^coalG=4fL9BOlT8j8@eBT;?|ksE$!oZ9qNGSkDh#M5&L7`Yy*?keLqI6DpbhBcfFQ7lgO8faLW4{2p`tvY zZB!y;VXUWSX3*tV2M!ug_Ie^X(?oDmRd~A!CPRU~45*NRtAeUh@#3e>FoI7r0_{?TlkOAU`YtZamPu{VN17 z>%akh{~lP*lSD+X0eK(;wgWLdhO4)MoeRGZq&z{@I1pAy#yOpnyTT3t1)Eab&2?v61D0*^d|x++sYs_ z>XjyhZ&K`(SAZIJp!yPr`;mGWEtM>-Xu%m(&heR9ZKLeWE)n1bAbQ`b?cH&>eU+%; zk<6>p3%R@~j3fAj^wXcRTnK9hYFJAjRo>C9s7>oO;jpRUDT0j|dAv!u0vQ>D+{*2c zBC}nb1T3JS5#$~dhQvwhI!wECDkpE*+trxVMYY}@MrHjh8b1O)PFqH8JzYX7)WjgH zgbaO(1Bi7&6n7uyKpKI4n)_)0sraq>euT#XPlNh0;Q~w=?MilhrgaD00xLr$33O?g zAN4w=O1*0YOv3UdazCekSApPAg^1?K;G71ILq6TRB5BG8PLTPI=m&fvu77# z)}gBHU&6riLoqb5FdVz@fA<^fsFPXT=dJfo_TaAToi!Hj$+A05dFq@71}!Ia&ai4U z4<`9uFfVY7O|m8e0Bir+-!Uh^dY%YiOo;Wieg^7`8Jd{`;q*PqWYsl z;XyYjyAS^QxGzOxI2cN_-3fE!A6F`McS7ANxu|<%Tx8^g8hV!nprtHD;q+26du!(rl$dkF70m*o zTW-sG`w@XnX9)dZhz#_~zH_UmT9EhE+3D?U3P*^?B-J6Abd&ea$95v_2{5eSAy%CW zjKbT?4N(w!=hY~d++VZ1WuNSqqZG=*(HGu%=WkOrduYPH3@*g1ThltqI5XdgtqQK9 z86Wdif9iE?v+Z=MV_h)WhnQq7-YKx*veqGN1^{c>Cp5#BRG-ZymId&LEOBdBTULx! zK^8sOFP178MsVA)LhOsx^DBA#XWepMncnM$-;D)3X5O-U3TkNeiZ)GtXGwX3u8Q&f zj*+D~>^5Aa@J^>IqN=_e&N2@8um3*=dc?cAb{WfLpRVx3)gC{&Kaq z5i?b!;t^*%npqL)`{uiMmJOZYZ{7sRVr&4gc>23NaxG!CK?7Bkjj#o#wY;L-6Z@r6 z3>Z5^-2(@6;|tdzf)jP=HYyWVxA73l}>Al?wcubIB7vvNlWcV!RjL!B0A{rU9Ged@Ja zJ=cP%~(ZioHK#^GP+g${KP$qFlZX`imGs`uu!K5q_V| zwc1=rY2L{m`LJLQ<%DKE^fc^2{t?usgX4*p#P|MYrb+-yytQ)|)3SKM{JY2JgLWi| zqQGUdalB<`$T>uY;vOpa9bhqfIpxDt0acA^fhs`3$H1Q%d{VuJ-vFR$UcF)l9@vYk z_qP^zNgVEx>2P>NbPWAi6Ium!f1T3-1P!1OV-*A3qA!6DfFp$4L5o8}Z^@VIkbMn~ zx91^wrSX|L>>GXB#_8myn z86xlT%V|2M66D^oKn`n6ZyhpFSy@`KcwWy^#M!^J%)BM=d056`q)%#5r8n3T!2aU1 z3r%A8A17p==(7@uMGrSzYZst??i(cAUc4wu2gUp_MWCuehL|DZl@P2#kvNU{!b$BI zOMeUf-mrM4Hu)UphlxAk@|zGlb6L#8q=}8e>c&!qxUO41Z(5CNuk*3<)%<|KFMbxy zpVNg7PC9T4xTdX6|K61JbbO_!XA)D~2q-#q10{{X3;i6e;@B@(Jepp@)}^|nHkD+~ z1+AV8G4wDwhf7h@KY$)X@` zyq=3vBFfD$-dBAk9&!x5mWq=gVk1!;%~xtBS%Fe!(Sw60G#|GO_661ex@{!DUaD0I zJj-sm!mLMn!QEu1uN@2hDNoT;*T$+OBwA;_3Gq;A&~?5CPKs6e_J)LiA+X)wqYZH} zkXonj+($?`cqrj#8AuDp@jg+Ii^b!UGoS4wEDcB4UVn1S&9Jq9 zrT37kv<-RXDhIO&+MJ?_s@qKqOs^6;S3tw8p+*XwGqaF2IutssiS2ZNN+V!AVgL<9 zwsdOOf{w)lw&`x}obqG9oma^BUuDz<=HrZGRuxE*exh5A*tMaG@rHwur8a;-9rDrm zr;Nf*-#^!Cd3g>>gjRW^yIe+$+f|lsx8$&9A{Iksgx`{dUs6PYNq832ePTA1cFQnw z5Ns%onL@my6+f5_iV&K7qhf$xLM>v|5x4xmfipb}ydb7IaR<_Cx29ckrC#)&DB49# z1y=tI!bpz(8kyaMn&6)8R3EZ}Z0*OA{x?JQa&zsOdc2*`&3Xd&cgZ3T;~#zz?O$sM zcwe*!^UwAPga+1A-dpYvdIw>YWQ7MXGaOGn-C@^*;w~_%;gp3xXPXnmFqk8uqH@c9 zaJ4|*J$oTufjvMEQ^VDG6y03|&vhGDS@2R32Ufza)r)0ISwbYyxP@#+-iPl8#8n41 zv)YF0%flASgi&`FKojcu1nEvZazg3R2&+6OoZps(yH zfGLl}SsTa+yaN}3bf*?1MG=}BGhbx~@Gry~>cjAhvtYgvCBL5?06D4q<$3OSFmgx4 zLw_uRG!GU55gHRSL|ULB`Sy@T5r!w1;U|Z$>E@5}ok$SgGe0=Od?D|UqhJu3zw|kx zQu|8JDPNZWcgEOG(2MFz`CH}Yru_MUsznLHFz&-Og4T;d*R=b73D$n$ODi=(_ZaUB zwqAbq6>MV1lWQMADdZr>a1HM~tXOHA+nTl5S^u;&@l?-1`GC%#QS*MvgUFk7V=t8U zK$Ni(iV(imXQophtY4TN&h_@@wyQF^sw|r@N|BJ)+_QD%WipqAG8NsQU7SAg@{vhH zqk?!Zx~t9we#|}Av;XF508vm#4iX;CGJj?hbTF~Gi?|}#LcRC{`KXx)TBQWi8++}S z2dGH)Rz2d#K7xFQ=L~*-z?Z((R;_!#G(!8tvO@HF+2L1nTj5GSDAs(eig20NGlA7( z@n$!>*)RZ6Q5<)=1-wvzLPRd}pepGW_=pYVAy*K=U^khUNv zQYeGPgc$uU)x(AnHucPzkwfSAr6dE$fsD69Lk`%abpFhC9~4=M6y*N_bCkBK(NHb6 zX{s0}n>kdCJ!an3myPmKciZVAOZJVAj;kq>)T zBap&ii4$}Ph%xzkD=wN*QbgVB8U?T)1#?ifg$s~QwdRccDrTqBv8dq+r%_Zo78iRl zy5O`1`)aiBe&N0-tpQ(+188u!{HKUfSE??|SozeXJ`Vh;uyI17 zvL}+DFVsT)tH#wqTlSzVkD8z%Jj3@;aK{<}K3lJKr$BZL?|F91i+_A*zZ`x8^&0$i z9HxADkLT#aK+OyOEQ0;Zs;y|@yP1f6fGP?uJwRggF8nR`tIg2uh2%5cMhA+SOAu4_ znJ7Da2ieQ!-|`_;jJCsnRPL`~{}x26Cl{e5R#f8rPlAWFhL-w*E5SR0Xv8n8o{+Qw z{b?5flutYO2;9`ESzXhm<3ANY}iuXJA$k)dT7ko79T+HUj@>jMWX)hes&$W8)KJ#d{#p=Lg z?$4XsJ+4+-=_8|qDEpS?vW0b?ilMZ?ek(-ciwrZHa^K7)cSod5e7flisK>Yqz`@~? zQZEaKPwTP5^olDR9#{bdm9(}wR&2{{crZ#R!Y%z{ED((Xv(NZc<3XBGI=Y#`KZY)r z1yV&w2h6MlJY#pB~AF&B^j}Ja@kM28Q9e9A-2uoFB@pG%p&2)H{ zIg^1&18_t2iJ9poKz~qSdZz-EY&Sm;XLUlNgt>Icf81y63^=@hvlM3BU^-PM#u^EA zv0`T7D1*W?mZjDs>JVF?iP!=x4WvvhMM+74NPEm&?Y)!WeKi#6IV0L<{R)>{t0wbM z^p+oR05arFx94C|=>-Z~GOq2zdpifG-1Rhnc5vve3VY{f7S8I!K!wbR6tTXugEeVp zXck^7�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 z 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 1 ) THEN @@ -3438,9 +3445,9 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END DO ! Add up total number of joints flagged with JoinOvrlp = 1 option - IF ( InitInp%Morison%InpJoints(I)%JointOvrlp == 1 ) THEN - InitInp%Morison%TotalPossibleSuperMembers = InitInp%Morison%TotalPossibleSuperMembers + 1 - END IF + !IF ( InitInp%Morison%InpJoints(I)%JointOvrlp == 1 ) THEN + ! InitInp%Morison%TotalPossibleSuperMembers = InitInp%Morison%TotalPossibleSuperMembers + 1 + !END IF ! Check that every joint id is used at least once in the members table JointUsed = .FALSE. @@ -3541,15 +3548,23 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF + IF ( InitInp%Morison%SimplAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplAxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%SimplAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF IF ( InitInp%Morison%SimplAxCa < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + CALL SetErrStat( ErrID_Fatal,'SimplAxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF IF ( InitInp%Morison%SimplAxCaMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + CALL SetErrStat( ErrID_Fatal,'SimplAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF - + !TODO: Do we need a test for AxCp !------------------------------------------------------------------------------------------------- ! Depth-based Hydrodynamic Coefficients Section @@ -3602,6 +3617,14 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InitInp%Morison%CoefDpths(I)%DpthAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF IF ( InitInp%Morison%CoefDpths(I)%DpthAxCa < 0 ) THEN CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3720,8 +3743,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%Morison%InpMembers(I)%MPropSetID2Indx = -1 InitInp%Morison%InpMembers(I)%MmbrFilledIDIndx = -1 InitInp%Morison%InpMembers(I)%MmbrCoefIDIndx = -1 - InitInp%Morison%InpMembers(I)%NumSplits = 0 - InitInp%Morison%InpMembers(I)%Splits = 0.0_ReKi END DO DO I = 1,InitInp%Morison%NMembers @@ -3744,7 +3765,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) IF ( InitInp%Morison%InpMembers(I)%MJointID2 == InitInp%Morison%InpJoints(J)%JointID ) THEN InitInp%Morison%InpMembers(I)%MJointID2Indx = J InitInp%Morison%InpJoints(J)%NConnections = InitInp%Morison%InpJoints(J)%NConnections + 1 - InitInp%Morison%InpJoints(J)%ConnectionList(InitInp%Morison%InpJoints(J)%NConnections) = I + InitInp%Morison%InpJoints(J)%ConnectionList(InitInp%Morison%InpJoints(J)%NConnections) = -I !TODO: Come up with a better method for this work GJH 4/6/20 END IF END DO @@ -3759,7 +3780,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF ! Make sure we do not have any zero length members - lvec = InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID1Indx)%JointPos - InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID2Indx)%JointPos + lvec = InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID1Indx)%Position - InitInp%Morison%InpJoints(InitInp%Morison%InpMembers(I)%MJointID2Indx)%Position l = sqrt( lvec(1)*lvec(1) + lvec(2)*lvec(2) + lvec(3)*lvec(3) ) IF ( EqualRealNos(0.0_ReKi, l) ) THEN CALL SetErrStat( ErrID_Fatal,'A member cannot have zero length.',ErrStat,ErrMsg,RoutineName) @@ -3810,8 +3831,8 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF ! We will not extrapolate depth-based coefficient values, so make sure that the depth-based table has values that are outside the depth range of this member ! NOTE: This is actually potentially overly conservative because the final member may be shorter due to joint overlap handling. - z1 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID1Indx )%JointPos(3) - z2 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID2Indx )%JointPos(3) + z1 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID1Indx )%Position(3) + z2 = InitInp%Morison%InpJoints( InitInp%Morison%InpMembers(I)%MJointID2Indx )%Position(3) MinMembrDpth = min( z1, z2 ) MaxMembrDpth = max( z1, z2 ) IF ( ( MinMembrDpth < MinDepth ) .OR. ( MaxMembrDpth > MaxDepth ) ) THEN @@ -4043,7 +4064,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF END DO - ! Make sure that a PropSetID entry in the Member cross-section properties table was found + ! Make sure that a Joint Output ID found in the JOutLst is in the Joints table IF ( InitInp%Morison%JOutLst(I)%JointIDIndx == -1 ) THEN CALL SetErrStat( ErrID_Fatal,'JointID in the Joint output list table does not appear in the Joints table.',ErrStat,ErrMsg,RoutineName) RETURN @@ -4146,14 +4167,14 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! Current ! For wave kinematic calculations, the effective water depth is the user input water depth (positive valued) + MSL2SWL (positive when SWL is above MSL). - InitInp%Current%WtrDpth = InitInp%Morison%WtrDpth + InitInp%Morison%MSL2SWL ! Adjust for the MSL2SWL. + InitInp%Current%WtrDpth = InitInp%Morison%WtrDpth ! already adjusted for the MSL2SWL. ! Waves InitInp%Waves%Gravity = InitInp%Gravity InitInp%Waves%UnSum = InitInp%UnSum ! For wave kinematic calculations, the effective water depth is the user input water depth (positive valued) + MSL2SWL (positive when SWL is above MSL). - InitInp%Waves%WtrDpth = InitInp%Morison%WtrDpth + InitInp%Morison%MSL2SWL ! Adjust for the MSL2SWL + InitInp%Waves%WtrDpth = InitInp%Morison%WtrDpth ! already adjusted for the MSL2SWL. ! Waves2 IF (InitInp%Waves2%WvDiffQTFF .OR. InitInp%Waves2%WvSumQTFF ) THEN @@ -4188,7 +4209,8 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%Morison%OutAll = InitInp%OutAll ! Process the input geometry and generate the simulation mesh representation - CALL Morison_ProcessMorisonGeometry( InitInp%Morison, ErrStat2, ErrMsg2 ) + call Morison_GenerateSimulationNodes( InitInp%Morison%MSL2SWL, InitInp%Morison%NJoints, InitInp%Morison%InpJoints, InitInp%Morison%NMembers, InitInp%Morison%InpMembers, InitInp%Morison%NNodes, InitInp%Morison%Nodes, errStat2, errMsg2 ) + !CALL Morison_ProcessMorisonGeometry( InitInp%Morison, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -4222,9 +4244,9 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) RETURN END IF DO I=1,InitInp%Morison%NNodes - InitInp%Waves%WaveKinxi(I) = InitInp%Morison%Nodes(I)%JointPos(1) ! xi-coordinates for points where the incident wave kinematics will be computed; - InitInp%Waves%WaveKinyi(I) = InitInp%Morison%Nodes(I)%JointPos(2) ! yi-coordinates for points where the incident wave kinematics will be computed; - InitInp%Waves%WaveKinzi(I) = InitInp%Morison%Nodes(I)%JointPos(3) - InitInp%Morison%MSL2SWL ! zi-coordinates for points where the incident wave kinematics will be computed, adjusted to the still water level(meters) + InitInp%Waves%WaveKinxi(I) = InitInp%Morison%Nodes(I)%Position(1) ! xi-coordinates for points where the incident wave kinematics will be computed; + InitInp%Waves%WaveKinyi(I) = InitInp%Morison%Nodes(I)%Position(2) ! yi-coordinates for points where the incident wave kinematics will be computed; + InitInp%Waves%WaveKinzi(I) = InitInp%Morison%Nodes(I)%Position(3) ! zi-coordinates for points where the incident wave kinematics will be computed; InitInp%Current%MorisonNodezi(I) = InitInp%Waves%WaveKinzi(I) END DO diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index f2016a6bb..5e968b5d1 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -119,7 +119,6 @@ MODULE HydroDyn_Types TYPE(MeshMapType) :: uW_P_2_PRP_P !< Mesh mapping data: WAMIT body kinematics to PRP node at (0,0,0) [-] TYPE(MeshMapType) :: W_P_2_PRP_P !< Mesh mapping data: WAMIT loads to PRP node at (0,0,0) [-] TYPE(MeshMapType) :: M_P_2_PRP_P !< Mesh mapping data: lumped Morison loads to PRP node at (0,0,0) [-] - TYPE(MeshMapType) :: M_L_2_PRP_P !< Mesh mapping data: distributed Morison loads to PRP node at (0,0,0) [-] END TYPE HD_ModuleMapType ! ======================= ! ========= HydroDyn_ContinuousStateType ======= @@ -157,8 +156,7 @@ MODULE HydroDyn_Types ! ========= HydroDyn_MiscVarType ======= TYPE, PUBLIC :: HydroDyn_MiscVarType TYPE(MeshType) :: AllHdroOrigin !< An intermediate mesh used to transfer hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] - TYPE(MeshType) :: MrsnLumpedMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] - TYPE(MeshType) :: MrsnDistribMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] + TYPE(MeshType) :: MrsnMesh_position !< A motions mesh which has all translational displacements set to zero. Used in the transfer of hydrodynamic loads from the various HD-related meshes to the AllHdroOrigin mesh [-] TYPE(HD_ModuleMapType) :: HD_MeshMap INTEGER(IntKi) :: Decimate !< The output decimation counter [-] REAL(DbKi) :: LastOutTime !< Last time step which was written to the output file (sec) [-] @@ -3267,9 +3265,6 @@ SUBROUTINE HydroDyn_CopyHD_ModuleMapType( SrcHD_ModuleMapTypeData, DstHD_ModuleM CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_P_2_PRP_P, DstHD_ModuleMapTypeData%M_P_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcHD_ModuleMapTypeData%M_L_2_PRP_P, DstHD_ModuleMapTypeData%M_L_2_PRP_P, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE HydroDyn_CopyHD_ModuleMapType SUBROUTINE HydroDyn_DestroyHD_ModuleMapType( HD_ModuleMapTypeData, ErrStat, ErrMsg ) @@ -3284,7 +3279,6 @@ SUBROUTINE HydroDyn_DestroyHD_ModuleMapType( HD_ModuleMapTypeData, ErrStat, ErrM CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%uW_P_2_PRP_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%W_P_2_PRP_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_P_2_PRP_P, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( HD_ModuleMapTypeData%M_L_2_PRP_P, ErrStat, ErrMsg ) END SUBROUTINE HydroDyn_DestroyHD_ModuleMapType SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -3374,23 +3368,6 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! M_L_2_PRP_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_PRP_P, ErrStat2, ErrMsg2, .TRUE. ) ! M_L_2_PRP_P - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! M_L_2_PRP_P - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! M_L_2_PRP_P - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! M_L_2_PRP_P - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -3502,34 +3479,6 @@ SUBROUTINE HydroDyn_PackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%M_L_2_PRP_P, ErrStat2, ErrMsg2, OnlySize ) ! M_L_2_PRP_P - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF END SUBROUTINE HydroDyn_PackHD_ModuleMapType SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -3684,46 +3633,6 @@ SUBROUTINE HydroDyn_UnPackHD_ModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%M_L_2_PRP_P, ErrStat2, ErrMsg2 ) ! M_L_2_PRP_P - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE HydroDyn_UnPackHD_ModuleMapType SUBROUTINE HydroDyn_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -5996,10 +5905,7 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs CALL MeshCopy( SrcMiscData%AllHdroOrigin, DstMiscData%AllHdroOrigin, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcMiscData%MrsnLumpedMesh_position, DstMiscData%MrsnLumpedMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcMiscData%MrsnDistribMesh_position, DstMiscData%MrsnDistribMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcMiscData%MrsnMesh_position, DstMiscData%MrsnMesh_position, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL HydroDyn_Copyhd_modulemaptype( SrcMiscData%HD_MeshMap, DstMiscData%HD_MeshMap, CtrlCode, ErrStat2, ErrMsg2 ) @@ -6119,8 +6025,7 @@ SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" CALL MeshDestroy( MiscData%AllHdroOrigin, ErrStat, ErrMsg ) - CALL MeshDestroy( MiscData%MrsnLumpedMesh_position, ErrStat, ErrMsg ) - CALL MeshDestroy( MiscData%MrsnDistribMesh_position, ErrStat, ErrMsg ) + CALL MeshDestroy( MiscData%MrsnMesh_position, ErrStat, ErrMsg ) CALL HydroDyn_Destroyhd_modulemaptype( MiscData%HD_MeshMap, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%F_PtfmAdd)) THEN DEALLOCATE(MiscData%F_PtfmAdd) @@ -6210,37 +6115,20 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! MrsnLumpedMesh_position: size of buffers for each call to pack subtype - CALL MeshPack( InData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnLumpedMesh_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! MrsnLumpedMesh_position - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! MrsnLumpedMesh_position - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! MrsnLumpedMesh_position - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! MrsnDistribMesh_position: size of buffers for each call to pack subtype - CALL MeshPack( InData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnDistribMesh_position + Int_BufSz = Int_BufSz + 3 ! MrsnMesh_position: size of buffers for each call to pack subtype + CALL MeshPack( InData%MrsnMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! MrsnMesh_position CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! MrsnDistribMesh_position + IF(ALLOCATED(Re_Buf)) THEN ! MrsnMesh_position Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! MrsnDistribMesh_position + IF(ALLOCATED(Db_Buf)) THEN ! MrsnMesh_position Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! MrsnDistribMesh_position + IF(ALLOCATED(Int_Buf)) THEN ! MrsnMesh_position Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -6474,35 +6362,7 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL MeshPack( InData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! MrsnLumpedMesh_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! MrsnDistribMesh_position + CALL MeshPack( InData%MrsnMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! MrsnMesh_position CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6950,47 +6810,7 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%MrsnLumpedMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! MrsnLumpedMesh_position - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%MrsnDistribMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! MrsnDistribMesh_position + CALL MeshUnpack( OutData%MrsnMesh_position, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! MrsnMesh_position CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 32b329b4a..83e0b9b07 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -35,7 +35,7 @@ MODULE Morison ! ..... Public Subroutines ................................................................................................... - PUBLIC:: Morison_ProcessMorisonGeometry + PUBLIC:: Morison_GenerateSimulationNodes PUBLIC :: Morison_Init ! Initialization routine PUBLIC :: Morison_End ! Ending routine (includes clean up) @@ -100,8 +100,8 @@ SUBROUTINE Morison_DirCosMtrx( pos0, pos1, DirCos ) ELSE - DirCos(1, 1) = -(z0-z1)/xz - DirCos(1, 2) = -(x0-x1)*(y0-y1)/(xz*xyz) + DirCos(1, 1) = (z1-z0)/xz + DirCos(1, 2) = -(x1-x0)*(y1-y0)/(xz*xyz) DirCos(1, 3) = (x1-x0)/xyz DirCos(2, 1) = 0.0 @@ -109,13 +109,9 @@ SUBROUTINE Morison_DirCosMtrx( pos0, pos1, DirCos ) DirCos(2, 3) = (y1-y0)/xyz DirCos(3, 1) = -(x1-x0)/xz - DirCos(3, 2) = -(y0-y1)*(z0-z1)/(xz*xyz) + DirCos(3, 2) = -(y1-y0)*(z1-z0)/(xz*xyz) DirCos(3, 3) = (z1-z0)/xyz - - ! DEBUG: TODO : Remove - !PRINT*, sqrt(DirCos(1,1)*DirCos(1,1) + DirCos(1,2)*DirCos(1,2)+DirCos(1,3)*DirCos(1,3)) - !PRINT*, sqrt(DirCos(2,1)*DirCos(2,1) + DirCos(2,2)*DirCos(2,2)+DirCos(2,3)*DirCos(2,3)) - !PRINT*, sqrt(DirCos(3,1)*DirCos(3,1) + DirCos(3,2)*DirCos(3,2)+DirCos(3,3)*DirCos(3,3)) + END IF END SUBROUTINE Morison_DirCosMtrx @@ -350,299 +346,6 @@ FUNCTION InterpWrappedStpLogical( XValIn, XAry, YAry, Ind, AryLen ) RETURN END FUNCTION InterpWrappedStpLogical ! ( XVal, XAry, YAry, Ind, AryLen ) -SUBROUTINE DistrBuoyancy( densWater, R, tMG, dRdz, Z, C, g, F_B ) - ! This calculates the distributed buoyancy forces and moments on a given node - - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R ! Radius of node [m] - REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] - REAL(ReKi), INTENT ( IN ) :: dRdz ! Rate of change in radius with length at node [-] - REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of node [m] (not currently used) - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Distributed force and moment vector [N/m and N-m/m] - - REAL(DbKi) :: Reff,ReffSq,ReffCub,f1,f2,f3 - - REAL(DbKi) :: CC(3,3) - - CC = REAL(C,DbKi) - Reff = REAL(R + tMG,DbKi) ! Effective radius after adding marine growth - - - - ReffSq = Reff*Reff - ReffCub = ReffSq*Reff - f1 = REAL(denswater,DbKi)*REAL(g,DbKi)*Pi_D - f2 = f1*ReffCub*REAL(dRdz,DbKi) - f3 = Reff*REAL(dRdz,DbKi)*REAL(Z,DbKi) - - - F_B(1) = f1*( (CC(1,1)*CC(3,1) + CC(1,2)*CC(3,2))*ReffSq - 2.0*CC(1,3)*f3 ) - F_B(2) = f1*( (CC(2,1)*CC(3,1) + CC(2,2)*CC(3,2))*ReffSq - 2.0*CC(2,3)*f3 ) - F_B(3) = f1*( (CC(3,1)*CC(3,1) + CC(3,2)*CC(3,2))*ReffSq - 2.0*CC(3,3)*f3 ) - F_B(4) = -f2*( CC(1,1)*CC(3,2) - CC(1,2)*CC(3,1) ) - F_B(5) = -f2*( CC(2,1)*CC(3,2) - CC(2,2)*CC(3,1) ) - F_B(6) = -f2*( CC(3,1)*CC(3,2) - CC(3,2)*CC(3,1) ) - - - - -END SUBROUTINE DistrBuoyancy - - -SUBROUTINE DistrInertialLoads( nodeIndx, densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, NStepWave, WaveAcc0, WaveDynP0, F_I, ErrStat, ErrMsg ) - - INTEGER, INTENT ( IN ) :: nodeIndx - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: Ca - REAL(ReKi), INTENT ( IN ) :: Cp - REAL(ReKi), INTENT ( IN ) :: AxCa - REAL(ReKi), INTENT ( IN ) :: AxCp - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( IN ) :: dRdZ - REAL(ReKi), INTENT ( IN ) :: k(3) - INTEGER, INTENT ( IN ) :: NStepWave - REAL(SiKi), INTENT ( IN ) :: WaveAcc0(0:,:,:) - REAL(SiKi), INTENT ( IN ) :: WaveDynP0(0:,:) - REAL(ReKi),ALLOCATABLE, INTENT ( OUT ) :: F_I(:,:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I - REAL(ReKi) :: f, f1, f2, f3, adotk !, v_len - REAL(ReKi) :: v(3), af(3) !p0(3), m(3), - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - ! Allocate F_I - ALLOCATE ( F_I(0:NStepWave, 6), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating distributed inertial loads array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - f = (Ca + Cp)*densWater*Pi*(R+tMG)*(R+tMG) - f2 = AxCa*densWater*2.0*Pi*(R+tMG)*(R+tMG)*abs(dRdZ) - f1 = AxCp*2.0*Pi*(R+tMG)*dRdz - - DO I=0,NStepWave - - af = WaveAcc0(I,nodeIndx,:) - adotk = af(1)*k(1) + af(2)*k(2) + af(3)*k(3) - v = af - adotk*k - - ! NOTE: (k cross l) x k = l - (l dot k)k - - f3 = f1*WaveDynP0(I,nodeIndx) - - !CALL GetDistance( p0, v, v_len ) - !TODO What about multiplying by the magnitude? - - - - F_I(I,1) = f*v(1) + (f3 + f2*adotk)*k(1) - F_I(I,2) = f*v(2) + (f3 + f2*adotk)*k(2) - F_I(I,3) = f*v(3) + (f3 + f2*adotk)*k(3) - F_I(I,4) = 0.0 - F_I(I,5) = 0.0 - F_I(I,6) = 0.0 - - END DO - -END SUBROUTINE DistrInertialLoads - - - -SUBROUTINE DistrInertialLoads2( densWater, Ca, Cp, AxCa, AxCp, R, tMG, dRdZ, k, WaveAcc, WaveDynP, F_I, ErrStat, ErrMsg ) - - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: Ca - REAL(ReKi), INTENT ( IN ) :: Cp - REAL(ReKi), INTENT ( IN ) :: AxCa - REAL(ReKi), INTENT ( IN ) :: AxCp - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( IN ) :: dRdZ - REAL(ReKi), INTENT ( IN ) :: k(3) - REAL(ReKi), INTENT ( IN ) :: WaveAcc(3) - REAL(ReKi), INTENT ( IN ) :: WaveDynP - REAL(ReKi), INTENT ( OUT ) :: F_I(3) - !REAL(ReKi), INTENT ( OUT ) :: F_I(3) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I - REAL(ReKi) :: f, f1, f2, f3, v_len, adotk - REAL(ReKi) :: p0(3), m(3), v(3), af(3) - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - - f = (Ca + Cp)*densWater*Pi*(R+tMG)*(R+tMG) - f2 = AxCa*densWater*2.0*Pi*(R+tMG)*(R+tMG)*abs(dRdZ) - f1 = AxCp*2.0*Pi*(R+tMG)*dRdz - - adotk = WaveAcc(1)*k(1) + WaveAcc(2)*k(2) + WaveAcc(3)*k(3) - v = WaveAcc - adotk*k - - ! NOTE: (k cross l) x k = l - (l dot k)k - - f3 = f1*WaveDynP - - !CALL GetDistance( p0, v, v_len ) - !TODO What about multiplying by the magnitude? - - - - F_I(1) = f*v(1) + (f3 + f2*adotk)*k(1) - F_I(2) = f*v(2) + (f3 + f2*adotk)*k(2) - F_I(3) = f*v(3) + (f3 + f2*adotk)*k(3) - !F_I(4) = 0.0_ReKi - !F_I(5) = 0.0_ReKi - !F_I(6) = 0.0_ReKi - - - -END SUBROUTINE DistrInertialLoads2 - - -SUBROUTINE DistrMGLoads(MGdens, g, R, tMG, F_MG ) - REAL(ReKi), INTENT ( IN ) :: MGdens - REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( OUT ) :: F_MG(6) - - F_MG(:) = 0.0 - F_MG(3) = -MGdens*g*Pi* ( (R + tMG ) * ( R + tMG ) - R*R ) - -END SUBROUTINE DistrMGLoads - -SUBROUTINE DistrDragConst( densWater, Cd, R, tMG, DragConst ) !@mhall: is there any reason to have this function? - ! It's only called once and it's a simple multiplication. - - ! This is used to minimize the computations which occur at each timestep - - REAL(ReKi), INTENT ( IN ) :: Cd - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( OUT ) :: DragConst - - DragConst = Cd*densWater*(R+tMG) - -END SUBROUTINE DistrDragConst - - -SUBROUTINE DistrFloodedBuoyancy( densFluid, Z_f, R, t, dRdz, Z, C, g, F_B ) - - REAL(ReKi), INTENT ( IN ) :: densFluid - REAL(ReKi), INTENT ( IN ) :: Z_f - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: t - REAL(ReKi), INTENT ( IN ) :: dRdz - REAL(ReKi), INTENT ( IN ) :: Z - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_B(6) - - REAL(DbKi) :: Zeff,Reff,ReffSq,ReffCub,f1,f2,f3 - - - REAL(DbKi) :: CC(3,3) - CC = REAL(C,DbKi) - - - Reff = REAL(R - t,DbKi) - Zeff = REAL(Z - Z_f,DbKi) - - ReffSq = Reff*Reff - ReffCub = ReffSq*Reff - f1 = -REAL(densFluid,DbKi)*REAL(g,DbKi)*Pi_D - f2 = f1*ReffCub*REAL(dRdz,DbKi) - f3 = Reff*REAL(dRdz,DbKi)*Zeff - - - - F_B(1) = f1*( (CC(1,1)*CC(3,1) + CC(1,2)*CC(3,2))*ReffSq - 2.0*CC(1,3)*f3 ) - F_B(2) = f1*( (CC(2,1)*CC(3,1) + CC(2,2)*CC(3,2))*ReffSq - 2.0*CC(2,3)*f3 ) - F_B(3) = f1*( (CC(3,1)*CC(3,1) + CC(3,2)*CC(3,2))*ReffSq - 2.0*CC(3,3)*f3 ) - F_B(4) = -f2*( CC(1,1)*CC(3,2) - CC(1,2)*CC(3,1) ) - F_B(5) = -f2*( CC(2,1)*CC(3,2) - CC(2,2)*CC(3,1) ) - F_B(6) = -f2*( CC(3,1)*CC(3,2) - CC(3,2)*CC(3,1) ) - -END SUBROUTINE DistrFloodedBuoyancy - -SUBROUTINE DistrAddedMass( densWater, Ca, AxCa, C, R, tMG, dRdZ, AM_M) - ! This calculates the distributed hydrodynamic added mass matrix for a given node. - - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: Ca ! Transverse added mass coefficient - REAL(ReKi), INTENT ( IN ) :: AxCa ! Axial added mass coefficient (applied to tapered portions) - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: R ! Radius at node [m] - REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] - REAL(ReKi), INTENT ( IN ) :: dRdZ ! Rate of change in radius with length at node [-] - REAL(ReKi), INTENT ( OUT ) :: AM_M(3,3) ! Distributed added mass matrix to be calculated [kg/m] - - REAL(ReKi) :: f,f2 - - f = Ca*densWater*Pi*(R+tMG)*(R+tMG) ! Transverse added mass scaler, applied to I - k*k^T - f2 = AxCa*2.0*densWater*Pi*abs(dRdZ)*(R+tMG)*(R+tMG) ! Axial added mass scaler, applied to k k^T - !AM_M = 0.0 - AM_M(1,1) = f*( C(2,3)*C(2,3) + C(3,3)*C(3,3) ) -f2*C(1,3)*C(1,3) !<----@mhall: why is the f2 term being subtracted rather than added? - AM_M(1,2) = f*( -C(1,3)*C(2,3) ) -f2*C(1,3)*C(2,3) - AM_M(1,3) = f*( -C(1,3)*C(3,3) ) -f2*C(1,3)*C(3,3) - - AM_M(2,1) = f*( -C(1,3)*C(2,3) ) -f2*C(2,3)*C(1,3) - AM_M(2,2) = f*( C(1,3)*C(1,3) + C(3,3)*C(3,3) ) -f2*C(2,3)*C(2,3) !<----@mhall: would it be cleaner to just use the k unit vector? (also, diagonal terms can be shortened (1-k*kT)) - AM_M(2,3) = f*( -C(2,3)*C(3,3) ) -f2*C(2,3)*C(3,3) - - AM_M(3,1) = f*( -C(1,3)*C(3,3) ) -f2*C(3,3)*C(1,3) - AM_M(3,2) = f*( -C(2,3)*C(3,3) ) -f2*C(3,3)*C(2,3) - AM_M(3,3) = f*( C(1,3)*C(1,3) + C(2,3)*C(2,3) ) -f2*C(3,3)*C(3,3) - - -END SUBROUTINE DistrAddedMass - - -SUBROUTINE DistrAddedMassMG( densMG, R, tMG, AM_MG) - - REAL(ReKi), INTENT ( IN ) :: densMG - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( OUT ) :: AM_MG - - AM_MG = densMG*Pi*((R+tMG)*(R+tMG) - R*R) - - -END SUBROUTINE DistrAddedMassMG - - -SUBROUTINE DistrAddedMassFlood( densFluid, R, t, AM_F) - - REAL(ReKi), INTENT ( IN ) :: densFluid - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: t - REAL(ReKi), INTENT ( OUT ) :: AM_F - - - AM_F = densFluid*Pi*(R-t)*(R-t) - -END SUBROUTINE DistrAddedMassFlood - - - SUBROUTINE LumpDragConst( densWater, Cd, R, tMG, DragConst ) ! This is used to minimize the computations which occur at each timestep @@ -658,7 +361,7 @@ SUBROUTINE LumpDragConst( densWater, Cd, R, tMG, DragConst ) END SUBROUTINE LumpDragConst -SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg ) +SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, errStat, errMsg ) INTEGER, INTENT ( IN ) :: nodeIndx @@ -669,23 +372,23 @@ SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, INTEGER, INTENT ( IN ) :: NStepWave REAL(SiKi), INTENT ( IN ) :: WaveDynP(0:,:) REAL(ReKi),ALLOCATABLE, INTENT ( OUT ) :: F_DP(:,:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER, INTENT ( OUT ) :: errStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: errMsg ! Error message if errStat /= ErrID_None INTEGER :: I - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ! Allocate F_DP - ALLOCATE ( F_DP(0:NStepWave,6), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating distributed dynamic pressure loads array.' - ErrStat = ErrID_Fatal + ALLOCATE ( F_DP(0:NStepWave,6), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating distributed dynamic pressure loads array.' + errStat = ErrID_Fatal RETURN END IF @@ -700,290 +403,200 @@ SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, END SUBROUTINE LumpDynPressure - - - -SUBROUTINE LumpBuoyancy( sgn, densWater, R, tMG, Z, C, g, F_B ) - ! This calculates lumped buoyancy forces/moments on a member end. - - REAL(ReKi), INTENT ( IN ) :: sgn ! @mhall: this indicates if this is the start or end node so that direction is correct? - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R ! Radius of end [m] - REAL(ReKi), INTENT ( IN ) :: tMG ! Thickness of marine growth (adds to radius) [m] - REAL(ReKi), INTENT ( IN ) :: Z ! z elevation of end [m] - - REAL(ReKi), INTENT ( IN ) :: C(3,3) - REAL(ReKi), INTENT ( IN ) :: g - REAL(ReKi), INTENT ( OUT ) :: F_B(6) ! Lumped force and moment vector [N and N-m] - - - REAL(DbKi) :: f, f1, f2, f3, Reff, Rsq,R_4 - Reff = REAL(R+tMG,DbKi) - Rsq = Reff**2 - R_4 = Rsq**2 - f = REAL(g,DbKi)*REAL(densWater,DbKi)*REAL(sgn,DbKi) - f1 = -REAL(Z,DbKi)*Pi_D*Rsq - f2 = f*Pi_D*R_4 - !f3 = C(3,1)*R_4 - - F_B(1) = C(1,3)*f1*f - F_B(2) = C(2,3)*f1*f - F_B(3) = C(3,3)*f1*f - F_B(4) = 0.25*( -C(3,2)*C(1,1) + C(1,2)*C(3,1) )*f2 ! TODO: We flipped the signs of the moments because 1 member tapered integrated moments were not zero. GJH 10/1/13 Jason is verifying. - F_B(5) = 0.25*( -C(3,2)*C(2,1) + C(2,2)*C(3,1) )*f2 - F_B(6) = 0.25*( -C(3,2)*C(3,1) + C(3,2)*C(3,1) )*f2 +subroutine GetOrientationAngles(p1, p2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat, errMsg) + real(ReKi), intent(in ) :: p1(3),p2(3) + real(ReKi), intent( out) :: phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat(3) + integer, intent( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent( out) :: errMsg ! Error message if errStat /= ErrID_None + + + real(ReKi) :: vec(3), vecLen, vecLen2D, beta + + ! Initialize errStat + + errStat = ErrID_None + errMsg = "" + + ! calculate isntantaneous incline angle and heading, and related trig values + ! the first and last NodeIndx values point to the corresponding Joint nodes idices which are at the start of the Mesh + vec = p2 - p1 + vecLen = SQRT(Dot_Product(vec,vec)) + vecLen2D = SQRT(vec(1)**2+vec(2)**2) + if ( vecLen < 0.000001 ) then + call SeterrStat(ErrID_Fatal, 'An element of the Morison structure has co-located endpoints! This should never occur. Please review your model.', errStat, errMsg, 'Morison_CalcOutput' ) + else + k_hat = vec / vecLen + phi = atan2(vecLen2D, vec(3)) ! incline angle + end if + if ( EqualRealNos(phi, 0.0_ReKi) ) then + beta = 0.0_ReKi + else + beta = atan2(vec(2), vec(1)) ! heading of incline + endif + sinPhi = sin(phi) + cosPhi = cos(phi) + tanPhi = tan(phi) + sinBeta = sin(beta) + cosBeta = cos(beta) + +end subroutine GetOrientationAngles + + +!function to return conical taper geometry calculations (volume and center of volume) +SUBROUTINE TaperCalc(R1, R2, H, taperV, h_c) + REAL(ReKi), INTENT ( IN ) :: R1 + REAL(ReKi), INTENT ( IN ) :: R2 + REAL(ReKi), INTENT ( IN ) :: H + REAL(ReKi), INTENT ( OUT ) :: taperV ! volume of tapered section + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + + real(ReKi) :: m + + m = (R2-R1)/H + + if ( EqualRealNos(R1, R2) ) then ! if just a cylinder + taperV = abs(pi*R1*R1*H) + h_c = H/2.0 + elseif ( EqualRealNos(R1,0.0_ReKi) ) then ! seperate this case out because it gives a divide by zero in general formula + taperV = abs(1./3.*pi*R2*R2*H) ! cone volume + h_c = 3./4.*H ! from base + else + taperV = abs(pi/3/m*(R2**3 - R1**3)) + h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) !( coneV*1./4.*coneH - coneVtip*(1./4.*(coneH-H) + H) )/ taperV ! from base + end if +END SUBROUTINE TaperCalc + + +SUBROUTINE CylInertia(R1, R2, H, rho, Il, Ir) + REAL(ReKi), INTENT ( IN ) :: R1 + REAL(ReKi), INTENT ( IN ) :: R2 + REAL(ReKi), INTENT ( IN ) :: H + REAL(ReKi), INTENT ( IN ) :: rho ! density of material + REAL(ReKi), INTENT ( OUT ) :: Il + REAL(ReKi), INTENT ( OUT ) :: Ir + + real(ReKi) :: m, Ir_tip, h_c + + m = (R2-R1)/H + + if ( EqualRealNos(R1, R2) ) then ! if just a cylinder + Ir = abs(1/12* rho*pi*R1*R1*H *(3*R1*R1 + 4*H*H)) ! radial inertia about node 1 + Il = abs(0.5* rho*pi*R1*R1*H *R1*R1) + ELSEIF ( EqualRealNos(R1,0.0_ReKi) ) then ! seperate this case out because it gives a divide by zero in general formula + Ir = abs(rho*pi*(1/20/m + 1/5/m**3) * R2**5) + Il = abs(1/10*rho*pi/m*R2**5) + ELSE + h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) + !l_c = R1/M + (R2-R1)/m *(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) + Ir_tip = abs(pi/20 *rho/m*(1 + 4/m**2) * (R2**5 - R1**5)) ! radial moment of inertia about tip of cone + Ir = abs(Ir_tip - rho/3/m*pi*(R2**3-R1**3) * (R1/m + 2*h_c)*R1/m ) ! radial moment of inertia about node 1 + Il = abs(1/10/m*rho*pi*(R2**5 - R1**5)) + END IF -END SUBROUTINE LumpBuoyancy +END SUBROUTINE CylInertia -LOGICAL FUNCTION IsThisSplitValueUsed(nSplits, splits, checkVal) - INTEGER, INTENT ( IN ) :: nSplits - REAL(ReKi), INTENT ( IN ) :: splits(:) - REAL(ReKi), INTENT ( IN ) :: checkVal +SUBROUTINE MarineGrowthPartSegment(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, m_mg, h_c, Ilmg, Irmg) - INTEGER :: I + REAL(ReKi), INTENT ( IN ) :: R1 + REAL(ReKi), INTENT ( IN ) :: R2 + REAL(ReKi), INTENT ( IN ) :: Rmg1 + REAL(ReKi), INTENT ( IN ) :: Rmg2 + REAL(ReKi), INTENT ( IN ) :: L + REAL(ReKi), INTENT ( IN ) :: rho ! density of material + REAL(ReKi), INTENT ( OUT ) :: Vinner ! volume from inner radius + REAL(ReKi), INTENT ( OUT ) :: Vouter ! volume from outer radius + REAL(ReKi), INTENT ( OUT ) :: m_mg ! mass of marine growth + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + REAL(ReKi), INTENT ( OUT ) :: Ilmg ! moment of inertia about axis + REAL(ReKi), INTENT ( OUT ) :: Irmg ! moment of inertia about radial axis from first node - DO I=1,nSplits - IF ( EqualRealNos(splits(I), checkVal ) ) THEN - IsThisSplitValueUsed = .TRUE. - RETURN - END IF -END DO + ! Local variables + + REAL(ReKi) :: cVinner ! center of volume from inner radius + REAL(ReKi) :: cVouter ! center of volume from outer radius + REAL(ReKi) :: Ilinner + REAL(ReKi) :: Irinner + REAL(ReKi) :: Ilouter + REAL(ReKi) :: Irouter + + + + ! get V and CV for element + call TaperCalc(R1, R2, L, Vinner, cVinner) - IsThisSplitValueUsed = .FALSE. + ! get V and CV for marine growth displacement + call TaperCalc(Rmg1, Rmg2, L, Vouter, cVouter) -END FUNCTION IsThisSplitValueUsed -!==================================================================================================== -SUBROUTINE GetMaxSimQuantities( numMGDepths, MGTop, MGBottom, MSL2SWL, Zseabed, filledGroups, numJoints, joints, numMembers, members, maxNodes, maxElements, maxSuperMembers ) -! This private subroutine determines the maximum nodes, elements, and super members which may appear -! in the final simulation mesh. This is based on the following: -! 1) Member splitting at the marine growth boundaries ( new nodes and members ) -! 2) Member splitting due to internal subdivision ( new nodes and members ) -! 3) New nodes and super members if a joint marked with JointOvrlp = 1 (and additional conditions are satisfied) -! -!---------------------------------------------------------------------------------------------------- - INTEGER, INTENT ( IN ) :: numMGDepths ! number of MGDepths specified in the input table - REAL(ReKi), INTENT ( IN ) :: MGTop ! Global Z-value of the upper marine growth boundary - REAL(ReKi), INTENT ( IN ) :: MGBottom ! Global Z-value of the lower marine growth boundary - REAL(ReKi), INTENT ( IN ) :: MSL2SWL ! Global Z-value of mean sea level - REAL(ReKi), INTENT ( IN ) :: Zseabed ! Global Z-value of the top of the seabed - TYPE(Morison_FilledGroupType), INTENT ( IN ) :: filledGroups(:) - INTEGER, INTENT ( IN ) :: numJoints ! number of joints specified in the inputs - TYPE(Morison_JointType), INTENT ( IN ) :: joints(:) ! array of input joint data structures - INTEGER, INTENT ( IN ) :: numMembers ! number of members specified in the inputs - TYPE(Morison_MemberInputType), INTENT ( INOUT ) :: members(:) ! array of input member data structures - INTEGER, INTENT ( OUT ) :: maxNodes ! maximum number of nodes which may appear in the final simulation mesh - INTEGER, INTENT ( OUT ) :: maxElements ! maximum number of elements which may appear in the final simulation mesh - INTEGER, INTENT ( OUT ) :: maxSuperMembers ! maximum number of super members which may appear in the final simulation mesh + ! get mass and CV specific to marine growth thickness + m_mg = (cVouter - cVinner)*rho + if ( EqualRealNos(m_mg, 0.0_ReKi) ) then + h_c = 0.0 + else + h_c = (cVouter*cVouter - Vinner*cVinner)/(Vouter - Vinner) + end if - ! Local variables - INTEGER :: WtrSplitCount = 0 ! number of possible new members due to splitting at water boundaries - INTEGER :: MGsplitCount = 0 ! number of possible new members due to splitting at marine growth boundaries - INTEGER :: maxSubMembers = 0 ! maximum added nodes and members due to member subdivision - INTEGER :: maxSuperMemNodes = 0 ! maximum number of new nodes due to super member generation - INTEGER :: I, J, j1, j2 ! generic integer for counting - TYPE(Morison_JointType) :: joint1, joint2 ! joint data structures - Real(ReKi) :: z1, z2 ! z values of the first and second joints - Real(ReKi) :: temp ! temporary variable - REAL(ReKi) :: memLen ! member length - INTEGER :: nSplits, totalSplits, nodeSplits - REAL(ReKi) :: possibleSplits(5) - ! Initialize quantities - maxNodes = numJoints - maxElements = numMembers - maxSuperMembers = 0 - maxSuperMemNodes = 0 - maxSubMembers = 0 - MGsplitCount = 0 - WtrSplitCount = 0 - nodeSplits = 0 - totalSplits = 0 - - ! Determine new members and nodes due to internal member subdivision - DO I = 1,numMembers - - - z1 = joints( members(I)%MJointID1Indx )%JointPos(3) - z2 = joints( members(I)%MJointID2Indx )%JointPos(3) - IF ( z1 > z2) THEN - temp = z1 - z1 = z2 - z2 = temp - END IF - - - - ! For this member, determine possible split conditions due to crossing through: - ! MSL, seabed, marine growth boundaries, filled free surface location. - ! - - ! Start with no splits. - nSplits = 0 - possibleSplits = -9999999.0 ! Initialize possibleSplit values to a number that never appears in the geometry. - - ! If the member is filled, add a possible split location at the global Z location of the filled free surface. - IF ( members(I)%MmbrFilledIDIndx /= -1 ) THEN - nSplits = 1 - ! The free surface is specified relative to the MSL. - possibleSplits(1) = filledGroups(members(I)%MmbrFilledIDIndx)%FillFSLoc - END IF - - - ! If the filled fluid hasn't already caused a split in the member at the still water line, then add a possible split there (at the water free surface, MSL2SWL). - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MSL2SWL )) THEN - nSplits = nSplits + 1 - possibleSplits(nSplits) = MSL2SWL - END IF - - ! If there are one more depth-defined marine growth regions, add a possible split at each boundary if one doesn't already exist. - IF ( numMGDepths > 0 ) THEN - - ! Recursively check to see if this - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MGTop) ) THEN - nSplits = nSplits + 1 - possibleSplits(nSplits) = MGTop - END IF - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, MGBottom) ) THEN - nSplits = nSplits + 1 - possibleSplits(nSplits) = MGBottom - END IF - - END IF - - ! Add a possible split a the seabed if there isn't already one there. - ! Check if seabed is equal to other possibleSplits - IF ( .NOT. IsThisSplitValueUsed(nSplits, possibleSplits, Zseabed) ) THEN - nSplits = nSplits + 1 - possibleSplits(nSplits) = Zseabed - END IF - - - ! Now determine which possible splits this member actually crosses and record them in the member's data structure. - - DO J=1,nSplits - - IF ( z1 < possibleSplits(J) .AND. z2 > possibleSplits(J) ) THEN - members(I)%NumSplits = members(I)%NumSplits + 1 - members(I)%Splits(members(I)%NumSplits) = possibleSplits(J) - END IF - - END DO - ! Sort the splits from smallest Z value to largest Z value - CALL BSortReal ( members(I)%Splits, members(I)%NumSplits ) - totalSplits = totalSplits + members(I)%NumSplits - - ! ! Determine new members due to elements crossing the MSL or the seabed - !IF ( z2 > MSL2SWL ) THEN - ! IF ( z1 < MSL2SWL .AND. z1 >= Zseabed ) THEN - ! ! Split this member - ! WtrSplitCount = WtrSplitCount + 1 - ! members(I).WtrSplitState = 1 - ! END IF - ! IF ( z1 < Zseabed ) THEN - ! ! Split this member twice because it crosses both boundaries - ! WtrSplitCount = WtrSplitCount + 2 - ! members(I).WtrSplitState = 3 - ! END IF - !END IF - !IF ( z2 < MSL2SWL .AND. z2 >= Zseabed ) THEN - ! IF ( z1 < MGBottom ) THEN - ! ! Split this member - ! WtrSplitCount = WtrSplitCount + 1 - ! members(I).WtrSplitState = 2 - ! END IF - ! - !END IF - ! - ! ! Determine new members and nodes due to marine growth boundary splitting - ! members(I).MGSplitState = 0 - !IF ( numMGDepths > 0 ) THEN - ! - ! IF ( z2 > MGTop ) THEN - ! IF ( z1 < MGTop .AND. z1 >= MGBottom ) THEN - ! ! Split this member - ! MGsplitCount = MGsplitCount + 1 - ! members(I).MGSplitState = 1 - ! END IF - ! IF ( z1 < MGBottom ) THEN - ! ! Split this member twice because it crosses both boundaries - ! MGsplitCount = MGsplitCount + 2 - ! members(I).MGSplitState = 3 - ! END IF - ! END IF - ! IF ( z2 < MGTop .AND. z2 >= MGBottom ) THEN - ! IF ( z1 < MGBottom ) THEN - ! ! Split this member - ! MGsplitCount = MGsplitCount + 1 - ! members(I).MGSplitState = 2 - ! END IF - ! - ! END IF - ! - !END IF - - j1 = members(I)%MJointID1Indx - j2 = members(I)%MJointID2Indx - joint1 = joints(j1) ! note Inspector complains of uninitialized variables; this is due to copying types here (and some fields haven't been initialized) - joint2 = joints(j2) ! note Inspector complains of uninitialized variables; this is due to copying types here (and some fields haven't been initialized) - CALL GetDistance(joint1%JointPos, joint2%JointPos, memLen) - maxSubMembers = maxSubMembers + CEILING( memLen / members(I)%MDivSize ) - 1 - - END DO + ! get two moments of inertia for marine growth as if solid... + call CylInertia(Rmg1, Rmg2, L, rho, Ilouter, Irouter) ! inertias for marine growth if solid + call CylInertia(R1 , R2 , L, rho, Ilinner, Irinner) ! inertias for element if filled with marine growth + + ! subtract to get moments of inertia of marine growth shell + Ilmg = Ilouter - Ilinner + Irmg = Irouter - Irinner + +END SUBROUTINE MarineGrowthPartSegment + + +SUBROUTINE FloodedBallastPartSegment(R1, R2, L, rho, V, m, h_c, Il, Ir) - ! Look for all possible super member creation - DO I = 1,numJoints - - ! Check #1 are there more than 2 members connected to the joint? - IF ( joints(I)%JointOvrlp == 1 .AND. joints(I)%NConnections > 2) THEN - maxSuperMemNodes = maxSuperMemNodes + ( joints(I)%NConnections - 1 ) - maxSuperMembers = maxSuperMembers + 1 - ELSE - nodeSplits = nodeSplits + joints(I)%NConnections - 1 - END IF - - - END DO + REAL(ReKi), INTENT ( IN ) :: R1 ! interior radius of element at node point + REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element + REAL(ReKi), INTENT ( IN ) :: L ! distance positive along axis to end of part-element + REAL(ReKi), INTENT ( OUT ) :: V ! volume from inner radius + REAL(ReKi), INTENT ( IN ) :: rho ! density of ballast + REAL(ReKi), INTENT ( OUT ) :: m ! mass of material + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + REAL(ReKi), INTENT ( OUT ) :: Il ! moment of inertia about axis + REAL(ReKi), INTENT ( OUT ) :: Ir ! moment of inertia about radial axis from first node - maxNodes = maxNodes + totalSplits*2 + nodeSplits + maxSubMembers + maxSuperMemNodes - maxElements = maxElements + totalSplits + maxSubMembers + + ! get V and CV for flooded part of part-element + call TaperCalc(R1, R2, L, V, h_c) + m = rho*V -END SUBROUTINE GetMaxSimQuantities + call CylInertia(R1, R2, L, rho, Il, Ir) ! inertias for filled section -SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElements, elements, NOutputs, OutParam, NMOutputs, MOutLst, distribToNodeIndx, NJOutputs, JOutLst, inLumpedMesh, outLumpedMesh, inDistribMesh, outDistribMesh, L_F_B, L_F_BF, D_F_B, D_F_BF, D_F_MG, g, ErrStat, ErrMsg ) !, numDistribMarkers, distribMarkers, numLumpedMarkers, lumpedMarkers +END SUBROUTINE FloodedBallastPartSegment + +SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, nodes, numMembers, members, & + NOutputs, OutParam, NMOutputs, MOutLst, NJOutputs, JOutLst, uMesh, yMesh, & + p, m, errStat, errMsg ) + + INTEGER, INTENT ( IN ) :: UnSum + REAL(ReKi), INTENT ( IN ) :: g ! gravity REAL(ReKi), INTENT ( IN ) :: MSL2SWL REAL(ReKi), INTENT ( IN ) :: WtrDpth - INTEGER, INTENT ( IN ) :: UnSum + INTEGER, INTENT ( IN ) :: numJoints INTEGER, INTENT ( IN ) :: numNodes TYPE(Morison_NodeType), INTENT ( IN ) :: nodes(:) - INTEGER, INTENT ( IN ) :: numElements - TYPE(Morison_MemberType), INTENT ( IN ) :: elements(:) + INTEGER, INTENT ( IN ) :: numMembers + TYPE(Morison_MemberType), INTENT ( IN ) :: members(:) INTEGER, INTENT ( IN ) :: NOutputs TYPE(OutParmType), INTENT ( IN ) :: OutParam(:) INTEGER, INTENT ( IN ) :: NMOutputs TYPE(Morison_MOutput), INTENT ( IN ) :: MOutLst(:) - INTEGER, INTENT ( IN ) :: distribToNodeIndx(:) INTEGER, INTENT ( IN ) :: NJOutputs TYPE(Morison_JOutput), INTENT ( IN ) :: JOutLst(:) - TYPE(MeshType), INTENT ( INOUT ) :: inLumpedMesh - TYPE(MeshType), INTENT ( INOUT ) :: outLumpedMesh - TYPE(MeshType), INTENT ( INOUT ) :: inDistribMesh - TYPE(MeshType), INTENT ( INOUT ) :: outDistribMesh - REAL(ReKi), INTENT ( IN ) :: L_F_B(:,:) ! Lumped buoyancy force associated with the member - REAL(ReKi), INTENT ( IN ) :: L_F_BF(:,:) ! Lumped buoyancy force associated flooded/filled fluid within the member - REAL(ReKi), INTENT ( IN ) :: D_F_B(:,:) ! Distributed buoyancy force associated with the member - REAL(ReKi), INTENT ( IN ) :: D_F_BF(:,:) ! Distributed buoyancy force associated flooded/filled fluid within the member - REAL(ReKi), INTENT ( IN ) :: D_F_MG(:,:) - REAL(ReKi), INTENT ( IN ) :: g ! gravity - !INTEGER, INTENT ( IN ) :: numDistribMarkers - !TYPE(Morison_NodeType), INTENT ( IN ) :: distribMarkers(:) - !INTEGER, INTENT ( IN ) :: numLumpedMarkers - !TYPE(Morison_NodeType), INTENT ( IN ) :: lumpedMarkers(:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + TYPE(MeshType), INTENT ( INOUT ) :: uMesh + TYPE(MeshType), INTENT ( INOUT ) :: yMesh + TYPE(Morison_ParameterType), INTENT ( IN ) :: p + TYPE(Morison_MiscVarType), INTENT ( IN ) :: m + INTEGER, INTENT ( OUT ) :: errStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT ( OUT ) :: errMsg ! Error message if errStat /= ErrID_None INTEGER :: I, J REAL(ReKi) :: l ! length of an element @@ -1009,16 +622,19 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location REAL(ReKi) :: s ! The linear interpolation factor for the requested location REAL(ReKi) :: outloc(3) ! Position of the requested member output - INTEGER :: mbrIndx, nodeIndx + INTEGER :: mbrIndx, nodeIndx, c, N CHARACTER(10) :: tmpName - REAL(ReKi) :: totalFillMass, mass_fill, fillVol + REAL(ReKi) :: totalFillMass, mass_fill, fillVol, memberVol REAL(ReKi) :: totalMGMass, mass_MG TYPE(Morison_NodeType) :: node1, node2 - REAL(ReKi) :: Cd1, Cd2, Ca1, Ca2, Cp1, Cp2, AxCa1, AxCa2, AxCp1, AxCp2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 ! tmp coefs - + real(ReKi) :: ptLoad(6) + logical :: fillFlag + type(Morison_MemberType) :: mem + REAL(ReKi) :: Cd1, Cd2, Ca1, Ca2, Cp1, Cp2, AxCd1, AxCd2, AxCa1, AxCa2, AxCp1, AxCp2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 ! tmp coefs + ! Initialize data - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ExtBuoyancy = 0.0 totalFillMass = 0.0 totalDisplVol = 0.0 @@ -1029,72 +645,31 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen COB = 0.0 ! Create identity matrix - CALL EYE(ident,ErrStat,ErrMsg) + CALL EYE(ident,errStat,errMsg) IF ( UnSum > 0 ) THEN - - - - !WRITE( UnSum, '(//)' ) - !WRITE( UnSum, '(A8)' ) 'Elements' - !WRITE( UnSum, '(/)' ) - !WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,5(2X,A12),2X,A12,17(2X,A12))' ) ' i ', 'node1','node2',' Length ', ' MGVolume ', ' MGDensity ', 'PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' CdMG1 ', ' Ca1 ', ' CaMG1 ', ' R1 ', ' t1 ',' Cd2 ', ' CdMG2 ', ' Ca2 ', ' CaMG2 ', ' R2 ', ' t2 ' - !WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,5(2X,A12),2X,A12,17(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (m^3) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ',' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ' - ! - - DO I = 1,numElements - - node1 = nodes(elements(I)%Node1Indx) - node2 = nodes(elements(I)%Node2Indx) - IF ( ( (node1%tMG > 0.0_ReKi ) .AND. EqualRealNos(node2%tMG,0.0_ReKi) ) .OR. ( (node2%tMG > 0.0_ReKi ) .AND. EqualRealNos(node1%tMG,0.0_ReKi) ) ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'If one node of an element has MG, then both must. This is an internal code problem within HydroDyn.' - RETURN - END IF - CALL GetDistance( nodes(elements(I)%Node1Indx)%JointPos, nodes(elements(I)%Node2Indx)%JointPos, l ) - - - IF (elements(I)%PropPot) THEN - MGvolume = 0.0 - elementVol = 0.0 - ELSE - elementVol = ElementVolume(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, l) - MGvolume = elementVol - ElementVolume(elements(I)%R1, elements(I)%R2, l) - END IF - totalMGVol = totalMGVol + MGvolume - mass_MG = MGvolume*elements(I)%FillDens - totalMGMass = totalMGMass + mass_MG - CALL ElementCentroid(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, node1%JointPos, l, elements(I)%R_LToG, elemCentroid) - - COB = COB + elementVol*elemCentroid - - totalVol = totalVol + elementVol - - IF ( node2%JointPos(3) <= MSL2SWL .AND. node1%JointPos(3) >= -WtrDpth) totalDisplVol = totalDisplVol + elementVol - - IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN - ! filledFlag = .TRUE. - !IF ( ( node2%JointPos(3) <= elements(I)%FillFSLoc ) .AND. ( node1%JointPos(3) <= elements(I)%FillFSLoc ) ) THEN - fillVol = ElementVolume(elements(I)%R1 - elements(I)%t1, elements(I)%R2 - elements(I)%t2, l) - totalFillVol = totalFillVol + fillVol - mass_fill = elements(I)%FillDens*fillVol - totalFillMass = totalFillMass + mass_fill - !END IF - ELSE - ! mass_fill = 0.0 - ! filledFlag = .FALSE. - END IF + do j = 1, numMembers + + mem = members(j) + totalVol = totalVol + mem%Vouter + totalMGVol = totalMGVol + mem%Vouter - mem%Vinner + totalDisplVol = totalDisplVol + mem%Vsubmerged + totalFillVol = totalFillVol + mem%Vballast - !WRITE( UnSum, '(1X,I5,2X,I5,2X,I5,3(2X,ES12.5),2(2X,L12),2X,ES12.5,17(2X,ES12.5))' ) I, elements(I)%Node1Indx, elements(I)%Node2Indx, l, MGvolume, node1%MGdensity, elements(I)%PropPot, filledFlag, elements(I)%FillDens, elements(I)%FillFSLoc, mass_fill, elements(I)%Cd1, elements(I)%CdMG1, elements(I)%Ca1, elements(I)%CaMG1, elements(I)%R1, elements(I)%t1, elements(I)%Cd2, elements(I)%CdMG2, elements(I)%Ca2, elements(I)%CaMG2, elements(I)%R2, elements(I)%t2 + ! IF ( node2%Position(3) <= MSL2SWL .AND. node1%Position(3) >= -WtrDpth) totalDisplVol = totalDisplVol + elementVol - END DO ! I = 1,numElements - + + do i = 1, mem%NElements + totalMGMass = totalMGMass + mem%m_mg_l(i) + totalMGMass = totalMGMass + mem%m_mg_u(i) + end do + + end do - WRITE( UnSum, '(//)' ) - WRITE( UnSum, '(A24)' ) 'Volume Calculations(m^3)' - WRITE( UnSum, '(A24)' ) '------------------------' + WRITE( UnSum, '(A37)' ) 'Strip-Theory Volume Calculations(m^3)' + WRITE( UnSum, '(A37)' ) '-------------------------------------' WRITE( UnSum, '(A27,ES12.5)' ) ' Structure Volume : ', totalVol WRITE( UnSum, '(A27,ES12.5)' ) ' Submerged Volume : ', totalDisplVol WRITE( UnSum, '(A27,ES12.5)' ) ' Marine Growth Volume : ', totalMGVol @@ -1102,25 +677,14 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen WRITE( UnSum, '(A111)') ' NOTE: Structure, Submerged and Marine Growth volumes are based on members not modelled with WAMIT' WRITE( UnSum, '(A149)') ' Ballasted volume is computed from all members which are marked as filled in the HydroDyn input file, regardless of PropPot flag' - - - ! Sum all buoyancy loads to the COB - ! Do this by creating a temporary mesh which is for (0,0,0) - - !COB = COB / totalVol - - ! Write out the Center of Buoyancy (geometric center of the displaced volume) - !WRITE( UnSum, '(//)' ) - !WRITE( UnSum, '(A18)' ) 'Center of Buoyancy' - !WRITE( UnSum, '(3(2X,A10 ))' ) ' COBXi ', ' COBYi ', ' COBZi ' - !WRITE( UnSum, '(3(2X,A10 ))' ) ' (m) ', ' (m) ', ' (m) ' - !WRITE( UnSum, '(3(2X,F10.3))' ) COB(1) , COB(2) , COB(3) + + ! Create a point mesh at (0,0,0) so that we can integrate the Morison load contributions to a single point for reporting purposes CALL MeshCreate( BlankMesh = WRP_Mesh & ,IOS = COMPONENT_INPUT & ,Nnodes = 1 & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & + ,errStat = errStat & + ,ErrMess = errMsg & ,Force = .TRUE. & ,Moment = .TRUE. & ) @@ -1129,25 +693,25 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen CALL MeshPositionNode (WRP_Mesh & , 1 & , (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi/) & - , ErrStat & - , ErrMsg & + , errStat & + , errMsg & ) - IF ( ErrStat /= 0 ) RETURN + IF ( errStat /= 0 ) RETURN ! Create the mesh element CALL MeshConstructElement ( WRP_Mesh & , ELEMENT_POINT & - , ErrStat & - , ErrMsg & + , errStat & + , errMsg & , 1 & ) CALL MeshCommit ( WRP_Mesh & - , ErrStat & - , ErrMsg ) + , errStat & + , errMsg ) - IF ( ErrStat /= ErrID_None ) RETURN + IF ( errStat /= ErrID_None ) RETURN ! we need the translation displacement mesh for loads transfer: CALL MeshCopy ( SrcMesh = WRP_Mesh & @@ -1155,10 +719,10 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen , CtrlCode = MESH_SIBLING & , IOS = COMPONENT_INPUT & , TranslationDisp = .TRUE. & - , ErrStat = ErrStat & - , ErrMess = ErrMsg ) ! automatically sets DestMesh%RemapFlag = .TRUE. + , errStat = errStat & + , ErrMess = errMsg ) ! automatically sets DestMesh%RemapFlag = .TRUE. - IF ( ErrStat /= ErrID_None ) RETURN + IF ( errStat /= ErrID_None ) RETURN WRP_Mesh_position%TranslationDisp = 0.0 ! bjj: this is actually initialized in the ModMesh module, but I'll do it here anyway. WRP_Mesh%RemapFlag = .TRUE. @@ -1170,319 +734,199 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen ! in the hydrodynamics for conditions where the wave height is > SWL. So we now need to check that the vertical position ! is <= SWL for this summary file calculation. - DO J = 1, outDistribMesh%Nnodes - if ( outDistribMesh%Position(3,J) <= MSL2SWL ) then - DO I=1,6 - - IF (I < 4 ) THEN - - outDistribMesh%Force(I ,J) = D_F_B(I,J) - - ELSE - - outDistribMesh%Moment(I-3,J) = D_F_B(I,J) - - END IF + + DO J = 1, yMesh%Nnodes + if ( yMesh%Position(3,J) <= 0.0 ) then - END DO ! DO I - end if ! <= MSL2SWL check + if (J <= numJoints) then + ptLoad = m%F_B(:,J) + m%F_B_end(:,J) + else + ptLoad = m%F_B(:,J) + end if + yMesh%Force(:,J) = ptLoad(1:3) + yMesh%Moment(:,J) = ptLoad(4:6) + else + yMesh%Force(:,J) = 0.0 + yMesh%Moment(:,J) = 0.0 + end if ! <= still water line check END DO ! DO J - + ! Transfer the loads from the distributed mesh to the (0,0,0) point mesh - CALL MeshMapCreate ( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg ) - !CALL CheckError( ErrStat, 'Message from MeshMapCreate HD_M_L_2_ED_P: '//NewLine//ErrMsg ) - CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + CALL MeshMapCreate ( yMesh, WRP_Mesh, M_P_2_P, errStat, errMsg ) + !CALL CheckError( errStat, 'Message from MeshMapCreate HD_M_L_2_ED_P: '//NewLine//errMsg ) + CALL Transfer_Point_to_Point( yMesh, WRP_Mesh, M_P_2_P, errStat, errMsg, uMesh, WRP_Mesh_position ) ExtBuoyancy(1:3) = WRP_Mesh%Force (:,1) ExtBuoyancy(4:6) = WRP_Mesh%Moment(:,1) - - - ! Transfer the loads from the lumped mesh to the (0,0,0) point mesh - - ! Because of wave stretching and user-supplied waves, we may have loads above the still water line (SWL) which will be used - ! in the hydrodynamics for conditions where the wave height is > SWL. So we now need to check that the vertical position - ! is <= SWL for this summary file calculation. - - DO J = 1, outLumpedMesh%Nnodes - if ( outLumpedMesh%Position(3,J) <= MSL2SWL ) then - DO I=1,6 - - IF (I < 4 ) THEN - - outLumpedMesh%Force(I ,J) = L_F_B(I,J) - - ELSE - - outLumpedMesh%Moment(I-3,J) = L_F_B(I,J) - - END IF - - END DO ! DO I - end if ! <= MSL2SWL check - END DO ! DO J - - ! Remap for the lumped to WRP mesh transfer - WRP_Mesh%RemapFlag = .TRUE. - - CALL MeshMapCreate ( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg ) - CALL Transfer_Point_to_Point( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg, inLumpedMesh, WRP_Mesh_position ) - - ExtBuoyancy(1:3) = ExtBuoyancy(1:3) + WRP_Mesh%Force (:,1) - ExtBuoyancy(4:6) = ExtBuoyancy(4:6) + WRP_Mesh%Moment(:,1) - - - - ! Write the buoyancy table headers and the external results - - WRITE( UnSum, '(//)' ) - WRITE( UnSum, '(A45)' ) 'Buoyancy loads summed about ( 0.0, 0.0, 0.0 )' - WRITE( UnSum, '(A45)' ) '---------------------------------------------' - WRITE( UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' - WRITE( UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' - WRITE( UnSum, '(A18,6(2X,ES20.6))') 'External: ', ExtBuoyancy(1), ExtBuoyancy(2), ExtBuoyancy(3), ExtBuoyancy(4), ExtBuoyancy(5), ExtBuoyancy(6) + + ! Write the buoyancy table headers and the external results + + WRITE( UnSum, '(//)' ) + WRITE( UnSum, '(A51)' ) 'Total Buoyancy loads summed about ( 0.0, 0.0, 0.0 )' + WRITE( UnSum, '(A51)' ) '---------------------------------------------------' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' BuoyFxi ', ' BuoyFyi ', ' BuoyFzi ', ' BuoyMxi ', ' BuoyMyi ', ' BuoyMzi ' + WRITE( UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' + WRITE( UnSum, '(A18,6(2X,ES20.6))') 'External: ', ExtBuoyancy(1), ExtBuoyancy(2), ExtBuoyancy(3), ExtBuoyancy(4), ExtBuoyancy(5), ExtBuoyancy(6) ! Now compute internal Buoyancy - DO J = 1, outDistribMesh%Nnodes + DO J = 1, yMesh%Nnodes - DO I=1,6 - - IF (I < 4 ) THEN - - outDistribMesh%Force(I,J ) = D_F_BF(I,J) - - ELSE - - outDistribMesh%Moment(I-3,J) = D_F_BF(I,J) - - END IF - - END DO ! DO I + if (J <= numJoints) then + ptLoad = m%F_BF(:,J) + m%F_BF_end(:,J) + else + ptLoad = m%F_BF(:,J) + end if + yMesh%Force(:,J) = ptLoad(1:3) + yMesh%Moment(:,J) = ptLoad(4:6) END DO ! DO J IntBuoyancy = 0.0 - CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + CALL Transfer_Point_to_Point( yMesh, WRP_Mesh, M_P_2_P, errStat, errMsg, uMesh, WRP_Mesh_position ) IntBuoyancy(1:3) = WRP_Mesh%Force(:,1) IntBuoyancy(4:6) = WRP_Mesh%Moment(:,1) - - DO J = 1, outLumpedMesh%Nnodes - - DO I=1,6 - - IF (I < 4 ) THEN - - outLumpedMesh%Force(I,J) = L_F_BF(I,J) - - ELSE - - outLumpedMesh%Moment(I-3,J) = L_F_BF(I,J) - - END IF - - END DO ! DO I - - END DO ! DO J - - CALL Transfer_Point_to_Point( outLumpedMesh, WRP_Mesh, M_P_2_P, ErrStat, ErrMsg, inLumpedMesh, WRP_Mesh_position ) - IntBuoyancy(1:3) = IntBuoyancy(1:3) + WRP_Mesh%Force(:,1) - IntBuoyancy(4:6) = IntBuoyancy(4:6) + WRP_Mesh%Moment(:,1) - - - ! clean up - - CALL MeshMapDestroy( M_P_2_P, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Internal: ', IntBuoyancy(1), IntBuoyancy(2), IntBuoyancy(3), IntBuoyancy(4), IntBuoyancy(5), IntBuoyancy(6) IntBuoyancy = IntBuoyancy + ExtBuoyancy WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Total : ', IntBuoyancy(1), IntBuoyancy(2), IntBuoyancy(3), IntBuoyancy(4), IntBuoyancy(5), IntBuoyancy(6) - !WRITE( UnSum, '(/)' ) WRITE( UnSum, '(A81)') ' NOTE: External buoyancy is based on members not modelled with WAMIT' WRITE( UnSum, '(A150)') ' Internal buoyancy is computed from all members which are marked as filled in the HydroDyn input file, regardless of PropPot flag' WRITE( UnSum, '(A88)') ' Total buoyancy does not include WAMIT-modelled buoyancy contribution' - ! Now compute marine growth weight at the WRP + ! ! Now compute marine growth weight at the WRP - DO J = 1, outDistribMesh%Nnodes + DO J = 1, yMesh%Nnodes + if (J <= numJoints) then + yMesh%Force(:,J) = m%F_WMG(1:3,J) + p%F_WMG_End(:,J) + else + yMesh%Force(:,J) = m%F_WMG(1:3,J) + end if - DO I=1,6 - - IF (I < 4 ) THEN - - outDistribMesh%Force(I,J) = D_F_MG(I,J) - - ELSE - - outDistribMesh%Moment(I-3,J) = D_F_MG(I,J) - - END IF - - END DO ! DO I + yMesh%Moment(:,J) = m%F_WMG(4:6,J) - END DO ! DO J - + END DO ! DO J MG_Wt = 0.0 - CALL Transfer_Line2_to_Point( outDistribMesh, WRP_Mesh, M_L_2_P, ErrStat, ErrMsg, inDistribMesh, WRP_Mesh_position ) + CALL Transfer_Point_to_Point( yMesh, WRP_Mesh, M_P_2_P, errStat, errMsg, uMesh, WRP_Mesh_position ) MG_Wt(1:3) = WRP_Mesh%Force(:,1) MG_Wt(4:6) = WRP_Mesh%Moment(:,1) - + ! + CALL MeshMapDestroy( M_P_2_P, errStat, errMsg ); IF ( errStat /= ErrID_None ) CALL WrScr(TRIM(errMsg)) + WRITE( UnSum, '(//)' ) WRITE( UnSum, '(A36)' ) 'Weight loads about ( 0.0, 0.0, 0.0 )' WRITE( UnSum, '(A36)' ) '------------------------------------' WRITE( UnSum, '(18x,6(2X,A20))' ) ' MGFxi ', ' MGFyi ', ' MGFzi ', ' MGMxi ', ' MGMyi ', ' MGMzi ' WRITE( UnSum, '(18x,6(2X,A20))' ) ' (N) ', ' (N) ', ' (N) ', ' (N-m) ', ' (N-m) ', ' (N-m) ' - !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Structure : ', M_Wt(1), M_Wt(2), M_Wt(3), M_Wt(4), M_Wt(5), M_Wt(6) WRITE( UnSum, '(A18,6(2X,ES20.6))') 'Marine Growth: ', MG_Wt(1), MG_Wt(2), MG_Wt(3), MG_Wt(4), MG_Wt(5), MG_Wt(6) - !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Filled Fluid : ', F_Wt(1), F_Wt(2), F_Wt(3), F_Wt(4), F_Wt(5), F_Wt(6) - !M_Wt = M_Wt + MG_Wt + F_Wt - !WRITE( UnSum, '(A16,6(2X,E20.6))') 'Total : ', M_Wt(1), M_Wt(2), M_Wt(3), M_Wt(4), M_Wt(5), M_Wt(6) - - - CALL MeshMapDestroy( M_L_2_P, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) - CALL MeshDestroy(WRP_Mesh, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) - CALL MeshDestroy(WRP_Mesh_position, ErrStat, ErrMsg ); IF ( ErrStat /= ErrID_None ) CALL WrScr(TRIM(ErrMsg)) + - ! Write the header for this section + CALL MeshDestroy(WRP_Mesh, errStat, errMsg ); IF ( errStat /= ErrID_None ) CALL WrScr(TRIM(errMsg)) + CALL MeshDestroy(WRP_Mesh_position, errStat, errMsg ); IF ( errStat /= ErrID_None ) CALL WrScr(TRIM(errMsg)) + ! + ! ! Write the header for this section WRITE( UnSum, '(//)' ) - WRITE( UnSum, '(A5)' ) 'Nodes' + WRITE( UnSum, '(A14,I4,A44)' ) 'Nodes (first [',numJoints,'] are joints, remainder are internal nodes)' WRITE( UnSum, '(/)' ) - WRITE( UnSum, '(1X,A5,24(2X,A10),2X,A5,2X,A15)' ) ' i ', 'JointIndx ', 'JointOvrlp', 'InpMbrIndx', ' Nxi ', ' Nyi ', ' Nzi ', 'InpMbrDist', ' R ', ' dRdZ ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', ' FillDens ', 'FillFSLoc ', ' Cd ', ' Ca ', ' Cp ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ', 'NConn ', 'Connection List' - WRITE( UnSum, '(1X,A5,24(2X,A10),2X,A5,2X,A15)' ) ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (m) ', ' (-) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' ' - - ! Write the data - DO I = 1,numNodes - WRITE(strFmt,'(I2)') nodes(I)%NConnections - IF ( nodes(I)%NodeType == 1 ) THEN - strNodeType = 'End ' - ELSE IF ( nodes(I)%NodeType == 2 ) THEN - strNodeType = 'Interior ' - ELSE IF ( nodes(I)%NodeType == 3 ) THEN - strNodeType = 'Super ' - ELSE - strNodeType = 'ERROR ' - END IF - - WRITE( UnSum, '(1X,I5,3(2X,I10),4(2X,F10.4),5(2X,ES10.3),2(2X,L10),10(2X,ES10.3),2X,I5,' // strFmt // '(2X,I4))' ) I, nodes(I)%JointIndx, nodes(I)%JointOvrlp, nodes(I)%InpMbrIndx, nodes(I)%JointPos, nodes(I)%InpMbrDist, nodes(I)%R, nodes(I)%DRDZ, nodes(I)%t, nodes(I)%tMG, nodes(I)%MGdensity, nodes(I)%PropPot, nodes(I)%FillFlag, nodes(I)%FillDensity, nodes(I)%FillFSLoc, nodes(I)%Cd, nodes(I)%Ca, nodes(I)%Cp, nodes(I)%AxCa, nodes(I)%AxCp, nodes(I)%JAxCd, nodes(I)%JAxCa, nodes(I)%JAxCp, nodes(I)%NConnections, nodes(I)%ConnectionList(1:nodes(I)%NConnections) - END DO + WRITE( UnSum, '(1X,A5,19(2X,A10))' ) ' i ', ' MbrIndx ', ' Nxi ', ' Nyi ', ' Nzi ', ' R ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', ' Cd ', ' Ca ', ' Cp ', ' AxCd ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ' + WRITE( UnSum, '(1X,A5,19(2X,A10))' ) ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' - WRITE( UnSum, '(//)' ) - WRITE( UnSum, '(A8)' ) 'Elements' - WRITE( UnSum, '(/)' ) - WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,13(2X,A12),2X,A12,21(2X,A12))' ) ' i ', 'node1','node2',' Length ', ' Volume ', ' MGVolume ', ' R1 ', ' tMG1 ', ' t1 ', ' R2 ', ' tMG2 ', ' t2 ', ' MGDens1 ', ' MGDens2 ', ' PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' Ca1 ', ' Cp1 ', ' AxCa1 ', ' AxCp1 ', ' JAxCd1 ', ' JAxCa1 ', ' JAxCp1 ', ' Cd2 ', ' Ca2 ', ' Cp2 ', ' AxCa2 ', ' AxCp2 ', ' JAxCd2 ', ' JAxCa2 ', ' JAxCp2 ' - WRITE( UnSum, '(1X,A5,2X,A5,2X,A5,13(2X,A12),2X,A12,21(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (m^3) ', ' (m^3) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' + ! Write the node data + do I = 1,numJoints + write( UnSum, '(1X,I5,(2X,A10),3(2X,F10.4),2(2X,A10),2(2X,ES10.3),8(2X,A10),3(2X,ES10.3))' ) i,' - ', nodes(i)%Position, ' - ', ' - ', nodes(i)%tMG, nodes(i)%MGdensity, ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', nodes(i)%JAxCd, nodes(i)%JAxCa, nodes(i)%JAxCp + end do + c = numJoints + do j= 1, numMembers + do i = 2, members(j)%NElements + c = c + 1 + if (members(j)%l_fill - members(j)%dl*(i-1) > 0.0) then + fillFlag = .true. + else + fillFlag = .false. + end if + write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),4(2X,ES10.3),2(6X,L6),6(2X,ES10.3),3(7x,A5))' ) c, members(j)%MemberID, nodes(c)%Position, members(j)%R(i), members(j)%R(i)-members(j)%Rin(i), members(j)%tMG(i), members(j)%MGdensity(i), members(j)%PropPot, fillFlag, members(j)%Cd(i), members(j)%Ca(i), members(j)%Cp(i), members(j)%AxCd(i), members(j)%AxCa(i), members(j)%AxCp(i), ' - ', ' - ', ' - ' + end do + end do - - - DO I = 1,numElements - - node1 = nodes(elements(I)%Node1Indx) - node2 = nodes(elements(I)%Node2Indx) - IF ( ( (node1%tMG > 0.0_ReKi ) .AND. EqualRealNos(node2%tMG,0.0_ReKi) ) .OR. ( (node2%tMG > 0.0_ReKi ) .AND. EqualRealNos(node1%tMG,0.0_ReKi) ) ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'If one node of an element has MG, then both must. This is an internal code problem within HydroDyn.' - RETURN - END IF - CALL GetDistance( nodes(elements(I)%Node1Indx)%JointPos, nodes(elements(I)%Node2Indx)%JointPos, l ) - - - IF (elements(I)%PropPot) THEN + write( UnSum, '(//)' ) + write( UnSum, '(A8)' ) 'Members' + write( UnSum, '(/)' ) + write( UnSum, '(1X,A8,2X,A6,2X,A6,31(2X,A12))' ) 'MemberID', 'joint1','joint2',' Length ', ' NElem ', ' Volume ', ' MGVolume ', ' R1 ', ' t1 ', ' R2 ', ' t2 ', ' PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' Ca1 ', ' Cp1 ', ' AxCd1 ', ' AxCa1 ', ' AxCp1 ', ' JAxCd1 ', ' JAxCa1 ', ' JAxCp1 ', ' Cd2 ', ' Ca2 ', ' Cp2 ', ' AxCd2 ', ' AxCa2 ', ' AxCp2 ', ' JAxCd2 ', ' JAxCa2 ', ' JAxCp2 ' + write( UnSum, '(1X,A8,2X,A6,2X,A6,31(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (-) ', ' (m^3) ', ' (m^3) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' + + + + + do i = 1,numMembers + N = members(i)%NElements + + IF (members(i)%PropPot) THEN MGvolume = 0.0 - elementVol = 0.0 + memberVol = 0.0 ELSE - elementVol = ElementVolume(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, l) - MGvolume = elementVol - ElementVolume(elements(I)%R1, elements(I)%R2, l) + memberVol = members(i)%Vouter + MGvolume = members(i)%Vouter - members(i)%Vinner END IF - ! totalMGVol = totalMGVol + MGvolume - ! mass_MG = MGvolume*elements(I)%FillDens - ! totalMGMass = totalMGMass + mass_MG - CALL ElementCentroid(elements(I)%R1 + node1%tMG, elements(I)%R2 + node2%tMG, node1%JointPos, l, elements(I)%R_LToG, elemCentroid) - - ! COB = COB + elementVol*elemCentroid - - ! totalVol = totalVol + elementVol - - !IF ( node2%JointPos(3) <= MSL2SWL .AND. node1%JointPos(3) >= ) totalDisplVol = totalDisplVol + elementVol - - IF ( elements(I)%MmbrFilledIDIndx > 0 ) THEN - filledFlag = .TRUE. - !IF ( ( node2%JointPos(3) <= elements(I)%FillFSLoc ) .AND. ( node1%JointPos(3) <= elements(I)%FillFSLoc ) ) THEN - fillVol = ElementVolume(elements(I)%R1 - elements(I)%t1, elements(I)%R2 - elements(I)%t2, l) - ! totalFillVol = totalFillVol + fillVol - mass_fill = elements(I)%FillDens*fillVol - ! totalFillMass = totalFillMass + mass_fill - !END IF + + IF ( members(i)%l_fill > 0.0 ) THEN + filledFlag = .TRUE. + mass_fill = members(i)%FillDens*members(i)%Vballast ELSE mass_fill = 0.0 filledFlag = .FALSE. END IF + + Cd1 = members(i)%Cd(1) + Cd2 = members(i)%Cd(N+1) + Ca1 = members(i)%Ca(1) + Ca2 = members(i)%Ca(N+1) + Cp1 = members(i)%Cp(1) + Cp2 = members(i)%Cp(N+1) + AxCd1 = members(i)%AxCd(1) + AxCd2 = members(i)%AxCd(N+1) + AxCa1 = members(i)%AxCa(1) + AxCa2 = members(i)%AxCa(N+1) + AxCp1 = members(i)%AxCp(1) + AxCp2 = members(i)%AxCp(N+1) + + JAxCd1 = nodes(members(i)%NodeIndx(1 ))%JAxCd + JAxCd2 = nodes(members(i)%NodeIndx(1+N))%JAxCa + JAxCa1 = nodes(members(i)%NodeIndx(1 ))%JAxCp + JAxCa2 = nodes(members(i)%NodeIndx(1+N))%JAxCd + JAxCp1 = nodes(members(i)%NodeIndx(1 ))%JAxCa + JAxCp2 = nodes(members(i)%NodeIndx(1+N))%JAxCp + - IF (EqualRealNos(node1%tMG,0.0_ReKi)) THEN - Cd1 = elements(I)%Cd1 - Cd2 = elements(I)%Cd2 - Ca1 = elements(I)%Ca1 - Ca2 = elements(I)%Ca2 - Cp1 = elements(I)%Cp1 - Cp2 = elements(I)%Cp2 - AxCa1 = elements(I)%AxCa1 - AxCa2 = elements(I)%AxCa2 - AxCp1 = elements(I)%AxCp1 - AxCp2 = elements(I)%AxCp2 - ELSE - Cd1 = elements(I)%CdMG1 - Cd2 = elements(I)%CdMG2 - Ca1 = elements(I)%CaMG1 - Ca2 = elements(I)%CaMG2 - Cp1 = elements(I)%CpMG1 - Cp2 = elements(I)%CpMG2 - AxCa1 = elements(I)%AxCaMG1 - AxCa2 = elements(I)%AxCaMG2 - AxCp1 = elements(I)%AxCpMG1 - AxCp2 = elements(I)%AxCpMG2 - END IF - - JAxCd1 = node1%JAxCd - JAxCa1 = node1%JAxCa - JAxCp1 = node1%JAxCp - JAxCd2 = node2%JAxCd - JAxCa2 = node2%JAxCa - JAxCp2 = node2%JAxCp - - WRITE( UnSum, '(1X,I5,2X,I5,2X,I5,11(2X,ES12.5),2(2X,L12),2X,ES12.5,21(2X,ES12.5))' ) I, & - elements(I)%Node1Indx, elements(I)%Node2Indx, l, elementVol, MGvolume, elements(I)%R1, & - node1%tMG, elements(I)%t1, elements(I)%R2, node2%tMG, elements(I)%t2, node1%MGdensity, node2%MGdensity, & - elements(I)%PropPot, filledFlag, elements(I)%FillDens, elements(I)%FillFSLoc, & - mass_fill, Cd1, Ca1, Cp1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & - Cd2, Ca2, Cp2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 - - END DO ! I = 1,numElements + write( UnSum, '(1X,I8,2X,I6,2X,I6,2X,ES12.5,2X,I12, 6(2X,ES12.5),2(2X,L12),21(2X,ES12.5))' ) members(i)%MemberID, & + members(i)%NodeIndx(1), members(i)%NodeIndx(N+1), members(i)%RefLength, N, & + memberVol, MGvolume, members(i)%Rmg(1), members(i)%Rmg(1)-members(i)%Rin(1), & + members(i)%Rmg(N+1), members(i)%Rmg(N+1)-members(i)%Rin(N+1), & + members(i)%PropPot, filledFlag, members(i)%FillDens, members(i)%FillFSLoc, & + mass_fill, Cd1, Ca1, Cp1, AxCd1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & + Cd2, Ca2, Cp2, AxCd2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 + + end do ! i = 1,numMembers WRITE( UnSum, '(//)' ) WRITE( UnSum, '(A24)' ) 'Requested Member Outputs' WRITE( UnSum, '(/)' ) - WRITE( UnSum, '(1X,A10,11(2X,A10))' ) ' Label ', ' Xi ', ' Yi ', ' Zi ', 'InpMbrIndx', ' StartXi ', ' StartYi ', ' StartZi ', ' EndXi ', ' EndYi ', ' EndZi ', ' Loc ' + WRITE( UnSum, '(1X,A10,11(2X,A10))' ) ' Label ', ' Xi ', ' Yi ', ' Zi ', ' MemberID ', ' StartXi ', ' StartYi ', ' StartZi ', ' EndXi ', ' EndYi ', ' EndZi ', ' Loc ' WRITE( UnSum, '(1X,A10,11(2X,A10))' ) ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ' DO I = 1,NOutputs - ! DO J=1, NMOutputs - !DO I=1, MOutLst(J)%NOutLoc - - - ! Get the member index and node index for this output label. If this is not a member output the indices will return 0 with no errcode. - ! CALL MrsnOut_GetMemberOutputInfo(WriteOutputHdr(I), NMOutputs, MOutLst, mbrIndx, nodeIndx, ErrStat, ErrMsg ) - ! IF (ErrStat >= AbortErrLev ) RETURN - ! IF ( mbrIndx > 0 ) THEN + tmpName = OutParam(I)%Name IF (OutParam(I)%SignM == -1 ) tmpName = tmpName(2:10) @@ -1494,21 +938,19 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you want ! to index into the nodes array or wave kinematics arrays - m1 = MOutLst(mbrIndx)%Marker1(nodeIndx) - m2 = MOutLst(mbrIndx)%Marker2(nodeIndx) - s = MOutLst(mbrIndx)%s (nodeIndx) - + + s = MOutLst(mbrIndx)%NodeLocs(nodeIndx) + ! Find the member starting and ending node locations ! The member output is computed as a linear interpolation of the nearest two markers - node1 = nodes(distribToNodeIndx((m1))) - node2 = nodes(distribToNodeIndx((m2))) + mem = members(MOutLst(mbrIndx)%MemberIDIndx) + node1 = nodes(mem%NodeIndx(1)) + node2 = nodes(mem%NodeIndx(mem%NElements+1)) + + outLoc = node1%Position*(1-s) + node2%Position*s - outLoc = node1%JointPos*(1-s) + node2%JointPos*s - WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10,7(2x,F10.4))' ) OutParam(I)%Name, outLoc, node1%InpMbrIndx, node1%JointPos, node2%JointPos, s + WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10,7(2x,F10.4))' ) OutParam(I)%Name, outLoc, MOutLst(mbrIndx)%MemberID, node1%Position, node2%Position, s END IF - - ! END IF - !WRITE( UnSum, '(1X,A10,11(2X,ES10.3))' ) WriteOutputHdr(I) - ! END DO + END DO @@ -1520,14 +962,6 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen DO I = 1,NOutputs - ! DO J=1, NMOutputs - !DO I=1, MOutLst(J)%NOutLoc - - - ! Get the member index and node index for this output label. If this is not a member output the indices will return 0 with no errcode. - ! CALL MrsnOut_GetMemberOutputInfo(WriteOutputHdr(I), NMOutputs, MOutLst, mbrIndx, nodeIndx, ErrStat, ErrMsg ) - ! IF (ErrStat >= AbortErrLev ) RETURN - ! IF ( mbrIndx > 0 ) THEN tmpName = OutParam(I)%Name IF (OutParam(I)%SignM == -1 ) tmpName = tmpName(2:10) @@ -1535,263 +969,128 @@ SUBROUTINE WriteSummaryFile( UnSum, MSL2SWL, WtrDpth, numNodes, nodes, numElemen !Get Member index and Node index read (tmpName(2:2),*) nodeIndx - m1 = JOutLst(nodeIndx)%Markers(1) - WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10)' ) OutParam(I)%Name, nodes(m1)%JointPos, JOutLst(nodeIndx)%JointID + m1 = JOutLst(nodeIndx)%JointIDIndx + WRITE( UnSum, '(1X,A10,3(2x,F10.4),2x,I10)' ) OutParam(I)%Name, nodes(m1)%Position, JOutLst(nodeIndx)%JointID END IF - ! END IF - !WRITE( UnSum, '(1X,A10,11(2X,ES10.3))' ) WriteOutputHdr(I) - ! END DO + END DO + END IF END SUBROUTINE WriteSummaryFile -!==================================================================================================== -SUBROUTINE SplitElementOnZBoundary( axis, boundary, numNodes, node1, node2, newNode, ErrStat, ErrMsg ) - !@mhall: This splits an element at a given global x, y, or z location? - - INTEGER, INTENT ( IN ) :: axis ! which axis to work with in calculating positions along element (global x,y, or z)? - REAL(ReKi), INTENT ( IN ) :: boundary ! [axis] coordinate of boundary? - INTEGER, INTENT ( INOUT ) :: numNodes - TYPE(Morison_NodeType), INTENT ( INOUT ) :: node1, node2 - TYPE(Morison_NodeType), INTENT ( OUT ) :: newNode - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: I, J - REAL(ReKi) :: s ! interpolation factor - - ErrStat = ErrID_None - ErrMsg = "" - - - ! find normalized distance from 1nd node to the boundary - CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) - newNode = node1 ! copy all base node properties - - newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] - - !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates - DO I=axis,axis+1 - J = MOD(I,3) + 1 - newNode%JointPos(J) = node1%JointPos(J)*(1-s) + node2%JointPos(J)*s - END DO - - newNode%R_LToG = node1%R_LToG - -END SUBROUTINE SplitElementOnZBoundary - - - - -SUBROUTINE DiscretizeMember( numNodes, nodes, member, propSet1, propSet2, numMGDepths, MGDepths, ErrStat, ErrMsg ) + + +subroutine Morison_GenerateSimulationNodes( MSL2SWL, numJoints, inpJoints, numMembers, inpMembers, numNodes, nodes, errStat, errMsg ) ! This subdivides a Morison member according to its maximum desired ! element length (MDivSize), allocating the member's arrays, and ! adding resuling new nodes to the master node array. + real(ReKi), intent (in ) :: MSL2SWL ! mean sea level To still water level offset value + integer, intent (in ) :: numJoints ! number of joints in the input file + type(Morison_JointType), intent (in ) :: inpJoints(:) ! array of input joint data structures + integer, intent (in ) :: numMembers ! number of members specified in the inputs + type(Morison_MemberInputType), intent (inout) :: inpMembers(:) ! array of input member data structures + integer, intent (inout) :: numNodes ! the total number of nodes being used for the simulation model + type(Morison_NodeType), allocatable, intent (inout) :: nodes(:) ! the array of simulation nodes + integer, intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + + integer :: numDiv, maxNodes + integer :: i, j + real(ReKi) :: s ! interpolation factor + real(ReKi) :: memLength ! member length + integer :: j1, j2 ! generic integer for counting + INTEGER(IntKi) :: errStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + + ! Initialize errStat + + errStat = ErrID_None + errMsg = "" - INTEGER, INTENT ( INOUT ) :: numNodes ! the current number of nodes being used in the model - TYPE(Morison_NodeType), INTENT ( INOUT ) :: nodes(:) ! the array of nodes (maximum size for now) - TYPE(Morison_MemberType), INTENT ( INOUT ) :: member ! the morison member to discretize - TYPE(Morison_MemberPropType) INTENT( IN ) :: propSet1 ! property set of node 1 - TYPE(Morison_MemberPropType) INTENT( IN ) :: propSet2 ! property set of node N+1 - INTEGER, INTENT( IN ) :: numMGDepths - TYPE(Morison_MGDepthsType), INTENT( IN ) :: MGDepths(:) - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - TYPE(Morison_NodeType) :: node1, node2, newNode - !TYPE(Morison_MemberType) :: element, newElement - INTEGER :: numDiv - REAL(ReKi) :: divSize(3) - INTEGER :: I, J, K - INTEGER :: origNumElements - INTEGER :: node1Indx, node2Indx, axis - REAL(ReKi) :: start, Loc - REAL(ReKi) :: s ! interpolation factor - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" + ! Initialize quantities + maxNodes = numJoints - - ! some copying for convenience - node1Indx = member%Node1Indx - CALL Morison_CopyNodeType( nodes(node1Indx), node1, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node1 = nodes(node1Indx); bjj: note that not all fields have been initialized, but maybe that's okay. + ! Determine maximum nodes in simulation mesh due to internal member subdivision + do i = 1,numMembers - node2Indx = member%Node2Indx ! We need this index for the last sub-element - CALL Morison_CopyNodeType( nodes(node2Indx), node2, MESH_NEWCOPY, ErrStat, ErrMsg ) ! node2 = nodes(node2Indx); bjj: note that not all fields have been initialized, but maybe that's okay. - - - ! calculate and save member length - CALL GetDistance(node1%JointPos, node2%JointPos, member%Len) ! Calculate member length. - - + j1 = inpMembers(I)%MJointID1Indx + j2 = inpMembers(I)%MJointID2Indx + call GetDistance(inpJoints(j1)%Position, inpJoints(j2)%Position, memLength) + if ( EqualRealNos(memLength, 0.0_ReKi) )then + errMsg = ' Input file member with ID: '//trim(num2lstr(inpMembers(i)%MemberID))//' must have length greater than zero.' + errStat = ErrID_Fatal + return + end if + numDiv = CEILING( memLength / inpMembers(i)%MDivSize ) + ! set number of elements in member and element size + inpMembers(i)%NElements = numDiv + inpMembers(i)%dl = memLength/numDiv + inpMembers(i)%refLength = memLength + maxNodes = maxNodes + numDiv - 1 + + end do + + ! Allocate nodes array + allocate ( nodes(maxNodes), STAT = errStat ) + if ( errStat /= 0 ) then + errMsg = ' Error allocating space for Nodes array for Morison Module.' + errStat = ErrID_Fatal + return + end if + + ! Loop over the input file joints and add there positions as the node positions at the beginning of the nodes array + do i = 1, numJoints + nodes(i)%Position(1:2) = inpJoints(i)%Position(1:2) + nodes(i)%Position(3) = inpJoints(i)%Position(3) - MSL2SWL ! Correct the Z-coordinate based on the mean sea level To still water level offset value + end do + + numNodes = numJoints + ! Now loop over the input file members and create necessary internal nodes and add them to the nodes array + ! Also augment the input file members data with the new discretization information + do i = 1,numMembers + call AllocAry(inpMembers(i)%NodeIndx, inpMembers(i)%NElements+1, 'inpMembers(i)%NodeIndx', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'Morison_GenerateSimulationNodes') + if (errStat >= AbortErrLev) return + + j1 = inpMembers(i)%MJointID1Indx + j2 = inpMembers(i)%MJointID2Indx + numDiv = inpMembers(i)%NElements + inpMembers(i)%NodeIndx(1) = j1 + inpMembers(i)%NodeIndx(1+numDiv) = j2 ! If the requested division size is less then the member length, create nodes along the member - IF ( member%MDivSize < member%Len ) THEN - - ! Ensure a safe choice of x/y/z axis to use for splitting. - IF ( .NOT. ( EqualRealNos( node2%JointPos(3) , node1%JointPos(3) ) ) ) THEN - axis = 3 - ELSE IF ( .NOT. ( EqualRealNos( node2%JointPos(2) , node1%JointPos(2) ) ) ) THEN - axis = 2 - ELSE IF ( .NOT. ( EqualRealNos( node2%JointPos(1) , node1%JointPos(1) ) ) ) THEN - axis = 1 - ELSE - ! ERROR - END IF - - start = node1%JointPos(axis) - numDiv = CEILING( memLen / member%MDivSize ) - - ! set number of elements in member and element size - member%NElements = numDiv - member%dl = member%Len/numDiv - - ! allocate member arrays - CALL AllocateMemberVariables(member, ErrStat2, ErrMsg2) - - ! now that the arrays are allocated, fill in values for the ends of the member - member%R( 1) = propSet1%PropD / 2.0 - member%RMG(1) = propSet1%PropD / 2.0 + node1%tMG - member%Rin(1) = propSet1%PropD / 2.0 - propSet1%PropThck - member%R( N+1) = propSet2%PropD / 2.0 - member%RMG(N+1) = propSet2%PropD / 2.0 + node2%tMG - member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck - - member%NodeIndx( 1) = node1Indx - member%NodeIndx(N+1) = node2Indx - - - ! get the division size along each axis - DO K=1,3 - divSize(K) = (node2%JointPos(K) - node1%JointPos(K)) / numDiv - END DO - - + if (numDiv > 1 ) THEN ! loop through the new node locations along the member and add a node at each - DO J=1,numDiv - 1 - - loc = start + divSize(axis)*J - - ! below was previously CALL SplitElementOnZBoundary( axis, loc, numNodes, node1, node2, newNode, ErrStat, ErrMsg ) - - ! find normalized distance from 1nd node to the boundary - CALL FindInterpFactor( boundary, node1%JointPos(axis), node2%JointPos(axis), s ) - newNode = node1 ! copy all base node properties - - newNode%JointPos(axis) = boundary !@mhall: set [axis] coordinate of new node based on provided input [boundary] - - ! Set properties of new node based on interpolation of original end node coordinates - - !@mthall: set other two coordinates of new node based on interpolation of original end node coordinates - DO I=axis,axis+1 - K = MOD(I,3) + 1 - newNode%JointPos(K) = node1%JointPos(K)*(1-s) + node2%JointPos(K)*s - END DO - - newNode%R_LToG = node1%R_LToG - - newNode%NodeType = 2 ! interior node - newNode%JointIndx = -1 - - ! Set the marine growth thickness and density information for the new node - CALL SetNodeMG( numMGDepths, MGDepths, newNode ) - - ! Copy new node into the nodes array (this now just appends the new node to the list, the variables node1 and node2 don't need to change) - numNodes = numNodes + 1 - nodes(numNodes) = newNode ! this is copying all the fields in the type; type contains no allocatable arrays or pointers - - ! Now fill in properties of the member at the new node location - I = J+1 ! the node index along the member, from 1 to N+1 - member%R( I) = member%R( 1)*(1-s) + member%R( N+1)*s - member%Rin(I) = member%Rin(1)*(1-s) + member%Rin(N+1)*s - member%RMG(I) = member%R(I) + newNode%tMG - - ! record the node index in the member's node index list - member%NodeIndx(I) = node1Indx + J - - END DO - - - ELSE ! if the member will only be one element long, record that and allocate its arrays - - ! set number of elements in member and element size - member%NElements = 1 - member%dl = member%Len - - ! allocate member arrays - CALL AllocateMemberVariables(member, ErrStat2, ErrMsg2) - - ! now that the arrays are allocated, fill in values for the ends of the member - member%R( 1) = propSet1%PropD / 2.0 - member%RMG(1) = propSet1%PropD / 2.0 + node1%tMG - member%Rin(1) = propSet1%PropD / 2.0 - propSet1%PropThck - member%R( N+1) = propSet2%PropD / 2.0 - member%RMG(N+1) = propSet2%PropD / 2.0 + node2%tMG - member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck - - member%NodeIndx( 1) = node1Indx - member%NodeIndx(N+1) = node2Indx - - END IF - -END SUBROUTINE DiscretizeMember - - -SUBROUTINE AllocateMemberVariables(member, ErrStat, ErrMsg) - - TYPE(Morison_MemberType), INTENT ( INOUT ) :: member ! the morison member to discretize - INTEGER, INTENT ( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - INTEGER :: N - - - N = member%NElements - - !@mhall: I'm hoping the arrays for each member can be allocated like this - - ALLOCATE ( member%NodeIndx(N+1), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the member node index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( member%R(N+1), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the member node radius array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - !@mhall: etc. + do j = 1, numDiv-1 + numNodes = numNodes + 1 + s = real(j, ReKi) / real(numDiv, ReKi) + nodes(numNodes)%Position = inpJoints(j1)%Position*(1-s) + inpJoints(j2)%Position*s + inpMembers(i)%NodeIndx(j+1) = numNodes + end do + end if + end do +end subroutine Morison_GenerateSimulationNodes -END SUBROUTINE AllocateMemberVariables !==================================================================================================== -SUBROUTINE SetDepthBasedCoefs( z, NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) +SUBROUTINE SetDepthBasedCoefs( z, tMG, NCoefDpth, CoefDpths, Cd, Ca, Cp, AxCd, AxCa, AxCp ) - REAL(ReKi), INTENT ( IN ) :: z - INTEGER, INTENT (IN ) :: NCoefDpth - TYPE(Morison_CoefDpths), INTENT (IN ) :: CoefDpths(:) + REAL(ReKi), INTENT (IN ) :: z + REAL(ReKi), INTENT (IN ) :: tMG + INTEGER, INTENT (IN ) :: NCoefDpth + TYPE(Morison_CoefDpths), INTENT (IN ):: CoefDpths(:) REAL(ReKi), INTENT ( OUT) :: Cd - REAL(ReKi), INTENT ( OUT) :: CdMG REAL(ReKi), INTENT ( OUT) :: Ca - REAL(ReKi), INTENT ( OUT) :: CaMG REAL(ReKi), INTENT ( OUT) :: Cp - REAL(ReKi), INTENT ( OUT) :: CpMG + REAL(ReKi), INTENT ( OUT) :: AxCd REAL(ReKi), INTENT ( OUT) :: AxCa - REAL(ReKi), INTENT ( OUT) :: AxCaMG REAL(ReKi), INTENT ( OUT) :: AxCp - REAL(ReKi), INTENT ( OUT) :: AxCpMG INTEGER :: I, indx1, indx2 REAL(ReKi) :: dd, s @@ -1828,183 +1127,121 @@ SUBROUTINE SetDepthBasedCoefs( z, NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, ELSE s = ( CoefDpths(indx1)%Dpth - z ) / dd END IF + if ( tMG > 0.0_ReKi ) then + Cd = CoefDpths(indx1)%DpthCdMG*(1-s) + CoefDpths(indx2)%DpthCdMG*s + Ca = CoefDpths(indx1)%DpthCaMG*(1-s) + CoefDpths(indx2)%DpthCaMG*s + Cp = CoefDpths(indx1)%DpthCpMG*(1-s) + CoefDpths(indx2)%DpthCpMG*s + AxCd = CoefDpths(indx1)%DpthAxCdMG*(1-s) + CoefDpths(indx2)%DpthAxCdMG*s + AxCa = CoefDpths(indx1)%DpthAxCaMG*(1-s) + CoefDpths(indx2)%DpthAxCaMG*s + AxCp = CoefDpths(indx1)%DpthAxCpMG*(1-s) + CoefDpths(indx2)%DpthAxCpMG*s + else + Cd = CoefDpths(indx1)%DpthCd*(1-s) + CoefDpths(indx2)%DpthCd*s + Ca = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthCa*s + Cp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthCp*s + AxCd = CoefDpths(indx1)%DpthCd*(1-s) + CoefDpths(indx2)%DpthAxCd*s + AxCa = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthAxCa*s + AxCp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthAxCp*s + end if - Cd = CoefDpths(indx1)%DpthCd*(1-s) + CoefDpths(indx2)%DpthCd*s - Ca = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthCa*s - Cp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthCp*s - AxCa = CoefDpths(indx1)%DpthCa*(1-s) + CoefDpths(indx2)%DpthAxCa*s - AxCp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthAxCp*s - CdMG = CoefDpths(indx1)%DpthCdMG*(1-s) + CoefDpths(indx2)%DpthCdMG*s - CaMG = CoefDpths(indx1)%DpthCaMG*(1-s) + CoefDpths(indx2)%DpthCaMG*s - CpMG = CoefDpths(indx1)%DpthCpMG*(1-s) + CoefDpths(indx2)%DpthCpMG*s - AxCaMG = CoefDpths(indx1)%DpthAxCaMG*(1-s) + CoefDpths(indx2)%DpthAxCaMG*s - AxCpMG = CoefDpths(indx1)%DpthAxCpMG*(1-s) + CoefDpths(indx2)%DpthAxCpMG*s END SUBROUTINE SetDepthBasedCoefs !==================================================================================================== -!SUBROUTINE SetMemberCoefs( SimplCd, SimplCdMG, SimplCa, SimplCaMG, CoefMembers, NCoefDpth, CoefDpths, element, node1, node2 ) -SUBROUTINE SetElementCoefs( SimplCd, SimplCdMG, SimplCa, SimplCaMG, SimplCp, SimplCpMG, SimplAxCa, SimplAxCaMG, SimplAxCp, SimplAxCpMG,CoefMembers, NCoefDpth, CoefDpths, numNodes, nodes, numElements, elements ) +!SUBROUTINE SetExternalHydroCoefs +SUBROUTINE SetExternalHydroCoefs( MCoefMod, MmbrCoefIDIndx, SimplCd, SimplCdMG, SimplCa, SimplCaMG, SimplCp, & + SimplCpMG, SimplAxCd, SimplAxCdMG, SimplAxCa, SimplAxCaMG, SimplAxCp, SimplAxCpMG, CoefMembers, & + NCoefDpth, CoefDpths, numNodes, nodes, member ) ! This private subroutine generates the Cd, Ca, Cp, CdMG, CaMG and CpMG coefs for the member based on ! the input data. !---------------------------------------------------------------------------------------------------- - - REAL(ReKi), INTENT( IN ) :: SimplCd - REAL(ReKi), INTENT( IN ) :: SimplCdMG - REAL(ReKi), INTENT( IN ) :: SimplCa - REAL(ReKi), INTENT( IN ) :: SimplCaMG - REAL(ReKi), INTENT( IN ) :: SimplCp - REAL(ReKi), INTENT( IN ) :: SimplCpMG - REAL(ReKi), INTENT( IN ) :: SimplAxCa - REAL(ReKi), INTENT( IN ) :: SimplAxCaMG - REAL(ReKi), INTENT( IN ) :: SimplAxCp - REAL(ReKi), INTENT( IN ) :: SimplAxCpMG - TYPE(Morison_CoefMembers), INTENT( IN ) :: CoefMembers(:) - INTEGER, INTENT( IN ) :: NCoefDpth - TYPE(Morison_CoefDpths), INTENT( IN ) :: CoefDpths(:) - INTEGER, INTENT( IN ) :: numNodes - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) - TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) - - TYPE(Morison_NodeType) :: node1, node2 - - INTEGER :: MCoefMod - INTEGER :: I, J - REAL(ReKi) :: Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCp, AxCaMG, AxCpMG - DO I=1,numElements - - - MCoefMod = elements(I)%MCoefMod - node1 = nodes(elements(I)%Node1Indx) - node2 = nodes(elements(I)%Node2Indx) - - SELECT CASE ( MCoefMod ) - - CASE (1) - - elements(I)%Cd1 = SimplCd - elements(I)%Cd2 = SimplCd - elements(I)%Ca1 = SimplCa - elements(I)%Ca2 = SimplCa - elements(I)%Cp1 = SimplCp - elements(I)%Cp2 = SimplCp - elements(I)%AxCa1 = SimplAxCa - elements(I)%AxCa2 = SimplAxCa - elements(I)%AxCp1 = SimplAxCp - elements(I)%AxCp2 = SimplAxCp - elements(I)%CdMG1 = SimplCdMG - elements(I)%CdMG2 = SimplCdMG - elements(I)%CaMG1 = SimplCaMG - elements(I)%CaMG2 = SimplCaMG - elements(I)%CpMG1 = SimplCpMG - elements(I)%CpMG2 = SimplCpMG - elements(I)%AxCaMG1 = SimplAxCaMG - elements(I)%AxCaMG2 = SimplAxCaMG - elements(I)%AxCpMG1 = SimplAxCpMG - elements(I)%AxCpMG2 = SimplAxCpMG - - CASE (2) - - CALL SetDepthBasedCoefs( node1%JointPos(3), NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) - elements(I)%Cd1 = Cd - elements(I)%Ca1 = Ca - elements(I)%Cp1 = Cp - elements(I)%AxCa1 = AxCa - elements(I)%AxCp1 = AxCp - elements(I)%CdMG1 = CdMG - elements(I)%CaMG1 = CaMG - elements(I)%CpMG1 = CpMG - elements(I)%AxCaMG1 = AxCaMG - elements(I)%AxCpMG1 = AxCpMG - - CALL SetDepthBasedCoefs( node2%JointPos(3), NCoefDpth, CoefDpths, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCaMG, AxCp, AxCpMG ) - elements(I)%Cd2 = Cd - elements(I)%Ca2 = Ca - elements(I)%Cp2 = Cp - elements(I)%AxCa2 = Ca - elements(I)%AxCp2 = Cp - elements(I)%CdMG2 = CdMG - elements(I)%CaMG2 = CaMG - elements(I)%CpMG2 = CpMG - elements(I)%AxCaMG2 = AxCaMG - elements(I)%AxCpMG2 = AxCpMG - - CASE (3) - - J = elements(I)%MmbrCoefIDIndx - elements(I)%Cd1 = CoefMembers(J)%MemberCd1 - elements(I)%Cd2 = CoefMembers(J)%MemberCd2 - elements(I)%Ca1 = CoefMembers(J)%MemberCa1 - elements(I)%Ca2 = CoefMembers(J)%MemberCa2 - elements(I)%Cp1 = CoefMembers(J)%MemberCp1 - elements(I)%Cp2 = CoefMembers(J)%MemberCp2 - elements(I)%AxCa1 = CoefMembers(J)%MemberAxCa1 - elements(I)%AxCa2 = CoefMembers(J)%MemberAxCa2 - elements(I)%AxCp1 = CoefMembers(J)%MemberAxCp1 - elements(I)%AxCp2 = CoefMembers(J)%MemberAxCp2 - elements(I)%CdMG1 = CoefMembers(J)%MemberCdMG1 - elements(I)%CdMG2 = CoefMembers(J)%MemberCdMG2 - elements(I)%CaMG1 = CoefMembers(J)%MemberCaMG1 - elements(I)%CaMG2 = CoefMembers(J)%MemberCaMG2 - elements(I)%CpMG1 = CoefMembers(J)%MemberCpMG1 - elements(I)%CpMG2 = CoefMembers(J)%MemberCpMG2 - elements(I)%AxCaMG1 = CoefMembers(J)%MemberAxCaMG1 - elements(I)%AxCaMG2 = CoefMembers(J)%MemberAxCaMG2 - elements(I)%AxCpMG1 = CoefMembers(J)%MemberAxCpMG1 - elements(I)%AxCpMG2 = CoefMembers(J)%MemberAxCpMG2 - - END SELECT - - - END DO - -END SUBROUTINE SetElementCoefs - - -SUBROUTINE SetAxialCoefs( NJoints, NAxCoefs, AxialCoefs, numNodes, nodes, numElements, elements ) - - INTEGER, INTENT( IN ) :: NJoints - INTEGER, INTENT( IN ) :: NAxCoefs - TYPE(Morison_AxialCoefType),INTENT( IN ) :: AxialCoefs(:) - INTEGER, INTENT( IN ) :: numNodes - INTEGER, INTENT( IN ) :: numElements - TYPE(Morison_MemberType), INTENT( INOUT ) :: elements(:) - TYPE(Morison_NodeType), INTENT( INOUT ) :: nodes(:) - - ! TYPE(Morison_NodeType) :: node1, node2 - - INTEGER :: I !, J - - DO I=1,numNodes - - IF ( nodes(I)%JointAxIDIndx > 0 .AND. nodes(I)%JointIndx > 0 .AND. nodes(I)%JointIndx <= NJoints) THEN - nodes(I)%JAxCd = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCd - nodes(I)%JAxCa = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCa - nodes(I)%JAxCp = AxialCoefs(nodes(I)%JointAxIDIndx)%AxCp - ELSE ! These are end nodes that were generated by the software, and hence do not have lumped axial loads, or they are interior nodes. - nodes(I)%JAxCd = 0.0 - nodes(I)%JAxCa = 0.0 - nodes(I)%JAxCp = 0.0 - END IF - - !node1 = nodes(elements(I)%Node1Indx) - !node2 = nodes(elements(I)%Node2Indx) - - END DO - -END SUBROUTINE SetAxialCoefs + integer(IntKi), intent(in ) :: MCoefMod + integer(IntKi), intent(in ) :: MmbrCoefIDIndx + real(ReKi), intent(in ) :: SimplCd + real(ReKi), intent(in ) :: SimplCdMG + real(ReKi), intent(in ) :: SimplCa + real(ReKi), intent(in ) :: SimplCaMG + real(ReKi), intent(in ) :: SimplCp + real(ReKi), intent(in ) :: SimplCpMG + real(ReKi), intent(in ) :: SimplAxCd + real(ReKi), intent(in ) :: SimplAxCdMG + real(ReKi), intent(in ) :: SimplAxCa + real(ReKi), intent(in ) :: SimplAxCaMG + real(ReKi), intent(in ) :: SimplAxCp + real(ReKi), intent(in ) :: SimplAxCpMG + type(Morison_CoefMembers), intent(in ) :: CoefMembers(:) + integer(IntKi), intent(in ) :: NCoefDpth + type(Morison_CoefDpths), intent(in ) :: CoefDpths(:) + integer(IntKi), intent(in ) :: numNodes + type(Morison_NodeType), intent(in ) :: nodes(:) + type(Morison_MemberType), intent(inout) :: member + + type(Morison_NodeType) :: node, node1, node2 + integer(IntKi) :: i, j + real(ReKi) :: s, Cd, CdMG, Ca, CaMG, Cp, CpMG, AxCa, AxCp, AxCaMG, AxCpMG + + select case ( MCoefMod ) + + case (1) ! Simple model : all nodes receive the same coefficients + do i = 1, member%NElements + 1 + if ( member%tMG(i) > 0.0_ReKi ) then + member%Cd (i) = SimplCdMG + member%Ca (i) = SimplCaMG + member%Cp (i) = SimplCpMG + member%AxCd (i) = SimplAxCdMG + member%AxCa (i) = SimplAxCaMG + member%AxCp (i) = SimplAxCpMG + else + member%Cd (i) = SimplCd + member%Ca (i) = SimplCa + member%Cp (i) = SimplCp + member%AxCd (i) = SimplAxCd + member%AxCa (i) = SimplAxCa + member%AxCp (i) = SimplAxCp + end if + end do + + CASE (2) ! Depth-based model: coefficients are set using depth-based table data + do i = 1, member%NElements + 1 + CALL SetDepthBasedCoefs( nodes(member%NodeIndx(i))%Position(3), member%tMG(i), NCoefDpth, CoefDpths, member%Cd(i), member%Ca(i), & + member%Cp(i), member%AxCd(i), member%AxCa(i), member%AxCp(i) ) + end do + + CASE (3) ! Member-based model: coefficients set using member-specific coefficient tables + do i = 1, member%NElements + 1 + ! Pull member end-node data from the tables and then linearly interpolate it onto the interior member nodes + s = (i-1) / member%NElements + if ( member%tMG(i) > 0.0_ReKi ) then + member%Cd (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdMG2*s + member%Ca (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaMG2*s + member%Cp (i) = CoefMembers(MmbrCoefIDIndx)%MemberCpMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCpMG2*s + member%AxCd (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCdMG2*s + member%AxCa (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG2*s + member%AxCp (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCpMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCpMG2*s + else + member%Cd (i) = CoefMembers(MmbrCoefIDIndx)%MemberCd1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCd2 *s + member%Ca (i) = CoefMembers(MmbrCoefIDIndx)%MemberCa1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCa2 *s + member%Cp (i) = CoefMembers(MmbrCoefIDIndx)%MemberCp1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCp2 *s + member%AxCd (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCd1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCd2 *s + member%AxCa (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCa1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCa2 *s + member%AxCp (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCp1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCp2 *s + end if + end do + end select + +end subroutine SetExternalHydroCoefs -SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node ) +SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node, tMG, MGdensity ) ! sets the margine growth thickness of a single node (previously all nodes) INTEGER, INTENT( IN ) :: numMGDepths TYPE(Morison_MGDepthsType), INTENT( IN ) :: MGDepths(:) - TYPE(Morison_NodeType), INTENT( INOUT ) :: node - - INTEGER :: I, J + TYPE(Morison_NodeType), INTENT( IN ) :: node + real(ReKi), intent( inout ) :: tMG + real(ReKi), intent( inout ) :: MGdensity + + INTEGER :: I, J REAL(ReKi) :: z INTEGER :: indx1, indx2 REAL(ReKi) :: dd, s @@ -2014,7 +1251,7 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node ) !Find the table entry(ies) which match the node's depth value ! The assumption here is that the depth table is stored from largest ! to smallest in depth - z = node%JointPos(3) + z = node%Position(3) foundLess = .FALSE. indx1 = 0 indx2 = 0 @@ -2031,8 +1268,8 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node ) END DO IF ( indx2 == 0 .OR. .NOT. foundLess ) THEN !Not at a marine growth depth - node%tMG = 0.0 - node%MGdensity = 0.0 + tMG = 0.0 + MGdensity = 0.0 ELSE ! Linearly interpolate the coef values based on depth !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) @@ -2043,514 +1280,629 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node ) ELSE s = ( MGDepths(indx1)%MGDpth - z ) / dd END IF - node%tMG = MGDepths(indx1)%MGThck*(1-s) + MGDepths(indx2)%MGThck*s - node%MGdensity = MGDepths(indx1)%MGDens*(1-s) + MGDepths(indx2)%MGDens*s + tMG = MGDepths(indx1)%MGThck*(1-s) + MGDepths(indx2)%MGThck*s + MGdensity = MGDepths(indx1)%MGDens*(1-s) + MGDepths(indx2)%MGDens*s END IF END SUBROUTINE SetNodeMG - - -!==================================================================================================== -SUBROUTINE Morison_ProcessMorisonGeometry( InitInp, ErrStat, ErrMsg ) -! This public subroutine process the input geometry and parameters and eliminates joint overlaps, -! sub-divides members, sets joint-level properties, etc. It is called by HydroDyn before Morison_Init -! so that the node positions are available beforehand for other parts of HydroDyn. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - TYPE(Morison_InitInputType), INTENT( INOUT ) :: InitInp ! the Morison initialization data - !TYPE(Morison_ParameterType), INTENT( INOUT ) :: p ! tge Morison parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables + +subroutine AllocateMemberDataArrays( member, errStat, errMsg ) + type(Morison_MemberType), intent (inout) :: member + integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + integer(IntKi) :: errStat2 ! returns a non-zero value when an error occurs + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + character(*), parameter :: routineName = 'AllocateMemberDataArrays' + + errStat = ErrID_None + errMSg = '' + call AllocAry(member%NodeIndx , member%NElements, 'member%NodeIndx' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dRdl_mg , member%NElements, 'member%dRdl_mg' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dRdl_in , member%NElements, 'member%dRdl_in' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%floodstatus , member%NElements, 'member%floodstatus' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%alpha , member%NElements, 'member%alpha' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%alpha_fb , member%NElements, 'member%alpha_fb' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%alpha_fb_star, member%NElements, 'member%alpha_fb_star', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%m_fb_l , member%NElements, 'member%m_fb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%m_fb_u , member%NElements, 'member%m_fb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%h_cfb_l , member%NElements, 'member%h_cfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%h_cfb_u , member%NElements, 'member%h_cfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_lfb_l , member%NElements, 'member%I_lfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_lfb_u , member%NElements, 'member%I_lfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rfb_l , member%NElements, 'member%I_rfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rfb_u , member%NElements, 'member%I_rfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%m_mg_l , member%NElements, 'member%m_mg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%m_mg_u , member%NElements, 'member%m_mg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%h_cmg_l , member%NElements, 'member%h_cmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%h_cmg_u , member%NElements, 'member%h_cmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_lmg_l , member%NElements, 'member%I_lmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_lmg_u , member%NElements, 'member%I_lmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rmg_l , member%NElements, 'member%I_rmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rmg_u , member%NElements, 'member%I_rmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Cfl_fb , member%NElements, 'member%Cfl_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Cfr_fb , member%NElements, 'member%Cfr_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%CM0_fb , member%NElements, 'member%CM0_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%R , member%NElements+1, 'member%R ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%RMG , member%NElements+1, 'member%RMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Rin , member%NElements+1, 'member%Rin ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%tMG , member%NElements+1, 'member%tMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%MGdensity , member%NElements+1, 'member%MGdensity ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Cd , member%NElements+1, 'member%Cd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Ca , member%NElements+1, 'member%Ca ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Cp , member%NElements+1, 'member%Cp ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%AxCd , member%NElements+1, 'member%AxCd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%AxCa , member%NElements+1, 'member%AxCa ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%AxCp , member%NElements+1, 'member%AxCp ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + + ! Initialize everything to zero + member%NodeIndx = 0.0_ReKi + member%dRdl_mg = 0.0_ReKi + member%dRdl_in = 0.0_ReKi + member%floodstatus = 0.0_ReKi + member%alpha = 0.0_ReKi + member%alpha_fb = 0.0_ReKi + member%alpha_fb_star = 0.0_ReKi + member%m_fb_l = 0.0_ReKi + member%m_fb_u = 0.0_ReKi + member%h_cfb_l = 0.0_ReKi + member%h_cfb_u = 0.0_ReKi + member%I_lfb_l = 0.0_ReKi + member%I_lfb_u = 0.0_ReKi + member%I_rfb_l = 0.0_ReKi + member%I_rfb_u = 0.0_ReKi + member%m_mg_l = 0.0_ReKi + member%m_mg_u = 0.0_ReKi + member%h_cmg_l = 0.0_ReKi + member%h_cmg_u = 0.0_ReKi + member%I_lmg_l = 0.0_ReKi + member%I_lmg_u = 0.0_ReKi + member%I_rmg_l = 0.0_ReKi + member%I_rmg_u = 0.0_ReKi + member%Cfl_fb = 0.0_ReKi + member%Cfr_fb = 0.0_ReKi + member%CM0_fb = 0.0_ReKi + member%R = 0.0_ReKi + member%RMG = 0.0_ReKi + member%Rin = 0.0_ReKi + member%tMG = 0.0_ReKi + member%MGdensity = 0.0_ReKi + member%Cd = 0.0_ReKi + member%Ca = 0.0_ReKi + member%Cp = 0.0_ReKi + member%AxCd = 0.0_ReKi + member%AxCa = 0.0_ReKi + member%AxCp = 0.0_ReKi + +end subroutine AllocateMemberDataArrays + +subroutine FlipMemberNodeData( member, nodes, doSwap, errStat, errMsg ) + type(Morison_MemberType), intent (inout) :: member + type(Morison_NodeType), intent (in ) :: nodes(:) + logical, intent ( out) :: doSwap + integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + integer(IntKi) :: i, j1, j2, numMemNodes, indx + + errStat = ErrID_None + errMSg = '' + + doSwap = .FALSE. + numMemNodes = member%NElements + 1 + j1 = member%NodeIndx(1) + j2 = member%NodeIndx(numMemNodes) + IF ( EqualRealNos(nodes(j1)%Position(3), nodes(j2)%Position(3) ) ) THEN ! Z1 = Z2 + IF ( EqualRealNos(nodes(j1)%Position(1), nodes(j2)%Position(1) ) ) THEN ! X1 = X2 + IF ( nodes(j1)%Position(2) > nodes(j2)%Position(2) ) THEN + doSwap = .TRUE. ! Y1 > Y2 + END IF + ELSE IF ( nodes(j1)%Position(1) > nodes(j2)%Position(1) ) THEN + doSwap = .TRUE. ! X1 > X2 + END IF + ELSE IF ( nodes(j1)%Position(3) > nodes(j2)%Position(3) ) THEN + doSwap = .TRUE. ! Z1 > Z2 + END IF - INTEGER :: I, J !, j1, j2, tempINT ! generic integer for counting -! TYPE(Morison_JointType) :: joint1, joint2 -! Real(ReKi) :: z1 -! Real(ReKi) :: z2 - Real(ReKi) :: d - INTEGER :: temp - INTEGER :: prop1Indx, prop2Indx, node1Indx, node2Indx - INTEGER :: maxNodes = 0 - INTEGER :: maxElements = 0 - INTEGER :: maxSuperMembers = 0 - ! TYPE(Morison_NodeType) :: node1, node2, tempNode - INTEGER :: numSplitNodes - INTEGER :: Node1Indx, Node2Indx ! indices of joint nodes at member ends - TYPE(Morison_NodeType),ALLOCATABLE :: splitNodes(:) - LOGICAL :: doSwap + IF ( doSwap ) THEN + member%NodeIndx(1) = j2 + member%NodeIndx(numMemNodes) = j1 + + ! Loop over half the interior nodes and swap their indices + do i = 1, ceiling( (numMemNodes-2.0_ReKi)/2.0_ReKi) + indx = member%NodeIndx(1+i) + member%NodeIndx(1+i) = member%NodeIndx(numMemNodes-1-i) + member%NodeIndx(numMemNodes-1-i) = indx + end do + + end if + +end subroutine FlipMemberNodeData + +subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrFilledIDIndx, propSet1, propSet2, InitInp, errStat, errMsg ) + real(ReKi), intent (in ) :: gravity + type(Morison_MemberType), intent (inout) :: member + integer(IntKi), intent (in ) :: MCoefMod + integer(IntKi), intent (in ) :: MmbrCoefIDIndx + integer(IntKi), intent (in ) :: MmbrFilledIDIndx + type(Morison_MemberPropType), intent (in ) :: propSet1 ! property set of node 1 + type(Morison_MemberPropType), intent (in ) :: propSet2 ! property set of node N+1 + type(Morison_InitInputType), intent (in ) :: InitInp + integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + integer(IntKi) :: N, i + real(ReKi) :: WtrDepth,s, dl + type(Morison_NodeType) :: node1, node2 + real(ReKi) :: vec(3), vecLen + real(ReKi) :: memLength + real(ReKi) :: Za + real(ReKi) :: Zb + real(ReKi) :: phi + real(ReKi) :: sinPhi + real(ReKi) :: cosPhi + real(ReKi) :: Rmid + real(ReKi) :: RmidMG + real(ReKi) :: Rmidin + real(ReKi) :: Lmid + real(ReKi) :: li + real(ReKi) :: Vinner_l, Vinner_u, Vouter_l, Vouter_u, Vballast_l, Vballast_u + real(ReKi) :: tk(1,3), Imat(3,3) + REAL(ReKi) :: h_c ! center of mass offset from first node + + errStat = ErrID_None + errMSg = '' + + WtrDepth = InitInp%WtrDpth + N = member%NElements + dl = member%dl + + vec = InitInp%Nodes(member%NodeIndx(N+1))%Position - InitInp%Nodes(member%NodeIndx(1))%Position + + ! calculate reference orientation information. Note: members are straight to start + memLength = member%RefLength + member%k(1:3) = (vec/memLength) ! vector along member from start to end point, length > 0 was already checked when the members were parsed and generated from the input file data + tk(1,1) = member%k(1) + tk(1,2) = member%k(2) + tk(1,3) = member%k(3) + member%kkt = matmul(transpose(tk),tk) + call Eye(Imat,errStat,errMsg) + member%Ak = Imat - member%kkt + phi = acos(vec(3)/memLength) ! incline angle + sinPhi = sin(phi) + cosPhi = cos(phi) + - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" + ! These are all per node and not done here, yet + do i = 1, member%NElements+1 + call SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%Nodes(member%NodeIndx(i)), member%tMG(i), member%MGDensity(i) ) + end do + + member%R( 1) = propSet1%PropD / 2.0 + member%RMG(1) = propSet1%PropD / 2.0 + member%tMG(1) + member%Rin(1) = propSet1%PropD / 2.0 - propSet1%PropThck + member%R( N+1) = propSet2%PropD / 2.0 + member%RMG(N+1) = propSet2%PropD / 2.0 + member%tMG(N+1) + member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck + do i = 2, member%NElements + s = (i-1) / member%NElements + member%R( i) = member%R( 1)*(1-s) + member%R( N+1)*s + member%Rin(i) = member%Rin(1)*(1-s) + member%Rin(N+1)*s + member%RMG(i) = member%R(i) + member%tMG(i) + end do + + call SetExternalHydroCoefs( MCoefMod, MmbrCoefIDIndx, InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, & + InitInp%SimplCpMG, InitInp%SimplAxCd, InitInp%SimplAxCdMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG, InitInp%CoefMembers, & + InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%NNodes, InitInp%Nodes, member ) - IF ( InitInp%NMembers > 0 ) THEN - - - ! Determine the maximum number of nodes, elements, and super members which might be generated for the simulation mesh - CALL GetMaxSimQuantities( InitInp%NMGDepths, InitInp%MGTop, InitInp%MGBottom, InitInp%MSL2SWL, -InitInp%WtrDpth, InitInp%FilledGroups, InitInp%NJoints, InitInp%InpJoints, InitInp%NMembers, InitInp%InpMembers, maxNodes, maxElements, maxSuperMembers ) - - - ! Create a worse case size for the number of nodes and number of elements that will be generated for the simulation - ! marine growth split + super member split + member subdivision all creates new nodes - - ! marine growth split + member subdivision creates new elements + + ! calculate reference incline angle and heading, and related trig values. Note: members are straight to start + Za = InitInp%Nodes(member%NodeIndx(1 ))%Position(3) + Zb = InitInp%Nodes(member%NodeIndx(N+1))%Position(3) + + ! find fill location of member (previously in SetElementFillProps) + member%MmbrFilledIDIndx = MmbrFilledIDIndx ! Set this to the parameter version of this member data + if ( MmbrFilledIDIndx > 0 ) then + member%FillDens = InitInp%FilledGroups(MmbrFilledIDIndx)%FillDens + member%FillFSLoc = InitInp%FilledGroups(MmbrFilledIDIndx)%FillFSLoc + if (member%FillFSLoc >= Zb) then + member%z_overfill = member%FillFSLoc - Zb + member%l_fill = member%RefLength + member%memfloodstatus = 1 ! fully flooded + elseif (Za >= member%FillFSLoc) then + ! No ballast + member%memfloodstatus = 0 + member%z_overfill = 0.0_ReKi + member%l_fill = 0.0_ReKi + else + member%z_overfill =0 + if ( Zb <= -InitInp%WtrDpth ) then + member%memfloodstatus = 0 ! member fully buried in seabed + member%l_fill = 0 + else + member%memfloodstatus = 2 ! partially flooded member + member%l_fill = (member%FillFSLoc - Za)/cosPhi + end if - ! Create a worse case size for the number of super members - - ! 1) Let's start by generating a mirror of the input mesh (joints and members) as the initial version of the simulation mesh - ! In doing so, create the initial mapping between the input mesh and this current version of the simulation mesh - - - ! Allocate memory for Joint-related arrays - - InitInp%NNodes = InitInp%NJoints - - ALLOCATE ( InitInp%Nodes(maxNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Nodes array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - DO I = 1,InitInp%NNodes - ! Copy all necessary data from the input joints to these node data structures - InitInp%Nodes(I)%JointPos = InitInp%InpJoints(I)%JointPos - InitInp%Nodes(I)%JointAxIDIndx = InitInp%InpJoints(I)%JointAxIDIndx - InitInp%Nodes(I)%JointOvrlp = InitInp%InpJoints(I)%JointOvrlp - InitInp%Nodes(I)%NConnections = InitInp%InpJoints(I)%NConnections - InitInp%Nodes(I)%ConnectionList = InitInp%InpJoints(I)%ConnectionList - InitInp%Nodes(I)%JointIndx = I - InitInp%Nodes(I)%NodeType = 1 ! 1 = end of a member, 2 = interior of a member, 3 = super member node - InitInp%Nodes(I)%FillFSLoc = InitInp%MSL2SWL - InitInp%Nodes(I)%FillFlag = .FALSE. - InitInp%Nodes(I)%FillDensity = 0.0 - - ! Set the marine growth thickness and density information for each joint node - CALL SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%Nodes(I) ) - - END DO + end if + else + member%FillDens = 0.0 + member%FillFSLoc = 0.0 ! Future calculations for ballasting MUST verify that MbrFilledIDIndx > 0 for any ballasting calcs or this value will cause errors + member%z_overfill =0 + member%l_fill = 0 + member%memfloodstatus = 0 + end if + + ! Check the member does not exhibit any of the following conditions + if (.not. member%PropPot) then + if ( abs(Zb) < abs(member%Rmg(N+1)*sinPhi) ) then + call SetErrStat(ErrID_Fatal, 'The upper end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + end if + if ( abs(Za) < abs(member%Rmg(1)*sinPhi) ) then + call SetErrStat(ErrID_Fatal, 'The lower end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + end if + if ( ( Za < -WtrDepth .and. Zb >= -WtrDepth ) .and. ( phi > 10.0*d2r .or. abs((member%RMG(N+1) - member%RMG(i))/member%RefLength)>0.1 ) ) then + call SetErrStat(ErrID_Fatal, 'A member which crosses the seabed must not be inclined more than 10 degrees from vertical or have a taper larger than 0.1. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + end if + end if + + + ! calculate h_floor if seabed-piercing + member%h_floor = 0.0_ReKi + member%i_floor = 0 + if (Za < -WtrDepth) then + do i= 2, member%NElements+1 + Za = InitInp%Nodes(member%NodeIndx(i))%Position(3) + if (Za > -WtrDepth) then ! find the lowest node above the seabed + + if (cosPhi < 0.173648178 ) then ! phi > 80 degrees and member is seabed crossing + call SetErrStat(ErrID_Fatal, 'A seabed crossing member must have an inclination angle of <= 80 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + end if + + member%h_floor = (-WtrDepth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) + member%i_floor = i-1 ! record the number of the element that pierces the seabed + exit + end if + end do + end if + + + + ! calculate element-level values + + do i = 1, member%NElements + member%dRdl_mg(i) = (member%RMG(i+1) - member%RMG(i))/dl + member%dRdl_in(i) = (member%Rin(i+1) - member%Rin(i))/dl - ! Allocate memory for Members arrays - - InitInp%NElements = InitInp%NMembers + member%alpha( i) = GetAlpha(member%RMG(i), member%RMG(i+1)) + member%alpha_fb(i) = GetAlpha(member%Rin(i), member%Rin(i+1)) - ALLOCATE ( InitInp%Members(maxElements), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Members array.' - ErrStat = ErrID_Fatal - RETURN - END IF - + end do + + member%Vinner = 0.0_ReKi ! Total volume of member without marine growth + member%Vouter = 0.0_ReKi ! Total outer volume of member including marine growth + member%Vballast = 0.0_ReKi ! Total ballasted volume of member + + ! force-related constants for each element + do i = 1, member%NElements + + Za = InitInp%Nodes(member%NodeIndx( i))%Position(3) ! z location of node i + Zb = InitInp%Nodes(member%NodeIndx(i+1))%Position(3) ! z location of node i+1 - ! loop through members, assign each its nodes, etc. - DO I = 1,InitInp%NMembers - - InitInp%Members(I)%Node1Indx = InitInp%InpMembers(I)%MJointID1Indx ! Index of the first node in the Morison_NodeType array - InitInp%Members(I)%Node2Indx = InitInp%InpMembers(I)%MJointID2Indx ! Index of the second node in the Morison_NodeType array - node1Indx = InitInp%Members(I)%Node1Indx - node2Indx = InitInp%Members(I)%Node2Indx - prop1Indx = InitInp%InpMembers(I)%MPropSetID1Indx - prop2Indx = InitInp%InpMembers(I)%MPropSetID2Indx - - ! Make sure that Node1 has the lower Z value, re-order if necessary - ! We need to do this because the local element coordinate system is defined such that the first node is located with a smaller global Z value - ! than the second node. - ! The local element coordinate system requires that Z1 <= Z2, and if Z1=Z2 then X1 <= X2, and if Z1=Z2, X1=X2 then Y1 InitInp%Nodes(node2Indx)%JointPos(2) ) THEN - doSwap = .TRUE. ! Y1 > Y2 - END IF - ELSE IF ( InitInp%Nodes(node1Indx)%JointPos(1) > InitInp%Nodes(node2Indx)%JointPos(1) ) THEN - doSwap = .TRUE. ! X1 > X2 - END IF - ELSE IF ( InitInp%Nodes(node1Indx)%JointPos(3) > InitInp%Nodes(node2Indx)%JointPos(3) ) THEN - doSwap = .TRUE. ! Z1 > Z2 - END IF + ! ------------------ marine growth weight and inertia, and flooded ballast inertia-------------------- + Vinner_l = 0.0 + Vouter_l = 0.0 + Vinner_U = 0.0 + Vouter_U = 0.0 + Vballast_l = 0.0 + Vballast_U = 0.0 + if (i > member%i_floor) then + ! full marine growth: get the properties for each half-element lumped to the appropriate node + + Rmid = 0.5*(member%R( i)+member%R( i+1)) ! radius at middle of segment, where division occurs + RmidMG = 0.5*(member%RMG(i)+member%RMG(i+1)) ! radius with marine growth at middle of segment, where division occurs + Rmidin = 0.5*(member%Rin(i)+member%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs + Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment + + CALL MarineGrowthPartSegment(member%R(i ), Rmid, member%RMG(i ),RmidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_rmg_l(i)) ! get precomupted quantities for lower half-segment + CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomupted quantities for upper half-segment + CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomupted quantities for lower half-segment + CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomupted quantities for upper half-segment - IF ( doSwap ) THEN - - ! Swap node indices to satisfy orientation rules for element nodes + + else if (i == member%i_floor) then + ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node + + Rmid = (-member%h_floor*member%R( i) +(dl+member%h_floor)*member%R( i+1))/dl + RmidMG = (-member%h_floor*member%RMG(i) +(dl+member%h_floor)*member%RMG(i+1))/dl + Rmidin = (-member%h_floor*member%Rin(i) +(dl+member%h_floor)*member%Rin(i+1))/dl + Lmid = -member%h_floor + + CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG, -Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomupted quantities for upper half-segment + CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomupted quantities for upper half-segment + Vinner_l = 0.0 + Vouter_l = 0.0 + Vballast_l = 0.0 + end if + + + ! Determine volumes to add to Non-WAMIT modeled members, etc. + if (.not. member%PropPot) then + + if (Zb < -WtrDepth) then + ! fully buried element, do not add these volume contributions to totals + else if (0.0 > Zb) then + ! fully submerged elements. + ! NOTE: For an element which is fractionaly in the seabed, the entire element volume is added to totals + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + member%Vsubmerged = member%Vsubmerged + Vouter_l + Vouter_u + else if ((0.0 > Za) .AND. (0.0 < Zb)) then + if (i == 1) then + call SetErrStat(ErrID_Fatal, 'The lowest element of a member must not cross the free surface. This is true for MemberID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties') + end if - InitInp%Members(I)%Node1Indx = InitInp%InpMembers(I)%MJointID2Indx - InitInp%Members(I)%Node2Indx = InitInp%InpMembers(I)%MJointID1Indx - node1Indx = InitInp%Members(I)%Node1Indx - node2Indx = InitInp%Members(I)%Node2Indx - temp = prop1Indx - prop1Indx = prop2Indx - prop2Indx = temp - InitInp%Members(I)%InpMbrDist1 = 1.0 - InitInp%Members(I)%InpMbrDist2 = 0.0 + ! partially submerged element + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + ! compute volume portion which is submerged + Lmid = -Za/cosPhi + call TaperCalc( member%Rmg(i), member%Rmg(i)+Lmid*member%dRdl_mg(i), Lmid, Vouter_l, h_c) - ! --- Swap member coeffs if needed. - ! Fine in this loop since there is a unique CoefMember per Member (otherwise we could swap them several times). - J = InitInp%InpMembers(I)%MmbrCoefIDIndx ! Index in CoefMembers table - IF (J>0) THEN - ! NOTE: SWAP defined at the end of the current subroutine - CALL SWAP(InitInp%CoefMembers(J)%MemberCd1 , InitInp%CoefMembers(J)%MemberCd2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCa1 , InitInp%CoefMembers(J)%MemberCa2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCp1 , InitInp%CoefMembers(J)%MemberCp2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCa1 , InitInp%CoefMembers(J)%MemberAxCa2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCp1 , InitInp%CoefMembers(J)%MemberAxCp2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCdMG1 , InitInp%CoefMembers(J)%MemberCdMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCaMG1 , InitInp%CoefMembers(J)%MemberCaMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberCpMG1 , InitInp%CoefMembers(J)%MemberCpMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCaMG1, InitInp%CoefMembers(J)%MemberAxCaMG2) - CALL SWAP(InitInp%CoefMembers(J)%MemberAxCpMG1, InitInp%CoefMembers(J)%MemberAxCpMG2) - END IF + member%Vsubmerged = member%Vsubmerged + Vouter_l - END IF + else ! fully above the water + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + end if + end if + + ! ------------------ flooded ballast weight (done) -------------------- + + li = dl*(i-1) + ! fully buried element + if (Zb < -WtrDepth) then + member%floodstatus(i) = 0 + + ! fully filled elements + else if (member%memfloodstatus > 0 .and. member%FillFSLoc > Zb) then + member%floodstatus(i) = 1 + member%Vballast = member%Vballast + Vballast_l + Vballast_u + ! depth-adjusted force distribution constant + member%alpha_fb_star(i) = member%alpha_fb(i)*( Zb - member%FillFSLoc )**3 / ( ( (1-member%alpha_fb(i))*(Za - member%FillFSLoc))**3 + member%alpha_fb(i)*(Zb - member%FillFSLoc)**3 ) + ! force and moment magnitude constants + - ! assign member to its joints' lists of connected members - Node1Indx = InitInp%Members(I)%Node1Indx - Node2Indx = InitInp%Members(I)%Node2Indx - InitInp%Nodes(Node1Indx)%Nconnections = InitInp%Nodes(Node1Indx)%Nconnections + 1 ! increment the joint's number of connections - InitInp%Nodes(Node2Indx)%Nconnections = InitInp%Nodes(Node2Indx)%Nconnections + 1 ! increment the joint's number of connections - InitInp%Nodes(Node1Indx)%ConnectionList(InitInp%Nodes(Node1Indx)%Nconnections) = I ! assign the member ID to the joint's connection list (positive since end 1) - InitInp%Nodes(Node2Indx)%ConnectionList(InitInp%Nodes(Node2Indx)%Nconnections) =-I ! assign the member ID to the joint's connection list (negative since end 2) + member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * dl *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)* member%dRdl_in(i) + member%Rin(i))*dl + 1/3* member%dRdl_in(i)*dl**2 ) + member%Cfr_fb(i) = Pi * member%FillDens * gravity * dl *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*dl +1/3 * member%dRdl_in(i)**2 *dl**2 ) + member%CM0_fb(i) = TwoPi * member%FillDens * gravity * dl *( 0.25*dl**3* member%dRdl_in(i)**4 + 0.25*dl**3* member%dRdl_in(i)**2 + dl**2* member%dRdl_in(i)**3*member%Rin(i) + 2/3*dl**2* member%dRdl_in(i)*member%Rin(i) + 1.5*dl* member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*dl*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) - ! assign member some input quantities - InitInp%Members(I)%InpMbrIndx = I - InitInp%Members(I)%MDivSize = InitInp%InpMembers(I)%MDivSize - InitInp%Members(I)%MCoefMod = InitInp%InpMembers(I)%MCoefMod - InitInp%Members(I)%MmbrCoefIDIndx = InitInp%InpMembers(I)%MmbrCoefIDIndx - InitInp%Members(I)%MmbrFilledIDIndx = InitInp%InpMembers(I)%MmbrFilledIDIndx - - ! assign member length - CALL GetDistance( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, d) - InitInp%Members(I)%InpMbrLen = d - ! Calculate the element-level direction cosine matrix and attach it to the entry in the elements array - CALL Morison_DirCosMtrx( InitInp%Nodes(node1Indx)%JointPos, InitInp%Nodes(node2Indx)%JointPos, InitInp%Members(I)%R_LToG ) - - InitInp%Members(I)%PropPot = InitInp%InpMembers(I)%PropPot ! Flag specifying whether member is modelled in WAMIT [true = modelled in WAMIT, false = not modelled in WAMIT] + ! partially filled element + else if ((member%memfloodstatus > 0) .and. (member%FillFSLoc > Za) .AND. (member%FillFSLoc < Zb)) then - ! InitInp%Nodes(node1Indx)%R_LToG = InitInp%Members(I)%R_LToG - ! InitInp%Nodes(node2Indx)%R_LToG = InitInp%Members(I)%R_LToG - - !@mhall: no longer any need to split or subdivide members. - ! Instead, we need to discretize a member and create node points along it. - - DO I = 1, InitInp%NMembers - ! discretize a member and create node points along it. This will be done in Morison_Init - CALL DiscretizeMember( InitInp%NNodes, InitInp%Nodes, InitInp%Members(I), InitInp%MPropSets(prop1Indx), InitInp%MPropSets(prop2Indx), InitInp%NMGDepths, InitInp%MGDepths, ErrStat, ErrMsg ) - !@mhall: hoping passing one entry of Members is okay - otherwise can pass all and put for loop inside DiscretizeMember + ! Need to enforce the modeling requirement that the first/bottom-most element of a member be fully flooded + if (i == 1) then + call SetErrStat(ErrID_Fatal,'The modeling of partially flooded/ballested members requires that the first/bottom-most element of a member must be fully flooded. This is not true for MemberID '//trim(num2lstr(member%MemberID)),ErrStat,ErrMsg,'SetMemberProperties') + return + end if + ! Need to enforce the modeling requirement that a partially flooded member must not be close to horizontal + if ( (InitInp%Nodes(member%NodeIndx(N+1))%Position(3) - member%Rin(N+1)*sinPhi) < member%FillFSLoc ) then + call SetErrStat(ErrID_Fatal,'The modeling of partially flooded/ballested members requires the the member not be near horizontal. This is not true for MemberID '//trim(num2lstr(member%MemberID)),ErrStat,ErrMsg,'SetMemberProperties') + return + end if - END DO + member%floodstatus(i) = 2 + ! length along axis from node i to fill level + member%h_fill = member%l_fill - (i-1)*dl + !Since this element is only partially flooded/ballasted, compute the Volume fraction which is filled + call TaperCalc( member%Rin(i), member%Rin(i)+member%h_fill*member%dRdl_in(i), member%h_fill, Vballast_l, h_c) + Vballast_u = 0.0 + member%Vballast = member%Vballast + Vballast_l + Vballast_u ! TODO: Determine how to add only fraction of volume + + + ! depth-adjusted force distribution constant + member%alpha_fb_star(i) = (1 - member%alpha_fb(i))*( Za - member%FillFSLoc )**3 / ( ( (1-member%alpha_fb(i))*(Za - member%FillFSLoc))**3 - member%alpha_fb(i)*(Zb - member%FillFSLoc)**3 ) + + ! force and moment magnitude constants + member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * member%h_fill *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)*member%dRdl_in(i) + member%Rin(i))*member%h_fill + 1/3*member%dRdl_in(i)*member%h_fill**2 ) + member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1/3 *member%dRdl_in(i)**2 *member%h_fill**2 ) + member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2/3*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) + 1.5*member%h_fill*member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*member%h_fill*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) - ! Set the fill properties onto the elements - !@mthall: This is now done in member setup loop in Morison_Init. CALL SetElementFillProps( InitInp%NFillGroups, InitInp%FilledGroups, InitInp%NElements, InitInp%Members ) - - - !@mhall: The below should be changed to operate on each member m%Members(I) and the arrays within it, or each joint. - ! The hydro coefficients should be set for each node along a member. - - ! Set the element Cd, Ca, and Cp coefs - CALL SetElementCoefs( InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, InitInp%SimplCpMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG,InitInp%CoefMembers, InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members ) - - ! Set the axial coefs AxCd and AxCa - CALL SetAxialCoefs( InitInp%NJoints, InitInp%NAxCoefs, InitInp%AxialCoefs, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members ) - - - !@mhall: duplicate nodes at member ends no longer needed + ! unflooded element + else + member%floodstatus(i) = 0 + end if - - ! 6) Store information necessary to compute the user-requested member outputs and joint outputs. The requested output locations - ! may be located in between two simulation nodes, so quantities will need to be interpolated. qOutput = q1*s + q2*(1-s), where 0<= s <= 1. - - ! NOTE: since we need to mantain the input geometry, the altered members are now part of the simulation mesh and - ! we will generate a mapping between the input and simulation meshes which is needed to generate user-requested outputs. + + end do ! end looping through elements + + +end subroutine SetMemberProperties + + +subroutine SetupMembers( InitInp, p, errStat, errMsg ) + type(Morison_InitInputType), intent (inout) :: InitInp + type(Morison_ParameterType), intent (inout) :: p + integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + integer(IntKi) :: i, prop1Indx, prop2Indx + integer(IntKi) :: errStat2 ! returns a non-zero value when an error occurs + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + logical :: doSwap + + + errStat = ErrID_None + errMSg = '' + ! allocate and copy in the InpMembers array + p%NMembers = InitInp%NMembers + ALLOCATE ( p%Members(p%NMembers), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for the members array.' + errStat = ErrID_Fatal + RETURN + END IF + do i = 1, p%NMembers + p%Members(i)%MemberID = InitInp%InpMembers(i)%MemberID + p%Members(i)%RefLength = InitInp%InpMembers(i)%RefLength + p%Members(i)%dl = InitInp%InpMembers(i)%dl + p%Members(i)%NElements = InitInp%InpMembers(i)%NElements + p%Members(i)%PropPot = InitInp%InpMembers(i)%PropPot + + call AllocateMemberDataArrays(p%Members(i), errStat2, errMsg2) ; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') - END DO !I = 1,InitInp%NMembers + p%Members(i)%NodeIndx = InitInp%InpMembers(i)%NodeIndx ! now that the parameter version is allocated, copy the data from the InitInp version - - - ELSE - - - ! No Morison elements, so no processing is necessary, but set nodes and elements to 0. - - ! p%NMorisonNodes = 0 - ! p%NMorisonElements = 0 + ! only reorder the nodes if the end nodes do not follow the necessary coordinate ordering rules + call FlipMemberNodeData(p%Members(i), InitInp%nodes, doSwap, errStat2, errMsg2) ; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') + if (doSwap) then + prop2Indx = InitInp%InpMembers(I)%MPropSetID1Indx + prop1Indx = InitInp%InpMembers(I)%MPropSetID2Indx + else + prop1Indx = InitInp%InpMembers(I)%MPropSetID1Indx + prop2Indx = InitInp%InpMembers(I)%MPropSetID2Indx + end if + ! Now populate the various member data arrays using the HydroDyn input file data + call SetMemberProperties( InitInp%Gravity, p%Members(i), InitInp%InpMembers(i)%MCoefMod, InitInp%InpMembers(i)%MmbrCoefIDIndx, InitInp%InpMembers(i)%MmbrFilledIDIndx, InitInp%MPropSets(prop1Indx), InitInp%MPropSets(prop2Indx), InitInp, errStat2, errMsg2 ) ; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') + end do - END IF - CONTAINS - - SUBROUTINE SWAP(x1,x2) - Real(Reki),intent(inout) :: x1,x2 - Real(Reki) :: tmp - tmp = x1 - x1 = x2 - x2 = tmp - END SUBROUTINE SWAP -END SUBROUTINE Morison_ProcessMorisonGeometry - +end subroutine SetupMembers !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. !! The initial states and initial guess for the input are defined. !! A lot of the model setup has been done previously in Morison_ProcessMorisonGeometry, and stored in InitInp. -SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) +SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, errStat, errMsg ) !.................................................................................................................................. - TYPE(Morison_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine !intent out because of MOVE_ALLOC - TYPE(Morison_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined - TYPE(Morison_ParameterType), INTENT( OUT) :: p !< Parameters - TYPE(Morison_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states - TYPE(Morison_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states - TYPE(Morison_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states - TYPE(Morison_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (this contains the Members array) - TYPE(Morison_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; - !! only the output mesh is initialized) - TYPE(Morison_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables - REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that - !! (1) Morison_UpdateStates() is called in loose coupling & - !! (2) Morison_UpdateDiscState() is called in tight coupling. - !! Input is the suggested time from the glue code; - !! Output is the actual coupling interval that will be used - !! by the glue code. - TYPE(Morison_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - TYPE(Morison_MemberType) :: mem ! the current member - INTEGER :: N - REAL(ReKi) :: dl - REAL(ReKi) :: vec(3) - REAL(ReKi) :: phi ! member tilt angle - REAL(ReKi) :: beta ! member tilt heading - REAL(ReKi) :: cosPhi - REAL(ReKi) :: sinPhi - REAL(ReKi) :: tanPhi - REAL(ReKi) :: sinBeta - REAL(ReKi) :: cosBeta - REAL(ReKi) :: Za - REAL(ReKi) :: Zb - - - ! TYPE(Morison_InitInputType) :: InitLocal ! Local version of the input data for the geometry processing routine -! INTEGER, ALLOCATABLE :: distribToNodeIndx(:) -! INTEGER, ALLOCATABLE :: lumpedToNodeIndx(:) - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - ! Initialize the NWTC Subroutine Library - - CALL NWTC_Init( ) - - - ! InitLocal = InitInp - p%WtrDens = InitInp%WtrDens - p%NumOuts = InitInp%NumOuts - p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] - p%OutSwtch = InitInp%OutSwtch - ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for MOutLst array.' - ErrStat = ErrID_Fatal - RETURN - END IF -IF (ALLOCATED(InitInp%MOutLst) ) & - p%MOutLst = InitInp%MOutLst ! Member output data - - p%NJOutputs = InitInp%NJOutputs ! Number of joints to output [ >=0 and <10] - - ALLOCATE ( p%JOutLst(p%NJOutputs), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for JOutLst array.' - ErrStat = ErrID_Fatal - RETURN - END IF -IF (ALLOCATED(InitInp%JOutLst) ) & - p%JOutLst = InitInp%JOutLst ! Joint output data - - - - ! ----------------------- set up the members ----------------------- - - ! allocate and copy in the Members array - - ALLOCATE ( m%Members(p%NMembers), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the members array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - m%Members = InitInp%Members - - - ! ----------------------- set up the nodes ----------------------- - - ! allocate and copy in the nodes list - - p%NNodes = InitInp%NNodes - - ALLOCATE ( p%Nodes(p%NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for Nodes array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - p%Nodes = InitInp%Nodes - - - ! allocate and copy in hydrodynamic arrays for the nodes - - p%NStepWave= InitInp%NStepWave - - ALLOCATE ( p%WaveVel(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave velocities array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveVel = InitInp%WaveVel - - ALLOCATE ( p%WaveAcc(0:p%NStepWave, p%NNodes, 3), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave accelerations array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveAcc = InitInp%WaveAcc - - ALLOCATE ( p%WaveDynP(0:p%NStepWave, p%NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave dynamic pressure array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveDynP = InitInp%WaveDynP - - ALLOCATE ( p%WaveTime(0:p%NStepWave), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for wave time array.' - ErrStat = ErrID_Fatal - RETURN - END IF - p%WaveTime = InitInp%WaveTime - - - CALL MOVE_ALLOC( InitInp%nodeInWater, p%nodeInWater ) + TYPE(Morison_InitInputType), INTENT(INOUT) :: InitInp !< Input data for initialization routine !intent out because of MOVE_ALLOC + TYPE(Morison_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(Morison_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(Morison_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(Morison_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(Morison_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states (this contains the Members array) + TYPE(Morison_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + TYPE(Morison_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Morison_UpdateStates() is called in loose coupling & + !! (2) Morison_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(Morison_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None + + TYPE(Morison_MemberType) :: member ! the current member + type(Morison_MemberInputType) :: inpMember ! current input file-based member + INTEGER :: N, i, j, count + REAL(ReKi) :: dl + REAL(ReKi) :: vec(3),v2D(3,1) + REAL(ReKi) :: phi ! member tilt angle + REAL(ReKi) :: beta ! member tilt heading + REAL(ReKi) :: cosPhi + REAL(ReKi) :: sinPhi + REAL(ReKi) :: tanPhi + REAL(ReKi) :: sinBeta + REAL(ReKi) :: cosBeta + REAL(ReKi) :: Za + REAL(ReKi) :: Zb + real(ReKi) :: memLength ! reference member length + real(ReKi) :: An(3), An_drag(3), Vn(3), I_n(3), Z0, sgn, Amag, Amag_drag, Vmag, Imag, Ir_MG_end, Il_MG_end, R_I(3,3), IRl_mat(3,3), tMG, MGdens, F_I(3), F_DP(3), af(3), VnDotAf + integer(IntKi) :: MemberEndIndx, ncommon + INTEGER, ALLOCATABLE :: commonNodeLst(:) + LOGICAL, ALLOCATABLE :: usedJointList(:) + integer(IntKi) :: errStat2 ! returns a non-zero value when an error occurs + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + + + ! Initialize errStat + errStat = ErrID_None + errMsg = "" + - ! allocate and initialize some wave-related arrays - - ALLOCATE ( elementWaterStateArr( 0:NStepWave, p%NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the elementWaterStateArr array.' - ErrStat = ErrID_Fatal - RETURN - END IF - elementWaterStateArr = 0 ! out of the water - - - - ALLOCATE ( m%F_I( 0:NStepWave, 6, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the inertial forces/moments array.' - ErrStat = ErrID_Fatal + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + ! Define parameters here: + p%DT = Interval + p%WtrDens = InitInp%WtrDens + p%WtrDpth = InitInp%WtrDpth + p%Gravity = InitInp%Gravity + p%NNodes = InitInp%NNodes + p%NJoints = InitInp%NJoints + p%NStepWave = InitInp%NStepWave + p%NumOuts = InitInp%NumOuts + p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] + p%OutSwtch = InitInp%OutSwtch + + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for MOutLst array.' + errStat = ErrID_Fatal RETURN END IF - m%F_I = 0.0 - - ALLOCATE ( m%F_DP( 0:NStepWave, 6, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the dynamic pressure forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_DP = 0.0 - - - - ! allocate and initialize joint-specific arrays + IF (ALLOCATED(InitInp%MOutLst) ) & + p%MOutLst = InitInp%MOutLst ! Member output data - ALLOCATE ( commonNodeLst(10), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the commonNodeLst array.' - ErrStat = ErrID_Fatal - RETURN - END IF - commonNodeLst = -1 - - ALLOCATE ( usedJointList(numNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the UsedJointList array.' - ErrStat = ErrID_Fatal - RETURN - END IF - usedJointList = .FALSE. - - ALLOCATE ( lumpedToNodeIndx(numLumpedMarkers), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( nodeToLumpedIndx(numNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the lumped index array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - ALLOCATE ( L_An( 3, numLumpedMarkers ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the joint directional area array.' - ErrStat = ErrID_Fatal + p%NJOutputs = InitInp%NJOutputs ! Number of joints to output [ >=0 and <10] + + ALLOCATE ( p%JOutLst(p%NJOutputs), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for JOutLst array.' + errStat = ErrID_Fatal RETURN END IF - L_An = 0.0 - - - - ! initialize load arrays for all nodes - - CALL AllocateNodeLoadVariables(m, p%NNodes, ErrStat, ErrMsg) - - ! a few additional loads that - - - + IF (ALLOCATED(InitInp%JOutLst) ) & + p%JOutLst = InitInp%JOutLst ! Joint output data + + ! ----------------------- set up the members ----------------------- + call SetupMembers( InitInp, p, errStat2, errMsg2 ) ; call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'Morison_Init' ) + if ( errStat >= AbortErrLev ) return + + !------------------------ set up joint (or joint-node) properties -- + do i = 1, InitInp%NJoints + InitInp%Nodes(i)%JAxCd = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCd + InitInp%Nodes(i)%JAxCa = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCa + InitInp%Nodes(i)%JAxCp = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCp + InitInp%Nodes(i)%JAxCd = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCd + InitInp%Nodes(i)%JAxCa = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCa + InitInp%Nodes(i)%JAxCp = InitInp%AxialCoefs(InitInp%InpJoints(i)%JointAxIDIndx)%AxCp + ! Redundant work (these are already assigned to the member data arrays, + ! but is needed on the joint data because we report the tMG, and MGDensity at each Joint node in the Summary File + call SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%Nodes(i), InitInp%Nodes(i)%tMG, InitInp%Nodes(i)%MGDensity ) + end do + + ! allocate and copy in node-based load and hydrodynamic arrays + call AllocateNodeLoadVariables(InitInp, p, m, p%NNodes, errStat, errMsg ) + call MOVE_ALLOC( InitInp%nodeInWater, p%nodeInWater ) + + ! Create the input and output meshes associated with loads at the nodes CALL MeshCreate( BlankMesh = u%Mesh & ,IOS = COMPONENT_INPUT & ,Nnodes = p%NNodes & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & + ,errStat = errStat & + ,ErrMess = errMsg & ,TranslationDisp = .TRUE. & ,Orientation = .TRUE. & ,TranslationVel = .TRUE. & @@ -2558,56 +1910,45 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ,TranslationAcc = .TRUE. & ,RotationAcc = .TRUE. ) - IF ( ErrStat >= AbortErrLev ) RETURN - - CALL AllocAry( Morison_Rad, numDistribMarkers, 'Morison_Rad', ErrStat, ErrMsg) - IF ( ErrStat >= AbortErrLev ) RETURN + IF ( errStat >= AbortErrLev ) RETURN + +!TODO: Do we still need this for visualization? How is it used? GJH 3/26/2020 Actually need a line mesh to properly visualize the members + !CALL AllocAry( Morison_Rad, numDistribMarkers, 'Morison_Rad', errStat, errMsg) + !IF ( errStat >= AbortErrLev ) RETURN DO I=1,p%NNodes - - IF ( p%Nodes(I)%NodeType == 3 ) THEN - - END IF - - ! Create the node on the mesh - - !orientation = transpose(p%Nodes(I)%R_LToG ) - + + ! Create the node on the mesh CALL MeshPositionNode (u%Mesh & - , count & - , p%Nodes(I)%JointPos & ! this info comes from FAST - , ErrStat & - , ErrMsg & + , i & + , InitInp%Nodes(I)%Position & ! this info comes from HydroDyn input file and the subroutine: Morison_GenerateSimulationNodes + , errStat & + , errMsg & ) !, transpose(p%Nodes(I)%R_LToG) ) - IF ( ErrStat /= 0 ) RETURN - - - Morison_Rad(count) = p%Nodes(I)%R ! set this for FAST visualization + IF ( errStat /= 0 ) RETURN + +!TODO: Do we still need this for visualization? How is it used? GJH 3/26/2020 Actually need a line mesh to properly visualize the members + ! Morison_Rad(count) = p%Nodes(I)%R ! set this for FAST visualization - !@mhall: what is happening in these lines? - distribToNodeIndx(count) = I - nodeToDistribIndx(I) = count + ! Create the mesh element CALL MeshConstructElement (u%Mesh & , ELEMENT_POINT & - , ErrStat & - , ErrMsg & - , count & + , errStat & + , errMsg & + , i & ) - count = count + 1 - + END DO - - CALL MeshCommit ( u%Mesh & - , ErrStat & - , ErrMsg ) + , errStat & + , errMsg ) - IF ( ErrStat /= 0 ) THEN + IF ( errStat /= 0 ) THEN RETURN END IF @@ -2622,228 +1963,79 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In u%Mesh%TranslationAcc = 0.0 u%Mesh%RotationAcc = 0.0 - ! Duplicate the input mesh to create the output mesh - CALL MeshCopy ( SrcMesh = u%Mesh & ,DestMesh = y%Mesh & ,CtrlCode = MESH_SIBLING & ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & + ,errStat = errStat & + ,ErrMess = errMsg & ,Force = .TRUE. & ,Moment = .TRUE. ) - u%Mesh%RemapFlag = .TRUE. y%Mesh%RemapFlag = .TRUE. - - - - !--------------- - - ! Define parameters here: - - - p%DT = Interval - ! Define initial system states here: - x%DummyContState = 0 - xd%DummyDiscState = 0 - z%DummyConstrState = 0 - OtherState%DummyOtherState = 0 - m%LastIndWave = 1 + x%DummyContState = 0 + xd%DummyDiscState = 0 + z%DummyConstrState = 0 + OtherState%DummyOtherState = 0 + m%LastIndWave = 1 ! IF ( p%OutSwtch > 0 ) THEN @mhall: I think the below need to be allocated in all cases - - - - - ! loop through elements of each member and precalculate the required quantities - DO im = 1, p%NMembers - - - mem = m%Members(im) - - N = mem%NElements - dl = mem%dl - - ! find fill location of member (previously in SetElementFillProps) - IF ( mem%MmbrFilledIDIndx > 0 ) THEN - - mem%FillDens = InitInp%FilledGroups(elements(I)%MmbrFilledIDIndx)%FillDens - mem%FillFSLoc = InitInp%FilledGroups(elements(I)%MmbrFilledIDIndx)%FillFSLoc - ELSE - mem%FillDens = 0.0 - mem%FillFSLoc = 0.0 - END IF - - - ! calculate instantaneous incline angle and heading, and related trig values - vec = p%Nodes(mem%NodeIndx(N+1))%JointPos - p%Nodes(mem%NodeIndx(1))%JointPos - - phi = arccos(vec(3)/SQRT(Dot_Product(vec,vec))) ! incline angle -! beta = arctan2(vec(2), vec(1)) ! heading of incline - - sinPhi = sin(phi) - cosPhi = cos(phi) -! tanPhi = tan(phi) -! sinBeta = sin(beta) -! cosBeta = cos(beta) - - - - ! calculate l_fill or z_overfill for the member - mem%l_fill = (mem%FillFSLoc - )/cosPhi ! fill length along cylinder axis - - if mem%l_fill > mem%Len then - mem%z_overfill = mem%FillFSLoc - Zb - else - mem%z_overfill = 0.0 - end if - - - ! calculate h_floor if seabed-piercing - if (Za < -WtrDepth) then - do i=2,N+1 - if (Za > -WtrDepth) then ! find the lowest node above the seabed - mem%h_floor = (-WtrDepth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) - mem%i_floor = i-1 ! record the number of the element that pierces the seabed - break - end if - end do - end if - - - ! calculate element-level values - DO i = 1,N - mem%m_mg(i) = (mem%RMG(i+1) - mem%RMG(i))/dl - mem%m_in(i) = (mem%Rin(i+1) - mem%Rin(i))/dl - - mem%alpha( i) = GetAlpha(mem%RMG(i), mem%RMG(i+1)) - mem%alpha_fb(i) = GetAlpha(mem%Rin(i), mem%Rin(i+1)) - - END DO - - - ! force-related constants for each element - DO i = 1,N - - Za = p%Nodes(mem%NodeIndx( i))%JointPos(3) ! z location of node i - Zb = p%Nodes(mem%NodeIndx(i+1))%JointPos(3) ! z location of node i+1 - - ! ------------------ marine growth weight and inertia, and flooded ballast inertia-------------------- - - if (i > mem%i_floor) then - ! full marine growth: get the properties for each half-element lumped to the appropriate node - - Rmid = 0.5*(mem%R( i)+mem%R( i+1)) ! radius at middle of segment, where division occurs - RmidMG = 0.5*(mem%RMG(i)+mem%RMG(i+1)) ! radius with marine growth at middle of segment, where division occurs - Rmidin = 0.5*(mem%Rin(i)+mem%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs - Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment - - CALL MarineGrowthPartSegment(mem%R(i ), Rmid, mem%RMG(i ),RmidMG, Lmid, rhoMG, mem%m_mg_l(i), mem%h_cmg_l(i), mem%I_lmg_l(i), mem%I_rmg_l(i)) ! get precomupted quantities for lower half-segment - CALL MarineGrowthPartSegment(mem%R(i+1), Rmid, mem%RMG(i+1),RmidMG,-Lmid, rhoMG, mem%m_mg_u(i), mem%h_cmg_u(i), mem%I_lmg_u(i), mem%I_rmg_u(i)) ! get precomupted quantities for upper half-segment - CALL FloodedBallastPartSegment(mem%Rin(i ), mem%Rmidin, Lmid, FillDens, mem%m_fb_l(i), mem%h_cfb_l(i), mem%I_lfb_l(i), mem%I_rfb_l(i)) ! get precomupted quantities for lower half-segment - CALL FloodedBallastPartSegment(mem%Rin(i+1), mem%Rmidin, -Lmid, FillDens, mem%m_fb_u(i), mem%h_cfb_u(i), mem%I_lfb_u(i), mem%I_rfb_u(i)) ! get precomupted quantities for upper half-segment - - else if (i == mem%ifloor) then - ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node - - Rmid = (-mem%h_floor*mem%R( i) +(dl+mem%h_floor)*mem%R( i+1))/dl - RmidMG = (-mem%h_floor*mem%RMG(i) +(dl+mem%h_floor)*mem%RMG(i+1))/dl - Rmidin = (-mem%h_floor*mem%Rin(i) +(dl+mem%h_floor)*mem%Rin(i+1))/dl - Lmid = -mem%h_floor - - CALL MarineGrowthPartSegment(mem%R(i+1), Rmid, mem%RMG(i+1),RmidMG, -Lmid, rhoMG, mem%m_mg_u(i), mem%h_cmg_u(i), mem%I_lmg_u(i), mem%I_rmg_u(i)) ! get precomupted quantities for upper half-segment - CALL FloodedBallastPartSegment(mem%Rin(i+1), Rmidin, -Lmid, FillDens, mem%m_fb_u(i), mem%h_cfb_u(i), mem%I_lfb_u(i), mem%I_rfb_u(i)) ! get precomupted quantities for upper half-segment - - end if - - - ! ------------------ flooded ballast weight (done) -------------------- - - ! fully buried element - if (Zb < -WtrDepth) then - mem%floodstatus(i) = 0 - - ! fully filled elements - if (mem%FillFSLoc > Zb) then - mem%floodstatus(i) = 1 - - ! depth-adjusted force distribution constant - mem%alpha_fb_star(i) = mem%alpha_fb(i)*( Zb - mem%FillFSLoc )^3 / ( ( (1-mem%alpha_fb(i))*(Za - mem%FillFSLoc))^3 + mem%alpha_fb(i)*(Zb - mem%FillFSLoc)^3 ) - - ! force and moment magnitude constants - mem%Cfl_fb(i) = TwoPi * m * mem%FillDens * g * dl *( (li - mem%lfill)*Rin(i) + 0.5*((li - mem%lfill)*m_in + mem%Rin(i))*dl + 1/3*m_in*dl^2 ) - mem%Cfr_fb(i) = Pi * mem%FillDens * g * dl *( mem%Rin(i)^2 + m_in_in*Rin(i)*dl +1/3 m_in^2 *dl^2 ) - mem%CM0_fb(i) = TwoPi * mem%FillDens * g * dl *( 0.25*dl^3*m_in^4 + 0.25*dl^3*m_in^2 + dl^2*m_in^3*Rin(i) + 2/3*dl^2*m_in*mem%Rin(i) + 1.5*dl*m_in^2*mem%Rin(i)^2 + 0.5*dl*mem%Rin(i)^2 + m_in*mem%Rin(i)^3 ) - - - ! partially filled element - else if ((mem%FillFSLoc > Za) .AND. (mem%FillFSLoc < Zb)) then - mem%floodstatus(i) = 2 - - ! length along axis from node i to fill level - mem%h_fill = mem%l_fill - (i-1)*dl - - ! depth-adjusted force distribution constant - mem%alpha_fb_star(i) = (1 - mem%alpha_fb(i))*( Za - mem%FillFSLoc )^3 / ( ( (1-mem%alpha_fb(i))*(Za - mem%FillFSLoc))^3 - mem%alpha_fb(i)*(Zb - mem%FillFSLoc)^3 ) - - ! force and moment magnitude constants - mem%Cfl_fb(i) = TwoPi * m * mem%FillDens * g * mem%h_fill *( (li - mem%lfill)*mem%Rin(i) + 0.5*((li - mem%lfill)*m_in + mem%Rin(i))*mem%h_fill + 1/3*m_in*mem%h_fill^2 ) - mem%Cfr_fb(i) = Pi * mem%FillDens * g * mem%h_fill *( mem%Rin(i)^2 + m_in_in*mem%Rin(i)*mem%h_fill +1/3 m_in^2 *mem%h_fill^2 ) - mem%CM0_fb(i) = TwoPi * mem%FillDens * g * mem%h_fill *( 0.25*mem%h_fill^3*m_in^4 + 0.25*mem%h_fill^3*m_in^2 + mem%h_fill^2*m_in^3*mem%Rin(i) + 2/3*mem%h_fill^2*m_in*mem%Rin(i) + 1.5*mem%h_fill*m_in^2*mem%Rin(i)^2 + 0.5*mem%h_fill*mem%Rin(i)^2 + m_in*mem%Rin(i)^3 ) - - ! unflooded element - else - mem%floodstatus(i) = 0 - - end if - - - end do ! end looping through elements - -end do ! looping through members - - + ! allocate and initialize joint-specific arrays -! loop through joints to calculate joint quantities (the joints are the first NJoints nodes) - - - ! CA is the added mass coefficient for three dimensional bodies in infinite fluid (far from boundaries) The default value is 2/Pi - AMfactor = 2.0 * densWater * Pi / 3.0 - - usedJointList = .FALSE. + ALLOCATE ( commonNodeLst(10), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for the commonNodeLst array.' + errStat = ErrID_Fatal + RETURN + END IF commonNodeLst = -1 - -DO I = 1,p%NJoints - - An = 0.0 - Vn = 0.0 - I_n = 0.0 - IF ( p%Nodes(I)%JointPos(3) >= z0 ) THEN + ALLOCATE ( usedJointList(p%NJoints), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for the UsedJointList array.' + errStat = ErrID_Fatal + RETURN + END IF + usedJointList = .FALSE. - ! loop through each member attached to the joint, getting the radius of its appropriate end - DO J = 1, p%Nodes(I)%NConnections - - ! identify attached member and which end to us - IF (p%Nodes(I)%ConnectionList(J) > 0) THEN ! set up for end node 1 - member = p%Members(p%Nodes(I)%ConnectionList(J)) - MemberEndIndx = 1 - ELSE ! set up for end node N+1 - member = p%Members(-p%Nodes(I)%ConnectionList(J)) - MemberEndIndx = member%NElements + 1 - END IF + ! loop through joints to calculate joint quantities (the joints are the first NJoints nodes) + + usedJointList = .FALSE. + commonNodeLst = -1 + !TODO: Error Handling + + + do i = 1,p%NJoints + + An = 0.0 + Vn = 0.0 + I_n = 0.0 + MGdens = 0.0 + tMG = -999.0 + IF ( InitInp%InpJoints(i)%Position(3) >= -p%WtrDpth ) THEN + + ! loop through each member attached to the joint, getting the radius of its appropriate end + DO J = 1, InitInp%InpJoints(I)%NConnections + + ! identify attached member and which end to us + IF (InitInp%InpJoints(I)%ConnectionList(J) > 0) THEN ! set up for end node 1 + !TODO: Should not perform a copy here? A pointer to data would be better? + member = p%Members(InitInp%InpJoints(I)%ConnectionList(J)) + MemberEndIndx = 1 + ELSE + ! set up for end node N+1 + !TODO: I am not sure about the negative sign, is %ConnectionList(J) ever negative valued? + member = p%Members(-InitInp%InpJoints(I)%ConnectionList(J)) + MemberEndIndx = member%NElements + 1 + END IF - ! attached member cannot be modeled using WAMIT if we're to count it - IF (.NOT. member%PropPot) THEN - ! Compute the signed area*outward facing normal of this member sgn = 1.0 @@ -2852,102 +2044,104 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ELSE sgn = 1.0 ! Local coord sys points out of member at ending node, so leave sign of local z vector END IF - - ! Compute the signed quantities for this member end, and add them to the joint values - An = An + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector - Vn = Vn + sgn* member%k* (member%RMG(MemberEndIndx))**3 ! r^3-weighted normal vector used for mass - I_n=I_n + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**4 ! r^4-weighted normal vector used for moments of inertia - + + ! Compute the signed quantities for this member end (for drag regardless of PropPot value), and add them to the joint values + An_drag = An_drag + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector + + ! For the following quantities, the attached member cannot be modeled using WAMIT if we're to count it + IF (.NOT. member%PropPot) THEN + + ! Compute the signed quantities for this member end, and add them to the joint values + An = An + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector + Vn = Vn + sgn* member%k* (member%RMG(MemberEndIndx))**3 ! r^3-weighted normal vector used for mass + I_n=I_n + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**4 ! r^4-weighted normal vector used for moments of inertia + if (tMG == -999.0) then + ! All member nodes at this joint will have the same MG thickness and density, so only do this once + tMG = member%tMG(MemberEndIndx) + MGdens = member%MGdensity(MemberEndIndx) + end if + END IF + + END DO !J = 1, InitInp%InpJoints(I)%NConnections + + p%An_End(:,i) = An_drag + Amag_drag = Dot_Product(An_drag ,An_drag) + Amag = Dot_Product(An ,An) + IF (EqualRealNos(Amag_drag, 0.0_ReKi)) THEN + p%DragConst_End(i) = 0.0 + ELSE + p%DragConst_End(i) = InitInp%Nodes(i)%JAxCd*p%WtrDens / ( 4.0_ReKi * Amag_drag ) END IF + ! magnitudes of normal-weighted values + Amag = sqrt(Amag) + Vmag = sqrt(Dot_Product(Vn ,Vn)) + Imag = sqrt(Dot_Product(I_n,I_n)) + + ! Constant part of the external hydrodynamic added mass term + if ( Vmag > 0.0 ) then + v2D(:,1) = Vn + p%AM_End(:,:,i) = (InitInp%Nodes(I)%JAxCa*InitInp%WtrDens/ Vmag)*matmul(transpose(v2D), v2D) + end if - END DO !J = 1, p%Nodes(I)%NConnections - - ! magnitudes of normal-weighted values - Amag = sqrt(Dot_Product(An ,An)) - Vmag = sqrt(Dot_Product(Vn ,Vn)) - Imag = sqrt(Dot_Product(I_n,I_n)) - - - ! marine growth mass/inertia magnitudes - p%Nodes(I)%m_MG = p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Amag ! marine growth mass at joint - Ir_MG_end = 0.25* p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Imag ! radial moment of inertia magnitude - Il_MG_end = 0.5* p%Nodes(I)%MGdensity * p%Nodes(I)%tMG * Imag ! axial moment of inertia magnitude + ! Constant part of the external hydrodynamic dynamic pressure force + if ( Amag > 0.0 ) then + p%DP_Const_End(:,i) = InitInp%Nodes(i)%JAxCp*An + endif + + ! marine growth mass/inertia magnitudes + p%Mass_MG_End(i) = MGdens * tMG * Amag + p%F_WMG_End(3,i) = -MGdens * tMG * Amag * InitInp%Gravity ! Z component of the directional force due to marine growth mass at joint + Ir_MG_end = 0.25 * MGdens * tMG * Imag ! radial moment of inertia magnitude + Il_MG_end = 0.5 * MGdens * tMG * Imag ! axial moment of inertia magnitude - ! get rotation matrix for moment of inertia orientations - RodrigMat(I_n, R_I, ErrStat, ErrMsg) + ! get rotation matrix for moment of inertia orientations + call RodrigMat(I_n, R_I, errStat, errMsg) - ! globally-oreinted moment of inertia matrix for joint - Irl_mat = 0 - Irl_mat(1,1) = Ir_MG_end - Irl_mat(2,2) = Ir_MG_end - Irl_mat(3,3) = Il_MG_end - - p%Nodes(I)%I_MG = MatMul( MatMul(R_I, Irl_mat), Transpose(R_I) ) ! final moment of inertia matrix for node - + ! globally-oreinted moment of inertia matrix for joint + Irl_mat = 0.0 + Irl_mat(1,1) = Ir_MG_end + Irl_mat(2,2) = Ir_MG_end + Irl_mat(3,3) = Il_MG_end - - ! pre-compute wave inertia loads on joint - DO M=0,NStepWave - ! The WaveAcc array has indices of (timeIndx, nodeIndx, vectorIndx), the nodeIndx needs to correspond to the total list of nodes for which - ! the wave kinematics were generated. We can use the nodeToLumpedIndx however for L_F_I and it's indices are (timeIndx, nodeIndx, vectorIndx) + p%I_MG_End(:,:,i) = MatMul( MatMul(R_I, Irl_mat), Transpose(R_I) ) ! final moment of inertia matrix for node - F_I = 0.0 - IF ( (Vmag > 0.0) .AND. (.NOT. p%Nodes(I)%PropPot) ) THEN - af = p%WaveAcc(M, i,:) - VnDotAf = Dot_Product(Vn,af) - F_I(1:3) = ( p%Nodes(I)%JAxCa*AMfactor*VnDotAf / ( REAL( nCommon, ReKi ) * Vmag ) ) * Vn - END IF - m%L_F_I(M, :, i) = F_I - END DO - - ELSE ! if joint is below seabed - - p%Nodes(I)%m_MG = 0.0 - p%Nodes(I)%I_MG = 0.0 - m%L_F_I(:,:, i) = 0.0 - - END IF ! nodes(I)%JointPos(3) >= z0 + + END IF ! nodes(I)%Position(3) >= z0 -END DO ! looping through nodes that are joints - - - + END DO ! looping through nodes that are joints, i + ! Define initial guess for the system inputs here: - - ! u%DummyInput = 0 - - - ! Define system output initializations (set up mesh) here: - - + ! u%DummyInput = 0 + ! Define system output initializations (set up mesh) here: ! Define initialization-routine output here: - ! Initialize the outputs - + ! Initialize the outputs IF ( p%OutSwtch > 0) then !@mhall: moved this "if" to after allocations - CALL MrsnOUT_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) - IF ( ErrStat > ErrID_None ) RETURN + CALL MrsnOUT_Init( InitInp, y, p, InitOut, errStat, errMsg ) + IF ( errStat > AbortErrLev ) RETURN ! Determine if we need to perform output file handling IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - CALL MrsnOUT_OpenOutput( Morison_ProgDesc%Name, TRIM(InitInp%OutRootName)//'.HD', p, InitOut, ErrStat, ErrMsg ) - IF ( ErrStat > ErrID_None ) RETURN + CALL MrsnOUT_OpenOutput( Morison_ProgDesc%Name, TRIM(InitInp%OutRootName)//'.HD', p, InitOut, errStat, errMsg ) + IF ( errStat > AbortErrLev ) RETURN END IF END IF + ! We will call CalcOutput to compute the loads for the initial reference position + ! Then we can use the computed load components in the Summary File + ! NOTE: Morison module has no states, otherwise we could no do this. GJH - ! Write Summary information now that everything has been initialized. - - CALL WriteSummaryFile( InitInp%UnSum, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NNodes, InitInp%Nodes, InitInp%NElements, InitInp%Members, p%NumOuts, p%OutParam, p%NMOutputs, p%MOutLst, p%distribToNodeIndx, p%NJOutputs, p%JOutLst, u%LumpedMesh, y%LumpedMesh,u%DistribMesh, y%DistribMesh, p%L_F_B, p%L_F_BF, p%D_F_B, p%D_F_BF, p%D_F_MG, InitInp%Gravity, ErrStat, ErrMsg ) !p%NDistribMarkers, distribMarkers, p%NLumpedMarkers, lumpedMarkers, - IF ( ErrStat > ErrID_None ) RETURN - - ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which - ! this module must be called here: - - !Interval = p%DT + call Morison_CalcOutput(0.0_DbKi, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) + + ! Write Summary information now that everything has been initialized. + CALL WriteSummaryFile( InitInp%UnSum, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NJoints, InitInp%NNodes, InitInp%Nodes, p%NMembers, p%Members, & + p%NumOuts, p%OutParam, p%NMOutputs, p%MOutLst, p%NJOutputs, p%JOutLst, u%Mesh, y%Mesh, & + p, m, errStat, errMsg ) + IF ( errStat > AbortErrLev ) RETURN + !Contains: ! SUBROUTINE CleanUpInitOnErr ! IF (ALLOCATED(sw(1)%array)) DEALLOCATE(sw(1)%array, STAT=aviFail) @@ -2956,26 +2150,29 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In END SUBROUTINE Morison_Init -SUBROUTINE RodrigMat(a, R, ErrStat, ErrMsg) +SUBROUTINE RodrigMat(a, R, errStat, errMsg) ! calculates rotation matrix R to rotate unit vertical vector to direction of input vector a REAL(ReKi), INTENT ( IN ) :: a(3) ! input vector REAL(ReKi), INTENT ( INOUT ) :: R(3,3) ! rotation matrix from Rodrigues's rotation formula - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg ! Error message if errStat /= ErrID_None REAL(ReKi) :: vec(3) ! scaled and adjusted input vector - REAL(ReKi) :: factor ! denomenator used for scaling - - - IF ((a(1) == 0) .AND. (a(2)==0)) THEN ! return identity if vertical - CALL EYE(R, ErrStat,ErrMsg) - IF (a(3) < 0) THEN - R = -R - END IF - - ELSE - vec = a/SQRT(Dot_Product(a,a)) + REAL(ReKi) :: factor ! denomenator used for scaling + factor = Dot_Product(a,a) + if ( EqualRealNos(factor, 0.0_ReKi) ) then + !IF ((a(1) == 0) .AND. (a(2)==0)) THEN ! return identity if vertical + ! CALL EYE(R, errStat,errMsg) + ! IF (a(3) < 0) THEN + ! R = -R + ! END IF + ! + errStat = ErrID_Fatal + errMsg = 'RodrigMat encountered vector of zero length' + + else + vec = a/SQRT(factor) ! normalize a vec(3) = vec(3) + 1 factor = 2.0/Dot_Product(vec, vec) @@ -2989,162 +2186,142 @@ SUBROUTINE RodrigMat(a, R, ErrStat, ErrMsg) R(3,1) = factor*vec(3)*vec(1) R(3,2) = factor*vec(3)*vec(2) R(3,3) = factor*vec(3)*vec(3) - 1 - END IF + end if END SUBROUTINE RodrigMat FUNCTION GetAlpha(R1,R2) ! calculates relative center of volume location for a (tapered) cylindrical element - + real(ReKi) :: GetAlpha REAL(ReKi), INTENT ( IN ) :: R1 ! interior radius of element at node point REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element - - REAL(ReKi) :: alpha ! relative location of volumentric centroid between radius 1 and 2 (0= at radius 1, 1= at radius 2) - - alpha = (R1*R1 + 2*R1*R2 + 3*R2*R2)/4/(R1*R1 + R1*R2 + R2*R2) - - return alpha + + GetAlpha = (R1*R1 + 2*R1*R2 + 3*R2*R2)/4/(R1*R1 + R1*R2 + R2*R2) + END FUNCTION GetAlpha -SUBROUTINE AllocateNodeLoadVariables(m, NNodes, ErrStat, ErrMsg ) - TYPE(Morison_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables - INTEGER(IntKi), INTENT(IN ) :: NNodes ! number of nodes in node list - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - ALLOCATE ( m%F_D(3,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_D array.' - ErrStat = ErrID_Fatal +SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) + TYPE(Morison_InitInputType), INTENT(IN ) :: InitInp ! Initialization inputs + TYPE(Morison_ParameterType), INTENT(INOUT) :: p ! parameter variables + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m ! Misc/optimization variables + INTEGER(IntKi), INTENT(IN ) :: NNodes ! number of nodes in node list + INTEGER(IntKi), INTENT( OUT) :: errStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg ! Error message if errStat /= ErrID_None + integer(IntKi) :: errStat2 ! returns a non-zero value when an error occurs + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + character(*), parameter :: routineName = 'AllocateNodeLoadVariables' + + ! Initialize errStat + + errStat = ErrID_None + errMsg = "" + + call AllocAry( m%nodeInWater , NNodes , 'm%nodeInWater' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%vrel , 3, NNodes , 'm%vrel' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_D , 6, NNodes , 'm%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_A , 6, NNodes , 'm%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_B , 6, NNodes , 'm%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_BF , 6, NNodes , 'm%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_I , 6, NNodes , 'm%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_If , 6, NNodes , 'm%F_If' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_WMG , 6, NNodes , 'm%F_WMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_IMG , 6, NNodes , 'm%F_IMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%FV , 3, NNodes , 'm%FV' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%FA , 3, NNodes , 'm%FA' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%FDynP , NNodes , 'm%FDynP' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%An_End , 3, p%NJoints, 'p%An_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%DragConst_End, p%NJoints, 'p%DragConst_End', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_I_End , 3, p%NJoints, 'm%F_I_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_BF_End , 6, p%NJoints, 'm%F_BF_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_A_End , 6, p%NJoints, 'm%F_A_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_D_End , 6, p%NJoints, 'm%F_D_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_B_End , 6, p%NJoints, 'm%F_B_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_IMG_End , 6, p%NJoints, 'm%F_IMG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%I_MG_End , 3, 3, p%NJoints, 'p%I_MG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%F_WMG_End , 3, p%NJoints, 'p%F_WMG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%Mass_MG_End , p%NJoints, 'p%Mass_MG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%AM_End , 3, 3, p%NJoints, 'p%AM_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( p%DP_Const_End , 3, p%NJoints, 'p%DP_Const_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + if (errStat == ErrID_Fatal) return + + m%nodeInWater = 0 + m%vrel = 0.0_ReKi + m%F_D = 0.0_ReKi + m%F_A = 0.0_ReKi + m%F_B = 0.0 + m%F_BF = 0.0 + m%F_I = 0.0 + m%F_If = 0.0 + m%F_WMG = 0.0 + m%F_IMG = 0.0 + m%FV = 0.0_ReKi + m%FA = 0.0_ReKi + m%FDynP = 0.0_ReKi + p%An_End = 0.0 + p%DragConst_End = 0.0 + m%F_I_End = 0.0 + m%F_BF_End = 0.0 + m%F_A_End = 0.0 + m%F_D_End = 0.0 + m%F_B_End = 0.0 + m%F_IMG_End = 0.0 + p%DP_Const_End = 0.0 + p%I_MG_End = 0.0 + p%Mass_MG_End = 0.0 + p%F_WMG_End = 0.0 + p%AM_End = 0.0 + + allocate( p%WaveVel(0:p%NStepWave, p%NNodes, 3), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for wave velocities array.' + errStat = ErrID_Fatal RETURN END IF - m%F_D = 0.0_ReKi + p%WaveVel = InitInp%WaveVel - ALLOCATE ( m%F_B( 6, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the buoyancy forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_B = 0.0 - - - ALLOCATE ( m%F_MG( 6, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the marine growth weight forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_MG = 0.0 - - ALLOCATE ( m%F_BF( 6, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the buoyancy due to flooding forces/moments array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_BF = 0.0 - - - ALLOCATE ( m%AM_M( 3, 3, NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the added mass of flooded fluid.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%AM_M = 0.0 - - ALLOCATE ( m%AM_MG( NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the added mass of marine growth.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%AM_MG = 0.0 - - ALLOCATE ( m%AM_F( NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the added mass of flooded fluid.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%AM_F = 0.0 - - ALLOCATE ( m%F_AM(6,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_AM = 0.0_ReKi - - ALLOCATE ( m%F_AM_M(6,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM_M array.' - ErrStat = ErrID_Fatal + allocate( p%WaveAcc(0:p%NStepWave, p%NNodes, 3), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for wave accelerations array.' + errStat = ErrID_Fatal RETURN END IF - m%F_AM_M = 0.0_ReKi - - ALLOCATE ( m%F_AM_MG(6,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_F_AM_MG array.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%F_AM_MG = 0.0_ReKi - - ALLOCATE ( m%dragConst( NNodes ), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for the drag constants.' - ErrStat = ErrID_Fatal - RETURN - END IF - m%dragConst = 0.0 - - - ALLOCATE ( m%FV(3,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FV array.' - ErrStat = ErrID_Fatal + p%WaveAcc = InitInp%WaveAcc + + allocate( p%WaveDynP(0:p%NStepWave, p%NNodes), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for wave dynamic pressure array.' + errStat = ErrID_Fatal RETURN END IF - m%FV = 0.0_ReKi - - ALLOCATE ( m%FA(3,NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FA array.' - ErrStat = ErrID_Fatal + p%WaveDynP = InitInp%WaveDynP + + allocate( p%WaveTime(0:p%NStepWave), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for wave time array.' + errStat = ErrID_Fatal RETURN - END IF - m%FA = 0.0_ReKi + END IF + p%WaveTime = InitInp%WaveTime - ALLOCATE ( m%FDynP(NNodes), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for D_FDynP array.' - ErrStat = ErrID_Fatal + allocate( p%F_I_End( 0:p%NStepWave, 3, p%NJoints ), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for the inertial forces/moments array.' + errStat = ErrID_Fatal RETURN END IF - m%FDynP = 0.0_ReKi + p%F_I_End = 0.0 - END SUBROUTINE AllocateNodeLoadVariables !---------------------------------------------------------------------------------------------------------------------------------- !> This routine is called at the end of the simulation. -SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) !.................................................................................................................................. TYPE(Morison_InputType), INTENT(INOUT) :: u !< System inputs @@ -3155,15 +2332,15 @@ SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(Morison_OtherStateType), INTENT(INOUT) :: OtherState !< Other states TYPE(Morison_OutputType), INTENT(INOUT) :: y !< System outputs TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ! Place any last minute operations or calculations here: @@ -3175,33 +2352,33 @@ SUBROUTINE Morison_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Destroy the input data: - CALL Morison_DestroyInput( u, ErrStat, ErrMsg ) + CALL Morison_DestroyInput( u, errStat, errMsg ) ! Determine if we need to close the output file IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - CALL MrsnOut_CloseOutput( p, ErrStat, ErrMsg ) + CALL MrsnOut_CloseOutput( p, errStat, errMsg ) END IF ! Destroy the parameter data: - CALL Morison_DestroyParam( p, ErrStat, ErrMsg ) + CALL Morison_DestroyParam( p, errStat, errMsg ) ! Destroy the state data: - CALL Morison_DestroyContState( x, ErrStat, ErrMsg ) - CALL Morison_DestroyDiscState( xd, ErrStat, ErrMsg ) - CALL Morison_DestroyConstrState( z, ErrStat, ErrMsg ) - CALL Morison_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + CALL Morison_DestroyContState( x, errStat, errMsg ) + CALL Morison_DestroyDiscState( xd, errStat, errMsg ) + CALL Morison_DestroyConstrState( z, errStat, errMsg ) + CALL Morison_DestroyOtherState( OtherState, errStat, errMsg ) - CALL Morison_DestroyMisc( m, ErrStat, ErrMsg ) + CALL Morison_DestroyMisc( m, errStat, errMsg ) ! Destroy the output data: - CALL Morison_DestroyOutput( y, ErrStat, ErrMsg ) + CALL Morison_DestroyOutput( y, errStat, errMsg ) @@ -3210,7 +2387,7 @@ END SUBROUTINE Morison_End !---------------------------------------------------------------------------------------------------------------------------------- !> This is a loose coupling routine for solving constraint states, integrating continuous states, and updating discrete and other !! states. Continuous, constraint, discrete, and other states are updated to values at t + Interval. -SUBROUTINE Morison_UpdateStates( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +SUBROUTINE Morison_UpdateStates( Time, u, p, x, xd, z, OtherState, m, errStat, errMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds @@ -3225,18 +2402,18 @@ SUBROUTINE Morison_UpdateStates( Time, u, p, x, xd, z, OtherState, m, ErrStat, E TYPE(Morison_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at Time; !! Output: Other states at Time + Interval TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None ! Local variables - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + INTEGER(IntKi) :: errStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" @@ -3246,455 +2423,478 @@ END SUBROUTINE Morison_UpdateStates !---------------------------------------------------------------------------------------------------------------------------------- !> Routine for computing outputs, used in both loose and tight coupling. -SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) +SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) !.................................................................................................................................. - REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds - TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time - TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time - TYPE(Morison_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time - TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time - TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time - TYPE(Morison_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- - !! nectivity information does not have to be recalculated) - TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - REAL(ReKi) :: F_D(6), F_DP(6), D_F_I(3), kvec(3), v(3), vf(3), vrel(3), vmag - INTEGER :: I, J, K, nodeIndx - REAL(ReKi) :: elementWaterState - REAL(ReKi) :: AllOuts(MaxMrsnOutputs) ! TODO: think about adding to OtherState - REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node - !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node - REAL(ReKi) :: dragFactor ! The lumped drag factor - REAL(ReKi) :: AnProd ! Dot product of the directional area of the joint - REAL(ReKi) :: F_B(6) - REAL(ReKi) :: C(3,3) - REAL(ReKi) :: sgn - REAL(ReKi) :: D_AM_M(6,6) - REAL(ReKi) :: nodeInWater - REAL(ReKi) :: D_dragConst ! The distributed drag factor - - - TYPE(Morison_MemberType) :: mem ! the current member - INTEGER :: N - REAL(ReKi) :: dl - REAL(ReKi) :: vec(3) - REAL(ReKi) :: phi ! member tilt angle - REAL(ReKi) :: beta ! member tilt heading - REAL(ReKi) :: cosPhi - REAL(ReKi) :: sinPhi - REAL(ReKi) :: tanPhi - REAL(ReKi) :: sinBeta - REAL(ReKi) :: cosBeta - REAL(ReKi) :: z1 - REAL(ReKi) :: z2 - REAL(ReKi) :: r1 - REAL(ReKi) :: r2 - REAL(ReKi) :: m ! shorthand for taper including marine growth of segment i - REAL(ReKi) :: Rmid - REAL(ReKi) :: RmidMG - REAL(ReKi) :: Rmidin - REAL(ReKi) :: Lmid - REAL(ReKi) :: Imat - REAL(ReKi) :: Fl ! various element axial force - REAL(ReKi) :: Fr ! various element radial force - REAL(ReKi) :: M ! various element radial moment - REAL(ReKi) :: h0 ! distances along cylinder centerline from point 1 to the waterplane - REAL(ReKi) :: rh ! radius of cylinder at point where its centerline crosses the waterplane - REAL(ReKi) :: l1 ! distance from cone end to bottom node - REAL(ReKi) :: Vs ! segment submerged volume - REAL(ReKi) :: a0 ! waterplane ellipse shape - REAL(ReKi) :: b0 - REAL(ReKi) :: cr ! centroid of segment submerged volume relative to its lower node - REAL(ReKi) :: cl - REAL(ReKi) :: cx - REAL(ReKi) :: cz - REAL(ReKi) :: pwr ! exponent for buoyancy node distribution smoothing - REAL(ReKi) :: alpha ! final load distribution factor for element - REAL(ReKi) :: Fb !buoyant force - REAL(ReKi) :: Fr !radial component of buoyant force - REAL(ReKi) :: Fl !axial component of buoyant force - REAL(ReKi) :: M !moment induced about the center of the cylinder's bottom face - REAL(ReKi) :: BuoyF(3) ! buoyancy force vector aligned with an element - REAL(ReKi) :: BuoyM(3) ! buoyancy moment vector aligned with an element - - - - - - ! Initialize ErrStat - - ErrStat = ErrID_None - ErrMsg = "" - - - ! Compute outputs here: - - ! We need to attach the distributed drag force (D_F_D), distributed inertial force (D_F_I), and distributed dynamic pressure force (D_F_DP) to the Misc type so that we don't need to - ! allocate their data storage at each time step! If we could make them static local variables (like in C) then we could avoid adding them to the OtherState datatype. - ! The same is true for the lumped drag (L_F_D) and the lumped dynamic pressure (L_F_DP) - - DO J = 1, y%Mesh%Nnodes - - ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers - nodeIndx = p%distribToNodeIndx(J) - - ! Determine in or out of water status for the element which this node is a part of. - ! NOTE: This will find the closest WaveTime index (wvIndx) which is has waveTime(wvIndx) > = Time. If WaveDT = DT then waveTime(wvIndx) will equal Time - ! For WaveMod = 6 or WaveMod = 5 WaveDT must equal DT for the returned value of elementWaterState to be meaningful, for other WaveMod, - ! elementWaterState is the same for all time for a given node, J. - elementWaterState = REAL( InterpWrappedStpInt( REAL(Time, SiKi), p%WaveTime(:), p%elementWaterState(:,J), m%LastIndWave, p%NStepWave + 1 ), ReKi ) - - - ! Determine the dynamic pressure at the marker - m%D_FDynP(J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveDynP(:,nodeIndx), & - m%LastIndWave, p%NStepWave + 1 ) - - - DO I=1,3 - ! Determine the fluid acceleration and velocity at the marker - m%D_FA(I,J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveAcc(:,nodeIndx,I), & - m%LastIndWave, p%NStepWave + 1 ) - m%D_FV(I,J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveVel(:,nodeIndx,I), & - m%LastIndWave, p%NStepWave + 1 ) - - vrel(I) = m%D_FV(I,J) - u%DistribMesh%TranslationVel(I,J) - - m%D_F_I(I,J) = elementWaterState * InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%D_F_I(:,I,J), & - m%LastIndWave, p%NStepWave + 1 ) - END DO - - ! (k x vrel x k) - kvec = p%Nodes(nodeIndx)%R_LToG(:,3) - v = vrel - Dot_Product(kvec,vrel)*kvec - vmag = sqrt( v(1)*v(1) + v(2)*v(2) + v(3)*v(3) ) - - - ! Distributed added mass loads - ! need to multiply by elementInWater value to zero out loads when out of water - qdotdot2(1) = elementWaterState *u%DistribMesh%TranslationAcc(1,J) - qdotdot2(2) = elementWaterState *u%DistribMesh%TranslationAcc(2,J) - qdotdot2(3) = elementWaterState *u%DistribMesh%TranslationAcc(3,J) - - ! calculated the added mass forces (moments are zero) - m%D_F_AM_M(1:3,J) = -matmul( p%D_AM_M (:,:,J) , qdotdot2 ) !bjj: these lines take up a lot of time. are the matrices sparse? - - DO I=1,6 - IF (I < 4 ) THEN - ! We are now combining the dynamic pressure term into the inertia term - m%D_F_AM_MG(I,J) = -p%D_AM_MG(J)*u%DistribMesh%TranslationAcc(I,J) - m%D_F_AM_F(:,J) = -p%D_AM_F(J)*u%DistribMesh%TranslationAcc(I,J) !@mhall: should D_F_AM_F(:,J) be D_F_AM_F(I,J) ? - m%D_F_AM(I,J) = m%D_F_AM_M(I,J) + m%D_F_AM_MG(I,J) + m%D_F_AM_F(I,J) - m%D_F_D(I,J) = elementWaterState * vmag*v(I) * p%D_dragConst(J) - m%D_F_B(I,J) = elementWaterState * p%D_F_B(I,J) - y%DistribMesh%Force(I,J) = m%D_F_AM(I,J) + m%D_F_D(I,J) + m%D_F_I(I,J) + m%D_F_B(I,J) + p%D_F_MG(I,J) + p%D_F_BF(I,J) - ELSE - m%D_F_B(I,J) = elementWaterState * p%D_F_B(I,J) - y%DistribMesh%Moment(I-3,J) = m%D_F_B(I,J) + p%D_F_BF(I,J) - END IF - END DO ! DO I - - - - ENDDO - - - - - !!! below from GenerateLumpedLoads - need to make sure nothing is forgotten <<<<<< - IF (.NOT. node%PropPot ) THEN - k = sgn * node%R_LToG(:,3) - CALL LumpDynPressure( nodeIndx, node%JAxCp, k, node%R, node%tMG, NStepWave, WaveDynP, F_DP, ErrStat, ErrMsg) - - ! For buoyancy calculations we need to adjust the Z-location based on MSL2SWL. If MSL2SWL > 0 then SWL above MSL, and so we need to place the Z value at a deeper position. - ! SWL is at Z=0 for buoyancy calcs, but geometry was specified relative to MSL (MSL2SWL = 0) - ! CALL LumpBuoyancy( sgn, densWater, node%R, node%tMG, node%JointPos(3) - MSL2SWL, node%R_LToG, gravity, F_B ) - ELSE - ALLOCATE ( F_DP(0:NStepWave, 6), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating distributed dynamic pressure loads array.' - ErrStat = ErrID_Fatal - RETURN - END IF - F_DP = 0.0 - F_B = 0.0 - END IF - CALL LumpDragConst( densWater, node%Cd, node%R, node%tMG, dragConst ) - - -<<<<< most of above likely not used anymore!!! - + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(Morison_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(Morison_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None - ! Clear saved loads on each node since these are accumulated - !@mhall: Faster way to do this? Is this list right? - DO i = 1, p%NNodes - DO J=1,6 - F_D (i,J) = 0.0 - F_I (i,J) = 0.0 - F_B (i,J) = 0.0 - F_FB (i,J) = 0.0 - F_FBI (i,J) = 0.0 - F_MG (i,J) = 0.0 - F_MGI (i,J) = 0.0 - F_AM (i,J) = 0.0 - F_AM_M (i,J) = 0.0 - F_AM_MG(i,J) = 0.0 - F_AM_F (i,J) = 0.0 - END DO - END DO - - - - + ! Local variables + + INTEGER(IntKi) :: errStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None + + REAL(ReKi) :: F_D(6), F_DP(6), D_F_I(3), kvec(3), v(3), vf(3), vrel(3), vmag + INTEGER :: I, J, K, nodeIndx + REAL(ReKi) :: elementWaterState + REAL(ReKi) :: AllOuts(MaxMrsnOutputs) + REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node + !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node + REAL(ReKi) :: dragFactor ! The lumped drag factor + REAL(ReKi) :: AnProd ! Dot product of the directional area of the joint + REAL(ReKi) :: F_B(6) + REAL(ReKi) :: C(3,3) + REAL(ReKi) :: sgn + REAL(ReKi) :: D_AM_M(6,6) + REAL(ReKi) :: nodeInWater + REAL(ReKi) :: D_dragConst ! The distributed drag factor + + + TYPE(Morison_MemberType) :: mem ! the current member + INTEGER :: N ! Number of elements within a given member + REAL(ReKi) :: dl ! Element length within a given member, m + REAL(ReKi) :: vec(3) ! Vector pointing from a member's 1st node to its last node + REAL(ReKi) :: phi, phi1, phi2 ! member tilt angle + REAL(ReKi) :: beta ! member tilt heading + real(ReKi) :: vecLen ! distance between member end nodes (joints) [this should never be zero but we test for it just in case] + REAL(ReKi) :: cosPhi, cosPhi1, cosPhi2 + REAL(ReKi) :: sinPhi, sinPhi1, sinPhi2 + REAL(ReKi) :: tanPhi + REAL(ReKi) :: sinBeta, sinBeta1, sinBeta2 + REAL(ReKi) :: cosBeta, cosBeta1, cosBeta2 + real(ReKi) :: CMatrix(3,3), CTrans(3,3) ! Direction cosine matrix for element, and its transpose + REAL(ReKi) :: z1 + REAL(ReKi) :: z2 + REAL(ReKi) :: r1 + REAL(ReKi) :: r2 + real(ReKi) :: p1(3), p2(3) + REAL(ReKi) :: dRdl_mg ! shorthand for taper including marine growth of element i + REAL(ReKi) :: Rmid + REAL(ReKi) :: RmidMG + REAL(ReKi) :: Rmidin + REAL(ReKi) :: Lmid + real(ReKi) :: g ! gravity constant + REAL(ReKi) :: h0 ! distances along cylinder centerline from point 1 to the waterplane + real(ReKi) :: k_hat(3), k_hat1(3), k_hat2(3) ! Elemental unit vector pointing from 1st node to 2nd node of the element + REAL(ReKi) :: rh ! radius of cylinder at point where its centerline crosses the waterplane + REAL(ReKi) :: l1 ! distance from cone end to bottom node + REAL(ReKi) :: Vs ! segment submerged volume + REAL(ReKi) :: a0 ! waterplane ellipse shape + REAL(ReKi) :: b0 + REAL(ReKi) :: cr ! centroid of segment submerged volume relative to its lower node + REAL(ReKi) :: cl + REAL(ReKi) :: cx + REAL(ReKi) :: cz + REAL(ReKi) :: pwr ! exponent for buoyancy node distribution smoothing + REAL(ReKi) :: alpha ! final load distribution factor for element + REAL(ReKi) :: Fb !buoyant force + REAL(ReKi) :: Fr !radial component of buoyant force + REAL(ReKi) :: Fl !axial component of buoyant force + REAL(ReKi) :: Moment !moment induced about the center of the cylinder's bottom face + REAL(ReKi) :: BuoyF(3) ! buoyancy force vector aligned with an element + REAL(ReKi) :: BuoyM(3) ! buoyancy moment vector aligned with an element + integer(IntKi) :: im ! counter + real(ReKi) :: a_s1(3) + real(ReKi) :: alpha_s1(3) + real(ReKi) :: omega_s1(3) + real(ReKi) :: a_s2(3) + real(ReKi) :: alpha_s2(3) + real(ReKi) :: omega_s2(3) + real(ReKi) :: pos1(3), pos2(3) + real(ReKi) :: Imat(3,3) + real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), am(3,3), lstar + real(ReKi) :: C_1, C_2, a0b0, z1d, z2d + ! Initialize errStat + + errStat = ErrID_None + errMsg = "" + Imat = 0.0_ReKi + g = p%Gravity + + !=============================================================================================== + ! Calculate the fluid kinematics at all mesh nodes and store for use in the equations below + + do j = 1, p%NNodes + m%nodeInWater(j) = REAL( InterpWrappedStpInt( REAL(Time, SiKi), p%WaveTime(:), p%nodeInWater(:,j), m%LastIndWave, p%NStepWave + 1 ), ReKi ) + + ! Determine the dynamic pressure at the node + m%FDynP(j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveDynP(:,j), & + m%LastIndWave, p%NStepWave + 1 ) + do i=1,3 + ! Determine the fluid acceleration and velocity and relative structural velocity at the node + m%FA(i,j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveAcc(:,j,i), & + m%LastIndWave, p%NStepWave + 1 ) + + m%FV(i,j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveVel(:,j,i), & + m%LastIndWave, p%NStepWave + 1 ) + m%vrel(i,j) = m%FV(i,j) - u%Mesh%TranslationVel(i,j) + end do + end do ! ============================================================================================== ! Calculate instantaneous loads on each member except for the hydrodynamic loads on member ends. ! This covers aspects of the load calculations previously in CreateDistributedMesh. - + ! Zero out previous time-steps loads (these are loads which are computed at the member-level and summed onto a node, + ! so they need to be zeroed out before the summations happen) + m%F_WMG = 0.0_ReKi + m%F_IMG = 0.0_ReKi + m%F_If = 0.0_ReKi + m%F_D = 0.0_ReKi + m%F_A = 0.0_ReKi + m%F_I = 0.0_ReKi + m%F_B_End = 0.0_ReKi + ! Loop through each member - DO im = 1, p%NMembers - - N = m%Members(im)%NElements - - mem = m%Members(im) !@mhall: does this have much overhead? - - - ! calculate isntantaneous incline angle and heading, and related trig values - vec = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) - u%Mesh%TranslationDisp(:, mem%NodeIndx(1 )) - - phi = arccos(vec(3)/SQRT(Dot_Product(vec,vec))) ! incline angle - beta = arctan2(vec(2), vec(1)) ! heading of incline - - sinPhi = sin(phi) - cosPhi = cos(phi) - tanPhi = tan(phi) - - sinBeta = sin(beta) - cosBeta = cos(beta) - - + DO im = 1, p%NMembers + N = p%Members(im)%NElements + mem = p%Members(im) !@mhall: does this have much overhead? + DO i =1,N ! loop through member elements - ! save some commonly used variables - - dl = mem%dl - - z1 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i )) ! get node z locations from input mesh - z2 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i+1)) - r1 = m%Members(im)%RMG(i ) - r2 = m%Members(im)%RMG(i+1) + ! calculate isntantaneous incline angle and heading, and related trig values + ! the first and last NodeIndx values point to the corresponding Joint nodes idices which are at the start of the Mesh + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i)) + u%Mesh%Position(:, mem%NodeIndx(i)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i+1)) + u%Mesh%Position(:, mem%NodeIndx(i+1)) - m = mem%m_mg(i) - - ! should i_floor theshold be applied to below calculations to avoid wasting time on computing zero-valued things? <<<<< - ! should lumped half-element coefficients get combined at initialization? <<< - - ! ------------------ marine growth -------------------- - - ! lower node - m%F_MG(mem%NodeIndx(i ), 3) = m%F_MG(mem%NodeIndx(i ), 3) + mem%m_mg_l(i)*g ! weight force - m%F_MG(mem%NodeIndx(i ), 4) = m%F_MG(mem%NodeIndx(i ), 4) - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force - m%F_MG(mem%NodeIndx(i ), 5) = m%F_MG(mem%NodeIndx(i ), 5) + mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force - ! upper node - m%F_MG(mem%NodeIndx(i+1), 3) = m%F_MG(mem%NodeIndx(i+1), 3) + mem%m_mg_u(i)*g ! weight force - m%F_MG(mem%NodeIndx(i+1), 4) = m%F_MG(mem%NodeIndx(i+1), 4) - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force - m%F_MG(mem%NodeIndx(i+1), 5) = m%F_MG(mem%NodeIndx(i+1), 5) + mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force - - ! lower node - Imat = diag(mem%I_rmg_l(i), mem%I_rmg_l(i), mem%I_lmg_l(i)) - m%F_MGI(mem%NodeIndx(i ), 1:3) = m%F_MGI(mem%NodeIndx(i ), 1:3) - a_struct * mem%m_mg_l(i) - m%F_MGI(mem%NodeIndx(i ), 4:6) = m%F_MGI(mem%NodeIndx(i ), 4:6) - cross (a_struct * mem%m_mg_l(i), mem%h_cmg_l(i) * mem%k) + C * Imat * Ctrans - ! upper node - Imat = diag(mem%I_rmg_u(i), mem%I_rmg_u(i), mem%I_lmg_u(i)) - m%F_MGI(mem%NodeIndx(i+1), 1:3) = m%F_MGI(mem%NodeIndx(i+1), 1:3) - a_struct * mem%m_mg_u(i) - m%F_MGI(mem%NodeIndx(i+1), 4:6) = m%F_MGI(mem%NodeIndx(i+1), 4:6) - cross (a_struct * mem%m_mg_u(i), mem%h_cmg_u(i) * mem%k) + C * Imat * Ctrans - - - ! ------------------ flooded ballast inertia --------------------- - ! lower node - Imat = diag(mem%I_rfb_l(i), mem%I_rfb_l(i), mem%I_lfb_l(i)) - m%F_FBI(mem%NodeIndx(i ), 1:3) = m%F_FBI(mem%NodeIndx(i ), 1:3) - a_struct * mem%m_fb_l(i) - m%F_FBI(mem%NodeIndx(i ), 4:6) = m%F_FBI(mem%NodeIndx(i ), 4:6) - cross (a_struct * mem%m_fb_l(i), mem%h_cfb_l(i) * mem%k) + C * Imat * Ctrans - ! upper node - Imat = diag(mem%I_rfb_u(i), mem%I_rfb_u(i), mem%I_lfb_u(i)) - m%F_FBI(mem%NodeIndx(i+1), 1:3) = m%F_FBI(mem%NodeIndx(i+1), 1:3) - a_struct * mem%m_fb_u(i) - m%F_FBI(mem%NodeIndx(i+1), 4:6) = m%F_FBI(mem%NodeIndx(i+1), 4:6) - cross (a_struct * mem%m_fb_u(i), mem%h_cfb_u(i) * mem%k) + C * Imat * Ctrans - - - ! ------------------ flooded ballast weight --------------------- - - ! fully filled elements - if (floodstatus(i) == 1) then - - ! forces and moment in tilted coordinates about node i - Fl = mem%Cfl_fb(i)*cosPhi - Fr = mem%Cfr_fb(i)*sinPhi - M = mem%CM0_fb(i)*sinPhi - Fr(i)*alpha_fb_star(i)*dl - - ! calculate full vector and distribute to nodes - DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, (1-mem%alpha_fb_star(i)), m%F_FB(mem%NodeIndx(i), :), m%F_FB(mem%NodeIndx(i+1), :)) - - - ! partially filled element - else if (floodstatus(i) == 2) then - - ! forces and moment in tilted coordinates about node i - Fl = mem%Cfl_fb(i)*cosPhi - Fr = mem%Cfr_fb(i)*sinPhi - M = mem%CM0_fb(i)*sinPhi + Fr(i)*(1 - alpha_fb_star(i))*dl - - ! calculate full vector and distribute to nodes - DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, mem%alpha_fb_star(i), m%F_FB(mem%NodeIndx(i), :), m%F_FB(mem%NodeIndx(i-1), :)) - + call GetOrientationAngles( pos1, pos2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat2, errMsg2 ) + call Morison_DirCosMtrx( pos1, pos2, CMatrix ) + CTrans = transpose(CMatrix) + ! save some commonly used variables + dl = mem%dl + z1 = pos1(3) ! get node z locations from input mesh + z2 = pos2(3) + r1 = mem%RMG(i ) ! outer radius element nodes including marine growth + r2 = mem%RMG(i+1) + dRdl_mg = mem%dRdl_mg(i) ! mass of element including marine growth + a_s1 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i )) + alpha_s1= u%Mesh%RotationAcc (:, mem%NodeIndx(i )) + omega_s1= u%Mesh%RotationVel (:, mem%NodeIndx(i )) + a_s2 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i+1)) + alpha_s2= u%Mesh%RotationAcc (:, mem%NodeIndx(i+1)) + omega_s2= u%Mesh%RotationVel (:, mem%NodeIndx(i+1)) - ! no load for unflooded element or element fully below seabed - - end if - - - ! ------------------- buoyancy loads... ------------------------ - - if (z1 <= 0) then ! if segment is at least partially submerged ... + if ( .not. mem%PropPot ) then ! Member is NOT modeled with Potential Flow Theory + + ! should i_floor theshold be applied to below calculations to avoid wasting time on computing zero-valued things? <<<<< + ! should lumped half-element coefficients get combined at initialization? <<< + + ! ------------------ marine growth: Sides: Section 4.1.2 -------------------- + + ! lower node + m%F_WMG(3, mem%NodeIndx(i )) = m%F_WMG(3, mem%NodeIndx(i )) - mem%m_mg_l(i)*g ! weight force : Note: this is a constant + m%F_WMG(4, mem%NodeIndx(i )) = m%F_WMG(4, mem%NodeIndx(i )) - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force + m%F_WMG(5, mem%NodeIndx(i )) = m%F_WMG(5, mem%NodeIndx(i )) + mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force + ! upper node + m%F_WMG(3, mem%NodeIndx(i+1)) = m%F_WMG(3, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g ! weight force : Note: this is a constant + m%F_WMG(4, mem%NodeIndx(i+1)) = m%F_WMG(4, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force + m%F_WMG(5, mem%NodeIndx(i+1)) = m%F_WMG(5, mem%NodeIndx(i+1)) + mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force + + + ! lower node + Ioffset = mem%h_cmg_l(i)*mem%h_cmg_l(i)*mem%m_mg_l(i) + Imat(1,1) = mem%I_rmg_l(i) - Ioffset + Imat(2,2) = mem%I_rmg_l(i) - Ioffset + Imat(3,3) = mem%I_lmg_l(i) - Ioffset + Imat = matmul(matmul(CMatrix, Imat), CTrans) + iArm = mem%h_cmg_l(i) * k_hat + iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_mg_l(i) + m%F_IMG(1:3, mem%NodeIndx(i )) = m%F_IMG(1:3, mem%NodeIndx(i )) + iTerm + m%F_IMG(4:6, mem%NodeIndx(i )) = m%F_IMG(4:6, mem%NodeIndx(i )) & + - cross_product(a_s1 * mem%m_mg_l(i), mem%h_cmg_l(i) * k_hat) & + + matmul(Imat, alpha_s1) & + - cross_product(omega_s1,matmul(Imat,omega_s1)) + ! upper node + Ioffset = mem%h_cmg_u(i)*mem%h_cmg_u(i)*mem%m_mg_u(i) + Imat(1,1) = mem%I_rmg_u(i) - Ioffset + Imat(2,2) = mem%I_rmg_u(i) - Ioffset + Imat(3,3) = mem%I_lmg_u(i) - Ioffset + Imat = matmul(matmul(CMatrix, Imat), CTrans) + iArm = mem%h_cmg_u(i) * k_hat + iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_mg_u(i) + m%F_IMG(1:3, mem%NodeIndx(i+1)) = m%F_IMG(1:3, mem%NodeIndx(i+1)) + iTerm + m%F_IMG(4:6, mem%NodeIndx(i+1)) = m%F_IMG(4:6, mem%NodeIndx(i+1)) & + - cross_product(a_s2 * mem%m_mg_u(i), mem%h_cmg_u(i) * k_hat) & + + matmul(Imat, alpha_s2) & + - cross_product(omega_s2,matmul(Imat,omega_s2)) + + ! ------------------- buoyancy loads: sides: Sections 3.1 and 3.2 ------------------------ + +!TODO: What about elements which are buried in the seabed? This doesn't seem to be tested for + if (z1 <= 0) then ! if segment is at least partially submerged ... - if (z1*z2 <= 0) then ! special calculation if the slice is partially submerged + if (z1*z2 <= 0) then ! special calculation if the slice is partially submerged - h0 = -z1/cosPhi ! distances along element centerline from point 1 to the waterplane - rh = r1 + h0*m ! radius of element at point where its centerline crosses the waterplane + h0 = -z1/cosPhi ! distances along element centerline from point 1 to the waterplane - if (abs(m) < 0.0001) then ! untapered cylinder case + + if (abs(dRdl_mg) < 0.0001) then ! untapered cylinder case - Vs = Pi*r1*r1*h0 ! volume of total submerged portion + Vs = Pi*r1*r1*h0 ! volume of total submerged portion - cr = 0.25*r1*r1*tanPhi/h0 - cl = 0.5*h0 + 0.125*r1*r1*tanPhi*tanPhi/h0 + cr = 0.25*r1*r1*tanPhi/h0 + cl = 0.5*h0 + 0.125*r1*r1*tanPhi*tanPhi/h0 - cx = cr*cosPhi + cl*sinPhi - cz = cl*cosPhi - cr*sinPhi + cx = cr*cosPhi + cl*sinPhi - !alpha0 = 0.5*h0/dl ! force distribution between end nodes - - else ! inclined tapered cylinder case (note I've renamed r0 to rh here!!) - - l1 = r1/m ! distance from cone end to bottom node - - ! waterplane ellipse shape - b0 = rh/sqrt(1 - m^2 * tanPhi**2) - a0 = rh/((1 - m^2*tanPhi**2)*cosPhi) ! simplified from what's in ConicalCalcs.ipynb - - ! segment submerged volume - Vs = pi*(a0*b0*rh*cosPhi - l1^3*m^3)/(3*m) + !alpha0 = 0.5*h0/dl ! force distribution between end nodes - ! centroid of segment submerged volume (relative to bottom node) - cx = -0.25*(3*a0*b0*rh*rh*(m**2 + 1)*cosPhi + 3.0*l1**4*m**4*(m**2*tanPhi**2 - 1) + 4*l1*m*(m**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - 1.0*l1**3*m**3))*sin(phi)/(m*(m**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - l1**3*m**3)) - cz = 0.25*(-4.0*a0*b0*l1*m*rh*cosPhi + 3.0*a0*b0*rh*rh*cosPhi + 1.0*l1**4*m**4)*cosPhi/(m*(a0*b0*rh*cosPhi - l1**3*m**3)) - - !alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) ! this can be precomputed + else ! inclined tapered cylinder case (note I've renamed r0 to rh here!!) + !=================== + !Per plan equations + ! NOTE: Variable changes of Plan vs Code + !--------------------------------------------------- + ! V Vs + ! a_h a0 + ! b_h b0 + ! x_c cx + ! h h0 + ! r1 r_MG,i + ! r_c cr + ! h_c cl + ! NOTE: a0 and b0 always appear as a0b0, never separately. + rh = r1 + h0*dRdl_mg ! radius of element at point where its centerline crosses the waterplane + C_1 = 1.0_ReKi - dRdl_mg**2 * tanPhi**2 + ! waterplane ellipse shape + b0 = rh/sqrt(C_1) + a0 = rh/((C_1)*cosPhi) ! simplified from what's in ConicalCalcs.ipynb + a0b0 = a0*b0 + C_2 = a0b0*rh*cosPhi - r1**3 + cl = (0.75*a0b0*r1**2*cosPhi + 0.75*r1**4*C_1 + r1*C_1*C_2) / (dRdl_mg*C_1*C_2) + cr = (0.75*a0b0*dRdl_mg*rh**2*sinPhi)/(C_1*C_2) + cx = cr*cosPhi + cl*sinPhi + Vs = pi*(a0b0*rh*cosPhi - r1**3)/(3*dRdl_mg) + + ! End per plan equations + !=================== + + !rh = r1 + h0*dRdl_mg ! radius of element at point where its centerline crosses the waterplane + !l1 = r1/dRdl_mg ! distance from cone end to bottom node + ! + !! waterplane ellipse shape + !b0 = rh/sqrt(1 - dRdl_mg**2 * tanPhi**2) + !a0 = rh/((1 - dRdl_mg**2*tanPhi**2)*cosPhi) ! simplified from what's in ConicalCalcs.ipynb + ! + !! segment submerged volume + !!Vs = pi*(a0*b0*rh*cosPhi - l1**3*dRdl_mg**3)/(3*dRdl_mg) !Original code + !Vs = pi*(a0*b0*rh*cosPhi - r1**3)/(3*dRdl_mg) !Plan doc + ! + !! centroid of segment submerged volume (relative to bottom node) + !cx = -0.25*(3*a0*b0*rh*rh*(dRdl_mg**2 + 1)*cosPhi + 3.0*l1**4*dRdl_mg**4*(dRdl_mg**2*tanPhi**2 - 1) + 4*l1*dRdl_mg*(dRdl_mg**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - 1.0*l1**3*dRdl_mg**3))*sin(phi)/(dRdl_mg*(dRdl_mg**2*tanPhi**2 - 1)*(a0*b0*rh*cosPhi - l1**3*dRdl_mg**3)) + + !alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) ! this can be precomputed - end if - - pwr = 1 - alpha = (1-mem%alpha(i))*z1**pwr/(-mem%alpha(i)*z2**pwr + (1-mem%alpha(i))*z1**pwr) - - Fb = Vs*rho*g !buoyant force - Fr = -Fb*sinPhi !radial component of buoyant force - Fl = Fb*cosPhi !axial component of buoyant force - M = -Fb*cx !moment induced about the center of the cylinder's bottom face - - ! calculate (imaginary) bottom plate forces/moment to subtract from displacement-based values - Fl = Fl + rho*g*z1* Pi *r1*r1 - M0 = M + rho*g* sinPhi * Pi/4*r1**4 + end if + pwr = 1 + alpha = (1-mem%alpha(i))*z1**pwr/(-mem%alpha(i)*z2**pwr + (1-mem%alpha(i))*z1**pwr) - ! reduce taper-based moment to remove (not double count) radial force distribution to each node - M = M0 - Fr*alpha*dl + Fr*dl + Fb = Vs*p%WtrDens*g !buoyant force + Fr = -Fb*sinPhi !radial component of buoyant force + Fl = Fb*cosPhi !axial component of buoyant force + Moment = -Fb*cx !This was matt's code !moment induced about the center of the cylinder's bottom face - BuoyF(1) = Fr*cosBeta - BuoyF(2) = Fr*sinBeta - BuoyF(3) = Fl - BuoyM(1) = -M*sinBeta - BuoyM(2) = M*cosBeta - BuoyM(3) = 0 + ! calculate (imaginary) bottom plate forces/moment to subtract from displacement-based values + Fl = Fl + p%WtrDens*g*z1* Pi *r1*r1 + Moment = Moment + p%WtrDens*g* sinPhi * Pi/4*r1**4 - ! distribute force and moment to each adjacent node of the element BELOW THIS ONE - m%F_B(mem%NodeIndx(i-1), 1:3) = MatMul(C, BuoyF )*(1-alpha) - m%F_B(mem%NodeIndx(i-1), 4:6) = Matmul(C, BuoyMT)*(1-alpha) - - m%F_B(mem%NodeIndx(i ), 1:3) = MatMul(C, BuoyF )*alpha - m%F_B(mem%NodeIndx(i ), 4:6) = Matmul(C, BuoyMT)*alpha + ! reduce taper-based moment to remove (not double count) radial force distribution to each node + Moment = Moment + Fr*(1.0_ReKi-alpha)*dl + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i)), m%F_B(:, mem%NodeIndx(i-1))) - else ! normal, fully submerged case - - Fl = -2.0*Pi*m*rho*g*dl*( z1*r1 + 0.5*(z1*m + r1*cosPhi)*dl + 1/3*m*cosPhi*dl*dl ) ! from CylinderCalculationsR1.ipynb + else ! normal, fully submerged case - Fr = -Pi*rho*g*dl*(r1*r1 + m*r1*dl + 1/3*m**2*dl**2)*sinPhi ! from CylinderCalculationsR1.ipynb - - M0 = -Pi*dl*g*rho*(3*dl**3*m**4 + 3*dl**3*m**2 + 12*dl**2*m**3*r1 + 8*dl**2*m*r1 + 18*dl*m**2*r1*r1 + 6*dl*r1*r1 + 12*m*r1**3)*sin(phi)/12 ! latest from CylinderCalculationsR1.ipynb - - ! precomputed as mem%alpha(i) ... alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) + Fl = -2.0*Pi*dRdl_mg*p%WtrDens*g*dl*( z1*r1 + 0.5*(z1*dRdl_mg + r1*cosPhi)*dl + 1/3*dRdl_mg*cosPhi*dl*dl ) ! from CylinderCalculationsR1.ipynb - z1d = -min(0,z1) - z2d = -min(0,z2) + Fr = -Pi*p%WtrDens*g*dl*(r1*r1 + dRdl_mg*r1*dl + 1/3*dRdl_mg**2*dl**2)*sinPhi ! from CylinderCalculationsR1.ipynb + Moment = -Pi*dl*g*p%WtrDens*(3*dl**3*dRdl_mg**4 + 3*dl**3*dRdl_mg**2 + 12*dl**2*dRdl_mg**3*r1 + 8*dl**2*dRdl_mg*r1 + 18*dl*dRdl_mg**2*r1*r1 + 6*dl*r1*r1 + 12*dRdl_mg*r1**3)*sinPhi/12 ! latest from CylinderCalculationsR1.ipynb + + ! precomputed as mem%alpha(i) ... alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) + !TODO: Review the below alpha eqn, GJH + z1d = -min(0.0_ReKi,z1) + z2d = -min(0.0_ReKi,z2) - alpha = mem%alpha(i)*z2d/(mem%alpha(i)*z2d+(1-mem%alpha(i))*z1d) + alpha = mem%alpha(i)*z2d/(mem%alpha(i)*z2d+(1-mem%alpha(i))*z1d) - ! reduce moment to remove (not double count) radial force distribution to each node - M = M0 - Fr*alpha*dl - - BuoyF(1) = Fr*cosBeta - BuoyF(2) = Fr*sinBeta - BuoyF(3) = Fl - BuoyM(1) = -M*sinBeta - BuoyM(2) = M*cosBeta - BuoyM(3) = 0 - - ! distribute force and moment to each adjacent node - m%F_B(mem%NodeIndx(i ), 1:3) = MatMul(C, BuoyF)*(1-alpha) - m%F_B(mem%NodeIndx(i ), 4:6) = Matmul(C, BuoyM)*(1-alpha) - - m%F_B(mem%NodeIndx(i+1), 1:3) = MatMul(C, BuoyF)*alpha - m%F_B(mem%NodeIndx(i+1), 4:6) = Matmul(C, BuoyM)*alpha - - end if ! submergence cases + ! reduce moment to remove (not double count) radial force distribution to each node + Moment = Moment - Fr*alpha*dl + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i+1)), m%F_B(:, mem%NodeIndx(i))) + end if ! submergence cases - end if ! element at least partially submerged - + end if ! element at least partially submerged + + end if ! NOT Modeled with Potential flow theory + + ! ------------------ flooded ballast inertia: sides: Section 6.1.1 : Always compute regardless of PropPot setting --------------------- + + ! lower node + Ioffset = mem%h_cfb_l(i)*mem%h_cfb_l(i)*mem%m_fb_l(i) + Imat(1,1) = mem%I_rfb_l(i) - Ioffset + Imat(2,2) = mem%I_rfb_l(i) - Ioffset + Imat(3,3) = mem%I_lfb_l(i) - Ioffset + iArm = mem%h_cfb_l(i) * k_hat + iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_fb_l(i) + m%F_If(1:3, mem%NodeIndx(i )) = m%F_If(1:3, mem%NodeIndx(i )) + iTerm + m%F_If(4:6, mem%NodeIndx(i )) = m%F_If(4:6, mem%NodeIndx(i )) & + - cross_product(a_s1 * mem%m_fb_l(i), mem%h_cfb_l(i) * k_hat) & + + matmul(Imat, alpha_s1) & + - cross_product(omega_s1,matmul(Imat,omega_s1)) + ! upper node + Ioffset = mem%h_cfb_u(i)*mem%h_cfb_u(i)*mem%m_fb_u(i) + Imat(1,1) = mem%I_rfb_u(i) - Ioffset + Imat(2,2) = mem%I_rfb_u(i) - Ioffset + Imat(3,3) = mem%I_lfb_u(i) - Ioffset + iArm = mem%h_cfb_u(i) * k_hat + iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_fb_u(i) + m%F_If(1:3, mem%NodeIndx(i+1)) = m%F_If(1:3, mem%NodeIndx(i+1)) + iTerm + m%F_If(4:6, mem%NodeIndx(i+1)) = m%F_If(4:6, mem%NodeIndx(i+1)) & + - cross_product(a_s2 * mem%m_fb_u(i), mem%h_cfb_u(i) * k_hat) & + + matmul(Imat, alpha_s2) & + - cross_product(omega_s2,matmul(Imat,omega_s2)) + + ! ------------------ flooded ballast weight : sides : Section 5.1.2 & 5.2.2 : Always compute regardless of PropPot setting --------------------- + + ! fully filled elements + if (mem%floodstatus(i) == 1) then + + ! Compute lstar + if ( mem%memfloodstatus == 1) then + ! partially flooded MEMBER + lstar = dl*(i-1) - mem%l_fill + elseif (cosPhi >= 0.0 ) then + lstar = dl*(i-N-1) + else + lstar = dl*(i-1) + end if + Fl =TwoPi * mem%dRdl_in(i) * mem%FillDens * p%gravity * dl *( -( mem%Rin(i) + 0.5* mem%dRdl_in(i)*dl )*mem%z_overfill + & + ( lstar*mem%Rin(i) + 0.5*(lstar*mem%dRdl_in(i) + mem%Rin(i) )*dl + 1/3* mem%dRdl_in(i)*dl**2 )*cosphi ) + + ! forces and moment in tilted coordinates about node i + !Fl = mem%Cfl_fb(i)*cosPhi + Fr = mem%Cfr_fb(i)*sinPhi + Moment = mem%CM0_fb(i)*sinPhi - Fr*mem%alpha_fb_star(i)*dl + + ! calculate full vector and distribute to nodes + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, (1-mem%alpha_fb_star(i)), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i+1))) + + + ! partially filled element + else if (mem%floodstatus(i) == 2) then + + ! forces and moment in tilted coordinates about node i + Fl = mem%Cfl_fb(i)*cosPhi + Fr = mem%Cfr_fb(i)*sinPhi + Moment = mem%CM0_fb(i)*sinPhi + Fr*(1 - mem%alpha_fb_star(i))*dl + + ! calculate full vector and distribute to nodes + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, mem%alpha_fb_star(i), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i-1))) + + + ! no load for unflooded element or element fully below seabed + + end if + + + + END DO ! i =1,N ! loop through member elements + ! External Hydrodynamic Side Loads + DO i =1,N+1 ! loop through member elements + h_c = 0.0_ReKi !TODO: Determine actual h_c based on water level, etc. GJH 3/23/20 see table in Section 7.1.1 + if (i == 1) then + dRdl_p = abs(mem%dRdl_mg(i)) + dRdl_pp = mem%dRdl_mg(i) + elseif ( i > 1 .and. i < (N+1)) then + dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) + dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) + else + dRdl_p = abs(mem%dRdl_mg(N)) + dRdl_pp = mem%dRdl_mg(N) + end if + + ! ------------------- hydrodynamic drag loads: sides: Section 7.1.2 ------------------------ + vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) + f_hydro = mem%Cd(i)*p%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & + 0.5*mem%AxCd(i)*p%WtrDens*pi*mem%RMG(i)*dRdl_p * matmul( dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )*mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) + + if ( .not. mem%PropPot ) then + ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ + Am = mem%Ca(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt + f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) + + ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ + f_hydro=mem%Ca(i)*mem%Cp(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) + end if + END DO ! i =1,N+1 ! loop through member elements + + ! Any end plate loads that are modeled on a per-member basis ! reassign convenience variables to correspond to member ends - z1 = u%Mesh%TranslationDisp(3, m%Members(im)%NodeIndx(1 )) - z2 = u%Mesh%TranslationDisp(3, m%Members(im)%NodeIndx(N+1)) + + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(1)) + u%Mesh%Position(:, mem%NodeIndx(1)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(2)) + u%Mesh%Position(:, mem%NodeIndx(2)) + z1 = pos1(3) + + call GetOrientationAngles( pos1, pos2, phi1, sinPhi1, cosPhi1, tanPhi, sinBeta1, cosBeta1, k_hat1, errStat2, errMsg2 ) + if ( N == 1 ) then + + sinPhi2 = sinPhi1 + cosPhi2 = cosPhi1 + sinBeta2 = sinBeta1 + cosBeta2 = cosBeta1 + z2 = pos2(3) + else + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N)) + u%Mesh%Position(:, mem%NodeIndx(N)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) + u%Mesh%Position(:, mem%NodeIndx(N+1)) + z2 = pos2(3) + call GetOrientationAngles( pos1, pos2, phi2, sinPhi2, cosPhi2, tanPhi, sinBeta2, cosBeta2, k_hat2, errStat2, errMsg2 ) + end if + +! TODO: Do the equations below still work if z1 > z2 ? + !TODO, should not have to test seabed crossing in time-marching loop ! Water ballast buoyancy - if (z1 >= -wtrDpth) then ! end load only if end is above seabed + if (z1 >= -p%WtrDpth) then ! end load only if end is above seabed ! if member is fully flooded if (mem%z_overfill > 0) then - Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0)) - M = -mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi - AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB( 1,:)) + Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0.0_ReKi)) + Moment = mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) - Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0)) - M = mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi - AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB(N+1,:)) + Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) + Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) ! if member is partially flooded - else if (l_fill > 0) then - Fl = -mem%FillDens * g * pi *Rin(1)**2*l_fill*cosPhi - M = -mem%FillDens * g * pi *0.25*Rin(1)**4*sinPhi - AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, m%F_FB(1,:)) + else if (mem%l_fill > 0) then + Fl = -mem%FillDens * g * pi *mem%Rin(1)**2*mem%l_fill*cosPhi + Moment = mem%FillDens * g * pi *0.25*mem%Rin(1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) ! no load if member is not flooded at all end if @@ -3703,74 +2903,105 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! --- no inertia loads from water ballast modeled on ends - end do ! im - looping through members + ! --- external buoyancy loads: ends --- + +!TODO, should not have to test seabed crossing in time-marching loop + if ( .not. mem%PropPot ) then + if (z1 >= -p%WtrDpth) then ! NOTE: We could roll this into the section for Water ballast buoyancy to save the if-test + if (z2<= 0.0_ReKi) then + ! Compute loads on both ends + Fl = -p%WtrDens * g * pi *mem%RMG(1)**2*z1 + Moment = -p%WtrDens * g * pi *0.25*mem%RMG(1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_B_End(:, mem%NodeIndx(1))) + Fl = p%WtrDens * g * pi *mem%RMG(N+1)**2*z2 + Moment = p%WtrDens * g * pi *0.25*mem%RMG(N+1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_B_End(:, mem%NodeIndx(N+1))) + elseif ( z1< 0.0_ReKi ) then + ! Compute loads only on lower end + Fl = -p%WtrDens * g * pi *mem%RMG(1)**2*z1 + Moment = -p%WtrDens * g * pi *0.25*mem%RMG(1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_B_End(:, mem%NodeIndx(1))) + else + ! Entire member is above the still water line + end if + !TODO, should not have to test seabed crossing in time-marching loop + + elseif (z2 >-p%WtrDpth) then ! The member crosses the seabed line + ! Only compute the buoyancy contribution from the upper end + Fl = p%WtrDens * g * pi *mem%RMG(N+1)**2*z2 + Moment = p%WtrDens * g * pi *0.25*mem%RMG(N+1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_B_End(:, mem%NodeIndx(N+1))) + else + ! entire member is buried below the seabed + + end if + + end if ! PropPot + end do ! im - looping through members - !@mhall: hydrodynamic loads not yet implemented, below not yet adjusted + do j = 1, p%NNodes + ! Sum side load components onto output mesh + DO i=1,6 + IF (i < 4 ) THEN + y%Mesh%Force(I,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) + ELSE + y%Mesh%Moment(I-3,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) + END IF + END DO ! + end do + + ! --- Hydrodynamic drag loads: joints ! NOTE: All wave kinematics have already been zeroed out above the SWL or instantaneous wave height (for WaveStMod > 0), so loads derived from the kinematics will be correct ! without the use of a nodeInWater value, but other loads need to be multiplied by nodeInWater to zero them out above the SWL or instantaneous wave height. - DO J = 1, y%LumpedMesh%Nnodes + DO J = 1, p%NJoints ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers - nodeIndx = p%lumpedToNodeIndx(J) - nodeInWater = REAL( InterpWrappedStpInt( REAL(Time, SiKi), p%WaveTime(:), p%nodeInWater(:,nodeIndx), m%LastIndWave, p%NStepWave + 1 ), ReKi ) - ! Determine the dynamic pressure at the marker - m%L_FDynP(J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveDynP(:,nodeIndx), & - m%LastIndWave, p%NStepWave + 1 ) - - - DO I=1,3 - ! Determine the fluid acceleration and velocity at the marker - m%L_FA(I,J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveAcc(:,nodeIndx,I), & - m%LastIndWave, p%NStepWave + 1 ) - - m%L_FV(I,J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveVel(:,nodeIndx,I), & - m%LastIndWave, p%NStepWave + 1 ) - vrel(I) = m%L_FV(I,J) - u%LumpedMesh%TranslationVel(I,J) - END DO - - ! Compute the dot product of the relative velocity vector with the directional Area of the Joint - vmag = nodeInWater * ( vrel(1)*p%L_An(1,J) + vrel(2)*p%L_An(2,J) + vrel(3)*p%L_An(3,J) ) - AnProd = p%L_An(1,J)**2 + p%L_An(2,J)**2 + p%L_An(3,J)**2 - IF (EqualRealNos(AnProd, 0.0_ReKi)) THEN - dragFactor = 0.0 - ELSE - dragFactor = p%Nodes(nodeIndx)%JAxCd*p%WtrDens*abs(vmag)*vmag / ( 4.0_ReKi * AnProd ) - END IF + vmag = m%nodeInWater(j) * ( m%vrel(1,j)*p%An_End(1,J) + m%vrel(2,j)*p%An_End(2,J) + m%vrel(3,j)*p%An_End(3,J) ) + + !NOTE: The PropPot values are only for members, and when the p%AM_End, p%DP_Const_End, p%Mass_MG_End, and p%I_MG_End are computed at init, + ! contributions to these values are added only if the member connecting to the joint is NOT modeled with potential flow theory + ! However, the p%An_End term used data from ALL members attached to a node, regardless of the PropPot setting. - ! Lumped added mass loads - qdotdot = reshape((/u%LumpedMesh%TranslationAcc(:,J),u%LumpedMesh%RotationAcc(:,J)/),(/6/)) - m%L_F_AM(:,J) = matmul( p%L_AM_M(:,:,J) , ( - qdotdot) ) + qdotdot = reshape((/u%Mesh%TranslationAcc(:,J),u%Mesh%RotationAcc(:,J)/),(/6/)) + m%F_A_End(:,J) = matmul( p%AM_End(:,:,J) , ( - qdotdot) ) DO I=1,3 - m%L_F_AM(I,J) = nodeInWater * m%L_F_AM(I,J) ! Note that the rotational components are zero because L_AM_M is populated with only the upper-left 3x3 + m%F_A_End(I,J) = m%nodeInWater(j) * m%F_A_End(I,J) ! Note that the rotational components are zero END DO + m%F_I_End(:,J) = p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j)) + + ! Marine growth inertia: ends: Section 4.2.2 + m%F_IMG_End(1:3,j) = -p%Mass_MG_End(j)*qdotdot(1:3) + m%F_IMG_End(4:6,j) = -matmul(p%I_MG_End(:,:,j),qdotdot(4:6)) - cross_product(u%Mesh%RotationVel(:,J),matmul(p%I_MG_End(:,:,j),u%Mesh%RotationVel(:,J))) + DO I=1,6 ! We are now combining the dynamic pressure term into the inertia term - m%L_F_I(I,J) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%L_F_I(:,I,J), & - m%LastIndWave, p%NStepWave + 1 ) + IF (I < 4 ) THEN - - m%L_F_D(I,J) = p%L_An(I,J)*dragFactor - m%L_F_B(I,J) = nodeInWater*p%L_F_B(I,J) - y%LumpedMesh%Force(I,J) = m%L_F_AM(I,J) + m%L_F_D(I,J) + m%L_F_B(I,J) + m%L_F_I(I,J) + p%L_F_BF(I,J) + + + m%F_D_End(i,j) = p%An_End(i,j)*p%DragConst_End(j)*abs(vmag)*vmag + !TODO: This needs to be reworked with new equations + !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) + !y%Mesh%Force(I,J) = m%F_A_End(I,J) + m%F_D_End(I,J) + m%F_B_End(I,J) + m%F_I_End(I,J) !+ m%F_BF_End(I,J) + y%Mesh%Force(i,j) = m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) ELSE - m%L_F_B(I,J) = nodeInWater*p%L_F_B(I,J) - y%LumpedMesh%Moment(I-3,J) = m%L_F_AM(I,J) + m%L_F_B(I,J) + p%L_F_BF(I,J) + !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) + !y%Mesh%Moment(I-3,J) = m%F_A_End(I,J) + m%F_B_End(I,J) ! + m%F_BF_End(I,J) + y%Mesh%Moment(i-3,j) = m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) END IF - - - END DO - ENDDO + END DO ! I=1,6 + ENDDO ! J = 1, p%NJoints ! OutSwtch determines whether or not to actually output results via the WriteOutput array ! 1 = Morison will generate an output file of its own. 2 = the caller will handle the outputs, but @@ -3780,7 +3011,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, IF ( p%OutSwtch > 0 ) THEN ! Map calculated results into the AllOuts Array - CALL MrsnOut_MapOutputs(Time, y, p, u, m, AllOuts, ErrStat, ErrMsg) + CALL MrsnOut_MapOutputs(Time, y, p, u, m, AllOuts, errStat, errMsg) ! Put the output data in the WriteOutput array @@ -3795,17 +3026,25 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Generate output into the output file IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - CALL MrsnOut_WriteOutputs( p%UnOutFile, Time, y, p, ErrStat, ErrMsg ) + CALL MrsnOut_WriteOutputs( p%UnOutFile, Time, y, p, errStat, errMsg ) END IF END IF END SUBROUTINE Morison_CalcOutput - +subroutine LumpDistrHydroLoads( f_hydro, k_hat, dl, h_c, lumpedLoad ) + real(ReKi), intent(in ) :: f_hydro(3) + real(ReKi), intent(in ) :: k_hat(3) + real(ReKi), intent(in ) :: dl + real(ReKi), intent(in ) :: h_c + real(ReKi), intent(inout) :: lumpedLoad(6) + lumpedLoad(1:3) = lumpedLoad(1:3) + f_hydro*dl + lumpedLoad(4:6) = lumpedLoad(4:6) + cross_product(k_hat*h_c, f_hydro)*dl +end subroutine LumpDistrHydroLoads ! Takes loads on node i in element tilted frame and converts to 6DOF loads at node i and adjacent node -SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, alpha, Fi, F2) +SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, alpha, F1, F2) REAL(ReKi), INTENT ( IN ) :: Fl ! (N) axial load about node i REAL(ReKi), INTENT ( IN ) :: Fr ! (N) radial load about node i in direction of tilt @@ -3816,23 +3055,23 @@ SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, a REAL(ReKi), INTENT ( IN ) :: cosBeta REAL(ReKi), INTENT ( IN ) :: alpha ! fraction of load staying with node i (1-alpha goes to other node) - REAL(ReKi), INTENT ( OUT ) :: Fi(6) ! (N, Nm) force/moment vector for node i + REAL(ReKi), INTENT ( OUT ) :: F1(6) ! (N, Nm) force/moment vector for node i REAL(ReKi), INTENT ( OUT ) :: F2(6) ! (N, Nm) force/moment vector for the other node (whether i+1, or i-1) - Fi(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - Fi(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - Fi(3) = (Fl*cosPhi + Fr*sinPhi)*alpha - Fi(4) = sinBeta * M *alpha - Fi(5) = cosBeta * M *alpha - Fi(6) = 0.0 + F1(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(3) = (Fl*cosPhi - Fr*sinPhi)*alpha + F1(4) = sinBeta * M *alpha + F1(5) = cosBeta * M *alpha + F1(6) = 0.0 - Fi(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - Fi(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - Fi(3) = (Fl*cosPhi + Fr*sinPhi)*(1-alpha) - Fi(4) = sinBeta * M *(1-alpha) - Fi(5) = cosBeta * M *(1-alpha) - Fi(6) = 0.0 + F2(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(3) = (Fl*cosPhi - Fr*sinPhi)*(1-alpha) + F2(4) = sinBeta * M *(1-alpha) + F2(5) = cosBeta * M *(1-alpha) + F2(6) = 0.0 END SUBROUTINE DistributeElementLoads @@ -3851,15 +3090,15 @@ SUBROUTINE AddEndLoad(Fl, M, sinPhi, cosPhi, SinBeta, cosBeta, Fi) Fi(1) = Fi(1) + Fl*sinPhi*cosBeta Fi(2) = Fi(2) + Fl*sinPhi*sinBeta Fi(3) = Fi(3) + Fl*cosPhi - Fi(4) = Fi(4) + M*sinBeta - Fi(5) = Fi(5) - M*cosBeta + Fi(4) = Fi(4) - M*sinBeta + Fi(5) = Fi(5) + M*cosBeta END SUBROUTINE AddEndLoad !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for computing derivatives of continuous states -SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) +SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, errStat, errMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds @@ -3871,14 +3110,14 @@ SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables TYPE(Morison_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at Time - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ! Compute the first time derivatives of the continuous states here: @@ -3889,7 +3128,7 @@ SUBROUTINE Morison_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt END SUBROUTINE Morison_CalcContStateDeriv !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for updating discrete states -SUBROUTINE Morison_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) +SUBROUTINE Morison_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, errStat, errMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds @@ -3901,14 +3140,14 @@ SUBROUTINE Morison_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat TYPE(Morison_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time TYPE(Morison_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ! Update discrete states here: @@ -3918,7 +3157,7 @@ SUBROUTINE Morison_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat END SUBROUTINE Morison_UpdateDiscState !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for solving for the residual of the constraint state equations -SUBROUTINE Morison_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) +SUBROUTINE Morison_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, errStat, errMsg ) !.................................................................................................................................. REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds @@ -3931,14 +3170,14 @@ SUBROUTINE Morison_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables TYPE(Morison_ConstraintStateType), INTENT( OUT) :: z_residual !< Residual of the constraint state equations using !! the input values described above - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None - ! Initialize ErrStat + ! Initialize errStat - ErrStat = ErrID_None - ErrMsg = "" + errStat = ErrID_None + errMsg = "" ! Solve for the constraint states here: diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 2b403ae68..0addc92bd 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -15,38 +15,42 @@ include Registry_NWTC_Library.txt # # -param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "Total number of possible Morison module output channels" - -typedef Morison/Morison Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - -typedef ^ ^ ReKi JointPos {3} - - "Undisplaced location of the joint in the platform coordinate system" m +param Morison/Morison unused INTEGER MaxMrsnOutputs - 4599 - "Total number of possible Morison module output channels" - +typedef ^ Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - +typedef ^ ^ ReKi Position {3} - - "Undisplaced location of the joint in the platform coordinate system" m typedef ^ ^ INTEGER JointAxID - - - "Axial ID (found in the user-supplied Axial Coefficients Table) for this joint: used to determine axial coefs" - typedef ^ ^ INTEGER JointAxIDIndx - - - "The index into the Axial Coefs arrays corresponding to the above Axial ID" - typedef ^ ^ INTEGER JointOvrlp - - - "Joint overlap code [Unused" - typedef ^ ^ INTEGER NConnections - - - "Number of members connecting to this joint" - typedef ^ ^ INTEGER ConnectionList {10} - - "List of Members connected to this joint. The member index is what is stored, not the Member ID" - -typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - +typedef ^ Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - typedef ^ ^ ReKi PropD - - - "Diameter" m typedef ^ ^ ReKi PropThck - - - "Wall thickness" m -typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - +typedef ^ Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - typedef ^ ^ INTEGER FillMList {:} - - "List of Member IDs for the members in this fill group" - typedef ^ ^ ReKi FillFSLoc - - - "The free-surface location (in Z) for this fill group" m typedef ^ ^ CHARACTER(80) FillDensChr - - - "String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens]" kg/m^3 typedef ^ ^ ReKi FillDens - - - "Numerical fill density" kg/m^3 -typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m +typedef ^ Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m typedef ^ ^ ReKi DpthCd - - - "Depth-based drag coef" - typedef ^ ^ ReKi DpthCdMG - - - "Depth-based drag coef for marine growth" - typedef ^ ^ ReKi DpthCa - - - "Depth-based Ca" - typedef ^ ^ ReKi DpthCaMG - - - "Depth-based Ca for marine growth" - typedef ^ ^ ReKi DpthCp - - - "Depth-based Cp" - typedef ^ ^ ReKi DpthCpMG - - - "Depth-based Cp for marine growth" - +typedef ^ ^ ReKi DpthAxCd - - - "Depth-based Axial Cd" - +typedef ^ ^ ReKi DpthAxCdMG - - - "Depth-based Axial Cd for marine growth" - typedef ^ ^ ReKi DpthAxCa - - - "Depth-based Axial Ca" - typedef ^ ^ ReKi DpthAxCaMG - - - "Depth-based Axial Ca for marine growth" - typedef ^ ^ ReKi DpthAxCp - - - "Depth-based Axial Cp" - typedef ^ ^ ReKi DpthAxCpMG - - - "Depth-based Axial Cp for marine growth" - -typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - +typedef ^ Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - typedef ^ ^ ReKi AxCd - - - "Axial Cd" - typedef ^ ^ ReKi AxCa - - - "Axial Ca" - typedef ^ ^ ReKi AxCp - - - "Axial Cp" - -typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "User-supplied integer ID for this member" - +# +typedef ^ Morison_MemberInputType INTEGER MemberID - - - "User-supplied integer ID for this member" - +typedef ^ ^ INTEGER NodeIndx {:} - - "Index of each of the member's nodes in the master node list" - typedef ^ ^ INTEGER MJointID1 - - - "Joint ID for start of member" - typedef ^ ^ INTEGER MJointID2 - - - "Joint ID for end of member" - typedef ^ ^ INTEGER MJointID1Indx - - - "Index into the joint table for the start of this member" - @@ -60,75 +64,62 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "Index into the appropriate coefs table for this member's properties" - typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "Index into the filled group table if this is a filled member" - typedef ^ ^ LOGICAL PropPot - - - "Flag T/F for whether the member is modeled with potential flow theory" - -#typedef ^ ^ INTEGER MGSplitState - - - "No longer used" - -#typedef ^ ^ INTEGER WtrSplitState - - - "No longer used" - -typedef ^ ^ INTEGER NumSplits - - - "How many splits are needs beyond the user-specified geometry" - -typedef ^ ^ ReKi Splits {5} - - "Number of times a user member is subdivided by the software" - typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from local to global coordinates" - -typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - +typedef ^ ^ INTEGER NElements - - - "number of elements in this member" - +typedef ^ ^ ReKi RefLength - - - "the reference total length for this member" m +typedef ^ ^ ReKi dl - - - "the reference element length for this member (may be less than MDivSize to achieve uniform element lengths)" m +# +typedef ^ Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - typedef ^ ^ INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - -typedef ^ ^ ReKi JointPos {3} - - "Position of the node in global coordinates" m +typedef ^ ^ ReKi Position {3} - - "Position of the node in global coordinates" m typedef ^ ^ INTEGER JointOvrlp - - - "" - typedef ^ ^ INTEGER JointAxIDIndx - - - "" - typedef ^ ^ INTEGER NConnections - - - "Number of elements connecting to this node" - typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the members connected to this node (positive if end 1, negative if end 2)" - -typedef ^ ^ INTEGER NConnectPreSplit - - - "In code, but unused: should be removed" - -typedef ^ ^ ReKi Cd - - - "Nodal Cd" - -typedef ^ ^ ReKi CdMG - - - "Nodal Cd with marine growth" - -typedef ^ ^ ReKi Ca - - - "Nodal Ca" - -typedef ^ ^ ReKi CaMG - - - "Nodal Ca with marine growth" - -typedef ^ ^ ReKi Cp - - - "Nodal Cp" - -typedef ^ ^ ReKi CpMG - - - "Nodal Cp with marine growth" - typedef ^ ^ ReKi JAxCd - - - "Nodal lumped (joint) axial Cd" - typedef ^ ^ ReKi JAxCa - - - "Nodal lumped (joint) axial Cp" - typedef ^ ^ ReKi JAxCp - - - "Nodal lumped (joint) axial Ca" - -typedef ^ ^ ReKi AxCa - - - "Nodal axial Ca" - -typedef ^ ^ ReKi AxCp - - - "Nodal axial Cp" - -typedef ^ ^ ReKi AxCaMG - - - "Nodal axial Ca with marine growth" - -typedef ^ ^ ReKi AxCpMG - - - "Nodal axial Cp with marine growth" - -typedef ^ ^ ReKi R - - - "Nodal radius (of member at node location)" m -typedef ^ ^ ReKi t - - - "Nodal thickness (of member at node location)" m -typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth (of member at node location)" m -typedef ^ ^ ReKi dRdz - - - "Nodal rate of change in member radius with respect to member axial direction" -typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 -typedef ^ ^ ReKi m_MG - - - "marine growth mass at a joint" kg -typedef ^ ^ ReKi I_MG {3}{3} - - "marine growth inertia matrix at a joint" kg-m^2 -typedef ^ ^ ReKi FillFSLoc - - - "Nodal fill free surface location (of connected chamber to this node)" m -typedef ^ ^ LOGICAL FillFlag - - - "Is this node filled? T/F" - typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 typedef ^ ^ INTEGER InpMbrIndx - - - "Index of member this node is connected to (from the user-specified member list in the input file)" - typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - -typedef ^ ^ LOGICAL PropPot - - - "Is this node modeled with potential flow theory? T/F" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from node local to global coordinates" - -typedef Morison/Morison Morison_MemberType INTEGER NodeIndx {:} - - "Index of each of the member's nodes in the master node list" - +typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth " m +typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 +# +typedef ^ Morison_MemberType INTEGER NodeIndx {:} - - "Index of each of the member's nodes in the master node list" - +typedef ^ Morison_MemberType INTEGER MemberID - - - "User-supplied integer ID for this member" - typedef ^ ^ INTEGER NElements - - - "number of elements in this member" - -typedef ^ ^ ReKi Len - - - "the reference total length for this member" m +typedef ^ ^ ReKi RefLength - - - "the reference total length for this member" m typedef ^ ^ ReKi dl - - - "the reference element length for this member (may be less than MDivSize to achieve uniform element lengths)" m typedef ^ ^ ReKi k {3} - - "unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn)" m +typedef ^ ^ ReKi kkt {3}{3} - - "matrix of matmul(k_hat, transpose(k_hat)" - +typedef ^ ^ ReKi Ak {3}{3} - - "matrix of I - kkt" - typedef ^ ^ ReKi R {:} - - "outer member radius at each node" m typedef ^ ^ ReKi RMG {:} - - "radius at each node including marine growth" m typedef ^ ^ ReKi Rin {:} - - "inner member radius at node, equivalent to radius of water ballast at this node if filled" m -typedef ^ ^ ReKi m_mg {:} - - "taper dr/dl of outer surface including marine growth of each element" - -typedef ^ ^ ReKi m_in {:} - - "taper dr/dl of interior surface of each element" - +typedef ^ ^ ReKi tMG {:} - - "Nodal thickness with marine growth (of member at node location)" m +typedef ^ ^ ReKi MGdensity {:} - - "Nodal density of marine growth" kg/m^3 +typedef ^ ^ ReKi dRdl_mg {:} - - "taper dr/dl of outer surface including marine growth of each element" - +typedef ^ ^ ReKi dRdl_in {:} - - "taper dr/dl of interior surface of each element" - +typedef ^ ^ ReKi Vinner - - - "Member volume without marine growth" m^3 +typedef ^ ^ ReKi Vouter - - - "Member volume including marine growth" m^3 +typedef ^ ^ ReKi Vballast - - - "Member ballast volume" m^3 +typedef ^ ^ ReKi Vsubmerged - - - "Submerged volume corresponding to portion of Member in the water" m^3 typedef ^ ^ ReKi l_fill - - - "fill length along member axis from start node 1" m typedef ^ ^ ReKi h_fill - - - "fill length of partially flooded element" m typedef ^ ^ ReKi z_overfill - - - "if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled." m typedef ^ ^ ReKi h_floor - - - "the distance from the node to the seabed along the member axis (negative value)" m typedef ^ ^ INTEGER i_floor - - - "the number of the element that pierces the seabed (zero if the member doesn't pierce it)" - +typedef ^ ^ INTEGER memfloodstatus - - - "Member-level flooded status for each elemen: 0 unflooded or fully below seabed, 2 partially flooded, 1 fully flooded " - typedef ^ ^ INTEGER floodstatus {:} - - "flooded status for each element: 0 unflooded or fully below seabed, 1 fully flooded, 2 partially flooded" - typedef ^ ^ ReKi alpha {:} - - "relative volume centroid of each element including marine growth, from node i to node i+1" - typedef ^ ^ ReKi alpha_fb {:} - - "relative volume centroid of each element's flooded ballast, from node i to node i+1" - typedef ^ ^ ReKi alpha_fb_star {:} - - "load distribution factor for each element after adjusting alpha_fb for node reference depths" - typedef ^ ^ ReKi Cd {:} - - "Member Cd at each node" - -typedef ^ ^ ReKi CdMG {:} - - "Member Cd at each node with marine growth" - typedef ^ ^ ReKi Ca {:} - - "Member Ca at each node" - -typedef ^ ^ ReKi CaMG {:} - - "Member Ca at each node with marine growth" - typedef ^ ^ ReKi Cp {:} - - "Member Cp at each node" - -typedef ^ ^ ReKi CpMG {:} - - "Member Cp at each node with marine growth" - +typedef ^ ^ ReKi AxCd {:} - - "Member axial Cd at each node" - typedef ^ ^ ReKi AxCa {:} - - "Member axial Ca at each node" - -typedef ^ ^ ReKi AxCaMG {:} - - "Member axial Ca at each node with marine growth" - typedef ^ ^ ReKi AxCp {:} - - "Member axial Cp at each node" - -typedef ^ ^ ReKi AxCpMG {:} - - "Member axial Cp at each node with marine growth" - typedef ^ ^ ReKi m_fb_l {:} - - "mass of flooded ballast in lower portion of each element" kg typedef ^ ^ ReKi m_fb_u {:} - - "mass of flooded ballast in upper portion of each element" kg typedef ^ ^ ReKi h_cfb_l {:} - - "distance to flooded ballast centroid from node point in lower portion of each element" m @@ -163,7 +154,8 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi F_Bouy {6} - - "Unused" - typedef ^ ^ ReKi F_DP {6} - - "Unused" - typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - -typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - +# +typedef ^ Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - @@ -176,6 +168,10 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi MemberCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberAxCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberAxCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberAxCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - @@ -184,17 +180,17 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi MemberAxCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberAxCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberAxCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m +typedef ^ Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m typedef ^ ^ ReKi MGThck - - - "Marine growth thickness" m typedef ^ ^ ReKi MGDens - - - "Marine growth density" kg/m^3 -typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "Member ID for requested output" - +typedef ^ Morison_MOutput INTEGER MemberID - - - "Member ID for requested output" - typedef ^ ^ INTEGER NOutLoc - - - "The number of requested output locations" - typedef ^ ^ ReKi NodeLocs {:} - - "Normalized locations along user-specified member for the outputs" - typedef ^ ^ INTEGER MemberIDIndx - - - "Index for member in the master list" - typedef ^ ^ INTEGER Marker1 {:} - - "Index of node in DistribMesh for the start of the member" - typedef ^ ^ INTEGER Marker2 {:} - - "Index of node in DistribMesh for the end of the member" - typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - -typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - +typedef ^ Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - typedef ^ ^ INTEGER NumMarkers - - - "Number of lumped mesh nodes which are co-located at the requested Joint" - typedef ^ ^ INTEGER Markers {10} - - "Index of all nodes in lumped mesh which are co-located at the requested Joint" - @@ -202,16 +198,14 @@ typedef ^ ^ INTEGER # Define inputs that the initialization routine may need here: # e.g., the name of the input file, the file root name,etc. # -typedef Morison/Morison InitInputType ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 +typedef ^ InitInputType ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m typedef ^ ^ ReKi MSL2SWL - - - "Mean Sea Level to Still Water Level offset" m typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - typedef ^ ^ INTEGER NNodes - - - "Total number of nodes in the final software model" - -typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "Unused: For super member calculations" - typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - -typedef ^ ^ INTEGER NMembers - - - "Number of elements in the discretized model" - typedef ^ ^ Morison_MemberType Members {:} - - "Array of elements which were derived from the user-specified members" - typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - @@ -223,6 +217,8 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for marine growth" - typedef ^ ^ ReKi SimplCp - - - "Simple model Cp" - typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for marine growth" - +typedef ^ ^ ReKi SimplAxCd - - - "Simple model Axial Cd" - +typedef ^ ^ ReKi SimplAxCdMG - - - "Simple model Axial Cd for marine growth" - typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca" - typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for marine growth" - typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp" - @@ -231,7 +227,7 @@ typedef ^ ^ INTEGER typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - typedef ^ ^ INTEGER NCoefMembers - - - "" - typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - -typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - +typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "Array of user-specified members" - typedef ^ ^ INTEGER NFillGroups - - - "" - typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - @@ -261,8 +257,7 @@ typedef ^ ^ INTEGER # # Define outputs from the initialization routine here: # -typedef ^ InitOutputType MeshType DistribMesh - - - "Unused?" - -typedef ^ ^ MeshType LumpedMesh - - - "Unused?" - +typedef ^ InitOutputType MeshType Mesh - - - "Unused?" - typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "User-requested Output channel units" - @@ -290,22 +285,27 @@ typedef ^ OtherStateType IntKi # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi F_D {:}{:} - - "Nodal viscous drag loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_I {:}{:} - - "Nodal inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - -typedef ^ ^ ReKi F_B {:}{:} - - "Nodal bounancy loads" - -typedef ^ ^ ReKi F_FB {:}{:} - - "Nodal flooded ballast weight/buoyancy loads" - -typedef ^ ^ ReKi F_FBI {:}{:} - - "Nodal flooded ballast inertia loads" - -typedef ^ ^ ReKi F_MG {:}{:} - - "Nodal marine growth weight loads" - -typedef ^ ^ ReKi F_MGI {:}{:} - - "Nodal marine growth inertia loads" - -typedef ^ ^ ReKi F_AM {:}{:} - - "Nodal total added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_AM_M {:}{:} - - "Nodal member added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_AM_MG {:}{:} - - "Nodal marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_AM_F {:}{:} - - "Nodal added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - +typedef ^ MiscVarType ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - +typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - +typedef ^ ^ ReKi F_A {:}{:} - - "Member-based (side-effects) Nodal added mass loads at time t" - +typedef ^ ^ ReKi F_B {:}{:} - - "Member-based (side-effects) Nodal buoyancy loads" - +typedef ^ ^ ReKi F_BF {:}{:} - - "Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads" - +typedef ^ ^ ReKi F_If {:}{:} - - "Member-based (side-effects) Nodal flooded ballast inertia loads" - +typedef ^ ^ ReKi F_WMG {:}{:} - - "Member-based (side-effects) Nodal marine growth weight loads" - +typedef ^ ^ ReKi F_IMG {:}{:} - - "Member-based (side-effects) Nodal marine growth inertia loads" - typedef ^ ^ ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ Morison_MemberType Members {:} - - "Array of Morison members used during simulation" - +typedef ^ ^ ReKi vrel {:}{:} - - "velocity of structural node relative to the water" m/s^2 +typedef ^ ^ INTEGER nodeInWater {:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +typedef ^ ^ ReKi F_B_End {:}{:} - - "" - +typedef ^ ^ ReKi F_D_End {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_I_End {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_IMG_End {:}{:} - - "Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_DP_End {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_A_End {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_BF_End {:}{:} - - "" - typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - # ..... Parameters ................................................................................................................ @@ -313,20 +313,27 @@ typedef ^ ^ INTEGER # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: # typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) +typedef ^ ^ ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 -typedef ^ ^ INTEGER NMembers - - - "number of members" - +typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m +typedef ^ ^ INTEGER NMembers - - - "number of members" - +typedef ^ ^ Morison_MemberType Members {:} - - "Array of Morison members used during simulation" - typedef ^ ^ INTEGER NNodes - - - "" - -typedef ^ ^ Morison_NodeType Nodes {:} - - "" - +typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - +typedef ^ ^ ReKi I_MG_End {:}{:}{:} - - "Inertial matrix associated with marine growth mass at joint" - typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - typedef ^ ^ ReKi D_dragConst {:} - - "" - -typedef ^ ^ ReKi L_An {:}{:} - - "directional area vector of each joint" m^2 -typedef ^ ^ ReKi L_F_B {:}{:} - - "" - -typedef ^ ^ ReKi L_F_I {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_F_DP {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_F_BF {:}{:} - - "" - -typedef ^ ^ ReKi L_AM_M {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_dragConst {:} - - "" - +typedef ^ ^ ReKi An_End {:}{:} - - "directional area vector of each joint" m^2 +typedef ^ ^ ReKi F_B_End {:}{:} - - "" - +typedef ^ ^ ReKi F_I_End {:}{:}{:} - - "" - +typedef ^ ^ ReKi F_DP_End {:}{:}{:} - - "" - +typedef ^ ^ ReKi AM_M_End {:}{:}{:} - - "" - +typedef ^ ^ ReKi DragConst_End {:} - - "" - +typedef ^ ^ ReKi F_WMG_End {:}{:} - - "Joint marine growth weight loads, constant for all t" N +typedef ^ ^ ReKi DP_Const_End {:}{:} - - "Constant part of Joint dynamic pressure term" N +typedef ^ ^ ReKi Mass_MG_End {:} - - "Joint marine growth mass" kg +typedef ^ ^ ReKi AM_End {:}{:}{:} - - "3x3 Joint added mass matrix, constant for all t" N typedef ^ ^ INTEGER NDistribMarkers - - - "" - #typedef ^ ^ Morison_NodeType DistribMarkers {:} - - "" - typedef ^ ^ INTEGER distribToNodeIndx {:} - - "" - diff --git a/modules/hydrodyn/src/MorisonOutListParameters.xlsx b/modules/hydrodyn/src/MorisonOutListParameters.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ac55f6e73041d0f39fb446922ce90c99db221176 GIT binary patch literal 113539 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 literal 0 HcmV?d00001 diff --git a/modules/hydrodyn/src/Morison_Output.f90 b/modules/hydrodyn/src/Morison_Output.f90 index 294c3478c..872aa192e 100644 --- a/modules/hydrodyn/src/Morison_Output.f90 +++ b/modules/hydrodyn/src/Morison_Output.f90 @@ -48,13 +48,12 @@ MODULE Morison_Output ! (2) Array y%AllOuts() must be dimensioned to the value of the largest output parameter ! Time: + INTEGER(IntKi), PARAMETER :: Time = 0 - INTEGER(IntKi), PARAMETER :: Time = 0 + ! Member-level Wave Kinematics : - ! Category: - - INTEGER(IntKi), PARAMETER :: M1N1Axi = 1 + INTEGER(IntKi), PARAMETER :: M1N1Axi = 1 INTEGER(IntKi), PARAMETER :: M1N2Axi = 2 INTEGER(IntKi), PARAMETER :: M1N3Axi = 3 INTEGER(IntKi), PARAMETER :: M1N4Axi = 4 @@ -1109,7 +1108,7 @@ MODULE Morison_Output INTEGER(IntKi), PARAMETER :: M9N9STAzi = 1053 - ! Category: + ! Morison Element Loads: INTEGER(IntKi), PARAMETER :: M1N1FDxi = 1054 INTEGER(IntKi), PARAMETER :: M1N2FDxi = 1055 @@ -2812,1293 +2811,1859 @@ MODULE Morison_Output INTEGER(IntKi), PARAMETER :: M9N7FMGzi = 2752 INTEGER(IntKi), PARAMETER :: M9N8FMGzi = 2753 INTEGER(IntKi), PARAMETER :: M9N9FMGzi = 2754 - INTEGER(IntKi), PARAMETER :: M1N1FAMxi = 2755 - INTEGER(IntKi), PARAMETER :: M1N2FAMxi = 2756 - INTEGER(IntKi), PARAMETER :: M1N3FAMxi = 2757 - INTEGER(IntKi), PARAMETER :: M1N4FAMxi = 2758 - INTEGER(IntKi), PARAMETER :: M1N5FAMxi = 2759 - INTEGER(IntKi), PARAMETER :: M1N6FAMxi = 2760 - INTEGER(IntKi), PARAMETER :: M1N7FAMxi = 2761 - INTEGER(IntKi), PARAMETER :: M1N8FAMxi = 2762 - INTEGER(IntKi), PARAMETER :: M1N9FAMxi = 2763 - INTEGER(IntKi), PARAMETER :: M2N1FAMxi = 2764 - INTEGER(IntKi), PARAMETER :: M2N2FAMxi = 2765 - INTEGER(IntKi), PARAMETER :: M2N3FAMxi = 2766 - INTEGER(IntKi), PARAMETER :: M2N4FAMxi = 2767 - INTEGER(IntKi), PARAMETER :: M2N5FAMxi = 2768 - INTEGER(IntKi), PARAMETER :: M2N6FAMxi = 2769 - INTEGER(IntKi), PARAMETER :: M2N7FAMxi = 2770 - INTEGER(IntKi), PARAMETER :: M2N8FAMxi = 2771 - INTEGER(IntKi), PARAMETER :: M2N9FAMxi = 2772 - INTEGER(IntKi), PARAMETER :: M3N1FAMxi = 2773 - INTEGER(IntKi), PARAMETER :: M3N2FAMxi = 2774 - INTEGER(IntKi), PARAMETER :: M3N3FAMxi = 2775 - INTEGER(IntKi), PARAMETER :: M3N4FAMxi = 2776 - INTEGER(IntKi), PARAMETER :: M3N5FAMxi = 2777 - INTEGER(IntKi), PARAMETER :: M3N6FAMxi = 2778 - INTEGER(IntKi), PARAMETER :: M3N7FAMxi = 2779 - INTEGER(IntKi), PARAMETER :: M3N8FAMxi = 2780 - INTEGER(IntKi), PARAMETER :: M3N9FAMxi = 2781 - INTEGER(IntKi), PARAMETER :: M4N1FAMxi = 2782 - INTEGER(IntKi), PARAMETER :: M4N2FAMxi = 2783 - INTEGER(IntKi), PARAMETER :: M4N3FAMxi = 2784 - INTEGER(IntKi), PARAMETER :: M4N4FAMxi = 2785 - INTEGER(IntKi), PARAMETER :: M4N5FAMxi = 2786 - INTEGER(IntKi), PARAMETER :: M4N6FAMxi = 2787 - INTEGER(IntKi), PARAMETER :: M4N7FAMxi = 2788 - INTEGER(IntKi), PARAMETER :: M4N8FAMxi = 2789 - INTEGER(IntKi), PARAMETER :: M4N9FAMxi = 2790 - INTEGER(IntKi), PARAMETER :: M5N1FAMxi = 2791 - INTEGER(IntKi), PARAMETER :: M5N2FAMxi = 2792 - INTEGER(IntKi), PARAMETER :: M5N3FAMxi = 2793 - INTEGER(IntKi), PARAMETER :: M5N4FAMxi = 2794 - INTEGER(IntKi), PARAMETER :: M5N5FAMxi = 2795 - INTEGER(IntKi), PARAMETER :: M5N6FAMxi = 2796 - INTEGER(IntKi), PARAMETER :: M5N7FAMxi = 2797 - INTEGER(IntKi), PARAMETER :: M5N8FAMxi = 2798 - INTEGER(IntKi), PARAMETER :: M5N9FAMxi = 2799 - INTEGER(IntKi), PARAMETER :: M6N1FAMxi = 2800 - INTEGER(IntKi), PARAMETER :: M6N2FAMxi = 2801 - INTEGER(IntKi), PARAMETER :: M6N3FAMxi = 2802 - INTEGER(IntKi), PARAMETER :: M6N4FAMxi = 2803 - INTEGER(IntKi), PARAMETER :: M6N5FAMxi = 2804 - INTEGER(IntKi), PARAMETER :: M6N6FAMxi = 2805 - INTEGER(IntKi), PARAMETER :: M6N7FAMxi = 2806 - INTEGER(IntKi), PARAMETER :: M6N8FAMxi = 2807 - INTEGER(IntKi), PARAMETER :: M6N9FAMxi = 2808 - INTEGER(IntKi), PARAMETER :: M7N1FAMxi = 2809 - INTEGER(IntKi), PARAMETER :: M7N2FAMxi = 2810 - INTEGER(IntKi), PARAMETER :: M7N3FAMxi = 2811 - INTEGER(IntKi), PARAMETER :: M7N4FAMxi = 2812 - INTEGER(IntKi), PARAMETER :: M7N5FAMxi = 2813 - INTEGER(IntKi), PARAMETER :: M7N6FAMxi = 2814 - INTEGER(IntKi), PARAMETER :: M7N7FAMxi = 2815 - INTEGER(IntKi), PARAMETER :: M7N8FAMxi = 2816 - INTEGER(IntKi), PARAMETER :: M7N9FAMxi = 2817 - INTEGER(IntKi), PARAMETER :: M8N1FAMxi = 2818 - INTEGER(IntKi), PARAMETER :: M8N2FAMxi = 2819 - INTEGER(IntKi), PARAMETER :: M8N3FAMxi = 2820 - INTEGER(IntKi), PARAMETER :: M8N4FAMxi = 2821 - INTEGER(IntKi), PARAMETER :: M8N5FAMxi = 2822 - INTEGER(IntKi), PARAMETER :: M8N6FAMxi = 2823 - INTEGER(IntKi), PARAMETER :: M8N7FAMxi = 2824 - INTEGER(IntKi), PARAMETER :: M8N8FAMxi = 2825 - INTEGER(IntKi), PARAMETER :: M8N9FAMxi = 2826 - INTEGER(IntKi), PARAMETER :: M9N1FAMxi = 2827 - INTEGER(IntKi), PARAMETER :: M9N2FAMxi = 2828 - INTEGER(IntKi), PARAMETER :: M9N3FAMxi = 2829 - INTEGER(IntKi), PARAMETER :: M9N4FAMxi = 2830 - INTEGER(IntKi), PARAMETER :: M9N5FAMxi = 2831 - INTEGER(IntKi), PARAMETER :: M9N6FAMxi = 2832 - INTEGER(IntKi), PARAMETER :: M9N7FAMxi = 2833 - INTEGER(IntKi), PARAMETER :: M9N8FAMxi = 2834 - INTEGER(IntKi), PARAMETER :: M9N9FAMxi = 2835 - INTEGER(IntKi), PARAMETER :: M1N1FAMyi = 2836 - INTEGER(IntKi), PARAMETER :: M1N2FAMyi = 2837 - INTEGER(IntKi), PARAMETER :: M1N3FAMyi = 2838 - INTEGER(IntKi), PARAMETER :: M1N4FAMyi = 2839 - INTEGER(IntKi), PARAMETER :: M1N5FAMyi = 2840 - INTEGER(IntKi), PARAMETER :: M1N6FAMyi = 2841 - INTEGER(IntKi), PARAMETER :: M1N7FAMyi = 2842 - INTEGER(IntKi), PARAMETER :: M1N8FAMyi = 2843 - INTEGER(IntKi), PARAMETER :: M1N9FAMyi = 2844 - INTEGER(IntKi), PARAMETER :: M2N1FAMyi = 2845 - INTEGER(IntKi), PARAMETER :: M2N2FAMyi = 2846 - INTEGER(IntKi), PARAMETER :: M2N3FAMyi = 2847 - INTEGER(IntKi), PARAMETER :: M2N4FAMyi = 2848 - INTEGER(IntKi), PARAMETER :: M2N5FAMyi = 2849 - INTEGER(IntKi), PARAMETER :: M2N6FAMyi = 2850 - INTEGER(IntKi), PARAMETER :: M2N7FAMyi = 2851 - INTEGER(IntKi), PARAMETER :: M2N8FAMyi = 2852 - INTEGER(IntKi), PARAMETER :: M2N9FAMyi = 2853 - INTEGER(IntKi), PARAMETER :: M3N1FAMyi = 2854 - INTEGER(IntKi), PARAMETER :: M3N2FAMyi = 2855 - INTEGER(IntKi), PARAMETER :: M3N3FAMyi = 2856 - INTEGER(IntKi), PARAMETER :: M3N4FAMyi = 2857 - INTEGER(IntKi), PARAMETER :: M3N5FAMyi = 2858 - INTEGER(IntKi), PARAMETER :: M3N6FAMyi = 2859 - INTEGER(IntKi), PARAMETER :: M3N7FAMyi = 2860 - INTEGER(IntKi), PARAMETER :: M3N8FAMyi = 2861 - INTEGER(IntKi), PARAMETER :: M3N9FAMyi = 2862 - INTEGER(IntKi), PARAMETER :: M4N1FAMyi = 2863 - INTEGER(IntKi), PARAMETER :: M4N2FAMyi = 2864 - INTEGER(IntKi), PARAMETER :: M4N3FAMyi = 2865 - INTEGER(IntKi), PARAMETER :: M4N4FAMyi = 2866 - INTEGER(IntKi), PARAMETER :: M4N5FAMyi = 2867 - INTEGER(IntKi), PARAMETER :: M4N6FAMyi = 2868 - INTEGER(IntKi), PARAMETER :: M4N7FAMyi = 2869 - INTEGER(IntKi), PARAMETER :: M4N8FAMyi = 2870 - INTEGER(IntKi), PARAMETER :: M4N9FAMyi = 2871 - INTEGER(IntKi), PARAMETER :: M5N1FAMyi = 2872 - INTEGER(IntKi), PARAMETER :: M5N2FAMyi = 2873 - INTEGER(IntKi), PARAMETER :: M5N3FAMyi = 2874 - INTEGER(IntKi), PARAMETER :: M5N4FAMyi = 2875 - INTEGER(IntKi), PARAMETER :: M5N5FAMyi = 2876 - INTEGER(IntKi), PARAMETER :: M5N6FAMyi = 2877 - INTEGER(IntKi), PARAMETER :: M5N7FAMyi = 2878 - INTEGER(IntKi), PARAMETER :: M5N8FAMyi = 2879 - INTEGER(IntKi), PARAMETER :: M5N9FAMyi = 2880 - INTEGER(IntKi), PARAMETER :: M6N1FAMyi = 2881 - INTEGER(IntKi), PARAMETER :: M6N2FAMyi = 2882 - INTEGER(IntKi), PARAMETER :: M6N3FAMyi = 2883 - INTEGER(IntKi), PARAMETER :: M6N4FAMyi = 2884 - INTEGER(IntKi), PARAMETER :: M6N5FAMyi = 2885 - INTEGER(IntKi), PARAMETER :: M6N6FAMyi = 2886 - INTEGER(IntKi), PARAMETER :: M6N7FAMyi = 2887 - INTEGER(IntKi), PARAMETER :: M6N8FAMyi = 2888 - INTEGER(IntKi), PARAMETER :: M6N9FAMyi = 2889 - INTEGER(IntKi), PARAMETER :: M7N1FAMyi = 2890 - INTEGER(IntKi), PARAMETER :: M7N2FAMyi = 2891 - INTEGER(IntKi), PARAMETER :: M7N3FAMyi = 2892 - INTEGER(IntKi), PARAMETER :: M7N4FAMyi = 2893 - INTEGER(IntKi), PARAMETER :: M7N5FAMyi = 2894 - INTEGER(IntKi), PARAMETER :: M7N6FAMyi = 2895 - INTEGER(IntKi), PARAMETER :: M7N7FAMyi = 2896 - INTEGER(IntKi), PARAMETER :: M7N8FAMyi = 2897 - INTEGER(IntKi), PARAMETER :: M7N9FAMyi = 2898 - INTEGER(IntKi), PARAMETER :: M8N1FAMyi = 2899 - INTEGER(IntKi), PARAMETER :: M8N2FAMyi = 2900 - INTEGER(IntKi), PARAMETER :: M8N3FAMyi = 2901 - INTEGER(IntKi), PARAMETER :: M8N4FAMyi = 2902 - INTEGER(IntKi), PARAMETER :: M8N5FAMyi = 2903 - INTEGER(IntKi), PARAMETER :: M8N6FAMyi = 2904 - INTEGER(IntKi), PARAMETER :: M8N7FAMyi = 2905 - INTEGER(IntKi), PARAMETER :: M8N8FAMyi = 2906 - INTEGER(IntKi), PARAMETER :: M8N9FAMyi = 2907 - INTEGER(IntKi), PARAMETER :: M9N1FAMyi = 2908 - INTEGER(IntKi), PARAMETER :: M9N2FAMyi = 2909 - INTEGER(IntKi), PARAMETER :: M9N3FAMyi = 2910 - INTEGER(IntKi), PARAMETER :: M9N4FAMyi = 2911 - INTEGER(IntKi), PARAMETER :: M9N5FAMyi = 2912 - INTEGER(IntKi), PARAMETER :: M9N6FAMyi = 2913 - INTEGER(IntKi), PARAMETER :: M9N7FAMyi = 2914 - INTEGER(IntKi), PARAMETER :: M9N8FAMyi = 2915 - INTEGER(IntKi), PARAMETER :: M9N9FAMyi = 2916 - INTEGER(IntKi), PARAMETER :: M1N1FAMzi = 2917 - INTEGER(IntKi), PARAMETER :: M1N2FAMzi = 2918 - INTEGER(IntKi), PARAMETER :: M1N3FAMzi = 2919 - INTEGER(IntKi), PARAMETER :: M1N4FAMzi = 2920 - INTEGER(IntKi), PARAMETER :: M1N5FAMzi = 2921 - INTEGER(IntKi), PARAMETER :: M1N6FAMzi = 2922 - INTEGER(IntKi), PARAMETER :: M1N7FAMzi = 2923 - INTEGER(IntKi), PARAMETER :: M1N8FAMzi = 2924 - INTEGER(IntKi), PARAMETER :: M1N9FAMzi = 2925 - INTEGER(IntKi), PARAMETER :: M2N1FAMzi = 2926 - INTEGER(IntKi), PARAMETER :: M2N2FAMzi = 2927 - INTEGER(IntKi), PARAMETER :: M2N3FAMzi = 2928 - INTEGER(IntKi), PARAMETER :: M2N4FAMzi = 2929 - INTEGER(IntKi), PARAMETER :: M2N5FAMzi = 2930 - INTEGER(IntKi), PARAMETER :: M2N6FAMzi = 2931 - INTEGER(IntKi), PARAMETER :: M2N7FAMzi = 2932 - INTEGER(IntKi), PARAMETER :: M2N8FAMzi = 2933 - INTEGER(IntKi), PARAMETER :: M2N9FAMzi = 2934 - INTEGER(IntKi), PARAMETER :: M3N1FAMzi = 2935 - INTEGER(IntKi), PARAMETER :: M3N2FAMzi = 2936 - INTEGER(IntKi), PARAMETER :: M3N3FAMzi = 2937 - INTEGER(IntKi), PARAMETER :: M3N4FAMzi = 2938 - INTEGER(IntKi), PARAMETER :: M3N5FAMzi = 2939 - INTEGER(IntKi), PARAMETER :: M3N6FAMzi = 2940 - INTEGER(IntKi), PARAMETER :: M3N7FAMzi = 2941 - INTEGER(IntKi), PARAMETER :: M3N8FAMzi = 2942 - INTEGER(IntKi), PARAMETER :: M3N9FAMzi = 2943 - INTEGER(IntKi), PARAMETER :: M4N1FAMzi = 2944 - INTEGER(IntKi), PARAMETER :: M4N2FAMzi = 2945 - INTEGER(IntKi), PARAMETER :: M4N3FAMzi = 2946 - INTEGER(IntKi), PARAMETER :: M4N4FAMzi = 2947 - INTEGER(IntKi), PARAMETER :: M4N5FAMzi = 2948 - INTEGER(IntKi), PARAMETER :: M4N6FAMzi = 2949 - INTEGER(IntKi), PARAMETER :: M4N7FAMzi = 2950 - INTEGER(IntKi), PARAMETER :: M4N8FAMzi = 2951 - INTEGER(IntKi), PARAMETER :: M4N9FAMzi = 2952 - INTEGER(IntKi), PARAMETER :: M5N1FAMzi = 2953 - INTEGER(IntKi), PARAMETER :: M5N2FAMzi = 2954 - INTEGER(IntKi), PARAMETER :: M5N3FAMzi = 2955 - INTEGER(IntKi), PARAMETER :: M5N4FAMzi = 2956 - INTEGER(IntKi), PARAMETER :: M5N5FAMzi = 2957 - INTEGER(IntKi), PARAMETER :: M5N6FAMzi = 2958 - INTEGER(IntKi), PARAMETER :: M5N7FAMzi = 2959 - INTEGER(IntKi), PARAMETER :: M5N8FAMzi = 2960 - INTEGER(IntKi), PARAMETER :: M5N9FAMzi = 2961 - INTEGER(IntKi), PARAMETER :: M6N1FAMzi = 2962 - INTEGER(IntKi), PARAMETER :: M6N2FAMzi = 2963 - INTEGER(IntKi), PARAMETER :: M6N3FAMzi = 2964 - INTEGER(IntKi), PARAMETER :: M6N4FAMzi = 2965 - INTEGER(IntKi), PARAMETER :: M6N5FAMzi = 2966 - INTEGER(IntKi), PARAMETER :: M6N6FAMzi = 2967 - INTEGER(IntKi), PARAMETER :: M6N7FAMzi = 2968 - INTEGER(IntKi), PARAMETER :: M6N8FAMzi = 2969 - INTEGER(IntKi), PARAMETER :: M6N9FAMzi = 2970 - INTEGER(IntKi), PARAMETER :: M7N1FAMzi = 2971 - INTEGER(IntKi), PARAMETER :: M7N2FAMzi = 2972 - INTEGER(IntKi), PARAMETER :: M7N3FAMzi = 2973 - INTEGER(IntKi), PARAMETER :: M7N4FAMzi = 2974 - INTEGER(IntKi), PARAMETER :: M7N5FAMzi = 2975 - INTEGER(IntKi), PARAMETER :: M7N6FAMzi = 2976 - INTEGER(IntKi), PARAMETER :: M7N7FAMzi = 2977 - INTEGER(IntKi), PARAMETER :: M7N8FAMzi = 2978 - INTEGER(IntKi), PARAMETER :: M7N9FAMzi = 2979 - INTEGER(IntKi), PARAMETER :: M8N1FAMzi = 2980 - INTEGER(IntKi), PARAMETER :: M8N2FAMzi = 2981 - INTEGER(IntKi), PARAMETER :: M8N3FAMzi = 2982 - INTEGER(IntKi), PARAMETER :: M8N4FAMzi = 2983 - INTEGER(IntKi), PARAMETER :: M8N5FAMzi = 2984 - INTEGER(IntKi), PARAMETER :: M8N6FAMzi = 2985 - INTEGER(IntKi), PARAMETER :: M8N7FAMzi = 2986 - INTEGER(IntKi), PARAMETER :: M8N8FAMzi = 2987 - INTEGER(IntKi), PARAMETER :: M8N9FAMzi = 2988 - INTEGER(IntKi), PARAMETER :: M9N1FAMzi = 2989 - INTEGER(IntKi), PARAMETER :: M9N2FAMzi = 2990 - INTEGER(IntKi), PARAMETER :: M9N3FAMzi = 2991 - INTEGER(IntKi), PARAMETER :: M9N4FAMzi = 2992 - INTEGER(IntKi), PARAMETER :: M9N5FAMzi = 2993 - INTEGER(IntKi), PARAMETER :: M9N6FAMzi = 2994 - INTEGER(IntKi), PARAMETER :: M9N7FAMzi = 2995 - INTEGER(IntKi), PARAMETER :: M9N8FAMzi = 2996 - INTEGER(IntKi), PARAMETER :: M9N9FAMzi = 2997 - INTEGER(IntKi), PARAMETER :: M1N1FAGxi = 2998 - INTEGER(IntKi), PARAMETER :: M1N2FAGxi = 2999 - INTEGER(IntKi), PARAMETER :: M1N3FAGxi = 3000 - INTEGER(IntKi), PARAMETER :: M1N4FAGxi = 3001 - INTEGER(IntKi), PARAMETER :: M1N5FAGxi = 3002 - INTEGER(IntKi), PARAMETER :: M1N6FAGxi = 3003 - INTEGER(IntKi), PARAMETER :: M1N7FAGxi = 3004 - INTEGER(IntKi), PARAMETER :: M1N8FAGxi = 3005 - INTEGER(IntKi), PARAMETER :: M1N9FAGxi = 3006 - INTEGER(IntKi), PARAMETER :: M2N1FAGxi = 3007 - INTEGER(IntKi), PARAMETER :: M2N2FAGxi = 3008 - INTEGER(IntKi), PARAMETER :: M2N3FAGxi = 3009 - INTEGER(IntKi), PARAMETER :: M2N4FAGxi = 3010 - INTEGER(IntKi), PARAMETER :: M2N5FAGxi = 3011 - INTEGER(IntKi), PARAMETER :: M2N6FAGxi = 3012 - INTEGER(IntKi), PARAMETER :: M2N7FAGxi = 3013 - INTEGER(IntKi), PARAMETER :: M2N8FAGxi = 3014 - INTEGER(IntKi), PARAMETER :: M2N9FAGxi = 3015 - INTEGER(IntKi), PARAMETER :: M3N1FAGxi = 3016 - INTEGER(IntKi), PARAMETER :: M3N2FAGxi = 3017 - INTEGER(IntKi), PARAMETER :: M3N3FAGxi = 3018 - INTEGER(IntKi), PARAMETER :: M3N4FAGxi = 3019 - INTEGER(IntKi), PARAMETER :: M3N5FAGxi = 3020 - INTEGER(IntKi), PARAMETER :: M3N6FAGxi = 3021 - INTEGER(IntKi), PARAMETER :: M3N7FAGxi = 3022 - INTEGER(IntKi), PARAMETER :: M3N8FAGxi = 3023 - INTEGER(IntKi), PARAMETER :: M3N9FAGxi = 3024 - INTEGER(IntKi), PARAMETER :: M4N1FAGxi = 3025 - INTEGER(IntKi), PARAMETER :: M4N2FAGxi = 3026 - INTEGER(IntKi), PARAMETER :: M4N3FAGxi = 3027 - INTEGER(IntKi), PARAMETER :: M4N4FAGxi = 3028 - INTEGER(IntKi), PARAMETER :: M4N5FAGxi = 3029 - INTEGER(IntKi), PARAMETER :: M4N6FAGxi = 3030 - INTEGER(IntKi), PARAMETER :: M4N7FAGxi = 3031 - INTEGER(IntKi), PARAMETER :: M4N8FAGxi = 3032 - INTEGER(IntKi), PARAMETER :: M4N9FAGxi = 3033 - INTEGER(IntKi), PARAMETER :: M5N1FAGxi = 3034 - INTEGER(IntKi), PARAMETER :: M5N2FAGxi = 3035 - INTEGER(IntKi), PARAMETER :: M5N3FAGxi = 3036 - INTEGER(IntKi), PARAMETER :: M5N4FAGxi = 3037 - INTEGER(IntKi), PARAMETER :: M5N5FAGxi = 3038 - INTEGER(IntKi), PARAMETER :: M5N6FAGxi = 3039 - INTEGER(IntKi), PARAMETER :: M5N7FAGxi = 3040 - INTEGER(IntKi), PARAMETER :: M5N8FAGxi = 3041 - INTEGER(IntKi), PARAMETER :: M5N9FAGxi = 3042 - INTEGER(IntKi), PARAMETER :: M6N1FAGxi = 3043 - INTEGER(IntKi), PARAMETER :: M6N2FAGxi = 3044 - INTEGER(IntKi), PARAMETER :: M6N3FAGxi = 3045 - INTEGER(IntKi), PARAMETER :: M6N4FAGxi = 3046 - INTEGER(IntKi), PARAMETER :: M6N5FAGxi = 3047 - INTEGER(IntKi), PARAMETER :: M6N6FAGxi = 3048 - INTEGER(IntKi), PARAMETER :: M6N7FAGxi = 3049 - INTEGER(IntKi), PARAMETER :: M6N8FAGxi = 3050 - INTEGER(IntKi), PARAMETER :: M6N9FAGxi = 3051 - INTEGER(IntKi), PARAMETER :: M7N1FAGxi = 3052 - INTEGER(IntKi), PARAMETER :: M7N2FAGxi = 3053 - INTEGER(IntKi), PARAMETER :: M7N3FAGxi = 3054 - INTEGER(IntKi), PARAMETER :: M7N4FAGxi = 3055 - INTEGER(IntKi), PARAMETER :: M7N5FAGxi = 3056 - INTEGER(IntKi), PARAMETER :: M7N6FAGxi = 3057 - INTEGER(IntKi), PARAMETER :: M7N7FAGxi = 3058 - INTEGER(IntKi), PARAMETER :: M7N8FAGxi = 3059 - INTEGER(IntKi), PARAMETER :: M7N9FAGxi = 3060 - INTEGER(IntKi), PARAMETER :: M8N1FAGxi = 3061 - INTEGER(IntKi), PARAMETER :: M8N2FAGxi = 3062 - INTEGER(IntKi), PARAMETER :: M8N3FAGxi = 3063 - INTEGER(IntKi), PARAMETER :: M8N4FAGxi = 3064 - INTEGER(IntKi), PARAMETER :: M8N5FAGxi = 3065 - INTEGER(IntKi), PARAMETER :: M8N6FAGxi = 3066 - INTEGER(IntKi), PARAMETER :: M8N7FAGxi = 3067 - INTEGER(IntKi), PARAMETER :: M8N8FAGxi = 3068 - INTEGER(IntKi), PARAMETER :: M8N9FAGxi = 3069 - INTEGER(IntKi), PARAMETER :: M9N1FAGxi = 3070 - INTEGER(IntKi), PARAMETER :: M9N2FAGxi = 3071 - INTEGER(IntKi), PARAMETER :: M9N3FAGxi = 3072 - INTEGER(IntKi), PARAMETER :: M9N4FAGxi = 3073 - INTEGER(IntKi), PARAMETER :: M9N5FAGxi = 3074 - INTEGER(IntKi), PARAMETER :: M9N6FAGxi = 3075 - INTEGER(IntKi), PARAMETER :: M9N7FAGxi = 3076 - INTEGER(IntKi), PARAMETER :: M9N8FAGxi = 3077 - INTEGER(IntKi), PARAMETER :: M9N9FAGxi = 3078 - INTEGER(IntKi), PARAMETER :: M1N1FAGyi = 3079 - INTEGER(IntKi), PARAMETER :: M1N2FAGyi = 3080 - INTEGER(IntKi), PARAMETER :: M1N3FAGyi = 3081 - INTEGER(IntKi), PARAMETER :: M1N4FAGyi = 3082 - INTEGER(IntKi), PARAMETER :: M1N5FAGyi = 3083 - INTEGER(IntKi), PARAMETER :: M1N6FAGyi = 3084 - INTEGER(IntKi), PARAMETER :: M1N7FAGyi = 3085 - INTEGER(IntKi), PARAMETER :: M1N8FAGyi = 3086 - INTEGER(IntKi), PARAMETER :: M1N9FAGyi = 3087 - INTEGER(IntKi), PARAMETER :: M2N1FAGyi = 3088 - INTEGER(IntKi), PARAMETER :: M2N2FAGyi = 3089 - INTEGER(IntKi), PARAMETER :: M2N3FAGyi = 3090 - INTEGER(IntKi), PARAMETER :: M2N4FAGyi = 3091 - INTEGER(IntKi), PARAMETER :: M2N5FAGyi = 3092 - INTEGER(IntKi), PARAMETER :: M2N6FAGyi = 3093 - INTEGER(IntKi), PARAMETER :: M2N7FAGyi = 3094 - INTEGER(IntKi), PARAMETER :: M2N8FAGyi = 3095 - INTEGER(IntKi), PARAMETER :: M2N9FAGyi = 3096 - INTEGER(IntKi), PARAMETER :: M3N1FAGyi = 3097 - INTEGER(IntKi), PARAMETER :: M3N2FAGyi = 3098 - INTEGER(IntKi), PARAMETER :: M3N3FAGyi = 3099 - INTEGER(IntKi), PARAMETER :: M3N4FAGyi = 3100 - INTEGER(IntKi), PARAMETER :: M3N5FAGyi = 3101 - INTEGER(IntKi), PARAMETER :: M3N6FAGyi = 3102 - INTEGER(IntKi), PARAMETER :: M3N7FAGyi = 3103 - INTEGER(IntKi), PARAMETER :: M3N8FAGyi = 3104 - INTEGER(IntKi), PARAMETER :: M3N9FAGyi = 3105 - INTEGER(IntKi), PARAMETER :: M4N1FAGyi = 3106 - INTEGER(IntKi), PARAMETER :: M4N2FAGyi = 3107 - INTEGER(IntKi), PARAMETER :: M4N3FAGyi = 3108 - INTEGER(IntKi), PARAMETER :: M4N4FAGyi = 3109 - INTEGER(IntKi), PARAMETER :: M4N5FAGyi = 3110 - INTEGER(IntKi), PARAMETER :: M4N6FAGyi = 3111 - INTEGER(IntKi), PARAMETER :: M4N7FAGyi = 3112 - INTEGER(IntKi), PARAMETER :: M4N8FAGyi = 3113 - INTEGER(IntKi), PARAMETER :: M4N9FAGyi = 3114 - INTEGER(IntKi), PARAMETER :: M5N1FAGyi = 3115 - INTEGER(IntKi), PARAMETER :: M5N2FAGyi = 3116 - INTEGER(IntKi), PARAMETER :: M5N3FAGyi = 3117 - INTEGER(IntKi), PARAMETER :: M5N4FAGyi = 3118 - INTEGER(IntKi), PARAMETER :: M5N5FAGyi = 3119 - INTEGER(IntKi), PARAMETER :: M5N6FAGyi = 3120 - INTEGER(IntKi), PARAMETER :: M5N7FAGyi = 3121 - INTEGER(IntKi), PARAMETER :: M5N8FAGyi = 3122 - INTEGER(IntKi), PARAMETER :: M5N9FAGyi = 3123 - INTEGER(IntKi), PARAMETER :: M6N1FAGyi = 3124 - INTEGER(IntKi), PARAMETER :: M6N2FAGyi = 3125 - INTEGER(IntKi), PARAMETER :: M6N3FAGyi = 3126 - INTEGER(IntKi), PARAMETER :: M6N4FAGyi = 3127 - INTEGER(IntKi), PARAMETER :: M6N5FAGyi = 3128 - INTEGER(IntKi), PARAMETER :: M6N6FAGyi = 3129 - INTEGER(IntKi), PARAMETER :: M6N7FAGyi = 3130 - INTEGER(IntKi), PARAMETER :: M6N8FAGyi = 3131 - INTEGER(IntKi), PARAMETER :: M6N9FAGyi = 3132 - INTEGER(IntKi), PARAMETER :: M7N1FAGyi = 3133 - INTEGER(IntKi), PARAMETER :: M7N2FAGyi = 3134 - INTEGER(IntKi), PARAMETER :: M7N3FAGyi = 3135 - INTEGER(IntKi), PARAMETER :: M7N4FAGyi = 3136 - INTEGER(IntKi), PARAMETER :: M7N5FAGyi = 3137 - INTEGER(IntKi), PARAMETER :: M7N6FAGyi = 3138 - INTEGER(IntKi), PARAMETER :: M7N7FAGyi = 3139 - INTEGER(IntKi), PARAMETER :: M7N8FAGyi = 3140 - INTEGER(IntKi), PARAMETER :: M7N9FAGyi = 3141 - INTEGER(IntKi), PARAMETER :: M8N1FAGyi = 3142 - INTEGER(IntKi), PARAMETER :: M8N2FAGyi = 3143 - INTEGER(IntKi), PARAMETER :: M8N3FAGyi = 3144 - INTEGER(IntKi), PARAMETER :: M8N4FAGyi = 3145 - INTEGER(IntKi), PARAMETER :: M8N5FAGyi = 3146 - INTEGER(IntKi), PARAMETER :: M8N6FAGyi = 3147 - INTEGER(IntKi), PARAMETER :: M8N7FAGyi = 3148 - INTEGER(IntKi), PARAMETER :: M8N8FAGyi = 3149 - INTEGER(IntKi), PARAMETER :: M8N9FAGyi = 3150 - INTEGER(IntKi), PARAMETER :: M9N1FAGyi = 3151 - INTEGER(IntKi), PARAMETER :: M9N2FAGyi = 3152 - INTEGER(IntKi), PARAMETER :: M9N3FAGyi = 3153 - INTEGER(IntKi), PARAMETER :: M9N4FAGyi = 3154 - INTEGER(IntKi), PARAMETER :: M9N5FAGyi = 3155 - INTEGER(IntKi), PARAMETER :: M9N6FAGyi = 3156 - INTEGER(IntKi), PARAMETER :: M9N7FAGyi = 3157 - INTEGER(IntKi), PARAMETER :: M9N8FAGyi = 3158 - INTEGER(IntKi), PARAMETER :: M9N9FAGyi = 3159 - INTEGER(IntKi), PARAMETER :: M1N1FAGzi = 3160 - INTEGER(IntKi), PARAMETER :: M1N2FAGzi = 3161 - INTEGER(IntKi), PARAMETER :: M1N3FAGzi = 3162 - INTEGER(IntKi), PARAMETER :: M1N4FAGzi = 3163 - INTEGER(IntKi), PARAMETER :: M1N5FAGzi = 3164 - INTEGER(IntKi), PARAMETER :: M1N6FAGzi = 3165 - INTEGER(IntKi), PARAMETER :: M1N7FAGzi = 3166 - INTEGER(IntKi), PARAMETER :: M1N8FAGzi = 3167 - INTEGER(IntKi), PARAMETER :: M1N9FAGzi = 3168 - INTEGER(IntKi), PARAMETER :: M2N1FAGzi = 3169 - INTEGER(IntKi), PARAMETER :: M2N2FAGzi = 3170 - INTEGER(IntKi), PARAMETER :: M2N3FAGzi = 3171 - INTEGER(IntKi), PARAMETER :: M2N4FAGzi = 3172 - INTEGER(IntKi), PARAMETER :: M2N5FAGzi = 3173 - INTEGER(IntKi), PARAMETER :: M2N6FAGzi = 3174 - INTEGER(IntKi), PARAMETER :: M2N7FAGzi = 3175 - INTEGER(IntKi), PARAMETER :: M2N8FAGzi = 3176 - INTEGER(IntKi), PARAMETER :: M2N9FAGzi = 3177 - INTEGER(IntKi), PARAMETER :: M3N1FAGzi = 3178 - INTEGER(IntKi), PARAMETER :: M3N2FAGzi = 3179 - INTEGER(IntKi), PARAMETER :: M3N3FAGzi = 3180 - INTEGER(IntKi), PARAMETER :: M3N4FAGzi = 3181 - INTEGER(IntKi), PARAMETER :: M3N5FAGzi = 3182 - INTEGER(IntKi), PARAMETER :: M3N6FAGzi = 3183 - INTEGER(IntKi), PARAMETER :: M3N7FAGzi = 3184 - INTEGER(IntKi), PARAMETER :: M3N8FAGzi = 3185 - INTEGER(IntKi), PARAMETER :: M3N9FAGzi = 3186 - INTEGER(IntKi), PARAMETER :: M4N1FAGzi = 3187 - INTEGER(IntKi), PARAMETER :: M4N2FAGzi = 3188 - INTEGER(IntKi), PARAMETER :: M4N3FAGzi = 3189 - INTEGER(IntKi), PARAMETER :: M4N4FAGzi = 3190 - INTEGER(IntKi), PARAMETER :: M4N5FAGzi = 3191 - INTEGER(IntKi), PARAMETER :: M4N6FAGzi = 3192 - INTEGER(IntKi), PARAMETER :: M4N7FAGzi = 3193 - INTEGER(IntKi), PARAMETER :: M4N8FAGzi = 3194 - INTEGER(IntKi), PARAMETER :: M4N9FAGzi = 3195 - INTEGER(IntKi), PARAMETER :: M5N1FAGzi = 3196 - INTEGER(IntKi), PARAMETER :: M5N2FAGzi = 3197 - INTEGER(IntKi), PARAMETER :: M5N3FAGzi = 3198 - INTEGER(IntKi), PARAMETER :: M5N4FAGzi = 3199 - INTEGER(IntKi), PARAMETER :: M5N5FAGzi = 3200 - INTEGER(IntKi), PARAMETER :: M5N6FAGzi = 3201 - INTEGER(IntKi), PARAMETER :: M5N7FAGzi = 3202 - INTEGER(IntKi), PARAMETER :: M5N8FAGzi = 3203 - INTEGER(IntKi), PARAMETER :: M5N9FAGzi = 3204 - INTEGER(IntKi), PARAMETER :: M6N1FAGzi = 3205 - INTEGER(IntKi), PARAMETER :: M6N2FAGzi = 3206 - INTEGER(IntKi), PARAMETER :: M6N3FAGzi = 3207 - INTEGER(IntKi), PARAMETER :: M6N4FAGzi = 3208 - INTEGER(IntKi), PARAMETER :: M6N5FAGzi = 3209 - INTEGER(IntKi), PARAMETER :: M6N6FAGzi = 3210 - INTEGER(IntKi), PARAMETER :: M6N7FAGzi = 3211 - INTEGER(IntKi), PARAMETER :: M6N8FAGzi = 3212 - INTEGER(IntKi), PARAMETER :: M6N9FAGzi = 3213 - INTEGER(IntKi), PARAMETER :: M7N1FAGzi = 3214 - INTEGER(IntKi), PARAMETER :: M7N2FAGzi = 3215 - INTEGER(IntKi), PARAMETER :: M7N3FAGzi = 3216 - INTEGER(IntKi), PARAMETER :: M7N4FAGzi = 3217 - INTEGER(IntKi), PARAMETER :: M7N5FAGzi = 3218 - INTEGER(IntKi), PARAMETER :: M7N6FAGzi = 3219 - INTEGER(IntKi), PARAMETER :: M7N7FAGzi = 3220 - INTEGER(IntKi), PARAMETER :: M7N8FAGzi = 3221 - INTEGER(IntKi), PARAMETER :: M7N9FAGzi = 3222 - INTEGER(IntKi), PARAMETER :: M8N1FAGzi = 3223 - INTEGER(IntKi), PARAMETER :: M8N2FAGzi = 3224 - INTEGER(IntKi), PARAMETER :: M8N3FAGzi = 3225 - INTEGER(IntKi), PARAMETER :: M8N4FAGzi = 3226 - INTEGER(IntKi), PARAMETER :: M8N5FAGzi = 3227 - INTEGER(IntKi), PARAMETER :: M8N6FAGzi = 3228 - INTEGER(IntKi), PARAMETER :: M8N7FAGzi = 3229 - INTEGER(IntKi), PARAMETER :: M8N8FAGzi = 3230 - INTEGER(IntKi), PARAMETER :: M8N9FAGzi = 3231 - INTEGER(IntKi), PARAMETER :: M9N1FAGzi = 3232 - INTEGER(IntKi), PARAMETER :: M9N2FAGzi = 3233 - INTEGER(IntKi), PARAMETER :: M9N3FAGzi = 3234 - INTEGER(IntKi), PARAMETER :: M9N4FAGzi = 3235 - INTEGER(IntKi), PARAMETER :: M9N5FAGzi = 3236 - INTEGER(IntKi), PARAMETER :: M9N6FAGzi = 3237 - INTEGER(IntKi), PARAMETER :: M9N7FAGzi = 3238 - INTEGER(IntKi), PARAMETER :: M9N8FAGzi = 3239 - INTEGER(IntKi), PARAMETER :: M9N9FAGzi = 3240 - INTEGER(IntKi), PARAMETER :: M1N1FAFxi = 3241 - INTEGER(IntKi), PARAMETER :: M1N2FAFxi = 3242 - INTEGER(IntKi), PARAMETER :: M1N3FAFxi = 3243 - INTEGER(IntKi), PARAMETER :: M1N4FAFxi = 3244 - INTEGER(IntKi), PARAMETER :: M1N5FAFxi = 3245 - INTEGER(IntKi), PARAMETER :: M1N6FAFxi = 3246 - INTEGER(IntKi), PARAMETER :: M1N7FAFxi = 3247 - INTEGER(IntKi), PARAMETER :: M1N8FAFxi = 3248 - INTEGER(IntKi), PARAMETER :: M1N9FAFxi = 3249 - INTEGER(IntKi), PARAMETER :: M2N1FAFxi = 3250 - INTEGER(IntKi), PARAMETER :: M2N2FAFxi = 3251 - INTEGER(IntKi), PARAMETER :: M2N3FAFxi = 3252 - INTEGER(IntKi), PARAMETER :: M2N4FAFxi = 3253 - INTEGER(IntKi), PARAMETER :: M2N5FAFxi = 3254 - INTEGER(IntKi), PARAMETER :: M2N6FAFxi = 3255 - INTEGER(IntKi), PARAMETER :: M2N7FAFxi = 3256 - INTEGER(IntKi), PARAMETER :: M2N8FAFxi = 3257 - INTEGER(IntKi), PARAMETER :: M2N9FAFxi = 3258 - INTEGER(IntKi), PARAMETER :: M3N1FAFxi = 3259 - INTEGER(IntKi), PARAMETER :: M3N2FAFxi = 3260 - INTEGER(IntKi), PARAMETER :: M3N3FAFxi = 3261 - INTEGER(IntKi), PARAMETER :: M3N4FAFxi = 3262 - INTEGER(IntKi), PARAMETER :: M3N5FAFxi = 3263 - INTEGER(IntKi), PARAMETER :: M3N6FAFxi = 3264 - INTEGER(IntKi), PARAMETER :: M3N7FAFxi = 3265 - INTEGER(IntKi), PARAMETER :: M3N8FAFxi = 3266 - INTEGER(IntKi), PARAMETER :: M3N9FAFxi = 3267 - INTEGER(IntKi), PARAMETER :: M4N1FAFxi = 3268 - INTEGER(IntKi), PARAMETER :: M4N2FAFxi = 3269 - INTEGER(IntKi), PARAMETER :: M4N3FAFxi = 3270 - INTEGER(IntKi), PARAMETER :: M4N4FAFxi = 3271 - INTEGER(IntKi), PARAMETER :: M4N5FAFxi = 3272 - INTEGER(IntKi), PARAMETER :: M4N6FAFxi = 3273 - INTEGER(IntKi), PARAMETER :: M4N7FAFxi = 3274 - INTEGER(IntKi), PARAMETER :: M4N8FAFxi = 3275 - INTEGER(IntKi), PARAMETER :: M4N9FAFxi = 3276 - INTEGER(IntKi), PARAMETER :: M5N1FAFxi = 3277 - INTEGER(IntKi), PARAMETER :: M5N2FAFxi = 3278 - INTEGER(IntKi), PARAMETER :: M5N3FAFxi = 3279 - INTEGER(IntKi), PARAMETER :: M5N4FAFxi = 3280 - INTEGER(IntKi), PARAMETER :: M5N5FAFxi = 3281 - INTEGER(IntKi), PARAMETER :: M5N6FAFxi = 3282 - INTEGER(IntKi), PARAMETER :: M5N7FAFxi = 3283 - INTEGER(IntKi), PARAMETER :: M5N8FAFxi = 3284 - INTEGER(IntKi), PARAMETER :: M5N9FAFxi = 3285 - INTEGER(IntKi), PARAMETER :: M6N1FAFxi = 3286 - INTEGER(IntKi), PARAMETER :: M6N2FAFxi = 3287 - INTEGER(IntKi), PARAMETER :: M6N3FAFxi = 3288 - INTEGER(IntKi), PARAMETER :: M6N4FAFxi = 3289 - INTEGER(IntKi), PARAMETER :: M6N5FAFxi = 3290 - INTEGER(IntKi), PARAMETER :: M6N6FAFxi = 3291 - INTEGER(IntKi), PARAMETER :: M6N7FAFxi = 3292 - INTEGER(IntKi), PARAMETER :: M6N8FAFxi = 3293 - INTEGER(IntKi), PARAMETER :: M6N9FAFxi = 3294 - INTEGER(IntKi), PARAMETER :: M7N1FAFxi = 3295 - INTEGER(IntKi), PARAMETER :: M7N2FAFxi = 3296 - INTEGER(IntKi), PARAMETER :: M7N3FAFxi = 3297 - INTEGER(IntKi), PARAMETER :: M7N4FAFxi = 3298 - INTEGER(IntKi), PARAMETER :: M7N5FAFxi = 3299 - INTEGER(IntKi), PARAMETER :: M7N6FAFxi = 3300 - INTEGER(IntKi), PARAMETER :: M7N7FAFxi = 3301 - INTEGER(IntKi), PARAMETER :: M7N8FAFxi = 3302 - INTEGER(IntKi), PARAMETER :: M7N9FAFxi = 3303 - INTEGER(IntKi), PARAMETER :: M8N1FAFxi = 3304 - INTEGER(IntKi), PARAMETER :: M8N2FAFxi = 3305 - INTEGER(IntKi), PARAMETER :: M8N3FAFxi = 3306 - INTEGER(IntKi), PARAMETER :: M8N4FAFxi = 3307 - INTEGER(IntKi), PARAMETER :: M8N5FAFxi = 3308 - INTEGER(IntKi), PARAMETER :: M8N6FAFxi = 3309 - INTEGER(IntKi), PARAMETER :: M8N7FAFxi = 3310 - INTEGER(IntKi), PARAMETER :: M8N8FAFxi = 3311 - INTEGER(IntKi), PARAMETER :: M8N9FAFxi = 3312 - INTEGER(IntKi), PARAMETER :: M9N1FAFxi = 3313 - INTEGER(IntKi), PARAMETER :: M9N2FAFxi = 3314 - INTEGER(IntKi), PARAMETER :: M9N3FAFxi = 3315 - INTEGER(IntKi), PARAMETER :: M9N4FAFxi = 3316 - INTEGER(IntKi), PARAMETER :: M9N5FAFxi = 3317 - INTEGER(IntKi), PARAMETER :: M9N6FAFxi = 3318 - INTEGER(IntKi), PARAMETER :: M9N7FAFxi = 3319 - INTEGER(IntKi), PARAMETER :: M9N8FAFxi = 3320 - INTEGER(IntKi), PARAMETER :: M9N9FAFxi = 3321 - INTEGER(IntKi), PARAMETER :: M1N1FAFyi = 3322 - INTEGER(IntKi), PARAMETER :: M1N2FAFyi = 3323 - INTEGER(IntKi), PARAMETER :: M1N3FAFyi = 3324 - INTEGER(IntKi), PARAMETER :: M1N4FAFyi = 3325 - INTEGER(IntKi), PARAMETER :: M1N5FAFyi = 3326 - INTEGER(IntKi), PARAMETER :: M1N6FAFyi = 3327 - INTEGER(IntKi), PARAMETER :: M1N7FAFyi = 3328 - INTEGER(IntKi), PARAMETER :: M1N8FAFyi = 3329 - INTEGER(IntKi), PARAMETER :: M1N9FAFyi = 3330 - INTEGER(IntKi), PARAMETER :: M2N1FAFyi = 3331 - INTEGER(IntKi), PARAMETER :: M2N2FAFyi = 3332 - INTEGER(IntKi), PARAMETER :: M2N3FAFyi = 3333 - INTEGER(IntKi), PARAMETER :: M2N4FAFyi = 3334 - INTEGER(IntKi), PARAMETER :: M2N5FAFyi = 3335 - INTEGER(IntKi), PARAMETER :: M2N6FAFyi = 3336 - INTEGER(IntKi), PARAMETER :: M2N7FAFyi = 3337 - INTEGER(IntKi), PARAMETER :: M2N8FAFyi = 3338 - INTEGER(IntKi), PARAMETER :: M2N9FAFyi = 3339 - INTEGER(IntKi), PARAMETER :: M3N1FAFyi = 3340 - INTEGER(IntKi), PARAMETER :: M3N2FAFyi = 3341 - INTEGER(IntKi), PARAMETER :: M3N3FAFyi = 3342 - INTEGER(IntKi), PARAMETER :: M3N4FAFyi = 3343 - INTEGER(IntKi), PARAMETER :: M3N5FAFyi = 3344 - INTEGER(IntKi), PARAMETER :: M3N6FAFyi = 3345 - INTEGER(IntKi), PARAMETER :: M3N7FAFyi = 3346 - INTEGER(IntKi), PARAMETER :: M3N8FAFyi = 3347 - INTEGER(IntKi), PARAMETER :: M3N9FAFyi = 3348 - INTEGER(IntKi), PARAMETER :: M4N1FAFyi = 3349 - INTEGER(IntKi), PARAMETER :: M4N2FAFyi = 3350 - INTEGER(IntKi), PARAMETER :: M4N3FAFyi = 3351 - INTEGER(IntKi), PARAMETER :: M4N4FAFyi = 3352 - INTEGER(IntKi), PARAMETER :: M4N5FAFyi = 3353 - INTEGER(IntKi), PARAMETER :: M4N6FAFyi = 3354 - INTEGER(IntKi), PARAMETER :: M4N7FAFyi = 3355 - INTEGER(IntKi), PARAMETER :: M4N8FAFyi = 3356 - INTEGER(IntKi), PARAMETER :: M4N9FAFyi = 3357 - INTEGER(IntKi), PARAMETER :: M5N1FAFyi = 3358 - INTEGER(IntKi), PARAMETER :: M5N2FAFyi = 3359 - INTEGER(IntKi), PARAMETER :: M5N3FAFyi = 3360 - INTEGER(IntKi), PARAMETER :: M5N4FAFyi = 3361 - INTEGER(IntKi), PARAMETER :: M5N5FAFyi = 3362 - INTEGER(IntKi), PARAMETER :: M5N6FAFyi = 3363 - INTEGER(IntKi), PARAMETER :: M5N7FAFyi = 3364 - INTEGER(IntKi), PARAMETER :: M5N8FAFyi = 3365 - INTEGER(IntKi), PARAMETER :: M5N9FAFyi = 3366 - INTEGER(IntKi), PARAMETER :: M6N1FAFyi = 3367 - INTEGER(IntKi), PARAMETER :: M6N2FAFyi = 3368 - INTEGER(IntKi), PARAMETER :: M6N3FAFyi = 3369 - INTEGER(IntKi), PARAMETER :: M6N4FAFyi = 3370 - INTEGER(IntKi), PARAMETER :: M6N5FAFyi = 3371 - INTEGER(IntKi), PARAMETER :: M6N6FAFyi = 3372 - INTEGER(IntKi), PARAMETER :: M6N7FAFyi = 3373 - INTEGER(IntKi), PARAMETER :: M6N8FAFyi = 3374 - INTEGER(IntKi), PARAMETER :: M6N9FAFyi = 3375 - INTEGER(IntKi), PARAMETER :: M7N1FAFyi = 3376 - INTEGER(IntKi), PARAMETER :: M7N2FAFyi = 3377 - INTEGER(IntKi), PARAMETER :: M7N3FAFyi = 3378 - INTEGER(IntKi), PARAMETER :: M7N4FAFyi = 3379 - INTEGER(IntKi), PARAMETER :: M7N5FAFyi = 3380 - INTEGER(IntKi), PARAMETER :: M7N6FAFyi = 3381 - INTEGER(IntKi), PARAMETER :: M7N7FAFyi = 3382 - INTEGER(IntKi), PARAMETER :: M7N8FAFyi = 3383 - INTEGER(IntKi), PARAMETER :: M7N9FAFyi = 3384 - INTEGER(IntKi), PARAMETER :: M8N1FAFyi = 3385 - INTEGER(IntKi), PARAMETER :: M8N2FAFyi = 3386 - INTEGER(IntKi), PARAMETER :: M8N3FAFyi = 3387 - INTEGER(IntKi), PARAMETER :: M8N4FAFyi = 3388 - INTEGER(IntKi), PARAMETER :: M8N5FAFyi = 3389 - INTEGER(IntKi), PARAMETER :: M8N6FAFyi = 3390 - INTEGER(IntKi), PARAMETER :: M8N7FAFyi = 3391 - INTEGER(IntKi), PARAMETER :: M8N8FAFyi = 3392 - INTEGER(IntKi), PARAMETER :: M8N9FAFyi = 3393 - INTEGER(IntKi), PARAMETER :: M9N1FAFyi = 3394 - INTEGER(IntKi), PARAMETER :: M9N2FAFyi = 3395 - INTEGER(IntKi), PARAMETER :: M9N3FAFyi = 3396 - INTEGER(IntKi), PARAMETER :: M9N4FAFyi = 3397 - INTEGER(IntKi), PARAMETER :: M9N5FAFyi = 3398 - INTEGER(IntKi), PARAMETER :: M9N6FAFyi = 3399 - INTEGER(IntKi), PARAMETER :: M9N7FAFyi = 3400 - INTEGER(IntKi), PARAMETER :: M9N8FAFyi = 3401 - INTEGER(IntKi), PARAMETER :: M9N9FAFyi = 3402 - INTEGER(IntKi), PARAMETER :: M1N1FAFzi = 3403 - INTEGER(IntKi), PARAMETER :: M1N2FAFzi = 3404 - INTEGER(IntKi), PARAMETER :: M1N3FAFzi = 3405 - INTEGER(IntKi), PARAMETER :: M1N4FAFzi = 3406 - INTEGER(IntKi), PARAMETER :: M1N5FAFzi = 3407 - INTEGER(IntKi), PARAMETER :: M1N6FAFzi = 3408 - INTEGER(IntKi), PARAMETER :: M1N7FAFzi = 3409 - INTEGER(IntKi), PARAMETER :: M1N8FAFzi = 3410 - INTEGER(IntKi), PARAMETER :: M1N9FAFzi = 3411 - INTEGER(IntKi), PARAMETER :: M2N1FAFzi = 3412 - INTEGER(IntKi), PARAMETER :: M2N2FAFzi = 3413 - INTEGER(IntKi), PARAMETER :: M2N3FAFzi = 3414 - INTEGER(IntKi), PARAMETER :: M2N4FAFzi = 3415 - INTEGER(IntKi), PARAMETER :: M2N5FAFzi = 3416 - INTEGER(IntKi), PARAMETER :: M2N6FAFzi = 3417 - INTEGER(IntKi), PARAMETER :: M2N7FAFzi = 3418 - INTEGER(IntKi), PARAMETER :: M2N8FAFzi = 3419 - INTEGER(IntKi), PARAMETER :: M2N9FAFzi = 3420 - INTEGER(IntKi), PARAMETER :: M3N1FAFzi = 3421 - INTEGER(IntKi), PARAMETER :: M3N2FAFzi = 3422 - INTEGER(IntKi), PARAMETER :: M3N3FAFzi = 3423 - INTEGER(IntKi), PARAMETER :: M3N4FAFzi = 3424 - INTEGER(IntKi), PARAMETER :: M3N5FAFzi = 3425 - INTEGER(IntKi), PARAMETER :: M3N6FAFzi = 3426 - INTEGER(IntKi), PARAMETER :: M3N7FAFzi = 3427 - INTEGER(IntKi), PARAMETER :: M3N8FAFzi = 3428 - INTEGER(IntKi), PARAMETER :: M3N9FAFzi = 3429 - INTEGER(IntKi), PARAMETER :: M4N1FAFzi = 3430 - INTEGER(IntKi), PARAMETER :: M4N2FAFzi = 3431 - INTEGER(IntKi), PARAMETER :: M4N3FAFzi = 3432 - INTEGER(IntKi), PARAMETER :: M4N4FAFzi = 3433 - INTEGER(IntKi), PARAMETER :: M4N5FAFzi = 3434 - INTEGER(IntKi), PARAMETER :: M4N6FAFzi = 3435 - INTEGER(IntKi), PARAMETER :: M4N7FAFzi = 3436 - INTEGER(IntKi), PARAMETER :: M4N8FAFzi = 3437 - INTEGER(IntKi), PARAMETER :: M4N9FAFzi = 3438 - INTEGER(IntKi), PARAMETER :: M5N1FAFzi = 3439 - INTEGER(IntKi), PARAMETER :: M5N2FAFzi = 3440 - INTEGER(IntKi), PARAMETER :: M5N3FAFzi = 3441 - INTEGER(IntKi), PARAMETER :: M5N4FAFzi = 3442 - INTEGER(IntKi), PARAMETER :: M5N5FAFzi = 3443 - INTEGER(IntKi), PARAMETER :: M5N6FAFzi = 3444 - INTEGER(IntKi), PARAMETER :: M5N7FAFzi = 3445 - INTEGER(IntKi), PARAMETER :: M5N8FAFzi = 3446 - INTEGER(IntKi), PARAMETER :: M5N9FAFzi = 3447 - INTEGER(IntKi), PARAMETER :: M6N1FAFzi = 3448 - INTEGER(IntKi), PARAMETER :: M6N2FAFzi = 3449 - INTEGER(IntKi), PARAMETER :: M6N3FAFzi = 3450 - INTEGER(IntKi), PARAMETER :: M6N4FAFzi = 3451 - INTEGER(IntKi), PARAMETER :: M6N5FAFzi = 3452 - INTEGER(IntKi), PARAMETER :: M6N6FAFzi = 3453 - INTEGER(IntKi), PARAMETER :: M6N7FAFzi = 3454 - INTEGER(IntKi), PARAMETER :: M6N8FAFzi = 3455 - INTEGER(IntKi), PARAMETER :: M6N9FAFzi = 3456 - INTEGER(IntKi), PARAMETER :: M7N1FAFzi = 3457 - INTEGER(IntKi), PARAMETER :: M7N2FAFzi = 3458 - INTEGER(IntKi), PARAMETER :: M7N3FAFzi = 3459 - INTEGER(IntKi), PARAMETER :: M7N4FAFzi = 3460 - INTEGER(IntKi), PARAMETER :: M7N5FAFzi = 3461 - INTEGER(IntKi), PARAMETER :: M7N6FAFzi = 3462 - INTEGER(IntKi), PARAMETER :: M7N7FAFzi = 3463 - INTEGER(IntKi), PARAMETER :: M7N8FAFzi = 3464 - INTEGER(IntKi), PARAMETER :: M7N9FAFzi = 3465 - INTEGER(IntKi), PARAMETER :: M8N1FAFzi = 3466 - INTEGER(IntKi), PARAMETER :: M8N2FAFzi = 3467 - INTEGER(IntKi), PARAMETER :: M8N3FAFzi = 3468 - INTEGER(IntKi), PARAMETER :: M8N4FAFzi = 3469 - INTEGER(IntKi), PARAMETER :: M8N5FAFzi = 3470 - INTEGER(IntKi), PARAMETER :: M8N6FAFzi = 3471 - INTEGER(IntKi), PARAMETER :: M8N7FAFzi = 3472 - INTEGER(IntKi), PARAMETER :: M8N8FAFzi = 3473 - INTEGER(IntKi), PARAMETER :: M8N9FAFzi = 3474 - INTEGER(IntKi), PARAMETER :: M9N1FAFzi = 3475 - INTEGER(IntKi), PARAMETER :: M9N2FAFzi = 3476 - INTEGER(IntKi), PARAMETER :: M9N3FAFzi = 3477 - INTEGER(IntKi), PARAMETER :: M9N4FAFzi = 3478 - INTEGER(IntKi), PARAMETER :: M9N5FAFzi = 3479 - INTEGER(IntKi), PARAMETER :: M9N6FAFzi = 3480 - INTEGER(IntKi), PARAMETER :: M9N7FAFzi = 3481 - INTEGER(IntKi), PARAMETER :: M9N8FAFzi = 3482 - INTEGER(IntKi), PARAMETER :: M9N9FAFzi = 3483 - INTEGER(IntKi), PARAMETER :: M1N1FAxi = 3484 - INTEGER(IntKi), PARAMETER :: M1N2FAxi = 3485 - INTEGER(IntKi), PARAMETER :: M1N3FAxi = 3486 - INTEGER(IntKi), PARAMETER :: M1N4FAxi = 3487 - INTEGER(IntKi), PARAMETER :: M1N5FAxi = 3488 - INTEGER(IntKi), PARAMETER :: M1N6FAxi = 3489 - INTEGER(IntKi), PARAMETER :: M1N7FAxi = 3490 - INTEGER(IntKi), PARAMETER :: M1N8FAxi = 3491 - INTEGER(IntKi), PARAMETER :: M1N9FAxi = 3492 - INTEGER(IntKi), PARAMETER :: M2N1FAxi = 3493 - INTEGER(IntKi), PARAMETER :: M2N2FAxi = 3494 - INTEGER(IntKi), PARAMETER :: M2N3FAxi = 3495 - INTEGER(IntKi), PARAMETER :: M2N4FAxi = 3496 - INTEGER(IntKi), PARAMETER :: M2N5FAxi = 3497 - INTEGER(IntKi), PARAMETER :: M2N6FAxi = 3498 - INTEGER(IntKi), PARAMETER :: M2N7FAxi = 3499 - INTEGER(IntKi), PARAMETER :: M2N8FAxi = 3500 - INTEGER(IntKi), PARAMETER :: M2N9FAxi = 3501 - INTEGER(IntKi), PARAMETER :: M3N1FAxi = 3502 - INTEGER(IntKi), PARAMETER :: M3N2FAxi = 3503 - INTEGER(IntKi), PARAMETER :: M3N3FAxi = 3504 - INTEGER(IntKi), PARAMETER :: M3N4FAxi = 3505 - INTEGER(IntKi), PARAMETER :: M3N5FAxi = 3506 - INTEGER(IntKi), PARAMETER :: M3N6FAxi = 3507 - INTEGER(IntKi), PARAMETER :: M3N7FAxi = 3508 - INTEGER(IntKi), PARAMETER :: M3N8FAxi = 3509 - INTEGER(IntKi), PARAMETER :: M3N9FAxi = 3510 - INTEGER(IntKi), PARAMETER :: M4N1FAxi = 3511 - INTEGER(IntKi), PARAMETER :: M4N2FAxi = 3512 - INTEGER(IntKi), PARAMETER :: M4N3FAxi = 3513 - INTEGER(IntKi), PARAMETER :: M4N4FAxi = 3514 - INTEGER(IntKi), PARAMETER :: M4N5FAxi = 3515 - INTEGER(IntKi), PARAMETER :: M4N6FAxi = 3516 - INTEGER(IntKi), PARAMETER :: M4N7FAxi = 3517 - INTEGER(IntKi), PARAMETER :: M4N8FAxi = 3518 - INTEGER(IntKi), PARAMETER :: M4N9FAxi = 3519 - INTEGER(IntKi), PARAMETER :: M5N1FAxi = 3520 - INTEGER(IntKi), PARAMETER :: M5N2FAxi = 3521 - INTEGER(IntKi), PARAMETER :: M5N3FAxi = 3522 - INTEGER(IntKi), PARAMETER :: M5N4FAxi = 3523 - INTEGER(IntKi), PARAMETER :: M5N5FAxi = 3524 - INTEGER(IntKi), PARAMETER :: M5N6FAxi = 3525 - INTEGER(IntKi), PARAMETER :: M5N7FAxi = 3526 - INTEGER(IntKi), PARAMETER :: M5N8FAxi = 3527 - INTEGER(IntKi), PARAMETER :: M5N9FAxi = 3528 - INTEGER(IntKi), PARAMETER :: M6N1FAxi = 3529 - INTEGER(IntKi), PARAMETER :: M6N2FAxi = 3530 - INTEGER(IntKi), PARAMETER :: M6N3FAxi = 3531 - INTEGER(IntKi), PARAMETER :: M6N4FAxi = 3532 - INTEGER(IntKi), PARAMETER :: M6N5FAxi = 3533 - INTEGER(IntKi), PARAMETER :: M6N6FAxi = 3534 - INTEGER(IntKi), PARAMETER :: M6N7FAxi = 3535 - INTEGER(IntKi), PARAMETER :: M6N8FAxi = 3536 - INTEGER(IntKi), PARAMETER :: M6N9FAxi = 3537 - INTEGER(IntKi), PARAMETER :: M7N1FAxi = 3538 - INTEGER(IntKi), PARAMETER :: M7N2FAxi = 3539 - INTEGER(IntKi), PARAMETER :: M7N3FAxi = 3540 - INTEGER(IntKi), PARAMETER :: M7N4FAxi = 3541 - INTEGER(IntKi), PARAMETER :: M7N5FAxi = 3542 - INTEGER(IntKi), PARAMETER :: M7N6FAxi = 3543 - INTEGER(IntKi), PARAMETER :: M7N7FAxi = 3544 - INTEGER(IntKi), PARAMETER :: M7N8FAxi = 3545 - INTEGER(IntKi), PARAMETER :: M7N9FAxi = 3546 - INTEGER(IntKi), PARAMETER :: M8N1FAxi = 3547 - INTEGER(IntKi), PARAMETER :: M8N2FAxi = 3548 - INTEGER(IntKi), PARAMETER :: M8N3FAxi = 3549 - INTEGER(IntKi), PARAMETER :: M8N4FAxi = 3550 - INTEGER(IntKi), PARAMETER :: M8N5FAxi = 3551 - INTEGER(IntKi), PARAMETER :: M8N6FAxi = 3552 - INTEGER(IntKi), PARAMETER :: M8N7FAxi = 3553 - INTEGER(IntKi), PARAMETER :: M8N8FAxi = 3554 - INTEGER(IntKi), PARAMETER :: M8N9FAxi = 3555 - INTEGER(IntKi), PARAMETER :: M9N1FAxi = 3556 - INTEGER(IntKi), PARAMETER :: M9N2FAxi = 3557 - INTEGER(IntKi), PARAMETER :: M9N3FAxi = 3558 - INTEGER(IntKi), PARAMETER :: M9N4FAxi = 3559 - INTEGER(IntKi), PARAMETER :: M9N5FAxi = 3560 - INTEGER(IntKi), PARAMETER :: M9N6FAxi = 3561 - INTEGER(IntKi), PARAMETER :: M9N7FAxi = 3562 - INTEGER(IntKi), PARAMETER :: M9N8FAxi = 3563 - INTEGER(IntKi), PARAMETER :: M9N9FAxi = 3564 - INTEGER(IntKi), PARAMETER :: M1N1FAyi = 3565 - INTEGER(IntKi), PARAMETER :: M1N2FAyi = 3566 - INTEGER(IntKi), PARAMETER :: M1N3FAyi = 3567 - INTEGER(IntKi), PARAMETER :: M1N4FAyi = 3568 - INTEGER(IntKi), PARAMETER :: M1N5FAyi = 3569 - INTEGER(IntKi), PARAMETER :: M1N6FAyi = 3570 - INTEGER(IntKi), PARAMETER :: M1N7FAyi = 3571 - INTEGER(IntKi), PARAMETER :: M1N8FAyi = 3572 - INTEGER(IntKi), PARAMETER :: M1N9FAyi = 3573 - INTEGER(IntKi), PARAMETER :: M2N1FAyi = 3574 - INTEGER(IntKi), PARAMETER :: M2N2FAyi = 3575 - INTEGER(IntKi), PARAMETER :: M2N3FAyi = 3576 - INTEGER(IntKi), PARAMETER :: M2N4FAyi = 3577 - INTEGER(IntKi), PARAMETER :: M2N5FAyi = 3578 - INTEGER(IntKi), PARAMETER :: M2N6FAyi = 3579 - INTEGER(IntKi), PARAMETER :: M2N7FAyi = 3580 - INTEGER(IntKi), PARAMETER :: M2N8FAyi = 3581 - INTEGER(IntKi), PARAMETER :: M2N9FAyi = 3582 - INTEGER(IntKi), PARAMETER :: M3N1FAyi = 3583 - INTEGER(IntKi), PARAMETER :: M3N2FAyi = 3584 - INTEGER(IntKi), PARAMETER :: M3N3FAyi = 3585 - INTEGER(IntKi), PARAMETER :: M3N4FAyi = 3586 - INTEGER(IntKi), PARAMETER :: M3N5FAyi = 3587 - INTEGER(IntKi), PARAMETER :: M3N6FAyi = 3588 - INTEGER(IntKi), PARAMETER :: M3N7FAyi = 3589 - INTEGER(IntKi), PARAMETER :: M3N8FAyi = 3590 - INTEGER(IntKi), PARAMETER :: M3N9FAyi = 3591 - INTEGER(IntKi), PARAMETER :: M4N1FAyi = 3592 - INTEGER(IntKi), PARAMETER :: M4N2FAyi = 3593 - INTEGER(IntKi), PARAMETER :: M4N3FAyi = 3594 - INTEGER(IntKi), PARAMETER :: M4N4FAyi = 3595 - INTEGER(IntKi), PARAMETER :: M4N5FAyi = 3596 - INTEGER(IntKi), PARAMETER :: M4N6FAyi = 3597 - INTEGER(IntKi), PARAMETER :: M4N7FAyi = 3598 - INTEGER(IntKi), PARAMETER :: M4N8FAyi = 3599 - INTEGER(IntKi), PARAMETER :: M4N9FAyi = 3600 - INTEGER(IntKi), PARAMETER :: M5N1FAyi = 3601 - INTEGER(IntKi), PARAMETER :: M5N2FAyi = 3602 - INTEGER(IntKi), PARAMETER :: M5N3FAyi = 3603 - INTEGER(IntKi), PARAMETER :: M5N4FAyi = 3604 - INTEGER(IntKi), PARAMETER :: M5N5FAyi = 3605 - INTEGER(IntKi), PARAMETER :: M5N6FAyi = 3606 - INTEGER(IntKi), PARAMETER :: M5N7FAyi = 3607 - INTEGER(IntKi), PARAMETER :: M5N8FAyi = 3608 - INTEGER(IntKi), PARAMETER :: M5N9FAyi = 3609 - INTEGER(IntKi), PARAMETER :: M6N1FAyi = 3610 - INTEGER(IntKi), PARAMETER :: M6N2FAyi = 3611 - INTEGER(IntKi), PARAMETER :: M6N3FAyi = 3612 - INTEGER(IntKi), PARAMETER :: M6N4FAyi = 3613 - INTEGER(IntKi), PARAMETER :: M6N5FAyi = 3614 - INTEGER(IntKi), PARAMETER :: M6N6FAyi = 3615 - INTEGER(IntKi), PARAMETER :: M6N7FAyi = 3616 - INTEGER(IntKi), PARAMETER :: M6N8FAyi = 3617 - INTEGER(IntKi), PARAMETER :: M6N9FAyi = 3618 - INTEGER(IntKi), PARAMETER :: M7N1FAyi = 3619 - INTEGER(IntKi), PARAMETER :: M7N2FAyi = 3620 - INTEGER(IntKi), PARAMETER :: M7N3FAyi = 3621 - INTEGER(IntKi), PARAMETER :: M7N4FAyi = 3622 - INTEGER(IntKi), PARAMETER :: M7N5FAyi = 3623 - INTEGER(IntKi), PARAMETER :: M7N6FAyi = 3624 - INTEGER(IntKi), PARAMETER :: M7N7FAyi = 3625 - INTEGER(IntKi), PARAMETER :: M7N8FAyi = 3626 - INTEGER(IntKi), PARAMETER :: M7N9FAyi = 3627 - INTEGER(IntKi), PARAMETER :: M8N1FAyi = 3628 - INTEGER(IntKi), PARAMETER :: M8N2FAyi = 3629 - INTEGER(IntKi), PARAMETER :: M8N3FAyi = 3630 - INTEGER(IntKi), PARAMETER :: M8N4FAyi = 3631 - INTEGER(IntKi), PARAMETER :: M8N5FAyi = 3632 - INTEGER(IntKi), PARAMETER :: M8N6FAyi = 3633 - INTEGER(IntKi), PARAMETER :: M8N7FAyi = 3634 - INTEGER(IntKi), PARAMETER :: M8N8FAyi = 3635 - INTEGER(IntKi), PARAMETER :: M8N9FAyi = 3636 - INTEGER(IntKi), PARAMETER :: M9N1FAyi = 3637 - INTEGER(IntKi), PARAMETER :: M9N2FAyi = 3638 - INTEGER(IntKi), PARAMETER :: M9N3FAyi = 3639 - INTEGER(IntKi), PARAMETER :: M9N4FAyi = 3640 - INTEGER(IntKi), PARAMETER :: M9N5FAyi = 3641 - INTEGER(IntKi), PARAMETER :: M9N6FAyi = 3642 - INTEGER(IntKi), PARAMETER :: M9N7FAyi = 3643 - INTEGER(IntKi), PARAMETER :: M9N8FAyi = 3644 - INTEGER(IntKi), PARAMETER :: M9N9FAyi = 3645 - INTEGER(IntKi), PARAMETER :: M1N1FAzi = 3646 - INTEGER(IntKi), PARAMETER :: M1N2FAzi = 3647 - INTEGER(IntKi), PARAMETER :: M1N3FAzi = 3648 - INTEGER(IntKi), PARAMETER :: M1N4FAzi = 3649 - INTEGER(IntKi), PARAMETER :: M1N5FAzi = 3650 - INTEGER(IntKi), PARAMETER :: M1N6FAzi = 3651 - INTEGER(IntKi), PARAMETER :: M1N7FAzi = 3652 - INTEGER(IntKi), PARAMETER :: M1N8FAzi = 3653 - INTEGER(IntKi), PARAMETER :: M1N9FAzi = 3654 - INTEGER(IntKi), PARAMETER :: M2N1FAzi = 3655 - INTEGER(IntKi), PARAMETER :: M2N2FAzi = 3656 - INTEGER(IntKi), PARAMETER :: M2N3FAzi = 3657 - INTEGER(IntKi), PARAMETER :: M2N4FAzi = 3658 - INTEGER(IntKi), PARAMETER :: M2N5FAzi = 3659 - INTEGER(IntKi), PARAMETER :: M2N6FAzi = 3660 - INTEGER(IntKi), PARAMETER :: M2N7FAzi = 3661 - INTEGER(IntKi), PARAMETER :: M2N8FAzi = 3662 - INTEGER(IntKi), PARAMETER :: M2N9FAzi = 3663 - INTEGER(IntKi), PARAMETER :: M3N1FAzi = 3664 - INTEGER(IntKi), PARAMETER :: M3N2FAzi = 3665 - INTEGER(IntKi), PARAMETER :: M3N3FAzi = 3666 - INTEGER(IntKi), PARAMETER :: M3N4FAzi = 3667 - INTEGER(IntKi), PARAMETER :: M3N5FAzi = 3668 - INTEGER(IntKi), PARAMETER :: M3N6FAzi = 3669 - INTEGER(IntKi), PARAMETER :: M3N7FAzi = 3670 - INTEGER(IntKi), PARAMETER :: M3N8FAzi = 3671 - INTEGER(IntKi), PARAMETER :: M3N9FAzi = 3672 - INTEGER(IntKi), PARAMETER :: M4N1FAzi = 3673 - INTEGER(IntKi), PARAMETER :: M4N2FAzi = 3674 - INTEGER(IntKi), PARAMETER :: M4N3FAzi = 3675 - INTEGER(IntKi), PARAMETER :: M4N4FAzi = 3676 - INTEGER(IntKi), PARAMETER :: M4N5FAzi = 3677 - INTEGER(IntKi), PARAMETER :: M4N6FAzi = 3678 - INTEGER(IntKi), PARAMETER :: M4N7FAzi = 3679 - INTEGER(IntKi), PARAMETER :: M4N8FAzi = 3680 - INTEGER(IntKi), PARAMETER :: M4N9FAzi = 3681 - INTEGER(IntKi), PARAMETER :: M5N1FAzi = 3682 - INTEGER(IntKi), PARAMETER :: M5N2FAzi = 3683 - INTEGER(IntKi), PARAMETER :: M5N3FAzi = 3684 - INTEGER(IntKi), PARAMETER :: M5N4FAzi = 3685 - INTEGER(IntKi), PARAMETER :: M5N5FAzi = 3686 - INTEGER(IntKi), PARAMETER :: M5N6FAzi = 3687 - INTEGER(IntKi), PARAMETER :: M5N7FAzi = 3688 - INTEGER(IntKi), PARAMETER :: M5N8FAzi = 3689 - INTEGER(IntKi), PARAMETER :: M5N9FAzi = 3690 - INTEGER(IntKi), PARAMETER :: M6N1FAzi = 3691 - INTEGER(IntKi), PARAMETER :: M6N2FAzi = 3692 - INTEGER(IntKi), PARAMETER :: M6N3FAzi = 3693 - INTEGER(IntKi), PARAMETER :: M6N4FAzi = 3694 - INTEGER(IntKi), PARAMETER :: M6N5FAzi = 3695 - INTEGER(IntKi), PARAMETER :: M6N6FAzi = 3696 - INTEGER(IntKi), PARAMETER :: M6N7FAzi = 3697 - INTEGER(IntKi), PARAMETER :: M6N8FAzi = 3698 - INTEGER(IntKi), PARAMETER :: M6N9FAzi = 3699 - INTEGER(IntKi), PARAMETER :: M7N1FAzi = 3700 - INTEGER(IntKi), PARAMETER :: M7N2FAzi = 3701 - INTEGER(IntKi), PARAMETER :: M7N3FAzi = 3702 - INTEGER(IntKi), PARAMETER :: M7N4FAzi = 3703 - INTEGER(IntKi), PARAMETER :: M7N5FAzi = 3704 - INTEGER(IntKi), PARAMETER :: M7N6FAzi = 3705 - INTEGER(IntKi), PARAMETER :: M7N7FAzi = 3706 - INTEGER(IntKi), PARAMETER :: M7N8FAzi = 3707 - INTEGER(IntKi), PARAMETER :: M7N9FAzi = 3708 - INTEGER(IntKi), PARAMETER :: M8N1FAzi = 3709 - INTEGER(IntKi), PARAMETER :: M8N2FAzi = 3710 - INTEGER(IntKi), PARAMETER :: M8N3FAzi = 3711 - INTEGER(IntKi), PARAMETER :: M8N4FAzi = 3712 - INTEGER(IntKi), PARAMETER :: M8N5FAzi = 3713 - INTEGER(IntKi), PARAMETER :: M8N6FAzi = 3714 - INTEGER(IntKi), PARAMETER :: M8N7FAzi = 3715 - INTEGER(IntKi), PARAMETER :: M8N8FAzi = 3716 - INTEGER(IntKi), PARAMETER :: M8N9FAzi = 3717 - INTEGER(IntKi), PARAMETER :: M9N1FAzi = 3718 - INTEGER(IntKi), PARAMETER :: M9N2FAzi = 3719 - INTEGER(IntKi), PARAMETER :: M9N3FAzi = 3720 - INTEGER(IntKi), PARAMETER :: M9N4FAzi = 3721 - INTEGER(IntKi), PARAMETER :: M9N5FAzi = 3722 - INTEGER(IntKi), PARAMETER :: M9N6FAzi = 3723 - INTEGER(IntKi), PARAMETER :: M9N7FAzi = 3724 - INTEGER(IntKi), PARAMETER :: M9N8FAzi = 3725 - INTEGER(IntKi), PARAMETER :: M9N9FAzi = 3726 - + INTEGER(IntKi), PARAMETER :: M1N1MMGxi = 2755 + INTEGER(IntKi), PARAMETER :: M1N2MMGxi = 2756 + INTEGER(IntKi), PARAMETER :: M1N3MMGxi = 2757 + INTEGER(IntKi), PARAMETER :: M1N4MMGxi = 2758 + INTEGER(IntKi), PARAMETER :: M1N5MMGxi = 2759 + INTEGER(IntKi), PARAMETER :: M1N6MMGxi = 2760 + INTEGER(IntKi), PARAMETER :: M1N7MMGxi = 2761 + INTEGER(IntKi), PARAMETER :: M1N8MMGxi = 2762 + INTEGER(IntKi), PARAMETER :: M1N9MMGxi = 2763 + INTEGER(IntKi), PARAMETER :: M2N1MMGxi = 2764 + INTEGER(IntKi), PARAMETER :: M2N2MMGxi = 2765 + INTEGER(IntKi), PARAMETER :: M2N3MMGxi = 2766 + INTEGER(IntKi), PARAMETER :: M2N4MMGxi = 2767 + INTEGER(IntKi), PARAMETER :: M2N5MMGxi = 2768 + INTEGER(IntKi), PARAMETER :: M2N6MMGxi = 2769 + INTEGER(IntKi), PARAMETER :: M2N7MMGxi = 2770 + INTEGER(IntKi), PARAMETER :: M2N8MMGxi = 2771 + INTEGER(IntKi), PARAMETER :: M2N9MMGxi = 2772 + INTEGER(IntKi), PARAMETER :: M3N1MMGxi = 2773 + INTEGER(IntKi), PARAMETER :: M3N2MMGxi = 2774 + INTEGER(IntKi), PARAMETER :: M3N3MMGxi = 2775 + INTEGER(IntKi), PARAMETER :: M3N4MMGxi = 2776 + INTEGER(IntKi), PARAMETER :: M3N5MMGxi = 2777 + INTEGER(IntKi), PARAMETER :: M3N6MMGxi = 2778 + INTEGER(IntKi), PARAMETER :: M3N7MMGxi = 2779 + INTEGER(IntKi), PARAMETER :: M3N8MMGxi = 2780 + INTEGER(IntKi), PARAMETER :: M3N9MMGxi = 2781 + INTEGER(IntKi), PARAMETER :: M4N1MMGxi = 2782 + INTEGER(IntKi), PARAMETER :: M4N2MMGxi = 2783 + INTEGER(IntKi), PARAMETER :: M4N3MMGxi = 2784 + INTEGER(IntKi), PARAMETER :: M4N4MMGxi = 2785 + INTEGER(IntKi), PARAMETER :: M4N5MMGxi = 2786 + INTEGER(IntKi), PARAMETER :: M4N6MMGxi = 2787 + INTEGER(IntKi), PARAMETER :: M4N7MMGxi = 2788 + INTEGER(IntKi), PARAMETER :: M4N8MMGxi = 2789 + INTEGER(IntKi), PARAMETER :: M4N9MMGxi = 2790 + INTEGER(IntKi), PARAMETER :: M5N1MMGxi = 2791 + INTEGER(IntKi), PARAMETER :: M5N2MMGxi = 2792 + INTEGER(IntKi), PARAMETER :: M5N3MMGxi = 2793 + INTEGER(IntKi), PARAMETER :: M5N4MMGxi = 2794 + INTEGER(IntKi), PARAMETER :: M5N5MMGxi = 2795 + INTEGER(IntKi), PARAMETER :: M5N6MMGxi = 2796 + INTEGER(IntKi), PARAMETER :: M5N7MMGxi = 2797 + INTEGER(IntKi), PARAMETER :: M5N8MMGxi = 2798 + INTEGER(IntKi), PARAMETER :: M5N9MMGxi = 2799 + INTEGER(IntKi), PARAMETER :: M6N1MMGxi = 2800 + INTEGER(IntKi), PARAMETER :: M6N2MMGxi = 2801 + INTEGER(IntKi), PARAMETER :: M6N3MMGxi = 2802 + INTEGER(IntKi), PARAMETER :: M6N4MMGxi = 2803 + INTEGER(IntKi), PARAMETER :: M6N5MMGxi = 2804 + INTEGER(IntKi), PARAMETER :: M6N6MMGxi = 2805 + INTEGER(IntKi), PARAMETER :: M6N7MMGxi = 2806 + INTEGER(IntKi), PARAMETER :: M6N8MMGxi = 2807 + INTEGER(IntKi), PARAMETER :: M6N9MMGxi = 2808 + INTEGER(IntKi), PARAMETER :: M7N1MMGxi = 2809 + INTEGER(IntKi), PARAMETER :: M7N2MMGxi = 2810 + INTEGER(IntKi), PARAMETER :: M7N3MMGxi = 2811 + INTEGER(IntKi), PARAMETER :: M7N4MMGxi = 2812 + INTEGER(IntKi), PARAMETER :: M7N5MMGxi = 2813 + INTEGER(IntKi), PARAMETER :: M7N6MMGxi = 2814 + INTEGER(IntKi), PARAMETER :: M7N7MMGxi = 2815 + INTEGER(IntKi), PARAMETER :: M7N8MMGxi = 2816 + INTEGER(IntKi), PARAMETER :: M7N9MMGxi = 2817 + INTEGER(IntKi), PARAMETER :: M8N1MMGxi = 2818 + INTEGER(IntKi), PARAMETER :: M8N2MMGxi = 2819 + INTEGER(IntKi), PARAMETER :: M8N3MMGxi = 2820 + INTEGER(IntKi), PARAMETER :: M8N4MMGxi = 2821 + INTEGER(IntKi), PARAMETER :: M8N5MMGxi = 2822 + INTEGER(IntKi), PARAMETER :: M8N6MMGxi = 2823 + INTEGER(IntKi), PARAMETER :: M8N7MMGxi = 2824 + INTEGER(IntKi), PARAMETER :: M8N8MMGxi = 2825 + INTEGER(IntKi), PARAMETER :: M8N9MMGxi = 2826 + INTEGER(IntKi), PARAMETER :: M9N1MMGxi = 2827 + INTEGER(IntKi), PARAMETER :: M9N2MMGxi = 2828 + INTEGER(IntKi), PARAMETER :: M9N3MMGxi = 2829 + INTEGER(IntKi), PARAMETER :: M9N4MMGxi = 2830 + INTEGER(IntKi), PARAMETER :: M9N5MMGxi = 2831 + INTEGER(IntKi), PARAMETER :: M9N6MMGxi = 2832 + INTEGER(IntKi), PARAMETER :: M9N7MMGxi = 2833 + INTEGER(IntKi), PARAMETER :: M9N8MMGxi = 2834 + INTEGER(IntKi), PARAMETER :: M9N9MMGxi = 2835 + INTEGER(IntKi), PARAMETER :: M1N1MMGyi = 2836 + INTEGER(IntKi), PARAMETER :: M1N2MMGyi = 2837 + INTEGER(IntKi), PARAMETER :: M1N3MMGyi = 2838 + INTEGER(IntKi), PARAMETER :: M1N4MMGyi = 2839 + INTEGER(IntKi), PARAMETER :: M1N5MMGyi = 2840 + INTEGER(IntKi), PARAMETER :: M1N6MMGyi = 2841 + INTEGER(IntKi), PARAMETER :: M1N7MMGyi = 2842 + INTEGER(IntKi), PARAMETER :: M1N8MMGyi = 2843 + INTEGER(IntKi), PARAMETER :: M1N9MMGyi = 2844 + INTEGER(IntKi), PARAMETER :: M2N1MMGyi = 2845 + INTEGER(IntKi), PARAMETER :: M2N2MMGyi = 2846 + INTEGER(IntKi), PARAMETER :: M2N3MMGyi = 2847 + INTEGER(IntKi), PARAMETER :: M2N4MMGyi = 2848 + INTEGER(IntKi), PARAMETER :: M2N5MMGyi = 2849 + INTEGER(IntKi), PARAMETER :: M2N6MMGyi = 2850 + INTEGER(IntKi), PARAMETER :: M2N7MMGyi = 2851 + INTEGER(IntKi), PARAMETER :: M2N8MMGyi = 2852 + INTEGER(IntKi), PARAMETER :: M2N9MMGyi = 2853 + INTEGER(IntKi), PARAMETER :: M3N1MMGyi = 2854 + INTEGER(IntKi), PARAMETER :: M3N2MMGyi = 2855 + INTEGER(IntKi), PARAMETER :: M3N3MMGyi = 2856 + INTEGER(IntKi), PARAMETER :: M3N4MMGyi = 2857 + INTEGER(IntKi), PARAMETER :: M3N5MMGyi = 2858 + INTEGER(IntKi), PARAMETER :: M3N6MMGyi = 2859 + INTEGER(IntKi), PARAMETER :: M3N7MMGyi = 2860 + INTEGER(IntKi), PARAMETER :: M3N8MMGyi = 2861 + INTEGER(IntKi), PARAMETER :: M3N9MMGyi = 2862 + INTEGER(IntKi), PARAMETER :: M4N1MMGyi = 2863 + INTEGER(IntKi), PARAMETER :: M4N2MMGyi = 2864 + INTEGER(IntKi), PARAMETER :: M4N3MMGyi = 2865 + INTEGER(IntKi), PARAMETER :: M4N4MMGyi = 2866 + INTEGER(IntKi), PARAMETER :: M4N5MMGyi = 2867 + INTEGER(IntKi), PARAMETER :: M4N6MMGyi = 2868 + INTEGER(IntKi), PARAMETER :: M4N7MMGyi = 2869 + INTEGER(IntKi), PARAMETER :: M4N8MMGyi = 2870 + INTEGER(IntKi), PARAMETER :: M4N9MMGyi = 2871 + INTEGER(IntKi), PARAMETER :: M5N1MMGyi = 2872 + INTEGER(IntKi), PARAMETER :: M5N2MMGyi = 2873 + INTEGER(IntKi), PARAMETER :: M5N3MMGyi = 2874 + INTEGER(IntKi), PARAMETER :: M5N4MMGyi = 2875 + INTEGER(IntKi), PARAMETER :: M5N5MMGyi = 2876 + INTEGER(IntKi), PARAMETER :: M5N6MMGyi = 2877 + INTEGER(IntKi), PARAMETER :: M5N7MMGyi = 2878 + INTEGER(IntKi), PARAMETER :: M5N8MMGyi = 2879 + INTEGER(IntKi), PARAMETER :: M5N9MMGyi = 2880 + INTEGER(IntKi), PARAMETER :: M6N1MMGyi = 2881 + INTEGER(IntKi), PARAMETER :: M6N2MMGyi = 2882 + INTEGER(IntKi), PARAMETER :: M6N3MMGyi = 2883 + INTEGER(IntKi), PARAMETER :: M6N4MMGyi = 2884 + INTEGER(IntKi), PARAMETER :: M6N5MMGyi = 2885 + INTEGER(IntKi), PARAMETER :: M6N6MMGyi = 2886 + INTEGER(IntKi), PARAMETER :: M6N7MMGyi = 2887 + INTEGER(IntKi), PARAMETER :: M6N8MMGyi = 2888 + INTEGER(IntKi), PARAMETER :: M6N9MMGyi = 2889 + INTEGER(IntKi), PARAMETER :: M7N1MMGyi = 2890 + INTEGER(IntKi), PARAMETER :: M7N2MMGyi = 2891 + INTEGER(IntKi), PARAMETER :: M7N3MMGyi = 2892 + INTEGER(IntKi), PARAMETER :: M7N4MMGyi = 2893 + INTEGER(IntKi), PARAMETER :: M7N5MMGyi = 2894 + INTEGER(IntKi), PARAMETER :: M7N6MMGyi = 2895 + INTEGER(IntKi), PARAMETER :: M7N7MMGyi = 2896 + INTEGER(IntKi), PARAMETER :: M7N8MMGyi = 2897 + INTEGER(IntKi), PARAMETER :: M7N9MMGyi = 2898 + INTEGER(IntKi), PARAMETER :: M8N1MMGyi = 2899 + INTEGER(IntKi), PARAMETER :: M8N2MMGyi = 2900 + INTEGER(IntKi), PARAMETER :: M8N3MMGyi = 2901 + INTEGER(IntKi), PARAMETER :: M8N4MMGyi = 2902 + INTEGER(IntKi), PARAMETER :: M8N5MMGyi = 2903 + INTEGER(IntKi), PARAMETER :: M8N6MMGyi = 2904 + INTEGER(IntKi), PARAMETER :: M8N7MMGyi = 2905 + INTEGER(IntKi), PARAMETER :: M8N8MMGyi = 2906 + INTEGER(IntKi), PARAMETER :: M8N9MMGyi = 2907 + INTEGER(IntKi), PARAMETER :: M9N1MMGyi = 2908 + INTEGER(IntKi), PARAMETER :: M9N2MMGyi = 2909 + INTEGER(IntKi), PARAMETER :: M9N3MMGyi = 2910 + INTEGER(IntKi), PARAMETER :: M9N4MMGyi = 2911 + INTEGER(IntKi), PARAMETER :: M9N5MMGyi = 2912 + INTEGER(IntKi), PARAMETER :: M9N6MMGyi = 2913 + INTEGER(IntKi), PARAMETER :: M9N7MMGyi = 2914 + INTEGER(IntKi), PARAMETER :: M9N8MMGyi = 2915 + INTEGER(IntKi), PARAMETER :: M9N9MMGyi = 2916 + INTEGER(IntKi), PARAMETER :: M1N1MMGzi = 2917 + INTEGER(IntKi), PARAMETER :: M1N2MMGzi = 2918 + INTEGER(IntKi), PARAMETER :: M1N3MMGzi = 2919 + INTEGER(IntKi), PARAMETER :: M1N4MMGzi = 2920 + INTEGER(IntKi), PARAMETER :: M1N5MMGzi = 2921 + INTEGER(IntKi), PARAMETER :: M1N6MMGzi = 2922 + INTEGER(IntKi), PARAMETER :: M1N7MMGzi = 2923 + INTEGER(IntKi), PARAMETER :: M1N8MMGzi = 2924 + INTEGER(IntKi), PARAMETER :: M1N9MMGzi = 2925 + INTEGER(IntKi), PARAMETER :: M2N1MMGzi = 2926 + INTEGER(IntKi), PARAMETER :: M2N2MMGzi = 2927 + INTEGER(IntKi), PARAMETER :: M2N3MMGzi = 2928 + INTEGER(IntKi), PARAMETER :: M2N4MMGzi = 2929 + INTEGER(IntKi), PARAMETER :: M2N5MMGzi = 2930 + INTEGER(IntKi), PARAMETER :: M2N6MMGzi = 2931 + INTEGER(IntKi), PARAMETER :: M2N7MMGzi = 2932 + INTEGER(IntKi), PARAMETER :: M2N8MMGzi = 2933 + INTEGER(IntKi), PARAMETER :: M2N9MMGzi = 2934 + INTEGER(IntKi), PARAMETER :: M3N1MMGzi = 2935 + INTEGER(IntKi), PARAMETER :: M3N2MMGzi = 2936 + INTEGER(IntKi), PARAMETER :: M3N3MMGzi = 2937 + INTEGER(IntKi), PARAMETER :: M3N4MMGzi = 2938 + INTEGER(IntKi), PARAMETER :: M3N5MMGzi = 2939 + INTEGER(IntKi), PARAMETER :: M3N6MMGzi = 2940 + INTEGER(IntKi), PARAMETER :: M3N7MMGzi = 2941 + INTEGER(IntKi), PARAMETER :: M3N8MMGzi = 2942 + INTEGER(IntKi), PARAMETER :: M3N9MMGzi = 2943 + INTEGER(IntKi), PARAMETER :: M4N1MMGzi = 2944 + INTEGER(IntKi), PARAMETER :: M4N2MMGzi = 2945 + INTEGER(IntKi), PARAMETER :: M4N3MMGzi = 2946 + INTEGER(IntKi), PARAMETER :: M4N4MMGzi = 2947 + INTEGER(IntKi), PARAMETER :: M4N5MMGzi = 2948 + INTEGER(IntKi), PARAMETER :: M4N6MMGzi = 2949 + INTEGER(IntKi), PARAMETER :: M4N7MMGzi = 2950 + INTEGER(IntKi), PARAMETER :: M4N8MMGzi = 2951 + INTEGER(IntKi), PARAMETER :: M4N9MMGzi = 2952 + INTEGER(IntKi), PARAMETER :: M5N1MMGzi = 2953 + INTEGER(IntKi), PARAMETER :: M5N2MMGzi = 2954 + INTEGER(IntKi), PARAMETER :: M5N3MMGzi = 2955 + INTEGER(IntKi), PARAMETER :: M5N4MMGzi = 2956 + INTEGER(IntKi), PARAMETER :: M5N5MMGzi = 2957 + INTEGER(IntKi), PARAMETER :: M5N6MMGzi = 2958 + INTEGER(IntKi), PARAMETER :: M5N7MMGzi = 2959 + INTEGER(IntKi), PARAMETER :: M5N8MMGzi = 2960 + INTEGER(IntKi), PARAMETER :: M5N9MMGzi = 2961 + INTEGER(IntKi), PARAMETER :: M6N1MMGzi = 2962 + INTEGER(IntKi), PARAMETER :: M6N2MMGzi = 2963 + INTEGER(IntKi), PARAMETER :: M6N3MMGzi = 2964 + INTEGER(IntKi), PARAMETER :: M6N4MMGzi = 2965 + INTEGER(IntKi), PARAMETER :: M6N5MMGzi = 2966 + INTEGER(IntKi), PARAMETER :: M6N6MMGzi = 2967 + INTEGER(IntKi), PARAMETER :: M6N7MMGzi = 2968 + INTEGER(IntKi), PARAMETER :: M6N8MMGzi = 2969 + INTEGER(IntKi), PARAMETER :: M6N9MMGzi = 2970 + INTEGER(IntKi), PARAMETER :: M7N1MMGzi = 2971 + INTEGER(IntKi), PARAMETER :: M7N2MMGzi = 2972 + INTEGER(IntKi), PARAMETER :: M7N3MMGzi = 2973 + INTEGER(IntKi), PARAMETER :: M7N4MMGzi = 2974 + INTEGER(IntKi), PARAMETER :: M7N5MMGzi = 2975 + INTEGER(IntKi), PARAMETER :: M7N6MMGzi = 2976 + INTEGER(IntKi), PARAMETER :: M7N7MMGzi = 2977 + INTEGER(IntKi), PARAMETER :: M7N8MMGzi = 2978 + INTEGER(IntKi), PARAMETER :: M7N9MMGzi = 2979 + INTEGER(IntKi), PARAMETER :: M8N1MMGzi = 2980 + INTEGER(IntKi), PARAMETER :: M8N2MMGzi = 2981 + INTEGER(IntKi), PARAMETER :: M8N3MMGzi = 2982 + INTEGER(IntKi), PARAMETER :: M8N4MMGzi = 2983 + INTEGER(IntKi), PARAMETER :: M8N5MMGzi = 2984 + INTEGER(IntKi), PARAMETER :: M8N6MMGzi = 2985 + INTEGER(IntKi), PARAMETER :: M8N7MMGzi = 2986 + INTEGER(IntKi), PARAMETER :: M8N8MMGzi = 2987 + INTEGER(IntKi), PARAMETER :: M8N9MMGzi = 2988 + INTEGER(IntKi), PARAMETER :: M9N1MMGzi = 2989 + INTEGER(IntKi), PARAMETER :: M9N2MMGzi = 2990 + INTEGER(IntKi), PARAMETER :: M9N3MMGzi = 2991 + INTEGER(IntKi), PARAMETER :: M9N4MMGzi = 2992 + INTEGER(IntKi), PARAMETER :: M9N5MMGzi = 2993 + INTEGER(IntKi), PARAMETER :: M9N6MMGzi = 2994 + INTEGER(IntKi), PARAMETER :: M9N7MMGzi = 2995 + INTEGER(IntKi), PARAMETER :: M9N8MMGzi = 2996 + INTEGER(IntKi), PARAMETER :: M9N9MMGzi = 2997 + INTEGER(IntKi), PARAMETER :: M1N1FAMxi = 2998 + INTEGER(IntKi), PARAMETER :: M1N2FAMxi = 2999 + INTEGER(IntKi), PARAMETER :: M1N3FAMxi = 3000 + INTEGER(IntKi), PARAMETER :: M1N4FAMxi = 3001 + INTEGER(IntKi), PARAMETER :: M1N5FAMxi = 3002 + INTEGER(IntKi), PARAMETER :: M1N6FAMxi = 3003 + INTEGER(IntKi), PARAMETER :: M1N7FAMxi = 3004 + INTEGER(IntKi), PARAMETER :: M1N8FAMxi = 3005 + INTEGER(IntKi), PARAMETER :: M1N9FAMxi = 3006 + INTEGER(IntKi), PARAMETER :: M2N1FAMxi = 3007 + INTEGER(IntKi), PARAMETER :: M2N2FAMxi = 3008 + INTEGER(IntKi), PARAMETER :: M2N3FAMxi = 3009 + INTEGER(IntKi), PARAMETER :: M2N4FAMxi = 3010 + INTEGER(IntKi), PARAMETER :: M2N5FAMxi = 3011 + INTEGER(IntKi), PARAMETER :: M2N6FAMxi = 3012 + INTEGER(IntKi), PARAMETER :: M2N7FAMxi = 3013 + INTEGER(IntKi), PARAMETER :: M2N8FAMxi = 3014 + INTEGER(IntKi), PARAMETER :: M2N9FAMxi = 3015 + INTEGER(IntKi), PARAMETER :: M3N1FAMxi = 3016 + INTEGER(IntKi), PARAMETER :: M3N2FAMxi = 3017 + INTEGER(IntKi), PARAMETER :: M3N3FAMxi = 3018 + INTEGER(IntKi), PARAMETER :: M3N4FAMxi = 3019 + INTEGER(IntKi), PARAMETER :: M3N5FAMxi = 3020 + INTEGER(IntKi), PARAMETER :: M3N6FAMxi = 3021 + INTEGER(IntKi), PARAMETER :: M3N7FAMxi = 3022 + INTEGER(IntKi), PARAMETER :: M3N8FAMxi = 3023 + INTEGER(IntKi), PARAMETER :: M3N9FAMxi = 3024 + INTEGER(IntKi), PARAMETER :: M4N1FAMxi = 3025 + INTEGER(IntKi), PARAMETER :: M4N2FAMxi = 3026 + INTEGER(IntKi), PARAMETER :: M4N3FAMxi = 3027 + INTEGER(IntKi), PARAMETER :: M4N4FAMxi = 3028 + INTEGER(IntKi), PARAMETER :: M4N5FAMxi = 3029 + INTEGER(IntKi), PARAMETER :: M4N6FAMxi = 3030 + INTEGER(IntKi), PARAMETER :: M4N7FAMxi = 3031 + INTEGER(IntKi), PARAMETER :: M4N8FAMxi = 3032 + INTEGER(IntKi), PARAMETER :: M4N9FAMxi = 3033 + INTEGER(IntKi), PARAMETER :: M5N1FAMxi = 3034 + INTEGER(IntKi), PARAMETER :: M5N2FAMxi = 3035 + INTEGER(IntKi), PARAMETER :: M5N3FAMxi = 3036 + INTEGER(IntKi), PARAMETER :: M5N4FAMxi = 3037 + INTEGER(IntKi), PARAMETER :: M5N5FAMxi = 3038 + INTEGER(IntKi), PARAMETER :: M5N6FAMxi = 3039 + INTEGER(IntKi), PARAMETER :: M5N7FAMxi = 3040 + INTEGER(IntKi), PARAMETER :: M5N8FAMxi = 3041 + INTEGER(IntKi), PARAMETER :: M5N9FAMxi = 3042 + INTEGER(IntKi), PARAMETER :: M6N1FAMxi = 3043 + INTEGER(IntKi), PARAMETER :: M6N2FAMxi = 3044 + INTEGER(IntKi), PARAMETER :: M6N3FAMxi = 3045 + INTEGER(IntKi), PARAMETER :: M6N4FAMxi = 3046 + INTEGER(IntKi), PARAMETER :: M6N5FAMxi = 3047 + INTEGER(IntKi), PARAMETER :: M6N6FAMxi = 3048 + INTEGER(IntKi), PARAMETER :: M6N7FAMxi = 3049 + INTEGER(IntKi), PARAMETER :: M6N8FAMxi = 3050 + INTEGER(IntKi), PARAMETER :: M6N9FAMxi = 3051 + INTEGER(IntKi), PARAMETER :: M7N1FAMxi = 3052 + INTEGER(IntKi), PARAMETER :: M7N2FAMxi = 3053 + INTEGER(IntKi), PARAMETER :: M7N3FAMxi = 3054 + INTEGER(IntKi), PARAMETER :: M7N4FAMxi = 3055 + INTEGER(IntKi), PARAMETER :: M7N5FAMxi = 3056 + INTEGER(IntKi), PARAMETER :: M7N6FAMxi = 3057 + INTEGER(IntKi), PARAMETER :: M7N7FAMxi = 3058 + INTEGER(IntKi), PARAMETER :: M7N8FAMxi = 3059 + INTEGER(IntKi), PARAMETER :: M7N9FAMxi = 3060 + INTEGER(IntKi), PARAMETER :: M8N1FAMxi = 3061 + INTEGER(IntKi), PARAMETER :: M8N2FAMxi = 3062 + INTEGER(IntKi), PARAMETER :: M8N3FAMxi = 3063 + INTEGER(IntKi), PARAMETER :: M8N4FAMxi = 3064 + INTEGER(IntKi), PARAMETER :: M8N5FAMxi = 3065 + INTEGER(IntKi), PARAMETER :: M8N6FAMxi = 3066 + INTEGER(IntKi), PARAMETER :: M8N7FAMxi = 3067 + INTEGER(IntKi), PARAMETER :: M8N8FAMxi = 3068 + INTEGER(IntKi), PARAMETER :: M8N9FAMxi = 3069 + INTEGER(IntKi), PARAMETER :: M9N1FAMxi = 3070 + INTEGER(IntKi), PARAMETER :: M9N2FAMxi = 3071 + INTEGER(IntKi), PARAMETER :: M9N3FAMxi = 3072 + INTEGER(IntKi), PARAMETER :: M9N4FAMxi = 3073 + INTEGER(IntKi), PARAMETER :: M9N5FAMxi = 3074 + INTEGER(IntKi), PARAMETER :: M9N6FAMxi = 3075 + INTEGER(IntKi), PARAMETER :: M9N7FAMxi = 3076 + INTEGER(IntKi), PARAMETER :: M9N8FAMxi = 3077 + INTEGER(IntKi), PARAMETER :: M9N9FAMxi = 3078 + INTEGER(IntKi), PARAMETER :: M1N1FAMyi = 3079 + INTEGER(IntKi), PARAMETER :: M1N2FAMyi = 3080 + INTEGER(IntKi), PARAMETER :: M1N3FAMyi = 3081 + INTEGER(IntKi), PARAMETER :: M1N4FAMyi = 3082 + INTEGER(IntKi), PARAMETER :: M1N5FAMyi = 3083 + INTEGER(IntKi), PARAMETER :: M1N6FAMyi = 3084 + INTEGER(IntKi), PARAMETER :: M1N7FAMyi = 3085 + INTEGER(IntKi), PARAMETER :: M1N8FAMyi = 3086 + INTEGER(IntKi), PARAMETER :: M1N9FAMyi = 3087 + INTEGER(IntKi), PARAMETER :: M2N1FAMyi = 3088 + INTEGER(IntKi), PARAMETER :: M2N2FAMyi = 3089 + INTEGER(IntKi), PARAMETER :: M2N3FAMyi = 3090 + INTEGER(IntKi), PARAMETER :: M2N4FAMyi = 3091 + INTEGER(IntKi), PARAMETER :: M2N5FAMyi = 3092 + INTEGER(IntKi), PARAMETER :: M2N6FAMyi = 3093 + INTEGER(IntKi), PARAMETER :: M2N7FAMyi = 3094 + INTEGER(IntKi), PARAMETER :: M2N8FAMyi = 3095 + INTEGER(IntKi), PARAMETER :: M2N9FAMyi = 3096 + INTEGER(IntKi), PARAMETER :: M3N1FAMyi = 3097 + INTEGER(IntKi), PARAMETER :: M3N2FAMyi = 3098 + INTEGER(IntKi), PARAMETER :: M3N3FAMyi = 3099 + INTEGER(IntKi), PARAMETER :: M3N4FAMyi = 3100 + INTEGER(IntKi), PARAMETER :: M3N5FAMyi = 3101 + INTEGER(IntKi), PARAMETER :: M3N6FAMyi = 3102 + INTEGER(IntKi), PARAMETER :: M3N7FAMyi = 3103 + INTEGER(IntKi), PARAMETER :: M3N8FAMyi = 3104 + INTEGER(IntKi), PARAMETER :: M3N9FAMyi = 3105 + INTEGER(IntKi), PARAMETER :: M4N1FAMyi = 3106 + INTEGER(IntKi), PARAMETER :: M4N2FAMyi = 3107 + INTEGER(IntKi), PARAMETER :: M4N3FAMyi = 3108 + INTEGER(IntKi), PARAMETER :: M4N4FAMyi = 3109 + INTEGER(IntKi), PARAMETER :: M4N5FAMyi = 3110 + INTEGER(IntKi), PARAMETER :: M4N6FAMyi = 3111 + INTEGER(IntKi), PARAMETER :: M4N7FAMyi = 3112 + INTEGER(IntKi), PARAMETER :: M4N8FAMyi = 3113 + INTEGER(IntKi), PARAMETER :: M4N9FAMyi = 3114 + INTEGER(IntKi), PARAMETER :: M5N1FAMyi = 3115 + INTEGER(IntKi), PARAMETER :: M5N2FAMyi = 3116 + INTEGER(IntKi), PARAMETER :: M5N3FAMyi = 3117 + INTEGER(IntKi), PARAMETER :: M5N4FAMyi = 3118 + INTEGER(IntKi), PARAMETER :: M5N5FAMyi = 3119 + INTEGER(IntKi), PARAMETER :: M5N6FAMyi = 3120 + INTEGER(IntKi), PARAMETER :: M5N7FAMyi = 3121 + INTEGER(IntKi), PARAMETER :: M5N8FAMyi = 3122 + INTEGER(IntKi), PARAMETER :: M5N9FAMyi = 3123 + INTEGER(IntKi), PARAMETER :: M6N1FAMyi = 3124 + INTEGER(IntKi), PARAMETER :: M6N2FAMyi = 3125 + INTEGER(IntKi), PARAMETER :: M6N3FAMyi = 3126 + INTEGER(IntKi), PARAMETER :: M6N4FAMyi = 3127 + INTEGER(IntKi), PARAMETER :: M6N5FAMyi = 3128 + INTEGER(IntKi), PARAMETER :: M6N6FAMyi = 3129 + INTEGER(IntKi), PARAMETER :: M6N7FAMyi = 3130 + INTEGER(IntKi), PARAMETER :: M6N8FAMyi = 3131 + INTEGER(IntKi), PARAMETER :: M6N9FAMyi = 3132 + INTEGER(IntKi), PARAMETER :: M7N1FAMyi = 3133 + INTEGER(IntKi), PARAMETER :: M7N2FAMyi = 3134 + INTEGER(IntKi), PARAMETER :: M7N3FAMyi = 3135 + INTEGER(IntKi), PARAMETER :: M7N4FAMyi = 3136 + INTEGER(IntKi), PARAMETER :: M7N5FAMyi = 3137 + INTEGER(IntKi), PARAMETER :: M7N6FAMyi = 3138 + INTEGER(IntKi), PARAMETER :: M7N7FAMyi = 3139 + INTEGER(IntKi), PARAMETER :: M7N8FAMyi = 3140 + INTEGER(IntKi), PARAMETER :: M7N9FAMyi = 3141 + INTEGER(IntKi), PARAMETER :: M8N1FAMyi = 3142 + INTEGER(IntKi), PARAMETER :: M8N2FAMyi = 3143 + INTEGER(IntKi), PARAMETER :: M8N3FAMyi = 3144 + INTEGER(IntKi), PARAMETER :: M8N4FAMyi = 3145 + INTEGER(IntKi), PARAMETER :: M8N5FAMyi = 3146 + INTEGER(IntKi), PARAMETER :: M8N6FAMyi = 3147 + INTEGER(IntKi), PARAMETER :: M8N7FAMyi = 3148 + INTEGER(IntKi), PARAMETER :: M8N8FAMyi = 3149 + INTEGER(IntKi), PARAMETER :: M8N9FAMyi = 3150 + INTEGER(IntKi), PARAMETER :: M9N1FAMyi = 3151 + INTEGER(IntKi), PARAMETER :: M9N2FAMyi = 3152 + INTEGER(IntKi), PARAMETER :: M9N3FAMyi = 3153 + INTEGER(IntKi), PARAMETER :: M9N4FAMyi = 3154 + INTEGER(IntKi), PARAMETER :: M9N5FAMyi = 3155 + INTEGER(IntKi), PARAMETER :: M9N6FAMyi = 3156 + INTEGER(IntKi), PARAMETER :: M9N7FAMyi = 3157 + INTEGER(IntKi), PARAMETER :: M9N8FAMyi = 3158 + INTEGER(IntKi), PARAMETER :: M9N9FAMyi = 3159 + INTEGER(IntKi), PARAMETER :: M1N1FAMzi = 3160 + INTEGER(IntKi), PARAMETER :: M1N2FAMzi = 3161 + INTEGER(IntKi), PARAMETER :: M1N3FAMzi = 3162 + INTEGER(IntKi), PARAMETER :: M1N4FAMzi = 3163 + INTEGER(IntKi), PARAMETER :: M1N5FAMzi = 3164 + INTEGER(IntKi), PARAMETER :: M1N6FAMzi = 3165 + INTEGER(IntKi), PARAMETER :: M1N7FAMzi = 3166 + INTEGER(IntKi), PARAMETER :: M1N8FAMzi = 3167 + INTEGER(IntKi), PARAMETER :: M1N9FAMzi = 3168 + INTEGER(IntKi), PARAMETER :: M2N1FAMzi = 3169 + INTEGER(IntKi), PARAMETER :: M2N2FAMzi = 3170 + INTEGER(IntKi), PARAMETER :: M2N3FAMzi = 3171 + INTEGER(IntKi), PARAMETER :: M2N4FAMzi = 3172 + INTEGER(IntKi), PARAMETER :: M2N5FAMzi = 3173 + INTEGER(IntKi), PARAMETER :: M2N6FAMzi = 3174 + INTEGER(IntKi), PARAMETER :: M2N7FAMzi = 3175 + INTEGER(IntKi), PARAMETER :: M2N8FAMzi = 3176 + INTEGER(IntKi), PARAMETER :: M2N9FAMzi = 3177 + INTEGER(IntKi), PARAMETER :: M3N1FAMzi = 3178 + INTEGER(IntKi), PARAMETER :: M3N2FAMzi = 3179 + INTEGER(IntKi), PARAMETER :: M3N3FAMzi = 3180 + INTEGER(IntKi), PARAMETER :: M3N4FAMzi = 3181 + INTEGER(IntKi), PARAMETER :: M3N5FAMzi = 3182 + INTEGER(IntKi), PARAMETER :: M3N6FAMzi = 3183 + INTEGER(IntKi), PARAMETER :: M3N7FAMzi = 3184 + INTEGER(IntKi), PARAMETER :: M3N8FAMzi = 3185 + INTEGER(IntKi), PARAMETER :: M3N9FAMzi = 3186 + INTEGER(IntKi), PARAMETER :: M4N1FAMzi = 3187 + INTEGER(IntKi), PARAMETER :: M4N2FAMzi = 3188 + INTEGER(IntKi), PARAMETER :: M4N3FAMzi = 3189 + INTEGER(IntKi), PARAMETER :: M4N4FAMzi = 3190 + INTEGER(IntKi), PARAMETER :: M4N5FAMzi = 3191 + INTEGER(IntKi), PARAMETER :: M4N6FAMzi = 3192 + INTEGER(IntKi), PARAMETER :: M4N7FAMzi = 3193 + INTEGER(IntKi), PARAMETER :: M4N8FAMzi = 3194 + INTEGER(IntKi), PARAMETER :: M4N9FAMzi = 3195 + INTEGER(IntKi), PARAMETER :: M5N1FAMzi = 3196 + INTEGER(IntKi), PARAMETER :: M5N2FAMzi = 3197 + INTEGER(IntKi), PARAMETER :: M5N3FAMzi = 3198 + INTEGER(IntKi), PARAMETER :: M5N4FAMzi = 3199 + INTEGER(IntKi), PARAMETER :: M5N5FAMzi = 3200 + INTEGER(IntKi), PARAMETER :: M5N6FAMzi = 3201 + INTEGER(IntKi), PARAMETER :: M5N7FAMzi = 3202 + INTEGER(IntKi), PARAMETER :: M5N8FAMzi = 3203 + INTEGER(IntKi), PARAMETER :: M5N9FAMzi = 3204 + INTEGER(IntKi), PARAMETER :: M6N1FAMzi = 3205 + INTEGER(IntKi), PARAMETER :: M6N2FAMzi = 3206 + INTEGER(IntKi), PARAMETER :: M6N3FAMzi = 3207 + INTEGER(IntKi), PARAMETER :: M6N4FAMzi = 3208 + INTEGER(IntKi), PARAMETER :: M6N5FAMzi = 3209 + INTEGER(IntKi), PARAMETER :: M6N6FAMzi = 3210 + INTEGER(IntKi), PARAMETER :: M6N7FAMzi = 3211 + INTEGER(IntKi), PARAMETER :: M6N8FAMzi = 3212 + INTEGER(IntKi), PARAMETER :: M6N9FAMzi = 3213 + INTEGER(IntKi), PARAMETER :: M7N1FAMzi = 3214 + INTEGER(IntKi), PARAMETER :: M7N2FAMzi = 3215 + INTEGER(IntKi), PARAMETER :: M7N3FAMzi = 3216 + INTEGER(IntKi), PARAMETER :: M7N4FAMzi = 3217 + INTEGER(IntKi), PARAMETER :: M7N5FAMzi = 3218 + INTEGER(IntKi), PARAMETER :: M7N6FAMzi = 3219 + INTEGER(IntKi), PARAMETER :: M7N7FAMzi = 3220 + INTEGER(IntKi), PARAMETER :: M7N8FAMzi = 3221 + INTEGER(IntKi), PARAMETER :: M7N9FAMzi = 3222 + INTEGER(IntKi), PARAMETER :: M8N1FAMzi = 3223 + INTEGER(IntKi), PARAMETER :: M8N2FAMzi = 3224 + INTEGER(IntKi), PARAMETER :: M8N3FAMzi = 3225 + INTEGER(IntKi), PARAMETER :: M8N4FAMzi = 3226 + INTEGER(IntKi), PARAMETER :: M8N5FAMzi = 3227 + INTEGER(IntKi), PARAMETER :: M8N6FAMzi = 3228 + INTEGER(IntKi), PARAMETER :: M8N7FAMzi = 3229 + INTEGER(IntKi), PARAMETER :: M8N8FAMzi = 3230 + INTEGER(IntKi), PARAMETER :: M8N9FAMzi = 3231 + INTEGER(IntKi), PARAMETER :: M9N1FAMzi = 3232 + INTEGER(IntKi), PARAMETER :: M9N2FAMzi = 3233 + INTEGER(IntKi), PARAMETER :: M9N3FAMzi = 3234 + INTEGER(IntKi), PARAMETER :: M9N4FAMzi = 3235 + INTEGER(IntKi), PARAMETER :: M9N5FAMzi = 3236 + INTEGER(IntKi), PARAMETER :: M9N6FAMzi = 3237 + INTEGER(IntKi), PARAMETER :: M9N7FAMzi = 3238 + INTEGER(IntKi), PARAMETER :: M9N8FAMzi = 3239 + INTEGER(IntKi), PARAMETER :: M9N9FAMzi = 3240 + INTEGER(IntKi), PARAMETER :: M1N1FAGxi = 3241 + INTEGER(IntKi), PARAMETER :: M1N2FAGxi = 3242 + INTEGER(IntKi), PARAMETER :: M1N3FAGxi = 3243 + INTEGER(IntKi), PARAMETER :: M1N4FAGxi = 3244 + INTEGER(IntKi), PARAMETER :: M1N5FAGxi = 3245 + INTEGER(IntKi), PARAMETER :: M1N6FAGxi = 3246 + INTEGER(IntKi), PARAMETER :: M1N7FAGxi = 3247 + INTEGER(IntKi), PARAMETER :: M1N8FAGxi = 3248 + INTEGER(IntKi), PARAMETER :: M1N9FAGxi = 3249 + INTEGER(IntKi), PARAMETER :: M2N1FAGxi = 3250 + INTEGER(IntKi), PARAMETER :: M2N2FAGxi = 3251 + INTEGER(IntKi), PARAMETER :: M2N3FAGxi = 3252 + INTEGER(IntKi), PARAMETER :: M2N4FAGxi = 3253 + INTEGER(IntKi), PARAMETER :: M2N5FAGxi = 3254 + INTEGER(IntKi), PARAMETER :: M2N6FAGxi = 3255 + INTEGER(IntKi), PARAMETER :: M2N7FAGxi = 3256 + INTEGER(IntKi), PARAMETER :: M2N8FAGxi = 3257 + INTEGER(IntKi), PARAMETER :: M2N9FAGxi = 3258 + INTEGER(IntKi), PARAMETER :: M3N1FAGxi = 3259 + INTEGER(IntKi), PARAMETER :: M3N2FAGxi = 3260 + INTEGER(IntKi), PARAMETER :: M3N3FAGxi = 3261 + INTEGER(IntKi), PARAMETER :: M3N4FAGxi = 3262 + INTEGER(IntKi), PARAMETER :: M3N5FAGxi = 3263 + INTEGER(IntKi), PARAMETER :: M3N6FAGxi = 3264 + INTEGER(IntKi), PARAMETER :: M3N7FAGxi = 3265 + INTEGER(IntKi), PARAMETER :: M3N8FAGxi = 3266 + INTEGER(IntKi), PARAMETER :: M3N9FAGxi = 3267 + INTEGER(IntKi), PARAMETER :: M4N1FAGxi = 3268 + INTEGER(IntKi), PARAMETER :: M4N2FAGxi = 3269 + INTEGER(IntKi), PARAMETER :: M4N3FAGxi = 3270 + INTEGER(IntKi), PARAMETER :: M4N4FAGxi = 3271 + INTEGER(IntKi), PARAMETER :: M4N5FAGxi = 3272 + INTEGER(IntKi), PARAMETER :: M4N6FAGxi = 3273 + INTEGER(IntKi), PARAMETER :: M4N7FAGxi = 3274 + INTEGER(IntKi), PARAMETER :: M4N8FAGxi = 3275 + INTEGER(IntKi), PARAMETER :: M4N9FAGxi = 3276 + INTEGER(IntKi), PARAMETER :: M5N1FAGxi = 3277 + INTEGER(IntKi), PARAMETER :: M5N2FAGxi = 3278 + INTEGER(IntKi), PARAMETER :: M5N3FAGxi = 3279 + INTEGER(IntKi), PARAMETER :: M5N4FAGxi = 3280 + INTEGER(IntKi), PARAMETER :: M5N5FAGxi = 3281 + INTEGER(IntKi), PARAMETER :: M5N6FAGxi = 3282 + INTEGER(IntKi), PARAMETER :: M5N7FAGxi = 3283 + INTEGER(IntKi), PARAMETER :: M5N8FAGxi = 3284 + INTEGER(IntKi), PARAMETER :: M5N9FAGxi = 3285 + INTEGER(IntKi), PARAMETER :: M6N1FAGxi = 3286 + INTEGER(IntKi), PARAMETER :: M6N2FAGxi = 3287 + INTEGER(IntKi), PARAMETER :: M6N3FAGxi = 3288 + INTEGER(IntKi), PARAMETER :: M6N4FAGxi = 3289 + INTEGER(IntKi), PARAMETER :: M6N5FAGxi = 3290 + INTEGER(IntKi), PARAMETER :: M6N6FAGxi = 3291 + INTEGER(IntKi), PARAMETER :: M6N7FAGxi = 3292 + INTEGER(IntKi), PARAMETER :: M6N8FAGxi = 3293 + INTEGER(IntKi), PARAMETER :: M6N9FAGxi = 3294 + INTEGER(IntKi), PARAMETER :: M7N1FAGxi = 3295 + INTEGER(IntKi), PARAMETER :: M7N2FAGxi = 3296 + INTEGER(IntKi), PARAMETER :: M7N3FAGxi = 3297 + INTEGER(IntKi), PARAMETER :: M7N4FAGxi = 3298 + INTEGER(IntKi), PARAMETER :: M7N5FAGxi = 3299 + INTEGER(IntKi), PARAMETER :: M7N6FAGxi = 3300 + INTEGER(IntKi), PARAMETER :: M7N7FAGxi = 3301 + INTEGER(IntKi), PARAMETER :: M7N8FAGxi = 3302 + INTEGER(IntKi), PARAMETER :: M7N9FAGxi = 3303 + INTEGER(IntKi), PARAMETER :: M8N1FAGxi = 3304 + INTEGER(IntKi), PARAMETER :: M8N2FAGxi = 3305 + INTEGER(IntKi), PARAMETER :: M8N3FAGxi = 3306 + INTEGER(IntKi), PARAMETER :: M8N4FAGxi = 3307 + INTEGER(IntKi), PARAMETER :: M8N5FAGxi = 3308 + INTEGER(IntKi), PARAMETER :: M8N6FAGxi = 3309 + INTEGER(IntKi), PARAMETER :: M8N7FAGxi = 3310 + INTEGER(IntKi), PARAMETER :: M8N8FAGxi = 3311 + INTEGER(IntKi), PARAMETER :: M8N9FAGxi = 3312 + INTEGER(IntKi), PARAMETER :: M9N1FAGxi = 3313 + INTEGER(IntKi), PARAMETER :: M9N2FAGxi = 3314 + INTEGER(IntKi), PARAMETER :: M9N3FAGxi = 3315 + INTEGER(IntKi), PARAMETER :: M9N4FAGxi = 3316 + INTEGER(IntKi), PARAMETER :: M9N5FAGxi = 3317 + INTEGER(IntKi), PARAMETER :: M9N6FAGxi = 3318 + INTEGER(IntKi), PARAMETER :: M9N7FAGxi = 3319 + INTEGER(IntKi), PARAMETER :: M9N8FAGxi = 3320 + INTEGER(IntKi), PARAMETER :: M9N9FAGxi = 3321 + INTEGER(IntKi), PARAMETER :: M1N1FAGyi = 3322 + INTEGER(IntKi), PARAMETER :: M1N2FAGyi = 3323 + INTEGER(IntKi), PARAMETER :: M1N3FAGyi = 3324 + INTEGER(IntKi), PARAMETER :: M1N4FAGyi = 3325 + INTEGER(IntKi), PARAMETER :: M1N5FAGyi = 3326 + INTEGER(IntKi), PARAMETER :: M1N6FAGyi = 3327 + INTEGER(IntKi), PARAMETER :: M1N7FAGyi = 3328 + INTEGER(IntKi), PARAMETER :: M1N8FAGyi = 3329 + INTEGER(IntKi), PARAMETER :: M1N9FAGyi = 3330 + INTEGER(IntKi), PARAMETER :: M2N1FAGyi = 3331 + INTEGER(IntKi), PARAMETER :: M2N2FAGyi = 3332 + INTEGER(IntKi), PARAMETER :: M2N3FAGyi = 3333 + INTEGER(IntKi), PARAMETER :: M2N4FAGyi = 3334 + INTEGER(IntKi), PARAMETER :: M2N5FAGyi = 3335 + INTEGER(IntKi), PARAMETER :: M2N6FAGyi = 3336 + INTEGER(IntKi), PARAMETER :: M2N7FAGyi = 3337 + INTEGER(IntKi), PARAMETER :: M2N8FAGyi = 3338 + INTEGER(IntKi), PARAMETER :: M2N9FAGyi = 3339 + INTEGER(IntKi), PARAMETER :: M3N1FAGyi = 3340 + INTEGER(IntKi), PARAMETER :: M3N2FAGyi = 3341 + INTEGER(IntKi), PARAMETER :: M3N3FAGyi = 3342 + INTEGER(IntKi), PARAMETER :: M3N4FAGyi = 3343 + INTEGER(IntKi), PARAMETER :: M3N5FAGyi = 3344 + INTEGER(IntKi), PARAMETER :: M3N6FAGyi = 3345 + INTEGER(IntKi), PARAMETER :: M3N7FAGyi = 3346 + INTEGER(IntKi), PARAMETER :: M3N8FAGyi = 3347 + INTEGER(IntKi), PARAMETER :: M3N9FAGyi = 3348 + INTEGER(IntKi), PARAMETER :: M4N1FAGyi = 3349 + INTEGER(IntKi), PARAMETER :: M4N2FAGyi = 3350 + INTEGER(IntKi), PARAMETER :: M4N3FAGyi = 3351 + INTEGER(IntKi), PARAMETER :: M4N4FAGyi = 3352 + INTEGER(IntKi), PARAMETER :: M4N5FAGyi = 3353 + INTEGER(IntKi), PARAMETER :: M4N6FAGyi = 3354 + INTEGER(IntKi), PARAMETER :: M4N7FAGyi = 3355 + INTEGER(IntKi), PARAMETER :: M4N8FAGyi = 3356 + INTEGER(IntKi), PARAMETER :: M4N9FAGyi = 3357 + INTEGER(IntKi), PARAMETER :: M5N1FAGyi = 3358 + INTEGER(IntKi), PARAMETER :: M5N2FAGyi = 3359 + INTEGER(IntKi), PARAMETER :: M5N3FAGyi = 3360 + INTEGER(IntKi), PARAMETER :: M5N4FAGyi = 3361 + INTEGER(IntKi), PARAMETER :: M5N5FAGyi = 3362 + INTEGER(IntKi), PARAMETER :: M5N6FAGyi = 3363 + INTEGER(IntKi), PARAMETER :: M5N7FAGyi = 3364 + INTEGER(IntKi), PARAMETER :: M5N8FAGyi = 3365 + INTEGER(IntKi), PARAMETER :: M5N9FAGyi = 3366 + INTEGER(IntKi), PARAMETER :: M6N1FAGyi = 3367 + INTEGER(IntKi), PARAMETER :: M6N2FAGyi = 3368 + INTEGER(IntKi), PARAMETER :: M6N3FAGyi = 3369 + INTEGER(IntKi), PARAMETER :: M6N4FAGyi = 3370 + INTEGER(IntKi), PARAMETER :: M6N5FAGyi = 3371 + INTEGER(IntKi), PARAMETER :: M6N6FAGyi = 3372 + INTEGER(IntKi), PARAMETER :: M6N7FAGyi = 3373 + INTEGER(IntKi), PARAMETER :: M6N8FAGyi = 3374 + INTEGER(IntKi), PARAMETER :: M6N9FAGyi = 3375 + INTEGER(IntKi), PARAMETER :: M7N1FAGyi = 3376 + INTEGER(IntKi), PARAMETER :: M7N2FAGyi = 3377 + INTEGER(IntKi), PARAMETER :: M7N3FAGyi = 3378 + INTEGER(IntKi), PARAMETER :: M7N4FAGyi = 3379 + INTEGER(IntKi), PARAMETER :: M7N5FAGyi = 3380 + INTEGER(IntKi), PARAMETER :: M7N6FAGyi = 3381 + INTEGER(IntKi), PARAMETER :: M7N7FAGyi = 3382 + INTEGER(IntKi), PARAMETER :: M7N8FAGyi = 3383 + INTEGER(IntKi), PARAMETER :: M7N9FAGyi = 3384 + INTEGER(IntKi), PARAMETER :: M8N1FAGyi = 3385 + INTEGER(IntKi), PARAMETER :: M8N2FAGyi = 3386 + INTEGER(IntKi), PARAMETER :: M8N3FAGyi = 3387 + INTEGER(IntKi), PARAMETER :: M8N4FAGyi = 3388 + INTEGER(IntKi), PARAMETER :: M8N5FAGyi = 3389 + INTEGER(IntKi), PARAMETER :: M8N6FAGyi = 3390 + INTEGER(IntKi), PARAMETER :: M8N7FAGyi = 3391 + INTEGER(IntKi), PARAMETER :: M8N8FAGyi = 3392 + INTEGER(IntKi), PARAMETER :: M8N9FAGyi = 3393 + INTEGER(IntKi), PARAMETER :: M9N1FAGyi = 3394 + INTEGER(IntKi), PARAMETER :: M9N2FAGyi = 3395 + INTEGER(IntKi), PARAMETER :: M9N3FAGyi = 3396 + INTEGER(IntKi), PARAMETER :: M9N4FAGyi = 3397 + INTEGER(IntKi), PARAMETER :: M9N5FAGyi = 3398 + INTEGER(IntKi), PARAMETER :: M9N6FAGyi = 3399 + INTEGER(IntKi), PARAMETER :: M9N7FAGyi = 3400 + INTEGER(IntKi), PARAMETER :: M9N8FAGyi = 3401 + INTEGER(IntKi), PARAMETER :: M9N9FAGyi = 3402 + INTEGER(IntKi), PARAMETER :: M1N1FAGzi = 3403 + INTEGER(IntKi), PARAMETER :: M1N2FAGzi = 3404 + INTEGER(IntKi), PARAMETER :: M1N3FAGzi = 3405 + INTEGER(IntKi), PARAMETER :: M1N4FAGzi = 3406 + INTEGER(IntKi), PARAMETER :: M1N5FAGzi = 3407 + INTEGER(IntKi), PARAMETER :: M1N6FAGzi = 3408 + INTEGER(IntKi), PARAMETER :: M1N7FAGzi = 3409 + INTEGER(IntKi), PARAMETER :: M1N8FAGzi = 3410 + INTEGER(IntKi), PARAMETER :: M1N9FAGzi = 3411 + INTEGER(IntKi), PARAMETER :: M2N1FAGzi = 3412 + INTEGER(IntKi), PARAMETER :: M2N2FAGzi = 3413 + INTEGER(IntKi), PARAMETER :: M2N3FAGzi = 3414 + INTEGER(IntKi), PARAMETER :: M2N4FAGzi = 3415 + INTEGER(IntKi), PARAMETER :: M2N5FAGzi = 3416 + INTEGER(IntKi), PARAMETER :: M2N6FAGzi = 3417 + INTEGER(IntKi), PARAMETER :: M2N7FAGzi = 3418 + INTEGER(IntKi), PARAMETER :: M2N8FAGzi = 3419 + INTEGER(IntKi), PARAMETER :: M2N9FAGzi = 3420 + INTEGER(IntKi), PARAMETER :: M3N1FAGzi = 3421 + INTEGER(IntKi), PARAMETER :: M3N2FAGzi = 3422 + INTEGER(IntKi), PARAMETER :: M3N3FAGzi = 3423 + INTEGER(IntKi), PARAMETER :: M3N4FAGzi = 3424 + INTEGER(IntKi), PARAMETER :: M3N5FAGzi = 3425 + INTEGER(IntKi), PARAMETER :: M3N6FAGzi = 3426 + INTEGER(IntKi), PARAMETER :: M3N7FAGzi = 3427 + INTEGER(IntKi), PARAMETER :: M3N8FAGzi = 3428 + INTEGER(IntKi), PARAMETER :: M3N9FAGzi = 3429 + INTEGER(IntKi), PARAMETER :: M4N1FAGzi = 3430 + INTEGER(IntKi), PARAMETER :: M4N2FAGzi = 3431 + INTEGER(IntKi), PARAMETER :: M4N3FAGzi = 3432 + INTEGER(IntKi), PARAMETER :: M4N4FAGzi = 3433 + INTEGER(IntKi), PARAMETER :: M4N5FAGzi = 3434 + INTEGER(IntKi), PARAMETER :: M4N6FAGzi = 3435 + INTEGER(IntKi), PARAMETER :: M4N7FAGzi = 3436 + INTEGER(IntKi), PARAMETER :: M4N8FAGzi = 3437 + INTEGER(IntKi), PARAMETER :: M4N9FAGzi = 3438 + INTEGER(IntKi), PARAMETER :: M5N1FAGzi = 3439 + INTEGER(IntKi), PARAMETER :: M5N2FAGzi = 3440 + INTEGER(IntKi), PARAMETER :: M5N3FAGzi = 3441 + INTEGER(IntKi), PARAMETER :: M5N4FAGzi = 3442 + INTEGER(IntKi), PARAMETER :: M5N5FAGzi = 3443 + INTEGER(IntKi), PARAMETER :: M5N6FAGzi = 3444 + INTEGER(IntKi), PARAMETER :: M5N7FAGzi = 3445 + INTEGER(IntKi), PARAMETER :: M5N8FAGzi = 3446 + INTEGER(IntKi), PARAMETER :: M5N9FAGzi = 3447 + INTEGER(IntKi), PARAMETER :: M6N1FAGzi = 3448 + INTEGER(IntKi), PARAMETER :: M6N2FAGzi = 3449 + INTEGER(IntKi), PARAMETER :: M6N3FAGzi = 3450 + INTEGER(IntKi), PARAMETER :: M6N4FAGzi = 3451 + INTEGER(IntKi), PARAMETER :: M6N5FAGzi = 3452 + INTEGER(IntKi), PARAMETER :: M6N6FAGzi = 3453 + INTEGER(IntKi), PARAMETER :: M6N7FAGzi = 3454 + INTEGER(IntKi), PARAMETER :: M6N8FAGzi = 3455 + INTEGER(IntKi), PARAMETER :: M6N9FAGzi = 3456 + INTEGER(IntKi), PARAMETER :: M7N1FAGzi = 3457 + INTEGER(IntKi), PARAMETER :: M7N2FAGzi = 3458 + INTEGER(IntKi), PARAMETER :: M7N3FAGzi = 3459 + INTEGER(IntKi), PARAMETER :: M7N4FAGzi = 3460 + INTEGER(IntKi), PARAMETER :: M7N5FAGzi = 3461 + INTEGER(IntKi), PARAMETER :: M7N6FAGzi = 3462 + INTEGER(IntKi), PARAMETER :: M7N7FAGzi = 3463 + INTEGER(IntKi), PARAMETER :: M7N8FAGzi = 3464 + INTEGER(IntKi), PARAMETER :: M7N9FAGzi = 3465 + INTEGER(IntKi), PARAMETER :: M8N1FAGzi = 3466 + INTEGER(IntKi), PARAMETER :: M8N2FAGzi = 3467 + INTEGER(IntKi), PARAMETER :: M8N3FAGzi = 3468 + INTEGER(IntKi), PARAMETER :: M8N4FAGzi = 3469 + INTEGER(IntKi), PARAMETER :: M8N5FAGzi = 3470 + INTEGER(IntKi), PARAMETER :: M8N6FAGzi = 3471 + INTEGER(IntKi), PARAMETER :: M8N7FAGzi = 3472 + INTEGER(IntKi), PARAMETER :: M8N8FAGzi = 3473 + INTEGER(IntKi), PARAMETER :: M8N9FAGzi = 3474 + INTEGER(IntKi), PARAMETER :: M9N1FAGzi = 3475 + INTEGER(IntKi), PARAMETER :: M9N2FAGzi = 3476 + INTEGER(IntKi), PARAMETER :: M9N3FAGzi = 3477 + INTEGER(IntKi), PARAMETER :: M9N4FAGzi = 3478 + INTEGER(IntKi), PARAMETER :: M9N5FAGzi = 3479 + INTEGER(IntKi), PARAMETER :: M9N6FAGzi = 3480 + INTEGER(IntKi), PARAMETER :: M9N7FAGzi = 3481 + INTEGER(IntKi), PARAMETER :: M9N8FAGzi = 3482 + INTEGER(IntKi), PARAMETER :: M9N9FAGzi = 3483 + INTEGER(IntKi), PARAMETER :: M1N1MAGxi = 3484 + INTEGER(IntKi), PARAMETER :: M1N2MAGxi = 3485 + INTEGER(IntKi), PARAMETER :: M1N3MAGxi = 3486 + INTEGER(IntKi), PARAMETER :: M1N4MAGxi = 3487 + INTEGER(IntKi), PARAMETER :: M1N5MAGxi = 3488 + INTEGER(IntKi), PARAMETER :: M1N6MAGxi = 3489 + INTEGER(IntKi), PARAMETER :: M1N7MAGxi = 3490 + INTEGER(IntKi), PARAMETER :: M1N8MAGxi = 3491 + INTEGER(IntKi), PARAMETER :: M1N9MAGxi = 3492 + INTEGER(IntKi), PARAMETER :: M2N1MAGxi = 3493 + INTEGER(IntKi), PARAMETER :: M2N2MAGxi = 3494 + INTEGER(IntKi), PARAMETER :: M2N3MAGxi = 3495 + INTEGER(IntKi), PARAMETER :: M2N4MAGxi = 3496 + INTEGER(IntKi), PARAMETER :: M2N5MAGxi = 3497 + INTEGER(IntKi), PARAMETER :: M2N6MAGxi = 3498 + INTEGER(IntKi), PARAMETER :: M2N7MAGxi = 3499 + INTEGER(IntKi), PARAMETER :: M2N8MAGxi = 3500 + INTEGER(IntKi), PARAMETER :: M2N9MAGxi = 3501 + INTEGER(IntKi), PARAMETER :: M3N1MAGxi = 3502 + INTEGER(IntKi), PARAMETER :: M3N2MAGxi = 3503 + INTEGER(IntKi), PARAMETER :: M3N3MAGxi = 3504 + INTEGER(IntKi), PARAMETER :: M3N4MAGxi = 3505 + INTEGER(IntKi), PARAMETER :: M3N5MAGxi = 3506 + INTEGER(IntKi), PARAMETER :: M3N6MAGxi = 3507 + INTEGER(IntKi), PARAMETER :: M3N7MAGxi = 3508 + INTEGER(IntKi), PARAMETER :: M3N8MAGxi = 3509 + INTEGER(IntKi), PARAMETER :: M3N9MAGxi = 3510 + INTEGER(IntKi), PARAMETER :: M4N1MAGxi = 3511 + INTEGER(IntKi), PARAMETER :: M4N2MAGxi = 3512 + INTEGER(IntKi), PARAMETER :: M4N3MAGxi = 3513 + INTEGER(IntKi), PARAMETER :: M4N4MAGxi = 3514 + INTEGER(IntKi), PARAMETER :: M4N5MAGxi = 3515 + INTEGER(IntKi), PARAMETER :: M4N6MAGxi = 3516 + INTEGER(IntKi), PARAMETER :: M4N7MAGxi = 3517 + INTEGER(IntKi), PARAMETER :: M4N8MAGxi = 3518 + INTEGER(IntKi), PARAMETER :: M4N9MAGxi = 3519 + INTEGER(IntKi), PARAMETER :: M5N1MAGxi = 3520 + INTEGER(IntKi), PARAMETER :: M5N2MAGxi = 3521 + INTEGER(IntKi), PARAMETER :: M5N3MAGxi = 3522 + INTEGER(IntKi), PARAMETER :: M5N4MAGxi = 3523 + INTEGER(IntKi), PARAMETER :: M5N5MAGxi = 3524 + INTEGER(IntKi), PARAMETER :: M5N6MAGxi = 3525 + INTEGER(IntKi), PARAMETER :: M5N7MAGxi = 3526 + INTEGER(IntKi), PARAMETER :: M5N8MAGxi = 3527 + INTEGER(IntKi), PARAMETER :: M5N9MAGxi = 3528 + INTEGER(IntKi), PARAMETER :: M6N1MAGxi = 3529 + INTEGER(IntKi), PARAMETER :: M6N2MAGxi = 3530 + INTEGER(IntKi), PARAMETER :: M6N3MAGxi = 3531 + INTEGER(IntKi), PARAMETER :: M6N4MAGxi = 3532 + INTEGER(IntKi), PARAMETER :: M6N5MAGxi = 3533 + INTEGER(IntKi), PARAMETER :: M6N6MAGxi = 3534 + INTEGER(IntKi), PARAMETER :: M6N7MAGxi = 3535 + INTEGER(IntKi), PARAMETER :: M6N8MAGxi = 3536 + INTEGER(IntKi), PARAMETER :: M6N9MAGxi = 3537 + INTEGER(IntKi), PARAMETER :: M7N1MAGxi = 3538 + INTEGER(IntKi), PARAMETER :: M7N2MAGxi = 3539 + INTEGER(IntKi), PARAMETER :: M7N3MAGxi = 3540 + INTEGER(IntKi), PARAMETER :: M7N4MAGxi = 3541 + INTEGER(IntKi), PARAMETER :: M7N5MAGxi = 3542 + INTEGER(IntKi), PARAMETER :: M7N6MAGxi = 3543 + INTEGER(IntKi), PARAMETER :: M7N7MAGxi = 3544 + INTEGER(IntKi), PARAMETER :: M7N8MAGxi = 3545 + INTEGER(IntKi), PARAMETER :: M7N9MAGxi = 3546 + INTEGER(IntKi), PARAMETER :: M8N1MAGxi = 3547 + INTEGER(IntKi), PARAMETER :: M8N2MAGxi = 3548 + INTEGER(IntKi), PARAMETER :: M8N3MAGxi = 3549 + INTEGER(IntKi), PARAMETER :: M8N4MAGxi = 3550 + INTEGER(IntKi), PARAMETER :: M8N5MAGxi = 3551 + INTEGER(IntKi), PARAMETER :: M8N6MAGxi = 3552 + INTEGER(IntKi), PARAMETER :: M8N7MAGxi = 3553 + INTEGER(IntKi), PARAMETER :: M8N8MAGxi = 3554 + INTEGER(IntKi), PARAMETER :: M8N9MAGxi = 3555 + INTEGER(IntKi), PARAMETER :: M9N1MAGxi = 3556 + INTEGER(IntKi), PARAMETER :: M9N2MAGxi = 3557 + INTEGER(IntKi), PARAMETER :: M9N3MAGxi = 3558 + INTEGER(IntKi), PARAMETER :: M9N4MAGxi = 3559 + INTEGER(IntKi), PARAMETER :: M9N5MAGxi = 3560 + INTEGER(IntKi), PARAMETER :: M9N6MAGxi = 3561 + INTEGER(IntKi), PARAMETER :: M9N7MAGxi = 3562 + INTEGER(IntKi), PARAMETER :: M9N8MAGxi = 3563 + INTEGER(IntKi), PARAMETER :: M9N9MAGxi = 3564 + INTEGER(IntKi), PARAMETER :: M1N1MAGyi = 3565 + INTEGER(IntKi), PARAMETER :: M1N2MAGyi = 3566 + INTEGER(IntKi), PARAMETER :: M1N3MAGyi = 3567 + INTEGER(IntKi), PARAMETER :: M1N4MAGyi = 3568 + INTEGER(IntKi), PARAMETER :: M1N5MAGyi = 3569 + INTEGER(IntKi), PARAMETER :: M1N6MAGyi = 3570 + INTEGER(IntKi), PARAMETER :: M1N7MAGyi = 3571 + INTEGER(IntKi), PARAMETER :: M1N8MAGyi = 3572 + INTEGER(IntKi), PARAMETER :: M1N9MAGyi = 3573 + INTEGER(IntKi), PARAMETER :: M2N1MAGyi = 3574 + INTEGER(IntKi), PARAMETER :: M2N2MAGyi = 3575 + INTEGER(IntKi), PARAMETER :: M2N3MAGyi = 3576 + INTEGER(IntKi), PARAMETER :: M2N4MAGyi = 3577 + INTEGER(IntKi), PARAMETER :: M2N5MAGyi = 3578 + INTEGER(IntKi), PARAMETER :: M2N6MAGyi = 3579 + INTEGER(IntKi), PARAMETER :: M2N7MAGyi = 3580 + INTEGER(IntKi), PARAMETER :: M2N8MAGyi = 3581 + INTEGER(IntKi), PARAMETER :: M2N9MAGyi = 3582 + INTEGER(IntKi), PARAMETER :: M3N1MAGyi = 3583 + INTEGER(IntKi), PARAMETER :: M3N2MAGyi = 3584 + INTEGER(IntKi), PARAMETER :: M3N3MAGyi = 3585 + INTEGER(IntKi), PARAMETER :: M3N4MAGyi = 3586 + INTEGER(IntKi), PARAMETER :: M3N5MAGyi = 3587 + INTEGER(IntKi), PARAMETER :: M3N6MAGyi = 3588 + INTEGER(IntKi), PARAMETER :: M3N7MAGyi = 3589 + INTEGER(IntKi), PARAMETER :: M3N8MAGyi = 3590 + INTEGER(IntKi), PARAMETER :: M3N9MAGyi = 3591 + INTEGER(IntKi), PARAMETER :: M4N1MAGyi = 3592 + INTEGER(IntKi), PARAMETER :: M4N2MAGyi = 3593 + INTEGER(IntKi), PARAMETER :: M4N3MAGyi = 3594 + INTEGER(IntKi), PARAMETER :: M4N4MAGyi = 3595 + INTEGER(IntKi), PARAMETER :: M4N5MAGyi = 3596 + INTEGER(IntKi), PARAMETER :: M4N6MAGyi = 3597 + INTEGER(IntKi), PARAMETER :: M4N7MAGyi = 3598 + INTEGER(IntKi), PARAMETER :: M4N8MAGyi = 3599 + INTEGER(IntKi), PARAMETER :: M4N9MAGyi = 3600 + INTEGER(IntKi), PARAMETER :: M5N1MAGyi = 3601 + INTEGER(IntKi), PARAMETER :: M5N2MAGyi = 3602 + INTEGER(IntKi), PARAMETER :: M5N3MAGyi = 3603 + INTEGER(IntKi), PARAMETER :: M5N4MAGyi = 3604 + INTEGER(IntKi), PARAMETER :: M5N5MAGyi = 3605 + INTEGER(IntKi), PARAMETER :: M5N6MAGyi = 3606 + INTEGER(IntKi), PARAMETER :: M5N7MAGyi = 3607 + INTEGER(IntKi), PARAMETER :: M5N8MAGyi = 3608 + INTEGER(IntKi), PARAMETER :: M5N9MAGyi = 3609 + INTEGER(IntKi), PARAMETER :: M6N1MAGyi = 3610 + INTEGER(IntKi), PARAMETER :: M6N2MAGyi = 3611 + INTEGER(IntKi), PARAMETER :: M6N3MAGyi = 3612 + INTEGER(IntKi), PARAMETER :: M6N4MAGyi = 3613 + INTEGER(IntKi), PARAMETER :: M6N5MAGyi = 3614 + INTEGER(IntKi), PARAMETER :: M6N6MAGyi = 3615 + INTEGER(IntKi), PARAMETER :: M6N7MAGyi = 3616 + INTEGER(IntKi), PARAMETER :: M6N8MAGyi = 3617 + INTEGER(IntKi), PARAMETER :: M6N9MAGyi = 3618 + INTEGER(IntKi), PARAMETER :: M7N1MAGyi = 3619 + INTEGER(IntKi), PARAMETER :: M7N2MAGyi = 3620 + INTEGER(IntKi), PARAMETER :: M7N3MAGyi = 3621 + INTEGER(IntKi), PARAMETER :: M7N4MAGyi = 3622 + INTEGER(IntKi), PARAMETER :: M7N5MAGyi = 3623 + INTEGER(IntKi), PARAMETER :: M7N6MAGyi = 3624 + INTEGER(IntKi), PARAMETER :: M7N7MAGyi = 3625 + INTEGER(IntKi), PARAMETER :: M7N8MAGyi = 3626 + INTEGER(IntKi), PARAMETER :: M7N9MAGyi = 3627 + INTEGER(IntKi), PARAMETER :: M8N1MAGyi = 3628 + INTEGER(IntKi), PARAMETER :: M8N2MAGyi = 3629 + INTEGER(IntKi), PARAMETER :: M8N3MAGyi = 3630 + INTEGER(IntKi), PARAMETER :: M8N4MAGyi = 3631 + INTEGER(IntKi), PARAMETER :: M8N5MAGyi = 3632 + INTEGER(IntKi), PARAMETER :: M8N6MAGyi = 3633 + INTEGER(IntKi), PARAMETER :: M8N7MAGyi = 3634 + INTEGER(IntKi), PARAMETER :: M8N8MAGyi = 3635 + INTEGER(IntKi), PARAMETER :: M8N9MAGyi = 3636 + INTEGER(IntKi), PARAMETER :: M9N1MAGyi = 3637 + INTEGER(IntKi), PARAMETER :: M9N2MAGyi = 3638 + INTEGER(IntKi), PARAMETER :: M9N3MAGyi = 3639 + INTEGER(IntKi), PARAMETER :: M9N4MAGyi = 3640 + INTEGER(IntKi), PARAMETER :: M9N5MAGyi = 3641 + INTEGER(IntKi), PARAMETER :: M9N6MAGyi = 3642 + INTEGER(IntKi), PARAMETER :: M9N7MAGyi = 3643 + INTEGER(IntKi), PARAMETER :: M9N8MAGyi = 3644 + INTEGER(IntKi), PARAMETER :: M9N9MAGyi = 3645 + INTEGER(IntKi), PARAMETER :: M1N1MAGzi = 3646 + INTEGER(IntKi), PARAMETER :: M1N2MAGzi = 3647 + INTEGER(IntKi), PARAMETER :: M1N3MAGzi = 3648 + INTEGER(IntKi), PARAMETER :: M1N4MAGzi = 3649 + INTEGER(IntKi), PARAMETER :: M1N5MAGzi = 3650 + INTEGER(IntKi), PARAMETER :: M1N6MAGzi = 3651 + INTEGER(IntKi), PARAMETER :: M1N7MAGzi = 3652 + INTEGER(IntKi), PARAMETER :: M1N8MAGzi = 3653 + INTEGER(IntKi), PARAMETER :: M1N9MAGzi = 3654 + INTEGER(IntKi), PARAMETER :: M2N1MAGzi = 3655 + INTEGER(IntKi), PARAMETER :: M2N2MAGzi = 3656 + INTEGER(IntKi), PARAMETER :: M2N3MAGzi = 3657 + INTEGER(IntKi), PARAMETER :: M2N4MAGzi = 3658 + INTEGER(IntKi), PARAMETER :: M2N5MAGzi = 3659 + INTEGER(IntKi), PARAMETER :: M2N6MAGzi = 3660 + INTEGER(IntKi), PARAMETER :: M2N7MAGzi = 3661 + INTEGER(IntKi), PARAMETER :: M2N8MAGzi = 3662 + INTEGER(IntKi), PARAMETER :: M2N9MAGzi = 3663 + INTEGER(IntKi), PARAMETER :: M3N1MAGzi = 3664 + INTEGER(IntKi), PARAMETER :: M3N2MAGzi = 3665 + INTEGER(IntKi), PARAMETER :: M3N3MAGzi = 3666 + INTEGER(IntKi), PARAMETER :: M3N4MAGzi = 3667 + INTEGER(IntKi), PARAMETER :: M3N5MAGzi = 3668 + INTEGER(IntKi), PARAMETER :: M3N6MAGzi = 3669 + INTEGER(IntKi), PARAMETER :: M3N7MAGzi = 3670 + INTEGER(IntKi), PARAMETER :: M3N8MAGzi = 3671 + INTEGER(IntKi), PARAMETER :: M3N9MAGzi = 3672 + INTEGER(IntKi), PARAMETER :: M4N1MAGzi = 3673 + INTEGER(IntKi), PARAMETER :: M4N2MAGzi = 3674 + INTEGER(IntKi), PARAMETER :: M4N3MAGzi = 3675 + INTEGER(IntKi), PARAMETER :: M4N4MAGzi = 3676 + INTEGER(IntKi), PARAMETER :: M4N5MAGzi = 3677 + INTEGER(IntKi), PARAMETER :: M4N6MAGzi = 3678 + INTEGER(IntKi), PARAMETER :: M4N7MAGzi = 3679 + INTEGER(IntKi), PARAMETER :: M4N8MAGzi = 3680 + INTEGER(IntKi), PARAMETER :: M4N9MAGzi = 3681 + INTEGER(IntKi), PARAMETER :: M5N1MAGzi = 3682 + INTEGER(IntKi), PARAMETER :: M5N2MAGzi = 3683 + INTEGER(IntKi), PARAMETER :: M5N3MAGzi = 3684 + INTEGER(IntKi), PARAMETER :: M5N4MAGzi = 3685 + INTEGER(IntKi), PARAMETER :: M5N5MAGzi = 3686 + INTEGER(IntKi), PARAMETER :: M5N6MAGzi = 3687 + INTEGER(IntKi), PARAMETER :: M5N7MAGzi = 3688 + INTEGER(IntKi), PARAMETER :: M5N8MAGzi = 3689 + INTEGER(IntKi), PARAMETER :: M5N9MAGzi = 3690 + INTEGER(IntKi), PARAMETER :: M6N1MAGzi = 3691 + INTEGER(IntKi), PARAMETER :: M6N2MAGzi = 3692 + INTEGER(IntKi), PARAMETER :: M6N3MAGzi = 3693 + INTEGER(IntKi), PARAMETER :: M6N4MAGzi = 3694 + INTEGER(IntKi), PARAMETER :: M6N5MAGzi = 3695 + INTEGER(IntKi), PARAMETER :: M6N6MAGzi = 3696 + INTEGER(IntKi), PARAMETER :: M6N7MAGzi = 3697 + INTEGER(IntKi), PARAMETER :: M6N8MAGzi = 3698 + INTEGER(IntKi), PARAMETER :: M6N9MAGzi = 3699 + INTEGER(IntKi), PARAMETER :: M7N1MAGzi = 3700 + INTEGER(IntKi), PARAMETER :: M7N2MAGzi = 3701 + INTEGER(IntKi), PARAMETER :: M7N3MAGzi = 3702 + INTEGER(IntKi), PARAMETER :: M7N4MAGzi = 3703 + INTEGER(IntKi), PARAMETER :: M7N5MAGzi = 3704 + INTEGER(IntKi), PARAMETER :: M7N6MAGzi = 3705 + INTEGER(IntKi), PARAMETER :: M7N7MAGzi = 3706 + INTEGER(IntKi), PARAMETER :: M7N8MAGzi = 3707 + INTEGER(IntKi), PARAMETER :: M7N9MAGzi = 3708 + INTEGER(IntKi), PARAMETER :: M8N1MAGzi = 3709 + INTEGER(IntKi), PARAMETER :: M8N2MAGzi = 3710 + INTEGER(IntKi), PARAMETER :: M8N3MAGzi = 3711 + INTEGER(IntKi), PARAMETER :: M8N4MAGzi = 3712 + INTEGER(IntKi), PARAMETER :: M8N5MAGzi = 3713 + INTEGER(IntKi), PARAMETER :: M8N6MAGzi = 3714 + INTEGER(IntKi), PARAMETER :: M8N7MAGzi = 3715 + INTEGER(IntKi), PARAMETER :: M8N8MAGzi = 3716 + INTEGER(IntKi), PARAMETER :: M8N9MAGzi = 3717 + INTEGER(IntKi), PARAMETER :: M9N1MAGzi = 3718 + INTEGER(IntKi), PARAMETER :: M9N2MAGzi = 3719 + INTEGER(IntKi), PARAMETER :: M9N3MAGzi = 3720 + INTEGER(IntKi), PARAMETER :: M9N4MAGzi = 3721 + INTEGER(IntKi), PARAMETER :: M9N5MAGzi = 3722 + INTEGER(IntKi), PARAMETER :: M9N6MAGzi = 3723 + INTEGER(IntKi), PARAMETER :: M9N7MAGzi = 3724 + INTEGER(IntKi), PARAMETER :: M9N8MAGzi = 3725 + INTEGER(IntKi), PARAMETER :: M9N9MAGzi = 3726 + INTEGER(IntKi), PARAMETER :: M1N1FAFxi = 3727 + INTEGER(IntKi), PARAMETER :: M1N2FAFxi = 3728 + INTEGER(IntKi), PARAMETER :: M1N3FAFxi = 3729 + INTEGER(IntKi), PARAMETER :: M1N4FAFxi = 3730 + INTEGER(IntKi), PARAMETER :: M1N5FAFxi = 3731 + INTEGER(IntKi), PARAMETER :: M1N6FAFxi = 3732 + INTEGER(IntKi), PARAMETER :: M1N7FAFxi = 3733 + INTEGER(IntKi), PARAMETER :: M1N8FAFxi = 3734 + INTEGER(IntKi), PARAMETER :: M1N9FAFxi = 3735 + INTEGER(IntKi), PARAMETER :: M2N1FAFxi = 3736 + INTEGER(IntKi), PARAMETER :: M2N2FAFxi = 3737 + INTEGER(IntKi), PARAMETER :: M2N3FAFxi = 3738 + INTEGER(IntKi), PARAMETER :: M2N4FAFxi = 3739 + INTEGER(IntKi), PARAMETER :: M2N5FAFxi = 3740 + INTEGER(IntKi), PARAMETER :: M2N6FAFxi = 3741 + INTEGER(IntKi), PARAMETER :: M2N7FAFxi = 3742 + INTEGER(IntKi), PARAMETER :: M2N8FAFxi = 3743 + INTEGER(IntKi), PARAMETER :: M2N9FAFxi = 3744 + INTEGER(IntKi), PARAMETER :: M3N1FAFxi = 3745 + INTEGER(IntKi), PARAMETER :: M3N2FAFxi = 3746 + INTEGER(IntKi), PARAMETER :: M3N3FAFxi = 3747 + INTEGER(IntKi), PARAMETER :: M3N4FAFxi = 3748 + INTEGER(IntKi), PARAMETER :: M3N5FAFxi = 3749 + INTEGER(IntKi), PARAMETER :: M3N6FAFxi = 3750 + INTEGER(IntKi), PARAMETER :: M3N7FAFxi = 3751 + INTEGER(IntKi), PARAMETER :: M3N8FAFxi = 3752 + INTEGER(IntKi), PARAMETER :: M3N9FAFxi = 3753 + INTEGER(IntKi), PARAMETER :: M4N1FAFxi = 3754 + INTEGER(IntKi), PARAMETER :: M4N2FAFxi = 3755 + INTEGER(IntKi), PARAMETER :: M4N3FAFxi = 3756 + INTEGER(IntKi), PARAMETER :: M4N4FAFxi = 3757 + INTEGER(IntKi), PARAMETER :: M4N5FAFxi = 3758 + INTEGER(IntKi), PARAMETER :: M4N6FAFxi = 3759 + INTEGER(IntKi), PARAMETER :: M4N7FAFxi = 3760 + INTEGER(IntKi), PARAMETER :: M4N8FAFxi = 3761 + INTEGER(IntKi), PARAMETER :: M4N9FAFxi = 3762 + INTEGER(IntKi), PARAMETER :: M5N1FAFxi = 3763 + INTEGER(IntKi), PARAMETER :: M5N2FAFxi = 3764 + INTEGER(IntKi), PARAMETER :: M5N3FAFxi = 3765 + INTEGER(IntKi), PARAMETER :: M5N4FAFxi = 3766 + INTEGER(IntKi), PARAMETER :: M5N5FAFxi = 3767 + INTEGER(IntKi), PARAMETER :: M5N6FAFxi = 3768 + INTEGER(IntKi), PARAMETER :: M5N7FAFxi = 3769 + INTEGER(IntKi), PARAMETER :: M5N8FAFxi = 3770 + INTEGER(IntKi), PARAMETER :: M5N9FAFxi = 3771 + INTEGER(IntKi), PARAMETER :: M6N1FAFxi = 3772 + INTEGER(IntKi), PARAMETER :: M6N2FAFxi = 3773 + INTEGER(IntKi), PARAMETER :: M6N3FAFxi = 3774 + INTEGER(IntKi), PARAMETER :: M6N4FAFxi = 3775 + INTEGER(IntKi), PARAMETER :: M6N5FAFxi = 3776 + INTEGER(IntKi), PARAMETER :: M6N6FAFxi = 3777 + INTEGER(IntKi), PARAMETER :: M6N7FAFxi = 3778 + INTEGER(IntKi), PARAMETER :: M6N8FAFxi = 3779 + INTEGER(IntKi), PARAMETER :: M6N9FAFxi = 3780 + INTEGER(IntKi), PARAMETER :: M7N1FAFxi = 3781 + INTEGER(IntKi), PARAMETER :: M7N2FAFxi = 3782 + INTEGER(IntKi), PARAMETER :: M7N3FAFxi = 3783 + INTEGER(IntKi), PARAMETER :: M7N4FAFxi = 3784 + INTEGER(IntKi), PARAMETER :: M7N5FAFxi = 3785 + INTEGER(IntKi), PARAMETER :: M7N6FAFxi = 3786 + INTEGER(IntKi), PARAMETER :: M7N7FAFxi = 3787 + INTEGER(IntKi), PARAMETER :: M7N8FAFxi = 3788 + INTEGER(IntKi), PARAMETER :: M7N9FAFxi = 3789 + INTEGER(IntKi), PARAMETER :: M8N1FAFxi = 3790 + INTEGER(IntKi), PARAMETER :: M8N2FAFxi = 3791 + INTEGER(IntKi), PARAMETER :: M8N3FAFxi = 3792 + INTEGER(IntKi), PARAMETER :: M8N4FAFxi = 3793 + INTEGER(IntKi), PARAMETER :: M8N5FAFxi = 3794 + INTEGER(IntKi), PARAMETER :: M8N6FAFxi = 3795 + INTEGER(IntKi), PARAMETER :: M8N7FAFxi = 3796 + INTEGER(IntKi), PARAMETER :: M8N8FAFxi = 3797 + INTEGER(IntKi), PARAMETER :: M8N9FAFxi = 3798 + INTEGER(IntKi), PARAMETER :: M9N1FAFxi = 3799 + INTEGER(IntKi), PARAMETER :: M9N2FAFxi = 3800 + INTEGER(IntKi), PARAMETER :: M9N3FAFxi = 3801 + INTEGER(IntKi), PARAMETER :: M9N4FAFxi = 3802 + INTEGER(IntKi), PARAMETER :: M9N5FAFxi = 3803 + INTEGER(IntKi), PARAMETER :: M9N6FAFxi = 3804 + INTEGER(IntKi), PARAMETER :: M9N7FAFxi = 3805 + INTEGER(IntKi), PARAMETER :: M9N8FAFxi = 3806 + INTEGER(IntKi), PARAMETER :: M9N9FAFxi = 3807 + INTEGER(IntKi), PARAMETER :: M1N1FAFyi = 3808 + INTEGER(IntKi), PARAMETER :: M1N2FAFyi = 3809 + INTEGER(IntKi), PARAMETER :: M1N3FAFyi = 3810 + INTEGER(IntKi), PARAMETER :: M1N4FAFyi = 3811 + INTEGER(IntKi), PARAMETER :: M1N5FAFyi = 3812 + INTEGER(IntKi), PARAMETER :: M1N6FAFyi = 3813 + INTEGER(IntKi), PARAMETER :: M1N7FAFyi = 3814 + INTEGER(IntKi), PARAMETER :: M1N8FAFyi = 3815 + INTEGER(IntKi), PARAMETER :: M1N9FAFyi = 3816 + INTEGER(IntKi), PARAMETER :: M2N1FAFyi = 3817 + INTEGER(IntKi), PARAMETER :: M2N2FAFyi = 3818 + INTEGER(IntKi), PARAMETER :: M2N3FAFyi = 3819 + INTEGER(IntKi), PARAMETER :: M2N4FAFyi = 3820 + INTEGER(IntKi), PARAMETER :: M2N5FAFyi = 3821 + INTEGER(IntKi), PARAMETER :: M2N6FAFyi = 3822 + INTEGER(IntKi), PARAMETER :: M2N7FAFyi = 3823 + INTEGER(IntKi), PARAMETER :: M2N8FAFyi = 3824 + INTEGER(IntKi), PARAMETER :: M2N9FAFyi = 3825 + INTEGER(IntKi), PARAMETER :: M3N1FAFyi = 3826 + INTEGER(IntKi), PARAMETER :: M3N2FAFyi = 3827 + INTEGER(IntKi), PARAMETER :: M3N3FAFyi = 3828 + INTEGER(IntKi), PARAMETER :: M3N4FAFyi = 3829 + INTEGER(IntKi), PARAMETER :: M3N5FAFyi = 3830 + INTEGER(IntKi), PARAMETER :: M3N6FAFyi = 3831 + INTEGER(IntKi), PARAMETER :: M3N7FAFyi = 3832 + INTEGER(IntKi), PARAMETER :: M3N8FAFyi = 3833 + INTEGER(IntKi), PARAMETER :: M3N9FAFyi = 3834 + INTEGER(IntKi), PARAMETER :: M4N1FAFyi = 3835 + INTEGER(IntKi), PARAMETER :: M4N2FAFyi = 3836 + INTEGER(IntKi), PARAMETER :: M4N3FAFyi = 3837 + INTEGER(IntKi), PARAMETER :: M4N4FAFyi = 3838 + INTEGER(IntKi), PARAMETER :: M4N5FAFyi = 3839 + INTEGER(IntKi), PARAMETER :: M4N6FAFyi = 3840 + INTEGER(IntKi), PARAMETER :: M4N7FAFyi = 3841 + INTEGER(IntKi), PARAMETER :: M4N8FAFyi = 3842 + INTEGER(IntKi), PARAMETER :: M4N9FAFyi = 3843 + INTEGER(IntKi), PARAMETER :: M5N1FAFyi = 3844 + INTEGER(IntKi), PARAMETER :: M5N2FAFyi = 3845 + INTEGER(IntKi), PARAMETER :: M5N3FAFyi = 3846 + INTEGER(IntKi), PARAMETER :: M5N4FAFyi = 3847 + INTEGER(IntKi), PARAMETER :: M5N5FAFyi = 3848 + INTEGER(IntKi), PARAMETER :: M5N6FAFyi = 3849 + INTEGER(IntKi), PARAMETER :: M5N7FAFyi = 3850 + INTEGER(IntKi), PARAMETER :: M5N8FAFyi = 3851 + INTEGER(IntKi), PARAMETER :: M5N9FAFyi = 3852 + INTEGER(IntKi), PARAMETER :: M6N1FAFyi = 3853 + INTEGER(IntKi), PARAMETER :: M6N2FAFyi = 3854 + INTEGER(IntKi), PARAMETER :: M6N3FAFyi = 3855 + INTEGER(IntKi), PARAMETER :: M6N4FAFyi = 3856 + INTEGER(IntKi), PARAMETER :: M6N5FAFyi = 3857 + INTEGER(IntKi), PARAMETER :: M6N6FAFyi = 3858 + INTEGER(IntKi), PARAMETER :: M6N7FAFyi = 3859 + INTEGER(IntKi), PARAMETER :: M6N8FAFyi = 3860 + INTEGER(IntKi), PARAMETER :: M6N9FAFyi = 3861 + INTEGER(IntKi), PARAMETER :: M7N1FAFyi = 3862 + INTEGER(IntKi), PARAMETER :: M7N2FAFyi = 3863 + INTEGER(IntKi), PARAMETER :: M7N3FAFyi = 3864 + INTEGER(IntKi), PARAMETER :: M7N4FAFyi = 3865 + INTEGER(IntKi), PARAMETER :: M7N5FAFyi = 3866 + INTEGER(IntKi), PARAMETER :: M7N6FAFyi = 3867 + INTEGER(IntKi), PARAMETER :: M7N7FAFyi = 3868 + INTEGER(IntKi), PARAMETER :: M7N8FAFyi = 3869 + INTEGER(IntKi), PARAMETER :: M7N9FAFyi = 3870 + INTEGER(IntKi), PARAMETER :: M8N1FAFyi = 3871 + INTEGER(IntKi), PARAMETER :: M8N2FAFyi = 3872 + INTEGER(IntKi), PARAMETER :: M8N3FAFyi = 3873 + INTEGER(IntKi), PARAMETER :: M8N4FAFyi = 3874 + INTEGER(IntKi), PARAMETER :: M8N5FAFyi = 3875 + INTEGER(IntKi), PARAMETER :: M8N6FAFyi = 3876 + INTEGER(IntKi), PARAMETER :: M8N7FAFyi = 3877 + INTEGER(IntKi), PARAMETER :: M8N8FAFyi = 3878 + INTEGER(IntKi), PARAMETER :: M8N9FAFyi = 3879 + INTEGER(IntKi), PARAMETER :: M9N1FAFyi = 3880 + INTEGER(IntKi), PARAMETER :: M9N2FAFyi = 3881 + INTEGER(IntKi), PARAMETER :: M9N3FAFyi = 3882 + INTEGER(IntKi), PARAMETER :: M9N4FAFyi = 3883 + INTEGER(IntKi), PARAMETER :: M9N5FAFyi = 3884 + INTEGER(IntKi), PARAMETER :: M9N6FAFyi = 3885 + INTEGER(IntKi), PARAMETER :: M9N7FAFyi = 3886 + INTEGER(IntKi), PARAMETER :: M9N8FAFyi = 3887 + INTEGER(IntKi), PARAMETER :: M9N9FAFyi = 3888 + INTEGER(IntKi), PARAMETER :: M1N1FAFzi = 3889 + INTEGER(IntKi), PARAMETER :: M1N2FAFzi = 3890 + INTEGER(IntKi), PARAMETER :: M1N3FAFzi = 3891 + INTEGER(IntKi), PARAMETER :: M1N4FAFzi = 3892 + INTEGER(IntKi), PARAMETER :: M1N5FAFzi = 3893 + INTEGER(IntKi), PARAMETER :: M1N6FAFzi = 3894 + INTEGER(IntKi), PARAMETER :: M1N7FAFzi = 3895 + INTEGER(IntKi), PARAMETER :: M1N8FAFzi = 3896 + INTEGER(IntKi), PARAMETER :: M1N9FAFzi = 3897 + INTEGER(IntKi), PARAMETER :: M2N1FAFzi = 3898 + INTEGER(IntKi), PARAMETER :: M2N2FAFzi = 3899 + INTEGER(IntKi), PARAMETER :: M2N3FAFzi = 3900 + INTEGER(IntKi), PARAMETER :: M2N4FAFzi = 3901 + INTEGER(IntKi), PARAMETER :: M2N5FAFzi = 3902 + INTEGER(IntKi), PARAMETER :: M2N6FAFzi = 3903 + INTEGER(IntKi), PARAMETER :: M2N7FAFzi = 3904 + INTEGER(IntKi), PARAMETER :: M2N8FAFzi = 3905 + INTEGER(IntKi), PARAMETER :: M2N9FAFzi = 3906 + INTEGER(IntKi), PARAMETER :: M3N1FAFzi = 3907 + INTEGER(IntKi), PARAMETER :: M3N2FAFzi = 3908 + INTEGER(IntKi), PARAMETER :: M3N3FAFzi = 3909 + INTEGER(IntKi), PARAMETER :: M3N4FAFzi = 3910 + INTEGER(IntKi), PARAMETER :: M3N5FAFzi = 3911 + INTEGER(IntKi), PARAMETER :: M3N6FAFzi = 3912 + INTEGER(IntKi), PARAMETER :: M3N7FAFzi = 3913 + INTEGER(IntKi), PARAMETER :: M3N8FAFzi = 3914 + INTEGER(IntKi), PARAMETER :: M3N9FAFzi = 3915 + INTEGER(IntKi), PARAMETER :: M4N1FAFzi = 3916 + INTEGER(IntKi), PARAMETER :: M4N2FAFzi = 3917 + INTEGER(IntKi), PARAMETER :: M4N3FAFzi = 3918 + INTEGER(IntKi), PARAMETER :: M4N4FAFzi = 3919 + INTEGER(IntKi), PARAMETER :: M4N5FAFzi = 3920 + INTEGER(IntKi), PARAMETER :: M4N6FAFzi = 3921 + INTEGER(IntKi), PARAMETER :: M4N7FAFzi = 3922 + INTEGER(IntKi), PARAMETER :: M4N8FAFzi = 3923 + INTEGER(IntKi), PARAMETER :: M4N9FAFzi = 3924 + INTEGER(IntKi), PARAMETER :: M5N1FAFzi = 3925 + INTEGER(IntKi), PARAMETER :: M5N2FAFzi = 3926 + INTEGER(IntKi), PARAMETER :: M5N3FAFzi = 3927 + INTEGER(IntKi), PARAMETER :: M5N4FAFzi = 3928 + INTEGER(IntKi), PARAMETER :: M5N5FAFzi = 3929 + INTEGER(IntKi), PARAMETER :: M5N6FAFzi = 3930 + INTEGER(IntKi), PARAMETER :: M5N7FAFzi = 3931 + INTEGER(IntKi), PARAMETER :: M5N8FAFzi = 3932 + INTEGER(IntKi), PARAMETER :: M5N9FAFzi = 3933 + INTEGER(IntKi), PARAMETER :: M6N1FAFzi = 3934 + INTEGER(IntKi), PARAMETER :: M6N2FAFzi = 3935 + INTEGER(IntKi), PARAMETER :: M6N3FAFzi = 3936 + INTEGER(IntKi), PARAMETER :: M6N4FAFzi = 3937 + INTEGER(IntKi), PARAMETER :: M6N5FAFzi = 3938 + INTEGER(IntKi), PARAMETER :: M6N6FAFzi = 3939 + INTEGER(IntKi), PARAMETER :: M6N7FAFzi = 3940 + INTEGER(IntKi), PARAMETER :: M6N8FAFzi = 3941 + INTEGER(IntKi), PARAMETER :: M6N9FAFzi = 3942 + INTEGER(IntKi), PARAMETER :: M7N1FAFzi = 3943 + INTEGER(IntKi), PARAMETER :: M7N2FAFzi = 3944 + INTEGER(IntKi), PARAMETER :: M7N3FAFzi = 3945 + INTEGER(IntKi), PARAMETER :: M7N4FAFzi = 3946 + INTEGER(IntKi), PARAMETER :: M7N5FAFzi = 3947 + INTEGER(IntKi), PARAMETER :: M7N6FAFzi = 3948 + INTEGER(IntKi), PARAMETER :: M7N7FAFzi = 3949 + INTEGER(IntKi), PARAMETER :: M7N8FAFzi = 3950 + INTEGER(IntKi), PARAMETER :: M7N9FAFzi = 3951 + INTEGER(IntKi), PARAMETER :: M8N1FAFzi = 3952 + INTEGER(IntKi), PARAMETER :: M8N2FAFzi = 3953 + INTEGER(IntKi), PARAMETER :: M8N3FAFzi = 3954 + INTEGER(IntKi), PARAMETER :: M8N4FAFzi = 3955 + INTEGER(IntKi), PARAMETER :: M8N5FAFzi = 3956 + INTEGER(IntKi), PARAMETER :: M8N6FAFzi = 3957 + INTEGER(IntKi), PARAMETER :: M8N7FAFzi = 3958 + INTEGER(IntKi), PARAMETER :: M8N8FAFzi = 3959 + INTEGER(IntKi), PARAMETER :: M8N9FAFzi = 3960 + INTEGER(IntKi), PARAMETER :: M9N1FAFzi = 3961 + INTEGER(IntKi), PARAMETER :: M9N2FAFzi = 3962 + INTEGER(IntKi), PARAMETER :: M9N3FAFzi = 3963 + INTEGER(IntKi), PARAMETER :: M9N4FAFzi = 3964 + INTEGER(IntKi), PARAMETER :: M9N5FAFzi = 3965 + INTEGER(IntKi), PARAMETER :: M9N6FAFzi = 3966 + INTEGER(IntKi), PARAMETER :: M9N7FAFzi = 3967 + INTEGER(IntKi), PARAMETER :: M9N8FAFzi = 3968 + INTEGER(IntKi), PARAMETER :: M9N9FAFzi = 3969 + INTEGER(IntKi), PARAMETER :: M1N1MAFxi = 3970 + INTEGER(IntKi), PARAMETER :: M1N2MAFxi = 3971 + INTEGER(IntKi), PARAMETER :: M1N3MAFxi = 3972 + INTEGER(IntKi), PARAMETER :: M1N4MAFxi = 3973 + INTEGER(IntKi), PARAMETER :: M1N5MAFxi = 3974 + INTEGER(IntKi), PARAMETER :: M1N6MAFxi = 3975 + INTEGER(IntKi), PARAMETER :: M1N7MAFxi = 3976 + INTEGER(IntKi), PARAMETER :: M1N8MAFxi = 3977 + INTEGER(IntKi), PARAMETER :: M1N9MAFxi = 3978 + INTEGER(IntKi), PARAMETER :: M2N1MAFxi = 3979 + INTEGER(IntKi), PARAMETER :: M2N2MAFxi = 3980 + INTEGER(IntKi), PARAMETER :: M2N3MAFxi = 3981 + INTEGER(IntKi), PARAMETER :: M2N4MAFxi = 3982 + INTEGER(IntKi), PARAMETER :: M2N5MAFxi = 3983 + INTEGER(IntKi), PARAMETER :: M2N6MAFxi = 3984 + INTEGER(IntKi), PARAMETER :: M2N7MAFxi = 3985 + INTEGER(IntKi), PARAMETER :: M2N8MAFxi = 3986 + INTEGER(IntKi), PARAMETER :: M2N9MAFxi = 3987 + INTEGER(IntKi), PARAMETER :: M3N1MAFxi = 3988 + INTEGER(IntKi), PARAMETER :: M3N2MAFxi = 3989 + INTEGER(IntKi), PARAMETER :: M3N3MAFxi = 3990 + INTEGER(IntKi), PARAMETER :: M3N4MAFxi = 3991 + INTEGER(IntKi), PARAMETER :: M3N5MAFxi = 3992 + INTEGER(IntKi), PARAMETER :: M3N6MAFxi = 3993 + INTEGER(IntKi), PARAMETER :: M3N7MAFxi = 3994 + INTEGER(IntKi), PARAMETER :: M3N8MAFxi = 3995 + INTEGER(IntKi), PARAMETER :: M3N9MAFxi = 3996 + INTEGER(IntKi), PARAMETER :: M4N1MAFxi = 3997 + INTEGER(IntKi), PARAMETER :: M4N2MAFxi = 3998 + INTEGER(IntKi), PARAMETER :: M4N3MAFxi = 3999 + INTEGER(IntKi), PARAMETER :: M4N4MAFxi = 4000 + INTEGER(IntKi), PARAMETER :: M4N5MAFxi = 4001 + INTEGER(IntKi), PARAMETER :: M4N6MAFxi = 4002 + INTEGER(IntKi), PARAMETER :: M4N7MAFxi = 4003 + INTEGER(IntKi), PARAMETER :: M4N8MAFxi = 4004 + INTEGER(IntKi), PARAMETER :: M4N9MAFxi = 4005 + INTEGER(IntKi), PARAMETER :: M5N1MAFxi = 4006 + INTEGER(IntKi), PARAMETER :: M5N2MAFxi = 4007 + INTEGER(IntKi), PARAMETER :: M5N3MAFxi = 4008 + INTEGER(IntKi), PARAMETER :: M5N4MAFxi = 4009 + INTEGER(IntKi), PARAMETER :: M5N5MAFxi = 4010 + INTEGER(IntKi), PARAMETER :: M5N6MAFxi = 4011 + INTEGER(IntKi), PARAMETER :: M5N7MAFxi = 4012 + INTEGER(IntKi), PARAMETER :: M5N8MAFxi = 4013 + INTEGER(IntKi), PARAMETER :: M5N9MAFxi = 4014 + INTEGER(IntKi), PARAMETER :: M6N1MAFxi = 4015 + INTEGER(IntKi), PARAMETER :: M6N2MAFxi = 4016 + INTEGER(IntKi), PARAMETER :: M6N3MAFxi = 4017 + INTEGER(IntKi), PARAMETER :: M6N4MAFxi = 4018 + INTEGER(IntKi), PARAMETER :: M6N5MAFxi = 4019 + INTEGER(IntKi), PARAMETER :: M6N6MAFxi = 4020 + INTEGER(IntKi), PARAMETER :: M6N7MAFxi = 4021 + INTEGER(IntKi), PARAMETER :: M6N8MAFxi = 4022 + INTEGER(IntKi), PARAMETER :: M6N9MAFxi = 4023 + INTEGER(IntKi), PARAMETER :: M7N1MAFxi = 4024 + INTEGER(IntKi), PARAMETER :: M7N2MAFxi = 4025 + INTEGER(IntKi), PARAMETER :: M7N3MAFxi = 4026 + INTEGER(IntKi), PARAMETER :: M7N4MAFxi = 4027 + INTEGER(IntKi), PARAMETER :: M7N5MAFxi = 4028 + INTEGER(IntKi), PARAMETER :: M7N6MAFxi = 4029 + INTEGER(IntKi), PARAMETER :: M7N7MAFxi = 4030 + INTEGER(IntKi), PARAMETER :: M7N8MAFxi = 4031 + INTEGER(IntKi), PARAMETER :: M7N9MAFxi = 4032 + INTEGER(IntKi), PARAMETER :: M8N1MAFxi = 4033 + INTEGER(IntKi), PARAMETER :: M8N2MAFxi = 4034 + INTEGER(IntKi), PARAMETER :: M8N3MAFxi = 4035 + INTEGER(IntKi), PARAMETER :: M8N4MAFxi = 4036 + INTEGER(IntKi), PARAMETER :: M8N5MAFxi = 4037 + INTEGER(IntKi), PARAMETER :: M8N6MAFxi = 4038 + INTEGER(IntKi), PARAMETER :: M8N7MAFxi = 4039 + INTEGER(IntKi), PARAMETER :: M8N8MAFxi = 4040 + INTEGER(IntKi), PARAMETER :: M8N9MAFxi = 4041 + INTEGER(IntKi), PARAMETER :: M9N1MAFxi = 4042 + INTEGER(IntKi), PARAMETER :: M9N2MAFxi = 4043 + INTEGER(IntKi), PARAMETER :: M9N3MAFxi = 4044 + INTEGER(IntKi), PARAMETER :: M9N4MAFxi = 4045 + INTEGER(IntKi), PARAMETER :: M9N5MAFxi = 4046 + INTEGER(IntKi), PARAMETER :: M9N6MAFxi = 4047 + INTEGER(IntKi), PARAMETER :: M9N7MAFxi = 4048 + INTEGER(IntKi), PARAMETER :: M9N8MAFxi = 4049 + INTEGER(IntKi), PARAMETER :: M9N9MAFxi = 4050 + INTEGER(IntKi), PARAMETER :: M1N1MAFyi = 4051 + INTEGER(IntKi), PARAMETER :: M1N2MAFyi = 4052 + INTEGER(IntKi), PARAMETER :: M1N3MAFyi = 4053 + INTEGER(IntKi), PARAMETER :: M1N4MAFyi = 4054 + INTEGER(IntKi), PARAMETER :: M1N5MAFyi = 4055 + INTEGER(IntKi), PARAMETER :: M1N6MAFyi = 4056 + INTEGER(IntKi), PARAMETER :: M1N7MAFyi = 4057 + INTEGER(IntKi), PARAMETER :: M1N8MAFyi = 4058 + INTEGER(IntKi), PARAMETER :: M1N9MAFyi = 4059 + INTEGER(IntKi), PARAMETER :: M2N1MAFyi = 4060 + INTEGER(IntKi), PARAMETER :: M2N2MAFyi = 4061 + INTEGER(IntKi), PARAMETER :: M2N3MAFyi = 4062 + INTEGER(IntKi), PARAMETER :: M2N4MAFyi = 4063 + INTEGER(IntKi), PARAMETER :: M2N5MAFyi = 4064 + INTEGER(IntKi), PARAMETER :: M2N6MAFyi = 4065 + INTEGER(IntKi), PARAMETER :: M2N7MAFyi = 4066 + INTEGER(IntKi), PARAMETER :: M2N8MAFyi = 4067 + INTEGER(IntKi), PARAMETER :: M2N9MAFyi = 4068 + INTEGER(IntKi), PARAMETER :: M3N1MAFyi = 4069 + INTEGER(IntKi), PARAMETER :: M3N2MAFyi = 4070 + INTEGER(IntKi), PARAMETER :: M3N3MAFyi = 4071 + INTEGER(IntKi), PARAMETER :: M3N4MAFyi = 4072 + INTEGER(IntKi), PARAMETER :: M3N5MAFyi = 4073 + INTEGER(IntKi), PARAMETER :: M3N6MAFyi = 4074 + INTEGER(IntKi), PARAMETER :: M3N7MAFyi = 4075 + INTEGER(IntKi), PARAMETER :: M3N8MAFyi = 4076 + INTEGER(IntKi), PARAMETER :: M3N9MAFyi = 4077 + INTEGER(IntKi), PARAMETER :: M4N1MAFyi = 4078 + INTEGER(IntKi), PARAMETER :: M4N2MAFyi = 4079 + INTEGER(IntKi), PARAMETER :: M4N3MAFyi = 4080 + INTEGER(IntKi), PARAMETER :: M4N4MAFyi = 4081 + INTEGER(IntKi), PARAMETER :: M4N5MAFyi = 4082 + INTEGER(IntKi), PARAMETER :: M4N6MAFyi = 4083 + INTEGER(IntKi), PARAMETER :: M4N7MAFyi = 4084 + INTEGER(IntKi), PARAMETER :: M4N8MAFyi = 4085 + INTEGER(IntKi), PARAMETER :: M4N9MAFyi = 4086 + INTEGER(IntKi), PARAMETER :: M5N1MAFyi = 4087 + INTEGER(IntKi), PARAMETER :: M5N2MAFyi = 4088 + INTEGER(IntKi), PARAMETER :: M5N3MAFyi = 4089 + INTEGER(IntKi), PARAMETER :: M5N4MAFyi = 4090 + INTEGER(IntKi), PARAMETER :: M5N5MAFyi = 4091 + INTEGER(IntKi), PARAMETER :: M5N6MAFyi = 4092 + INTEGER(IntKi), PARAMETER :: M5N7MAFyi = 4093 + INTEGER(IntKi), PARAMETER :: M5N8MAFyi = 4094 + INTEGER(IntKi), PARAMETER :: M5N9MAFyi = 4095 + INTEGER(IntKi), PARAMETER :: M6N1MAFyi = 4096 + INTEGER(IntKi), PARAMETER :: M6N2MAFyi = 4097 + INTEGER(IntKi), PARAMETER :: M6N3MAFyi = 4098 + INTEGER(IntKi), PARAMETER :: M6N4MAFyi = 4099 + INTEGER(IntKi), PARAMETER :: M6N5MAFyi = 4100 + INTEGER(IntKi), PARAMETER :: M6N6MAFyi = 4101 + INTEGER(IntKi), PARAMETER :: M6N7MAFyi = 4102 + INTEGER(IntKi), PARAMETER :: M6N8MAFyi = 4103 + INTEGER(IntKi), PARAMETER :: M6N9MAFyi = 4104 + INTEGER(IntKi), PARAMETER :: M7N1MAFyi = 4105 + INTEGER(IntKi), PARAMETER :: M7N2MAFyi = 4106 + INTEGER(IntKi), PARAMETER :: M7N3MAFyi = 4107 + INTEGER(IntKi), PARAMETER :: M7N4MAFyi = 4108 + INTEGER(IntKi), PARAMETER :: M7N5MAFyi = 4109 + INTEGER(IntKi), PARAMETER :: M7N6MAFyi = 4110 + INTEGER(IntKi), PARAMETER :: M7N7MAFyi = 4111 + INTEGER(IntKi), PARAMETER :: M7N8MAFyi = 4112 + INTEGER(IntKi), PARAMETER :: M7N9MAFyi = 4113 + INTEGER(IntKi), PARAMETER :: M8N1MAFyi = 4114 + INTEGER(IntKi), PARAMETER :: M8N2MAFyi = 4115 + INTEGER(IntKi), PARAMETER :: M8N3MAFyi = 4116 + INTEGER(IntKi), PARAMETER :: M8N4MAFyi = 4117 + INTEGER(IntKi), PARAMETER :: M8N5MAFyi = 4118 + INTEGER(IntKi), PARAMETER :: M8N6MAFyi = 4119 + INTEGER(IntKi), PARAMETER :: M8N7MAFyi = 4120 + INTEGER(IntKi), PARAMETER :: M8N8MAFyi = 4121 + INTEGER(IntKi), PARAMETER :: M8N9MAFyi = 4122 + INTEGER(IntKi), PARAMETER :: M9N1MAFyi = 4123 + INTEGER(IntKi), PARAMETER :: M9N2MAFyi = 4124 + INTEGER(IntKi), PARAMETER :: M9N3MAFyi = 4125 + INTEGER(IntKi), PARAMETER :: M9N4MAFyi = 4126 + INTEGER(IntKi), PARAMETER :: M9N5MAFyi = 4127 + INTEGER(IntKi), PARAMETER :: M9N6MAFyi = 4128 + INTEGER(IntKi), PARAMETER :: M9N7MAFyi = 4129 + INTEGER(IntKi), PARAMETER :: M9N8MAFyi = 4130 + INTEGER(IntKi), PARAMETER :: M9N9MAFyi = 4131 + INTEGER(IntKi), PARAMETER :: M1N1MAFzi = 4132 + INTEGER(IntKi), PARAMETER :: M1N2MAFzi = 4133 + INTEGER(IntKi), PARAMETER :: M1N3MAFzi = 4134 + INTEGER(IntKi), PARAMETER :: M1N4MAFzi = 4135 + INTEGER(IntKi), PARAMETER :: M1N5MAFzi = 4136 + INTEGER(IntKi), PARAMETER :: M1N6MAFzi = 4137 + INTEGER(IntKi), PARAMETER :: M1N7MAFzi = 4138 + INTEGER(IntKi), PARAMETER :: M1N8MAFzi = 4139 + INTEGER(IntKi), PARAMETER :: M1N9MAFzi = 4140 + INTEGER(IntKi), PARAMETER :: M2N1MAFzi = 4141 + INTEGER(IntKi), PARAMETER :: M2N2MAFzi = 4142 + INTEGER(IntKi), PARAMETER :: M2N3MAFzi = 4143 + INTEGER(IntKi), PARAMETER :: M2N4MAFzi = 4144 + INTEGER(IntKi), PARAMETER :: M2N5MAFzi = 4145 + INTEGER(IntKi), PARAMETER :: M2N6MAFzi = 4146 + INTEGER(IntKi), PARAMETER :: M2N7MAFzi = 4147 + INTEGER(IntKi), PARAMETER :: M2N8MAFzi = 4148 + INTEGER(IntKi), PARAMETER :: M2N9MAFzi = 4149 + INTEGER(IntKi), PARAMETER :: M3N1MAFzi = 4150 + INTEGER(IntKi), PARAMETER :: M3N2MAFzi = 4151 + INTEGER(IntKi), PARAMETER :: M3N3MAFzi = 4152 + INTEGER(IntKi), PARAMETER :: M3N4MAFzi = 4153 + INTEGER(IntKi), PARAMETER :: M3N5MAFzi = 4154 + INTEGER(IntKi), PARAMETER :: M3N6MAFzi = 4155 + INTEGER(IntKi), PARAMETER :: M3N7MAFzi = 4156 + INTEGER(IntKi), PARAMETER :: M3N8MAFzi = 4157 + INTEGER(IntKi), PARAMETER :: M3N9MAFzi = 4158 + INTEGER(IntKi), PARAMETER :: M4N1MAFzi = 4159 + INTEGER(IntKi), PARAMETER :: M4N2MAFzi = 4160 + INTEGER(IntKi), PARAMETER :: M4N3MAFzi = 4161 + INTEGER(IntKi), PARAMETER :: M4N4MAFzi = 4162 + INTEGER(IntKi), PARAMETER :: M4N5MAFzi = 4163 + INTEGER(IntKi), PARAMETER :: M4N6MAFzi = 4164 + INTEGER(IntKi), PARAMETER :: M4N7MAFzi = 4165 + INTEGER(IntKi), PARAMETER :: M4N8MAFzi = 4166 + INTEGER(IntKi), PARAMETER :: M4N9MAFzi = 4167 + INTEGER(IntKi), PARAMETER :: M5N1MAFzi = 4168 + INTEGER(IntKi), PARAMETER :: M5N2MAFzi = 4169 + INTEGER(IntKi), PARAMETER :: M5N3MAFzi = 4170 + INTEGER(IntKi), PARAMETER :: M5N4MAFzi = 4171 + INTEGER(IntKi), PARAMETER :: M5N5MAFzi = 4172 + INTEGER(IntKi), PARAMETER :: M5N6MAFzi = 4173 + INTEGER(IntKi), PARAMETER :: M5N7MAFzi = 4174 + INTEGER(IntKi), PARAMETER :: M5N8MAFzi = 4175 + INTEGER(IntKi), PARAMETER :: M5N9MAFzi = 4176 + INTEGER(IntKi), PARAMETER :: M6N1MAFzi = 4177 + INTEGER(IntKi), PARAMETER :: M6N2MAFzi = 4178 + INTEGER(IntKi), PARAMETER :: M6N3MAFzi = 4179 + INTEGER(IntKi), PARAMETER :: M6N4MAFzi = 4180 + INTEGER(IntKi), PARAMETER :: M6N5MAFzi = 4181 + INTEGER(IntKi), PARAMETER :: M6N6MAFzi = 4182 + INTEGER(IntKi), PARAMETER :: M6N7MAFzi = 4183 + INTEGER(IntKi), PARAMETER :: M6N8MAFzi = 4184 + INTEGER(IntKi), PARAMETER :: M6N9MAFzi = 4185 + INTEGER(IntKi), PARAMETER :: M7N1MAFzi = 4186 + INTEGER(IntKi), PARAMETER :: M7N2MAFzi = 4187 + INTEGER(IntKi), PARAMETER :: M7N3MAFzi = 4188 + INTEGER(IntKi), PARAMETER :: M7N4MAFzi = 4189 + INTEGER(IntKi), PARAMETER :: M7N5MAFzi = 4190 + INTEGER(IntKi), PARAMETER :: M7N6MAFzi = 4191 + INTEGER(IntKi), PARAMETER :: M7N7MAFzi = 4192 + INTEGER(IntKi), PARAMETER :: M7N8MAFzi = 4193 + INTEGER(IntKi), PARAMETER :: M7N9MAFzi = 4194 + INTEGER(IntKi), PARAMETER :: M8N1MAFzi = 4195 + INTEGER(IntKi), PARAMETER :: M8N2MAFzi = 4196 + INTEGER(IntKi), PARAMETER :: M8N3MAFzi = 4197 + INTEGER(IntKi), PARAMETER :: M8N4MAFzi = 4198 + INTEGER(IntKi), PARAMETER :: M8N5MAFzi = 4199 + INTEGER(IntKi), PARAMETER :: M8N6MAFzi = 4200 + INTEGER(IntKi), PARAMETER :: M8N7MAFzi = 4201 + INTEGER(IntKi), PARAMETER :: M8N8MAFzi = 4202 + INTEGER(IntKi), PARAMETER :: M8N9MAFzi = 4203 + INTEGER(IntKi), PARAMETER :: M9N1MAFzi = 4204 + INTEGER(IntKi), PARAMETER :: M9N2MAFzi = 4205 + INTEGER(IntKi), PARAMETER :: M9N3MAFzi = 4206 + INTEGER(IntKi), PARAMETER :: M9N4MAFzi = 4207 + INTEGER(IntKi), PARAMETER :: M9N5MAFzi = 4208 + INTEGER(IntKi), PARAMETER :: M9N6MAFzi = 4209 + INTEGER(IntKi), PARAMETER :: M9N7MAFzi = 4210 + INTEGER(IntKi), PARAMETER :: M9N8MAFzi = 4211 + INTEGER(IntKi), PARAMETER :: M9N9MAFzi = 4212 - ! Category: - INTEGER(IntKi), PARAMETER :: J1Vxi = 3727 - INTEGER(IntKi), PARAMETER :: J2Vxi = 3728 - INTEGER(IntKi), PARAMETER :: J3Vxi = 3729 - INTEGER(IntKi), PARAMETER :: J4Vxi = 3730 - INTEGER(IntKi), PARAMETER :: J5Vxi = 3731 - INTEGER(IntKi), PARAMETER :: J6Vxi = 3732 - INTEGER(IntKi), PARAMETER :: J7Vxi = 3733 - INTEGER(IntKi), PARAMETER :: J8Vxi = 3734 - INTEGER(IntKi), PARAMETER :: J9Vxi = 3735 - INTEGER(IntKi), PARAMETER :: J1Vyi = 3736 - INTEGER(IntKi), PARAMETER :: J2Vyi = 3737 - INTEGER(IntKi), PARAMETER :: J3Vyi = 3738 - INTEGER(IntKi), PARAMETER :: J4Vyi = 3739 - INTEGER(IntKi), PARAMETER :: J5Vyi = 3740 - INTEGER(IntKi), PARAMETER :: J6Vyi = 3741 - INTEGER(IntKi), PARAMETER :: J7Vyi = 3742 - INTEGER(IntKi), PARAMETER :: J8Vyi = 3743 - INTEGER(IntKi), PARAMETER :: J9Vyi = 3744 - INTEGER(IntKi), PARAMETER :: J1Vzi = 3745 - INTEGER(IntKi), PARAMETER :: J2Vzi = 3746 - INTEGER(IntKi), PARAMETER :: J3Vzi = 3747 - INTEGER(IntKi), PARAMETER :: J4Vzi = 3748 - INTEGER(IntKi), PARAMETER :: J5Vzi = 3749 - INTEGER(IntKi), PARAMETER :: J6Vzi = 3750 - INTEGER(IntKi), PARAMETER :: J7Vzi = 3751 - INTEGER(IntKi), PARAMETER :: J8Vzi = 3752 - INTEGER(IntKi), PARAMETER :: J9Vzi = 3753 - INTEGER(IntKi), PARAMETER :: J1Axi = 3754 - INTEGER(IntKi), PARAMETER :: J2Axi = 3755 - INTEGER(IntKi), PARAMETER :: J3Axi = 3756 - INTEGER(IntKi), PARAMETER :: J4Axi = 3757 - INTEGER(IntKi), PARAMETER :: J5Axi = 3758 - INTEGER(IntKi), PARAMETER :: J6Axi = 3759 - INTEGER(IntKi), PARAMETER :: J7Axi = 3760 - INTEGER(IntKi), PARAMETER :: J8Axi = 3761 - INTEGER(IntKi), PARAMETER :: J9Axi = 3762 - INTEGER(IntKi), PARAMETER :: J1Ayi = 3763 - INTEGER(IntKi), PARAMETER :: J2Ayi = 3764 - INTEGER(IntKi), PARAMETER :: J3Ayi = 3765 - INTEGER(IntKi), PARAMETER :: J4Ayi = 3766 - INTEGER(IntKi), PARAMETER :: J5Ayi = 3767 - INTEGER(IntKi), PARAMETER :: J6Ayi = 3768 - INTEGER(IntKi), PARAMETER :: J7Ayi = 3769 - INTEGER(IntKi), PARAMETER :: J8Ayi = 3770 - INTEGER(IntKi), PARAMETER :: J9Ayi = 3771 - INTEGER(IntKi), PARAMETER :: J1Azi = 3772 - INTEGER(IntKi), PARAMETER :: J2Azi = 3773 - INTEGER(IntKi), PARAMETER :: J3Azi = 3774 - INTEGER(IntKi), PARAMETER :: J4Azi = 3775 - INTEGER(IntKi), PARAMETER :: J5Azi = 3776 - INTEGER(IntKi), PARAMETER :: J6Azi = 3777 - INTEGER(IntKi), PARAMETER :: J7Azi = 3778 - INTEGER(IntKi), PARAMETER :: J8Azi = 3779 - INTEGER(IntKi), PARAMETER :: J9Azi = 3780 - INTEGER(IntKi), PARAMETER :: J1DynP = 3781 - INTEGER(IntKi), PARAMETER :: J2DynP = 3782 - INTEGER(IntKi), PARAMETER :: J3DynP = 3783 - INTEGER(IntKi), PARAMETER :: J4DynP = 3784 - INTEGER(IntKi), PARAMETER :: J5DynP = 3785 - INTEGER(IntKi), PARAMETER :: J6DynP = 3786 - INTEGER(IntKi), PARAMETER :: J7DynP = 3787 - INTEGER(IntKi), PARAMETER :: J8DynP = 3788 - INTEGER(IntKi), PARAMETER :: J9DynP = 3789 - INTEGER(IntKi), PARAMETER :: J1STVxi = 3790 - INTEGER(IntKi), PARAMETER :: J2STVxi = 3791 - INTEGER(IntKi), PARAMETER :: J3STVxi = 3792 - INTEGER(IntKi), PARAMETER :: J4STVxi = 3793 - INTEGER(IntKi), PARAMETER :: J5STVxi = 3794 - INTEGER(IntKi), PARAMETER :: J6STVxi = 3795 - INTEGER(IntKi), PARAMETER :: J7STVxi = 3796 - INTEGER(IntKi), PARAMETER :: J8STVxi = 3797 - INTEGER(IntKi), PARAMETER :: J9STVxi = 3798 - INTEGER(IntKi), PARAMETER :: J1STVyi = 3799 - INTEGER(IntKi), PARAMETER :: J2STVyi = 3800 - INTEGER(IntKi), PARAMETER :: J3STVyi = 3801 - INTEGER(IntKi), PARAMETER :: J4STVyi = 3802 - INTEGER(IntKi), PARAMETER :: J5STVyi = 3803 - INTEGER(IntKi), PARAMETER :: J6STVyi = 3804 - INTEGER(IntKi), PARAMETER :: J7STVyi = 3805 - INTEGER(IntKi), PARAMETER :: J8STVyi = 3806 - INTEGER(IntKi), PARAMETER :: J9STVyi = 3807 - INTEGER(IntKi), PARAMETER :: J1STVzi = 3808 - INTEGER(IntKi), PARAMETER :: J2STVzi = 3809 - INTEGER(IntKi), PARAMETER :: J3STVzi = 3810 - INTEGER(IntKi), PARAMETER :: J4STVzi = 3811 - INTEGER(IntKi), PARAMETER :: J5STVzi = 3812 - INTEGER(IntKi), PARAMETER :: J6STVzi = 3813 - INTEGER(IntKi), PARAMETER :: J7STVzi = 3814 - INTEGER(IntKi), PARAMETER :: J8STVzi = 3815 - INTEGER(IntKi), PARAMETER :: J9STVzi = 3816 - INTEGER(IntKi), PARAMETER :: J1STAxi = 3817 - INTEGER(IntKi), PARAMETER :: J2STAxi = 3818 - INTEGER(IntKi), PARAMETER :: J3STAxi = 3819 - INTEGER(IntKi), PARAMETER :: J4STAxi = 3820 - INTEGER(IntKi), PARAMETER :: J5STAxi = 3821 - INTEGER(IntKi), PARAMETER :: J6STAxi = 3822 - INTEGER(IntKi), PARAMETER :: J7STAxi = 3823 - INTEGER(IntKi), PARAMETER :: J8STAxi = 3824 - INTEGER(IntKi), PARAMETER :: J9STAxi = 3825 - INTEGER(IntKi), PARAMETER :: J1STAyi = 3826 - INTEGER(IntKi), PARAMETER :: J2STAyi = 3827 - INTEGER(IntKi), PARAMETER :: J3STAyi = 3828 - INTEGER(IntKi), PARAMETER :: J4STAyi = 3829 - INTEGER(IntKi), PARAMETER :: J5STAyi = 3830 - INTEGER(IntKi), PARAMETER :: J6STAyi = 3831 - INTEGER(IntKi), PARAMETER :: J7STAyi = 3832 - INTEGER(IntKi), PARAMETER :: J8STAyi = 3833 - INTEGER(IntKi), PARAMETER :: J9STAyi = 3834 - INTEGER(IntKi), PARAMETER :: J1STAzi = 3835 - INTEGER(IntKi), PARAMETER :: J2STAzi = 3836 - INTEGER(IntKi), PARAMETER :: J3STAzi = 3837 - INTEGER(IntKi), PARAMETER :: J4STAzi = 3838 - INTEGER(IntKi), PARAMETER :: J5STAzi = 3839 - INTEGER(IntKi), PARAMETER :: J6STAzi = 3840 - INTEGER(IntKi), PARAMETER :: J7STAzi = 3841 - INTEGER(IntKi), PARAMETER :: J8STAzi = 3842 - INTEGER(IntKi), PARAMETER :: J9STAzi = 3843 + ! Joint-level Wave Kinematics : + INTEGER(IntKi), PARAMETER :: J1Vxi = 4213 + INTEGER(IntKi), PARAMETER :: J2Vxi = 4214 + INTEGER(IntKi), PARAMETER :: J3Vxi = 4215 + INTEGER(IntKi), PARAMETER :: J4Vxi = 4216 + INTEGER(IntKi), PARAMETER :: J5Vxi = 4217 + INTEGER(IntKi), PARAMETER :: J6Vxi = 4218 + INTEGER(IntKi), PARAMETER :: J7Vxi = 4219 + INTEGER(IntKi), PARAMETER :: J8Vxi = 4220 + INTEGER(IntKi), PARAMETER :: J9Vxi = 4221 + INTEGER(IntKi), PARAMETER :: J1Vyi = 4222 + INTEGER(IntKi), PARAMETER :: J2Vyi = 4223 + INTEGER(IntKi), PARAMETER :: J3Vyi = 4224 + INTEGER(IntKi), PARAMETER :: J4Vyi = 4225 + INTEGER(IntKi), PARAMETER :: J5Vyi = 4226 + INTEGER(IntKi), PARAMETER :: J6Vyi = 4227 + INTEGER(IntKi), PARAMETER :: J7Vyi = 4228 + INTEGER(IntKi), PARAMETER :: J8Vyi = 4229 + INTEGER(IntKi), PARAMETER :: J9Vyi = 4230 + INTEGER(IntKi), PARAMETER :: J1Vzi = 4231 + INTEGER(IntKi), PARAMETER :: J2Vzi = 4232 + INTEGER(IntKi), PARAMETER :: J3Vzi = 4233 + INTEGER(IntKi), PARAMETER :: J4Vzi = 4234 + INTEGER(IntKi), PARAMETER :: J5Vzi = 4235 + INTEGER(IntKi), PARAMETER :: J6Vzi = 4236 + INTEGER(IntKi), PARAMETER :: J7Vzi = 4237 + INTEGER(IntKi), PARAMETER :: J8Vzi = 4238 + INTEGER(IntKi), PARAMETER :: J9Vzi = 4239 + INTEGER(IntKi), PARAMETER :: J1Axi = 4240 + INTEGER(IntKi), PARAMETER :: J2Axi = 4241 + INTEGER(IntKi), PARAMETER :: J3Axi = 4242 + INTEGER(IntKi), PARAMETER :: J4Axi = 4243 + INTEGER(IntKi), PARAMETER :: J5Axi = 4244 + INTEGER(IntKi), PARAMETER :: J6Axi = 4245 + INTEGER(IntKi), PARAMETER :: J7Axi = 4246 + INTEGER(IntKi), PARAMETER :: J8Axi = 4247 + INTEGER(IntKi), PARAMETER :: J9Axi = 4248 + INTEGER(IntKi), PARAMETER :: J1Ayi = 4249 + INTEGER(IntKi), PARAMETER :: J2Ayi = 4250 + INTEGER(IntKi), PARAMETER :: J3Ayi = 4251 + INTEGER(IntKi), PARAMETER :: J4Ayi = 4252 + INTEGER(IntKi), PARAMETER :: J5Ayi = 4253 + INTEGER(IntKi), PARAMETER :: J6Ayi = 4254 + INTEGER(IntKi), PARAMETER :: J7Ayi = 4255 + INTEGER(IntKi), PARAMETER :: J8Ayi = 4256 + INTEGER(IntKi), PARAMETER :: J9Ayi = 4257 + INTEGER(IntKi), PARAMETER :: J1Azi = 4258 + INTEGER(IntKi), PARAMETER :: J2Azi = 4259 + INTEGER(IntKi), PARAMETER :: J3Azi = 4260 + INTEGER(IntKi), PARAMETER :: J4Azi = 4261 + INTEGER(IntKi), PARAMETER :: J5Azi = 4262 + INTEGER(IntKi), PARAMETER :: J6Azi = 4263 + INTEGER(IntKi), PARAMETER :: J7Azi = 4264 + INTEGER(IntKi), PARAMETER :: J8Azi = 4265 + INTEGER(IntKi), PARAMETER :: J9Azi = 4266 + INTEGER(IntKi), PARAMETER :: J1DynP = 4267 + INTEGER(IntKi), PARAMETER :: J2DynP = 4268 + INTEGER(IntKi), PARAMETER :: J3DynP = 4269 + INTEGER(IntKi), PARAMETER :: J4DynP = 4270 + INTEGER(IntKi), PARAMETER :: J5DynP = 4271 + INTEGER(IntKi), PARAMETER :: J6DynP = 4272 + INTEGER(IntKi), PARAMETER :: J7DynP = 4273 + INTEGER(IntKi), PARAMETER :: J8DynP = 4274 + INTEGER(IntKi), PARAMETER :: J9DynP = 4275 + INTEGER(IntKi), PARAMETER :: J1STVxi = 4276 + INTEGER(IntKi), PARAMETER :: J2STVxi = 4277 + INTEGER(IntKi), PARAMETER :: J3STVxi = 4278 + INTEGER(IntKi), PARAMETER :: J4STVxi = 4279 + INTEGER(IntKi), PARAMETER :: J5STVxi = 4280 + INTEGER(IntKi), PARAMETER :: J6STVxi = 4281 + INTEGER(IntKi), PARAMETER :: J7STVxi = 4282 + INTEGER(IntKi), PARAMETER :: J8STVxi = 4283 + INTEGER(IntKi), PARAMETER :: J9STVxi = 4284 + INTEGER(IntKi), PARAMETER :: J1STVyi = 4285 + INTEGER(IntKi), PARAMETER :: J2STVyi = 4286 + INTEGER(IntKi), PARAMETER :: J3STVyi = 4287 + INTEGER(IntKi), PARAMETER :: J4STVyi = 4288 + INTEGER(IntKi), PARAMETER :: J5STVyi = 4289 + INTEGER(IntKi), PARAMETER :: J6STVyi = 4290 + INTEGER(IntKi), PARAMETER :: J7STVyi = 4291 + INTEGER(IntKi), PARAMETER :: J8STVyi = 4292 + INTEGER(IntKi), PARAMETER :: J9STVyi = 4293 + INTEGER(IntKi), PARAMETER :: J1STVzi = 4294 + INTEGER(IntKi), PARAMETER :: J2STVzi = 4295 + INTEGER(IntKi), PARAMETER :: J3STVzi = 4296 + INTEGER(IntKi), PARAMETER :: J4STVzi = 4297 + INTEGER(IntKi), PARAMETER :: J5STVzi = 4298 + INTEGER(IntKi), PARAMETER :: J6STVzi = 4299 + INTEGER(IntKi), PARAMETER :: J7STVzi = 4300 + INTEGER(IntKi), PARAMETER :: J8STVzi = 4301 + INTEGER(IntKi), PARAMETER :: J9STVzi = 4302 + INTEGER(IntKi), PARAMETER :: J1STAxi = 4303 + INTEGER(IntKi), PARAMETER :: J2STAxi = 4304 + INTEGER(IntKi), PARAMETER :: J3STAxi = 4305 + INTEGER(IntKi), PARAMETER :: J4STAxi = 4306 + INTEGER(IntKi), PARAMETER :: J5STAxi = 4307 + INTEGER(IntKi), PARAMETER :: J6STAxi = 4308 + INTEGER(IntKi), PARAMETER :: J7STAxi = 4309 + INTEGER(IntKi), PARAMETER :: J8STAxi = 4310 + INTEGER(IntKi), PARAMETER :: J9STAxi = 4311 + INTEGER(IntKi), PARAMETER :: J1STAyi = 4312 + INTEGER(IntKi), PARAMETER :: J2STAyi = 4313 + INTEGER(IntKi), PARAMETER :: J3STAyi = 4314 + INTEGER(IntKi), PARAMETER :: J4STAyi = 4315 + INTEGER(IntKi), PARAMETER :: J5STAyi = 4316 + INTEGER(IntKi), PARAMETER :: J6STAyi = 4317 + INTEGER(IntKi), PARAMETER :: J7STAyi = 4318 + INTEGER(IntKi), PARAMETER :: J8STAyi = 4319 + INTEGER(IntKi), PARAMETER :: J9STAyi = 4320 + INTEGER(IntKi), PARAMETER :: J1STAzi = 4321 + INTEGER(IntKi), PARAMETER :: J2STAzi = 4322 + INTEGER(IntKi), PARAMETER :: J3STAzi = 4323 + INTEGER(IntKi), PARAMETER :: J4STAzi = 4324 + INTEGER(IntKi), PARAMETER :: J5STAzi = 4325 + INTEGER(IntKi), PARAMETER :: J6STAzi = 4326 + INTEGER(IntKi), PARAMETER :: J7STAzi = 4327 + INTEGER(IntKi), PARAMETER :: J8STAzi = 4328 + INTEGER(IntKi), PARAMETER :: J9STAzi = 4329 - ! Category: - INTEGER(IntKi), PARAMETER :: J1FDxi = 3844 - INTEGER(IntKi), PARAMETER :: J2FDxi = 3845 - INTEGER(IntKi), PARAMETER :: J3FDxi = 3846 - INTEGER(IntKi), PARAMETER :: J4FDxi = 3847 - INTEGER(IntKi), PARAMETER :: J5FDxi = 3848 - INTEGER(IntKi), PARAMETER :: J6FDxi = 3849 - INTEGER(IntKi), PARAMETER :: J7FDxi = 3850 - INTEGER(IntKi), PARAMETER :: J8FDxi = 3851 - INTEGER(IntKi), PARAMETER :: J9FDxi = 3852 - INTEGER(IntKi), PARAMETER :: J1FDyi = 3853 - INTEGER(IntKi), PARAMETER :: J2FDyi = 3854 - INTEGER(IntKi), PARAMETER :: J3FDyi = 3855 - INTEGER(IntKi), PARAMETER :: J4FDyi = 3856 - INTEGER(IntKi), PARAMETER :: J5FDyi = 3857 - INTEGER(IntKi), PARAMETER :: J6FDyi = 3858 - INTEGER(IntKi), PARAMETER :: J7FDyi = 3859 - INTEGER(IntKi), PARAMETER :: J8FDyi = 3860 - INTEGER(IntKi), PARAMETER :: J9FDyi = 3861 - INTEGER(IntKi), PARAMETER :: J1FDzi = 3862 - INTEGER(IntKi), PARAMETER :: J2FDzi = 3863 - INTEGER(IntKi), PARAMETER :: J3FDzi = 3864 - INTEGER(IntKi), PARAMETER :: J4FDzi = 3865 - INTEGER(IntKi), PARAMETER :: J5FDzi = 3866 - INTEGER(IntKi), PARAMETER :: J6FDzi = 3867 - INTEGER(IntKi), PARAMETER :: J7FDzi = 3868 - INTEGER(IntKi), PARAMETER :: J8FDzi = 3869 - INTEGER(IntKi), PARAMETER :: J9FDzi = 3870 - INTEGER(IntKi), PARAMETER :: J1FBxi = 3871 - INTEGER(IntKi), PARAMETER :: J2FBxi = 3872 - INTEGER(IntKi), PARAMETER :: J3FBxi = 3873 - INTEGER(IntKi), PARAMETER :: J4FBxi = 3874 - INTEGER(IntKi), PARAMETER :: J5FBxi = 3875 - INTEGER(IntKi), PARAMETER :: J6FBxi = 3876 - INTEGER(IntKi), PARAMETER :: J7FBxi = 3877 - INTEGER(IntKi), PARAMETER :: J8FBxi = 3878 - INTEGER(IntKi), PARAMETER :: J9FBxi = 3879 - INTEGER(IntKi), PARAMETER :: J1FByi = 3880 - INTEGER(IntKi), PARAMETER :: J2FByi = 3881 - INTEGER(IntKi), PARAMETER :: J3FByi = 3882 - INTEGER(IntKi), PARAMETER :: J4FByi = 3883 - INTEGER(IntKi), PARAMETER :: J5FByi = 3884 - INTEGER(IntKi), PARAMETER :: J6FByi = 3885 - INTEGER(IntKi), PARAMETER :: J7FByi = 3886 - INTEGER(IntKi), PARAMETER :: J8FByi = 3887 - INTEGER(IntKi), PARAMETER :: J9FByi = 3888 - INTEGER(IntKi), PARAMETER :: J1FBzi = 3889 - INTEGER(IntKi), PARAMETER :: J2FBzi = 3890 - INTEGER(IntKi), PARAMETER :: J3FBzi = 3891 - INTEGER(IntKi), PARAMETER :: J4FBzi = 3892 - INTEGER(IntKi), PARAMETER :: J5FBzi = 3893 - INTEGER(IntKi), PARAMETER :: J6FBzi = 3894 - INTEGER(IntKi), PARAMETER :: J7FBzi = 3895 - INTEGER(IntKi), PARAMETER :: J8FBzi = 3896 - INTEGER(IntKi), PARAMETER :: J9FBzi = 3897 - INTEGER(IntKi), PARAMETER :: J1MBxi = 3898 - INTEGER(IntKi), PARAMETER :: J2MBxi = 3899 - INTEGER(IntKi), PARAMETER :: J3MBxi = 3900 - INTEGER(IntKi), PARAMETER :: J4MBxi = 3901 - INTEGER(IntKi), PARAMETER :: J5MBxi = 3902 - INTEGER(IntKi), PARAMETER :: J6MBxi = 3903 - INTEGER(IntKi), PARAMETER :: J7MBxi = 3904 - INTEGER(IntKi), PARAMETER :: J8MBxi = 3905 - INTEGER(IntKi), PARAMETER :: J9MBxi = 3906 - INTEGER(IntKi), PARAMETER :: J1MByi = 3907 - INTEGER(IntKi), PARAMETER :: J2MByi = 3908 - INTEGER(IntKi), PARAMETER :: J3MByi = 3909 - INTEGER(IntKi), PARAMETER :: J4MByi = 3910 - INTEGER(IntKi), PARAMETER :: J5MByi = 3911 - INTEGER(IntKi), PARAMETER :: J6MByi = 3912 - INTEGER(IntKi), PARAMETER :: J7MByi = 3913 - INTEGER(IntKi), PARAMETER :: J8MByi = 3914 - INTEGER(IntKi), PARAMETER :: J9MByi = 3915 - INTEGER(IntKi), PARAMETER :: J1MBzi = 3916 - INTEGER(IntKi), PARAMETER :: J2MBzi = 3917 - INTEGER(IntKi), PARAMETER :: J3MBzi = 3918 - INTEGER(IntKi), PARAMETER :: J4MBzi = 3919 - INTEGER(IntKi), PARAMETER :: J5MBzi = 3920 - INTEGER(IntKi), PARAMETER :: J6MBzi = 3921 - INTEGER(IntKi), PARAMETER :: J7MBzi = 3922 - INTEGER(IntKi), PARAMETER :: J8MBzi = 3923 - INTEGER(IntKi), PARAMETER :: J9MBzi = 3924 - INTEGER(IntKi), PARAMETER :: J1FBFxi = 3925 - INTEGER(IntKi), PARAMETER :: J2FBFxi = 3926 - INTEGER(IntKi), PARAMETER :: J3FBFxi = 3927 - INTEGER(IntKi), PARAMETER :: J4FBFxi = 3928 - INTEGER(IntKi), PARAMETER :: J5FBFxi = 3929 - INTEGER(IntKi), PARAMETER :: J6FBFxi = 3930 - INTEGER(IntKi), PARAMETER :: J7FBFxi = 3931 - INTEGER(IntKi), PARAMETER :: J8FBFxi = 3932 - INTEGER(IntKi), PARAMETER :: J9FBFxi = 3933 - INTEGER(IntKi), PARAMETER :: J1FBFyi = 3934 - INTEGER(IntKi), PARAMETER :: J2FBFyi = 3935 - INTEGER(IntKi), PARAMETER :: J3FBFyi = 3936 - INTEGER(IntKi), PARAMETER :: J4FBFyi = 3937 - INTEGER(IntKi), PARAMETER :: J5FBFyi = 3938 - INTEGER(IntKi), PARAMETER :: J6FBFyi = 3939 - INTEGER(IntKi), PARAMETER :: J7FBFyi = 3940 - INTEGER(IntKi), PARAMETER :: J8FBFyi = 3941 - INTEGER(IntKi), PARAMETER :: J9FBFyi = 3942 - INTEGER(IntKi), PARAMETER :: J1FBFzi = 3943 - INTEGER(IntKi), PARAMETER :: J2FBFzi = 3944 - INTEGER(IntKi), PARAMETER :: J3FBFzi = 3945 - INTEGER(IntKi), PARAMETER :: J4FBFzi = 3946 - INTEGER(IntKi), PARAMETER :: J5FBFzi = 3947 - INTEGER(IntKi), PARAMETER :: J6FBFzi = 3948 - INTEGER(IntKi), PARAMETER :: J7FBFzi = 3949 - INTEGER(IntKi), PARAMETER :: J8FBFzi = 3950 - INTEGER(IntKi), PARAMETER :: J9FBFzi = 3951 - INTEGER(IntKi), PARAMETER :: J1MBFxi = 3952 - INTEGER(IntKi), PARAMETER :: J2MBFxi = 3953 - INTEGER(IntKi), PARAMETER :: J3MBFxi = 3954 - INTEGER(IntKi), PARAMETER :: J4MBFxi = 3955 - INTEGER(IntKi), PARAMETER :: J5MBFxi = 3956 - INTEGER(IntKi), PARAMETER :: J6MBFxi = 3957 - INTEGER(IntKi), PARAMETER :: J7MBFxi = 3958 - INTEGER(IntKi), PARAMETER :: J8MBFxi = 3959 - INTEGER(IntKi), PARAMETER :: J9MBFxi = 3960 - INTEGER(IntKi), PARAMETER :: J1MBFyi = 3961 - INTEGER(IntKi), PARAMETER :: J2MBFyi = 3962 - INTEGER(IntKi), PARAMETER :: J3MBFyi = 3963 - INTEGER(IntKi), PARAMETER :: J4MBFyi = 3964 - INTEGER(IntKi), PARAMETER :: J5MBFyi = 3965 - INTEGER(IntKi), PARAMETER :: J6MBFyi = 3966 - INTEGER(IntKi), PARAMETER :: J7MBFyi = 3967 - INTEGER(IntKi), PARAMETER :: J8MBFyi = 3968 - INTEGER(IntKi), PARAMETER :: J9MBFyi = 3969 - INTEGER(IntKi), PARAMETER :: J1MBFzi = 3970 - INTEGER(IntKi), PARAMETER :: J2MBFzi = 3971 - INTEGER(IntKi), PARAMETER :: J3MBFzi = 3972 - INTEGER(IntKi), PARAMETER :: J4MBFzi = 3973 - INTEGER(IntKi), PARAMETER :: J5MBFzi = 3974 - INTEGER(IntKi), PARAMETER :: J6MBFzi = 3975 - INTEGER(IntKi), PARAMETER :: J7MBFzi = 3976 - INTEGER(IntKi), PARAMETER :: J8MBFzi = 3977 - INTEGER(IntKi), PARAMETER :: J9MBFzi = 3978 - INTEGER(IntKi), PARAMETER :: J1FIxi = 3979 - INTEGER(IntKi), PARAMETER :: J2FIxi = 3980 - INTEGER(IntKi), PARAMETER :: J3FIxi = 3981 - INTEGER(IntKi), PARAMETER :: J4FIxi = 3982 - INTEGER(IntKi), PARAMETER :: J5FIxi = 3983 - INTEGER(IntKi), PARAMETER :: J6FIxi = 3984 - INTEGER(IntKi), PARAMETER :: J7FIxi = 3985 - INTEGER(IntKi), PARAMETER :: J8FIxi = 3986 - INTEGER(IntKi), PARAMETER :: J9FIxi = 3987 - INTEGER(IntKi), PARAMETER :: J1FIyi = 3988 - INTEGER(IntKi), PARAMETER :: J2FIyi = 3989 - INTEGER(IntKi), PARAMETER :: J3FIyi = 3990 - INTEGER(IntKi), PARAMETER :: J4FIyi = 3991 - INTEGER(IntKi), PARAMETER :: J5FIyi = 3992 - INTEGER(IntKi), PARAMETER :: J6FIyi = 3993 - INTEGER(IntKi), PARAMETER :: J7FIyi = 3994 - INTEGER(IntKi), PARAMETER :: J8FIyi = 3995 - INTEGER(IntKi), PARAMETER :: J9FIyi = 3996 - INTEGER(IntKi), PARAMETER :: J1FIzi = 3997 - INTEGER(IntKi), PARAMETER :: J2FIzi = 3998 - INTEGER(IntKi), PARAMETER :: J3FIzi = 3999 - INTEGER(IntKi), PARAMETER :: J4FIzi = 4000 - INTEGER(IntKi), PARAMETER :: J5FIzi = 4001 - INTEGER(IntKi), PARAMETER :: J6FIzi = 4002 - INTEGER(IntKi), PARAMETER :: J7FIzi = 4003 - INTEGER(IntKi), PARAMETER :: J8FIzi = 4004 - INTEGER(IntKi), PARAMETER :: J9FIzi = 4005 - INTEGER(IntKi), PARAMETER :: J1FAMxi = 4006 - INTEGER(IntKi), PARAMETER :: J2FAMxi = 4007 - INTEGER(IntKi), PARAMETER :: J3FAMxi = 4008 - INTEGER(IntKi), PARAMETER :: J4FAMxi = 4009 - INTEGER(IntKi), PARAMETER :: J5FAMxi = 4010 - INTEGER(IntKi), PARAMETER :: J6FAMxi = 4011 - INTEGER(IntKi), PARAMETER :: J7FAMxi = 4012 - INTEGER(IntKi), PARAMETER :: J8FAMxi = 4013 - INTEGER(IntKi), PARAMETER :: J9FAMxi = 4014 - INTEGER(IntKi), PARAMETER :: J1FAMyi = 4015 - INTEGER(IntKi), PARAMETER :: J2FAMyi = 4016 - INTEGER(IntKi), PARAMETER :: J3FAMyi = 4017 - INTEGER(IntKi), PARAMETER :: J4FAMyi = 4018 - INTEGER(IntKi), PARAMETER :: J5FAMyi = 4019 - INTEGER(IntKi), PARAMETER :: J6FAMyi = 4020 - INTEGER(IntKi), PARAMETER :: J7FAMyi = 4021 - INTEGER(IntKi), PARAMETER :: J8FAMyi = 4022 - INTEGER(IntKi), PARAMETER :: J9FAMyi = 4023 - INTEGER(IntKi), PARAMETER :: J1FAMzi = 4024 - INTEGER(IntKi), PARAMETER :: J2FAMzi = 4025 - INTEGER(IntKi), PARAMETER :: J3FAMzi = 4026 - INTEGER(IntKi), PARAMETER :: J4FAMzi = 4027 - INTEGER(IntKi), PARAMETER :: J5FAMzi = 4028 - INTEGER(IntKi), PARAMETER :: J6FAMzi = 4029 - INTEGER(IntKi), PARAMETER :: J7FAMzi = 4030 - INTEGER(IntKi), PARAMETER :: J8FAMzi = 4031 - INTEGER(IntKi), PARAMETER :: J9FAMzi = 4032 + ! Joint Loads: + INTEGER(IntKi), PARAMETER :: J1FDxi = 4330 + INTEGER(IntKi), PARAMETER :: J2FDxi = 4331 + INTEGER(IntKi), PARAMETER :: J3FDxi = 4332 + INTEGER(IntKi), PARAMETER :: J4FDxi = 4333 + INTEGER(IntKi), PARAMETER :: J5FDxi = 4334 + INTEGER(IntKi), PARAMETER :: J6FDxi = 4335 + INTEGER(IntKi), PARAMETER :: J7FDxi = 4336 + INTEGER(IntKi), PARAMETER :: J8FDxi = 4337 + INTEGER(IntKi), PARAMETER :: J9FDxi = 4338 + INTEGER(IntKi), PARAMETER :: J1FDyi = 4339 + INTEGER(IntKi), PARAMETER :: J2FDyi = 4340 + INTEGER(IntKi), PARAMETER :: J3FDyi = 4341 + INTEGER(IntKi), PARAMETER :: J4FDyi = 4342 + INTEGER(IntKi), PARAMETER :: J5FDyi = 4343 + INTEGER(IntKi), PARAMETER :: J6FDyi = 4344 + INTEGER(IntKi), PARAMETER :: J7FDyi = 4345 + INTEGER(IntKi), PARAMETER :: J8FDyi = 4346 + INTEGER(IntKi), PARAMETER :: J9FDyi = 4347 + INTEGER(IntKi), PARAMETER :: J1FDzi = 4348 + INTEGER(IntKi), PARAMETER :: J2FDzi = 4349 + INTEGER(IntKi), PARAMETER :: J3FDzi = 4350 + INTEGER(IntKi), PARAMETER :: J4FDzi = 4351 + INTEGER(IntKi), PARAMETER :: J5FDzi = 4352 + INTEGER(IntKi), PARAMETER :: J6FDzi = 4353 + INTEGER(IntKi), PARAMETER :: J7FDzi = 4354 + INTEGER(IntKi), PARAMETER :: J8FDzi = 4355 + INTEGER(IntKi), PARAMETER :: J9FDzi = 4356 + INTEGER(IntKi), PARAMETER :: J1FBxi = 4357 + INTEGER(IntKi), PARAMETER :: J2FBxi = 4358 + INTEGER(IntKi), PARAMETER :: J3FBxi = 4359 + INTEGER(IntKi), PARAMETER :: J4FBxi = 4360 + INTEGER(IntKi), PARAMETER :: J5FBxi = 4361 + INTEGER(IntKi), PARAMETER :: J6FBxi = 4362 + INTEGER(IntKi), PARAMETER :: J7FBxi = 4363 + INTEGER(IntKi), PARAMETER :: J8FBxi = 4364 + INTEGER(IntKi), PARAMETER :: J9FBxi = 4365 + INTEGER(IntKi), PARAMETER :: J1FByi = 4366 + INTEGER(IntKi), PARAMETER :: J2FByi = 4367 + INTEGER(IntKi), PARAMETER :: J3FByi = 4368 + INTEGER(IntKi), PARAMETER :: J4FByi = 4369 + INTEGER(IntKi), PARAMETER :: J5FByi = 4370 + INTEGER(IntKi), PARAMETER :: J6FByi = 4371 + INTEGER(IntKi), PARAMETER :: J7FByi = 4372 + INTEGER(IntKi), PARAMETER :: J8FByi = 4373 + INTEGER(IntKi), PARAMETER :: J9FByi = 4374 + INTEGER(IntKi), PARAMETER :: J1FBzi = 4375 + INTEGER(IntKi), PARAMETER :: J2FBzi = 4376 + INTEGER(IntKi), PARAMETER :: J3FBzi = 4377 + INTEGER(IntKi), PARAMETER :: J4FBzi = 4378 + INTEGER(IntKi), PARAMETER :: J5FBzi = 4379 + INTEGER(IntKi), PARAMETER :: J6FBzi = 4380 + INTEGER(IntKi), PARAMETER :: J7FBzi = 4381 + INTEGER(IntKi), PARAMETER :: J8FBzi = 4382 + INTEGER(IntKi), PARAMETER :: J9FBzi = 4383 + INTEGER(IntKi), PARAMETER :: J1MBxi = 4384 + INTEGER(IntKi), PARAMETER :: J2MBxi = 4385 + INTEGER(IntKi), PARAMETER :: J3MBxi = 4386 + INTEGER(IntKi), PARAMETER :: J4MBxi = 4387 + INTEGER(IntKi), PARAMETER :: J5MBxi = 4388 + INTEGER(IntKi), PARAMETER :: J6MBxi = 4389 + INTEGER(IntKi), PARAMETER :: J7MBxi = 4390 + INTEGER(IntKi), PARAMETER :: J8MBxi = 4391 + INTEGER(IntKi), PARAMETER :: J9MBxi = 4392 + INTEGER(IntKi), PARAMETER :: J1MByi = 4393 + INTEGER(IntKi), PARAMETER :: J2MByi = 4394 + INTEGER(IntKi), PARAMETER :: J3MByi = 4395 + INTEGER(IntKi), PARAMETER :: J4MByi = 4396 + INTEGER(IntKi), PARAMETER :: J5MByi = 4397 + INTEGER(IntKi), PARAMETER :: J6MByi = 4398 + INTEGER(IntKi), PARAMETER :: J7MByi = 4399 + INTEGER(IntKi), PARAMETER :: J8MByi = 4400 + INTEGER(IntKi), PARAMETER :: J9MByi = 4401 + INTEGER(IntKi), PARAMETER :: J1MBzi = 4402 + INTEGER(IntKi), PARAMETER :: J2MBzi = 4403 + INTEGER(IntKi), PARAMETER :: J3MBzi = 4404 + INTEGER(IntKi), PARAMETER :: J4MBzi = 4405 + INTEGER(IntKi), PARAMETER :: J5MBzi = 4406 + INTEGER(IntKi), PARAMETER :: J6MBzi = 4407 + INTEGER(IntKi), PARAMETER :: J7MBzi = 4408 + INTEGER(IntKi), PARAMETER :: J8MBzi = 4409 + INTEGER(IntKi), PARAMETER :: J9MBzi = 4410 + INTEGER(IntKi), PARAMETER :: J1FBFxi = 4411 + INTEGER(IntKi), PARAMETER :: J2FBFxi = 4412 + INTEGER(IntKi), PARAMETER :: J3FBFxi = 4413 + INTEGER(IntKi), PARAMETER :: J4FBFxi = 4414 + INTEGER(IntKi), PARAMETER :: J5FBFxi = 4415 + INTEGER(IntKi), PARAMETER :: J6FBFxi = 4416 + INTEGER(IntKi), PARAMETER :: J7FBFxi = 4417 + INTEGER(IntKi), PARAMETER :: J8FBFxi = 4418 + INTEGER(IntKi), PARAMETER :: J9FBFxi = 4419 + INTEGER(IntKi), PARAMETER :: J1FBFyi = 4420 + INTEGER(IntKi), PARAMETER :: J2FBFyi = 4421 + INTEGER(IntKi), PARAMETER :: J3FBFyi = 4422 + INTEGER(IntKi), PARAMETER :: J4FBFyi = 4423 + INTEGER(IntKi), PARAMETER :: J5FBFyi = 4424 + INTEGER(IntKi), PARAMETER :: J6FBFyi = 4425 + INTEGER(IntKi), PARAMETER :: J7FBFyi = 4426 + INTEGER(IntKi), PARAMETER :: J8FBFyi = 4427 + INTEGER(IntKi), PARAMETER :: J9FBFyi = 4428 + INTEGER(IntKi), PARAMETER :: J1FBFzi = 4429 + INTEGER(IntKi), PARAMETER :: J2FBFzi = 4430 + INTEGER(IntKi), PARAMETER :: J3FBFzi = 4431 + INTEGER(IntKi), PARAMETER :: J4FBFzi = 4432 + INTEGER(IntKi), PARAMETER :: J5FBFzi = 4433 + INTEGER(IntKi), PARAMETER :: J6FBFzi = 4434 + INTEGER(IntKi), PARAMETER :: J7FBFzi = 4435 + INTEGER(IntKi), PARAMETER :: J8FBFzi = 4436 + INTEGER(IntKi), PARAMETER :: J9FBFzi = 4437 + INTEGER(IntKi), PARAMETER :: J1MBFxi = 4438 + INTEGER(IntKi), PARAMETER :: J2MBFxi = 4439 + INTEGER(IntKi), PARAMETER :: J3MBFxi = 4440 + INTEGER(IntKi), PARAMETER :: J4MBFxi = 4441 + INTEGER(IntKi), PARAMETER :: J5MBFxi = 4442 + INTEGER(IntKi), PARAMETER :: J6MBFxi = 4443 + INTEGER(IntKi), PARAMETER :: J7MBFxi = 4444 + INTEGER(IntKi), PARAMETER :: J8MBFxi = 4445 + INTEGER(IntKi), PARAMETER :: J9MBFxi = 4446 + INTEGER(IntKi), PARAMETER :: J1MBFyi = 4447 + INTEGER(IntKi), PARAMETER :: J2MBFyi = 4448 + INTEGER(IntKi), PARAMETER :: J3MBFyi = 4449 + INTEGER(IntKi), PARAMETER :: J4MBFyi = 4450 + INTEGER(IntKi), PARAMETER :: J5MBFyi = 4451 + INTEGER(IntKi), PARAMETER :: J6MBFyi = 4452 + INTEGER(IntKi), PARAMETER :: J7MBFyi = 4453 + INTEGER(IntKi), PARAMETER :: J8MBFyi = 4454 + INTEGER(IntKi), PARAMETER :: J9MBFyi = 4455 + INTEGER(IntKi), PARAMETER :: J1MBFzi = 4456 + INTEGER(IntKi), PARAMETER :: J2MBFzi = 4457 + INTEGER(IntKi), PARAMETER :: J3MBFzi = 4458 + INTEGER(IntKi), PARAMETER :: J4MBFzi = 4459 + INTEGER(IntKi), PARAMETER :: J5MBFzi = 4460 + INTEGER(IntKi), PARAMETER :: J6MBFzi = 4461 + INTEGER(IntKi), PARAMETER :: J7MBFzi = 4462 + INTEGER(IntKi), PARAMETER :: J8MBFzi = 4463 + INTEGER(IntKi), PARAMETER :: J9MBFzi = 4464 + INTEGER(IntKi), PARAMETER :: J1FIxi = 4465 + INTEGER(IntKi), PARAMETER :: J2FIxi = 4466 + INTEGER(IntKi), PARAMETER :: J3FIxi = 4467 + INTEGER(IntKi), PARAMETER :: J4FIxi = 4468 + INTEGER(IntKi), PARAMETER :: J5FIxi = 4469 + INTEGER(IntKi), PARAMETER :: J6FIxi = 4470 + INTEGER(IntKi), PARAMETER :: J7FIxi = 4471 + INTEGER(IntKi), PARAMETER :: J8FIxi = 4472 + INTEGER(IntKi), PARAMETER :: J9FIxi = 4473 + INTEGER(IntKi), PARAMETER :: J1FIyi = 4474 + INTEGER(IntKi), PARAMETER :: J2FIyi = 4475 + INTEGER(IntKi), PARAMETER :: J3FIyi = 4476 + INTEGER(IntKi), PARAMETER :: J4FIyi = 4477 + INTEGER(IntKi), PARAMETER :: J5FIyi = 4478 + INTEGER(IntKi), PARAMETER :: J6FIyi = 4479 + INTEGER(IntKi), PARAMETER :: J7FIyi = 4480 + INTEGER(IntKi), PARAMETER :: J8FIyi = 4481 + INTEGER(IntKi), PARAMETER :: J9FIyi = 4482 + INTEGER(IntKi), PARAMETER :: J1FIzi = 4483 + INTEGER(IntKi), PARAMETER :: J2FIzi = 4484 + INTEGER(IntKi), PARAMETER :: J3FIzi = 4485 + INTEGER(IntKi), PARAMETER :: J4FIzi = 4486 + INTEGER(IntKi), PARAMETER :: J5FIzi = 4487 + INTEGER(IntKi), PARAMETER :: J6FIzi = 4488 + INTEGER(IntKi), PARAMETER :: J7FIzi = 4489 + INTEGER(IntKi), PARAMETER :: J8FIzi = 4490 + INTEGER(IntKi), PARAMETER :: J9FIzi = 4491 + INTEGER(IntKi), PARAMETER :: J1FAMxi = 4492 + INTEGER(IntKi), PARAMETER :: J2FAMxi = 4493 + INTEGER(IntKi), PARAMETER :: J3FAMxi = 4494 + INTEGER(IntKi), PARAMETER :: J4FAMxi = 4495 + INTEGER(IntKi), PARAMETER :: J5FAMxi = 4496 + INTEGER(IntKi), PARAMETER :: J6FAMxi = 4497 + INTEGER(IntKi), PARAMETER :: J7FAMxi = 4498 + INTEGER(IntKi), PARAMETER :: J8FAMxi = 4499 + INTEGER(IntKi), PARAMETER :: J9FAMxi = 4500 + INTEGER(IntKi), PARAMETER :: J1FAMyi = 4501 + INTEGER(IntKi), PARAMETER :: J2FAMyi = 4502 + INTEGER(IntKi), PARAMETER :: J3FAMyi = 4503 + INTEGER(IntKi), PARAMETER :: J4FAMyi = 4504 + INTEGER(IntKi), PARAMETER :: J5FAMyi = 4505 + INTEGER(IntKi), PARAMETER :: J6FAMyi = 4506 + INTEGER(IntKi), PARAMETER :: J7FAMyi = 4507 + INTEGER(IntKi), PARAMETER :: J8FAMyi = 4508 + INTEGER(IntKi), PARAMETER :: J9FAMyi = 4509 + INTEGER(IntKi), PARAMETER :: J1FAMzi = 4510 + INTEGER(IntKi), PARAMETER :: J2FAMzi = 4511 + INTEGER(IntKi), PARAMETER :: J3FAMzi = 4512 + INTEGER(IntKi), PARAMETER :: J4FAMzi = 4513 + INTEGER(IntKi), PARAMETER :: J5FAMzi = 4514 + INTEGER(IntKi), PARAMETER :: J6FAMzi = 4515 + INTEGER(IntKi), PARAMETER :: J7FAMzi = 4516 + INTEGER(IntKi), PARAMETER :: J8FAMzi = 4517 + INTEGER(IntKi), PARAMETER :: J9FAMzi = 4518 + INTEGER(IntKi), PARAMETER :: J1FAGxi = 4519 + INTEGER(IntKi), PARAMETER :: J2FAGxi = 4520 + INTEGER(IntKi), PARAMETER :: J3FAGxi = 4521 + INTEGER(IntKi), PARAMETER :: J4FAGxi = 4522 + INTEGER(IntKi), PARAMETER :: J5FAGxi = 4523 + INTEGER(IntKi), PARAMETER :: J6FAGxi = 4524 + INTEGER(IntKi), PARAMETER :: J7FAGxi = 4525 + INTEGER(IntKi), PARAMETER :: J8FAGxi = 4526 + INTEGER(IntKi), PARAMETER :: J9FAGxi = 4527 + INTEGER(IntKi), PARAMETER :: J1FAGyi = 4528 + INTEGER(IntKi), PARAMETER :: J2FAGyi = 4529 + INTEGER(IntKi), PARAMETER :: J3FAGyi = 4530 + INTEGER(IntKi), PARAMETER :: J4FAGyi = 4531 + INTEGER(IntKi), PARAMETER :: J5FAGyi = 4532 + INTEGER(IntKi), PARAMETER :: J6FAGyi = 4533 + INTEGER(IntKi), PARAMETER :: J7FAGyi = 4534 + INTEGER(IntKi), PARAMETER :: J8FAGyi = 4535 + INTEGER(IntKi), PARAMETER :: J9FAGyi = 4536 + INTEGER(IntKi), PARAMETER :: J1FAGzi = 4537 + INTEGER(IntKi), PARAMETER :: J2FAGzi = 4538 + INTEGER(IntKi), PARAMETER :: J3FAGzi = 4539 + INTEGER(IntKi), PARAMETER :: J4FAGzi = 4540 + INTEGER(IntKi), PARAMETER :: J5FAGzi = 4541 + INTEGER(IntKi), PARAMETER :: J6FAGzi = 4542 + INTEGER(IntKi), PARAMETER :: J7FAGzi = 4543 + INTEGER(IntKi), PARAMETER :: J8FAGzi = 4544 + INTEGER(IntKi), PARAMETER :: J9FAGzi = 4545 + INTEGER(IntKi), PARAMETER :: J1MAGxi = 4546 + INTEGER(IntKi), PARAMETER :: J2MAGxi = 4547 + INTEGER(IntKi), PARAMETER :: J3MAGxi = 4548 + INTEGER(IntKi), PARAMETER :: J4MAGxi = 4549 + INTEGER(IntKi), PARAMETER :: J5MAGxi = 4550 + INTEGER(IntKi), PARAMETER :: J6MAGxi = 4551 + INTEGER(IntKi), PARAMETER :: J7MAGxi = 4552 + INTEGER(IntKi), PARAMETER :: J8MAGxi = 4553 + INTEGER(IntKi), PARAMETER :: J9MAGxi = 4554 + INTEGER(IntKi), PARAMETER :: J1MAGyi = 4555 + INTEGER(IntKi), PARAMETER :: J2MAGyi = 4556 + INTEGER(IntKi), PARAMETER :: J3MAGyi = 4557 + INTEGER(IntKi), PARAMETER :: J4MAGyi = 4558 + INTEGER(IntKi), PARAMETER :: J5MAGyi = 4559 + INTEGER(IntKi), PARAMETER :: J6MAGyi = 4560 + INTEGER(IntKi), PARAMETER :: J7MAGyi = 4561 + INTEGER(IntKi), PARAMETER :: J8MAGyi = 4562 + INTEGER(IntKi), PARAMETER :: J9MAGyi = 4563 + INTEGER(IntKi), PARAMETER :: J1MAGzi = 4564 + INTEGER(IntKi), PARAMETER :: J2MAGzi = 4565 + INTEGER(IntKi), PARAMETER :: J3MAGzi = 4566 + INTEGER(IntKi), PARAMETER :: J4MAGzi = 4567 + INTEGER(IntKi), PARAMETER :: J5MAGzi = 4568 + INTEGER(IntKi), PARAMETER :: J6MAGzi = 4569 + INTEGER(IntKi), PARAMETER :: J7MAGzi = 4570 + INTEGER(IntKi), PARAMETER :: J8MAGzi = 4571 + INTEGER(IntKi), PARAMETER :: J9MAGzi = 4572 + INTEGER(IntKi), PARAMETER :: J1FMGxi = 4573 + INTEGER(IntKi), PARAMETER :: J2FMGxi = 4574 + INTEGER(IntKi), PARAMETER :: J3FMGxi = 4575 + INTEGER(IntKi), PARAMETER :: J4FMGxi = 4576 + INTEGER(IntKi), PARAMETER :: J5FMGxi = 4577 + INTEGER(IntKi), PARAMETER :: J6FMGxi = 4578 + INTEGER(IntKi), PARAMETER :: J7FMGxi = 4579 + INTEGER(IntKi), PARAMETER :: J8FMGxi = 4580 + INTEGER(IntKi), PARAMETER :: J9FMGxi = 4581 + INTEGER(IntKi), PARAMETER :: J1FMGyi = 4582 + INTEGER(IntKi), PARAMETER :: J2FMGyi = 4583 + INTEGER(IntKi), PARAMETER :: J3FMGyi = 4584 + INTEGER(IntKi), PARAMETER :: J4FMGyi = 4585 + INTEGER(IntKi), PARAMETER :: J5FMGyi = 4586 + INTEGER(IntKi), PARAMETER :: J6FMGyi = 4587 + INTEGER(IntKi), PARAMETER :: J7FMGyi = 4588 + INTEGER(IntKi), PARAMETER :: J8FMGyi = 4589 + INTEGER(IntKi), PARAMETER :: J9FMGyi = 4590 + INTEGER(IntKi), PARAMETER :: J1FMGzi = 4591 + INTEGER(IntKi), PARAMETER :: J2FMGzi = 4592 + INTEGER(IntKi), PARAMETER :: J3FMGzi = 4593 + INTEGER(IntKi), PARAMETER :: J4FMGzi = 4594 + INTEGER(IntKi), PARAMETER :: J5FMGzi = 4595 + INTEGER(IntKi), PARAMETER :: J6FMGzi = 4596 + INTEGER(IntKi), PARAMETER :: J7FMGzi = 4597 + INTEGER(IntKi), PARAMETER :: J8FMGzi = 4598 + INTEGER(IntKi), PARAMETER :: J9FMGzi = 4599 !End of code generated by Matlab script @@ -5020,6 +5585,88 @@ MODULE Morison_Output M9N8FMGxi,M9N8FMGyi,M9N8FMGzi, & M9N9FMGxi,M9N9FMGyi,M9N9FMGzi/), (/3,9,9/)) + INTEGER, PARAMETER :: MNMMGi(3,9,9) = reshape((/M1N1MMGxi,M1N1MMGyi,M1N1MMGzi, & + M1N2MMGxi,M1N2MMGyi,M1N2MMGzi, & + M1N3MMGxi,M1N3MMGyi,M1N3MMGzi, & + M1N4MMGxi,M1N4MMGyi,M1N4MMGzi, & + M1N5MMGxi,M1N5MMGyi,M1N5MMGzi, & + M1N6MMGxi,M1N6MMGyi,M1N6MMGzi, & + M1N7MMGxi,M1N7MMGyi,M1N7MMGzi, & + M1N8MMGxi,M1N8MMGyi,M1N8MMGzi, & + M1N9MMGxi,M1N9MMGyi,M1N9MMGzi, & + M2N1MMGxi,M2N1MMGyi,M2N1MMGzi, & + M2N2MMGxi,M2N2MMGyi,M2N2MMGzi, & + M2N3MMGxi,M2N3MMGyi,M2N3MMGzi, & + M2N4MMGxi,M2N4MMGyi,M2N4MMGzi, & + M2N5MMGxi,M2N5MMGyi,M2N5MMGzi, & + M2N6MMGxi,M2N6MMGyi,M2N6MMGzi, & + M2N7MMGxi,M2N7MMGyi,M2N7MMGzi, & + M2N8MMGxi,M2N8MMGyi,M2N8MMGzi, & + M2N9MMGxi,M2N9MMGyi,M2N9MMGzi, & + M3N1MMGxi,M3N1MMGyi,M3N1MMGzi, & + M3N2MMGxi,M3N2MMGyi,M3N2MMGzi, & + M3N3MMGxi,M3N3MMGyi,M3N3MMGzi, & + M3N4MMGxi,M3N4MMGyi,M3N4MMGzi, & + M3N5MMGxi,M3N5MMGyi,M3N5MMGzi, & + M3N6MMGxi,M3N6MMGyi,M3N6MMGzi, & + M3N7MMGxi,M3N7MMGyi,M3N7MMGzi, & + M3N8MMGxi,M3N8MMGyi,M3N8MMGzi, & + M3N9MMGxi,M3N9MMGyi,M3N9MMGzi, & + M4N1MMGxi,M4N1MMGyi,M4N1MMGzi, & + M4N2MMGxi,M4N2MMGyi,M4N2MMGzi, & + M4N3MMGxi,M4N3MMGyi,M4N3MMGzi, & + M4N4MMGxi,M4N4MMGyi,M4N4MMGzi, & + M4N5MMGxi,M4N5MMGyi,M4N5MMGzi, & + M4N6MMGxi,M4N6MMGyi,M4N6MMGzi, & + M4N7MMGxi,M4N7MMGyi,M4N7MMGzi, & + M4N8MMGxi,M4N8MMGyi,M4N8MMGzi, & + M4N9MMGxi,M4N9MMGyi,M4N9MMGzi, & + M5N1MMGxi,M5N1MMGyi,M5N1MMGzi, & + M5N2MMGxi,M5N2MMGyi,M5N2MMGzi, & + M5N3MMGxi,M5N3MMGyi,M5N3MMGzi, & + M5N4MMGxi,M5N4MMGyi,M5N4MMGzi, & + M5N5MMGxi,M5N5MMGyi,M5N5MMGzi, & + M5N6MMGxi,M5N6MMGyi,M5N6MMGzi, & + M5N7MMGxi,M5N7MMGyi,M5N7MMGzi, & + M5N8MMGxi,M5N8MMGyi,M5N8MMGzi, & + M5N9MMGxi,M5N9MMGyi,M5N9MMGzi, & + M6N1MMGxi,M6N1MMGyi,M6N1MMGzi, & + M6N2MMGxi,M6N2MMGyi,M6N2MMGzi, & + M6N3MMGxi,M6N3MMGyi,M6N3MMGzi, & + M6N4MMGxi,M6N4MMGyi,M6N4MMGzi, & + M6N5MMGxi,M6N5MMGyi,M6N5MMGzi, & + M6N6MMGxi,M6N6MMGyi,M6N6MMGzi, & + M6N7MMGxi,M6N7MMGyi,M6N7MMGzi, & + M6N8MMGxi,M6N8MMGyi,M6N8MMGzi, & + M6N9MMGxi,M6N9MMGyi,M6N9MMGzi, & + M7N1MMGxi,M7N1MMGyi,M7N1MMGzi, & + M7N2MMGxi,M7N2MMGyi,M7N2MMGzi, & + M7N3MMGxi,M7N3MMGyi,M7N3MMGzi, & + M7N4MMGxi,M7N4MMGyi,M7N4MMGzi, & + M7N5MMGxi,M7N5MMGyi,M7N5MMGzi, & + M7N6MMGxi,M7N6MMGyi,M7N6MMGzi, & + M7N7MMGxi,M7N7MMGyi,M7N7MMGzi, & + M7N8MMGxi,M7N8MMGyi,M7N8MMGzi, & + M7N9MMGxi,M7N9MMGyi,M7N9MMGzi, & + M8N1MMGxi,M8N1MMGyi,M8N1MMGzi, & + M8N2MMGxi,M8N2MMGyi,M8N2MMGzi, & + M8N3MMGxi,M8N3MMGyi,M8N3MMGzi, & + M8N4MMGxi,M8N4MMGyi,M8N4MMGzi, & + M8N5MMGxi,M8N5MMGyi,M8N5MMGzi, & + M8N6MMGxi,M8N6MMGyi,M8N6MMGzi, & + M8N7MMGxi,M8N7MMGyi,M8N7MMGzi, & + M8N8MMGxi,M8N8MMGyi,M8N8MMGzi, & + M8N9MMGxi,M8N9MMGyi,M8N9MMGzi, & + M9N1MMGxi,M9N1MMGyi,M9N1MMGzi, & + M9N2MMGxi,M9N2MMGyi,M9N2MMGzi, & + M9N3MMGxi,M9N3MMGyi,M9N3MMGzi, & + M9N4MMGxi,M9N4MMGyi,M9N4MMGzi, & + M9N5MMGxi,M9N5MMGyi,M9N5MMGzi, & + M9N6MMGxi,M9N6MMGyi,M9N6MMGzi, & + M9N7MMGxi,M9N7MMGyi,M9N7MMGzi, & + M9N8MMGxi,M9N8MMGyi,M9N8MMGzi, & + M9N9MMGxi,M9N9MMGyi,M9N9MMGzi/), (/3,9,9/)) + INTEGER, PARAMETER :: MNMBi(3,9,9) = reshape((/M1N1MBxi,M1N1MByi,M1N1MBzi, & M1N2MBxi,M1N2MByi,M1N2MBzi, & M1N3MBxi,M1N3MByi,M1N3MBzi, & @@ -5348,6 +5995,88 @@ MODULE Morison_Output M9N8FAGxi,M9N8FAGyi,M9N8FAGzi, & M9N9FAGxi,M9N9FAGyi,M9N9FAGzi/), (/3,9,9/)) + INTEGER, PARAMETER :: MNMAGi(3,9,9) = reshape((/M1N1MAGxi,M1N1MAGyi,M1N1MAGzi, & + M1N2MAGxi,M1N2MAGyi,M1N2MAGzi, & + M1N3MAGxi,M1N3MAGyi,M1N3MAGzi, & + M1N4MAGxi,M1N4MAGyi,M1N4MAGzi, & + M1N5MAGxi,M1N5MAGyi,M1N5MAGzi, & + M1N6MAGxi,M1N6MAGyi,M1N6MAGzi, & + M1N7MAGxi,M1N7MAGyi,M1N7MAGzi, & + M1N8MAGxi,M1N8MAGyi,M1N8MAGzi, & + M1N9MAGxi,M1N9MAGyi,M1N9MAGzi, & + M2N1MAGxi,M2N1MAGyi,M2N1MAGzi, & + M2N2MAGxi,M2N2MAGyi,M2N2MAGzi, & + M2N3MAGxi,M2N3MAGyi,M2N3MAGzi, & + M2N4MAGxi,M2N4MAGyi,M2N4MAGzi, & + M2N5MAGxi,M2N5MAGyi,M2N5MAGzi, & + M2N6MAGxi,M2N6MAGyi,M2N6MAGzi, & + M2N7MAGxi,M2N7MAGyi,M2N7MAGzi, & + M2N8MAGxi,M2N8MAGyi,M2N8MAGzi, & + M2N9MAGxi,M2N9MAGyi,M2N9MAGzi, & + M3N1MAGxi,M3N1MAGyi,M3N1MAGzi, & + M3N2MAGxi,M3N2MAGyi,M3N2MAGzi, & + M3N3MAGxi,M3N3MAGyi,M3N3MAGzi, & + M3N4MAGxi,M3N4MAGyi,M3N4MAGzi, & + M3N5MAGxi,M3N5MAGyi,M3N5MAGzi, & + M3N6MAGxi,M3N6MAGyi,M3N6MAGzi, & + M3N7MAGxi,M3N7MAGyi,M3N7MAGzi, & + M3N8MAGxi,M3N8MAGyi,M3N8MAGzi, & + M3N9MAGxi,M3N9MAGyi,M3N9MAGzi, & + M4N1MAGxi,M4N1MAGyi,M4N1MAGzi, & + M4N2MAGxi,M4N2MAGyi,M4N2MAGzi, & + M4N3MAGxi,M4N3MAGyi,M4N3MAGzi, & + M4N4MAGxi,M4N4MAGyi,M4N4MAGzi, & + M4N5MAGxi,M4N5MAGyi,M4N5MAGzi, & + M4N6MAGxi,M4N6MAGyi,M4N6MAGzi, & + M4N7MAGxi,M4N7MAGyi,M4N7MAGzi, & + M4N8MAGxi,M4N8MAGyi,M4N8MAGzi, & + M4N9MAGxi,M4N9MAGyi,M4N9MAGzi, & + M5N1MAGxi,M5N1MAGyi,M5N1MAGzi, & + M5N2MAGxi,M5N2MAGyi,M5N2MAGzi, & + M5N3MAGxi,M5N3MAGyi,M5N3MAGzi, & + M5N4MAGxi,M5N4MAGyi,M5N4MAGzi, & + M5N5MAGxi,M5N5MAGyi,M5N5MAGzi, & + M5N6MAGxi,M5N6MAGyi,M5N6MAGzi, & + M5N7MAGxi,M5N7MAGyi,M5N7MAGzi, & + M5N8MAGxi,M5N8MAGyi,M5N8MAGzi, & + M5N9MAGxi,M5N9MAGyi,M5N9MAGzi, & + M6N1MAGxi,M6N1MAGyi,M6N1MAGzi, & + M6N2MAGxi,M6N2MAGyi,M6N2MAGzi, & + M6N3MAGxi,M6N3MAGyi,M6N3MAGzi, & + M6N4MAGxi,M6N4MAGyi,M6N4MAGzi, & + M6N5MAGxi,M6N5MAGyi,M6N5MAGzi, & + M6N6MAGxi,M6N6MAGyi,M6N6MAGzi, & + M6N7MAGxi,M6N7MAGyi,M6N7MAGzi, & + M6N8MAGxi,M6N8MAGyi,M6N8MAGzi, & + M6N9MAGxi,M6N9MAGyi,M6N9MAGzi, & + M7N1MAGxi,M7N1MAGyi,M7N1MAGzi, & + M7N2MAGxi,M7N2MAGyi,M7N2MAGzi, & + M7N3MAGxi,M7N3MAGyi,M7N3MAGzi, & + M7N4MAGxi,M7N4MAGyi,M7N4MAGzi, & + M7N5MAGxi,M7N5MAGyi,M7N5MAGzi, & + M7N6MAGxi,M7N6MAGyi,M7N6MAGzi, & + M7N7MAGxi,M7N7MAGyi,M7N7MAGzi, & + M7N8MAGxi,M7N8MAGyi,M7N8MAGzi, & + M7N9MAGxi,M7N9MAGyi,M7N9MAGzi, & + M8N1MAGxi,M8N1MAGyi,M8N1MAGzi, & + M8N2MAGxi,M8N2MAGyi,M8N2MAGzi, & + M8N3MAGxi,M8N3MAGyi,M8N3MAGzi, & + M8N4MAGxi,M8N4MAGyi,M8N4MAGzi, & + M8N5MAGxi,M8N5MAGyi,M8N5MAGzi, & + M8N6MAGxi,M8N6MAGyi,M8N6MAGzi, & + M8N7MAGxi,M8N7MAGyi,M8N7MAGzi, & + M8N8MAGxi,M8N8MAGyi,M8N8MAGzi, & + M8N9MAGxi,M8N9MAGyi,M8N9MAGzi, & + M9N1MAGxi,M9N1MAGyi,M9N1MAGzi, & + M9N2MAGxi,M9N2MAGyi,M9N2MAGzi, & + M9N3MAGxi,M9N3MAGyi,M9N3MAGzi, & + M9N4MAGxi,M9N4MAGyi,M9N4MAGzi, & + M9N5MAGxi,M9N5MAGyi,M9N5MAGzi, & + M9N6MAGxi,M9N6MAGyi,M9N6MAGzi, & + M9N7MAGxi,M9N7MAGyi,M9N7MAGzi, & + M9N8MAGxi,M9N8MAGyi,M9N8MAGzi, & + M9N9MAGxi,M9N9MAGyi,M9N9MAGzi/), (/3,9,9/)) + INTEGER, PARAMETER :: MNFAFi(3,9,9) = reshape((/M1N1FAFxi,M1N1FAFyi,M1N1FAFzi, & M1N2FAFxi,M1N2FAFyi,M1N2FAFzi, & M1N3FAFxi,M1N3FAFyi,M1N3FAFzi, & @@ -5430,87 +6159,87 @@ MODULE Morison_Output M9N8FAFxi,M9N8FAFyi,M9N8FAFzi, & M9N9FAFxi,M9N9FAFyi,M9N9FAFzi/), (/3,9,9/)) - INTEGER, PARAMETER :: MNFAi(3,9,9) = reshape((/M1N1FAxi,M1N1FAyi,M1N1FAzi, & - M1N2FAxi,M1N2FAyi,M1N2FAzi, & - M1N3FAxi,M1N3FAyi,M1N3FAzi, & - M1N4FAxi,M1N4FAyi,M1N4FAzi, & - M1N5FAxi,M1N5FAyi,M1N5FAzi, & - M1N6FAxi,M1N6FAyi,M1N6FAzi, & - M1N7FAxi,M1N7FAyi,M1N7FAzi, & - M1N8FAxi,M1N8FAyi,M1N8FAzi, & - M1N9FAxi,M1N9FAyi,M1N9FAzi, & - M2N1FAxi,M2N1FAyi,M2N1FAzi, & - M2N2FAxi,M2N2FAyi,M2N2FAzi, & - M2N3FAxi,M2N3FAyi,M2N3FAzi, & - M2N4FAxi,M2N4FAyi,M2N4FAzi, & - M2N5FAxi,M2N5FAyi,M2N5FAzi, & - M2N6FAxi,M2N6FAyi,M2N6FAzi, & - M2N7FAxi,M2N7FAyi,M2N7FAzi, & - M2N8FAxi,M2N8FAyi,M2N8FAzi, & - M2N9FAxi,M2N9FAyi,M2N9FAzi, & - M3N1FAxi,M3N1FAyi,M3N1FAzi, & - M3N2FAxi,M3N2FAyi,M3N2FAzi, & - M3N3FAxi,M3N3FAyi,M3N3FAzi, & - M3N4FAxi,M3N4FAyi,M3N4FAzi, & - M3N5FAxi,M3N5FAyi,M3N5FAzi, & - M3N6FAxi,M3N6FAyi,M3N6FAzi, & - M3N7FAxi,M3N7FAyi,M3N7FAzi, & - M3N8FAxi,M3N8FAyi,M3N8FAzi, & - M3N9FAxi,M3N9FAyi,M3N9FAzi, & - M4N1FAxi,M4N1FAyi,M4N1FAzi, & - M4N2FAxi,M4N2FAyi,M4N2FAzi, & - M4N3FAxi,M4N3FAyi,M4N3FAzi, & - M4N4FAxi,M4N4FAyi,M4N4FAzi, & - M4N5FAxi,M4N5FAyi,M4N5FAzi, & - M4N6FAxi,M4N6FAyi,M4N6FAzi, & - M4N7FAxi,M4N7FAyi,M4N7FAzi, & - M4N8FAxi,M4N8FAyi,M4N8FAzi, & - M4N9FAxi,M4N9FAyi,M4N9FAzi, & - M5N1FAxi,M5N1FAyi,M5N1FAzi, & - M5N2FAxi,M5N2FAyi,M5N2FAzi, & - M5N3FAxi,M5N3FAyi,M5N3FAzi, & - M5N4FAxi,M5N4FAyi,M5N4FAzi, & - M5N5FAxi,M5N5FAyi,M5N5FAzi, & - M5N6FAxi,M5N6FAyi,M5N6FAzi, & - M5N7FAxi,M5N7FAyi,M5N7FAzi, & - M5N8FAxi,M5N8FAyi,M5N8FAzi, & - M5N9FAxi,M5N9FAyi,M5N9FAzi, & - M6N1FAxi,M6N1FAyi,M6N1FAzi, & - M6N2FAxi,M6N2FAyi,M6N2FAzi, & - M6N3FAxi,M6N3FAyi,M6N3FAzi, & - M6N4FAxi,M6N4FAyi,M6N4FAzi, & - M6N5FAxi,M6N5FAyi,M6N5FAzi, & - M6N6FAxi,M6N6FAyi,M6N6FAzi, & - M6N7FAxi,M6N7FAyi,M6N7FAzi, & - M6N8FAxi,M6N8FAyi,M6N8FAzi, & - M6N9FAxi,M6N9FAyi,M6N9FAzi, & - M7N1FAxi,M7N1FAyi,M7N1FAzi, & - M7N2FAxi,M7N2FAyi,M7N2FAzi, & - M7N3FAxi,M7N3FAyi,M7N3FAzi, & - M7N4FAxi,M7N4FAyi,M7N4FAzi, & - M7N5FAxi,M7N5FAyi,M7N5FAzi, & - M7N6FAxi,M7N6FAyi,M7N6FAzi, & - M7N7FAxi,M7N7FAyi,M7N7FAzi, & - M7N8FAxi,M7N8FAyi,M7N8FAzi, & - M7N9FAxi,M7N9FAyi,M7N9FAzi, & - M8N1FAxi,M8N1FAyi,M8N1FAzi, & - M8N2FAxi,M8N2FAyi,M8N2FAzi, & - M8N3FAxi,M8N3FAyi,M8N3FAzi, & - M8N4FAxi,M8N4FAyi,M8N4FAzi, & - M8N5FAxi,M8N5FAyi,M8N5FAzi, & - M8N6FAxi,M8N6FAyi,M8N6FAzi, & - M8N7FAxi,M8N7FAyi,M8N7FAzi, & - M8N8FAxi,M8N8FAyi,M8N8FAzi, & - M8N9FAxi,M8N9FAyi,M8N9FAzi, & - M9N1FAxi,M9N1FAyi,M9N1FAzi, & - M9N2FAxi,M9N2FAyi,M9N2FAzi, & - M9N3FAxi,M9N3FAyi,M9N3FAzi, & - M9N4FAxi,M9N4FAyi,M9N4FAzi, & - M9N5FAxi,M9N5FAyi,M9N5FAzi, & - M9N6FAxi,M9N6FAyi,M9N6FAzi, & - M9N7FAxi,M9N7FAyi,M9N7FAzi, & - M9N8FAxi,M9N8FAyi,M9N8FAzi, & - M9N9FAxi,M9N9FAyi,M9N9FAzi/), (/3,9,9/)) + INTEGER, PARAMETER :: MNMAFi(3,9,9) = reshape((/M1N1MAFxi,M1N1MAFyi,M1N1MAFzi, & + M1N2MAFxi,M1N2MAFyi,M1N2MAFzi, & + M1N3MAFxi,M1N3MAFyi,M1N3MAFzi, & + M1N4MAFxi,M1N4MAFyi,M1N4MAFzi, & + M1N5MAFxi,M1N5MAFyi,M1N5MAFzi, & + M1N6MAFxi,M1N6MAFyi,M1N6MAFzi, & + M1N7MAFxi,M1N7MAFyi,M1N7MAFzi, & + M1N8MAFxi,M1N8MAFyi,M1N8MAFzi, & + M1N9MAFxi,M1N9MAFyi,M1N9MAFzi, & + M2N1MAFxi,M2N1MAFyi,M2N1MAFzi, & + M2N2MAFxi,M2N2MAFyi,M2N2MAFzi, & + M2N3MAFxi,M2N3MAFyi,M2N3MAFzi, & + M2N4MAFxi,M2N4MAFyi,M2N4MAFzi, & + M2N5MAFxi,M2N5MAFyi,M2N5MAFzi, & + M2N6MAFxi,M2N6MAFyi,M2N6MAFzi, & + M2N7MAFxi,M2N7MAFyi,M2N7MAFzi, & + M2N8MAFxi,M2N8MAFyi,M2N8MAFzi, & + M2N9MAFxi,M2N9MAFyi,M2N9MAFzi, & + M3N1MAFxi,M3N1MAFyi,M3N1MAFzi, & + M3N2MAFxi,M3N2MAFyi,M3N2MAFzi, & + M3N3MAFxi,M3N3MAFyi,M3N3MAFzi, & + M3N4MAFxi,M3N4MAFyi,M3N4MAFzi, & + M3N5MAFxi,M3N5MAFyi,M3N5MAFzi, & + M3N6MAFxi,M3N6MAFyi,M3N6MAFzi, & + M3N7MAFxi,M3N7MAFyi,M3N7MAFzi, & + M3N8MAFxi,M3N8MAFyi,M3N8MAFzi, & + M3N9MAFxi,M3N9MAFyi,M3N9MAFzi, & + M4N1MAFxi,M4N1MAFyi,M4N1MAFzi, & + M4N2MAFxi,M4N2MAFyi,M4N2MAFzi, & + M4N3MAFxi,M4N3MAFyi,M4N3MAFzi, & + M4N4MAFxi,M4N4MAFyi,M4N4MAFzi, & + M4N5MAFxi,M4N5MAFyi,M4N5MAFzi, & + M4N6MAFxi,M4N6MAFyi,M4N6MAFzi, & + M4N7MAFxi,M4N7MAFyi,M4N7MAFzi, & + M4N8MAFxi,M4N8MAFyi,M4N8MAFzi, & + M4N9MAFxi,M4N9MAFyi,M4N9MAFzi, & + M5N1MAFxi,M5N1MAFyi,M5N1MAFzi, & + M5N2MAFxi,M5N2MAFyi,M5N2MAFzi, & + M5N3MAFxi,M5N3MAFyi,M5N3MAFzi, & + M5N4MAFxi,M5N4MAFyi,M5N4MAFzi, & + M5N5MAFxi,M5N5MAFyi,M5N5MAFzi, & + M5N6MAFxi,M5N6MAFyi,M5N6MAFzi, & + M5N7MAFxi,M5N7MAFyi,M5N7MAFzi, & + M5N8MAFxi,M5N8MAFyi,M5N8MAFzi, & + M5N9MAFxi,M5N9MAFyi,M5N9MAFzi, & + M6N1MAFxi,M6N1MAFyi,M6N1MAFzi, & + M6N2MAFxi,M6N2MAFyi,M6N2MAFzi, & + M6N3MAFxi,M6N3MAFyi,M6N3MAFzi, & + M6N4MAFxi,M6N4MAFyi,M6N4MAFzi, & + M6N5MAFxi,M6N5MAFyi,M6N5MAFzi, & + M6N6MAFxi,M6N6MAFyi,M6N6MAFzi, & + M6N7MAFxi,M6N7MAFyi,M6N7MAFzi, & + M6N8MAFxi,M6N8MAFyi,M6N8MAFzi, & + M6N9MAFxi,M6N9MAFyi,M6N9MAFzi, & + M7N1MAFxi,M7N1MAFyi,M7N1MAFzi, & + M7N2MAFxi,M7N2MAFyi,M7N2MAFzi, & + M7N3MAFxi,M7N3MAFyi,M7N3MAFzi, & + M7N4MAFxi,M7N4MAFyi,M7N4MAFzi, & + M7N5MAFxi,M7N5MAFyi,M7N5MAFzi, & + M7N6MAFxi,M7N6MAFyi,M7N6MAFzi, & + M7N7MAFxi,M7N7MAFyi,M7N7MAFzi, & + M7N8MAFxi,M7N8MAFyi,M7N8MAFzi, & + M7N9MAFxi,M7N9MAFyi,M7N9MAFzi, & + M8N1MAFxi,M8N1MAFyi,M8N1MAFzi, & + M8N2MAFxi,M8N2MAFyi,M8N2MAFzi, & + M8N3MAFxi,M8N3MAFyi,M8N3MAFzi, & + M8N4MAFxi,M8N4MAFyi,M8N4MAFzi, & + M8N5MAFxi,M8N5MAFyi,M8N5MAFzi, & + M8N6MAFxi,M8N6MAFyi,M8N6MAFzi, & + M8N7MAFxi,M8N7MAFyi,M8N7MAFzi, & + M8N8MAFxi,M8N8MAFyi,M8N8MAFzi, & + M8N9MAFxi,M8N9MAFyi,M8N9MAFzi, & + M9N1MAFxi,M9N1MAFyi,M9N1MAFzi, & + M9N2MAFxi,M9N2MAFyi,M9N2MAFzi, & + M9N3MAFxi,M9N3MAFyi,M9N3MAFzi, & + M9N4MAFxi,M9N4MAFyi,M9N4MAFzi, & + M9N5MAFxi,M9N5MAFyi,M9N5MAFzi, & + M9N6MAFxi,M9N6MAFyi,M9N6MAFzi, & + M9N7MAFxi,M9N7MAFyi,M9N7MAFzi, & + M9N8MAFxi,M9N8MAFyi,M9N8MAFzi, & + M9N9MAFxi,M9N9MAFyi,M9N9MAFzi/), (/3,9,9/)) INTEGER, PARAMETER :: JVi(3,9) = reshape((/J1Vxi, J1Vyi, J1Vzi , & J2Vxi, J2Vyi, J2Vzi , & @@ -5617,7 +6346,26 @@ MODULE Morison_Output J9MBFxi, J9MBFyi, J9MBFzi/), (/3,9/)) - + INTEGER, PARAMETER :: JFAGi(3,9) = reshape((/J1FAGxi, J1FAGyi, J1FAGzi , & + J2FAGxi, J2FAGyi, J2FAGzi , & + J3FAGxi, J3FAGyi, J3FAGzi , & + J4FAGxi, J4FAGyi, J4FAGzi , & + J5FAGxi, J5FAGyi, J5FAGzi , & + J6FAGxi, J6FAGyi, J6FAGzi , & + J7FAGxi, J7FAGyi, J7FAGzi , & + J8FAGxi, J8FAGyi, J8FAGzi , & + J9FAGxi, J9FAGyi, J9FAGzi/), (/3,9/)) + + INTEGER, PARAMETER :: JMAGi(3,9) = reshape((/J1MAGxi, J1MAGyi, J1MAGzi , & + J2MAGxi, J2MAGyi, J2MAGzi , & + J3MAGxi, J3MAGyi, J3MAGzi , & + J4MAGxi, J4MAGyi, J4MAGzi , & + J5MAGxi, J5MAGyi, J5MAGzi , & + J6MAGxi, J6MAGyi, J6MAGzi , & + J7MAGxi, J7MAGyi, J7MAGzi , & + J8MAGxi, J8MAGyi, J8MAGzi , & + J9MAGxi, J9MAGyi, J9MAGzi/), (/3,9/)) + INTEGER, PARAMETER :: JFAMi(3,9) = reshape((/J1FAMxi, J1FAMyi, J1FAMzi , & J2FAMxi, J2FAMyi, J2FAMzi , & J3FAMxi, J3FAMyi, J3FAMzi , & @@ -5627,1230 +6375,27 @@ MODULE Morison_Output J7FAMxi, J7FAMyi, J7FAMzi , & J8FAMxi, J8FAMyi, J8FAMzi , & J9FAMxi, J9FAMyi, J9FAMzi/), (/3,9/)) + + INTEGER, PARAMETER :: JFMGi(3,9) = reshape((/J1FMGxi, J1FMGyi, J1FMGzi , & + J2FMGxi, J2FMGyi, J2FMGzi , & + J3FMGxi, J3FMGyi, J3FMGzi , & + J4FMGxi, J4FMGyi, J4FMGzi , & + J5FMGxi, J5FMGyi, J5FMGzi , & + J6FMGxi, J6FMGyi, J6FMGzi , & + J7FMGxi, J7FMGyi, J7FMGzi , & + J8FMGxi, J8FMGyi, J8FMGzi , & + J9FMGxi, J9FMGyi, J9FMGzi/), (/3,9/)) !********************************************************************************************************************************** ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" ! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these ! lines should be modified in the Matlab script and/or Excel worksheet as necessary. ! This code was generated by Write_ChckOutLst.m at 04-Jan-2014 12:13:30. - - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(4032) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "J1AXI ","J1AYI ","J1AZI ","J1DYNP ","J1FAMXI ","J1FAMYI ","J1FAMZI ","J1FBFXI ","J1FBFYI ","J1FBFZI ", & - "J1FBXI ","J1FBYI ","J1FBZI ","J1FDXI ","J1FDYI ","J1FDZI ","J1FIXI ","J1FIYI ","J1FIZI ","J1MBFXI ", & - "J1MBFYI ","J1MBFZI ","J1MBXI ","J1MBYI ","J1MBZI ","J1STAXI ","J1STAYI ","J1STAZI ","J1STVXI ","J1STVYI ", & - "J1STVZI ","J1VXI ","J1VYI ","J1VZI ","J2AXI ","J2AYI ","J2AZI ","J2DYNP ","J2FAMXI ","J2FAMYI ", & - "J2FAMZI ","J2FBFXI ","J2FBFYI ","J2FBFZI ","J2FBXI ","J2FBYI ","J2FBZI ","J2FDXI ","J2FDYI ","J2FDZI ", & - "J2FIXI ","J2FIYI ","J2FIZI ","J2MBFXI ","J2MBFYI ","J2MBFZI ","J2MBXI ","J2MBYI ","J2MBZI ","J2STAXI ", & - "J2STAYI ","J2STAZI ","J2STVXI ","J2STVYI ","J2STVZI ","J2VXI ","J2VYI ","J2VZI ","J3AXI ","J3AYI ", & - "J3AZI ","J3DYNP ","J3FAMXI ","J3FAMYI ","J3FAMZI ","J3FBFXI ","J3FBFYI ","J3FBFZI ","J3FBXI ","J3FBYI ", & - "J3FBZI ","J3FDXI ","J3FDYI ","J3FDZI ","J3FIXI ","J3FIYI ","J3FIZI ","J3MBFXI ","J3MBFYI ","J3MBFZI ", & - "J3MBXI ","J3MBYI ","J3MBZI ","J3STAXI ","J3STAYI ","J3STAZI ","J3STVXI ","J3STVYI ","J3STVZI ","J3VXI ", & - "J3VYI ","J3VZI ","J4AXI ","J4AYI ","J4AZI ","J4DYNP ","J4FAMXI ","J4FAMYI ","J4FAMZI ","J4FBFXI ", & - "J4FBFYI ","J4FBFZI ","J4FBXI ","J4FBYI ","J4FBZI ","J4FDXI ","J4FDYI ","J4FDZI ","J4FIXI ","J4FIYI ", & - "J4FIZI ","J4MBFXI ","J4MBFYI ","J4MBFZI ","J4MBXI ","J4MBYI ","J4MBZI ","J4STAXI ","J4STAYI ","J4STAZI ", & - "J4STVXI ","J4STVYI ","J4STVZI ","J4VXI ","J4VYI ","J4VZI ","J5AXI ","J5AYI ","J5AZI ","J5DYNP ", & - "J5FAMXI ","J5FAMYI ","J5FAMZI ","J5FBFXI ","J5FBFYI ","J5FBFZI ","J5FBXI ","J5FBYI ","J5FBZI ","J5FDXI ", & - "J5FDYI ","J5FDZI ","J5FIXI ","J5FIYI ","J5FIZI ","J5MBFXI ","J5MBFYI ","J5MBFZI ","J5MBXI ","J5MBYI ", & - "J5MBZI ","J5STAXI ","J5STAYI ","J5STAZI ","J5STVXI ","J5STVYI ","J5STVZI ","J5VXI ","J5VYI ","J5VZI ", & - "J6AXI ","J6AYI ","J6AZI ","J6DYNP ","J6FAMXI ","J6FAMYI ","J6FAMZI ","J6FBFXI ","J6FBFYI ","J6FBFZI ", & - "J6FBXI ","J6FBYI ","J6FBZI ","J6FDXI ","J6FDYI ","J6FDZI ","J6FIXI ","J6FIYI ","J6FIZI ","J6MBFXI ", & - "J6MBFYI ","J6MBFZI ","J6MBXI ","J6MBYI ","J6MBZI ","J6STAXI ","J6STAYI ","J6STAZI ","J6STVXI ","J6STVYI ", & - "J6STVZI ","J6VXI ","J6VYI ","J6VZI ","J7AXI ","J7AYI ","J7AZI ","J7DYNP ","J7FAMXI ","J7FAMYI ", & - "J7FAMZI ","J7FBFXI ","J7FBFYI ","J7FBFZI ","J7FBXI ","J7FBYI ","J7FBZI ","J7FDXI ","J7FDYI ","J7FDZI ", & - "J7FIXI ","J7FIYI ","J7FIZI ","J7MBFXI ","J7MBFYI ","J7MBFZI ","J7MBXI ","J7MBYI ","J7MBZI ","J7STAXI ", & - "J7STAYI ","J7STAZI ","J7STVXI ","J7STVYI ","J7STVZI ","J7VXI ","J7VYI ","J7VZI ","J8AXI ","J8AYI ", & - "J8AZI ","J8DYNP ","J8FAMXI ","J8FAMYI ","J8FAMZI ","J8FBFXI ","J8FBFYI ","J8FBFZI ","J8FBXI ","J8FBYI ", & - "J8FBZI ","J8FDXI ","J8FDYI ","J8FDZI ","J8FIXI ","J8FIYI ","J8FIZI ","J8MBFXI ","J8MBFYI ","J8MBFZI ", & - "J8MBXI ","J8MBYI ","J8MBZI ","J8STAXI ","J8STAYI ","J8STAZI ","J8STVXI ","J8STVYI ","J8STVZI ","J8VXI ", & - "J8VYI ","J8VZI ","J9AXI ","J9AYI ","J9AZI ","J9DYNP ","J9FAMXI ","J9FAMYI ","J9FAMZI ","J9FBFXI ", & - "J9FBFYI ","J9FBFZI ","J9FBXI ","J9FBYI ","J9FBZI ","J9FDXI ","J9FDYI ","J9FDZI ","J9FIXI ","J9FIYI ", & - "J9FIZI ","J9MBFXI ","J9MBFYI ","J9MBFZI ","J9MBXI ","J9MBYI ","J9MBZI ","J9STAXI ","J9STAYI ","J9STAZI ", & - "J9STVXI ","J9STVYI ","J9STVZI ","J9VXI ","J9VYI ","J9VZI ","M1N1AXI ","M1N1AYI ","M1N1AZI ","M1N1DYNP ", & - "M1N1FAFXI","M1N1FAFYI","M1N1FAFZI","M1N1FAGXI","M1N1FAGYI","M1N1FAGZI","M1N1FAMXI","M1N1FAMYI","M1N1FAMZI","M1N1FAXI ", & - "M1N1FAYI ","M1N1FAZI ","M1N1FBFXI","M1N1FBFYI","M1N1FBFZI","M1N1FBXI ","M1N1FBYI ","M1N1FBZI ","M1N1FDXI ","M1N1FDYI ", & - "M1N1FDZI ","M1N1FIXI ","M1N1FIYI ","M1N1FIZI ","M1N1FMGXI","M1N1FMGYI","M1N1FMGZI","M1N1MBFXI","M1N1MBFYI","M1N1MBFZI", & - "M1N1MBXI ","M1N1MBYI ","M1N1MBZI ","M1N1STAXI","M1N1STAYI","M1N1STAZI","M1N1STVXI","M1N1STVYI","M1N1STVZI","M1N1VXI ", & - "M1N1VYI ","M1N1VZI ","M1N2AXI ","M1N2AYI ","M1N2AZI ","M1N2DYNP ","M1N2FAFXI","M1N2FAFYI","M1N2FAFZI","M1N2FAGXI", & - "M1N2FAGYI","M1N2FAGZI","M1N2FAMXI","M1N2FAMYI","M1N2FAMZI","M1N2FAXI ","M1N2FAYI ","M1N2FAZI ","M1N2FBFXI","M1N2FBFYI", & - "M1N2FBFZI","M1N2FBXI ","M1N2FBYI ","M1N2FBZI ","M1N2FDXI ","M1N2FDYI ","M1N2FDZI ","M1N2FIXI ","M1N2FIYI ","M1N2FIZI ", & - "M1N2FMGXI","M1N2FMGYI","M1N2FMGZI","M1N2MBFXI","M1N2MBFYI","M1N2MBFZI","M1N2MBXI ","M1N2MBYI ","M1N2MBZI ","M1N2STAXI", & - "M1N2STAYI","M1N2STAZI","M1N2STVXI","M1N2STVYI","M1N2STVZI","M1N2VXI ","M1N2VYI ","M1N2VZI ","M1N3AXI ","M1N3AYI ", & - "M1N3AZI ","M1N3DYNP ","M1N3FAFXI","M1N3FAFYI","M1N3FAFZI","M1N3FAGXI","M1N3FAGYI","M1N3FAGZI","M1N3FAMXI","M1N3FAMYI", & - "M1N3FAMZI","M1N3FAXI ","M1N3FAYI ","M1N3FAZI ","M1N3FBFXI","M1N3FBFYI","M1N3FBFZI","M1N3FBXI ","M1N3FBYI ","M1N3FBZI ", & - "M1N3FDXI ","M1N3FDYI ","M1N3FDZI ","M1N3FIXI ","M1N3FIYI ","M1N3FIZI ","M1N3FMGXI","M1N3FMGYI","M1N3FMGZI","M1N3MBFXI", & - "M1N3MBFYI","M1N3MBFZI","M1N3MBXI ","M1N3MBYI ","M1N3MBZI ","M1N3STAXI","M1N3STAYI","M1N3STAZI","M1N3STVXI","M1N3STVYI", & - "M1N3STVZI","M1N3VXI ","M1N3VYI ","M1N3VZI ","M1N4AXI ","M1N4AYI ","M1N4AZI ","M1N4DYNP ","M1N4FAFXI","M1N4FAFYI", & - "M1N4FAFZI","M1N4FAGXI","M1N4FAGYI","M1N4FAGZI","M1N4FAMXI","M1N4FAMYI","M1N4FAMZI","M1N4FAXI ","M1N4FAYI ","M1N4FAZI ", & - "M1N4FBFXI","M1N4FBFYI","M1N4FBFZI","M1N4FBXI ","M1N4FBYI ","M1N4FBZI ","M1N4FDXI ","M1N4FDYI ","M1N4FDZI ","M1N4FIXI ", & - "M1N4FIYI ","M1N4FIZI ","M1N4FMGXI","M1N4FMGYI","M1N4FMGZI","M1N4MBFXI","M1N4MBFYI","M1N4MBFZI","M1N4MBXI ","M1N4MBYI ", & - "M1N4MBZI ","M1N4STAXI","M1N4STAYI","M1N4STAZI","M1N4STVXI","M1N4STVYI","M1N4STVZI","M1N4VXI ","M1N4VYI ","M1N4VZI ", & - "M1N5AXI ","M1N5AYI ","M1N5AZI ","M1N5DYNP ","M1N5FAFXI","M1N5FAFYI","M1N5FAFZI","M1N5FAGXI","M1N5FAGYI","M1N5FAGZI", & - "M1N5FAMXI","M1N5FAMYI","M1N5FAMZI","M1N5FAXI ","M1N5FAYI ","M1N5FAZI ","M1N5FBFXI","M1N5FBFYI","M1N5FBFZI","M1N5FBXI ", & - "M1N5FBYI ","M1N5FBZI ","M1N5FDXI ","M1N5FDYI ","M1N5FDZI ","M1N5FIXI ","M1N5FIYI ","M1N5FIZI ","M1N5FMGXI","M1N5FMGYI", & - "M1N5FMGZI","M1N5MBFXI","M1N5MBFYI","M1N5MBFZI","M1N5MBXI ","M1N5MBYI ","M1N5MBZI ","M1N5STAXI","M1N5STAYI","M1N5STAZI", & - "M1N5STVXI","M1N5STVYI","M1N5STVZI","M1N5VXI ","M1N5VYI ","M1N5VZI ","M1N6AXI ","M1N6AYI ","M1N6AZI ","M1N6DYNP ", & - "M1N6FAFXI","M1N6FAFYI","M1N6FAFZI","M1N6FAGXI","M1N6FAGYI","M1N6FAGZI","M1N6FAMXI","M1N6FAMYI","M1N6FAMZI","M1N6FAXI ", & - "M1N6FAYI ","M1N6FAZI ","M1N6FBFXI","M1N6FBFYI","M1N6FBFZI","M1N6FBXI ","M1N6FBYI ","M1N6FBZI ","M1N6FDXI ","M1N6FDYI ", & - "M1N6FDZI ","M1N6FIXI ","M1N6FIYI ","M1N6FIZI ","M1N6FMGXI","M1N6FMGYI","M1N6FMGZI","M1N6MBFXI","M1N6MBFYI","M1N6MBFZI", & - "M1N6MBXI ","M1N6MBYI ","M1N6MBZI ","M1N6STAXI","M1N6STAYI","M1N6STAZI","M1N6STVXI","M1N6STVYI","M1N6STVZI","M1N6VXI ", & - "M1N6VYI ","M1N6VZI ","M1N7AXI ","M1N7AYI ","M1N7AZI ","M1N7DYNP ","M1N7FAFXI","M1N7FAFYI","M1N7FAFZI","M1N7FAGXI", & - "M1N7FAGYI","M1N7FAGZI","M1N7FAMXI","M1N7FAMYI","M1N7FAMZI","M1N7FAXI ","M1N7FAYI ","M1N7FAZI ","M1N7FBFXI","M1N7FBFYI", & - "M1N7FBFZI","M1N7FBXI ","M1N7FBYI ","M1N7FBZI ","M1N7FDXI ","M1N7FDYI ","M1N7FDZI ","M1N7FIXI ","M1N7FIYI ","M1N7FIZI ", & - "M1N7FMGXI","M1N7FMGYI","M1N7FMGZI","M1N7MBFXI","M1N7MBFYI","M1N7MBFZI","M1N7MBXI ","M1N7MBYI ","M1N7MBZI ","M1N7STAXI", & - "M1N7STAYI","M1N7STAZI","M1N7STVXI","M1N7STVYI","M1N7STVZI","M1N7VXI ","M1N7VYI ","M1N7VZI ","M1N8AXI ","M1N8AYI ", & - "M1N8AZI ","M1N8DYNP ","M1N8FAFXI","M1N8FAFYI","M1N8FAFZI","M1N8FAGXI","M1N8FAGYI","M1N8FAGZI","M1N8FAMXI","M1N8FAMYI", & - "M1N8FAMZI","M1N8FAXI ","M1N8FAYI ","M1N8FAZI ","M1N8FBFXI","M1N8FBFYI","M1N8FBFZI","M1N8FBXI ","M1N8FBYI ","M1N8FBZI ", & - "M1N8FDXI ","M1N8FDYI ","M1N8FDZI ","M1N8FIXI ","M1N8FIYI ","M1N8FIZI ","M1N8FMGXI","M1N8FMGYI","M1N8FMGZI","M1N8MBFXI", & - "M1N8MBFYI","M1N8MBFZI","M1N8MBXI ","M1N8MBYI ","M1N8MBZI ","M1N8STAXI","M1N8STAYI","M1N8STAZI","M1N8STVXI","M1N8STVYI", & - "M1N8STVZI","M1N8VXI ","M1N8VYI ","M1N8VZI ","M1N9AXI ","M1N9AYI ","M1N9AZI ","M1N9DYNP ","M1N9FAFXI","M1N9FAFYI", & - "M1N9FAFZI","M1N9FAGXI","M1N9FAGYI","M1N9FAGZI","M1N9FAMXI","M1N9FAMYI","M1N9FAMZI","M1N9FAXI ","M1N9FAYI ","M1N9FAZI ", & - "M1N9FBFXI","M1N9FBFYI","M1N9FBFZI","M1N9FBXI ","M1N9FBYI ","M1N9FBZI ","M1N9FDXI ","M1N9FDYI ","M1N9FDZI ","M1N9FIXI ", & - "M1N9FIYI ","M1N9FIZI ","M1N9FMGXI","M1N9FMGYI","M1N9FMGZI","M1N9MBFXI","M1N9MBFYI","M1N9MBFZI","M1N9MBXI ","M1N9MBYI ", & - "M1N9MBZI ","M1N9STAXI","M1N9STAYI","M1N9STAZI","M1N9STVXI","M1N9STVYI","M1N9STVZI","M1N9VXI ","M1N9VYI ","M1N9VZI ", & - "M2N1AXI ","M2N1AYI ","M2N1AZI ","M2N1DYNP ","M2N1FAFXI","M2N1FAFYI","M2N1FAFZI","M2N1FAGXI","M2N1FAGYI","M2N1FAGZI", & - "M2N1FAMXI","M2N1FAMYI","M2N1FAMZI","M2N1FAXI ","M2N1FAYI ","M2N1FAZI ","M2N1FBFXI","M2N1FBFYI","M2N1FBFZI","M2N1FBXI ", & - "M2N1FBYI ","M2N1FBZI ","M2N1FDXI ","M2N1FDYI ","M2N1FDZI ","M2N1FIXI ","M2N1FIYI ","M2N1FIZI ","M2N1FMGXI","M2N1FMGYI", & - "M2N1FMGZI","M2N1MBFXI","M2N1MBFYI","M2N1MBFZI","M2N1MBXI ","M2N1MBYI ","M2N1MBZI ","M2N1STAXI","M2N1STAYI","M2N1STAZI", & - "M2N1STVXI","M2N1STVYI","M2N1STVZI","M2N1VXI ","M2N1VYI ","M2N1VZI ","M2N2AXI ","M2N2AYI ","M2N2AZI ","M2N2DYNP ", & - "M2N2FAFXI","M2N2FAFYI","M2N2FAFZI","M2N2FAGXI","M2N2FAGYI","M2N2FAGZI","M2N2FAMXI","M2N2FAMYI","M2N2FAMZI","M2N2FAXI ", & - "M2N2FAYI ","M2N2FAZI ","M2N2FBFXI","M2N2FBFYI","M2N2FBFZI","M2N2FBXI ","M2N2FBYI ","M2N2FBZI ","M2N2FDXI ","M2N2FDYI ", & - "M2N2FDZI ","M2N2FIXI ","M2N2FIYI ","M2N2FIZI ","M2N2FMGXI","M2N2FMGYI","M2N2FMGZI","M2N2MBFXI","M2N2MBFYI","M2N2MBFZI", & - "M2N2MBXI ","M2N2MBYI ","M2N2MBZI ","M2N2STAXI","M2N2STAYI","M2N2STAZI","M2N2STVXI","M2N2STVYI","M2N2STVZI","M2N2VXI ", & - "M2N2VYI ","M2N2VZI ","M2N3AXI ","M2N3AYI ","M2N3AZI ","M2N3DYNP ","M2N3FAFXI","M2N3FAFYI","M2N3FAFZI","M2N3FAGXI", & - "M2N3FAGYI","M2N3FAGZI","M2N3FAMXI","M2N3FAMYI","M2N3FAMZI","M2N3FAXI ","M2N3FAYI ","M2N3FAZI ","M2N3FBFXI","M2N3FBFYI", & - "M2N3FBFZI","M2N3FBXI ","M2N3FBYI ","M2N3FBZI ","M2N3FDXI ","M2N3FDYI ","M2N3FDZI ","M2N3FIXI ","M2N3FIYI ","M2N3FIZI ", & - "M2N3FMGXI","M2N3FMGYI","M2N3FMGZI","M2N3MBFXI","M2N3MBFYI","M2N3MBFZI","M2N3MBXI ","M2N3MBYI ","M2N3MBZI ","M2N3STAXI", & - "M2N3STAYI","M2N3STAZI","M2N3STVXI","M2N3STVYI","M2N3STVZI","M2N3VXI ","M2N3VYI ","M2N3VZI ","M2N4AXI ","M2N4AYI ", & - "M2N4AZI ","M2N4DYNP ","M2N4FAFXI","M2N4FAFYI","M2N4FAFZI","M2N4FAGXI","M2N4FAGYI","M2N4FAGZI","M2N4FAMXI","M2N4FAMYI", & - "M2N4FAMZI","M2N4FAXI ","M2N4FAYI ","M2N4FAZI ","M2N4FBFXI","M2N4FBFYI","M2N4FBFZI","M2N4FBXI ","M2N4FBYI ","M2N4FBZI ", & - "M2N4FDXI ","M2N4FDYI ","M2N4FDZI ","M2N4FIXI ","M2N4FIYI ","M2N4FIZI ","M2N4FMGXI","M2N4FMGYI","M2N4FMGZI","M2N4MBFXI", & - "M2N4MBFYI","M2N4MBFZI","M2N4MBXI ","M2N4MBYI ","M2N4MBZI ","M2N4STAXI","M2N4STAYI","M2N4STAZI","M2N4STVXI","M2N4STVYI", & - "M2N4STVZI","M2N4VXI ","M2N4VYI ","M2N4VZI ","M2N5AXI ","M2N5AYI ","M2N5AZI ","M2N5DYNP ","M2N5FAFXI","M2N5FAFYI", & - "M2N5FAFZI","M2N5FAGXI","M2N5FAGYI","M2N5FAGZI","M2N5FAMXI","M2N5FAMYI","M2N5FAMZI","M2N5FAXI ","M2N5FAYI ","M2N5FAZI ", & - "M2N5FBFXI","M2N5FBFYI","M2N5FBFZI","M2N5FBXI ","M2N5FBYI ","M2N5FBZI ","M2N5FDXI ","M2N5FDYI ","M2N5FDZI ","M2N5FIXI ", & - "M2N5FIYI ","M2N5FIZI ","M2N5FMGXI","M2N5FMGYI","M2N5FMGZI","M2N5MBFXI","M2N5MBFYI","M2N5MBFZI","M2N5MBXI ","M2N5MBYI ", & - "M2N5MBZI ","M2N5STAXI","M2N5STAYI","M2N5STAZI","M2N5STVXI","M2N5STVYI","M2N5STVZI","M2N5VXI ","M2N5VYI ","M2N5VZI ", & - "M2N6AXI ","M2N6AYI ","M2N6AZI ","M2N6DYNP ","M2N6FAFXI","M2N6FAFYI","M2N6FAFZI","M2N6FAGXI","M2N6FAGYI","M2N6FAGZI", & - "M2N6FAMXI","M2N6FAMYI","M2N6FAMZI","M2N6FAXI ","M2N6FAYI ","M2N6FAZI ","M2N6FBFXI","M2N6FBFYI","M2N6FBFZI","M2N6FBXI ", & - "M2N6FBYI ","M2N6FBZI ","M2N6FDXI ","M2N6FDYI ","M2N6FDZI ","M2N6FIXI ","M2N6FIYI ","M2N6FIZI ","M2N6FMGXI","M2N6FMGYI", & - "M2N6FMGZI","M2N6MBFXI","M2N6MBFYI","M2N6MBFZI","M2N6MBXI ","M2N6MBYI ","M2N6MBZI ","M2N6STAXI","M2N6STAYI","M2N6STAZI", & - "M2N6STVXI","M2N6STVYI","M2N6STVZI","M2N6VXI ","M2N6VYI ","M2N6VZI ","M2N7AXI ","M2N7AYI ","M2N7AZI ","M2N7DYNP ", & - "M2N7FAFXI","M2N7FAFYI","M2N7FAFZI","M2N7FAGXI","M2N7FAGYI","M2N7FAGZI","M2N7FAMXI","M2N7FAMYI","M2N7FAMZI","M2N7FAXI ", & - "M2N7FAYI ","M2N7FAZI ","M2N7FBFXI","M2N7FBFYI","M2N7FBFZI","M2N7FBXI ","M2N7FBYI ","M2N7FBZI ","M2N7FDXI ","M2N7FDYI ", & - "M2N7FDZI ","M2N7FIXI ","M2N7FIYI ","M2N7FIZI ","M2N7FMGXI","M2N7FMGYI","M2N7FMGZI","M2N7MBFXI","M2N7MBFYI","M2N7MBFZI", & - "M2N7MBXI ","M2N7MBYI ","M2N7MBZI ","M2N7STAXI","M2N7STAYI","M2N7STAZI","M2N7STVXI","M2N7STVYI","M2N7STVZI","M2N7VXI ", & - "M2N7VYI ","M2N7VZI ","M2N8AXI ","M2N8AYI ","M2N8AZI ","M2N8DYNP ","M2N8FAFXI","M2N8FAFYI","M2N8FAFZI","M2N8FAGXI", & - "M2N8FAGYI","M2N8FAGZI","M2N8FAMXI","M2N8FAMYI","M2N8FAMZI","M2N8FAXI ","M2N8FAYI ","M2N8FAZI ","M2N8FBFXI","M2N8FBFYI", & - "M2N8FBFZI","M2N8FBXI ","M2N8FBYI ","M2N8FBZI ","M2N8FDXI ","M2N8FDYI ","M2N8FDZI ","M2N8FIXI ","M2N8FIYI ","M2N8FIZI ", & - "M2N8FMGXI","M2N8FMGYI","M2N8FMGZI","M2N8MBFXI","M2N8MBFYI","M2N8MBFZI","M2N8MBXI ","M2N8MBYI ","M2N8MBZI ","M2N8STAXI", & - "M2N8STAYI","M2N8STAZI","M2N8STVXI","M2N8STVYI","M2N8STVZI","M2N8VXI ","M2N8VYI ","M2N8VZI ","M2N9AXI ","M2N9AYI ", & - "M2N9AZI ","M2N9DYNP ","M2N9FAFXI","M2N9FAFYI","M2N9FAFZI","M2N9FAGXI","M2N9FAGYI","M2N9FAGZI","M2N9FAMXI","M2N9FAMYI", & - "M2N9FAMZI","M2N9FAXI ","M2N9FAYI ","M2N9FAZI ","M2N9FBFXI","M2N9FBFYI","M2N9FBFZI","M2N9FBXI ","M2N9FBYI ","M2N9FBZI ", & - "M2N9FDXI ","M2N9FDYI ","M2N9FDZI ","M2N9FIXI ","M2N9FIYI ","M2N9FIZI ","M2N9FMGXI","M2N9FMGYI","M2N9FMGZI","M2N9MBFXI", & - "M2N9MBFYI","M2N9MBFZI","M2N9MBXI ","M2N9MBYI ","M2N9MBZI ","M2N9STAXI","M2N9STAYI","M2N9STAZI","M2N9STVXI","M2N9STVYI", & - "M2N9STVZI","M2N9VXI ","M2N9VYI ","M2N9VZI ","M3N1AXI ","M3N1AYI ","M3N1AZI ","M3N1DYNP ","M3N1FAFXI","M3N1FAFYI", & - "M3N1FAFZI","M3N1FAGXI","M3N1FAGYI","M3N1FAGZI","M3N1FAMXI","M3N1FAMYI","M3N1FAMZI","M3N1FAXI ","M3N1FAYI ","M3N1FAZI ", & - "M3N1FBFXI","M3N1FBFYI","M3N1FBFZI","M3N1FBXI ","M3N1FBYI ","M3N1FBZI ","M3N1FDXI ","M3N1FDYI ","M3N1FDZI ","M3N1FIXI ", & - "M3N1FIYI ","M3N1FIZI ","M3N1FMGXI","M3N1FMGYI","M3N1FMGZI","M3N1MBFXI","M3N1MBFYI","M3N1MBFZI","M3N1MBXI ","M3N1MBYI ", & - "M3N1MBZI ","M3N1STAXI","M3N1STAYI","M3N1STAZI","M3N1STVXI","M3N1STVYI","M3N1STVZI","M3N1VXI ","M3N1VYI ","M3N1VZI ", & - "M3N2AXI ","M3N2AYI ","M3N2AZI ","M3N2DYNP ","M3N2FAFXI","M3N2FAFYI","M3N2FAFZI","M3N2FAGXI","M3N2FAGYI","M3N2FAGZI", & - "M3N2FAMXI","M3N2FAMYI","M3N2FAMZI","M3N2FAXI ","M3N2FAYI ","M3N2FAZI ","M3N2FBFXI","M3N2FBFYI","M3N2FBFZI","M3N2FBXI ", & - "M3N2FBYI ","M3N2FBZI ","M3N2FDXI ","M3N2FDYI ","M3N2FDZI ","M3N2FIXI ","M3N2FIYI ","M3N2FIZI ","M3N2FMGXI","M3N2FMGYI", & - "M3N2FMGZI","M3N2MBFXI","M3N2MBFYI","M3N2MBFZI","M3N2MBXI ","M3N2MBYI ","M3N2MBZI ","M3N2STAXI","M3N2STAYI","M3N2STAZI", & - "M3N2STVXI","M3N2STVYI","M3N2STVZI","M3N2VXI ","M3N2VYI ","M3N2VZI ","M3N3AXI ","M3N3AYI ","M3N3AZI ","M3N3DYNP ", & - "M3N3FAFXI","M3N3FAFYI","M3N3FAFZI","M3N3FAGXI","M3N3FAGYI","M3N3FAGZI","M3N3FAMXI","M3N3FAMYI","M3N3FAMZI","M3N3FAXI ", & - "M3N3FAYI ","M3N3FAZI ","M3N3FBFXI","M3N3FBFYI","M3N3FBFZI","M3N3FBXI ","M3N3FBYI ","M3N3FBZI ","M3N3FDXI ","M3N3FDYI ", & - "M3N3FDZI ","M3N3FIXI ","M3N3FIYI ","M3N3FIZI ","M3N3FMGXI","M3N3FMGYI","M3N3FMGZI","M3N3MBFXI","M3N3MBFYI","M3N3MBFZI", & - "M3N3MBXI ","M3N3MBYI ","M3N3MBZI ","M3N3STAXI","M3N3STAYI","M3N3STAZI","M3N3STVXI","M3N3STVYI","M3N3STVZI","M3N3VXI ", & - "M3N3VYI ","M3N3VZI ","M3N4AXI ","M3N4AYI ","M3N4AZI ","M3N4DYNP ","M3N4FAFXI","M3N4FAFYI","M3N4FAFZI","M3N4FAGXI", & - "M3N4FAGYI","M3N4FAGZI","M3N4FAMXI","M3N4FAMYI","M3N4FAMZI","M3N4FAXI ","M3N4FAYI ","M3N4FAZI ","M3N4FBFXI","M3N4FBFYI", & - "M3N4FBFZI","M3N4FBXI ","M3N4FBYI ","M3N4FBZI ","M3N4FDXI ","M3N4FDYI ","M3N4FDZI ","M3N4FIXI ","M3N4FIYI ","M3N4FIZI ", & - "M3N4FMGXI","M3N4FMGYI","M3N4FMGZI","M3N4MBFXI","M3N4MBFYI","M3N4MBFZI","M3N4MBXI ","M3N4MBYI ","M3N4MBZI ","M3N4STAXI", & - "M3N4STAYI","M3N4STAZI","M3N4STVXI","M3N4STVYI","M3N4STVZI","M3N4VXI ","M3N4VYI ","M3N4VZI ","M3N5AXI ","M3N5AYI ", & - "M3N5AZI ","M3N5DYNP ","M3N5FAFXI","M3N5FAFYI","M3N5FAFZI","M3N5FAGXI","M3N5FAGYI","M3N5FAGZI","M3N5FAMXI","M3N5FAMYI", & - "M3N5FAMZI","M3N5FAXI ","M3N5FAYI ","M3N5FAZI ","M3N5FBFXI","M3N5FBFYI","M3N5FBFZI","M3N5FBXI ","M3N5FBYI ","M3N5FBZI ", & - "M3N5FDXI ","M3N5FDYI ","M3N5FDZI ","M3N5FIXI ","M3N5FIYI ","M3N5FIZI ","M3N5FMGXI","M3N5FMGYI","M3N5FMGZI","M3N5MBFXI", & - "M3N5MBFYI","M3N5MBFZI","M3N5MBXI ","M3N5MBYI ","M3N5MBZI ","M3N5STAXI","M3N5STAYI","M3N5STAZI","M3N5STVXI","M3N5STVYI", & - "M3N5STVZI","M3N5VXI ","M3N5VYI ","M3N5VZI ","M3N6AXI ","M3N6AYI ","M3N6AZI ","M3N6DYNP ","M3N6FAFXI","M3N6FAFYI", & - "M3N6FAFZI","M3N6FAGXI","M3N6FAGYI","M3N6FAGZI","M3N6FAMXI","M3N6FAMYI","M3N6FAMZI","M3N6FAXI ","M3N6FAYI ","M3N6FAZI ", & - "M3N6FBFXI","M3N6FBFYI","M3N6FBFZI","M3N6FBXI ","M3N6FBYI ","M3N6FBZI ","M3N6FDXI ","M3N6FDYI ","M3N6FDZI ","M3N6FIXI ", & - "M3N6FIYI ","M3N6FIZI ","M3N6FMGXI","M3N6FMGYI","M3N6FMGZI","M3N6MBFXI","M3N6MBFYI","M3N6MBFZI","M3N6MBXI ","M3N6MBYI ", & - "M3N6MBZI ","M3N6STAXI","M3N6STAYI","M3N6STAZI","M3N6STVXI","M3N6STVYI","M3N6STVZI","M3N6VXI ","M3N6VYI ","M3N6VZI ", & - "M3N7AXI ","M3N7AYI ","M3N7AZI ","M3N7DYNP ","M3N7FAFXI","M3N7FAFYI","M3N7FAFZI","M3N7FAGXI","M3N7FAGYI","M3N7FAGZI", & - "M3N7FAMXI","M3N7FAMYI","M3N7FAMZI","M3N7FAXI ","M3N7FAYI ","M3N7FAZI ","M3N7FBFXI","M3N7FBFYI","M3N7FBFZI","M3N7FBXI ", & - "M3N7FBYI ","M3N7FBZI ","M3N7FDXI ","M3N7FDYI ","M3N7FDZI ","M3N7FIXI ","M3N7FIYI ","M3N7FIZI ","M3N7FMGXI","M3N7FMGYI", & - "M3N7FMGZI","M3N7MBFXI","M3N7MBFYI","M3N7MBFZI","M3N7MBXI ","M3N7MBYI ","M3N7MBZI ","M3N7STAXI","M3N7STAYI","M3N7STAZI", & - "M3N7STVXI","M3N7STVYI","M3N7STVZI","M3N7VXI ","M3N7VYI ","M3N7VZI ","M3N8AXI ","M3N8AYI ","M3N8AZI ","M3N8DYNP ", & - "M3N8FAFXI","M3N8FAFYI","M3N8FAFZI","M3N8FAGXI","M3N8FAGYI","M3N8FAGZI","M3N8FAMXI","M3N8FAMYI","M3N8FAMZI","M3N8FAXI ", & - "M3N8FAYI ","M3N8FAZI ","M3N8FBFXI","M3N8FBFYI","M3N8FBFZI","M3N8FBXI ","M3N8FBYI ","M3N8FBZI ","M3N8FDXI ","M3N8FDYI ", & - "M3N8FDZI ","M3N8FIXI ","M3N8FIYI ","M3N8FIZI ","M3N8FMGXI","M3N8FMGYI","M3N8FMGZI","M3N8MBFXI","M3N8MBFYI","M3N8MBFZI", & - "M3N8MBXI ","M3N8MBYI ","M3N8MBZI ","M3N8STAXI","M3N8STAYI","M3N8STAZI","M3N8STVXI","M3N8STVYI","M3N8STVZI","M3N8VXI ", & - "M3N8VYI ","M3N8VZI ","M3N9AXI ","M3N9AYI ","M3N9AZI ","M3N9DYNP ","M3N9FAFXI","M3N9FAFYI","M3N9FAFZI","M3N9FAGXI", & - "M3N9FAGYI","M3N9FAGZI","M3N9FAMXI","M3N9FAMYI","M3N9FAMZI","M3N9FAXI ","M3N9FAYI ","M3N9FAZI ","M3N9FBFXI","M3N9FBFYI", & - "M3N9FBFZI","M3N9FBXI ","M3N9FBYI ","M3N9FBZI ","M3N9FDXI ","M3N9FDYI ","M3N9FDZI ","M3N9FIXI ","M3N9FIYI ","M3N9FIZI ", & - "M3N9FMGXI","M3N9FMGYI","M3N9FMGZI","M3N9MBFXI","M3N9MBFYI","M3N9MBFZI","M3N9MBXI ","M3N9MBYI ","M3N9MBZI ","M3N9STAXI", & - "M3N9STAYI","M3N9STAZI","M3N9STVXI","M3N9STVYI","M3N9STVZI","M3N9VXI ","M3N9VYI ","M3N9VZI ","M4N1AXI ","M4N1AYI ", & - "M4N1AZI ","M4N1DYNP ","M4N1FAFXI","M4N1FAFYI","M4N1FAFZI","M4N1FAGXI","M4N1FAGYI","M4N1FAGZI","M4N1FAMXI","M4N1FAMYI", & - "M4N1FAMZI","M4N1FAXI ","M4N1FAYI ","M4N1FAZI ","M4N1FBFXI","M4N1FBFYI","M4N1FBFZI","M4N1FBXI ","M4N1FBYI ","M4N1FBZI ", & - "M4N1FDXI ","M4N1FDYI ","M4N1FDZI ","M4N1FIXI ","M4N1FIYI ","M4N1FIZI ","M4N1FMGXI","M4N1FMGYI","M4N1FMGZI","M4N1MBFXI", & - "M4N1MBFYI","M4N1MBFZI","M4N1MBXI ","M4N1MBYI ","M4N1MBZI ","M4N1STAXI","M4N1STAYI","M4N1STAZI","M4N1STVXI","M4N1STVYI", & - "M4N1STVZI","M4N1VXI ","M4N1VYI ","M4N1VZI ","M4N2AXI ","M4N2AYI ","M4N2AZI ","M4N2DYNP ","M4N2FAFXI","M4N2FAFYI", & - "M4N2FAFZI","M4N2FAGXI","M4N2FAGYI","M4N2FAGZI","M4N2FAMXI","M4N2FAMYI","M4N2FAMZI","M4N2FAXI ","M4N2FAYI ","M4N2FAZI ", & - "M4N2FBFXI","M4N2FBFYI","M4N2FBFZI","M4N2FBXI ","M4N2FBYI ","M4N2FBZI ","M4N2FDXI ","M4N2FDYI ","M4N2FDZI ","M4N2FIXI ", & - "M4N2FIYI ","M4N2FIZI ","M4N2FMGXI","M4N2FMGYI","M4N2FMGZI","M4N2MBFXI","M4N2MBFYI","M4N2MBFZI","M4N2MBXI ","M4N2MBYI ", & - "M4N2MBZI ","M4N2STAXI","M4N2STAYI","M4N2STAZI","M4N2STVXI","M4N2STVYI","M4N2STVZI","M4N2VXI ","M4N2VYI ","M4N2VZI ", & - "M4N3AXI ","M4N3AYI ","M4N3AZI ","M4N3DYNP ","M4N3FAFXI","M4N3FAFYI","M4N3FAFZI","M4N3FAGXI","M4N3FAGYI","M4N3FAGZI", & - "M4N3FAMXI","M4N3FAMYI","M4N3FAMZI","M4N3FAXI ","M4N3FAYI ","M4N3FAZI ","M4N3FBFXI","M4N3FBFYI","M4N3FBFZI","M4N3FBXI ", & - "M4N3FBYI ","M4N3FBZI ","M4N3FDXI ","M4N3FDYI ","M4N3FDZI ","M4N3FIXI ","M4N3FIYI ","M4N3FIZI ","M4N3FMGXI","M4N3FMGYI", & - "M4N3FMGZI","M4N3MBFXI","M4N3MBFYI","M4N3MBFZI","M4N3MBXI ","M4N3MBYI ","M4N3MBZI ","M4N3STAXI","M4N3STAYI","M4N3STAZI", & - "M4N3STVXI","M4N3STVYI","M4N3STVZI","M4N3VXI ","M4N3VYI ","M4N3VZI ","M4N4AXI ","M4N4AYI ","M4N4AZI ","M4N4DYNP ", & - "M4N4FAFXI","M4N4FAFYI","M4N4FAFZI","M4N4FAGXI","M4N4FAGYI","M4N4FAGZI","M4N4FAMXI","M4N4FAMYI","M4N4FAMZI","M4N4FAXI ", & - "M4N4FAYI ","M4N4FAZI ","M4N4FBFXI","M4N4FBFYI","M4N4FBFZI","M4N4FBXI ","M4N4FBYI ","M4N4FBZI ","M4N4FDXI ","M4N4FDYI ", & - "M4N4FDZI ","M4N4FIXI ","M4N4FIYI ","M4N4FIZI ","M4N4FMGXI","M4N4FMGYI","M4N4FMGZI","M4N4MBFXI","M4N4MBFYI","M4N4MBFZI", & - "M4N4MBXI ","M4N4MBYI ","M4N4MBZI ","M4N4STAXI","M4N4STAYI","M4N4STAZI","M4N4STVXI","M4N4STVYI","M4N4STVZI","M4N4VXI ", & - "M4N4VYI ","M4N4VZI ","M4N5AXI ","M4N5AYI ","M4N5AZI ","M4N5DYNP ","M4N5FAFXI","M4N5FAFYI","M4N5FAFZI","M4N5FAGXI", & - "M4N5FAGYI","M4N5FAGZI","M4N5FAMXI","M4N5FAMYI","M4N5FAMZI","M4N5FAXI ","M4N5FAYI ","M4N5FAZI ","M4N5FBFXI","M4N5FBFYI", & - "M4N5FBFZI","M4N5FBXI ","M4N5FBYI ","M4N5FBZI ","M4N5FDXI ","M4N5FDYI ","M4N5FDZI ","M4N5FIXI ","M4N5FIYI ","M4N5FIZI ", & - "M4N5FMGXI","M4N5FMGYI","M4N5FMGZI","M4N5MBFXI","M4N5MBFYI","M4N5MBFZI","M4N5MBXI ","M4N5MBYI ","M4N5MBZI ","M4N5STAXI", & - "M4N5STAYI","M4N5STAZI","M4N5STVXI","M4N5STVYI","M4N5STVZI","M4N5VXI ","M4N5VYI ","M4N5VZI ","M4N6AXI ","M4N6AYI ", & - "M4N6AZI ","M4N6DYNP ","M4N6FAFXI","M4N6FAFYI","M4N6FAFZI","M4N6FAGXI","M4N6FAGYI","M4N6FAGZI","M4N6FAMXI","M4N6FAMYI", & - "M4N6FAMZI","M4N6FAXI ","M4N6FAYI ","M4N6FAZI ","M4N6FBFXI","M4N6FBFYI","M4N6FBFZI","M4N6FBXI ","M4N6FBYI ","M4N6FBZI ", & - "M4N6FDXI ","M4N6FDYI ","M4N6FDZI ","M4N6FIXI ","M4N6FIYI ","M4N6FIZI ","M4N6FMGXI","M4N6FMGYI","M4N6FMGZI","M4N6MBFXI", & - "M4N6MBFYI","M4N6MBFZI","M4N6MBXI ","M4N6MBYI ","M4N6MBZI ","M4N6STAXI","M4N6STAYI","M4N6STAZI","M4N6STVXI","M4N6STVYI", & - "M4N6STVZI","M4N6VXI ","M4N6VYI ","M4N6VZI ","M4N7AXI ","M4N7AYI ","M4N7AZI ","M4N7DYNP ","M4N7FAFXI","M4N7FAFYI", & - "M4N7FAFZI","M4N7FAGXI","M4N7FAGYI","M4N7FAGZI","M4N7FAMXI","M4N7FAMYI","M4N7FAMZI","M4N7FAXI ","M4N7FAYI ","M4N7FAZI ", & - "M4N7FBFXI","M4N7FBFYI","M4N7FBFZI","M4N7FBXI ","M4N7FBYI ","M4N7FBZI ","M4N7FDXI ","M4N7FDYI ","M4N7FDZI ","M4N7FIXI ", & - "M4N7FIYI ","M4N7FIZI ","M4N7FMGXI","M4N7FMGYI","M4N7FMGZI","M4N7MBFXI","M4N7MBFYI","M4N7MBFZI","M4N7MBXI ","M4N7MBYI ", & - "M4N7MBZI ","M4N7STAXI","M4N7STAYI","M4N7STAZI","M4N7STVXI","M4N7STVYI","M4N7STVZI","M4N7VXI ","M4N7VYI ","M4N7VZI ", & - "M4N8AXI ","M4N8AYI ","M4N8AZI ","M4N8DYNP ","M4N8FAFXI","M4N8FAFYI","M4N8FAFZI","M4N8FAGXI","M4N8FAGYI","M4N8FAGZI", & - "M4N8FAMXI","M4N8FAMYI","M4N8FAMZI","M4N8FAXI ","M4N8FAYI ","M4N8FAZI ","M4N8FBFXI","M4N8FBFYI","M4N8FBFZI","M4N8FBXI ", & - "M4N8FBYI ","M4N8FBZI ","M4N8FDXI ","M4N8FDYI ","M4N8FDZI ","M4N8FIXI ","M4N8FIYI ","M4N8FIZI ","M4N8FMGXI","M4N8FMGYI", & - "M4N8FMGZI","M4N8MBFXI","M4N8MBFYI","M4N8MBFZI","M4N8MBXI ","M4N8MBYI ","M4N8MBZI ","M4N8STAXI","M4N8STAYI","M4N8STAZI", & - "M4N8STVXI","M4N8STVYI","M4N8STVZI","M4N8VXI ","M4N8VYI ","M4N8VZI ","M4N9AXI ","M4N9AYI ","M4N9AZI ","M4N9DYNP ", & - "M4N9FAFXI","M4N9FAFYI","M4N9FAFZI","M4N9FAGXI","M4N9FAGYI","M4N9FAGZI","M4N9FAMXI","M4N9FAMYI","M4N9FAMZI","M4N9FAXI ", & - "M4N9FAYI ","M4N9FAZI ","M4N9FBFXI","M4N9FBFYI","M4N9FBFZI","M4N9FBXI ","M4N9FBYI ","M4N9FBZI ","M4N9FDXI ","M4N9FDYI ", & - "M4N9FDZI ","M4N9FIXI ","M4N9FIYI ","M4N9FIZI ","M4N9FMGXI","M4N9FMGYI","M4N9FMGZI","M4N9MBFXI","M4N9MBFYI","M4N9MBFZI", & - "M4N9MBXI ","M4N9MBYI ","M4N9MBZI ","M4N9STAXI","M4N9STAYI","M4N9STAZI","M4N9STVXI","M4N9STVYI","M4N9STVZI","M4N9VXI ", & - "M4N9VYI ","M4N9VZI ","M5N1AXI ","M5N1AYI ","M5N1AZI ","M5N1DYNP ","M5N1FAFXI","M5N1FAFYI","M5N1FAFZI","M5N1FAGXI", & - "M5N1FAGYI","M5N1FAGZI","M5N1FAMXI","M5N1FAMYI","M5N1FAMZI","M5N1FAXI ","M5N1FAYI ","M5N1FAZI ","M5N1FBFXI","M5N1FBFYI", & - "M5N1FBFZI","M5N1FBXI ","M5N1FBYI ","M5N1FBZI ","M5N1FDXI ","M5N1FDYI ","M5N1FDZI ","M5N1FIXI ","M5N1FIYI ","M5N1FIZI ", & - "M5N1FMGXI","M5N1FMGYI","M5N1FMGZI","M5N1MBFXI","M5N1MBFYI","M5N1MBFZI","M5N1MBXI ","M5N1MBYI ","M5N1MBZI ","M5N1STAXI", & - "M5N1STAYI","M5N1STAZI","M5N1STVXI","M5N1STVYI","M5N1STVZI","M5N1VXI ","M5N1VYI ","M5N1VZI ","M5N2AXI ","M5N2AYI ", & - "M5N2AZI ","M5N2DYNP ","M5N2FAFXI","M5N2FAFYI","M5N2FAFZI","M5N2FAGXI","M5N2FAGYI","M5N2FAGZI","M5N2FAMXI","M5N2FAMYI", & - "M5N2FAMZI","M5N2FAXI ","M5N2FAYI ","M5N2FAZI ","M5N2FBFXI","M5N2FBFYI","M5N2FBFZI","M5N2FBXI ","M5N2FBYI ","M5N2FBZI ", & - "M5N2FDXI ","M5N2FDYI ","M5N2FDZI ","M5N2FIXI ","M5N2FIYI ","M5N2FIZI ","M5N2FMGXI","M5N2FMGYI","M5N2FMGZI","M5N2MBFXI", & - "M5N2MBFYI","M5N2MBFZI","M5N2MBXI ","M5N2MBYI ","M5N2MBZI ","M5N2STAXI","M5N2STAYI","M5N2STAZI","M5N2STVXI","M5N2STVYI", & - "M5N2STVZI","M5N2VXI ","M5N2VYI ","M5N2VZI ","M5N3AXI ","M5N3AYI ","M5N3AZI ","M5N3DYNP ","M5N3FAFXI","M5N3FAFYI", & - "M5N3FAFZI","M5N3FAGXI","M5N3FAGYI","M5N3FAGZI","M5N3FAMXI","M5N3FAMYI","M5N3FAMZI","M5N3FAXI ","M5N3FAYI ","M5N3FAZI ", & - "M5N3FBFXI","M5N3FBFYI","M5N3FBFZI","M5N3FBXI ","M5N3FBYI ","M5N3FBZI ","M5N3FDXI ","M5N3FDYI ","M5N3FDZI ","M5N3FIXI ", & - "M5N3FIYI ","M5N3FIZI ","M5N3FMGXI","M5N3FMGYI","M5N3FMGZI","M5N3MBFXI","M5N3MBFYI","M5N3MBFZI","M5N3MBXI ","M5N3MBYI ", & - "M5N3MBZI ","M5N3STAXI","M5N3STAYI","M5N3STAZI","M5N3STVXI","M5N3STVYI","M5N3STVZI","M5N3VXI ","M5N3VYI ","M5N3VZI ", & - "M5N4AXI ","M5N4AYI ","M5N4AZI ","M5N4DYNP ","M5N4FAFXI","M5N4FAFYI","M5N4FAFZI","M5N4FAGXI","M5N4FAGYI","M5N4FAGZI", & - "M5N4FAMXI","M5N4FAMYI","M5N4FAMZI","M5N4FAXI ","M5N4FAYI ","M5N4FAZI ","M5N4FBFXI","M5N4FBFYI","M5N4FBFZI","M5N4FBXI ", & - "M5N4FBYI ","M5N4FBZI ","M5N4FDXI ","M5N4FDYI ","M5N4FDZI ","M5N4FIXI ","M5N4FIYI ","M5N4FIZI ","M5N4FMGXI","M5N4FMGYI", & - "M5N4FMGZI","M5N4MBFXI","M5N4MBFYI","M5N4MBFZI","M5N4MBXI ","M5N4MBYI ","M5N4MBZI ","M5N4STAXI","M5N4STAYI","M5N4STAZI", & - "M5N4STVXI","M5N4STVYI","M5N4STVZI","M5N4VXI ","M5N4VYI ","M5N4VZI ","M5N5AXI ","M5N5AYI ","M5N5AZI ","M5N5DYNP ", & - "M5N5FAFXI","M5N5FAFYI","M5N5FAFZI","M5N5FAGXI","M5N5FAGYI","M5N5FAGZI","M5N5FAMXI","M5N5FAMYI","M5N5FAMZI","M5N5FAXI ", & - "M5N5FAYI ","M5N5FAZI ","M5N5FBFXI","M5N5FBFYI","M5N5FBFZI","M5N5FBXI ","M5N5FBYI ","M5N5FBZI ","M5N5FDXI ","M5N5FDYI ", & - "M5N5FDZI ","M5N5FIXI ","M5N5FIYI ","M5N5FIZI ","M5N5FMGXI","M5N5FMGYI","M5N5FMGZI","M5N5MBFXI","M5N5MBFYI","M5N5MBFZI", & - "M5N5MBXI ","M5N5MBYI ","M5N5MBZI ","M5N5STAXI","M5N5STAYI","M5N5STAZI","M5N5STVXI","M5N5STVYI","M5N5STVZI","M5N5VXI ", & - "M5N5VYI ","M5N5VZI ","M5N6AXI ","M5N6AYI ","M5N6AZI ","M5N6DYNP ","M5N6FAFXI","M5N6FAFYI","M5N6FAFZI","M5N6FAGXI", & - "M5N6FAGYI","M5N6FAGZI","M5N6FAMXI","M5N6FAMYI","M5N6FAMZI","M5N6FAXI ","M5N6FAYI ","M5N6FAZI ","M5N6FBFXI","M5N6FBFYI", & - "M5N6FBFZI","M5N6FBXI ","M5N6FBYI ","M5N6FBZI ","M5N6FDXI ","M5N6FDYI ","M5N6FDZI ","M5N6FIXI ","M5N6FIYI ","M5N6FIZI ", & - "M5N6FMGXI","M5N6FMGYI","M5N6FMGZI","M5N6MBFXI","M5N6MBFYI","M5N6MBFZI","M5N6MBXI ","M5N6MBYI ","M5N6MBZI ","M5N6STAXI", & - "M5N6STAYI","M5N6STAZI","M5N6STVXI","M5N6STVYI","M5N6STVZI","M5N6VXI ","M5N6VYI ","M5N6VZI ","M5N7AXI ","M5N7AYI ", & - "M5N7AZI ","M5N7DYNP ","M5N7FAFXI","M5N7FAFYI","M5N7FAFZI","M5N7FAGXI","M5N7FAGYI","M5N7FAGZI","M5N7FAMXI","M5N7FAMYI", & - "M5N7FAMZI","M5N7FAXI ","M5N7FAYI ","M5N7FAZI ","M5N7FBFXI","M5N7FBFYI","M5N7FBFZI","M5N7FBXI ","M5N7FBYI ","M5N7FBZI ", & - "M5N7FDXI ","M5N7FDYI ","M5N7FDZI ","M5N7FIXI ","M5N7FIYI ","M5N7FIZI ","M5N7FMGXI","M5N7FMGYI","M5N7FMGZI","M5N7MBFXI", & - "M5N7MBFYI","M5N7MBFZI","M5N7MBXI ","M5N7MBYI ","M5N7MBZI ","M5N7STAXI","M5N7STAYI","M5N7STAZI","M5N7STVXI","M5N7STVYI", & - "M5N7STVZI","M5N7VXI ","M5N7VYI ","M5N7VZI ","M5N8AXI ","M5N8AYI ","M5N8AZI ","M5N8DYNP ","M5N8FAFXI","M5N8FAFYI", & - "M5N8FAFZI","M5N8FAGXI","M5N8FAGYI","M5N8FAGZI","M5N8FAMXI","M5N8FAMYI","M5N8FAMZI","M5N8FAXI ","M5N8FAYI ","M5N8FAZI ", & - "M5N8FBFXI","M5N8FBFYI","M5N8FBFZI","M5N8FBXI ","M5N8FBYI ","M5N8FBZI ","M5N8FDXI ","M5N8FDYI ","M5N8FDZI ","M5N8FIXI ", & - "M5N8FIYI ","M5N8FIZI ","M5N8FMGXI","M5N8FMGYI","M5N8FMGZI","M5N8MBFXI","M5N8MBFYI","M5N8MBFZI","M5N8MBXI ","M5N8MBYI ", & - "M5N8MBZI ","M5N8STAXI","M5N8STAYI","M5N8STAZI","M5N8STVXI","M5N8STVYI","M5N8STVZI","M5N8VXI ","M5N8VYI ","M5N8VZI ", & - "M5N9AXI ","M5N9AYI ","M5N9AZI ","M5N9DYNP ","M5N9FAFXI","M5N9FAFYI","M5N9FAFZI","M5N9FAGXI","M5N9FAGYI","M5N9FAGZI", & - "M5N9FAMXI","M5N9FAMYI","M5N9FAMZI","M5N9FAXI ","M5N9FAYI ","M5N9FAZI ","M5N9FBFXI","M5N9FBFYI","M5N9FBFZI","M5N9FBXI ", & - "M5N9FBYI ","M5N9FBZI ","M5N9FDXI ","M5N9FDYI ","M5N9FDZI ","M5N9FIXI ","M5N9FIYI ","M5N9FIZI ","M5N9FMGXI","M5N9FMGYI", & - "M5N9FMGZI","M5N9MBFXI","M5N9MBFYI","M5N9MBFZI","M5N9MBXI ","M5N9MBYI ","M5N9MBZI ","M5N9STAXI","M5N9STAYI","M5N9STAZI", & - "M5N9STVXI","M5N9STVYI","M5N9STVZI","M5N9VXI ","M5N9VYI ","M5N9VZI ","M6N1AXI ","M6N1AYI ","M6N1AZI ","M6N1DYNP ", & - "M6N1FAFXI","M6N1FAFYI","M6N1FAFZI","M6N1FAGXI","M6N1FAGYI","M6N1FAGZI","M6N1FAMXI","M6N1FAMYI","M6N1FAMZI","M6N1FAXI ", & - "M6N1FAYI ","M6N1FAZI ","M6N1FBFXI","M6N1FBFYI","M6N1FBFZI","M6N1FBXI ","M6N1FBYI ","M6N1FBZI ","M6N1FDXI ","M6N1FDYI ", & - "M6N1FDZI ","M6N1FIXI ","M6N1FIYI ","M6N1FIZI ","M6N1FMGXI","M6N1FMGYI","M6N1FMGZI","M6N1MBFXI","M6N1MBFYI","M6N1MBFZI", & - "M6N1MBXI ","M6N1MBYI ","M6N1MBZI ","M6N1STAXI","M6N1STAYI","M6N1STAZI","M6N1STVXI","M6N1STVYI","M6N1STVZI","M6N1VXI ", & - "M6N1VYI ","M6N1VZI ","M6N2AXI ","M6N2AYI ","M6N2AZI ","M6N2DYNP ","M6N2FAFXI","M6N2FAFYI","M6N2FAFZI","M6N2FAGXI", & - "M6N2FAGYI","M6N2FAGZI","M6N2FAMXI","M6N2FAMYI","M6N2FAMZI","M6N2FAXI ","M6N2FAYI ","M6N2FAZI ","M6N2FBFXI","M6N2FBFYI", & - "M6N2FBFZI","M6N2FBXI ","M6N2FBYI ","M6N2FBZI ","M6N2FDXI ","M6N2FDYI ","M6N2FDZI ","M6N2FIXI ","M6N2FIYI ","M6N2FIZI ", & - "M6N2FMGXI","M6N2FMGYI","M6N2FMGZI","M6N2MBFXI","M6N2MBFYI","M6N2MBFZI","M6N2MBXI ","M6N2MBYI ","M6N2MBZI ","M6N2STAXI", & - "M6N2STAYI","M6N2STAZI","M6N2STVXI","M6N2STVYI","M6N2STVZI","M6N2VXI ","M6N2VYI ","M6N2VZI ","M6N3AXI ","M6N3AYI ", & - "M6N3AZI ","M6N3DYNP ","M6N3FAFXI","M6N3FAFYI","M6N3FAFZI","M6N3FAGXI","M6N3FAGYI","M6N3FAGZI","M6N3FAMXI","M6N3FAMYI", & - "M6N3FAMZI","M6N3FAXI ","M6N3FAYI ","M6N3FAZI ","M6N3FBFXI","M6N3FBFYI","M6N3FBFZI","M6N3FBXI ","M6N3FBYI ","M6N3FBZI ", & - "M6N3FDXI ","M6N3FDYI ","M6N3FDZI ","M6N3FIXI ","M6N3FIYI ","M6N3FIZI ","M6N3FMGXI","M6N3FMGYI","M6N3FMGZI","M6N3MBFXI", & - "M6N3MBFYI","M6N3MBFZI","M6N3MBXI ","M6N3MBYI ","M6N3MBZI ","M6N3STAXI","M6N3STAYI","M6N3STAZI","M6N3STVXI","M6N3STVYI", & - "M6N3STVZI","M6N3VXI ","M6N3VYI ","M6N3VZI ","M6N4AXI ","M6N4AYI ","M6N4AZI ","M6N4DYNP ","M6N4FAFXI","M6N4FAFYI", & - "M6N4FAFZI","M6N4FAGXI","M6N4FAGYI","M6N4FAGZI","M6N4FAMXI","M6N4FAMYI","M6N4FAMZI","M6N4FAXI ","M6N4FAYI ","M6N4FAZI ", & - "M6N4FBFXI","M6N4FBFYI","M6N4FBFZI","M6N4FBXI ","M6N4FBYI ","M6N4FBZI ","M6N4FDXI ","M6N4FDYI ","M6N4FDZI ","M6N4FIXI ", & - "M6N4FIYI ","M6N4FIZI ","M6N4FMGXI","M6N4FMGYI","M6N4FMGZI","M6N4MBFXI","M6N4MBFYI","M6N4MBFZI","M6N4MBXI ","M6N4MBYI ", & - "M6N4MBZI ","M6N4STAXI","M6N4STAYI","M6N4STAZI","M6N4STVXI","M6N4STVYI","M6N4STVZI","M6N4VXI ","M6N4VYI ","M6N4VZI ", & - "M6N5AXI ","M6N5AYI ","M6N5AZI ","M6N5DYNP ","M6N5FAFXI","M6N5FAFYI","M6N5FAFZI","M6N5FAGXI","M6N5FAGYI","M6N5FAGZI", & - "M6N5FAMXI","M6N5FAMYI","M6N5FAMZI","M6N5FAXI ","M6N5FAYI ","M6N5FAZI ","M6N5FBFXI","M6N5FBFYI","M6N5FBFZI","M6N5FBXI ", & - "M6N5FBYI ","M6N5FBZI ","M6N5FDXI ","M6N5FDYI ","M6N5FDZI ","M6N5FIXI ","M6N5FIYI ","M6N5FIZI ","M6N5FMGXI","M6N5FMGYI", & - "M6N5FMGZI","M6N5MBFXI","M6N5MBFYI","M6N5MBFZI","M6N5MBXI ","M6N5MBYI ","M6N5MBZI ","M6N5STAXI","M6N5STAYI","M6N5STAZI", & - "M6N5STVXI","M6N5STVYI","M6N5STVZI","M6N5VXI ","M6N5VYI ","M6N5VZI ","M6N6AXI ","M6N6AYI ","M6N6AZI ","M6N6DYNP ", & - "M6N6FAFXI","M6N6FAFYI","M6N6FAFZI","M6N6FAGXI","M6N6FAGYI","M6N6FAGZI","M6N6FAMXI","M6N6FAMYI","M6N6FAMZI","M6N6FAXI ", & - "M6N6FAYI ","M6N6FAZI ","M6N6FBFXI","M6N6FBFYI","M6N6FBFZI","M6N6FBXI ","M6N6FBYI ","M6N6FBZI ","M6N6FDXI ","M6N6FDYI ", & - "M6N6FDZI ","M6N6FIXI ","M6N6FIYI ","M6N6FIZI ","M6N6FMGXI","M6N6FMGYI","M6N6FMGZI","M6N6MBFXI","M6N6MBFYI","M6N6MBFZI", & - "M6N6MBXI ","M6N6MBYI ","M6N6MBZI ","M6N6STAXI","M6N6STAYI","M6N6STAZI","M6N6STVXI","M6N6STVYI","M6N6STVZI","M6N6VXI ", & - "M6N6VYI ","M6N6VZI ","M6N7AXI ","M6N7AYI ","M6N7AZI ","M6N7DYNP ","M6N7FAFXI","M6N7FAFYI","M6N7FAFZI","M6N7FAGXI", & - "M6N7FAGYI","M6N7FAGZI","M6N7FAMXI","M6N7FAMYI","M6N7FAMZI","M6N7FAXI ","M6N7FAYI ","M6N7FAZI ","M6N7FBFXI","M6N7FBFYI", & - "M6N7FBFZI","M6N7FBXI ","M6N7FBYI ","M6N7FBZI ","M6N7FDXI ","M6N7FDYI ","M6N7FDZI ","M6N7FIXI ","M6N7FIYI ","M6N7FIZI ", & - "M6N7FMGXI","M6N7FMGYI","M6N7FMGZI","M6N7MBFXI","M6N7MBFYI","M6N7MBFZI","M6N7MBXI ","M6N7MBYI ","M6N7MBZI ","M6N7STAXI", & - "M6N7STAYI","M6N7STAZI","M6N7STVXI","M6N7STVYI","M6N7STVZI","M6N7VXI ","M6N7VYI ","M6N7VZI ","M6N8AXI ","M6N8AYI ", & - "M6N8AZI ","M6N8DYNP ","M6N8FAFXI","M6N8FAFYI","M6N8FAFZI","M6N8FAGXI","M6N8FAGYI","M6N8FAGZI","M6N8FAMXI","M6N8FAMYI", & - "M6N8FAMZI","M6N8FAXI ","M6N8FAYI ","M6N8FAZI ","M6N8FBFXI","M6N8FBFYI","M6N8FBFZI","M6N8FBXI ","M6N8FBYI ","M6N8FBZI ", & - "M6N8FDXI ","M6N8FDYI ","M6N8FDZI ","M6N8FIXI ","M6N8FIYI ","M6N8FIZI ","M6N8FMGXI","M6N8FMGYI","M6N8FMGZI","M6N8MBFXI", & - "M6N8MBFYI","M6N8MBFZI","M6N8MBXI ","M6N8MBYI ","M6N8MBZI ","M6N8STAXI","M6N8STAYI","M6N8STAZI","M6N8STVXI","M6N8STVYI", & - "M6N8STVZI","M6N8VXI ","M6N8VYI ","M6N8VZI ","M6N9AXI ","M6N9AYI ","M6N9AZI ","M6N9DYNP ","M6N9FAFXI","M6N9FAFYI", & - "M6N9FAFZI","M6N9FAGXI","M6N9FAGYI","M6N9FAGZI","M6N9FAMXI","M6N9FAMYI","M6N9FAMZI","M6N9FAXI ","M6N9FAYI ","M6N9FAZI ", & - "M6N9FBFXI","M6N9FBFYI","M6N9FBFZI","M6N9FBXI ","M6N9FBYI ","M6N9FBZI ","M6N9FDXI ","M6N9FDYI ","M6N9FDZI ","M6N9FIXI ", & - "M6N9FIYI ","M6N9FIZI ","M6N9FMGXI","M6N9FMGYI","M6N9FMGZI","M6N9MBFXI","M6N9MBFYI","M6N9MBFZI","M6N9MBXI ","M6N9MBYI ", & - "M6N9MBZI ","M6N9STAXI","M6N9STAYI","M6N9STAZI","M6N9STVXI","M6N9STVYI","M6N9STVZI","M6N9VXI ","M6N9VYI ","M6N9VZI ", & - "M7N1AXI ","M7N1AYI ","M7N1AZI ","M7N1DYNP ","M7N1FAFXI","M7N1FAFYI","M7N1FAFZI","M7N1FAGXI","M7N1FAGYI","M7N1FAGZI", & - "M7N1FAMXI","M7N1FAMYI","M7N1FAMZI","M7N1FAXI ","M7N1FAYI ","M7N1FAZI ","M7N1FBFXI","M7N1FBFYI","M7N1FBFZI","M7N1FBXI ", & - "M7N1FBYI ","M7N1FBZI ","M7N1FDXI ","M7N1FDYI ","M7N1FDZI ","M7N1FIXI ","M7N1FIYI ","M7N1FIZI ","M7N1FMGXI","M7N1FMGYI", & - "M7N1FMGZI","M7N1MBFXI","M7N1MBFYI","M7N1MBFZI","M7N1MBXI ","M7N1MBYI ","M7N1MBZI ","M7N1STAXI","M7N1STAYI","M7N1STAZI", & - "M7N1STVXI","M7N1STVYI","M7N1STVZI","M7N1VXI ","M7N1VYI ","M7N1VZI ","M7N2AXI ","M7N2AYI ","M7N2AZI ","M7N2DYNP ", & - "M7N2FAFXI","M7N2FAFYI","M7N2FAFZI","M7N2FAGXI","M7N2FAGYI","M7N2FAGZI","M7N2FAMXI","M7N2FAMYI","M7N2FAMZI","M7N2FAXI ", & - "M7N2FAYI ","M7N2FAZI ","M7N2FBFXI","M7N2FBFYI","M7N2FBFZI","M7N2FBXI ","M7N2FBYI ","M7N2FBZI ","M7N2FDXI ","M7N2FDYI ", & - "M7N2FDZI ","M7N2FIXI ","M7N2FIYI ","M7N2FIZI ","M7N2FMGXI","M7N2FMGYI","M7N2FMGZI","M7N2MBFXI","M7N2MBFYI","M7N2MBFZI", & - "M7N2MBXI ","M7N2MBYI ","M7N2MBZI ","M7N2STAXI","M7N2STAYI","M7N2STAZI","M7N2STVXI","M7N2STVYI","M7N2STVZI","M7N2VXI ", & - "M7N2VYI ","M7N2VZI ","M7N3AXI ","M7N3AYI ","M7N3AZI ","M7N3DYNP ","M7N3FAFXI","M7N3FAFYI","M7N3FAFZI","M7N3FAGXI", & - "M7N3FAGYI","M7N3FAGZI","M7N3FAMXI","M7N3FAMYI","M7N3FAMZI","M7N3FAXI ","M7N3FAYI ","M7N3FAZI ","M7N3FBFXI","M7N3FBFYI", & - "M7N3FBFZI","M7N3FBXI ","M7N3FBYI ","M7N3FBZI ","M7N3FDXI ","M7N3FDYI ","M7N3FDZI ","M7N3FIXI ","M7N3FIYI ","M7N3FIZI ", & - "M7N3FMGXI","M7N3FMGYI","M7N3FMGZI","M7N3MBFXI","M7N3MBFYI","M7N3MBFZI","M7N3MBXI ","M7N3MBYI ","M7N3MBZI ","M7N3STAXI", & - "M7N3STAYI","M7N3STAZI","M7N3STVXI","M7N3STVYI","M7N3STVZI","M7N3VXI ","M7N3VYI ","M7N3VZI ","M7N4AXI ","M7N4AYI ", & - "M7N4AZI ","M7N4DYNP ","M7N4FAFXI","M7N4FAFYI","M7N4FAFZI","M7N4FAGXI","M7N4FAGYI","M7N4FAGZI","M7N4FAMXI","M7N4FAMYI", & - "M7N4FAMZI","M7N4FAXI ","M7N4FAYI ","M7N4FAZI ","M7N4FBFXI","M7N4FBFYI","M7N4FBFZI","M7N4FBXI ","M7N4FBYI ","M7N4FBZI ", & - "M7N4FDXI ","M7N4FDYI ","M7N4FDZI ","M7N4FIXI ","M7N4FIYI ","M7N4FIZI ","M7N4FMGXI","M7N4FMGYI","M7N4FMGZI","M7N4MBFXI", & - "M7N4MBFYI","M7N4MBFZI","M7N4MBXI ","M7N4MBYI ","M7N4MBZI ","M7N4STAXI","M7N4STAYI","M7N4STAZI","M7N4STVXI","M7N4STVYI", & - "M7N4STVZI","M7N4VXI ","M7N4VYI ","M7N4VZI ","M7N5AXI ","M7N5AYI ","M7N5AZI ","M7N5DYNP ","M7N5FAFXI","M7N5FAFYI", & - "M7N5FAFZI","M7N5FAGXI","M7N5FAGYI","M7N5FAGZI","M7N5FAMXI","M7N5FAMYI","M7N5FAMZI","M7N5FAXI ","M7N5FAYI ","M7N5FAZI ", & - "M7N5FBFXI","M7N5FBFYI","M7N5FBFZI","M7N5FBXI ","M7N5FBYI ","M7N5FBZI ","M7N5FDXI ","M7N5FDYI ","M7N5FDZI ","M7N5FIXI ", & - "M7N5FIYI ","M7N5FIZI ","M7N5FMGXI","M7N5FMGYI","M7N5FMGZI","M7N5MBFXI","M7N5MBFYI","M7N5MBFZI","M7N5MBXI ","M7N5MBYI ", & - "M7N5MBZI ","M7N5STAXI","M7N5STAYI","M7N5STAZI","M7N5STVXI","M7N5STVYI","M7N5STVZI","M7N5VXI ","M7N5VYI ","M7N5VZI ", & - "M7N6AXI ","M7N6AYI ","M7N6AZI ","M7N6DYNP ","M7N6FAFXI","M7N6FAFYI","M7N6FAFZI","M7N6FAGXI","M7N6FAGYI","M7N6FAGZI", & - "M7N6FAMXI","M7N6FAMYI","M7N6FAMZI","M7N6FAXI ","M7N6FAYI ","M7N6FAZI ","M7N6FBFXI","M7N6FBFYI","M7N6FBFZI","M7N6FBXI ", & - "M7N6FBYI ","M7N6FBZI ","M7N6FDXI ","M7N6FDYI ","M7N6FDZI ","M7N6FIXI ","M7N6FIYI ","M7N6FIZI ","M7N6FMGXI","M7N6FMGYI", & - "M7N6FMGZI","M7N6MBFXI","M7N6MBFYI","M7N6MBFZI","M7N6MBXI ","M7N6MBYI ","M7N6MBZI ","M7N6STAXI","M7N6STAYI","M7N6STAZI", & - "M7N6STVXI","M7N6STVYI","M7N6STVZI","M7N6VXI ","M7N6VYI ","M7N6VZI ","M7N7AXI ","M7N7AYI ","M7N7AZI ","M7N7DYNP ", & - "M7N7FAFXI","M7N7FAFYI","M7N7FAFZI","M7N7FAGXI","M7N7FAGYI","M7N7FAGZI","M7N7FAMXI","M7N7FAMYI","M7N7FAMZI","M7N7FAXI ", & - "M7N7FAYI ","M7N7FAZI ","M7N7FBFXI","M7N7FBFYI","M7N7FBFZI","M7N7FBXI ","M7N7FBYI ","M7N7FBZI ","M7N7FDXI ","M7N7FDYI ", & - "M7N7FDZI ","M7N7FIXI ","M7N7FIYI ","M7N7FIZI ","M7N7FMGXI","M7N7FMGYI","M7N7FMGZI","M7N7MBFXI","M7N7MBFYI","M7N7MBFZI", & - "M7N7MBXI ","M7N7MBYI ","M7N7MBZI ","M7N7STAXI","M7N7STAYI","M7N7STAZI","M7N7STVXI","M7N7STVYI","M7N7STVZI","M7N7VXI ", & - "M7N7VYI ","M7N7VZI ","M7N8AXI ","M7N8AYI ","M7N8AZI ","M7N8DYNP ","M7N8FAFXI","M7N8FAFYI","M7N8FAFZI","M7N8FAGXI", & - "M7N8FAGYI","M7N8FAGZI","M7N8FAMXI","M7N8FAMYI","M7N8FAMZI","M7N8FAXI ","M7N8FAYI ","M7N8FAZI ","M7N8FBFXI","M7N8FBFYI", & - "M7N8FBFZI","M7N8FBXI ","M7N8FBYI ","M7N8FBZI ","M7N8FDXI ","M7N8FDYI ","M7N8FDZI ","M7N8FIXI ","M7N8FIYI ","M7N8FIZI ", & - "M7N8FMGXI","M7N8FMGYI","M7N8FMGZI","M7N8MBFXI","M7N8MBFYI","M7N8MBFZI","M7N8MBXI ","M7N8MBYI ","M7N8MBZI ","M7N8STAXI", & - "M7N8STAYI","M7N8STAZI","M7N8STVXI","M7N8STVYI","M7N8STVZI","M7N8VXI ","M7N8VYI ","M7N8VZI ","M7N9AXI ","M7N9AYI ", & - "M7N9AZI ","M7N9DYNP ","M7N9FAFXI","M7N9FAFYI","M7N9FAFZI","M7N9FAGXI","M7N9FAGYI","M7N9FAGZI","M7N9FAMXI","M7N9FAMYI", & - "M7N9FAMZI","M7N9FAXI ","M7N9FAYI ","M7N9FAZI ","M7N9FBFXI","M7N9FBFYI","M7N9FBFZI","M7N9FBXI ","M7N9FBYI ","M7N9FBZI ", & - "M7N9FDXI ","M7N9FDYI ","M7N9FDZI ","M7N9FIXI ","M7N9FIYI ","M7N9FIZI ","M7N9FMGXI","M7N9FMGYI","M7N9FMGZI","M7N9MBFXI", & - "M7N9MBFYI","M7N9MBFZI","M7N9MBXI ","M7N9MBYI ","M7N9MBZI ","M7N9STAXI","M7N9STAYI","M7N9STAZI","M7N9STVXI","M7N9STVYI", & - "M7N9STVZI","M7N9VXI ","M7N9VYI ","M7N9VZI ","M8N1AXI ","M8N1AYI ","M8N1AZI ","M8N1DYNP ","M8N1FAFXI","M8N1FAFYI", & - "M8N1FAFZI","M8N1FAGXI","M8N1FAGYI","M8N1FAGZI","M8N1FAMXI","M8N1FAMYI","M8N1FAMZI","M8N1FAXI ","M8N1FAYI ","M8N1FAZI ", & - "M8N1FBFXI","M8N1FBFYI","M8N1FBFZI","M8N1FBXI ","M8N1FBYI ","M8N1FBZI ","M8N1FDXI ","M8N1FDYI ","M8N1FDZI ","M8N1FIXI ", & - "M8N1FIYI ","M8N1FIZI ","M8N1FMGXI","M8N1FMGYI","M8N1FMGZI","M8N1MBFXI","M8N1MBFYI","M8N1MBFZI","M8N1MBXI ","M8N1MBYI ", & - "M8N1MBZI ","M8N1STAXI","M8N1STAYI","M8N1STAZI","M8N1STVXI","M8N1STVYI","M8N1STVZI","M8N1VXI ","M8N1VYI ","M8N1VZI ", & - "M8N2AXI ","M8N2AYI ","M8N2AZI ","M8N2DYNP ","M8N2FAFXI","M8N2FAFYI","M8N2FAFZI","M8N2FAGXI","M8N2FAGYI","M8N2FAGZI", & - "M8N2FAMXI","M8N2FAMYI","M8N2FAMZI","M8N2FAXI ","M8N2FAYI ","M8N2FAZI ","M8N2FBFXI","M8N2FBFYI","M8N2FBFZI","M8N2FBXI ", & - "M8N2FBYI ","M8N2FBZI ","M8N2FDXI ","M8N2FDYI ","M8N2FDZI ","M8N2FIXI ","M8N2FIYI ","M8N2FIZI ","M8N2FMGXI","M8N2FMGYI", & - "M8N2FMGZI","M8N2MBFXI","M8N2MBFYI","M8N2MBFZI","M8N2MBXI ","M8N2MBYI ","M8N2MBZI ","M8N2STAXI","M8N2STAYI","M8N2STAZI", & - "M8N2STVXI","M8N2STVYI","M8N2STVZI","M8N2VXI ","M8N2VYI ","M8N2VZI ","M8N3AXI ","M8N3AYI ","M8N3AZI ","M8N3DYNP ", & - "M8N3FAFXI","M8N3FAFYI","M8N3FAFZI","M8N3FAGXI","M8N3FAGYI","M8N3FAGZI","M8N3FAMXI","M8N3FAMYI","M8N3FAMZI","M8N3FAXI ", & - "M8N3FAYI ","M8N3FAZI ","M8N3FBFXI","M8N3FBFYI","M8N3FBFZI","M8N3FBXI ","M8N3FBYI ","M8N3FBZI ","M8N3FDXI ","M8N3FDYI ", & - "M8N3FDZI ","M8N3FIXI ","M8N3FIYI ","M8N3FIZI ","M8N3FMGXI","M8N3FMGYI","M8N3FMGZI","M8N3MBFXI","M8N3MBFYI","M8N3MBFZI", & - "M8N3MBXI ","M8N3MBYI ","M8N3MBZI ","M8N3STAXI","M8N3STAYI","M8N3STAZI","M8N3STVXI","M8N3STVYI","M8N3STVZI","M8N3VXI ", & - "M8N3VYI ","M8N3VZI ","M8N4AXI ","M8N4AYI ","M8N4AZI ","M8N4DYNP ","M8N4FAFXI","M8N4FAFYI","M8N4FAFZI","M8N4FAGXI", & - "M8N4FAGYI","M8N4FAGZI","M8N4FAMXI","M8N4FAMYI","M8N4FAMZI","M8N4FAXI ","M8N4FAYI ","M8N4FAZI ","M8N4FBFXI","M8N4FBFYI", & - "M8N4FBFZI","M8N4FBXI ","M8N4FBYI ","M8N4FBZI ","M8N4FDXI ","M8N4FDYI ","M8N4FDZI ","M8N4FIXI ","M8N4FIYI ","M8N4FIZI ", & - "M8N4FMGXI","M8N4FMGYI","M8N4FMGZI","M8N4MBFXI","M8N4MBFYI","M8N4MBFZI","M8N4MBXI ","M8N4MBYI ","M8N4MBZI ","M8N4STAXI", & - "M8N4STAYI","M8N4STAZI","M8N4STVXI","M8N4STVYI","M8N4STVZI","M8N4VXI ","M8N4VYI ","M8N4VZI ","M8N5AXI ","M8N5AYI ", & - "M8N5AZI ","M8N5DYNP ","M8N5FAFXI","M8N5FAFYI","M8N5FAFZI","M8N5FAGXI","M8N5FAGYI","M8N5FAGZI","M8N5FAMXI","M8N5FAMYI", & - "M8N5FAMZI","M8N5FAXI ","M8N5FAYI ","M8N5FAZI ","M8N5FBFXI","M8N5FBFYI","M8N5FBFZI","M8N5FBXI ","M8N5FBYI ","M8N5FBZI ", & - "M8N5FDXI ","M8N5FDYI ","M8N5FDZI ","M8N5FIXI ","M8N5FIYI ","M8N5FIZI ","M8N5FMGXI","M8N5FMGYI","M8N5FMGZI","M8N5MBFXI", & - "M8N5MBFYI","M8N5MBFZI","M8N5MBXI ","M8N5MBYI ","M8N5MBZI ","M8N5STAXI","M8N5STAYI","M8N5STAZI","M8N5STVXI","M8N5STVYI", & - "M8N5STVZI","M8N5VXI ","M8N5VYI ","M8N5VZI ","M8N6AXI ","M8N6AYI ","M8N6AZI ","M8N6DYNP ","M8N6FAFXI","M8N6FAFYI", & - "M8N6FAFZI","M8N6FAGXI","M8N6FAGYI","M8N6FAGZI","M8N6FAMXI","M8N6FAMYI","M8N6FAMZI","M8N6FAXI ","M8N6FAYI ","M8N6FAZI ", & - "M8N6FBFXI","M8N6FBFYI","M8N6FBFZI","M8N6FBXI ","M8N6FBYI ","M8N6FBZI ","M8N6FDXI ","M8N6FDYI ","M8N6FDZI ","M8N6FIXI ", & - "M8N6FIYI ","M8N6FIZI ","M8N6FMGXI","M8N6FMGYI","M8N6FMGZI","M8N6MBFXI","M8N6MBFYI","M8N6MBFZI","M8N6MBXI ","M8N6MBYI ", & - "M8N6MBZI ","M8N6STAXI","M8N6STAYI","M8N6STAZI","M8N6STVXI","M8N6STVYI","M8N6STVZI","M8N6VXI ","M8N6VYI ","M8N6VZI ", & - "M8N7AXI ","M8N7AYI ","M8N7AZI ","M8N7DYNP ","M8N7FAFXI","M8N7FAFYI","M8N7FAFZI","M8N7FAGXI","M8N7FAGYI","M8N7FAGZI", & - "M8N7FAMXI","M8N7FAMYI","M8N7FAMZI","M8N7FAXI ","M8N7FAYI ","M8N7FAZI ","M8N7FBFXI","M8N7FBFYI","M8N7FBFZI","M8N7FBXI ", & - "M8N7FBYI ","M8N7FBZI ","M8N7FDXI ","M8N7FDYI ","M8N7FDZI ","M8N7FIXI ","M8N7FIYI ","M8N7FIZI ","M8N7FMGXI","M8N7FMGYI", & - "M8N7FMGZI","M8N7MBFXI","M8N7MBFYI","M8N7MBFZI","M8N7MBXI ","M8N7MBYI ","M8N7MBZI ","M8N7STAXI","M8N7STAYI","M8N7STAZI", & - "M8N7STVXI","M8N7STVYI","M8N7STVZI","M8N7VXI ","M8N7VYI ","M8N7VZI ","M8N8AXI ","M8N8AYI ","M8N8AZI ","M8N8DYNP ", & - "M8N8FAFXI","M8N8FAFYI","M8N8FAFZI","M8N8FAGXI","M8N8FAGYI","M8N8FAGZI","M8N8FAMXI","M8N8FAMYI","M8N8FAMZI","M8N8FAXI ", & - "M8N8FAYI ","M8N8FAZI ","M8N8FBFXI","M8N8FBFYI","M8N8FBFZI","M8N8FBXI ","M8N8FBYI ","M8N8FBZI ","M8N8FDXI ","M8N8FDYI ", & - "M8N8FDZI ","M8N8FIXI ","M8N8FIYI ","M8N8FIZI ","M8N8FMGXI","M8N8FMGYI","M8N8FMGZI","M8N8MBFXI","M8N8MBFYI","M8N8MBFZI", & - "M8N8MBXI ","M8N8MBYI ","M8N8MBZI ","M8N8STAXI","M8N8STAYI","M8N8STAZI","M8N8STVXI","M8N8STVYI","M8N8STVZI","M8N8VXI ", & - "M8N8VYI ","M8N8VZI ","M8N9AXI ","M8N9AYI ","M8N9AZI ","M8N9DYNP ","M8N9FAFXI","M8N9FAFYI","M8N9FAFZI","M8N9FAGXI", & - "M8N9FAGYI","M8N9FAGZI","M8N9FAMXI","M8N9FAMYI","M8N9FAMZI","M8N9FAXI ","M8N9FAYI ","M8N9FAZI ","M8N9FBFXI","M8N9FBFYI", & - "M8N9FBFZI","M8N9FBXI ","M8N9FBYI ","M8N9FBZI ","M8N9FDXI ","M8N9FDYI ","M8N9FDZI ","M8N9FIXI ","M8N9FIYI ","M8N9FIZI ", & - "M8N9FMGXI","M8N9FMGYI","M8N9FMGZI","M8N9MBFXI","M8N9MBFYI","M8N9MBFZI","M8N9MBXI ","M8N9MBYI ","M8N9MBZI ","M8N9STAXI", & - "M8N9STAYI","M8N9STAZI","M8N9STVXI","M8N9STVYI","M8N9STVZI","M8N9VXI ","M8N9VYI ","M8N9VZI ","M9N1AXI ","M9N1AYI ", & - "M9N1AZI ","M9N1DYNP ","M9N1FAFXI","M9N1FAFYI","M9N1FAFZI","M9N1FAGXI","M9N1FAGYI","M9N1FAGZI","M9N1FAMXI","M9N1FAMYI", & - "M9N1FAMZI","M9N1FAXI ","M9N1FAYI ","M9N1FAZI ","M9N1FBFXI","M9N1FBFYI","M9N1FBFZI","M9N1FBXI ","M9N1FBYI ","M9N1FBZI ", & - "M9N1FDXI ","M9N1FDYI ","M9N1FDZI ","M9N1FIXI ","M9N1FIYI ","M9N1FIZI ","M9N1FMGXI","M9N1FMGYI","M9N1FMGZI","M9N1MBFXI", & - "M9N1MBFYI","M9N1MBFZI","M9N1MBXI ","M9N1MBYI ","M9N1MBZI ","M9N1STAXI","M9N1STAYI","M9N1STAZI","M9N1STVXI","M9N1STVYI", & - "M9N1STVZI","M9N1VXI ","M9N1VYI ","M9N1VZI ","M9N2AXI ","M9N2AYI ","M9N2AZI ","M9N2DYNP ","M9N2FAFXI","M9N2FAFYI", & - "M9N2FAFZI","M9N2FAGXI","M9N2FAGYI","M9N2FAGZI","M9N2FAMXI","M9N2FAMYI","M9N2FAMZI","M9N2FAXI ","M9N2FAYI ","M9N2FAZI ", & - "M9N2FBFXI","M9N2FBFYI","M9N2FBFZI","M9N2FBXI ","M9N2FBYI ","M9N2FBZI ","M9N2FDXI ","M9N2FDYI ","M9N2FDZI ","M9N2FIXI ", & - "M9N2FIYI ","M9N2FIZI ","M9N2FMGXI","M9N2FMGYI","M9N2FMGZI","M9N2MBFXI","M9N2MBFYI","M9N2MBFZI","M9N2MBXI ","M9N2MBYI ", & - "M9N2MBZI ","M9N2STAXI","M9N2STAYI","M9N2STAZI","M9N2STVXI","M9N2STVYI","M9N2STVZI","M9N2VXI ","M9N2VYI ","M9N2VZI ", & - "M9N3AXI ","M9N3AYI ","M9N3AZI ","M9N3DYNP ","M9N3FAFXI","M9N3FAFYI","M9N3FAFZI","M9N3FAGXI","M9N3FAGYI","M9N3FAGZI", & - "M9N3FAMXI","M9N3FAMYI","M9N3FAMZI","M9N3FAXI ","M9N3FAYI ","M9N3FAZI ","M9N3FBFXI","M9N3FBFYI","M9N3FBFZI","M9N3FBXI ", & - "M9N3FBYI ","M9N3FBZI ","M9N3FDXI ","M9N3FDYI ","M9N3FDZI ","M9N3FIXI ","M9N3FIYI ","M9N3FIZI ","M9N3FMGXI","M9N3FMGYI", & - "M9N3FMGZI","M9N3MBFXI","M9N3MBFYI","M9N3MBFZI","M9N3MBXI ","M9N3MBYI ","M9N3MBZI ","M9N3STAXI","M9N3STAYI","M9N3STAZI", & - "M9N3STVXI","M9N3STVYI","M9N3STVZI","M9N3VXI ","M9N3VYI ","M9N3VZI ","M9N4AXI ","M9N4AYI ","M9N4AZI ","M9N4DYNP ", & - "M9N4FAFXI","M9N4FAFYI","M9N4FAFZI","M9N4FAGXI","M9N4FAGYI","M9N4FAGZI","M9N4FAMXI","M9N4FAMYI","M9N4FAMZI","M9N4FAXI ", & - "M9N4FAYI ","M9N4FAZI ","M9N4FBFXI","M9N4FBFYI","M9N4FBFZI","M9N4FBXI ","M9N4FBYI ","M9N4FBZI ","M9N4FDXI ","M9N4FDYI ", & - "M9N4FDZI ","M9N4FIXI ","M9N4FIYI ","M9N4FIZI ","M9N4FMGXI","M9N4FMGYI","M9N4FMGZI","M9N4MBFXI","M9N4MBFYI","M9N4MBFZI", & - "M9N4MBXI ","M9N4MBYI ","M9N4MBZI ","M9N4STAXI","M9N4STAYI","M9N4STAZI","M9N4STVXI","M9N4STVYI","M9N4STVZI","M9N4VXI ", & - "M9N4VYI ","M9N4VZI ","M9N5AXI ","M9N5AYI ","M9N5AZI ","M9N5DYNP ","M9N5FAFXI","M9N5FAFYI","M9N5FAFZI","M9N5FAGXI", & - "M9N5FAGYI","M9N5FAGZI","M9N5FAMXI","M9N5FAMYI","M9N5FAMZI","M9N5FAXI ","M9N5FAYI ","M9N5FAZI ","M9N5FBFXI","M9N5FBFYI", & - "M9N5FBFZI","M9N5FBXI ","M9N5FBYI ","M9N5FBZI ","M9N5FDXI ","M9N5FDYI ","M9N5FDZI ","M9N5FIXI ","M9N5FIYI ","M9N5FIZI ", & - "M9N5FMGXI","M9N5FMGYI","M9N5FMGZI","M9N5MBFXI","M9N5MBFYI","M9N5MBFZI","M9N5MBXI ","M9N5MBYI ","M9N5MBZI ","M9N5STAXI", & - "M9N5STAYI","M9N5STAZI","M9N5STVXI","M9N5STVYI","M9N5STVZI","M9N5VXI ","M9N5VYI ","M9N5VZI ","M9N6AXI ","M9N6AYI ", & - "M9N6AZI ","M9N6DYNP ","M9N6FAFXI","M9N6FAFYI","M9N6FAFZI","M9N6FAGXI","M9N6FAGYI","M9N6FAGZI","M9N6FAMXI","M9N6FAMYI", & - "M9N6FAMZI","M9N6FAXI ","M9N6FAYI ","M9N6FAZI ","M9N6FBFXI","M9N6FBFYI","M9N6FBFZI","M9N6FBXI ","M9N6FBYI ","M9N6FBZI ", & - "M9N6FDXI ","M9N6FDYI ","M9N6FDZI ","M9N6FIXI ","M9N6FIYI ","M9N6FIZI ","M9N6FMGXI","M9N6FMGYI","M9N6FMGZI","M9N6MBFXI", & - "M9N6MBFYI","M9N6MBFZI","M9N6MBXI ","M9N6MBYI ","M9N6MBZI ","M9N6STAXI","M9N6STAYI","M9N6STAZI","M9N6STVXI","M9N6STVYI", & - "M9N6STVZI","M9N6VXI ","M9N6VYI ","M9N6VZI ","M9N7AXI ","M9N7AYI ","M9N7AZI ","M9N7DYNP ","M9N7FAFXI","M9N7FAFYI", & - "M9N7FAFZI","M9N7FAGXI","M9N7FAGYI","M9N7FAGZI","M9N7FAMXI","M9N7FAMYI","M9N7FAMZI","M9N7FAXI ","M9N7FAYI ","M9N7FAZI ", & - "M9N7FBFXI","M9N7FBFYI","M9N7FBFZI","M9N7FBXI ","M9N7FBYI ","M9N7FBZI ","M9N7FDXI ","M9N7FDYI ","M9N7FDZI ","M9N7FIXI ", & - "M9N7FIYI ","M9N7FIZI ","M9N7FMGXI","M9N7FMGYI","M9N7FMGZI","M9N7MBFXI","M9N7MBFYI","M9N7MBFZI","M9N7MBXI ","M9N7MBYI ", & - "M9N7MBZI ","M9N7STAXI","M9N7STAYI","M9N7STAZI","M9N7STVXI","M9N7STVYI","M9N7STVZI","M9N7VXI ","M9N7VYI ","M9N7VZI ", & - "M9N8AXI ","M9N8AYI ","M9N8AZI ","M9N8DYNP ","M9N8FAFXI","M9N8FAFYI","M9N8FAFZI","M9N8FAGXI","M9N8FAGYI","M9N8FAGZI", & - "M9N8FAMXI","M9N8FAMYI","M9N8FAMZI","M9N8FAXI ","M9N8FAYI ","M9N8FAZI ","M9N8FBFXI","M9N8FBFYI","M9N8FBFZI","M9N8FBXI ", & - "M9N8FBYI ","M9N8FBZI ","M9N8FDXI ","M9N8FDYI ","M9N8FDZI ","M9N8FIXI ","M9N8FIYI ","M9N8FIZI ","M9N8FMGXI","M9N8FMGYI", & - "M9N8FMGZI","M9N8MBFXI","M9N8MBFYI","M9N8MBFZI","M9N8MBXI ","M9N8MBYI ","M9N8MBZI ","M9N8STAXI","M9N8STAYI","M9N8STAZI", & - "M9N8STVXI","M9N8STVYI","M9N8STVZI","M9N8VXI ","M9N8VYI ","M9N8VZI ","M9N9AXI ","M9N9AYI ","M9N9AZI ","M9N9DYNP ", & - "M9N9FAFXI","M9N9FAFYI","M9N9FAFZI","M9N9FAGXI","M9N9FAGYI","M9N9FAGZI","M9N9FAMXI","M9N9FAMYI","M9N9FAMZI","M9N9FAXI ", & - "M9N9FAYI ","M9N9FAZI ","M9N9FBFXI","M9N9FBFYI","M9N9FBFZI","M9N9FBXI ","M9N9FBYI ","M9N9FBZI ","M9N9FDXI ","M9N9FDYI ", & - "M9N9FDZI ","M9N9FIXI ","M9N9FIYI ","M9N9FIZI ","M9N9FMGXI","M9N9FMGYI","M9N9FMGZI","M9N9MBFXI","M9N9MBFYI","M9N9MBFZI", & - "M9N9MBXI ","M9N9MBYI ","M9N9MBZI ","M9N9STAXI","M9N9STAYI","M9N9STAZI","M9N9STVXI","M9N9STVYI","M9N9STVZI","M9N9VXI ", & - "M9N9VYI ","M9N9VZI "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(4032) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - J1Axi , J1Ayi , J1Azi , J1DynP , J1FAMxi , J1FAMyi , J1FAMzi , J1FBFxi , J1FBFyi , J1FBFzi , & - J1FBxi , J1FByi , J1FBzi , J1FDxi , J1FDyi , J1FDzi , J1FIxi , J1FIyi , J1FIzi , J1MBFxi , & - J1MBFyi , J1MBFzi , J1MBxi , J1MByi , J1MBzi , J1STAxi , J1STAyi , J1STAzi , J1STVxi , J1STVyi , & - J1STVzi , J1Vxi , J1Vyi , J1Vzi , J2Axi , J2Ayi , J2Azi , J2DynP , J2FAMxi , J2FAMyi , & - J2FAMzi , J2FBFxi , J2FBFyi , J2FBFzi , J2FBxi , J2FByi , J2FBzi , J2FDxi , J2FDyi , J2FDzi , & - J2FIxi , J2FIyi , J2FIzi , J2MBFxi , J2MBFyi , J2MBFzi , J2MBxi , J2MByi , J2MBzi , J2STAxi , & - J2STAyi , J2STAzi , J2STVxi , J2STVyi , J2STVzi , J2Vxi , J2Vyi , J2Vzi , J3Axi , J3Ayi , & - J3Azi , J3DynP , J3FAMxi , J3FAMyi , J3FAMzi , J3FBFxi , J3FBFyi , J3FBFzi , J3FBxi , J3FByi , & - J3FBzi , J3FDxi , J3FDyi , J3FDzi , J3FIxi , J3FIyi , J3FIzi , J3MBFxi , J3MBFyi , J3MBFzi , & - J3MBxi , J3MByi , J3MBzi , J3STAxi , J3STAyi , J3STAzi , J3STVxi , J3STVyi , J3STVzi , J3Vxi , & - J3Vyi , J3Vzi , J4Axi , J4Ayi , J4Azi , J4DynP , J4FAMxi , J4FAMyi , J4FAMzi , J4FBFxi , & - J4FBFyi , J4FBFzi , J4FBxi , J4FByi , J4FBzi , J4FDxi , J4FDyi , J4FDzi , J4FIxi , J4FIyi , & - J4FIzi , J4MBFxi , J4MBFyi , J4MBFzi , J4MBxi , J4MByi , J4MBzi , J4STAxi , J4STAyi , J4STAzi , & - J4STVxi , J4STVyi , J4STVzi , J4Vxi , J4Vyi , J4Vzi , J5Axi , J5Ayi , J5Azi , J5DynP , & - J5FAMxi , J5FAMyi , J5FAMzi , J5FBFxi , J5FBFyi , J5FBFzi , J5FBxi , J5FByi , J5FBzi , J5FDxi , & - J5FDyi , J5FDzi , J5FIxi , J5FIyi , J5FIzi , J5MBFxi , J5MBFyi , J5MBFzi , J5MBxi , J5MByi , & - J5MBzi , J5STAxi , J5STAyi , J5STAzi , J5STVxi , J5STVyi , J5STVzi , J5Vxi , J5Vyi , J5Vzi , & - J6Axi , J6Ayi , J6Azi , J6DynP , J6FAMxi , J6FAMyi , J6FAMzi , J6FBFxi , J6FBFyi , J6FBFzi , & - J6FBxi , J6FByi , J6FBzi , J6FDxi , J6FDyi , J6FDzi , J6FIxi , J6FIyi , J6FIzi , J6MBFxi , & - J6MBFyi , J6MBFzi , J6MBxi , J6MByi , J6MBzi , J6STAxi , J6STAyi , J6STAzi , J6STVxi , J6STVyi , & - J6STVzi , J6Vxi , J6Vyi , J6Vzi , J7Axi , J7Ayi , J7Azi , J7DynP , J7FAMxi , J7FAMyi , & - J7FAMzi , J7FBFxi , J7FBFyi , J7FBFzi , J7FBxi , J7FByi , J7FBzi , J7FDxi , J7FDyi , J7FDzi , & - J7FIxi , J7FIyi , J7FIzi , J7MBFxi , J7MBFyi , J7MBFzi , J7MBxi , J7MByi , J7MBzi , J7STAxi , & - J7STAyi , J7STAzi , J7STVxi , J7STVyi , J7STVzi , J7Vxi , J7Vyi , J7Vzi , J8Axi , J8Ayi , & - J8Azi , J8DynP , J8FAMxi , J8FAMyi , J8FAMzi , J8FBFxi , J8FBFyi , J8FBFzi , J8FBxi , J8FByi , & - J8FBzi , J8FDxi , J8FDyi , J8FDzi , J8FIxi , J8FIyi , J8FIzi , J8MBFxi , J8MBFyi , J8MBFzi , & - J8MBxi , J8MByi , J8MBzi , J8STAxi , J8STAyi , J8STAzi , J8STVxi , J8STVyi , J8STVzi , J8Vxi , & - J8Vyi , J8Vzi , J9Axi , J9Ayi , J9Azi , J9DynP , J9FAMxi , J9FAMyi , J9FAMzi , J9FBFxi , & - J9FBFyi , J9FBFzi , J9FBxi , J9FByi , J9FBzi , J9FDxi , J9FDyi , J9FDzi , J9FIxi , J9FIyi , & - J9FIzi , J9MBFxi , J9MBFyi , J9MBFzi , J9MBxi , J9MByi , J9MBzi , J9STAxi , J9STAyi , J9STAzi , & - J9STVxi , J9STVyi , J9STVzi , J9Vxi , J9Vyi , J9Vzi , M1N1Axi , M1N1Ayi , M1N1Azi , M1N1DynP , & - M1N1FAFxi , M1N1FAFyi , M1N1FAFzi , M1N1FAGxi , M1N1FAGyi , M1N1FAGzi , M1N1FAMxi , M1N1FAMyi , M1N1FAMzi , M1N1FAxi , & - M1N1FAyi , M1N1FAzi , M1N1FBFxi , M1N1FBFyi , M1N1FBFzi , M1N1FBxi , M1N1FByi , M1N1FBzi , M1N1FDxi , M1N1FDyi , & - M1N1FDzi , M1N1FIxi , M1N1FIyi , M1N1FIzi , M1N1FMGxi , M1N1FMGyi , M1N1FMGzi , M1N1MBFxi , M1N1MBFyi , M1N1MBFzi , & - M1N1MBxi , M1N1MByi , M1N1MBzi , M1N1STAxi , M1N1STAyi , M1N1STAzi , M1N1STVxi , M1N1STVyi , M1N1STVzi , M1N1Vxi , & - M1N1Vyi , M1N1Vzi , M1N2Axi , M1N2Ayi , M1N2Azi , M1N2DynP , M1N2FAFxi , M1N2FAFyi , M1N2FAFzi , M1N2FAGxi , & - M1N2FAGyi , M1N2FAGzi , M1N2FAMxi , M1N2FAMyi , M1N2FAMzi , M1N2FAxi , M1N2FAyi , M1N2FAzi , M1N2FBFxi , M1N2FBFyi , & - M1N2FBFzi , M1N2FBxi , M1N2FByi , M1N2FBzi , M1N2FDxi , M1N2FDyi , M1N2FDzi , M1N2FIxi , M1N2FIyi , M1N2FIzi , & - M1N2FMGxi , M1N2FMGyi , M1N2FMGzi , M1N2MBFxi , M1N2MBFyi , M1N2MBFzi , M1N2MBxi , M1N2MByi , M1N2MBzi , M1N2STAxi , & - M1N2STAyi , M1N2STAzi , M1N2STVxi , M1N2STVyi , M1N2STVzi , M1N2Vxi , M1N2Vyi , M1N2Vzi , M1N3Axi , M1N3Ayi , & - M1N3Azi , M1N3DynP , M1N3FAFxi , M1N3FAFyi , M1N3FAFzi , M1N3FAGxi , M1N3FAGyi , M1N3FAGzi , M1N3FAMxi , M1N3FAMyi , & - M1N3FAMzi , M1N3FAxi , M1N3FAyi , M1N3FAzi , M1N3FBFxi , M1N3FBFyi , M1N3FBFzi , M1N3FBxi , M1N3FByi , M1N3FBzi , & - M1N3FDxi , M1N3FDyi , M1N3FDzi , M1N3FIxi , M1N3FIyi , M1N3FIzi , M1N3FMGxi , M1N3FMGyi , M1N3FMGzi , M1N3MBFxi , & - M1N3MBFyi , M1N3MBFzi , M1N3MBxi , M1N3MByi , M1N3MBzi , M1N3STAxi , M1N3STAyi , M1N3STAzi , M1N3STVxi , M1N3STVyi , & - M1N3STVzi , M1N3Vxi , M1N3Vyi , M1N3Vzi , M1N4Axi , M1N4Ayi , M1N4Azi , M1N4DynP , M1N4FAFxi , M1N4FAFyi , & - M1N4FAFzi , M1N4FAGxi , M1N4FAGyi , M1N4FAGzi , M1N4FAMxi , M1N4FAMyi , M1N4FAMzi , M1N4FAxi , M1N4FAyi , M1N4FAzi , & - M1N4FBFxi , M1N4FBFyi , M1N4FBFzi , M1N4FBxi , M1N4FByi , M1N4FBzi , M1N4FDxi , M1N4FDyi , M1N4FDzi , M1N4FIxi , & - M1N4FIyi , M1N4FIzi , M1N4FMGxi , M1N4FMGyi , M1N4FMGzi , M1N4MBFxi , M1N4MBFyi , M1N4MBFzi , M1N4MBxi , M1N4MByi , & - M1N4MBzi , M1N4STAxi , M1N4STAyi , M1N4STAzi , M1N4STVxi , M1N4STVyi , M1N4STVzi , M1N4Vxi , M1N4Vyi , M1N4Vzi , & - M1N5Axi , M1N5Ayi , M1N5Azi , M1N5DynP , M1N5FAFxi , M1N5FAFyi , M1N5FAFzi , M1N5FAGxi , M1N5FAGyi , M1N5FAGzi , & - M1N5FAMxi , M1N5FAMyi , M1N5FAMzi , M1N5FAxi , M1N5FAyi , M1N5FAzi , M1N5FBFxi , M1N5FBFyi , M1N5FBFzi , M1N5FBxi , & - M1N5FByi , M1N5FBzi , M1N5FDxi , M1N5FDyi , M1N5FDzi , M1N5FIxi , M1N5FIyi , M1N5FIzi , M1N5FMGxi , M1N5FMGyi , & - M1N5FMGzi , M1N5MBFxi , M1N5MBFyi , M1N5MBFzi , M1N5MBxi , M1N5MByi , M1N5MBzi , M1N5STAxi , M1N5STAyi , M1N5STAzi , & - M1N5STVxi , M1N5STVyi , M1N5STVzi , M1N5Vxi , M1N5Vyi , M1N5Vzi , M1N6Axi , M1N6Ayi , M1N6Azi , M1N6DynP , & - M1N6FAFxi , M1N6FAFyi , M1N6FAFzi , M1N6FAGxi , M1N6FAGyi , M1N6FAGzi , M1N6FAMxi , M1N6FAMyi , M1N6FAMzi , M1N6FAxi , & - M1N6FAyi , M1N6FAzi , M1N6FBFxi , M1N6FBFyi , M1N6FBFzi , M1N6FBxi , M1N6FByi , M1N6FBzi , M1N6FDxi , M1N6FDyi , & - M1N6FDzi , M1N6FIxi , M1N6FIyi , M1N6FIzi , M1N6FMGxi , M1N6FMGyi , M1N6FMGzi , M1N6MBFxi , M1N6MBFyi , M1N6MBFzi , & - M1N6MBxi , M1N6MByi , M1N6MBzi , M1N6STAxi , M1N6STAyi , M1N6STAzi , M1N6STVxi , M1N6STVyi , M1N6STVzi , M1N6Vxi , & - M1N6Vyi , M1N6Vzi , M1N7Axi , M1N7Ayi , M1N7Azi , M1N7DynP , M1N7FAFxi , M1N7FAFyi , M1N7FAFzi , M1N7FAGxi , & - M1N7FAGyi , M1N7FAGzi , M1N7FAMxi , M1N7FAMyi , M1N7FAMzi , M1N7FAxi , M1N7FAyi , M1N7FAzi , M1N7FBFxi , M1N7FBFyi , & - M1N7FBFzi , M1N7FBxi , M1N7FByi , M1N7FBzi , M1N7FDxi , M1N7FDyi , M1N7FDzi , M1N7FIxi , M1N7FIyi , M1N7FIzi , & - M1N7FMGxi , M1N7FMGyi , M1N7FMGzi , M1N7MBFxi , M1N7MBFyi , M1N7MBFzi , M1N7MBxi , M1N7MByi , M1N7MBzi , M1N7STAxi , & - M1N7STAyi , M1N7STAzi , M1N7STVxi , M1N7STVyi , M1N7STVzi , M1N7Vxi , M1N7Vyi , M1N7Vzi , M1N8Axi , M1N8Ayi , & - M1N8Azi , M1N8DynP , M1N8FAFxi , M1N8FAFyi , M1N8FAFzi , M1N8FAGxi , M1N8FAGyi , M1N8FAGzi , M1N8FAMxi , M1N8FAMyi , & - M1N8FAMzi , M1N8FAxi , M1N8FAyi , M1N8FAzi , M1N8FBFxi , M1N8FBFyi , M1N8FBFzi , M1N8FBxi , M1N8FByi , M1N8FBzi , & - M1N8FDxi , M1N8FDyi , M1N8FDzi , M1N8FIxi , M1N8FIyi , M1N8FIzi , M1N8FMGxi , M1N8FMGyi , M1N8FMGzi , M1N8MBFxi , & - M1N8MBFyi , M1N8MBFzi , M1N8MBxi , M1N8MByi , M1N8MBzi , M1N8STAxi , M1N8STAyi , M1N8STAzi , M1N8STVxi , M1N8STVyi , & - M1N8STVzi , M1N8Vxi , M1N8Vyi , M1N8Vzi , M1N9Axi , M1N9Ayi , M1N9Azi , M1N9DynP , M1N9FAFxi , M1N9FAFyi , & - M1N9FAFzi , M1N9FAGxi , M1N9FAGyi , M1N9FAGzi , M1N9FAMxi , M1N9FAMyi , M1N9FAMzi , M1N9FAxi , M1N9FAyi , M1N9FAzi , & - M1N9FBFxi , M1N9FBFyi , M1N9FBFzi , M1N9FBxi , M1N9FByi , M1N9FBzi , M1N9FDxi , M1N9FDyi , M1N9FDzi , M1N9FIxi , & - M1N9FIyi , M1N9FIzi , M1N9FMGxi , M1N9FMGyi , M1N9FMGzi , M1N9MBFxi , M1N9MBFyi , M1N9MBFzi , M1N9MBxi , M1N9MByi , & - M1N9MBzi , M1N9STAxi , M1N9STAyi , M1N9STAzi , M1N9STVxi , M1N9STVyi , M1N9STVzi , M1N9Vxi , M1N9Vyi , M1N9Vzi , & - M2N1Axi , M2N1Ayi , M2N1Azi , M2N1DynP , M2N1FAFxi , M2N1FAFyi , M2N1FAFzi , M2N1FAGxi , M2N1FAGyi , M2N1FAGzi , & - M2N1FAMxi , M2N1FAMyi , M2N1FAMzi , M2N1FAxi , M2N1FAyi , M2N1FAzi , M2N1FBFxi , M2N1FBFyi , M2N1FBFzi , M2N1FBxi , & - M2N1FByi , M2N1FBzi , M2N1FDxi , M2N1FDyi , M2N1FDzi , M2N1FIxi , M2N1FIyi , M2N1FIzi , M2N1FMGxi , M2N1FMGyi , & - M2N1FMGzi , M2N1MBFxi , M2N1MBFyi , M2N1MBFzi , M2N1MBxi , M2N1MByi , M2N1MBzi , M2N1STAxi , M2N1STAyi , M2N1STAzi , & - M2N1STVxi , M2N1STVyi , M2N1STVzi , M2N1Vxi , M2N1Vyi , M2N1Vzi , M2N2Axi , M2N2Ayi , M2N2Azi , M2N2DynP , & - M2N2FAFxi , M2N2FAFyi , M2N2FAFzi , M2N2FAGxi , M2N2FAGyi , M2N2FAGzi , M2N2FAMxi , M2N2FAMyi , M2N2FAMzi , M2N2FAxi , & - M2N2FAyi , M2N2FAzi , M2N2FBFxi , M2N2FBFyi , M2N2FBFzi , M2N2FBxi , M2N2FByi , M2N2FBzi , M2N2FDxi , M2N2FDyi , & - M2N2FDzi , M2N2FIxi , M2N2FIyi , M2N2FIzi , M2N2FMGxi , M2N2FMGyi , M2N2FMGzi , M2N2MBFxi , M2N2MBFyi , M2N2MBFzi , & - M2N2MBxi , M2N2MByi , M2N2MBzi , M2N2STAxi , M2N2STAyi , M2N2STAzi , M2N2STVxi , M2N2STVyi , M2N2STVzi , M2N2Vxi , & - M2N2Vyi , M2N2Vzi , M2N3Axi , M2N3Ayi , M2N3Azi , M2N3DynP , M2N3FAFxi , M2N3FAFyi , M2N3FAFzi , M2N3FAGxi , & - M2N3FAGyi , M2N3FAGzi , M2N3FAMxi , M2N3FAMyi , M2N3FAMzi , M2N3FAxi , M2N3FAyi , M2N3FAzi , M2N3FBFxi , M2N3FBFyi , & - M2N3FBFzi , M2N3FBxi , M2N3FByi , M2N3FBzi , M2N3FDxi , M2N3FDyi , M2N3FDzi , M2N3FIxi , M2N3FIyi , M2N3FIzi , & - M2N3FMGxi , M2N3FMGyi , M2N3FMGzi , M2N3MBFxi , M2N3MBFyi , M2N3MBFzi , M2N3MBxi , M2N3MByi , M2N3MBzi , M2N3STAxi , & - M2N3STAyi , M2N3STAzi , M2N3STVxi , M2N3STVyi , M2N3STVzi , M2N3Vxi , M2N3Vyi , M2N3Vzi , M2N4Axi , M2N4Ayi , & - M2N4Azi , M2N4DynP , M2N4FAFxi , M2N4FAFyi , M2N4FAFzi , M2N4FAGxi , M2N4FAGyi , M2N4FAGzi , M2N4FAMxi , M2N4FAMyi , & - M2N4FAMzi , M2N4FAxi , M2N4FAyi , M2N4FAzi , M2N4FBFxi , M2N4FBFyi , M2N4FBFzi , M2N4FBxi , M2N4FByi , M2N4FBzi , & - M2N4FDxi , M2N4FDyi , M2N4FDzi , M2N4FIxi , M2N4FIyi , M2N4FIzi , M2N4FMGxi , M2N4FMGyi , M2N4FMGzi , M2N4MBFxi , & - M2N4MBFyi , M2N4MBFzi , M2N4MBxi , M2N4MByi , M2N4MBzi , M2N4STAxi , M2N4STAyi , M2N4STAzi , M2N4STVxi , M2N4STVyi , & - M2N4STVzi , M2N4Vxi , M2N4Vyi , M2N4Vzi , M2N5Axi , M2N5Ayi , M2N5Azi , M2N5DynP , M2N5FAFxi , M2N5FAFyi , & - M2N5FAFzi , M2N5FAGxi , M2N5FAGyi , M2N5FAGzi , M2N5FAMxi , M2N5FAMyi , M2N5FAMzi , M2N5FAxi , M2N5FAyi , M2N5FAzi , & - M2N5FBFxi , M2N5FBFyi , M2N5FBFzi , M2N5FBxi , M2N5FByi , M2N5FBzi , M2N5FDxi , M2N5FDyi , M2N5FDzi , M2N5FIxi , & - M2N5FIyi , M2N5FIzi , M2N5FMGxi , M2N5FMGyi , M2N5FMGzi , M2N5MBFxi , M2N5MBFyi , M2N5MBFzi , M2N5MBxi , M2N5MByi , & - M2N5MBzi , M2N5STAxi , M2N5STAyi , M2N5STAzi , M2N5STVxi , M2N5STVyi , M2N5STVzi , M2N5Vxi , M2N5Vyi , M2N5Vzi , & - M2N6Axi , M2N6Ayi , M2N6Azi , M2N6DynP , M2N6FAFxi , M2N6FAFyi , M2N6FAFzi , M2N6FAGxi , M2N6FAGyi , M2N6FAGzi , & - M2N6FAMxi , M2N6FAMyi , M2N6FAMzi , M2N6FAxi , M2N6FAyi , M2N6FAzi , M2N6FBFxi , M2N6FBFyi , M2N6FBFzi , M2N6FBxi , & - M2N6FByi , M2N6FBzi , M2N6FDxi , M2N6FDyi , M2N6FDzi , M2N6FIxi , M2N6FIyi , M2N6FIzi , M2N6FMGxi , M2N6FMGyi , & - M2N6FMGzi , M2N6MBFxi , M2N6MBFyi , M2N6MBFzi , M2N6MBxi , M2N6MByi , M2N6MBzi , M2N6STAxi , M2N6STAyi , M2N6STAzi , & - M2N6STVxi , M2N6STVyi , M2N6STVzi , M2N6Vxi , M2N6Vyi , M2N6Vzi , M2N7Axi , M2N7Ayi , M2N7Azi , M2N7DynP , & - M2N7FAFxi , M2N7FAFyi , M2N7FAFzi , M2N7FAGxi , M2N7FAGyi , M2N7FAGzi , M2N7FAMxi , M2N7FAMyi , M2N7FAMzi , M2N7FAxi , & - M2N7FAyi , M2N7FAzi , M2N7FBFxi , M2N7FBFyi , M2N7FBFzi , M2N7FBxi , M2N7FByi , M2N7FBzi , M2N7FDxi , M2N7FDyi , & - M2N7FDzi , M2N7FIxi , M2N7FIyi , M2N7FIzi , M2N7FMGxi , M2N7FMGyi , M2N7FMGzi , M2N7MBFxi , M2N7MBFyi , M2N7MBFzi , & - M2N7MBxi , M2N7MByi , M2N7MBzi , M2N7STAxi , M2N7STAyi , M2N7STAzi , M2N7STVxi , M2N7STVyi , M2N7STVzi , M2N7Vxi , & - M2N7Vyi , M2N7Vzi , M2N8Axi , M2N8Ayi , M2N8Azi , M2N8DynP , M2N8FAFxi , M2N8FAFyi , M2N8FAFzi , M2N8FAGxi , & - M2N8FAGyi , M2N8FAGzi , M2N8FAMxi , M2N8FAMyi , M2N8FAMzi , M2N8FAxi , M2N8FAyi , M2N8FAzi , M2N8FBFxi , M2N8FBFyi , & - M2N8FBFzi , M2N8FBxi , M2N8FByi , M2N8FBzi , M2N8FDxi , M2N8FDyi , M2N8FDzi , M2N8FIxi , M2N8FIyi , M2N8FIzi , & - M2N8FMGxi , M2N8FMGyi , M2N8FMGzi , M2N8MBFxi , M2N8MBFyi , M2N8MBFzi , M2N8MBxi , M2N8MByi , M2N8MBzi , M2N8STAxi , & - M2N8STAyi , M2N8STAzi , M2N8STVxi , M2N8STVyi , M2N8STVzi , M2N8Vxi , M2N8Vyi , M2N8Vzi , M2N9Axi , M2N9Ayi , & - M2N9Azi , M2N9DynP , M2N9FAFxi , M2N9FAFyi , M2N9FAFzi , M2N9FAGxi , M2N9FAGyi , M2N9FAGzi , M2N9FAMxi , M2N9FAMyi , & - M2N9FAMzi , M2N9FAxi , M2N9FAyi , M2N9FAzi , M2N9FBFxi , M2N9FBFyi , M2N9FBFzi , M2N9FBxi , M2N9FByi , M2N9FBzi , & - M2N9FDxi , M2N9FDyi , M2N9FDzi , M2N9FIxi , M2N9FIyi , M2N9FIzi , M2N9FMGxi , M2N9FMGyi , M2N9FMGzi , M2N9MBFxi , & - M2N9MBFyi , M2N9MBFzi , M2N9MBxi , M2N9MByi , M2N9MBzi , M2N9STAxi , M2N9STAyi , M2N9STAzi , M2N9STVxi , M2N9STVyi , & - M2N9STVzi , M2N9Vxi , M2N9Vyi , M2N9Vzi , M3N1Axi , M3N1Ayi , M3N1Azi , M3N1DynP , M3N1FAFxi , M3N1FAFyi , & - M3N1FAFzi , M3N1FAGxi , M3N1FAGyi , M3N1FAGzi , M3N1FAMxi , M3N1FAMyi , M3N1FAMzi , M3N1FAxi , M3N1FAyi , M3N1FAzi , & - M3N1FBFxi , M3N1FBFyi , M3N1FBFzi , M3N1FBxi , M3N1FByi , M3N1FBzi , M3N1FDxi , M3N1FDyi , M3N1FDzi , M3N1FIxi , & - M3N1FIyi , M3N1FIzi , M3N1FMGxi , M3N1FMGyi , M3N1FMGzi , M3N1MBFxi , M3N1MBFyi , M3N1MBFzi , M3N1MBxi , M3N1MByi , & - M3N1MBzi , M3N1STAxi , M3N1STAyi , M3N1STAzi , M3N1STVxi , M3N1STVyi , M3N1STVzi , M3N1Vxi , M3N1Vyi , M3N1Vzi , & - M3N2Axi , M3N2Ayi , M3N2Azi , M3N2DynP , M3N2FAFxi , M3N2FAFyi , M3N2FAFzi , M3N2FAGxi , M3N2FAGyi , M3N2FAGzi , & - M3N2FAMxi , M3N2FAMyi , M3N2FAMzi , M3N2FAxi , M3N2FAyi , M3N2FAzi , M3N2FBFxi , M3N2FBFyi , M3N2FBFzi , M3N2FBxi , & - M3N2FByi , M3N2FBzi , M3N2FDxi , M3N2FDyi , M3N2FDzi , M3N2FIxi , M3N2FIyi , M3N2FIzi , M3N2FMGxi , M3N2FMGyi , & - M3N2FMGzi , M3N2MBFxi , M3N2MBFyi , M3N2MBFzi , M3N2MBxi , M3N2MByi , M3N2MBzi , M3N2STAxi , M3N2STAyi , M3N2STAzi , & - M3N2STVxi , M3N2STVyi , M3N2STVzi , M3N2Vxi , M3N2Vyi , M3N2Vzi , M3N3Axi , M3N3Ayi , M3N3Azi , M3N3DynP , & - M3N3FAFxi , M3N3FAFyi , M3N3FAFzi , M3N3FAGxi , M3N3FAGyi , M3N3FAGzi , M3N3FAMxi , M3N3FAMyi , M3N3FAMzi , M3N3FAxi , & - M3N3FAyi , M3N3FAzi , M3N3FBFxi , M3N3FBFyi , M3N3FBFzi , M3N3FBxi , M3N3FByi , M3N3FBzi , M3N3FDxi , M3N3FDyi , & - M3N3FDzi , M3N3FIxi , M3N3FIyi , M3N3FIzi , M3N3FMGxi , M3N3FMGyi , M3N3FMGzi , M3N3MBFxi , M3N3MBFyi , M3N3MBFzi , & - M3N3MBxi , M3N3MByi , M3N3MBzi , M3N3STAxi , M3N3STAyi , M3N3STAzi , M3N3STVxi , M3N3STVyi , M3N3STVzi , M3N3Vxi , & - M3N3Vyi , M3N3Vzi , M3N4Axi , M3N4Ayi , M3N4Azi , M3N4DynP , M3N4FAFxi , M3N4FAFyi , M3N4FAFzi , M3N4FAGxi , & - M3N4FAGyi , M3N4FAGzi , M3N4FAMxi , M3N4FAMyi , M3N4FAMzi , M3N4FAxi , M3N4FAyi , M3N4FAzi , M3N4FBFxi , M3N4FBFyi , & - M3N4FBFzi , M3N4FBxi , M3N4FByi , M3N4FBzi , M3N4FDxi , M3N4FDyi , M3N4FDzi , M3N4FIxi , M3N4FIyi , M3N4FIzi , & - M3N4FMGxi , M3N4FMGyi , M3N4FMGzi , M3N4MBFxi , M3N4MBFyi , M3N4MBFzi , M3N4MBxi , M3N4MByi , M3N4MBzi , M3N4STAxi , & - M3N4STAyi , M3N4STAzi , M3N4STVxi , M3N4STVyi , M3N4STVzi , M3N4Vxi , M3N4Vyi , M3N4Vzi , M3N5Axi , M3N5Ayi , & - M3N5Azi , M3N5DynP , M3N5FAFxi , M3N5FAFyi , M3N5FAFzi , M3N5FAGxi , M3N5FAGyi , M3N5FAGzi , M3N5FAMxi , M3N5FAMyi , & - M3N5FAMzi , M3N5FAxi , M3N5FAyi , M3N5FAzi , M3N5FBFxi , M3N5FBFyi , M3N5FBFzi , M3N5FBxi , M3N5FByi , M3N5FBzi , & - M3N5FDxi , M3N5FDyi , M3N5FDzi , M3N5FIxi , M3N5FIyi , M3N5FIzi , M3N5FMGxi , M3N5FMGyi , M3N5FMGzi , M3N5MBFxi , & - M3N5MBFyi , M3N5MBFzi , M3N5MBxi , M3N5MByi , M3N5MBzi , M3N5STAxi , M3N5STAyi , M3N5STAzi , M3N5STVxi , M3N5STVyi , & - M3N5STVzi , M3N5Vxi , M3N5Vyi , M3N5Vzi , M3N6Axi , M3N6Ayi , M3N6Azi , M3N6DynP , M3N6FAFxi , M3N6FAFyi , & - M3N6FAFzi , M3N6FAGxi , M3N6FAGyi , M3N6FAGzi , M3N6FAMxi , M3N6FAMyi , M3N6FAMzi , M3N6FAxi , M3N6FAyi , M3N6FAzi , & - M3N6FBFxi , M3N6FBFyi , M3N6FBFzi , M3N6FBxi , M3N6FByi , M3N6FBzi , M3N6FDxi , M3N6FDyi , M3N6FDzi , M3N6FIxi , & - M3N6FIyi , M3N6FIzi , M3N6FMGxi , M3N6FMGyi , M3N6FMGzi , M3N6MBFxi , M3N6MBFyi , M3N6MBFzi , M3N6MBxi , M3N6MByi , & - M3N6MBzi , M3N6STAxi , M3N6STAyi , M3N6STAzi , M3N6STVxi , M3N6STVyi , M3N6STVzi , M3N6Vxi , M3N6Vyi , M3N6Vzi , & - M3N7Axi , M3N7Ayi , M3N7Azi , M3N7DynP , M3N7FAFxi , M3N7FAFyi , M3N7FAFzi , M3N7FAGxi , M3N7FAGyi , M3N7FAGzi , & - M3N7FAMxi , M3N7FAMyi , M3N7FAMzi , M3N7FAxi , M3N7FAyi , M3N7FAzi , M3N7FBFxi , M3N7FBFyi , M3N7FBFzi , M3N7FBxi , & - M3N7FByi , M3N7FBzi , M3N7FDxi , M3N7FDyi , M3N7FDzi , M3N7FIxi , M3N7FIyi , M3N7FIzi , M3N7FMGxi , M3N7FMGyi , & - M3N7FMGzi , M3N7MBFxi , M3N7MBFyi , M3N7MBFzi , M3N7MBxi , M3N7MByi , M3N7MBzi , M3N7STAxi , M3N7STAyi , M3N7STAzi , & - M3N7STVxi , M3N7STVyi , M3N7STVzi , M3N7Vxi , M3N7Vyi , M3N7Vzi , M3N8Axi , M3N8Ayi , M3N8Azi , M3N8DynP , & - M3N8FAFxi , M3N8FAFyi , M3N8FAFzi , M3N8FAGxi , M3N8FAGyi , M3N8FAGzi , M3N8FAMxi , M3N8FAMyi , M3N8FAMzi , M3N8FAxi , & - M3N8FAyi , M3N8FAzi , M3N8FBFxi , M3N8FBFyi , M3N8FBFzi , M3N8FBxi , M3N8FByi , M3N8FBzi , M3N8FDxi , M3N8FDyi , & - M3N8FDzi , M3N8FIxi , M3N8FIyi , M3N8FIzi , M3N8FMGxi , M3N8FMGyi , M3N8FMGzi , M3N8MBFxi , M3N8MBFyi , M3N8MBFzi , & - M3N8MBxi , M3N8MByi , M3N8MBzi , M3N8STAxi , M3N8STAyi , M3N8STAzi , M3N8STVxi , M3N8STVyi , M3N8STVzi , M3N8Vxi , & - M3N8Vyi , M3N8Vzi , M3N9Axi , M3N9Ayi , M3N9Azi , M3N9DynP , M3N9FAFxi , M3N9FAFyi , M3N9FAFzi , M3N9FAGxi , & - M3N9FAGyi , M3N9FAGzi , M3N9FAMxi , M3N9FAMyi , M3N9FAMzi , M3N9FAxi , M3N9FAyi , M3N9FAzi , M3N9FBFxi , M3N9FBFyi , & - M3N9FBFzi , M3N9FBxi , M3N9FByi , M3N9FBzi , M3N9FDxi , M3N9FDyi , M3N9FDzi , M3N9FIxi , M3N9FIyi , M3N9FIzi , & - M3N9FMGxi , M3N9FMGyi , M3N9FMGzi , M3N9MBFxi , M3N9MBFyi , M3N9MBFzi , M3N9MBxi , M3N9MByi , M3N9MBzi , M3N9STAxi , & - M3N9STAyi , M3N9STAzi , M3N9STVxi , M3N9STVyi , M3N9STVzi , M3N9Vxi , M3N9Vyi , M3N9Vzi , M4N1Axi , M4N1Ayi , & - M4N1Azi , M4N1DynP , M4N1FAFxi , M4N1FAFyi , M4N1FAFzi , M4N1FAGxi , M4N1FAGyi , M4N1FAGzi , M4N1FAMxi , M4N1FAMyi , & - M4N1FAMzi , M4N1FAxi , M4N1FAyi , M4N1FAzi , M4N1FBFxi , M4N1FBFyi , M4N1FBFzi , M4N1FBxi , M4N1FByi , M4N1FBzi , & - M4N1FDxi , M4N1FDyi , M4N1FDzi , M4N1FIxi , M4N1FIyi , M4N1FIzi , M4N1FMGxi , M4N1FMGyi , M4N1FMGzi , M4N1MBFxi , & - M4N1MBFyi , M4N1MBFzi , M4N1MBxi , M4N1MByi , M4N1MBzi , M4N1STAxi , M4N1STAyi , M4N1STAzi , M4N1STVxi , M4N1STVyi , & - M4N1STVzi , M4N1Vxi , M4N1Vyi , M4N1Vzi , M4N2Axi , M4N2Ayi , M4N2Azi , M4N2DynP , M4N2FAFxi , M4N2FAFyi , & - M4N2FAFzi , M4N2FAGxi , M4N2FAGyi , M4N2FAGzi , M4N2FAMxi , M4N2FAMyi , M4N2FAMzi , M4N2FAxi , M4N2FAyi , M4N2FAzi , & - M4N2FBFxi , M4N2FBFyi , M4N2FBFzi , M4N2FBxi , M4N2FByi , M4N2FBzi , M4N2FDxi , M4N2FDyi , M4N2FDzi , M4N2FIxi , & - M4N2FIyi , M4N2FIzi , M4N2FMGxi , M4N2FMGyi , M4N2FMGzi , M4N2MBFxi , M4N2MBFyi , M4N2MBFzi , M4N2MBxi , M4N2MByi , & - M4N2MBzi , M4N2STAxi , M4N2STAyi , M4N2STAzi , M4N2STVxi , M4N2STVyi , M4N2STVzi , M4N2Vxi , M4N2Vyi , M4N2Vzi , & - M4N3Axi , M4N3Ayi , M4N3Azi , M4N3DynP , M4N3FAFxi , M4N3FAFyi , M4N3FAFzi , M4N3FAGxi , M4N3FAGyi , M4N3FAGzi , & - M4N3FAMxi , M4N3FAMyi , M4N3FAMzi , M4N3FAxi , M4N3FAyi , M4N3FAzi , M4N3FBFxi , M4N3FBFyi , M4N3FBFzi , M4N3FBxi , & - M4N3FByi , M4N3FBzi , M4N3FDxi , M4N3FDyi , M4N3FDzi , M4N3FIxi , M4N3FIyi , M4N3FIzi , M4N3FMGxi , M4N3FMGyi , & - M4N3FMGzi , M4N3MBFxi , M4N3MBFyi , M4N3MBFzi , M4N3MBxi , M4N3MByi , M4N3MBzi , M4N3STAxi , M4N3STAyi , M4N3STAzi , & - M4N3STVxi , M4N3STVyi , M4N3STVzi , M4N3Vxi , M4N3Vyi , M4N3Vzi , M4N4Axi , M4N4Ayi , M4N4Azi , M4N4DynP , & - M4N4FAFxi , M4N4FAFyi , M4N4FAFzi , M4N4FAGxi , M4N4FAGyi , M4N4FAGzi , M4N4FAMxi , M4N4FAMyi , M4N4FAMzi , M4N4FAxi , & - M4N4FAyi , M4N4FAzi , M4N4FBFxi , M4N4FBFyi , M4N4FBFzi , M4N4FBxi , M4N4FByi , M4N4FBzi , M4N4FDxi , M4N4FDyi , & - M4N4FDzi , M4N4FIxi , M4N4FIyi , M4N4FIzi , M4N4FMGxi , M4N4FMGyi , M4N4FMGzi , M4N4MBFxi , M4N4MBFyi , M4N4MBFzi , & - M4N4MBxi , M4N4MByi , M4N4MBzi , M4N4STAxi , M4N4STAyi , M4N4STAzi , M4N4STVxi , M4N4STVyi , M4N4STVzi , M4N4Vxi , & - M4N4Vyi , M4N4Vzi , M4N5Axi , M4N5Ayi , M4N5Azi , M4N5DynP , M4N5FAFxi , M4N5FAFyi , M4N5FAFzi , M4N5FAGxi , & - M4N5FAGyi , M4N5FAGzi , M4N5FAMxi , M4N5FAMyi , M4N5FAMzi , M4N5FAxi , M4N5FAyi , M4N5FAzi , M4N5FBFxi , M4N5FBFyi , & - M4N5FBFzi , M4N5FBxi , M4N5FByi , M4N5FBzi , M4N5FDxi , M4N5FDyi , M4N5FDzi , M4N5FIxi , M4N5FIyi , M4N5FIzi , & - M4N5FMGxi , M4N5FMGyi , M4N5FMGzi , M4N5MBFxi , M4N5MBFyi , M4N5MBFzi , M4N5MBxi , M4N5MByi , M4N5MBzi , M4N5STAxi , & - M4N5STAyi , M4N5STAzi , M4N5STVxi , M4N5STVyi , M4N5STVzi , M4N5Vxi , M4N5Vyi , M4N5Vzi , M4N6Axi , M4N6Ayi , & - M4N6Azi , M4N6DynP , M4N6FAFxi , M4N6FAFyi , M4N6FAFzi , M4N6FAGxi , M4N6FAGyi , M4N6FAGzi , M4N6FAMxi , M4N6FAMyi , & - M4N6FAMzi , M4N6FAxi , M4N6FAyi , M4N6FAzi , M4N6FBFxi , M4N6FBFyi , M4N6FBFzi , M4N6FBxi , M4N6FByi , M4N6FBzi , & - M4N6FDxi , M4N6FDyi , M4N6FDzi , M4N6FIxi , M4N6FIyi , M4N6FIzi , M4N6FMGxi , M4N6FMGyi , M4N6FMGzi , M4N6MBFxi , & - M4N6MBFyi , M4N6MBFzi , M4N6MBxi , M4N6MByi , M4N6MBzi , M4N6STAxi , M4N6STAyi , M4N6STAzi , M4N6STVxi , M4N6STVyi , & - M4N6STVzi , M4N6Vxi , M4N6Vyi , M4N6Vzi , M4N7Axi , M4N7Ayi , M4N7Azi , M4N7DynP , M4N7FAFxi , M4N7FAFyi , & - M4N7FAFzi , M4N7FAGxi , M4N7FAGyi , M4N7FAGzi , M4N7FAMxi , M4N7FAMyi , M4N7FAMzi , M4N7FAxi , M4N7FAyi , M4N7FAzi , & - M4N7FBFxi , M4N7FBFyi , M4N7FBFzi , M4N7FBxi , M4N7FByi , M4N7FBzi , M4N7FDxi , M4N7FDyi , M4N7FDzi , M4N7FIxi , & - M4N7FIyi , M4N7FIzi , M4N7FMGxi , M4N7FMGyi , M4N7FMGzi , M4N7MBFxi , M4N7MBFyi , M4N7MBFzi , M4N7MBxi , M4N7MByi , & - M4N7MBzi , M4N7STAxi , M4N7STAyi , M4N7STAzi , M4N7STVxi , M4N7STVyi , M4N7STVzi , M4N7Vxi , M4N7Vyi , M4N7Vzi , & - M4N8Axi , M4N8Ayi , M4N8Azi , M4N8DynP , M4N8FAFxi , M4N8FAFyi , M4N8FAFzi , M4N8FAGxi , M4N8FAGyi , M4N8FAGzi , & - M4N8FAMxi , M4N8FAMyi , M4N8FAMzi , M4N8FAxi , M4N8FAyi , M4N8FAzi , M4N8FBFxi , M4N8FBFyi , M4N8FBFzi , M4N8FBxi , & - M4N8FByi , M4N8FBzi , M4N8FDxi , M4N8FDyi , M4N8FDzi , M4N8FIxi , M4N8FIyi , M4N8FIzi , M4N8FMGxi , M4N8FMGyi , & - M4N8FMGzi , M4N8MBFxi , M4N8MBFyi , M4N8MBFzi , M4N8MBxi , M4N8MByi , M4N8MBzi , M4N8STAxi , M4N8STAyi , M4N8STAzi , & - M4N8STVxi , M4N8STVyi , M4N8STVzi , M4N8Vxi , M4N8Vyi , M4N8Vzi , M4N9Axi , M4N9Ayi , M4N9Azi , M4N9DynP , & - M4N9FAFxi , M4N9FAFyi , M4N9FAFzi , M4N9FAGxi , M4N9FAGyi , M4N9FAGzi , M4N9FAMxi , M4N9FAMyi , M4N9FAMzi , M4N9FAxi , & - M4N9FAyi , M4N9FAzi , M4N9FBFxi , M4N9FBFyi , M4N9FBFzi , M4N9FBxi , M4N9FByi , M4N9FBzi , M4N9FDxi , M4N9FDyi , & - M4N9FDzi , M4N9FIxi , M4N9FIyi , M4N9FIzi , M4N9FMGxi , M4N9FMGyi , M4N9FMGzi , M4N9MBFxi , M4N9MBFyi , M4N9MBFzi , & - M4N9MBxi , M4N9MByi , M4N9MBzi , M4N9STAxi , M4N9STAyi , M4N9STAzi , M4N9STVxi , M4N9STVyi , M4N9STVzi , M4N9Vxi , & - M4N9Vyi , M4N9Vzi , M5N1Axi , M5N1Ayi , M5N1Azi , M5N1DynP , M5N1FAFxi , M5N1FAFyi , M5N1FAFzi , M5N1FAGxi , & - M5N1FAGyi , M5N1FAGzi , M5N1FAMxi , M5N1FAMyi , M5N1FAMzi , M5N1FAxi , M5N1FAyi , M5N1FAzi , M5N1FBFxi , M5N1FBFyi , & - M5N1FBFzi , M5N1FBxi , M5N1FByi , M5N1FBzi , M5N1FDxi , M5N1FDyi , M5N1FDzi , M5N1FIxi , M5N1FIyi , M5N1FIzi , & - M5N1FMGxi , M5N1FMGyi , M5N1FMGzi , M5N1MBFxi , M5N1MBFyi , M5N1MBFzi , M5N1MBxi , M5N1MByi , M5N1MBzi , M5N1STAxi , & - M5N1STAyi , M5N1STAzi , M5N1STVxi , M5N1STVyi , M5N1STVzi , M5N1Vxi , M5N1Vyi , M5N1Vzi , M5N2Axi , M5N2Ayi , & - M5N2Azi , M5N2DynP , M5N2FAFxi , M5N2FAFyi , M5N2FAFzi , M5N2FAGxi , M5N2FAGyi , M5N2FAGzi , M5N2FAMxi , M5N2FAMyi , & - M5N2FAMzi , M5N2FAxi , M5N2FAyi , M5N2FAzi , M5N2FBFxi , M5N2FBFyi , M5N2FBFzi , M5N2FBxi , M5N2FByi , M5N2FBzi , & - M5N2FDxi , M5N2FDyi , M5N2FDzi , M5N2FIxi , M5N2FIyi , M5N2FIzi , M5N2FMGxi , M5N2FMGyi , M5N2FMGzi , M5N2MBFxi , & - M5N2MBFyi , M5N2MBFzi , M5N2MBxi , M5N2MByi , M5N2MBzi , M5N2STAxi , M5N2STAyi , M5N2STAzi , M5N2STVxi , M5N2STVyi , & - M5N2STVzi , M5N2Vxi , M5N2Vyi , M5N2Vzi , M5N3Axi , M5N3Ayi , M5N3Azi , M5N3DynP , M5N3FAFxi , M5N3FAFyi , & - M5N3FAFzi , M5N3FAGxi , M5N3FAGyi , M5N3FAGzi , M5N3FAMxi , M5N3FAMyi , M5N3FAMzi , M5N3FAxi , M5N3FAyi , M5N3FAzi , & - M5N3FBFxi , M5N3FBFyi , M5N3FBFzi , M5N3FBxi , M5N3FByi , M5N3FBzi , M5N3FDxi , M5N3FDyi , M5N3FDzi , M5N3FIxi , & - M5N3FIyi , M5N3FIzi , M5N3FMGxi , M5N3FMGyi , M5N3FMGzi , M5N3MBFxi , M5N3MBFyi , M5N3MBFzi , M5N3MBxi , M5N3MByi , & - M5N3MBzi , M5N3STAxi , M5N3STAyi , M5N3STAzi , M5N3STVxi , M5N3STVyi , M5N3STVzi , M5N3Vxi , M5N3Vyi , M5N3Vzi , & - M5N4Axi , M5N4Ayi , M5N4Azi , M5N4DynP , M5N4FAFxi , M5N4FAFyi , M5N4FAFzi , M5N4FAGxi , M5N4FAGyi , M5N4FAGzi , & - M5N4FAMxi , M5N4FAMyi , M5N4FAMzi , M5N4FAxi , M5N4FAyi , M5N4FAzi , M5N4FBFxi , M5N4FBFyi , M5N4FBFzi , M5N4FBxi , & - M5N4FByi , M5N4FBzi , M5N4FDxi , M5N4FDyi , M5N4FDzi , M5N4FIxi , M5N4FIyi , M5N4FIzi , M5N4FMGxi , M5N4FMGyi , & - M5N4FMGzi , M5N4MBFxi , M5N4MBFyi , M5N4MBFzi , M5N4MBxi , M5N4MByi , M5N4MBzi , M5N4STAxi , M5N4STAyi , M5N4STAzi , & - M5N4STVxi , M5N4STVyi , M5N4STVzi , M5N4Vxi , M5N4Vyi , M5N4Vzi , M5N5Axi , M5N5Ayi , M5N5Azi , M5N5DynP , & - M5N5FAFxi , M5N5FAFyi , M5N5FAFzi , M5N5FAGxi , M5N5FAGyi , M5N5FAGzi , M5N5FAMxi , M5N5FAMyi , M5N5FAMzi , M5N5FAxi , & - M5N5FAyi , M5N5FAzi , M5N5FBFxi , M5N5FBFyi , M5N5FBFzi , M5N5FBxi , M5N5FByi , M5N5FBzi , M5N5FDxi , M5N5FDyi , & - M5N5FDzi , M5N5FIxi , M5N5FIyi , M5N5FIzi , M5N5FMGxi , M5N5FMGyi , M5N5FMGzi , M5N5MBFxi , M5N5MBFyi , M5N5MBFzi , & - M5N5MBxi , M5N5MByi , M5N5MBzi , M5N5STAxi , M5N5STAyi , M5N5STAzi , M5N5STVxi , M5N5STVyi , M5N5STVzi , M5N5Vxi , & - M5N5Vyi , M5N5Vzi , M5N6Axi , M5N6Ayi , M5N6Azi , M5N6DynP , M5N6FAFxi , M5N6FAFyi , M5N6FAFzi , M5N6FAGxi , & - M5N6FAGyi , M5N6FAGzi , M5N6FAMxi , M5N6FAMyi , M5N6FAMzi , M5N6FAxi , M5N6FAyi , M5N6FAzi , M5N6FBFxi , M5N6FBFyi , & - M5N6FBFzi , M5N6FBxi , M5N6FByi , M5N6FBzi , M5N6FDxi , M5N6FDyi , M5N6FDzi , M5N6FIxi , M5N6FIyi , M5N6FIzi , & - M5N6FMGxi , M5N6FMGyi , M5N6FMGzi , M5N6MBFxi , M5N6MBFyi , M5N6MBFzi , M5N6MBxi , M5N6MByi , M5N6MBzi , M5N6STAxi , & - M5N6STAyi , M5N6STAzi , M5N6STVxi , M5N6STVyi , M5N6STVzi , M5N6Vxi , M5N6Vyi , M5N6Vzi , M5N7Axi , M5N7Ayi , & - M5N7Azi , M5N7DynP , M5N7FAFxi , M5N7FAFyi , M5N7FAFzi , M5N7FAGxi , M5N7FAGyi , M5N7FAGzi , M5N7FAMxi , M5N7FAMyi , & - M5N7FAMzi , M5N7FAxi , M5N7FAyi , M5N7FAzi , M5N7FBFxi , M5N7FBFyi , M5N7FBFzi , M5N7FBxi , M5N7FByi , M5N7FBzi , & - M5N7FDxi , M5N7FDyi , M5N7FDzi , M5N7FIxi , M5N7FIyi , M5N7FIzi , M5N7FMGxi , M5N7FMGyi , M5N7FMGzi , M5N7MBFxi , & - M5N7MBFyi , M5N7MBFzi , M5N7MBxi , M5N7MByi , M5N7MBzi , M5N7STAxi , M5N7STAyi , M5N7STAzi , M5N7STVxi , M5N7STVyi , & - M5N7STVzi , M5N7Vxi , M5N7Vyi , M5N7Vzi , M5N8Axi , M5N8Ayi , M5N8Azi , M5N8DynP , M5N8FAFxi , M5N8FAFyi , & - M5N8FAFzi , M5N8FAGxi , M5N8FAGyi , M5N8FAGzi , M5N8FAMxi , M5N8FAMyi , M5N8FAMzi , M5N8FAxi , M5N8FAyi , M5N8FAzi , & - M5N8FBFxi , M5N8FBFyi , M5N8FBFzi , M5N8FBxi , M5N8FByi , M5N8FBzi , M5N8FDxi , M5N8FDyi , M5N8FDzi , M5N8FIxi , & - M5N8FIyi , M5N8FIzi , M5N8FMGxi , M5N8FMGyi , M5N8FMGzi , M5N8MBFxi , M5N8MBFyi , M5N8MBFzi , M5N8MBxi , M5N8MByi , & - M5N8MBzi , M5N8STAxi , M5N8STAyi , M5N8STAzi , M5N8STVxi , M5N8STVyi , M5N8STVzi , M5N8Vxi , M5N8Vyi , M5N8Vzi , & - M5N9Axi , M5N9Ayi , M5N9Azi , M5N9DynP , M5N9FAFxi , M5N9FAFyi , M5N9FAFzi , M5N9FAGxi , M5N9FAGyi , M5N9FAGzi , & - M5N9FAMxi , M5N9FAMyi , M5N9FAMzi , M5N9FAxi , M5N9FAyi , M5N9FAzi , M5N9FBFxi , M5N9FBFyi , M5N9FBFzi , M5N9FBxi , & - M5N9FByi , M5N9FBzi , M5N9FDxi , M5N9FDyi , M5N9FDzi , M5N9FIxi , M5N9FIyi , M5N9FIzi , M5N9FMGxi , M5N9FMGyi , & - M5N9FMGzi , M5N9MBFxi , M5N9MBFyi , M5N9MBFzi , M5N9MBxi , M5N9MByi , M5N9MBzi , M5N9STAxi , M5N9STAyi , M5N9STAzi , & - M5N9STVxi , M5N9STVyi , M5N9STVzi , M5N9Vxi , M5N9Vyi , M5N9Vzi , M6N1Axi , M6N1Ayi , M6N1Azi , M6N1DynP , & - M6N1FAFxi , M6N1FAFyi , M6N1FAFzi , M6N1FAGxi , M6N1FAGyi , M6N1FAGzi , M6N1FAMxi , M6N1FAMyi , M6N1FAMzi , M6N1FAxi , & - M6N1FAyi , M6N1FAzi , M6N1FBFxi , M6N1FBFyi , M6N1FBFzi , M6N1FBxi , M6N1FByi , M6N1FBzi , M6N1FDxi , M6N1FDyi , & - M6N1FDzi , M6N1FIxi , M6N1FIyi , M6N1FIzi , M6N1FMGxi , M6N1FMGyi , M6N1FMGzi , M6N1MBFxi , M6N1MBFyi , M6N1MBFzi , & - M6N1MBxi , M6N1MByi , M6N1MBzi , M6N1STAxi , M6N1STAyi , M6N1STAzi , M6N1STVxi , M6N1STVyi , M6N1STVzi , M6N1Vxi , & - M6N1Vyi , M6N1Vzi , M6N2Axi , M6N2Ayi , M6N2Azi , M6N2DynP , M6N2FAFxi , M6N2FAFyi , M6N2FAFzi , M6N2FAGxi , & - M6N2FAGyi , M6N2FAGzi , M6N2FAMxi , M6N2FAMyi , M6N2FAMzi , M6N2FAxi , M6N2FAyi , M6N2FAzi , M6N2FBFxi , M6N2FBFyi , & - M6N2FBFzi , M6N2FBxi , M6N2FByi , M6N2FBzi , M6N2FDxi , M6N2FDyi , M6N2FDzi , M6N2FIxi , M6N2FIyi , M6N2FIzi , & - M6N2FMGxi , M6N2FMGyi , M6N2FMGzi , M6N2MBFxi , M6N2MBFyi , M6N2MBFzi , M6N2MBxi , M6N2MByi , M6N2MBzi , M6N2STAxi , & - M6N2STAyi , M6N2STAzi , M6N2STVxi , M6N2STVyi , M6N2STVzi , M6N2Vxi , M6N2Vyi , M6N2Vzi , M6N3Axi , M6N3Ayi , & - M6N3Azi , M6N3DynP , M6N3FAFxi , M6N3FAFyi , M6N3FAFzi , M6N3FAGxi , M6N3FAGyi , M6N3FAGzi , M6N3FAMxi , M6N3FAMyi , & - M6N3FAMzi , M6N3FAxi , M6N3FAyi , M6N3FAzi , M6N3FBFxi , M6N3FBFyi , M6N3FBFzi , M6N3FBxi , M6N3FByi , M6N3FBzi , & - M6N3FDxi , M6N3FDyi , M6N3FDzi , M6N3FIxi , M6N3FIyi , M6N3FIzi , M6N3FMGxi , M6N3FMGyi , M6N3FMGzi , M6N3MBFxi , & - M6N3MBFyi , M6N3MBFzi , M6N3MBxi , M6N3MByi , M6N3MBzi , M6N3STAxi , M6N3STAyi , M6N3STAzi , M6N3STVxi , M6N3STVyi , & - M6N3STVzi , M6N3Vxi , M6N3Vyi , M6N3Vzi , M6N4Axi , M6N4Ayi , M6N4Azi , M6N4DynP , M6N4FAFxi , M6N4FAFyi , & - M6N4FAFzi , M6N4FAGxi , M6N4FAGyi , M6N4FAGzi , M6N4FAMxi , M6N4FAMyi , M6N4FAMzi , M6N4FAxi , M6N4FAyi , M6N4FAzi , & - M6N4FBFxi , M6N4FBFyi , M6N4FBFzi , M6N4FBxi , M6N4FByi , M6N4FBzi , M6N4FDxi , M6N4FDyi , M6N4FDzi , M6N4FIxi , & - M6N4FIyi , M6N4FIzi , M6N4FMGxi , M6N4FMGyi , M6N4FMGzi , M6N4MBFxi , M6N4MBFyi , M6N4MBFzi , M6N4MBxi , M6N4MByi , & - M6N4MBzi , M6N4STAxi , M6N4STAyi , M6N4STAzi , M6N4STVxi , M6N4STVyi , M6N4STVzi , M6N4Vxi , M6N4Vyi , M6N4Vzi , & - M6N5Axi , M6N5Ayi , M6N5Azi , M6N5DynP , M6N5FAFxi , M6N5FAFyi , M6N5FAFzi , M6N5FAGxi , M6N5FAGyi , M6N5FAGzi , & - M6N5FAMxi , M6N5FAMyi , M6N5FAMzi , M6N5FAxi , M6N5FAyi , M6N5FAzi , M6N5FBFxi , M6N5FBFyi , M6N5FBFzi , M6N5FBxi , & - M6N5FByi , M6N5FBzi , M6N5FDxi , M6N5FDyi , M6N5FDzi , M6N5FIxi , M6N5FIyi , M6N5FIzi , M6N5FMGxi , M6N5FMGyi , & - M6N5FMGzi , M6N5MBFxi , M6N5MBFyi , M6N5MBFzi , M6N5MBxi , M6N5MByi , M6N5MBzi , M6N5STAxi , M6N5STAyi , M6N5STAzi , & - M6N5STVxi , M6N5STVyi , M6N5STVzi , M6N5Vxi , M6N5Vyi , M6N5Vzi , M6N6Axi , M6N6Ayi , M6N6Azi , M6N6DynP , & - M6N6FAFxi , M6N6FAFyi , M6N6FAFzi , M6N6FAGxi , M6N6FAGyi , M6N6FAGzi , M6N6FAMxi , M6N6FAMyi , M6N6FAMzi , M6N6FAxi , & - M6N6FAyi , M6N6FAzi , M6N6FBFxi , M6N6FBFyi , M6N6FBFzi , M6N6FBxi , M6N6FByi , M6N6FBzi , M6N6FDxi , M6N6FDyi , & - M6N6FDzi , M6N6FIxi , M6N6FIyi , M6N6FIzi , M6N6FMGxi , M6N6FMGyi , M6N6FMGzi , M6N6MBFxi , M6N6MBFyi , M6N6MBFzi , & - M6N6MBxi , M6N6MByi , M6N6MBzi , M6N6STAxi , M6N6STAyi , M6N6STAzi , M6N6STVxi , M6N6STVyi , M6N6STVzi , M6N6Vxi , & - M6N6Vyi , M6N6Vzi , M6N7Axi , M6N7Ayi , M6N7Azi , M6N7DynP , M6N7FAFxi , M6N7FAFyi , M6N7FAFzi , M6N7FAGxi , & - M6N7FAGyi , M6N7FAGzi , M6N7FAMxi , M6N7FAMyi , M6N7FAMzi , M6N7FAxi , M6N7FAyi , M6N7FAzi , M6N7FBFxi , M6N7FBFyi , & - M6N7FBFzi , M6N7FBxi , M6N7FByi , M6N7FBzi , M6N7FDxi , M6N7FDyi , M6N7FDzi , M6N7FIxi , M6N7FIyi , M6N7FIzi , & - M6N7FMGxi , M6N7FMGyi , M6N7FMGzi , M6N7MBFxi , M6N7MBFyi , M6N7MBFzi , M6N7MBxi , M6N7MByi , M6N7MBzi , M6N7STAxi , & - M6N7STAyi , M6N7STAzi , M6N7STVxi , M6N7STVyi , M6N7STVzi , M6N7Vxi , M6N7Vyi , M6N7Vzi , M6N8Axi , M6N8Ayi , & - M6N8Azi , M6N8DynP , M6N8FAFxi , M6N8FAFyi , M6N8FAFzi , M6N8FAGxi , M6N8FAGyi , M6N8FAGzi , M6N8FAMxi , M6N8FAMyi , & - M6N8FAMzi , M6N8FAxi , M6N8FAyi , M6N8FAzi , M6N8FBFxi , M6N8FBFyi , M6N8FBFzi , M6N8FBxi , M6N8FByi , M6N8FBzi , & - M6N8FDxi , M6N8FDyi , M6N8FDzi , M6N8FIxi , M6N8FIyi , M6N8FIzi , M6N8FMGxi , M6N8FMGyi , M6N8FMGzi , M6N8MBFxi , & - M6N8MBFyi , M6N8MBFzi , M6N8MBxi , M6N8MByi , M6N8MBzi , M6N8STAxi , M6N8STAyi , M6N8STAzi , M6N8STVxi , M6N8STVyi , & - M6N8STVzi , M6N8Vxi , M6N8Vyi , M6N8Vzi , M6N9Axi , M6N9Ayi , M6N9Azi , M6N9DynP , M6N9FAFxi , M6N9FAFyi , & - M6N9FAFzi , M6N9FAGxi , M6N9FAGyi , M6N9FAGzi , M6N9FAMxi , M6N9FAMyi , M6N9FAMzi , M6N9FAxi , M6N9FAyi , M6N9FAzi , & - M6N9FBFxi , M6N9FBFyi , M6N9FBFzi , M6N9FBxi , M6N9FByi , M6N9FBzi , M6N9FDxi , M6N9FDyi , M6N9FDzi , M6N9FIxi , & - M6N9FIyi , M6N9FIzi , M6N9FMGxi , M6N9FMGyi , M6N9FMGzi , M6N9MBFxi , M6N9MBFyi , M6N9MBFzi , M6N9MBxi , M6N9MByi , & - M6N9MBzi , M6N9STAxi , M6N9STAyi , M6N9STAzi , M6N9STVxi , M6N9STVyi , M6N9STVzi , M6N9Vxi , M6N9Vyi , M6N9Vzi , & - M7N1Axi , M7N1Ayi , M7N1Azi , M7N1DynP , M7N1FAFxi , M7N1FAFyi , M7N1FAFzi , M7N1FAGxi , M7N1FAGyi , M7N1FAGzi , & - M7N1FAMxi , M7N1FAMyi , M7N1FAMzi , M7N1FAxi , M7N1FAyi , M7N1FAzi , M7N1FBFxi , M7N1FBFyi , M7N1FBFzi , M7N1FBxi , & - M7N1FByi , M7N1FBzi , M7N1FDxi , M7N1FDyi , M7N1FDzi , M7N1FIxi , M7N1FIyi , M7N1FIzi , M7N1FMGxi , M7N1FMGyi , & - M7N1FMGzi , M7N1MBFxi , M7N1MBFyi , M7N1MBFzi , M7N1MBxi , M7N1MByi , M7N1MBzi , M7N1STAxi , M7N1STAyi , M7N1STAzi , & - M7N1STVxi , M7N1STVyi , M7N1STVzi , M7N1Vxi , M7N1Vyi , M7N1Vzi , M7N2Axi , M7N2Ayi , M7N2Azi , M7N2DynP , & - M7N2FAFxi , M7N2FAFyi , M7N2FAFzi , M7N2FAGxi , M7N2FAGyi , M7N2FAGzi , M7N2FAMxi , M7N2FAMyi , M7N2FAMzi , M7N2FAxi , & - M7N2FAyi , M7N2FAzi , M7N2FBFxi , M7N2FBFyi , M7N2FBFzi , M7N2FBxi , M7N2FByi , M7N2FBzi , M7N2FDxi , M7N2FDyi , & - M7N2FDzi , M7N2FIxi , M7N2FIyi , M7N2FIzi , M7N2FMGxi , M7N2FMGyi , M7N2FMGzi , M7N2MBFxi , M7N2MBFyi , M7N2MBFzi , & - M7N2MBxi , M7N2MByi , M7N2MBzi , M7N2STAxi , M7N2STAyi , M7N2STAzi , M7N2STVxi , M7N2STVyi , M7N2STVzi , M7N2Vxi , & - M7N2Vyi , M7N2Vzi , M7N3Axi , M7N3Ayi , M7N3Azi , M7N3DynP , M7N3FAFxi , M7N3FAFyi , M7N3FAFzi , M7N3FAGxi , & - M7N3FAGyi , M7N3FAGzi , M7N3FAMxi , M7N3FAMyi , M7N3FAMzi , M7N3FAxi , M7N3FAyi , M7N3FAzi , M7N3FBFxi , M7N3FBFyi , & - M7N3FBFzi , M7N3FBxi , M7N3FByi , M7N3FBzi , M7N3FDxi , M7N3FDyi , M7N3FDzi , M7N3FIxi , M7N3FIyi , M7N3FIzi , & - M7N3FMGxi , M7N3FMGyi , M7N3FMGzi , M7N3MBFxi , M7N3MBFyi , M7N3MBFzi , M7N3MBxi , M7N3MByi , M7N3MBzi , M7N3STAxi , & - M7N3STAyi , M7N3STAzi , M7N3STVxi , M7N3STVyi , M7N3STVzi , M7N3Vxi , M7N3Vyi , M7N3Vzi , M7N4Axi , M7N4Ayi , & - M7N4Azi , M7N4DynP , M7N4FAFxi , M7N4FAFyi , M7N4FAFzi , M7N4FAGxi , M7N4FAGyi , M7N4FAGzi , M7N4FAMxi , M7N4FAMyi , & - M7N4FAMzi , M7N4FAxi , M7N4FAyi , M7N4FAzi , M7N4FBFxi , M7N4FBFyi , M7N4FBFzi , M7N4FBxi , M7N4FByi , M7N4FBzi , & - M7N4FDxi , M7N4FDyi , M7N4FDzi , M7N4FIxi , M7N4FIyi , M7N4FIzi , M7N4FMGxi , M7N4FMGyi , M7N4FMGzi , M7N4MBFxi , & - M7N4MBFyi , M7N4MBFzi , M7N4MBxi , M7N4MByi , M7N4MBzi , M7N4STAxi , M7N4STAyi , M7N4STAzi , M7N4STVxi , M7N4STVyi , & - M7N4STVzi , M7N4Vxi , M7N4Vyi , M7N4Vzi , M7N5Axi , M7N5Ayi , M7N5Azi , M7N5DynP , M7N5FAFxi , M7N5FAFyi , & - M7N5FAFzi , M7N5FAGxi , M7N5FAGyi , M7N5FAGzi , M7N5FAMxi , M7N5FAMyi , M7N5FAMzi , M7N5FAxi , M7N5FAyi , M7N5FAzi , & - M7N5FBFxi , M7N5FBFyi , M7N5FBFzi , M7N5FBxi , M7N5FByi , M7N5FBzi , M7N5FDxi , M7N5FDyi , M7N5FDzi , M7N5FIxi , & - M7N5FIyi , M7N5FIzi , M7N5FMGxi , M7N5FMGyi , M7N5FMGzi , M7N5MBFxi , M7N5MBFyi , M7N5MBFzi , M7N5MBxi , M7N5MByi , & - M7N5MBzi , M7N5STAxi , M7N5STAyi , M7N5STAzi , M7N5STVxi , M7N5STVyi , M7N5STVzi , M7N5Vxi , M7N5Vyi , M7N5Vzi , & - M7N6Axi , M7N6Ayi , M7N6Azi , M7N6DynP , M7N6FAFxi , M7N6FAFyi , M7N6FAFzi , M7N6FAGxi , M7N6FAGyi , M7N6FAGzi , & - M7N6FAMxi , M7N6FAMyi , M7N6FAMzi , M7N6FAxi , M7N6FAyi , M7N6FAzi , M7N6FBFxi , M7N6FBFyi , M7N6FBFzi , M7N6FBxi , & - M7N6FByi , M7N6FBzi , M7N6FDxi , M7N6FDyi , M7N6FDzi , M7N6FIxi , M7N6FIyi , M7N6FIzi , M7N6FMGxi , M7N6FMGyi , & - M7N6FMGzi , M7N6MBFxi , M7N6MBFyi , M7N6MBFzi , M7N6MBxi , M7N6MByi , M7N6MBzi , M7N6STAxi , M7N6STAyi , M7N6STAzi , & - M7N6STVxi , M7N6STVyi , M7N6STVzi , M7N6Vxi , M7N6Vyi , M7N6Vzi , M7N7Axi , M7N7Ayi , M7N7Azi , M7N7DynP , & - M7N7FAFxi , M7N7FAFyi , M7N7FAFzi , M7N7FAGxi , M7N7FAGyi , M7N7FAGzi , M7N7FAMxi , M7N7FAMyi , M7N7FAMzi , M7N7FAxi , & - M7N7FAyi , M7N7FAzi , M7N7FBFxi , M7N7FBFyi , M7N7FBFzi , M7N7FBxi , M7N7FByi , M7N7FBzi , M7N7FDxi , M7N7FDyi , & - M7N7FDzi , M7N7FIxi , M7N7FIyi , M7N7FIzi , M7N7FMGxi , M7N7FMGyi , M7N7FMGzi , M7N7MBFxi , M7N7MBFyi , M7N7MBFzi , & - M7N7MBxi , M7N7MByi , M7N7MBzi , M7N7STAxi , M7N7STAyi , M7N7STAzi , M7N7STVxi , M7N7STVyi , M7N7STVzi , M7N7Vxi , & - M7N7Vyi , M7N7Vzi , M7N8Axi , M7N8Ayi , M7N8Azi , M7N8DynP , M7N8FAFxi , M7N8FAFyi , M7N8FAFzi , M7N8FAGxi , & - M7N8FAGyi , M7N8FAGzi , M7N8FAMxi , M7N8FAMyi , M7N8FAMzi , M7N8FAxi , M7N8FAyi , M7N8FAzi , M7N8FBFxi , M7N8FBFyi , & - M7N8FBFzi , M7N8FBxi , M7N8FByi , M7N8FBzi , M7N8FDxi , M7N8FDyi , M7N8FDzi , M7N8FIxi , M7N8FIyi , M7N8FIzi , & - M7N8FMGxi , M7N8FMGyi , M7N8FMGzi , M7N8MBFxi , M7N8MBFyi , M7N8MBFzi , M7N8MBxi , M7N8MByi , M7N8MBzi , M7N8STAxi , & - M7N8STAyi , M7N8STAzi , M7N8STVxi , M7N8STVyi , M7N8STVzi , M7N8Vxi , M7N8Vyi , M7N8Vzi , M7N9Axi , M7N9Ayi , & - M7N9Azi , M7N9DynP , M7N9FAFxi , M7N9FAFyi , M7N9FAFzi , M7N9FAGxi , M7N9FAGyi , M7N9FAGzi , M7N9FAMxi , M7N9FAMyi , & - M7N9FAMzi , M7N9FAxi , M7N9FAyi , M7N9FAzi , M7N9FBFxi , M7N9FBFyi , M7N9FBFzi , M7N9FBxi , M7N9FByi , M7N9FBzi , & - M7N9FDxi , M7N9FDyi , M7N9FDzi , M7N9FIxi , M7N9FIyi , M7N9FIzi , M7N9FMGxi , M7N9FMGyi , M7N9FMGzi , M7N9MBFxi , & - M7N9MBFyi , M7N9MBFzi , M7N9MBxi , M7N9MByi , M7N9MBzi , M7N9STAxi , M7N9STAyi , M7N9STAzi , M7N9STVxi , M7N9STVyi , & - M7N9STVzi , M7N9Vxi , M7N9Vyi , M7N9Vzi , M8N1Axi , M8N1Ayi , M8N1Azi , M8N1DynP , M8N1FAFxi , M8N1FAFyi , & - M8N1FAFzi , M8N1FAGxi , M8N1FAGyi , M8N1FAGzi , M8N1FAMxi , M8N1FAMyi , M8N1FAMzi , M8N1FAxi , M8N1FAyi , M8N1FAzi , & - M8N1FBFxi , M8N1FBFyi , M8N1FBFzi , M8N1FBxi , M8N1FByi , M8N1FBzi , M8N1FDxi , M8N1FDyi , M8N1FDzi , M8N1FIxi , & - M8N1FIyi , M8N1FIzi , M8N1FMGxi , M8N1FMGyi , M8N1FMGzi , M8N1MBFxi , M8N1MBFyi , M8N1MBFzi , M8N1MBxi , M8N1MByi , & - M8N1MBzi , M8N1STAxi , M8N1STAyi , M8N1STAzi , M8N1STVxi , M8N1STVyi , M8N1STVzi , M8N1Vxi , M8N1Vyi , M8N1Vzi , & - M8N2Axi , M8N2Ayi , M8N2Azi , M8N2DynP , M8N2FAFxi , M8N2FAFyi , M8N2FAFzi , M8N2FAGxi , M8N2FAGyi , M8N2FAGzi , & - M8N2FAMxi , M8N2FAMyi , M8N2FAMzi , M8N2FAxi , M8N2FAyi , M8N2FAzi , M8N2FBFxi , M8N2FBFyi , M8N2FBFzi , M8N2FBxi , & - M8N2FByi , M8N2FBzi , M8N2FDxi , M8N2FDyi , M8N2FDzi , M8N2FIxi , M8N2FIyi , M8N2FIzi , M8N2FMGxi , M8N2FMGyi , & - M8N2FMGzi , M8N2MBFxi , M8N2MBFyi , M8N2MBFzi , M8N2MBxi , M8N2MByi , M8N2MBzi , M8N2STAxi , M8N2STAyi , M8N2STAzi , & - M8N2STVxi , M8N2STVyi , M8N2STVzi , M8N2Vxi , M8N2Vyi , M8N2Vzi , M8N3Axi , M8N3Ayi , M8N3Azi , M8N3DynP , & - M8N3FAFxi , M8N3FAFyi , M8N3FAFzi , M8N3FAGxi , M8N3FAGyi , M8N3FAGzi , M8N3FAMxi , M8N3FAMyi , M8N3FAMzi , M8N3FAxi , & - M8N3FAyi , M8N3FAzi , M8N3FBFxi , M8N3FBFyi , M8N3FBFzi , M8N3FBxi , M8N3FByi , M8N3FBzi , M8N3FDxi , M8N3FDyi , & - M8N3FDzi , M8N3FIxi , M8N3FIyi , M8N3FIzi , M8N3FMGxi , M8N3FMGyi , M8N3FMGzi , M8N3MBFxi , M8N3MBFyi , M8N3MBFzi , & - M8N3MBxi , M8N3MByi , M8N3MBzi , M8N3STAxi , M8N3STAyi , M8N3STAzi , M8N3STVxi , M8N3STVyi , M8N3STVzi , M8N3Vxi , & - M8N3Vyi , M8N3Vzi , M8N4Axi , M8N4Ayi , M8N4Azi , M8N4DynP , M8N4FAFxi , M8N4FAFyi , M8N4FAFzi , M8N4FAGxi , & - M8N4FAGyi , M8N4FAGzi , M8N4FAMxi , M8N4FAMyi , M8N4FAMzi , M8N4FAxi , M8N4FAyi , M8N4FAzi , M8N4FBFxi , M8N4FBFyi , & - M8N4FBFzi , M8N4FBxi , M8N4FByi , M8N4FBzi , M8N4FDxi , M8N4FDyi , M8N4FDzi , M8N4FIxi , M8N4FIyi , M8N4FIzi , & - M8N4FMGxi , M8N4FMGyi , M8N4FMGzi , M8N4MBFxi , M8N4MBFyi , M8N4MBFzi , M8N4MBxi , M8N4MByi , M8N4MBzi , M8N4STAxi , & - M8N4STAyi , M8N4STAzi , M8N4STVxi , M8N4STVyi , M8N4STVzi , M8N4Vxi , M8N4Vyi , M8N4Vzi , M8N5Axi , M8N5Ayi , & - M8N5Azi , M8N5DynP , M8N5FAFxi , M8N5FAFyi , M8N5FAFzi , M8N5FAGxi , M8N5FAGyi , M8N5FAGzi , M8N5FAMxi , M8N5FAMyi , & - M8N5FAMzi , M8N5FAxi , M8N5FAyi , M8N5FAzi , M8N5FBFxi , M8N5FBFyi , M8N5FBFzi , M8N5FBxi , M8N5FByi , M8N5FBzi , & - M8N5FDxi , M8N5FDyi , M8N5FDzi , M8N5FIxi , M8N5FIyi , M8N5FIzi , M8N5FMGxi , M8N5FMGyi , M8N5FMGzi , M8N5MBFxi , & - M8N5MBFyi , M8N5MBFzi , M8N5MBxi , M8N5MByi , M8N5MBzi , M8N5STAxi , M8N5STAyi , M8N5STAzi , M8N5STVxi , M8N5STVyi , & - M8N5STVzi , M8N5Vxi , M8N5Vyi , M8N5Vzi , M8N6Axi , M8N6Ayi , M8N6Azi , M8N6DynP , M8N6FAFxi , M8N6FAFyi , & - M8N6FAFzi , M8N6FAGxi , M8N6FAGyi , M8N6FAGzi , M8N6FAMxi , M8N6FAMyi , M8N6FAMzi , M8N6FAxi , M8N6FAyi , M8N6FAzi , & - M8N6FBFxi , M8N6FBFyi , M8N6FBFzi , M8N6FBxi , M8N6FByi , M8N6FBzi , M8N6FDxi , M8N6FDyi , M8N6FDzi , M8N6FIxi , & - M8N6FIyi , M8N6FIzi , M8N6FMGxi , M8N6FMGyi , M8N6FMGzi , M8N6MBFxi , M8N6MBFyi , M8N6MBFzi , M8N6MBxi , M8N6MByi , & - M8N6MBzi , M8N6STAxi , M8N6STAyi , M8N6STAzi , M8N6STVxi , M8N6STVyi , M8N6STVzi , M8N6Vxi , M8N6Vyi , M8N6Vzi , & - M8N7Axi , M8N7Ayi , M8N7Azi , M8N7DynP , M8N7FAFxi , M8N7FAFyi , M8N7FAFzi , M8N7FAGxi , M8N7FAGyi , M8N7FAGzi , & - M8N7FAMxi , M8N7FAMyi , M8N7FAMzi , M8N7FAxi , M8N7FAyi , M8N7FAzi , M8N7FBFxi , M8N7FBFyi , M8N7FBFzi , M8N7FBxi , & - M8N7FByi , M8N7FBzi , M8N7FDxi , M8N7FDyi , M8N7FDzi , M8N7FIxi , M8N7FIyi , M8N7FIzi , M8N7FMGxi , M8N7FMGyi , & - M8N7FMGzi , M8N7MBFxi , M8N7MBFyi , M8N7MBFzi , M8N7MBxi , M8N7MByi , M8N7MBzi , M8N7STAxi , M8N7STAyi , M8N7STAzi , & - M8N7STVxi , M8N7STVyi , M8N7STVzi , M8N7Vxi , M8N7Vyi , M8N7Vzi , M8N8Axi , M8N8Ayi , M8N8Azi , M8N8DynP , & - M8N8FAFxi , M8N8FAFyi , M8N8FAFzi , M8N8FAGxi , M8N8FAGyi , M8N8FAGzi , M8N8FAMxi , M8N8FAMyi , M8N8FAMzi , M8N8FAxi , & - M8N8FAyi , M8N8FAzi , M8N8FBFxi , M8N8FBFyi , M8N8FBFzi , M8N8FBxi , M8N8FByi , M8N8FBzi , M8N8FDxi , M8N8FDyi , & - M8N8FDzi , M8N8FIxi , M8N8FIyi , M8N8FIzi , M8N8FMGxi , M8N8FMGyi , M8N8FMGzi , M8N8MBFxi , M8N8MBFyi , M8N8MBFzi , & - M8N8MBxi , M8N8MByi , M8N8MBzi , M8N8STAxi , M8N8STAyi , M8N8STAzi , M8N8STVxi , M8N8STVyi , M8N8STVzi , M8N8Vxi , & - M8N8Vyi , M8N8Vzi , M8N9Axi , M8N9Ayi , M8N9Azi , M8N9DynP , M8N9FAFxi , M8N9FAFyi , M8N9FAFzi , M8N9FAGxi , & - M8N9FAGyi , M8N9FAGzi , M8N9FAMxi , M8N9FAMyi , M8N9FAMzi , M8N9FAxi , M8N9FAyi , M8N9FAzi , M8N9FBFxi , M8N9FBFyi , & - M8N9FBFzi , M8N9FBxi , M8N9FByi , M8N9FBzi , M8N9FDxi , M8N9FDyi , M8N9FDzi , M8N9FIxi , M8N9FIyi , M8N9FIzi , & - M8N9FMGxi , M8N9FMGyi , M8N9FMGzi , M8N9MBFxi , M8N9MBFyi , M8N9MBFzi , M8N9MBxi , M8N9MByi , M8N9MBzi , M8N9STAxi , & - M8N9STAyi , M8N9STAzi , M8N9STVxi , M8N9STVyi , M8N9STVzi , M8N9Vxi , M8N9Vyi , M8N9Vzi , M9N1Axi , M9N1Ayi , & - M9N1Azi , M9N1DynP , M9N1FAFxi , M9N1FAFyi , M9N1FAFzi , M9N1FAGxi , M9N1FAGyi , M9N1FAGzi , M9N1FAMxi , M9N1FAMyi , & - M9N1FAMzi , M9N1FAxi , M9N1FAyi , M9N1FAzi , M9N1FBFxi , M9N1FBFyi , M9N1FBFzi , M9N1FBxi , M9N1FByi , M9N1FBzi , & - M9N1FDxi , M9N1FDyi , M9N1FDzi , M9N1FIxi , M9N1FIyi , M9N1FIzi , M9N1FMGxi , M9N1FMGyi , M9N1FMGzi , M9N1MBFxi , & - M9N1MBFyi , M9N1MBFzi , M9N1MBxi , M9N1MByi , M9N1MBzi , M9N1STAxi , M9N1STAyi , M9N1STAzi , M9N1STVxi , M9N1STVyi , & - M9N1STVzi , M9N1Vxi , M9N1Vyi , M9N1Vzi , M9N2Axi , M9N2Ayi , M9N2Azi , M9N2DynP , M9N2FAFxi , M9N2FAFyi , & - M9N2FAFzi , M9N2FAGxi , M9N2FAGyi , M9N2FAGzi , M9N2FAMxi , M9N2FAMyi , M9N2FAMzi , M9N2FAxi , M9N2FAyi , M9N2FAzi , & - M9N2FBFxi , M9N2FBFyi , M9N2FBFzi , M9N2FBxi , M9N2FByi , M9N2FBzi , M9N2FDxi , M9N2FDyi , M9N2FDzi , M9N2FIxi , & - M9N2FIyi , M9N2FIzi , M9N2FMGxi , M9N2FMGyi , M9N2FMGzi , M9N2MBFxi , M9N2MBFyi , M9N2MBFzi , M9N2MBxi , M9N2MByi , & - M9N2MBzi , M9N2STAxi , M9N2STAyi , M9N2STAzi , M9N2STVxi , M9N2STVyi , M9N2STVzi , M9N2Vxi , M9N2Vyi , M9N2Vzi , & - M9N3Axi , M9N3Ayi , M9N3Azi , M9N3DynP , M9N3FAFxi , M9N3FAFyi , M9N3FAFzi , M9N3FAGxi , M9N3FAGyi , M9N3FAGzi , & - M9N3FAMxi , M9N3FAMyi , M9N3FAMzi , M9N3FAxi , M9N3FAyi , M9N3FAzi , M9N3FBFxi , M9N3FBFyi , M9N3FBFzi , M9N3FBxi , & - M9N3FByi , M9N3FBzi , M9N3FDxi , M9N3FDyi , M9N3FDzi , M9N3FIxi , M9N3FIyi , M9N3FIzi , M9N3FMGxi , M9N3FMGyi , & - M9N3FMGzi , M9N3MBFxi , M9N3MBFyi , M9N3MBFzi , M9N3MBxi , M9N3MByi , M9N3MBzi , M9N3STAxi , M9N3STAyi , M9N3STAzi , & - M9N3STVxi , M9N3STVyi , M9N3STVzi , M9N3Vxi , M9N3Vyi , M9N3Vzi , M9N4Axi , M9N4Ayi , M9N4Azi , M9N4DynP , & - M9N4FAFxi , M9N4FAFyi , M9N4FAFzi , M9N4FAGxi , M9N4FAGyi , M9N4FAGzi , M9N4FAMxi , M9N4FAMyi , M9N4FAMzi , M9N4FAxi , & - M9N4FAyi , M9N4FAzi , M9N4FBFxi , M9N4FBFyi , M9N4FBFzi , M9N4FBxi , M9N4FByi , M9N4FBzi , M9N4FDxi , M9N4FDyi , & - M9N4FDzi , M9N4FIxi , M9N4FIyi , M9N4FIzi , M9N4FMGxi , M9N4FMGyi , M9N4FMGzi , M9N4MBFxi , M9N4MBFyi , M9N4MBFzi , & - M9N4MBxi , M9N4MByi , M9N4MBzi , M9N4STAxi , M9N4STAyi , M9N4STAzi , M9N4STVxi , M9N4STVyi , M9N4STVzi , M9N4Vxi , & - M9N4Vyi , M9N4Vzi , M9N5Axi , M9N5Ayi , M9N5Azi , M9N5DynP , M9N5FAFxi , M9N5FAFyi , M9N5FAFzi , M9N5FAGxi , & - M9N5FAGyi , M9N5FAGzi , M9N5FAMxi , M9N5FAMyi , M9N5FAMzi , M9N5FAxi , M9N5FAyi , M9N5FAzi , M9N5FBFxi , M9N5FBFyi , & - M9N5FBFzi , M9N5FBxi , M9N5FByi , M9N5FBzi , M9N5FDxi , M9N5FDyi , M9N5FDzi , M9N5FIxi , M9N5FIyi , M9N5FIzi , & - M9N5FMGxi , M9N5FMGyi , M9N5FMGzi , M9N5MBFxi , M9N5MBFyi , M9N5MBFzi , M9N5MBxi , M9N5MByi , M9N5MBzi , M9N5STAxi , & - M9N5STAyi , M9N5STAzi , M9N5STVxi , M9N5STVyi , M9N5STVzi , M9N5Vxi , M9N5Vyi , M9N5Vzi , M9N6Axi , M9N6Ayi , & - M9N6Azi , M9N6DynP , M9N6FAFxi , M9N6FAFyi , M9N6FAFzi , M9N6FAGxi , M9N6FAGyi , M9N6FAGzi , M9N6FAMxi , M9N6FAMyi , & - M9N6FAMzi , M9N6FAxi , M9N6FAyi , M9N6FAzi , M9N6FBFxi , M9N6FBFyi , M9N6FBFzi , M9N6FBxi , M9N6FByi , M9N6FBzi , & - M9N6FDxi , M9N6FDyi , M9N6FDzi , M9N6FIxi , M9N6FIyi , M9N6FIzi , M9N6FMGxi , M9N6FMGyi , M9N6FMGzi , M9N6MBFxi , & - M9N6MBFyi , M9N6MBFzi , M9N6MBxi , M9N6MByi , M9N6MBzi , M9N6STAxi , M9N6STAyi , M9N6STAzi , M9N6STVxi , M9N6STVyi , & - M9N6STVzi , M9N6Vxi , M9N6Vyi , M9N6Vzi , M9N7Axi , M9N7Ayi , M9N7Azi , M9N7DynP , M9N7FAFxi , M9N7FAFyi , & - M9N7FAFzi , M9N7FAGxi , M9N7FAGyi , M9N7FAGzi , M9N7FAMxi , M9N7FAMyi , M9N7FAMzi , M9N7FAxi , M9N7FAyi , M9N7FAzi , & - M9N7FBFxi , M9N7FBFyi , M9N7FBFzi , M9N7FBxi , M9N7FByi , M9N7FBzi , M9N7FDxi , M9N7FDyi , M9N7FDzi , M9N7FIxi , & - M9N7FIyi , M9N7FIzi , M9N7FMGxi , M9N7FMGyi , M9N7FMGzi , M9N7MBFxi , M9N7MBFyi , M9N7MBFzi , M9N7MBxi , M9N7MByi , & - M9N7MBzi , M9N7STAxi , M9N7STAyi , M9N7STAzi , M9N7STVxi , M9N7STVyi , M9N7STVzi , M9N7Vxi , M9N7Vyi , M9N7Vzi , & - M9N8Axi , M9N8Ayi , M9N8Azi , M9N8DynP , M9N8FAFxi , M9N8FAFyi , M9N8FAFzi , M9N8FAGxi , M9N8FAGyi , M9N8FAGzi , & - M9N8FAMxi , M9N8FAMyi , M9N8FAMzi , M9N8FAxi , M9N8FAyi , M9N8FAzi , M9N8FBFxi , M9N8FBFyi , M9N8FBFzi , M9N8FBxi , & - M9N8FByi , M9N8FBzi , M9N8FDxi , M9N8FDyi , M9N8FDzi , M9N8FIxi , M9N8FIyi , M9N8FIzi , M9N8FMGxi , M9N8FMGyi , & - M9N8FMGzi , M9N8MBFxi , M9N8MBFyi , M9N8MBFzi , M9N8MBxi , M9N8MByi , M9N8MBzi , M9N8STAxi , M9N8STAyi , M9N8STAzi , & - M9N8STVxi , M9N8STVyi , M9N8STVzi , M9N8Vxi , M9N8Vyi , M9N8Vzi , M9N9Axi , M9N9Ayi , M9N9Azi , M9N9DynP , & - M9N9FAFxi , M9N9FAFyi , M9N9FAFzi , M9N9FAGxi , M9N9FAGyi , M9N9FAGzi , M9N9FAMxi , M9N9FAMyi , M9N9FAMzi , M9N9FAxi , & - M9N9FAyi , M9N9FAzi , M9N9FBFxi , M9N9FBFyi , M9N9FBFzi , M9N9FBxi , M9N9FByi , M9N9FBzi , M9N9FDxi , M9N9FDyi , & - M9N9FDzi , M9N9FIxi , M9N9FIyi , M9N9FIzi , M9N9FMGxi , M9N9FMGyi , M9N9FMGzi , M9N9MBFxi , M9N9MBFyi , M9N9MBFzi , & - M9N9MBxi , M9N9MByi , M9N9MBzi , M9N9STAxi , M9N9STAyi , M9N9STAzi , M9N9STVxi , M9N9STVyi , M9N9STVzi , M9N9Vxi , & - M9N9Vyi , M9N9Vzi /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(4032) = (/ & ! This lists the units corresponding to the allowed parameters - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & - "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & - "(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & - "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & - "(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & - "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) "/) - + CHARACTER(OutStrLenM1) :: ValidParamAry(4599) ! This lists the names of the allowed parameters, which must be sorted alphabetically + INTEGER(IntKi) :: ParamIndxAry(4599) ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + CHARACTER(OutStrLenM1) :: ParamUnitsAry(4599) ! This lists the names of the allowed parameters, which must be sorted alphabetically + ! ..... Public Subroutines ................................................................................................... PUBLIC :: MrsnOut_MapOutputs @@ -6896,8 +6441,10 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg INTEGER :: I, J - INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location - REAL(ReKi) :: s ! The linear interpolation factor for the requested location + INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location + real(ReKi) :: mult1, mult2 ! Load multiplier for joint nodes vs interior nodes + real(ReKi) :: dl ! member element length (m) + REAL(ReKi) :: s ! The linear interpolation factor for the requested location ErrStat = ErrID_None @@ -6915,89 +6462,87 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg m1 = p%MOutLst(J)%Marker1(I) m2 = p%MOutLst(J)%Marker2(I) s = p%MOutLst(J)%s (I) - - ! The member output is computed as a linear interpolation of the nearest two markers + dl = p%Members(p%MOutLst(J)%MemberIDIndx)%dl + + ! The member output is computed as a linear interpolation of the nearest two member nodes + ! These nodes have the loads stored as concentrated loads, we will report per unit length versions of these loads + ! Member joint nodes will have their values doubled, interior member loads will not. + ! The concentrated load is then divided by the member's dl (element length) + if ( m1 <= p%NJoints ) then + mult1 = 2.0 + else + mult1 = 1.0 + end if + if ( m2 <= p%NJoints ) then + mult2 = 2.0 + else + mult2 = 1.0 + end if ! wave kinematics along the member - AllOuts(MNVi (:,I,J)) = m%D_FV (: ,m1)*(1-s) + m%D_FV (: ,m2)*s - AllOuts(MNAi (:,I,J)) = m%D_FA (: ,m1)*(1-s) + m%D_FA (: ,m2)*s - AllOuts(MNDynP( I,J)) = m%D_FDynP( m1)*(1-s) + m%D_FDynP( m2)*s + AllOuts(MNVi (:,I,J)) = m%FV (: ,m1)*(1-s) + m%FV (: ,m2)*s + AllOuts(MNAi (:,I,J)) = m%FA (: ,m1)*(1-s) + m%FA (: ,m2)*s + AllOuts(MNDynP( I,J)) = m%FDynP( m1)*(1-s) + m%FDynP( m2)*s ! Input motions - AllOuts(MNSTVi(:,I,J)) = u%DistribMesh%TranslationVel(: ,m1)*(1-s) + u%DistribMesh%TranslationVel(: ,m2)*s + AllOuts(MNSTVi(:,I,J)) = u%Mesh%TranslationVel(: ,m1)*(1-s) + u%Mesh%TranslationVel(: ,m2)*s ! AllOuts(MNSRVi(:,I,J)) = u%DistribMesh%RotationVel (: ,m1)*(1-s) + u%DistribMesh%RotationVel (: ,m2)*s - AllOuts(MNSTAi(:,I,J)) = u%DistribMesh%TranslationAcc(: ,m1)*(1-s) + u%DistribMesh%TranslationAcc(: ,m2)*s + AllOuts(MNSTAi(:,I,J)) = u%Mesh%TranslationAcc(: ,m1)*(1-s) + u%Mesh%TranslationAcc(: ,m2)*s ! AllOuts(MNSRAi(:,I,J)) = u%DistribMesh%RotationAcc (: ,m1)*(1-s) + u%DistribMesh%RotationAcc (: ,m2)*s ! transverse drag force - AllOuts(MNFDi (:,I,J)) = m%D_F_D (: ,m1)*(1-s) + m%D_F_D (: ,m2)*s - ! inertial force - AllOuts(MNFIi (:,I,J)) = m%D_F_I (: ,m1)*(1-s) + m%D_F_I (: ,m2)*s - - ! marine growth weight - AllOuts(MNFMGi(:,I,J)) = p%D_F_MG (1:3,m1)*(1-s) + p%D_F_MG (1:3,m2)*s - - ! buoyancy forces - AllOuts(MNFBi (:,I,J)) = m%D_F_B (1:3,m1)*(1-s) + m%D_F_B (1:3,m2)*s - AllOuts(MNFBFi(:,I,J)) = p%D_F_BF (1:3,m1)*(1-s) + p%D_F_BF (1:3,m2)*s - + AllOuts(MNFDi (:,I,J)) =(mult1*m%F_D (1:3,m1)*(1-s) + mult2*m%F_D (1:3,m2)*s)/dl + ! inertial force + AllOuts(MNFIi (:,I,J)) =(mult1*m%F_I (1:3,m1)*(1-s) + mult2*m%F_I (1:3,m2)*s)/dl + + ! marine growth weight + AllOuts(MNFMGi(:,I,J)) =(mult1*m%F_WMG (1:3,m1)*(1-s) + mult2*m%F_WMG(1:3,m2)*s)/dl + AllOuts(MNMMGi(:,I,J)) =(mult1*m%F_WMG (4:6,m1)*(1-s) + mult2*m%F_WMG(4:6,m2)*s)/dl + + ! buoyancy forces + AllOuts(MNFBi (:,I,J)) =(mult1*m%F_B (1:3,m1)*(1-s) + mult2*m%F_B (1:3,m2)*s)/dl + AllOuts(MNFBFi(:,I,J)) =(mult1*m%F_BF (1:3,m1)*(1-s) + mult2*m%F_BF (1:3,m2)*s)/dl + ! buoyancy moments - AllOuts(MNMBi (:,I,J)) = m%D_F_B (4:6,m1)*(1-s) + m%D_F_B (4:6,m2)*s - AllOuts(MNMBFi(:,I,J)) = p%D_F_BF (4:6,m1)*(1-s) + p%D_F_BF (4:6,m2)*s - - ! added mass forces - AllOuts(MNFAGi(:,I,J)) = m%D_F_AM_MG(:,m1)*(1-s) + m%D_F_AM_MG(:,m2)*s ! due to marine growth - AllOuts(MNFAMi (:,I,J)) = m%D_F_AM_M(: ,m1)*(1-s) + m%D_F_AM_M(: ,m2)*s ! due to the structural member moving the fluid - AllOuts(MNFAFi (:,I,J)) = m%D_F_AM_F(: ,m1)*(1-s) + m%D_F_AM_F(: ,m2)*s ! due to the ballasted/flooded fluid - AllOuts(MNFAi (:,I,J)) = m%D_F_AM(: ,m1)*(1-s) + m%D_F_AM(: ,m2)*s ! the combined added mass force - - + AllOuts(MNMBi (:,I,J)) =(mult1*m%F_B (4:6,m1)*(1-s) + mult2*m%F_B (4:6,m2)*s)/dl + AllOuts(MNMBFi(:,I,J)) =(mult1*m%F_BF (4:6,m1)*(1-s) + mult2*m%F_BF (4:6,m2)*s)/dl + + ! added mass forces + AllOuts(MNFAGi(:,I,J)) =(mult1*m%F_IMG (1:3,m1)*(1-s) + mult2*m%F_IMG(1:3,m2)*s)/dl ! due to marine growth + AllOuts(MNMAGi(:,I,J)) =(mult1*m%F_IMG (4:6,m1)*(1-s) + mult2*m%F_IMG(4:6,m2)*s)/dl + AllOuts(MNFAMi (:,I,J)) =(mult1*m%F_A (1:3,m1)*(1-s) + mult2*m%F_A (1:3,m2)*s)/dl ! due to the structural member moving the fluid + AllOuts(MNFAFi (:,I,J)) =(mult1*m%F_If (1:3,m1)*(1-s) + mult2*m%F_If(1:3 ,m2)*s)/dl ! due to the ballasted/flooded fluid + AllOuts(MNMAFi (:,I,J)) =(mult1*m%F_If (4:6,m1)*(1-s) + mult2*m%F_If(4:6 ,m2)*s)/dl + END DO END DO ! Only generate joint-based outputs for the number of user-requested joint outputs - DO I=1,p%NJOutputs - - ! Zero-out the channels because we will be accumulating results - AllOuts(JVi (:,I)) = 0.0 - AllOuts(JAi (:,I)) = 0.0 - AllOuts(JDynP( I)) = 0.0 - AllOuts(JSTVi (:,I)) = 0.0 - AllOuts(JSTAi (:,I)) = 0.0 - AllOuts(JFDi (:,I)) = 0.0 - AllOuts(JFIi (:,I)) = 0.0 - AllOuts(JFBi (:,I)) = 0.0 - AllOuts(JMBi (:,I)) = 0.0 - AllOuts(JFBFi(:,I)) = 0.0 - AllOuts(JMBFi(:,I)) = 0.0 - - AllOuts(JFAMi(:,I)) = 0.0 + DO I=1,p%NJOutputs - - ! Which of the lumped mesh marker does this Output Joint point to? - DO J=1,p%JOutLst(I)%NumMarkers - m1 = p%JOutlst(I)%Markers(J) + ! Which of the mesh nodes does this Output Joint point to? + m1 = p%JOutlst(I)%JointIDIndx - ! Do not accumulate the wave kinematics and structural kinematics quantities - IF ( J == 1 ) THEN - AllOuts(JVi (:,I)) = m%L_FV (1:3,m1) ! fluid velocity - AllOuts(JAi (:,I)) = m%L_FA (1:3,m1) ! fluid acceleration - AllOuts(JDynP( I)) = m%L_FDynP( m1) ! fluid dynamic pressure - AllOuts(JSTVi (:,I)) = u%LumpedMesh%TranslationVel(: ,m1) ! structural velocity - AllOuts(JSTAi (:,I)) = u%LumpedMesh%TranslationAcc(: ,m1) ! structural acceleration - END IF + + AllOuts(JVi (:,I)) = m%FV (1:3,m1) ! fluid velocity + AllOuts(JAi (:,I)) = m%FA (1:3,m1) ! fluid acceleration + AllOuts(JDynP( I)) = m%FDynP( m1) ! fluid dynamic pressure + AllOuts(JSTVi (:,I)) = u%Mesh%TranslationVel(: ,m1) ! structural velocity + AllOuts(JSTAi (:,I)) = u%Mesh%TranslationAcc(: ,m1) ! structural acceleration + + AllOuts(JFDi (:,I)) = m%F_D_End (1:3, m1) ! axial drag force + AllOuts(JFBi (:,I)) = m%F_B_End (1:3, m1) ! buoyancy force + AllOuts(JMBi (:,I)) = m%F_B_End (4:6, m1) ! buoyancy moment + AllOuts(JFBFi(:,I)) = m%F_BF_End(1:3, m1) ! ballasted/filled buoyancy force + AllOuts(JMBFi(:,I)) = m%F_BF_End(4:6, m1) ! ballasted/filled buoyancy moment + AllOuts(JFIi (:,I)) = m%F_I_End (1:3, m1) ! inertial force + AllOuts(JFAMi(:,I)) = m%F_A_End(1:3, m1) ! added mass force + AllOuts(JFAGi(:,I)) = m%F_IMG_End(1:3, m1) ! marine growth inertia + AllOuts(JMAGi(:,I)) = m%F_IMG_End(4:6, m1) ! marine growth inertia + AllOuts(JFMGi(:,I)) = p%F_WMG_End(1:3, m1) ! marine growth weight - AllOuts(JFDi (:,I)) = AllOuts(JFDi (:,I)) + m%L_F_D (1:3, m1) ! axial drag force - AllOuts(JFBi (:,I)) = AllOuts(JFBi (:,I)) + m%L_F_B (1:3, m1) ! buoyancy force - AllOuts(JMBi (:,I)) = AllOuts(JMBi (:,I)) + m%L_F_B (4:6, m1) ! buoyancy moment - AllOuts(JFBFi(:,I)) = AllOuts(JFBFi(:,I)) + p%L_F_BF(1:3, m1) ! ballasted/filled buoyancy force - AllOuts(JMBFi(:,I)) = AllOuts(JMBFi(:,I)) + p%L_F_BF(4:6, m1) ! ballasted/filled buoyancy moment - AllOuts(JFIi (:,I)) = AllOuts(JFIi(:,I)) + m%L_F_I (1:3, m1) ! inertial force - AllOuts(JFAMi(:,I)) = AllOuts(JFAMi(:,I)) + m%L_F_AM(1:3, m1) ! added mass force - - END DO END DO @@ -7219,12 +6764,9 @@ SUBROUTINE MrsnOut_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) END SUBROUTINE MrsnOut_WriteOutputs -SUBROUTINE GetNeighboringMarkers(memberIndx, d, numMarkers, nodes, distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) +SUBROUTINE GetNeighboringNodes(member, d, m1, m2, s, ErrStat, ErrMsg) - INTEGER, INTENT( IN ) :: numMarkers - TYPE(Morison_NodeType), INTENT( IN ) :: nodes(:) - INTEGER, INTENT( IN ) :: distribToNodeIndx(:) - INTEGER, INTENT( IN ) :: memberIndx + TYPE(Morison_MemberType), INTENT( IN ) :: member REAL(ReKi), INTENT( IN ) :: d INTEGER, INTENT( OUT ) :: m1 INTEGER, INTENT( OUT ) :: m2 @@ -7233,50 +6775,30 @@ SUBROUTINE GetNeighboringMarkers(memberIndx, d, numMarkers, nodes, distribToNode CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - INTEGER :: I - REAL(ReKi) :: dLess - REAL(ReKi) :: dGreater - TYPE(Morison_NodeType) :: node - - !TODO: This is not working correctly! Fix it now! - - - ! Find all nodes which have the desired memberIndx and then look for the ones with the smallest neg and pos distance from the target point + INTEGER :: i1, i2 + ErrStat = ErrID_None ErrMsg = '' - dLess = -1000000.0 - dGreater = 1000000.0 + ! This only works because the member nodes are equally spaced - DO I=1,numMarkers - node = nodes(distribToNodeIndx(I)) - IF ( node%InpMbrIndx == memberIndx ) THEN - - IF ( node%InpMbrDist >= d ) THEN - IF ( node%InpMbrDist < dGreater ) THEN - dGreater = node%InpMbrDist - m2 = I - END IF - END IF - IF ( node%InpMbrDist <= d ) THEN - IF ( node%InpMbrDist > dLess ) THEN - dLess = node%InpMbrDist - m1 = I - END IF - END IF - END IF - - - END DO + i1 = floor(member%NElements*d) ! 0<= d <= 1.0 - IF ( EqualRealNos(dGreater - dLess, 0.0_ReKi ) ) THEN - s = 0.0 - ELSE - s = (d - dLess ) / ( dGreater - dLess ) - END IF + if ( i1 == member%NElements ) then + ! special case when d = 1.0_ReKi + i2 = i1 + 1 + s = 1.0_ReKi + else + s = member%NElements*d - i1 ! here i1 is zero-based + i1 = i1 + 1 ! Shift to one-based indices + i2 = i1 + 1 + end if + + m1 = member%NodeIndx(i1) + m2 = member%NodeIndx(i2) -END SUBROUTINE GetNeighboringMarkers +END SUBROUTINE GetNeighboringNodes !==================================================================================================== @@ -7314,6 +6836,7 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" + !------------------------------------------------------------------------------------------------- ! Check that the variables in OutList are valid !------------------------------------------------------------------------------------------------- @@ -7354,7 +6877,9 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! Need to search mesh for the two markers which surround the requested output location and then store those marker indices and compute the ! scale factor based on how far they are from the requested output location. ! Since this is being done on markers and not nodes, the subroutine must be called after the Morison_Init() subroutine is called - CALL GetNeighboringMarkers(memberIndx, p%MOutLst(I)%NodeLocs(J), p%NDistribMarkers, p%Nodes, p%distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) + !TODO: Need to reimplement the following + CALL GetNeighboringNodes(p%Members(memberIndx), p%MOutLst(I)%NodeLocs(J), m1, m2, s, ErrStat, ErrMsg) + ! CALL GetNeighboringNodes(memberIndx, p%MOutLst(I)%NodeLocs(J), p%NDistribMarkers, p%Nodes, p%distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you ! want to index into the nodes array or wave kinematics arrays @@ -7366,23 +6891,7 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) END DO - - ! We need to map each Output Joint the user requested to the correct marker in the lumped mesh - - DO I=1,p%NJOutputs - - p%JOutlst(I)%NumMarkers = 0 - - DO J=1,p%NLumpedMarkers - IF ( p%Nodes(p%lumpedToNodeIndx(J))%JointIndx == p%JOutlst(I)%JointIDIndx ) THEN - p%JOutlst(I)%NumMarkers = p%JOutlst(I)%NumMarkers + 1 - p%JOutlst(I)%Markers(p%JOutlst(I)%NumMarkers) = J - END IF - END DO - - END DO - - + ! These variables are to help follow the framework template, but the data in them is simply a copy of data ! already available in the OutParam data structure @@ -7453,6 +6962,2029 @@ FUNCTION GetMorisonChannels ( NUserOutputs, UserOutputs, OutList, foundMask ErrStat = ErrID_None ErrMsg = "" + + ValidParamAry(1:500) = (/ & + "J1AXI ","J1AYI ","J1AZI ","J1DYNP ","J1FAGXI ","J1FAGYI ","J1FAGZI ", & + "J1FAMXI ","J1FAMYI ","J1FAMZI ","J1FBFXI ","J1FBFYI ","J1FBFZI ","J1FBXI ", & + "J1FBYI ","J1FBZI ","J1FDXI ","J1FDYI ","J1FDZI ","J1FIXI ","J1FIYI ", & + "J1FIZI ","J1FMGXI ","J1FMGYI ","J1FMGZI ","J1MAGXI ","J1MAGYI ","J1MAGZI ", & + "J1MBFXI ","J1MBFYI ","J1MBFZI ","J1MBXI ","J1MBYI ","J1MBZI ","J1STAXI ", & + "J1STAYI ","J1STAZI ","J1STVXI ","J1STVYI ","J1STVZI ","J1VXI ","J1VYI ", & + "J1VZI ","J2AXI ","J2AYI ","J2AZI ","J2DYNP ","J2FAGXI ","J2FAGYI ", & + "J2FAGZI ","J2FAMXI ","J2FAMYI ","J2FAMZI ","J2FBFXI ","J2FBFYI ","J2FBFZI ", & + "J2FBXI ","J2FBYI ","J2FBZI ","J2FDXI ","J2FDYI ","J2FDZI ","J2FIXI ", & + "J2FIYI ","J2FIZI ","J2FMGXI ","J2FMGYI ","J2FMGZI ","J2MAGXI ","J2MAGYI ", & + "J2MAGZI ","J2MBFXI ","J2MBFYI ","J2MBFZI ","J2MBXI ","J2MBYI ","J2MBZI ", & + "J2STAXI ","J2STAYI ","J2STAZI ","J2STVXI ","J2STVYI ","J2STVZI ","J2VXI ", & + "J2VYI ","J2VZI ","J3AXI ","J3AYI ","J3AZI ","J3DYNP ","J3FAGXI ", & + "J3FAGYI ","J3FAGZI ","J3FAMXI ","J3FAMYI ","J3FAMZI ","J3FBFXI ","J3FBFYI ", & + "J3FBFZI ","J3FBXI ","J3FBYI ","J3FBZI ","J3FDXI ","J3FDYI ","J3FDZI ", & + "J3FIXI ","J3FIYI ","J3FIZI ","J3FMGXI ","J3FMGYI ","J3FMGZI ","J3MAGXI ", & + "J3MAGYI ","J3MAGZI ","J3MBFXI ","J3MBFYI ","J3MBFZI ","J3MBXI ","J3MBYI ", & + "J3MBZI ","J3STAXI ","J3STAYI ","J3STAZI ","J3STVXI ","J3STVYI ","J3STVZI ", & + "J3VXI ","J3VYI ","J3VZI ","J4AXI ","J4AYI ","J4AZI ","J4DYNP ", & + "J4FAGXI ","J4FAGYI ","J4FAGZI ","J4FAMXI ","J4FAMYI ","J4FAMZI ","J4FBFXI ", & + "J4FBFYI ","J4FBFZI ","J4FBXI ","J4FBYI ","J4FBZI ","J4FDXI ","J4FDYI ", & + "J4FDZI ","J4FIXI ","J4FIYI ","J4FIZI ","J4FMGXI ","J4FMGYI ","J4FMGZI ", & + "J4MAGXI ","J4MAGYI ","J4MAGZI ","J4MBFXI ","J4MBFYI ","J4MBFZI ","J4MBXI ", & + "J4MBYI ","J4MBZI ","J4STAXI ","J4STAYI ","J4STAZI ","J4STVXI ","J4STVYI ", & + "J4STVZI ","J4VXI ","J4VYI ","J4VZI ","J5AXI ","J5AYI ","J5AZI ", & + "J5DYNP ","J5FAGXI ","J5FAGYI ","J5FAGZI ","J5FAMXI ","J5FAMYI ","J5FAMZI ", & + "J5FBFXI ","J5FBFYI ","J5FBFZI ","J5FBXI ","J5FBYI ","J5FBZI ","J5FDXI ", & + "J5FDYI ","J5FDZI ","J5FIXI ","J5FIYI ","J5FIZI ","J5FMGXI ","J5FMGYI ", & + "J5FMGZI ","J5MAGXI ","J5MAGYI ","J5MAGZI ","J5MBFXI ","J5MBFYI ","J5MBFZI ", & + "J5MBXI ","J5MBYI ","J5MBZI ","J5STAXI ","J5STAYI ","J5STAZI ","J5STVXI ", & + "J5STVYI ","J5STVZI ","J5VXI ","J5VYI ","J5VZI ","J6AXI ","J6AYI ", & + "J6AZI ","J6DYNP ","J6FAGXI ","J6FAGYI ","J6FAGZI ","J6FAMXI ","J6FAMYI ", & + "J6FAMZI ","J6FBFXI ","J6FBFYI ","J6FBFZI ","J6FBXI ","J6FBYI ","J6FBZI ", & + "J6FDXI ","J6FDYI ","J6FDZI ","J6FIXI ","J6FIYI ","J6FIZI ","J6FMGXI ", & + "J6FMGYI ","J6FMGZI ","J6MAGXI ","J6MAGYI ","J6MAGZI ","J6MBFXI ","J6MBFYI ", & + "J6MBFZI ","J6MBXI ","J6MBYI ","J6MBZI ","J6STAXI ","J6STAYI ","J6STAZI ", & + "J6STVXI ","J6STVYI ","J6STVZI ","J6VXI ","J6VYI ","J6VZI ","J7AXI ", & + "J7AYI ","J7AZI ","J7DYNP ","J7FAGXI ","J7FAGYI ","J7FAGZI ","J7FAMXI ", & + "J7FAMYI ","J7FAMZI ","J7FBFXI ","J7FBFYI ","J7FBFZI ","J7FBXI ","J7FBYI ", & + "J7FBZI ","J7FDXI ","J7FDYI ","J7FDZI ","J7FIXI ","J7FIYI ","J7FIZI ", & + "J7FMGXI ","J7FMGYI ","J7FMGZI ","J7MAGXI ","J7MAGYI ","J7MAGZI ","J7MBFXI ", & + "J7MBFYI ","J7MBFZI ","J7MBXI ","J7MBYI ","J7MBZI ","J7STAXI ","J7STAYI ", & + "J7STAZI ","J7STVXI ","J7STVYI ","J7STVZI ","J7VXI ","J7VYI ","J7VZI ", & + "J8AXI ","J8AYI ","J8AZI ","J8DYNP ","J8FAGXI ","J8FAGYI ","J8FAGZI ", & + "J8FAMXI ","J8FAMYI ","J8FAMZI ","J8FBFXI ","J8FBFYI ","J8FBFZI ","J8FBXI ", & + "J8FBYI ","J8FBZI ","J8FDXI ","J8FDYI ","J8FDZI ","J8FIXI ","J8FIYI ", & + "J8FIZI ","J8FMGXI ","J8FMGYI ","J8FMGZI ","J8MAGXI ","J8MAGYI ","J8MAGZI ", & + "J8MBFXI ","J8MBFYI ","J8MBFZI ","J8MBXI ","J8MBYI ","J8MBZI ","J8STAXI ", & + "J8STAYI ","J8STAZI ","J8STVXI ","J8STVYI ","J8STVZI ","J8VXI ","J8VYI ", & + "J8VZI ","J9AXI ","J9AYI ","J9AZI ","J9DYNP ","J9FAGXI ","J9FAGYI ", & + "J9FAGZI ","J9FAMXI ","J9FAMYI ","J9FAMZI ","J9FBFXI ","J9FBFYI ","J9FBFZI ", & + "J9FBXI ","J9FBYI ","J9FBZI ","J9FDXI ","J9FDYI ","J9FDZI ","J9FIXI ", & + "J9FIYI ","J9FIZI ","J9FMGXI ","J9FMGYI ","J9FMGZI ","J9MAGXI ","J9MAGYI ", & + "J9MAGZI ","J9MBFXI ","J9MBFYI ","J9MBFZI ","J9MBXI ","J9MBYI ","J9MBZI ", & + "J9STAXI ","J9STAYI ","J9STAZI ","J9STVXI ","J9STVYI ","J9STVZI ","J9VXI ", & + "J9VYI ","J9VZI ","M1N1AXI ","M1N1AYI ","M1N1AZI ","M1N1DYNP ","M1N1FAFXI", & + "M1N1FAFYI","M1N1FAFZI","M1N1FAGXI","M1N1FAGYI","M1N1FAGZI","M1N1FAMXI","M1N1FAMYI", & + "M1N1FAMZI","M1N1FBFXI","M1N1FBFYI","M1N1FBFZI","M1N1FBXI ","M1N1FBYI ","M1N1FBZI ", & + "M1N1FDXI ","M1N1FDYI ","M1N1FDZI ","M1N1FIXI ","M1N1FIYI ","M1N1FIZI ","M1N1FMGXI", & + "M1N1FMGYI","M1N1FMGZI","M1N1MAFXI","M1N1MAFYI","M1N1MAFZI","M1N1MAGXI","M1N1MAGYI", & + "M1N1MAGZI","M1N1MBFXI","M1N1MBFYI","M1N1MBFZI","M1N1MBXI ","M1N1MBYI ","M1N1MBZI ", & + "M1N1MMGXI","M1N1MMGYI","M1N1MMGZI","M1N1STAXI","M1N1STAYI","M1N1STAZI","M1N1STVXI", & + "M1N1STVYI","M1N1STVZI","M1N1VXI ","M1N1VYI ","M1N1VZI ","M1N2AXI ","M1N2AYI ", & + "M1N2AZI ","M1N2DYNP ","M1N2FAFXI","M1N2FAFYI","M1N2FAFZI","M1N2FAGXI","M1N2FAGYI", & + "M1N2FAGZI","M1N2FAMXI","M1N2FAMYI","M1N2FAMZI","M1N2FBFXI","M1N2FBFYI","M1N2FBFZI", & + "M1N2FBXI ","M1N2FBYI ","M1N2FBZI ","M1N2FDXI ","M1N2FDYI ","M1N2FDZI ","M1N2FIXI ", & + "M1N2FIYI ","M1N2FIZI ","M1N2FMGXI","M1N2FMGYI","M1N2FMGZI","M1N2MAFXI","M1N2MAFYI", & + "M1N2MAFZI","M1N2MAGXI","M1N2MAGYI","M1N2MAGZI","M1N2MBFXI","M1N2MBFYI","M1N2MBFZI", & + "M1N2MBXI ","M1N2MBYI ","M1N2MBZI ","M1N2MMGXI","M1N2MMGYI","M1N2MMGZI","M1N2STAXI", & + "M1N2STAYI","M1N2STAZI","M1N2STVXI","M1N2STVYI","M1N2STVZI","M1N2VXI ","M1N2VYI ", & + "M1N2VZI ","M1N3AXI ","M1N3AYI ","M1N3AZI ","M1N3DYNP ","M1N3FAFXI","M1N3FAFYI", & + "M1N3FAFZI","M1N3FAGXI","M1N3FAGYI"/) + ValidParamAry(501:1000) = (/ & + "M1N3FAGZI","M1N3FAMXI","M1N3FAMYI","M1N3FAMZI","M1N3FBFXI","M1N3FBFYI","M1N3FBFZI", & + "M1N3FBXI ","M1N3FBYI ","M1N3FBZI ","M1N3FDXI ","M1N3FDYI ","M1N3FDZI ","M1N3FIXI ", & + "M1N3FIYI ","M1N3FIZI ","M1N3FMGXI","M1N3FMGYI","M1N3FMGZI","M1N3MAFXI","M1N3MAFYI", & + "M1N3MAFZI","M1N3MAGXI","M1N3MAGYI","M1N3MAGZI","M1N3MBFXI","M1N3MBFYI","M1N3MBFZI", & + "M1N3MBXI ","M1N3MBYI ","M1N3MBZI ","M1N3MMGXI","M1N3MMGYI","M1N3MMGZI","M1N3STAXI", & + "M1N3STAYI","M1N3STAZI","M1N3STVXI","M1N3STVYI","M1N3STVZI","M1N3VXI ","M1N3VYI ", & + "M1N3VZI ","M1N4AXI ","M1N4AYI ","M1N4AZI ","M1N4DYNP ","M1N4FAFXI","M1N4FAFYI", & + "M1N4FAFZI","M1N4FAGXI","M1N4FAGYI","M1N4FAGZI","M1N4FAMXI","M1N4FAMYI","M1N4FAMZI", & + "M1N4FBFXI","M1N4FBFYI","M1N4FBFZI","M1N4FBXI ","M1N4FBYI ","M1N4FBZI ","M1N4FDXI ", & + "M1N4FDYI ","M1N4FDZI ","M1N4FIXI ","M1N4FIYI ","M1N4FIZI ","M1N4FMGXI","M1N4FMGYI", & + "M1N4FMGZI","M1N4MAFXI","M1N4MAFYI","M1N4MAFZI","M1N4MAGXI","M1N4MAGYI","M1N4MAGZI", & + "M1N4MBFXI","M1N4MBFYI","M1N4MBFZI","M1N4MBXI ","M1N4MBYI ","M1N4MBZI ","M1N4MMGXI", & + "M1N4MMGYI","M1N4MMGZI","M1N4STAXI","M1N4STAYI","M1N4STAZI","M1N4STVXI","M1N4STVYI", & + "M1N4STVZI","M1N4VXI ","M1N4VYI ","M1N4VZI ","M1N5AXI ","M1N5AYI ","M1N5AZI ", & + "M1N5DYNP ","M1N5FAFXI","M1N5FAFYI","M1N5FAFZI","M1N5FAGXI","M1N5FAGYI","M1N5FAGZI", & + "M1N5FAMXI","M1N5FAMYI","M1N5FAMZI","M1N5FBFXI","M1N5FBFYI","M1N5FBFZI","M1N5FBXI ", & + "M1N5FBYI ","M1N5FBZI ","M1N5FDXI ","M1N5FDYI ","M1N5FDZI ","M1N5FIXI ","M1N5FIYI ", & + "M1N5FIZI ","M1N5FMGXI","M1N5FMGYI","M1N5FMGZI","M1N5MAFXI","M1N5MAFYI","M1N5MAFZI", & + "M1N5MAGXI","M1N5MAGYI","M1N5MAGZI","M1N5MBFXI","M1N5MBFYI","M1N5MBFZI","M1N5MBXI ", & + "M1N5MBYI ","M1N5MBZI ","M1N5MMGXI","M1N5MMGYI","M1N5MMGZI","M1N5STAXI","M1N5STAYI", & + "M1N5STAZI","M1N5STVXI","M1N5STVYI","M1N5STVZI","M1N5VXI ","M1N5VYI ","M1N5VZI ", & + "M1N6AXI ","M1N6AYI ","M1N6AZI ","M1N6DYNP ","M1N6FAFXI","M1N6FAFYI","M1N6FAFZI", & + "M1N6FAGXI","M1N6FAGYI","M1N6FAGZI","M1N6FAMXI","M1N6FAMYI","M1N6FAMZI","M1N6FBFXI", & + "M1N6FBFYI","M1N6FBFZI","M1N6FBXI ","M1N6FBYI ","M1N6FBZI ","M1N6FDXI ","M1N6FDYI ", & + "M1N6FDZI ","M1N6FIXI ","M1N6FIYI ","M1N6FIZI ","M1N6FMGXI","M1N6FMGYI","M1N6FMGZI", & + "M1N6MAFXI","M1N6MAFYI","M1N6MAFZI","M1N6MAGXI","M1N6MAGYI","M1N6MAGZI","M1N6MBFXI", & + "M1N6MBFYI","M1N6MBFZI","M1N6MBXI ","M1N6MBYI ","M1N6MBZI ","M1N6MMGXI","M1N6MMGYI", & + "M1N6MMGZI","M1N6STAXI","M1N6STAYI","M1N6STAZI","M1N6STVXI","M1N6STVYI","M1N6STVZI", & + "M1N6VXI ","M1N6VYI ","M1N6VZI ","M1N7AXI ","M1N7AYI ","M1N7AZI ","M1N7DYNP ", & + "M1N7FAFXI","M1N7FAFYI","M1N7FAFZI","M1N7FAGXI","M1N7FAGYI","M1N7FAGZI","M1N7FAMXI", & + "M1N7FAMYI","M1N7FAMZI","M1N7FBFXI","M1N7FBFYI","M1N7FBFZI","M1N7FBXI ","M1N7FBYI ", & + "M1N7FBZI ","M1N7FDXI ","M1N7FDYI ","M1N7FDZI ","M1N7FIXI ","M1N7FIYI ","M1N7FIZI ", & + "M1N7FMGXI","M1N7FMGYI","M1N7FMGZI","M1N7MAFXI","M1N7MAFYI","M1N7MAFZI","M1N7MAGXI", & + "M1N7MAGYI","M1N7MAGZI","M1N7MBFXI","M1N7MBFYI","M1N7MBFZI","M1N7MBXI ","M1N7MBYI ", & + "M1N7MBZI ","M1N7MMGXI","M1N7MMGYI","M1N7MMGZI","M1N7STAXI","M1N7STAYI","M1N7STAZI", & + "M1N7STVXI","M1N7STVYI","M1N7STVZI","M1N7VXI ","M1N7VYI ","M1N7VZI ","M1N8AXI ", & + "M1N8AYI ","M1N8AZI ","M1N8DYNP ","M1N8FAFXI","M1N8FAFYI","M1N8FAFZI","M1N8FAGXI", & + "M1N8FAGYI","M1N8FAGZI","M1N8FAMXI","M1N8FAMYI","M1N8FAMZI","M1N8FBFXI","M1N8FBFYI", & + "M1N8FBFZI","M1N8FBXI ","M1N8FBYI ","M1N8FBZI ","M1N8FDXI ","M1N8FDYI ","M1N8FDZI ", & + "M1N8FIXI ","M1N8FIYI ","M1N8FIZI ","M1N8FMGXI","M1N8FMGYI","M1N8FMGZI","M1N8MAFXI", & + "M1N8MAFYI","M1N8MAFZI","M1N8MAGXI","M1N8MAGYI","M1N8MAGZI","M1N8MBFXI","M1N8MBFYI", & + "M1N8MBFZI","M1N8MBXI ","M1N8MBYI ","M1N8MBZI ","M1N8MMGXI","M1N8MMGYI","M1N8MMGZI", & + "M1N8STAXI","M1N8STAYI","M1N8STAZI","M1N8STVXI","M1N8STVYI","M1N8STVZI","M1N8VXI ", & + "M1N8VYI ","M1N8VZI ","M1N9AXI ","M1N9AYI ","M1N9AZI ","M1N9DYNP ","M1N9FAFXI", & + "M1N9FAFYI","M1N9FAFZI","M1N9FAGXI","M1N9FAGYI","M1N9FAGZI","M1N9FAMXI","M1N9FAMYI", & + "M1N9FAMZI","M1N9FBFXI","M1N9FBFYI","M1N9FBFZI","M1N9FBXI ","M1N9FBYI ","M1N9FBZI ", & + "M1N9FDXI ","M1N9FDYI ","M1N9FDZI ","M1N9FIXI ","M1N9FIYI ","M1N9FIZI ","M1N9FMGXI", & + "M1N9FMGYI","M1N9FMGZI","M1N9MAFXI","M1N9MAFYI","M1N9MAFZI","M1N9MAGXI","M1N9MAGYI", & + "M1N9MAGZI","M1N9MBFXI","M1N9MBFYI","M1N9MBFZI","M1N9MBXI ","M1N9MBYI ","M1N9MBZI ", & + "M1N9MMGXI","M1N9MMGYI","M1N9MMGZI","M1N9STAXI","M1N9STAYI","M1N9STAZI","M1N9STVXI", & + "M1N9STVYI","M1N9STVZI","M1N9VXI ","M1N9VYI ","M1N9VZI ","M2N1AXI ","M2N1AYI ", & + "M2N1AZI ","M2N1DYNP ","M2N1FAFXI","M2N1FAFYI","M2N1FAFZI","M2N1FAGXI","M2N1FAGYI", & + "M2N1FAGZI","M2N1FAMXI","M2N1FAMYI","M2N1FAMZI","M2N1FBFXI","M2N1FBFYI","M2N1FBFZI", & + "M2N1FBXI ","M2N1FBYI ","M2N1FBZI ","M2N1FDXI ","M2N1FDYI ","M2N1FDZI ","M2N1FIXI ", & + "M2N1FIYI ","M2N1FIZI ","M2N1FMGXI","M2N1FMGYI","M2N1FMGZI","M2N1MAFXI","M2N1MAFYI", & + "M2N1MAFZI","M2N1MAGXI","M2N1MAGYI","M2N1MAGZI","M2N1MBFXI","M2N1MBFYI","M2N1MBFZI", & + "M2N1MBXI ","M2N1MBYI ","M2N1MBZI ","M2N1MMGXI","M2N1MMGYI","M2N1MMGZI","M2N1STAXI", & + "M2N1STAYI","M2N1STAZI","M2N1STVXI","M2N1STVYI","M2N1STVZI","M2N1VXI ","M2N1VYI ", & + "M2N1VZI ","M2N2AXI ","M2N2AYI ","M2N2AZI ","M2N2DYNP ","M2N2FAFXI","M2N2FAFYI", & + "M2N2FAFZI","M2N2FAGXI","M2N2FAGYI","M2N2FAGZI","M2N2FAMXI","M2N2FAMYI","M2N2FAMZI", & + "M2N2FBFXI","M2N2FBFYI","M2N2FBFZI","M2N2FBXI ","M2N2FBYI ","M2N2FBZI ","M2N2FDXI ", & + "M2N2FDYI ","M2N2FDZI ","M2N2FIXI ","M2N2FIYI ","M2N2FIZI ","M2N2FMGXI","M2N2FMGYI", & + "M2N2FMGZI","M2N2MAFXI","M2N2MAFYI","M2N2MAFZI","M2N2MAGXI","M2N2MAGYI","M2N2MAGZI", & + "M2N2MBFXI","M2N2MBFYI","M2N2MBFZI","M2N2MBXI ","M2N2MBYI ","M2N2MBZI ","M2N2MMGXI", & + "M2N2MMGYI","M2N2MMGZI","M2N2STAXI","M2N2STAYI","M2N2STAZI","M2N2STVXI","M2N2STVYI", & + "M2N2STVZI","M2N2VXI ","M2N2VYI ","M2N2VZI ","M2N3AXI ","M2N3AYI ","M2N3AZI ", & + "M2N3DYNP ","M2N3FAFXI","M2N3FAFYI","M2N3FAFZI","M2N3FAGXI","M2N3FAGYI","M2N3FAGZI", & + "M2N3FAMXI","M2N3FAMYI","M2N3FAMZI","M2N3FBFXI","M2N3FBFYI","M2N3FBFZI","M2N3FBXI ", & + "M2N3FBYI ","M2N3FBZI ","M2N3FDXI ","M2N3FDYI ","M2N3FDZI ","M2N3FIXI ","M2N3FIYI ", & + "M2N3FIZI ","M2N3FMGXI","M2N3FMGYI","M2N3FMGZI","M2N3MAFXI","M2N3MAFYI","M2N3MAFZI", & + "M2N3MAGXI","M2N3MAGYI","M2N3MAGZI","M2N3MBFXI","M2N3MBFYI","M2N3MBFZI","M2N3MBXI ", & + "M2N3MBYI ","M2N3MBZI ","M2N3MMGXI"/) + ValidParamAry(1001:1500) = (/ & + "M2N3MMGYI","M2N3MMGZI","M2N3STAXI","M2N3STAYI","M2N3STAZI","M2N3STVXI","M2N3STVYI", & + "M2N3STVZI","M2N3VXI ","M2N3VYI ","M2N3VZI ","M2N4AXI ","M2N4AYI ","M2N4AZI ", & + "M2N4DYNP ","M2N4FAFXI","M2N4FAFYI","M2N4FAFZI","M2N4FAGXI","M2N4FAGYI","M2N4FAGZI", & + "M2N4FAMXI","M2N4FAMYI","M2N4FAMZI","M2N4FBFXI","M2N4FBFYI","M2N4FBFZI","M2N4FBXI ", & + "M2N4FBYI ","M2N4FBZI ","M2N4FDXI ","M2N4FDYI ","M2N4FDZI ","M2N4FIXI ","M2N4FIYI ", & + "M2N4FIZI ","M2N4FMGXI","M2N4FMGYI","M2N4FMGZI","M2N4MAFXI","M2N4MAFYI","M2N4MAFZI", & + "M2N4MAGXI","M2N4MAGYI","M2N4MAGZI","M2N4MBFXI","M2N4MBFYI","M2N4MBFZI","M2N4MBXI ", & + "M2N4MBYI ","M2N4MBZI ","M2N4MMGXI","M2N4MMGYI","M2N4MMGZI","M2N4STAXI","M2N4STAYI", & + "M2N4STAZI","M2N4STVXI","M2N4STVYI","M2N4STVZI","M2N4VXI ","M2N4VYI ","M2N4VZI ", & + "M2N5AXI ","M2N5AYI ","M2N5AZI ","M2N5DYNP ","M2N5FAFXI","M2N5FAFYI","M2N5FAFZI", & + "M2N5FAGXI","M2N5FAGYI","M2N5FAGZI","M2N5FAMXI","M2N5FAMYI","M2N5FAMZI","M2N5FBFXI", & + "M2N5FBFYI","M2N5FBFZI","M2N5FBXI ","M2N5FBYI ","M2N5FBZI ","M2N5FDXI ","M2N5FDYI ", & + "M2N5FDZI ","M2N5FIXI ","M2N5FIYI ","M2N5FIZI ","M2N5FMGXI","M2N5FMGYI","M2N5FMGZI", & + "M2N5MAFXI","M2N5MAFYI","M2N5MAFZI","M2N5MAGXI","M2N5MAGYI","M2N5MAGZI","M2N5MBFXI", & + "M2N5MBFYI","M2N5MBFZI","M2N5MBXI ","M2N5MBYI ","M2N5MBZI ","M2N5MMGXI","M2N5MMGYI", & + "M2N5MMGZI","M2N5STAXI","M2N5STAYI","M2N5STAZI","M2N5STVXI","M2N5STVYI","M2N5STVZI", & + "M2N5VXI ","M2N5VYI ","M2N5VZI ","M2N6AXI ","M2N6AYI ","M2N6AZI ","M2N6DYNP ", & + "M2N6FAFXI","M2N6FAFYI","M2N6FAFZI","M2N6FAGXI","M2N6FAGYI","M2N6FAGZI","M2N6FAMXI", & + "M2N6FAMYI","M2N6FAMZI","M2N6FBFXI","M2N6FBFYI","M2N6FBFZI","M2N6FBXI ","M2N6FBYI ", & + "M2N6FBZI ","M2N6FDXI ","M2N6FDYI ","M2N6FDZI ","M2N6FIXI ","M2N6FIYI ","M2N6FIZI ", & + "M2N6FMGXI","M2N6FMGYI","M2N6FMGZI","M2N6MAFXI","M2N6MAFYI","M2N6MAFZI","M2N6MAGXI", & + "M2N6MAGYI","M2N6MAGZI","M2N6MBFXI","M2N6MBFYI","M2N6MBFZI","M2N6MBXI ","M2N6MBYI ", & + "M2N6MBZI ","M2N6MMGXI","M2N6MMGYI","M2N6MMGZI","M2N6STAXI","M2N6STAYI","M2N6STAZI", & + "M2N6STVXI","M2N6STVYI","M2N6STVZI","M2N6VXI ","M2N6VYI ","M2N6VZI ","M2N7AXI ", & + "M2N7AYI ","M2N7AZI ","M2N7DYNP ","M2N7FAFXI","M2N7FAFYI","M2N7FAFZI","M2N7FAGXI", & + "M2N7FAGYI","M2N7FAGZI","M2N7FAMXI","M2N7FAMYI","M2N7FAMZI","M2N7FBFXI","M2N7FBFYI", & + "M2N7FBFZI","M2N7FBXI ","M2N7FBYI ","M2N7FBZI ","M2N7FDXI ","M2N7FDYI ","M2N7FDZI ", & + "M2N7FIXI ","M2N7FIYI ","M2N7FIZI ","M2N7FMGXI","M2N7FMGYI","M2N7FMGZI","M2N7MAFXI", & + "M2N7MAFYI","M2N7MAFZI","M2N7MAGXI","M2N7MAGYI","M2N7MAGZI","M2N7MBFXI","M2N7MBFYI", & + "M2N7MBFZI","M2N7MBXI ","M2N7MBYI ","M2N7MBZI ","M2N7MMGXI","M2N7MMGYI","M2N7MMGZI", & + "M2N7STAXI","M2N7STAYI","M2N7STAZI","M2N7STVXI","M2N7STVYI","M2N7STVZI","M2N7VXI ", & + "M2N7VYI ","M2N7VZI ","M2N8AXI ","M2N8AYI ","M2N8AZI ","M2N8DYNP ","M2N8FAFXI", & + "M2N8FAFYI","M2N8FAFZI","M2N8FAGXI","M2N8FAGYI","M2N8FAGZI","M2N8FAMXI","M2N8FAMYI", & + "M2N8FAMZI","M2N8FBFXI","M2N8FBFYI","M2N8FBFZI","M2N8FBXI ","M2N8FBYI ","M2N8FBZI ", & + "M2N8FDXI ","M2N8FDYI ","M2N8FDZI ","M2N8FIXI ","M2N8FIYI ","M2N8FIZI ","M2N8FMGXI", & + "M2N8FMGYI","M2N8FMGZI","M2N8MAFXI","M2N8MAFYI","M2N8MAFZI","M2N8MAGXI","M2N8MAGYI", & + "M2N8MAGZI","M2N8MBFXI","M2N8MBFYI","M2N8MBFZI","M2N8MBXI ","M2N8MBYI ","M2N8MBZI ", & + "M2N8MMGXI","M2N8MMGYI","M2N8MMGZI","M2N8STAXI","M2N8STAYI","M2N8STAZI","M2N8STVXI", & + "M2N8STVYI","M2N8STVZI","M2N8VXI ","M2N8VYI ","M2N8VZI ","M2N9AXI ","M2N9AYI ", & + "M2N9AZI ","M2N9DYNP ","M2N9FAFXI","M2N9FAFYI","M2N9FAFZI","M2N9FAGXI","M2N9FAGYI", & + "M2N9FAGZI","M2N9FAMXI","M2N9FAMYI","M2N9FAMZI","M2N9FBFXI","M2N9FBFYI","M2N9FBFZI", & + "M2N9FBXI ","M2N9FBYI ","M2N9FBZI ","M2N9FDXI ","M2N9FDYI ","M2N9FDZI ","M2N9FIXI ", & + "M2N9FIYI ","M2N9FIZI ","M2N9FMGXI","M2N9FMGYI","M2N9FMGZI","M2N9MAFXI","M2N9MAFYI", & + "M2N9MAFZI","M2N9MAGXI","M2N9MAGYI","M2N9MAGZI","M2N9MBFXI","M2N9MBFYI","M2N9MBFZI", & + "M2N9MBXI ","M2N9MBYI ","M2N9MBZI ","M2N9MMGXI","M2N9MMGYI","M2N9MMGZI","M2N9STAXI", & + "M2N9STAYI","M2N9STAZI","M2N9STVXI","M2N9STVYI","M2N9STVZI","M2N9VXI ","M2N9VYI ", & + "M2N9VZI ","M3N1AXI ","M3N1AYI ","M3N1AZI ","M3N1DYNP ","M3N1FAFXI","M3N1FAFYI", & + "M3N1FAFZI","M3N1FAGXI","M3N1FAGYI","M3N1FAGZI","M3N1FAMXI","M3N1FAMYI","M3N1FAMZI", & + "M3N1FBFXI","M3N1FBFYI","M3N1FBFZI","M3N1FBXI ","M3N1FBYI ","M3N1FBZI ","M3N1FDXI ", & + "M3N1FDYI ","M3N1FDZI ","M3N1FIXI ","M3N1FIYI ","M3N1FIZI ","M3N1FMGXI","M3N1FMGYI", & + "M3N1FMGZI","M3N1MAFXI","M3N1MAFYI","M3N1MAFZI","M3N1MAGXI","M3N1MAGYI","M3N1MAGZI", & + "M3N1MBFXI","M3N1MBFYI","M3N1MBFZI","M3N1MBXI ","M3N1MBYI ","M3N1MBZI ","M3N1MMGXI", & + "M3N1MMGYI","M3N1MMGZI","M3N1STAXI","M3N1STAYI","M3N1STAZI","M3N1STVXI","M3N1STVYI", & + "M3N1STVZI","M3N1VXI ","M3N1VYI ","M3N1VZI ","M3N2AXI ","M3N2AYI ","M3N2AZI ", & + "M3N2DYNP ","M3N2FAFXI","M3N2FAFYI","M3N2FAFZI","M3N2FAGXI","M3N2FAGYI","M3N2FAGZI", & + "M3N2FAMXI","M3N2FAMYI","M3N2FAMZI","M3N2FBFXI","M3N2FBFYI","M3N2FBFZI","M3N2FBXI ", & + "M3N2FBYI ","M3N2FBZI ","M3N2FDXI ","M3N2FDYI ","M3N2FDZI ","M3N2FIXI ","M3N2FIYI ", & + "M3N2FIZI ","M3N2FMGXI","M3N2FMGYI","M3N2FMGZI","M3N2MAFXI","M3N2MAFYI","M3N2MAFZI", & + "M3N2MAGXI","M3N2MAGYI","M3N2MAGZI","M3N2MBFXI","M3N2MBFYI","M3N2MBFZI","M3N2MBXI ", & + "M3N2MBYI ","M3N2MBZI ","M3N2MMGXI","M3N2MMGYI","M3N2MMGZI","M3N2STAXI","M3N2STAYI", & + "M3N2STAZI","M3N2STVXI","M3N2STVYI","M3N2STVZI","M3N2VXI ","M3N2VYI ","M3N2VZI ", & + "M3N3AXI ","M3N3AYI ","M3N3AZI ","M3N3DYNP ","M3N3FAFXI","M3N3FAFYI","M3N3FAFZI", & + "M3N3FAGXI","M3N3FAGYI","M3N3FAGZI","M3N3FAMXI","M3N3FAMYI","M3N3FAMZI","M3N3FBFXI", & + "M3N3FBFYI","M3N3FBFZI","M3N3FBXI ","M3N3FBYI ","M3N3FBZI ","M3N3FDXI ","M3N3FDYI ", & + "M3N3FDZI ","M3N3FIXI ","M3N3FIYI ","M3N3FIZI ","M3N3FMGXI","M3N3FMGYI","M3N3FMGZI", & + "M3N3MAFXI","M3N3MAFYI","M3N3MAFZI","M3N3MAGXI","M3N3MAGYI","M3N3MAGZI","M3N3MBFXI", & + "M3N3MBFYI","M3N3MBFZI","M3N3MBXI ","M3N3MBYI ","M3N3MBZI ","M3N3MMGXI","M3N3MMGYI", & + "M3N3MMGZI","M3N3STAXI","M3N3STAYI","M3N3STAZI","M3N3STVXI","M3N3STVYI","M3N3STVZI", & + "M3N3VXI ","M3N3VYI ","M3N3VZI ","M3N4AXI ","M3N4AYI ","M3N4AZI ","M3N4DYNP ", & + "M3N4FAFXI","M3N4FAFYI","M3N4FAFZI","M3N4FAGXI","M3N4FAGYI","M3N4FAGZI","M3N4FAMXI", & + "M3N4FAMYI","M3N4FAMZI","M3N4FBFXI","M3N4FBFYI","M3N4FBFZI","M3N4FBXI ","M3N4FBYI ", & + "M3N4FBZI ","M3N4FDXI ","M3N4FDYI "/) + ValidParamAry(1501:2000) = (/ & + "M3N4FDZI ","M3N4FIXI ","M3N4FIYI ","M3N4FIZI ","M3N4FMGXI","M3N4FMGYI","M3N4FMGZI", & + "M3N4MAFXI","M3N4MAFYI","M3N4MAFZI","M3N4MAGXI","M3N4MAGYI","M3N4MAGZI","M3N4MBFXI", & + "M3N4MBFYI","M3N4MBFZI","M3N4MBXI ","M3N4MBYI ","M3N4MBZI ","M3N4MMGXI","M3N4MMGYI", & + "M3N4MMGZI","M3N4STAXI","M3N4STAYI","M3N4STAZI","M3N4STVXI","M3N4STVYI","M3N4STVZI", & + "M3N4VXI ","M3N4VYI ","M3N4VZI ","M3N5AXI ","M3N5AYI ","M3N5AZI ","M3N5DYNP ", & + "M3N5FAFXI","M3N5FAFYI","M3N5FAFZI","M3N5FAGXI","M3N5FAGYI","M3N5FAGZI","M3N5FAMXI", & + "M3N5FAMYI","M3N5FAMZI","M3N5FBFXI","M3N5FBFYI","M3N5FBFZI","M3N5FBXI ","M3N5FBYI ", & + "M3N5FBZI ","M3N5FDXI ","M3N5FDYI ","M3N5FDZI ","M3N5FIXI ","M3N5FIYI ","M3N5FIZI ", & + "M3N5FMGXI","M3N5FMGYI","M3N5FMGZI","M3N5MAFXI","M3N5MAFYI","M3N5MAFZI","M3N5MAGXI", & + "M3N5MAGYI","M3N5MAGZI","M3N5MBFXI","M3N5MBFYI","M3N5MBFZI","M3N5MBXI ","M3N5MBYI ", & + "M3N5MBZI ","M3N5MMGXI","M3N5MMGYI","M3N5MMGZI","M3N5STAXI","M3N5STAYI","M3N5STAZI", & + "M3N5STVXI","M3N5STVYI","M3N5STVZI","M3N5VXI ","M3N5VYI ","M3N5VZI ","M3N6AXI ", & + "M3N6AYI ","M3N6AZI ","M3N6DYNP ","M3N6FAFXI","M3N6FAFYI","M3N6FAFZI","M3N6FAGXI", & + "M3N6FAGYI","M3N6FAGZI","M3N6FAMXI","M3N6FAMYI","M3N6FAMZI","M3N6FBFXI","M3N6FBFYI", & + "M3N6FBFZI","M3N6FBXI ","M3N6FBYI ","M3N6FBZI ","M3N6FDXI ","M3N6FDYI ","M3N6FDZI ", & + "M3N6FIXI ","M3N6FIYI ","M3N6FIZI ","M3N6FMGXI","M3N6FMGYI","M3N6FMGZI","M3N6MAFXI", & + "M3N6MAFYI","M3N6MAFZI","M3N6MAGXI","M3N6MAGYI","M3N6MAGZI","M3N6MBFXI","M3N6MBFYI", & + "M3N6MBFZI","M3N6MBXI ","M3N6MBYI ","M3N6MBZI ","M3N6MMGXI","M3N6MMGYI","M3N6MMGZI", & + "M3N6STAXI","M3N6STAYI","M3N6STAZI","M3N6STVXI","M3N6STVYI","M3N6STVZI","M3N6VXI ", & + "M3N6VYI ","M3N6VZI ","M3N7AXI ","M3N7AYI ","M3N7AZI ","M3N7DYNP ","M3N7FAFXI", & + "M3N7FAFYI","M3N7FAFZI","M3N7FAGXI","M3N7FAGYI","M3N7FAGZI","M3N7FAMXI","M3N7FAMYI", & + "M3N7FAMZI","M3N7FBFXI","M3N7FBFYI","M3N7FBFZI","M3N7FBXI ","M3N7FBYI ","M3N7FBZI ", & + "M3N7FDXI ","M3N7FDYI ","M3N7FDZI ","M3N7FIXI ","M3N7FIYI ","M3N7FIZI ","M3N7FMGXI", & + "M3N7FMGYI","M3N7FMGZI","M3N7MAFXI","M3N7MAFYI","M3N7MAFZI","M3N7MAGXI","M3N7MAGYI", & + "M3N7MAGZI","M3N7MBFXI","M3N7MBFYI","M3N7MBFZI","M3N7MBXI ","M3N7MBYI ","M3N7MBZI ", & + "M3N7MMGXI","M3N7MMGYI","M3N7MMGZI","M3N7STAXI","M3N7STAYI","M3N7STAZI","M3N7STVXI", & + "M3N7STVYI","M3N7STVZI","M3N7VXI ","M3N7VYI ","M3N7VZI ","M3N8AXI ","M3N8AYI ", & + "M3N8AZI ","M3N8DYNP ","M3N8FAFXI","M3N8FAFYI","M3N8FAFZI","M3N8FAGXI","M3N8FAGYI", & + "M3N8FAGZI","M3N8FAMXI","M3N8FAMYI","M3N8FAMZI","M3N8FBFXI","M3N8FBFYI","M3N8FBFZI", & + "M3N8FBXI ","M3N8FBYI ","M3N8FBZI ","M3N8FDXI ","M3N8FDYI ","M3N8FDZI ","M3N8FIXI ", & + "M3N8FIYI ","M3N8FIZI ","M3N8FMGXI","M3N8FMGYI","M3N8FMGZI","M3N8MAFXI","M3N8MAFYI", & + "M3N8MAFZI","M3N8MAGXI","M3N8MAGYI","M3N8MAGZI","M3N8MBFXI","M3N8MBFYI","M3N8MBFZI", & + "M3N8MBXI ","M3N8MBYI ","M3N8MBZI ","M3N8MMGXI","M3N8MMGYI","M3N8MMGZI","M3N8STAXI", & + "M3N8STAYI","M3N8STAZI","M3N8STVXI","M3N8STVYI","M3N8STVZI","M3N8VXI ","M3N8VYI ", & + "M3N8VZI ","M3N9AXI ","M3N9AYI ","M3N9AZI ","M3N9DYNP ","M3N9FAFXI","M3N9FAFYI", & + "M3N9FAFZI","M3N9FAGXI","M3N9FAGYI","M3N9FAGZI","M3N9FAMXI","M3N9FAMYI","M3N9FAMZI", & + "M3N9FBFXI","M3N9FBFYI","M3N9FBFZI","M3N9FBXI ","M3N9FBYI ","M3N9FBZI ","M3N9FDXI ", & + "M3N9FDYI ","M3N9FDZI ","M3N9FIXI ","M3N9FIYI ","M3N9FIZI ","M3N9FMGXI","M3N9FMGYI", & + "M3N9FMGZI","M3N9MAFXI","M3N9MAFYI","M3N9MAFZI","M3N9MAGXI","M3N9MAGYI","M3N9MAGZI", & + "M3N9MBFXI","M3N9MBFYI","M3N9MBFZI","M3N9MBXI ","M3N9MBYI ","M3N9MBZI ","M3N9MMGXI", & + "M3N9MMGYI","M3N9MMGZI","M3N9STAXI","M3N9STAYI","M3N9STAZI","M3N9STVXI","M3N9STVYI", & + "M3N9STVZI","M3N9VXI ","M3N9VYI ","M3N9VZI ","M4N1AXI ","M4N1AYI ","M4N1AZI ", & + "M4N1DYNP ","M4N1FAFXI","M4N1FAFYI","M4N1FAFZI","M4N1FAGXI","M4N1FAGYI","M4N1FAGZI", & + "M4N1FAMXI","M4N1FAMYI","M4N1FAMZI","M4N1FBFXI","M4N1FBFYI","M4N1FBFZI","M4N1FBXI ", & + "M4N1FBYI ","M4N1FBZI ","M4N1FDXI ","M4N1FDYI ","M4N1FDZI ","M4N1FIXI ","M4N1FIYI ", & + "M4N1FIZI ","M4N1FMGXI","M4N1FMGYI","M4N1FMGZI","M4N1MAFXI","M4N1MAFYI","M4N1MAFZI", & + "M4N1MAGXI","M4N1MAGYI","M4N1MAGZI","M4N1MBFXI","M4N1MBFYI","M4N1MBFZI","M4N1MBXI ", & + "M4N1MBYI ","M4N1MBZI ","M4N1MMGXI","M4N1MMGYI","M4N1MMGZI","M4N1STAXI","M4N1STAYI", & + "M4N1STAZI","M4N1STVXI","M4N1STVYI","M4N1STVZI","M4N1VXI ","M4N1VYI ","M4N1VZI ", & + "M4N2AXI ","M4N2AYI ","M4N2AZI ","M4N2DYNP ","M4N2FAFXI","M4N2FAFYI","M4N2FAFZI", & + "M4N2FAGXI","M4N2FAGYI","M4N2FAGZI","M4N2FAMXI","M4N2FAMYI","M4N2FAMZI","M4N2FBFXI", & + "M4N2FBFYI","M4N2FBFZI","M4N2FBXI ","M4N2FBYI ","M4N2FBZI ","M4N2FDXI ","M4N2FDYI ", & + "M4N2FDZI ","M4N2FIXI ","M4N2FIYI ","M4N2FIZI ","M4N2FMGXI","M4N2FMGYI","M4N2FMGZI", & + "M4N2MAFXI","M4N2MAFYI","M4N2MAFZI","M4N2MAGXI","M4N2MAGYI","M4N2MAGZI","M4N2MBFXI", & + "M4N2MBFYI","M4N2MBFZI","M4N2MBXI ","M4N2MBYI ","M4N2MBZI ","M4N2MMGXI","M4N2MMGYI", & + "M4N2MMGZI","M4N2STAXI","M4N2STAYI","M4N2STAZI","M4N2STVXI","M4N2STVYI","M4N2STVZI", & + "M4N2VXI ","M4N2VYI ","M4N2VZI ","M4N3AXI ","M4N3AYI ","M4N3AZI ","M4N3DYNP ", & + "M4N3FAFXI","M4N3FAFYI","M4N3FAFZI","M4N3FAGXI","M4N3FAGYI","M4N3FAGZI","M4N3FAMXI", & + "M4N3FAMYI","M4N3FAMZI","M4N3FBFXI","M4N3FBFYI","M4N3FBFZI","M4N3FBXI ","M4N3FBYI ", & + "M4N3FBZI ","M4N3FDXI ","M4N3FDYI ","M4N3FDZI ","M4N3FIXI ","M4N3FIYI ","M4N3FIZI ", & + "M4N3FMGXI","M4N3FMGYI","M4N3FMGZI","M4N3MAFXI","M4N3MAFYI","M4N3MAFZI","M4N3MAGXI", & + "M4N3MAGYI","M4N3MAGZI","M4N3MBFXI","M4N3MBFYI","M4N3MBFZI","M4N3MBXI ","M4N3MBYI ", & + "M4N3MBZI ","M4N3MMGXI","M4N3MMGYI","M4N3MMGZI","M4N3STAXI","M4N3STAYI","M4N3STAZI", & + "M4N3STVXI","M4N3STVYI","M4N3STVZI","M4N3VXI ","M4N3VYI ","M4N3VZI ","M4N4AXI ", & + "M4N4AYI ","M4N4AZI ","M4N4DYNP ","M4N4FAFXI","M4N4FAFYI","M4N4FAFZI","M4N4FAGXI", & + "M4N4FAGYI","M4N4FAGZI","M4N4FAMXI","M4N4FAMYI","M4N4FAMZI","M4N4FBFXI","M4N4FBFYI", & + "M4N4FBFZI","M4N4FBXI ","M4N4FBYI ","M4N4FBZI ","M4N4FDXI ","M4N4FDYI ","M4N4FDZI ", & + "M4N4FIXI ","M4N4FIYI ","M4N4FIZI ","M4N4FMGXI","M4N4FMGYI","M4N4FMGZI","M4N4MAFXI", & + "M4N4MAFYI","M4N4MAFZI","M4N4MAGXI","M4N4MAGYI","M4N4MAGZI","M4N4MBFXI","M4N4MBFYI", & + "M4N4MBFZI","M4N4MBXI ","M4N4MBYI ","M4N4MBZI ","M4N4MMGXI","M4N4MMGYI","M4N4MMGZI", & + "M4N4STAXI","M4N4STAYI","M4N4STAZI","M4N4STVXI","M4N4STVYI","M4N4STVZI","M4N4VXI ", & + "M4N4VYI ","M4N4VZI ","M4N5AXI "/) + ValidParamAry(2001:2500) = (/ & + "M4N5AYI ","M4N5AZI ","M4N5DYNP ","M4N5FAFXI","M4N5FAFYI","M4N5FAFZI","M4N5FAGXI", & + "M4N5FAGYI","M4N5FAGZI","M4N5FAMXI","M4N5FAMYI","M4N5FAMZI","M4N5FBFXI","M4N5FBFYI", & + "M4N5FBFZI","M4N5FBXI ","M4N5FBYI ","M4N5FBZI ","M4N5FDXI ","M4N5FDYI ","M4N5FDZI ", & + "M4N5FIXI ","M4N5FIYI ","M4N5FIZI ","M4N5FMGXI","M4N5FMGYI","M4N5FMGZI","M4N5MAFXI", & + "M4N5MAFYI","M4N5MAFZI","M4N5MAGXI","M4N5MAGYI","M4N5MAGZI","M4N5MBFXI","M4N5MBFYI", & + "M4N5MBFZI","M4N5MBXI ","M4N5MBYI ","M4N5MBZI ","M4N5MMGXI","M4N5MMGYI","M4N5MMGZI", & + "M4N5STAXI","M4N5STAYI","M4N5STAZI","M4N5STVXI","M4N5STVYI","M4N5STVZI","M4N5VXI ", & + "M4N5VYI ","M4N5VZI ","M4N6AXI ","M4N6AYI ","M4N6AZI ","M4N6DYNP ","M4N6FAFXI", & + "M4N6FAFYI","M4N6FAFZI","M4N6FAGXI","M4N6FAGYI","M4N6FAGZI","M4N6FAMXI","M4N6FAMYI", & + "M4N6FAMZI","M4N6FBFXI","M4N6FBFYI","M4N6FBFZI","M4N6FBXI ","M4N6FBYI ","M4N6FBZI ", & + "M4N6FDXI ","M4N6FDYI ","M4N6FDZI ","M4N6FIXI ","M4N6FIYI ","M4N6FIZI ","M4N6FMGXI", & + "M4N6FMGYI","M4N6FMGZI","M4N6MAFXI","M4N6MAFYI","M4N6MAFZI","M4N6MAGXI","M4N6MAGYI", & + "M4N6MAGZI","M4N6MBFXI","M4N6MBFYI","M4N6MBFZI","M4N6MBXI ","M4N6MBYI ","M4N6MBZI ", & + "M4N6MMGXI","M4N6MMGYI","M4N6MMGZI","M4N6STAXI","M4N6STAYI","M4N6STAZI","M4N6STVXI", & + "M4N6STVYI","M4N6STVZI","M4N6VXI ","M4N6VYI ","M4N6VZI ","M4N7AXI ","M4N7AYI ", & + "M4N7AZI ","M4N7DYNP ","M4N7FAFXI","M4N7FAFYI","M4N7FAFZI","M4N7FAGXI","M4N7FAGYI", & + "M4N7FAGZI","M4N7FAMXI","M4N7FAMYI","M4N7FAMZI","M4N7FBFXI","M4N7FBFYI","M4N7FBFZI", & + "M4N7FBXI ","M4N7FBYI ","M4N7FBZI ","M4N7FDXI ","M4N7FDYI ","M4N7FDZI ","M4N7FIXI ", & + "M4N7FIYI ","M4N7FIZI ","M4N7FMGXI","M4N7FMGYI","M4N7FMGZI","M4N7MAFXI","M4N7MAFYI", & + "M4N7MAFZI","M4N7MAGXI","M4N7MAGYI","M4N7MAGZI","M4N7MBFXI","M4N7MBFYI","M4N7MBFZI", & + "M4N7MBXI ","M4N7MBYI ","M4N7MBZI ","M4N7MMGXI","M4N7MMGYI","M4N7MMGZI","M4N7STAXI", & + "M4N7STAYI","M4N7STAZI","M4N7STVXI","M4N7STVYI","M4N7STVZI","M4N7VXI ","M4N7VYI ", & + "M4N7VZI ","M4N8AXI ","M4N8AYI ","M4N8AZI ","M4N8DYNP ","M4N8FAFXI","M4N8FAFYI", & + "M4N8FAFZI","M4N8FAGXI","M4N8FAGYI","M4N8FAGZI","M4N8FAMXI","M4N8FAMYI","M4N8FAMZI", & + "M4N8FBFXI","M4N8FBFYI","M4N8FBFZI","M4N8FBXI ","M4N8FBYI ","M4N8FBZI ","M4N8FDXI ", & + "M4N8FDYI ","M4N8FDZI ","M4N8FIXI ","M4N8FIYI ","M4N8FIZI ","M4N8FMGXI","M4N8FMGYI", & + "M4N8FMGZI","M4N8MAFXI","M4N8MAFYI","M4N8MAFZI","M4N8MAGXI","M4N8MAGYI","M4N8MAGZI", & + "M4N8MBFXI","M4N8MBFYI","M4N8MBFZI","M4N8MBXI ","M4N8MBYI ","M4N8MBZI ","M4N8MMGXI", & + "M4N8MMGYI","M4N8MMGZI","M4N8STAXI","M4N8STAYI","M4N8STAZI","M4N8STVXI","M4N8STVYI", & + "M4N8STVZI","M4N8VXI ","M4N8VYI ","M4N8VZI ","M4N9AXI ","M4N9AYI ","M4N9AZI ", & + "M4N9DYNP ","M4N9FAFXI","M4N9FAFYI","M4N9FAFZI","M4N9FAGXI","M4N9FAGYI","M4N9FAGZI", & + "M4N9FAMXI","M4N9FAMYI","M4N9FAMZI","M4N9FBFXI","M4N9FBFYI","M4N9FBFZI","M4N9FBXI ", & + "M4N9FBYI ","M4N9FBZI ","M4N9FDXI ","M4N9FDYI ","M4N9FDZI ","M4N9FIXI ","M4N9FIYI ", & + "M4N9FIZI ","M4N9FMGXI","M4N9FMGYI","M4N9FMGZI","M4N9MAFXI","M4N9MAFYI","M4N9MAFZI", & + "M4N9MAGXI","M4N9MAGYI","M4N9MAGZI","M4N9MBFXI","M4N9MBFYI","M4N9MBFZI","M4N9MBXI ", & + "M4N9MBYI ","M4N9MBZI ","M4N9MMGXI","M4N9MMGYI","M4N9MMGZI","M4N9STAXI","M4N9STAYI", & + "M4N9STAZI","M4N9STVXI","M4N9STVYI","M4N9STVZI","M4N9VXI ","M4N9VYI ","M4N9VZI ", & + "M5N1AXI ","M5N1AYI ","M5N1AZI ","M5N1DYNP ","M5N1FAFXI","M5N1FAFYI","M5N1FAFZI", & + "M5N1FAGXI","M5N1FAGYI","M5N1FAGZI","M5N1FAMXI","M5N1FAMYI","M5N1FAMZI","M5N1FBFXI", & + "M5N1FBFYI","M5N1FBFZI","M5N1FBXI ","M5N1FBYI ","M5N1FBZI ","M5N1FDXI ","M5N1FDYI ", & + "M5N1FDZI ","M5N1FIXI ","M5N1FIYI ","M5N1FIZI ","M5N1FMGXI","M5N1FMGYI","M5N1FMGZI", & + "M5N1MAFXI","M5N1MAFYI","M5N1MAFZI","M5N1MAGXI","M5N1MAGYI","M5N1MAGZI","M5N1MBFXI", & + "M5N1MBFYI","M5N1MBFZI","M5N1MBXI ","M5N1MBYI ","M5N1MBZI ","M5N1MMGXI","M5N1MMGYI", & + "M5N1MMGZI","M5N1STAXI","M5N1STAYI","M5N1STAZI","M5N1STVXI","M5N1STVYI","M5N1STVZI", & + "M5N1VXI ","M5N1VYI ","M5N1VZI ","M5N2AXI ","M5N2AYI ","M5N2AZI ","M5N2DYNP ", & + "M5N2FAFXI","M5N2FAFYI","M5N2FAFZI","M5N2FAGXI","M5N2FAGYI","M5N2FAGZI","M5N2FAMXI", & + "M5N2FAMYI","M5N2FAMZI","M5N2FBFXI","M5N2FBFYI","M5N2FBFZI","M5N2FBXI ","M5N2FBYI ", & + "M5N2FBZI ","M5N2FDXI ","M5N2FDYI ","M5N2FDZI ","M5N2FIXI ","M5N2FIYI ","M5N2FIZI ", & + "M5N2FMGXI","M5N2FMGYI","M5N2FMGZI","M5N2MAFXI","M5N2MAFYI","M5N2MAFZI","M5N2MAGXI", & + "M5N2MAGYI","M5N2MAGZI","M5N2MBFXI","M5N2MBFYI","M5N2MBFZI","M5N2MBXI ","M5N2MBYI ", & + "M5N2MBZI ","M5N2MMGXI","M5N2MMGYI","M5N2MMGZI","M5N2STAXI","M5N2STAYI","M5N2STAZI", & + "M5N2STVXI","M5N2STVYI","M5N2STVZI","M5N2VXI ","M5N2VYI ","M5N2VZI ","M5N3AXI ", & + "M5N3AYI ","M5N3AZI ","M5N3DYNP ","M5N3FAFXI","M5N3FAFYI","M5N3FAFZI","M5N3FAGXI", & + "M5N3FAGYI","M5N3FAGZI","M5N3FAMXI","M5N3FAMYI","M5N3FAMZI","M5N3FBFXI","M5N3FBFYI", & + "M5N3FBFZI","M5N3FBXI ","M5N3FBYI ","M5N3FBZI ","M5N3FDXI ","M5N3FDYI ","M5N3FDZI ", & + "M5N3FIXI ","M5N3FIYI ","M5N3FIZI ","M5N3FMGXI","M5N3FMGYI","M5N3FMGZI","M5N3MAFXI", & + "M5N3MAFYI","M5N3MAFZI","M5N3MAGXI","M5N3MAGYI","M5N3MAGZI","M5N3MBFXI","M5N3MBFYI", & + "M5N3MBFZI","M5N3MBXI ","M5N3MBYI ","M5N3MBZI ","M5N3MMGXI","M5N3MMGYI","M5N3MMGZI", & + "M5N3STAXI","M5N3STAYI","M5N3STAZI","M5N3STVXI","M5N3STVYI","M5N3STVZI","M5N3VXI ", & + "M5N3VYI ","M5N3VZI ","M5N4AXI ","M5N4AYI ","M5N4AZI ","M5N4DYNP ","M5N4FAFXI", & + "M5N4FAFYI","M5N4FAFZI","M5N4FAGXI","M5N4FAGYI","M5N4FAGZI","M5N4FAMXI","M5N4FAMYI", & + "M5N4FAMZI","M5N4FBFXI","M5N4FBFYI","M5N4FBFZI","M5N4FBXI ","M5N4FBYI ","M5N4FBZI ", & + "M5N4FDXI ","M5N4FDYI ","M5N4FDZI ","M5N4FIXI ","M5N4FIYI ","M5N4FIZI ","M5N4FMGXI", & + "M5N4FMGYI","M5N4FMGZI","M5N4MAFXI","M5N4MAFYI","M5N4MAFZI","M5N4MAGXI","M5N4MAGYI", & + "M5N4MAGZI","M5N4MBFXI","M5N4MBFYI","M5N4MBFZI","M5N4MBXI ","M5N4MBYI ","M5N4MBZI ", & + "M5N4MMGXI","M5N4MMGYI","M5N4MMGZI","M5N4STAXI","M5N4STAYI","M5N4STAZI","M5N4STVXI", & + "M5N4STVYI","M5N4STVZI","M5N4VXI ","M5N4VYI ","M5N4VZI ","M5N5AXI ","M5N5AYI ", & + "M5N5AZI ","M5N5DYNP ","M5N5FAFXI","M5N5FAFYI","M5N5FAFZI","M5N5FAGXI","M5N5FAGYI", & + "M5N5FAGZI","M5N5FAMXI","M5N5FAMYI","M5N5FAMZI","M5N5FBFXI","M5N5FBFYI","M5N5FBFZI", & + "M5N5FBXI ","M5N5FBYI ","M5N5FBZI ","M5N5FDXI ","M5N5FDYI ","M5N5FDZI ","M5N5FIXI ", & + "M5N5FIYI ","M5N5FIZI ","M5N5FMGXI","M5N5FMGYI","M5N5FMGZI","M5N5MAFXI","M5N5MAFYI", & + "M5N5MAFZI","M5N5MAGXI","M5N5MAGYI"/) + ValidParamAry(2501:3000) = (/ & + "M5N5MAGZI","M5N5MBFXI","M5N5MBFYI","M5N5MBFZI","M5N5MBXI ","M5N5MBYI ","M5N5MBZI ", & + "M5N5MMGXI","M5N5MMGYI","M5N5MMGZI","M5N5STAXI","M5N5STAYI","M5N5STAZI","M5N5STVXI", & + "M5N5STVYI","M5N5STVZI","M5N5VXI ","M5N5VYI ","M5N5VZI ","M5N6AXI ","M5N6AYI ", & + "M5N6AZI ","M5N6DYNP ","M5N6FAFXI","M5N6FAFYI","M5N6FAFZI","M5N6FAGXI","M5N6FAGYI", & + "M5N6FAGZI","M5N6FAMXI","M5N6FAMYI","M5N6FAMZI","M5N6FBFXI","M5N6FBFYI","M5N6FBFZI", & + "M5N6FBXI ","M5N6FBYI ","M5N6FBZI ","M5N6FDXI ","M5N6FDYI ","M5N6FDZI ","M5N6FIXI ", & + "M5N6FIYI ","M5N6FIZI ","M5N6FMGXI","M5N6FMGYI","M5N6FMGZI","M5N6MAFXI","M5N6MAFYI", & + "M5N6MAFZI","M5N6MAGXI","M5N6MAGYI","M5N6MAGZI","M5N6MBFXI","M5N6MBFYI","M5N6MBFZI", & + "M5N6MBXI ","M5N6MBYI ","M5N6MBZI ","M5N6MMGXI","M5N6MMGYI","M5N6MMGZI","M5N6STAXI", & + "M5N6STAYI","M5N6STAZI","M5N6STVXI","M5N6STVYI","M5N6STVZI","M5N6VXI ","M5N6VYI ", & + "M5N6VZI ","M5N7AXI ","M5N7AYI ","M5N7AZI ","M5N7DYNP ","M5N7FAFXI","M5N7FAFYI", & + "M5N7FAFZI","M5N7FAGXI","M5N7FAGYI","M5N7FAGZI","M5N7FAMXI","M5N7FAMYI","M5N7FAMZI", & + "M5N7FBFXI","M5N7FBFYI","M5N7FBFZI","M5N7FBXI ","M5N7FBYI ","M5N7FBZI ","M5N7FDXI ", & + "M5N7FDYI ","M5N7FDZI ","M5N7FIXI ","M5N7FIYI ","M5N7FIZI ","M5N7FMGXI","M5N7FMGYI", & + "M5N7FMGZI","M5N7MAFXI","M5N7MAFYI","M5N7MAFZI","M5N7MAGXI","M5N7MAGYI","M5N7MAGZI", & + "M5N7MBFXI","M5N7MBFYI","M5N7MBFZI","M5N7MBXI ","M5N7MBYI ","M5N7MBZI ","M5N7MMGXI", & + "M5N7MMGYI","M5N7MMGZI","M5N7STAXI","M5N7STAYI","M5N7STAZI","M5N7STVXI","M5N7STVYI", & + "M5N7STVZI","M5N7VXI ","M5N7VYI ","M5N7VZI ","M5N8AXI ","M5N8AYI ","M5N8AZI ", & + "M5N8DYNP ","M5N8FAFXI","M5N8FAFYI","M5N8FAFZI","M5N8FAGXI","M5N8FAGYI","M5N8FAGZI", & + "M5N8FAMXI","M5N8FAMYI","M5N8FAMZI","M5N8FBFXI","M5N8FBFYI","M5N8FBFZI","M5N8FBXI ", & + "M5N8FBYI ","M5N8FBZI ","M5N8FDXI ","M5N8FDYI ","M5N8FDZI ","M5N8FIXI ","M5N8FIYI ", & + "M5N8FIZI ","M5N8FMGXI","M5N8FMGYI","M5N8FMGZI","M5N8MAFXI","M5N8MAFYI","M5N8MAFZI", & + "M5N8MAGXI","M5N8MAGYI","M5N8MAGZI","M5N8MBFXI","M5N8MBFYI","M5N8MBFZI","M5N8MBXI ", & + "M5N8MBYI ","M5N8MBZI ","M5N8MMGXI","M5N8MMGYI","M5N8MMGZI","M5N8STAXI","M5N8STAYI", & + "M5N8STAZI","M5N8STVXI","M5N8STVYI","M5N8STVZI","M5N8VXI ","M5N8VYI ","M5N8VZI ", & + "M5N9AXI ","M5N9AYI ","M5N9AZI ","M5N9DYNP ","M5N9FAFXI","M5N9FAFYI","M5N9FAFZI", & + "M5N9FAGXI","M5N9FAGYI","M5N9FAGZI","M5N9FAMXI","M5N9FAMYI","M5N9FAMZI","M5N9FBFXI", & + "M5N9FBFYI","M5N9FBFZI","M5N9FBXI ","M5N9FBYI ","M5N9FBZI ","M5N9FDXI ","M5N9FDYI ", & + "M5N9FDZI ","M5N9FIXI ","M5N9FIYI ","M5N9FIZI ","M5N9FMGXI","M5N9FMGYI","M5N9FMGZI", & + "M5N9MAFXI","M5N9MAFYI","M5N9MAFZI","M5N9MAGXI","M5N9MAGYI","M5N9MAGZI","M5N9MBFXI", & + "M5N9MBFYI","M5N9MBFZI","M5N9MBXI ","M5N9MBYI ","M5N9MBZI ","M5N9MMGXI","M5N9MMGYI", & + "M5N9MMGZI","M5N9STAXI","M5N9STAYI","M5N9STAZI","M5N9STVXI","M5N9STVYI","M5N9STVZI", & + "M5N9VXI ","M5N9VYI ","M5N9VZI ","M6N1AXI ","M6N1AYI ","M6N1AZI ","M6N1DYNP ", & + "M6N1FAFXI","M6N1FAFYI","M6N1FAFZI","M6N1FAGXI","M6N1FAGYI","M6N1FAGZI","M6N1FAMXI", & + "M6N1FAMYI","M6N1FAMZI","M6N1FBFXI","M6N1FBFYI","M6N1FBFZI","M6N1FBXI ","M6N1FBYI ", & + "M6N1FBZI ","M6N1FDXI ","M6N1FDYI ","M6N1FDZI ","M6N1FIXI ","M6N1FIYI ","M6N1FIZI ", & + "M6N1FMGXI","M6N1FMGYI","M6N1FMGZI","M6N1MAFXI","M6N1MAFYI","M6N1MAFZI","M6N1MAGXI", & + "M6N1MAGYI","M6N1MAGZI","M6N1MBFXI","M6N1MBFYI","M6N1MBFZI","M6N1MBXI ","M6N1MBYI ", & + "M6N1MBZI ","M6N1MMGXI","M6N1MMGYI","M6N1MMGZI","M6N1STAXI","M6N1STAYI","M6N1STAZI", & + "M6N1STVXI","M6N1STVYI","M6N1STVZI","M6N1VXI ","M6N1VYI ","M6N1VZI ","M6N2AXI ", & + "M6N2AYI ","M6N2AZI ","M6N2DYNP ","M6N2FAFXI","M6N2FAFYI","M6N2FAFZI","M6N2FAGXI", & + "M6N2FAGYI","M6N2FAGZI","M6N2FAMXI","M6N2FAMYI","M6N2FAMZI","M6N2FBFXI","M6N2FBFYI", & + "M6N2FBFZI","M6N2FBXI ","M6N2FBYI ","M6N2FBZI ","M6N2FDXI ","M6N2FDYI ","M6N2FDZI ", & + "M6N2FIXI ","M6N2FIYI ","M6N2FIZI ","M6N2FMGXI","M6N2FMGYI","M6N2FMGZI","M6N2MAFXI", & + "M6N2MAFYI","M6N2MAFZI","M6N2MAGXI","M6N2MAGYI","M6N2MAGZI","M6N2MBFXI","M6N2MBFYI", & + "M6N2MBFZI","M6N2MBXI ","M6N2MBYI ","M6N2MBZI ","M6N2MMGXI","M6N2MMGYI","M6N2MMGZI", & + "M6N2STAXI","M6N2STAYI","M6N2STAZI","M6N2STVXI","M6N2STVYI","M6N2STVZI","M6N2VXI ", & + "M6N2VYI ","M6N2VZI ","M6N3AXI ","M6N3AYI ","M6N3AZI ","M6N3DYNP ","M6N3FAFXI", & + "M6N3FAFYI","M6N3FAFZI","M6N3FAGXI","M6N3FAGYI","M6N3FAGZI","M6N3FAMXI","M6N3FAMYI", & + "M6N3FAMZI","M6N3FBFXI","M6N3FBFYI","M6N3FBFZI","M6N3FBXI ","M6N3FBYI ","M6N3FBZI ", & + "M6N3FDXI ","M6N3FDYI ","M6N3FDZI ","M6N3FIXI ","M6N3FIYI ","M6N3FIZI ","M6N3FMGXI", & + "M6N3FMGYI","M6N3FMGZI","M6N3MAFXI","M6N3MAFYI","M6N3MAFZI","M6N3MAGXI","M6N3MAGYI", & + "M6N3MAGZI","M6N3MBFXI","M6N3MBFYI","M6N3MBFZI","M6N3MBXI ","M6N3MBYI ","M6N3MBZI ", & + "M6N3MMGXI","M6N3MMGYI","M6N3MMGZI","M6N3STAXI","M6N3STAYI","M6N3STAZI","M6N3STVXI", & + "M6N3STVYI","M6N3STVZI","M6N3VXI ","M6N3VYI ","M6N3VZI ","M6N4AXI ","M6N4AYI ", & + "M6N4AZI ","M6N4DYNP ","M6N4FAFXI","M6N4FAFYI","M6N4FAFZI","M6N4FAGXI","M6N4FAGYI", & + "M6N4FAGZI","M6N4FAMXI","M6N4FAMYI","M6N4FAMZI","M6N4FBFXI","M6N4FBFYI","M6N4FBFZI", & + "M6N4FBXI ","M6N4FBYI ","M6N4FBZI ","M6N4FDXI ","M6N4FDYI ","M6N4FDZI ","M6N4FIXI ", & + "M6N4FIYI ","M6N4FIZI ","M6N4FMGXI","M6N4FMGYI","M6N4FMGZI","M6N4MAFXI","M6N4MAFYI", & + "M6N4MAFZI","M6N4MAGXI","M6N4MAGYI","M6N4MAGZI","M6N4MBFXI","M6N4MBFYI","M6N4MBFZI", & + "M6N4MBXI ","M6N4MBYI ","M6N4MBZI ","M6N4MMGXI","M6N4MMGYI","M6N4MMGZI","M6N4STAXI", & + "M6N4STAYI","M6N4STAZI","M6N4STVXI","M6N4STVYI","M6N4STVZI","M6N4VXI ","M6N4VYI ", & + "M6N4VZI ","M6N5AXI ","M6N5AYI ","M6N5AZI ","M6N5DYNP ","M6N5FAFXI","M6N5FAFYI", & + "M6N5FAFZI","M6N5FAGXI","M6N5FAGYI","M6N5FAGZI","M6N5FAMXI","M6N5FAMYI","M6N5FAMZI", & + "M6N5FBFXI","M6N5FBFYI","M6N5FBFZI","M6N5FBXI ","M6N5FBYI ","M6N5FBZI ","M6N5FDXI ", & + "M6N5FDYI ","M6N5FDZI ","M6N5FIXI ","M6N5FIYI ","M6N5FIZI ","M6N5FMGXI","M6N5FMGYI", & + "M6N5FMGZI","M6N5MAFXI","M6N5MAFYI","M6N5MAFZI","M6N5MAGXI","M6N5MAGYI","M6N5MAGZI", & + "M6N5MBFXI","M6N5MBFYI","M6N5MBFZI","M6N5MBXI ","M6N5MBYI ","M6N5MBZI ","M6N5MMGXI", & + "M6N5MMGYI","M6N5MMGZI","M6N5STAXI","M6N5STAYI","M6N5STAZI","M6N5STVXI","M6N5STVYI", & + "M6N5STVZI","M6N5VXI ","M6N5VYI ","M6N5VZI ","M6N6AXI ","M6N6AYI ","M6N6AZI ", & + "M6N6DYNP ","M6N6FAFXI","M6N6FAFYI","M6N6FAFZI","M6N6FAGXI","M6N6FAGYI","M6N6FAGZI", & + "M6N6FAMXI","M6N6FAMYI","M6N6FAMZI"/) + ValidParamAry(3001:3500) = (/ & + "M6N6FBFXI","M6N6FBFYI","M6N6FBFZI","M6N6FBXI ","M6N6FBYI ","M6N6FBZI ","M6N6FDXI ", & + "M6N6FDYI ","M6N6FDZI ","M6N6FIXI ","M6N6FIYI ","M6N6FIZI ","M6N6FMGXI","M6N6FMGYI", & + "M6N6FMGZI","M6N6MAFXI","M6N6MAFYI","M6N6MAFZI","M6N6MAGXI","M6N6MAGYI","M6N6MAGZI", & + "M6N6MBFXI","M6N6MBFYI","M6N6MBFZI","M6N6MBXI ","M6N6MBYI ","M6N6MBZI ","M6N6MMGXI", & + "M6N6MMGYI","M6N6MMGZI","M6N6STAXI","M6N6STAYI","M6N6STAZI","M6N6STVXI","M6N6STVYI", & + "M6N6STVZI","M6N6VXI ","M6N6VYI ","M6N6VZI ","M6N7AXI ","M6N7AYI ","M6N7AZI ", & + "M6N7DYNP ","M6N7FAFXI","M6N7FAFYI","M6N7FAFZI","M6N7FAGXI","M6N7FAGYI","M6N7FAGZI", & + "M6N7FAMXI","M6N7FAMYI","M6N7FAMZI","M6N7FBFXI","M6N7FBFYI","M6N7FBFZI","M6N7FBXI ", & + "M6N7FBYI ","M6N7FBZI ","M6N7FDXI ","M6N7FDYI ","M6N7FDZI ","M6N7FIXI ","M6N7FIYI ", & + "M6N7FIZI ","M6N7FMGXI","M6N7FMGYI","M6N7FMGZI","M6N7MAFXI","M6N7MAFYI","M6N7MAFZI", & + "M6N7MAGXI","M6N7MAGYI","M6N7MAGZI","M6N7MBFXI","M6N7MBFYI","M6N7MBFZI","M6N7MBXI ", & + "M6N7MBYI ","M6N7MBZI ","M6N7MMGXI","M6N7MMGYI","M6N7MMGZI","M6N7STAXI","M6N7STAYI", & + "M6N7STAZI","M6N7STVXI","M6N7STVYI","M6N7STVZI","M6N7VXI ","M6N7VYI ","M6N7VZI ", & + "M6N8AXI ","M6N8AYI ","M6N8AZI ","M6N8DYNP ","M6N8FAFXI","M6N8FAFYI","M6N8FAFZI", & + "M6N8FAGXI","M6N8FAGYI","M6N8FAGZI","M6N8FAMXI","M6N8FAMYI","M6N8FAMZI","M6N8FBFXI", & + "M6N8FBFYI","M6N8FBFZI","M6N8FBXI ","M6N8FBYI ","M6N8FBZI ","M6N8FDXI ","M6N8FDYI ", & + "M6N8FDZI ","M6N8FIXI ","M6N8FIYI ","M6N8FIZI ","M6N8FMGXI","M6N8FMGYI","M6N8FMGZI", & + "M6N8MAFXI","M6N8MAFYI","M6N8MAFZI","M6N8MAGXI","M6N8MAGYI","M6N8MAGZI","M6N8MBFXI", & + "M6N8MBFYI","M6N8MBFZI","M6N8MBXI ","M6N8MBYI ","M6N8MBZI ","M6N8MMGXI","M6N8MMGYI", & + "M6N8MMGZI","M6N8STAXI","M6N8STAYI","M6N8STAZI","M6N8STVXI","M6N8STVYI","M6N8STVZI", & + "M6N8VXI ","M6N8VYI ","M6N8VZI ","M6N9AXI ","M6N9AYI ","M6N9AZI ","M6N9DYNP ", & + "M6N9FAFXI","M6N9FAFYI","M6N9FAFZI","M6N9FAGXI","M6N9FAGYI","M6N9FAGZI","M6N9FAMXI", & + "M6N9FAMYI","M6N9FAMZI","M6N9FBFXI","M6N9FBFYI","M6N9FBFZI","M6N9FBXI ","M6N9FBYI ", & + "M6N9FBZI ","M6N9FDXI ","M6N9FDYI ","M6N9FDZI ","M6N9FIXI ","M6N9FIYI ","M6N9FIZI ", & + "M6N9FMGXI","M6N9FMGYI","M6N9FMGZI","M6N9MAFXI","M6N9MAFYI","M6N9MAFZI","M6N9MAGXI", & + "M6N9MAGYI","M6N9MAGZI","M6N9MBFXI","M6N9MBFYI","M6N9MBFZI","M6N9MBXI ","M6N9MBYI ", & + "M6N9MBZI ","M6N9MMGXI","M6N9MMGYI","M6N9MMGZI","M6N9STAXI","M6N9STAYI","M6N9STAZI", & + "M6N9STVXI","M6N9STVYI","M6N9STVZI","M6N9VXI ","M6N9VYI ","M6N9VZI ","M7N1AXI ", & + "M7N1AYI ","M7N1AZI ","M7N1DYNP ","M7N1FAFXI","M7N1FAFYI","M7N1FAFZI","M7N1FAGXI", & + "M7N1FAGYI","M7N1FAGZI","M7N1FAMXI","M7N1FAMYI","M7N1FAMZI","M7N1FBFXI","M7N1FBFYI", & + "M7N1FBFZI","M7N1FBXI ","M7N1FBYI ","M7N1FBZI ","M7N1FDXI ","M7N1FDYI ","M7N1FDZI ", & + "M7N1FIXI ","M7N1FIYI ","M7N1FIZI ","M7N1FMGXI","M7N1FMGYI","M7N1FMGZI","M7N1MAFXI", & + "M7N1MAFYI","M7N1MAFZI","M7N1MAGXI","M7N1MAGYI","M7N1MAGZI","M7N1MBFXI","M7N1MBFYI", & + "M7N1MBFZI","M7N1MBXI ","M7N1MBYI ","M7N1MBZI ","M7N1MMGXI","M7N1MMGYI","M7N1MMGZI", & + "M7N1STAXI","M7N1STAYI","M7N1STAZI","M7N1STVXI","M7N1STVYI","M7N1STVZI","M7N1VXI ", & + "M7N1VYI ","M7N1VZI ","M7N2AXI ","M7N2AYI ","M7N2AZI ","M7N2DYNP ","M7N2FAFXI", & + "M7N2FAFYI","M7N2FAFZI","M7N2FAGXI","M7N2FAGYI","M7N2FAGZI","M7N2FAMXI","M7N2FAMYI", & + "M7N2FAMZI","M7N2FBFXI","M7N2FBFYI","M7N2FBFZI","M7N2FBXI ","M7N2FBYI ","M7N2FBZI ", & + "M7N2FDXI ","M7N2FDYI ","M7N2FDZI ","M7N2FIXI ","M7N2FIYI ","M7N2FIZI ","M7N2FMGXI", & + "M7N2FMGYI","M7N2FMGZI","M7N2MAFXI","M7N2MAFYI","M7N2MAFZI","M7N2MAGXI","M7N2MAGYI", & + "M7N2MAGZI","M7N2MBFXI","M7N2MBFYI","M7N2MBFZI","M7N2MBXI ","M7N2MBYI ","M7N2MBZI ", & + "M7N2MMGXI","M7N2MMGYI","M7N2MMGZI","M7N2STAXI","M7N2STAYI","M7N2STAZI","M7N2STVXI", & + "M7N2STVYI","M7N2STVZI","M7N2VXI ","M7N2VYI ","M7N2VZI ","M7N3AXI ","M7N3AYI ", & + "M7N3AZI ","M7N3DYNP ","M7N3FAFXI","M7N3FAFYI","M7N3FAFZI","M7N3FAGXI","M7N3FAGYI", & + "M7N3FAGZI","M7N3FAMXI","M7N3FAMYI","M7N3FAMZI","M7N3FBFXI","M7N3FBFYI","M7N3FBFZI", & + "M7N3FBXI ","M7N3FBYI ","M7N3FBZI ","M7N3FDXI ","M7N3FDYI ","M7N3FDZI ","M7N3FIXI ", & + "M7N3FIYI ","M7N3FIZI ","M7N3FMGXI","M7N3FMGYI","M7N3FMGZI","M7N3MAFXI","M7N3MAFYI", & + "M7N3MAFZI","M7N3MAGXI","M7N3MAGYI","M7N3MAGZI","M7N3MBFXI","M7N3MBFYI","M7N3MBFZI", & + "M7N3MBXI ","M7N3MBYI ","M7N3MBZI ","M7N3MMGXI","M7N3MMGYI","M7N3MMGZI","M7N3STAXI", & + "M7N3STAYI","M7N3STAZI","M7N3STVXI","M7N3STVYI","M7N3STVZI","M7N3VXI ","M7N3VYI ", & + "M7N3VZI ","M7N4AXI ","M7N4AYI ","M7N4AZI ","M7N4DYNP ","M7N4FAFXI","M7N4FAFYI", & + "M7N4FAFZI","M7N4FAGXI","M7N4FAGYI","M7N4FAGZI","M7N4FAMXI","M7N4FAMYI","M7N4FAMZI", & + "M7N4FBFXI","M7N4FBFYI","M7N4FBFZI","M7N4FBXI ","M7N4FBYI ","M7N4FBZI ","M7N4FDXI ", & + "M7N4FDYI ","M7N4FDZI ","M7N4FIXI ","M7N4FIYI ","M7N4FIZI ","M7N4FMGXI","M7N4FMGYI", & + "M7N4FMGZI","M7N4MAFXI","M7N4MAFYI","M7N4MAFZI","M7N4MAGXI","M7N4MAGYI","M7N4MAGZI", & + "M7N4MBFXI","M7N4MBFYI","M7N4MBFZI","M7N4MBXI ","M7N4MBYI ","M7N4MBZI ","M7N4MMGXI", & + "M7N4MMGYI","M7N4MMGZI","M7N4STAXI","M7N4STAYI","M7N4STAZI","M7N4STVXI","M7N4STVYI", & + "M7N4STVZI","M7N4VXI ","M7N4VYI ","M7N4VZI ","M7N5AXI ","M7N5AYI ","M7N5AZI ", & + "M7N5DYNP ","M7N5FAFXI","M7N5FAFYI","M7N5FAFZI","M7N5FAGXI","M7N5FAGYI","M7N5FAGZI", & + "M7N5FAMXI","M7N5FAMYI","M7N5FAMZI","M7N5FBFXI","M7N5FBFYI","M7N5FBFZI","M7N5FBXI ", & + "M7N5FBYI ","M7N5FBZI ","M7N5FDXI ","M7N5FDYI ","M7N5FDZI ","M7N5FIXI ","M7N5FIYI ", & + "M7N5FIZI ","M7N5FMGXI","M7N5FMGYI","M7N5FMGZI","M7N5MAFXI","M7N5MAFYI","M7N5MAFZI", & + "M7N5MAGXI","M7N5MAGYI","M7N5MAGZI","M7N5MBFXI","M7N5MBFYI","M7N5MBFZI","M7N5MBXI ", & + "M7N5MBYI ","M7N5MBZI ","M7N5MMGXI","M7N5MMGYI","M7N5MMGZI","M7N5STAXI","M7N5STAYI", & + "M7N5STAZI","M7N5STVXI","M7N5STVYI","M7N5STVZI","M7N5VXI ","M7N5VYI ","M7N5VZI ", & + "M7N6AXI ","M7N6AYI ","M7N6AZI ","M7N6DYNP ","M7N6FAFXI","M7N6FAFYI","M7N6FAFZI", & + "M7N6FAGXI","M7N6FAGYI","M7N6FAGZI","M7N6FAMXI","M7N6FAMYI","M7N6FAMZI","M7N6FBFXI", & + "M7N6FBFYI","M7N6FBFZI","M7N6FBXI ","M7N6FBYI ","M7N6FBZI ","M7N6FDXI ","M7N6FDYI ", & + "M7N6FDZI ","M7N6FIXI ","M7N6FIYI ","M7N6FIZI ","M7N6FMGXI","M7N6FMGYI","M7N6FMGZI", & + "M7N6MAFXI","M7N6MAFYI","M7N6MAFZI","M7N6MAGXI","M7N6MAGYI","M7N6MAGZI","M7N6MBFXI", & + "M7N6MBFYI","M7N6MBFZI","M7N6MBXI ","M7N6MBYI ","M7N6MBZI ","M7N6MMGXI","M7N6MMGYI", & + "M7N6MMGZI","M7N6STAXI","M7N6STAYI"/) + ValidParamAry(3501:4000) = (/ & + "M7N6STAZI","M7N6STVXI","M7N6STVYI","M7N6STVZI","M7N6VXI ","M7N6VYI ","M7N6VZI ", & + "M7N7AXI ","M7N7AYI ","M7N7AZI ","M7N7DYNP ","M7N7FAFXI","M7N7FAFYI","M7N7FAFZI", & + "M7N7FAGXI","M7N7FAGYI","M7N7FAGZI","M7N7FAMXI","M7N7FAMYI","M7N7FAMZI","M7N7FBFXI", & + "M7N7FBFYI","M7N7FBFZI","M7N7FBXI ","M7N7FBYI ","M7N7FBZI ","M7N7FDXI ","M7N7FDYI ", & + "M7N7FDZI ","M7N7FIXI ","M7N7FIYI ","M7N7FIZI ","M7N7FMGXI","M7N7FMGYI","M7N7FMGZI", & + "M7N7MAFXI","M7N7MAFYI","M7N7MAFZI","M7N7MAGXI","M7N7MAGYI","M7N7MAGZI","M7N7MBFXI", & + "M7N7MBFYI","M7N7MBFZI","M7N7MBXI ","M7N7MBYI ","M7N7MBZI ","M7N7MMGXI","M7N7MMGYI", & + "M7N7MMGZI","M7N7STAXI","M7N7STAYI","M7N7STAZI","M7N7STVXI","M7N7STVYI","M7N7STVZI", & + "M7N7VXI ","M7N7VYI ","M7N7VZI ","M7N8AXI ","M7N8AYI ","M7N8AZI ","M7N8DYNP ", & + "M7N8FAFXI","M7N8FAFYI","M7N8FAFZI","M7N8FAGXI","M7N8FAGYI","M7N8FAGZI","M7N8FAMXI", & + "M7N8FAMYI","M7N8FAMZI","M7N8FBFXI","M7N8FBFYI","M7N8FBFZI","M7N8FBXI ","M7N8FBYI ", & + "M7N8FBZI ","M7N8FDXI ","M7N8FDYI ","M7N8FDZI ","M7N8FIXI ","M7N8FIYI ","M7N8FIZI ", & + "M7N8FMGXI","M7N8FMGYI","M7N8FMGZI","M7N8MAFXI","M7N8MAFYI","M7N8MAFZI","M7N8MAGXI", & + "M7N8MAGYI","M7N8MAGZI","M7N8MBFXI","M7N8MBFYI","M7N8MBFZI","M7N8MBXI ","M7N8MBYI ", & + "M7N8MBZI ","M7N8MMGXI","M7N8MMGYI","M7N8MMGZI","M7N8STAXI","M7N8STAYI","M7N8STAZI", & + "M7N8STVXI","M7N8STVYI","M7N8STVZI","M7N8VXI ","M7N8VYI ","M7N8VZI ","M7N9AXI ", & + "M7N9AYI ","M7N9AZI ","M7N9DYNP ","M7N9FAFXI","M7N9FAFYI","M7N9FAFZI","M7N9FAGXI", & + "M7N9FAGYI","M7N9FAGZI","M7N9FAMXI","M7N9FAMYI","M7N9FAMZI","M7N9FBFXI","M7N9FBFYI", & + "M7N9FBFZI","M7N9FBXI ","M7N9FBYI ","M7N9FBZI ","M7N9FDXI ","M7N9FDYI ","M7N9FDZI ", & + "M7N9FIXI ","M7N9FIYI ","M7N9FIZI ","M7N9FMGXI","M7N9FMGYI","M7N9FMGZI","M7N9MAFXI", & + "M7N9MAFYI","M7N9MAFZI","M7N9MAGXI","M7N9MAGYI","M7N9MAGZI","M7N9MBFXI","M7N9MBFYI", & + "M7N9MBFZI","M7N9MBXI ","M7N9MBYI ","M7N9MBZI ","M7N9MMGXI","M7N9MMGYI","M7N9MMGZI", & + "M7N9STAXI","M7N9STAYI","M7N9STAZI","M7N9STVXI","M7N9STVYI","M7N9STVZI","M7N9VXI ", & + "M7N9VYI ","M7N9VZI ","M8N1AXI ","M8N1AYI ","M8N1AZI ","M8N1DYNP ","M8N1FAFXI", & + "M8N1FAFYI","M8N1FAFZI","M8N1FAGXI","M8N1FAGYI","M8N1FAGZI","M8N1FAMXI","M8N1FAMYI", & + "M8N1FAMZI","M8N1FBFXI","M8N1FBFYI","M8N1FBFZI","M8N1FBXI ","M8N1FBYI ","M8N1FBZI ", & + "M8N1FDXI ","M8N1FDYI ","M8N1FDZI ","M8N1FIXI ","M8N1FIYI ","M8N1FIZI ","M8N1FMGXI", & + "M8N1FMGYI","M8N1FMGZI","M8N1MAFXI","M8N1MAFYI","M8N1MAFZI","M8N1MAGXI","M8N1MAGYI", & + "M8N1MAGZI","M8N1MBFXI","M8N1MBFYI","M8N1MBFZI","M8N1MBXI ","M8N1MBYI ","M8N1MBZI ", & + "M8N1MMGXI","M8N1MMGYI","M8N1MMGZI","M8N1STAXI","M8N1STAYI","M8N1STAZI","M8N1STVXI", & + "M8N1STVYI","M8N1STVZI","M8N1VXI ","M8N1VYI ","M8N1VZI ","M8N2AXI ","M8N2AYI ", & + "M8N2AZI ","M8N2DYNP ","M8N2FAFXI","M8N2FAFYI","M8N2FAFZI","M8N2FAGXI","M8N2FAGYI", & + "M8N2FAGZI","M8N2FAMXI","M8N2FAMYI","M8N2FAMZI","M8N2FBFXI","M8N2FBFYI","M8N2FBFZI", & + "M8N2FBXI ","M8N2FBYI ","M8N2FBZI ","M8N2FDXI ","M8N2FDYI ","M8N2FDZI ","M8N2FIXI ", & + "M8N2FIYI ","M8N2FIZI ","M8N2FMGXI","M8N2FMGYI","M8N2FMGZI","M8N2MAFXI","M8N2MAFYI", & + "M8N2MAFZI","M8N2MAGXI","M8N2MAGYI","M8N2MAGZI","M8N2MBFXI","M8N2MBFYI","M8N2MBFZI", & + "M8N2MBXI ","M8N2MBYI ","M8N2MBZI ","M8N2MMGXI","M8N2MMGYI","M8N2MMGZI","M8N2STAXI", & + "M8N2STAYI","M8N2STAZI","M8N2STVXI","M8N2STVYI","M8N2STVZI","M8N2VXI ","M8N2VYI ", & + "M8N2VZI ","M8N3AXI ","M8N3AYI ","M8N3AZI ","M8N3DYNP ","M8N3FAFXI","M8N3FAFYI", & + "M8N3FAFZI","M8N3FAGXI","M8N3FAGYI","M8N3FAGZI","M8N3FAMXI","M8N3FAMYI","M8N3FAMZI", & + "M8N3FBFXI","M8N3FBFYI","M8N3FBFZI","M8N3FBXI ","M8N3FBYI ","M8N3FBZI ","M8N3FDXI ", & + "M8N3FDYI ","M8N3FDZI ","M8N3FIXI ","M8N3FIYI ","M8N3FIZI ","M8N3FMGXI","M8N3FMGYI", & + "M8N3FMGZI","M8N3MAFXI","M8N3MAFYI","M8N3MAFZI","M8N3MAGXI","M8N3MAGYI","M8N3MAGZI", & + "M8N3MBFXI","M8N3MBFYI","M8N3MBFZI","M8N3MBXI ","M8N3MBYI ","M8N3MBZI ","M8N3MMGXI", & + "M8N3MMGYI","M8N3MMGZI","M8N3STAXI","M8N3STAYI","M8N3STAZI","M8N3STVXI","M8N3STVYI", & + "M8N3STVZI","M8N3VXI ","M8N3VYI ","M8N3VZI ","M8N4AXI ","M8N4AYI ","M8N4AZI ", & + "M8N4DYNP ","M8N4FAFXI","M8N4FAFYI","M8N4FAFZI","M8N4FAGXI","M8N4FAGYI","M8N4FAGZI", & + "M8N4FAMXI","M8N4FAMYI","M8N4FAMZI","M8N4FBFXI","M8N4FBFYI","M8N4FBFZI","M8N4FBXI ", & + "M8N4FBYI ","M8N4FBZI ","M8N4FDXI ","M8N4FDYI ","M8N4FDZI ","M8N4FIXI ","M8N4FIYI ", & + "M8N4FIZI ","M8N4FMGXI","M8N4FMGYI","M8N4FMGZI","M8N4MAFXI","M8N4MAFYI","M8N4MAFZI", & + "M8N4MAGXI","M8N4MAGYI","M8N4MAGZI","M8N4MBFXI","M8N4MBFYI","M8N4MBFZI","M8N4MBXI ", & + "M8N4MBYI ","M8N4MBZI ","M8N4MMGXI","M8N4MMGYI","M8N4MMGZI","M8N4STAXI","M8N4STAYI", & + "M8N4STAZI","M8N4STVXI","M8N4STVYI","M8N4STVZI","M8N4VXI ","M8N4VYI ","M8N4VZI ", & + "M8N5AXI ","M8N5AYI ","M8N5AZI ","M8N5DYNP ","M8N5FAFXI","M8N5FAFYI","M8N5FAFZI", & + "M8N5FAGXI","M8N5FAGYI","M8N5FAGZI","M8N5FAMXI","M8N5FAMYI","M8N5FAMZI","M8N5FBFXI", & + "M8N5FBFYI","M8N5FBFZI","M8N5FBXI ","M8N5FBYI ","M8N5FBZI ","M8N5FDXI ","M8N5FDYI ", & + "M8N5FDZI ","M8N5FIXI ","M8N5FIYI ","M8N5FIZI ","M8N5FMGXI","M8N5FMGYI","M8N5FMGZI", & + "M8N5MAFXI","M8N5MAFYI","M8N5MAFZI","M8N5MAGXI","M8N5MAGYI","M8N5MAGZI","M8N5MBFXI", & + "M8N5MBFYI","M8N5MBFZI","M8N5MBXI ","M8N5MBYI ","M8N5MBZI ","M8N5MMGXI","M8N5MMGYI", & + "M8N5MMGZI","M8N5STAXI","M8N5STAYI","M8N5STAZI","M8N5STVXI","M8N5STVYI","M8N5STVZI", & + "M8N5VXI ","M8N5VYI ","M8N5VZI ","M8N6AXI ","M8N6AYI ","M8N6AZI ","M8N6DYNP ", & + "M8N6FAFXI","M8N6FAFYI","M8N6FAFZI","M8N6FAGXI","M8N6FAGYI","M8N6FAGZI","M8N6FAMXI", & + "M8N6FAMYI","M8N6FAMZI","M8N6FBFXI","M8N6FBFYI","M8N6FBFZI","M8N6FBXI ","M8N6FBYI ", & + "M8N6FBZI ","M8N6FDXI ","M8N6FDYI ","M8N6FDZI ","M8N6FIXI ","M8N6FIYI ","M8N6FIZI ", & + "M8N6FMGXI","M8N6FMGYI","M8N6FMGZI","M8N6MAFXI","M8N6MAFYI","M8N6MAFZI","M8N6MAGXI", & + "M8N6MAGYI","M8N6MAGZI","M8N6MBFXI","M8N6MBFYI","M8N6MBFZI","M8N6MBXI ","M8N6MBYI ", & + "M8N6MBZI ","M8N6MMGXI","M8N6MMGYI","M8N6MMGZI","M8N6STAXI","M8N6STAYI","M8N6STAZI", & + "M8N6STVXI","M8N6STVYI","M8N6STVZI","M8N6VXI ","M8N6VYI ","M8N6VZI ","M8N7AXI ", & + "M8N7AYI ","M8N7AZI ","M8N7DYNP ","M8N7FAFXI","M8N7FAFYI","M8N7FAFZI","M8N7FAGXI", & + "M8N7FAGYI","M8N7FAGZI","M8N7FAMXI","M8N7FAMYI","M8N7FAMZI","M8N7FBFXI","M8N7FBFYI", & + "M8N7FBFZI","M8N7FBXI ","M8N7FBYI ","M8N7FBZI ","M8N7FDXI ","M8N7FDYI ","M8N7FDZI ", & + "M8N7FIXI ","M8N7FIYI ","M8N7FIZI "/) + ValidParamAry(4001:4500) = (/ & + "M8N7FMGXI","M8N7FMGYI","M8N7FMGZI","M8N7MAFXI","M8N7MAFYI","M8N7MAFZI","M8N7MAGXI", & + "M8N7MAGYI","M8N7MAGZI","M8N7MBFXI","M8N7MBFYI","M8N7MBFZI","M8N7MBXI ","M8N7MBYI ", & + "M8N7MBZI ","M8N7MMGXI","M8N7MMGYI","M8N7MMGZI","M8N7STAXI","M8N7STAYI","M8N7STAZI", & + "M8N7STVXI","M8N7STVYI","M8N7STVZI","M8N7VXI ","M8N7VYI ","M8N7VZI ","M8N8AXI ", & + "M8N8AYI ","M8N8AZI ","M8N8DYNP ","M8N8FAFXI","M8N8FAFYI","M8N8FAFZI","M8N8FAGXI", & + "M8N8FAGYI","M8N8FAGZI","M8N8FAMXI","M8N8FAMYI","M8N8FAMZI","M8N8FBFXI","M8N8FBFYI", & + "M8N8FBFZI","M8N8FBXI ","M8N8FBYI ","M8N8FBZI ","M8N8FDXI ","M8N8FDYI ","M8N8FDZI ", & + "M8N8FIXI ","M8N8FIYI ","M8N8FIZI ","M8N8FMGXI","M8N8FMGYI","M8N8FMGZI","M8N8MAFXI", & + "M8N8MAFYI","M8N8MAFZI","M8N8MAGXI","M8N8MAGYI","M8N8MAGZI","M8N8MBFXI","M8N8MBFYI", & + "M8N8MBFZI","M8N8MBXI ","M8N8MBYI ","M8N8MBZI ","M8N8MMGXI","M8N8MMGYI","M8N8MMGZI", & + "M8N8STAXI","M8N8STAYI","M8N8STAZI","M8N8STVXI","M8N8STVYI","M8N8STVZI","M8N8VXI ", & + "M8N8VYI ","M8N8VZI ","M8N9AXI ","M8N9AYI ","M8N9AZI ","M8N9DYNP ","M8N9FAFXI", & + "M8N9FAFYI","M8N9FAFZI","M8N9FAGXI","M8N9FAGYI","M8N9FAGZI","M8N9FAMXI","M8N9FAMYI", & + "M8N9FAMZI","M8N9FBFXI","M8N9FBFYI","M8N9FBFZI","M8N9FBXI ","M8N9FBYI ","M8N9FBZI ", & + "M8N9FDXI ","M8N9FDYI ","M8N9FDZI ","M8N9FIXI ","M8N9FIYI ","M8N9FIZI ","M8N9FMGXI", & + "M8N9FMGYI","M8N9FMGZI","M8N9MAFXI","M8N9MAFYI","M8N9MAFZI","M8N9MAGXI","M8N9MAGYI", & + "M8N9MAGZI","M8N9MBFXI","M8N9MBFYI","M8N9MBFZI","M8N9MBXI ","M8N9MBYI ","M8N9MBZI ", & + "M8N9MMGXI","M8N9MMGYI","M8N9MMGZI","M8N9STAXI","M8N9STAYI","M8N9STAZI","M8N9STVXI", & + "M8N9STVYI","M8N9STVZI","M8N9VXI ","M8N9VYI ","M8N9VZI ","M9N1AXI ","M9N1AYI ", & + "M9N1AZI ","M9N1DYNP ","M9N1FAFXI","M9N1FAFYI","M9N1FAFZI","M9N1FAGXI","M9N1FAGYI", & + "M9N1FAGZI","M9N1FAMXI","M9N1FAMYI","M9N1FAMZI","M9N1FBFXI","M9N1FBFYI","M9N1FBFZI", & + "M9N1FBXI ","M9N1FBYI ","M9N1FBZI ","M9N1FDXI ","M9N1FDYI ","M9N1FDZI ","M9N1FIXI ", & + "M9N1FIYI ","M9N1FIZI ","M9N1FMGXI","M9N1FMGYI","M9N1FMGZI","M9N1MAFXI","M9N1MAFYI", & + "M9N1MAFZI","M9N1MAGXI","M9N1MAGYI","M9N1MAGZI","M9N1MBFXI","M9N1MBFYI","M9N1MBFZI", & + "M9N1MBXI ","M9N1MBYI ","M9N1MBZI ","M9N1MMGXI","M9N1MMGYI","M9N1MMGZI","M9N1STAXI", & + "M9N1STAYI","M9N1STAZI","M9N1STVXI","M9N1STVYI","M9N1STVZI","M9N1VXI ","M9N1VYI ", & + "M9N1VZI ","M9N2AXI ","M9N2AYI ","M9N2AZI ","M9N2DYNP ","M9N2FAFXI","M9N2FAFYI", & + "M9N2FAFZI","M9N2FAGXI","M9N2FAGYI","M9N2FAGZI","M9N2FAMXI","M9N2FAMYI","M9N2FAMZI", & + "M9N2FBFXI","M9N2FBFYI","M9N2FBFZI","M9N2FBXI ","M9N2FBYI ","M9N2FBZI ","M9N2FDXI ", & + "M9N2FDYI ","M9N2FDZI ","M9N2FIXI ","M9N2FIYI ","M9N2FIZI ","M9N2FMGXI","M9N2FMGYI", & + "M9N2FMGZI","M9N2MAFXI","M9N2MAFYI","M9N2MAFZI","M9N2MAGXI","M9N2MAGYI","M9N2MAGZI", & + "M9N2MBFXI","M9N2MBFYI","M9N2MBFZI","M9N2MBXI ","M9N2MBYI ","M9N2MBZI ","M9N2MMGXI", & + "M9N2MMGYI","M9N2MMGZI","M9N2STAXI","M9N2STAYI","M9N2STAZI","M9N2STVXI","M9N2STVYI", & + "M9N2STVZI","M9N2VXI ","M9N2VYI ","M9N2VZI ","M9N3AXI ","M9N3AYI ","M9N3AZI ", & + "M9N3DYNP ","M9N3FAFXI","M9N3FAFYI","M9N3FAFZI","M9N3FAGXI","M9N3FAGYI","M9N3FAGZI", & + "M9N3FAMXI","M9N3FAMYI","M9N3FAMZI","M9N3FBFXI","M9N3FBFYI","M9N3FBFZI","M9N3FBXI ", & + "M9N3FBYI ","M9N3FBZI ","M9N3FDXI ","M9N3FDYI ","M9N3FDZI ","M9N3FIXI ","M9N3FIYI ", & + "M9N3FIZI ","M9N3FMGXI","M9N3FMGYI","M9N3FMGZI","M9N3MAFXI","M9N3MAFYI","M9N3MAFZI", & + "M9N3MAGXI","M9N3MAGYI","M9N3MAGZI","M9N3MBFXI","M9N3MBFYI","M9N3MBFZI","M9N3MBXI ", & + "M9N3MBYI ","M9N3MBZI ","M9N3MMGXI","M9N3MMGYI","M9N3MMGZI","M9N3STAXI","M9N3STAYI", & + "M9N3STAZI","M9N3STVXI","M9N3STVYI","M9N3STVZI","M9N3VXI ","M9N3VYI ","M9N3VZI ", & + "M9N4AXI ","M9N4AYI ","M9N4AZI ","M9N4DYNP ","M9N4FAFXI","M9N4FAFYI","M9N4FAFZI", & + "M9N4FAGXI","M9N4FAGYI","M9N4FAGZI","M9N4FAMXI","M9N4FAMYI","M9N4FAMZI","M9N4FBFXI", & + "M9N4FBFYI","M9N4FBFZI","M9N4FBXI ","M9N4FBYI ","M9N4FBZI ","M9N4FDXI ","M9N4FDYI ", & + "M9N4FDZI ","M9N4FIXI ","M9N4FIYI ","M9N4FIZI ","M9N4FMGXI","M9N4FMGYI","M9N4FMGZI", & + "M9N4MAFXI","M9N4MAFYI","M9N4MAFZI","M9N4MAGXI","M9N4MAGYI","M9N4MAGZI","M9N4MBFXI", & + "M9N4MBFYI","M9N4MBFZI","M9N4MBXI ","M9N4MBYI ","M9N4MBZI ","M9N4MMGXI","M9N4MMGYI", & + "M9N4MMGZI","M9N4STAXI","M9N4STAYI","M9N4STAZI","M9N4STVXI","M9N4STVYI","M9N4STVZI", & + "M9N4VXI ","M9N4VYI ","M9N4VZI ","M9N5AXI ","M9N5AYI ","M9N5AZI ","M9N5DYNP ", & + "M9N5FAFXI","M9N5FAFYI","M9N5FAFZI","M9N5FAGXI","M9N5FAGYI","M9N5FAGZI","M9N5FAMXI", & + "M9N5FAMYI","M9N5FAMZI","M9N5FBFXI","M9N5FBFYI","M9N5FBFZI","M9N5FBXI ","M9N5FBYI ", & + "M9N5FBZI ","M9N5FDXI ","M9N5FDYI ","M9N5FDZI ","M9N5FIXI ","M9N5FIYI ","M9N5FIZI ", & + "M9N5FMGXI","M9N5FMGYI","M9N5FMGZI","M9N5MAFXI","M9N5MAFYI","M9N5MAFZI","M9N5MAGXI", & + "M9N5MAGYI","M9N5MAGZI","M9N5MBFXI","M9N5MBFYI","M9N5MBFZI","M9N5MBXI ","M9N5MBYI ", & + "M9N5MBZI ","M9N5MMGXI","M9N5MMGYI","M9N5MMGZI","M9N5STAXI","M9N5STAYI","M9N5STAZI", & + "M9N5STVXI","M9N5STVYI","M9N5STVZI","M9N5VXI ","M9N5VYI ","M9N5VZI ","M9N6AXI ", & + "M9N6AYI ","M9N6AZI ","M9N6DYNP ","M9N6FAFXI","M9N6FAFYI","M9N6FAFZI","M9N6FAGXI", & + "M9N6FAGYI","M9N6FAGZI","M9N6FAMXI","M9N6FAMYI","M9N6FAMZI","M9N6FBFXI","M9N6FBFYI", & + "M9N6FBFZI","M9N6FBXI ","M9N6FBYI ","M9N6FBZI ","M9N6FDXI ","M9N6FDYI ","M9N6FDZI ", & + "M9N6FIXI ","M9N6FIYI ","M9N6FIZI ","M9N6FMGXI","M9N6FMGYI","M9N6FMGZI","M9N6MAFXI", & + "M9N6MAFYI","M9N6MAFZI","M9N6MAGXI","M9N6MAGYI","M9N6MAGZI","M9N6MBFXI","M9N6MBFYI", & + "M9N6MBFZI","M9N6MBXI ","M9N6MBYI ","M9N6MBZI ","M9N6MMGXI","M9N6MMGYI","M9N6MMGZI", & + "M9N6STAXI","M9N6STAYI","M9N6STAZI","M9N6STVXI","M9N6STVYI","M9N6STVZI","M9N6VXI ", & + "M9N6VYI ","M9N6VZI ","M9N7AXI ","M9N7AYI ","M9N7AZI ","M9N7DYNP ","M9N7FAFXI", & + "M9N7FAFYI","M9N7FAFZI","M9N7FAGXI","M9N7FAGYI","M9N7FAGZI","M9N7FAMXI","M9N7FAMYI", & + "M9N7FAMZI","M9N7FBFXI","M9N7FBFYI","M9N7FBFZI","M9N7FBXI ","M9N7FBYI ","M9N7FBZI ", & + "M9N7FDXI ","M9N7FDYI ","M9N7FDZI ","M9N7FIXI ","M9N7FIYI ","M9N7FIZI ","M9N7FMGXI", & + "M9N7FMGYI","M9N7FMGZI","M9N7MAFXI","M9N7MAFYI","M9N7MAFZI","M9N7MAGXI","M9N7MAGYI", & + "M9N7MAGZI","M9N7MBFXI","M9N7MBFYI","M9N7MBFZI","M9N7MBXI ","M9N7MBYI ","M9N7MBZI ", & + "M9N7MMGXI","M9N7MMGYI","M9N7MMGZI","M9N7STAXI","M9N7STAYI","M9N7STAZI","M9N7STVXI", & + "M9N7STVYI","M9N7STVZI","M9N7VXI ","M9N7VYI ","M9N7VZI ","M9N8AXI ","M9N8AYI ", & + "M9N8AZI ","M9N8DYNP ","M9N8FAFXI"/) + ValidParamAry(4501:4599) = (/ & + "M9N8FAFYI","M9N8FAFZI","M9N8FAGXI","M9N8FAGYI","M9N8FAGZI","M9N8FAMXI","M9N8FAMYI", & + "M9N8FAMZI","M9N8FBFXI","M9N8FBFYI","M9N8FBFZI","M9N8FBXI ","M9N8FBYI ","M9N8FBZI ", & + "M9N8FDXI ","M9N8FDYI ","M9N8FDZI ","M9N8FIXI ","M9N8FIYI ","M9N8FIZI ","M9N8FMGXI", & + "M9N8FMGYI","M9N8FMGZI","M9N8MAFXI","M9N8MAFYI","M9N8MAFZI","M9N8MAGXI","M9N8MAGYI", & + "M9N8MAGZI","M9N8MBFXI","M9N8MBFYI","M9N8MBFZI","M9N8MBXI ","M9N8MBYI ","M9N8MBZI ", & + "M9N8MMGXI","M9N8MMGYI","M9N8MMGZI","M9N8STAXI","M9N8STAYI","M9N8STAZI","M9N8STVXI", & + "M9N8STVYI","M9N8STVZI","M9N8VXI ","M9N8VYI ","M9N8VZI ","M9N9AXI ","M9N9AYI ", & + "M9N9AZI ","M9N9DYNP ","M9N9FAFXI","M9N9FAFYI","M9N9FAFZI","M9N9FAGXI","M9N9FAGYI", & + "M9N9FAGZI","M9N9FAMXI","M9N9FAMYI","M9N9FAMZI","M9N9FBFXI","M9N9FBFYI","M9N9FBFZI", & + "M9N9FBXI ","M9N9FBYI ","M9N9FBZI ","M9N9FDXI ","M9N9FDYI ","M9N9FDZI ","M9N9FIXI ", & + "M9N9FIYI ","M9N9FIZI ","M9N9FMGXI","M9N9FMGYI","M9N9FMGZI","M9N9MAFXI","M9N9MAFYI", & + "M9N9MAFZI","M9N9MAGXI","M9N9MAGYI","M9N9MAGZI","M9N9MBFXI","M9N9MBFYI","M9N9MBFZI", & + "M9N9MBXI ","M9N9MBYI ","M9N9MBZI ","M9N9MMGXI","M9N9MMGYI","M9N9MMGZI","M9N9STAXI", & + "M9N9STAYI","M9N9STAZI","M9N9STVXI","M9N9STVYI","M9N9STVZI","M9N9VXI ","M9N9VYI ", & + "M9N9VZI "/) + ParamIndxAry(1:500) = (/ & + J1Axi , J1Ayi , J1Azi , J1DynP , J1FAGxi , J1FAGyi , J1FAGzi , & + J1FAMxi , J1FAMyi , J1FAMzi , J1FBFxi , J1FBFyi , J1FBFzi , J1FBxi , & + J1FByi , J1FBzi , J1FDxi , J1FDyi , J1FDzi , J1FIxi , J1FIyi , & + J1FIzi , J1FMGxi , J1FMGyi , J1FMGzi , J1MAGxi , J1MAGyi , J1MAGzi , & + J1MBFxi , J1MBFyi , J1MBFzi , J1MBxi , J1MByi , J1MBzi , J1STAxi , & + J1STAyi , J1STAzi , J1STVxi , J1STVyi , J1STVzi , J1Vxi , J1Vyi , & + J1Vzi , J2Axi , J2Ayi , J2Azi , J2DynP , J2FAGxi , J2FAGyi , & + J2FAGzi , J2FAMxi , J2FAMyi , J2FAMzi , J2FBFxi , J2FBFyi , J2FBFzi , & + J2FBxi , J2FByi , J2FBzi , J2FDxi , J2FDyi , J2FDzi , J2FIxi , & + J2FIyi , J2FIzi , J2FMGxi , J2FMGyi , J2FMGzi , J2MAGxi , J2MAGyi , & + J2MAGzi , J2MBFxi , J2MBFyi , J2MBFzi , J2MBxi , J2MByi , J2MBzi , & + J2STAxi , J2STAyi , J2STAzi , J2STVxi , J2STVyi , J2STVzi , J2Vxi , & + J2Vyi , J2Vzi , J3Axi , J3Ayi , J3Azi , J3DynP , J3FAGxi , & + J3FAGyi , J3FAGzi , J3FAMxi , J3FAMyi , J3FAMzi , J3FBFxi , J3FBFyi , & + J3FBFzi , J3FBxi , J3FByi , J3FBzi , J3FDxi , J3FDyi , J3FDzi , & + J3FIxi , J3FIyi , J3FIzi , J3FMGxi , J3FMGyi , J3FMGzi , J3MAGxi , & + J3MAGyi , J3MAGzi , J3MBFxi , J3MBFyi , J3MBFzi , J3MBxi , J3MByi , & + J3MBzi , J3STAxi , J3STAyi , J3STAzi , J3STVxi , J3STVyi , J3STVzi , & + J3Vxi , J3Vyi , J3Vzi , J4Axi , J4Ayi , J4Azi , J4DynP , & + J4FAGxi , J4FAGyi , J4FAGzi , J4FAMxi , J4FAMyi , J4FAMzi , J4FBFxi , & + J4FBFyi , J4FBFzi , J4FBxi , J4FByi , J4FBzi , J4FDxi , J4FDyi , & + J4FDzi , J4FIxi , J4FIyi , J4FIzi , J4FMGxi , J4FMGyi , J4FMGzi , & + J4MAGxi , J4MAGyi , J4MAGzi , J4MBFxi , J4MBFyi , J4MBFzi , J4MBxi , & + J4MByi , J4MBzi , J4STAxi , J4STAyi , J4STAzi , J4STVxi , J4STVyi , & + J4STVzi , J4Vxi , J4Vyi , J4Vzi , J5Axi , J5Ayi , J5Azi , & + J5DynP , J5FAGxi , J5FAGyi , J5FAGzi , J5FAMxi , J5FAMyi , J5FAMzi , & + J5FBFxi , J5FBFyi , J5FBFzi , J5FBxi , J5FByi , J5FBzi , J5FDxi , & + J5FDyi , J5FDzi , J5FIxi , J5FIyi , J5FIzi , J5FMGxi , J5FMGyi , & + J5FMGzi , J5MAGxi , J5MAGyi , J5MAGzi , J5MBFxi , J5MBFyi , J5MBFzi , & + J5MBxi , J5MByi , J5MBzi , J5STAxi , J5STAyi , J5STAzi , J5STVxi , & + J5STVyi , J5STVzi , J5Vxi , J5Vyi , J5Vzi , J6Axi , J6Ayi , & + J6Azi , J6DynP , J6FAGxi , J6FAGyi , J6FAGzi , J6FAMxi , J6FAMyi , & + J6FAMzi , J6FBFxi , J6FBFyi , J6FBFzi , J6FBxi , J6FByi , J6FBzi , & + J6FDxi , J6FDyi , J6FDzi , J6FIxi , J6FIyi , J6FIzi , J6FMGxi , & + J6FMGyi , J6FMGzi , J6MAGxi , J6MAGyi , J6MAGzi , J6MBFxi , J6MBFyi , & + J6MBFzi , J6MBxi , J6MByi , J6MBzi , J6STAxi , J6STAyi , J6STAzi , & + J6STVxi , J6STVyi , J6STVzi , J6Vxi , J6Vyi , J6Vzi , J7Axi , & + J7Ayi , J7Azi , J7DynP , J7FAGxi , J7FAGyi , J7FAGzi , J7FAMxi , & + J7FAMyi , J7FAMzi , J7FBFxi , J7FBFyi , J7FBFzi , J7FBxi , J7FByi , & + J7FBzi , J7FDxi , J7FDyi , J7FDzi , J7FIxi , J7FIyi , J7FIzi , & + J7FMGxi , J7FMGyi , J7FMGzi , J7MAGxi , J7MAGyi , J7MAGzi , J7MBFxi , & + J7MBFyi , J7MBFzi , J7MBxi , J7MByi , J7MBzi , J7STAxi , J7STAyi , & + J7STAzi , J7STVxi , J7STVyi , J7STVzi , J7Vxi , J7Vyi , J7Vzi , & + J8Axi , J8Ayi , J8Azi , J8DynP , J8FAGxi , J8FAGyi , J8FAGzi , & + J8FAMxi , J8FAMyi , J8FAMzi , J8FBFxi , J8FBFyi , J8FBFzi , J8FBxi , & + J8FByi , J8FBzi , J8FDxi , J8FDyi , J8FDzi , J8FIxi , J8FIyi , & + J8FIzi , J8FMGxi , J8FMGyi , J8FMGzi , J8MAGxi , J8MAGyi , J8MAGzi , & + J8MBFxi , J8MBFyi , J8MBFzi , J8MBxi , J8MByi , J8MBzi , J8STAxi , & + J8STAyi , J8STAzi , J8STVxi , J8STVyi , J8STVzi , J8Vxi , J8Vyi , & + J8Vzi , J9Axi , J9Ayi , J9Azi , J9DynP , J9FAGxi , J9FAGyi , & + J9FAGzi , J9FAMxi , J9FAMyi , J9FAMzi , J9FBFxi , J9FBFyi , J9FBFzi , & + J9FBxi , J9FByi , J9FBzi , J9FDxi , J9FDyi , J9FDzi , J9FIxi , & + J9FIyi , J9FIzi , J9FMGxi , J9FMGyi , J9FMGzi , J9MAGxi , J9MAGyi , & + J9MAGzi , J9MBFxi , J9MBFyi , J9MBFzi , J9MBxi , J9MByi , J9MBzi , & + J9STAxi , J9STAyi , J9STAzi , J9STVxi , J9STVyi , J9STVzi , J9Vxi , & + J9Vyi , J9Vzi , M1N1Axi , M1N1Ayi , M1N1Azi , M1N1DynP , M1N1FAFxi , & + M1N1FAFyi , M1N1FAFzi , M1N1FAGxi , M1N1FAGyi , M1N1FAGzi , M1N1FAMxi , M1N1FAMyi , & + M1N1FAMzi , M1N1FBFxi , M1N1FBFyi , M1N1FBFzi , M1N1FBxi , M1N1FByi , M1N1FBzi , & + M1N1FDxi , M1N1FDyi , M1N1FDzi , M1N1FIxi , M1N1FIyi , M1N1FIzi , M1N1FMGxi , & + M1N1FMGyi , M1N1FMGzi , M1N1MAFxi , M1N1MAFyi , M1N1MAFzi , M1N1MAGxi , M1N1MAGyi , & + M1N1MAGzi , M1N1MBFxi , M1N1MBFyi , M1N1MBFzi , M1N1MBxi , M1N1MByi , M1N1MBzi , & + M1N1MMGxi , M1N1MMGyi , M1N1MMGzi , M1N1STAxi , M1N1STAyi , M1N1STAzi , M1N1STVxi , & + M1N1STVyi , M1N1STVzi , M1N1Vxi , M1N1Vyi , M1N1Vzi , M1N2Axi , M1N2Ayi , & + M1N2Azi , M1N2DynP , M1N2FAFxi , M1N2FAFyi , M1N2FAFzi , M1N2FAGxi , M1N2FAGyi , & + M1N2FAGzi , M1N2FAMxi , M1N2FAMyi , M1N2FAMzi , M1N2FBFxi , M1N2FBFyi , M1N2FBFzi , & + M1N2FBxi , M1N2FByi , M1N2FBzi , M1N2FDxi , M1N2FDyi , M1N2FDzi , M1N2FIxi , & + M1N2FIyi , M1N2FIzi , M1N2FMGxi , M1N2FMGyi , M1N2FMGzi , M1N2MAFxi , M1N2MAFyi , & + M1N2MAFzi , M1N2MAGxi , M1N2MAGyi , M1N2MAGzi , M1N2MBFxi , M1N2MBFyi , M1N2MBFzi , & + M1N2MBxi , M1N2MByi , M1N2MBzi , M1N2MMGxi , M1N2MMGyi , M1N2MMGzi , M1N2STAxi , & + M1N2STAyi , M1N2STAzi , M1N2STVxi , M1N2STVyi , M1N2STVzi , M1N2Vxi , M1N2Vyi , & + M1N2Vzi , M1N3Axi , M1N3Ayi , M1N3Azi , M1N3DynP , M1N3FAFxi , M1N3FAFyi , & + M1N3FAFzi , M1N3FAGxi , M1N3FAGyi /) + ParamIndxAry(501:1000) = (/ & + M1N3FAGzi , M1N3FAMxi , M1N3FAMyi , M1N3FAMzi , M1N3FBFxi , M1N3FBFyi , M1N3FBFzi , & + M1N3FBxi , M1N3FByi , M1N3FBzi , M1N3FDxi , M1N3FDyi , M1N3FDzi , M1N3FIxi , & + M1N3FIyi , M1N3FIzi , M1N3FMGxi , M1N3FMGyi , M1N3FMGzi , M1N3MAFxi , M1N3MAFyi , & + M1N3MAFzi , M1N3MAGxi , M1N3MAGyi , M1N3MAGzi , M1N3MBFxi , M1N3MBFyi , M1N3MBFzi , & + M1N3MBxi , M1N3MByi , M1N3MBzi , M1N3MMGxi , M1N3MMGyi , M1N3MMGzi , M1N3STAxi , & + M1N3STAyi , M1N3STAzi , M1N3STVxi , M1N3STVyi , M1N3STVzi , M1N3Vxi , M1N3Vyi , & + M1N3Vzi , M1N4Axi , M1N4Ayi , M1N4Azi , M1N4DynP , M1N4FAFxi , M1N4FAFyi , & + M1N4FAFzi , M1N4FAGxi , M1N4FAGyi , M1N4FAGzi , M1N4FAMxi , M1N4FAMyi , M1N4FAMzi , & + M1N4FBFxi , M1N4FBFyi , M1N4FBFzi , M1N4FBxi , M1N4FByi , M1N4FBzi , M1N4FDxi , & + M1N4FDyi , M1N4FDzi , M1N4FIxi , M1N4FIyi , M1N4FIzi , M1N4FMGxi , M1N4FMGyi , & + M1N4FMGzi , M1N4MAFxi , M1N4MAFyi , M1N4MAFzi , M1N4MAGxi , M1N4MAGyi , M1N4MAGzi , & + M1N4MBFxi , M1N4MBFyi , M1N4MBFzi , M1N4MBxi , M1N4MByi , M1N4MBzi , M1N4MMGxi , & + M1N4MMGyi , M1N4MMGzi , M1N4STAxi , M1N4STAyi , M1N4STAzi , M1N4STVxi , M1N4STVyi , & + M1N4STVzi , M1N4Vxi , M1N4Vyi , M1N4Vzi , M1N5Axi , M1N5Ayi , M1N5Azi , & + M1N5DynP , M1N5FAFxi , M1N5FAFyi , M1N5FAFzi , M1N5FAGxi , M1N5FAGyi , M1N5FAGzi , & + M1N5FAMxi , M1N5FAMyi , M1N5FAMzi , M1N5FBFxi , M1N5FBFyi , M1N5FBFzi , M1N5FBxi , & + M1N5FByi , M1N5FBzi , M1N5FDxi , M1N5FDyi , M1N5FDzi , M1N5FIxi , M1N5FIyi , & + M1N5FIzi , M1N5FMGxi , M1N5FMGyi , M1N5FMGzi , M1N5MAFxi , M1N5MAFyi , M1N5MAFzi , & + M1N5MAGxi , M1N5MAGyi , M1N5MAGzi , M1N5MBFxi , M1N5MBFyi , M1N5MBFzi , M1N5MBxi , & + M1N5MByi , M1N5MBzi , M1N5MMGxi , M1N5MMGyi , M1N5MMGzi , M1N5STAxi , M1N5STAyi , & + M1N5STAzi , M1N5STVxi , M1N5STVyi , M1N5STVzi , M1N5Vxi , M1N5Vyi , M1N5Vzi , & + M1N6Axi , M1N6Ayi , M1N6Azi , M1N6DynP , M1N6FAFxi , M1N6FAFyi , M1N6FAFzi , & + M1N6FAGxi , M1N6FAGyi , M1N6FAGzi , M1N6FAMxi , M1N6FAMyi , M1N6FAMzi , M1N6FBFxi , & + M1N6FBFyi , M1N6FBFzi , M1N6FBxi , M1N6FByi , M1N6FBzi , M1N6FDxi , M1N6FDyi , & + M1N6FDzi , M1N6FIxi , M1N6FIyi , M1N6FIzi , M1N6FMGxi , M1N6FMGyi , M1N6FMGzi , & + M1N6MAFxi , M1N6MAFyi , M1N6MAFzi , M1N6MAGxi , M1N6MAGyi , M1N6MAGzi , M1N6MBFxi , & + M1N6MBFyi , M1N6MBFzi , M1N6MBxi , M1N6MByi , M1N6MBzi , M1N6MMGxi , M1N6MMGyi , & + M1N6MMGzi , M1N6STAxi , M1N6STAyi , M1N6STAzi , M1N6STVxi , M1N6STVyi , M1N6STVzi , & + M1N6Vxi , M1N6Vyi , M1N6Vzi , M1N7Axi , M1N7Ayi , M1N7Azi , M1N7DynP , & + M1N7FAFxi , M1N7FAFyi , M1N7FAFzi , M1N7FAGxi , M1N7FAGyi , M1N7FAGzi , M1N7FAMxi , & + M1N7FAMyi , M1N7FAMzi , M1N7FBFxi , M1N7FBFyi , M1N7FBFzi , M1N7FBxi , M1N7FByi , & + M1N7FBzi , M1N7FDxi , M1N7FDyi , M1N7FDzi , M1N7FIxi , M1N7FIyi , M1N7FIzi , & + M1N7FMGxi , M1N7FMGyi , M1N7FMGzi , M1N7MAFxi , M1N7MAFyi , M1N7MAFzi , M1N7MAGxi , & + M1N7MAGyi , M1N7MAGzi , M1N7MBFxi , M1N7MBFyi , M1N7MBFzi , M1N7MBxi , M1N7MByi , & + M1N7MBzi , M1N7MMGxi , M1N7MMGyi , M1N7MMGzi , M1N7STAxi , M1N7STAyi , M1N7STAzi , & + M1N7STVxi , M1N7STVyi , M1N7STVzi , M1N7Vxi , M1N7Vyi , M1N7Vzi , M1N8Axi , & + M1N8Ayi , M1N8Azi , M1N8DynP , M1N8FAFxi , M1N8FAFyi , M1N8FAFzi , M1N8FAGxi , & + M1N8FAGyi , M1N8FAGzi , M1N8FAMxi , M1N8FAMyi , M1N8FAMzi , M1N8FBFxi , M1N8FBFyi , & + M1N8FBFzi , M1N8FBxi , M1N8FByi , M1N8FBzi , M1N8FDxi , M1N8FDyi , M1N8FDzi , & + M1N8FIxi , M1N8FIyi , M1N8FIzi , M1N8FMGxi , M1N8FMGyi , M1N8FMGzi , M1N8MAFxi , & + M1N8MAFyi , M1N8MAFzi , M1N8MAGxi , M1N8MAGyi , M1N8MAGzi , M1N8MBFxi , M1N8MBFyi , & + M1N8MBFzi , M1N8MBxi , M1N8MByi , M1N8MBzi , M1N8MMGxi , M1N8MMGyi , M1N8MMGzi , & + M1N8STAxi , M1N8STAyi , M1N8STAzi , M1N8STVxi , M1N8STVyi , M1N8STVzi , M1N8Vxi , & + M1N8Vyi , M1N8Vzi , M1N9Axi , M1N9Ayi , M1N9Azi , M1N9DynP , M1N9FAFxi , & + M1N9FAFyi , M1N9FAFzi , M1N9FAGxi , M1N9FAGyi , M1N9FAGzi , M1N9FAMxi , M1N9FAMyi , & + M1N9FAMzi , M1N9FBFxi , M1N9FBFyi , M1N9FBFzi , M1N9FBxi , M1N9FByi , M1N9FBzi , & + M1N9FDxi , M1N9FDyi , M1N9FDzi , M1N9FIxi , M1N9FIyi , M1N9FIzi , M1N9FMGxi , & + M1N9FMGyi , M1N9FMGzi , M1N9MAFxi , M1N9MAFyi , M1N9MAFzi , M1N9MAGxi , M1N9MAGyi , & + M1N9MAGzi , M1N9MBFxi , M1N9MBFyi , M1N9MBFzi , M1N9MBxi , M1N9MByi , M1N9MBzi , & + M1N9MMGxi , M1N9MMGyi , M1N9MMGzi , M1N9STAxi , M1N9STAyi , M1N9STAzi , M1N9STVxi , & + M1N9STVyi , M1N9STVzi , M1N9Vxi , M1N9Vyi , M1N9Vzi , M2N1Axi , M2N1Ayi , & + M2N1Azi , M2N1DynP , M2N1FAFxi , M2N1FAFyi , M2N1FAFzi , M2N1FAGxi , M2N1FAGyi , & + M2N1FAGzi , M2N1FAMxi , M2N1FAMyi , M2N1FAMzi , M2N1FBFxi , M2N1FBFyi , M2N1FBFzi , & + M2N1FBxi , M2N1FByi , M2N1FBzi , M2N1FDxi , M2N1FDyi , M2N1FDzi , M2N1FIxi , & + M2N1FIyi , M2N1FIzi , M2N1FMGxi , M2N1FMGyi , M2N1FMGzi , M2N1MAFxi , M2N1MAFyi , & + M2N1MAFzi , M2N1MAGxi , M2N1MAGyi , M2N1MAGzi , M2N1MBFxi , M2N1MBFyi , M2N1MBFzi , & + M2N1MBxi , M2N1MByi , M2N1MBzi , M2N1MMGxi , M2N1MMGyi , M2N1MMGzi , M2N1STAxi , & + M2N1STAyi , M2N1STAzi , M2N1STVxi , M2N1STVyi , M2N1STVzi , M2N1Vxi , M2N1Vyi , & + M2N1Vzi , M2N2Axi , M2N2Ayi , M2N2Azi , M2N2DynP , M2N2FAFxi , M2N2FAFyi , & + M2N2FAFzi , M2N2FAGxi , M2N2FAGyi , M2N2FAGzi , M2N2FAMxi , M2N2FAMyi , M2N2FAMzi , & + M2N2FBFxi , M2N2FBFyi , M2N2FBFzi , M2N2FBxi , M2N2FByi , M2N2FBzi , M2N2FDxi , & + M2N2FDyi , M2N2FDzi , M2N2FIxi , M2N2FIyi , M2N2FIzi , M2N2FMGxi , M2N2FMGyi , & + M2N2FMGzi , M2N2MAFxi , M2N2MAFyi , M2N2MAFzi , M2N2MAGxi , M2N2MAGyi , M2N2MAGzi , & + M2N2MBFxi , M2N2MBFyi , M2N2MBFzi , M2N2MBxi , M2N2MByi , M2N2MBzi , M2N2MMGxi , & + M2N2MMGyi , M2N2MMGzi , M2N2STAxi , M2N2STAyi , M2N2STAzi , M2N2STVxi , M2N2STVyi , & + M2N2STVzi , M2N2Vxi , M2N2Vyi , M2N2Vzi , M2N3Axi , M2N3Ayi , M2N3Azi , & + M2N3DynP , M2N3FAFxi , M2N3FAFyi , M2N3FAFzi , M2N3FAGxi , M2N3FAGyi , M2N3FAGzi , & + M2N3FAMxi , M2N3FAMyi , M2N3FAMzi , M2N3FBFxi , M2N3FBFyi , M2N3FBFzi , M2N3FBxi , & + M2N3FByi , M2N3FBzi , M2N3FDxi , M2N3FDyi , M2N3FDzi , M2N3FIxi , M2N3FIyi , & + M2N3FIzi , M2N3FMGxi , M2N3FMGyi , M2N3FMGzi , M2N3MAFxi , M2N3MAFyi , M2N3MAFzi , & + M2N3MAGxi , M2N3MAGyi , M2N3MAGzi , M2N3MBFxi , M2N3MBFyi , M2N3MBFzi , M2N3MBxi , & + M2N3MByi , M2N3MBzi , M2N3MMGxi /) + ParamIndxAry(1001:1500) = (/ & + M2N3MMGyi , M2N3MMGzi , M2N3STAxi , M2N3STAyi , M2N3STAzi , M2N3STVxi , M2N3STVyi , & + M2N3STVzi , M2N3Vxi , M2N3Vyi , M2N3Vzi , M2N4Axi , M2N4Ayi , M2N4Azi , & + M2N4DynP , M2N4FAFxi , M2N4FAFyi , M2N4FAFzi , M2N4FAGxi , M2N4FAGyi , M2N4FAGzi , & + M2N4FAMxi , M2N4FAMyi , M2N4FAMzi , M2N4FBFxi , M2N4FBFyi , M2N4FBFzi , M2N4FBxi , & + M2N4FByi , M2N4FBzi , M2N4FDxi , M2N4FDyi , M2N4FDzi , M2N4FIxi , M2N4FIyi , & + M2N4FIzi , M2N4FMGxi , M2N4FMGyi , M2N4FMGzi , M2N4MAFxi , M2N4MAFyi , M2N4MAFzi , & + M2N4MAGxi , M2N4MAGyi , M2N4MAGzi , M2N4MBFxi , M2N4MBFyi , M2N4MBFzi , M2N4MBxi , & + M2N4MByi , M2N4MBzi , M2N4MMGxi , M2N4MMGyi , M2N4MMGzi , M2N4STAxi , M2N4STAyi , & + M2N4STAzi , M2N4STVxi , M2N4STVyi , M2N4STVzi , M2N4Vxi , M2N4Vyi , M2N4Vzi , & + M2N5Axi , M2N5Ayi , M2N5Azi , M2N5DynP , M2N5FAFxi , M2N5FAFyi , M2N5FAFzi , & + M2N5FAGxi , M2N5FAGyi , M2N5FAGzi , M2N5FAMxi , M2N5FAMyi , M2N5FAMzi , M2N5FBFxi , & + M2N5FBFyi , M2N5FBFzi , M2N5FBxi , M2N5FByi , M2N5FBzi , M2N5FDxi , M2N5FDyi , & + M2N5FDzi , M2N5FIxi , M2N5FIyi , M2N5FIzi , M2N5FMGxi , M2N5FMGyi , M2N5FMGzi , & + M2N5MAFxi , M2N5MAFyi , M2N5MAFzi , M2N5MAGxi , M2N5MAGyi , M2N5MAGzi , M2N5MBFxi , & + M2N5MBFyi , M2N5MBFzi , M2N5MBxi , M2N5MByi , M2N5MBzi , M2N5MMGxi , M2N5MMGyi , & + M2N5MMGzi , M2N5STAxi , M2N5STAyi , M2N5STAzi , M2N5STVxi , M2N5STVyi , M2N5STVzi , & + M2N5Vxi , M2N5Vyi , M2N5Vzi , M2N6Axi , M2N6Ayi , M2N6Azi , M2N6DynP , & + M2N6FAFxi , M2N6FAFyi , M2N6FAFzi , M2N6FAGxi , M2N6FAGyi , M2N6FAGzi , M2N6FAMxi , & + M2N6FAMyi , M2N6FAMzi , M2N6FBFxi , M2N6FBFyi , M2N6FBFzi , M2N6FBxi , M2N6FByi , & + M2N6FBzi , M2N6FDxi , M2N6FDyi , M2N6FDzi , M2N6FIxi , M2N6FIyi , M2N6FIzi , & + M2N6FMGxi , M2N6FMGyi , M2N6FMGzi , M2N6MAFxi , M2N6MAFyi , M2N6MAFzi , M2N6MAGxi , & + M2N6MAGyi , M2N6MAGzi , M2N6MBFxi , M2N6MBFyi , M2N6MBFzi , M2N6MBxi , M2N6MByi , & + M2N6MBzi , M2N6MMGxi , M2N6MMGyi , M2N6MMGzi , M2N6STAxi , M2N6STAyi , M2N6STAzi , & + M2N6STVxi , M2N6STVyi , M2N6STVzi , M2N6Vxi , M2N6Vyi , M2N6Vzi , M2N7Axi , & + M2N7Ayi , M2N7Azi , M2N7DynP , M2N7FAFxi , M2N7FAFyi , M2N7FAFzi , M2N7FAGxi , & + M2N7FAGyi , M2N7FAGzi , M2N7FAMxi , M2N7FAMyi , M2N7FAMzi , M2N7FBFxi , M2N7FBFyi , & + M2N7FBFzi , M2N7FBxi , M2N7FByi , M2N7FBzi , M2N7FDxi , M2N7FDyi , M2N7FDzi , & + M2N7FIxi , M2N7FIyi , M2N7FIzi , M2N7FMGxi , M2N7FMGyi , M2N7FMGzi , M2N7MAFxi , & + M2N7MAFyi , M2N7MAFzi , M2N7MAGxi , M2N7MAGyi , M2N7MAGzi , M2N7MBFxi , M2N7MBFyi , & + M2N7MBFzi , M2N7MBxi , M2N7MByi , M2N7MBzi , M2N7MMGxi , M2N7MMGyi , M2N7MMGzi , & + M2N7STAxi , M2N7STAyi , M2N7STAzi , M2N7STVxi , M2N7STVyi , M2N7STVzi , M2N7Vxi , & + M2N7Vyi , M2N7Vzi , M2N8Axi , M2N8Ayi , M2N8Azi , M2N8DynP , M2N8FAFxi , & + M2N8FAFyi , M2N8FAFzi , M2N8FAGxi , M2N8FAGyi , M2N8FAGzi , M2N8FAMxi , M2N8FAMyi , & + M2N8FAMzi , M2N8FBFxi , M2N8FBFyi , M2N8FBFzi , M2N8FBxi , M2N8FByi , M2N8FBzi , & + M2N8FDxi , M2N8FDyi , M2N8FDzi , M2N8FIxi , M2N8FIyi , M2N8FIzi , M2N8FMGxi , & + M2N8FMGyi , M2N8FMGzi , M2N8MAFxi , M2N8MAFyi , M2N8MAFzi , M2N8MAGxi , M2N8MAGyi , & + M2N8MAGzi , M2N8MBFxi , M2N8MBFyi , M2N8MBFzi , M2N8MBxi , M2N8MByi , M2N8MBzi , & + M2N8MMGxi , M2N8MMGyi , M2N8MMGzi , M2N8STAxi , M2N8STAyi , M2N8STAzi , M2N8STVxi , & + M2N8STVyi , M2N8STVzi , M2N8Vxi , M2N8Vyi , M2N8Vzi , M2N9Axi , M2N9Ayi , & + M2N9Azi , M2N9DynP , M2N9FAFxi , M2N9FAFyi , M2N9FAFzi , M2N9FAGxi , M2N9FAGyi , & + M2N9FAGzi , M2N9FAMxi , M2N9FAMyi , M2N9FAMzi , M2N9FBFxi , M2N9FBFyi , M2N9FBFzi , & + M2N9FBxi , M2N9FByi , M2N9FBzi , M2N9FDxi , M2N9FDyi , M2N9FDzi , M2N9FIxi , & + M2N9FIyi , M2N9FIzi , M2N9FMGxi , M2N9FMGyi , M2N9FMGzi , M2N9MAFxi , M2N9MAFyi , & + M2N9MAFzi , M2N9MAGxi , M2N9MAGyi , M2N9MAGzi , M2N9MBFxi , M2N9MBFyi , M2N9MBFzi , & + M2N9MBxi , M2N9MByi , M2N9MBzi , M2N9MMGxi , M2N9MMGyi , M2N9MMGzi , M2N9STAxi , & + M2N9STAyi , M2N9STAzi , M2N9STVxi , M2N9STVyi , M2N9STVzi , M2N9Vxi , M2N9Vyi , & + M2N9Vzi , M3N1Axi , M3N1Ayi , M3N1Azi , M3N1DynP , M3N1FAFxi , M3N1FAFyi , & + M3N1FAFzi , M3N1FAGxi , M3N1FAGyi , M3N1FAGzi , M3N1FAMxi , M3N1FAMyi , M3N1FAMzi , & + M3N1FBFxi , M3N1FBFyi , M3N1FBFzi , M3N1FBxi , M3N1FByi , M3N1FBzi , M3N1FDxi , & + M3N1FDyi , M3N1FDzi , M3N1FIxi , M3N1FIyi , M3N1FIzi , M3N1FMGxi , M3N1FMGyi , & + M3N1FMGzi , M3N1MAFxi , M3N1MAFyi , M3N1MAFzi , M3N1MAGxi , M3N1MAGyi , M3N1MAGzi , & + M3N1MBFxi , M3N1MBFyi , M3N1MBFzi , M3N1MBxi , M3N1MByi , M3N1MBzi , M3N1MMGxi , & + M3N1MMGyi , M3N1MMGzi , M3N1STAxi , M3N1STAyi , M3N1STAzi , M3N1STVxi , M3N1STVyi , & + M3N1STVzi , M3N1Vxi , M3N1Vyi , M3N1Vzi , M3N2Axi , M3N2Ayi , M3N2Azi , & + M3N2DynP , M3N2FAFxi , M3N2FAFyi , M3N2FAFzi , M3N2FAGxi , M3N2FAGyi , M3N2FAGzi , & + M3N2FAMxi , M3N2FAMyi , M3N2FAMzi , M3N2FBFxi , M3N2FBFyi , M3N2FBFzi , M3N2FBxi , & + M3N2FByi , M3N2FBzi , M3N2FDxi , M3N2FDyi , M3N2FDzi , M3N2FIxi , M3N2FIyi , & + M3N2FIzi , M3N2FMGxi , M3N2FMGyi , M3N2FMGzi , M3N2MAFxi , M3N2MAFyi , M3N2MAFzi , & + M3N2MAGxi , M3N2MAGyi , M3N2MAGzi , M3N2MBFxi , M3N2MBFyi , M3N2MBFzi , M3N2MBxi , & + M3N2MByi , M3N2MBzi , M3N2MMGxi , M3N2MMGyi , M3N2MMGzi , M3N2STAxi , M3N2STAyi , & + M3N2STAzi , M3N2STVxi , M3N2STVyi , M3N2STVzi , M3N2Vxi , M3N2Vyi , M3N2Vzi , & + M3N3Axi , M3N3Ayi , M3N3Azi , M3N3DynP , M3N3FAFxi , M3N3FAFyi , M3N3FAFzi , & + M3N3FAGxi , M3N3FAGyi , M3N3FAGzi , M3N3FAMxi , M3N3FAMyi , M3N3FAMzi , M3N3FBFxi , & + M3N3FBFyi , M3N3FBFzi , M3N3FBxi , M3N3FByi , M3N3FBzi , M3N3FDxi , M3N3FDyi , & + M3N3FDzi , M3N3FIxi , M3N3FIyi , M3N3FIzi , M3N3FMGxi , M3N3FMGyi , M3N3FMGzi , & + M3N3MAFxi , M3N3MAFyi , M3N3MAFzi , M3N3MAGxi , M3N3MAGyi , M3N3MAGzi , M3N3MBFxi , & + M3N3MBFyi , M3N3MBFzi , M3N3MBxi , M3N3MByi , M3N3MBzi , M3N3MMGxi , M3N3MMGyi , & + M3N3MMGzi , M3N3STAxi , M3N3STAyi , M3N3STAzi , M3N3STVxi , M3N3STVyi , M3N3STVzi , & + M3N3Vxi , M3N3Vyi , M3N3Vzi , M3N4Axi , M3N4Ayi , M3N4Azi , M3N4DynP , & + M3N4FAFxi , M3N4FAFyi , M3N4FAFzi , M3N4FAGxi , M3N4FAGyi , M3N4FAGzi , M3N4FAMxi , & + M3N4FAMyi , M3N4FAMzi , M3N4FBFxi , M3N4FBFyi , M3N4FBFzi , M3N4FBxi , M3N4FByi , & + M3N4FBzi , M3N4FDxi , M3N4FDyi /) + ParamIndxAry(1501:2000) = (/ & + M3N4FDzi , M3N4FIxi , M3N4FIyi , M3N4FIzi , M3N4FMGxi , M3N4FMGyi , M3N4FMGzi , & + M3N4MAFxi , M3N4MAFyi , M3N4MAFzi , M3N4MAGxi , M3N4MAGyi , M3N4MAGzi , M3N4MBFxi , & + M3N4MBFyi , M3N4MBFzi , M3N4MBxi , M3N4MByi , M3N4MBzi , M3N4MMGxi , M3N4MMGyi , & + M3N4MMGzi , M3N4STAxi , M3N4STAyi , M3N4STAzi , M3N4STVxi , M3N4STVyi , M3N4STVzi , & + M3N4Vxi , M3N4Vyi , M3N4Vzi , M3N5Axi , M3N5Ayi , M3N5Azi , M3N5DynP , & + M3N5FAFxi , M3N5FAFyi , M3N5FAFzi , M3N5FAGxi , M3N5FAGyi , M3N5FAGzi , M3N5FAMxi , & + M3N5FAMyi , M3N5FAMzi , M3N5FBFxi , M3N5FBFyi , M3N5FBFzi , M3N5FBxi , M3N5FByi , & + M3N5FBzi , M3N5FDxi , M3N5FDyi , M3N5FDzi , M3N5FIxi , M3N5FIyi , M3N5FIzi , & + M3N5FMGxi , M3N5FMGyi , M3N5FMGzi , M3N5MAFxi , M3N5MAFyi , M3N5MAFzi , M3N5MAGxi , & + M3N5MAGyi , M3N5MAGzi , M3N5MBFxi , M3N5MBFyi , M3N5MBFzi , M3N5MBxi , M3N5MByi , & + M3N5MBzi , M3N5MMGxi , M3N5MMGyi , M3N5MMGzi , M3N5STAxi , M3N5STAyi , M3N5STAzi , & + M3N5STVxi , M3N5STVyi , M3N5STVzi , M3N5Vxi , M3N5Vyi , M3N5Vzi , M3N6Axi , & + M3N6Ayi , M3N6Azi , M3N6DynP , M3N6FAFxi , M3N6FAFyi , M3N6FAFzi , M3N6FAGxi , & + M3N6FAGyi , M3N6FAGzi , M3N6FAMxi , M3N6FAMyi , M3N6FAMzi , M3N6FBFxi , M3N6FBFyi , & + M3N6FBFzi , M3N6FBxi , M3N6FByi , M3N6FBzi , M3N6FDxi , M3N6FDyi , M3N6FDzi , & + M3N6FIxi , M3N6FIyi , M3N6FIzi , M3N6FMGxi , M3N6FMGyi , M3N6FMGzi , M3N6MAFxi , & + M3N6MAFyi , M3N6MAFzi , M3N6MAGxi , M3N6MAGyi , M3N6MAGzi , M3N6MBFxi , M3N6MBFyi , & + M3N6MBFzi , M3N6MBxi , M3N6MByi , M3N6MBzi , M3N6MMGxi , M3N6MMGyi , M3N6MMGzi , & + M3N6STAxi , M3N6STAyi , M3N6STAzi , M3N6STVxi , M3N6STVyi , M3N6STVzi , M3N6Vxi , & + M3N6Vyi , M3N6Vzi , M3N7Axi , M3N7Ayi , M3N7Azi , M3N7DynP , M3N7FAFxi , & + M3N7FAFyi , M3N7FAFzi , M3N7FAGxi , M3N7FAGyi , M3N7FAGzi , M3N7FAMxi , M3N7FAMyi , & + M3N7FAMzi , M3N7FBFxi , M3N7FBFyi , M3N7FBFzi , M3N7FBxi , M3N7FByi , M3N7FBzi , & + M3N7FDxi , M3N7FDyi , M3N7FDzi , M3N7FIxi , M3N7FIyi , M3N7FIzi , M3N7FMGxi , & + M3N7FMGyi , M3N7FMGzi , M3N7MAFxi , M3N7MAFyi , M3N7MAFzi , M3N7MAGxi , M3N7MAGyi , & + M3N7MAGzi , M3N7MBFxi , M3N7MBFyi , M3N7MBFzi , M3N7MBxi , M3N7MByi , M3N7MBzi , & + M3N7MMGxi , M3N7MMGyi , M3N7MMGzi , M3N7STAxi , M3N7STAyi , M3N7STAzi , M3N7STVxi , & + M3N7STVyi , M3N7STVzi , M3N7Vxi , M3N7Vyi , M3N7Vzi , M3N8Axi , M3N8Ayi , & + M3N8Azi , M3N8DynP , M3N8FAFxi , M3N8FAFyi , M3N8FAFzi , M3N8FAGxi , M3N8FAGyi , & + M3N8FAGzi , M3N8FAMxi , M3N8FAMyi , M3N8FAMzi , M3N8FBFxi , M3N8FBFyi , M3N8FBFzi , & + M3N8FBxi , M3N8FByi , M3N8FBzi , M3N8FDxi , M3N8FDyi , M3N8FDzi , M3N8FIxi , & + M3N8FIyi , M3N8FIzi , M3N8FMGxi , M3N8FMGyi , M3N8FMGzi , M3N8MAFxi , M3N8MAFyi , & + M3N8MAFzi , M3N8MAGxi , M3N8MAGyi , M3N8MAGzi , M3N8MBFxi , M3N8MBFyi , M3N8MBFzi , & + M3N8MBxi , M3N8MByi , M3N8MBzi , M3N8MMGxi , M3N8MMGyi , M3N8MMGzi , M3N8STAxi , & + M3N8STAyi , M3N8STAzi , M3N8STVxi , M3N8STVyi , M3N8STVzi , M3N8Vxi , M3N8Vyi , & + M3N8Vzi , M3N9Axi , M3N9Ayi , M3N9Azi , M3N9DynP , M3N9FAFxi , M3N9FAFyi , & + M3N9FAFzi , M3N9FAGxi , M3N9FAGyi , M3N9FAGzi , M3N9FAMxi , M3N9FAMyi , M3N9FAMzi , & + M3N9FBFxi , M3N9FBFyi , M3N9FBFzi , M3N9FBxi , M3N9FByi , M3N9FBzi , M3N9FDxi , & + M3N9FDyi , M3N9FDzi , M3N9FIxi , M3N9FIyi , M3N9FIzi , M3N9FMGxi , M3N9FMGyi , & + M3N9FMGzi , M3N9MAFxi , M3N9MAFyi , M3N9MAFzi , M3N9MAGxi , M3N9MAGyi , M3N9MAGzi , & + M3N9MBFxi , M3N9MBFyi , M3N9MBFzi , M3N9MBxi , M3N9MByi , M3N9MBzi , M3N9MMGxi , & + M3N9MMGyi , M3N9MMGzi , M3N9STAxi , M3N9STAyi , M3N9STAzi , M3N9STVxi , M3N9STVyi , & + M3N9STVzi , M3N9Vxi , M3N9Vyi , M3N9Vzi , M4N1Axi , M4N1Ayi , M4N1Azi , & + M4N1DynP , M4N1FAFxi , M4N1FAFyi , M4N1FAFzi , M4N1FAGxi , M4N1FAGyi , M4N1FAGzi , & + M4N1FAMxi , M4N1FAMyi , M4N1FAMzi , M4N1FBFxi , M4N1FBFyi , M4N1FBFzi , M4N1FBxi , & + M4N1FByi , M4N1FBzi , M4N1FDxi , M4N1FDyi , M4N1FDzi , M4N1FIxi , M4N1FIyi , & + M4N1FIzi , M4N1FMGxi , M4N1FMGyi , M4N1FMGzi , M4N1MAFxi , M4N1MAFyi , M4N1MAFzi , & + M4N1MAGxi , M4N1MAGyi , M4N1MAGzi , M4N1MBFxi , M4N1MBFyi , M4N1MBFzi , M4N1MBxi , & + M4N1MByi , M4N1MBzi , M4N1MMGxi , M4N1MMGyi , M4N1MMGzi , M4N1STAxi , M4N1STAyi , & + M4N1STAzi , M4N1STVxi , M4N1STVyi , M4N1STVzi , M4N1Vxi , M4N1Vyi , M4N1Vzi , & + M4N2Axi , M4N2Ayi , M4N2Azi , M4N2DynP , M4N2FAFxi , M4N2FAFyi , M4N2FAFzi , & + M4N2FAGxi , M4N2FAGyi , M4N2FAGzi , M4N2FAMxi , M4N2FAMyi , M4N2FAMzi , M4N2FBFxi , & + M4N2FBFyi , M4N2FBFzi , M4N2FBxi , M4N2FByi , M4N2FBzi , M4N2FDxi , M4N2FDyi , & + M4N2FDzi , M4N2FIxi , M4N2FIyi , M4N2FIzi , M4N2FMGxi , M4N2FMGyi , M4N2FMGzi , & + M4N2MAFxi , M4N2MAFyi , M4N2MAFzi , M4N2MAGxi , M4N2MAGyi , M4N2MAGzi , M4N2MBFxi , & + M4N2MBFyi , M4N2MBFzi , M4N2MBxi , M4N2MByi , M4N2MBzi , M4N2MMGxi , M4N2MMGyi , & + M4N2MMGzi , M4N2STAxi , M4N2STAyi , M4N2STAzi , M4N2STVxi , M4N2STVyi , M4N2STVzi , & + M4N2Vxi , M4N2Vyi , M4N2Vzi , M4N3Axi , M4N3Ayi , M4N3Azi , M4N3DynP , & + M4N3FAFxi , M4N3FAFyi , M4N3FAFzi , M4N3FAGxi , M4N3FAGyi , M4N3FAGzi , M4N3FAMxi , & + M4N3FAMyi , M4N3FAMzi , M4N3FBFxi , M4N3FBFyi , M4N3FBFzi , M4N3FBxi , M4N3FByi , & + M4N3FBzi , M4N3FDxi , M4N3FDyi , M4N3FDzi , M4N3FIxi , M4N3FIyi , M4N3FIzi , & + M4N3FMGxi , M4N3FMGyi , M4N3FMGzi , M4N3MAFxi , M4N3MAFyi , M4N3MAFzi , M4N3MAGxi , & + M4N3MAGyi , M4N3MAGzi , M4N3MBFxi , M4N3MBFyi , M4N3MBFzi , M4N3MBxi , M4N3MByi , & + M4N3MBzi , M4N3MMGxi , M4N3MMGyi , M4N3MMGzi , M4N3STAxi , M4N3STAyi , M4N3STAzi , & + M4N3STVxi , M4N3STVyi , M4N3STVzi , M4N3Vxi , M4N3Vyi , M4N3Vzi , M4N4Axi , & + M4N4Ayi , M4N4Azi , M4N4DynP , M4N4FAFxi , M4N4FAFyi , M4N4FAFzi , M4N4FAGxi , & + M4N4FAGyi , M4N4FAGzi , M4N4FAMxi , M4N4FAMyi , M4N4FAMzi , M4N4FBFxi , M4N4FBFyi , & + M4N4FBFzi , M4N4FBxi , M4N4FByi , M4N4FBzi , M4N4FDxi , M4N4FDyi , M4N4FDzi , & + M4N4FIxi , M4N4FIyi , M4N4FIzi , M4N4FMGxi , M4N4FMGyi , M4N4FMGzi , M4N4MAFxi , & + M4N4MAFyi , M4N4MAFzi , M4N4MAGxi , M4N4MAGyi , M4N4MAGzi , M4N4MBFxi , M4N4MBFyi , & + M4N4MBFzi , M4N4MBxi , M4N4MByi , M4N4MBzi , M4N4MMGxi , M4N4MMGyi , M4N4MMGzi , & + M4N4STAxi , M4N4STAyi , M4N4STAzi , M4N4STVxi , M4N4STVyi , M4N4STVzi , M4N4Vxi , & + M4N4Vyi , M4N4Vzi , M4N5Axi /) + ParamIndxAry(2001:2500) = (/ & + M4N5Ayi , M4N5Azi , M4N5DynP , M4N5FAFxi , M4N5FAFyi , M4N5FAFzi , M4N5FAGxi , & + M4N5FAGyi , M4N5FAGzi , M4N5FAMxi , M4N5FAMyi , M4N5FAMzi , M4N5FBFxi , M4N5FBFyi , & + M4N5FBFzi , M4N5FBxi , M4N5FByi , M4N5FBzi , M4N5FDxi , M4N5FDyi , M4N5FDzi , & + M4N5FIxi , M4N5FIyi , M4N5FIzi , M4N5FMGxi , M4N5FMGyi , M4N5FMGzi , M4N5MAFxi , & + M4N5MAFyi , M4N5MAFzi , M4N5MAGxi , M4N5MAGyi , M4N5MAGzi , M4N5MBFxi , M4N5MBFyi , & + M4N5MBFzi , M4N5MBxi , M4N5MByi , M4N5MBzi , M4N5MMGxi , M4N5MMGyi , M4N5MMGzi , & + M4N5STAxi , M4N5STAyi , M4N5STAzi , M4N5STVxi , M4N5STVyi , M4N5STVzi , M4N5Vxi , & + M4N5Vyi , M4N5Vzi , M4N6Axi , M4N6Ayi , M4N6Azi , M4N6DynP , M4N6FAFxi , & + M4N6FAFyi , M4N6FAFzi , M4N6FAGxi , M4N6FAGyi , M4N6FAGzi , M4N6FAMxi , M4N6FAMyi , & + M4N6FAMzi , M4N6FBFxi , M4N6FBFyi , M4N6FBFzi , M4N6FBxi , M4N6FByi , M4N6FBzi , & + M4N6FDxi , M4N6FDyi , M4N6FDzi , M4N6FIxi , M4N6FIyi , M4N6FIzi , M4N6FMGxi , & + M4N6FMGyi , M4N6FMGzi , M4N6MAFxi , M4N6MAFyi , M4N6MAFzi , M4N6MAGxi , M4N6MAGyi , & + M4N6MAGzi , M4N6MBFxi , M4N6MBFyi , M4N6MBFzi , M4N6MBxi , M4N6MByi , M4N6MBzi , & + M4N6MMGxi , M4N6MMGyi , M4N6MMGzi , M4N6STAxi , M4N6STAyi , M4N6STAzi , M4N6STVxi , & + M4N6STVyi , M4N6STVzi , M4N6Vxi , M4N6Vyi , M4N6Vzi , M4N7Axi , M4N7Ayi , & + M4N7Azi , M4N7DynP , M4N7FAFxi , M4N7FAFyi , M4N7FAFzi , M4N7FAGxi , M4N7FAGyi , & + M4N7FAGzi , M4N7FAMxi , M4N7FAMyi , M4N7FAMzi , M4N7FBFxi , M4N7FBFyi , M4N7FBFzi , & + M4N7FBxi , M4N7FByi , M4N7FBzi , M4N7FDxi , M4N7FDyi , M4N7FDzi , M4N7FIxi , & + M4N7FIyi , M4N7FIzi , M4N7FMGxi , M4N7FMGyi , M4N7FMGzi , M4N7MAFxi , M4N7MAFyi , & + M4N7MAFzi , M4N7MAGxi , M4N7MAGyi , M4N7MAGzi , M4N7MBFxi , M4N7MBFyi , M4N7MBFzi , & + M4N7MBxi , M4N7MByi , M4N7MBzi , M4N7MMGxi , M4N7MMGyi , M4N7MMGzi , M4N7STAxi , & + M4N7STAyi , M4N7STAzi , M4N7STVxi , M4N7STVyi , M4N7STVzi , M4N7Vxi , M4N7Vyi , & + M4N7Vzi , M4N8Axi , M4N8Ayi , M4N8Azi , M4N8DynP , M4N8FAFxi , M4N8FAFyi , & + M4N8FAFzi , M4N8FAGxi , M4N8FAGyi , M4N8FAGzi , M4N8FAMxi , M4N8FAMyi , M4N8FAMzi , & + M4N8FBFxi , M4N8FBFyi , M4N8FBFzi , M4N8FBxi , M4N8FByi , M4N8FBzi , M4N8FDxi , & + M4N8FDyi , M4N8FDzi , M4N8FIxi , M4N8FIyi , M4N8FIzi , M4N8FMGxi , M4N8FMGyi , & + M4N8FMGzi , M4N8MAFxi , M4N8MAFyi , M4N8MAFzi , M4N8MAGxi , M4N8MAGyi , M4N8MAGzi , & + M4N8MBFxi , M4N8MBFyi , M4N8MBFzi , M4N8MBxi , M4N8MByi , M4N8MBzi , M4N8MMGxi , & + M4N8MMGyi , M4N8MMGzi , M4N8STAxi , M4N8STAyi , M4N8STAzi , M4N8STVxi , M4N8STVyi , & + M4N8STVzi , M4N8Vxi , M4N8Vyi , M4N8Vzi , M4N9Axi , M4N9Ayi , M4N9Azi , & + M4N9DynP , M4N9FAFxi , M4N9FAFyi , M4N9FAFzi , M4N9FAGxi , M4N9FAGyi , M4N9FAGzi , & + M4N9FAMxi , M4N9FAMyi , M4N9FAMzi , M4N9FBFxi , M4N9FBFyi , M4N9FBFzi , M4N9FBxi , & + M4N9FByi , M4N9FBzi , M4N9FDxi , M4N9FDyi , M4N9FDzi , M4N9FIxi , M4N9FIyi , & + M4N9FIzi , M4N9FMGxi , M4N9FMGyi , M4N9FMGzi , M4N9MAFxi , M4N9MAFyi , M4N9MAFzi , & + M4N9MAGxi , M4N9MAGyi , M4N9MAGzi , M4N9MBFxi , M4N9MBFyi , M4N9MBFzi , M4N9MBxi , & + M4N9MByi , M4N9MBzi , M4N9MMGxi , M4N9MMGyi , M4N9MMGzi , M4N9STAxi , M4N9STAyi , & + M4N9STAzi , M4N9STVxi , M4N9STVyi , M4N9STVzi , M4N9Vxi , M4N9Vyi , M4N9Vzi , & + M5N1Axi , M5N1Ayi , M5N1Azi , M5N1DynP , M5N1FAFxi , M5N1FAFyi , M5N1FAFzi , & + M5N1FAGxi , M5N1FAGyi , M5N1FAGzi , M5N1FAMxi , M5N1FAMyi , M5N1FAMzi , M5N1FBFxi , & + M5N1FBFyi , M5N1FBFzi , M5N1FBxi , M5N1FByi , M5N1FBzi , M5N1FDxi , M5N1FDyi , & + M5N1FDzi , M5N1FIxi , M5N1FIyi , M5N1FIzi , M5N1FMGxi , M5N1FMGyi , M5N1FMGzi , & + M5N1MAFxi , M5N1MAFyi , M5N1MAFzi , M5N1MAGxi , M5N1MAGyi , M5N1MAGzi , M5N1MBFxi , & + M5N1MBFyi , M5N1MBFzi , M5N1MBxi , M5N1MByi , M5N1MBzi , M5N1MMGxi , M5N1MMGyi , & + M5N1MMGzi , M5N1STAxi , M5N1STAyi , M5N1STAzi , M5N1STVxi , M5N1STVyi , M5N1STVzi , & + M5N1Vxi , M5N1Vyi , M5N1Vzi , M5N2Axi , M5N2Ayi , M5N2Azi , M5N2DynP , & + M5N2FAFxi , M5N2FAFyi , M5N2FAFzi , M5N2FAGxi , M5N2FAGyi , M5N2FAGzi , M5N2FAMxi , & + M5N2FAMyi , M5N2FAMzi , M5N2FBFxi , M5N2FBFyi , M5N2FBFzi , M5N2FBxi , M5N2FByi , & + M5N2FBzi , M5N2FDxi , M5N2FDyi , M5N2FDzi , M5N2FIxi , M5N2FIyi , M5N2FIzi , & + M5N2FMGxi , M5N2FMGyi , M5N2FMGzi , M5N2MAFxi , M5N2MAFyi , M5N2MAFzi , M5N2MAGxi , & + M5N2MAGyi , M5N2MAGzi , M5N2MBFxi , M5N2MBFyi , M5N2MBFzi , M5N2MBxi , M5N2MByi , & + M5N2MBzi , M5N2MMGxi , M5N2MMGyi , M5N2MMGzi , M5N2STAxi , M5N2STAyi , M5N2STAzi , & + M5N2STVxi , M5N2STVyi , M5N2STVzi , M5N2Vxi , M5N2Vyi , M5N2Vzi , M5N3Axi , & + M5N3Ayi , M5N3Azi , M5N3DynP , M5N3FAFxi , M5N3FAFyi , M5N3FAFzi , M5N3FAGxi , & + M5N3FAGyi , M5N3FAGzi , M5N3FAMxi , M5N3FAMyi , M5N3FAMzi , M5N3FBFxi , M5N3FBFyi , & + M5N3FBFzi , M5N3FBxi , M5N3FByi , M5N3FBzi , M5N3FDxi , M5N3FDyi , M5N3FDzi , & + M5N3FIxi , M5N3FIyi , M5N3FIzi , M5N3FMGxi , M5N3FMGyi , M5N3FMGzi , M5N3MAFxi , & + M5N3MAFyi , M5N3MAFzi , M5N3MAGxi , M5N3MAGyi , M5N3MAGzi , M5N3MBFxi , M5N3MBFyi , & + M5N3MBFzi , M5N3MBxi , M5N3MByi , M5N3MBzi , M5N3MMGxi , M5N3MMGyi , M5N3MMGzi , & + M5N3STAxi , M5N3STAyi , M5N3STAzi , M5N3STVxi , M5N3STVyi , M5N3STVzi , M5N3Vxi , & + M5N3Vyi , M5N3Vzi , M5N4Axi , M5N4Ayi , M5N4Azi , M5N4DynP , M5N4FAFxi , & + M5N4FAFyi , M5N4FAFzi , M5N4FAGxi , M5N4FAGyi , M5N4FAGzi , M5N4FAMxi , M5N4FAMyi , & + M5N4FAMzi , M5N4FBFxi , M5N4FBFyi , M5N4FBFzi , M5N4FBxi , M5N4FByi , M5N4FBzi , & + M5N4FDxi , M5N4FDyi , M5N4FDzi , M5N4FIxi , M5N4FIyi , M5N4FIzi , M5N4FMGxi , & + M5N4FMGyi , M5N4FMGzi , M5N4MAFxi , M5N4MAFyi , M5N4MAFzi , M5N4MAGxi , M5N4MAGyi , & + M5N4MAGzi , M5N4MBFxi , M5N4MBFyi , M5N4MBFzi , M5N4MBxi , M5N4MByi , M5N4MBzi , & + M5N4MMGxi , M5N4MMGyi , M5N4MMGzi , M5N4STAxi , M5N4STAyi , M5N4STAzi , M5N4STVxi , & + M5N4STVyi , M5N4STVzi , M5N4Vxi , M5N4Vyi , M5N4Vzi , M5N5Axi , M5N5Ayi , & + M5N5Azi , M5N5DynP , M5N5FAFxi , M5N5FAFyi , M5N5FAFzi , M5N5FAGxi , M5N5FAGyi , & + M5N5FAGzi , M5N5FAMxi , M5N5FAMyi , M5N5FAMzi , M5N5FBFxi , M5N5FBFyi , M5N5FBFzi , & + M5N5FBxi , M5N5FByi , M5N5FBzi , M5N5FDxi , M5N5FDyi , M5N5FDzi , M5N5FIxi , & + M5N5FIyi , M5N5FIzi , M5N5FMGxi , M5N5FMGyi , M5N5FMGzi , M5N5MAFxi , M5N5MAFyi , & + M5N5MAFzi , M5N5MAGxi , M5N5MAGyi /) + ParamIndxAry(2501:3000) = (/ & + M5N5MAGzi , M5N5MBFxi , M5N5MBFyi , M5N5MBFzi , M5N5MBxi , M5N5MByi , M5N5MBzi , & + M5N5MMGxi , M5N5MMGyi , M5N5MMGzi , M5N5STAxi , M5N5STAyi , M5N5STAzi , M5N5STVxi , & + M5N5STVyi , M5N5STVzi , M5N5Vxi , M5N5Vyi , M5N5Vzi , M5N6Axi , M5N6Ayi , & + M5N6Azi , M5N6DynP , M5N6FAFxi , M5N6FAFyi , M5N6FAFzi , M5N6FAGxi , M5N6FAGyi , & + M5N6FAGzi , M5N6FAMxi , M5N6FAMyi , M5N6FAMzi , M5N6FBFxi , M5N6FBFyi , M5N6FBFzi , & + M5N6FBxi , M5N6FByi , M5N6FBzi , M5N6FDxi , M5N6FDyi , M5N6FDzi , M5N6FIxi , & + M5N6FIyi , M5N6FIzi , M5N6FMGxi , M5N6FMGyi , M5N6FMGzi , M5N6MAFxi , M5N6MAFyi , & + M5N6MAFzi , M5N6MAGxi , M5N6MAGyi , M5N6MAGzi , M5N6MBFxi , M5N6MBFyi , M5N6MBFzi , & + M5N6MBxi , M5N6MByi , M5N6MBzi , M5N6MMGxi , M5N6MMGyi , M5N6MMGzi , M5N6STAxi , & + M5N6STAyi , M5N6STAzi , M5N6STVxi , M5N6STVyi , M5N6STVzi , M5N6Vxi , M5N6Vyi , & + M5N6Vzi , M5N7Axi , M5N7Ayi , M5N7Azi , M5N7DynP , M5N7FAFxi , M5N7FAFyi , & + M5N7FAFzi , M5N7FAGxi , M5N7FAGyi , M5N7FAGzi , M5N7FAMxi , M5N7FAMyi , M5N7FAMzi , & + M5N7FBFxi , M5N7FBFyi , M5N7FBFzi , M5N7FBxi , M5N7FByi , M5N7FBzi , M5N7FDxi , & + M5N7FDyi , M5N7FDzi , M5N7FIxi , M5N7FIyi , M5N7FIzi , M5N7FMGxi , M5N7FMGyi , & + M5N7FMGzi , M5N7MAFxi , M5N7MAFyi , M5N7MAFzi , M5N7MAGxi , M5N7MAGyi , M5N7MAGzi , & + M5N7MBFxi , M5N7MBFyi , M5N7MBFzi , M5N7MBxi , M5N7MByi , M5N7MBzi , M5N7MMGxi , & + M5N7MMGyi , M5N7MMGzi , M5N7STAxi , M5N7STAyi , M5N7STAzi , M5N7STVxi , M5N7STVyi , & + M5N7STVzi , M5N7Vxi , M5N7Vyi , M5N7Vzi , M5N8Axi , M5N8Ayi , M5N8Azi , & + M5N8DynP , M5N8FAFxi , M5N8FAFyi , M5N8FAFzi , M5N8FAGxi , M5N8FAGyi , M5N8FAGzi , & + M5N8FAMxi , M5N8FAMyi , M5N8FAMzi , M5N8FBFxi , M5N8FBFyi , M5N8FBFzi , M5N8FBxi , & + M5N8FByi , M5N8FBzi , M5N8FDxi , M5N8FDyi , M5N8FDzi , M5N8FIxi , M5N8FIyi , & + M5N8FIzi , M5N8FMGxi , M5N8FMGyi , M5N8FMGzi , M5N8MAFxi , M5N8MAFyi , M5N8MAFzi , & + M5N8MAGxi , M5N8MAGyi , M5N8MAGzi , M5N8MBFxi , M5N8MBFyi , M5N8MBFzi , M5N8MBxi , & + M5N8MByi , M5N8MBzi , M5N8MMGxi , M5N8MMGyi , M5N8MMGzi , M5N8STAxi , M5N8STAyi , & + M5N8STAzi , M5N8STVxi , M5N8STVyi , M5N8STVzi , M5N8Vxi , M5N8Vyi , M5N8Vzi , & + M5N9Axi , M5N9Ayi , M5N9Azi , M5N9DynP , M5N9FAFxi , M5N9FAFyi , M5N9FAFzi , & + M5N9FAGxi , M5N9FAGyi , M5N9FAGzi , M5N9FAMxi , M5N9FAMyi , M5N9FAMzi , M5N9FBFxi , & + M5N9FBFyi , M5N9FBFzi , M5N9FBxi , M5N9FByi , M5N9FBzi , M5N9FDxi , M5N9FDyi , & + M5N9FDzi , M5N9FIxi , M5N9FIyi , M5N9FIzi , M5N9FMGxi , M5N9FMGyi , M5N9FMGzi , & + M5N9MAFxi , M5N9MAFyi , M5N9MAFzi , M5N9MAGxi , M5N9MAGyi , M5N9MAGzi , M5N9MBFxi , & + M5N9MBFyi , M5N9MBFzi , M5N9MBxi , M5N9MByi , M5N9MBzi , M5N9MMGxi , M5N9MMGyi , & + M5N9MMGzi , M5N9STAxi , M5N9STAyi , M5N9STAzi , M5N9STVxi , M5N9STVyi , M5N9STVzi , & + M5N9Vxi , M5N9Vyi , M5N9Vzi , M6N1Axi , M6N1Ayi , M6N1Azi , M6N1DynP , & + M6N1FAFxi , M6N1FAFyi , M6N1FAFzi , M6N1FAGxi , M6N1FAGyi , M6N1FAGzi , M6N1FAMxi , & + M6N1FAMyi , M6N1FAMzi , M6N1FBFxi , M6N1FBFyi , M6N1FBFzi , M6N1FBxi , M6N1FByi , & + M6N1FBzi , M6N1FDxi , M6N1FDyi , M6N1FDzi , M6N1FIxi , M6N1FIyi , M6N1FIzi , & + M6N1FMGxi , M6N1FMGyi , M6N1FMGzi , M6N1MAFxi , M6N1MAFyi , M6N1MAFzi , M6N1MAGxi , & + M6N1MAGyi , M6N1MAGzi , M6N1MBFxi , M6N1MBFyi , M6N1MBFzi , M6N1MBxi , M6N1MByi , & + M6N1MBzi , M6N1MMGxi , M6N1MMGyi , M6N1MMGzi , M6N1STAxi , M6N1STAyi , M6N1STAzi , & + M6N1STVxi , M6N1STVyi , M6N1STVzi , M6N1Vxi , M6N1Vyi , M6N1Vzi , M6N2Axi , & + M6N2Ayi , M6N2Azi , M6N2DynP , M6N2FAFxi , M6N2FAFyi , M6N2FAFzi , M6N2FAGxi , & + M6N2FAGyi , M6N2FAGzi , M6N2FAMxi , M6N2FAMyi , M6N2FAMzi , M6N2FBFxi , M6N2FBFyi , & + M6N2FBFzi , M6N2FBxi , M6N2FByi , M6N2FBzi , M6N2FDxi , M6N2FDyi , M6N2FDzi , & + M6N2FIxi , M6N2FIyi , M6N2FIzi , M6N2FMGxi , M6N2FMGyi , M6N2FMGzi , M6N2MAFxi , & + M6N2MAFyi , M6N2MAFzi , M6N2MAGxi , M6N2MAGyi , M6N2MAGzi , M6N2MBFxi , M6N2MBFyi , & + M6N2MBFzi , M6N2MBxi , M6N2MByi , M6N2MBzi , M6N2MMGxi , M6N2MMGyi , M6N2MMGzi , & + M6N2STAxi , M6N2STAyi , M6N2STAzi , M6N2STVxi , M6N2STVyi , M6N2STVzi , M6N2Vxi , & + M6N2Vyi , M6N2Vzi , M6N3Axi , M6N3Ayi , M6N3Azi , M6N3DynP , M6N3FAFxi , & + M6N3FAFyi , M6N3FAFzi , M6N3FAGxi , M6N3FAGyi , M6N3FAGzi , M6N3FAMxi , M6N3FAMyi , & + M6N3FAMzi , M6N3FBFxi , M6N3FBFyi , M6N3FBFzi , M6N3FBxi , M6N3FByi , M6N3FBzi , & + M6N3FDxi , M6N3FDyi , M6N3FDzi , M6N3FIxi , M6N3FIyi , M6N3FIzi , M6N3FMGxi , & + M6N3FMGyi , M6N3FMGzi , M6N3MAFxi , M6N3MAFyi , M6N3MAFzi , M6N3MAGxi , M6N3MAGyi , & + M6N3MAGzi , M6N3MBFxi , M6N3MBFyi , M6N3MBFzi , M6N3MBxi , M6N3MByi , M6N3MBzi , & + M6N3MMGxi , M6N3MMGyi , M6N3MMGzi , M6N3STAxi , M6N3STAyi , M6N3STAzi , M6N3STVxi , & + M6N3STVyi , M6N3STVzi , M6N3Vxi , M6N3Vyi , M6N3Vzi , M6N4Axi , M6N4Ayi , & + M6N4Azi , M6N4DynP , M6N4FAFxi , M6N4FAFyi , M6N4FAFzi , M6N4FAGxi , M6N4FAGyi , & + M6N4FAGzi , M6N4FAMxi , M6N4FAMyi , M6N4FAMzi , M6N4FBFxi , M6N4FBFyi , M6N4FBFzi , & + M6N4FBxi , M6N4FByi , M6N4FBzi , M6N4FDxi , M6N4FDyi , M6N4FDzi , M6N4FIxi , & + M6N4FIyi , M6N4FIzi , M6N4FMGxi , M6N4FMGyi , M6N4FMGzi , M6N4MAFxi , M6N4MAFyi , & + M6N4MAFzi , M6N4MAGxi , M6N4MAGyi , M6N4MAGzi , M6N4MBFxi , M6N4MBFyi , M6N4MBFzi , & + M6N4MBxi , M6N4MByi , M6N4MBzi , M6N4MMGxi , M6N4MMGyi , M6N4MMGzi , M6N4STAxi , & + M6N4STAyi , M6N4STAzi , M6N4STVxi , M6N4STVyi , M6N4STVzi , M6N4Vxi , M6N4Vyi , & + M6N4Vzi , M6N5Axi , M6N5Ayi , M6N5Azi , M6N5DynP , M6N5FAFxi , M6N5FAFyi , & + M6N5FAFzi , M6N5FAGxi , M6N5FAGyi , M6N5FAGzi , M6N5FAMxi , M6N5FAMyi , M6N5FAMzi , & + M6N5FBFxi , M6N5FBFyi , M6N5FBFzi , M6N5FBxi , M6N5FByi , M6N5FBzi , M6N5FDxi , & + M6N5FDyi , M6N5FDzi , M6N5FIxi , M6N5FIyi , M6N5FIzi , M6N5FMGxi , M6N5FMGyi , & + M6N5FMGzi , M6N5MAFxi , M6N5MAFyi , M6N5MAFzi , M6N5MAGxi , M6N5MAGyi , M6N5MAGzi , & + M6N5MBFxi , M6N5MBFyi , M6N5MBFzi , M6N5MBxi , M6N5MByi , M6N5MBzi , M6N5MMGxi , & + M6N5MMGyi , M6N5MMGzi , M6N5STAxi , M6N5STAyi , M6N5STAzi , M6N5STVxi , M6N5STVyi , & + M6N5STVzi , M6N5Vxi , M6N5Vyi , M6N5Vzi , M6N6Axi , M6N6Ayi , M6N6Azi , & + M6N6DynP , M6N6FAFxi , M6N6FAFyi , M6N6FAFzi , M6N6FAGxi , M6N6FAGyi , M6N6FAGzi , & + M6N6FAMxi , M6N6FAMyi , M6N6FAMzi /) + ParamIndxAry(3001:3500) = (/ & + M6N6FBFxi , M6N6FBFyi , M6N6FBFzi , M6N6FBxi , M6N6FByi , M6N6FBzi , M6N6FDxi , & + M6N6FDyi , M6N6FDzi , M6N6FIxi , M6N6FIyi , M6N6FIzi , M6N6FMGxi , M6N6FMGyi , & + M6N6FMGzi , M6N6MAFxi , M6N6MAFyi , M6N6MAFzi , M6N6MAGxi , M6N6MAGyi , M6N6MAGzi , & + M6N6MBFxi , M6N6MBFyi , M6N6MBFzi , M6N6MBxi , M6N6MByi , M6N6MBzi , M6N6MMGxi , & + M6N6MMGyi , M6N6MMGzi , M6N6STAxi , M6N6STAyi , M6N6STAzi , M6N6STVxi , M6N6STVyi , & + M6N6STVzi , M6N6Vxi , M6N6Vyi , M6N6Vzi , M6N7Axi , M6N7Ayi , M6N7Azi , & + M6N7DynP , M6N7FAFxi , M6N7FAFyi , M6N7FAFzi , M6N7FAGxi , M6N7FAGyi , M6N7FAGzi , & + M6N7FAMxi , M6N7FAMyi , M6N7FAMzi , M6N7FBFxi , M6N7FBFyi , M6N7FBFzi , M6N7FBxi , & + M6N7FByi , M6N7FBzi , M6N7FDxi , M6N7FDyi , M6N7FDzi , M6N7FIxi , M6N7FIyi , & + M6N7FIzi , M6N7FMGxi , M6N7FMGyi , M6N7FMGzi , M6N7MAFxi , M6N7MAFyi , M6N7MAFzi , & + M6N7MAGxi , M6N7MAGyi , M6N7MAGzi , M6N7MBFxi , M6N7MBFyi , M6N7MBFzi , M6N7MBxi , & + M6N7MByi , M6N7MBzi , M6N7MMGxi , M6N7MMGyi , M6N7MMGzi , M6N7STAxi , M6N7STAyi , & + M6N7STAzi , M6N7STVxi , M6N7STVyi , M6N7STVzi , M6N7Vxi , M6N7Vyi , M6N7Vzi , & + M6N8Axi , M6N8Ayi , M6N8Azi , M6N8DynP , M6N8FAFxi , M6N8FAFyi , M6N8FAFzi , & + M6N8FAGxi , M6N8FAGyi , M6N8FAGzi , M6N8FAMxi , M6N8FAMyi , M6N8FAMzi , M6N8FBFxi , & + M6N8FBFyi , M6N8FBFzi , M6N8FBxi , M6N8FByi , M6N8FBzi , M6N8FDxi , M6N8FDyi , & + M6N8FDzi , M6N8FIxi , M6N8FIyi , M6N8FIzi , M6N8FMGxi , M6N8FMGyi , M6N8FMGzi , & + M6N8MAFxi , M6N8MAFyi , M6N8MAFzi , M6N8MAGxi , M6N8MAGyi , M6N8MAGzi , M6N8MBFxi , & + M6N8MBFyi , M6N8MBFzi , M6N8MBxi , M6N8MByi , M6N8MBzi , M6N8MMGxi , M6N8MMGyi , & + M6N8MMGzi , M6N8STAxi , M6N8STAyi , M6N8STAzi , M6N8STVxi , M6N8STVyi , M6N8STVzi , & + M6N8Vxi , M6N8Vyi , M6N8Vzi , M6N9Axi , M6N9Ayi , M6N9Azi , M6N9DynP , & + M6N9FAFxi , M6N9FAFyi , M6N9FAFzi , M6N9FAGxi , M6N9FAGyi , M6N9FAGzi , M6N9FAMxi , & + M6N9FAMyi , M6N9FAMzi , M6N9FBFxi , M6N9FBFyi , M6N9FBFzi , M6N9FBxi , M6N9FByi , & + M6N9FBzi , M6N9FDxi , M6N9FDyi , M6N9FDzi , M6N9FIxi , M6N9FIyi , M6N9FIzi , & + M6N9FMGxi , M6N9FMGyi , M6N9FMGzi , M6N9MAFxi , M6N9MAFyi , M6N9MAFzi , M6N9MAGxi , & + M6N9MAGyi , M6N9MAGzi , M6N9MBFxi , M6N9MBFyi , M6N9MBFzi , M6N9MBxi , M6N9MByi , & + M6N9MBzi , M6N9MMGxi , M6N9MMGyi , M6N9MMGzi , M6N9STAxi , M6N9STAyi , M6N9STAzi , & + M6N9STVxi , M6N9STVyi , M6N9STVzi , M6N9Vxi , M6N9Vyi , M6N9Vzi , M7N1Axi , & + M7N1Ayi , M7N1Azi , M7N1DynP , M7N1FAFxi , M7N1FAFyi , M7N1FAFzi , M7N1FAGxi , & + M7N1FAGyi , M7N1FAGzi , M7N1FAMxi , M7N1FAMyi , M7N1FAMzi , M7N1FBFxi , M7N1FBFyi , & + M7N1FBFzi , M7N1FBxi , M7N1FByi , M7N1FBzi , M7N1FDxi , M7N1FDyi , M7N1FDzi , & + M7N1FIxi , M7N1FIyi , M7N1FIzi , M7N1FMGxi , M7N1FMGyi , M7N1FMGzi , M7N1MAFxi , & + M7N1MAFyi , M7N1MAFzi , M7N1MAGxi , M7N1MAGyi , M7N1MAGzi , M7N1MBFxi , M7N1MBFyi , & + M7N1MBFzi , M7N1MBxi , M7N1MByi , M7N1MBzi , M7N1MMGxi , M7N1MMGyi , M7N1MMGzi , & + M7N1STAxi , M7N1STAyi , M7N1STAzi , M7N1STVxi , M7N1STVyi , M7N1STVzi , M7N1Vxi , & + M7N1Vyi , M7N1Vzi , M7N2Axi , M7N2Ayi , M7N2Azi , M7N2DynP , M7N2FAFxi , & + M7N2FAFyi , M7N2FAFzi , M7N2FAGxi , M7N2FAGyi , M7N2FAGzi , M7N2FAMxi , M7N2FAMyi , & + M7N2FAMzi , M7N2FBFxi , M7N2FBFyi , M7N2FBFzi , M7N2FBxi , M7N2FByi , M7N2FBzi , & + M7N2FDxi , M7N2FDyi , M7N2FDzi , M7N2FIxi , M7N2FIyi , M7N2FIzi , M7N2FMGxi , & + M7N2FMGyi , M7N2FMGzi , M7N2MAFxi , M7N2MAFyi , M7N2MAFzi , M7N2MAGxi , M7N2MAGyi , & + M7N2MAGzi , M7N2MBFxi , M7N2MBFyi , M7N2MBFzi , M7N2MBxi , M7N2MByi , M7N2MBzi , & + M7N2MMGxi , M7N2MMGyi , M7N2MMGzi , M7N2STAxi , M7N2STAyi , M7N2STAzi , M7N2STVxi , & + M7N2STVyi , M7N2STVzi , M7N2Vxi , M7N2Vyi , M7N2Vzi , M7N3Axi , M7N3Ayi , & + M7N3Azi , M7N3DynP , M7N3FAFxi , M7N3FAFyi , M7N3FAFzi , M7N3FAGxi , M7N3FAGyi , & + M7N3FAGzi , M7N3FAMxi , M7N3FAMyi , M7N3FAMzi , M7N3FBFxi , M7N3FBFyi , M7N3FBFzi , & + M7N3FBxi , M7N3FByi , M7N3FBzi , M7N3FDxi , M7N3FDyi , M7N3FDzi , M7N3FIxi , & + M7N3FIyi , M7N3FIzi , M7N3FMGxi , M7N3FMGyi , M7N3FMGzi , M7N3MAFxi , M7N3MAFyi , & + M7N3MAFzi , M7N3MAGxi , M7N3MAGyi , M7N3MAGzi , M7N3MBFxi , M7N3MBFyi , M7N3MBFzi , & + M7N3MBxi , M7N3MByi , M7N3MBzi , M7N3MMGxi , M7N3MMGyi , M7N3MMGzi , M7N3STAxi , & + M7N3STAyi , M7N3STAzi , M7N3STVxi , M7N3STVyi , M7N3STVzi , M7N3Vxi , M7N3Vyi , & + M7N3Vzi , M7N4Axi , M7N4Ayi , M7N4Azi , M7N4DynP , M7N4FAFxi , M7N4FAFyi , & + M7N4FAFzi , M7N4FAGxi , M7N4FAGyi , M7N4FAGzi , M7N4FAMxi , M7N4FAMyi , M7N4FAMzi , & + M7N4FBFxi , M7N4FBFyi , M7N4FBFzi , M7N4FBxi , M7N4FByi , M7N4FBzi , M7N4FDxi , & + M7N4FDyi , M7N4FDzi , M7N4FIxi , M7N4FIyi , M7N4FIzi , M7N4FMGxi , M7N4FMGyi , & + M7N4FMGzi , M7N4MAFxi , M7N4MAFyi , M7N4MAFzi , M7N4MAGxi , M7N4MAGyi , M7N4MAGzi , & + M7N4MBFxi , M7N4MBFyi , M7N4MBFzi , M7N4MBxi , M7N4MByi , M7N4MBzi , M7N4MMGxi , & + M7N4MMGyi , M7N4MMGzi , M7N4STAxi , M7N4STAyi , M7N4STAzi , M7N4STVxi , M7N4STVyi , & + M7N4STVzi , M7N4Vxi , M7N4Vyi , M7N4Vzi , M7N5Axi , M7N5Ayi , M7N5Azi , & + M7N5DynP , M7N5FAFxi , M7N5FAFyi , M7N5FAFzi , M7N5FAGxi , M7N5FAGyi , M7N5FAGzi , & + M7N5FAMxi , M7N5FAMyi , M7N5FAMzi , M7N5FBFxi , M7N5FBFyi , M7N5FBFzi , M7N5FBxi , & + M7N5FByi , M7N5FBzi , M7N5FDxi , M7N5FDyi , M7N5FDzi , M7N5FIxi , M7N5FIyi , & + M7N5FIzi , M7N5FMGxi , M7N5FMGyi , M7N5FMGzi , M7N5MAFxi , M7N5MAFyi , M7N5MAFzi , & + M7N5MAGxi , M7N5MAGyi , M7N5MAGzi , M7N5MBFxi , M7N5MBFyi , M7N5MBFzi , M7N5MBxi , & + M7N5MByi , M7N5MBzi , M7N5MMGxi , M7N5MMGyi , M7N5MMGzi , M7N5STAxi , M7N5STAyi , & + M7N5STAzi , M7N5STVxi , M7N5STVyi , M7N5STVzi , M7N5Vxi , M7N5Vyi , M7N5Vzi , & + M7N6Axi , M7N6Ayi , M7N6Azi , M7N6DynP , M7N6FAFxi , M7N6FAFyi , M7N6FAFzi , & + M7N6FAGxi , M7N6FAGyi , M7N6FAGzi , M7N6FAMxi , M7N6FAMyi , M7N6FAMzi , M7N6FBFxi , & + M7N6FBFyi , M7N6FBFzi , M7N6FBxi , M7N6FByi , M7N6FBzi , M7N6FDxi , M7N6FDyi , & + M7N6FDzi , M7N6FIxi , M7N6FIyi , M7N6FIzi , M7N6FMGxi , M7N6FMGyi , M7N6FMGzi , & + M7N6MAFxi , M7N6MAFyi , M7N6MAFzi , M7N6MAGxi , M7N6MAGyi , M7N6MAGzi , M7N6MBFxi , & + M7N6MBFyi , M7N6MBFzi , M7N6MBxi , M7N6MByi , M7N6MBzi , M7N6MMGxi , M7N6MMGyi , & + M7N6MMGzi , M7N6STAxi , M7N6STAyi /) + ParamIndxAry(3501:4000) = (/ & + M7N6STAzi , M7N6STVxi , M7N6STVyi , M7N6STVzi , M7N6Vxi , M7N6Vyi , M7N6Vzi , & + M7N7Axi , M7N7Ayi , M7N7Azi , M7N7DynP , M7N7FAFxi , M7N7FAFyi , M7N7FAFzi , & + M7N7FAGxi , M7N7FAGyi , M7N7FAGzi , M7N7FAMxi , M7N7FAMyi , M7N7FAMzi , M7N7FBFxi , & + M7N7FBFyi , M7N7FBFzi , M7N7FBxi , M7N7FByi , M7N7FBzi , M7N7FDxi , M7N7FDyi , & + M7N7FDzi , M7N7FIxi , M7N7FIyi , M7N7FIzi , M7N7FMGxi , M7N7FMGyi , M7N7FMGzi , & + M7N7MAFxi , M7N7MAFyi , M7N7MAFzi , M7N7MAGxi , M7N7MAGyi , M7N7MAGzi , M7N7MBFxi , & + M7N7MBFyi , M7N7MBFzi , M7N7MBxi , M7N7MByi , M7N7MBzi , M7N7MMGxi , M7N7MMGyi , & + M7N7MMGzi , M7N7STAxi , M7N7STAyi , M7N7STAzi , M7N7STVxi , M7N7STVyi , M7N7STVzi , & + M7N7Vxi , M7N7Vyi , M7N7Vzi , M7N8Axi , M7N8Ayi , M7N8Azi , M7N8DynP , & + M7N8FAFxi , M7N8FAFyi , M7N8FAFzi , M7N8FAGxi , M7N8FAGyi , M7N8FAGzi , M7N8FAMxi , & + M7N8FAMyi , M7N8FAMzi , M7N8FBFxi , M7N8FBFyi , M7N8FBFzi , M7N8FBxi , M7N8FByi , & + M7N8FBzi , M7N8FDxi , M7N8FDyi , M7N8FDzi , M7N8FIxi , M7N8FIyi , M7N8FIzi , & + M7N8FMGxi , M7N8FMGyi , M7N8FMGzi , M7N8MAFxi , M7N8MAFyi , M7N8MAFzi , M7N8MAGxi , & + M7N8MAGyi , M7N8MAGzi , M7N8MBFxi , M7N8MBFyi , M7N8MBFzi , M7N8MBxi , M7N8MByi , & + M7N8MBzi , M7N8MMGxi , M7N8MMGyi , M7N8MMGzi , M7N8STAxi , M7N8STAyi , M7N8STAzi , & + M7N8STVxi , M7N8STVyi , M7N8STVzi , M7N8Vxi , M7N8Vyi , M7N8Vzi , M7N9Axi , & + M7N9Ayi , M7N9Azi , M7N9DynP , M7N9FAFxi , M7N9FAFyi , M7N9FAFzi , M7N9FAGxi , & + M7N9FAGyi , M7N9FAGzi , M7N9FAMxi , M7N9FAMyi , M7N9FAMzi , M7N9FBFxi , M7N9FBFyi , & + M7N9FBFzi , M7N9FBxi , M7N9FByi , M7N9FBzi , M7N9FDxi , M7N9FDyi , M7N9FDzi , & + M7N9FIxi , M7N9FIyi , M7N9FIzi , M7N9FMGxi , M7N9FMGyi , M7N9FMGzi , M7N9MAFxi , & + M7N9MAFyi , M7N9MAFzi , M7N9MAGxi , M7N9MAGyi , M7N9MAGzi , M7N9MBFxi , M7N9MBFyi , & + M7N9MBFzi , M7N9MBxi , M7N9MByi , M7N9MBzi , M7N9MMGxi , M7N9MMGyi , M7N9MMGzi , & + M7N9STAxi , M7N9STAyi , M7N9STAzi , M7N9STVxi , M7N9STVyi , M7N9STVzi , M7N9Vxi , & + M7N9Vyi , M7N9Vzi , M8N1Axi , M8N1Ayi , M8N1Azi , M8N1DynP , M8N1FAFxi , & + M8N1FAFyi , M8N1FAFzi , M8N1FAGxi , M8N1FAGyi , M8N1FAGzi , M8N1FAMxi , M8N1FAMyi , & + M8N1FAMzi , M8N1FBFxi , M8N1FBFyi , M8N1FBFzi , M8N1FBxi , M8N1FByi , M8N1FBzi , & + M8N1FDxi , M8N1FDyi , M8N1FDzi , M8N1FIxi , M8N1FIyi , M8N1FIzi , M8N1FMGxi , & + M8N1FMGyi , M8N1FMGzi , M8N1MAFxi , M8N1MAFyi , M8N1MAFzi , M8N1MAGxi , M8N1MAGyi , & + M8N1MAGzi , M8N1MBFxi , M8N1MBFyi , M8N1MBFzi , M8N1MBxi , M8N1MByi , M8N1MBzi , & + M8N1MMGxi , M8N1MMGyi , M8N1MMGzi , M8N1STAxi , M8N1STAyi , M8N1STAzi , M8N1STVxi , & + M8N1STVyi , M8N1STVzi , M8N1Vxi , M8N1Vyi , M8N1Vzi , M8N2Axi , M8N2Ayi , & + M8N2Azi , M8N2DynP , M8N2FAFxi , M8N2FAFyi , M8N2FAFzi , M8N2FAGxi , M8N2FAGyi , & + M8N2FAGzi , M8N2FAMxi , M8N2FAMyi , M8N2FAMzi , M8N2FBFxi , M8N2FBFyi , M8N2FBFzi , & + M8N2FBxi , M8N2FByi , M8N2FBzi , M8N2FDxi , M8N2FDyi , M8N2FDzi , M8N2FIxi , & + M8N2FIyi , M8N2FIzi , M8N2FMGxi , M8N2FMGyi , M8N2FMGzi , M8N2MAFxi , M8N2MAFyi , & + M8N2MAFzi , M8N2MAGxi , M8N2MAGyi , M8N2MAGzi , M8N2MBFxi , M8N2MBFyi , M8N2MBFzi , & + M8N2MBxi , M8N2MByi , M8N2MBzi , M8N2MMGxi , M8N2MMGyi , M8N2MMGzi , M8N2STAxi , & + M8N2STAyi , M8N2STAzi , M8N2STVxi , M8N2STVyi , M8N2STVzi , M8N2Vxi , M8N2Vyi , & + M8N2Vzi , M8N3Axi , M8N3Ayi , M8N3Azi , M8N3DynP , M8N3FAFxi , M8N3FAFyi , & + M8N3FAFzi , M8N3FAGxi , M8N3FAGyi , M8N3FAGzi , M8N3FAMxi , M8N3FAMyi , M8N3FAMzi , & + M8N3FBFxi , M8N3FBFyi , M8N3FBFzi , M8N3FBxi , M8N3FByi , M8N3FBzi , M8N3FDxi , & + M8N3FDyi , M8N3FDzi , M8N3FIxi , M8N3FIyi , M8N3FIzi , M8N3FMGxi , M8N3FMGyi , & + M8N3FMGzi , M8N3MAFxi , M8N3MAFyi , M8N3MAFzi , M8N3MAGxi , M8N3MAGyi , M8N3MAGzi , & + M8N3MBFxi , M8N3MBFyi , M8N3MBFzi , M8N3MBxi , M8N3MByi , M8N3MBzi , M8N3MMGxi , & + M8N3MMGyi , M8N3MMGzi , M8N3STAxi , M8N3STAyi , M8N3STAzi , M8N3STVxi , M8N3STVyi , & + M8N3STVzi , M8N3Vxi , M8N3Vyi , M8N3Vzi , M8N4Axi , M8N4Ayi , M8N4Azi , & + M8N4DynP , M8N4FAFxi , M8N4FAFyi , M8N4FAFzi , M8N4FAGxi , M8N4FAGyi , M8N4FAGzi , & + M8N4FAMxi , M8N4FAMyi , M8N4FAMzi , M8N4FBFxi , M8N4FBFyi , M8N4FBFzi , M8N4FBxi , & + M8N4FByi , M8N4FBzi , M8N4FDxi , M8N4FDyi , M8N4FDzi , M8N4FIxi , M8N4FIyi , & + M8N4FIzi , M8N4FMGxi , M8N4FMGyi , M8N4FMGzi , M8N4MAFxi , M8N4MAFyi , M8N4MAFzi , & + M8N4MAGxi , M8N4MAGyi , M8N4MAGzi , M8N4MBFxi , M8N4MBFyi , M8N4MBFzi , M8N4MBxi , & + M8N4MByi , M8N4MBzi , M8N4MMGxi , M8N4MMGyi , M8N4MMGzi , M8N4STAxi , M8N4STAyi , & + M8N4STAzi , M8N4STVxi , M8N4STVyi , M8N4STVzi , M8N4Vxi , M8N4Vyi , M8N4Vzi , & + M8N5Axi , M8N5Ayi , M8N5Azi , M8N5DynP , M8N5FAFxi , M8N5FAFyi , M8N5FAFzi , & + M8N5FAGxi , M8N5FAGyi , M8N5FAGzi , M8N5FAMxi , M8N5FAMyi , M8N5FAMzi , M8N5FBFxi , & + M8N5FBFyi , M8N5FBFzi , M8N5FBxi , M8N5FByi , M8N5FBzi , M8N5FDxi , M8N5FDyi , & + M8N5FDzi , M8N5FIxi , M8N5FIyi , M8N5FIzi , M8N5FMGxi , M8N5FMGyi , M8N5FMGzi , & + M8N5MAFxi , M8N5MAFyi , M8N5MAFzi , M8N5MAGxi , M8N5MAGyi , M8N5MAGzi , M8N5MBFxi , & + M8N5MBFyi , M8N5MBFzi , M8N5MBxi , M8N5MByi , M8N5MBzi , M8N5MMGxi , M8N5MMGyi , & + M8N5MMGzi , M8N5STAxi , M8N5STAyi , M8N5STAzi , M8N5STVxi , M8N5STVyi , M8N5STVzi , & + M8N5Vxi , M8N5Vyi , M8N5Vzi , M8N6Axi , M8N6Ayi , M8N6Azi , M8N6DynP , & + M8N6FAFxi , M8N6FAFyi , M8N6FAFzi , M8N6FAGxi , M8N6FAGyi , M8N6FAGzi , M8N6FAMxi , & + M8N6FAMyi , M8N6FAMzi , M8N6FBFxi , M8N6FBFyi , M8N6FBFzi , M8N6FBxi , M8N6FByi , & + M8N6FBzi , M8N6FDxi , M8N6FDyi , M8N6FDzi , M8N6FIxi , M8N6FIyi , M8N6FIzi , & + M8N6FMGxi , M8N6FMGyi , M8N6FMGzi , M8N6MAFxi , M8N6MAFyi , M8N6MAFzi , M8N6MAGxi , & + M8N6MAGyi , M8N6MAGzi , M8N6MBFxi , M8N6MBFyi , M8N6MBFzi , M8N6MBxi , M8N6MByi , & + M8N6MBzi , M8N6MMGxi , M8N6MMGyi , M8N6MMGzi , M8N6STAxi , M8N6STAyi , M8N6STAzi , & + M8N6STVxi , M8N6STVyi , M8N6STVzi , M8N6Vxi , M8N6Vyi , M8N6Vzi , M8N7Axi , & + M8N7Ayi , M8N7Azi , M8N7DynP , M8N7FAFxi , M8N7FAFyi , M8N7FAFzi , M8N7FAGxi , & + M8N7FAGyi , M8N7FAGzi , M8N7FAMxi , M8N7FAMyi , M8N7FAMzi , M8N7FBFxi , M8N7FBFyi , & + M8N7FBFzi , M8N7FBxi , M8N7FByi , M8N7FBzi , M8N7FDxi , M8N7FDyi , M8N7FDzi , & + M8N7FIxi , M8N7FIyi , M8N7FIzi /) + ParamIndxAry(4001:4500) = (/ & + M8N7FMGxi , M8N7FMGyi , M8N7FMGzi , M8N7MAFxi , M8N7MAFyi , M8N7MAFzi , M8N7MAGxi , & + M8N7MAGyi , M8N7MAGzi , M8N7MBFxi , M8N7MBFyi , M8N7MBFzi , M8N7MBxi , M8N7MByi , & + M8N7MBzi , M8N7MMGxi , M8N7MMGyi , M8N7MMGzi , M8N7STAxi , M8N7STAyi , M8N7STAzi , & + M8N7STVxi , M8N7STVyi , M8N7STVzi , M8N7Vxi , M8N7Vyi , M8N7Vzi , M8N8Axi , & + M8N8Ayi , M8N8Azi , M8N8DynP , M8N8FAFxi , M8N8FAFyi , M8N8FAFzi , M8N8FAGxi , & + M8N8FAGyi , M8N8FAGzi , M8N8FAMxi , M8N8FAMyi , M8N8FAMzi , M8N8FBFxi , M8N8FBFyi , & + M8N8FBFzi , M8N8FBxi , M8N8FByi , M8N8FBzi , M8N8FDxi , M8N8FDyi , M8N8FDzi , & + M8N8FIxi , M8N8FIyi , M8N8FIzi , M8N8FMGxi , M8N8FMGyi , M8N8FMGzi , M8N8MAFxi , & + M8N8MAFyi , M8N8MAFzi , M8N8MAGxi , M8N8MAGyi , M8N8MAGzi , M8N8MBFxi , M8N8MBFyi , & + M8N8MBFzi , M8N8MBxi , M8N8MByi , M8N8MBzi , M8N8MMGxi , M8N8MMGyi , M8N8MMGzi , & + M8N8STAxi , M8N8STAyi , M8N8STAzi , M8N8STVxi , M8N8STVyi , M8N8STVzi , M8N8Vxi , & + M8N8Vyi , M8N8Vzi , M8N9Axi , M8N9Ayi , M8N9Azi , M8N9DynP , M8N9FAFxi , & + M8N9FAFyi , M8N9FAFzi , M8N9FAGxi , M8N9FAGyi , M8N9FAGzi , M8N9FAMxi , M8N9FAMyi , & + M8N9FAMzi , M8N9FBFxi , M8N9FBFyi , M8N9FBFzi , M8N9FBxi , M8N9FByi , M8N9FBzi , & + M8N9FDxi , M8N9FDyi , M8N9FDzi , M8N9FIxi , M8N9FIyi , M8N9FIzi , M8N9FMGxi , & + M8N9FMGyi , M8N9FMGzi , M8N9MAFxi , M8N9MAFyi , M8N9MAFzi , M8N9MAGxi , M8N9MAGyi , & + M8N9MAGzi , M8N9MBFxi , M8N9MBFyi , M8N9MBFzi , M8N9MBxi , M8N9MByi , M8N9MBzi , & + M8N9MMGxi , M8N9MMGyi , M8N9MMGzi , M8N9STAxi , M8N9STAyi , M8N9STAzi , M8N9STVxi , & + M8N9STVyi , M8N9STVzi , M8N9Vxi , M8N9Vyi , M8N9Vzi , M9N1Axi , M9N1Ayi , & + M9N1Azi , M9N1DynP , M9N1FAFxi , M9N1FAFyi , M9N1FAFzi , M9N1FAGxi , M9N1FAGyi , & + M9N1FAGzi , M9N1FAMxi , M9N1FAMyi , M9N1FAMzi , M9N1FBFxi , M9N1FBFyi , M9N1FBFzi , & + M9N1FBxi , M9N1FByi , M9N1FBzi , M9N1FDxi , M9N1FDyi , M9N1FDzi , M9N1FIxi , & + M9N1FIyi , M9N1FIzi , M9N1FMGxi , M9N1FMGyi , M9N1FMGzi , M9N1MAFxi , M9N1MAFyi , & + M9N1MAFzi , M9N1MAGxi , M9N1MAGyi , M9N1MAGzi , M9N1MBFxi , M9N1MBFyi , M9N1MBFzi , & + M9N1MBxi , M9N1MByi , M9N1MBzi , M9N1MMGxi , M9N1MMGyi , M9N1MMGzi , M9N1STAxi , & + M9N1STAyi , M9N1STAzi , M9N1STVxi , M9N1STVyi , M9N1STVzi , M9N1Vxi , M9N1Vyi , & + M9N1Vzi , M9N2Axi , M9N2Ayi , M9N2Azi , M9N2DynP , M9N2FAFxi , M9N2FAFyi , & + M9N2FAFzi , M9N2FAGxi , M9N2FAGyi , M9N2FAGzi , M9N2FAMxi , M9N2FAMyi , M9N2FAMzi , & + M9N2FBFxi , M9N2FBFyi , M9N2FBFzi , M9N2FBxi , M9N2FByi , M9N2FBzi , M9N2FDxi , & + M9N2FDyi , M9N2FDzi , M9N2FIxi , M9N2FIyi , M9N2FIzi , M9N2FMGxi , M9N2FMGyi , & + M9N2FMGzi , M9N2MAFxi , M9N2MAFyi , M9N2MAFzi , M9N2MAGxi , M9N2MAGyi , M9N2MAGzi , & + M9N2MBFxi , M9N2MBFyi , M9N2MBFzi , M9N2MBxi , M9N2MByi , M9N2MBzi , M9N2MMGxi , & + M9N2MMGyi , M9N2MMGzi , M9N2STAxi , M9N2STAyi , M9N2STAzi , M9N2STVxi , M9N2STVyi , & + M9N2STVzi , M9N2Vxi , M9N2Vyi , M9N2Vzi , M9N3Axi , M9N3Ayi , M9N3Azi , & + M9N3DynP , M9N3FAFxi , M9N3FAFyi , M9N3FAFzi , M9N3FAGxi , M9N3FAGyi , M9N3FAGzi , & + M9N3FAMxi , M9N3FAMyi , M9N3FAMzi , M9N3FBFxi , M9N3FBFyi , M9N3FBFzi , M9N3FBxi , & + M9N3FByi , M9N3FBzi , M9N3FDxi , M9N3FDyi , M9N3FDzi , M9N3FIxi , M9N3FIyi , & + M9N3FIzi , M9N3FMGxi , M9N3FMGyi , M9N3FMGzi , M9N3MAFxi , M9N3MAFyi , M9N3MAFzi , & + M9N3MAGxi , M9N3MAGyi , M9N3MAGzi , M9N3MBFxi , M9N3MBFyi , M9N3MBFzi , M9N3MBxi , & + M9N3MByi , M9N3MBzi , M9N3MMGxi , M9N3MMGyi , M9N3MMGzi , M9N3STAxi , M9N3STAyi , & + M9N3STAzi , M9N3STVxi , M9N3STVyi , M9N3STVzi , M9N3Vxi , M9N3Vyi , M9N3Vzi , & + M9N4Axi , M9N4Ayi , M9N4Azi , M9N4DynP , M9N4FAFxi , M9N4FAFyi , M9N4FAFzi , & + M9N4FAGxi , M9N4FAGyi , M9N4FAGzi , M9N4FAMxi , M9N4FAMyi , M9N4FAMzi , M9N4FBFxi , & + M9N4FBFyi , M9N4FBFzi , M9N4FBxi , M9N4FByi , M9N4FBzi , M9N4FDxi , M9N4FDyi , & + M9N4FDzi , M9N4FIxi , M9N4FIyi , M9N4FIzi , M9N4FMGxi , M9N4FMGyi , M9N4FMGzi , & + M9N4MAFxi , M9N4MAFyi , M9N4MAFzi , M9N4MAGxi , M9N4MAGyi , M9N4MAGzi , M9N4MBFxi , & + M9N4MBFyi , M9N4MBFzi , M9N4MBxi , M9N4MByi , M9N4MBzi , M9N4MMGxi , M9N4MMGyi , & + M9N4MMGzi , M9N4STAxi , M9N4STAyi , M9N4STAzi , M9N4STVxi , M9N4STVyi , M9N4STVzi , & + M9N4Vxi , M9N4Vyi , M9N4Vzi , M9N5Axi , M9N5Ayi , M9N5Azi , M9N5DynP , & + M9N5FAFxi , M9N5FAFyi , M9N5FAFzi , M9N5FAGxi , M9N5FAGyi , M9N5FAGzi , M9N5FAMxi , & + M9N5FAMyi , M9N5FAMzi , M9N5FBFxi , M9N5FBFyi , M9N5FBFzi , M9N5FBxi , M9N5FByi , & + M9N5FBzi , M9N5FDxi , M9N5FDyi , M9N5FDzi , M9N5FIxi , M9N5FIyi , M9N5FIzi , & + M9N5FMGxi , M9N5FMGyi , M9N5FMGzi , M9N5MAFxi , M9N5MAFyi , M9N5MAFzi , M9N5MAGxi , & + M9N5MAGyi , M9N5MAGzi , M9N5MBFxi , M9N5MBFyi , M9N5MBFzi , M9N5MBxi , M9N5MByi , & + M9N5MBzi , M9N5MMGxi , M9N5MMGyi , M9N5MMGzi , M9N5STAxi , M9N5STAyi , M9N5STAzi , & + M9N5STVxi , M9N5STVyi , M9N5STVzi , M9N5Vxi , M9N5Vyi , M9N5Vzi , M9N6Axi , & + M9N6Ayi , M9N6Azi , M9N6DynP , M9N6FAFxi , M9N6FAFyi , M9N6FAFzi , M9N6FAGxi , & + M9N6FAGyi , M9N6FAGzi , M9N6FAMxi , M9N6FAMyi , M9N6FAMzi , M9N6FBFxi , M9N6FBFyi , & + M9N6FBFzi , M9N6FBxi , M9N6FByi , M9N6FBzi , M9N6FDxi , M9N6FDyi , M9N6FDzi , & + M9N6FIxi , M9N6FIyi , M9N6FIzi , M9N6FMGxi , M9N6FMGyi , M9N6FMGzi , M9N6MAFxi , & + M9N6MAFyi , M9N6MAFzi , M9N6MAGxi , M9N6MAGyi , M9N6MAGzi , M9N6MBFxi , M9N6MBFyi , & + M9N6MBFzi , M9N6MBxi , M9N6MByi , M9N6MBzi , M9N6MMGxi , M9N6MMGyi , M9N6MMGzi , & + M9N6STAxi , M9N6STAyi , M9N6STAzi , M9N6STVxi , M9N6STVyi , M9N6STVzi , M9N6Vxi , & + M9N6Vyi , M9N6Vzi , M9N7Axi , M9N7Ayi , M9N7Azi , M9N7DynP , M9N7FAFxi , & + M9N7FAFyi , M9N7FAFzi , M9N7FAGxi , M9N7FAGyi , M9N7FAGzi , M9N7FAMxi , M9N7FAMyi , & + M9N7FAMzi , M9N7FBFxi , M9N7FBFyi , M9N7FBFzi , M9N7FBxi , M9N7FByi , M9N7FBzi , & + M9N7FDxi , M9N7FDyi , M9N7FDzi , M9N7FIxi , M9N7FIyi , M9N7FIzi , M9N7FMGxi , & + M9N7FMGyi , M9N7FMGzi , M9N7MAFxi , M9N7MAFyi , M9N7MAFzi , M9N7MAGxi , M9N7MAGyi , & + M9N7MAGzi , M9N7MBFxi , M9N7MBFyi , M9N7MBFzi , M9N7MBxi , M9N7MByi , M9N7MBzi , & + M9N7MMGxi , M9N7MMGyi , M9N7MMGzi , M9N7STAxi , M9N7STAyi , M9N7STAzi , M9N7STVxi , & + M9N7STVyi , M9N7STVzi , M9N7Vxi , M9N7Vyi , M9N7Vzi , M9N8Axi , M9N8Ayi , & + M9N8Azi , M9N8DynP , M9N8FAFxi /) + ParamIndxAry(4501:4599) = (/ & + M9N8FAFyi , M9N8FAFzi , M9N8FAGxi , M9N8FAGyi , M9N8FAGzi , M9N8FAMxi , M9N8FAMyi , & + M9N8FAMzi , M9N8FBFxi , M9N8FBFyi , M9N8FBFzi , M9N8FBxi , M9N8FByi , M9N8FBzi , & + M9N8FDxi , M9N8FDyi , M9N8FDzi , M9N8FIxi , M9N8FIyi , M9N8FIzi , M9N8FMGxi , & + M9N8FMGyi , M9N8FMGzi , M9N8MAFxi , M9N8MAFyi , M9N8MAFzi , M9N8MAGxi , M9N8MAGyi , & + M9N8MAGzi , M9N8MBFxi , M9N8MBFyi , M9N8MBFzi , M9N8MBxi , M9N8MByi , M9N8MBzi , & + M9N8MMGxi , M9N8MMGyi , M9N8MMGzi , M9N8STAxi , M9N8STAyi , M9N8STAzi , M9N8STVxi , & + M9N8STVyi , M9N8STVzi , M9N8Vxi , M9N8Vyi , M9N8Vzi , M9N9Axi , M9N9Ayi , & + M9N9Azi , M9N9DynP , M9N9FAFxi , M9N9FAFyi , M9N9FAFzi , M9N9FAGxi , M9N9FAGyi , & + M9N9FAGzi , M9N9FAMxi , M9N9FAMyi , M9N9FAMzi , M9N9FBFxi , M9N9FBFyi , M9N9FBFzi , & + M9N9FBxi , M9N9FByi , M9N9FBzi , M9N9FDxi , M9N9FDyi , M9N9FDzi , M9N9FIxi , & + M9N9FIyi , M9N9FIzi , M9N9FMGxi , M9N9FMGyi , M9N9FMGzi , M9N9MAFxi , M9N9MAFyi , & + M9N9MAFzi , M9N9MAGxi , M9N9MAGyi , M9N9MAGzi , M9N9MBFxi , M9N9MBFyi , M9N9MBFzi , & + M9N9MBxi , M9N9MByi , M9N9MBzi , M9N9MMGxi , M9N9MMGyi , M9N9MMGzi , M9N9STAxi , & + M9N9STAyi , M9N9STAzi , M9N9STVxi , M9N9STVyi , M9N9STVzi , M9N9Vxi , M9N9Vyi , & + M9N9Vzi /) + ParamUnitsAry(1:500) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) "/) + ParamUnitsAry(501:1000) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) "/) + ParamUnitsAry(1001:1500) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) "/) + ParamUnitsAry(1501:2000) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) "/) + ParamUnitsAry(2001:2500) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) "/) + ParamUnitsAry(2501:3000) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) "/) + ParamUnitsAry(3001:3500) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) "/) + ParamUnitsAry(3501:4000) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) "/) + ParamUnitsAry(4001:4500) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(Pa) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) "/) + ParamUnitsAry(4501:4599) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", & + "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ", & + "(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(N-m/m) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) "/) + + + GetMorisonChannels = 0 newFoundMask = .FALSE. diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index 2dc14c9d7..a359a8edc 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -33,11 +33,11 @@ MODULE Morison_Types !--------------------------------------------------------------------------------------------------------------------------------- USE NWTC_Library IMPLICIT NONE - INTEGER(IntKi), PUBLIC, PARAMETER :: MaxMrsnOutputs = 4032 ! Total number of possible Morison module output channels [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: MaxMrsnOutputs = 4599 ! Total number of possible Morison module output channels [-] ! ========= Morison_JointType ======= TYPE, PUBLIC :: Morison_JointType INTEGER(IntKi) :: JointID !< User-specified integer ID for the given joint [-] - REAL(ReKi) , DIMENSION(1:3) :: JointPos !< Undisplaced location of the joint in the platform coordinate system [m] + REAL(ReKi) , DIMENSION(1:3) :: Position !< Undisplaced location of the joint in the platform coordinate system [m] INTEGER(IntKi) :: JointAxID !< Axial ID (found in the user-supplied Axial Coefficients Table) for this joint: used to determine axial coefs [-] INTEGER(IntKi) :: JointAxIDIndx !< The index into the Axial Coefs arrays corresponding to the above Axial ID [-] INTEGER(IntKi) :: JointOvrlp !< Joint overlap code [Unused [-] @@ -70,6 +70,8 @@ MODULE Morison_Types REAL(ReKi) :: DpthCaMG !< Depth-based Ca for marine growth [-] REAL(ReKi) :: DpthCp !< Depth-based Cp [-] REAL(ReKi) :: DpthCpMG !< Depth-based Cp for marine growth [-] + REAL(ReKi) :: DpthAxCd !< Depth-based Axial Cd [-] + REAL(ReKi) :: DpthAxCdMG !< Depth-based Axial Cd for marine growth [-] REAL(ReKi) :: DpthAxCa !< Depth-based Axial Ca [-] REAL(ReKi) :: DpthAxCaMG !< Depth-based Axial Ca for marine growth [-] REAL(ReKi) :: DpthAxCp !< Depth-based Axial Cp [-] @@ -87,6 +89,7 @@ MODULE Morison_Types ! ========= Morison_MemberInputType ======= TYPE, PUBLIC :: Morison_MemberInputType INTEGER(IntKi) :: MemberID !< User-supplied integer ID for this member [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIndx !< Index of each of the member's nodes in the master node list [-] INTEGER(IntKi) :: MJointID1 !< Joint ID for start of member [-] INTEGER(IntKi) :: MJointID2 !< Joint ID for end of member [-] INTEGER(IntKi) :: MJointID1Indx !< Index into the joint table for the start of this member [-] @@ -100,83 +103,92 @@ MODULE Morison_Types INTEGER(IntKi) :: MmbrCoefIDIndx !< Index into the appropriate coefs table for this member's properties [-] INTEGER(IntKi) :: MmbrFilledIDIndx !< Index into the filled group table if this is a filled member [-] LOGICAL :: PropPot !< Flag T/F for whether the member is modeled with potential flow theory [-] - INTEGER(IntKi) :: NumSplits !< How many splits are needs beyond the user-specified geometry [-] - REAL(ReKi) , DIMENSION(1:5) :: Splits !< Number of times a user member is subdivided by the software [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< Rotation matrix to transform from local to global coordinates [-] + INTEGER(IntKi) :: NElements !< number of elements in this member [-] + REAL(ReKi) :: RefLength !< the reference total length for this member [m] + REAL(ReKi) :: dl !< the reference element length for this member (may be less than MDivSize to achieve uniform element lengths) [m] END TYPE Morison_MemberInputType ! ======================= ! ========= Morison_NodeType ======= TYPE, PUBLIC :: Morison_NodeType INTEGER(IntKi) :: NodeType !< Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version] [-] INTEGER(IntKi) :: JointIndx !< Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1 [-] - REAL(ReKi) , DIMENSION(1:3) :: JointPos !< Position of the node in global coordinates [m] + REAL(ReKi) , DIMENSION(1:3) :: Position !< Position of the node in global coordinates [m] INTEGER(IntKi) :: JointOvrlp !< [-] INTEGER(IntKi) :: JointAxIDIndx !< [-] INTEGER(IntKi) :: NConnections !< Number of elements connecting to this node [-] - INTEGER(IntKi) , DIMENSION(1:10) :: ConnectionList !< Indices of all the elements connected to this node [-] - INTEGER(IntKi) :: NConnectPreSplit !< In code, but unused: should be removed [-] - REAL(ReKi) :: Cd !< Nodal Cd [-] - REAL(ReKi) :: CdMG !< Nodal Cd with marine growth [-] - REAL(ReKi) :: Ca !< Nodal Ca [-] - REAL(ReKi) :: CaMG !< Nodal Ca with marine growth [-] - REAL(ReKi) :: Cp !< Nodal Cp [-] - REAL(ReKi) :: CpMG !< Nodal Cp with marine growth [-] + INTEGER(IntKi) , DIMENSION(1:10) :: ConnectionList !< Indices of all the members connected to this node (positive if end 1, negative if end 2) [-] REAL(ReKi) :: JAxCd !< Nodal lumped (joint) axial Cd [-] REAL(ReKi) :: JAxCa !< Nodal lumped (joint) axial Cp [-] REAL(ReKi) :: JAxCp !< Nodal lumped (joint) axial Ca [-] - REAL(ReKi) :: AxCa !< Nodal axial Ca [-] - REAL(ReKi) :: AxCp !< Nodal axial Cp [-] - REAL(ReKi) :: AxCaMG !< Nodal axial Ca with marine growth [-] - REAL(ReKi) :: AxCpMG !< Nodal axial Cp with marine growth [-] - REAL(ReKi) :: R !< Nodal radius (of member at node location) [m] - REAL(ReKi) :: t !< Nodal thickness (of member at node location) [m] - REAL(ReKi) :: tMG !< Nodal thickness with marine growth (of member at node location) [m] - REAL(ReKi) :: dRdz !< Nodal rate of change in member radius with respect to member axial direction [-] - REAL(ReKi) :: MGdensity !< Nodal density of marine growth [kg/m^3] - REAL(ReKi) :: FillFSLoc !< Nodal fill free surface location (of connected chamber to this node) [m] - LOGICAL :: FillFlag !< Is this node filled? T/F [-] REAL(ReKi) :: FillDensity !< Fill fluid density [kg/m^3] INTEGER(IntKi) :: InpMbrIndx !< Index of member this node is connected to (from the user-specified member list in the input file) [-] REAL(ReKi) :: InpMbrDist !< Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end [-] - LOGICAL :: PropPot !< Is this node modeled with potential flow theory? T/F [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< Rotation matrix to transform from node local to global coordinates [-] + REAL(ReKi) :: tMG !< Nodal thickness with marine growth [m] + REAL(ReKi) :: MGdensity !< Nodal density of marine growth [kg/m^3] END TYPE Morison_NodeType ! ======================= ! ========= Morison_MemberType ======= TYPE, PUBLIC :: Morison_MemberType - INTEGER(IntKi) :: Node1Indx !< Index of member's node 1 in the master node list [-] - INTEGER(IntKi) :: Node2Indx !< Index of member's node 2 in the master node list [-] - REAL(ReKi) :: R1 !< Radius of node 1 [m] - REAL(ReKi) :: t1 !< Member thickness at node 1 [m] - REAL(ReKi) :: R2 !< Radius of node 2 [m] - REAL(ReKi) :: t2 !< Member thickness at node 2 [m] - REAL(ReKi) :: Cd1 !< Member Cd at node 1 [-] - REAL(ReKi) :: CdMG1 !< Member Cd at node 1 with marine growth [-] - REAL(ReKi) :: Ca1 !< Member Ca at node 1 [-] - REAL(ReKi) :: CaMG1 !< Member Ca at node 1 with marine growth [-] - REAL(ReKi) :: Cp1 !< Member Cp at node 1 [-] - REAL(ReKi) :: CpMG1 !< Member Cp at node 1 with marine growth [-] - REAL(ReKi) :: AxCa1 !< Member axial Ca at node 1 [-] - REAL(ReKi) :: AxCaMG1 !< Member axial Ca at node 1 with marine growth [-] - REAL(ReKi) :: AxCp1 !< Member axial Cp at node 1 [-] - REAL(ReKi) :: AxCpMG1 !< Member axial Cp at node 1 with marine growth [-] - REAL(ReKi) :: Cd2 !< Member Cd at node 2 [-] - REAL(ReKi) :: CdMG2 !< Member Cd at node 2 with marine growth [-] - REAL(ReKi) :: Ca2 !< Member Ca at node 2 [-] - REAL(ReKi) :: CaMG2 !< Member Ca at node 2 with marine growth [-] - REAL(ReKi) :: Cp2 !< Member Cp at node 2 [-] - REAL(ReKi) :: CpMG2 !< Member Cp at node 2 with marine growth [-] - REAL(ReKi) :: AxCa2 !< Member axial Ca at node 2 [-] - REAL(ReKi) :: AxCaMG2 !< Member axial Ca at node 2 with marine growth [-] - REAL(ReKi) :: AxCp2 !< Member axial Cp at node 2 [-] - REAL(ReKi) :: AxCpMG2 !< Member axial Cp at node 2 with marine growth [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIndx !< Index of each of the member's nodes in the master node list [-] + INTEGER(IntKi) :: MemberID !< User-supplied integer ID for this member [-] + INTEGER(IntKi) :: NElements !< number of elements in this member [-] + REAL(ReKi) :: RefLength !< the reference total length for this member [m] + REAL(ReKi) :: dl !< the reference element length for this member (may be less than MDivSize to achieve uniform element lengths) [m] + REAL(ReKi) , DIMENSION(1:3) :: k !< unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn) [m] + REAL(ReKi) , DIMENSION(1:3,1:3) :: kkt !< matrix of matmul(k_hat, transpose(k_hat) [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: Ak !< matrix of I - kkt [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: R !< outer member radius at each node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RMG !< radius at each node including marine growth [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Rin !< inner member radius at node, equivalent to radius of water ballast at this node if filled [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: tMG !< Nodal thickness with marine growth (of member at node location) [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: MGdensity !< Nodal density of marine growth [kg/m^3] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dRdl_mg !< taper dr/dl of outer surface including marine growth of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dRdl_in !< taper dr/dl of interior surface of each element [-] + REAL(ReKi) :: Vinner !< Member volume without marine growth [m^3] + REAL(ReKi) :: Vouter !< Member volume including marine growth [m^3] + REAL(ReKi) :: Vballast !< Member ballast volume [m^3] + REAL(ReKi) :: Vsubmerged !< Submerged volume corresponding to portion of Member in the water [m^3] + REAL(ReKi) :: l_fill !< fill length along member axis from start node 1 [m] + REAL(ReKi) :: h_fill !< fill length of partially flooded element [m] + REAL(ReKi) :: z_overfill !< if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled. [m] + REAL(ReKi) :: h_floor !< the distance from the node to the seabed along the member axis (negative value) [m] + INTEGER(IntKi) :: i_floor !< the number of the element that pierces the seabed (zero if the member doesn't pierce it) [-] + INTEGER(IntKi) :: memfloodstatus !< Member-level flooded status for each elemen: 0 unflooded or fully below seabed, 2 partially flooded, 1 fully flooded [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: floodstatus !< flooded status for each element: 0 unflooded or fully below seabed, 1 fully flooded, 2 partially flooded [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: alpha !< relative volume centroid of each element including marine growth, from node i to node i+1 [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: alpha_fb !< relative volume centroid of each element's flooded ballast, from node i to node i+1 [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: alpha_fb_star !< load distribution factor for each element after adjusting alpha_fb for node reference depths [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cd !< Member Cd at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Ca !< Member Ca at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cp !< Member Cp at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AxCd !< Member axial Cd at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AxCa !< Member axial Ca at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AxCp !< Member axial Cp at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_fb_l !< mass of flooded ballast in lower portion of each element [kg] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_fb_u !< mass of flooded ballast in upper portion of each element [kg] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: h_cfb_l !< distance to flooded ballast centroid from node point in lower portion of each element [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: h_cfb_u !< distance to flooded ballast centroid from node point in upper portion of each element [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lfb_l !< axial moment of inertia of flooded ballast in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lfb_u !< axial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rfb_l !< radial moment of inertia of flooded ballast in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rfb_u !< radial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_mg_l !< mass of marine growth in lower portion of each element [kg] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_mg_u !< mass of marine growth in upper portion of each element [kg] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: h_cmg_l !< distance to marine growth centroid from node point in lower portion of each element [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: h_cmg_u !< distance to marine growth centroid from node point in upper portion of each element [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lmg_l !< axial moment of inertia of marine growth in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lmg_u !< axial moment of inertia of marine growth in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rmg_l !< radial moment of inertia of marine growth in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rmg_u !< radial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfl_fb !< axial force constant due to flooded ballast, for each element [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfr_fb !< radial force constant due to flooded ballast, for each element [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CM0_fb !< moment constant due to flooded ballast, for each element about lower node [Nm] REAL(ReKi) :: InpMbrDist1 !< Normalized distance of node 1 from the user-specified corresponding member in the input file [-] REAL(ReKi) :: InpMbrDist2 !< Normalized distance of node 2 from the user-specified corresponding member in the input file [-] REAL(ReKi) :: InpMbrLen !< Length of the user-specified member this is a part of [-] INTEGER(IntKi) :: InpMbrIndx !< Index of the user-specified member this is a part of [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< Rotation matrix to transform from member local to global coordinates [-] - INTEGER(IntKi) :: NumSplits !< How many splits need to be created in the member/element [-] - REAL(ReKi) , DIMENSION(1:5) :: Splits !< Locations of the splits in the Z coordinate [m] REAL(ReKi) :: MGvolume !< Volume of marine growth material for this member/element [m^3] REAL(ReKi) :: MDivSize !< User-requested final element length (actual length may vary from this request) [m] INTEGER(IntKi) :: MCoefMod !< Coefs model for member: 1 = simple, 2 =depth, 3 = member-based [-] @@ -204,6 +216,10 @@ MODULE Morison_Types REAL(ReKi) :: MemberCp2 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] REAL(ReKi) :: MemberCpMG1 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] REAL(ReKi) :: MemberCpMG2 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd1 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd2 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG1 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG2 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] REAL(ReKi) :: MemberAxCa1 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] REAL(ReKi) :: MemberAxCa2 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] REAL(ReKi) :: MemberAxCaMG1 !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] @@ -248,11 +264,9 @@ MODULE Morison_Types REAL(ReKi) :: MSL2SWL !< Mean Sea Level to Still Water Level offset [m] INTEGER(IntKi) :: NJoints !< Number of user-specified joints [-] INTEGER(IntKi) :: NNodes !< Total number of nodes in the final software model [-] - INTEGER(IntKi) :: TotalPossibleSuperMembers !< Unused: For super member calculations [-] TYPE(Morison_JointType) , DIMENSION(:), ALLOCATABLE :: InpJoints !< Array of user-specified joints [-] TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< Array of simulation node (some correspond to user-specified joints, others are created by software) [-] - INTEGER(IntKi) :: NElements !< Number of elements in the discretized model [-] - TYPE(Morison_MemberType) , DIMENSION(:), ALLOCATABLE :: Elements !< Array of elements which were derived from the user-specified members [-] + TYPE(Morison_MemberType) , DIMENSION(:), ALLOCATABLE :: Members !< Array of elements which were derived from the user-specified members [-] INTEGER(IntKi) :: NAxCoefs !< Number of axial Coefs entries in input file table [-] TYPE(Morison_AxialCoefType) , DIMENSION(:), ALLOCATABLE :: AxialCoefs !< List of axial coefs [-] INTEGER(IntKi) :: NPropSets !< Number of member property sets [-] @@ -263,6 +277,8 @@ MODULE Morison_Types REAL(ReKi) :: SimplCaMG !< Simple model Ca for marine growth [-] REAL(ReKi) :: SimplCp !< Simple model Cp [-] REAL(ReKi) :: SimplCpMG !< Simple model Cp for marine growth [-] + REAL(ReKi) :: SimplAxCd !< Simple model Axial Cd [-] + REAL(ReKi) :: SimplAxCdMG !< Simple model Axial Cd for marine growth [-] REAL(ReKi) :: SimplAxCa !< Simple model Axial Ca [-] REAL(ReKi) :: SimplAxCaMG !< Simple model Axial Ca for marine growth [-] REAL(ReKi) :: SimplAxCp !< Simple model Axial Cp [-] @@ -301,8 +317,7 @@ MODULE Morison_Types ! ======================= ! ========= Morison_InitOutputType ======= TYPE, PUBLIC :: Morison_InitOutputType - TYPE(MeshType) :: DistribMesh !< Unused? [-] - TYPE(MeshType) :: LumpedMesh !< Unused? [-] + TYPE(MeshType) :: Mesh !< Unused? [-] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: Morison_Rad !< radius of node (for FAST visualization) [(m)] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< User-requested Output channel names [-] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< User-requested Output channel units [-] @@ -330,43 +345,54 @@ MODULE Morison_Types ! ======================= ! ========= Morison_MiscVarType ======= TYPE, PUBLIC :: Morison_MiscVarType - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_D !< Distributed viscous drag loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_I !< Distributed inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_B !< Distributed bounancy loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_B was computed) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM !< Distributed total added mass loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_M !< Distributed member added mass loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_MG !< Distributed marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_AM_F !< Distributed added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_FV !< Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_FA !< Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_FDynP !< Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_B !< [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_D !< Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_I !< Lumped intertia loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_AM !< Lumped added mass loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_FV !< Fluid velocity at point element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_FA !< Fluid acceleration at point element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: L_FDynP !< Fluid dynamic pressure at point element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D !< Member-based (side-effects) Nodal viscous drag loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I !< Member-based (side-effects) Nodal inertial loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A !< Member-based (side-effects) Nodal added mass loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B !< Member-based (side-effects) Nodal buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF !< Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_If !< Member-based (side-effects) Nodal flooded ballast inertia loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_WMG !< Member-based (side-effects) Nodal marine growth weight loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG !< Member-based (side-effects) Nodal marine growth inertia loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FV !< Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FA !< Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FDynP !< Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: vrel !< velocity of structural node relative to the water [m/s^2] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B_End !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D_End !< Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I_End !< Lumped intertia loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG_End !< Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP_End !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A_End !< Lumped added mass loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< [-] INTEGER(IntKi) :: LastIndWave !< Last time index used in the wave kinematics arrays [-] END TYPE Morison_MiscVarType ! ======================= ! ========= Morison_ParameterType ======= TYPE, PUBLIC :: Morison_ParameterType REAL(DbKi) :: DT !< Time step for continuous state integration & discrete state update [(sec)] + REAL(ReKi) :: Gravity !< Gravity (scalar, positive-valued) [m/s^2] REAL(ReKi) :: WtrDens !< Water density [kg/m^3] + REAL(ReKi) :: WtrDpth !< Water depth (positive-valued) [m] + INTEGER(IntKi) :: NMembers !< number of members [-] + TYPE(Morison_MemberType) , DIMENSION(:), ALLOCATABLE :: Members !< Array of Morison members used during simulation [-] INTEGER(IntKi) :: NNodes !< [-] - TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< [-] + INTEGER(IntKi) :: NJoints !< Number of user-specified joints [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: I_MG_End !< Inertial matrix associated with marine growth mass at joint [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_I !< Distributed inertial loads for all WaveTimes [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_DP !< [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_dragConst !< [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_An !< [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_B !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_F_I !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_F_DP !< [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: L_F_BF !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: L_AM_M !< [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: L_dragConst !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: An_End !< directional area vector of each joint [m^2] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B_End !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: F_I_End !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: F_DP_End !< [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AM_M_End !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DragConst_End !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_WMG_End !< Joint marine growth weight loads, constant for all t [N] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DP_Const_End !< Constant part of Joint dynamic pressure term [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Mass_MG_End !< Joint marine growth mass [kg] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AM_End !< 3x3 Joint added mass matrix, constant for all t [N] INTEGER(IntKi) :: NDistribMarkers !< [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: distribToNodeIndx !< [-] INTEGER(IntKi) :: NLumpedMarkers !< [-] @@ -401,14 +427,12 @@ MODULE Morison_Types ! ======================= ! ========= Morison_InputType ======= TYPE, PUBLIC :: Morison_InputType - TYPE(MeshType) :: DistribMesh !< Distributed Loads Meshed input data [-] - TYPE(MeshType) :: LumpedMesh !< Lumped Loads Meshed input data [-] + TYPE(MeshType) :: Mesh !< Kinematics of each node input mesh [-] END TYPE Morison_InputType ! ======================= ! ========= Morison_OutputType ======= TYPE, PUBLIC :: Morison_OutputType - TYPE(MeshType) :: DistribMesh !< Distributed Loads Meshed output data [-] - TYPE(MeshType) :: LumpedMesh !< Lumped Loads Meshed output data [-] + TYPE(MeshType) :: Mesh !< Loads on each node output mesh [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-] END TYPE Morison_OutputType ! ======================= @@ -431,7 +455,7 @@ SUBROUTINE Morison_CopyJointType( SrcJointTypeData, DstJointTypeData, CtrlCode, ErrStat = ErrID_None ErrMsg = "" DstJointTypeData%JointID = SrcJointTypeData%JointID - DstJointTypeData%JointPos = SrcJointTypeData%JointPos + DstJointTypeData%Position = SrcJointTypeData%Position DstJointTypeData%JointAxID = SrcJointTypeData%JointAxID DstJointTypeData%JointAxIDIndx = SrcJointTypeData%JointAxIDIndx DstJointTypeData%JointOvrlp = SrcJointTypeData%JointOvrlp @@ -486,7 +510,7 @@ SUBROUTINE Morison_PackJointType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! JointID - Re_BufSz = Re_BufSz + SIZE(InData%JointPos) ! JointPos + Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position Int_BufSz = Int_BufSz + 1 ! JointAxID Int_BufSz = Int_BufSz + 1 ! JointAxIDIndx Int_BufSz = Int_BufSz + 1 ! JointOvrlp @@ -521,8 +545,8 @@ SUBROUTINE Morison_PackJointType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointID Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%JointPos))-1 ) = PACK(InData%JointPos,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%JointPos) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Position))-1 ) = PACK(InData%Position,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Position) IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointAxID Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointAxIDIndx @@ -572,16 +596,16 @@ SUBROUTINE Morison_UnPackJointType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Int_Xferred = 1 OutData%JointID = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%JointPos,1) - i1_u = UBOUND(OutData%JointPos,1) + i1_l = LBOUND(OutData%Position,1) + i1_u = UBOUND(OutData%Position,1) ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%JointPos = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%JointPos))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%JointPos) + OutData%Position = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Position))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Position) DEALLOCATE(mask1) OutData%JointAxID = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -979,6 +1003,8 @@ SUBROUTINE Morison_CopyCoefDpths( SrcCoefDpthsData, DstCoefDpthsData, CtrlCode, DstCoefDpthsData%DpthCaMG = SrcCoefDpthsData%DpthCaMG DstCoefDpthsData%DpthCp = SrcCoefDpthsData%DpthCp DstCoefDpthsData%DpthCpMG = SrcCoefDpthsData%DpthCpMG + DstCoefDpthsData%DpthAxCd = SrcCoefDpthsData%DpthAxCd + DstCoefDpthsData%DpthAxCdMG = SrcCoefDpthsData%DpthAxCdMG DstCoefDpthsData%DpthAxCa = SrcCoefDpthsData%DpthAxCa DstCoefDpthsData%DpthAxCaMG = SrcCoefDpthsData%DpthAxCaMG DstCoefDpthsData%DpthAxCp = SrcCoefDpthsData%DpthAxCp @@ -1038,6 +1064,8 @@ SUBROUTINE Morison_PackCoefDpths( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = Re_BufSz + 1 ! DpthCaMG Re_BufSz = Re_BufSz + 1 ! DpthCp Re_BufSz = Re_BufSz + 1 ! DpthCpMG + Re_BufSz = Re_BufSz + 1 ! DpthAxCd + Re_BufSz = Re_BufSz + 1 ! DpthAxCdMG Re_BufSz = Re_BufSz + 1 ! DpthAxCa Re_BufSz = Re_BufSz + 1 ! DpthAxCaMG Re_BufSz = Re_BufSz + 1 ! DpthAxCp @@ -1083,6 +1111,10 @@ SUBROUTINE Morison_PackCoefDpths( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DpthCpMG Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DpthAxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DpthAxCdMG + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DpthAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DpthAxCaMG @@ -1139,6 +1171,10 @@ SUBROUTINE Morison_UnPackCoefDpths( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = Re_Xferred + 1 OutData%DpthCpMG = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCd = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCdMG = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%DpthAxCa = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%DpthAxCaMG = ReKiBuf( Re_Xferred ) @@ -1315,6 +1351,18 @@ SUBROUTINE Morison_CopyMemberInputType( SrcMemberInputTypeData, DstMemberInputTy ErrStat = ErrID_None ErrMsg = "" DstMemberInputTypeData%MemberID = SrcMemberInputTypeData%MemberID +IF (ALLOCATED(SrcMemberInputTypeData%NodeIndx)) THEN + i1_l = LBOUND(SrcMemberInputTypeData%NodeIndx,1) + i1_u = UBOUND(SrcMemberInputTypeData%NodeIndx,1) + IF (.NOT. ALLOCATED(DstMemberInputTypeData%NodeIndx)) THEN + ALLOCATE(DstMemberInputTypeData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberInputTypeData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberInputTypeData%NodeIndx = SrcMemberInputTypeData%NodeIndx +ENDIF DstMemberInputTypeData%MJointID1 = SrcMemberInputTypeData%MJointID1 DstMemberInputTypeData%MJointID2 = SrcMemberInputTypeData%MJointID2 DstMemberInputTypeData%MJointID1Indx = SrcMemberInputTypeData%MJointID1Indx @@ -1328,9 +1376,10 @@ SUBROUTINE Morison_CopyMemberInputType( SrcMemberInputTypeData, DstMemberInputTy DstMemberInputTypeData%MmbrCoefIDIndx = SrcMemberInputTypeData%MmbrCoefIDIndx DstMemberInputTypeData%MmbrFilledIDIndx = SrcMemberInputTypeData%MmbrFilledIDIndx DstMemberInputTypeData%PropPot = SrcMemberInputTypeData%PropPot - DstMemberInputTypeData%NumSplits = SrcMemberInputTypeData%NumSplits - DstMemberInputTypeData%Splits = SrcMemberInputTypeData%Splits DstMemberInputTypeData%R_LToG = SrcMemberInputTypeData%R_LToG + DstMemberInputTypeData%NElements = SrcMemberInputTypeData%NElements + DstMemberInputTypeData%RefLength = SrcMemberInputTypeData%RefLength + DstMemberInputTypeData%dl = SrcMemberInputTypeData%dl END SUBROUTINE Morison_CopyMemberInputType SUBROUTINE Morison_DestroyMemberInputType( MemberInputTypeData, ErrStat, ErrMsg ) @@ -1342,6 +1391,9 @@ SUBROUTINE Morison_DestroyMemberInputType( MemberInputTypeData, ErrStat, ErrMsg ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(MemberInputTypeData%NodeIndx)) THEN + DEALLOCATE(MemberInputTypeData%NodeIndx) +ENDIF END SUBROUTINE Morison_DestroyMemberInputType SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1380,6 +1432,11 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NodeIndx allocated yes/no + IF ( ALLOCATED(InData%NodeIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeIndx) ! NodeIndx + END IF Int_BufSz = Int_BufSz + 1 ! MJointID1 Int_BufSz = Int_BufSz + 1 ! MJointID2 Int_BufSz = Int_BufSz + 1 ! MJointID1Indx @@ -1393,9 +1450,10 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx Int_BufSz = Int_BufSz + 1 ! PropPot - Int_BufSz = Int_BufSz + 1 ! NumSplits - Re_BufSz = Re_BufSz + SIZE(InData%Splits) ! Splits Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + Int_BufSz = Int_BufSz + 1 ! NElements + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! dl IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1425,6 +1483,19 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MemberID Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeIndx) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodeIndx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeIndx))-1 ) = PACK(InData%NodeIndx,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodeIndx) + END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MJointID1 Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MJointID2 @@ -1451,12 +1522,14 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumSplits - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Splits))-1 ) = PACK(InData%Splits,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Splits) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElements + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%dl + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_PackMemberInputType SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1495,6 +1568,29 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%MemberID = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIndx not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIndx)) DEALLOCATE(OutData%NodeIndx) + ALLOCATE(OutData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NodeIndx)>0) OutData%NodeIndx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeIndx))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodeIndx) + DEALLOCATE(mask1) + END IF OutData%MJointID1 = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%MJointID2 = IntKiBuf( Int_Xferred ) @@ -1521,19 +1617,6 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = Int_Xferred + 1 OutData%PropPot = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 - OutData%NumSplits = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Splits,1) - i1_u = UBOUND(OutData%Splits,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%Splits = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Splits))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Splits) - DEALLOCATE(mask1) i1_l = LBOUND(OutData%R_LToG,1) i1_u = UBOUND(OutData%R_LToG,1) i2_l = LBOUND(OutData%R_LToG,2) @@ -1547,6 +1630,12 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E OutData%R_LToG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R_LToG))-1 ), mask2, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%R_LToG) DEALLOCATE(mask2) + OutData%NElements = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%RefLength = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%dl = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_UnPackMemberInputType SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -1558,7 +1647,6 @@ SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, Err ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyNodeType' @@ -1567,37 +1655,19 @@ SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, Err ErrMsg = "" DstNodeTypeData%NodeType = SrcNodeTypeData%NodeType DstNodeTypeData%JointIndx = SrcNodeTypeData%JointIndx - DstNodeTypeData%JointPos = SrcNodeTypeData%JointPos + DstNodeTypeData%Position = SrcNodeTypeData%Position DstNodeTypeData%JointOvrlp = SrcNodeTypeData%JointOvrlp DstNodeTypeData%JointAxIDIndx = SrcNodeTypeData%JointAxIDIndx DstNodeTypeData%NConnections = SrcNodeTypeData%NConnections DstNodeTypeData%ConnectionList = SrcNodeTypeData%ConnectionList - DstNodeTypeData%NConnectPreSplit = SrcNodeTypeData%NConnectPreSplit - DstNodeTypeData%Cd = SrcNodeTypeData%Cd - DstNodeTypeData%CdMG = SrcNodeTypeData%CdMG - DstNodeTypeData%Ca = SrcNodeTypeData%Ca - DstNodeTypeData%CaMG = SrcNodeTypeData%CaMG - DstNodeTypeData%Cp = SrcNodeTypeData%Cp - DstNodeTypeData%CpMG = SrcNodeTypeData%CpMG DstNodeTypeData%JAxCd = SrcNodeTypeData%JAxCd DstNodeTypeData%JAxCa = SrcNodeTypeData%JAxCa DstNodeTypeData%JAxCp = SrcNodeTypeData%JAxCp - DstNodeTypeData%AxCa = SrcNodeTypeData%AxCa - DstNodeTypeData%AxCp = SrcNodeTypeData%AxCp - DstNodeTypeData%AxCaMG = SrcNodeTypeData%AxCaMG - DstNodeTypeData%AxCpMG = SrcNodeTypeData%AxCpMG - DstNodeTypeData%R = SrcNodeTypeData%R - DstNodeTypeData%t = SrcNodeTypeData%t - DstNodeTypeData%tMG = SrcNodeTypeData%tMG - DstNodeTypeData%dRdz = SrcNodeTypeData%dRdz - DstNodeTypeData%MGdensity = SrcNodeTypeData%MGdensity - DstNodeTypeData%FillFSLoc = SrcNodeTypeData%FillFSLoc - DstNodeTypeData%FillFlag = SrcNodeTypeData%FillFlag DstNodeTypeData%FillDensity = SrcNodeTypeData%FillDensity DstNodeTypeData%InpMbrIndx = SrcNodeTypeData%InpMbrIndx DstNodeTypeData%InpMbrDist = SrcNodeTypeData%InpMbrDist - DstNodeTypeData%PropPot = SrcNodeTypeData%PropPot - DstNodeTypeData%R_LToG = SrcNodeTypeData%R_LToG + DstNodeTypeData%tMG = SrcNodeTypeData%tMG + DstNodeTypeData%MGdensity = SrcNodeTypeData%MGdensity END SUBROUTINE Morison_CopyNodeType SUBROUTINE Morison_DestroyNodeType( NodeTypeData, ErrStat, ErrMsg ) @@ -1648,37 +1718,19 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! NodeType Int_BufSz = Int_BufSz + 1 ! JointIndx - Re_BufSz = Re_BufSz + SIZE(InData%JointPos) ! JointPos + Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position Int_BufSz = Int_BufSz + 1 ! JointOvrlp Int_BufSz = Int_BufSz + 1 ! JointAxIDIndx Int_BufSz = Int_BufSz + 1 ! NConnections Int_BufSz = Int_BufSz + SIZE(InData%ConnectionList) ! ConnectionList - Int_BufSz = Int_BufSz + 1 ! NConnectPreSplit - Re_BufSz = Re_BufSz + 1 ! Cd - Re_BufSz = Re_BufSz + 1 ! CdMG - Re_BufSz = Re_BufSz + 1 ! Ca - Re_BufSz = Re_BufSz + 1 ! CaMG - Re_BufSz = Re_BufSz + 1 ! Cp - Re_BufSz = Re_BufSz + 1 ! CpMG Re_BufSz = Re_BufSz + 1 ! JAxCd Re_BufSz = Re_BufSz + 1 ! JAxCa Re_BufSz = Re_BufSz + 1 ! JAxCp - Re_BufSz = Re_BufSz + 1 ! AxCa - Re_BufSz = Re_BufSz + 1 ! AxCp - Re_BufSz = Re_BufSz + 1 ! AxCaMG - Re_BufSz = Re_BufSz + 1 ! AxCpMG - Re_BufSz = Re_BufSz + 1 ! R - Re_BufSz = Re_BufSz + 1 ! t - Re_BufSz = Re_BufSz + 1 ! tMG - Re_BufSz = Re_BufSz + 1 ! dRdz - Re_BufSz = Re_BufSz + 1 ! MGdensity - Re_BufSz = Re_BufSz + 1 ! FillFSLoc - Int_BufSz = Int_BufSz + 1 ! FillFlag Re_BufSz = Re_BufSz + 1 ! FillDensity Int_BufSz = Int_BufSz + 1 ! InpMbrIndx Re_BufSz = Re_BufSz + 1 ! InpMbrDist - Int_BufSz = Int_BufSz + 1 ! PropPot - Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + Re_BufSz = Re_BufSz + 1 ! tMG + Re_BufSz = Re_BufSz + 1 ! MGdensity IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1710,8 +1762,8 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointIndx Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%JointPos))-1 ) = PACK(InData%JointPos,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%JointPos) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Position))-1 ) = PACK(InData%Position,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Position) IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointOvrlp Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointAxIDIndx @@ -1720,58 +1772,22 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ConnectionList))-1 ) = PACK(InData%ConnectionList,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%ConnectionList) - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NConnectPreSplit - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cd - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CdMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ca - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CaMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cp - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CpMG - Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%JAxCd Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%JAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%JAxCp Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCa - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCp - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCaMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCpMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%R - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%t - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%tMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%dRdz - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGdensity - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillFSLoc - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%FillFlag , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillDensity Re_Xferred = Re_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%InpMbrIndx Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%tMG + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGdensity + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_PackNodeType SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1794,7 +1810,6 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackNodeType' @@ -1812,16 +1827,16 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%JointIndx = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%JointPos,1) - i1_u = UBOUND(OutData%JointPos,1) + i1_l = LBOUND(OutData%Position,1) + i1_u = UBOUND(OutData%Position,1) ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN END IF mask1 = .TRUE. - OutData%JointPos = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%JointPos))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%JointPos) + OutData%Position = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Position))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Position) DEALLOCATE(mask1) OutData%JointOvrlp = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -1840,69 +1855,22 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%ConnectionList = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ConnectionList))-1 ), mask1, 0_IntKi ) Int_Xferred = Int_Xferred + SIZE(OutData%ConnectionList) DEALLOCATE(mask1) - OutData%NConnectPreSplit = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Cd = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CdMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Ca = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CaMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Cp = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CpMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 OutData%JAxCd = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%JAxCa = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%JAxCp = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - OutData%AxCa = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCp = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%R = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%t = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%tMG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%dRdz = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%MGdensity = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%FillFSLoc = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%FillFlag = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 OutData%FillDensity = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%InpMbrIndx = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%InpMbrDist = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - OutData%PropPot = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%R_LToG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R_LToG))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%R_LToG) - DEALLOCATE(mask2) + OutData%tMG = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%MGdensity = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_UnPackNodeType SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -1921,341 +1889,2382 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod ! ErrStat = ErrID_None ErrMsg = "" - DstMemberTypeData%Node1Indx = SrcMemberTypeData%Node1Indx - DstMemberTypeData%Node2Indx = SrcMemberTypeData%Node2Indx - DstMemberTypeData%R1 = SrcMemberTypeData%R1 - DstMemberTypeData%t1 = SrcMemberTypeData%t1 - DstMemberTypeData%R2 = SrcMemberTypeData%R2 - DstMemberTypeData%t2 = SrcMemberTypeData%t2 - DstMemberTypeData%Cd1 = SrcMemberTypeData%Cd1 - DstMemberTypeData%CdMG1 = SrcMemberTypeData%CdMG1 - DstMemberTypeData%Ca1 = SrcMemberTypeData%Ca1 - DstMemberTypeData%CaMG1 = SrcMemberTypeData%CaMG1 - DstMemberTypeData%Cp1 = SrcMemberTypeData%Cp1 - DstMemberTypeData%CpMG1 = SrcMemberTypeData%CpMG1 - DstMemberTypeData%AxCa1 = SrcMemberTypeData%AxCa1 - DstMemberTypeData%AxCaMG1 = SrcMemberTypeData%AxCaMG1 - DstMemberTypeData%AxCp1 = SrcMemberTypeData%AxCp1 - DstMemberTypeData%AxCpMG1 = SrcMemberTypeData%AxCpMG1 - DstMemberTypeData%Cd2 = SrcMemberTypeData%Cd2 - DstMemberTypeData%CdMG2 = SrcMemberTypeData%CdMG2 - DstMemberTypeData%Ca2 = SrcMemberTypeData%Ca2 - DstMemberTypeData%CaMG2 = SrcMemberTypeData%CaMG2 - DstMemberTypeData%Cp2 = SrcMemberTypeData%Cp2 - DstMemberTypeData%CpMG2 = SrcMemberTypeData%CpMG2 - DstMemberTypeData%AxCa2 = SrcMemberTypeData%AxCa2 - DstMemberTypeData%AxCaMG2 = SrcMemberTypeData%AxCaMG2 - DstMemberTypeData%AxCp2 = SrcMemberTypeData%AxCp2 - DstMemberTypeData%AxCpMG2 = SrcMemberTypeData%AxCpMG2 - DstMemberTypeData%InpMbrDist1 = SrcMemberTypeData%InpMbrDist1 - DstMemberTypeData%InpMbrDist2 = SrcMemberTypeData%InpMbrDist2 - DstMemberTypeData%InpMbrLen = SrcMemberTypeData%InpMbrLen - DstMemberTypeData%InpMbrIndx = SrcMemberTypeData%InpMbrIndx - DstMemberTypeData%R_LToG = SrcMemberTypeData%R_LToG - DstMemberTypeData%NumSplits = SrcMemberTypeData%NumSplits - DstMemberTypeData%Splits = SrcMemberTypeData%Splits - DstMemberTypeData%MGvolume = SrcMemberTypeData%MGvolume - DstMemberTypeData%MDivSize = SrcMemberTypeData%MDivSize - DstMemberTypeData%MCoefMod = SrcMemberTypeData%MCoefMod - DstMemberTypeData%MmbrCoefIDIndx = SrcMemberTypeData%MmbrCoefIDIndx - DstMemberTypeData%MmbrFilledIDIndx = SrcMemberTypeData%MmbrFilledIDIndx - DstMemberTypeData%FillFSLoc = SrcMemberTypeData%FillFSLoc - DstMemberTypeData%FillDens = SrcMemberTypeData%FillDens - DstMemberTypeData%F_Bouy = SrcMemberTypeData%F_Bouy - DstMemberTypeData%F_DP = SrcMemberTypeData%F_DP - DstMemberTypeData%PropPot = SrcMemberTypeData%PropPot - END SUBROUTINE Morison_CopyMemberType - - SUBROUTINE Morison_DestroyMemberType( MemberTypeData, ErrStat, ErrMsg ) - TYPE(Morison_MemberType), INTENT(INOUT) :: MemberTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberType' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - END SUBROUTINE Morison_DestroyMemberType - - SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(Morison_MemberType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_PackMemberType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Node1Indx - Int_BufSz = Int_BufSz + 1 ! Node2Indx - Re_BufSz = Re_BufSz + 1 ! R1 - Re_BufSz = Re_BufSz + 1 ! t1 - Re_BufSz = Re_BufSz + 1 ! R2 - Re_BufSz = Re_BufSz + 1 ! t2 - Re_BufSz = Re_BufSz + 1 ! Cd1 - Re_BufSz = Re_BufSz + 1 ! CdMG1 - Re_BufSz = Re_BufSz + 1 ! Ca1 - Re_BufSz = Re_BufSz + 1 ! CaMG1 - Re_BufSz = Re_BufSz + 1 ! Cp1 - Re_BufSz = Re_BufSz + 1 ! CpMG1 - Re_BufSz = Re_BufSz + 1 ! AxCa1 - Re_BufSz = Re_BufSz + 1 ! AxCaMG1 - Re_BufSz = Re_BufSz + 1 ! AxCp1 - Re_BufSz = Re_BufSz + 1 ! AxCpMG1 - Re_BufSz = Re_BufSz + 1 ! Cd2 - Re_BufSz = Re_BufSz + 1 ! CdMG2 - Re_BufSz = Re_BufSz + 1 ! Ca2 - Re_BufSz = Re_BufSz + 1 ! CaMG2 - Re_BufSz = Re_BufSz + 1 ! Cp2 - Re_BufSz = Re_BufSz + 1 ! CpMG2 - Re_BufSz = Re_BufSz + 1 ! AxCa2 - Re_BufSz = Re_BufSz + 1 ! AxCaMG2 - Re_BufSz = Re_BufSz + 1 ! AxCp2 - Re_BufSz = Re_BufSz + 1 ! AxCpMG2 - Re_BufSz = Re_BufSz + 1 ! InpMbrDist1 - Re_BufSz = Re_BufSz + 1 ! InpMbrDist2 - Re_BufSz = Re_BufSz + 1 ! InpMbrLen - Int_BufSz = Int_BufSz + 1 ! InpMbrIndx - Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG - Int_BufSz = Int_BufSz + 1 ! NumSplits - Re_BufSz = Re_BufSz + SIZE(InData%Splits) ! Splits - Re_BufSz = Re_BufSz + 1 ! MGvolume - Re_BufSz = Re_BufSz + 1 ! MDivSize - Int_BufSz = Int_BufSz + 1 ! MCoefMod - Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx - Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx - Re_BufSz = Re_BufSz + 1 ! FillFSLoc - Re_BufSz = Re_BufSz + 1 ! FillDens - Re_BufSz = Re_BufSz + SIZE(InData%F_Bouy) ! F_Bouy - Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP - Int_BufSz = Int_BufSz + 1 ! PropPot - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF +IF (ALLOCATED(SrcMemberTypeData%NodeIndx)) THEN + i1_l = LBOUND(SrcMemberTypeData%NodeIndx,1) + i1_u = UBOUND(SrcMemberTypeData%NodeIndx,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%NodeIndx)) THEN + ALLOCATE(DstMemberTypeData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF + DstMemberTypeData%NodeIndx = SrcMemberTypeData%NodeIndx +ENDIF + DstMemberTypeData%MemberID = SrcMemberTypeData%MemberID + DstMemberTypeData%NElements = SrcMemberTypeData%NElements + DstMemberTypeData%RefLength = SrcMemberTypeData%RefLength + DstMemberTypeData%dl = SrcMemberTypeData%dl + DstMemberTypeData%k = SrcMemberTypeData%k + DstMemberTypeData%kkt = SrcMemberTypeData%kkt + DstMemberTypeData%Ak = SrcMemberTypeData%Ak +IF (ALLOCATED(SrcMemberTypeData%R)) THEN + i1_l = LBOUND(SrcMemberTypeData%R,1) + i1_u = UBOUND(SrcMemberTypeData%R,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%R)) THEN + ALLOCATE(DstMemberTypeData%R(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%R.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + DstMemberTypeData%R = SrcMemberTypeData%R +ENDIF +IF (ALLOCATED(SrcMemberTypeData%RMG)) THEN + i1_l = LBOUND(SrcMemberTypeData%RMG,1) + i1_u = UBOUND(SrcMemberTypeData%RMG,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%RMG)) THEN + ALLOCATE(DstMemberTypeData%RMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%RMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%RMG = SrcMemberTypeData%RMG +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Rin)) THEN + i1_l = LBOUND(SrcMemberTypeData%Rin,1) + i1_u = UBOUND(SrcMemberTypeData%Rin,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Rin)) THEN + ALLOCATE(DstMemberTypeData%Rin(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Rin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Rin = SrcMemberTypeData%Rin +ENDIF +IF (ALLOCATED(SrcMemberTypeData%tMG)) THEN + i1_l = LBOUND(SrcMemberTypeData%tMG,1) + i1_u = UBOUND(SrcMemberTypeData%tMG,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%tMG)) THEN + ALLOCATE(DstMemberTypeData%tMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%tMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%tMG = SrcMemberTypeData%tMG +ENDIF +IF (ALLOCATED(SrcMemberTypeData%MGdensity)) THEN + i1_l = LBOUND(SrcMemberTypeData%MGdensity,1) + i1_u = UBOUND(SrcMemberTypeData%MGdensity,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%MGdensity)) THEN + ALLOCATE(DstMemberTypeData%MGdensity(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%MGdensity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%MGdensity = SrcMemberTypeData%MGdensity +ENDIF +IF (ALLOCATED(SrcMemberTypeData%dRdl_mg)) THEN + i1_l = LBOUND(SrcMemberTypeData%dRdl_mg,1) + i1_u = UBOUND(SrcMemberTypeData%dRdl_mg,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%dRdl_mg)) THEN + ALLOCATE(DstMemberTypeData%dRdl_mg(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dRdl_mg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%dRdl_mg = SrcMemberTypeData%dRdl_mg +ENDIF +IF (ALLOCATED(SrcMemberTypeData%dRdl_in)) THEN + i1_l = LBOUND(SrcMemberTypeData%dRdl_in,1) + i1_u = UBOUND(SrcMemberTypeData%dRdl_in,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%dRdl_in)) THEN + ALLOCATE(DstMemberTypeData%dRdl_in(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dRdl_in.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%dRdl_in = SrcMemberTypeData%dRdl_in +ENDIF + DstMemberTypeData%Vinner = SrcMemberTypeData%Vinner + DstMemberTypeData%Vouter = SrcMemberTypeData%Vouter + DstMemberTypeData%Vballast = SrcMemberTypeData%Vballast + DstMemberTypeData%Vsubmerged = SrcMemberTypeData%Vsubmerged + DstMemberTypeData%l_fill = SrcMemberTypeData%l_fill + DstMemberTypeData%h_fill = SrcMemberTypeData%h_fill + DstMemberTypeData%z_overfill = SrcMemberTypeData%z_overfill + DstMemberTypeData%h_floor = SrcMemberTypeData%h_floor + DstMemberTypeData%i_floor = SrcMemberTypeData%i_floor + DstMemberTypeData%memfloodstatus = SrcMemberTypeData%memfloodstatus +IF (ALLOCATED(SrcMemberTypeData%floodstatus)) THEN + i1_l = LBOUND(SrcMemberTypeData%floodstatus,1) + i1_u = UBOUND(SrcMemberTypeData%floodstatus,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%floodstatus)) THEN + ALLOCATE(DstMemberTypeData%floodstatus(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%floodstatus.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%floodstatus = SrcMemberTypeData%floodstatus +ENDIF +IF (ALLOCATED(SrcMemberTypeData%alpha)) THEN + i1_l = LBOUND(SrcMemberTypeData%alpha,1) + i1_u = UBOUND(SrcMemberTypeData%alpha,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%alpha)) THEN + ALLOCATE(DstMemberTypeData%alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%alpha = SrcMemberTypeData%alpha +ENDIF +IF (ALLOCATED(SrcMemberTypeData%alpha_fb)) THEN + i1_l = LBOUND(SrcMemberTypeData%alpha_fb,1) + i1_u = UBOUND(SrcMemberTypeData%alpha_fb,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%alpha_fb)) THEN + ALLOCATE(DstMemberTypeData%alpha_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%alpha_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%alpha_fb = SrcMemberTypeData%alpha_fb +ENDIF +IF (ALLOCATED(SrcMemberTypeData%alpha_fb_star)) THEN + i1_l = LBOUND(SrcMemberTypeData%alpha_fb_star,1) + i1_u = UBOUND(SrcMemberTypeData%alpha_fb_star,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%alpha_fb_star)) THEN + ALLOCATE(DstMemberTypeData%alpha_fb_star(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%alpha_fb_star.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%alpha_fb_star = SrcMemberTypeData%alpha_fb_star +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Cd)) THEN + i1_l = LBOUND(SrcMemberTypeData%Cd,1) + i1_u = UBOUND(SrcMemberTypeData%Cd,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Cd)) THEN + ALLOCATE(DstMemberTypeData%Cd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Cd = SrcMemberTypeData%Cd +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Ca)) THEN + i1_l = LBOUND(SrcMemberTypeData%Ca,1) + i1_u = UBOUND(SrcMemberTypeData%Ca,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Ca)) THEN + ALLOCATE(DstMemberTypeData%Ca(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Ca.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Ca = SrcMemberTypeData%Ca +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Cp)) THEN + i1_l = LBOUND(SrcMemberTypeData%Cp,1) + i1_u = UBOUND(SrcMemberTypeData%Cp,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Cp)) THEN + ALLOCATE(DstMemberTypeData%Cp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Cp = SrcMemberTypeData%Cp +ENDIF +IF (ALLOCATED(SrcMemberTypeData%AxCd)) THEN + i1_l = LBOUND(SrcMemberTypeData%AxCd,1) + i1_u = UBOUND(SrcMemberTypeData%AxCd,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%AxCd)) THEN + ALLOCATE(DstMemberTypeData%AxCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%AxCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%AxCd = SrcMemberTypeData%AxCd +ENDIF +IF (ALLOCATED(SrcMemberTypeData%AxCa)) THEN + i1_l = LBOUND(SrcMemberTypeData%AxCa,1) + i1_u = UBOUND(SrcMemberTypeData%AxCa,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%AxCa)) THEN + ALLOCATE(DstMemberTypeData%AxCa(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%AxCa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%AxCa = SrcMemberTypeData%AxCa +ENDIF +IF (ALLOCATED(SrcMemberTypeData%AxCp)) THEN + i1_l = LBOUND(SrcMemberTypeData%AxCp,1) + i1_u = UBOUND(SrcMemberTypeData%AxCp,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%AxCp)) THEN + ALLOCATE(DstMemberTypeData%AxCp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%AxCp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%AxCp = SrcMemberTypeData%AxCp +ENDIF +IF (ALLOCATED(SrcMemberTypeData%m_fb_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%m_fb_l,1) + i1_u = UBOUND(SrcMemberTypeData%m_fb_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%m_fb_l)) THEN + ALLOCATE(DstMemberTypeData%m_fb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%m_fb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%m_fb_l = SrcMemberTypeData%m_fb_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%m_fb_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%m_fb_u,1) + i1_u = UBOUND(SrcMemberTypeData%m_fb_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%m_fb_u)) THEN + ALLOCATE(DstMemberTypeData%m_fb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%m_fb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%m_fb_u = SrcMemberTypeData%m_fb_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%h_cfb_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%h_cfb_l,1) + i1_u = UBOUND(SrcMemberTypeData%h_cfb_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%h_cfb_l)) THEN + ALLOCATE(DstMemberTypeData%h_cfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%h_cfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%h_cfb_l = SrcMemberTypeData%h_cfb_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%h_cfb_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%h_cfb_u,1) + i1_u = UBOUND(SrcMemberTypeData%h_cfb_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%h_cfb_u)) THEN + ALLOCATE(DstMemberTypeData%h_cfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%h_cfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%h_cfb_u = SrcMemberTypeData%h_cfb_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_lfb_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_lfb_l,1) + i1_u = UBOUND(SrcMemberTypeData%I_lfb_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_lfb_l)) THEN + ALLOCATE(DstMemberTypeData%I_lfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_lfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_lfb_l = SrcMemberTypeData%I_lfb_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_lfb_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_lfb_u,1) + i1_u = UBOUND(SrcMemberTypeData%I_lfb_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_lfb_u)) THEN + ALLOCATE(DstMemberTypeData%I_lfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_lfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_lfb_u = SrcMemberTypeData%I_lfb_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_rfb_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_rfb_l,1) + i1_u = UBOUND(SrcMemberTypeData%I_rfb_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_rfb_l)) THEN + ALLOCATE(DstMemberTypeData%I_rfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_rfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_rfb_l = SrcMemberTypeData%I_rfb_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_rfb_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_rfb_u,1) + i1_u = UBOUND(SrcMemberTypeData%I_rfb_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_rfb_u)) THEN + ALLOCATE(DstMemberTypeData%I_rfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_rfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_rfb_u = SrcMemberTypeData%I_rfb_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%m_mg_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%m_mg_l,1) + i1_u = UBOUND(SrcMemberTypeData%m_mg_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%m_mg_l)) THEN + ALLOCATE(DstMemberTypeData%m_mg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%m_mg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%m_mg_l = SrcMemberTypeData%m_mg_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%m_mg_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%m_mg_u,1) + i1_u = UBOUND(SrcMemberTypeData%m_mg_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%m_mg_u)) THEN + ALLOCATE(DstMemberTypeData%m_mg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%m_mg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%m_mg_u = SrcMemberTypeData%m_mg_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%h_cmg_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%h_cmg_l,1) + i1_u = UBOUND(SrcMemberTypeData%h_cmg_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%h_cmg_l)) THEN + ALLOCATE(DstMemberTypeData%h_cmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%h_cmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%h_cmg_l = SrcMemberTypeData%h_cmg_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%h_cmg_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%h_cmg_u,1) + i1_u = UBOUND(SrcMemberTypeData%h_cmg_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%h_cmg_u)) THEN + ALLOCATE(DstMemberTypeData%h_cmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%h_cmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%h_cmg_u = SrcMemberTypeData%h_cmg_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_lmg_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_lmg_l,1) + i1_u = UBOUND(SrcMemberTypeData%I_lmg_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_lmg_l)) THEN + ALLOCATE(DstMemberTypeData%I_lmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_lmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_lmg_l = SrcMemberTypeData%I_lmg_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_lmg_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_lmg_u,1) + i1_u = UBOUND(SrcMemberTypeData%I_lmg_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_lmg_u)) THEN + ALLOCATE(DstMemberTypeData%I_lmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_lmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_lmg_u = SrcMemberTypeData%I_lmg_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_rmg_l)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_rmg_l,1) + i1_u = UBOUND(SrcMemberTypeData%I_rmg_l,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_rmg_l)) THEN + ALLOCATE(DstMemberTypeData%I_rmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_rmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_rmg_l = SrcMemberTypeData%I_rmg_l +ENDIF +IF (ALLOCATED(SrcMemberTypeData%I_rmg_u)) THEN + i1_l = LBOUND(SrcMemberTypeData%I_rmg_u,1) + i1_u = UBOUND(SrcMemberTypeData%I_rmg_u,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%I_rmg_u)) THEN + ALLOCATE(DstMemberTypeData%I_rmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_rmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%I_rmg_u = SrcMemberTypeData%I_rmg_u +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Cfl_fb)) THEN + i1_l = LBOUND(SrcMemberTypeData%Cfl_fb,1) + i1_u = UBOUND(SrcMemberTypeData%Cfl_fb,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Cfl_fb)) THEN + ALLOCATE(DstMemberTypeData%Cfl_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cfl_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Cfl_fb = SrcMemberTypeData%Cfl_fb +ENDIF +IF (ALLOCATED(SrcMemberTypeData%Cfr_fb)) THEN + i1_l = LBOUND(SrcMemberTypeData%Cfr_fb,1) + i1_u = UBOUND(SrcMemberTypeData%Cfr_fb,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%Cfr_fb)) THEN + ALLOCATE(DstMemberTypeData%Cfr_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cfr_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%Cfr_fb = SrcMemberTypeData%Cfr_fb +ENDIF +IF (ALLOCATED(SrcMemberTypeData%CM0_fb)) THEN + i1_l = LBOUND(SrcMemberTypeData%CM0_fb,1) + i1_u = UBOUND(SrcMemberTypeData%CM0_fb,1) + IF (.NOT. ALLOCATED(DstMemberTypeData%CM0_fb)) THEN + ALLOCATE(DstMemberTypeData%CM0_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CM0_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberTypeData%CM0_fb = SrcMemberTypeData%CM0_fb +ENDIF + DstMemberTypeData%InpMbrDist1 = SrcMemberTypeData%InpMbrDist1 + DstMemberTypeData%InpMbrDist2 = SrcMemberTypeData%InpMbrDist2 + DstMemberTypeData%InpMbrLen = SrcMemberTypeData%InpMbrLen + DstMemberTypeData%InpMbrIndx = SrcMemberTypeData%InpMbrIndx + DstMemberTypeData%R_LToG = SrcMemberTypeData%R_LToG + DstMemberTypeData%MGvolume = SrcMemberTypeData%MGvolume + DstMemberTypeData%MDivSize = SrcMemberTypeData%MDivSize + DstMemberTypeData%MCoefMod = SrcMemberTypeData%MCoefMod + DstMemberTypeData%MmbrCoefIDIndx = SrcMemberTypeData%MmbrCoefIDIndx + DstMemberTypeData%MmbrFilledIDIndx = SrcMemberTypeData%MmbrFilledIDIndx + DstMemberTypeData%FillFSLoc = SrcMemberTypeData%FillFSLoc + DstMemberTypeData%FillDens = SrcMemberTypeData%FillDens + DstMemberTypeData%F_Bouy = SrcMemberTypeData%F_Bouy + DstMemberTypeData%F_DP = SrcMemberTypeData%F_DP + DstMemberTypeData%PropPot = SrcMemberTypeData%PropPot + END SUBROUTINE Morison_CopyMemberType + + SUBROUTINE Morison_DestroyMemberType( MemberTypeData, ErrStat, ErrMsg ) + TYPE(Morison_MemberType), INTENT(INOUT) :: MemberTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MemberTypeData%NodeIndx)) THEN + DEALLOCATE(MemberTypeData%NodeIndx) +ENDIF +IF (ALLOCATED(MemberTypeData%R)) THEN + DEALLOCATE(MemberTypeData%R) +ENDIF +IF (ALLOCATED(MemberTypeData%RMG)) THEN + DEALLOCATE(MemberTypeData%RMG) +ENDIF +IF (ALLOCATED(MemberTypeData%Rin)) THEN + DEALLOCATE(MemberTypeData%Rin) +ENDIF +IF (ALLOCATED(MemberTypeData%tMG)) THEN + DEALLOCATE(MemberTypeData%tMG) +ENDIF +IF (ALLOCATED(MemberTypeData%MGdensity)) THEN + DEALLOCATE(MemberTypeData%MGdensity) +ENDIF +IF (ALLOCATED(MemberTypeData%dRdl_mg)) THEN + DEALLOCATE(MemberTypeData%dRdl_mg) +ENDIF +IF (ALLOCATED(MemberTypeData%dRdl_in)) THEN + DEALLOCATE(MemberTypeData%dRdl_in) +ENDIF +IF (ALLOCATED(MemberTypeData%floodstatus)) THEN + DEALLOCATE(MemberTypeData%floodstatus) +ENDIF +IF (ALLOCATED(MemberTypeData%alpha)) THEN + DEALLOCATE(MemberTypeData%alpha) +ENDIF +IF (ALLOCATED(MemberTypeData%alpha_fb)) THEN + DEALLOCATE(MemberTypeData%alpha_fb) +ENDIF +IF (ALLOCATED(MemberTypeData%alpha_fb_star)) THEN + DEALLOCATE(MemberTypeData%alpha_fb_star) +ENDIF +IF (ALLOCATED(MemberTypeData%Cd)) THEN + DEALLOCATE(MemberTypeData%Cd) +ENDIF +IF (ALLOCATED(MemberTypeData%Ca)) THEN + DEALLOCATE(MemberTypeData%Ca) +ENDIF +IF (ALLOCATED(MemberTypeData%Cp)) THEN + DEALLOCATE(MemberTypeData%Cp) +ENDIF +IF (ALLOCATED(MemberTypeData%AxCd)) THEN + DEALLOCATE(MemberTypeData%AxCd) +ENDIF +IF (ALLOCATED(MemberTypeData%AxCa)) THEN + DEALLOCATE(MemberTypeData%AxCa) +ENDIF +IF (ALLOCATED(MemberTypeData%AxCp)) THEN + DEALLOCATE(MemberTypeData%AxCp) +ENDIF +IF (ALLOCATED(MemberTypeData%m_fb_l)) THEN + DEALLOCATE(MemberTypeData%m_fb_l) +ENDIF +IF (ALLOCATED(MemberTypeData%m_fb_u)) THEN + DEALLOCATE(MemberTypeData%m_fb_u) +ENDIF +IF (ALLOCATED(MemberTypeData%h_cfb_l)) THEN + DEALLOCATE(MemberTypeData%h_cfb_l) +ENDIF +IF (ALLOCATED(MemberTypeData%h_cfb_u)) THEN + DEALLOCATE(MemberTypeData%h_cfb_u) +ENDIF +IF (ALLOCATED(MemberTypeData%I_lfb_l)) THEN + DEALLOCATE(MemberTypeData%I_lfb_l) +ENDIF +IF (ALLOCATED(MemberTypeData%I_lfb_u)) THEN + DEALLOCATE(MemberTypeData%I_lfb_u) +ENDIF +IF (ALLOCATED(MemberTypeData%I_rfb_l)) THEN + DEALLOCATE(MemberTypeData%I_rfb_l) +ENDIF +IF (ALLOCATED(MemberTypeData%I_rfb_u)) THEN + DEALLOCATE(MemberTypeData%I_rfb_u) +ENDIF +IF (ALLOCATED(MemberTypeData%m_mg_l)) THEN + DEALLOCATE(MemberTypeData%m_mg_l) +ENDIF +IF (ALLOCATED(MemberTypeData%m_mg_u)) THEN + DEALLOCATE(MemberTypeData%m_mg_u) +ENDIF +IF (ALLOCATED(MemberTypeData%h_cmg_l)) THEN + DEALLOCATE(MemberTypeData%h_cmg_l) +ENDIF +IF (ALLOCATED(MemberTypeData%h_cmg_u)) THEN + DEALLOCATE(MemberTypeData%h_cmg_u) +ENDIF +IF (ALLOCATED(MemberTypeData%I_lmg_l)) THEN + DEALLOCATE(MemberTypeData%I_lmg_l) +ENDIF +IF (ALLOCATED(MemberTypeData%I_lmg_u)) THEN + DEALLOCATE(MemberTypeData%I_lmg_u) +ENDIF +IF (ALLOCATED(MemberTypeData%I_rmg_l)) THEN + DEALLOCATE(MemberTypeData%I_rmg_l) +ENDIF +IF (ALLOCATED(MemberTypeData%I_rmg_u)) THEN + DEALLOCATE(MemberTypeData%I_rmg_u) +ENDIF +IF (ALLOCATED(MemberTypeData%Cfl_fb)) THEN + DEALLOCATE(MemberTypeData%Cfl_fb) +ENDIF +IF (ALLOCATED(MemberTypeData%Cfr_fb)) THEN + DEALLOCATE(MemberTypeData%Cfr_fb) +ENDIF +IF (ALLOCATED(MemberTypeData%CM0_fb)) THEN + DEALLOCATE(MemberTypeData%CM0_fb) +ENDIF + END SUBROUTINE Morison_DestroyMemberType + + SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Morison_MemberType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_PackMemberType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! NodeIndx allocated yes/no + IF ( ALLOCATED(InData%NodeIndx) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeIndx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeIndx) ! NodeIndx + END IF + Int_BufSz = Int_BufSz + 1 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NElements + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! dl + Re_BufSz = Re_BufSz + SIZE(InData%k) ! k + Re_BufSz = Re_BufSz + SIZE(InData%kkt) ! kkt + Re_BufSz = Re_BufSz + SIZE(InData%Ak) ! Ak + Int_BufSz = Int_BufSz + 1 ! R allocated yes/no + IF ( ALLOCATED(InData%R) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! R upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%R) ! R + END IF + Int_BufSz = Int_BufSz + 1 ! RMG allocated yes/no + IF ( ALLOCATED(InData%RMG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%RMG) ! RMG + END IF + Int_BufSz = Int_BufSz + 1 ! Rin allocated yes/no + IF ( ALLOCATED(InData%Rin) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Rin upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Rin) ! Rin + END IF + Int_BufSz = Int_BufSz + 1 ! tMG allocated yes/no + IF ( ALLOCATED(InData%tMG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! tMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%tMG) ! tMG + END IF + Int_BufSz = Int_BufSz + 1 ! MGdensity allocated yes/no + IF ( ALLOCATED(InData%MGdensity) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MGdensity upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MGdensity) ! MGdensity + END IF + Int_BufSz = Int_BufSz + 1 ! dRdl_mg allocated yes/no + IF ( ALLOCATED(InData%dRdl_mg) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dRdl_mg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dRdl_mg) ! dRdl_mg + END IF + Int_BufSz = Int_BufSz + 1 ! dRdl_in allocated yes/no + IF ( ALLOCATED(InData%dRdl_in) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! dRdl_in upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%dRdl_in) ! dRdl_in + END IF + Re_BufSz = Re_BufSz + 1 ! Vinner + Re_BufSz = Re_BufSz + 1 ! Vouter + Re_BufSz = Re_BufSz + 1 ! Vballast + Re_BufSz = Re_BufSz + 1 ! Vsubmerged + Re_BufSz = Re_BufSz + 1 ! l_fill + Re_BufSz = Re_BufSz + 1 ! h_fill + Re_BufSz = Re_BufSz + 1 ! z_overfill + Re_BufSz = Re_BufSz + 1 ! h_floor + Int_BufSz = Int_BufSz + 1 ! i_floor + Int_BufSz = Int_BufSz + 1 ! memfloodstatus + Int_BufSz = Int_BufSz + 1 ! floodstatus allocated yes/no + IF ( ALLOCATED(InData%floodstatus) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! floodstatus upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%floodstatus) ! floodstatus + END IF + Int_BufSz = Int_BufSz + 1 ! alpha allocated yes/no + IF ( ALLOCATED(InData%alpha) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! alpha upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha) ! alpha + END IF + Int_BufSz = Int_BufSz + 1 ! alpha_fb allocated yes/no + IF ( ALLOCATED(InData%alpha_fb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! alpha_fb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha_fb) ! alpha_fb + END IF + Int_BufSz = Int_BufSz + 1 ! alpha_fb_star allocated yes/no + IF ( ALLOCATED(InData%alpha_fb_star) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! alpha_fb_star upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%alpha_fb_star) ! alpha_fb_star + END IF + Int_BufSz = Int_BufSz + 1 ! Cd allocated yes/no + IF ( ALLOCATED(InData%Cd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Cd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cd) ! Cd + END IF + Int_BufSz = Int_BufSz + 1 ! Ca allocated yes/no + IF ( ALLOCATED(InData%Ca) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Ca upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Ca) ! Ca + END IF + Int_BufSz = Int_BufSz + 1 ! Cp allocated yes/no + IF ( ALLOCATED(InData%Cp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Cp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cp) ! Cp + END IF + Int_BufSz = Int_BufSz + 1 ! AxCd allocated yes/no + IF ( ALLOCATED(InData%AxCd) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AxCd upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxCd) ! AxCd + END IF + Int_BufSz = Int_BufSz + 1 ! AxCa allocated yes/no + IF ( ALLOCATED(InData%AxCa) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AxCa upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxCa) ! AxCa + END IF + Int_BufSz = Int_BufSz + 1 ! AxCp allocated yes/no + IF ( ALLOCATED(InData%AxCp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AxCp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AxCp) ! AxCp + END IF + Int_BufSz = Int_BufSz + 1 ! m_fb_l allocated yes/no + IF ( ALLOCATED(InData%m_fb_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m_fb_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%m_fb_l) ! m_fb_l + END IF + Int_BufSz = Int_BufSz + 1 ! m_fb_u allocated yes/no + IF ( ALLOCATED(InData%m_fb_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m_fb_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%m_fb_u) ! m_fb_u + END IF + Int_BufSz = Int_BufSz + 1 ! h_cfb_l allocated yes/no + IF ( ALLOCATED(InData%h_cfb_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! h_cfb_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%h_cfb_l) ! h_cfb_l + END IF + Int_BufSz = Int_BufSz + 1 ! h_cfb_u allocated yes/no + IF ( ALLOCATED(InData%h_cfb_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! h_cfb_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%h_cfb_u) ! h_cfb_u + END IF + Int_BufSz = Int_BufSz + 1 ! I_lfb_l allocated yes/no + IF ( ALLOCATED(InData%I_lfb_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_lfb_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_lfb_l) ! I_lfb_l + END IF + Int_BufSz = Int_BufSz + 1 ! I_lfb_u allocated yes/no + IF ( ALLOCATED(InData%I_lfb_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_lfb_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_lfb_u) ! I_lfb_u + END IF + Int_BufSz = Int_BufSz + 1 ! I_rfb_l allocated yes/no + IF ( ALLOCATED(InData%I_rfb_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_rfb_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_rfb_l) ! I_rfb_l + END IF + Int_BufSz = Int_BufSz + 1 ! I_rfb_u allocated yes/no + IF ( ALLOCATED(InData%I_rfb_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_rfb_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_rfb_u) ! I_rfb_u + END IF + Int_BufSz = Int_BufSz + 1 ! m_mg_l allocated yes/no + IF ( ALLOCATED(InData%m_mg_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m_mg_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%m_mg_l) ! m_mg_l + END IF + Int_BufSz = Int_BufSz + 1 ! m_mg_u allocated yes/no + IF ( ALLOCATED(InData%m_mg_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! m_mg_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%m_mg_u) ! m_mg_u + END IF + Int_BufSz = Int_BufSz + 1 ! h_cmg_l allocated yes/no + IF ( ALLOCATED(InData%h_cmg_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! h_cmg_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%h_cmg_l) ! h_cmg_l + END IF + Int_BufSz = Int_BufSz + 1 ! h_cmg_u allocated yes/no + IF ( ALLOCATED(InData%h_cmg_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! h_cmg_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%h_cmg_u) ! h_cmg_u + END IF + Int_BufSz = Int_BufSz + 1 ! I_lmg_l allocated yes/no + IF ( ALLOCATED(InData%I_lmg_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_lmg_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_lmg_l) ! I_lmg_l + END IF + Int_BufSz = Int_BufSz + 1 ! I_lmg_u allocated yes/no + IF ( ALLOCATED(InData%I_lmg_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_lmg_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_lmg_u) ! I_lmg_u + END IF + Int_BufSz = Int_BufSz + 1 ! I_rmg_l allocated yes/no + IF ( ALLOCATED(InData%I_rmg_l) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_rmg_l upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_rmg_l) ! I_rmg_l + END IF + Int_BufSz = Int_BufSz + 1 ! I_rmg_u allocated yes/no + IF ( ALLOCATED(InData%I_rmg_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! I_rmg_u upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_rmg_u) ! I_rmg_u + END IF + Int_BufSz = Int_BufSz + 1 ! Cfl_fb allocated yes/no + IF ( ALLOCATED(InData%Cfl_fb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Cfl_fb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cfl_fb) ! Cfl_fb + END IF + Int_BufSz = Int_BufSz + 1 ! Cfr_fb allocated yes/no + IF ( ALLOCATED(InData%Cfr_fb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Cfr_fb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Cfr_fb) ! Cfr_fb + END IF + Int_BufSz = Int_BufSz + 1 ! CM0_fb allocated yes/no + IF ( ALLOCATED(InData%CM0_fb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CM0_fb upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CM0_fb) ! CM0_fb + END IF + Re_BufSz = Re_BufSz + 1 ! InpMbrDist1 + Re_BufSz = Re_BufSz + 1 ! InpMbrDist2 + Re_BufSz = Re_BufSz + 1 ! InpMbrLen + Int_BufSz = Int_BufSz + 1 ! InpMbrIndx + Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG + Re_BufSz = Re_BufSz + 1 ! MGvolume + Re_BufSz = Re_BufSz + 1 ! MDivSize + Int_BufSz = Int_BufSz + 1 ! MCoefMod + Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx + Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx + Re_BufSz = Re_BufSz + 1 ! FillFSLoc + Re_BufSz = Re_BufSz + 1 ! FillDens + Re_BufSz = Re_BufSz + SIZE(InData%F_Bouy) ! F_Bouy + Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP + Int_BufSz = Int_BufSz + 1 ! PropPot + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%NodeIndx) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodeIndx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeIndx))-1 ) = PACK(InData%NodeIndx,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodeIndx) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElements + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%dl + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%k))-1 ) = PACK(InData%k,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%k) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%kkt))-1 ) = PACK(InData%kkt,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%kkt) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ak))-1 ) = PACK(InData%Ak,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Ak) + IF ( .NOT. ALLOCATED(InData%R) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%R,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%R)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R))-1 ) = PACK(InData%R,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%R) + END IF + IF ( .NOT. ALLOCATED(InData%RMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMG,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%RMG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RMG))-1 ) = PACK(InData%RMG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%RMG) + END IF + IF ( .NOT. ALLOCATED(InData%Rin) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Rin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Rin,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Rin)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Rin))-1 ) = PACK(InData%Rin,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Rin) + END IF + IF ( .NOT. ALLOCATED(InData%tMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tMG,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%tMG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%tMG))-1 ) = PACK(InData%tMG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%tMG) + END IF + IF ( .NOT. ALLOCATED(InData%MGdensity) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MGdensity,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MGdensity,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MGdensity)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MGdensity))-1 ) = PACK(InData%MGdensity,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MGdensity) + END IF + IF ( .NOT. ALLOCATED(InData%dRdl_mg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dRdl_mg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dRdl_mg,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%dRdl_mg)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%dRdl_mg))-1 ) = PACK(InData%dRdl_mg,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%dRdl_mg) + END IF + IF ( .NOT. ALLOCATED(InData%dRdl_in) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dRdl_in,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dRdl_in,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%dRdl_in)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%dRdl_in))-1 ) = PACK(InData%dRdl_in,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%dRdl_in) + END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Vinner + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Vouter + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Vballast + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Vsubmerged + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%l_fill + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%h_fill + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%z_overfill + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%h_floor + Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%i_floor + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%memfloodstatus + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%floodstatus) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%floodstatus,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%floodstatus,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%floodstatus)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%floodstatus))-1 ) = PACK(InData%floodstatus,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%floodstatus) + END IF + IF ( .NOT. ALLOCATED(InData%alpha) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%alpha)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%alpha))-1 ) = PACK(InData%alpha,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%alpha) + END IF + IF ( .NOT. ALLOCATED(InData%alpha_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_fb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%alpha_fb)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%alpha_fb))-1 ) = PACK(InData%alpha_fb,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%alpha_fb) + END IF + IF ( .NOT. ALLOCATED(InData%alpha_fb_star) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_fb_star,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_fb_star,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%alpha_fb_star)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%alpha_fb_star))-1 ) = PACK(InData%alpha_fb_star,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%alpha_fb_star) + END IF + IF ( .NOT. ALLOCATED(InData%Cd) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cd,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Cd)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Cd))-1 ) = PACK(InData%Cd,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Cd) + END IF + IF ( .NOT. ALLOCATED(InData%Ca) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ca,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ca,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Ca)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ca))-1 ) = PACK(InData%Ca,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Ca) + END IF + IF ( .NOT. ALLOCATED(InData%Cp) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cp,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Cp)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Cp))-1 ) = PACK(InData%Cp,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Cp) + END IF + IF ( .NOT. ALLOCATED(InData%AxCd) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCd,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AxCd)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AxCd))-1 ) = PACK(InData%AxCd,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AxCd) + END IF + IF ( .NOT. ALLOCATED(InData%AxCa) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCa,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCa,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AxCa)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AxCa))-1 ) = PACK(InData%AxCa,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AxCa) + END IF + IF ( .NOT. ALLOCATED(InData%AxCp) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCp,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AxCp)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AxCp))-1 ) = PACK(InData%AxCp,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AxCp) + END IF + IF ( .NOT. ALLOCATED(InData%m_fb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_fb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_fb_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%m_fb_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%m_fb_l))-1 ) = PACK(InData%m_fb_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%m_fb_l) + END IF + IF ( .NOT. ALLOCATED(InData%m_fb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_fb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_fb_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%m_fb_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%m_fb_u))-1 ) = PACK(InData%m_fb_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%m_fb_u) + END IF + IF ( .NOT. ALLOCATED(InData%h_cfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cfb_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%h_cfb_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%h_cfb_l))-1 ) = PACK(InData%h_cfb_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%h_cfb_l) + END IF + IF ( .NOT. ALLOCATED(InData%h_cfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cfb_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%h_cfb_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%h_cfb_u))-1 ) = PACK(InData%h_cfb_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%h_cfb_u) + END IF + IF ( .NOT. ALLOCATED(InData%I_lfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lfb_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_lfb_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_lfb_l))-1 ) = PACK(InData%I_lfb_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_lfb_l) + END IF + IF ( .NOT. ALLOCATED(InData%I_lfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lfb_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_lfb_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_lfb_u))-1 ) = PACK(InData%I_lfb_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_lfb_u) + END IF + IF ( .NOT. ALLOCATED(InData%I_rfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rfb_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_rfb_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_rfb_l))-1 ) = PACK(InData%I_rfb_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_rfb_l) + END IF + IF ( .NOT. ALLOCATED(InData%I_rfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rfb_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_rfb_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_rfb_u))-1 ) = PACK(InData%I_rfb_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_rfb_u) + END IF + IF ( .NOT. ALLOCATED(InData%m_mg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_mg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_mg_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%m_mg_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%m_mg_l))-1 ) = PACK(InData%m_mg_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%m_mg_l) + END IF + IF ( .NOT. ALLOCATED(InData%m_mg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_mg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_mg_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%m_mg_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%m_mg_u))-1 ) = PACK(InData%m_mg_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%m_mg_u) + END IF + IF ( .NOT. ALLOCATED(InData%h_cmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cmg_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%h_cmg_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%h_cmg_l))-1 ) = PACK(InData%h_cmg_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%h_cmg_l) + END IF + IF ( .NOT. ALLOCATED(InData%h_cmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cmg_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%h_cmg_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%h_cmg_u))-1 ) = PACK(InData%h_cmg_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%h_cmg_u) + END IF + IF ( .NOT. ALLOCATED(InData%I_lmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lmg_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_lmg_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_lmg_l))-1 ) = PACK(InData%I_lmg_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_lmg_l) + END IF + IF ( .NOT. ALLOCATED(InData%I_lmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lmg_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_lmg_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_lmg_u))-1 ) = PACK(InData%I_lmg_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_lmg_u) + END IF + IF ( .NOT. ALLOCATED(InData%I_rmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rmg_l,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_rmg_l)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_rmg_l))-1 ) = PACK(InData%I_rmg_l,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_rmg_l) + END IF + IF ( .NOT. ALLOCATED(InData%I_rmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rmg_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_rmg_u)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_rmg_u))-1 ) = PACK(InData%I_rmg_u,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_rmg_u) + END IF + IF ( .NOT. ALLOCATED(InData%Cfl_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cfl_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cfl_fb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Cfl_fb)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Cfl_fb))-1 ) = PACK(InData%Cfl_fb,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Cfl_fb) + END IF + IF ( .NOT. ALLOCATED(InData%Cfr_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cfr_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cfr_fb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Cfr_fb)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Cfr_fb))-1 ) = PACK(InData%Cfr_fb,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Cfr_fb) + END IF + IF ( .NOT. ALLOCATED(InData%CM0_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM0_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM0_fb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CM0_fb)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CM0_fb))-1 ) = PACK(InData%CM0_fb,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CM0_fb) + END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrLen + Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%InpMbrIndx + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGvolume + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MDivSize + Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MCoefMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MmbrCoefIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MmbrFilledIDIndx + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillFSLoc + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillDens + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_Bouy))-1 ) = PACK(InData%F_Bouy,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_Bouy) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP))-1 ) = PACK(InData%F_DP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_DP) + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackMemberType + + SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Morison_MemberType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIndx not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIndx)) DEALLOCATE(OutData%NodeIndx) + ALLOCATE(OutData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NodeIndx)>0) OutData%NodeIndx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeIndx))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodeIndx) + DEALLOCATE(mask1) + END IF + OutData%MemberID = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NElements = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%RefLength = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%dl = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%k,1) + i1_u = UBOUND(OutData%k,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%k = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%k))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%k) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%kkt,1) + i1_u = UBOUND(OutData%kkt,1) + i2_l = LBOUND(OutData%kkt,2) + i2_u = UBOUND(OutData%kkt,2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + OutData%kkt = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%kkt))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%kkt) + DEALLOCATE(mask2) + i1_l = LBOUND(OutData%Ak,1) + i1_u = UBOUND(OutData%Ak,1) + i2_l = LBOUND(OutData%Ak,2) + i2_u = UBOUND(OutData%Ak,2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + OutData%Ak = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ak))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Ak) + DEALLOCATE(mask2) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! R not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%R)) DEALLOCATE(OutData%R) + ALLOCATE(OutData%R(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%R.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%R)>0) OutData%R = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%R) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RMG)) DEALLOCATE(OutData%RMG) + ALLOCATE(OutData%RMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%RMG)>0) OutData%RMG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RMG))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%RMG) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Rin not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Rin)) DEALLOCATE(OutData%Rin) + ALLOCATE(OutData%Rin(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Rin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Rin)>0) OutData%Rin = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Rin))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Rin) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%tMG)) DEALLOCATE(OutData%tMG) + ALLOCATE(OutData%tMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%tMG)>0) OutData%tMG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%tMG))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%tMG) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MGdensity not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MGdensity)) DEALLOCATE(OutData%MGdensity) + ALLOCATE(OutData%MGdensity(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MGdensity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%MGdensity)>0) OutData%MGdensity = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MGdensity))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MGdensity) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dRdl_mg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dRdl_mg)) DEALLOCATE(OutData%dRdl_mg) + ALLOCATE(OutData%dRdl_mg(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dRdl_mg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%dRdl_mg)>0) OutData%dRdl_mg = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%dRdl_mg))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%dRdl_mg) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dRdl_in not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dRdl_in)) DEALLOCATE(OutData%dRdl_in) + ALLOCATE(OutData%dRdl_in(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dRdl_in.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%dRdl_in)>0) OutData%dRdl_in = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%dRdl_in))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%dRdl_in) + DEALLOCATE(mask1) + END IF + OutData%Vinner = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Vouter = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Vballast = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Vsubmerged = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%l_fill = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%h_fill = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%z_overfill = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%h_floor = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%i_floor = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%memfloodstatus = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! floodstatus not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%floodstatus)) DEALLOCATE(OutData%floodstatus) + ALLOCATE(OutData%floodstatus(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%floodstatus.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%floodstatus)>0) OutData%floodstatus = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%floodstatus))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%floodstatus) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha)) DEALLOCATE(OutData%alpha) + ALLOCATE(OutData%alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%alpha)>0) OutData%alpha = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%alpha))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%alpha) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha_fb)) DEALLOCATE(OutData%alpha_fb) + ALLOCATE(OutData%alpha_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%alpha_fb)>0) OutData%alpha_fb = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%alpha_fb))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%alpha_fb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_fb_star not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha_fb_star)) DEALLOCATE(OutData%alpha_fb_star) + ALLOCATE(OutData%alpha_fb_star(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_fb_star.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%alpha_fb_star)>0) OutData%alpha_fb_star = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%alpha_fb_star))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%alpha_fb_star) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cd not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cd)) DEALLOCATE(OutData%Cd) + ALLOCATE(OutData%Cd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Cd)>0) OutData%Cd = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Cd))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Cd) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ca not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Ca)) DEALLOCATE(OutData%Ca) + ALLOCATE(OutData%Ca(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ca.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Ca)>0) OutData%Ca = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ca))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Ca) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cp not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cp)) DEALLOCATE(OutData%Cp) + ALLOCATE(OutData%Cp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Cp)>0) OutData%Cp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Cp))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Cp) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCd not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCd)) DEALLOCATE(OutData%AxCd) + ALLOCATE(OutData%AxCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%AxCd)>0) OutData%AxCd = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AxCd))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AxCd) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCa not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCa)) DEALLOCATE(OutData%AxCa) + ALLOCATE(OutData%AxCa(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%AxCa)>0) OutData%AxCa = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AxCa))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AxCa) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCp not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCp)) DEALLOCATE(OutData%AxCp) + ALLOCATE(OutData%AxCp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%AxCp)>0) OutData%AxCp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AxCp))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AxCp) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_fb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_fb_l)) DEALLOCATE(OutData%m_fb_l) + ALLOCATE(OutData%m_fb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_fb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%m_fb_l)>0) OutData%m_fb_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%m_fb_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%m_fb_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_fb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_fb_u)) DEALLOCATE(OutData%m_fb_u) + ALLOCATE(OutData%m_fb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_fb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%m_fb_u)>0) OutData%m_fb_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%m_fb_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%m_fb_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cfb_l)) DEALLOCATE(OutData%h_cfb_l) + ALLOCATE(OutData%h_cfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%h_cfb_l)>0) OutData%h_cfb_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%h_cfb_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%h_cfb_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cfb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cfb_u)) DEALLOCATE(OutData%h_cfb_u) + ALLOCATE(OutData%h_cfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%h_cfb_u)>0) OutData%h_cfb_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%h_cfb_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%h_cfb_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lfb_l)) DEALLOCATE(OutData%I_lfb_l) + ALLOCATE(OutData%I_lfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_lfb_l)>0) OutData%I_lfb_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_lfb_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_lfb_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lfb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lfb_u)) DEALLOCATE(OutData%I_lfb_u) + ALLOCATE(OutData%I_lfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_lfb_u)>0) OutData%I_lfb_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_lfb_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_lfb_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rfb_l)) DEALLOCATE(OutData%I_rfb_l) + ALLOCATE(OutData%I_rfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_rfb_l)>0) OutData%I_rfb_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_rfb_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_rfb_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rfb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rfb_u)) DEALLOCATE(OutData%I_rfb_u) + ALLOCATE(OutData%I_rfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_rfb_u)>0) OutData%I_rfb_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_rfb_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_rfb_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_mg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_mg_l)) DEALLOCATE(OutData%m_mg_l) + ALLOCATE(OutData%m_mg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_mg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%m_mg_l)>0) OutData%m_mg_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%m_mg_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%m_mg_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_mg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_mg_u)) DEALLOCATE(OutData%m_mg_u) + ALLOCATE(OutData%m_mg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_mg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%m_mg_u)>0) OutData%m_mg_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%m_mg_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%m_mg_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cmg_l)) DEALLOCATE(OutData%h_cmg_l) + ALLOCATE(OutData%h_cmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%h_cmg_l)>0) OutData%h_cmg_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%h_cmg_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%h_cmg_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cmg_u)) DEALLOCATE(OutData%h_cmg_u) + ALLOCATE(OutData%h_cmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%h_cmg_u)>0) OutData%h_cmg_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%h_cmg_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%h_cmg_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lmg_l)) DEALLOCATE(OutData%I_lmg_l) + ALLOCATE(OutData%I_lmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_lmg_l)>0) OutData%I_lmg_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_lmg_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_lmg_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lmg_u)) DEALLOCATE(OutData%I_lmg_u) + ALLOCATE(OutData%I_lmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_lmg_u)>0) OutData%I_lmg_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_lmg_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_lmg_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rmg_l)) DEALLOCATE(OutData%I_rmg_l) + ALLOCATE(OutData%I_rmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_rmg_l)>0) OutData%I_rmg_l = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_rmg_l))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_rmg_l) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rmg_u)) DEALLOCATE(OutData%I_rmg_u) + ALLOCATE(OutData%I_rmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%I_rmg_u)>0) OutData%I_rmg_u = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_rmg_u))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_rmg_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cfl_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cfl_fb)) DEALLOCATE(OutData%Cfl_fb) + ALLOCATE(OutData%Cfl_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cfl_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Cfl_fb)>0) OutData%Cfl_fb = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Cfl_fb))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Cfl_fb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cfr_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cfr_fb)) DEALLOCATE(OutData%Cfr_fb) + ALLOCATE(OutData%Cfr_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cfr_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Cfr_fb)>0) OutData%Cfr_fb = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Cfr_fb))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Cfr_fb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CM0_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CM0_fb)) DEALLOCATE(OutData%CM0_fb) + ALLOCATE(OutData%CM0_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CM0_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) RETURN - END IF + END IF + mask1 = .TRUE. + IF (SIZE(OutData%CM0_fb)>0) OutData%CM0_fb = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CM0_fb))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CM0_fb) + DEALLOCATE(mask1) END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Node1Indx - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Node2Indx - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%R1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%t1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%R2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%t2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cd1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CdMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ca1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCa1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cd2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CdMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ca2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Cp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%CpMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCa2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%AxCpMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrLen - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%InpMbrIndx - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumSplits - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Splits))-1 ) = PACK(InData%Splits,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Splits) - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGvolume - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MDivSize - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MCoefMod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MmbrCoefIDIndx - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MmbrFilledIDIndx - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillFSLoc - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillDens - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_Bouy))-1 ) = PACK(InData%F_Bouy,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_Bouy) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP))-1 ) = PACK(InData%F_DP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_DP) - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE Morison_PackMemberType - - SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Morison_MemberType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Node1Indx = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Node2Indx = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%R1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%t1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%R2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%t2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Cd1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CdMG1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Ca1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CaMG1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Cp1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CpMG1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCa1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCp1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Cd2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CdMG2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Ca2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CaMG2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Cp2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%CpMG2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCa2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCp2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 OutData%InpMbrDist1 = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%InpMbrDist2 = ReKiBuf( Re_Xferred ) @@ -2277,19 +4286,6 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta OutData%R_LToG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R_LToG))-1 ), mask2, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%R_LToG) DEALLOCATE(mask2) - OutData%NumSplits = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Splits,1) - i1_u = UBOUND(OutData%Splits,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%Splits = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Splits))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Splits) - DEALLOCATE(mask1) OutData%MGvolume = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%MDivSize = ReKiBuf( Re_Xferred ) @@ -2357,6 +4353,10 @@ SUBROUTINE Morison_CopyCoefMembers( SrcCoefMembersData, DstCoefMembersData, Ctrl DstCoefMembersData%MemberCp2 = SrcCoefMembersData%MemberCp2 DstCoefMembersData%MemberCpMG1 = SrcCoefMembersData%MemberCpMG1 DstCoefMembersData%MemberCpMG2 = SrcCoefMembersData%MemberCpMG2 + DstCoefMembersData%MemberAxCd1 = SrcCoefMembersData%MemberAxCd1 + DstCoefMembersData%MemberAxCd2 = SrcCoefMembersData%MemberAxCd2 + DstCoefMembersData%MemberAxCdMG1 = SrcCoefMembersData%MemberAxCdMG1 + DstCoefMembersData%MemberAxCdMG2 = SrcCoefMembersData%MemberAxCdMG2 DstCoefMembersData%MemberAxCa1 = SrcCoefMembersData%MemberAxCa1 DstCoefMembersData%MemberAxCa2 = SrcCoefMembersData%MemberAxCa2 DstCoefMembersData%MemberAxCaMG1 = SrcCoefMembersData%MemberAxCaMG1 @@ -2426,6 +4426,10 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = Re_BufSz + 1 ! MemberCp2 Re_BufSz = Re_BufSz + 1 ! MemberCpMG1 Re_BufSz = Re_BufSz + 1 ! MemberCpMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCd1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCd2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG2 Re_BufSz = Re_BufSz + 1 ! MemberAxCa1 Re_BufSz = Re_BufSz + 1 ! MemberAxCa2 Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG1 @@ -2487,6 +4491,14 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberCpMG2 Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCdMG2 + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCa1 Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MemberAxCa2 @@ -2563,6 +4575,14 @@ SUBROUTINE Morison_UnPackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt Re_Xferred = Re_Xferred + 1 OutData%MemberCpMG2 = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCd1 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCd2 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCdMG1 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCdMG2 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%MemberAxCa1 = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%MemberAxCa2 = ReKiBuf( Re_Xferred ) @@ -3276,7 +5296,6 @@ SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL DstInitInputData%NJoints = SrcInitInputData%NJoints DstInitInputData%NNodes = SrcInitInputData%NNodes - DstInitInputData%TotalPossibleSuperMembers = SrcInitInputData%TotalPossibleSuperMembers IF (ALLOCATED(SrcInitInputData%InpJoints)) THEN i1_l = LBOUND(SrcInitInputData%InpJoints,1) i1_u = UBOUND(SrcInitInputData%InpJoints,1) @@ -3309,19 +5328,18 @@ SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF - DstInitInputData%NElements = SrcInitInputData%NElements -IF (ALLOCATED(SrcInitInputData%Elements)) THEN - i1_l = LBOUND(SrcInitInputData%Elements,1) - i1_u = UBOUND(SrcInitInputData%Elements,1) - IF (.NOT. ALLOCATED(DstInitInputData%Elements)) THEN - ALLOCATE(DstInitInputData%Elements(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitInputData%Members)) THEN + i1_l = LBOUND(SrcInitInputData%Members,1) + i1_u = UBOUND(SrcInitInputData%Members,1) + IF (.NOT. ALLOCATED(DstInitInputData%Members)) THEN + ALLOCATE(DstInitInputData%Members(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Elements.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Members.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DO i1 = LBOUND(SrcInitInputData%Elements,1), UBOUND(SrcInitInputData%Elements,1) - CALL Morison_Copymembertype( SrcInitInputData%Elements(i1), DstInitInputData%Elements(i1), CtrlCode, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(SrcInitInputData%Members,1), UBOUND(SrcInitInputData%Members,1) + CALL Morison_Copymembertype( SrcInitInputData%Members(i1), DstInitInputData%Members(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO @@ -3366,6 +5384,8 @@ SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, DstInitInputData%SimplCaMG = SrcInitInputData%SimplCaMG DstInitInputData%SimplCp = SrcInitInputData%SimplCp DstInitInputData%SimplCpMG = SrcInitInputData%SimplCpMG + DstInitInputData%SimplAxCd = SrcInitInputData%SimplAxCd + DstInitInputData%SimplAxCdMG = SrcInitInputData%SimplAxCdMG DstInitInputData%SimplAxCa = SrcInitInputData%SimplAxCa DstInitInputData%SimplAxCaMG = SrcInitInputData%SimplAxCaMG DstInitInputData%SimplAxCp = SrcInitInputData%SimplAxCp @@ -3606,11 +5626,11 @@ SUBROUTINE Morison_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(InitInputData%Nodes) ENDIF -IF (ALLOCATED(InitInputData%Elements)) THEN -DO i1 = LBOUND(InitInputData%Elements,1), UBOUND(InitInputData%Elements,1) - CALL Morison_Destroymembertype( InitInputData%Elements(i1), ErrStat, ErrMsg ) +IF (ALLOCATED(InitInputData%Members)) THEN +DO i1 = LBOUND(InitInputData%Members,1), UBOUND(InitInputData%Members,1) + CALL Morison_Destroymembertype( InitInputData%Members(i1), ErrStat, ErrMsg ) ENDDO - DEALLOCATE(InitInputData%Elements) + DEALLOCATE(InitInputData%Members) ENDIF IF (ALLOCATED(InitInputData%AxialCoefs)) THEN DO i1 = LBOUND(InitInputData%AxialCoefs,1), UBOUND(InitInputData%AxialCoefs,1) @@ -3727,7 +5747,6 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = Re_BufSz + 1 ! MSL2SWL Int_BufSz = Int_BufSz + 1 ! NJoints Int_BufSz = Int_BufSz + 1 ! NNodes - Int_BufSz = Int_BufSz + 1 ! TotalPossibleSuperMembers Int_BufSz = Int_BufSz + 1 ! InpJoints allocated yes/no IF ( ALLOCATED(InData%InpJoints) ) THEN Int_BufSz = Int_BufSz + 2*1 ! InpJoints upper/lower bounds for each dimension @@ -3775,25 +5794,24 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! NElements - Int_BufSz = Int_BufSz + 1 ! Elements allocated yes/no - IF ( ALLOCATED(InData%Elements) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Elements upper/lower bounds for each dimension - DO i1 = LBOUND(InData%Elements,1), UBOUND(InData%Elements,1) - Int_BufSz = Int_BufSz + 3 ! Elements: size of buffers for each call to pack subtype - CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Elements(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Elements + Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no + IF ( ALLOCATED(InData%Members) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Members upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) + Int_BufSz = Int_BufSz + 3 ! Members: size of buffers for each call to pack subtype + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Elements + IF(ALLOCATED(Re_Buf)) THEN ! Members Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Elements + IF(ALLOCATED(Db_Buf)) THEN ! Members Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Elements + IF(ALLOCATED(Int_Buf)) THEN ! Members Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -3853,6 +5871,8 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = Re_BufSz + 1 ! SimplCaMG Re_BufSz = Re_BufSz + 1 ! SimplCp Re_BufSz = Re_BufSz + 1 ! SimplCpMG + Re_BufSz = Re_BufSz + 1 ! SimplAxCd + Re_BufSz = Re_BufSz + 1 ! SimplAxCdMG Re_BufSz = Re_BufSz + 1 ! SimplAxCa Re_BufSz = Re_BufSz + 1 ! SimplAxCaMG Re_BufSz = Re_BufSz + 1 ! SimplAxCp @@ -4104,8 +6124,6 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%TotalPossibleSuperMembers - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%InpJoints) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4188,20 +6206,18 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E ENDIF END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElements - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Elements) ) THEN + IF ( .NOT. ALLOCATED(InData%Members) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elements,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elements,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Elements,1), UBOUND(InData%Elements,1) - CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Elements(i1), ErrStat2, ErrMsg2, OnlySize ) ! Elements + DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, OnlySize ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4329,6 +6345,10 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SimplCpMG Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SimplAxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SimplAxCdMG + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SimplAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SimplAxCaMG @@ -4809,8 +6829,6 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Int_Xferred = Int_Xferred + 1 OutData%NNodes = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%TotalPossibleSuperMembers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpJoints not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4923,22 +6941,20 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%NElements = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elements not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Elements)) DEALLOCATE(OutData%Elements) - ALLOCATE(OutData%Elements(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%Members)) DEALLOCATE(OutData%Members) + ALLOCATE(OutData%Members(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elements.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%Elements,1), UBOUND(OutData%Elements,1) + DO i1 = LBOUND(OutData%Members,1), UBOUND(OutData%Members,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -4972,7 +6988,7 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Elements(i1), ErrStat2, ErrMsg2 ) ! Elements + CALL Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Members(i1), ErrStat2, ErrMsg2 ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -5109,6 +7125,10 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = Re_Xferred + 1 OutData%SimplCpMG = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCd = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCdMG = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%SimplAxCa = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%SimplAxCaMG = ReKiBuf( Re_Xferred ) @@ -5731,10 +7751,7 @@ SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCod ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshCopy( SrcInitOutputData%DistribMesh, DstInitOutputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcInitOutputData%LumpedMesh, DstInitOutputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcInitOutputData%Mesh, DstInitOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcInitOutputData%Morison_Rad)) THEN @@ -5784,8 +7801,7 @@ SUBROUTINE Morison_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshDestroy( InitOutputData%DistribMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( InitOutputData%LumpedMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InitOutputData%Mesh, ErrStat, ErrMsg ) IF (ALLOCATED(InitOutputData%Morison_Rad)) THEN DEALLOCATE(InitOutputData%Morison_Rad) ENDIF @@ -5833,37 +7849,20 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_BufSz = 0 Int_BufSz = 0 ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! DistribMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh + IF(ALLOCATED(Re_Buf)) THEN ! Mesh Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh + IF(ALLOCATED(Db_Buf)) THEN ! Mesh Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Int_Buf)) THEN ! Mesh Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -5909,35 +7908,7 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6080,47 +8051,7 @@ SUBROUTINE Morison_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + CALL MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6746,253 +8677,295 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcMiscData%D_F_D)) THEN - i1_l = LBOUND(SrcMiscData%D_F_D,1) - i1_u = UBOUND(SrcMiscData%D_F_D,1) - i2_l = LBOUND(SrcMiscData%D_F_D,2) - i2_u = UBOUND(SrcMiscData%D_F_D,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_D)) THEN - ALLOCATE(DstMiscData%D_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_D.', ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(SrcMiscData%F_D)) THEN + i1_l = LBOUND(SrcMiscData%F_D,1) + i1_u = UBOUND(SrcMiscData%F_D,1) + i2_l = LBOUND(SrcMiscData%F_D,2) + i2_u = UBOUND(SrcMiscData%F_D,2) + IF (.NOT. ALLOCATED(DstMiscData%F_D)) THEN + ALLOCATE(DstMiscData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%F_D = SrcMiscData%F_D +ENDIF +IF (ALLOCATED(SrcMiscData%F_I)) THEN + i1_l = LBOUND(SrcMiscData%F_I,1) + i1_u = UBOUND(SrcMiscData%F_I,1) + i2_l = LBOUND(SrcMiscData%F_I,2) + i2_u = UBOUND(SrcMiscData%F_I,2) + IF (.NOT. ALLOCATED(DstMiscData%F_I)) THEN + ALLOCATE(DstMiscData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%F_I = SrcMiscData%F_I +ENDIF +IF (ALLOCATED(SrcMiscData%F_A)) THEN + i1_l = LBOUND(SrcMiscData%F_A,1) + i1_u = UBOUND(SrcMiscData%F_A,1) + i2_l = LBOUND(SrcMiscData%F_A,2) + i2_u = UBOUND(SrcMiscData%F_A,2) + IF (.NOT. ALLOCATED(DstMiscData%F_A)) THEN + ALLOCATE(DstMiscData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_A.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_D = SrcMiscData%D_F_D + DstMiscData%F_A = SrcMiscData%F_A ENDIF -IF (ALLOCATED(SrcMiscData%D_F_I)) THEN - i1_l = LBOUND(SrcMiscData%D_F_I,1) - i1_u = UBOUND(SrcMiscData%D_F_I,1) - i2_l = LBOUND(SrcMiscData%D_F_I,2) - i2_u = UBOUND(SrcMiscData%D_F_I,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_I)) THEN - ALLOCATE(DstMiscData%D_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_B)) THEN + i1_l = LBOUND(SrcMiscData%F_B,1) + i1_u = UBOUND(SrcMiscData%F_B,1) + i2_l = LBOUND(SrcMiscData%F_B,2) + i2_u = UBOUND(SrcMiscData%F_B,2) + IF (.NOT. ALLOCATED(DstMiscData%F_B)) THEN + ALLOCATE(DstMiscData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_B.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_I = SrcMiscData%D_F_I + DstMiscData%F_B = SrcMiscData%F_B ENDIF -IF (ALLOCATED(SrcMiscData%D_F_B)) THEN - i1_l = LBOUND(SrcMiscData%D_F_B,1) - i1_u = UBOUND(SrcMiscData%D_F_B,1) - i2_l = LBOUND(SrcMiscData%D_F_B,2) - i2_u = UBOUND(SrcMiscData%D_F_B,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_B)) THEN - ALLOCATE(DstMiscData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_BF)) THEN + i1_l = LBOUND(SrcMiscData%F_BF,1) + i1_u = UBOUND(SrcMiscData%F_BF,1) + i2_l = LBOUND(SrcMiscData%F_BF,2) + i2_u = UBOUND(SrcMiscData%F_BF,2) + IF (.NOT. ALLOCATED(DstMiscData%F_BF)) THEN + ALLOCATE(DstMiscData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_BF.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_B = SrcMiscData%D_F_B + DstMiscData%F_BF = SrcMiscData%F_BF ENDIF -IF (ALLOCATED(SrcMiscData%D_F_AM)) THEN - i1_l = LBOUND(SrcMiscData%D_F_AM,1) - i1_u = UBOUND(SrcMiscData%D_F_AM,1) - i2_l = LBOUND(SrcMiscData%D_F_AM,2) - i2_u = UBOUND(SrcMiscData%D_F_AM,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_AM)) THEN - ALLOCATE(DstMiscData%D_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_If)) THEN + i1_l = LBOUND(SrcMiscData%F_If,1) + i1_u = UBOUND(SrcMiscData%F_If,1) + i2_l = LBOUND(SrcMiscData%F_If,2) + i2_u = UBOUND(SrcMiscData%F_If,2) + IF (.NOT. ALLOCATED(DstMiscData%F_If)) THEN + ALLOCATE(DstMiscData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_If.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_AM = SrcMiscData%D_F_AM + DstMiscData%F_If = SrcMiscData%F_If ENDIF -IF (ALLOCATED(SrcMiscData%D_F_AM_M)) THEN - i1_l = LBOUND(SrcMiscData%D_F_AM_M,1) - i1_u = UBOUND(SrcMiscData%D_F_AM_M,1) - i2_l = LBOUND(SrcMiscData%D_F_AM_M,2) - i2_u = UBOUND(SrcMiscData%D_F_AM_M,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_M)) THEN - ALLOCATE(DstMiscData%D_F_AM_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_WMG)) THEN + i1_l = LBOUND(SrcMiscData%F_WMG,1) + i1_u = UBOUND(SrcMiscData%F_WMG,1) + i2_l = LBOUND(SrcMiscData%F_WMG,2) + i2_u = UBOUND(SrcMiscData%F_WMG,2) + IF (.NOT. ALLOCATED(DstMiscData%F_WMG)) THEN + ALLOCATE(DstMiscData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_M.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_WMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_AM_M = SrcMiscData%D_F_AM_M + DstMiscData%F_WMG = SrcMiscData%F_WMG ENDIF -IF (ALLOCATED(SrcMiscData%D_F_AM_MG)) THEN - i1_l = LBOUND(SrcMiscData%D_F_AM_MG,1) - i1_u = UBOUND(SrcMiscData%D_F_AM_MG,1) - i2_l = LBOUND(SrcMiscData%D_F_AM_MG,2) - i2_u = UBOUND(SrcMiscData%D_F_AM_MG,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_MG)) THEN - ALLOCATE(DstMiscData%D_F_AM_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_IMG)) THEN + i1_l = LBOUND(SrcMiscData%F_IMG,1) + i1_u = UBOUND(SrcMiscData%F_IMG,1) + i2_l = LBOUND(SrcMiscData%F_IMG,2) + i2_u = UBOUND(SrcMiscData%F_IMG,2) + IF (.NOT. ALLOCATED(DstMiscData%F_IMG)) THEN + ALLOCATE(DstMiscData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_MG.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_IMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_AM_MG = SrcMiscData%D_F_AM_MG + DstMiscData%F_IMG = SrcMiscData%F_IMG ENDIF -IF (ALLOCATED(SrcMiscData%D_F_AM_F)) THEN - i1_l = LBOUND(SrcMiscData%D_F_AM_F,1) - i1_u = UBOUND(SrcMiscData%D_F_AM_F,1) - i2_l = LBOUND(SrcMiscData%D_F_AM_F,2) - i2_u = UBOUND(SrcMiscData%D_F_AM_F,2) - IF (.NOT. ALLOCATED(DstMiscData%D_F_AM_F)) THEN - ALLOCATE(DstMiscData%D_F_AM_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%FV)) THEN + i1_l = LBOUND(SrcMiscData%FV,1) + i1_u = UBOUND(SrcMiscData%FV,1) + i2_l = LBOUND(SrcMiscData%FV,2) + i2_u = UBOUND(SrcMiscData%FV,2) + IF (.NOT. ALLOCATED(DstMiscData%FV)) THEN + ALLOCATE(DstMiscData%FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_F_AM_F.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FV.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_F_AM_F = SrcMiscData%D_F_AM_F + DstMiscData%FV = SrcMiscData%FV ENDIF -IF (ALLOCATED(SrcMiscData%D_FV)) THEN - i1_l = LBOUND(SrcMiscData%D_FV,1) - i1_u = UBOUND(SrcMiscData%D_FV,1) - i2_l = LBOUND(SrcMiscData%D_FV,2) - i2_u = UBOUND(SrcMiscData%D_FV,2) - IF (.NOT. ALLOCATED(DstMiscData%D_FV)) THEN - ALLOCATE(DstMiscData%D_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%FA)) THEN + i1_l = LBOUND(SrcMiscData%FA,1) + i1_u = UBOUND(SrcMiscData%FA,1) + i2_l = LBOUND(SrcMiscData%FA,2) + i2_u = UBOUND(SrcMiscData%FA,2) + IF (.NOT. ALLOCATED(DstMiscData%FA)) THEN + ALLOCATE(DstMiscData%FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FV.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FA.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_FV = SrcMiscData%D_FV + DstMiscData%FA = SrcMiscData%FA ENDIF -IF (ALLOCATED(SrcMiscData%D_FA)) THEN - i1_l = LBOUND(SrcMiscData%D_FA,1) - i1_u = UBOUND(SrcMiscData%D_FA,1) - i2_l = LBOUND(SrcMiscData%D_FA,2) - i2_u = UBOUND(SrcMiscData%D_FA,2) - IF (.NOT. ALLOCATED(DstMiscData%D_FA)) THEN - ALLOCATE(DstMiscData%D_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%FDynP)) THEN + i1_l = LBOUND(SrcMiscData%FDynP,1) + i1_u = UBOUND(SrcMiscData%FDynP,1) + IF (.NOT. ALLOCATED(DstMiscData%FDynP)) THEN + ALLOCATE(DstMiscData%FDynP(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FA.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FDynP.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_FA = SrcMiscData%D_FA + DstMiscData%FDynP = SrcMiscData%FDynP ENDIF -IF (ALLOCATED(SrcMiscData%D_FDynP)) THEN - i1_l = LBOUND(SrcMiscData%D_FDynP,1) - i1_u = UBOUND(SrcMiscData%D_FDynP,1) - IF (.NOT. ALLOCATED(DstMiscData%D_FDynP)) THEN - ALLOCATE(DstMiscData%D_FDynP(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_DP)) THEN + i1_l = LBOUND(SrcMiscData%F_DP,1) + i1_u = UBOUND(SrcMiscData%F_DP,1) + i2_l = LBOUND(SrcMiscData%F_DP,2) + i2_u = UBOUND(SrcMiscData%F_DP,2) + IF (.NOT. ALLOCATED(DstMiscData%F_DP)) THEN + ALLOCATE(DstMiscData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%D_FDynP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_DP.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%D_FDynP = SrcMiscData%D_FDynP + DstMiscData%F_DP = SrcMiscData%F_DP ENDIF -IF (ALLOCATED(SrcMiscData%L_F_B)) THEN - i1_l = LBOUND(SrcMiscData%L_F_B,1) - i1_u = UBOUND(SrcMiscData%L_F_B,1) - i2_l = LBOUND(SrcMiscData%L_F_B,2) - i2_u = UBOUND(SrcMiscData%L_F_B,2) - IF (.NOT. ALLOCATED(DstMiscData%L_F_B)) THEN - ALLOCATE(DstMiscData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%vrel)) THEN + i1_l = LBOUND(SrcMiscData%vrel,1) + i1_u = UBOUND(SrcMiscData%vrel,1) + i2_l = LBOUND(SrcMiscData%vrel,2) + i2_u = UBOUND(SrcMiscData%vrel,2) + IF (.NOT. ALLOCATED(DstMiscData%vrel)) THEN + ALLOCATE(DstMiscData%vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%vrel.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_F_B = SrcMiscData%L_F_B + DstMiscData%vrel = SrcMiscData%vrel ENDIF -IF (ALLOCATED(SrcMiscData%L_F_D)) THEN - i1_l = LBOUND(SrcMiscData%L_F_D,1) - i1_u = UBOUND(SrcMiscData%L_F_D,1) - i2_l = LBOUND(SrcMiscData%L_F_D,2) - i2_u = UBOUND(SrcMiscData%L_F_D,2) - IF (.NOT. ALLOCATED(DstMiscData%L_F_D)) THEN - ALLOCATE(DstMiscData%L_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%nodeInWater)) THEN + i1_l = LBOUND(SrcMiscData%nodeInWater,1) + i1_u = UBOUND(SrcMiscData%nodeInWater,1) + IF (.NOT. ALLOCATED(DstMiscData%nodeInWater)) THEN + ALLOCATE(DstMiscData%nodeInWater(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_D.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%nodeInWater.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_F_D = SrcMiscData%L_F_D + DstMiscData%nodeInWater = SrcMiscData%nodeInWater ENDIF -IF (ALLOCATED(SrcMiscData%L_F_I)) THEN - i1_l = LBOUND(SrcMiscData%L_F_I,1) - i1_u = UBOUND(SrcMiscData%L_F_I,1) - i2_l = LBOUND(SrcMiscData%L_F_I,2) - i2_u = UBOUND(SrcMiscData%L_F_I,2) - IF (.NOT. ALLOCATED(DstMiscData%L_F_I)) THEN - ALLOCATE(DstMiscData%L_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_B_End)) THEN + i1_l = LBOUND(SrcMiscData%F_B_End,1) + i1_u = UBOUND(SrcMiscData%F_B_End,1) + i2_l = LBOUND(SrcMiscData%F_B_End,2) + i2_u = UBOUND(SrcMiscData%F_B_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_B_End)) THEN + ALLOCATE(DstMiscData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_B_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_F_I = SrcMiscData%L_F_I + DstMiscData%F_B_End = SrcMiscData%F_B_End ENDIF -IF (ALLOCATED(SrcMiscData%L_F_DP)) THEN - i1_l = LBOUND(SrcMiscData%L_F_DP,1) - i1_u = UBOUND(SrcMiscData%L_F_DP,1) - i2_l = LBOUND(SrcMiscData%L_F_DP,2) - i2_u = UBOUND(SrcMiscData%L_F_DP,2) - IF (.NOT. ALLOCATED(DstMiscData%L_F_DP)) THEN - ALLOCATE(DstMiscData%L_F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_D_End)) THEN + i1_l = LBOUND(SrcMiscData%F_D_End,1) + i1_u = UBOUND(SrcMiscData%F_D_End,1) + i2_l = LBOUND(SrcMiscData%F_D_End,2) + i2_u = UBOUND(SrcMiscData%F_D_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_D_End)) THEN + ALLOCATE(DstMiscData%F_D_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_D_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_F_DP = SrcMiscData%L_F_DP + DstMiscData%F_D_End = SrcMiscData%F_D_End ENDIF -IF (ALLOCATED(SrcMiscData%L_F_AM)) THEN - i1_l = LBOUND(SrcMiscData%L_F_AM,1) - i1_u = UBOUND(SrcMiscData%L_F_AM,1) - i2_l = LBOUND(SrcMiscData%L_F_AM,2) - i2_u = UBOUND(SrcMiscData%L_F_AM,2) - IF (.NOT. ALLOCATED(DstMiscData%L_F_AM)) THEN - ALLOCATE(DstMiscData%L_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_I_End)) THEN + i1_l = LBOUND(SrcMiscData%F_I_End,1) + i1_u = UBOUND(SrcMiscData%F_I_End,1) + i2_l = LBOUND(SrcMiscData%F_I_End,2) + i2_u = UBOUND(SrcMiscData%F_I_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_I_End)) THEN + ALLOCATE(DstMiscData%F_I_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_F_AM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_I_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_F_AM = SrcMiscData%L_F_AM + DstMiscData%F_I_End = SrcMiscData%F_I_End ENDIF -IF (ALLOCATED(SrcMiscData%L_FV)) THEN - i1_l = LBOUND(SrcMiscData%L_FV,1) - i1_u = UBOUND(SrcMiscData%L_FV,1) - i2_l = LBOUND(SrcMiscData%L_FV,2) - i2_u = UBOUND(SrcMiscData%L_FV,2) - IF (.NOT. ALLOCATED(DstMiscData%L_FV)) THEN - ALLOCATE(DstMiscData%L_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_IMG_End)) THEN + i1_l = LBOUND(SrcMiscData%F_IMG_End,1) + i1_u = UBOUND(SrcMiscData%F_IMG_End,1) + i2_l = LBOUND(SrcMiscData%F_IMG_End,2) + i2_u = UBOUND(SrcMiscData%F_IMG_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_IMG_End)) THEN + ALLOCATE(DstMiscData%F_IMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FV.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_IMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_FV = SrcMiscData%L_FV + DstMiscData%F_IMG_End = SrcMiscData%F_IMG_End ENDIF -IF (ALLOCATED(SrcMiscData%L_FA)) THEN - i1_l = LBOUND(SrcMiscData%L_FA,1) - i1_u = UBOUND(SrcMiscData%L_FA,1) - i2_l = LBOUND(SrcMiscData%L_FA,2) - i2_u = UBOUND(SrcMiscData%L_FA,2) - IF (.NOT. ALLOCATED(DstMiscData%L_FA)) THEN - ALLOCATE(DstMiscData%L_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_DP_End)) THEN + i1_l = LBOUND(SrcMiscData%F_DP_End,1) + i1_u = UBOUND(SrcMiscData%F_DP_End,1) + i2_l = LBOUND(SrcMiscData%F_DP_End,2) + i2_u = UBOUND(SrcMiscData%F_DP_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_DP_End)) THEN + ALLOCATE(DstMiscData%F_DP_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FA.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_DP_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_FA = SrcMiscData%L_FA + DstMiscData%F_DP_End = SrcMiscData%F_DP_End ENDIF -IF (ALLOCATED(SrcMiscData%L_FDynP)) THEN - i1_l = LBOUND(SrcMiscData%L_FDynP,1) - i1_u = UBOUND(SrcMiscData%L_FDynP,1) - IF (.NOT. ALLOCATED(DstMiscData%L_FDynP)) THEN - ALLOCATE(DstMiscData%L_FDynP(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_A_End)) THEN + i1_l = LBOUND(SrcMiscData%F_A_End,1) + i1_u = UBOUND(SrcMiscData%F_A_End,1) + i2_l = LBOUND(SrcMiscData%F_A_End,2) + i2_u = UBOUND(SrcMiscData%F_A_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_A_End)) THEN + ALLOCATE(DstMiscData%F_A_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%L_FDynP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_A_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%L_FDynP = SrcMiscData%L_FDynP + DstMiscData%F_A_End = SrcMiscData%F_A_End +ENDIF +IF (ALLOCATED(SrcMiscData%F_BF_End)) THEN + i1_l = LBOUND(SrcMiscData%F_BF_End,1) + i1_u = UBOUND(SrcMiscData%F_BF_End,1) + i2_l = LBOUND(SrcMiscData%F_BF_End,2) + i2_u = UBOUND(SrcMiscData%F_BF_End,2) + IF (.NOT. ALLOCATED(DstMiscData%F_BF_End)) THEN + ALLOCATE(DstMiscData%F_BF_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_BF_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%F_BF_End = SrcMiscData%F_BF_End ENDIF DstMiscData%LastIndWave = SrcMiscData%LastIndWave END SUBROUTINE Morison_CopyMisc @@ -7006,59 +8979,68 @@ SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(MiscData%D_F_D)) THEN - DEALLOCATE(MiscData%D_F_D) +IF (ALLOCATED(MiscData%F_D)) THEN + DEALLOCATE(MiscData%F_D) +ENDIF +IF (ALLOCATED(MiscData%F_I)) THEN + DEALLOCATE(MiscData%F_I) +ENDIF +IF (ALLOCATED(MiscData%F_A)) THEN + DEALLOCATE(MiscData%F_A) +ENDIF +IF (ALLOCATED(MiscData%F_B)) THEN + DEALLOCATE(MiscData%F_B) ENDIF -IF (ALLOCATED(MiscData%D_F_I)) THEN - DEALLOCATE(MiscData%D_F_I) +IF (ALLOCATED(MiscData%F_BF)) THEN + DEALLOCATE(MiscData%F_BF) ENDIF -IF (ALLOCATED(MiscData%D_F_B)) THEN - DEALLOCATE(MiscData%D_F_B) +IF (ALLOCATED(MiscData%F_If)) THEN + DEALLOCATE(MiscData%F_If) ENDIF -IF (ALLOCATED(MiscData%D_F_AM)) THEN - DEALLOCATE(MiscData%D_F_AM) +IF (ALLOCATED(MiscData%F_WMG)) THEN + DEALLOCATE(MiscData%F_WMG) ENDIF -IF (ALLOCATED(MiscData%D_F_AM_M)) THEN - DEALLOCATE(MiscData%D_F_AM_M) +IF (ALLOCATED(MiscData%F_IMG)) THEN + DEALLOCATE(MiscData%F_IMG) ENDIF -IF (ALLOCATED(MiscData%D_F_AM_MG)) THEN - DEALLOCATE(MiscData%D_F_AM_MG) +IF (ALLOCATED(MiscData%FV)) THEN + DEALLOCATE(MiscData%FV) ENDIF -IF (ALLOCATED(MiscData%D_F_AM_F)) THEN - DEALLOCATE(MiscData%D_F_AM_F) +IF (ALLOCATED(MiscData%FA)) THEN + DEALLOCATE(MiscData%FA) ENDIF -IF (ALLOCATED(MiscData%D_FV)) THEN - DEALLOCATE(MiscData%D_FV) +IF (ALLOCATED(MiscData%FDynP)) THEN + DEALLOCATE(MiscData%FDynP) ENDIF -IF (ALLOCATED(MiscData%D_FA)) THEN - DEALLOCATE(MiscData%D_FA) +IF (ALLOCATED(MiscData%F_DP)) THEN + DEALLOCATE(MiscData%F_DP) ENDIF -IF (ALLOCATED(MiscData%D_FDynP)) THEN - DEALLOCATE(MiscData%D_FDynP) +IF (ALLOCATED(MiscData%vrel)) THEN + DEALLOCATE(MiscData%vrel) ENDIF -IF (ALLOCATED(MiscData%L_F_B)) THEN - DEALLOCATE(MiscData%L_F_B) +IF (ALLOCATED(MiscData%nodeInWater)) THEN + DEALLOCATE(MiscData%nodeInWater) ENDIF -IF (ALLOCATED(MiscData%L_F_D)) THEN - DEALLOCATE(MiscData%L_F_D) +IF (ALLOCATED(MiscData%F_B_End)) THEN + DEALLOCATE(MiscData%F_B_End) ENDIF -IF (ALLOCATED(MiscData%L_F_I)) THEN - DEALLOCATE(MiscData%L_F_I) +IF (ALLOCATED(MiscData%F_D_End)) THEN + DEALLOCATE(MiscData%F_D_End) ENDIF -IF (ALLOCATED(MiscData%L_F_DP)) THEN - DEALLOCATE(MiscData%L_F_DP) +IF (ALLOCATED(MiscData%F_I_End)) THEN + DEALLOCATE(MiscData%F_I_End) ENDIF -IF (ALLOCATED(MiscData%L_F_AM)) THEN - DEALLOCATE(MiscData%L_F_AM) +IF (ALLOCATED(MiscData%F_IMG_End)) THEN + DEALLOCATE(MiscData%F_IMG_End) ENDIF -IF (ALLOCATED(MiscData%L_FV)) THEN - DEALLOCATE(MiscData%L_FV) +IF (ALLOCATED(MiscData%F_DP_End)) THEN + DEALLOCATE(MiscData%F_DP_End) ENDIF -IF (ALLOCATED(MiscData%L_FA)) THEN - DEALLOCATE(MiscData%L_FA) +IF (ALLOCATED(MiscData%F_A_End)) THEN + DEALLOCATE(MiscData%F_A_End) ENDIF -IF (ALLOCATED(MiscData%L_FDynP)) THEN - DEALLOCATE(MiscData%L_FDynP) +IF (ALLOCATED(MiscData%F_BF_End)) THEN + DEALLOCATE(MiscData%F_BF_End) ENDIF END SUBROUTINE Morison_DestroyMisc @@ -7097,95 +9079,110 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! D_F_D allocated yes/no - IF ( ALLOCATED(InData%D_F_D) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_D upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_D) ! D_F_D + Int_BufSz = Int_BufSz + 1 ! F_D allocated yes/no + IF ( ALLOCATED(InData%F_D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_D) ! F_D + END IF + Int_BufSz = Int_BufSz + 1 ! F_I allocated yes/no + IF ( ALLOCATED(InData%F_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_I) ! F_I + END IF + Int_BufSz = Int_BufSz + 1 ! F_A allocated yes/no + IF ( ALLOCATED(InData%F_A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_A upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_A) ! F_A + END IF + Int_BufSz = Int_BufSz + 1 ! F_B allocated yes/no + IF ( ALLOCATED(InData%F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_B) ! F_B + END IF + Int_BufSz = Int_BufSz + 1 ! F_BF allocated yes/no + IF ( ALLOCATED(InData%F_BF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_BF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_BF) ! F_BF + END IF + Int_BufSz = Int_BufSz + 1 ! F_If allocated yes/no + IF ( ALLOCATED(InData%F_If) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_If upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_If) ! F_If + END IF + Int_BufSz = Int_BufSz + 1 ! F_WMG allocated yes/no + IF ( ALLOCATED(InData%F_WMG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_WMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_WMG) ! F_WMG + END IF + Int_BufSz = Int_BufSz + 1 ! F_IMG allocated yes/no + IF ( ALLOCATED(InData%F_IMG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_IMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_IMG) ! F_IMG + END IF + Int_BufSz = Int_BufSz + 1 ! FV allocated yes/no + IF ( ALLOCATED(InData%FV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FV) ! FV + END IF + Int_BufSz = Int_BufSz + 1 ! FA allocated yes/no + IF ( ALLOCATED(InData%FA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FA) ! FA + END IF + Int_BufSz = Int_BufSz + 1 ! FDynP allocated yes/no + IF ( ALLOCATED(InData%FDynP) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FDynP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FDynP) ! FDynP + END IF + Int_BufSz = Int_BufSz + 1 ! F_DP allocated yes/no + IF ( ALLOCATED(InData%F_DP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_DP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP END IF - Int_BufSz = Int_BufSz + 1 ! D_F_I allocated yes/no - IF ( ALLOCATED(InData%D_F_I) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_I upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_I) ! D_F_I + Int_BufSz = Int_BufSz + 1 ! vrel allocated yes/no + IF ( ALLOCATED(InData%vrel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! vrel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%vrel) ! vrel END IF - Int_BufSz = Int_BufSz + 1 ! D_F_B allocated yes/no - IF ( ALLOCATED(InData%D_F_B) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_B) ! D_F_B + Int_BufSz = Int_BufSz + 1 ! nodeInWater allocated yes/no + IF ( ALLOCATED(InData%nodeInWater) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! nodeInWater upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater END IF - Int_BufSz = Int_BufSz + 1 ! D_F_AM allocated yes/no - IF ( ALLOCATED(InData%D_F_AM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_AM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM) ! D_F_AM - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_AM_M allocated yes/no - IF ( ALLOCATED(InData%D_F_AM_M) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_M) ! D_F_AM_M - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_AM_MG allocated yes/no - IF ( ALLOCATED(InData%D_F_AM_MG) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_MG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_MG) ! D_F_AM_MG - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_AM_F allocated yes/no - IF ( ALLOCATED(InData%D_F_AM_F) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_AM_F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_AM_F) ! D_F_AM_F - END IF - Int_BufSz = Int_BufSz + 1 ! D_FV allocated yes/no - IF ( ALLOCATED(InData%D_FV) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_FV upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_FV) ! D_FV - END IF - Int_BufSz = Int_BufSz + 1 ! D_FA allocated yes/no - IF ( ALLOCATED(InData%D_FA) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_FA upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_FA) ! D_FA - END IF - Int_BufSz = Int_BufSz + 1 ! D_FDynP allocated yes/no - IF ( ALLOCATED(InData%D_FDynP) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! D_FDynP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_FDynP) ! D_FDynP - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_B allocated yes/no - IF ( ALLOCATED(InData%L_F_B) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_B) ! L_F_B - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_D allocated yes/no - IF ( ALLOCATED(InData%L_F_D) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_D upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_D) ! L_F_D - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_I allocated yes/no - IF ( ALLOCATED(InData%L_F_I) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_I upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_I) ! L_F_I - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_DP allocated yes/no - IF ( ALLOCATED(InData%L_F_DP) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_DP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_DP) ! L_F_DP - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_AM allocated yes/no - IF ( ALLOCATED(InData%L_F_AM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_AM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_AM) ! L_F_AM - END IF - Int_BufSz = Int_BufSz + 1 ! L_FV allocated yes/no - IF ( ALLOCATED(InData%L_FV) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_FV upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_FV) ! L_FV - END IF - Int_BufSz = Int_BufSz + 1 ! L_FA allocated yes/no - IF ( ALLOCATED(InData%L_FA) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_FA upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_FA) ! L_FA - END IF - Int_BufSz = Int_BufSz + 1 ! L_FDynP allocated yes/no - IF ( ALLOCATED(InData%L_FDynP) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! L_FDynP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_FDynP) ! L_FDynP + Int_BufSz = Int_BufSz + 1 ! F_B_End allocated yes/no + IF ( ALLOCATED(InData%F_B_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_B_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_B_End) ! F_B_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_D_End allocated yes/no + IF ( ALLOCATED(InData%F_D_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_D_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_D_End) ! F_D_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_I_End allocated yes/no + IF ( ALLOCATED(InData%F_I_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_I_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_I_End) ! F_I_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_IMG_End allocated yes/no + IF ( ALLOCATED(InData%F_IMG_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_IMG_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_IMG_End) ! F_IMG_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_DP_End allocated yes/no + IF ( ALLOCATED(InData%F_DP_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_DP_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_DP_End) ! F_DP_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_A_End allocated yes/no + IF ( ALLOCATED(InData%F_A_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_A_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_A_End) ! F_A_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_BF_End allocated yes/no + IF ( ALLOCATED(InData%F_BF_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_BF_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_BF_End) ! F_BF_End END IF Int_BufSz = Int_BufSz + 1 ! LastIndWave IF ( Re_BufSz .GT. 0 ) THEN @@ -7215,287 +9212,335 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%D_F_D) ) THEN + IF ( .NOT. ALLOCATED(InData%F_D) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_D,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_D,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_D,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_D,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_D))-1 ) = PACK(InData%D_F_D,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_D) + IF (SIZE(InData%F_D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_D))-1 ) = PACK(InData%F_D,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_D) END IF - IF ( .NOT. ALLOCATED(InData%D_F_I) ) THEN + IF ( .NOT. ALLOCATED(InData%F_I) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_I)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_I))-1 ) = PACK(InData%D_F_I,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_I) + IF (SIZE(InData%F_I)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_I))-1 ) = PACK(InData%F_I,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_I) END IF - IF ( .NOT. ALLOCATED(InData%D_F_B) ) THEN + IF ( .NOT. ALLOCATED(InData%F_A) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_B)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_B))-1 ) = PACK(InData%D_F_B,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_B) + IF (SIZE(InData%F_A)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_A))-1 ) = PACK(InData%F_A,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_A) + END IF + IF ( .NOT. ALLOCATED(InData%F_B) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%F_B)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_B))-1 ) = PACK(InData%F_B,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_B) END IF - IF ( .NOT. ALLOCATED(InData%D_F_AM) ) THEN + IF ( .NOT. ALLOCATED(InData%F_BF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_AM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_AM))-1 ) = PACK(InData%D_F_AM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_AM) + IF (SIZE(InData%F_BF)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_BF))-1 ) = PACK(InData%F_BF,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_BF) END IF - IF ( .NOT. ALLOCATED(InData%D_F_AM_M) ) THEN + IF ( .NOT. ALLOCATED(InData%F_If) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_M,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_M,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_AM_M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_AM_M))-1 ) = PACK(InData%D_F_AM_M,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_AM_M) + IF (SIZE(InData%F_If)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_If))-1 ) = PACK(InData%F_If,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_If) END IF - IF ( .NOT. ALLOCATED(InData%D_F_AM_MG) ) THEN + IF ( .NOT. ALLOCATED(InData%F_WMG) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_MG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_MG,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_MG,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_MG,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_AM_MG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_AM_MG))-1 ) = PACK(InData%D_F_AM_MG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_AM_MG) + IF (SIZE(InData%F_WMG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_WMG))-1 ) = PACK(InData%F_WMG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_WMG) END IF - IF ( .NOT. ALLOCATED(InData%D_F_AM_F) ) THEN + IF ( .NOT. ALLOCATED(InData%F_IMG) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_F,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_AM_F,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_AM_F,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_AM_F)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_AM_F))-1 ) = PACK(InData%D_F_AM_F,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_AM_F) + IF (SIZE(InData%F_IMG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_IMG))-1 ) = PACK(InData%F_IMG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_IMG) END IF - IF ( .NOT. ALLOCATED(InData%D_FV) ) THEN + IF ( .NOT. ALLOCATED(InData%FV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FV,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FV,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FV,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FV,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FV,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FV,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_FV)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_FV))-1 ) = PACK(InData%D_FV,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_FV) + IF (SIZE(InData%FV)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FV))-1 ) = PACK(InData%FV,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FV) END IF - IF ( .NOT. ALLOCATED(InData%D_FA) ) THEN + IF ( .NOT. ALLOCATED(InData%FA) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FA,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FA,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FA,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FA,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FA,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FA,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FA)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FA))-1 ) = PACK(InData%FA,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FA) + END IF + IF ( .NOT. ALLOCATED(InData%FDynP) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FDynP,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_FA)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_FA))-1 ) = PACK(InData%D_FA,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_FA) + IF (SIZE(InData%FDynP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FDynP))-1 ) = PACK(InData%FDynP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FDynP) END IF - IF ( .NOT. ALLOCATED(InData%D_FDynP) ) THEN + IF ( .NOT. ALLOCATED(InData%F_DP) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_FDynP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_FDynP,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_FDynP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_FDynP))-1 ) = PACK(InData%D_FDynP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_FDynP) + IF (SIZE(InData%F_DP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP))-1 ) = PACK(InData%F_DP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_DP) END IF - IF ( .NOT. ALLOCATED(InData%L_F_B) ) THEN + IF ( .NOT. ALLOCATED(InData%vrel) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%vrel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vrel,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%vrel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vrel,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%vrel)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%vrel))-1 ) = PACK(InData%vrel,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%vrel) + END IF + IF ( .NOT. ALLOCATED(InData%nodeInWater) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_B)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_B))-1 ) = PACK(InData%L_F_B,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_B) + IF (SIZE(InData%nodeInWater)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%nodeInWater))-1 ) = PACK(InData%nodeInWater,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%nodeInWater) END IF - IF ( .NOT. ALLOCATED(InData%L_F_D) ) THEN + IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_D,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_D,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_D,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_D,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_D))-1 ) = PACK(InData%L_F_D,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_D) + IF (SIZE(InData%F_B_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_B_End))-1 ) = PACK(InData%F_B_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_B_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_I) ) THEN + IF ( .NOT. ALLOCATED(InData%F_D_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_I)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_I))-1 ) = PACK(InData%L_F_I,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_I) + IF (SIZE(InData%F_D_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_D_End))-1 ) = PACK(InData%F_D_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_D_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_DP) ) THEN + IF ( .NOT. ALLOCATED(InData%F_I_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_DP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_DP))-1 ) = PACK(InData%L_F_DP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_DP) + IF (SIZE(InData%F_I_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_I_End))-1 ) = PACK(InData%F_I_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_I_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_AM) ) THEN + IF ( .NOT. ALLOCATED(InData%F_IMG_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_AM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_AM,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_AM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_AM,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_AM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_AM))-1 ) = PACK(InData%L_F_AM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_AM) + IF (SIZE(InData%F_IMG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_IMG_End))-1 ) = PACK(InData%F_IMG_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_IMG_End) END IF - IF ( .NOT. ALLOCATED(InData%L_FV) ) THEN + IF ( .NOT. ALLOCATED(InData%F_DP_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FV,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FV,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FV,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FV,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_FV)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_FV))-1 ) = PACK(InData%L_FV,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_FV) + IF (SIZE(InData%F_DP_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP_End))-1 ) = PACK(InData%F_DP_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_DP_End) END IF - IF ( .NOT. ALLOCATED(InData%L_FA) ) THEN + IF ( .NOT. ALLOCATED(InData%F_A_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FA,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FA,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FA,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FA,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_FA)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_FA))-1 ) = PACK(InData%L_FA,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_FA) + IF (SIZE(InData%F_A_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_A_End))-1 ) = PACK(InData%F_A_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_A_End) END IF - IF ( .NOT. ALLOCATED(InData%L_FDynP) ) THEN + IF ( .NOT. ALLOCATED(InData%F_BF_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_FDynP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_FDynP,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_FDynP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_FDynP))-1 ) = PACK(InData%L_FDynP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_FDynP) + IF (SIZE(InData%F_BF_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_BF_End))-1 ) = PACK(InData%F_BF_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_BF_End) END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%LastIndWave Int_Xferred = Int_Xferred + 1 @@ -7535,7 +9580,7 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_D not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_D not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7545,10 +9590,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_D)) DEALLOCATE(OutData%D_F_D) - ALLOCATE(OutData%D_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_D)) DEALLOCATE(OutData%F_D) + ALLOCATE(OutData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_D.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7557,11 +9602,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_D)>0) OutData%D_F_D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_D))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_D) + IF (SIZE(OutData%F_D)>0) OutData%F_D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_D))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_D) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_I not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7571,10 +9616,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_I)) DEALLOCATE(OutData%D_F_I) - ALLOCATE(OutData%D_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_I)) DEALLOCATE(OutData%F_I) + ALLOCATE(OutData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7583,11 +9628,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_I)>0) OutData%D_F_I = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_I))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_I) + IF (SIZE(OutData%F_I)>0) OutData%F_I = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_I))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_I) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_B not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_A not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7597,10 +9642,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_B)) DEALLOCATE(OutData%D_F_B) - ALLOCATE(OutData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_A)) DEALLOCATE(OutData%F_A) + ALLOCATE(OutData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7609,11 +9654,37 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_B)>0) OutData%D_F_B = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_B))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_B) + IF (SIZE(OutData%F_A)>0) OutData%F_A = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_A))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_A) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_B)) DEALLOCATE(OutData%F_B) + ALLOCATE(OutData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%F_B)>0) OutData%F_B = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_B))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_B) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_BF not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7623,10 +9694,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_AM)) DEALLOCATE(OutData%D_F_AM) - ALLOCATE(OutData%D_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_BF)) DEALLOCATE(OutData%F_BF) + ALLOCATE(OutData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7635,11 +9706,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_AM)>0) OutData%D_F_AM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_AM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_AM) + IF (SIZE(OutData%F_BF)>0) OutData%F_BF = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_BF))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_BF) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_M not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_If not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7649,10 +9720,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_AM_M)) DEALLOCATE(OutData%D_F_AM_M) - ALLOCATE(OutData%D_F_AM_M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_If)) DEALLOCATE(OutData%F_If) + ALLOCATE(OutData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_M.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_If.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7661,11 +9732,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_AM_M)>0) OutData%D_F_AM_M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_AM_M))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_AM_M) + IF (SIZE(OutData%F_If)>0) OutData%F_If = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_If))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_If) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_MG not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7675,10 +9746,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_AM_MG)) DEALLOCATE(OutData%D_F_AM_MG) - ALLOCATE(OutData%D_F_AM_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_WMG)) DEALLOCATE(OutData%F_WMG) + ALLOCATE(OutData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_MG.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7687,11 +9758,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_AM_MG)>0) OutData%D_F_AM_MG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_AM_MG))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_AM_MG) + IF (SIZE(OutData%F_WMG)>0) OutData%F_WMG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_WMG))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_WMG) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_AM_F not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_IMG not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7701,10 +9772,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_AM_F)) DEALLOCATE(OutData%D_F_AM_F) - ALLOCATE(OutData%D_F_AM_F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_IMG)) DEALLOCATE(OutData%F_IMG) + ALLOCATE(OutData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_AM_F.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7713,11 +9784,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_F_AM_F)>0) OutData%D_F_AM_F = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_AM_F))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_AM_F) + IF (SIZE(OutData%F_IMG)>0) OutData%F_IMG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_IMG))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_IMG) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FV not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FV not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7727,10 +9798,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_FV)) DEALLOCATE(OutData%D_FV) - ALLOCATE(OutData%D_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%FV)) DEALLOCATE(OutData%FV) + ALLOCATE(OutData%FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FV.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FV.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7739,11 +9810,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_FV)>0) OutData%D_FV = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_FV))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_FV) + IF (SIZE(OutData%FV)>0) OutData%FV = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FV))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FV) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FA not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FA not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7753,10 +9824,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_FA)) DEALLOCATE(OutData%D_FA) - ALLOCATE(OutData%D_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%FA)) DEALLOCATE(OutData%FA) + ALLOCATE(OutData%FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FA.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FA.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7765,21 +9836,21 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%D_FA)>0) OutData%D_FA = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_FA))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_FA) + IF (SIZE(OutData%FA)>0) OutData%FA = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FA))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FA) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_FDynP not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FDynP not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_FDynP)) DEALLOCATE(OutData%D_FDynP) - ALLOCATE(OutData%D_FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%FDynP)) DEALLOCATE(OutData%FDynP) + ALLOCATE(OutData%FDynP(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_FDynP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FDynP.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -7788,11 +9859,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%D_FDynP)>0) OutData%D_FDynP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_FDynP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_FDynP) + IF (SIZE(OutData%FDynP)>0) OutData%FDynP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FDynP))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FDynP) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_B not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7802,10 +9873,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_B)) DEALLOCATE(OutData%L_F_B) - ALLOCATE(OutData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_DP)) DEALLOCATE(OutData%F_DP) + ALLOCATE(OutData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7814,11 +9885,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_B)>0) OutData%L_F_B = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_B))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_B) + IF (SIZE(OutData%F_DP)>0) OutData%F_DP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_DP) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_D not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! vrel not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7828,10 +9899,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_D)) DEALLOCATE(OutData%L_F_D) - ALLOCATE(OutData%L_F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%vrel)) DEALLOCATE(OutData%vrel) + ALLOCATE(OutData%vrel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_D.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%vrel.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7840,11 +9911,34 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_D)>0) OutData%L_F_D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_D))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_D) + IF (SIZE(OutData%vrel)>0) OutData%vrel = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%vrel))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%vrel) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_I not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! nodeInWater not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%nodeInWater)) DEALLOCATE(OutData%nodeInWater) + ALLOCATE(OutData%nodeInWater(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%nodeInWater.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%nodeInWater)>0) OutData%nodeInWater = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%nodeInWater))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%nodeInWater) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7854,10 +9948,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_I)) DEALLOCATE(OutData%L_F_I) - ALLOCATE(OutData%L_F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_B_End)) DEALLOCATE(OutData%F_B_End) + ALLOCATE(OutData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7866,11 +9960,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_I)>0) OutData%L_F_I = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_I))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_I) + IF (SIZE(OutData%F_B_End)>0) OutData%F_B_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_B_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_B_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_DP not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_D_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7880,10 +9974,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_DP)) DEALLOCATE(OutData%L_F_DP) - ALLOCATE(OutData%L_F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_D_End)) DEALLOCATE(OutData%F_D_End) + ALLOCATE(OutData%F_D_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7892,11 +9986,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_DP)>0) OutData%L_F_DP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_DP))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_DP) + IF (SIZE(OutData%F_D_End)>0) OutData%F_D_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_D_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_D_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_AM not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7906,10 +10000,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_AM)) DEALLOCATE(OutData%L_F_AM) - ALLOCATE(OutData%L_F_AM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_I_End)) DEALLOCATE(OutData%F_I_End) + ALLOCATE(OutData%F_I_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_AM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7918,11 +10012,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_AM)>0) OutData%L_F_AM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_AM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_AM) + IF (SIZE(OutData%F_I_End)>0) OutData%F_I_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_I_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_I_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FV not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_IMG_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7932,10 +10026,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_FV)) DEALLOCATE(OutData%L_FV) - ALLOCATE(OutData%L_FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_IMG_End)) DEALLOCATE(OutData%F_IMG_End) + ALLOCATE(OutData%F_IMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FV.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7944,11 +10038,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_FV)>0) OutData%L_FV = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_FV))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_FV) + IF (SIZE(OutData%F_IMG_End)>0) OutData%F_IMG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_IMG_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_IMG_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FA not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -7958,10 +10052,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_FA)) DEALLOCATE(OutData%L_FA) - ALLOCATE(OutData%L_FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_DP_End)) DEALLOCATE(OutData%F_DP_End) + ALLOCATE(OutData%F_DP_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FA.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -7970,32 +10064,61 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_FA)>0) OutData%L_FA = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_FA))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_FA) + IF (SIZE(OutData%F_DP_End)>0) OutData%F_DP_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_DP_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_FDynP not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_A_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_FDynP)) DEALLOCATE(OutData%L_FDynP) - ALLOCATE(OutData%L_FDynP(i1_l:i1_u),STAT=ErrStat2) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_A_End)) DEALLOCATE(OutData%F_A_End) + ALLOCATE(OutData%F_A_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_FDynP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) RETURN END IF - mask1 = .TRUE. - IF (SIZE(OutData%L_FDynP)>0) OutData%L_FDynP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_FDynP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_FDynP) - DEALLOCATE(mask1) + mask2 = .TRUE. + IF (SIZE(OutData%F_A_End)>0) OutData%F_A_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_A_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_A_End) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_BF_End not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_BF_End)) DEALLOCATE(OutData%F_BF_End) + ALLOCATE(OutData%F_BF_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%F_BF_End)>0) OutData%F_BF_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_BF_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_BF_End) + DEALLOCATE(mask2) END IF OutData%LastIndWave = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -8019,23 +10142,43 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err ErrStat = ErrID_None ErrMsg = "" DstParamData%DT = SrcParamData%DT + DstParamData%Gravity = SrcParamData%Gravity DstParamData%WtrDens = SrcParamData%WtrDens - DstParamData%NNodes = SrcParamData%NNodes -IF (ALLOCATED(SrcParamData%Nodes)) THEN - i1_l = LBOUND(SrcParamData%Nodes,1) - i1_u = UBOUND(SrcParamData%Nodes,1) - IF (.NOT. ALLOCATED(DstParamData%Nodes)) THEN - ALLOCATE(DstParamData%Nodes(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes.', ErrStat, ErrMsg,RoutineName) + DstParamData%WtrDpth = SrcParamData%WtrDpth + DstParamData%NMembers = SrcParamData%NMembers +IF (ALLOCATED(SrcParamData%Members)) THEN + i1_l = LBOUND(SrcParamData%Members,1) + i1_u = UBOUND(SrcParamData%Members,1) + IF (.NOT. ALLOCATED(DstParamData%Members)) THEN + ALLOCATE(DstParamData%Members(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Members.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DO i1 = LBOUND(SrcParamData%Nodes,1), UBOUND(SrcParamData%Nodes,1) - CALL Morison_Copynodetype( SrcParamData%Nodes(i1), DstParamData%Nodes(i1), CtrlCode, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(SrcParamData%Members,1), UBOUND(SrcParamData%Members,1) + CALL Morison_Copymembertype( SrcParamData%Members(i1), DstParamData%Members(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO +ENDIF + DstParamData%NNodes = SrcParamData%NNodes + DstParamData%NJoints = SrcParamData%NJoints +IF (ALLOCATED(SrcParamData%I_MG_End)) THEN + i1_l = LBOUND(SrcParamData%I_MG_End,1) + i1_u = UBOUND(SrcParamData%I_MG_End,1) + i2_l = LBOUND(SrcParamData%I_MG_End,2) + i2_u = UBOUND(SrcParamData%I_MG_End,2) + i3_l = LBOUND(SrcParamData%I_MG_End,3) + i3_u = UBOUND(SrcParamData%I_MG_End,3) + IF (.NOT. ALLOCATED(DstParamData%I_MG_End)) THEN + ALLOCATE(DstParamData%I_MG_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%I_MG_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%I_MG_End = SrcParamData%I_MG_End ENDIF IF (ALLOCATED(SrcParamData%D_F_I)) THEN i1_l = LBOUND(SrcParamData%D_F_I,1) @@ -8081,107 +10224,149 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF DstParamData%D_dragConst = SrcParamData%D_dragConst ENDIF -IF (ALLOCATED(SrcParamData%L_An)) THEN - i1_l = LBOUND(SrcParamData%L_An,1) - i1_u = UBOUND(SrcParamData%L_An,1) - i2_l = LBOUND(SrcParamData%L_An,2) - i2_u = UBOUND(SrcParamData%L_An,2) - IF (.NOT. ALLOCATED(DstParamData%L_An)) THEN - ALLOCATE(DstParamData%L_An(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%An_End)) THEN + i1_l = LBOUND(SrcParamData%An_End,1) + i1_u = UBOUND(SrcParamData%An_End,1) + i2_l = LBOUND(SrcParamData%An_End,2) + i2_u = UBOUND(SrcParamData%An_End,2) + IF (.NOT. ALLOCATED(DstParamData%An_End)) THEN + ALLOCATE(DstParamData%An_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%An_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%An_End = SrcParamData%An_End +ENDIF +IF (ALLOCATED(SrcParamData%F_B_End)) THEN + i1_l = LBOUND(SrcParamData%F_B_End,1) + i1_u = UBOUND(SrcParamData%F_B_End,1) + i2_l = LBOUND(SrcParamData%F_B_End,2) + i2_u = UBOUND(SrcParamData%F_B_End,2) + IF (.NOT. ALLOCATED(DstParamData%F_B_End)) THEN + ALLOCATE(DstParamData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_B_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%F_B_End = SrcParamData%F_B_End +ENDIF +IF (ALLOCATED(SrcParamData%F_I_End)) THEN + i1_l = LBOUND(SrcParamData%F_I_End,1) + i1_u = UBOUND(SrcParamData%F_I_End,1) + i2_l = LBOUND(SrcParamData%F_I_End,2) + i2_u = UBOUND(SrcParamData%F_I_End,2) + i3_l = LBOUND(SrcParamData%F_I_End,3) + i3_u = UBOUND(SrcParamData%F_I_End,3) + IF (.NOT. ALLOCATED(DstParamData%F_I_End)) THEN + ALLOCATE(DstParamData%F_I_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_I_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%F_I_End = SrcParamData%F_I_End +ENDIF +IF (ALLOCATED(SrcParamData%F_DP_End)) THEN + i1_l = LBOUND(SrcParamData%F_DP_End,1) + i1_u = UBOUND(SrcParamData%F_DP_End,1) + i2_l = LBOUND(SrcParamData%F_DP_End,2) + i2_u = UBOUND(SrcParamData%F_DP_End,2) + i3_l = LBOUND(SrcParamData%F_DP_End,3) + i3_u = UBOUND(SrcParamData%F_DP_End,3) + IF (.NOT. ALLOCATED(DstParamData%F_DP_End)) THEN + ALLOCATE(DstParamData%F_DP_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_An.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_DP_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_An = SrcParamData%L_An + DstParamData%F_DP_End = SrcParamData%F_DP_End ENDIF -IF (ALLOCATED(SrcParamData%L_F_B)) THEN - i1_l = LBOUND(SrcParamData%L_F_B,1) - i1_u = UBOUND(SrcParamData%L_F_B,1) - i2_l = LBOUND(SrcParamData%L_F_B,2) - i2_u = UBOUND(SrcParamData%L_F_B,2) - IF (.NOT. ALLOCATED(DstParamData%L_F_B)) THEN - ALLOCATE(DstParamData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%AM_M_End)) THEN + i1_l = LBOUND(SrcParamData%AM_M_End,1) + i1_u = UBOUND(SrcParamData%AM_M_End,1) + i2_l = LBOUND(SrcParamData%AM_M_End,2) + i2_u = UBOUND(SrcParamData%AM_M_End,2) + i3_l = LBOUND(SrcParamData%AM_M_End,3) + i3_u = UBOUND(SrcParamData%AM_M_End,3) + IF (.NOT. ALLOCATED(DstParamData%AM_M_End)) THEN + ALLOCATE(DstParamData%AM_M_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM_M_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_F_B = SrcParamData%L_F_B + DstParamData%AM_M_End = SrcParamData%AM_M_End ENDIF -IF (ALLOCATED(SrcParamData%L_F_I)) THEN - i1_l = LBOUND(SrcParamData%L_F_I,1) - i1_u = UBOUND(SrcParamData%L_F_I,1) - i2_l = LBOUND(SrcParamData%L_F_I,2) - i2_u = UBOUND(SrcParamData%L_F_I,2) - i3_l = LBOUND(SrcParamData%L_F_I,3) - i3_u = UBOUND(SrcParamData%L_F_I,3) - IF (.NOT. ALLOCATED(DstParamData%L_F_I)) THEN - ALLOCATE(DstParamData%L_F_I(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%DragConst_End)) THEN + i1_l = LBOUND(SrcParamData%DragConst_End,1) + i1_u = UBOUND(SrcParamData%DragConst_End,1) + IF (.NOT. ALLOCATED(DstParamData%DragConst_End)) THEN + ALLOCATE(DstParamData%DragConst_End(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DragConst_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_F_I = SrcParamData%L_F_I + DstParamData%DragConst_End = SrcParamData%DragConst_End ENDIF -IF (ALLOCATED(SrcParamData%L_F_DP)) THEN - i1_l = LBOUND(SrcParamData%L_F_DP,1) - i1_u = UBOUND(SrcParamData%L_F_DP,1) - i2_l = LBOUND(SrcParamData%L_F_DP,2) - i2_u = UBOUND(SrcParamData%L_F_DP,2) - i3_l = LBOUND(SrcParamData%L_F_DP,3) - i3_u = UBOUND(SrcParamData%L_F_DP,3) - IF (.NOT. ALLOCATED(DstParamData%L_F_DP)) THEN - ALLOCATE(DstParamData%L_F_DP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%F_WMG_End)) THEN + i1_l = LBOUND(SrcParamData%F_WMG_End,1) + i1_u = UBOUND(SrcParamData%F_WMG_End,1) + i2_l = LBOUND(SrcParamData%F_WMG_End,2) + i2_u = UBOUND(SrcParamData%F_WMG_End,2) + IF (.NOT. ALLOCATED(DstParamData%F_WMG_End)) THEN + ALLOCATE(DstParamData%F_WMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_WMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_F_DP = SrcParamData%L_F_DP + DstParamData%F_WMG_End = SrcParamData%F_WMG_End ENDIF -IF (ALLOCATED(SrcParamData%L_F_BF)) THEN - i1_l = LBOUND(SrcParamData%L_F_BF,1) - i1_u = UBOUND(SrcParamData%L_F_BF,1) - i2_l = LBOUND(SrcParamData%L_F_BF,2) - i2_u = UBOUND(SrcParamData%L_F_BF,2) - IF (.NOT. ALLOCATED(DstParamData%L_F_BF)) THEN - ALLOCATE(DstParamData%L_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%DP_Const_End)) THEN + i1_l = LBOUND(SrcParamData%DP_Const_End,1) + i1_u = UBOUND(SrcParamData%DP_Const_End,1) + i2_l = LBOUND(SrcParamData%DP_Const_End,2) + i2_u = UBOUND(SrcParamData%DP_Const_End,2) + IF (.NOT. ALLOCATED(DstParamData%DP_Const_End)) THEN + ALLOCATE(DstParamData%DP_Const_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_F_BF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DP_Const_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_F_BF = SrcParamData%L_F_BF + DstParamData%DP_Const_End = SrcParamData%DP_Const_End ENDIF -IF (ALLOCATED(SrcParamData%L_AM_M)) THEN - i1_l = LBOUND(SrcParamData%L_AM_M,1) - i1_u = UBOUND(SrcParamData%L_AM_M,1) - i2_l = LBOUND(SrcParamData%L_AM_M,2) - i2_u = UBOUND(SrcParamData%L_AM_M,2) - i3_l = LBOUND(SrcParamData%L_AM_M,3) - i3_u = UBOUND(SrcParamData%L_AM_M,3) - IF (.NOT. ALLOCATED(DstParamData%L_AM_M)) THEN - ALLOCATE(DstParamData%L_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%Mass_MG_End)) THEN + i1_l = LBOUND(SrcParamData%Mass_MG_End,1) + i1_u = UBOUND(SrcParamData%Mass_MG_End,1) + IF (.NOT. ALLOCATED(DstParamData%Mass_MG_End)) THEN + ALLOCATE(DstParamData%Mass_MG_End(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_AM_M.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Mass_MG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_AM_M = SrcParamData%L_AM_M + DstParamData%Mass_MG_End = SrcParamData%Mass_MG_End ENDIF -IF (ALLOCATED(SrcParamData%L_dragConst)) THEN - i1_l = LBOUND(SrcParamData%L_dragConst,1) - i1_u = UBOUND(SrcParamData%L_dragConst,1) - IF (.NOT. ALLOCATED(DstParamData%L_dragConst)) THEN - ALLOCATE(DstParamData%L_dragConst(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%AM_End)) THEN + i1_l = LBOUND(SrcParamData%AM_End,1) + i1_u = UBOUND(SrcParamData%AM_End,1) + i2_l = LBOUND(SrcParamData%AM_End,2) + i2_u = UBOUND(SrcParamData%AM_End,2) + i3_l = LBOUND(SrcParamData%AM_End,3) + i3_u = UBOUND(SrcParamData%AM_End,3) + IF (.NOT. ALLOCATED(DstParamData%AM_End)) THEN + ALLOCATE(DstParamData%AM_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%L_dragConst.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%L_dragConst = SrcParamData%L_dragConst + DstParamData%AM_End = SrcParamData%AM_End ENDIF DstParamData%NDistribMarkers = SrcParamData%NDistribMarkers IF (ALLOCATED(SrcParamData%distribToNodeIndx)) THEN @@ -8458,11 +10643,14 @@ SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(ParamData%Nodes)) THEN -DO i1 = LBOUND(ParamData%Nodes,1), UBOUND(ParamData%Nodes,1) - CALL Morison_Destroynodetype( ParamData%Nodes(i1), ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%Members)) THEN +DO i1 = LBOUND(ParamData%Members,1), UBOUND(ParamData%Members,1) + CALL Morison_Destroymembertype( ParamData%Members(i1), ErrStat, ErrMsg ) ENDDO - DEALLOCATE(ParamData%Nodes) + DEALLOCATE(ParamData%Members) +ENDIF +IF (ALLOCATED(ParamData%I_MG_End)) THEN + DEALLOCATE(ParamData%I_MG_End) ENDIF IF (ALLOCATED(ParamData%D_F_I)) THEN DEALLOCATE(ParamData%D_F_I) @@ -8473,26 +10661,35 @@ SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D_dragConst)) THEN DEALLOCATE(ParamData%D_dragConst) ENDIF -IF (ALLOCATED(ParamData%L_An)) THEN - DEALLOCATE(ParamData%L_An) +IF (ALLOCATED(ParamData%An_End)) THEN + DEALLOCATE(ParamData%An_End) ENDIF -IF (ALLOCATED(ParamData%L_F_B)) THEN - DEALLOCATE(ParamData%L_F_B) +IF (ALLOCATED(ParamData%F_B_End)) THEN + DEALLOCATE(ParamData%F_B_End) ENDIF -IF (ALLOCATED(ParamData%L_F_I)) THEN - DEALLOCATE(ParamData%L_F_I) +IF (ALLOCATED(ParamData%F_I_End)) THEN + DEALLOCATE(ParamData%F_I_End) ENDIF -IF (ALLOCATED(ParamData%L_F_DP)) THEN - DEALLOCATE(ParamData%L_F_DP) +IF (ALLOCATED(ParamData%F_DP_End)) THEN + DEALLOCATE(ParamData%F_DP_End) ENDIF -IF (ALLOCATED(ParamData%L_F_BF)) THEN - DEALLOCATE(ParamData%L_F_BF) +IF (ALLOCATED(ParamData%AM_M_End)) THEN + DEALLOCATE(ParamData%AM_M_End) ENDIF -IF (ALLOCATED(ParamData%L_AM_M)) THEN - DEALLOCATE(ParamData%L_AM_M) +IF (ALLOCATED(ParamData%DragConst_End)) THEN + DEALLOCATE(ParamData%DragConst_End) ENDIF -IF (ALLOCATED(ParamData%L_dragConst)) THEN - DEALLOCATE(ParamData%L_dragConst) +IF (ALLOCATED(ParamData%F_WMG_End)) THEN + DEALLOCATE(ParamData%F_WMG_End) +ENDIF +IF (ALLOCATED(ParamData%DP_Const_End)) THEN + DEALLOCATE(ParamData%DP_Const_End) +ENDIF +IF (ALLOCATED(ParamData%Mass_MG_End)) THEN + DEALLOCATE(ParamData%Mass_MG_End) +ENDIF +IF (ALLOCATED(ParamData%AM_End)) THEN + DEALLOCATE(ParamData%AM_End) ENDIF IF (ALLOCATED(ParamData%distribToNodeIndx)) THEN DEALLOCATE(ParamData%distribToNodeIndx) @@ -8595,31 +10792,40 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_BufSz = 0 Int_BufSz = 0 Db_BufSz = Db_BufSz + 1 ! DT + Re_BufSz = Re_BufSz + 1 ! Gravity Re_BufSz = Re_BufSz + 1 ! WtrDens - Int_BufSz = Int_BufSz + 1 ! NNodes - Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no - IF ( ALLOCATED(InData%Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Nodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Int_BufSz = Int_BufSz + 1 ! NMembers + Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no + IF ( ALLOCATED(InData%Members) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Members upper/lower bounds for each dimension ! Allocate buffers for subtypes, if any (we'll get sizes from these) - DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) - Int_BufSz = Int_BufSz + 3 ! Nodes: size of buffers for each call to pack subtype - CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Nodes + DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) + Int_BufSz = Int_BufSz + 3 ! Members: size of buffers for each call to pack subtype + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Nodes + IF(ALLOCATED(Re_Buf)) THEN ! Members Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Nodes + IF(ALLOCATED(Db_Buf)) THEN ! Members Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Nodes + IF(ALLOCATED(Int_Buf)) THEN ! Members Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NNodes + Int_BufSz = Int_BufSz + 1 ! NJoints + Int_BufSz = Int_BufSz + 1 ! I_MG_End allocated yes/no + IF ( ALLOCATED(InData%I_MG_End) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! I_MG_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%I_MG_End) ! I_MG_End END IF Int_BufSz = Int_BufSz + 1 ! D_F_I allocated yes/no IF ( ALLOCATED(InData%D_F_I) ) THEN @@ -8636,40 +10842,55 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + 2*1 ! D_dragConst upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D_dragConst) ! D_dragConst END IF - Int_BufSz = Int_BufSz + 1 ! L_An allocated yes/no - IF ( ALLOCATED(InData%L_An) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_An upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_An) ! L_An - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_B allocated yes/no - IF ( ALLOCATED(InData%L_F_B) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_B) ! L_F_B - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_I allocated yes/no - IF ( ALLOCATED(InData%L_F_I) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! L_F_I upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_I) ! L_F_I - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_DP allocated yes/no - IF ( ALLOCATED(InData%L_F_DP) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! L_F_DP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_DP) ! L_F_DP - END IF - Int_BufSz = Int_BufSz + 1 ! L_F_BF allocated yes/no - IF ( ALLOCATED(InData%L_F_BF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! L_F_BF upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_F_BF) ! L_F_BF - END IF - Int_BufSz = Int_BufSz + 1 ! L_AM_M allocated yes/no - IF ( ALLOCATED(InData%L_AM_M) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! L_AM_M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_AM_M) ! L_AM_M - END IF - Int_BufSz = Int_BufSz + 1 ! L_dragConst allocated yes/no - IF ( ALLOCATED(InData%L_dragConst) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! L_dragConst upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%L_dragConst) ! L_dragConst + Int_BufSz = Int_BufSz + 1 ! An_End allocated yes/no + IF ( ALLOCATED(InData%An_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! An_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%An_End) ! An_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_B_End allocated yes/no + IF ( ALLOCATED(InData%F_B_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_B_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_B_End) ! F_B_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_I_End allocated yes/no + IF ( ALLOCATED(InData%F_I_End) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! F_I_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_I_End) ! F_I_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_DP_End allocated yes/no + IF ( ALLOCATED(InData%F_DP_End) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! F_DP_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_DP_End) ! F_DP_End + END IF + Int_BufSz = Int_BufSz + 1 ! AM_M_End allocated yes/no + IF ( ALLOCATED(InData%AM_M_End) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AM_M_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AM_M_End) ! AM_M_End + END IF + Int_BufSz = Int_BufSz + 1 ! DragConst_End allocated yes/no + IF ( ALLOCATED(InData%DragConst_End) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DragConst_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DragConst_End) ! DragConst_End + END IF + Int_BufSz = Int_BufSz + 1 ! F_WMG_End allocated yes/no + IF ( ALLOCATED(InData%F_WMG_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_WMG_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_WMG_End) ! F_WMG_End + END IF + Int_BufSz = Int_BufSz + 1 ! DP_Const_End allocated yes/no + IF ( ALLOCATED(InData%DP_Const_End) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DP_Const_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DP_Const_End) ! DP_Const_End + END IF + Int_BufSz = Int_BufSz + 1 ! Mass_MG_End allocated yes/no + IF ( ALLOCATED(InData%Mass_MG_End) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Mass_MG_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Mass_MG_End) ! Mass_MG_End + END IF + Int_BufSz = Int_BufSz + 1 ! AM_End allocated yes/no + IF ( ALLOCATED(InData%AM_End) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AM_End upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AM_End) ! AM_End END IF Int_BufSz = Int_BufSz + 1 ! NDistribMarkers Int_BufSz = Int_BufSz + 1 ! distribToNodeIndx allocated yes/no @@ -8856,22 +11077,26 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT Db_Xferred = Db_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Gravity + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDens Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMembers Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN + IF ( .NOT. ALLOCATED(InData%Members) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) - CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, OnlySize ) ! Nodes + DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) + CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, OnlySize ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -8900,6 +11125,29 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF END DO + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%I_MG_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_MG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_MG_End,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_MG_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_MG_End,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_MG_End,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_MG_End,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%I_MG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_MG_End))-1 ) = PACK(InData%I_MG_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%I_MG_End) END IF IF ( .NOT. ALLOCATED(InData%D_F_I) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8952,123 +11200,171 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF (SIZE(InData%D_dragConst)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_dragConst))-1 ) = PACK(InData%D_dragConst,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%D_dragConst) END IF - IF ( .NOT. ALLOCATED(InData%L_An) ) THEN + IF ( .NOT. ALLOCATED(InData%An_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_An,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_An,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_An,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_An,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_An)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_An))-1 ) = PACK(InData%L_An,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_An) + IF (SIZE(InData%An_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%An_End))-1 ) = PACK(InData%An_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%An_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_B) ) THEN + IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_B,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_B)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_B))-1 ) = PACK(InData%L_F_B,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_B) + IF (SIZE(InData%F_B_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_B_End))-1 ) = PACK(InData%F_B_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_B_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_I) ) THEN + IF ( .NOT. ALLOCATED(InData%F_I_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_I,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_I,3) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,3) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_I)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_I))-1 ) = PACK(InData%L_F_I,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_I) + IF (SIZE(InData%F_I_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_I_End))-1 ) = PACK(InData%F_I_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_I_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_DP) ) THEN + IF ( .NOT. ALLOCATED(InData%F_DP_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,2) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_DP,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_DP,3) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%F_DP_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP_End))-1 ) = PACK(InData%F_DP_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_DP_End) + END IF + IF ( .NOT. ALLOCATED(InData%AM_M_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AM_M_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM_M_End))-1 ) = PACK(InData%AM_M_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AM_M_End) + END IF + IF ( .NOT. ALLOCATED(InData%DragConst_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DragConst_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DragConst_End,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_DP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_DP))-1 ) = PACK(InData%L_F_DP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_DP) + IF (SIZE(InData%DragConst_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DragConst_End))-1 ) = PACK(InData%DragConst_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%DragConst_End) END IF - IF ( .NOT. ALLOCATED(InData%L_F_BF) ) THEN + IF ( .NOT. ALLOCATED(InData%F_WMG_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_BF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_BF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_F_BF)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_F_BF))-1 ) = PACK(InData%L_F_BF,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_F_BF) + IF (SIZE(InData%F_WMG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_WMG_End))-1 ) = PACK(InData%F_WMG_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_WMG_End) END IF - IF ( .NOT. ALLOCATED(InData%L_AM_M) ) THEN + IF ( .NOT. ALLOCATED(InData%DP_Const_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,2) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,3) + + IF (SIZE(InData%DP_Const_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DP_Const_End))-1 ) = PACK(InData%DP_Const_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%DP_Const_End) + END IF + IF ( .NOT. ALLOCATED(InData%Mass_MG_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Mass_MG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass_MG_End,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_AM_M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_AM_M))-1 ) = PACK(InData%L_AM_M,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_AM_M) + IF (SIZE(InData%Mass_MG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Mass_MG_End))-1 ) = PACK(InData%Mass_MG_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Mass_MG_End) END IF - IF ( .NOT. ALLOCATED(InData%L_dragConst) ) THEN + IF ( .NOT. ALLOCATED(InData%AM_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_dragConst,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_dragConst,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_End,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_End,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_End,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_End,3) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%L_dragConst)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%L_dragConst))-1 ) = PACK(InData%L_dragConst,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%L_dragConst) + IF (SIZE(InData%AM_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM_End))-1 ) = PACK(InData%AM_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AM_End) END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NDistribMarkers Int_Xferred = Int_Xferred + 1 @@ -9493,24 +11789,28 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Xferred = 1 OutData%DT = DbKiBuf( Db_Xferred ) Db_Xferred = Db_Xferred + 1 + OutData%Gravity = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%WtrDens = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - OutData%NNodes = IntKiBuf( Int_Xferred ) + OutData%WtrDpth = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%NMembers = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes)) DEALLOCATE(OutData%Nodes) - ALLOCATE(OutData%Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%Members)) DEALLOCATE(OutData%Members) + ALLOCATE(OutData%Members(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%Nodes,1), UBOUND(OutData%Nodes,1) + DO i1 = LBOUND(OutData%Members,1), UBOUND(OutData%Members,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -9544,7 +11844,7 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL Morison_Unpacknodetype( Re_Buf, Db_Buf, Int_Buf, OutData%Nodes(i1), ErrStat2, ErrMsg2 ) ! Nodes + CALL Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Members(i1), ErrStat2, ErrMsg2 ) ! Members CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9552,6 +11852,39 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO + END IF + OutData%NNodes = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NJoints = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_MG_End not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_MG_End)) DEALLOCATE(OutData%I_MG_End) + ALLOCATE(OutData%I_MG_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_MG_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%I_MG_End)>0) OutData%I_MG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%I_MG_End))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%I_MG_End) + DEALLOCATE(mask3) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_I not allocated Int_Xferred = Int_Xferred + 1 @@ -9634,7 +11967,7 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = Re_Xferred + SIZE(OutData%D_dragConst) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_An not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! An_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9644,10 +11977,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_An)) DEALLOCATE(OutData%L_An) - ALLOCATE(OutData%L_An(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%An_End)) DEALLOCATE(OutData%An_End) + ALLOCATE(OutData%An_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_An.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%An_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9656,11 +11989,11 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_An)>0) OutData%L_An = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_An))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_An) + IF (SIZE(OutData%An_End)>0) OutData%An_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%An_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%An_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_B not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9670,10 +12003,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_B)) DEALLOCATE(OutData%L_F_B) - ALLOCATE(OutData%L_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_B_End)) DEALLOCATE(OutData%F_B_End) + ALLOCATE(OutData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_B.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9682,11 +12015,40 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_B)>0) OutData%L_F_B = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_B))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_B) + IF (SIZE(OutData%F_B_End)>0) OutData%F_B_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_B_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_B_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_I not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I_End not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_I_End)) DEALLOCATE(OutData%F_I_End) + ALLOCATE(OutData%F_I_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%F_I_End)>0) OutData%F_I_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_I_End))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_I_End) + DEALLOCATE(mask3) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9699,10 +12061,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i3_l = IntKiBuf( Int_Xferred ) i3_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_I)) DEALLOCATE(OutData%L_F_I) - ALLOCATE(OutData%L_F_I(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_DP_End)) DEALLOCATE(OutData%F_DP_End) + ALLOCATE(OutData%F_DP_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_I.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) @@ -9711,11 +12073,11 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask3 = .TRUE. - IF (SIZE(OutData%L_F_I)>0) OutData%L_F_I = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_I))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_I) + IF (SIZE(OutData%F_DP_End)>0) OutData%F_DP_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP_End))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_DP_End) DEALLOCATE(mask3) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_DP not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM_M_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9728,10 +12090,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i3_l = IntKiBuf( Int_Xferred ) i3_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_DP)) DEALLOCATE(OutData%L_F_DP) - ALLOCATE(OutData%L_F_DP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%AM_M_End)) DEALLOCATE(OutData%AM_M_End) + ALLOCATE(OutData%AM_M_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_DP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM_M_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) @@ -9740,11 +12102,34 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask3 = .TRUE. - IF (SIZE(OutData%L_F_DP)>0) OutData%L_F_DP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_DP))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_DP) + IF (SIZE(OutData%AM_M_End)>0) OutData%AM_M_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM_M_End))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AM_M_End) DEALLOCATE(mask3) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_BF not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DragConst_End not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DragConst_End)) DEALLOCATE(OutData%DragConst_End) + ALLOCATE(OutData%DragConst_End(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DragConst_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%DragConst_End)>0) OutData%DragConst_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DragConst_End))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%DragConst_End) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9754,10 +12139,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_BF)) DEALLOCATE(OutData%L_F_BF) - ALLOCATE(OutData%L_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_WMG_End)) DEALLOCATE(OutData%F_WMG_End) + ALLOCATE(OutData%F_WMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_BF.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9766,11 +12151,11 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%L_F_BF)>0) OutData%L_F_BF = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_F_BF))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_F_BF) + IF (SIZE(OutData%F_WMG_End)>0) OutData%F_WMG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_WMG_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_WMG_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_AM_M not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DP_Const_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9780,36 +12165,33 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_AM_M)) DEALLOCATE(OutData%L_AM_M) - ALLOCATE(OutData%L_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%DP_Const_End)) DEALLOCATE(OutData%DP_Const_End) + ALLOCATE(OutData%DP_Const_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_AM_M.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP_Const_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) RETURN END IF - mask3 = .TRUE. - IF (SIZE(OutData%L_AM_M)>0) OutData%L_AM_M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_AM_M))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_AM_M) - DEALLOCATE(mask3) + mask2 = .TRUE. + IF (SIZE(OutData%DP_Const_End)>0) OutData%DP_Const_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DP_Const_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%DP_Const_End) + DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_dragConst not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Mass_MG_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_dragConst)) DEALLOCATE(OutData%L_dragConst) - ALLOCATE(OutData%L_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%Mass_MG_End)) DEALLOCATE(OutData%Mass_MG_End) + ALLOCATE(OutData%Mass_MG_End(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_dragConst.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Mass_MG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9818,9 +12200,38 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%L_dragConst)>0) OutData%L_dragConst = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%L_dragConst))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%L_dragConst) + IF (SIZE(OutData%Mass_MG_End)>0) OutData%Mass_MG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Mass_MG_End))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Mass_MG_End) DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM_End not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AM_End)) DEALLOCATE(OutData%AM_End) + ALLOCATE(OutData%AM_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM_End.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%AM_End)>0) OutData%AM_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM_End))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AM_End) + DEALLOCATE(mask3) END IF OutData%NDistribMarkers = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -10417,10 +12828,7 @@ SUBROUTINE Morison_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, Err ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshCopy( SrcInputData%DistribMesh, DstInputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcInputData%LumpedMesh, DstInputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcInputData%Mesh, DstInputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE Morison_CopyInput @@ -10434,8 +12842,7 @@ SUBROUTINE Morison_DestroyInput( InputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshDestroy( InputData%DistribMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( InputData%LumpedMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%Mesh, ErrStat, ErrMsg ) END SUBROUTINE Morison_DestroyInput SUBROUTINE Morison_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -10474,37 +12881,20 @@ SUBROUTINE Morison_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_BufSz = 0 Int_BufSz = 0 ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! DistribMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Re_Buf)) THEN ! Mesh Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Db_Buf)) THEN ! Mesh Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Int_Buf)) THEN ! Mesh Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -10535,35 +12925,7 @@ SUBROUTINE Morison_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -10658,47 +13020,7 @@ SUBROUTINE Morison_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + CALL MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -10722,10 +13044,7 @@ SUBROUTINE Morison_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshCopy( SrcOutputData%DistribMesh, DstOutputData%DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcOutputData%LumpedMesh, DstOutputData%LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN @@ -10751,8 +13070,7 @@ SUBROUTINE Morison_DestroyOutput( OutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshDestroy( OutputData%DistribMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( OutputData%LumpedMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%Mesh, ErrStat, ErrMsg ) IF (ALLOCATED(OutputData%WriteOutput)) THEN DEALLOCATE(OutputData%WriteOutput) ENDIF @@ -10794,37 +13112,20 @@ SUBROUTINE Morison_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Db_BufSz = 0 Int_BufSz = 0 ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! DistribMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! DistribMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! DistribMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! DistribMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! LumpedMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LumpedMesh + Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Re_Buf)) THEN ! Mesh Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Db_Buf)) THEN ! Mesh Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! LumpedMesh + IF(ALLOCATED(Int_Buf)) THEN ! Mesh Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -10860,35 +13161,7 @@ SUBROUTINE Morison_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh + CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -10997,47 +13270,7 @@ SUBROUTINE Morison_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh + CALL MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -11160,9 +13393,7 @@ SUBROUTINE Morison_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF - CALL MeshExtrapInterp1(u1%DistribMesh, u2%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp1(u1%LumpedMesh, u2%LumpedMesh, tin, u_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE Morison_Input_ExtrapInterp1 @@ -11216,9 +13447,7 @@ SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF - CALL MeshExtrapInterp2(u1%DistribMesh, u2%DistribMesh, u3%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp2(u1%LumpedMesh, u2%LumpedMesh, u3%LumpedMesh, tin, u_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE Morison_Input_ExtrapInterp2 @@ -11315,9 +13544,7 @@ SUBROUTINE Morison_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF - CALL MeshExtrapInterp1(y1%DistribMesh, y2%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp1(y1%LumpedMesh, y2%LumpedMesh, tin, y_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) @@ -11381,9 +13608,7 @@ SUBROUTINE Morison_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) RETURN END IF - CALL MeshExtrapInterp2(y1%DistribMesh, y2%DistribMesh, y3%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp2(y1%LumpedMesh, y2%LumpedMesh, y3%LumpedMesh, tin, y_out%LumpedMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) diff --git a/modules/hydrodyn/src/SS_Excitation.f90 b/modules/hydrodyn/src/SS_Excitation.f90 index 55d38d838..dbac29e1f 100644 --- a/modules/hydrodyn/src/SS_Excitation.f90 +++ b/modules/hydrodyn/src/SS_Excitation.f90 @@ -112,6 +112,7 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. INTEGER :: Sttus ! Error in reading .ssexctn file real(ReKi) :: WaveDir ! Temp wave direction angle (deg) + character(3) :: bodystr integer :: ErrStat2 character(1024) :: ErrMsg2 @@ -232,8 +233,14 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! Allocate Wave-elevation related arrays p%NStepWave = InitInp%NStepWave allocate ( p%WaveElev0(0:p%NStepWave) , STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Error allocating p%WaveElev0 array',ErrStat,ErrMsg,'SS_Exc_Init') + end if allocate ( p%WaveTime (0:p%NStepWave) , STAT=ErrStat2 ) -!TODO: Error Handling + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal,'Error allocating p%WaveTime array',ErrStat,ErrMsg,'SS_Exc_Init') + end if + IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() RETURN @@ -268,20 +275,24 @@ SUBROUTINE SS_Exc_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini ! no inputs ! Define system output initializations (set up mesh) here: - call AllocAry( y%y, p%NBody*6+1, 'y%y', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') - y%y = 0 + call AllocAry( y%y, p%NBody*6, 'y%y', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Exc_Init') + y%y = 0 + call AllocAry( y%WriteOutput, 6*p%NBody+1, 'y%WriteOutput', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') y%WriteOutput = 0 ! Define initialization-routine output here: + ! For OpenFAST, these outputs are attached (via HydroDyn) to the Radiation Force/Moment channels within HydroDyn call AllocAry( InitOut%WriteOutputHdr, 6*p%NBody+1, 'InitOut%WriteOutputHdr', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - call AllocAry( InitOut%WriteOutputUnt, 6*p%NBody+1, 'InitOut%WriteOutputUnt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') - !TODO: Create actual NBody ouput headers - !InitOut%WriteOutputHdr = (/ 'Time', 'FX ' , 'FY ' , 'FZ ' , 'MX ' , 'MY ' , 'MZ ' /) - !InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) - - + call AllocAry( InitOut%WriteOutputUnt, 6*p%NBody+1, 'InitOut%WriteOutputUnt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') + InitOut%WriteOutputHdr(1) = 'Time' + InitOut%WriteOutputUnt(1) = '(s) ' + do i = 1, p%NBody + bodystr = 'B'//trim(num2lstr(i)) + InitOut%WriteOutputHdr( (i-1)*6+2: (i-1)*6+7 ) = (/ trim(bodystr)//'FX ' , trim(bodystr)//'FY ' , trim(bodystr)//'FZ ' , trim(bodystr)//'MX ' , trim(bodystr)//'MY ' , trim(bodystr)//'MZ ' /) + InitOut%WriteOutputUnt( (i-1)*6+2: (i-1)*6+7 ) = (/ '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + end do CALL CleanUp() ! deallocate local arrays CONTAINS diff --git a/modules/hydrodyn/src/SS_Radiation.f90 b/modules/hydrodyn/src/SS_Radiation.f90 index 046651219..28969b8b6 100644 --- a/modules/hydrodyn/src/SS_Radiation.f90 +++ b/modules/hydrodyn/src/SS_Radiation.f90 @@ -125,7 +125,7 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini INTEGER :: Nlines ! Number of lines in the input file, used to determine N INTEGER :: UnSS ! I/O unit number for the WAMIT output file with the .ss extension; this file contains the state-space matrices. INTEGER :: Sttus ! Error in reading .ss file - + character(3) :: bodystr integer :: ErrStat2 character(1024) :: ErrMsg2 @@ -331,16 +331,21 @@ SUBROUTINE SS_Rad_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Ini y%WriteOutput = 0 - ! Define initialization-routine output here: + ! Define initialization-routine output here: + ! This output channels are only used by the stand-alone driver program and not by the OpenFAST coupled version. ! For OpenFAST, these outputs are attached (via HydroDyn) to the Radiation Force/Moment channels within HydroDyn - ! Define system output initializations (set up mesh) here: + call AllocAry( InitOut%WriteOutputHdr, 6*p%NBody+1, 'InitOut%WriteOutputHdr', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') call AllocAry( InitOut%WriteOutputUnt, 6*p%NBody+1, 'InitOut%WriteOutputUnt', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SS_Rad_Init') -!TODO: Create actual NBody ouput headers -! InitOut%WriteOutputHdr = (/ 'Time', 'F1 ' , 'F2 ' , 'F3 ' , 'F4 ' , 'F5 ' , 'F6 ' /) -! InitOut%WriteOutputUnt = (/ '(s) ', '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) - + + InitOut%WriteOutputHdr(1) = 'Time' + InitOut%WriteOutputUnt(1) = '(s) ' + do i = 1, p%NBody + bodystr = 'B'//trim(num2lstr(i)) + InitOut%WriteOutputHdr( (i-1)*6+2: (i-1)*6+7 ) = (/ trim(bodystr)//'FX ' , trim(bodystr)//'FY ' , trim(bodystr)//'FZ ' , trim(bodystr)//'MX ' , trim(bodystr)//'MY ' , trim(bodystr)//'MZ ' /) + InitOut%WriteOutputUnt( (i-1)*6+2: (i-1)*6+7 ) = (/ '(N) ' , '(N) ' , '(N) ' , '(Nm)' , '(Nm)' , '(Nm)' /) + end do ! If you want to choose your own rate instead of using what the glue code suggests, tell the glue code the rate at which ! this module must be called here: diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 6b50e557e..ea09e7c74 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -558,7 +558,6 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Indx = 6*( I - 1 ) + J - ( I*( I - 1 ) )/2 ! Convert from row/column indices to an index in the format used to save only the upper-triangular portion of the matrix. NOTE: ( I*( I - 1 ) )/2 = SUM(I,START=1,END=I-1). iSub = mod(I-1,6)+1 ! Finds the 6x6 sub-matrix indexing for the SttcDim multiplier matrix jSub = mod(J-1,6)+1 -!TODO need to transform these when PtfmRefztRot is nonzero per plan HdroAddMs(SortFreqInd(K),I,J) = TmpData1*RdtnDim(iSub,jSub) ! Redimensionalize the data and place it at the appropriate location within the array HdroDmpng(SortFreqInd(K),I,J) = TmpData2*RdtnDim(iSub,jSub)*HdroFreq(SortFreqInd(K)) ! Redimensionalize the data and place it at the appropriate location within the array ! END IF @@ -998,7 +997,6 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Transform the wave excitation coefs !==================================== - ! TODO: Need to create rotation corrrection for NBODYMOD = 1,3, but do not use Fxy and do not adjust beta (tmpAngle) if ( p%NBodyMod == 2 ) then ! Since NBodyMod = 2, then NBody = 1 for this WAMIT object (this requirement is encoded at the HydroDyn module level) @@ -1616,6 +1614,11 @@ SUBROUTINE WAMIT_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState END IF DO I=1,nTime + ALLOCATE( SS_Rdtn_u(I)%dq(size(m%SS_Rdtn_u%dq)), STAT = ErrStat ) + IF (ErrStat /=0) THEN + ErrMsg = ' Failed to allocate array SS_Rdtn_u(I)%dq.' + RETURN + END IF do iBody=1,p%NBody indxStart = (iBody-1)*6+1 SS_Rdtn_u(I)%dq(indxStart:indxStart+2) = Inputs(I)%Mesh%TranslationVel(:,iBody) diff --git a/vs-build/HydroDyn/HydroDynDriver.vfproj b/vs-build/HydroDyn/HydroDynDriver.vfproj index efab18895..9ca3b1a51 100644 --- a/vs-build/HydroDyn/HydroDynDriver.vfproj +++ b/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -25,7 +25,7 @@ - + From 01427a7283c290ac872f1298de9e928ce4b46105 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 16 Apr 2020 18:42:36 -0600 Subject: [PATCH 171/377] Added offsets for MSL2SWL for FillFSLoc and MGDpth values --- modules/hydrodyn/src/HydroDyn_Input.f90 | 6 ++++-- modules/hydrodyn/src/Morison.f90 | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 9d4b10c51..11d4151e2 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -3952,9 +3952,11 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%Morison%MGTop = -999999.0 InitInp%Morison%MGBottom = 999999.0 - + do I = 1,InitInp%Morison%NMGDepths + ! Adjust the depth values based on MSL2SWL + InitInp%Morison%MGDepths(I)%MGDpth = InitInp%Morison%MGDepths(I)%MGDpth - InitInp%MSL2SWL + end do DO I = 1,InitInp%Morison%NMGDepths - ! Store the boundaries of the marine growth zone IF ( InitInp%Morison%MGDepths(I)%MGDpth > InitInp%Morison%MGTop ) THEN InitInp%Morison%MGTop = InitInp%Morison%MGDepths(I)%MGDpth diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 83e0b9b07..69555fc55 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1509,7 +1509,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%MmbrFilledIDIndx = MmbrFilledIDIndx ! Set this to the parameter version of this member data if ( MmbrFilledIDIndx > 0 ) then member%FillDens = InitInp%FilledGroups(MmbrFilledIDIndx)%FillDens - member%FillFSLoc = InitInp%FilledGroups(MmbrFilledIDIndx)%FillFSLoc + member%FillFSLoc = InitInp%FilledGroups(MmbrFilledIDIndx)%FillFSLoc - InitInp%MSL2SWL if (member%FillFSLoc >= Zb) then member%z_overfill = member%FillFSLoc - Zb member%l_fill = member%RefLength @@ -2817,8 +2817,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! External Hydrodynamic Side Loads - DO i =1,N+1 ! loop through member elements + DO i =1,N+1 ! loop through member elements h_c = 0.0_ReKi !TODO: Determine actual h_c based on water level, etc. GJH 3/23/20 see table in Section 7.1.1 + !TODO: call GetExtHydroForceMomentMultipliers( i, N+1, Za, Zb, Zi, h_c, deltal ) if (i == 1) then dRdl_p = abs(mem%dRdl_mg(i)) dRdl_pp = mem%dRdl_mg(i) From 4503c549b3e33b8cb05c348b73cfddc7b430b4da Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:11:02 -0600 Subject: [PATCH 172/377] Added and removed some comments --- modules/hydrodyn/src/Morison_Output.f90 | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/modules/hydrodyn/src/Morison_Output.f90 b/modules/hydrodyn/src/Morison_Output.f90 index 872aa192e..80044021c 100644 --- a/modules/hydrodyn/src/Morison_Output.f90 +++ b/modules/hydrodyn/src/Morison_Output.f90 @@ -6456,9 +6456,7 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg DO J=1,p%NMOutputs DO I=1,p%MOutLst(J)%NOutLoc - ! These indices are in the DistribMesh index system, not the overall nodes index system, so distribToNodeIndx() mapping needs to be performed if you want to index into the nodes array or wave kinematics arrays - ! But, all of the D_* arrays are already using the DistribMesh index system, so we are OK for those - + m1 = p%MOutLst(J)%Marker1(I) m2 = p%MOutLst(J)%Marker2(I) s = p%MOutLst(J)%s (I) @@ -6782,16 +6780,18 @@ SUBROUTINE GetNeighboringNodes(member, d, m1, m2, s, ErrStat, ErrMsg) ErrMsg = '' ! This only works because the member nodes are equally spaced + ! d is in the range [0,1] and is from the member starting node to the member ending node + ! s is in the range [0,1] but is the normalized distance between any two adjacent member nodes. i1 = floor(member%NElements*d) ! 0<= d <= 1.0 if ( i1 == member%NElements ) then ! special case when d = 1.0_ReKi - i2 = i1 + 1 + i2 = i1 + 1 ! In this case, i1 = N and i2 = N+1 (one-based indexing which is what is needed to index into the NodeIndx arrays, below. s = 1.0_ReKi else - s = member%NElements*d - i1 ! here i1 is zero-based - i1 = i1 + 1 ! Shift to one-based indices + s = member%NElements*d - i1 ! here i1 is zero-based, s is fractional amount of between adjacent nodes, s = [0,1] + i1 = i1 + 1 ! Shift to one-based indices for work to follow, below i2 = i1 + 1 end if @@ -6877,12 +6877,9 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! Need to search mesh for the two markers which surround the requested output location and then store those marker indices and compute the ! scale factor based on how far they are from the requested output location. ! Since this is being done on markers and not nodes, the subroutine must be called after the Morison_Init() subroutine is called - !TODO: Need to reimplement the following + CALL GetNeighboringNodes(p%Members(memberIndx), p%MOutLst(I)%NodeLocs(J), m1, m2, s, ErrStat, ErrMsg) - ! CALL GetNeighboringNodes(memberIndx, p%MOutLst(I)%NodeLocs(J), p%NDistribMarkers, p%Nodes, p%distribToNodeIndx, m1, m2, s, ErrStat, ErrMsg) - - ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you - ! want to index into the nodes array or wave kinematics arrays + p%MOutLst(I)%Marker1(J) = m1 p%MOutLst(I)%Marker2(J) = m2 ! The 2nd marker indx which is used to p%MOutLst(I)%s(J) = s ! linear interpolation factor From ee693b877c16e36f59f184df545d3a5f3c6f4955 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:11:27 -0600 Subject: [PATCH 173/377] Removed unused registry entries --- modules/hydrodyn/src/Morison_orig/Morison.txt | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 modules/hydrodyn/src/Morison_orig/Morison.txt diff --git a/modules/hydrodyn/src/Morison_orig/Morison.txt b/modules/hydrodyn/src/Morison_orig/Morison.txt new file mode 100644 index 000000000..27fb926eb --- /dev/null +++ b/modules/hydrodyn/src/Morison_orig/Morison.txt @@ -0,0 +1,356 @@ +################################################################################################################################### +# Registry for Morison in the FAST Modularization Framework +# This Registry file is used to create MODULE Morison which contains all of the user-defined types needed in Morison. +# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. +# See NWTC Programmer's Handbook for further information on the format/contents of this file. +# +# Entries are of the form +# +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### + +# ...... Include files (definitions from NWTC Library) ............................................................................ +# make sure that the file name does not have any trailing white spaces! +include Registry_NWTC_Library.txt +# +# +param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "Total number of possible Morison module output channels" - +typedef Morison/Morison Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - +typedef ^ ^ ReKi JointPos {3} - - "Undisplaced location of the joint in the platform coordinate system" m +typedef ^ ^ INTEGER JointAxID - - - "Axial ID (found in the user-supplied Axial Coefficients Table) for this joint: used to determine axial coefs" - +typedef ^ ^ INTEGER JointAxIDIndx - - - "The index into the Axial Coefs arrays corresponding to the above Axial ID" - +typedef ^ ^ INTEGER JointOvrlp - - - "Joint overlap code [Unused" - +typedef ^ ^ INTEGER NConnections - - - "Number of members connecting to this joint" - +typedef ^ ^ INTEGER ConnectionList {10} - - "List of Members connected to this joint. The member index is what is stored, not the Member ID" - +typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - +typedef ^ ^ ReKi PropD - - - "Diameter" m +typedef ^ ^ ReKi PropThck - - - "Wall thickness" m +typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - +typedef ^ ^ INTEGER FillMList {:} - - "List of Member IDs for the members in this fill group" - +typedef ^ ^ ReKi FillFSLoc - - - "The free-surface location (in Z) for this fill group" m +typedef ^ ^ CHARACTER(80) FillDensChr - - - "String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens]" kg/m^3 +typedef ^ ^ ReKi FillDens - - - "Numerical fill density" kg/m^3 +typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m +typedef ^ ^ ReKi DpthCd - - - "Depth-based drag coef" - +typedef ^ ^ ReKi DpthCdMG - - - "Depth-based drag coef for marine growth" - +typedef ^ ^ ReKi DpthCa - - - "Depth-based Ca" - +typedef ^ ^ ReKi DpthCaMG - - - "Depth-based Ca for marine growth" - +typedef ^ ^ ReKi DpthCp - - - "Depth-based Cp" - +typedef ^ ^ ReKi DpthCpMG - - - "Depth-based Cp for marine growth" - +typedef ^ ^ ReKi DpthAxCa - - - "Depth-based Axial Ca" - +typedef ^ ^ ReKi DpthAxCaMG - - - "Depth-based Axial Ca for marine growth" - +typedef ^ ^ ReKi DpthAxCp - - - "Depth-based Axial Cp" - +typedef ^ ^ ReKi DpthAxCpMG - - - "Depth-based Axial Cp for marine growth" - +typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - +typedef ^ ^ ReKi AxCd - - - "Axial Cd" - +typedef ^ ^ ReKi AxCa - - - "Axial Ca" - +typedef ^ ^ ReKi AxCp - - - "Axial Cp" - +typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "User-supplied integer ID for this member" - +typedef ^ ^ INTEGER MJointID1 - - - "Joint ID for start of member" - +typedef ^ ^ INTEGER MJointID2 - - - "Joint ID for end of member" - +typedef ^ ^ INTEGER MJointID1Indx - - - "Index into the joint table for the start of this member" - +typedef ^ ^ INTEGER MJointID2Indx - - - "Index into the joint table for the end of this member" - +typedef ^ ^ INTEGER MPropSetID1 - - - "Property set ID for the start of this member" - +typedef ^ ^ INTEGER MPropSetID2 - - - "Property set ID for the end of this member" - +typedef ^ ^ INTEGER MPropSetID1Indx - - - "Index into the Property table for the start of this member" - +typedef ^ ^ INTEGER MPropSetID2Indx - - - "Index into the Property table for the end of this member" - +typedef ^ ^ ReKi MDivSize - - - "User-specified desired member discretization size for the final element" m +typedef ^ ^ INTEGER MCoefMod - - - "Which coef. model is being used for this member [1=simple, 2=depth-based, 3=member-based]" - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "Index into the appropriate coefs table for this member's properties" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "Index into the filled group table if this is a filled member" - +typedef ^ ^ LOGICAL PropPot - - - "Flag T/F for whether the member is modeled with potential flow theory" - +#typedef ^ ^ INTEGER MGSplitState - - - "No longer used" - +#typedef ^ ^ INTEGER WtrSplitState - - - "No longer used" - +typedef ^ ^ INTEGER NumSplits - - - "How many splits are needs beyond the user-specified geometry" - +typedef ^ ^ ReKi Splits {5} - - "Number of times a user member is subdivided by the software" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from local to global coordinates" - +typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - +typedef ^ ^ INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - +typedef ^ ^ ReKi JointPos {3} - - "Position of the node in global coordinates" m +typedef ^ ^ INTEGER JointOvrlp - - - "" - +typedef ^ ^ INTEGER JointAxIDIndx - - - "" - +typedef ^ ^ INTEGER NConnections - - - "Number of elements connecting to this node" - +typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the elements connected to this node" - +typedef ^ ^ INTEGER NConnectPreSplit - - - "In code, but unused: should be removed" - +typedef ^ ^ ReKi Cd - - - "Nodal Cd" - +typedef ^ ^ ReKi CdMG - - - "Nodal Cd with marine growth" - +typedef ^ ^ ReKi Ca - - - "Nodal Ca" - +typedef ^ ^ ReKi CaMG - - - "Nodal Ca with marine growth" - +typedef ^ ^ ReKi Cp - - - "Nodal Cp" - +typedef ^ ^ ReKi CpMG - - - "Nodal Cp with marine growth" - +typedef ^ ^ ReKi JAxCd - - - "Nodal lumped (joint) axial Cd" - +typedef ^ ^ ReKi JAxCa - - - "Nodal lumped (joint) axial Cp" - +typedef ^ ^ ReKi JAxCp - - - "Nodal lumped (joint) axial Ca" - +typedef ^ ^ ReKi AxCa - - - "Nodal axial Ca" - +typedef ^ ^ ReKi AxCp - - - "Nodal axial Cp" - +typedef ^ ^ ReKi AxCaMG - - - "Nodal axial Ca with marine growth" - +typedef ^ ^ ReKi AxCpMG - - - "Nodal axial Cp with marine growth" - +typedef ^ ^ ReKi R - - - "Nodal radius (of member at node location)" m +typedef ^ ^ ReKi t - - - "Nodal thickness (of member at node location)" m +typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth (of member at node location)" m +typedef ^ ^ ReKi dRdz - - - "Nodal rate of change in member radius with respect to member axial direction" +typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 +typedef ^ ^ ReKi FillFSLoc - - - "Nodal fill free surface location (of connected chamber to this node)" m +typedef ^ ^ LOGICAL FillFlag - - - "Is this node filled? T/F" - +typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 +typedef ^ ^ INTEGER InpMbrIndx - - - "Index of member this node is connected to (from the user-specified member list in the input file)" - +typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - +typedef ^ ^ LOGICAL PropPot - - - "Is this node modeled with potential flow theory? T/F" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from node local to global coordinates" - +typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "Index of member's node 1 in the master node list" - +typedef ^ ^ INTEGER Node2Indx - - - "Index of member's node 2 in the master node list" - +typedef ^ ^ ReKi R1 - - - "Radius of node 1" m +typedef ^ ^ ReKi t1 - - - "Member thickness at node 1" m +typedef ^ ^ ReKi R2 - - - "Radius of node 2" m +typedef ^ ^ ReKi t2 - - - "Member thickness at node 2" m +typedef ^ ^ ReKi Cd1 - - - "Member Cd at node 1" - +typedef ^ ^ ReKi CdMG1 - - - "Member Cd at node 1 with marine growth" - +typedef ^ ^ ReKi Ca1 - - - "Member Ca at node 1" - +typedef ^ ^ ReKi CaMG1 - - - "Member Ca at node 1 with marine growth" - +typedef ^ ^ ReKi Cp1 - - - "Member Cp at node 1" - +typedef ^ ^ ReKi CpMG1 - - - "Member Cp at node 1 with marine growth" - +typedef ^ ^ ReKi AxCa1 - - - "Member axial Ca at node 1" - +typedef ^ ^ ReKi AxCaMG1 - - - "Member axial Ca at node 1 with marine growth" - +typedef ^ ^ ReKi AxCp1 - - - "Member axial Cp at node 1" - +typedef ^ ^ ReKi AxCpMG1 - - - "Member axial Cp at node 1 with marine growth" - +typedef ^ ^ ReKi Cd2 - - - "Member Cd at node 2" - +typedef ^ ^ ReKi CdMG2 - - - "Member Cd at node 2 with marine growth" - +typedef ^ ^ ReKi Ca2 - - - "Member Ca at node 2" - +typedef ^ ^ ReKi CaMG2 - - - "Member Ca at node 2 with marine growth" - +typedef ^ ^ ReKi Cp2 - - - "Member Cp at node 2" - +typedef ^ ^ ReKi CpMG2 - - - "Member Cp at node 2 with marine growth" - +typedef ^ ^ ReKi AxCa2 - - - "Member axial Ca at node 2" - +typedef ^ ^ ReKi AxCaMG2 - - - "Member axial Ca at node 2 with marine growth" - +typedef ^ ^ ReKi AxCp2 - - - "Member axial Cp at node 2" - +typedef ^ ^ ReKi AxCpMG2 - - - "Member axial Cp at node 2 with marine growth" - +typedef ^ ^ ReKi InpMbrDist1 - - - "Normalized distance of node 1 from the user-specified corresponding member in the input file" - +typedef ^ ^ ReKi InpMbrDist2 - - - "Normalized distance of node 2 from the user-specified corresponding member in the input file" - +typedef ^ ^ ReKi InpMbrLen - - - "Length of the user-specified member this is a part of" - +typedef ^ ^ INTEGER InpMbrIndx - - - "Index of the user-specified member this is a part of" - +typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from member local to global coordinates" - +#typedef ^ ^ INTEGER MGSplitState - - - "Unused" - +#typedef ^ ^ INTEGER WtrSplitState - - - "Unused" - +typedef ^ ^ INTEGER NumSplits - - - "How many splits need to be created in the member/element" - +typedef ^ ^ ReKi Splits {5} - - "Locations of the splits in the Z coordinate" m +typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 +typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m +typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - +typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m +typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 +typedef ^ ^ ReKi F_Bouy {6} - - "Unused" - +typedef ^ ^ ReKi F_DP {6} - - "Unused" - +typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - +typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - +typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m +typedef ^ ^ ReKi MGThck - - - "Marine growth thickness" m +typedef ^ ^ ReKi MGDens - - - "Marine growth density" kg/m^3 +typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "Member ID for requested output" - +typedef ^ ^ INTEGER NOutLoc - - - "The number of requested output locations" - +typedef ^ ^ ReKi NodeLocs {:} - - "Normalized locations along user-specified member for the outputs" - +typedef ^ ^ INTEGER MemberIDIndx - - - "Index for member in the master list" - +typedef ^ ^ INTEGER Marker1 {:} - - "Index of node in DistribMesh for the start of the member" - +typedef ^ ^ INTEGER Marker2 {:} - - "Index of node in DistribMesh for the end of the member" - +typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - +typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - +typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - +typedef ^ ^ INTEGER NumMarkers - - - "Number of lumped mesh nodes which are co-located at the requested Joint" - +typedef ^ ^ INTEGER Markers {10} - - "Index of all nodes in lumped mesh which are co-located at the requested Joint" - +# ..... Initialization data ....................................................................................................... +# Define inputs that the initialization routine may need here: +# e.g., the name of the input file, the file root name,etc. +# +typedef Morison/Morison InitInputType ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 +typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 +typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m +typedef ^ ^ ReKi MSL2SWL - - - "Mean Sea Level to Still Water Level offset" m +typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - +typedef ^ ^ INTEGER NNodes - - - "Total number of nodes in the final software model" - +typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "Unused: For super member calculations" - +typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - +typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - +typedef ^ ^ INTEGER NElements - - - "Number of elements in the discretized model" - +typedef ^ ^ Morison_MemberType Elements {:} - - "Array of elements which were derived from the user-specified members" - +typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - +typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - +typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - +typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "List of Member property sets" - +typedef ^ ^ ReKi SimplCd - - - "Simple model drag coef" - +typedef ^ ^ ReKi SimplCdMG - - - "Simple model drag coef for marine growth" - +typedef ^ ^ ReKi SimplCa - - - "Simple model Ca" - +typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for marine growth" - +typedef ^ ^ ReKi SimplCp - - - "Simple model Cp" - +typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for marine growth" - +typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca" - +typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for marine growth" - +typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp" - +typedef ^ ^ ReKi SimplAxCpMG - - - "Simple model Axial Cp for marine growth" - +typedef ^ ^ INTEGER NCoefDpth - - - "" - +typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - +typedef ^ ^ INTEGER NCoefMembers - - - "" - +typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - +typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - +typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "Array of user-specified members" - +typedef ^ ^ INTEGER NFillGroups - - - "" - +typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - +typedef ^ ^ INTEGER NMGDepths - - - "" - +typedef ^ ^ Morison_MGDepthsType MGDepths {:} - - "" - +typedef ^ ^ ReKi MGTop - - - "" - +typedef ^ ^ ReKi MGBottom - - - "" - +typedef ^ ^ INTEGER NMOutputs - - - "" - +typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - +typedef ^ ^ INTEGER NJOutputs - - - "" - +typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - +typedef ^ ^ CHARACTER(10) OutList {4032} - - "This list size needs to be the maximum # of possible outputs because of the use of ReadAry()" - +typedef ^ ^ LOGICAL ValidOutList {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER OutSwtch - - - "" - +typedef ^ ^ LOGICAL OutAll - - - "" - +typedef ^ ^ CHARACTER(1024) OutRootName - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - +typedef ^ ^ INTEGER UnSum - - - "" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "" - +typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - +typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - +typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +# +# +# Define outputs from the initialization routine here: +# +typedef ^ InitOutputType MeshType DistribMesh - - - "Unused?" - +typedef ^ ^ MeshType LumpedMesh - - - "Unused?" - +typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) +typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - +typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "User-requested Output channel units" - +# +# +# ..... States .................................................................................................................... +# Define continuous (differentiable) states here: +# +typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - +# +# +# Define discrete (nondifferentiable) states here: +# +typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - +# +# +# Define constraint states here: +# +typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - +# +# +# Define any other states, including integer or logical states here: +typedef ^ OtherStateType IntKi DummyOtherState - - - "Remove this variable if you have other states" - + +# ..... Misc/Optimization variables................................................................................................. +# Define any data that are used only for efficiency purposes (these variables are not associated with time): +# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. +typedef ^ MiscVarType ReKi D_F_D {:}{:} - - "Distributed viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - +typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_B was computed)" - +#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Unused: Distributed dynamic pressure loads" - +typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_B {:}{:} - - "" - +typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - + +# ..... Parameters ................................................................................................................ +# Define parameters here: +# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: +# +typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) +typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 +typedef ^ ^ INTEGER NNodes - - - "" - +typedef ^ ^ Morison_NodeType Nodes {:} - - "" - +typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - +typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - +typedef ^ ^ ReKi D_dragConst {:} - - "" - +typedef ^ ^ ReKi L_An {:}{:} - - "" - +typedef ^ ^ ReKi L_F_B {:}{:} - - "" - +typedef ^ ^ ReKi L_F_I {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_F_DP {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_F_BF {:}{:} - - "" - +typedef ^ ^ ReKi L_AM_M {:}{:}{:} - - "" - +typedef ^ ^ ReKi L_dragConst {:} - - "" - +typedef ^ ^ INTEGER NDistribMarkers - - - "" - +#typedef ^ ^ Morison_NodeType DistribMarkers {:} - - "" - +typedef ^ ^ INTEGER distribToNodeIndx {:} - - "" - +typedef ^ ^ INTEGER NLumpedMarkers - - - "" - +typedef ^ ^ INTEGER lumpedToNodeIndx {:} - - "" - +typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - +typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - +typedef ^ ^ SiKi WaveTime {:} - - "Times for which the wave kinematics are pre-computed" s +typedef ^ ^ INTEGER elementWaterState {:}{:} - - "State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2]" - +typedef ^ ^ INTEGER elementFillState {:} - - "State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2]" - +typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed buoyancy loads" - +typedef ^ ^ ReKi D_F_BF {:}{:} - - "Distributed filled buoyancy loads" - +typedef ^ ^ ReKi D_F_MG {:}{:} - - "Distributed marine growth loads" - +typedef ^ ^ ReKi D_AM_M {:}{:}{:} - - "Distributed member added mass matrix" - +typedef ^ ^ ReKi D_AM_MG {:} - - "Distributed marine growth added mass matrix (weight)" - +typedef ^ ^ ReKi D_AM_F {:} - - "Distributed added mass matrix due to flooding/filled fluid" - +typedef ^ ^ INTEGER NStepWave - - - "" - +typedef ^ ^ INTEGER NMOutputs - - - "" - +typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - +typedef ^ ^ INTEGER NJOutputs - - - "" - +typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - +typedef ^ ^ OutParmType OutParam {:} - - "" - +typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ INTEGER NumOutAll - - - "" - +typedef ^ ^ INTEGER OutSwtch - - - "" - +typedef ^ ^ INTEGER UnOutFile - - - "" - +typedef ^ ^ CHARACTER(20) OutFmt - - - "" - +typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - +typedef ^ ^ CHARACTER(10) Delim - - - "" - +# +# +# ..... Inputs .................................................................................................................... +# Define inputs that are contained on the mesh here: +# +typedef ^ InputType MeshType DistribMesh - - - "Distributed Loads Meshed input data" - +typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed input data" - +# +# +# ..... Outputs ................................................................................................................... +# Define outputs that are contained on the mesh here: +typedef ^ OutputType MeshType DistribMesh - - - "Distributed Loads Meshed output data" - +typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed output data" - +typedef ^ ^ ReKi WriteOutput {:} - - "" - From be4306f566eecd269155f82509c268580f3a2495 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:11:27 -0600 Subject: [PATCH 174/377] Revert "Removed unused registry entries" This reverts commit ee693b877c16e36f59f184df545d3a5f3c6f4955. --- modules/hydrodyn/src/Morison_orig/Morison.txt | 356 ------------------ 1 file changed, 356 deletions(-) delete mode 100644 modules/hydrodyn/src/Morison_orig/Morison.txt diff --git a/modules/hydrodyn/src/Morison_orig/Morison.txt b/modules/hydrodyn/src/Morison_orig/Morison.txt deleted file mode 100644 index 27fb926eb..000000000 --- a/modules/hydrodyn/src/Morison_orig/Morison.txt +++ /dev/null @@ -1,356 +0,0 @@ -################################################################################################################################### -# Registry for Morison in the FAST Modularization Framework -# This Registry file is used to create MODULE Morison which contains all of the user-defined types needed in Morison. -# It also contains copy, destroy, pack, and unpack routines associated with each defined data types. -# See NWTC Programmer's Handbook for further information on the format/contents of this file. -# -# Entries are of the form -# -# -# Use ^ as a shortcut for the value in the same column from the previous line. -################################################################################################################################### - -# ...... Include files (definitions from NWTC Library) ............................................................................ -# make sure that the file name does not have any trailing white spaces! -include Registry_NWTC_Library.txt -# -# -param Morison/Morison unused INTEGER MaxMrsnOutputs - 4032 - "Total number of possible Morison module output channels" - -typedef Morison/Morison Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - -typedef ^ ^ ReKi JointPos {3} - - "Undisplaced location of the joint in the platform coordinate system" m -typedef ^ ^ INTEGER JointAxID - - - "Axial ID (found in the user-supplied Axial Coefficients Table) for this joint: used to determine axial coefs" - -typedef ^ ^ INTEGER JointAxIDIndx - - - "The index into the Axial Coefs arrays corresponding to the above Axial ID" - -typedef ^ ^ INTEGER JointOvrlp - - - "Joint overlap code [Unused" - -typedef ^ ^ INTEGER NConnections - - - "Number of members connecting to this joint" - -typedef ^ ^ INTEGER ConnectionList {10} - - "List of Members connected to this joint. The member index is what is stored, not the Member ID" - -typedef Morison/Morison Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - -typedef ^ ^ ReKi PropD - - - "Diameter" m -typedef ^ ^ ReKi PropThck - - - "Wall thickness" m -typedef Morison/Morison Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - -typedef ^ ^ INTEGER FillMList {:} - - "List of Member IDs for the members in this fill group" - -typedef ^ ^ ReKi FillFSLoc - - - "The free-surface location (in Z) for this fill group" m -typedef ^ ^ CHARACTER(80) FillDensChr - - - "String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens]" kg/m^3 -typedef ^ ^ ReKi FillDens - - - "Numerical fill density" kg/m^3 -typedef Morison/Morison Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m -typedef ^ ^ ReKi DpthCd - - - "Depth-based drag coef" - -typedef ^ ^ ReKi DpthCdMG - - - "Depth-based drag coef for marine growth" - -typedef ^ ^ ReKi DpthCa - - - "Depth-based Ca" - -typedef ^ ^ ReKi DpthCaMG - - - "Depth-based Ca for marine growth" - -typedef ^ ^ ReKi DpthCp - - - "Depth-based Cp" - -typedef ^ ^ ReKi DpthCpMG - - - "Depth-based Cp for marine growth" - -typedef ^ ^ ReKi DpthAxCa - - - "Depth-based Axial Ca" - -typedef ^ ^ ReKi DpthAxCaMG - - - "Depth-based Axial Ca for marine growth" - -typedef ^ ^ ReKi DpthAxCp - - - "Depth-based Axial Cp" - -typedef ^ ^ ReKi DpthAxCpMG - - - "Depth-based Axial Cp for marine growth" - -typedef Morison/Morison Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - -typedef ^ ^ ReKi AxCd - - - "Axial Cd" - -typedef ^ ^ ReKi AxCa - - - "Axial Ca" - -typedef ^ ^ ReKi AxCp - - - "Axial Cp" - -typedef Morison/Morison Morison_MemberInputType INTEGER MemberID - - - "User-supplied integer ID for this member" - -typedef ^ ^ INTEGER MJointID1 - - - "Joint ID for start of member" - -typedef ^ ^ INTEGER MJointID2 - - - "Joint ID for end of member" - -typedef ^ ^ INTEGER MJointID1Indx - - - "Index into the joint table for the start of this member" - -typedef ^ ^ INTEGER MJointID2Indx - - - "Index into the joint table for the end of this member" - -typedef ^ ^ INTEGER MPropSetID1 - - - "Property set ID for the start of this member" - -typedef ^ ^ INTEGER MPropSetID2 - - - "Property set ID for the end of this member" - -typedef ^ ^ INTEGER MPropSetID1Indx - - - "Index into the Property table for the start of this member" - -typedef ^ ^ INTEGER MPropSetID2Indx - - - "Index into the Property table for the end of this member" - -typedef ^ ^ ReKi MDivSize - - - "User-specified desired member discretization size for the final element" m -typedef ^ ^ INTEGER MCoefMod - - - "Which coef. model is being used for this member [1=simple, 2=depth-based, 3=member-based]" - -typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "Index into the appropriate coefs table for this member's properties" - -typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "Index into the filled group table if this is a filled member" - -typedef ^ ^ LOGICAL PropPot - - - "Flag T/F for whether the member is modeled with potential flow theory" - -#typedef ^ ^ INTEGER MGSplitState - - - "No longer used" - -#typedef ^ ^ INTEGER WtrSplitState - - - "No longer used" - -typedef ^ ^ INTEGER NumSplits - - - "How many splits are needs beyond the user-specified geometry" - -typedef ^ ^ ReKi Splits {5} - - "Number of times a user member is subdivided by the software" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from local to global coordinates" - -typedef Morison/Morison Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - -typedef ^ ^ INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - -typedef ^ ^ ReKi JointPos {3} - - "Position of the node in global coordinates" m -typedef ^ ^ INTEGER JointOvrlp - - - "" - -typedef ^ ^ INTEGER JointAxIDIndx - - - "" - -typedef ^ ^ INTEGER NConnections - - - "Number of elements connecting to this node" - -typedef ^ ^ INTEGER ConnectionList {10} - - "Indices of all the elements connected to this node" - -typedef ^ ^ INTEGER NConnectPreSplit - - - "In code, but unused: should be removed" - -typedef ^ ^ ReKi Cd - - - "Nodal Cd" - -typedef ^ ^ ReKi CdMG - - - "Nodal Cd with marine growth" - -typedef ^ ^ ReKi Ca - - - "Nodal Ca" - -typedef ^ ^ ReKi CaMG - - - "Nodal Ca with marine growth" - -typedef ^ ^ ReKi Cp - - - "Nodal Cp" - -typedef ^ ^ ReKi CpMG - - - "Nodal Cp with marine growth" - -typedef ^ ^ ReKi JAxCd - - - "Nodal lumped (joint) axial Cd" - -typedef ^ ^ ReKi JAxCa - - - "Nodal lumped (joint) axial Cp" - -typedef ^ ^ ReKi JAxCp - - - "Nodal lumped (joint) axial Ca" - -typedef ^ ^ ReKi AxCa - - - "Nodal axial Ca" - -typedef ^ ^ ReKi AxCp - - - "Nodal axial Cp" - -typedef ^ ^ ReKi AxCaMG - - - "Nodal axial Ca with marine growth" - -typedef ^ ^ ReKi AxCpMG - - - "Nodal axial Cp with marine growth" - -typedef ^ ^ ReKi R - - - "Nodal radius (of member at node location)" m -typedef ^ ^ ReKi t - - - "Nodal thickness (of member at node location)" m -typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth (of member at node location)" m -typedef ^ ^ ReKi dRdz - - - "Nodal rate of change in member radius with respect to member axial direction" -typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 -typedef ^ ^ ReKi FillFSLoc - - - "Nodal fill free surface location (of connected chamber to this node)" m -typedef ^ ^ LOGICAL FillFlag - - - "Is this node filled? T/F" - -typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 -typedef ^ ^ INTEGER InpMbrIndx - - - "Index of member this node is connected to (from the user-specified member list in the input file)" - -typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - -typedef ^ ^ LOGICAL PropPot - - - "Is this node modeled with potential flow theory? T/F" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from node local to global coordinates" - -typedef Morison/Morison Morison_MemberType INTEGER Node1Indx - - - "Index of member's node 1 in the master node list" - -typedef ^ ^ INTEGER Node2Indx - - - "Index of member's node 2 in the master node list" - -typedef ^ ^ ReKi R1 - - - "Radius of node 1" m -typedef ^ ^ ReKi t1 - - - "Member thickness at node 1" m -typedef ^ ^ ReKi R2 - - - "Radius of node 2" m -typedef ^ ^ ReKi t2 - - - "Member thickness at node 2" m -typedef ^ ^ ReKi Cd1 - - - "Member Cd at node 1" - -typedef ^ ^ ReKi CdMG1 - - - "Member Cd at node 1 with marine growth" - -typedef ^ ^ ReKi Ca1 - - - "Member Ca at node 1" - -typedef ^ ^ ReKi CaMG1 - - - "Member Ca at node 1 with marine growth" - -typedef ^ ^ ReKi Cp1 - - - "Member Cp at node 1" - -typedef ^ ^ ReKi CpMG1 - - - "Member Cp at node 1 with marine growth" - -typedef ^ ^ ReKi AxCa1 - - - "Member axial Ca at node 1" - -typedef ^ ^ ReKi AxCaMG1 - - - "Member axial Ca at node 1 with marine growth" - -typedef ^ ^ ReKi AxCp1 - - - "Member axial Cp at node 1" - -typedef ^ ^ ReKi AxCpMG1 - - - "Member axial Cp at node 1 with marine growth" - -typedef ^ ^ ReKi Cd2 - - - "Member Cd at node 2" - -typedef ^ ^ ReKi CdMG2 - - - "Member Cd at node 2 with marine growth" - -typedef ^ ^ ReKi Ca2 - - - "Member Ca at node 2" - -typedef ^ ^ ReKi CaMG2 - - - "Member Ca at node 2 with marine growth" - -typedef ^ ^ ReKi Cp2 - - - "Member Cp at node 2" - -typedef ^ ^ ReKi CpMG2 - - - "Member Cp at node 2 with marine growth" - -typedef ^ ^ ReKi AxCa2 - - - "Member axial Ca at node 2" - -typedef ^ ^ ReKi AxCaMG2 - - - "Member axial Ca at node 2 with marine growth" - -typedef ^ ^ ReKi AxCp2 - - - "Member axial Cp at node 2" - -typedef ^ ^ ReKi AxCpMG2 - - - "Member axial Cp at node 2 with marine growth" - -typedef ^ ^ ReKi InpMbrDist1 - - - "Normalized distance of node 1 from the user-specified corresponding member in the input file" - -typedef ^ ^ ReKi InpMbrDist2 - - - "Normalized distance of node 2 from the user-specified corresponding member in the input file" - -typedef ^ ^ ReKi InpMbrLen - - - "Length of the user-specified member this is a part of" - -typedef ^ ^ INTEGER InpMbrIndx - - - "Index of the user-specified member this is a part of" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from member local to global coordinates" - -#typedef ^ ^ INTEGER MGSplitState - - - "Unused" - -#typedef ^ ^ INTEGER WtrSplitState - - - "Unused" - -typedef ^ ^ INTEGER NumSplits - - - "How many splits need to be created in the member/element" - -typedef ^ ^ ReKi Splits {5} - - "Locations of the splits in the Z coordinate" m -typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 -typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m -typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - -typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table" - -typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - -typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m -typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 -typedef ^ ^ ReKi F_Bouy {6} - - "Unused" - -typedef ^ ^ ReKi F_DP {6} - - "Unused" - -typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - -typedef Morison/Morison Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - -typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef Morison/Morison Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m -typedef ^ ^ ReKi MGThck - - - "Marine growth thickness" m -typedef ^ ^ ReKi MGDens - - - "Marine growth density" kg/m^3 -typedef Morison/Morison Morison_MOutput INTEGER MemberID - - - "Member ID for requested output" - -typedef ^ ^ INTEGER NOutLoc - - - "The number of requested output locations" - -typedef ^ ^ ReKi NodeLocs {:} - - "Normalized locations along user-specified member for the outputs" - -typedef ^ ^ INTEGER MemberIDIndx - - - "Index for member in the master list" - -typedef ^ ^ INTEGER Marker1 {:} - - "Index of node in DistribMesh for the start of the member" - -typedef ^ ^ INTEGER Marker2 {:} - - "Index of node in DistribMesh for the end of the member" - -typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - -typedef Morison/Morison Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - -typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - -typedef ^ ^ INTEGER NumMarkers - - - "Number of lumped mesh nodes which are co-located at the requested Joint" - -typedef ^ ^ INTEGER Markers {10} - - "Index of all nodes in lumped mesh which are co-located at the requested Joint" - -# ..... Initialization data ....................................................................................................... -# Define inputs that the initialization routine may need here: -# e.g., the name of the input file, the file root name,etc. -# -typedef Morison/Morison InitInputType ReKi Gravity - - - "Gravity (scalar, positive-valued)" m/s^2 -typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 -typedef ^ ^ ReKi WtrDpth - - - "Water depth (positive-valued)" m -typedef ^ ^ ReKi MSL2SWL - - - "Mean Sea Level to Still Water Level offset" m -typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - -typedef ^ ^ INTEGER NNodes - - - "Total number of nodes in the final software model" - -typedef ^ ^ INTEGER TotalPossibleSuperMembers - - - "Unused: For super member calculations" - -typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - -typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - -typedef ^ ^ INTEGER NElements - - - "Number of elements in the discretized model" - -typedef ^ ^ Morison_MemberType Elements {:} - - "Array of elements which were derived from the user-specified members" - -typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - -typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - -typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - -typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "List of Member property sets" - -typedef ^ ^ ReKi SimplCd - - - "Simple model drag coef" - -typedef ^ ^ ReKi SimplCdMG - - - "Simple model drag coef for marine growth" - -typedef ^ ^ ReKi SimplCa - - - "Simple model Ca" - -typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for marine growth" - -typedef ^ ^ ReKi SimplCp - - - "Simple model Cp" - -typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for marine growth" - -typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca" - -typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for marine growth" - -typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp" - -typedef ^ ^ ReKi SimplAxCpMG - - - "Simple model Axial Cp for marine growth" - -typedef ^ ^ INTEGER NCoefDpth - - - "" - -typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - -typedef ^ ^ INTEGER NCoefMembers - - - "" - -typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - -typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - -typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "Array of user-specified members" - -typedef ^ ^ INTEGER NFillGroups - - - "" - -typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - -typedef ^ ^ INTEGER NMGDepths - - - "" - -typedef ^ ^ Morison_MGDepthsType MGDepths {:} - - "" - -typedef ^ ^ ReKi MGTop - - - "" - -typedef ^ ^ ReKi MGBottom - - - "" - -typedef ^ ^ INTEGER NMOutputs - - - "" - -typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - -typedef ^ ^ INTEGER NJOutputs - - - "" - -typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - -typedef ^ ^ CHARACTER(10) OutList {4032} - - "This list size needs to be the maximum # of possible outputs because of the use of ReadAry()" - -typedef ^ ^ LOGICAL ValidOutList {:} - - "" - -typedef ^ ^ INTEGER NumOuts - - - "" - -typedef ^ ^ INTEGER OutSwtch - - - "" - -typedef ^ ^ LOGICAL OutAll - - - "" - -typedef ^ ^ CHARACTER(1024) OutRootName - - - "" - -typedef ^ ^ INTEGER UnOutFile - - - "" - -typedef ^ ^ INTEGER UnSum - - - "" - -typedef ^ ^ INTEGER NStepWave - - - "" - -typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - -typedef ^ ^ SiKi WaveTime {:} - - "" - -typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - -typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - -typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - -# -# -# Define outputs from the initialization routine here: -# -typedef ^ InitOutputType MeshType DistribMesh - - - "Unused?" - -typedef ^ ^ MeshType LumpedMesh - - - "Unused?" - -typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) -typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - -typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "User-requested Output channel units" - -# -# -# ..... States .................................................................................................................... -# Define continuous (differentiable) states here: -# -typedef ^ ContinuousStateType SiKi DummyContState - - - "Remove this variable if you have continuous states" - -# -# -# Define discrete (nondifferentiable) states here: -# -typedef ^ DiscreteStateType SiKi DummyDiscState - - - "Remove this variable if you have discrete states" - -# -# -# Define constraint states here: -# -typedef ^ ConstraintStateType SiKi DummyConstrState - - - "Remove this variable if you have constraint states" - -# -# -# Define any other states, including integer or logical states here: -typedef ^ OtherStateType IntKi DummyOtherState - - - "Remove this variable if you have other states" - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi D_F_D {:}{:} - - "Distributed viscous drag loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_I {:}{:} - - "Distributed inertial loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_I was computed)" - -typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed bounancy loads at time t, which may not correspond to the WaveTime array of times (for which p%D_F_B was computed)" - -#typedef ^ ^ ReKi D_F_DP {:}{:} - - "Unused: Distributed dynamic pressure loads" - -typedef ^ ^ ReKi D_F_AM {:}{:} - - "Distributed total added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_M {:}{:} - - "Distributed member added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_MG {:}{:} - - "Distributed marine growth added mass (weight) loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_F_AM_F {:}{:} - - "Distributed added mass loads due to flooding/filled fluid at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi D_FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_B {:}{:} - - "" - -typedef ^ ^ ReKi L_F_D {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_I {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_F_AM {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FV {:}{:} - - "Fluid velocity at point element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FA {:}{:} - - "Fluid acceleration at point element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi L_FDynP {:} - - "Fluid dynamic pressure at point element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -# -typedef ^ ParameterType DbKi DT - - - "Time step for continuous state integration & discrete state update" (sec) -typedef ^ ^ ReKi WtrDens - - - "Water density" kg/m^3 -typedef ^ ^ INTEGER NNodes - - - "" - -typedef ^ ^ Morison_NodeType Nodes {:} - - "" - -typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - -typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - -typedef ^ ^ ReKi D_dragConst {:} - - "" - -typedef ^ ^ ReKi L_An {:}{:} - - "" - -typedef ^ ^ ReKi L_F_B {:}{:} - - "" - -typedef ^ ^ ReKi L_F_I {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_F_DP {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_F_BF {:}{:} - - "" - -typedef ^ ^ ReKi L_AM_M {:}{:}{:} - - "" - -typedef ^ ^ ReKi L_dragConst {:} - - "" - -typedef ^ ^ INTEGER NDistribMarkers - - - "" - -#typedef ^ ^ Morison_NodeType DistribMarkers {:} - - "" - -typedef ^ ^ INTEGER distribToNodeIndx {:} - - "" - -typedef ^ ^ INTEGER NLumpedMarkers - - - "" - -typedef ^ ^ INTEGER lumpedToNodeIndx {:} - - "" - -typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - -typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - -typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - -typedef ^ ^ SiKi WaveTime {:} - - "Times for which the wave kinematics are pre-computed" s -typedef ^ ^ INTEGER elementWaterState {:}{:} - - "State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2]" - -typedef ^ ^ INTEGER elementFillState {:} - - "State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2]" - -typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - -typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed buoyancy loads" - -typedef ^ ^ ReKi D_F_BF {:}{:} - - "Distributed filled buoyancy loads" - -typedef ^ ^ ReKi D_F_MG {:}{:} - - "Distributed marine growth loads" - -typedef ^ ^ ReKi D_AM_M {:}{:}{:} - - "Distributed member added mass matrix" - -typedef ^ ^ ReKi D_AM_MG {:} - - "Distributed marine growth added mass matrix (weight)" - -typedef ^ ^ ReKi D_AM_F {:} - - "Distributed added mass matrix due to flooding/filled fluid" - -typedef ^ ^ INTEGER NStepWave - - - "" - -typedef ^ ^ INTEGER NMOutputs - - - "" - -typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - -typedef ^ ^ INTEGER NJOutputs - - - "" - -typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - -typedef ^ ^ OutParmType OutParam {:} - - "" - -typedef ^ ^ INTEGER NumOuts - - - "" - -typedef ^ ^ INTEGER NumOutAll - - - "" - -typedef ^ ^ INTEGER OutSwtch - - - "" - -typedef ^ ^ INTEGER UnOutFile - - - "" - -typedef ^ ^ CHARACTER(20) OutFmt - - - "" - -typedef ^ ^ CHARACTER(20) OutSFmt - - - "" - -typedef ^ ^ CHARACTER(10) Delim - - - "" - -# -# -# ..... Inputs .................................................................................................................... -# Define inputs that are contained on the mesh here: -# -typedef ^ InputType MeshType DistribMesh - - - "Distributed Loads Meshed input data" - -typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed input data" - -# -# -# ..... Outputs ................................................................................................................... -# Define outputs that are contained on the mesh here: -typedef ^ OutputType MeshType DistribMesh - - - "Distributed Loads Meshed output data" - -typedef ^ ^ MeshType LumpedMesh - - - "Lumped Loads Meshed output data" - -typedef ^ ^ ReKi WriteOutput {:} - - "" - From a756bcfe2e4b32e7661142004b41ba53e25f6274 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:14:34 -0600 Subject: [PATCH 175/377] Removed unused registry entries after Morison rework --- modules/hydrodyn/src/Morison.txt | 46 +- modules/hydrodyn/src/Morison_Types.f90 | 1740 +----------------------- 2 files changed, 70 insertions(+), 1716 deletions(-) diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 0addc92bd..f0fc39586 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -64,13 +64,11 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "Index into the appropriate coefs table for this member's properties" - typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "Index into the filled group table if this is a filled member" - typedef ^ ^ LOGICAL PropPot - - - "Flag T/F for whether the member is modeled with potential flow theory" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from local to global coordinates" - typedef ^ ^ INTEGER NElements - - - "number of elements in this member" - typedef ^ ^ ReKi RefLength - - - "the reference total length for this member" m typedef ^ ^ ReKi dl - - - "the reference element length for this member (may be less than MDivSize to achieve uniform element lengths)" m # -typedef ^ Morison_NodeType INTEGER NodeType - - - "Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version]" - -typedef ^ ^ INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - +typedef ^ Morison_NodeType INTEGER JointIndx - - - "Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1" - typedef ^ ^ ReKi Position {3} - - "Position of the node in global coordinates" m typedef ^ ^ INTEGER JointOvrlp - - - "" - typedef ^ ^ INTEGER JointAxIDIndx - - - "" - @@ -80,15 +78,14 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi JAxCa - - - "Nodal lumped (joint) axial Cp" - typedef ^ ^ ReKi JAxCp - - - "Nodal lumped (joint) axial Ca" - typedef ^ ^ ReKi FillDensity - - - "Fill fluid density" kg/m^3 -typedef ^ ^ INTEGER InpMbrIndx - - - "Index of member this node is connected to (from the user-specified member list in the input file)" - -typedef ^ ^ ReKi InpMbrDist - - - "Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end" - typedef ^ ^ ReKi tMG - - - "Nodal thickness with marine growth " m typedef ^ ^ ReKi MGdensity - - - "Nodal density of marine growth" kg/m^3 # typedef ^ Morison_MemberType INTEGER NodeIndx {:} - - "Index of each of the member's nodes in the master node list" - -typedef ^ Morison_MemberType INTEGER MemberID - - - "User-supplied integer ID for this member" - +typedef ^ ^ INTEGER MemberID - - - "User-supplied integer ID for this member" - typedef ^ ^ INTEGER NElements - - - "number of elements in this member" - typedef ^ ^ ReKi RefLength - - - "the reference total length for this member" m +typedef ^ ^ ReKi cosPhi_ref - - - "the reference cosine of the inclination angle of the member" - typedef ^ ^ ReKi dl - - - "the reference element length for this member (may be less than MDivSize to achieve uniform element lengths)" m typedef ^ ^ ReKi k {3} - - "unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn)" m typedef ^ ^ ReKi kkt {3}{3} - - "matrix of matmul(k_hat, transpose(k_hat)" - @@ -139,11 +136,6 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi Cfl_fb {:} - - "axial force constant due to flooded ballast, for each element" N typedef ^ ^ ReKi Cfr_fb {:} - - "radial force constant due to flooded ballast, for each element" N typedef ^ ^ ReKi CM0_fb {:} - - "moment constant due to flooded ballast, for each element about lower node" Nm -typedef ^ ^ ReKi InpMbrDist1 - - - "Normalized distance of node 1 from the user-specified corresponding member in the input file" - -typedef ^ ^ ReKi InpMbrDist2 - - - "Normalized distance of node 2 from the user-specified corresponding member in the input file" - -typedef ^ ^ ReKi InpMbrLen - - - "Length of the user-specified member this is a part of" - -typedef ^ ^ INTEGER InpMbrIndx - - - "Index of the user-specified member this is a part of" - -typedef ^ ^ ReKi R_LToG {3}{3} - - "Rotation matrix to transform from member local to global coordinates" - typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - @@ -151,8 +143,6 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 -typedef ^ ^ ReKi F_Bouy {6} - - "Unused" - -typedef ^ ^ ReKi F_DP {6} - - "Unused" - typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - # typedef ^ Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - @@ -192,8 +182,6 @@ typedef ^ ^ INTEGER typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - typedef ^ Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - -typedef ^ ^ INTEGER NumMarkers - - - "Number of lumped mesh nodes which are co-located at the requested Joint" - -typedef ^ ^ INTEGER Markers {10} - - "Index of all nodes in lumped mesh which are co-located at the requested Joint" - # ..... Initialization data ....................................................................................................... # Define inputs that the initialization routine may need here: # e.g., the name of the input file, the file root name,etc. @@ -206,7 +194,6 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER NNodes - - - "Total number of nodes in the final software model" - typedef ^ ^ Morison_JointType InpJoints {:} - - "Array of user-specified joints" - typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - -typedef ^ ^ Morison_MemberType Members {:} - - "Array of elements which were derived from the user-specified members" - typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - @@ -257,9 +244,9 @@ typedef ^ ^ INTEGER # # Define outputs from the initialization routine here: # -typedef ^ InitOutputType MeshType Mesh - - - "Unused?" - -typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) -typedef ^ ^ CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - +#typedef ^ InitOutputType MeshType Mesh - - - "Unused?" - +#typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) +typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - typedef ^ ^ CHARACTER(10) WriteOutputUnt {:} - - "User-requested Output channel units" - # # @@ -303,7 +290,6 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi F_D_End {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_I_End {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_IMG_End {:}{:} - - "Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_DP_End {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_A_End {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_BF_End {:}{:} - - "" - typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" - @@ -321,37 +307,17 @@ typedef ^ ^ Morison_Mem typedef ^ ^ INTEGER NNodes - - - "" - typedef ^ ^ INTEGER NJoints - - - "Number of user-specified joints" - typedef ^ ^ ReKi I_MG_End {:}{:}{:} - - "Inertial matrix associated with marine growth mass at joint" - -typedef ^ ^ ReKi D_F_I {:}{:}{:} - - "Distributed inertial loads for all WaveTimes" - -typedef ^ ^ ReKi D_F_DP {:}{:}{:} - - "" - -typedef ^ ^ ReKi D_dragConst {:} - - "" - typedef ^ ^ ReKi An_End {:}{:} - - "directional area vector of each joint" m^2 -typedef ^ ^ ReKi F_B_End {:}{:} - - "" - -typedef ^ ^ ReKi F_I_End {:}{:}{:} - - "" - -typedef ^ ^ ReKi F_DP_End {:}{:}{:} - - "" - -typedef ^ ^ ReKi AM_M_End {:}{:}{:} - - "" - typedef ^ ^ ReKi DragConst_End {:} - - "" - typedef ^ ^ ReKi F_WMG_End {:}{:} - - "Joint marine growth weight loads, constant for all t" N typedef ^ ^ ReKi DP_Const_End {:}{:} - - "Constant part of Joint dynamic pressure term" N typedef ^ ^ ReKi Mass_MG_End {:} - - "Joint marine growth mass" kg typedef ^ ^ ReKi AM_End {:}{:}{:} - - "3x3 Joint added mass matrix, constant for all t" N -typedef ^ ^ INTEGER NDistribMarkers - - - "" - -#typedef ^ ^ Morison_NodeType DistribMarkers {:} - - "" - -typedef ^ ^ INTEGER distribToNodeIndx {:} - - "" - -typedef ^ ^ INTEGER NLumpedMarkers - - - "" - -typedef ^ ^ INTEGER lumpedToNodeIndx {:} - - "" - typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" - typedef ^ ^ SiKi WaveAcc {:}{:}{:} - - "" - typedef ^ ^ SiKi WaveDynP {:}{:} - - "" - typedef ^ ^ SiKi WaveTime {:} - - "Times for which the wave kinematics are pre-computed" s -typedef ^ ^ INTEGER elementWaterState {:}{:} - - "State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2]" - -typedef ^ ^ INTEGER elementFillState {:} - - "State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2]" - typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - -typedef ^ ^ ReKi D_F_B {:}{:} - - "Distributed buoyancy loads" - -typedef ^ ^ ReKi D_F_BF {:}{:} - - "Distributed filled buoyancy loads" - -typedef ^ ^ ReKi D_F_MG {:}{:} - - "Distributed marine growth loads" - -typedef ^ ^ ReKi D_AM_M {:}{:}{:} - - "Distributed member added mass matrix" - -typedef ^ ^ ReKi D_AM_MG {:} - - "Distributed marine growth added mass matrix (weight)" - -typedef ^ ^ ReKi D_AM_F {:} - - "Distributed added mass matrix due to flooding/filled fluid" - typedef ^ ^ INTEGER NStepWave - - - "" - typedef ^ ^ INTEGER NMOutputs - - - "" - typedef ^ ^ Morison_MOutput MOutLst {:} - - "" - diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index a359a8edc..a37cea43c 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -103,7 +103,6 @@ MODULE Morison_Types INTEGER(IntKi) :: MmbrCoefIDIndx !< Index into the appropriate coefs table for this member's properties [-] INTEGER(IntKi) :: MmbrFilledIDIndx !< Index into the filled group table if this is a filled member [-] LOGICAL :: PropPot !< Flag T/F for whether the member is modeled with potential flow theory [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< Rotation matrix to transform from local to global coordinates [-] INTEGER(IntKi) :: NElements !< number of elements in this member [-] REAL(ReKi) :: RefLength !< the reference total length for this member [m] REAL(ReKi) :: dl !< the reference element length for this member (may be less than MDivSize to achieve uniform element lengths) [m] @@ -111,7 +110,6 @@ MODULE Morison_Types ! ======================= ! ========= Morison_NodeType ======= TYPE, PUBLIC :: Morison_NodeType - INTEGER(IntKi) :: NodeType !< Node type: 1=End node, 2=Interior node, 3=Super node [unused in current version] [-] INTEGER(IntKi) :: JointIndx !< Joint index from the user joint table that this node corresponds to. If the software created this node, index is set to -1 [-] REAL(ReKi) , DIMENSION(1:3) :: Position !< Position of the node in global coordinates [m] INTEGER(IntKi) :: JointOvrlp !< [-] @@ -122,8 +120,6 @@ MODULE Morison_Types REAL(ReKi) :: JAxCa !< Nodal lumped (joint) axial Cp [-] REAL(ReKi) :: JAxCp !< Nodal lumped (joint) axial Ca [-] REAL(ReKi) :: FillDensity !< Fill fluid density [kg/m^3] - INTEGER(IntKi) :: InpMbrIndx !< Index of member this node is connected to (from the user-specified member list in the input file) [-] - REAL(ReKi) :: InpMbrDist !< Normalized distance of this node from the start of the user-specified member. 0.0=start, 1.0=end [-] REAL(ReKi) :: tMG !< Nodal thickness with marine growth [m] REAL(ReKi) :: MGdensity !< Nodal density of marine growth [kg/m^3] END TYPE Morison_NodeType @@ -134,6 +130,7 @@ MODULE Morison_Types INTEGER(IntKi) :: MemberID !< User-supplied integer ID for this member [-] INTEGER(IntKi) :: NElements !< number of elements in this member [-] REAL(ReKi) :: RefLength !< the reference total length for this member [m] + REAL(ReKi) :: cosPhi_ref !< the reference cosine of the inclination angle of the member [-] REAL(ReKi) :: dl !< the reference element length for this member (may be less than MDivSize to achieve uniform element lengths) [m] REAL(ReKi) , DIMENSION(1:3) :: k !< unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn) [m] REAL(ReKi) , DIMENSION(1:3,1:3) :: kkt !< matrix of matmul(k_hat, transpose(k_hat) [-] @@ -184,11 +181,6 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfl_fb !< axial force constant due to flooded ballast, for each element [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfr_fb !< radial force constant due to flooded ballast, for each element [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CM0_fb !< moment constant due to flooded ballast, for each element about lower node [Nm] - REAL(ReKi) :: InpMbrDist1 !< Normalized distance of node 1 from the user-specified corresponding member in the input file [-] - REAL(ReKi) :: InpMbrDist2 !< Normalized distance of node 2 from the user-specified corresponding member in the input file [-] - REAL(ReKi) :: InpMbrLen !< Length of the user-specified member this is a part of [-] - INTEGER(IntKi) :: InpMbrIndx !< Index of the user-specified member this is a part of [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: R_LToG !< Rotation matrix to transform from member local to global coordinates [-] REAL(ReKi) :: MGvolume !< Volume of marine growth material for this member/element [m^3] REAL(ReKi) :: MDivSize !< User-requested final element length (actual length may vary from this request) [m] INTEGER(IntKi) :: MCoefMod !< Coefs model for member: 1 = simple, 2 =depth, 3 = member-based [-] @@ -196,8 +188,6 @@ MODULE Morison_Types INTEGER(IntKi) :: MmbrFilledIDIndx !< If this member is part of a fill group, this is the index into the master fill group table, if not = -1 [-] REAL(ReKi) :: FillFSLoc !< Z-location of the filled free-surface [m] REAL(ReKi) :: FillDens !< Filled fluid density [kg/m^3] - REAL(ReKi) , DIMENSION(1:6) :: F_Bouy !< Unused [-] - REAL(ReKi) , DIMENSION(1:6) :: F_DP !< Unused [-] LOGICAL :: PropPot !< Is this element/member modeled with potential flow theory T/F [-] END TYPE Morison_MemberType ! ======================= @@ -252,8 +242,6 @@ MODULE Morison_Types TYPE, PUBLIC :: Morison_JOutput INTEGER(IntKi) :: JointID !< Joint ID for the requested output [-] INTEGER(IntKi) :: JointIDIndx !< Joint index in the master list [-] - INTEGER(IntKi) :: NumMarkers !< Number of lumped mesh nodes which are co-located at the requested Joint [-] - INTEGER(IntKi) , DIMENSION(1:10) :: Markers !< Index of all nodes in lumped mesh which are co-located at the requested Joint [-] END TYPE Morison_JOutput ! ======================= ! ========= Morison_InitInputType ======= @@ -266,7 +254,6 @@ MODULE Morison_Types INTEGER(IntKi) :: NNodes !< Total number of nodes in the final software model [-] TYPE(Morison_JointType) , DIMENSION(:), ALLOCATABLE :: InpJoints !< Array of user-specified joints [-] TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< Array of simulation node (some correspond to user-specified joints, others are created by software) [-] - TYPE(Morison_MemberType) , DIMENSION(:), ALLOCATABLE :: Members !< Array of elements which were derived from the user-specified members [-] INTEGER(IntKi) :: NAxCoefs !< Number of axial Coefs entries in input file table [-] TYPE(Morison_AxialCoefType) , DIMENSION(:), ALLOCATABLE :: AxialCoefs !< List of axial coefs [-] INTEGER(IntKi) :: NPropSets !< Number of member property sets [-] @@ -317,8 +304,6 @@ MODULE Morison_Types ! ======================= ! ========= Morison_InitOutputType ======= TYPE, PUBLIC :: Morison_InitOutputType - TYPE(MeshType) :: Mesh !< Unused? [-] - REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: Morison_Rad !< radius of node (for FAST visualization) [(m)] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< User-requested Output channel names [-] CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< User-requested Output channel units [-] END TYPE Morison_InitOutputType @@ -363,7 +348,6 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D_End !< Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I_End !< Lumped intertia loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG_End !< Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP_End !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A_End !< Lumped added mass loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< [-] INTEGER(IntKi) :: LastIndWave !< Last time index used in the wave kinematics arrays [-] @@ -380,36 +364,17 @@ MODULE Morison_Types INTEGER(IntKi) :: NNodes !< [-] INTEGER(IntKi) :: NJoints !< Number of user-specified joints [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: I_MG_End !< Inertial matrix associated with marine growth mass at joint [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_I !< Distributed inertial loads for all WaveTimes [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_F_DP !< [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_dragConst !< [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: An_End !< directional area vector of each joint [m^2] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B_End !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: F_I_End !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: F_DP_End !< [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AM_M_End !< [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DragConst_End !< [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_WMG_End !< Joint marine growth weight loads, constant for all t [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DP_Const_End !< Constant part of Joint dynamic pressure term [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Mass_MG_End !< Joint marine growth mass [kg] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AM_End !< 3x3 Joint added mass matrix, constant for all t [N] - INTEGER(IntKi) :: NDistribMarkers !< [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: distribToNodeIndx !< [-] - INTEGER(IntKi) :: NLumpedMarkers !< [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: lumpedToNodeIndx !< [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc !< [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP !< [-] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times for which the wave kinematics are pre-computed [s] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: elementWaterState !< State indicating if the element a node is attached to at the given time step is in the water [0], above the water [1], or in the seabed [2] [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: elementFillState !< State indicating if the element a node is attached to is in the filled fluid [0], above the fluid [1], or in the seabed [2] [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_B !< Distributed buoyancy loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_BF !< Distributed filled buoyancy loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D_F_MG !< Distributed marine growth loads [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: D_AM_M !< Distributed member added mass matrix [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_AM_MG !< Distributed marine growth added mass matrix (weight) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: D_AM_F !< Distributed added mass matrix due to flooding/filled fluid [-] INTEGER(IntKi) :: NStepWave !< [-] INTEGER(IntKi) :: NMOutputs !< [-] TYPE(Morison_MOutput) , DIMENSION(:), ALLOCATABLE :: MOutLst !< [-] @@ -1343,7 +1308,6 @@ SUBROUTINE Morison_CopyMemberInputType( SrcMemberInputTypeData, DstMemberInputTy ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyMemberInputType' @@ -1376,7 +1340,6 @@ SUBROUTINE Morison_CopyMemberInputType( SrcMemberInputTypeData, DstMemberInputTy DstMemberInputTypeData%MmbrCoefIDIndx = SrcMemberInputTypeData%MmbrCoefIDIndx DstMemberInputTypeData%MmbrFilledIDIndx = SrcMemberInputTypeData%MmbrFilledIDIndx DstMemberInputTypeData%PropPot = SrcMemberInputTypeData%PropPot - DstMemberInputTypeData%R_LToG = SrcMemberInputTypeData%R_LToG DstMemberInputTypeData%NElements = SrcMemberInputTypeData%NElements DstMemberInputTypeData%RefLength = SrcMemberInputTypeData%RefLength DstMemberInputTypeData%dl = SrcMemberInputTypeData%dl @@ -1450,7 +1413,6 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + 1 ! MmbrCoefIDIndx Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx Int_BufSz = Int_BufSz + 1 ! PropPot - Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG Int_BufSz = Int_BufSz + 1 ! NElements Re_BufSz = Re_BufSz + 1 ! RefLength Re_BufSz = Re_BufSz + 1 ! dl @@ -1522,8 +1484,6 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElements Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%RefLength @@ -1552,7 +1512,6 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberInputType' @@ -1617,19 +1576,6 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = Int_Xferred + 1 OutData%PropPot = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%R_LToG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R_LToG))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%R_LToG) - DEALLOCATE(mask2) OutData%NElements = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%RefLength = ReKiBuf( Re_Xferred ) @@ -1653,7 +1599,6 @@ SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, Err ! ErrStat = ErrID_None ErrMsg = "" - DstNodeTypeData%NodeType = SrcNodeTypeData%NodeType DstNodeTypeData%JointIndx = SrcNodeTypeData%JointIndx DstNodeTypeData%Position = SrcNodeTypeData%Position DstNodeTypeData%JointOvrlp = SrcNodeTypeData%JointOvrlp @@ -1664,8 +1609,6 @@ SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, Err DstNodeTypeData%JAxCa = SrcNodeTypeData%JAxCa DstNodeTypeData%JAxCp = SrcNodeTypeData%JAxCp DstNodeTypeData%FillDensity = SrcNodeTypeData%FillDensity - DstNodeTypeData%InpMbrIndx = SrcNodeTypeData%InpMbrIndx - DstNodeTypeData%InpMbrDist = SrcNodeTypeData%InpMbrDist DstNodeTypeData%tMG = SrcNodeTypeData%tMG DstNodeTypeData%MGdensity = SrcNodeTypeData%MGdensity END SUBROUTINE Morison_CopyNodeType @@ -1716,7 +1659,6 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! NodeType Int_BufSz = Int_BufSz + 1 ! JointIndx Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position Int_BufSz = Int_BufSz + 1 ! JointOvrlp @@ -1727,8 +1669,6 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = Re_BufSz + 1 ! JAxCa Re_BufSz = Re_BufSz + 1 ! JAxCp Re_BufSz = Re_BufSz + 1 ! FillDensity - Int_BufSz = Int_BufSz + 1 ! InpMbrIndx - Re_BufSz = Re_BufSz + 1 ! InpMbrDist Re_BufSz = Re_BufSz + 1 ! tMG Re_BufSz = Re_BufSz + 1 ! MGdensity IF ( Re_BufSz .GT. 0 ) THEN @@ -1758,8 +1698,6 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NodeType - Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointIndx Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Position))-1 ) = PACK(InData%Position,.TRUE.) @@ -1780,10 +1718,6 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillDensity Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%InpMbrIndx - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist - Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%tMG Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGdensity @@ -1823,8 +1757,6 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%NodeType = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 OutData%JointIndx = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%Position,1) @@ -1863,10 +1795,6 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%FillDensity = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - OutData%InpMbrIndx = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%InpMbrDist = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 OutData%tMG = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%MGdensity = ReKiBuf( Re_Xferred ) @@ -1904,6 +1832,7 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod DstMemberTypeData%MemberID = SrcMemberTypeData%MemberID DstMemberTypeData%NElements = SrcMemberTypeData%NElements DstMemberTypeData%RefLength = SrcMemberTypeData%RefLength + DstMemberTypeData%cosPhi_ref = SrcMemberTypeData%cosPhi_ref DstMemberTypeData%dl = SrcMemberTypeData%dl DstMemberTypeData%k = SrcMemberTypeData%k DstMemberTypeData%kkt = SrcMemberTypeData%kkt @@ -2350,11 +2279,6 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod END IF DstMemberTypeData%CM0_fb = SrcMemberTypeData%CM0_fb ENDIF - DstMemberTypeData%InpMbrDist1 = SrcMemberTypeData%InpMbrDist1 - DstMemberTypeData%InpMbrDist2 = SrcMemberTypeData%InpMbrDist2 - DstMemberTypeData%InpMbrLen = SrcMemberTypeData%InpMbrLen - DstMemberTypeData%InpMbrIndx = SrcMemberTypeData%InpMbrIndx - DstMemberTypeData%R_LToG = SrcMemberTypeData%R_LToG DstMemberTypeData%MGvolume = SrcMemberTypeData%MGvolume DstMemberTypeData%MDivSize = SrcMemberTypeData%MDivSize DstMemberTypeData%MCoefMod = SrcMemberTypeData%MCoefMod @@ -2362,8 +2286,6 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod DstMemberTypeData%MmbrFilledIDIndx = SrcMemberTypeData%MmbrFilledIDIndx DstMemberTypeData%FillFSLoc = SrcMemberTypeData%FillFSLoc DstMemberTypeData%FillDens = SrcMemberTypeData%FillDens - DstMemberTypeData%F_Bouy = SrcMemberTypeData%F_Bouy - DstMemberTypeData%F_DP = SrcMemberTypeData%F_DP DstMemberTypeData%PropPot = SrcMemberTypeData%PropPot END SUBROUTINE Morison_CopyMemberType @@ -2532,6 +2454,7 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 1 ! MemberID Int_BufSz = Int_BufSz + 1 ! NElements Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! cosPhi_ref Re_BufSz = Re_BufSz + 1 ! dl Re_BufSz = Re_BufSz + SIZE(InData%k) ! k Re_BufSz = Re_BufSz + SIZE(InData%kkt) ! kkt @@ -2726,11 +2649,6 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 2*1 ! CM0_fb upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%CM0_fb) ! CM0_fb END IF - Re_BufSz = Re_BufSz + 1 ! InpMbrDist1 - Re_BufSz = Re_BufSz + 1 ! InpMbrDist2 - Re_BufSz = Re_BufSz + 1 ! InpMbrLen - Int_BufSz = Int_BufSz + 1 ! InpMbrIndx - Re_BufSz = Re_BufSz + SIZE(InData%R_LToG) ! R_LToG Re_BufSz = Re_BufSz + 1 ! MGvolume Re_BufSz = Re_BufSz + 1 ! MDivSize Int_BufSz = Int_BufSz + 1 ! MCoefMod @@ -2738,8 +2656,6 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 1 ! MmbrFilledIDIndx Re_BufSz = Re_BufSz + 1 ! FillFSLoc Re_BufSz = Re_BufSz + 1 ! FillDens - Re_BufSz = Re_BufSz + SIZE(InData%F_Bouy) ! F_Bouy - Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP Int_BufSz = Int_BufSz + 1 ! PropPot IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -2787,6 +2703,8 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_Xferred = Int_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%RefLength Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%cosPhi_ref + Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%dl Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%k))-1 ) = PACK(InData%k,.TRUE.) @@ -3283,16 +3201,6 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IF (SIZE(InData%CM0_fb)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CM0_fb))-1 ) = PACK(InData%CM0_fb,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%CM0_fb) END IF - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrDist2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%InpMbrLen - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%InpMbrIndx - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%R_LToG))-1 ) = PACK(InData%R_LToG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%R_LToG) ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MGvolume Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%MDivSize @@ -3307,10 +3215,6 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%FillDens Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_Bouy))-1 ) = PACK(InData%F_Bouy,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_Bouy) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP))-1 ) = PACK(InData%F_DP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_DP) IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%PropPot , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_PackMemberType @@ -3378,6 +3282,8 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = Int_Xferred + 1 OutData%RefLength = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%cosPhi_ref = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 OutData%dl = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 i1_l = LBOUND(OutData%k,1) @@ -4265,27 +4171,6 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + SIZE(OutData%CM0_fb) DEALLOCATE(mask1) END IF - OutData%InpMbrDist1 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%InpMbrDist2 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%InpMbrLen = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%InpMbrIndx = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%R_LToG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%R_LToG))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%R_LToG) - DEALLOCATE(mask2) OutData%MGvolume = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 OutData%MDivSize = ReKiBuf( Re_Xferred ) @@ -4300,28 +4185,6 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%FillDens = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%F_Bouy,1) - i1_u = UBOUND(OutData%F_Bouy,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%F_Bouy = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_Bouy))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_Bouy) - DEALLOCATE(mask1) - i1_l = LBOUND(OutData%F_DP,1) - i1_u = UBOUND(OutData%F_DP,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%F_DP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_DP) - DEALLOCATE(mask1) OutData%PropPot = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_UnPackMemberType @@ -5121,7 +4984,6 @@ SUBROUTINE Morison_CopyJOutput( SrcJOutputData, DstJOutputData, CtrlCode, ErrSta CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyJOutput' @@ -5130,8 +4992,6 @@ SUBROUTINE Morison_CopyJOutput( SrcJOutputData, DstJOutputData, CtrlCode, ErrSta ErrMsg = "" DstJOutputData%JointID = SrcJOutputData%JointID DstJOutputData%JointIDIndx = SrcJOutputData%JointIDIndx - DstJOutputData%NumMarkers = SrcJOutputData%NumMarkers - DstJOutputData%Markers = SrcJOutputData%Markers END SUBROUTINE Morison_CopyJOutput SUBROUTINE Morison_DestroyJOutput( JOutputData, ErrStat, ErrMsg ) @@ -5182,8 +5042,6 @@ SUBROUTINE Morison_PackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! JointID Int_BufSz = Int_BufSz + 1 ! JointIDIndx - Int_BufSz = Int_BufSz + 1 ! NumMarkers - Int_BufSz = Int_BufSz + SIZE(InData%Markers) ! Markers IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5215,10 +5073,6 @@ SUBROUTINE Morison_PackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%JointIDIndx Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumMarkers - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Markers))-1 ) = PACK(InData%Markers,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Markers) END SUBROUTINE Morison_PackJOutput SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -5240,7 +5094,6 @@ SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackJOutput' @@ -5258,19 +5111,6 @@ SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%JointIDIndx = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%NumMarkers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Markers,1) - i1_u = UBOUND(OutData%Markers,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%Markers = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Markers))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Markers) - DEALLOCATE(mask1) END SUBROUTINE Morison_UnPackJOutput SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) @@ -5327,22 +5167,6 @@ SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO -ENDIF -IF (ALLOCATED(SrcInitInputData%Members)) THEN - i1_l = LBOUND(SrcInitInputData%Members,1) - i1_u = UBOUND(SrcInitInputData%Members,1) - IF (.NOT. ALLOCATED(DstInitInputData%Members)) THEN - ALLOCATE(DstInitInputData%Members(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%Members.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcInitInputData%Members,1), UBOUND(SrcInitInputData%Members,1) - CALL Morison_Copymembertype( SrcInitInputData%Members(i1), DstInitInputData%Members(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO ENDIF DstInitInputData%NAxCoefs = SrcInitInputData%NAxCoefs IF (ALLOCATED(SrcInitInputData%AxialCoefs)) THEN @@ -5626,12 +5450,6 @@ SUBROUTINE Morison_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(InitInputData%Nodes) ENDIF -IF (ALLOCATED(InitInputData%Members)) THEN -DO i1 = LBOUND(InitInputData%Members,1), UBOUND(InitInputData%Members,1) - CALL Morison_Destroymembertype( InitInputData%Members(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(InitInputData%Members) -ENDIF IF (ALLOCATED(InitInputData%AxialCoefs)) THEN DO i1 = LBOUND(InitInputData%AxialCoefs,1), UBOUND(InitInputData%AxialCoefs,1) CALL Morison_Destroyaxialcoeftype( InitInputData%AxialCoefs(i1), ErrStat, ErrMsg ) @@ -5793,29 +5611,6 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E DEALLOCATE(Int_Buf) END IF END DO - END IF - Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no - IF ( ALLOCATED(InData%Members) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Members upper/lower bounds for each dimension - DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) - Int_BufSz = Int_BufSz + 3 ! Members: size of buffers for each call to pack subtype - CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Members - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Members - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Members - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Members - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO END IF Int_BufSz = Int_BufSz + 1 ! NAxCoefs Int_BufSz = Int_BufSz + 1 ! AxialCoefs allocated yes/no @@ -6206,47 +6001,6 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%Members) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%Members,1), UBOUND(InData%Members,1) - CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Members(i1), ErrStat2, ErrMsg2, OnlySize ) ! Members - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NAxCoefs Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%AxialCoefs) ) THEN @@ -6941,62 +6695,6 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Members)) DEALLOCATE(OutData%Members) - ALLOCATE(OutData%Members(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%Members,1), UBOUND(OutData%Members,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Members(i1), ErrStat2, ErrMsg2 ) ! Members - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF OutData%NAxCoefs = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxialCoefs not allocated @@ -7737,7 +7435,7 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END SUBROUTINE Morison_UnPackInitInput SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(Morison_InitOutputType), INTENT(INOUT) :: SrcInitOutputData + TYPE(Morison_InitOutputType), INTENT(IN) :: SrcInitOutputData TYPE(Morison_InitOutputType), INTENT(INOUT) :: DstInitOutputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat @@ -7751,21 +7449,6 @@ SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCod ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshCopy( SrcInitOutputData%Mesh, DstInitOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcInitOutputData%Morison_Rad)) THEN - i1_l = LBOUND(SrcInitOutputData%Morison_Rad,1) - i1_u = UBOUND(SrcInitOutputData%Morison_Rad,1) - IF (.NOT. ALLOCATED(DstInitOutputData%Morison_Rad)) THEN - ALLOCATE(DstInitOutputData%Morison_Rad(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%Morison_Rad.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%Morison_Rad = SrcInitOutputData%Morison_Rad -ENDIF IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) @@ -7801,10 +7484,6 @@ SUBROUTINE Morison_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" - CALL MeshDestroy( InitOutputData%Mesh, ErrStat, ErrMsg ) -IF (ALLOCATED(InitOutputData%Morison_Rad)) THEN - DEALLOCATE(InitOutputData%Morison_Rad) -ENDIF IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN DEALLOCATE(InitOutputData%WriteOutputHdr) ENDIF @@ -7848,29 +7527,6 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Mesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Mesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Mesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Mesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 1 ! Morison_Rad allocated yes/no - IF ( ALLOCATED(InData%Morison_Rad) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Morison_Rad upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Morison_Rad) ! Morison_Rad - END IF Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension @@ -7908,47 +7564,6 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF ( .NOT. ALLOCATED(InData%Morison_Rad) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Morison_Rad,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Morison_Rad,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Morison_Rad)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Morison_Rad))-1 ) = PACK(InData%Morison_Rad,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Morison_Rad) - END IF IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8018,69 +7633,6 @@ SUBROUTINE Morison_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Morison_Rad not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Morison_Rad)) DEALLOCATE(OutData%Morison_Rad) - ALLOCATE(OutData%Morison_Rad(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Morison_Rad.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Morison_Rad)>0) OutData%Morison_Rad = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Morison_Rad))-1 ), mask1, 0.0_ReKi ), SiKi) - Re_Xferred = Re_Xferred + SIZE(OutData%Morison_Rad) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -8925,20 +8477,6 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg END IF DstMiscData%F_IMG_End = SrcMiscData%F_IMG_End ENDIF -IF (ALLOCATED(SrcMiscData%F_DP_End)) THEN - i1_l = LBOUND(SrcMiscData%F_DP_End,1) - i1_u = UBOUND(SrcMiscData%F_DP_End,1) - i2_l = LBOUND(SrcMiscData%F_DP_End,2) - i2_u = UBOUND(SrcMiscData%F_DP_End,2) - IF (.NOT. ALLOCATED(DstMiscData%F_DP_End)) THEN - ALLOCATE(DstMiscData%F_DP_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_DP_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_DP_End = SrcMiscData%F_DP_End -ENDIF IF (ALLOCATED(SrcMiscData%F_A_End)) THEN i1_l = LBOUND(SrcMiscData%F_A_End,1) i1_u = UBOUND(SrcMiscData%F_A_End,1) @@ -9033,9 +8571,6 @@ SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%F_IMG_End)) THEN DEALLOCATE(MiscData%F_IMG_End) ENDIF -IF (ALLOCATED(MiscData%F_DP_End)) THEN - DEALLOCATE(MiscData%F_DP_End) -ENDIF IF (ALLOCATED(MiscData%F_A_End)) THEN DEALLOCATE(MiscData%F_A_End) ENDIF @@ -9169,11 +8704,6 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*2 ! F_IMG_End upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%F_IMG_End) ! F_IMG_End END IF - Int_BufSz = Int_BufSz + 1 ! F_DP_End allocated yes/no - IF ( ALLOCATED(InData%F_DP_End) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_DP_End upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_DP_End) ! F_DP_End - END IF Int_BufSz = Int_BufSz + 1 ! F_A_End allocated yes/no IF ( ALLOCATED(InData%F_A_End) ) THEN Int_BufSz = Int_BufSz + 2*2 ! F_A_End upper/lower bounds for each dimension @@ -9494,22 +9024,6 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IF (SIZE(InData%F_IMG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_IMG_End))-1 ) = PACK(InData%F_IMG_End,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%F_IMG_End) END IF - IF ( .NOT. ALLOCATED(InData%F_DP_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F_DP_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP_End))-1 ) = PACK(InData%F_DP_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_DP_End) - END IF IF ( .NOT. ALLOCATED(InData%F_A_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10042,32 +9556,6 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = Re_Xferred + SIZE(OutData%F_IMG_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_DP_End)) DEALLOCATE(OutData%F_DP_End) - ALLOCATE(OutData%F_DP_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%F_DP_End)>0) OutData%F_DP_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP_End))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_DP_End) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_A_End not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10180,50 +9668,6 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF DstParamData%I_MG_End = SrcParamData%I_MG_End ENDIF -IF (ALLOCATED(SrcParamData%D_F_I)) THEN - i1_l = LBOUND(SrcParamData%D_F_I,1) - i1_u = UBOUND(SrcParamData%D_F_I,1) - i2_l = LBOUND(SrcParamData%D_F_I,2) - i2_u = UBOUND(SrcParamData%D_F_I,2) - i3_l = LBOUND(SrcParamData%D_F_I,3) - i3_u = UBOUND(SrcParamData%D_F_I,3) - IF (.NOT. ALLOCATED(DstParamData%D_F_I)) THEN - ALLOCATE(DstParamData%D_F_I(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_F_I = SrcParamData%D_F_I -ENDIF -IF (ALLOCATED(SrcParamData%D_F_DP)) THEN - i1_l = LBOUND(SrcParamData%D_F_DP,1) - i1_u = UBOUND(SrcParamData%D_F_DP,1) - i2_l = LBOUND(SrcParamData%D_F_DP,2) - i2_u = UBOUND(SrcParamData%D_F_DP,2) - i3_l = LBOUND(SrcParamData%D_F_DP,3) - i3_u = UBOUND(SrcParamData%D_F_DP,3) - IF (.NOT. ALLOCATED(DstParamData%D_F_DP)) THEN - ALLOCATE(DstParamData%D_F_DP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_DP.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_F_DP = SrcParamData%D_F_DP -ENDIF -IF (ALLOCATED(SrcParamData%D_dragConst)) THEN - i1_l = LBOUND(SrcParamData%D_dragConst,1) - i1_u = UBOUND(SrcParamData%D_dragConst,1) - IF (.NOT. ALLOCATED(DstParamData%D_dragConst)) THEN - ALLOCATE(DstParamData%D_dragConst(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_dragConst.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_dragConst = SrcParamData%D_dragConst -ENDIF IF (ALLOCATED(SrcParamData%An_End)) THEN i1_l = LBOUND(SrcParamData%An_End,1) i1_u = UBOUND(SrcParamData%An_End,1) @@ -10238,68 +9682,6 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF DstParamData%An_End = SrcParamData%An_End ENDIF -IF (ALLOCATED(SrcParamData%F_B_End)) THEN - i1_l = LBOUND(SrcParamData%F_B_End,1) - i1_u = UBOUND(SrcParamData%F_B_End,1) - i2_l = LBOUND(SrcParamData%F_B_End,2) - i2_u = UBOUND(SrcParamData%F_B_End,2) - IF (.NOT. ALLOCATED(DstParamData%F_B_End)) THEN - ALLOCATE(DstParamData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_B_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%F_B_End = SrcParamData%F_B_End -ENDIF -IF (ALLOCATED(SrcParamData%F_I_End)) THEN - i1_l = LBOUND(SrcParamData%F_I_End,1) - i1_u = UBOUND(SrcParamData%F_I_End,1) - i2_l = LBOUND(SrcParamData%F_I_End,2) - i2_u = UBOUND(SrcParamData%F_I_End,2) - i3_l = LBOUND(SrcParamData%F_I_End,3) - i3_u = UBOUND(SrcParamData%F_I_End,3) - IF (.NOT. ALLOCATED(DstParamData%F_I_End)) THEN - ALLOCATE(DstParamData%F_I_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_I_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%F_I_End = SrcParamData%F_I_End -ENDIF -IF (ALLOCATED(SrcParamData%F_DP_End)) THEN - i1_l = LBOUND(SrcParamData%F_DP_End,1) - i1_u = UBOUND(SrcParamData%F_DP_End,1) - i2_l = LBOUND(SrcParamData%F_DP_End,2) - i2_u = UBOUND(SrcParamData%F_DP_End,2) - i3_l = LBOUND(SrcParamData%F_DP_End,3) - i3_u = UBOUND(SrcParamData%F_DP_End,3) - IF (.NOT. ALLOCATED(DstParamData%F_DP_End)) THEN - ALLOCATE(DstParamData%F_DP_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F_DP_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%F_DP_End = SrcParamData%F_DP_End -ENDIF -IF (ALLOCATED(SrcParamData%AM_M_End)) THEN - i1_l = LBOUND(SrcParamData%AM_M_End,1) - i1_u = UBOUND(SrcParamData%AM_M_End,1) - i2_l = LBOUND(SrcParamData%AM_M_End,2) - i2_u = UBOUND(SrcParamData%AM_M_End,2) - i3_l = LBOUND(SrcParamData%AM_M_End,3) - i3_u = UBOUND(SrcParamData%AM_M_End,3) - IF (.NOT. ALLOCATED(DstParamData%AM_M_End)) THEN - ALLOCATE(DstParamData%AM_M_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM_M_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%AM_M_End = SrcParamData%AM_M_End -ENDIF IF (ALLOCATED(SrcParamData%DragConst_End)) THEN i1_l = LBOUND(SrcParamData%DragConst_End,1) i1_u = UBOUND(SrcParamData%DragConst_End,1) @@ -10367,32 +9749,6 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF END IF DstParamData%AM_End = SrcParamData%AM_End -ENDIF - DstParamData%NDistribMarkers = SrcParamData%NDistribMarkers -IF (ALLOCATED(SrcParamData%distribToNodeIndx)) THEN - i1_l = LBOUND(SrcParamData%distribToNodeIndx,1) - i1_u = UBOUND(SrcParamData%distribToNodeIndx,1) - IF (.NOT. ALLOCATED(DstParamData%distribToNodeIndx)) THEN - ALLOCATE(DstParamData%distribToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%distribToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%distribToNodeIndx = SrcParamData%distribToNodeIndx -ENDIF - DstParamData%NLumpedMarkers = SrcParamData%NLumpedMarkers -IF (ALLOCATED(SrcParamData%lumpedToNodeIndx)) THEN - i1_l = LBOUND(SrcParamData%lumpedToNodeIndx,1) - i1_u = UBOUND(SrcParamData%lumpedToNodeIndx,1) - IF (.NOT. ALLOCATED(DstParamData%lumpedToNodeIndx)) THEN - ALLOCATE(DstParamData%lumpedToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%lumpedToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%lumpedToNodeIndx = SrcParamData%lumpedToNodeIndx ENDIF IF (ALLOCATED(SrcParamData%WaveVel)) THEN i1_l = LBOUND(SrcParamData%WaveVel,1) @@ -10452,32 +9808,6 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF DstParamData%WaveTime = SrcParamData%WaveTime ENDIF -IF (ALLOCATED(SrcParamData%elementWaterState)) THEN - i1_l = LBOUND(SrcParamData%elementWaterState,1) - i1_u = UBOUND(SrcParamData%elementWaterState,1) - i2_l = LBOUND(SrcParamData%elementWaterState,2) - i2_u = UBOUND(SrcParamData%elementWaterState,2) - IF (.NOT. ALLOCATED(DstParamData%elementWaterState)) THEN - ALLOCATE(DstParamData%elementWaterState(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%elementWaterState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%elementWaterState = SrcParamData%elementWaterState -ENDIF -IF (ALLOCATED(SrcParamData%elementFillState)) THEN - i1_l = LBOUND(SrcParamData%elementFillState,1) - i1_u = UBOUND(SrcParamData%elementFillState,1) - IF (.NOT. ALLOCATED(DstParamData%elementFillState)) THEN - ALLOCATE(DstParamData%elementFillState(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%elementFillState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%elementFillState = SrcParamData%elementFillState -ENDIF IF (ALLOCATED(SrcParamData%nodeInWater)) THEN i1_l = LBOUND(SrcParamData%nodeInWater,1) i1_u = UBOUND(SrcParamData%nodeInWater,1) @@ -10491,88 +9821,6 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err END IF END IF DstParamData%nodeInWater = SrcParamData%nodeInWater -ENDIF -IF (ALLOCATED(SrcParamData%D_F_B)) THEN - i1_l = LBOUND(SrcParamData%D_F_B,1) - i1_u = UBOUND(SrcParamData%D_F_B,1) - i2_l = LBOUND(SrcParamData%D_F_B,2) - i2_u = UBOUND(SrcParamData%D_F_B,2) - IF (.NOT. ALLOCATED(DstParamData%D_F_B)) THEN - ALLOCATE(DstParamData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_B.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_F_B = SrcParamData%D_F_B -ENDIF -IF (ALLOCATED(SrcParamData%D_F_BF)) THEN - i1_l = LBOUND(SrcParamData%D_F_BF,1) - i1_u = UBOUND(SrcParamData%D_F_BF,1) - i2_l = LBOUND(SrcParamData%D_F_BF,2) - i2_u = UBOUND(SrcParamData%D_F_BF,2) - IF (.NOT. ALLOCATED(DstParamData%D_F_BF)) THEN - ALLOCATE(DstParamData%D_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_F_BF = SrcParamData%D_F_BF -ENDIF -IF (ALLOCATED(SrcParamData%D_F_MG)) THEN - i1_l = LBOUND(SrcParamData%D_F_MG,1) - i1_u = UBOUND(SrcParamData%D_F_MG,1) - i2_l = LBOUND(SrcParamData%D_F_MG,2) - i2_u = UBOUND(SrcParamData%D_F_MG,2) - IF (.NOT. ALLOCATED(DstParamData%D_F_MG)) THEN - ALLOCATE(DstParamData%D_F_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_F_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_F_MG = SrcParamData%D_F_MG -ENDIF -IF (ALLOCATED(SrcParamData%D_AM_M)) THEN - i1_l = LBOUND(SrcParamData%D_AM_M,1) - i1_u = UBOUND(SrcParamData%D_AM_M,1) - i2_l = LBOUND(SrcParamData%D_AM_M,2) - i2_u = UBOUND(SrcParamData%D_AM_M,2) - i3_l = LBOUND(SrcParamData%D_AM_M,3) - i3_u = UBOUND(SrcParamData%D_AM_M,3) - IF (.NOT. ALLOCATED(DstParamData%D_AM_M)) THEN - ALLOCATE(DstParamData%D_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_AM_M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_AM_M = SrcParamData%D_AM_M -ENDIF -IF (ALLOCATED(SrcParamData%D_AM_MG)) THEN - i1_l = LBOUND(SrcParamData%D_AM_MG,1) - i1_u = UBOUND(SrcParamData%D_AM_MG,1) - IF (.NOT. ALLOCATED(DstParamData%D_AM_MG)) THEN - ALLOCATE(DstParamData%D_AM_MG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_AM_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_AM_MG = SrcParamData%D_AM_MG -ENDIF -IF (ALLOCATED(SrcParamData%D_AM_F)) THEN - i1_l = LBOUND(SrcParamData%D_AM_F,1) - i1_u = UBOUND(SrcParamData%D_AM_F,1) - IF (.NOT. ALLOCATED(DstParamData%D_AM_F)) THEN - ALLOCATE(DstParamData%D_AM_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D_AM_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D_AM_F = SrcParamData%D_AM_F ENDIF DstParamData%NStepWave = SrcParamData%NStepWave DstParamData%NMOutputs = SrcParamData%NMOutputs @@ -10652,30 +9900,9 @@ SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%I_MG_End)) THEN DEALLOCATE(ParamData%I_MG_End) ENDIF -IF (ALLOCATED(ParamData%D_F_I)) THEN - DEALLOCATE(ParamData%D_F_I) -ENDIF -IF (ALLOCATED(ParamData%D_F_DP)) THEN - DEALLOCATE(ParamData%D_F_DP) -ENDIF -IF (ALLOCATED(ParamData%D_dragConst)) THEN - DEALLOCATE(ParamData%D_dragConst) -ENDIF IF (ALLOCATED(ParamData%An_End)) THEN DEALLOCATE(ParamData%An_End) ENDIF -IF (ALLOCATED(ParamData%F_B_End)) THEN - DEALLOCATE(ParamData%F_B_End) -ENDIF -IF (ALLOCATED(ParamData%F_I_End)) THEN - DEALLOCATE(ParamData%F_I_End) -ENDIF -IF (ALLOCATED(ParamData%F_DP_End)) THEN - DEALLOCATE(ParamData%F_DP_End) -ENDIF -IF (ALLOCATED(ParamData%AM_M_End)) THEN - DEALLOCATE(ParamData%AM_M_End) -ENDIF IF (ALLOCATED(ParamData%DragConst_End)) THEN DEALLOCATE(ParamData%DragConst_End) ENDIF @@ -10691,12 +9918,6 @@ SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%AM_End)) THEN DEALLOCATE(ParamData%AM_End) ENDIF -IF (ALLOCATED(ParamData%distribToNodeIndx)) THEN - DEALLOCATE(ParamData%distribToNodeIndx) -ENDIF -IF (ALLOCATED(ParamData%lumpedToNodeIndx)) THEN - DEALLOCATE(ParamData%lumpedToNodeIndx) -ENDIF IF (ALLOCATED(ParamData%WaveVel)) THEN DEALLOCATE(ParamData%WaveVel) ENDIF @@ -10709,33 +9930,9 @@ SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%WaveTime)) THEN DEALLOCATE(ParamData%WaveTime) ENDIF -IF (ALLOCATED(ParamData%elementWaterState)) THEN - DEALLOCATE(ParamData%elementWaterState) -ENDIF -IF (ALLOCATED(ParamData%elementFillState)) THEN - DEALLOCATE(ParamData%elementFillState) -ENDIF IF (ALLOCATED(ParamData%nodeInWater)) THEN DEALLOCATE(ParamData%nodeInWater) ENDIF -IF (ALLOCATED(ParamData%D_F_B)) THEN - DEALLOCATE(ParamData%D_F_B) -ENDIF -IF (ALLOCATED(ParamData%D_F_BF)) THEN - DEALLOCATE(ParamData%D_F_BF) -ENDIF -IF (ALLOCATED(ParamData%D_F_MG)) THEN - DEALLOCATE(ParamData%D_F_MG) -ENDIF -IF (ALLOCATED(ParamData%D_AM_M)) THEN - DEALLOCATE(ParamData%D_AM_M) -ENDIF -IF (ALLOCATED(ParamData%D_AM_MG)) THEN - DEALLOCATE(ParamData%D_AM_MG) -ENDIF -IF (ALLOCATED(ParamData%D_AM_F)) THEN - DEALLOCATE(ParamData%D_AM_F) -ENDIF IF (ALLOCATED(ParamData%MOutLst)) THEN DO i1 = LBOUND(ParamData%MOutLst,1), UBOUND(ParamData%MOutLst,1) CALL Morison_Destroymoutput( ParamData%MOutLst(i1), ErrStat, ErrMsg ) @@ -10827,46 +10024,11 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + 2*3 ! I_MG_End upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%I_MG_End) ! I_MG_End END IF - Int_BufSz = Int_BufSz + 1 ! D_F_I allocated yes/no - IF ( ALLOCATED(InData%D_F_I) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! D_F_I upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_I) ! D_F_I - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_DP allocated yes/no - IF ( ALLOCATED(InData%D_F_DP) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! D_F_DP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_DP) ! D_F_DP - END IF - Int_BufSz = Int_BufSz + 1 ! D_dragConst allocated yes/no - IF ( ALLOCATED(InData%D_dragConst) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! D_dragConst upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_dragConst) ! D_dragConst - END IF Int_BufSz = Int_BufSz + 1 ! An_End allocated yes/no IF ( ALLOCATED(InData%An_End) ) THEN Int_BufSz = Int_BufSz + 2*2 ! An_End upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%An_End) ! An_End END IF - Int_BufSz = Int_BufSz + 1 ! F_B_End allocated yes/no - IF ( ALLOCATED(InData%F_B_End) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_B_End upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_B_End) ! F_B_End - END IF - Int_BufSz = Int_BufSz + 1 ! F_I_End allocated yes/no - IF ( ALLOCATED(InData%F_I_End) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! F_I_End upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_I_End) ! F_I_End - END IF - Int_BufSz = Int_BufSz + 1 ! F_DP_End allocated yes/no - IF ( ALLOCATED(InData%F_DP_End) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! F_DP_End upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_DP_End) ! F_DP_End - END IF - Int_BufSz = Int_BufSz + 1 ! AM_M_End allocated yes/no - IF ( ALLOCATED(InData%AM_M_End) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! AM_M_End upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%AM_M_End) ! AM_M_End - END IF Int_BufSz = Int_BufSz + 1 ! DragConst_End allocated yes/no IF ( ALLOCATED(InData%DragConst_End) ) THEN Int_BufSz = Int_BufSz + 2*1 ! DragConst_End upper/lower bounds for each dimension @@ -10891,18 +10053,6 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF ( ALLOCATED(InData%AM_End) ) THEN Int_BufSz = Int_BufSz + 2*3 ! AM_End upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%AM_End) ! AM_End - END IF - Int_BufSz = Int_BufSz + 1 ! NDistribMarkers - Int_BufSz = Int_BufSz + 1 ! distribToNodeIndx allocated yes/no - IF ( ALLOCATED(InData%distribToNodeIndx) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! distribToNodeIndx upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%distribToNodeIndx) ! distribToNodeIndx - END IF - Int_BufSz = Int_BufSz + 1 ! NLumpedMarkers - Int_BufSz = Int_BufSz + 1 ! lumpedToNodeIndx allocated yes/no - IF ( ALLOCATED(InData%lumpedToNodeIndx) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! lumpedToNodeIndx upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%lumpedToNodeIndx) ! lumpedToNodeIndx END IF Int_BufSz = Int_BufSz + 1 ! WaveVel allocated yes/no IF ( ALLOCATED(InData%WaveVel) ) THEN @@ -10924,50 +10074,10 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WaveTime) ! WaveTime END IF - Int_BufSz = Int_BufSz + 1 ! elementWaterState allocated yes/no - IF ( ALLOCATED(InData%elementWaterState) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! elementWaterState upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%elementWaterState) ! elementWaterState - END IF - Int_BufSz = Int_BufSz + 1 ! elementFillState allocated yes/no - IF ( ALLOCATED(InData%elementFillState) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! elementFillState upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%elementFillState) ! elementFillState - END IF Int_BufSz = Int_BufSz + 1 ! nodeInWater allocated yes/no IF ( ALLOCATED(InData%nodeInWater) ) THEN Int_BufSz = Int_BufSz + 2*2 ! nodeInWater upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_B allocated yes/no - IF ( ALLOCATED(InData%D_F_B) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_B) ! D_F_B - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_BF allocated yes/no - IF ( ALLOCATED(InData%D_F_BF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_BF upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_BF) ! D_F_BF - END IF - Int_BufSz = Int_BufSz + 1 ! D_F_MG allocated yes/no - IF ( ALLOCATED(InData%D_F_MG) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D_F_MG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_F_MG) ! D_F_MG - END IF - Int_BufSz = Int_BufSz + 1 ! D_AM_M allocated yes/no - IF ( ALLOCATED(InData%D_AM_M) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! D_AM_M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_AM_M) ! D_AM_M - END IF - Int_BufSz = Int_BufSz + 1 ! D_AM_MG allocated yes/no - IF ( ALLOCATED(InData%D_AM_MG) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! D_AM_MG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_AM_MG) ! D_AM_MG - END IF - Int_BufSz = Int_BufSz + 1 ! D_AM_F allocated yes/no - IF ( ALLOCATED(InData%D_AM_F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! D_AM_F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D_AM_F) ! D_AM_F END IF Int_BufSz = Int_BufSz + 1 ! NStepWave Int_BufSz = Int_BufSz + 1 ! NMOutputs @@ -11149,192 +10259,68 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF (SIZE(InData%I_MG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%I_MG_End))-1 ) = PACK(InData%I_MG_End,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%I_MG_End) END IF - IF ( .NOT. ALLOCATED(InData%D_F_I) ) THEN + IF ( .NOT. ALLOCATED(InData%An_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_I,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_I,3) + IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_I)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_I))-1 ) = PACK(InData%D_F_I,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_I) + IF (SIZE(InData%An_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%An_End))-1 ) = PACK(InData%An_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%An_End) END IF - IF ( .NOT. ALLOCATED(InData%D_F_DP) ) THEN + IF ( .NOT. ALLOCATED(InData%DragConst_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_DP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_DP,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_DP,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_DP,3) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DragConst_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DragConst_End,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_F_DP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_DP))-1 ) = PACK(InData%D_F_DP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_DP) + IF (SIZE(InData%DragConst_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DragConst_End))-1 ) = PACK(InData%DragConst_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%DragConst_End) END IF - IF ( .NOT. ALLOCATED(InData%D_dragConst) ) THEN + IF ( .NOT. ALLOCATED(InData%F_WMG_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_dragConst,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_dragConst,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D_dragConst)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_dragConst))-1 ) = PACK(InData%D_dragConst,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_dragConst) + IF (SIZE(InData%F_WMG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_WMG_End))-1 ) = PACK(InData%F_WMG_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F_WMG_End) END IF - IF ( .NOT. ALLOCATED(InData%An_End) ) THEN + IF ( .NOT. ALLOCATED(InData%DP_Const_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%An_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%An_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%An_End))-1 ) = PACK(InData%An_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%An_End) + IF (SIZE(InData%DP_Const_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DP_Const_End))-1 ) = PACK(InData%DP_Const_End,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%DP_Const_End) END IF - IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F_B_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_B_End))-1 ) = PACK(InData%F_B_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_B_End) - END IF - IF ( .NOT. ALLOCATED(InData%F_I_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F_I_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_I_End))-1 ) = PACK(InData%F_I_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_I_End) - END IF - IF ( .NOT. ALLOCATED(InData%F_DP_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP_End,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP_End,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F_DP_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_DP_End))-1 ) = PACK(InData%F_DP_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_DP_End) - END IF - IF ( .NOT. ALLOCATED(InData%AM_M_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM_M_End,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_M_End,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%AM_M_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM_M_End))-1 ) = PACK(InData%AM_M_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%AM_M_End) - END IF - IF ( .NOT. ALLOCATED(InData%DragConst_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DragConst_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DragConst_End,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DragConst_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DragConst_End))-1 ) = PACK(InData%DragConst_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DragConst_End) - END IF - IF ( .NOT. ALLOCATED(InData%F_WMG_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F_WMG_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F_WMG_End))-1 ) = PACK(InData%F_WMG_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F_WMG_End) - END IF - IF ( .NOT. ALLOCATED(InData%DP_Const_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DP_Const_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DP_Const_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DP_Const_End))-1 ) = PACK(InData%DP_Const_End,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DP_Const_End) - END IF - IF ( .NOT. ALLOCATED(InData%Mass_MG_End) ) THEN + IF ( .NOT. ALLOCATED(InData%Mass_MG_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE @@ -11365,36 +10351,6 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF (SIZE(InData%AM_End)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM_End))-1 ) = PACK(InData%AM_End,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%AM_End) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NDistribMarkers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%distribToNodeIndx) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%distribToNodeIndx,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%distribToNodeIndx,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%distribToNodeIndx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%distribToNodeIndx))-1 ) = PACK(InData%distribToNodeIndx,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%distribToNodeIndx) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NLumpedMarkers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%lumpedToNodeIndx) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%lumpedToNodeIndx,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lumpedToNodeIndx,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%lumpedToNodeIndx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%lumpedToNodeIndx))-1 ) = PACK(InData%lumpedToNodeIndx,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%lumpedToNodeIndx) END IF IF ( .NOT. ALLOCATED(InData%WaveVel) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -11463,35 +10419,6 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF (SIZE(InData%WaveTime)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WaveTime))-1 ) = PACK(InData%WaveTime,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%WaveTime) END IF - IF ( .NOT. ALLOCATED(InData%elementWaterState) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementWaterState,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementWaterState,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%elementWaterState)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%elementWaterState))-1 ) = PACK(InData%elementWaterState,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%elementWaterState) - END IF - IF ( .NOT. ALLOCATED(InData%elementFillState) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementFillState,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementFillState,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%elementFillState)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%elementFillState))-1 ) = PACK(InData%elementFillState,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%elementFillState) - END IF IF ( .NOT. ALLOCATED(InData%nodeInWater) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -11507,99 +10434,6 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IF (SIZE(InData%nodeInWater)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%nodeInWater))-1 ) = PACK(InData%nodeInWater,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%nodeInWater) - END IF - IF ( .NOT. ALLOCATED(InData%D_F_B) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_F_B)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_B))-1 ) = PACK(InData%D_F_B,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_B) - END IF - IF ( .NOT. ALLOCATED(InData%D_F_BF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_BF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_BF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_F_BF)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_BF))-1 ) = PACK(InData%D_F_BF,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_BF) - END IF - IF ( .NOT. ALLOCATED(InData%D_F_MG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_MG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_MG,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_F_MG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_F_MG))-1 ) = PACK(InData%D_F_MG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_F_MG) - END IF - IF ( .NOT. ALLOCATED(InData%D_AM_M) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_AM_M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_AM_M))-1 ) = PACK(InData%D_AM_M,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_AM_M) - END IF - IF ( .NOT. ALLOCATED(InData%D_AM_MG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_MG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_MG,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_AM_MG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_AM_MG))-1 ) = PACK(InData%D_AM_MG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_AM_MG) - END IF - IF ( .NOT. ALLOCATED(InData%D_AM_F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D_AM_F)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D_AM_F))-1 ) = PACK(InData%D_AM_F,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D_AM_F) END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NStepWave Int_Xferred = Int_Xferred + 1 @@ -11886,36 +10720,7 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = Re_Xferred + SIZE(OutData%I_MG_End) DEALLOCATE(mask3) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_I not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_I)) DEALLOCATE(OutData%D_F_I) - ALLOCATE(OutData%D_F_I(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%D_F_I)>0) OutData%D_F_I = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_I))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_I) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_DP not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! An_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -11925,36 +10730,33 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_DP)) DEALLOCATE(OutData%D_F_DP) - ALLOCATE(OutData%D_F_DP(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%An_End)) DEALLOCATE(OutData%An_End) + ALLOCATE(OutData%An_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_DP.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%An_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) RETURN END IF - mask3 = .TRUE. - IF (SIZE(OutData%D_F_DP)>0) OutData%D_F_DP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_DP))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_DP) - DEALLOCATE(mask3) + mask2 = .TRUE. + IF (SIZE(OutData%An_End)>0) OutData%An_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%An_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%An_End) + DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_dragConst not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DragConst_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_dragConst)) DEALLOCATE(OutData%D_dragConst) - ALLOCATE(OutData%D_dragConst(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%DragConst_End)) DEALLOCATE(OutData%DragConst_End) + ALLOCATE(OutData%DragConst_End(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_dragConst.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DragConst_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -11963,11 +10765,11 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%D_dragConst)>0) OutData%D_dragConst = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_dragConst))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_dragConst) + IF (SIZE(OutData%DragConst_End)>0) OutData%DragConst_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DragConst_End))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%DragConst_End) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! An_End not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -11977,10 +10779,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%An_End)) DEALLOCATE(OutData%An_End) - ALLOCATE(OutData%An_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_WMG_End)) DEALLOCATE(OutData%F_WMG_End) + ALLOCATE(OutData%F_WMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%An_End.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -11989,11 +10791,11 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%An_End)>0) OutData%An_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%An_End))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%An_End) + IF (SIZE(OutData%F_WMG_End)>0) OutData%F_WMG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_WMG_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F_WMG_End) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B_End not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DP_Const_End not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -12003,10 +10805,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_B_End)) DEALLOCATE(OutData%F_B_End) - ALLOCATE(OutData%F_B_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%DP_Const_End)) DEALLOCATE(OutData%DP_Const_End) + ALLOCATE(OutData%DP_Const_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B_End.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP_Const_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -12015,170 +10817,8 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%F_B_End)>0) OutData%F_B_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_B_End))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_B_End) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_I_End)) DEALLOCATE(OutData%F_I_End) - ALLOCATE(OutData%F_I_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%F_I_End)>0) OutData%F_I_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_I_End))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_I_End) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_DP_End)) DEALLOCATE(OutData%F_DP_End) - ALLOCATE(OutData%F_DP_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%F_DP_End)>0) OutData%F_DP_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_DP_End))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_DP_End) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM_M_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%AM_M_End)) DEALLOCATE(OutData%AM_M_End) - ALLOCATE(OutData%AM_M_End(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM_M_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%AM_M_End)>0) OutData%AM_M_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM_M_End))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%AM_M_End) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DragConst_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DragConst_End)) DEALLOCATE(OutData%DragConst_End) - ALLOCATE(OutData%DragConst_End(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DragConst_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DragConst_End)>0) OutData%DragConst_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DragConst_End))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%DragConst_End) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_WMG_End)) DEALLOCATE(OutData%F_WMG_End) - ALLOCATE(OutData%F_WMG_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%F_WMG_End)>0) OutData%F_WMG_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F_WMG_End))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F_WMG_End) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DP_Const_End not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DP_Const_End)) DEALLOCATE(OutData%DP_Const_End) - ALLOCATE(OutData%DP_Const_End(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP_Const_End.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%DP_Const_End)>0) OutData%DP_Const_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DP_Const_End))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%DP_Const_End) + IF (SIZE(OutData%DP_Const_End)>0) OutData%DP_Const_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DP_Const_End))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%DP_Const_End) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Mass_MG_End not allocated @@ -12232,56 +10872,6 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF (SIZE(OutData%AM_End)>0) OutData%AM_End = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM_End))-1 ), mask3, 0.0_ReKi ) Re_Xferred = Re_Xferred + SIZE(OutData%AM_End) DEALLOCATE(mask3) - END IF - OutData%NDistribMarkers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! distribToNodeIndx not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%distribToNodeIndx)) DEALLOCATE(OutData%distribToNodeIndx) - ALLOCATE(OutData%distribToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%distribToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%distribToNodeIndx)>0) OutData%distribToNodeIndx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%distribToNodeIndx))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%distribToNodeIndx) - DEALLOCATE(mask1) - END IF - OutData%NLumpedMarkers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lumpedToNodeIndx not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%lumpedToNodeIndx)) DEALLOCATE(OutData%lumpedToNodeIndx) - ALLOCATE(OutData%lumpedToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lumpedToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%lumpedToNodeIndx)>0) OutData%lumpedToNodeIndx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%lumpedToNodeIndx))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%lumpedToNodeIndx) - DEALLOCATE(mask1) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel not allocated Int_Xferred = Int_Xferred + 1 @@ -12390,55 +10980,6 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = Re_Xferred + SIZE(OutData%WaveTime) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementWaterState not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%elementWaterState)) DEALLOCATE(OutData%elementWaterState) - ALLOCATE(OutData%elementWaterState(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementWaterState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%elementWaterState)>0) OutData%elementWaterState = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%elementWaterState))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%elementWaterState) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementFillState not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%elementFillState)) DEALLOCATE(OutData%elementFillState) - ALLOCATE(OutData%elementFillState(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementFillState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%elementFillState)>0) OutData%elementFillState = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%elementFillState))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%elementFillState) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! nodeInWater not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -12464,159 +11005,6 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF (SIZE(OutData%nodeInWater)>0) OutData%nodeInWater = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%nodeInWater))-1 ), mask2, 0_IntKi ) Int_Xferred = Int_Xferred + SIZE(OutData%nodeInWater) DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_B not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_B)) DEALLOCATE(OutData%D_F_B) - ALLOCATE(OutData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_B.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D_F_B)>0) OutData%D_F_B = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_B))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_B) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_BF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_BF)) DEALLOCATE(OutData%D_F_BF) - ALLOCATE(OutData%D_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D_F_BF)>0) OutData%D_F_BF = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_BF))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_BF) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_MG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_MG)) DEALLOCATE(OutData%D_F_MG) - ALLOCATE(OutData%D_F_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D_F_MG)>0) OutData%D_F_MG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_F_MG))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_F_MG) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_M not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_M)) DEALLOCATE(OutData%D_AM_M) - ALLOCATE(OutData%D_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%D_AM_M)>0) OutData%D_AM_M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_AM_M))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_AM_M) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_MG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_MG)) DEALLOCATE(OutData%D_AM_MG) - ALLOCATE(OutData%D_AM_MG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%D_AM_MG)>0) OutData%D_AM_MG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_AM_MG))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_AM_MG) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_F)) DEALLOCATE(OutData%D_AM_F) - ALLOCATE(OutData%D_AM_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%D_AM_F)>0) OutData%D_AM_F = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D_AM_F))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D_AM_F) - DEALLOCATE(mask1) END IF OutData%NStepWave = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 From c6341824ba5c7697e816cbdcfb598a69460853c4 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:16:06 -0600 Subject: [PATCH 176/377] Shifted marine growth depth values by -MSL2SWL --- modules/hydrodyn/src/HydroDyn_Input.f90 | 31 +++---------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 11d4151e2..82b7ab1a7 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -2398,12 +2398,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) CALL SetErrStat( ErrID_Fatal,'MSL2SWL must be 0 when PotMod = 1 (WAMIT).',ErrStat,ErrMsg,RoutineName) RETURN END IF - - !IF ( .NOT. EqualRealNos(InitInp%Morison%MSL2SWL, 0.0_ReKi) ) THEN !TODO Alter this check when we support MSL2SWL - ! CALL SetErrStat( ErrID_Fatal,'MSL2SWL must be 0. Future versions of HydroDyn will once again support any value of MSL2SWL.' - ! RETURN - !END IF - + ! WaveMod - Wave kinematics model switch. @@ -3385,19 +3380,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) IF ( InitInp%Morison%NAxCoefs > 0 ) THEN DO I = 1,InitInp%Morison%NAxCoefs - - !IF ( .NOT. EqualRealNos(InitInp%Morison%AxialCoefs(I)%AxCd, 0.0) ) THEN - ! ErrMsg = ' AxCd must be equal to zero. Future versions will allow for non-zero axial coefficients.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - !IF ( .NOT. EqualRealNos(InitInp%Morison%AxialCoefs(I)%AxCa, 0.0) ) THEN - ! ErrMsg = ' AxCa must be equal to zero. Future versions will allow for non-zero axial coefficients.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - - ! TODO: Once Axial Coefs are working remove the above checks and uncomment the checks below. GJH 9/29/2013 + IF ( InitInp%Morison%AxialCoefs(I)%AxCd < 0 ) THEN CALL SetErrStat( ErrID_Fatal,'AxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3422,7 +3405,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! Check JointOvrlp values !NOTE: This is ignored in the current version of Morison. 3/15/2020 GJH - ! InitInp%Morison%TotalPossibleSuperMembers = 0 IF ( InitInp%Morison%NJoints > 1 ) THEN @@ -3954,7 +3936,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%Morison%MGBottom = 999999.0 do I = 1,InitInp%Morison%NMGDepths ! Adjust the depth values based on MSL2SWL - InitInp%Morison%MGDepths(I)%MGDpth = InitInp%Morison%MGDepths(I)%MGDpth - InitInp%MSL2SWL + InitInp%Morison%MGDepths(I)%MGDpth = InitInp%Morison%MGDepths(I)%MGDpth - InitInp%Morison%MSL2SWL end do DO I = 1,InitInp%Morison%NMGDepths ! Store the boundaries of the marine growth zone @@ -4040,13 +4022,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! Joint Output List Section !------------------------------------------------------------------------------------------------- - !IF ( InitInp%Morison%NJOutputs /= 0 ) THEN ! TODO Remove this check and add back the other checks once Joint Outputs are supported - !CALL SetErrStat( ErrID_Fatal,'NJOutputs in the Joint output list must be equal to zero. Future versions of HydroDyn will support values greater or equal to zero and less than 10.' - ! ErrStat = ErrID_Fatal - ! RETURN - !END IF - - IF ( ( InitInp%Morison%NJOutputs < 0 ) .OR. ( InitInp%Morison%NMOutputs > 9 ) ) THEN CALL SetErrStat( ErrID_Fatal,'NJOutputs in the Joint output list must be greater or equal to zero and less than 10.',ErrStat,ErrMsg,RoutineName) RETURN From 71e89253c534abc7e64f9ce28274dee88aecea68 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:16:24 -0600 Subject: [PATCH 177/377] Altered some comments --- modules/hydrodyn/src/Conv_Radiation.f90 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/Conv_Radiation.f90 b/modules/hydrodyn/src/Conv_Radiation.f90 index 4f8d74077..1aa6b961f 100644 --- a/modules/hydrodyn/src/Conv_Radiation.f90 +++ b/modules/hydrodyn/src/Conv_Radiation.f90 @@ -111,11 +111,10 @@ SUBROUTINE Conv_Rdtn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, ErrStat = ErrID_None ErrMsg = "" -!TODO -!BJJ: This was uninitialized; not sure how it should be set >>> -!PRINT *, 'Greg, please initialize this variable:RdtnFrmA' -RdtnFrmAM = .FALSE. -!<<< + + ! For now, this is the only model we have implemented + RdtnFrmAM = .FALSE. + ! Initialize the NWTC Subroutine Library CALL NWTC_Init( ) From 75f7351333cc33d1a7240f66946dc22a0a11cf2a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 21 Apr 2020 09:21:06 -0600 Subject: [PATCH 178/377] Bug Fixes in Morison An_drag now zeroed for each joint loop Added cosPhi_ref to member data (reference value of cos(Phi) at init) Draft h_c and deltal calculations for lumping external distributed HD loads Replaced time marching seabed crossing Z-valued tests with i_floor tests Added nodeInWater to calculations for end loads: F_I_End, F_IMG_End --- modules/hydrodyn/src/Morison.f90 | 104 ++++++++++++++++++------------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 69555fc55..fbe4a3286 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -935,9 +935,7 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no read (tmpName(2:2),*) mbrIndx read (tmpName(4:4),*) nodeIndx - ! These indices are in the DistribMesh index system, not the overal nodes index system, so distribToNodeIndx() mapping needs to be performed if you want - ! to index into the nodes array or wave kinematics arrays - + s = MOutLst(mbrIndx)%NodeLocs(nodeIndx) ! Find the member starting and ending node locations @@ -1475,7 +1473,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF phi = acos(vec(3)/memLength) ! incline angle sinPhi = sin(phi) cosPhi = cos(phi) - + member%cosPhi_ref = cosPhi ! These are all per node and not done here, yet @@ -2019,6 +2017,8 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In I_n = 0.0 MGdens = 0.0 tMG = -999.0 + An_drag = 0.0 + IF ( InitInp%InpJoints(i)%Position(3) >= -p%WtrDpth ) THEN ! loop through each member attached to the joint, getting the radius of its appropriate end @@ -2106,7 +2106,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In p%I_MG_End(:,:,i) = MatMul( MatMul(R_I, Irl_mat), Transpose(R_I) ) ! final moment of inertia matrix for node - END IF ! nodes(I)%Position(3) >= z0 + END IF ! InitInp%InpJoints(i)%Position(3) >= -p%WtrDpth END DO ! looping through nodes that are joints, i @@ -2307,13 +2307,6 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) END IF p%WaveTime = InitInp%WaveTime - allocate( p%F_I_End( 0:p%NStepWave, 3, p%NJoints ), STAT = errStat ) - IF ( errStat /= ErrID_None ) THEN - errMsg = ' Error allocating space for the inertial forces/moments array.' - errStat = ErrID_Fatal - RETURN - END IF - p%F_I_End = 0.0 END SUBROUTINE AllocateNodeLoadVariables @@ -2446,7 +2439,6 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, REAL(ReKi) :: F_D(6), F_DP(6), D_F_I(3), kvec(3), v(3), vf(3), vrel(3), vmag INTEGER :: I, J, K, nodeIndx - REAL(ReKi) :: elementWaterState REAL(ReKi) :: AllOuts(MaxMrsnOutputs) REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node @@ -2512,8 +2504,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, real(ReKi) :: omega_s2(3) real(ReKi) :: pos1(3), pos2(3) real(ReKi) :: Imat(3,3) - real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), am(3,3), lstar - real(ReKi) :: C_1, C_2, a0b0, z1d, z2d + real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), am(3,3), lstar, deltal + real(ReKi) :: C_1, C_2, a0b0, z1d, z2d, h ! Initialize errStat errStat = ErrID_None @@ -2817,9 +2809,36 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! External Hydrodynamic Side Loads - DO i =1,N+1 ! loop through member elements - h_c = 0.0_ReKi !TODO: Determine actual h_c based on water level, etc. GJH 3/23/20 see table in Section 7.1.1 - !TODO: call GetExtHydroForceMomentMultipliers( i, N+1, Za, Zb, Zi, h_c, deltal ) + DO i =1,N+1 ! loop through member nodes + ! TODO: Note that for computational efficiency, we could precompute h_c and deltal for each element when we are NOT using wave stretching + ! We would still need to test at time marching for nodes just below the free surface because that uses the current locations not the reference locations + ! see table in Section 7.1.1 + if ( i == 1 ) then + deltal = mem%dl/2.0_ReKi + h_c = mem%dl/4.0_ReKi + elseif (i == N+1) then + deltal = mem%dl/2.0_ReKi + h_c = -mem%dl/4.0_ReKi + elseif ( mem%i_floor == i ) then ! This node is the upper node of an element which crosses the seabed + deltal = mem%dl/2.0_ReKi - mem%h_floor ! TODO: h_floor is negative valued, should we be subrtracting it from dl/2? GJH + h_c = 0.5_ReKi*(mem%dl/2.0_ReKi + mem%h_floor) + else + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i)) + u%Mesh%Position(:, mem%NodeIndx(i)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i+1)) + u%Mesh%Position(:, mem%NodeIndx(i+1)) + if (pos1(3) <= 0.0 .and. 0.0 < pos2(3) ) then ! This node is just below the free surface !TODO: Needs to be augmented for wave stretching + !TODO: Fix this one + pos1 = u%Mesh%Position(:, mem%NodeIndx(i)) ! use reference position for following equation + h = ( pos1(3) ) / mem%cosPhi_ref !TODO: Needs to be augmented for wave stretching + deltal = mem%dl/2.0 + h + h_c = 0.5*(h-mem%dl/2.0) + else + ! This node is a fully submerged interior node + deltal = mem%dl + h_c = 0.0_ReKi + end if + + end if + if (i == 1) then dRdl_p = abs(mem%dRdl_mg(i)) dRdl_pp = mem%dRdl_mg(i) @@ -2849,7 +2868,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) end if - END DO ! i =1,N+1 ! loop through member elements + END DO ! i =1,N+1 ! loop through member nodes ! Any end plate loads that are modeled on a per-member basis @@ -2878,9 +2897,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! TODO: Do the equations below still work if z1 > z2 ? !TODO, should not have to test seabed crossing in time-marching loop - ! Water ballast buoyancy - if (z1 >= -p%WtrDpth) then ! end load only if end is above seabed - + + if ( mem%i_floor == 0 ) then ! both ends are above seabed + !--- Water ballast buoyancy --- ! if member is fully flooded if (mem%z_overfill > 0) then Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0.0_ReKi)) @@ -2896,19 +2915,27 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Fl = -mem%FillDens * g * pi *mem%Rin(1)**2*mem%l_fill*cosPhi Moment = mem%FillDens * g * pi *0.25*mem%Rin(1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) - - ! no load if member is not flooded at all + else + ! no load if member is not flooded at all end if - ! no load if end is below seabed + + elseif ( mem%i_floor < mem%NElements ) then ! upper node is still above the seabed + if (mem%z_overfill > 0) then + Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) + Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi + call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) + end if + + else + ! no loads because both end nodes are below seabed end if ! --- no inertia loads from water ballast modeled on ends ! --- external buoyancy loads: ends --- -!TODO, should not have to test seabed crossing in time-marching loop if ( .not. mem%PropPot ) then - if (z1 >= -p%WtrDpth) then ! NOTE: We could roll this into the section for Water ballast buoyancy to save the if-test + if (mem%i_floor == 0) then ! both ends above or at seabed if (z2<= 0.0_ReKi) then ! Compute loads on both ends Fl = -p%WtrDens * g * pi *mem%RMG(1)**2*z1 @@ -2925,16 +2952,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, else ! Entire member is above the still water line end if - !TODO, should not have to test seabed crossing in time-marching loop - elseif (z2 >-p%WtrDpth) then ! The member crosses the seabed line + elseif ( mem%i_floor < mem%NElements) then ! The member crosses the seabed line ! Only compute the buoyancy contribution from the upper end Fl = p%WtrDens * g * pi *mem%RMG(N+1)**2*z2 Moment = p%WtrDens * g * pi *0.25*mem%RMG(N+1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_B_End(:, mem%NodeIndx(N+1))) else - ! entire member is buried below the seabed - + ! entire member is buried below the seabed end if end if ! PropPot @@ -2972,16 +2997,13 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Lumped added mass loads qdotdot = reshape((/u%Mesh%TranslationAcc(:,J),u%Mesh%RotationAcc(:,J)/),(/6/)) - m%F_A_End(:,J) = matmul( p%AM_End(:,:,J) , ( - qdotdot) ) - DO I=1,3 - m%F_A_End(I,J) = m%nodeInWater(j) * m%F_A_End(I,J) ! Note that the rotational components are zero - END DO + m%F_A_End(:,J) = m%nodeInWater(j) * matmul( p%AM_End(:,:,J) , ( - qdotdot) ) - m%F_I_End(:,J) = p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j)) + m%F_I_End(:,J) = m%nodeInWater(j) * (p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j))) ! Marine growth inertia: ends: Section 4.2.2 - m%F_IMG_End(1:3,j) = -p%Mass_MG_End(j)*qdotdot(1:3) - m%F_IMG_End(4:6,j) = -matmul(p%I_MG_End(:,:,j),qdotdot(4:6)) - cross_product(u%Mesh%RotationVel(:,J),matmul(p%I_MG_End(:,:,j),u%Mesh%RotationVel(:,J))) + m%F_IMG_End(1:3,j) = -m%nodeInWater(j) * p%Mass_MG_End(j)*qdotdot(1:3) + m%F_IMG_End(4:6,j) = -m%nodeInWater(j) * (matmul(p%I_MG_End(:,:,j),qdotdot(4:6)) - cross_product(u%Mesh%RotationVel(:,J),matmul(p%I_MG_End(:,:,j),u%Mesh%RotationVel(:,J)))) DO I=1,6 @@ -2991,15 +3013,13 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, IF (I < 4 ) THEN - m%F_D_End(i,j) = p%An_End(i,j)*p%DragConst_End(j)*abs(vmag)*vmag + m%F_D_End(i,j) = p%An_End(i,j)*p%DragConst_End(j)*abs(vmag)*vmag ! Note: vmag is zero if node is not in the water !TODO: This needs to be reworked with new equations !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) - !y%Mesh%Force(I,J) = m%F_A_End(I,J) + m%F_D_End(I,J) + m%F_B_End(I,J) + m%F_I_End(I,J) !+ m%F_BF_End(I,J) y%Mesh%Force(i,j) = m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) ELSE !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) - !y%Mesh%Moment(I-3,J) = m%F_A_End(I,J) + m%F_B_End(I,J) ! + m%F_BF_End(I,J) - y%Mesh%Moment(i-3,j) = m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) + y%Mesh%Moment(i-3,j) = m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) END IF END DO ! I=1,6 ENDDO ! J = 1, p%NJoints From 1d57ebfc783ced388e72ce460f55558e4744fb58 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 23 Apr 2020 08:33:20 -0600 Subject: [PATCH 179/377] Bug Fixes + Augmentation of i_floor for fully buried members interpolation factor (s) was incorrect because Intel compiler was applying integer math i_floor = NElements + 1 means complete member is below seabed Checking for node submergence when computing side external hydrodynamic loads --- modules/hydrodyn/src/Morison.f90 | 124 +++++++++++++++++-------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index fbe4a3286..c7bc82804 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1209,7 +1209,7 @@ SUBROUTINE SetExternalHydroCoefs( MCoefMod, MmbrCoefIDIndx, SimplCd, SimplCdMG, CASE (3) ! Member-based model: coefficients set using member-specific coefficient tables do i = 1, member%NElements + 1 ! Pull member end-node data from the tables and then linearly interpolate it onto the interior member nodes - s = (i-1) / member%NElements + s = (real(i,ReKi)-1.0) / real(member%NElements,ReKi) if ( member%tMG(i) > 0.0_ReKi ) then member%Cd (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdMG2*s member%Ca (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaMG2*s @@ -1488,7 +1488,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%RMG(N+1) = propSet2%PropD / 2.0 + member%tMG(N+1) member%Rin(N+1) = propSet2%PropD / 2.0 - propSet2%PropThck do i = 2, member%NElements - s = (i-1) / member%NElements + s = (real(i,ReKi)-1.0) / real(member%NElements,ReKi) member%R( i) = member%R( 1)*(1-s) + member%R( N+1)*s member%Rin(i) = member%Rin(1)*(1-s) + member%Rin(N+1)*s member%RMG(i) = member%R(i) + member%tMG(i) @@ -1555,7 +1555,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! calculate h_floor if seabed-piercing member%h_floor = 0.0_ReKi - member%i_floor = 0 + member%i_floor = member%NElements+1 ! Default to entire member is below the seabed if (Za < -WtrDepth) then do i= 2, member%NElements+1 Za = InitInp%Nodes(member%NodeIndx(i))%Position(3) @@ -1570,6 +1570,8 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF exit end if end do + else + member%i_floor = 0 ! lower end is at or above the seabed end if @@ -2810,64 +2812,68 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! External Hydrodynamic Side Loads DO i =1,N+1 ! loop through member nodes - ! TODO: Note that for computational efficiency, we could precompute h_c and deltal for each element when we are NOT using wave stretching - ! We would still need to test at time marching for nodes just below the free surface because that uses the current locations not the reference locations - ! see table in Section 7.1.1 - if ( i == 1 ) then - deltal = mem%dl/2.0_ReKi - h_c = mem%dl/4.0_ReKi - elseif (i == N+1) then - deltal = mem%dl/2.0_ReKi - h_c = -mem%dl/4.0_ReKi - elseif ( mem%i_floor == i ) then ! This node is the upper node of an element which crosses the seabed - deltal = mem%dl/2.0_ReKi - mem%h_floor ! TODO: h_floor is negative valued, should we be subrtracting it from dl/2? GJH - h_c = 0.5_ReKi*(mem%dl/2.0_ReKi + mem%h_floor) - else - pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i)) + u%Mesh%Position(:, mem%NodeIndx(i)) - pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i+1)) + u%Mesh%Position(:, mem%NodeIndx(i+1)) - if (pos1(3) <= 0.0 .and. 0.0 < pos2(3) ) then ! This node is just below the free surface !TODO: Needs to be augmented for wave stretching - !TODO: Fix this one - pos1 = u%Mesh%Position(:, mem%NodeIndx(i)) ! use reference position for following equation - h = ( pos1(3) ) / mem%cosPhi_ref !TODO: Needs to be augmented for wave stretching - deltal = mem%dl/2.0 + h - h_c = 0.5*(h-mem%dl/2.0) + z1 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i)) + u%Mesh%Position(3, mem%NodeIndx(i)) + if ( i > mem%i_floor .and. z1 <= 0.0 ) then ! node is above (or at? TODO: check) seabed and below or at free-surface) + ! TODO: Note that for computational efficiency, we could precompute h_c and deltal for each element when we are NOT using wave stretching + ! We would still need to test at time marching for nodes just below the free surface because that uses the current locations not the reference locations + ! see table in Section 7.1.1 + if ( i == 1 ) then + deltal = mem%dl/2.0_ReKi + h_c = mem%dl/4.0_ReKi + elseif (i == N+1) then + deltal = mem%dl/2.0_ReKi + h_c = -mem%dl/4.0_ReKi + elseif ( mem%i_floor == i+1 ) then ! This node is the upper node of an element which crosses the seabed + deltal = mem%dl/2.0_ReKi - mem%h_floor ! TODO: h_floor is negative valued, should we be subrtracting it from dl/2? GJH + h_c = 0.5_ReKi*(mem%dl/2.0_ReKi + mem%h_floor) else - ! This node is a fully submerged interior node - deltal = mem%dl - h_c = 0.0_ReKi - end if + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i)) + u%Mesh%Position(:, mem%NodeIndx(i)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i+1)) + u%Mesh%Position(:, mem%NodeIndx(i+1)) + if (pos1(3) <= 0.0 .and. 0.0 < pos2(3) ) then ! This node is just below the free surface !TODO: Needs to be augmented for wave stretching + !TODO: Fix this one + pos1 = u%Mesh%Position(:, mem%NodeIndx(i)) ! use reference position for following equation + h = ( pos1(3) ) / mem%cosPhi_ref !TODO: Needs to be augmented for wave stretching + deltal = mem%dl/2.0 + h + h_c = 0.5*(h-mem%dl/2.0) + else + ! This node is a fully submerged interior node + deltal = mem%dl + h_c = 0.0_ReKi + end if - end if + end if - if (i == 1) then - dRdl_p = abs(mem%dRdl_mg(i)) - dRdl_pp = mem%dRdl_mg(i) - elseif ( i > 1 .and. i < (N+1)) then - dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) - dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) - else - dRdl_p = abs(mem%dRdl_mg(N)) - dRdl_pp = mem%dRdl_mg(N) - end if + if (i == 1) then + dRdl_p = abs(mem%dRdl_mg(i)) + dRdl_pp = mem%dRdl_mg(i) + elseif ( i > 1 .and. i < (N+1)) then + dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) + dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) + else + dRdl_p = abs(mem%dRdl_mg(N)) + dRdl_pp = mem%dRdl_mg(N) + end if + + ! ------------------- hydrodynamic drag loads: sides: Section 7.1.2 ------------------------ + vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) + f_hydro = mem%Cd(i)*p%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & + 0.5*mem%AxCd(i)*p%WtrDens*pi*mem%RMG(i)*dRdl_p * matmul( dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )*mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) + + if ( .not. mem%PropPot ) then + ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ + Am = mem%Ca(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt + f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) + + ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ + f_hydro=mem%Ca(i)*mem%Cp(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) + end if + end if ! ( i > mem%i_floor .and. Zi <= 0.0 ) - ! ------------------- hydrodynamic drag loads: sides: Section 7.1.2 ------------------------ - vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) - f_hydro = mem%Cd(i)*p%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & - 0.5*mem%AxCd(i)*p%WtrDens*pi*mem%RMG(i)*dRdl_p * matmul( dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )*mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) - - if ( .not. mem%PropPot ) then - ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ - Am = mem%Ca(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt - f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) - - ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ - f_hydro=mem%Ca(i)*mem%Cp(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) - end if END DO ! i =1,N+1 ! loop through member nodes @@ -2935,6 +2941,10 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! --- external buoyancy loads: ends --- if ( .not. mem%PropPot ) then + pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(1)) + u%Mesh%Position(:, mem%NodeIndx(1)) + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) + u%Mesh%Position(:, mem%NodeIndx(N+1)) + z1 = pos1(3) + z2 = pos2(3) if (mem%i_floor == 0) then ! both ends above or at seabed if (z2<= 0.0_ReKi) then ! Compute loads on both ends From ef8edfcc747526fbeabcac4ea6f1a0749106c67c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 29 Apr 2020 11:08:59 -0600 Subject: [PATCH 180/377] FlexSub: adding extra contribution from lever arm --- modules/subdyn/src/SubDyn.f90 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 254012fc0..748167192 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -381,6 +381,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOFL), UL0m(p%nDOFL), FLt(p%nDOFL) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) + REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) @@ -489,10 +490,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) END IF + ! Computing extra moments due to lever arm introduced by interface displacement + ! MExtra = -u_TP x f_TP0 + ! Y1_MExtra = - MExtra = u_TP x f_TP0 !<< + Y1_ExtraMoment(1) = m%u_TP(2) * Y1(3) - m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = m%u_TP(3) * Y1(1) - m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = m%u_TP(1) * Y1(2) - m%u_TP(2) * Y1(1) ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) + y%Y1Mesh%Moment(:,1) = Y1(4:6) + Y1_ExtraMoment !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE @@ -1319,7 +1326,7 @@ SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg SUBROUTINE CleanUp() INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) - CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) CALL SD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k1, ErrStat3, ErrMsg3 ) CALL SD_DestroyContState( k2, ErrStat3, ErrMsg3 ) From 944cf8e4b4dd3861ab6de5a2ea7021bebbfd4427 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 29 Apr 2020 15:15:23 -0600 Subject: [PATCH 181/377] FlexSub: reversed sign for extra contrib --- modules/subdyn/src/SubDyn.f90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 748167192..a31722f64 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -491,11 +491,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) END IF ! Computing extra moments due to lever arm introduced by interface displacement - ! MExtra = -u_TP x f_TP0 - ! Y1_MExtra = - MExtra = u_TP x f_TP0 !<< - Y1_ExtraMoment(1) = m%u_TP(2) * Y1(3) - m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = m%u_TP(3) * Y1(1) - m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = m%u_TP(1) * Y1(2) - m%u_TP(2) * Y1(1) + ! Y1(:3) = -f_TP + ! MExtra = -u_TP x f_TP + ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces y%Y1Mesh%Force (:,1) = Y1(1:3) From 652a53eee1bc67e2a80b22888d91e5339fff501a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Apr 2020 11:44:10 -0600 Subject: [PATCH 182/377] FlexSub: reading interface and reaction DOF and SoilMatrix string if persent in inputs --- modules/subdyn/src/SD_FEM.f90 | 1 + modules/subdyn/src/SubDyn.f90 | 103 ++++++++++++++++++++++--- modules/subdyn/src/SubDyn_Registry.txt | 7 +- modules/subdyn/src/SubDyn_Types.f90 | 71 ++++++++++++++++- 4 files changed, 164 insertions(+), 18 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 5a74455e9..db8ac1a91 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -30,6 +30,7 @@ MODULE SD_FEM ! values of these parameters are ordered by their place in SubDyn input file: INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) + INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a31722f64..11613a198 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -618,14 +618,14 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) LOGICAL :: LegacyFormat LOGICAL :: bNumeric INTEGER(IntKi) :: UnIn -INTEGER(IntKi) :: nColumns +INTEGER(IntKi) :: nColumns, nColValid, nColNumeric INTEGER(IntKi) :: IOS INTEGER(IntKi) :: UnEc !Echo file ID REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf -REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) +REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -772,7 +772,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ) if (ErrStat2/=0) then - ! We try we 4 columns (legacy format) + ! We try with 4 columns (legacy format) nColumns = 4 deallocate(StrArray) CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return @@ -787,16 +787,15 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 - nColsReactInterf=InterfCol else ! New format LegacyFormat=.False. - nColsReactInterf=1 endif ! Extract fields from first line DO I = 1, nColumns bNumeric = is_numeric(StrArray(I), Init%Joints(1,I)) ! Convert from string to float ENDDO +deallocate(StrArray) ! Read remaining lines DO I = 2, Init%NJoints CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, nColumns, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -813,10 +812,30 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_C, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Nodes_C, p%nNodes_C, nColsReactInterf, 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return + +CALL AllocAry(p%Nodes_C, p%nNodes_C, ReactCol , 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +p%Nodes_C(:,:) = 1 ! Important: By default all DOFs are contrained +p%Nodes_C(:,1) = -1 ! First column is node, initalize to wrong value for safety + +ALLOCATE(Init%SSIfile(p%nNodes_C)) ! Soil Structure Interaction (SSI) files to associated with each reaction node +Init%SSIfile(:) = '' +! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile DO I = 1, p%nNodes_C - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColsReactInterf, 'Reacts', 'Joint number and dof', ErrStat2 ,ErrMsg2, UnEc); if(Failed()) return - p%Nodes_C(I,:) = Dummy_IntAry(1:nColsReactInterf) + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return + call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); + if (nColValid==1 .and. nColNumeric==1) then + ! Temporary allowing this + print*,'Warning: SubDyn reaction line has only 1 column. Please use 7 or 8 values' + else if (nColNumeric==7 .and.(nColValid==7.or.nColValid==8)) then + ! This is fine. + else + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') + return + endif + if (any(p%Nodes_C(I,:)<=0)) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for reactions. Problematic line: "'//trim(Line)//'"') + return + endif ENDDO IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return @@ -826,10 +845,22 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_I, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(p%Nodes_I, p%nNodes_I, nColsReactInterf, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return + +CALL AllocAry(p%Nodes_I, p%nNodes_I, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +p%Nodes_I(:,:) = 1 ! Important: By default all DOFs are contrained +p%Nodes_I(:,1) = -1 ! First column is node, initalize to wrong value for safety +! Reading interface lines one by one, allowing for 1 or 7 columns (cannot use ReadIAry) DO I = 1, p%nNodes_I - CALL ReadIAry( UnIn, SDInputFile, Dummy_IntAry, nColsReactInterf, 'Interf', 'Interface joint number and dof', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - p%Nodes_I(I,:) = Dummy_IntAry(1:nColsReactInterf) + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='Reading interface line'; if (Failed()) return + call ReadIAryFromStr(Line, p%Nodes_I(I,:), 7, nColValid, nColNumeric); + if ((nColValid/=nColNumeric).or.((nColNumeric/=1).and.(nColNumeric/=7)) ) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 1 or 7 numerical values. Problematic line: "'//trim(Line)//'"') + return + endif + if (any(p%Nodes_I(I,:)<=0)) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for interface lines. Problematic line: "'//trim(Line)//'"') + return + endif ENDDO IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN @@ -1047,11 +1078,59 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp() CLOSE( UnIn ) + if(allocated(StrArray)) deallocate(StrArray) IF (Echo) CLOSE( UnEc ) END SUBROUTINE - END SUBROUTINE SD_Input +!> Extract integers from a string (space delimited substrings) +!! If StrArrayOut is present, non numeric strings are also returned +!! Example Str="1 2 not_a_int 3" -> IntArray = (/1,2,3/) StrArrayOut=(/"not_a_int"/) +!! No need for error handling, the caller will check how many valid inputs were on the line +!! TODO, place me in NWTC LIb +SUBROUTINE ReadIAryFromStr(Str, IntArray, nColMax, nColValid, nColNumeric, StrArrayOut) + character(len=*), intent(in) :: Str !< + integer(IntKi), dimension(:), intent(inout) :: IntArray !< NOTE: inout, to allow for init values + integer(IntKi), intent(in) :: nColMax + integer(IntKi), intent(out) :: nColValid, nColNumeric !< + character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric + character(255), allocatable :: StrArray(:) ! Array of strings extracted from line + real(ReKi) :: DummyFloat + integer(IntKi) :: J, nColStr + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + nColValid = 0 ; + nColNumeric = 0 ; + nColStr = 0 ; + ! --- First extract the different sub strings + CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); + if (ErrStat2/=ErrID_None) then + return ! User should notice that there is 0 valid columns + endif + StrArray(:)=''; + CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! + ! --- Then look for numerical values + do J = 1, nColMax + if (len(trim(StrArray(J)))>0) then + nColValid=nColValid+1 + if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! + nColNumeric=nColNumeric+1 + if (nColNumeric<=size(IntArray)) then + IntArray(nColNumeric) = int(DummyFloat) + endif + else + nColStr = nColStr+1 + if (present(StrArrayOut)) then + if (nColStr <=size(StrArrayOut) )then + StrArrayOut(nColStr) = StrArray(J) + endif + endif + endif + endif + enddo + if(allocated(StrArray)) deallocate(StrArray) +END SUBROUTINE ReadIAryFromStr + !---------------------------------------------------------------------------------------------------------------------------------- !> Rotate the joint coordinates with respect to global z diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 6e6d365a2..166454ed8 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -23,8 +23,8 @@ typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transitio typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" # ============================== Define Initialization outputs here: ============================================================================================================================================ -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "Names of the output-to-file channels" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - # ============================== Define Internal data types here: ============================================================================================================================================ @@ -86,9 +86,10 @@ typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" -typedef ^ ^ CHARACTER(10) SSOutList {:} - - "List of Output Channels" +typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" +typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ typedef ^ ^ INTEGER NElem - - - "Total number of elements" typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 7fab8ba69..d084001cd 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -50,8 +50,8 @@ MODULE SubDyn_Types ! ======================= ! ========= SD_InitOutputType ======= TYPE, PUBLIC :: SD_InitOutputType - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] END TYPE SD_InitOutputType ! ======================= @@ -122,9 +122,10 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] - CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] @@ -2574,6 +2575,18 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ENDIF DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim +IF (ALLOCATED(SrcInitTypeData%SSIfile)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIfile,1) + i1_u = UBOUND(SrcInitTypeData%SSIfile,1) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIfile)) THEN + ALLOCATE(DstInitTypeData%SSIfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIfile = SrcInitTypeData%SSIfile +ENDIF DstInitTypeData%NElem = SrcInitTypeData%NElem DstInitTypeData%NPropB = SrcInitTypeData%NPropB DstInitTypeData%NPropC = SrcInitTypeData%NPropC @@ -2826,6 +2839,9 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%SSOutList)) THEN DEALLOCATE(InitTypeData%SSOutList) ENDIF +IF (ALLOCATED(InitTypeData%SSIfile)) THEN + DEALLOCATE(InitTypeData%SSIfile) +ENDIF IF (ALLOCATED(InitTypeData%Nodes)) THEN DEALLOCATE(InitTypeData%Nodes) ENDIF @@ -2975,6 +2991,11 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END IF Int_BufSz = Int_BufSz + 1 ! OutCOSM Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1 ! SSIfile allocated yes/no + IF ( ALLOCATED(InData%SSIfile) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SSIfile upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SSIfile)*LEN(InData%SSIfile) ! SSIfile + END IF Int_BufSz = Int_BufSz + 1 ! NElem Int_BufSz = Int_BufSz + 1 ! NPropB Int_BufSz = Int_BufSz + 1 ! NPropC @@ -3276,6 +3297,23 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIfile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIfile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SSIfile,1), UBOUND(InData%SSIfile,1) + DO I = 1, LEN(InData%SSIfile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SSIfile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB @@ -3859,6 +3897,33 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIfile)) DEALLOCATE(OutData%SSIfile) + ALLOCATE(OutData%SSIfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%SSIfile,1), UBOUND(OutData%SSIfile,1) + DO I = 1, LEN(OutData%SSIfile) + OutData%SSIfile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF OutData%NElem = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 OutData%NPropB = IntKiBuf( Int_Xferred ) From 6e7eb93b71e95e72cf32e44bc9f10dbe065b289d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Apr 2020 12:56:25 -0600 Subject: [PATCH 183/377] FlexSub: reading of SSI matrices if present --- modules/subdyn/src/SubDyn.f90 | 69 ++++++++++++- modules/subdyn/src/SubDyn_Registry.txt | 2 + modules/subdyn/src/SubDyn_Types.f90 | 130 +++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 11613a198..da554ba57 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -817,8 +817,12 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) p%Nodes_C(:,:) = 1 ! Important: By default all DOFs are contrained p%Nodes_C(:,1) = -1 ! First column is node, initalize to wrong value for safety -ALLOCATE(Init%SSIfile(p%nNodes_C)) ! Soil Structure Interaction (SSI) files to associated with each reaction node +call AllocAry(Init%SSIfile, p%nNodes_C, 'SSIFile', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIK , p%nNodes_C, 21 , 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIM , p%nNodes_C, 21 , 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return Init%SSIfile(:) = '' +Init%SSIK = HUGE(Init%SSIK) ! NOTE: huge used later. TODO: read these matrices on the fly in SD_FEM maybe? +Init%SSIM = 0.0_ReKi ! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile DO I = 1, p%nNodes_C READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return @@ -839,6 +843,17 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ENDDO IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return + +! Reading SSI matrices if present +DO I = 1, p%nNodes_C + if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then + Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) + CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(I,:),Init%SSIM(I,:), ErrStat, ErrMsg, UnEc ); if(Failed()) return + endif +enddo + + + !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- ! Joints with reaction forces, joint number and locked/free dof CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -2910,4 +2925,54 @@ FUNCTION is_numeric(string, x) is_numeric = e == 0 END FUNCTION is_numeric -End Module SubDyn +!> Parses a file for Kxx,Kxy,..Kxthtx,..Kxtz, Kytx, Kyty,..Kztz +SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) + USE NWTC_IO + INTEGER, INTENT(IN) :: JointID !< ID of th ejoint for which we are reading SSI + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + INTEGER :: CurLine !< The current line to be parsed in the FileInfo structure. + REAL(ReKi), INTENT(INOUT) , dimension(21) :: SSIK, SSIM !< Matrices being filled by reading the file. + CHARACTER(*), INTENT(IN) :: Filename !< Name of the input file. + ! Local declarations: + CHARACTER(5), DIMENSION(21) :: Knames=(/'Kxx ','Kxy ','Kyy ','Kxz ','Kyz ', 'Kzz ','Kxtx ','Kytx ','Kztx ','Ktxtx', & + 'Kxty ','Kyty ','Kzty ','Ktxty','Ktyty', & + 'Kxtz ','Kytz ','Kztz ','Ktxtz','Ktytz','Ktztz'/) ! Dictionary of names by column for an Upper Triangular Matrix + CHARACTER(5), DIMENSION(21) :: Mnames=(/'Mxx ','Mxy ','Myy ','Mxz ','Myz ', 'Mzz ','Mxtx ','Mytx ','Mztx ','Mtxtx', & + 'Mxty ','Myty ','Mzty ','Mtxty','Mtyty', & + 'Mxtz ','Mytz ','Mztz ','Mtxtz','Mtytz','Mtztz'/) + TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. + INTEGER :: IOS ! I/O status returned from the read statement. + INTEGER(IntKi) :: i, j, imax !counters + CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: ErrStat2 ! Error status; if present, program does not abort on error + CHARACTER(*), PARAMETER :: RoutineName = 'ReadSSIfile' + + SSIK=0.0_ReKi + SSIM=0.0_ReKi + + CALL ProcessComFile ( Filename, FileInfo, ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); IF (ErrStat >= AbortErrLev) RETURN + CurLine = 1 + imax=21 + DO i=1, imax !This will search also for already hit up names, but that's ok, it should be pretty fast + DO j=1,FileInfo%NumLines + CurLine=j + CALL ParseVarWDefault ( FileInfo, CurLine, Knames(i), SSIK(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) + CALL ParseVarWDefault ( FileInfo, CurLine, Mnames(i), SSIM(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) + ENDDO + ENDDO + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc .GT. 0 ) THEN + WRITE (UnEc,'(1X,A20," = ",I11)') 'JOINT ID',JointID + DO i=1,21 + WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIK(i), Knames(i) + WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIM(i), Mnames(i) + ENDDO + ENDIF + END IF + RETURN +END SUBROUTINE ReadSSIfile + + +end module SubDyn diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 166454ed8..dd1267611 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -89,6 +89,8 @@ typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" +typedef ^ ^ ReKi SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" +typedef ^ ^ ReKi SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ typedef ^ ^ INTEGER NElem - - - "Total number of elements" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index d084001cd..d49b82909 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -125,6 +125,8 @@ MODULE SubDyn_Types CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] @@ -2575,6 +2577,34 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ENDIF DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim +IF (ALLOCATED(SrcInitTypeData%SSIK)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIK,1) + i1_u = UBOUND(SrcInitTypeData%SSIK,1) + i2_l = LBOUND(SrcInitTypeData%SSIK,2) + i2_u = UBOUND(SrcInitTypeData%SSIK,2) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIK)) THEN + ALLOCATE(DstInitTypeData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIK = SrcInitTypeData%SSIK +ENDIF +IF (ALLOCATED(SrcInitTypeData%SSIM)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIM,1) + i1_u = UBOUND(SrcInitTypeData%SSIM,1) + i2_l = LBOUND(SrcInitTypeData%SSIM,2) + i2_u = UBOUND(SrcInitTypeData%SSIM,2) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIM)) THEN + ALLOCATE(DstInitTypeData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIM = SrcInitTypeData%SSIM +ENDIF IF (ALLOCATED(SrcInitTypeData%SSIfile)) THEN i1_l = LBOUND(SrcInitTypeData%SSIfile,1) i1_u = UBOUND(SrcInitTypeData%SSIfile,1) @@ -2839,6 +2869,12 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%SSOutList)) THEN DEALLOCATE(InitTypeData%SSOutList) ENDIF +IF (ALLOCATED(InitTypeData%SSIK)) THEN + DEALLOCATE(InitTypeData%SSIK) +ENDIF +IF (ALLOCATED(InitTypeData%SSIM)) THEN + DEALLOCATE(InitTypeData%SSIM) +ENDIF IF (ALLOCATED(InitTypeData%SSIfile)) THEN DEALLOCATE(InitTypeData%SSIfile) ENDIF @@ -2991,6 +3027,16 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END IF Int_BufSz = Int_BufSz + 1 ! OutCOSM Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1 ! SSIK allocated yes/no + IF ( ALLOCATED(InData%SSIK) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SSIK upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SSIK) ! SSIK + END IF + Int_BufSz = Int_BufSz + 1 ! SSIM allocated yes/no + IF ( ALLOCATED(InData%SSIM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SSIM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SSIM) ! SSIM + END IF Int_BufSz = Int_BufSz + 1 ! SSIfile allocated yes/no IF ( ALLOCATED(InData%SSIfile) ) THEN Int_BufSz = Int_BufSz + 2*1 ! SSIfile upper/lower bounds for each dimension @@ -3297,6 +3343,38 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SSIK) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SSIK)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SSIK) + END IF + IF ( .NOT. ALLOCATED(InData%SSIM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SSIM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SSIM) + END IF IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3897,6 +3975,58 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIK not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIK)) DEALLOCATE(OutData%SSIK) + ALLOCATE(OutData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%SSIK)>0) OutData%SSIK = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SSIK) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIM)) DEALLOCATE(OutData%SSIM) + ALLOCATE(OutData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%SSIM)>0) OutData%SSIM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SSIM) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated Int_Xferred = Int_Xferred + 1 ELSE From fe8252b2c650b88981fbfae7e1af4c68f28dd32f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Apr 2020 15:09:36 -0600 Subject: [PATCH 184/377] FlexSub: adding soil stiffness and mass, but dof elimination not supported --- .../src/NetLib/lapack/NWTC_LAPACK.f90 | 61 ++++++++++++++++++- modules/subdyn/src/SD_FEM.f90 | 56 ++++++++++++++++- modules/subdyn/src/SubDyn.f90 | 13 +++- 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 b/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 index f82fff275..70e3a1fe6 100644 --- a/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 +++ b/modules/nwtc-library/src/NetLib/lapack/NWTC_LAPACK.f90 @@ -93,12 +93,17 @@ MODULE NWTC_LAPACK MODULE PROCEDURE LAPACK_spptrf END INTERFACE -!> Compute the SVD for a general matrix A = USV^T. + !> Compute the SVD for a general matrix A = USV^T. INTERFACE LAPACK_gesvd MODULE PROCEDURE LAPACK_dgesvd MODULE PROCEDURE LAPACK_sgesvd END INTERFACE + !> Unpack packed (1D) to regular matrix format (2D) + INTERFACE LAPACK_TPTTR + MODULE PROCEDURE LAPACK_STPTTR + MODULE PROCEDURE LAPACK_DTPTTR + END INTERFACE CONTAINS @@ -1529,5 +1534,57 @@ SUBROUTINE LAPACK_SGESVD(JOBU, JOBVT, M, N, A, S, U, VT, WORK, LWORK, ErrStat, E RETURN END SUBROUTINE LAPACK_SGESVD -!======================================================================= + !======================================================================= + !INTERFACE LAPACK_TPTTR: + !> Unpack a by-column-packed array into a 2D matrix format + !! See documentation in DTPTTR/STPTTR source code. + SUBROUTINE LAPACK_DTPTTR( UPLO, N, AP, A, LDA, ErrStat, ErrMsg ) + CHARACTER(1), intent(in ) :: UPLO !< = 'U': A is an upper triangular matrix; 'L': A is a lower triangular matrix + INTEGER, intent(in ) :: N !< The order of matrix A and AP. + INTEGER, intent(in) :: LDA !< The leading dimension of the matrix A. LDA ? max(1,N) + INTEGER(IntKi), intent(out) :: ErrStat !< Error level + CHARACTER(*), intent(out) :: ErrMsg !< Message describing error + REAL(R8Ki), intent(in) :: AP( : ) !< Packed array + REAL(R8Ki), intent(out) :: A( :,: ) !< Unpacked array : Note AP(1)=A(1,1); AP(2)=A(1,2); AP(3)=A(2,2); AP(4)=A(1,3) etc. by column, upper triang + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value + ErrStat = ErrID_None + ErrMsg = "" + CALL DTPTTR( UPLO, N, AP, A, LDA, INFO ) + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_DTPTTR: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_DTPTTR: Unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + RETURN + END SUBROUTINE LAPACK_DTPTTR + !======================================================================= + !> Unpack a by-column-packed array into a 2D matrix format + SUBROUTINE LAPACK_STPTTR( UPLO, N, AP, A, LDA, ErrStat, ErrMsg ) + CHARACTER(1), intent(in ) :: UPLO !< = 'U': A is an upper triangular matrix; 'L': A is a lower triangular matrix + INTEGER, intent(in ) :: N !< The order of matrix A and AP. + INTEGER, intent(in) :: LDA !< The leading dimension of the matrix A. LDA ? max(1,N) + INTEGER(IntKi), intent(out) :: ErrStat !< Error level + CHARACTER(*), intent(out) :: ErrMsg !< Message describing error + REAL(SiKi), intent(in) :: AP( : ) !< Packed array + REAL(SiKi), intent(out) :: A( :,: ) !< Unpacked array : Note AP(1)=A(1,1); AP(2)=A(1,2); AP(3)=A(2,2); AP(4)=A(1,3) etc. by column, upper triang + INTEGER :: INFO ! = 0: successful exit; < 0: if INFO = -i, the i-th argument had an illegal value + ErrStat = ErrID_None + ErrMsg = "" + CALL STPTTR( UPLO, N, AP, A, LDA, INFO ) + IF (INFO /= 0) THEN + ErrStat = ErrID_FATAL + WRITE( ErrMsg, * ) INFO + IF (INFO < 0) THEN + ErrMsg = "LAPACK_STPTTR: illegal value in argument "//TRIM(ErrMsg)//"." + ELSE + ErrMsg = 'LAPACK_STPTTR: Unknown error '//TRIM(ErrMsg)//'.' + END IF + END IF + RETURN + END SUBROUTINE LAPACK_STPTTR + !======================================================================= END MODULE NWTC_LAPACK diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index db8ac1a91..d08582f4d 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -866,6 +866,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) INTEGER :: iGlob REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector REAL(ReKi) :: FCe(12) ! Pretension force from cable element + REAL(ReKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 INTEGER(IntKi) :: iNode !< Node index @@ -917,7 +918,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) ENDDO ENDDO ! Loop on concentrated mass - ! add concentrated mass induced gravity force + ! Add concentrated mass induced gravity force DO I = 1, Init%NCMass iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added iGlob = p%NodesDOF(iNode)%List(3) ! uz @@ -959,6 +960,59 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM +!> Add soil stiffness and mass to global system matrices +SUBROUTINE InsertSoilMatrices(M, K, Init, p, ErrStat, ErrMsg, Substract) + real(ReKi), dimension(:,:), intent(inout) :: M + real(ReKi), dimension(:,:), intent(inout) :: K + type(SD_InitType), intent(in ) :: Init + type(SD_ParameterType), intent(in ) :: p + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding + integer :: I, J + integer :: iDOF, iNode !< DOF and node indices + real(ReKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil + ErrMsg = "" + ErrStat = ErrID_None + ! TODO consider doing the 21 -> 6x6 conversion while reading + ! 6x6 matrix goes to one node of one element only + do I = 1, p%nNodes_C ! loop on constrained nodes + iNode = p%Nodes_C(I,1) + call Array21_to_6by6(Init%SSIK(I,:), K_soil) + call Array21_to_6by6(Init%SSIM(I,:), M_soil) + if (present(Substract)) then + if (Substract) then + K_soil = - K_soil + M_soil = - M_soil + endif + endif + do J = 1, 6 + iDOF = p%NodesDOF(iNode)%List(J) ! DOF index + K(iDOF, iDOF) = K(iDOF, iDOF) + K_soil(J,J) + M(iDOF, iDOF) = M(iDOF, iDOF) + M_soil(J,J) + enddo + enddo +contains + !> Convert a flatten array of 21 values into a symmetric 6x6 matrix + SUBROUTINE Array21_to_6by6(A21, M66) + use NWTC_LAPACK, only: LAPACK_TPTTR + real(ReKi), dimension(21) , intent(in) :: A21 + real(ReKi), dimension(6,6), intent(out) :: M66 + integer :: j + M66 = 0.0_ReKi + ! Reconstruct from sparse elements + CALL LAPACK_TPTTR('U',6,A21,M66,6, ErrStat, ErrMsg) + ! Ensuring symmetry + do j=1,6 + M66(j,j) = M66(j,j)/2 + enddo + M66=M66+TRANSPOSE(M66) + END SUBROUTINE Array21_to_6by6 +END SUBROUTINE InsertSoilMatrices + + + + !------------------------------------------------------------------------------------------------------ !> Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index da554ba57..73f6ed7b2 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -232,10 +232,17 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Assemble Stiffness and mass matrix CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! Insert soil stiffness and mass matrix + ! TODO, let's see if we can go without storing the "noSSI" matrices + ! Init%MorignoSSI=Init%M !original M, full and no SSI m + ! Init%KorignoSSI=Init%K !original K, full and no SSI k + CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! Init%Morig=Init%M !original M, full and WITH SSI-k effects + ! Init%Korig=Init%K !original K, full and WITH SSI-k effects + ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Additional Damping and stiffness at pin/ball/universal joints CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return @@ -821,8 +828,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) call AllocAry(Init%SSIK , p%nNodes_C, 21 , 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return call AllocAry(Init%SSIM , p%nNodes_C, 21 , 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return Init%SSIfile(:) = '' -Init%SSIK = HUGE(Init%SSIK) ! NOTE: huge used later. TODO: read these matrices on the fly in SD_FEM maybe? -Init%SSIM = 0.0_ReKi +Init%SSIK = 0.0_ReKi ! Important init TODO: read these matrices on the fly in SD_FEM maybe? +Init%SSIM = 0.0_ReKi ! Important init ! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile DO I = 1, p%nNodes_C READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return From 00ac04db490a7a2f2966c94f0aadb8d34a348550 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Apr 2020 15:31:33 -0600 Subject: [PATCH 185/377] FlexSub: reading extra 6 concentrated mass if present --- modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src/SubDyn.f90 | 72 +++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d08582f4d..b04e239f2 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -38,7 +38,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) - INTEGER(IntKi), PARAMETER :: CMassCol = 5 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ) + INTEGER(IntKi), PARAMETER :: CMassCol = 11 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ, Optional:JMXY,JMXZ,JMYZ,CGX,CGY,CGZ) ! Indices in Members table INTEGER(IntKi), PARAMETER :: iMType= 6 ! Index in Members table where the type is stored INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 73f6ed7b2..54eab8a9f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -832,7 +832,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%SSIM = 0.0_ReKi ! Important init ! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile DO I = 1, p%nNodes_C - READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading reaction line'; if (Failed()) return call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); if (nColValid==1 .and. nColNumeric==1) then ! Temporary allowing this @@ -873,7 +873,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) p%Nodes_I(:,1) = -1 ! First column is node, initalize to wrong value for safety ! Reading interface lines one by one, allowing for 1 or 7 columns (cannot use ReadIAry) DO I = 1, p%nNodes_I - READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='Reading interface line'; if (Failed()) return + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='Error reading interface line'; if (Failed()) return call ReadIAryFromStr(Line, p%Nodes_I(I,:), 7, nColValid, nColNumeric); if ((nColValid/=nColNumeric).or.((nColNumeric/=1).and.(nColNumeric/=7)) ) then CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 1 or 7 numerical values. Problematic line: "'//trim(Line)//'"') @@ -970,15 +970,25 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) !------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- CALL ReadCom ( UnIn, SDInputFile, 'Additional concentrated masses at joints ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NCMass, 'NCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%nCMass, 'nCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%CMass, Init%NCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return -Init%CMass = 0.0 -DO I = 1, Init%NCMass - CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%CMass, Init%nCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return +Init%CMass = 0.0 ! Important init since we allow user to only provide diagonal terms +DO I = 1, Init%nCMass + ! CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading concentrated mass line'; if (Failed()) return + call ReadFAryFromStr(Line, Init%CMass(I,:), CMassCol, nColValid, nColNumeric); + if ((nColValid/=nColNumeric).or.((nColNumeric/=5).and.(nColNumeric/=11)) ) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 5 or 11 numerical values. Problematic line: "'//trim(Line)//'"') + return + endif + if (any(p%Nodes_I(I,:)<=0)) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for interface lines. Problematic line: "'//trim(Line)//'"') + return + endif ENDDO -IF (Check( Init%NCMass < 0 , 'NCMass must be >=0')) return +IF (Check( Init%nCMass < 0 , 'NCMass must be >=0')) return !---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ CALL ReadCom (UnIn, SDInputFile, 'OUTPUT' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -1153,6 +1163,52 @@ SUBROUTINE ReadIAryFromStr(Str, IntArray, nColMax, nColValid, nColNumeric, StrAr if(allocated(StrArray)) deallocate(StrArray) END SUBROUTINE ReadIAryFromStr +!> See ReadIAryFromStr, same but for floats +SUBROUTINE ReadFAryFromStr(Str, FloatArray, nColMax, nColValid, nColNumeric, StrArrayOut) + character(len=*), intent(in) :: Str !< + real(ReKi), dimension(:), intent(inout) :: FloatArray !< NOTE: inout, to allow for init values + integer(IntKi), intent(in) :: nColMax + integer(IntKi), intent(out) :: nColValid, nColNumeric !< + character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric + character(255), allocatable :: StrArray(:) ! Array of strings extracted from line + real(ReKi) :: DummyFloat + integer(IntKi) :: J, nColStr + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + nColValid = 0 ; + nColNumeric = 0 ; + nColStr = 0 ; + ! --- First extract the different sub strings + CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); + if (ErrStat2/=ErrID_None) then + return ! User should notice that there is 0 valid columns + endif + StrArray(:)=''; + CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! + ! --- Then look for numerical values + do J = 1, nColMax + if (len(trim(StrArray(J)))>0) then + nColValid=nColValid+1 + if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! + nColNumeric=nColNumeric+1 + if (nColNumeric<=size(FloatArray)) then + FloatArray(nColNumeric) = DummyFloat + endif + else + nColStr = nColStr+1 + if (present(StrArrayOut)) then + if (nColStr <=size(StrArrayOut) )then + StrArrayOut(nColStr) = StrArray(J) + endif + endif + endif + endif + enddo + if(allocated(StrArray)) deallocate(StrArray) +END SUBROUTINE ReadFAryFromStr + + + !---------------------------------------------------------------------------------------------------------------------------------- !> Rotate the joint coordinates with respect to global z From 04d3f856bc8bf8fb008d1ed61631c22392c41cb5 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Apr 2020 18:05:29 -0600 Subject: [PATCH 186/377] FlexSub: adding extra inertial terms for concentrated mass --- modules/subdyn/src/SD_FEM.f90 | 43 +++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index b04e239f2..d242e234e 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -872,6 +872,9 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) INTEGER(IntKi) :: iNode !< Node index integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system + real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node + real(ReKi) :: m, x, y, z, Jxx, Jyy, Jzz, Jxy, Jxz, Jyz + INTEGER :: jGlob, kGlob ErrMsg = "" ErrStat = ErrID_None @@ -881,7 +884,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector Init%K = 0.0_ReKi Init%M = 0.0_ReKi Init%FG = 0.0_ReKi @@ -898,32 +901,44 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) - ENDDO ! end loop over elements , i + ENDDO - ! add concentrated mass - DO I = 1, Init%NCMass + ! Add concentrated mass to mass matrix + DO I = 1, Init%nCMass iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added - ! Safety + ! Safety check (otherwise we might have more than 6 DOF) if (Init%Nodes(iNode,iJointType) /= idJointCantilever) then ErrMsg2='Concentrated mass is only for cantilever joints. Problematic node: '//trim(Num2LStr(iNode)); ErrStat2=ErrID_Fatal; if(Failed()) return endif - DO J = 1, 3 - iGlob = p%NodesDOF(iNode)%List(J) ! ux, uy, uz - Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, 2) - ENDDO - DO J = 4, 6 - iGlob = p%NodesDOF(iNode)%List(J) ! theta_x, theta_y, theta_z - Init%M(iGlob, iGlob) = Init%M(iGlob, iGlob) + Init%CMass(I, J-1) + ! Mass matrix of a rigid body + M66 = 0.0_ReKi + m = Init%CMass(I,2) + Jxx = Init%CMass(I,3 ); Jxy = Init%CMass(I,6 ); x = Init%CMass(I,9 ); + Jyy = Init%CMass(I,4 ); Jxz = Init%CMass(I,7 ); y = Init%CMass(I,10); + Jzz = Init%CMass(I,5 ); Jyz = Init%CMass(I,8 ); z = Init%CMass(I,11); + M66(1 , :)=(/ m , 0._ReKi , 0._ReKi , 0._ReKi , z*m , -y*m /) + M66(2 , :)=(/ 0._ReKi , m , 0._ReKi , -z*m , 0._ReKi , x*m /) + M66(3 , :)=(/ 0._ReKi , 0._ReKi , m , y*m , -x*m , 0._ReKi /) + M66(4 , :)=(/ 0._ReKi , -z*m , y*m , Jxx + m*(y**2+z**2) , Jxy - m*x*y , Jxz - m*x*z /) + M66(5 , :)=(/ z*m , 0._ReKi , -x*m , Jxy - m*x*y , Jyy + m*(x**2+z**2) , Jyz - m*y*z /) + M66(6 , :)=(/ -y*m , x*m , 0._ReKi , Jxz - m*x*z , Jyz - m*y*z , Jzz + m*(x**2+y**2) /) + ! Adding + DO J = 1, 6 + jGlob = p%NodesDOF(iNode)%List(J) + DO K = 1, 6 + kGlob = p%NodesDOF(iNode)%List(K) + Init%M(jGlob, kGlob) = Init%M(jGlob, kGlob) + M66(J,K) + ENDDO ENDDO ENDDO ! Loop on concentrated mass ! Add concentrated mass induced gravity force - DO I = 1, Init%NCMass + DO I = 1, Init%nCMass iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added iGlob = p%NodesDOF(iNode)%List(3) ! uz Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g - ENDDO ! I concentrated mass induced gravity + ENDDO CALL CleanUp_AssembleKM() From 81fc25578acbb5925da4ce630e6ceb58fa3e0688 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 1 May 2020 16:40:19 -0600 Subject: [PATCH 187/377] FlexSub: output of full joints info in summary file --- modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src/SubDyn.f90 | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d242e234e..9f18854fa 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -28,7 +28,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 ! 6 degrees of freedom (length of u subarray [UTP]) ! values of these parameters are ordered by their place in SubDyn input file: - INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss) + INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff JointDamp) INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 54eab8a9f..14ddf3194 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2618,9 +2618,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',p%nNodes - WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' - WRITE(UnSum, '(A8,1x,A11,3(1x,A15))') '--------', '-----------', '---------------', '---------------', '---------------' -! WRITE(UnSum, '(I8.0, E15.6,E15.6,E15.6)') (INT(Init%Nodes(i, 1)),(Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) !do not group the format or it won't work 3(E15.6) does not work !bjj??? + WRITE(UnSum, '(A8,1x,A11,9(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' , 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & (NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) From 4404a540cc96286b3a864a132ca2b632ee3830f7 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 1 May 2020 19:08:43 -0600 Subject: [PATCH 188/377] FlexSub: using more generic function RigidTransf, more comments --- modules/subdyn/src/SD_FEM.f90 | 5 ++- modules/subdyn/src/SubDyn.f90 | 80 +++++++++++++++-------------------- 2 files changed, 37 insertions(+), 48 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 9f18854fa..ec9fdfeea 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1118,6 +1118,8 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) endif else ! --- Regular cantilever joint + ! TODO/NOTE: We could apply fixed constraint/BC here, returning Tc as a 6xn matrix with n<6 + ! Extreme case would be Tc: 6*0, in which case NodesDOFtilde would be empty ([]) allocate(Tc(1:6,1:6)) allocate(IDOFOld(1:6)) Tc=I6 @@ -1230,6 +1232,7 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" + ! Setup list of rigid link assemblies (RA) and the inverse function RA^{-1} call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return @@ -1293,7 +1296,7 @@ SUBROUTINE ReInitBCs(Init, p) INTEGER(IntKi) :: I, J, iNode DO I = 1, p%nNodes_C iNode = p%Nodes_C(I,1) ! Node index - DO J = 1, 6 + DO J = 1, 6 ! TODO NOTE here assumptions that 6 DOF are present Init%BCs( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) ENDDO ENDDO diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 14ddf3194..087032ae3 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1651,8 +1651,10 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) - ! Set p%TI and CBparams%TI2 - CALL TrnsfTI(Init, p, p%TI, p%nDOFI, p%IDI, CBparams%TI2, p%nDOFR, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return + ! Set TI, transformation matrix from interface DOFs to TP ref point + CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI, p%nDOFI, p%TI, ErrStat2, ErrMsg2); if(Failed()) return + ! Set TI2, transformation matrix from interface DOFs to TP ref point + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR, p%nDOFR, CBparams%TI2, ErrStat2, ErrMsg2); if(Failed()) return !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1836,6 +1838,9 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & ! Set OmegaL and PhiL from Eq. 2 !.................................................... IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... + ! NOTE: + ! bRemoveConstraint = False + ! bCheckSingularity = True CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .False.,Init,p, .True., PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL @@ -1919,74 +1924,51 @@ subroutine CleanUp() END SUBROUTINE CBMatrix !------------------------------------------------------------------------------------------------------ -!> -SUBROUTINE TrnsfTI(Init, p, TI, nDOFI, IDI, TI2, nDOFR, IDR, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine +!> Returns a rigid body transformation matrix from nDOF to 6 reference DOF: T_ref (6 x nDOF), such that Uref = T_ref.U_subset +!! Typically called to get: +!! - the transformation from the interface points to the TP point +!! - the transformation from the bottom nodes to SubDyn origin (0,0,) +SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(IN ) :: p - INTEGER(IntKi), INTENT(IN ) :: nDOFI ! # of DOFS of interface nodes - INTEGER(IntKi), INTENT(IN ) :: nDOFR ! # of DOFS of restrained nodes (restraints and interface) - INTEGER(IntKi), INTENT(IN ) :: IDI(nDOFI) - INTEGER(IntKi), INTENT(IN ) :: IDR(nDOFR) - REAL(ReKi), INTENT(INOUT) :: TI( nDOFI,6) ! matrix TI that relates the reduced matrix to the TP, - REAL(ReKi), INTENT(INOUT) :: TI2(nDOFR,6) ! matrix TI2 that relates to (0,0,0) the overall substructure mass + REAL(ReKi), INTENT(IN ) :: RefPoint(3) ! Coordinate of the reference point + INTEGER(IntKi), INTENT(IN ) :: nDOF ! Number of DOFS + INTEGER(IntKi), INTENT(IN ) :: DOF(nDOF) ! DOF indices that are used to create the transformation matrix + REAL(ReKi), INTENT( OUT) :: T_ref(nDOF,6) ! matrix that relates the subset of DOFs to the reference point INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - INTEGER :: I, J, K, iDOF, iiDOF, iNode, nDOFPerNode + INTEGER :: I, iDOF, iiDOF, iNode, nDOFPerNode REAL(ReKi) :: dx, dy, dz REAL(ReKi), dimension(6) :: Line - ErrStat = ErrID_None ErrMsg = "" - - ! --- TI: Transformation matrix from interface points to ref point - TI(:,:)=0 - DO I = 1, nDOFI - iDOF = IDI(I) ! DOF index in constrained system + T_ref(:,:)=0 + DO I = 1, nDOF + iDOF = DOF(I) ! DOF index in constrained system iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) if ((iiDOF<1) .or. (iiDOF>6)) then - ErrMsg = 'TransfTI, interface node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal return endif if (nDOFPerNode/=6) then - ErrMsg = 'TransfTI, interface node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + ErrMsg = 'RigidTrnsf, node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal return endif - dx = Init%Nodes(iNode, 2) - Init%TP_RefPoint(1) - dy = Init%Nodes(iNode, 3) - Init%TP_RefPoint(2) - dz = Init%Nodes(iNode, 4) - Init%TP_RefPoint(3) + dx = Init%Nodes(iNode, 2) - RefPoint(1) + dy = Init%Nodes(iNode, 3) - RefPoint(2) + dz = Init%Nodes(iNode, 4) - RefPoint(3) CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line - TI(I, 1:6) = Line + T_ref(I, 1:6) = Line ENDDO - ! --- TI2: Transformation matrix from reaction points to origin - TI2(:,:) = 0. !Initialize - DO I = 1, nDOFR - iDOF = IDR(I) ! DOF index in constrained system - iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) +END SUBROUTINE RigidTrnsf + - if ((iiDOF<1) .or. (iiDOF>6)) then - ErrMsg = 'TransfTI, reaction node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal - return - endif - if (nDOFPerNode/=6) then - ErrMsg = 'TransfTI, reaction node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal - return - endif - - dx = Init%Nodes(iNode, 2) - dy = Init%Nodes(iNode, 3) - dz = Init%Nodes(iNode, 4) - CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) ! returns Line - TI2(I, 1:6) = Line - ENDDO -END SUBROUTINE TrnsfTI !------------------------------------------------------------------------------------------------------ !> Wrapper function for eigen value analyses, for two cases: @@ -2582,6 +2564,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) nOmega = p%nDOF_red - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2 ); if(Failed()) return CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2 ); if(Failed()) return + ! NOTE: below, we don't check for singularity, since this is full system (R+L), which may contain rigid body modes + ! M and K are reduced matrices, but Boundary conditions are not applied + ! bRemoveConstraint = True + ! bCheckSingularity = False CALL EigenSolveWrap( Init%K, Init%M, p%nDOF_red, nOmega, .True., Init, p, .False., Modes, Omega, ErrStat2, ErrMsg2 ); if(Failed()) return !------------------------------------------------------------------------------------------------------------- From 7ea06193abd12b318a0fee42c8b14955050ced8d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 1 May 2020 20:01:03 -0600 Subject: [PATCH 189/377] FlexSub: starting to simplify BC handling --- modules/subdyn/src/SD_FEM.f90 | 45 +++--- modules/subdyn/src/SubDyn.f90 | 204 +++++++++++-------------- modules/subdyn/src/SubDyn_Registry.txt | 1 - modules/subdyn/src/SubDyn_Types.f90 | 65 -------- 4 files changed, 106 insertions(+), 209 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ec9fdfeea..2911249c9 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -59,6 +59,11 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idMemberBeam = 1 INTEGER(IntKi), PARAMETER :: idMemberCable = 2 INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 + + ! Types of Boundary Conditions + INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 + INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 + INTEGER(IntKi), PARAMETER :: idBC_Leader = 13 ! TODO, and maybe "BC" not appropriate here INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) @@ -830,7 +835,20 @@ SUBROUTINE InitBCs(Init, p) iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%BCs( (I-1)*6+J, 2) = 1 ! NOTE: Always selected now p%Nodes_C(I, J+1); ! 0 or 1 if fixed reaction or not + if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) + Init%BCs( (I-1)*6+J, 2) = idBC_Fixed + else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF + Init%BCs( (I-1)*6+J, 2) = idBC_Internal + print*,'BC 0 not allowed for now, node',iNode + STOP + else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF + Init%BCs( (I-1)*6+J, 2) = idBC_Leader + print*,'BC 2 not allowed for now, node',iNode + STOP + else + print*,'Wrong boundary condition input for reaction node',iNode + STOP + endif ENDDO ENDDO END SUBROUTINE InitBCs @@ -1289,7 +1307,7 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(RA )) deallocate(RA ) END SUBROUTINE CleanUp_DirectElimination - !> Reset DOF indices after elimination + !> Reset DOF indices after elimination, does not change the BC SUBROUTINE ReInitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p @@ -1659,29 +1677,6 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) enddo END SUBROUTINE InsertJointStiffDamp -!> Apply constraint (Boundary conditions) on Mass and Stiffness matrices -SUBROUTINE ApplyConstr(Init,p) - TYPE(SD_InitType ),INTENT(INOUT):: Init - TYPE(SD_ParameterType),INTENT(IN ):: p - - INTEGER :: I !, J, k - INTEGER :: row_n !bgn_j, end_j, - - DO I = 1, p%nNodes_C*6 - row_n = Init%BCs(I, 1) - IF (Init%BCs(I, 2) == 1) THEN - Init%K(row_n,: )= 0 - Init%K(: ,row_n)= 0 - Init%K(row_n,row_n)= 1 - - Init%M(row_n,: )= 0 - Init%M(: ,row_n)= 0 - Init%M(row_n,row_n)= 0 - ENDIF - ENDDO ! I, loop on reaction nodes -END SUBROUTINE ApplyConstr - - SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(ReKi), INTENT(OUT) :: Me(12, 12) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 087032ae3..b69ee192d 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1644,7 +1644,6 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%TI2, p%nDOFR, 6, 'CBparams%TI2', ErrStat2, ErrMsg2 ); if(Failed()) return ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on @@ -1653,8 +1652,6 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! Set TI, transformation matrix from interface DOFs to TP ref point CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI, p%nDOFI, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - ! Set TI2, transformation matrix from interface DOFs to TP ref point - CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR, p%nDOFR, CBparams%TI2, ErrStat2, ErrMsg2); if(Failed()) return !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1688,9 +1685,15 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! MBBb, MBMb, KBBb, PHiRb, FGRb ! (throw out rows/columns of first matrices to create second matrices) !................................ - CALL CBApplyConstr(p%nDOFI, p%nDOFR, p%nDOFM, p%nDOFL, & - CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR , & - MBBb, MBMb, KBBb, PHiRb, FGRb) + ! TODO avoid this all together + MBBb = CBparams%MBB(p%nDOFR-p%nDOFI+1:p%nDOFR, p%nDOFR-p%nDOFI+1:p%nDOFR) + KBBb = CBparams%KBB(p%nDOFR-p%nDOFI+1:p%nDOFR, p%nDOFR-p%nDOFI+1:p%nDOFR) +IF (p%nDOFM > 0) THEN + MBMb = CBparams%MBM(p%nDOFR-p%nDOFI+1:p%nDOFR, : ) +END IF + FGRb = FGR(p%nDOFR-p%nDOFI+1:p%nDOFR ) + PhiRb = CBparams%PhiR( :, p%nDOFR-p%nDOFI+1:p%nDOFR) + ! TODO TODO TODO Transform new damping matrix as well !................................ ! set values needed to calculate outputs and update states: @@ -1841,7 +1844,7 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & ! NOTE: ! bRemoveConstraint = False ! bCheckSingularity = True - CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .False.,Init,p, .True., PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .True., PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL ! bjj: break up this equation to avoid as many tenporary variables on the stack @@ -1972,82 +1975,77 @@ END SUBROUTINE RigidTrnsf !------------------------------------------------------------------------------------------------------ !> Wrapper function for eigen value analyses, for two cases: -!! Case1: K and M are taken "as is" (bRemoveConstraints=false), This is used for the "LL" part of the matrix -!! Case2: K and M constain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system -SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bRemoveConstraints, Init, p, bCheckSingularity, Phi, Omega, ErrStat, ErrMsg ) - USE NWTC_ScaLAPACK, only: ScaLAPACK_LASRT +!! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix +!! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system +SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues - LOGICAL, INTENT(IN ) :: bRemoveConstraints ! Whether or not to reduce matrices, this will be removed altogether later, when reduction will be done apriori - TYPE(SD_InitType), INTENT(IN ) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present - REAL(ReKi), INTENT( OUT) :: Phi(nDOF, NOmega) ! Returned Eigenvectors + REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) + ! LOCALS - REAL(LAKi), ALLOCATABLE :: Kred(:,:), Mred(:,:) - REAL(LAKi), ALLOCATABLE :: EigVect(:,:), Omega2_LaKi(:) + REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) + REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) REAL(ReKi) :: Om2 INTEGER(IntKi) :: N, i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) - ErrStat = ErrID_None ErrMsg = '' - - ! --- Special handling if constraint are present, and type conversion - IF (bRemoveConstraints) THEN - ! Removing constrained nodes DOFs, only done for printing out the 'full' set of eigenvalues - ! Mred = M[bDOF,bDOF], Kred = K[bDOF,bDOF] - call SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(M, bDOF, Mred, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(K, bDOF, Kred, ErrStat2, ErrMsg2); if(Failed()) return - N=SIZE(Kred,1) - ELSE - ! This is actually done whe we are generating the CB-reduced set of eigenvalues - N=SIZE(K,1) - CALL AllocAry( Kred, n, n, 'Kred', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry( Mred, n, n, 'Mred', ErrStat2, ErrMsg2 ); if(Failed()) return - Kred=REAL( K, LAKi ) - Mred=REAL( M, LAKi ) - ENDIF + + ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi + if (present(bDOF)) then + ! Remove unwanted DOFs + call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + else + N=size(K,1) + CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + K_LaKi = real( K, LaKi ) + M_LaKi = real( M, LaKi ) + endif + N=size(K_LaKi,1) + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - IF ( NOmega > N ) THEN + if ( NOmega > nDOF ) then CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') CALL CleanupEigen() - RETURN - END IF + return + end if + ! --- Eigenvalue analysis - CALL AllocAry( Omega2_LaKi, N, 'Omega', ErrStat2, ErrMsg2 ); if (Failed()) return; - CALL AllocAry( EigVect , N, N, 'EigVect', ErrStat2, ErrMsg2 ); if (Failed()) return; - CALL EigenSolve(Kred, Mred, N, bCheckSingularity, EigVect, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; + CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion do i = 1, NOmega Om2 = real(Omega2_LaKi(i), ReKi) - if (Om2>0) then + if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics + Omega(i)=0.0_ReKi + elseif (Om2>0) then Omega(i)=sqrt(Om2) ! was getting floating invalid else print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 Omega(i)= 0.0_ReKi endif enddo - IF ( bRemoveConstraints ) THEN ! this is called for the full system Eigenvalues: - !Need to expand eigenvectors for removed DOFs, setting Phi - CALL InsertDOFRows(EigVect(:,1:NOmega), bDOF, 0.0_ReKi, Phi, ErrStat2, ErrMsg2 ); if(Failed()) return - ELSE - Phi=REAL( EigVect(:,1:NOmega), ReKi ) ! eigenvectors - ENDIF - + if (present(bDOF)) then + ! Insert 0s where bDOF was false + CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return + else + EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors + endif CALL CleanupEigen() - RETURN - + return CONTAINS LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') @@ -2056,72 +2054,37 @@ LOGICAL FUNCTION Failed() END FUNCTION Failed SUBROUTINE CleanupEigen() - IF (ALLOCATED(Omega2_LaKi)) DEALLOCATE(Omega2_LaKi) - IF (ALLOCATED(EigVect) ) DEALLOCATE(EigVect) - IF (ALLOCATED(Kred) ) DEALLOCATE(Kred) - IF (ALLOCATED(Mred) ) DEALLOCATE(Mred) - IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) + IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) + IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) + IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) + IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolveWrap -!> Returns a list of boolean which are true if a DOF is not part of a BC constraint -SUBROUTINE SelectNonBCConstraintsDOF(Init, p, nDOF, bDOF, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT( in) :: Init - TYPE(SD_ParameterType), INTENT( in) :: p - INTEGER(IntKi), INTENT( in) :: nDOF - LOGICAL, ALLOCATABLE, INTENT( out) :: bDOF(:) ! Mask, False for DOF that are Constraints BC DOF +!> Returns a list of boolean which are true if a DOF is not part of a fixed BC +SUBROUTINE SelectNonFixedDOF(BCs, bDOF, ErrStat, ErrMsg ) + INTEGER(IntKi), INTENT( IN) :: BCs(:,:) ! nx2 array, columns: iDOF, BC_type + LOGICAL, INTENT( OUT) :: bDOF(:) ! Mask, False for DOF that are Constraints BC DOF INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER :: I ! counters into full or reduced matrix - INTEGER :: NReactDOFs + INTEGER :: iBC, iDOF ErrStat = ErrID_None ErrMsg = '' - - NReactDOFs = p%nNodes_C*6 !p%nDOFC - IF (NReactDOFs > nDOF) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'SelectNonBCConstraintsDOF: invalid matrix sizes.' - RETURN - END IF - - CALL AllocAry(bDOF, nDOF, 'bDOF', ErrStat, ErrMsg ); IF (ErrStat >= AbortErrLev) RETURN - ! Setting array of DOF, true if we keep them - bDOF(1:nDOF)=.True. - do I = 1, NReactDOFs !Cycle on reaction DOFs - if (Init%BCs(I, 2) == 1) THEN - bDOF(Init%BCs(I, 1)) = .False. ! Eliminate this one + bDOF(:)=.True. + do iBC = 1, size(BCs,1) !Cycle on reaction DOFs + if (BCs(iBC, 2) == idBC_Fixed) then + iDOF = BCs(iBC,1) + if (iDOF>size(bDOF)) then + ErrMsg='Error setting boundary condition, DOF index too large: '//trim(Num2LStr(iDOF)) + ErrStat=ErrID_Fatal; + return + endif + bDOF(iDOF) = .False. ! Eliminate this one end if end do -END SUBROUTINE -!------------------------------------------------------------------------------------------------------ -SUBROUTINE CBApplyConstr(nDOFI, nDOFR, nDOFM, nDOFL, & - MBB , MBM , KBB , PHiR , FGR , & - MBBb, MBMb, KBBb, PHiRb, FGRb) - INTEGER(IntKi), INTENT(IN ) :: nDOFR, nDOFI, nDOFM, nDOFL - REAL(ReKi), INTENT(IN ) :: FGR(nDOFR) - REAL(ReKi), INTENT(IN ) :: MBB(nDOFR, nDOFR) - REAL(ReKi), INTENT(IN ) :: MBM(nDOFR, nDOFM) - REAL(ReKi), INTENT(IN ) :: KBB(nDOFR, nDOFR) - REAL(ReKi), INTENT(IN ) :: PhiR(nDOFL, nDOFR) - REAL(ReKi), INTENT( OUT) :: MBBb(nDOFI, nDOFI) - REAL(ReKi), INTENT( OUT) :: KBBb(nDOFI, nDOFI) - REAL(ReKi), INTENT( OUT) :: MBMb(nDOFI, nDOFM) - REAL(ReKi), INTENT( OUT) :: FGRb(nDOFI) - REAL(ReKi), INTENT( OUT) :: PhiRb(nDOFL, nDOFI) - - MBBb = MBB(nDOFR-nDOFI+1:nDOFR, nDOFR-nDOFI+1:nDOFR) - KBBb = KBB(nDOFR-nDOFI+1:nDOFR, nDOFR-nDOFI+1:nDOFR) -IF (nDOFM > 0) THEN - MBMb = MBM(nDOFR-nDOFI+1:nDOFR, : ) -END IF - FGRb = FGR(nDOFR-nDOFI+1:nDOFR ) - PhiRb = PhiR( :, nDOFR-nDOFI+1:nDOFR) - -END SUBROUTINE CBApplyConstr - +END SUBROUTINE SelectNonFixedDOF !------------------------------------------------------------------------------------------------------ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine @@ -2547,28 +2510,29 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices + real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega real(ReKi), dimension(:,:), allocatable :: Modes real(ReKi), dimension(:) , allocatable :: Omega + logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) ! ErrStat = ErrID_None ErrMsg = "" ! --- Eigen values of full system (for summary file output only) - ! True below is to remove the constraints ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! M and K are reduced matrices, but Boundary conditions are not applied + ! We set bDOF, which is true if not a fixed Boundary conditions ! NOTE: we don't check for singularities/rigig body modes here CALL WrScr(' Calculating Full System Modes (for summary file output)') - - nOmega = p%nDOF_red - p%nNodes_C*6 !removed an extra "-6" !Note if fixity changes at the reaction points, this will need to change - CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2 ); if(Failed()) return - ! NOTE: below, we don't check for singularity, since this is full system (R+L), which may contain rigid body modes - ! M and K are reduced matrices, but Boundary conditions are not applied - ! bRemoveConstraint = True - ! bCheckSingularity = False - CALL EigenSolveWrap( Init%K, Init%M, p%nDOF_red, nOmega, .True., Init, p, .False., Modes, Omega, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return + call SelectNonFixedDOF(Init%BCs, bDOF, ErrStat2, ErrMsg2); if(Failed()) return + nOmega = count(bDOF) + CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2); if(Failed()) return + call EigenSolveWrap(Init%K, Init%M, p%nDOF_red, nOmega, .False., Modes, Omega, ErrStat2, ErrMsg2, bDOF); if(Failed()) return + IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) !------------------------------------------------------------------------------------------------------------- ! open txt file @@ -2732,7 +2696,11 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%MBB(i,j), j = 1, 6) ENDDO - MRB=matmul(TRANSPOSE(CBparams%TI2),matmul(CBparams%MBB,CBparams%TI2)) !Equivalent mass matrix of the rigid body + ! Set TI2, transformation matrix from R DOFs to SubDyn Origin + CALL AllocAry( TI2, p%nDOFR, 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR, p%nDOFR, TI2, ErrStat2, ErrMsg2); if(Failed()) return + MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body + deallocate(TI2) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' WRITE(UnSum, '(A)') SubSectionDivide diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index dd1267611..8c127cc46 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -38,7 +38,6 @@ typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connect typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" # CB_MatArrays: Matrices and arrays for CB summary -typedef SubDyn/SD CB_MatArrays ReKi TI2 {:}{:} - - "TI2 matrix to refer to total mass to (0,0,0)" typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index d49b82909..f5c7b8a4d 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -70,7 +70,6 @@ MODULE SubDyn_Types ! ======================= ! ========= CB_MatArrays ======= TYPE, PUBLIC :: CB_MatArrays - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI2 !< TI2 matrix to refer to total mass to (0,0,0) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] @@ -1637,20 +1636,6 @@ SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCo ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcCB_MatArraysData%TI2)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%TI2,1) - i1_u = UBOUND(SrcCB_MatArraysData%TI2,1) - i2_l = LBOUND(SrcCB_MatArraysData%TI2,2) - i2_u = UBOUND(SrcCB_MatArraysData%TI2,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%TI2)) THEN - ALLOCATE(DstCB_MatArraysData%TI2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%TI2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%TI2 = SrcCB_MatArraysData%TI2 -ENDIF IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) @@ -1744,9 +1729,6 @@ SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(CB_MatArraysData%TI2)) THEN - DEALLOCATE(CB_MatArraysData%TI2) -ENDIF IF (ALLOCATED(CB_MatArraysData%MBB)) THEN DEALLOCATE(CB_MatArraysData%MBB) ENDIF @@ -1802,11 +1784,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! TI2 allocated yes/no - IF ( ALLOCATED(InData%TI2) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! TI2 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%TI2) ! TI2 - END IF Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no IF ( ALLOCATED(InData%MBB) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension @@ -1864,22 +1841,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%TI2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TI2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI2,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TI2,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI2,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%TI2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TI2))-1 ) = PACK(InData%TI2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TI2) - END IF IF ( .NOT. ALLOCATED(InData%MBB) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2009,32 +1970,6 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%TI2)) DEALLOCATE(OutData%TI2) - ALLOCATE(OutData%TI2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%TI2)>0) OutData%TI2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TI2))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TI2) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated Int_Xferred = Int_Xferred + 1 ELSE From 62c5bfa7e49f4fbcffb4ea19b3bd6ee4d0e38aa0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 1 May 2020 22:30:44 -0600 Subject: [PATCH 190/377] FlexSub: isolating generic code --- modules/subdyn/src/SubDyn.f90 | 266 +++++++++++++++++++--------------- 1 file changed, 149 insertions(+), 117 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b69ee192d..45382ad29 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -246,6 +246,30 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! --- Additional Damping and stiffness at pin/ball/universal joints CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return + + ! Allocate the output matrices and the index mapping array +! DOF_reduced = Init%TDOF-p%DOFCr +! CALL AllocAry(p%IDCr, p%DOFCr, 'IDCR', ErrStat2, ErrMsg2 ) +! CALL AllocAry(RetDOFs, DOF_reduced, 'RetDOFs', ErrStat2, ErrMsg2 ) +! !........ +! ! set the indices we want to keep (i.e., a mapping from reduced to full matrix) +! J = 1 +! J2 = 1 +! DO I=1,Init%TDOF +! idx(J) = idx(I) +! IF ( idx(J) /= 0 ) THEN +! J = J + 1 +! ELSE +! p%IDCR(J2) = I +! j2=j2+1 +! ENDIF +! +! END DO +! !idx retains the rows (column) indices that are still active and has 0-padding (from elementTDOF-DOFCR to TDOF) to account for the removed ones, and everywhere else +! !idx2 retains the rows (column) indices that are removed (fixed DOFs, there are DOFCR of them) +! RetDOFs=idx(1:DOF_reduced) + + ! -------------------------------------------------------------------------------- ! --- CB, Misc ! -------------------------------------------------------------------------------- @@ -983,8 +1007,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 5 or 11 numerical values. Problematic line: "'//trim(Line)//'"') return endif - if (any(p%Nodes_I(I,:)<=0)) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for interface lines. Problematic line: "'//trim(Line)//'"') + if (Init%CMass(I,1)<=0) then ! Further checks in JointIDs are done in SD_FEM + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Invalid concentrated mass JointID. Problematic line: "'//trim(Line)//'"') return endif ENDDO @@ -1600,6 +1624,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(ReKi), ALLOCATABLE :: FGRb(:) REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array + INTEGER(IntKi) :: nM_Out, i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None @@ -1629,6 +1654,9 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) + CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI, p%nDOFI, p%TI, ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry( MRR, p%nDOFR, p%nDOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( MLL, p%nDOFL, p%nDOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( MRL, p%nDOFR, p%nDOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') @@ -1644,15 +1672,11 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - - ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on - ! Init%M, Init%K, and Init%FG data and indices p%IDR and p%IDL: - CALL BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on M, K, FG and indices IDR and IDL + ! NOTE: generic FEM code + CALL BreakSysMtrx(Init%M, Init%K, Init%FG, p%IDR, p%IDL, p%nDOFR, p%nDOFL, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) - ! Set TI, transformation matrix from interface DOFs to TP ref point - CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI, p%nDOFI, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: ! CBparams%OmegaL (omega) and CBparams%PhiL from Eq. 2 @@ -1660,8 +1684,23 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! CBparams%PhiR from Eq. 3 ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. !................................ - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFM, Init, & ! < inputs - CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2, p) ! <- outputs (p is also input ) + CALL WrScr(' Performing Craig-Bampton decomposition') + IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT + nM_Out=p%nDOFL ! Selecting all CB modes for outputs to the function below + ELSE + nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes + ENDIF + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFR, p%nDOFL, p%nDOFM, nM_Out, & ! < inputs + CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2) ! <- outputs + + ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement + IF (p%SttcSolve) THEN + p%PhiL_T=TRANSPOSE(CBparams%PhiL) !transpose of PhiL for static improvement + DO I = 1, nM_Out + p%PhiLInvOmgL2(:,I) = CBparams%PhiL(:,I)* (1./CBparams%OmegaL(I)**2) + ENDDO + END IF + ! TODO TODO TODO DAMPING MATRIX if(Failed()) return @@ -1737,80 +1776,89 @@ END SUBROUTINE Craig_Bampton !------------------------------------------------------------------------------------------------------ !> Partition matrices and vectors into Boundary (R) and internal (L) nodes -!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FGR = FG(IDR) -!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FGL = FG(IDL) +!! M = [ MRR, MRL ] +!! [ sym, MLL ] +!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FR = F(IDR) +!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) !! MRL = M(IDR, IDL), KRR = K(IDR, IDL) -SUBROUTINE BreakSysMtrx(Init, p, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL ) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT( OUT) :: MRR(p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT( OUT) :: MLL(p%nDOFL, p%nDOFL) - REAL(ReKi), INTENT( OUT) :: MRL(p%nDOFR, p%nDOFL) - REAL(ReKi), INTENT( OUT) :: KRR(p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT( OUT) :: KLL(p%nDOFL, p%nDOFL) - REAL(ReKi), INTENT( OUT) :: KRL(p%nDOFR, p%nDOFL) - REAL(ReKi), INTENT( OUT) :: FGR(p%nDOFR) - REAL(ReKi), INTENT( OUT) :: FGL(p%nDOFL) - ! local variables - INTEGER(IntKi) :: I, J, II, JJ - - !MRR = Init%M(p%IDR,p%IDR) - !KRR = Init%K(p%IDR,p%IDR) - DO I = 1, p%nDOFR !Boundary DOFs - II = p%IDR(I) - FGR(I) = Init%FG(II) - DO J = 1, p%nDOFR - JJ = p%IDR(J) - MRR(I, J) = Init%M(II, JJ) - KRR(I, J) = Init%K(II, JJ) +!! NOTE: generic code, TODO: move me to FEM +SUBROUTINE BreakSysMtrx(MM, KK, FG, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix + REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix + REAL(ReKi), INTENT(IN ) :: FG(:) !< Force vector + INTEGER(IntKi), INTENT(IN ) :: nR + INTEGER(IntKi), INTENT(IN ) :: nL + INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs + INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs + REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) + REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) + REAL(ReKi), INTENT( OUT) :: FGR(nR) + REAL(ReKi), INTENT( OUT) :: FGL(nL) + INTEGER(IntKi) :: I, J, II, JJ + + ! RR: Leader/Boundary DOFs + DO I = 1, nR + II = IDR(I) + FGR(I) = FG(II) + DO J = 1, nR + JJ = IDR(J) + MRR(I, J) = MM(II, JJ) + KRR(I, J) = KK(II, JJ) ENDDO ENDDO - - DO I = 1, p%nDOFL - II = p%IDL(I) - FGL(I) = Init%FG(II) - DO J = 1, p%nDOFL - JJ = p%IDL(J) - MLL(I, J) = Init%M(II, JJ) - KLL(I, J) = Init%K(II, JJ) + ! LL: Interior/follower DOFs + DO I = 1, nL + II = IDL(I) + FGL(I) = FG(II) + DO J = 1, nL + JJ = IDL(J) + MLL(I, J) = MM(II, JJ) + KLL(I, J) = KK(II, JJ) ENDDO ENDDO - - DO I = 1, p%nDOFR - II = p%IDR(I) - DO J = 1, p%nDOFL - JJ = p%IDL(J) - MRL(I, J) = Init%M(II, JJ) - KRL(I, J) = Init%K(II, JJ) !Note KRL and MRL are getting data from a constraint-applied formatted M and K (i.e. Mbar and Kbar) this may not be legit!! RRD - ENDDO !I think this is fixed now since the constraint application occurs later + ! RL: cross terms + DO I = 1, nR + II = IDR(I) + DO J = 1, nL + JJ = IDL(J) + MRL(I, J) = MM(II, JJ) + KRL(I, J) = KK(II, JJ) + ENDDO ENDDO - END SUBROUTINE BreakSysMtrx !------------------------------------------------------------------------------------------------------ -!> Sets the CB values, as documented in the SubDyn Theory Guide: -! OmegaL (omega) and PhiL from Eq. 2 -! p%PhiL_T and p%PhiLInvOmgL2 for static improvement (will be added to theory guide later?) -! PhiR from Eq. 3 -! MBB, MBM, and KBB from Eq. 4. -!................................ -SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,p) - TYPE(SD_InitType), INTENT(IN) :: Init ! TODO remove me - TYPE(SD_ParameterType), INTENT(INOUT) :: p ! TODO remove m - INTEGER(IntKi), INTENT( in) :: nDOFM - REAL(ReKi), INTENT( IN) :: MRR( p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT( IN) :: MLL( p%nDOFL, p%nDOFL) - REAL(ReKi), INTENT( IN) :: MRL( p%nDOFR, p%nDOFL) - REAL(ReKi), INTENT( IN) :: KRR( p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT(INOUT) :: KLL( p%nDOFL, p%nDOFL) ! on exit, it has been factored (otherwise not changed) - REAL(ReKi), INTENT( IN) :: KRL( p%nDOFR, p%nDOFL) - REAL(ReKi), INTENT(INOUT) :: MBB( p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT(INOUT) :: MBM( p%nDOFR, nDOFM) - REAL(ReKi), INTENT(INOUT) :: KBB( p%nDOFR, p%nDOFR) - REAL(ReKi), INTENT(INOUT) :: PhiR(p%nDOFL, p%nDOFR) - REAL(ReKi), INTENT(INOUT) :: PhiL(p%nDOFL, p%nDOFL) !used to be PhiM(nDOFL,nDOFM), now it is more generic - REAL(ReKi), INTENT(INOUT) :: OmegaL(p%nDOFL) !used to be omegaM only ! Eigenvalues +!> Performs Craig-Bampton reduction based on partitioned matrices M and K +!! Convention is: +!! "R": leader DOF -> "B": reduced leader DOF +!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) +!! NOTE: +!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned +!! - Possibility to get all the CB modes using the input nM_Out>nM +!! +!! NOTE: generic code, TODO: move me to FEM +SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) + INTEGER(IntKi), INTENT( in) :: nR + INTEGER(IntKi), INTENT( in) :: nL + INTEGER(IntKi), INTENT( in) :: nM_Out + INTEGER(IntKi), INTENT( in) :: nM + REAL(ReKi), INTENT( IN) :: MRR( nR, nR) + REAL(ReKi), INTENT( IN) :: MLL( nL, nL) + REAL(ReKi), INTENT( IN) :: MRL( nR, nL) + REAL(ReKi), INTENT( IN) :: KRR( nR, nR) + REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) + REAL(ReKi), INTENT( IN) :: KRL( nR, nL) + REAL(ReKi), INTENT(INOUT) :: MBB( nR, nR) + REAL(ReKi), INTENT(INOUT) :: MBM( nR, nM) + REAL(ReKi), INTENT(INOUT) :: KBB( nR, nR) + REAL(ReKi), INTENT(INOUT) :: PhiR(nL, nR) ! Guyan Modes + REAL(ReKi), INTENT(INOUT) :: PhiL(nL, nL) ! Craig-Bampton modes TODO nM_out? + REAL(ReKi), INTENT(INOUT) :: OmegaL(nL) ! Eigenvalues TODO nM_out? INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! LOCAL VARIABLES @@ -1818,93 +1866,72 @@ SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nDOFM, Init, & REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%nDOFR,p%nDOFL) = transpose of PhiR * MLL (temporary storage) INTEGER :: I !, lwork !counter, and varibales for inversion routines - INTEGER :: DOFvar !placeholder used to get both PhiL or PhiM into 1 process - INTEGER :: ipiv(p%nDOFL) !the integer vector ipvt of length min(m,n), containing the pivot indices. + INTEGER :: ipiv(nL) !the integer vector ipvt of length min(m,n), containing the pivot indices. !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' - ErrStat = ErrID_None ErrMsg = '' - CALL WrScr(' Calculating Internal Modal Eigenvectors') - - IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT - DOFvar=p%nDOFL - ELSE - DOFvar=nDOFM !Initialize for normal cases, dynamic only - ENDIF + if (nM_out>nL) then + ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; + if(Failed()) return; + endif !.................................................... ! Set OmegaL and PhiL from Eq. 2 !.................................................... - IF ( DOFvar > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - ! NOTE: - ! bRemoveConstraint = False - ! bCheckSingularity = True - CALL EigenSolveWrap(KLL, MLL, p%nDOFL, DOFvar, .True., PhiL(:,1:DOFvar), OmegaL(1:DOFvar), ErrStat2, ErrMsg2); if(Failed()) return + IF ( nM_out > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... + ! bCheckSingularity = True + CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL - ! bjj: break up this equation to avoid as many tenporary variables on the stack + ! bjj: break up this equation to avoid as many temporary variables on the stack ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) - CALL AllocAry( Temp , p%nDOFL , p%nDOFL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return - CALL AllocAry( MU , p%nDOFL , p%nDOFL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , nL , nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL) Temp = MATMUL( MU, MLL ) MU = MATMUL( Temp, PhiL ) DEALLOCATE(Temp) ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) - DO I = 1, DOFvar + DO I = 1, nM_out PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) ENDDO - DO I=DOFvar+1, p%nDOFL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) + DO I=nM_out+1, nL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) PhiL(:,I) = 0.0_ReKi OmegaL(I) = 0.0_ReKi END DO DEALLOCATE(MU) - - !.................................................... - ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement - !.................................................... - IF (p%SttcSolve) THEN - p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement - DO I = 1, p%nDOFL - p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) - ENDDO - END IF - - ! ELSE .not. p%SttcSolve .and. nDOFM < p%nDOFL (in this case, PhiL, OmegaL aren't used) END IF - !.................................................... ! Set PhiR from Eq. 3: !.................................................... ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** - CALL LAPACK_getrf( p%nDOFL, p%nDOFL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return + CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N',N=p%nDOFL,A=KLL,IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return + CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return !.................................................... ! Set MBB, MBM, and KBB from Eq. 4: !.................................................... - CALL AllocAry( PhiR_T_MLL, p%nDOFR, p%nDOFL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return PhiR_T_MLL = TRANSPOSE(PhiR) PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) MBB = MATMUL(MRL, PhiR) MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) - - IF ( nDOFM .EQ. 0) THEN + IF ( nM == 0) THEN MBM = 0.0_ReKi ELSE - MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nDOFM)) ! last half of operation - MBM = MATMUL( MRL, PhiL(:,1:nDOFM) ) + MBM !This had PhiM + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM ENDIF DEALLOCATE( PhiR_T_MLL ) @@ -2096,7 +2123,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOFL, p%nDOFI) REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOFL) REAL(ReKi), INTENT(IN ) :: FGRb(p%nDOFI) - REAL(ReKi), INTENT(IN ) :: FGL(p%nDOFL) + REAL(ReKi), INTENT(IN ) :: FGL(p%nDOFL) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -2418,6 +2445,11 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ! call CleanUp() + print*,'DOF_I ',p%IDI + print*,'DOF_L ',p%IDL + print*,'DOF_C ',p%IDC + print*,'Nodes_C',p%Nodes_C(:,1) + print*,'Nodes_L',p%Nodes_L print*,'Nodes_I',p%Nodes_I(:,1) print*,'Nodes_C',p%Nodes_C(:,1) print*,'Nodes_L',p%Nodes_L From 0300b6d5449a06c3638b574696a25cd9f20e3f8d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 2 May 2020 16:01:33 -0600 Subject: [PATCH 191/377] FlexSub: extensive partitioning of DOF --- cmake/OpenfastFortranOptions.cmake | 2 +- modules/subdyn/src/IntegerList.f90 | 11 + modules/subdyn/src/SD_FEM.f90 | 54 +- modules/subdyn/src/SubDyn.f90 | 546 +++++++++++------- modules/subdyn/src/SubDyn_Output.f90 | 6 +- modules/subdyn/src/SubDyn_Registry.txt | 33 +- modules/subdyn/src/SubDyn_Types.f90 | 755 ++++++++++++++++++++----- 7 files changed, 1017 insertions(+), 390 deletions(-) diff --git a/cmake/OpenfastFortranOptions.cmake b/cmake/OpenfastFortranOptions.cmake index 6e8980f80..3ed50e780 100644 --- a/cmake/OpenfastFortranOptions.cmake +++ b/cmake/OpenfastFortranOptions.cmake @@ -93,7 +93,7 @@ macro(set_fast_gfortran) # debug flags if(CMAKE_BUILD_TYPE MATCHES Debug) - set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fcheck=all -pedantic -fbacktrace" ) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} " ) endif() if(CYGWIN) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index d988c523c..299622368 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -47,6 +47,17 @@ subroutine concatenate_lists(I1,I2,I3, ErrStat, ErrMsg) I3(1:size(I1)) = I1 I3(size(I1)+1:size(I1)+size(I2)) = I2 endsubroutine + subroutine concatenate_3lists(I1,I2,I3,I4, ErrStat, ErrMsg) + integer(intki), intent(in) :: i1(:), i2(:), i3(:) + integer(intki), intent(out) :: i4(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat=ErrID_None + ErrMsg='' + I4( 1:size(I1) ) = I1 + I4(size(I1) +1:size(I1)+size(I2) ) = I2 + I4(size(I1)+size(I2)+1:size(I1)+size(I2)+size(I3)) = I3 + endsubroutine !> Set difference: I3=I1-I2 (assumes I1 is biggger than I2), elements of I1 not in I2 subroutine lists_difference(I1, I2, I3, ErrStat, ErrMsg) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 2911249c9..4a22a6af0 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -566,9 +566,9 @@ SUBROUTINE SetNewNode(k, x, y, z, Init) Init%Nodes(k, 4) = z Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever ! Properties below are for non-cantilever joints - Init%Nodes(k, iJointDir:iJointDir+2) = -99999 - Init%Nodes(k, iJointStiff) = -99999 - Init%Nodes(k, iJointDamp) = -99999 + Init%Nodes(k, iJointDir:iJointDir+2) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes + Init%Nodes(k, iJointStiff) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes + Init%Nodes(k, iJointDamp) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes END SUBROUTINE SetNewNode !> Set properties of element k @@ -828,7 +828,7 @@ END FUNCTION Failed !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" SUBROUTINE InitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p + TYPE(SD_ParameterType),INTENT(INOUT) :: p INTEGER(IntKi) :: I, J, iNode Init%BCs = -9999 DO I = 1, p%nNodes_C @@ -837,12 +837,15 @@ SUBROUTINE InitBCs(Init, p) Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) Init%BCs( (I-1)*6+J, 2) = idBC_Fixed + p%Nodes_C(I, J+1) = idBC_Fixed else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF Init%BCs( (I-1)*6+J, 2) = idBC_Internal + p%Nodes_C(I, J+1) = idBC_Internal print*,'BC 0 not allowed for now, node',iNode STOP else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF Init%BCs( (I-1)*6+J, 2) = idBC_Leader + p%Nodes_C(I, J+1) = idBC_Leader print*,'BC 2 not allowed for now, node',iNode STOP else @@ -858,14 +861,26 @@ END SUBROUTINE InitBCs !! TODO remove me and merge me with CraigBampton SUBROUTINE InitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p + TYPE(SD_ParameterType),INTENT(INOUT) :: p INTEGER(IntKi) :: I, J, iNode Init%IntFc = -9999 DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - Init%IntFc( (I-1)*6+J, 2) = 1 ! NOTE: Always selected now p%Nodes_I(I, J+1); ! 0 or 1 if fixed to interface + + if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF + Init%IntFc((I-1)*6+J, 2) = idBC_Leader + p%Nodes_I(I,J+1) = idBC_Leader + elseif (p%Nodes_I(I,J+1)==1) then ! User input 0=Fixed DOF + Init%IntFc( (I-1)*6+J, 2) = idBC_Fixed + p%Nodes_I(I,J+1) = idBC_Fixed + print*,'Fixed boundary condition not yet supported for interface nodes, node:',iNode + STOP + else + print*,'Wrong boundary condition input for interface node',iNode + STOP + endif ENDDO ENDDO END SUBROUTINE InitIntFc @@ -1002,27 +1017,30 @@ SUBROUTINE InsertSoilMatrices(M, K, Init, p, ErrStat, ErrMsg, Substract) integer(IntKi), intent( out) :: ErrStat ! Error status of the operation character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding - integer :: I, J - integer :: iDOF, iNode !< DOF and node indices + integer :: I, J, iiNode + integer :: iDOF, jDOF, iNode !< DOF and node indices real(ReKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil ErrMsg = "" ErrStat = ErrID_None ! TODO consider doing the 21 -> 6x6 conversion while reading ! 6x6 matrix goes to one node of one element only - do I = 1, p%nNodes_C ! loop on constrained nodes - iNode = p%Nodes_C(I,1) - call Array21_to_6by6(Init%SSIK(I,:), K_soil) - call Array21_to_6by6(Init%SSIM(I,:), M_soil) + do iiNode = 1, p%nNodes_C ! loop on constrained nodes + iNode = p%Nodes_C(iiNode,1) + call Array21_to_6by6(Init%SSIK(:,iiNode), K_soil) + call Array21_to_6by6(Init%SSIM(:,iiNode), M_soil) if (present(Substract)) then if (Substract) then K_soil = - K_soil M_soil = - M_soil endif endif - do J = 1, 6 - iDOF = p%NodesDOF(iNode)%List(J) ! DOF index - K(iDOF, iDOF) = K(iDOF, iDOF) + K_soil(J,J) - M(iDOF, iDOF) = M(iDOF, iDOF) + M_soil(J,J) + do I = 1, 6 + iDOF = p%NodesDOF(iNode)%List(I) ! DOF index + do J = 1, 6 + jDOF = p%NodesDOF(iNode)%List(J) ! DOF index + K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) + M(iDOF, jDOF) = M(iDOF, jDOF) + M_soil(I,J) + enddo enddo enddo contains @@ -1154,8 +1172,8 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - print*,'N',iNode,'I ',IDOFOld - print*,'N',iNode,'It',IDOFNew + !print*,'N',iNode,'I ',IDOFOld + !print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc iPrev = iPrev + nc enddo diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 45382ad29..52f5775fa 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -247,32 +247,14 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return - ! Allocate the output matrices and the index mapping array -! DOF_reduced = Init%TDOF-p%DOFCr -! CALL AllocAry(p%IDCr, p%DOFCr, 'IDCR', ErrStat2, ErrMsg2 ) -! CALL AllocAry(RetDOFs, DOF_reduced, 'RetDOFs', ErrStat2, ErrMsg2 ) -! !........ -! ! set the indices we want to keep (i.e., a mapping from reduced to full matrix) -! J = 1 -! J2 = 1 -! DO I=1,Init%TDOF -! idx(J) = idx(I) -! IF ( idx(J) /= 0 ) THEN -! J = J + 1 -! ELSE -! p%IDCR(J2) = I -! j2=j2+1 -! ENDIF -! -! END DO -! !idx retains the rows (column) indices that are still active and has 0-padding (from elementTDOF-DOFCR to TDOF) to account for the removed ones, and everywhere else -! !idx2 retains the rows (column) indices that are removed (fixed DOFs, there are DOFCR of them) -! RetDOFs=idx(1:DOF_reduced) - - ! -------------------------------------------------------------------------------- ! --- CB, Misc ! -------------------------------------------------------------------------------- + ! --- Partitioning + ! Nodes into (I,C,L,R): I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior + ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior + call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return + ! --- Craig-Bampton reduction (sets many parameters) CALL Craig_Bampton(Init, p, m, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -410,7 +392,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) INTEGER(IntKi) :: iSDNode, iY2Node REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) - REAL(ReKi) :: ULS(p%nDOFL), UL0m(p%nDOFL), FLt(p%nDOFL) ! Temporary values in static improvement method + REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) @@ -466,15 +448,18 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END IF ENDIF ! --- Build original DOF vectors (DOF before the CB reduction) - m%U_red (p%IDI) = m%UR_bar - m%U_red (p%IDL) = m%UL - m%U_red (p%IDC) = 0 !!! TODO, might not be generic - m%U_red_dot (p%IDI) = m%UR_bar_dot - m%U_red_dot (p%IDL) = m%UL_dot - m%U_red_dot (p%IDC) = 0 !!! TODO, might not be generic - m%U_red_dotdot(p%IDI) = m%UR_bar_dotdot - m%U_red_dotdot(p%IDL) = m%UL_dotdot - m%U_red_dotdot(p%IDC) = 0 !!! TODO, might not be generic + m%U_red (p%IDI__) = m%UR_bar + m%U_red (p%ID__L) = m%UL + m%U_red (p%IDC_Rb)= 0 ! TODO + m%U_red (p%ID__F) = 0 + m%U_red_dot (p%IDI__) = m%UR_bar_dot + m%U_red_dot (p%ID__L) = m%UL_dot + m%U_red_dot (p%IDC_Rb)= 0 ! TODO + m%U_red_dot (p%ID__F) = 0 + m%U_red_dotdot(p%IDI__) = m%UR_bar_dotdot + m%U_red_dotdot(p%ID__L) = m%UL_dotdot + m%U_red_dotdot(p%IDC_Rb)= 0 ! TODO + m%U_red_dotdot(p%ID__F) = 0 m%U_full = matmul(p%T_red, m%U_red) m%U_full_dot = matmul(p%T_red, m%U_red_dot) @@ -848,9 +833,9 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) p%Nodes_C(:,:) = 1 ! Important: By default all DOFs are contrained p%Nodes_C(:,1) = -1 ! First column is node, initalize to wrong value for safety -call AllocAry(Init%SSIfile, p%nNodes_C, 'SSIFile', ErrStat2, ErrMsg2); if(Failed()) return -call AllocAry(Init%SSIK , p%nNodes_C, 21 , 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return -call AllocAry(Init%SSIM , p%nNodes_C, 21 , 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIfile, p%nNodes_C, 'SSIFile', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIK, 21, p%nNodes_C, 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIM, 21, p%nNodes_C, 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return Init%SSIfile(:) = '' Init%SSIK = 0.0_ReKi ! Important init TODO: read these matrices on the fly in SD_FEM maybe? Init%SSIM = 0.0_ReKi ! Important init @@ -879,7 +864,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) DO I = 1, p%nNodes_C if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) - CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(I,:),Init%SSIM(I,:), ErrStat, ErrMsg, UnEc ); if(Failed()) return + CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(:,I),Init%SSIM(:,I), ErrStat, ErrMsg, UnEc ); if(Failed()) return endif enddo @@ -1553,7 +1538,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_InputType) :: u_interp ! interpolated value of inputs REAL(ReKi) :: junk2(2*p%nDOFM) !temporary states (qm and qmdot only) REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP - REAL(ReKi) :: UFL2(p%nDOFL) ! temporary copy of UFL + REAL(ReKi) :: UFL2(p%nDOF__L) ! temporary copy of UFL INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -1629,53 +1614,50 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = "" - ! --- Partitioon DOFs and Nodes into sets: I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior - !! Partition Nodes into: Nodes_I (Interf), Nodes_C (React), Nodes_L - !! Partitions the DOF index arrays into IDR=[IDC, ICI] and IDL (interior) - !! Sets the DOF mapping [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] - call PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes - IF(p%nDOFM > p%nDOFL) THEN + IF(p%nDOFM > p%nDOFL_L) THEN CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than number of internal DOFs. ',ErrStat,ErrMsg,'Craig_Bampton') CALL CleanupCB() RETURN ENDIF ELSE ! full FEM - p%nDOFM = p%nDOFL + p%nDOFM = p%nDOFL_L !Jdampings need to be reallocated here because nDOFL not known during Init !So assign value to one temporary variable JDamping1=Init%Jdampings(1) DEALLOCATE(Init%JDampings) - CALL AllocAry( Init%JDampings, p%nDOFL, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return + CALL AllocAry( Init%JDampings, p%nDOFL_L, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return Init%JDampings = JDamping1 ! set default values for all modes ENDIF CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) - CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI, p%nDOFI, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - - CALL AllocAry( MRR, p%nDOFR, p%nDOFR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MLL, p%nDOFL, p%nDOFL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MRL, p%nDOFR, p%nDOFL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRR, p%nDOFR, p%nDOFR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KLL, p%nDOFL, p%nDOFL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRL, p%nDOFR, p%nDOFL, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGL, p%nDOFL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGR, p%nDOFR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return + + ! TODO Used __Rb instead of R__ + CALL AllocAry( MRR, p%nDOFR__, p%nDOFR__, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MLL, p%nDOF__L, p%nDOF__L, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, p%nDOFR__, p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, p%nDOFR__, p%nDOFR__, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KLL, p%nDOF__L, p%nDOF__L, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, p%nDOFR__, p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGL, p%nDOF__L, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, p%nDOFR__, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBB, p%nDOFR, p%nDOFR, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBM, p%nDOFR, p%nDOFM, 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%KBB, p%nDOFR, p%nDOFR, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiL, p%nDOFL, p%nDOFL, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%nDOFL, p%nDOFR, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%OmegaL, p%nDOFL, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBB, p%nDOFR__, p%nDOFR__, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, p%nDOFR__, p%nDOFM , 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, p%nDOFR__, p%nDOFR__, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiL, p%nDOF__L, p%nDOF__L, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%nDOF__L, p%nDOFR__, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%OmegaL, p%nDOF__L, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on M, K, FG and indices IDR and IDL ! NOTE: generic FEM code - CALL BreakSysMtrx(Init%M, Init%K, Init%FG, p%IDR, p%IDL, p%nDOFR, p%nDOFL, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + ! TODO use __Rb + CALL BreakSysMtrx(Init%M, Init%K, Init%FG, p%IDR__, p%ID__L, p%nDOFR__, p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1684,14 +1666,15 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! CBparams%PhiR from Eq. 3 ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. !................................ - CALL WrScr(' Performing Craig-Bampton decomposition') + CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT - nM_Out=p%nDOFL ! Selecting all CB modes for outputs to the function below + nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ! TODO ELSE nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes ENDIF - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFR, p%nDOFL, p%nDOFM, nM_Out, & ! < inputs + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFR__, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs ! TODO CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2) ! <- outputs + if(Failed()) return ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement IF (p%SttcSolve) THEN @@ -1702,7 +1685,6 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) END IF ! TODO TODO TODO DAMPING MATRIX - if(Failed()) return ! to use a little less space, let's deallocate these arrays that we don't need anymore, then allocate the next set of temporary arrays: IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) @@ -1713,11 +1695,12 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) ! "b" stands for "bar"; "t" stands for "tilde" - CALL AllocAry( MBBb, p%nDOFI, p%nDOFI, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MBmb, p%nDOFI, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KBBb, p%nDOFI, p%nDOFI, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( PhiRb, p%nDOFL, p%nDOFI, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGRb, p%nDOFI, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return + ! TODO TODO TODO this is wrong + CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return + CALL AllocAry( FGRb, p%nDOF__Rb, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return !................................ ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to @@ -1725,13 +1708,13 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! (throw out rows/columns of first matrices to create second matrices) !................................ ! TODO avoid this all together - MBBb = CBparams%MBB(p%nDOFR-p%nDOFI+1:p%nDOFR, p%nDOFR-p%nDOFI+1:p%nDOFR) - KBBb = CBparams%KBB(p%nDOFR-p%nDOFI+1:p%nDOFR, p%nDOFR-p%nDOFI+1:p%nDOFR) + MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) IF (p%nDOFM > 0) THEN - MBMb = CBparams%MBM(p%nDOFR-p%nDOFI+1:p%nDOFR, : ) + MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) END IF - FGRb = FGR(p%nDOFR-p%nDOFI+1:p%nDOFR ) - PhiRb = CBparams%PhiR( :, p%nDOFR-p%nDOFI+1:p%nDOFR) + FGRb = FGR (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) + PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) ! TODO TODO TODO Transform new damping matrix as well !................................ @@ -2116,26 +2099,33 @@ END SUBROUTINE SelectNonFixedDOF SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOFI, p%nDOFI) - REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOFI, p%nDOFM) - REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOFI, p%nDOFI) - REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOFL, p%nDOFL) - REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOFL, p%nDOFI) - REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOFL) - REAL(ReKi), INTENT(IN ) :: FGRb(p%nDOFI) - REAL(ReKi), INTENT(IN ) :: FGL(p%nDOFL) + REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) + REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, p%nDOF__L) + REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOF__L) + REAL(ReKi), INTENT(IN ) :: FGRb(p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI) !bjj: added this so we don't have to take the transpose 5+ times + REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI__) !bjj: added this so we don't have to take the transpose 5+ times INTEGER(IntKi) :: I integer(IntKi) :: n ! size of jacobian in AM2 calculation INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' - ErrStat = ErrID_None ErrMsg = '' + + if (p%nDOFI__/=p%nDOF__Rb) then + ! Limitation due to the TI matrix, on the input U_R to the module for now + ErrMsg2='For now number of leader DOF has to be the same a Rb DOF' + ErrStat2=ErrID_Fatal + if(Failed()) return + endif + TI_transpose = TRANSPOSE(p%TI) @@ -2279,10 +2269,10 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%TI, p%nDOFI, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOFL, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiRb_TI, p%nDOFL, nDOFL_TP, 'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') if (p%nDOFM > 0 ) THEN CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2292,19 +2282,19 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiM, p%nDOFL, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_61, p%nDOFL, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_62, p%nDOFL, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 - CALL AllocAry( p%D2_63, p%nDOFL, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 - CALL AllocAry( p%D2_64, p%nDOFL, p%nDOFL, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 - CALL AllocAry( p%F2_61, p%nDOFL, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 + CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if if ( p%SttcSolve ) THEN - CALL AllocAry( p%PhiL_T, p%nDOFL, p%nDOFL, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiLInvOmgL2, p%nDOFL, p%nDOFL, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FGL, p%nDOFL, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') end if END SUBROUTINE AllocParameters @@ -2324,16 +2314,16 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) ErrMsg = "" ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( Misc%UFL, p%nDOFL, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar, p%nDOFI, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar_dot, p%nDOFI, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL, p%nDOFL, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dot, p%nDOFL, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dotdot, p%nDOFL, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UFL, p%nDOF__L, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar, p%nDOFI__, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UR_bar_dot, p%nDOFI__, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI__, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UL, p%nDOF__L, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dot, p%nDOF__L, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dotdot, p%nDOF__L, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') @@ -2344,24 +2334,33 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) END SUBROUTINE AllocMiscVars !------------------------------------------------------------------------------------------------------ -!> Partition DOFs and Nodes into sets: I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior -!! Partition Nodes into: Nodes_I (Interf), Nodes_C (React), Nodes_L -!! Partition the DOF index arrays into IDR=[IDC, ICI] and IDL (interior) -!! Sets the DOF mapping [_,IDY] =sort([IDI, IDL, IDC]), Y is in the continuous order [I,L,C] -SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) +!> Partition DOFs and Nodes into sets: +!! Nodes are partitioned into the I,C,L (and R) sets, Nodes_I, Nodes_C, Nodes_L, with: +!! I="Interface" nodes +!! C="Reaction" nodes +!! L=Interior nodes +!! R=I+C +!! DOFs indices are partitioned into B, F, L +!! B=Leader DOFs (Rbar in SubDyn documentation) +!! F=Fixed DOFS +!! L=Interior DOFs +!! Subpartitions of both categories use the convention: "NodePartition_DOFPartition" +!! e.g. C_F : "reaction" nodes DOFs that are fixed +!! C_L : "reaction" nodes DOFs that will be counted as internal +!! I_B : "interface" nodes DOFs that are leader DOFs +SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) use qsort_c_module, only: QsortC - use IntegerList, only: len, concatenate_lists, lists_difference + use IntegerList, only: len, concatenate_lists, lists_difference, concatenate_3lists, sort_in_place type(SD_Inittype), intent( in) :: Init !< Input data for initialization routine type(SD_MiscVartype), intent( in) :: m !< Misc type(SD_Parametertype), intent(inout) :: p !< Parameters integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables - integer(IntKi), allocatable :: TempIDY(:,:) - integer(IntKi), allocatable :: IDT(:) - integer(IntKi) :: I ! counters + integer(IntKi) :: I, J, c_B, c_F, c_L ! counters integer(IntKi) :: iNode, iiNode - integer(IntKi) :: nNodes_R + integer(IntKi) :: nNodes_R + integer(IntKi), allocatable :: IDAll(:) integer(IntKi), allocatable :: INodesAll(:) integer(IntKi), allocatable :: Nodes_R(:) integer(IntKi) :: ErrStat2 ! < Error status of the operation @@ -2370,14 +2369,16 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ErrMsg = "" ! --- Count nodes per types p%nNodes_I = p%nNodes_I ! Number of interface nodes - nNodes_R = p%nNodes_I+p%nNodes_C ! Number of retained nodes - p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes =(TDOF-nDOFC-nDOFI)/6 = (6*p%nNodes - (p%nNodes_C+p%nNodes_I)*6 ) / 6 = p%nNodes - p%nNodes_C -p%nNodes_I + nNodes_R = p%nNodes_I+p%nNodes_C ! I+C nodes + p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. - CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + ! -------------------------------------------------------------------------------- ! --- Partition Nodes: Nodes_L = IAll - NodesR + ! -------------------------------------------------------------------------------- allocate(INodesAll(1:p%nNodes)); do iNode=1,p%nNodes INodesAll(iNode)=iNode @@ -2387,99 +2388,215 @@ SUBROUTINE PartitionDOFNodes_I_C_R_L(Init, m, p, ErrStat, ErrMsg) ! Nodes_L = IAll - Nodes_R call lists_difference(INodesAll, Nodes_R, p%Nodes_L(:,1), ErrStat2, ErrMsg2); if(Failed()) return - ! --- Count DOFs - ! Interface DOFS - p%nDOFI =0 + ! -------------------------------------------------------------------------------- + ! --- Count DOFs - NOTE: we count node by node + ! -------------------------------------------------------------------------------- + ! DOFs of interface nodes + p%nDOFI__ =0 ! Total + p%nDOFI_Rb=0 ! Leader + p%nDOFI_F =0 ! Fixed do iiNode= 1,p%nNodes_I - p%nDOFI = p%nDOFI + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) + p%nDOFI__ = p%nDOFI__ + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) + p%nDOFI_Rb= p%nDOFI_Rb+ count(p%Nodes_I(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs + p%nDOFI_F = p%nDOFI_F + count(p%Nodes_I(iiNode, 2:7)==idBC_Fixed) ! assumes 6 DOFs enddo - ! Reaction DOFs - p%nDOFC =0 + if (p%nDOFI__/=p%nDOFI_Rb+p%nDOFI_F) then + call Fatal('Error in distributing interface DOFs, total number of DOF does not equal number of leader and fixed DOF'); return + endif + + ! DOFs of reaction nodes + p%nDOFC__ =0 ! Total + p%nDOFC_Rb=0 ! Leader + p%nDOFC_F =0 ! Fixed + p%nDOFC_L =0 ! Internal do iiNode= 1,p%nNodes_C - p%nDOFC = p%nDOFC + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) + p%nDOFC__ = p%nDOFC__ + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) + p%nDOFC_Rb= p%nDOFC_Rb+ count(p%Nodes_C(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs + p%nDOFC_F = p%nDOFC_F + count(p%Nodes_C(iiNode, 2:7)==idBC_Fixed ) ! assumes 6 DOFs + p%nDOFC_L = p%nDOFC_L + count(p%Nodes_C(iiNode, 2:7)==idBC_Internal) ! assumes 6 DOFs enddo - p%nDOFR = p%nDOFC + p%nDOFI - p%nDOFL = p%nDOF_red - p%nDOFR ! TODO - ! --- Safety checks - if (p%nDOFC /= p%nNodes_C*6) then + if (p%nDOFC__/=p%nDOFC_Rb+p%nDOFC_F+p%nDOFC_L) then + call Fatal('Error in distributing reaction DOFs, total number of DOF does not equal number of leader, fixed and internal DOF'); return + endif + ! DOFs of reaction + interface nodes + p%nDOFR__ = p%nDOFI__ + p%nDOFC__ ! Total number, used to be called "nDOFR" + + ! DOFs of internal nodes + p%nDOFL_L=0 + do iiNode= 1,p%nNodes_L + p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) + enddo + if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then + call Fatal('Error in distributing internal DOFs, total number of DOF does not equal total number of DOF minus interface and reaction'); return + endif + + ! Total number of DOFs in each category: + p%nDOF__Rb = p%nDOFC_Rb + p%nDOFI_Rb ! OK, generic + p%nDOF__F = p%nDOFC_F + p%nDOFI_F ! OK, generic + p%nDOF__L = p%nDOFC_L + p%nDOFL_L ! OK, generic + + ! --- Safety checks ! TODO: these checks are temporary! + if (p%nDOFC_F /= p%nNodes_C*6) then call Fatal('Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'); return endif - if (p%nDOFI /= p%nNodes_I*6) then + if (p%nDOFI_Rb /= p%nNodes_I*6) then call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'); return endif - ! Set the index arrays p%IDI, p%IDR, p%IDL, p%IDC, and p%IDY. - CALL AllocAry( p%IDI, p%nDOFI, 'p%IDI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDC, p%nDOFC, 'p%IDC', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDR, p%nDOFR, 'p%IDR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDL, p%nDOFL, 'p%IDL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') - CALL AllocAry( p%IDY, p%nDOFC+p%nDOFI+p%nDOFL, 'p%IDY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + ! Set the index arrays + CALL AllocAry( p%IDI__, p%nDOFI__, 'p%IDI__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDI_Rb,p%nDOFI_Rb, 'p%IDI_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDI_F, p%nDOFI_F, 'p%IDI_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC__, p%nDOFC__, 'p%IDC__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_Rb,p%nDOFC_Rb, 'p%IDC_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_F, p%nDOFC_F, 'p%IDC_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_L, p%nDOFC_L, 'p%IDC_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDL_L, p%nDOFL_L, 'p%IDL_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDR__, p%nDOFR__, 'p%IDR__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__Rb,p%nDOF__Rb, 'p%ID__Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__F, p%nDOF__F, 'p%ID__F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__L, p%nDOF__L, 'p%ID__L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') ! TODO TODO if(Failed()) return - ! Indices IDI for interface DOFs - p%IDI = Init%IntFc(1:p%nDOFI, 1) ! Interface DOFs (indices updated after DirectElimination) - ! Indices IDC for constraint DOFs - p%IDC = Init%BCs(1:p%nDOFC, 1) ! Reaction DOFs (indices updated after DirectElimination) - ! Indices IDR = [IDC, IDI], "retained interface DOFS" - call concatenate_lists(p%IDC, p%IDI, p%IDR, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Indices IDL for internal DOFs = AllDOF - IDR - ! First set the all DOFs indices IDT = 1:nnDOFRed - allocate(IDT(1:p%nDOF_red)) - DO I = 1, p%nDOF_red; IDT(I) = I; ENDDO - call lists_difference(IDT, p%IDR, p%IDL, ErrStat2, ErrMsg2); if(Failed()) return + ! -------------------------------------------------------------------------------- + ! --- Distibutes the I, L, C nodal DOFs into B, F, L sub-categories + ! -------------------------------------------------------------------------------- + + ! Distribute the interface DOFs into R,F + c_B=0; c_F=0 ! Counters over R and F dofs + do iiNode= 1,p%nNodes_I !Loop on interface nodes + iNode = p%Nodes_I(iiNode,1) + do J = 1, 6 ! DOFs: ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + if (p%Nodes_I(iiNode, J+1)==idBC_Leader) then + c_B=c_B+1 + p%IDI_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_I(iiNode, J+1)==idBC_Fixed) then ! + c_F=c_F+1 + p%IDI_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + endif + enddo + enddo + ! Indices IDI__ = [IDI_B, IDI_F], interface + call concatenate_lists(p%IDI_Rb, p%IDI_F, p%IDI__, ErrStat2, ErrMsg2); if(Failed()) return + + ! Distribute the reaction DOFs into R,F,L + c_B=0; c_F=0; c_L=0; ! Counters over R, F, L dofs + do iiNode= 1,p%nNodes_C !Loop on interface nodes + iNode = p%Nodes_C(iiNode,1) + do J = 1, 6 ! DOFs + if (p%Nodes_C(iiNode, J+1)==idBC_Leader) then + c_B=c_B+1 + p%IDC_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_C(iiNode, J+1)==idBC_Fixed) then ! + c_F=c_F+1 + p%IDC_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_C(iiNode, J+1)==idBC_Internal) then ! + c_L=c_L+1 + p%IDC_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + endif + enddo + enddo + ! Indices IDC__ = [IDC_B, IDC_F, IDC_L], interface + call concatenate_3lists(p%IDC_Rb, p%IDC_F, p%IDC_L, p%IDC__, ErrStat2, ErrMsg2); if(Failed()) return + + ! Indices IDR__ = [IDI__, IDC__], interface + !call concatenate_lists(p%IDI__, p%IDC__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return + ! TODO, NOTE: Backward compatibility [IDC, IDI] + call concatenate_lists(p%IDC__, p%IDI__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return + + ! Distribute the internal DOFs + c_L=0; ! Counters over L dofs + do iiNode= 1,p%nNodes_L !Loop on interface nodes + iNode = p%Nodes_L(iiNode,1) + do J = 1, 6 ! DOFs + c_L=c_L+1 + p%IDL_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + enddo + enddo + + ! -------------------------------------------------------------------------------- + ! --- Total indices per partition B, F, L + ! -------------------------------------------------------------------------------- + ! Indices ID__Rb = [IDC_B, IDI_B], retained/leader DOFs + call concatenate_lists(p%IDC_Rb, p%IDI_Rb, p%ID__Rb, ErrStat2, ErrMsg2); if(Failed()) return + ! Indices ID__F = [IDC_F, IDI_F], fixed DOFs + call concatenate_lists(p%IDC_F, p%IDI_F, p%ID__F, ErrStat2, ErrMsg2); if(Failed()) return + ! Indices ID__L = [IDL_L, IDC_L], internal DOFs + call concatenate_lists(p%IDL_L, p%IDC_L, p%ID__L, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Check that partition is complete + if (any(p%ID__Rb<=0)) then + call Fatal('R - Partioning incorrect.'); return + elseif (any(p%ID__F<=0)) then + call Fatal('F - Partioning incorrect.'); return + elseif (any(p%ID__L<=0)) then + call Fatal('L - Partioning incorrect.'); return + endif + allocate(IDAll(1:p%nDOF_red)) + call concatenate_3lists(p%ID__Rb, p%ID__L, p%ID__F, IDAll, ErrStat2, ErrMsg2); if(Failed()) return + call sort_in_place(IDAll) + do I = 1, p%nDOF_red + if (IDAll(I)/=I) then + call Fatal('DOF '//trim(Num2LStr(I))//' missing, problem in R, L F partitioning'); return + endif + enddo - ! --- Index [_,IDY] =sort([IDI, IDL, IDC]), DOF map, Y is in the continuous order [I,L,C] - ! set the second column of the temp array - allocate(TempIDY(p%nDOFI+p%nDOFL+p%nDOFC, 2)) - print*,SIZE(TempIDY),p%nDOF_red - DO I = 1, SIZE(TempIDY,1) - TempIDY(I, 2) = I ! this column will become the returned "key" (i.e., the original location in the array) - ENDDO - ! set the first column of the temp array - TempIDY(1:p%nDOFI, 1) = p%IDI - TempIDY(p%nDOFI+1 : p%nDOFI+p%nDOFL, 1) = p%IDL - TempIDY(p%nDOFI+p%nDOFL+1: p%nDOFI+p%nDOFL+p%nDOFC, 1) = p%IDC - CALL QsortC( TempIDY ) ! sort based on the first column - p%IDY = TempIDY(:, 2) ! the second column is the key: - ! + !print*,'DOFI__ ',p%IDI__ + !print*,'DOFI_Rb ',p%IDI_Rb + !print*,'DOFI_F ',p%IDI_F + !print*,'DOFC__ ',p%IDC__ + !print*,'DOFC_Rb ',p%IDC_Rb + !print*,'DOFC_F ',p%IDC_F + !print*,'DOFC_L ',p%IDC_L + !print*,'DOFR__ ',p%IDR__ + !print*,'DOFL_L ',p%IDL_L + !print*,'DOF__Rb ',p%ID__Rb + !print*,'DOF__F ',p%ID__F + !print*,'DOF__L ',p%ID__L + !print*,'Nodes_C',p%Nodes_C(:,1) + !print*,'Nodes_L',p%Nodes_L(:,1) + !print*,'Nodes_I',p%Nodes_I(:,1) + write(*,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ + write(*,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb + write(*,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F + write(*,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ + write(*,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb + write(*,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L + write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F + write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ + write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L + write(*,'(A,I0)')'Number of DOFs: total retained (__B): ',p%nDOF__Rb + write(*,'(A,I0)')'Number of DOFs: total internal (__L): ',p%nDOF__L + write(*,'(A,I0)')'Number of DOFs: total fixed (__F): ',p%nDOF__F + write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red + write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I + write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C + write(*,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L + write(*,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes + call CleanUp() - print*,'DOF_I ',p%IDI - print*,'DOF_L ',p%IDL - print*,'DOF_C ',p%IDC - print*,'Nodes_C',p%Nodes_C(:,1) - print*,'Nodes_L',p%Nodes_L - print*,'Nodes_I',p%Nodes_I(:,1) - print*,'Nodes_C',p%Nodes_C(:,1) - print*,'Nodes_L',p%Nodes_L - print*,'Number of DOFs: "interface" (I)',p%nDOFI - print*,'Number of DOFs: "reactions" (C)',p%nDOFC - print*,'Number of DOFs: interface (R)',p%nDOFR - print*,'Number of DOFs: internal (L)',p%nDOFL - print*,'Number of DOFs: total (R+L)',p%nDOF_red - print*,'Number of Nodes: "interface" (I)',p%nNodes_I - print*,'Number of Nodes: "reactions" (C)',p%nNodes_C - print*,'Number of Nodes: internal (L)',p%nNodes_L - print*,'Number of Nodes: total (R+L)',p%nNodes contains LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L') + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') Failed = ErrStat >= AbortErrLev if (Failed) call CleanUp() END FUNCTION Failed SUBROUTINE Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'PartitionDOFNodes_I_C_R_L'); + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'PartitionDOFNodes'); CALL CleanUp() END SUBROUTINE Fatal SUBROUTINE CleanUp() - if(allocated(TempIDY)) deallocate(TempIDY) - if(allocated(IDT)) deallocate(IDT) if(allocated(INodesAll)) deallocate(INodesAll) + if(allocated(IDAll)) deallocate(IDAll) + if(allocated(Nodes_R)) deallocate(Nodes_R) END SUBROUTINE CleanUp -END SUBROUTINE PartitionDOFNodes_I_C_R_L +END SUBROUTINE PartitionDOFNodes !------------------------------------------------------------------------------------------------------ !> Construct force vector on internal DOF (L) from the values on the input mesh @@ -2489,7 +2606,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%nDOFL) + real(ReKi) , intent(out) :: UFL(p%nDOFL_L) integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes integer :: nMembers real(ReKi), parameter :: myNaN = -9999998.989_ReKi @@ -2515,7 +2632,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) ! --- Reduced vector of external force m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL=0 - UFL= m%Fext_red(p%IDL) + UFL= m%Fext_red(p%IDL_L) END SUBROUTINE ConstructUFL @@ -2585,15 +2702,23 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) !write(UnSum,'(A)')'Nodes_I',p%Nodes_I(:,1) !write(UnSum,'(A)')'Nodes_C',p%Nodes_C(:,1) !write(UnSum,'(A)')'Nodes_L',p%Nodes_L - write(UnSum,'(A,I0)')'Number of DOFs: "interface" (I): ',p%nDOFI - write(UnSum,'(A,I0)')'Number of DOFs: "reactions" (C): ',p%nDOFC - write(UnSum,'(A,I0)')'Number of DOFs: interface (R): ',p%nDOFR - write(UnSum,'(A,I0)')'Number of DOFs: internal (L): ',p%nDOFL - write(UnSum,'(A,I0)')'Number of DOFs: total (R+L): ',p%nDOF_red + write(UnSum,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ + write(UnSum,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb + write(UnSum,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F + write(UnSum,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ + write(UnSum,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb + write(UnSum,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L + write(UnSum,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F + write(UnSum,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ + write(UnSum,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L + write(UnSum,'(A,I0)')'Number of DOFs: total retained (__B): ',p%nDOF__Rb + write(UnSum,'(A,I0)')'Number of DOFs: total internal (__L): ',p%nDOF__L + write(UnSum,'(A,I0)')'Number of DOFs: total fixed (__F): ',p%nDOF__F + write(UnSum,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red write(UnSum,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I write(UnSum,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C - write(UnSum,'(A,I0)')'Number of Nodes: internal (L): ',p%nNodes_L - write(UnSum,'(A,I0)')'Number of Nodes: total (R+L): ',p%nNodes + write(UnSum,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L + write(UnSum,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes write(UnSum,'(A,3(E15.6))')'TP reference point:',InitInput%TP_RefPoint(1:3) @@ -2615,19 +2740,22 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%nNodes_C*6 - WRITE(UnSum, '(A, A6)') 'Reaction DOF_ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%BCs(i, j), j = 1, 2), i = 1, p%nNodes_C*6)! TODO TODO TODO might have been updated + WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%nDOFC__ + WRITE(UnSum, '(A, A6)') 'React. DOF_ID', 'BC' + do i = 1, size(p%IDC_F ); WRITE(UnSum, '(I10, A10)') p%IDC_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDC_L ); WRITE(UnSum, '(I10, A10)') p%IDC_L(i) , ' Free' ; enddo + do i = 1, size(p%IDC_Rb); WRITE(UnSum, '(I10, A10)') p%IDC_Rb(i), ' Leader'; enddo WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%nDOFI - WRITE(UnSum, '(A,A6)') 'Interface DOF ID', 'LOCK' - WRITE(UnSum, '(I10, I10)') ((Init%IntFc(i, j), j = 1, 2), i = 1, p%nDOFI) ! TODO TODO TODO might have been updated + WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%nDOFI__ + WRITE(UnSum, '(A,A6)') 'Interf. DOF_ID', 'BC' + do i = 1, size(p%IDI_F ); WRITE(UnSum, '(I10, A10)') p%IDI_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDI_Rb); WRITE(UnSum, '(I10, A10)') p%IDI_Rb(i), ' Leader'; enddo WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of concentrated masses (NCMass):',Init%NCMass - WRITE(UnSum, '(A10,A15,A15,A15,A15)') 'JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ' - WRITE(UnSum, '(F10.0, E15.6,E15.6,E15.6,E15.6)') ((Init%Cmass(i, j), j = 1, 5), i = 1, Init%NCMass) + WRITE(UnSum, '(A10,10(A15))') 'JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' + WRITE(UnSum, '(F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers @@ -2703,7 +2831,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) IF (p%nDOFM > 0) THEN CALL WrMatrix( CBparams%PhiL(:,1:p%nDOFM ), UnSum, 'e15.6', 'PhiM' ) ELSE - WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%nDOFL)), '0' + WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%nDOFL_L)), '0' END IF WRITE(UnSum, '(A)') SubSectionDivide @@ -2729,8 +2857,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ENDDO ! Set TI2, transformation matrix from R DOFs to SubDyn Origin - CALL AllocAry( TI2, p%nDOFR, 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR, p%nDOFR, TI2, ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry( TI2, p%nDOFR__, 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body deallocate(TI2) WRITE(UnSum, '(A)') SectionDivide diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 46e15c2f4..14844eb30 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -262,12 +262,12 @@ SUBROUTINE ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) ErrStat=ErrID_None ErrMsg="" - CALL AllocAry(p%TIreact, 6, p%nDOFC, 'TIReact', ErrStat, ErrMsg); if ( ErrStat /= ErrID_None ) return + CALL AllocAry(p%TIreact, 6, p%nDOFC__, 'TIReact', ErrStat, ErrMsg); if ( ErrStat /= ErrID_None ) return ! --- TI: Transformation matrix from interface points to ref point p%TIreact(1:6,:)=0 !Initialize - DO I = 1, p%nDOFC - iDOF = p%IDC(I) ! DOF index in constrained system + DO I = 1, p%nDOFC__ + iDOF = p%IDC__(I) ! DOF index in constrained system iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 8c127cc46..918bbae44 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -210,15 +210,30 @@ typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" -typedef ^ ParameterType IntKi nDOFI - - - "Interface nodes # of DOFs" -typedef ^ ParameterType IntKi nDOFL - - - "Internal nodes # of DOFs" -typedef ^ ParameterType IntKi nDOFC - - - "Contrained nodes # of DOFs" -typedef ^ ParameterType IntKi nDOFR - - - "Interface and restrained nodes # of DOFs" -typedef ^ ParameterType IntKi IDI {:} - - "Index array of the interface(nodes connect to TP) dofs" -typedef ^ ParameterType IntKi IDL {:} - - "Index array of the internal dofs" -typedef ^ ParameterType IntKi IDC {:} - - "Index array of the contraint dofs" -typedef ^ ParameterType IntKi IDR {:} - - "Index array of the interface and restraint dofs" -typedef ^ ParameterType IntKi IDY {:} - - "Index array of the all dofs in Y2" +typedef ^ ParameterType IntKi nDOFI__ - - - "Size of IDI__" +typedef ^ ParameterType IntKi nDOFI_Rb - - - "Size of IDI_Rb" +typedef ^ ParameterType IntKi nDOFI_F - - - "Size of IDI_F" +typedef ^ ParameterType IntKi nDOFL_L - - - "Size of IDL_L" +typedef ^ ParameterType IntKi nDOFC__ - - - "Size of IDC__" +typedef ^ ParameterType IntKi nDOFC_Rb - - - "Size of IDC_Rb" +typedef ^ ParameterType IntKi nDOFC_L - - - "Size of IDC_L" +typedef ^ ParameterType IntKi nDOFC_F - - - "Size of IDC_F" +typedef ^ ParameterType IntKi nDOFR__ - - - "Size of IDR__" +typedef ^ ParameterType IntKi nDOF__Rb - - - "Size of ID__Rb" +typedef ^ ParameterType IntKi nDOF__L - - - "Size of ID__L" +typedef ^ ParameterType IntKi nDOF__F - - - "Size of ID__F" +typedef ^ ParameterType IntKi IDI__ {:} - - "Index of all Interface DOFs" +typedef ^ ParameterType IntKi IDI_Rb {:} - - "Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs" +typedef ^ ParameterType IntKi IDI_F {:} - - "Index array of the interface (nodes connect to TP) dofs that are fixed DOF" +typedef ^ ParameterType IntKi IDL_L {:} - - "Index array of the internal dofs coming from internal nodes" +typedef ^ ParameterType IntKi IDC__ {:} - - "Index of all bottom DOF" +typedef ^ ParameterType IntKi IDC_Rb {:} - - "Index array of the contraint dofs that are retained/master/follower DOF" +typedef ^ ParameterType IntKi IDC_L {:} - - "Index array of the contraint dofs that are follower/internal DOF" +typedef ^ ParameterType IntKi IDC_F {:} - - "Index array of the contraint dofs that are fixd DOF" +typedef ^ ParameterType IntKi IDR__ {:} - - "Index array of the interface and restraint dofs" +typedef ^ ParameterType IntKi ID__Rb {:} - - "Index array of all the retained/leader/master dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__L {:} - - "Index array of all the follower/internal dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__F {:} - - "Index array of the DOF that are fixed (from any nodes of the structure)" typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" # --- Outputs typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index f5c7b8a4d..800200e62 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -247,15 +247,30 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_I !< Interface degree of freedoms [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_C !< React degree of freedoms [-] - INTEGER(IntKi) :: nDOFI !< Interface nodes of DOFs [-] - INTEGER(IntKi) :: nDOFL !< Internal nodes of DOFs [-] - INTEGER(IntKi) :: nDOFC !< Contrained nodes of DOFs [-] - INTEGER(IntKi) :: nDOFR !< Interface and restrained nodes of DOFs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI !< Index array of the interface(nodes connect to TP) dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL !< Index array of the internal dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC !< Index array of the contraint dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR !< Index array of the interface and restraint dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDY !< Index array of the all dofs in Y2 [-] + INTEGER(IntKi) :: nDOFI__ !< Size of IDI__ [-] + INTEGER(IntKi) :: nDOFI_Rb !< Size of IDI_Rb [-] + INTEGER(IntKi) :: nDOFI_F !< Size of IDI_F [-] + INTEGER(IntKi) :: nDOFL_L !< Size of IDL_L [-] + INTEGER(IntKi) :: nDOFC__ !< Size of IDC__ [-] + INTEGER(IntKi) :: nDOFC_Rb !< Size of IDC_Rb [-] + INTEGER(IntKi) :: nDOFC_L !< Size of IDC_L [-] + INTEGER(IntKi) :: nDOFC_F !< Size of IDC_F [-] + INTEGER(IntKi) :: nDOFR__ !< Size of IDR__ [-] + INTEGER(IntKi) :: nDOF__Rb !< Size of ID__Rb [-] + INTEGER(IntKi) :: nDOF__L !< Size of ID__L [-] + INTEGER(IntKi) :: nDOF__F !< Size of ID__F [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI__ !< Index of all Interface DOFs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_Rb !< Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_F !< Index array of the interface (nodes connect to TP) dofs that are fixed DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL_L !< Index array of the internal dofs coming from internal nodes [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC__ !< Index of all bottom DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_Rb !< Index array of the contraint dofs that are retained/master/follower DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_L !< Index array of the contraint dofs that are follower/internal DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_F !< Index array of the contraint dofs that are fixd DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR__ !< Index array of the interface and restraint dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__Rb !< Index array of all the retained/leader/master dofs (from any nodes of the structure) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__L !< Index array of all the follower/internal dofs (from any nodes of the structure) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__F !< Index array of the DOF that are fixed (from any nodes of the structure) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] @@ -6833,69 +6848,161 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%Nodes_C = SrcParamData%Nodes_C ENDIF - DstParamData%nDOFI = SrcParamData%nDOFI - DstParamData%nDOFL = SrcParamData%nDOFL - DstParamData%nDOFC = SrcParamData%nDOFC - DstParamData%nDOFR = SrcParamData%nDOFR -IF (ALLOCATED(SrcParamData%IDI)) THEN - i1_l = LBOUND(SrcParamData%IDI,1) - i1_u = UBOUND(SrcParamData%IDI,1) - IF (.NOT. ALLOCATED(DstParamData%IDI)) THEN - ALLOCATE(DstParamData%IDI(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI.', ErrStat, ErrMsg,RoutineName) + DstParamData%nDOFI__ = SrcParamData%nDOFI__ + DstParamData%nDOFI_Rb = SrcParamData%nDOFI_Rb + DstParamData%nDOFI_F = SrcParamData%nDOFI_F + DstParamData%nDOFL_L = SrcParamData%nDOFL_L + DstParamData%nDOFC__ = SrcParamData%nDOFC__ + DstParamData%nDOFC_Rb = SrcParamData%nDOFC_Rb + DstParamData%nDOFC_L = SrcParamData%nDOFC_L + DstParamData%nDOFC_F = SrcParamData%nDOFC_F + DstParamData%nDOFR__ = SrcParamData%nDOFR__ + DstParamData%nDOF__Rb = SrcParamData%nDOF__Rb + DstParamData%nDOF__L = SrcParamData%nDOF__L + DstParamData%nDOF__F = SrcParamData%nDOF__F +IF (ALLOCATED(SrcParamData%IDI__)) THEN + i1_l = LBOUND(SrcParamData%IDI__,1) + i1_u = UBOUND(SrcParamData%IDI__,1) + IF (.NOT. ALLOCATED(DstParamData%IDI__)) THEN + ALLOCATE(DstParamData%IDI__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI__.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%IDI = SrcParamData%IDI + DstParamData%IDI__ = SrcParamData%IDI__ ENDIF -IF (ALLOCATED(SrcParamData%IDL)) THEN - i1_l = LBOUND(SrcParamData%IDL,1) - i1_u = UBOUND(SrcParamData%IDL,1) - IF (.NOT. ALLOCATED(DstParamData%IDL)) THEN - ALLOCATE(DstParamData%IDL(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%IDI_Rb)) THEN + i1_l = LBOUND(SrcParamData%IDI_Rb,1) + i1_u = UBOUND(SrcParamData%IDI_Rb,1) + IF (.NOT. ALLOCATED(DstParamData%IDI_Rb)) THEN + ALLOCATE(DstParamData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%IDL = SrcParamData%IDL + DstParamData%IDI_Rb = SrcParamData%IDI_Rb ENDIF -IF (ALLOCATED(SrcParamData%IDC)) THEN - i1_l = LBOUND(SrcParamData%IDC,1) - i1_u = UBOUND(SrcParamData%IDC,1) - IF (.NOT. ALLOCATED(DstParamData%IDC)) THEN - ALLOCATE(DstParamData%IDC(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%IDI_F)) THEN + i1_l = LBOUND(SrcParamData%IDI_F,1) + i1_u = UBOUND(SrcParamData%IDI_F,1) + IF (.NOT. ALLOCATED(DstParamData%IDI_F)) THEN + ALLOCATE(DstParamData%IDI_F(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_F.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%IDC = SrcParamData%IDC + DstParamData%IDI_F = SrcParamData%IDI_F ENDIF -IF (ALLOCATED(SrcParamData%IDR)) THEN - i1_l = LBOUND(SrcParamData%IDR,1) - i1_u = UBOUND(SrcParamData%IDR,1) - IF (.NOT. ALLOCATED(DstParamData%IDR)) THEN - ALLOCATE(DstParamData%IDR(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%IDL_L)) THEN + i1_l = LBOUND(SrcParamData%IDL_L,1) + i1_u = UBOUND(SrcParamData%IDL_L,1) + IF (.NOT. ALLOCATED(DstParamData%IDL_L)) THEN + ALLOCATE(DstParamData%IDL_L(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDL_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%IDR = SrcParamData%IDR + DstParamData%IDL_L = SrcParamData%IDL_L ENDIF -IF (ALLOCATED(SrcParamData%IDY)) THEN - i1_l = LBOUND(SrcParamData%IDY,1) - i1_u = UBOUND(SrcParamData%IDY,1) - IF (.NOT. ALLOCATED(DstParamData%IDY)) THEN - ALLOCATE(DstParamData%IDY(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%IDC__)) THEN + i1_l = LBOUND(SrcParamData%IDC__,1) + i1_u = UBOUND(SrcParamData%IDC__,1) + IF (.NOT. ALLOCATED(DstParamData%IDC__)) THEN + ALLOCATE(DstParamData%IDC__(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDY.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC__.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%IDY = SrcParamData%IDY + DstParamData%IDC__ = SrcParamData%IDC__ +ENDIF +IF (ALLOCATED(SrcParamData%IDC_Rb)) THEN + i1_l = LBOUND(SrcParamData%IDC_Rb,1) + i1_u = UBOUND(SrcParamData%IDC_Rb,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_Rb)) THEN + ALLOCATE(DstParamData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_Rb = SrcParamData%IDC_Rb +ENDIF +IF (ALLOCATED(SrcParamData%IDC_L)) THEN + i1_l = LBOUND(SrcParamData%IDC_L,1) + i1_u = UBOUND(SrcParamData%IDC_L,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_L)) THEN + ALLOCATE(DstParamData%IDC_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_L = SrcParamData%IDC_L +ENDIF +IF (ALLOCATED(SrcParamData%IDC_F)) THEN + i1_l = LBOUND(SrcParamData%IDC_F,1) + i1_u = UBOUND(SrcParamData%IDC_F,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_F)) THEN + ALLOCATE(DstParamData%IDC_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_F = SrcParamData%IDC_F +ENDIF +IF (ALLOCATED(SrcParamData%IDR__)) THEN + i1_l = LBOUND(SrcParamData%IDR__,1) + i1_u = UBOUND(SrcParamData%IDR__,1) + IF (.NOT. ALLOCATED(DstParamData%IDR__)) THEN + ALLOCATE(DstParamData%IDR__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDR__ = SrcParamData%IDR__ +ENDIF +IF (ALLOCATED(SrcParamData%ID__Rb)) THEN + i1_l = LBOUND(SrcParamData%ID__Rb,1) + i1_u = UBOUND(SrcParamData%ID__Rb,1) + IF (.NOT. ALLOCATED(DstParamData%ID__Rb)) THEN + ALLOCATE(DstParamData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__Rb = SrcParamData%ID__Rb +ENDIF +IF (ALLOCATED(SrcParamData%ID__L)) THEN + i1_l = LBOUND(SrcParamData%ID__L,1) + i1_u = UBOUND(SrcParamData%ID__L,1) + IF (.NOT. ALLOCATED(DstParamData%ID__L)) THEN + ALLOCATE(DstParamData%ID__L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__L = SrcParamData%ID__L +ENDIF +IF (ALLOCATED(SrcParamData%ID__F)) THEN + i1_l = LBOUND(SrcParamData%ID__F,1) + i1_u = UBOUND(SrcParamData%ID__F,1) + IF (.NOT. ALLOCATED(DstParamData%ID__F)) THEN + ALLOCATE(DstParamData%ID__F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__F = SrcParamData%ID__F ENDIF IF (ALLOCATED(SrcParamData%FGL)) THEN i1_l = LBOUND(SrcParamData%FGL,1) @@ -7116,20 +7223,41 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%Nodes_C)) THEN DEALLOCATE(ParamData%Nodes_C) ENDIF -IF (ALLOCATED(ParamData%IDI)) THEN - DEALLOCATE(ParamData%IDI) +IF (ALLOCATED(ParamData%IDI__)) THEN + DEALLOCATE(ParamData%IDI__) +ENDIF +IF (ALLOCATED(ParamData%IDI_Rb)) THEN + DEALLOCATE(ParamData%IDI_Rb) +ENDIF +IF (ALLOCATED(ParamData%IDI_F)) THEN + DEALLOCATE(ParamData%IDI_F) +ENDIF +IF (ALLOCATED(ParamData%IDL_L)) THEN + DEALLOCATE(ParamData%IDL_L) ENDIF -IF (ALLOCATED(ParamData%IDL)) THEN - DEALLOCATE(ParamData%IDL) +IF (ALLOCATED(ParamData%IDC__)) THEN + DEALLOCATE(ParamData%IDC__) ENDIF -IF (ALLOCATED(ParamData%IDC)) THEN - DEALLOCATE(ParamData%IDC) +IF (ALLOCATED(ParamData%IDC_Rb)) THEN + DEALLOCATE(ParamData%IDC_Rb) ENDIF -IF (ALLOCATED(ParamData%IDR)) THEN - DEALLOCATE(ParamData%IDR) +IF (ALLOCATED(ParamData%IDC_L)) THEN + DEALLOCATE(ParamData%IDC_L) ENDIF -IF (ALLOCATED(ParamData%IDY)) THEN - DEALLOCATE(ParamData%IDY) +IF (ALLOCATED(ParamData%IDC_F)) THEN + DEALLOCATE(ParamData%IDC_F) +ENDIF +IF (ALLOCATED(ParamData%IDR__)) THEN + DEALLOCATE(ParamData%IDR__) +ENDIF +IF (ALLOCATED(ParamData%ID__Rb)) THEN + DEALLOCATE(ParamData%ID__Rb) +ENDIF +IF (ALLOCATED(ParamData%ID__L)) THEN + DEALLOCATE(ParamData%ID__L) +ENDIF +IF (ALLOCATED(ParamData%ID__F)) THEN + DEALLOCATE(ParamData%ID__F) ENDIF IF (ALLOCATED(ParamData%FGL)) THEN DEALLOCATE(ParamData%FGL) @@ -7446,34 +7574,77 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! Nodes_C upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%Nodes_C) ! Nodes_C END IF - Int_BufSz = Int_BufSz + 1 ! nDOFI - Int_BufSz = Int_BufSz + 1 ! nDOFL - Int_BufSz = Int_BufSz + 1 ! nDOFC - Int_BufSz = Int_BufSz + 1 ! nDOFR - Int_BufSz = Int_BufSz + 1 ! IDI allocated yes/no - IF ( ALLOCATED(InData%IDI) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDI upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDI) ! IDI - END IF - Int_BufSz = Int_BufSz + 1 ! IDL allocated yes/no - IF ( ALLOCATED(InData%IDL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDL upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDL) ! IDL - END IF - Int_BufSz = Int_BufSz + 1 ! IDC allocated yes/no - IF ( ALLOCATED(InData%IDC) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDC upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDC) ! IDC - END IF - Int_BufSz = Int_BufSz + 1 ! IDR allocated yes/no - IF ( ALLOCATED(InData%IDR) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDR upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDR) ! IDR - END IF - Int_BufSz = Int_BufSz + 1 ! IDY allocated yes/no - IF ( ALLOCATED(InData%IDY) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDY upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDY) ! IDY + Int_BufSz = Int_BufSz + 1 ! nDOFI__ + Int_BufSz = Int_BufSz + 1 ! nDOFI_Rb + Int_BufSz = Int_BufSz + 1 ! nDOFI_F + Int_BufSz = Int_BufSz + 1 ! nDOFL_L + Int_BufSz = Int_BufSz + 1 ! nDOFC__ + Int_BufSz = Int_BufSz + 1 ! nDOFC_Rb + Int_BufSz = Int_BufSz + 1 ! nDOFC_L + Int_BufSz = Int_BufSz + 1 ! nDOFC_F + Int_BufSz = Int_BufSz + 1 ! nDOFR__ + Int_BufSz = Int_BufSz + 1 ! nDOF__Rb + Int_BufSz = Int_BufSz + 1 ! nDOF__L + Int_BufSz = Int_BufSz + 1 ! nDOF__F + Int_BufSz = Int_BufSz + 1 ! IDI__ allocated yes/no + IF ( ALLOCATED(InData%IDI__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI__) ! IDI__ + END IF + Int_BufSz = Int_BufSz + 1 ! IDI_Rb allocated yes/no + IF ( ALLOCATED(InData%IDI_Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI_Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI_Rb) ! IDI_Rb + END IF + Int_BufSz = Int_BufSz + 1 ! IDI_F allocated yes/no + IF ( ALLOCATED(InData%IDI_F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI_F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI_F) ! IDI_F + END IF + Int_BufSz = Int_BufSz + 1 ! IDL_L allocated yes/no + IF ( ALLOCATED(InData%IDL_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDL_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDL_L) ! IDL_L + END IF + Int_BufSz = Int_BufSz + 1 ! IDC__ allocated yes/no + IF ( ALLOCATED(InData%IDC__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC__) ! IDC__ + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_Rb allocated yes/no + IF ( ALLOCATED(InData%IDC_Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_Rb) ! IDC_Rb + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_L allocated yes/no + IF ( ALLOCATED(InData%IDC_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_L) ! IDC_L + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_F allocated yes/no + IF ( ALLOCATED(InData%IDC_F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_F) ! IDC_F + END IF + Int_BufSz = Int_BufSz + 1 ! IDR__ allocated yes/no + IF ( ALLOCATED(InData%IDR__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDR__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDR__) ! IDR__ + END IF + Int_BufSz = Int_BufSz + 1 ! ID__Rb allocated yes/no + IF ( ALLOCATED(InData%ID__Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__Rb) ! ID__Rb + END IF + Int_BufSz = Int_BufSz + 1 ! ID__L allocated yes/no + IF ( ALLOCATED(InData%ID__L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__L) ! ID__L + END IF + Int_BufSz = Int_BufSz + 1 ! ID__F allocated yes/no + IF ( ALLOCATED(InData%ID__F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__F) ! ID__F END IF Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no IF ( ALLOCATED(InData%FGL) ) THEN @@ -8276,78 +8447,185 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%Nodes_C)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_C))-1 ) = PACK(InData%Nodes_C,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%Nodes_C) END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL_L Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC__ Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_Rb Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_L Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%IDI) ) THEN + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__F + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%IDI__) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI__,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDI__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI__))-1 ) = PACK(InData%IDI__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI__) + END IF + IF ( .NOT. ALLOCATED(InData%IDI_Rb) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_Rb,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDI)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI))-1 ) = PACK(InData%IDI,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI) + IF (SIZE(InData%IDI_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_Rb))-1 ) = PACK(InData%IDI_Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI_Rb) END IF - IF ( .NOT. ALLOCATED(InData%IDL) ) THEN + IF ( .NOT. ALLOCATED(InData%IDI_F) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_F,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDL)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDL))-1 ) = PACK(InData%IDL,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDL) + IF (SIZE(InData%IDI_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_F))-1 ) = PACK(InData%IDI_F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI_F) END IF - IF ( .NOT. ALLOCATED(InData%IDC) ) THEN + IF ( .NOT. ALLOCATED(InData%IDL_L) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDL_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL_L,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDC)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC))-1 ) = PACK(InData%IDC,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC) + IF (SIZE(InData%IDL_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDL_L))-1 ) = PACK(InData%IDL_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDL_L) END IF - IF ( .NOT. ALLOCATED(InData%IDR) ) THEN + IF ( .NOT. ALLOCATED(InData%IDC__) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC__,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDR)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR))-1 ) = PACK(InData%IDR,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDR) + IF (SIZE(InData%IDC__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC__))-1 ) = PACK(InData%IDC__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC__) END IF - IF ( .NOT. ALLOCATED(InData%IDY) ) THEN + IF ( .NOT. ALLOCATED(InData%IDC_Rb) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDY,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDY,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_Rb,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDY)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDY))-1 ) = PACK(InData%IDY,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDY) + IF (SIZE(InData%IDC_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_Rb))-1 ) = PACK(InData%IDC_Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_Rb) + END IF + IF ( .NOT. ALLOCATED(InData%IDC_L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_L,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_L))-1 ) = PACK(InData%IDC_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_L) + END IF + IF ( .NOT. ALLOCATED(InData%IDC_F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_F))-1 ) = PACK(InData%IDC_F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_F) + END IF + IF ( .NOT. ALLOCATED(InData%IDR__) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR__,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDR__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR__))-1 ) = PACK(InData%IDR__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDR__) + END IF + IF ( .NOT. ALLOCATED(InData%ID__Rb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__Rb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__Rb))-1 ) = PACK(InData%ID__Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__Rb) + END IF + IF ( .NOT. ALLOCATED(InData%ID__L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__L,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__L))-1 ) = PACK(InData%ID__L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__L) + END IF + IF ( .NOT. ALLOCATED(InData%ID__F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__F))-1 ) = PACK(InData%ID__F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__F) END IF IF ( .NOT. ALLOCATED(InData%FGL) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9642,25 +9920,202 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_C) DEALLOCATE(mask2) END IF - OutData%nDOFI = IntKiBuf( Int_Xferred ) + OutData%nDOFI__ = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_Rb = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_F = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFL_L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC__ = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%nDOFL = IntKiBuf( Int_Xferred ) + OutData%nDOFC_Rb = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%nDOFC = IntKiBuf( Int_Xferred ) + OutData%nDOFC_L = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%nDOFR = IntKiBuf( Int_Xferred ) + OutData%nDOFC_F = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI not allocated + OutData%nDOFR__ = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__Rb = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__F = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI__ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI__)) DEALLOCATE(OutData%IDI__) + ALLOCATE(OutData%IDI__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI__)>0) OutData%IDI__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI__) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_Rb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI_Rb)) DEALLOCATE(OutData%IDI_Rb) + ALLOCATE(OutData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI_Rb)>0) OutData%IDI_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI_Rb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_F not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI_F)) DEALLOCATE(OutData%IDI_F) + ALLOCATE(OutData%IDI_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI_F)>0) OutData%IDI_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI_F) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDL_L)) DEALLOCATE(OutData%IDL_L) + ALLOCATE(OutData%IDL_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDL_L)>0) OutData%IDL_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL_L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDL_L) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC__ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC__)) DEALLOCATE(OutData%IDC__) + ALLOCATE(OutData%IDC__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC__)>0) OutData%IDC__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC__) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_Rb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC_Rb)) DEALLOCATE(OutData%IDC_Rb) + ALLOCATE(OutData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC_Rb)>0) OutData%IDC_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_Rb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC_L)) DEALLOCATE(OutData%IDC_L) + ALLOCATE(OutData%IDC_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC_L)>0) OutData%IDC_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_L) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_F not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDI)) DEALLOCATE(OutData%IDI) - ALLOCATE(OutData%IDI(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IDC_F)) DEALLOCATE(OutData%IDC_F) + ALLOCATE(OutData%IDC_F(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_F.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9669,21 +10124,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDI)>0) OutData%IDI = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI) + IF (SIZE(OutData%IDC_F)>0) OutData%IDC_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_F) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR__ not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDL)) DEALLOCATE(OutData%IDL) - ALLOCATE(OutData%IDL(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IDR__)) DEALLOCATE(OutData%IDR__) + ALLOCATE(OutData%IDR__(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR__.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9692,21 +10147,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDL)>0) OutData%IDL = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDL) + IF (SIZE(OutData%IDR__)>0) OutData%IDR__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDR__) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__Rb not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC)) DEALLOCATE(OutData%IDC) - ALLOCATE(OutData%IDC(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%ID__Rb)) DEALLOCATE(OutData%ID__Rb) + ALLOCATE(OutData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__Rb.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9715,21 +10170,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDC)>0) OutData%IDC = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC) + IF (SIZE(OutData%ID__Rb)>0) OutData%ID__Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__Rb) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__L not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDR)) DEALLOCATE(OutData%IDR) - ALLOCATE(OutData%IDR(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%ID__L)) DEALLOCATE(OutData%ID__L) + ALLOCATE(OutData%ID__L(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__L.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9738,21 +10193,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDR)>0) OutData%IDR = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDR) + IF (SIZE(OutData%ID__L)>0) OutData%ID__L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__L) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDY not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__F not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDY)) DEALLOCATE(OutData%IDY) - ALLOCATE(OutData%IDY(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%ID__F)) DEALLOCATE(OutData%ID__F) + ALLOCATE(OutData%ID__F(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDY.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__F.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9761,8 +10216,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%IDY)>0) OutData%IDY = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDY))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDY) + IF (SIZE(OutData%ID__F)>0) OutData%ID__F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__F) DEALLOCATE(mask1) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated From daddf13906a367d3d17da0e04047042bec05fa7d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 2 May 2020 21:51:47 -0600 Subject: [PATCH 192/377] FlexSub: using rigid transformation function for TIreact --- modules/subdyn/src/SD_FEM.f90 | 44 ++++++++++++++++++++ modules/subdyn/src/SubDyn.f90 | 47 --------------------- modules/subdyn/src/SubDyn_Output.f90 | 61 +++++----------------------- 3 files changed, 54 insertions(+), 98 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 4a22a6af0..fd19e90d9 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -211,6 +211,50 @@ LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p, ei) enddo ei=-1 END FUNCTION NodeHasRigidElem +!------------------------------------------------------------------------------------------------------ +!> Returns a rigid body transformation matrix from nDOF to 6 reference DOF: T_ref (6 x nDOF), such that Uref = T_ref.U_subset +!! Typically called to get: +!! - the transformation from the interface points to the TP point +!! - the transformation from the bottom nodes to SubDyn origin (0,0,) +SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(IN ) :: p + REAL(ReKi), INTENT(IN ) :: RefPoint(3) ! Coordinate of the reference point + INTEGER(IntKi), INTENT(IN ) :: nDOF ! Number of DOFS + INTEGER(IntKi), INTENT(IN ) :: DOF(nDOF) ! DOF indices that are used to create the transformation matrix + REAL(ReKi), INTENT( OUT) :: T_ref(nDOF,6) ! matrix that relates the subset of DOFs to the reference point + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER :: I, iDOF, iiDOF, iNode, nDOFPerNode + REAL(ReKi) :: dx, dy, dz + REAL(ReKi), dimension(6) :: Line + ErrStat = ErrID_None + ErrMsg = "" + T_ref(:,:)=0 + DO I = 1, nDOF + iDOF = DOF(I) ! DOF index in constrained system + iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + + if ((iiDOF<1) .or. (iiDOF>6)) then + ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + return + endif + if (nDOFPerNode/=6) then + ErrMsg = 'RigidTrnsf, node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + return + endif + + dx = Init%Nodes(iNode, 2) - RefPoint(1) + dy = Init%Nodes(iNode, 3) - RefPoint(2) + dz = Init%Nodes(iNode, 4) - RefPoint(3) + + CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line + T_ref(I, 1:6) = Line + ENDDO +END SUBROUTINE RigidTrnsf !------------------------------------------------------------------------------------------------------ ! --- Main routines, more or less listed in order in which they are called diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 52f5775fa..a6681efd4 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1936,53 +1936,6 @@ subroutine CleanUp() end subroutine END SUBROUTINE CBMatrix -!------------------------------------------------------------------------------------------------------ -!> Returns a rigid body transformation matrix from nDOF to 6 reference DOF: T_ref (6 x nDOF), such that Uref = T_ref.U_subset -!! Typically called to get: -!! - the transformation from the interface points to the TP point -!! - the transformation from the bottom nodes to SubDyn origin (0,0,) -SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT(IN ) :: RefPoint(3) ! Coordinate of the reference point - INTEGER(IntKi), INTENT(IN ) :: nDOF ! Number of DOFS - INTEGER(IntKi), INTENT(IN ) :: DOF(nDOF) ! DOF indices that are used to create the transformation matrix - REAL(ReKi), INTENT( OUT) :: T_ref(nDOF,6) ! matrix that relates the subset of DOFs to the reference point - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER :: I, iDOF, iiDOF, iNode, nDOFPerNode - REAL(ReKi) :: dx, dy, dz - REAL(ReKi), dimension(6) :: Line - ErrStat = ErrID_None - ErrMsg = "" - T_ref(:,:)=0 - DO I = 1, nDOF - iDOF = DOF(I) ! DOF index in constrained system - iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) - - if ((iiDOF<1) .or. (iiDOF>6)) then - ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal - return - endif - if (nDOFPerNode/=6) then - ErrMsg = 'RigidTrnsf, node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal - return - endif - - dx = Init%Nodes(iNode, 2) - RefPoint(1) - dy = Init%Nodes(iNode, 3) - RefPoint(2) - dz = Init%Nodes(iNode, 4) - RefPoint(3) - - CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line - T_ref(I, 1:6) = Line - ENDDO -END SUBROUTINE RigidTrnsf - - - !------------------------------------------------------------------------------------------------------ !> Wrapper function for eigen value analyses, for two cases: !! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 14844eb30..003a8ea0f 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -65,6 +65,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) INTEGER(IntKi) :: iiElem ! Loop counter on element index INTEGER(IntKi) :: nElemPerNode ! Number of elements connecting to a node type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities + real(ReKi), allocatable :: T_TIreact(:,:) ! Transpose of TIreact, temporary ErrStat = 0 ErrMsg="" @@ -182,8 +183,12 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=1, iStore=iiElem, NodeID2=iNode) ENDDO ENDDO - ! Compute p%TIreact, matrix to calculate single point reaction at the base of structure - CALL ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) + ! Compute p%TIreact, rigid transf. matrix from reaction DOFs to base structure point (0,0,-WD) + CALL AllocAry(p%TIreact, 6, p%nDOFC__, 'TIReact ', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(T_TIreact, p%nDOFC__, 6, 'TIReact_T', ErrStat2, ErrMsg2); if(Failed()) return + call RigidTrnsf(Init, p, (/0.0_Reki, 0.0_ReKi, -WtrDpth /), p%IDC__, p%nDOFC__, T_TIreact, ErrStat2, ErrMsg2); if(Failed()) return + p%TIreact=transpose(T_TIreact) + deallocate(T_TIreact) ENDIF RETURN @@ -245,58 +250,12 @@ END SUBROUTINE ConfigOutputNode_MKF_ID END SUBROUTINE SDOut_Init - !------------------------------------------------------------------------------------------------------ -!>This subroutine allocates and calculated TIreact, Matrix to go from local reactions at constrained nodes to single point reactions -SUBROUTINE ReactMatx(Init, WtrDpth, p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init !< Input data for initialization routine - REAL(ReKi), INTENT(IN ) :: WtrDpth !< Water depth - TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameter data - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - INTEGER :: I !counter - INTEGER(IntKi) :: iDOF, iiDOF, iNode, nDOFPerNode ! - REAL(ReKi) :: dx, dy, dz ! distances from reaction points to subdyn origin (mudline) - REAL(ReKi), dimension(6) :: Line - ErrStat=ErrID_None - ErrMsg="" - - CALL AllocAry(p%TIreact, 6, p%nDOFC__, 'TIReact', ErrStat, ErrMsg); if ( ErrStat /= ErrID_None ) return - - ! --- TI: Transformation matrix from interface points to ref point - p%TIreact(1:6,:)=0 !Initialize - DO I = 1, p%nDOFC__ - iDOF = p%IDC__(I) ! DOF index in constrained system - iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) - if ((iiDOF<1) .or. (iiDOF>6)) then - ErrMsg = 'ReactMatx, interface node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal - return - endif - if (nDOFPerNode/=6) then - ErrMsg = 'ReactMatx, interface node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal - return - endif - - dx = Init%Nodes(iNode, 2) - dy = Init%Nodes(iNode, 3) - dz = Init%Nodes(iNode, 4) + WtrDpth - - CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line - p%TIreact(1:6, I) = Line - enddo - -END SUBROUTINE ReactMatx - -!==================================================================================================== !> Writes the data stored in the y variable to the correct indexed postions in WriteOutput !! This is called by SD_CalcOutput() at each time step. !! This routine does fill Allouts !! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling !! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) -!---------------------------------------------------------------------------------------------------- SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) real(DbKi), intent( in ) :: CurrentTime ! Current simulation time in seconds type(SD_InputType), intent( in ) :: u ! SubDyn module's input data @@ -419,10 +378,10 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ErrStat = ErrID_Fatal RETURN END IF - ReactNs = 0.0 !Initialize + ReactNs = 0.0_ReKi !Initialize DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh - FK_elm2=0. !Initialize for cumulative force - FM_elm2=0. !Initialize + FK_elm2=0._ReKi !Initialize for cumulative force + FM_elm2=0._ReKi !Initialize pLst => p%MOutLst3(I) !Find the joint forces DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) From e57f22afee97d2b358c1249ed46188061f0690ba Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 2 May 2020 23:27:50 -0600 Subject: [PATCH 193/377] FlexSub: consistent order of DOFs with Nodes --- modules/subdyn/src/SubDyn.f90 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a6681efd4..f531c6287 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2310,7 +2310,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables - integer(IntKi) :: I, J, c_B, c_F, c_L ! counters + integer(IntKi) :: I, J, c_B, c_F, c_L, c__ ! counters integer(IntKi) :: iNode, iiNode integer(IntKi) :: nNodes_R integer(IntKi), allocatable :: IDAll(:) @@ -2416,10 +2416,12 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) ! -------------------------------------------------------------------------------- ! Distribute the interface DOFs into R,F - c_B=0; c_F=0 ! Counters over R and F dofs + c__=0; c_B=0; c_F=0 ! Counters over R and F dofs do iiNode= 1,p%nNodes_I !Loop on interface nodes iNode = p%Nodes_I(iiNode,1) do J = 1, 6 ! DOFs: ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + c__=c__+1 + p%IDI__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number if (p%Nodes_I(iiNode, J+1)==idBC_Leader) then c_B=c_B+1 p%IDI_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number @@ -2431,13 +2433,15 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) enddo enddo ! Indices IDI__ = [IDI_B, IDI_F], interface - call concatenate_lists(p%IDI_Rb, p%IDI_F, p%IDI__, ErrStat2, ErrMsg2); if(Failed()) return + !call concatenate_lists(p%IDI_Rb, p%IDI_F, p%IDI__, ErrStat2, ErrMsg2); if(Failed()) return ! Distribute the reaction DOFs into R,F,L - c_B=0; c_F=0; c_L=0; ! Counters over R, F, L dofs + c__=0; c_B=0; c_F=0; c_L=0; ! Counters over R, F, L dofs do iiNode= 1,p%nNodes_C !Loop on interface nodes iNode = p%Nodes_C(iiNode,1) do J = 1, 6 ! DOFs + c__=c__+1 + p%IDC__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number if (p%Nodes_C(iiNode, J+1)==idBC_Leader) then c_B=c_B+1 p%IDC_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number @@ -2453,7 +2457,9 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) enddo enddo ! Indices IDC__ = [IDC_B, IDC_F, IDC_L], interface - call concatenate_3lists(p%IDC_Rb, p%IDC_F, p%IDC_L, p%IDC__, ErrStat2, ErrMsg2); if(Failed()) return + !call concatenate_3lists(p%IDC_Rb, p%IDC_F, p%IDC_L, p%IDC__, ErrStat2, ErrMsg2); if(Failed()) return + !call sort_in_place(p%IDC__) + ! Indices IDR__ = [IDI__, IDC__], interface !call concatenate_lists(p%IDI__, p%IDC__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return From b859bd7c3de0f96344840e3d55dfddc93144f1d8 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sun, 3 May 2020 00:10:17 -0600 Subject: [PATCH 194/377] FlexSub: allowing C nodes to be free, temp switch CB before BC for backward compatibility --- modules/subdyn/src/SD_FEM.f90 | 2 - modules/subdyn/src/SubDyn.f90 | 184 ++++++++++++++++++---------------- 2 files changed, 100 insertions(+), 86 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index fd19e90d9..f2df149f6 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -885,8 +885,6 @@ SUBROUTINE InitBCs(Init, p) else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF Init%BCs( (I-1)*6+J, 2) = idBC_Internal p%Nodes_C(I, J+1) = idBC_Internal - print*,'BC 0 not allowed for now, node',iNode - STOP else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF Init%BCs( (I-1)*6+J, 2) = idBC_Leader p%Nodes_C(I, J+1) = idBC_Leader diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f531c6287..44582f0ba 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -852,10 +852,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') return endif - if (any(p%Nodes_C(I,:)<=0)) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for reactions. Problematic line: "'//trim(Line)//'"') - return - endif ENDDO IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return @@ -1589,7 +1585,7 @@ END SUBROUTINE SD_AM2 !> Perform Craig Bampton reduction SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType),INTENT(INOUT) :: p ! Parameters + TYPE(SD_ParameterType),INTENT(INOUT),target::p ! Parameters TYPE(SD_MiscVarType), INTENT(IN ) :: m TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation @@ -1603,15 +1599,13 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) REAL(ReKi), ALLOCATABLE :: KRL(:, :) REAL(ReKi), ALLOCATABLE :: FGR(:) REAL(ReKi), ALLOCATABLE :: FGL(:) - REAL(ReKi), ALLOCATABLE :: MBBb(:, :) - REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: FGRb(:) REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array INTEGER(IntKi) :: nM_Out, i + INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) + INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 + LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility ErrStat = ErrID_None ErrMsg = "" @@ -1637,27 +1631,38 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - ! TODO Used __Rb instead of R__ - CALL AllocAry( MRR, p%nDOFR__, p%nDOFR__, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + ! Temporary backward compatibility + BC_Before_CB=p%nDOFC_L>0 ! if we have some free C DOFs + if(BC_Before_CB) then + print*,' > Boundary conditions will be applied before Craig-Bampton (New)' + nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction + IDR => p%ID__Rb + else + print*,' > Craig-Bampton will be applied before boundary conditions (Legacy)' + nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system + IDR => p%IDR__ + endif + + ! NOTE: these below are either "R" or "Rb" matrices + CALL AllocAry( MRR, nR , nR , 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( MLL, p%nDOF__L, p%nDOF__L, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MRL, p%nDOFR__, p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRR, p%nDOFR__, p%nDOFR__, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( MRL, nR , p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRR, nR , nR , 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( KLL, p%nDOF__L, p%nDOF__L, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRL, p%nDOFR__, p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( KRL, nR , p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( FGL, p%nDOF__L, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGR, p%nDOFR__, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( FGR, nR , 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBB, p%nDOFR__, p%nDOFR__, 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBM, p%nDOFR__, p%nDOFM , 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%KBB, p%nDOFR__, p%nDOFR__, 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBB, nR , nR , 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%MBM, nR , p%nDOFM , 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%KBB, nR , nR , 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%PhiL, p%nDOF__L, p%nDOF__L, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%nDOF__L, p%nDOFR__, 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + CALL AllocAry( CBparams%PhiR, p%nDOF__L, nR , 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') CALL AllocAry( CBparams%OmegaL, p%nDOF__L, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on M, K, FG and indices IDR and IDL ! NOTE: generic FEM code - ! TODO use __Rb - CALL BreakSysMtrx(Init%M, Init%K, Init%FG, p%IDR__, p%ID__L, p%nDOFR__, p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + CALL BreakSysMtrx(Init%M, Init%K, Init%FG, IDR , p%ID__L, nR , p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1668,11 +1673,11 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) !................................ CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT - nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ! TODO + nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ELSE nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes ENDIF - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, p%nDOFR__, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs ! TODO + CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, nR, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2) ! <- outputs if(Failed()) return @@ -1685,42 +1690,14 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) END IF ! TODO TODO TODO DAMPING MATRIX - - ! to use a little less space, let's deallocate these arrays that we don't need anymore, then allocate the next set of temporary arrays: - IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) - IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) - IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) - IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) - IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) - IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) - - ! "b" stands for "bar"; "t" stands for "tilde" - ! TODO TODO TODO this is wrong - CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); if (Failed()) return - CALL AllocAry( FGRb, p%nDOF__Rb, 'array FGRb', ErrStat2, ErrMsg2 ); if (Failed()) return - - !................................ - ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to - ! MBBb, MBMb, KBBb, PHiRb, FGRb - ! (throw out rows/columns of first matrices to create second matrices) - !................................ - ! TODO avoid this all together - MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) -IF (p%nDOFM > 0) THEN - MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) -END IF - FGRb = FGR (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) - PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - ! TODO TODO TODO Transform new damping matrix as well - !................................ - ! set values needed to calculate outputs and update states: - !................................ - CALL SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, CBparams%OmegaL, FGL, CBparams%PhiL, ErrStat2, ErrMsg2) + + if(.not.BC_Before_CB) then + ! We apply the BC now, removing unwanted DOFs + call applyConstr(CBParams, FGR) + endif + + CALL SetParameters(Init, p, CBparams%MBB, CBparams%MBM, CBparams%KBB, FGR, CBparams%PhiR, CBparams%OmegaL, FGL, CBparams%PhiL, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1748,13 +1725,50 @@ subroutine CleanUpCB() IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) - IF(ALLOCATED(MBBb) ) DEALLOCATE(MBBb) - IF(ALLOCATED(MBmb) ) DEALLOCATE(MBmb) - IF(ALLOCATED(KBBb) ) DEALLOCATE(KBBb) - IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) - IF(ALLOCATED(FGRb) ) DEALLOCATE(FGRb) end subroutine CleanUpCB + !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system + !! NOTE: PhiL and OmegaL are not modified + subroutine applyConstr(CBParams, FGR) + TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGR(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi), ALLOCATABLE :: MBBb(:, :) + REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: KBBb(:, :) + REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) + REAL(ReKi), ALLOCATABLE :: FGRb(:) + ! "b" stands for "bar" + ! TODO TODO TODO this is wrong + CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); + CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); + CALL AllocAry( FGRb, p%nDOF__Rb, 'array FGRb', ErrStat2, ErrMsg2 ); + !................................ + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to + ! MBBb, MBMb, KBBb, PHiRb, FGRb + ! (throw out rows/columns of first matrices to create second matrices) + !................................ + ! TODO avoid this all together + MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + IF (p%nDOFM > 0) THEN + MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) + END IF + FGRb = FGR (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) + PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + deallocate(CBparams%MBB) + deallocate(CBparams%KBB) + deallocate(CBparams%MBM) + deallocate(CBparams%PhiR) + deallocate(FGR) + call move_alloc(MBBb, CBparams%MBB) + call move_alloc(KBBb, CBparams%KBB) + call move_alloc(MBMb, CBparams%MBM) + call move_alloc(PhiRb, CBparams%PhiR) + call move_alloc(FGRb, FGR) + end subroutine applyConstr + END SUBROUTINE Craig_Bampton !------------------------------------------------------------------------------------------------------ @@ -2389,11 +2403,8 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) p%nDOF__L = p%nDOFC_L + p%nDOFL_L ! OK, generic ! --- Safety checks ! TODO: these checks are temporary! - if (p%nDOFC_F /= p%nNodes_C*6) then - call Fatal('Wrong number of DOF for reactions nodes, likely some reaction nodes are special joints and should be cantilever instead.'); return - endif if (p%nDOFI_Rb /= p%nNodes_I*6) then - call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints and should be cantilever instead.'); return + call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints or are fixed'); return endif ! Set the index arrays @@ -2816,22 +2827,27 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ENDDO ! Set TI2, transformation matrix from R DOFs to SubDyn Origin - CALL AllocAry( TI2, p%nDOFR__, 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return - MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body - deallocate(TI2) - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' - WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') 'MRB' - WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) - DO i=1,6 - WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) - ENDDO - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) - WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + ! TODO TODO TODO + if (p%nDOFR__/=p%nDOF__Rb) then + WRITE(UnSum, '(A)') 'TODO, Equivalent mass matrix not available yet' + else + CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return + MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') 'MRB' + WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) + DO i=1,6 + WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) + ENDDO + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + deallocate(TI2) + endif #ifdef SD_SUMMARY_DEBUG From 50a1ae1c550a7169e4799d63fa5167b4e78881d2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 4 May 2020 20:08:20 -0600 Subject: [PATCH 195/377] FlexSub: isolating generic FEM code (no type dependency) --- modules/subdyn/src/FEM.f90 | 281 ++++++++++++++++++++++++++++++ modules/subdyn/src/SubDyn.f90 | 317 ++-------------------------------- 2 files changed, 291 insertions(+), 307 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 07daecafb..7967b1950 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -188,6 +188,287 @@ FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) endif END FUNCTION Determinant !------------------------------------------------------------------------------------------------------ +!> Partition matrices and vectors into Boundary (R) and internal (L) nodes +!! M = [ MRR, MRL ] +!! [ sym, MLL ] +!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FR = F(IDR) +!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) +!! MRL = M(IDR, IDL), KRR = K(IDR, IDL) +!! NOTE: generic code +SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) + REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix + REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix + INTEGER(IntKi), INTENT(IN ) :: nR + INTEGER(IntKi), INTENT(IN ) :: nL + INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs + INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs + REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) + REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) + REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) + INTEGER(IntKi) :: I, J, II, JJ + + ! RR: Leader/Boundary DOFs + DO I = 1, nR + II = IDR(I) + DO J = 1, nR + JJ = IDR(J) + MRR(I, J) = MM(II, JJ) + KRR(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! LL: Interior/follower DOFs + DO I = 1, nL + II = IDL(I) + DO J = 1, nL + JJ = IDL(J) + MLL(I, J) = MM(II, JJ) + KLL(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! RL: cross terms + DO I = 1, nR + II = IDR(I) + DO J = 1, nL + JJ = IDL(J) + MRL(I, J) = MM(II, JJ) + KRL(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! Forces + if (present(FG)) then + if (present(FGR)) then + do I = 1, nR + II = IDR(I) + FGR(I) = FG(II) + enddo + endif + if (present(FGL)) then + do I = 1, nL + II = IDL(I) + FGL(I) = FG(II) + enddo + endif + endif +END SUBROUTINE BreakSysMtrx + +!------------------------------------------------------------------------------------------------------ +!> Performs Craig-Bampton reduction based on partitioned matrices M and K +!! Convention is: +!! "R": leader DOF -> "B": reduced leader DOF +!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) +!! NOTE: +!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned +!! - Possibility to get all the CB modes using the input nM_Out>nM +!! +!! NOTE: generic code +SUBROUTINE CraigBamptonReduction( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) + USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf + INTEGER(IntKi), INTENT( in) :: nR + INTEGER(IntKi), INTENT( in) :: nL + INTEGER(IntKi), INTENT( in) :: nM_Out + INTEGER(IntKi), INTENT( in) :: nM + REAL(ReKi), INTENT( IN) :: MRR( nR, nR) + REAL(ReKi), INTENT( IN) :: MLL( nL, nL) + REAL(ReKi), INTENT( IN) :: MRL( nR, nL) + REAL(ReKi), INTENT( IN) :: KRR( nR, nR) + REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) + REAL(ReKi), INTENT( IN) :: KRL( nR, nL) + REAL(ReKi), INTENT(INOUT) :: MBB( nR, nR) + REAL(ReKi), INTENT(INOUT) :: MBM( nR, nM) + REAL(ReKi), INTENT(INOUT) :: KBB( nR, nR) + REAL(ReKi), INTENT(INOUT) :: PhiR(nL, nR) ! Guyan Modes + REAL(ReKi), INTENT(INOUT) :: PhiL(nL, nL) ! Craig-Bampton modes TODO nM_out? + REAL(ReKi), INTENT(INOUT) :: OmegaL(nL) ! Eigenvalues TODO nM_out? + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! LOCAL VARIABLES + REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%nDOFR,p%nDOFL) = transpose of PhiR * MLL (temporary storage) + INTEGER :: I !, lwork !counter, and varibales for inversion routines + INTEGER :: ipiv(nL) !the integer vector ipvt of length min(m,n), containing the pivot indices. + !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, + !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' + ErrStat = ErrID_None + ErrMsg = '' + + if (nM_out>nL) then + ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; + if(Failed()) return; + endif + + !.................................................... + ! Set OmegaL and PhiL from Eq. 2 + !.................................................... + IF ( nM_out > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... + ! bCheckSingularity = True + CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Normalize PhiL + ! bjj: break up this equation to avoid as many temporary variables on the stack + ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) + CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , nL , nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + MU = TRANSPOSE(PhiL) + Temp = MATMUL( MU, MLL ) + MU = MATMUL( Temp, PhiL ) + DEALLOCATE(Temp) + ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) + DO I = 1, nM_out + PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) + ENDDO + DO I=nM_out+1, nL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) + PhiL(:,I) = 0.0_ReKi + OmegaL(I) = 0.0_ReKi + END DO + DEALLOCATE(MU) + END IF + + !.................................................... + ! Set PhiR from Eq. 3: + !.................................................... + ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) + ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** + CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return + + PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) + CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return + + !.................................................... + ! Set MBB, MBM, and KBB from Eq. 4: + !.................................................... + CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + + PhiR_T_MLL = TRANSPOSE(PhiR) + PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) + MBB = MATMUL(MRL, PhiR) + MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) + + IF ( nM == 0) THEN + MBM = 0.0_ReKi + ELSE + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM + ENDIF + DEALLOCATE( PhiR_T_MLL ) + + KBB = MATMUL(KRL, PhiR) + KBB = KBB + KRR + +CONTAINS + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + if (allocated(Mu )) DEALLOCATE(Mu ) + if (allocated(Temp )) DEALLOCATE(Temp ) + if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) + end subroutine +END SUBROUTINE CraigBamptonReduction + +!------------------------------------------------------------------------------------------------------ +!> Wrapper function for eigen value analyses, for two cases: +!! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix +!! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system +SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) + INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system + REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix + REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix + INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues + LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present + REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors + REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) + + ! LOCALS + REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) + REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) + REAL(ReKi) :: Om2 + INTEGER(IntKi) :: N, i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = '' + + ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi + if (present(bDOF)) then + ! Remove unwanted DOFs + call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + else + N=size(K,1) + CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + K_LaKi = real( K, LaKi ) + M_LaKi = real( M, LaKi ) + endif + N=size(K_LaKi,1) + + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! + if ( NOmega > nDOF ) then + CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') + CALL CleanupEigen() + return + end if + + + ! --- Eigenvalue analysis + CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; + CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + + ! --- Setting up Phi, and type conversion + do i = 1, NOmega + Om2 = real(Omega2_LaKi(i), ReKi) + if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics + Omega(i)=0.0_ReKi + elseif (Om2>0) then + Omega(i)=sqrt(Om2) ! was getting floating invalid + else + print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 + Omega(i)= 0.0_ReKi + endif + enddo + if (present(bDOF)) then + ! Insert 0s where bDOF was false + CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return + else + EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors + endif + CALL CleanupEigen() + return +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + + SUBROUTINE CleanupEigen() + IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) + IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) + IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) + IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) + END SUBROUTINE CleanupEigen + +END SUBROUTINE EigenSolveWrap +!------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 44582f0ba..4e466610a 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -24,7 +24,6 @@ Module SubDyn USE NWTC_Library - USE NWTC_LAPACK USE SubDyn_Types USE SubDyn_Output USE SubDyn_Tests @@ -233,12 +232,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! Insert soil stiffness and mass matrix - ! TODO, let's see if we can go without storing the "noSSI" matrices - ! Init%MorignoSSI=Init%M !original M, full and no SSI m - ! Init%KorignoSSI=Init%K !original K, full and no SSI k CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - ! Init%Morig=Init%M !original M, full and WITH SSI-k effects - ! Init%Korig=Init%K !original K, full and WITH SSI-k effects ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return @@ -256,7 +250,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return ! --- Craig-Bampton reduction (sets many parameters) - CALL Craig_Bampton(Init, p, m, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return ! --- Initial system states IF ( p%nDOFM > 0 ) THEN @@ -1518,6 +1512,7 @@ END SUBROUTINE SD_RK4 !! Thus x_n+1 = x_n - J^-1 *dt/2 * (2*A*x_n + B *(u_n + u_n+1) +2*Fx) !! or J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + USE NWTC_LAPACK, only: LAPACK_getrs REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds INTEGER(IntKi), INTENT(IN ) :: n !< time step number TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t @@ -1582,11 +1577,10 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg END SUBROUTINE SD_AM2 !------------------------------------------------------------------------------------------------------ -!> Perform Craig Bampton reduction -SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) +!> Perform Craig Bampton reduction and set parameters needed for States and Ouputs equations +SUBROUTINE SD_Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine TYPE(SD_ParameterType),INTENT(INOUT),target::p ! Parameters - TYPE(SD_MiscVarType), INTENT(IN ) :: m TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -1662,7 +1656,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on M, K, FG and indices IDR and IDL ! NOTE: generic FEM code - CALL BreakSysMtrx(Init%M, Init%K, Init%FG, IDR , p%ID__L, nR , p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) + CALL BreakSysMtrx(Init%M, Init%K, IDR , p%ID__L, nR , p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, Init%FG, FGR, FGL) !................................ ! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1677,7 +1671,7 @@ SUBROUTINE Craig_Bampton(Init, p, m, CBparams, ErrStat, ErrMsg) ELSE nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes ENDIF - CALL CBMatrix(MRR, MLL, MRL, KRR, KLL, KRL, nR, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs + CALL CraigBamptonReduction(MRR, MLL, MRL, KRR, KLL, KRL, nR, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2) ! <- outputs if(Failed()) return @@ -1769,301 +1763,10 @@ subroutine applyConstr(CBParams, FGR) call move_alloc(FGRb, FGR) end subroutine applyConstr -END SUBROUTINE Craig_Bampton - -!------------------------------------------------------------------------------------------------------ -!> Partition matrices and vectors into Boundary (R) and internal (L) nodes -!! M = [ MRR, MRL ] -!! [ sym, MLL ] -!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FR = F(IDR) -!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) -!! MRL = M(IDR, IDL), KRR = K(IDR, IDL) -!! NOTE: generic code, TODO: move me to FEM -SUBROUTINE BreakSysMtrx(MM, KK, FG, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL) - REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix - REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix - REAL(ReKi), INTENT(IN ) :: FG(:) !< Force vector - INTEGER(IntKi), INTENT(IN ) :: nR - INTEGER(IntKi), INTENT(IN ) :: nL - INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs - INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs - REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) - REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) - REAL(ReKi), INTENT( OUT) :: FGR(nR) - REAL(ReKi), INTENT( OUT) :: FGL(nL) - INTEGER(IntKi) :: I, J, II, JJ - - ! RR: Leader/Boundary DOFs - DO I = 1, nR - II = IDR(I) - FGR(I) = FG(II) - DO J = 1, nR - JJ = IDR(J) - MRR(I, J) = MM(II, JJ) - KRR(I, J) = KK(II, JJ) - ENDDO - ENDDO - ! LL: Interior/follower DOFs - DO I = 1, nL - II = IDL(I) - FGL(I) = FG(II) - DO J = 1, nL - JJ = IDL(J) - MLL(I, J) = MM(II, JJ) - KLL(I, J) = KK(II, JJ) - ENDDO - ENDDO - ! RL: cross terms - DO I = 1, nR - II = IDR(I) - DO J = 1, nL - JJ = IDL(J) - MRL(I, J) = MM(II, JJ) - KRL(I, J) = KK(II, JJ) - ENDDO - ENDDO -END SUBROUTINE BreakSysMtrx - -!------------------------------------------------------------------------------------------------------ -!> Performs Craig-Bampton reduction based on partitioned matrices M and K -!! Convention is: -!! "R": leader DOF -> "B": reduced leader DOF -!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) -!! NOTE: -!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned -!! - Possibility to get all the CB modes using the input nM_Out>nM -!! -!! NOTE: generic code, TODO: move me to FEM -SUBROUTINE CBMatrix( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) - INTEGER(IntKi), INTENT( in) :: nR - INTEGER(IntKi), INTENT( in) :: nL - INTEGER(IntKi), INTENT( in) :: nM_Out - INTEGER(IntKi), INTENT( in) :: nM - REAL(ReKi), INTENT( IN) :: MRR( nR, nR) - REAL(ReKi), INTENT( IN) :: MLL( nL, nL) - REAL(ReKi), INTENT( IN) :: MRL( nR, nL) - REAL(ReKi), INTENT( IN) :: KRR( nR, nR) - REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) - REAL(ReKi), INTENT( IN) :: KRL( nR, nL) - REAL(ReKi), INTENT(INOUT) :: MBB( nR, nR) - REAL(ReKi), INTENT(INOUT) :: MBM( nR, nM) - REAL(ReKi), INTENT(INOUT) :: KBB( nR, nR) - REAL(ReKi), INTENT(INOUT) :: PhiR(nL, nR) ! Guyan Modes - REAL(ReKi), INTENT(INOUT) :: PhiL(nL, nL) ! Craig-Bampton modes TODO nM_out? - REAL(ReKi), INTENT(INOUT) :: OmegaL(nL) ! Eigenvalues TODO nM_out? - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! LOCAL VARIABLES - REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%nDOFR,p%nDOFL) = transpose of PhiR * MLL (temporary storage) - INTEGER :: I !, lwork !counter, and varibales for inversion routines - INTEGER :: ipiv(nL) !the integer vector ipvt of length min(m,n), containing the pivot indices. - !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, - !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' - ErrStat = ErrID_None - ErrMsg = '' - - if (nM_out>nL) then - ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; - if(Failed()) return; - endif - - !.................................................... - ! Set OmegaL and PhiL from Eq. 2 - !.................................................... - IF ( nM_out > 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... - ! bCheckSingularity = True - CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Normalize PhiL - ! bjj: break up this equation to avoid as many temporary variables on the stack - ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) - CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return - CALL AllocAry( MU , nL , nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return - MU = TRANSPOSE(PhiL) - Temp = MATMUL( MU, MLL ) - MU = MATMUL( Temp, PhiL ) - DEALLOCATE(Temp) - ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) - DO I = 1, nM_out - PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) - ENDDO - DO I=nM_out+1, nL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) - PhiL(:,I) = 0.0_ReKi - OmegaL(I) = 0.0_ReKi - END DO - DEALLOCATE(MU) - END IF - - !.................................................... - ! Set PhiR from Eq. 3: - !.................................................... - ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) - ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** - CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return - - PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return - - !.................................................... - ! Set MBB, MBM, and KBB from Eq. 4: - !.................................................... - CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return - - PhiR_T_MLL = TRANSPOSE(PhiR) - PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) - MBB = MATMUL(MRL, PhiR) - MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) - - IF ( nM == 0) THEN - MBM = 0.0_ReKi - ELSE - MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation - MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM - ENDIF - DEALLOCATE( PhiR_T_MLL ) - - KBB = MATMUL(KRL, PhiR) - KBB = KBB + KRR - -CONTAINS - - logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CBMatrix') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - end function Failed - - subroutine CleanUp() - if (allocated(Mu )) DEALLOCATE(Mu ) - if (allocated(Temp )) DEALLOCATE(Temp ) - if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) - end subroutine -END SUBROUTINE CBMatrix - -!------------------------------------------------------------------------------------------------------ -!> Wrapper function for eigen value analyses, for two cases: -!! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix -!! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system -SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) - INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system - REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix - REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix - INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues - LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present - REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors - REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) - - ! LOCALS - REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) - REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) - REAL(ReKi) :: Om2 - INTEGER(IntKi) :: N, i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = '' - - ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi - if (present(bDOF)) then - ! Remove unwanted DOFs - call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return - else - N=size(K,1) - CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - K_LaKi = real( K, LaKi ) - M_LaKi = real( M, LaKi ) - endif - N=size(K_LaKi,1) - - ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - if ( NOmega > nDOF ) then - CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') - CALL CleanupEigen() - return - end if - - - ! --- Eigenvalue analysis - CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; - - ! --- Setting up Phi, and type conversion - do i = 1, NOmega - Om2 = real(Omega2_LaKi(i), ReKi) - if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics - Omega(i)=0.0_ReKi - elseif (Om2>0) then - Omega(i)=sqrt(Om2) ! was getting floating invalid - else - print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 - Omega(i)= 0.0_ReKi - endif - enddo - if (present(bDOF)) then - ! Insert 0s where bDOF was false - CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return - else - EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors - endif - CALL CleanupEigen() - return -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUpEigen() - END FUNCTION Failed - - SUBROUTINE CleanupEigen() - IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) - IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) - IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) - IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) - END SUBROUTINE CleanupEigen - -END SUBROUTINE EigenSolveWrap - -!> Returns a list of boolean which are true if a DOF is not part of a fixed BC -SUBROUTINE SelectNonFixedDOF(BCs, bDOF, ErrStat, ErrMsg ) - INTEGER(IntKi), INTENT( IN) :: BCs(:,:) ! nx2 array, columns: iDOF, BC_type - LOGICAL, INTENT( OUT) :: bDOF(:) ! Mask, False for DOF that are Constraints BC DOF - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - INTEGER :: iBC, iDOF - ErrStat = ErrID_None - ErrMsg = '' - ! Setting array of DOF, true if we keep them - bDOF(:)=.True. - do iBC = 1, size(BCs,1) !Cycle on reaction DOFs - if (BCs(iBC, 2) == idBC_Fixed) then - iDOF = BCs(iBC,1) - if (iDOF>size(bDOF)) then - ErrMsg='Error setting boundary condition, DOF index too large: '//trim(Num2LStr(iDOF)) - ErrStat=ErrID_Fatal; - return - endif - bDOF(iDOF) = .False. ! Eliminate this one - end if - end do -END SUBROUTINE SelectNonFixedDOF +END SUBROUTINE SD_Craig_Bampton !------------------------------------------------------------------------------------------------------ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) + use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) @@ -2218,7 +1921,6 @@ END FUNCTION Failed END SUBROUTINE SetParameters !------------------------------------------------------------------------------------------------------ - !> Allocate parameter arrays, based on the dimensions already set in the parameter data type. SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters @@ -2646,7 +2348,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! NOTE: we don't check for singularities/rigig body modes here CALL WrScr(' Calculating Full System Modes (for summary file output)') CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return - call SelectNonFixedDOF(Init%BCs, bDOF, ErrStat2, ErrMsg2); if(Failed()) return + bDOF(:) = .true. + bDOF(p%ID__F) = .false. nOmega = count(bDOF) CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2); if(Failed()) return From 8107c4effb0cc8b0b44077067e7eae440210201e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 4 May 2020 21:14:16 -0600 Subject: [PATCH 196/377] FlexSub: Guyan reduction to output Equivalent Mass --- modules/subdyn/src/SubDyn.f90 | 114 ++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 20 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 4e466610a..a349518cf 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1764,6 +1764,78 @@ subroutine applyConstr(CBParams, FGR) end subroutine applyConstr END SUBROUTINE SD_Craig_Bampton + +!> Extract rigid body mass without SSI +!! NOTE: performs a Guyan reduction +SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) + type(SD_InitType), intent(inout) :: Init ! NOTE: Mass and Stiffness are modified but then set back to original + type(SD_ParameterType), intent(in ) :: p ! Parameters + real(ReKi), allocatable, intent(out) :: MBB(:,:) !< MBB + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< error message if errstat /= errid_none + ! + integer(IntKi) :: nM, nR, nL, nM_out + real(ReKi), allocatable :: MRR(:, :) + real(ReKi), allocatable :: MLL(:, :) + real(ReKi), allocatable :: MRL(:, :) + real(ReKi), allocatable :: KRR(:, :) + real(ReKi), allocatable :: KLL(:, :) + real(ReKi), allocatable :: KRL(:, :) + real(ReKi), allocatable :: MBM(:, :) + real(ReKi), allocatable :: KBB(:, :) + real(ReKi), allocatable :: PhiL(:, :) + real(ReKi), allocatable :: PhiR(:, :) + real(ReKi), allocatable :: OmegaL(:) + character(*), parameter :: RoutineName = 'SD_Guyan_RigidBodyMass' + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! --- Remove SSI from Mass and stiffness matrix + CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.True.); + + ! --- Break system + nR = p%nDOFR__ + nL = p%nDOF__L + CALL AllocAry( MRR, p%nDOFR__, p%nDOFR__, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( MLL, p%nDOF__L, p%nDOF__L, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( MRL, p%nDOFR__, p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( KRR, p%nDOFR__, p%nDOFR__, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( KLL, p%nDOF__L, p%nDOF__L, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( KRL, p%nDOFR__, p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + CALL BreakSysMtrx(Init%M, Init%K, p%IDR__, p%ID__L, p%nDOFR__, p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL) + + ! --- Perform CB reduction to get MBB + nM = 0 + nM_out = 0 ! TODO nM_out is not well implemented + if(allocated(MBB)) deallocate(MBB) + CALL AllocAry( MBB, nR, nR, 'MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( MBM, nR, nM, 'MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( KBB, nR, nR, 'KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( PhiL, nL, nL, 'PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( PhiR, nL, nR, 'PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( OmegaL, nL, 'OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL CraigBamptonReduction(MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_out, & ! < inputs + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) ! <- outputs + + if(allocated(MRR) ) deallocate(MRR) + if(allocated(MLL) ) deallocate(MLL) + if(allocated(MRL) ) deallocate(MRL) + if(allocated(KRR) ) deallocate(KRR) + if(allocated(KLL) ) deallocate(KLL) + if(allocated(KRL) ) deallocate(KRL) + if(allocated(KBB) ) deallocate(KBB) + if(allocated(MBM) ) deallocate(MBM) + if(allocated(PhiR) ) deallocate(PhiR) + if(allocated(PhiL) ) deallocate(PhiL) + if(allocated(OmegaL)) deallocate(OmegaL) + + ! --- Insert SSI from Mass and stiffness matrix again + CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.False.); +END SUBROUTINE SD_Guyan_RigidBodyMass + + + !------------------------------------------------------------------------------------------------------ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf @@ -2311,7 +2383,7 @@ END SUBROUTINE ConstructUFL !------------------------------------------------------------------------------------------------------ !> Output the summary file SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) - TYPE(SD_InitType), INTENT(IN) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file + TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use @@ -2326,7 +2398,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) INTEGER(IntKi) :: iNode1, iNode2 ! Node indices INTEGER(IntKi) :: mType ! Member Type Real(ReKi) :: mMass, mLength ! Member mass and length - REAL(ReKi) :: MRB(6,6) !REDUCED SYSTEM Kmatrix, equivalent mass matrix + REAL(ReKi) :: MRB(6,6) ! REDUCED SYSTEM Kmatrix, equivalent mass matrix + REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' @@ -2529,28 +2602,29 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%MBB(i,j), j = 1, 6) ENDDO - ! Set TI2, transformation matrix from R DOFs to SubDyn Origin - ! TODO TODO TODO + ! Set TI2, transformation matrix from R DOFs to SubDyn Origin + CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return + ! Compute Rigid body mass matrix (without Soil, and using both Interface and Reactions nodes as leader DOF) if (p%nDOFR__/=p%nDOF__Rb) then - WRITE(UnSum, '(A)') 'TODO, Equivalent mass matrix not available yet' + call SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat2, ErrMsg2); if(Failed()) return + MRB=matmul(TRANSPOSE(TI2),matmul(MBB,TI2)) !Equivalent mass matrix of the rigid body else - CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' - WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') 'MRB' - WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) - DO i=1,6 - WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) - ENDDO - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) - WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) - deallocate(TI2) endif + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' + WRITE(UnSum, '(A)') SubSectionDivide + WRITE(UnSum, '(A)') 'MRB' + WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) + DO i=1,6 + WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) + ENDDO + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + deallocate(TI2) #ifdef SD_SUMMARY_DEBUG From 8fbd4c6c9335760be76f15d79e7b9725cbabd008 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 4 May 2020 22:39:31 -0600 Subject: [PATCH 197/377] FlexSub: implemented generic Craig Bampton function --- modules/subdyn/src/FEM.f90 | 164 ++++++++++++++++++++++-------- modules/subdyn/src/SubDyn.f90 | 182 +++++++++++++--------------------- 2 files changed, 190 insertions(+), 156 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 7967b1950..dc87f5242 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -257,6 +257,93 @@ SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, endif END SUBROUTINE BreakSysMtrx +!------------------------------------------------------------------------------------------------------ +!> Performs Craig-Bampton reduction of M and K matrices and optional Force vector +!! TODO: (Damping optional) +!! Convention is: +!! "R": leader DOF -> "B": reduced leader DOF +!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) +!! NOTE: +!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned +!! - Possibility to get more CB modes using the input nM_Out>nM +!! +!! NOTE: generic code +SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM) + REAL(ReKi), INTENT(IN ) :: MM(:, :) !< Mass matrix + REAL(ReKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix + INTEGER(IntKi), INTENT(IN ) :: nR + INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs + INTEGER(IntKi), INTENT(IN ) :: nL + INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs + INTEGER(IntKi), INTENT(IN ) :: nM !< Number of CB modes + INTEGER(IntKi), INTENT(IN ) :: nM_Out !< Number of modes returned for PhiL & OmegaL + REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) !< Reduced Guyan Mass Matrix + REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) !< Reduced Guyan Stiffness matrix + REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) !< Cross term + REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_out) !< Craig-Bampton modes + REAL(ReKi), INTENT( OUT) :: OmegaL(nM_out) !< Eigenvalues + REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector (typically a constant force, like gravity) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) !< Force vector partitioned for R DOFs (TODO remove me) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' + ! Partitioned variables + real(ReKi), allocatable :: MRR(:, :) + real(ReKi), allocatable :: MLL(:, :) + real(ReKi), allocatable :: MRL(:, :) + real(ReKi), allocatable :: KRR(:, :) + real(ReKi), allocatable :: KLL(:, :) + real(ReKi), allocatable :: KRL(:, :) + ! --- Break system + CALL AllocAry(MRR, nR, nR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(MLL, nL, nL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(MRL, nR, nL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KRR, nR, nR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KLL, nL, nL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KRL, nR, nL, 'matrix KRL', ErrStat2, ErrMsg2 ); if(Failed()) return + if (present(FG).and.present(FGR).and.present(FGL)) then + call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) + else + call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL) + endif + ! --- CB reduction + call CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& !< Inputs + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) !< Outputs + if(Failed()) return + + ! --- Reduction of force if provided + if (present(FG).and.present(FGR).and.present(FGL)) then + if (present(FGM)) then + FGB = FGR + matmul( transpose(PhiR), FGL) + endif + if (present(FGB)) then + FGM = matmul( FGL, PhiL(:,1:nM) ) != matmul( transpose(PhiM), FGL ) because FGL is 1-D + endif + endif + call CleanUp() + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) + IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) + IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) + IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) + IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) + IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) + end subroutine +END SUBROUTINE CraigBamptonReduction + !------------------------------------------------------------------------------------------------------ !> Performs Craig-Bampton reduction based on partitioned matrices M and K !! Convention is: @@ -264,41 +351,39 @@ END SUBROUTINE BreakSysMtrx !! "L": interior DOF -> "M": reduced interior DOF (CB-modes) !! NOTE: !! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned -!! - Possibility to get all the CB modes using the input nM_Out>nM +!! - Possibility to get more CB modes using the input nM_Out>nM (e.g. for static improvement) !! !! NOTE: generic code -SUBROUTINE CraigBamptonReduction( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& +SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf INTEGER(IntKi), INTENT( in) :: nR INTEGER(IntKi), INTENT( in) :: nL INTEGER(IntKi), INTENT( in) :: nM_Out INTEGER(IntKi), INTENT( in) :: nM - REAL(ReKi), INTENT( IN) :: MRR( nR, nR) + REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Paritioned matrices REAL(ReKi), INTENT( IN) :: MLL( nL, nL) REAL(ReKi), INTENT( IN) :: MRL( nR, nL) REAL(ReKi), INTENT( IN) :: KRR( nR, nR) REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) REAL(ReKi), INTENT( IN) :: KRL( nR, nL) - REAL(ReKi), INTENT(INOUT) :: MBB( nR, nR) - REAL(ReKi), INTENT(INOUT) :: MBM( nR, nM) - REAL(ReKi), INTENT(INOUT) :: KBB( nR, nR) - REAL(ReKi), INTENT(INOUT) :: PhiR(nL, nR) ! Guyan Modes - REAL(ReKi), INTENT(INOUT) :: PhiL(nL, nL) ! Craig-Bampton modes TODO nM_out? - REAL(ReKi), INTENT(INOUT) :: OmegaL(nL) ! Eigenvalues TODO nM_out? - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) + REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) + REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) + REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes + REAL(ReKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! LOCAL VARIABLES - REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(p%nDOFR,p%nDOFL) = transpose of PhiR * MLL (temporary storage) - INTEGER :: I !, lwork !counter, and varibales for inversion routines - INTEGER :: ipiv(nL) !the integer vector ipvt of length min(m,n), containing the pivot indices. - !Returned as: a one-dimensional array of (at least) length min(m,n), containing integers, - !where 1 <= less than or equal to ipvt(i) <= less than or equal to m. - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'CBMatrix' + REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(nR,nL) = transpose of PhiR * MLL (temporary storage) + INTEGER :: I !counter + INTEGER :: ipiv(nL) ! length min(m,n) (See LAPACK documentation) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' ErrStat = ErrID_None ErrMsg = '' @@ -306,47 +391,40 @@ SUBROUTINE CraigBamptonReduction( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_O ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; if(Failed()) return; endif + if (nM_out 0 ) THEN ! Only time this wouldn't happen is if no modes retained and no static improvement... + ! --- Compute CB modes (PhiL) and eigenvalues (OmegaL) + IF ( nM > 0 ) THEN ! bCheckSingularity = True CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return - ! --- Normalize PhiL ! bjj: break up this equation to avoid as many temporary variables on the stack ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) - CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return - CALL AllocAry( MU , nL , nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , nM_out, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL) Temp = MATMUL( MU, MLL ) - MU = MATMUL( Temp, PhiL ) + MU(1:nM_Out,1:nM_Out) = MATMUL( Temp, PhiL ) DEALLOCATE(Temp) ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) DO I = 1, nM_out PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) ENDDO - DO I=nM_out+1, nL !loop done only if .not. p%SttcSolve .and. nDOFM < p%nDOFL (and actually, in that case, these values aren't used anywhere anyway) - PhiL(:,I) = 0.0_ReKi - OmegaL(I) = 0.0_ReKi - END DO DEALLOCATE(MU) END IF - !.................................................... - ! Set PhiR from Eq. 3: - !.................................................... - ! now factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) + ! --- Compute Guyan Modes (PhiR) + ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return - !.................................................... - ! Set MBB, MBM, and KBB from Eq. 4: - !.................................................... + ! --- Set MBB, MBM, and KBB from Eq. 4: CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return PhiR_T_MLL = TRANSPOSE(PhiR) @@ -360,15 +438,15 @@ SUBROUTINE CraigBamptonReduction( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_O MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM ENDIF - DEALLOCATE( PhiR_T_MLL ) KBB = MATMUL(KRL, PhiR) KBB = KBB + KRR + call CleanUp() CONTAINS logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction') + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction_FromPartition') Failed = ErrStat >= AbortErrLev if (Failed) call CleanUp() end function Failed @@ -378,7 +456,7 @@ subroutine CleanUp() if (allocated(Temp )) DEALLOCATE(Temp ) if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) end subroutine -END SUBROUTINE CraigBamptonReduction +END SUBROUTINE CraigBamptonReduction_FromPartition !------------------------------------------------------------------------------------------------------ !> Wrapper function for eigen value analyses, for two cases: diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a349518cf..9924d32e7 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1577,38 +1577,37 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg END SUBROUTINE SD_AM2 !------------------------------------------------------------------------------------------------------ -!> Perform Craig Bampton reduction and set parameters needed for States and Ouputs equations -SUBROUTINE SD_Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) +!> Perform Craig Bampton (CB) reduction and set parameters needed for States and Ouputs equations +!! Sets the following values, as documented in the SubDyn Theory Guide: +!! CB%OmegaL (omega) and CB%PhiL from Eq. 2 +!! p%PhiL_T and p%PhiLInvOmgL2 for static improvement +!! CB%PhiR from Eq. 3 +!! CB%MBB, CB%MBM, and CB%KBB from Eq. 4. +SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine TYPE(SD_ParameterType),INTENT(INOUT),target::p ! Parameters - TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams ! CB parameters that will be passed out for summary file use + TYPE(CB_MatArrays), INTENT(INOUT) :: CB ! CB parameters that will be passed out for summary file use INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(ReKi), ALLOCATABLE :: MRR(:, :) - REAL(ReKi), ALLOCATABLE :: MLL(:, :) - REAL(ReKi), ALLOCATABLE :: MRL(:, :) - REAL(ReKi), ALLOCATABLE :: KRR(:, :) - REAL(ReKi), ALLOCATABLE :: KLL(:, :) - REAL(ReKi), ALLOCATABLE :: KRL(:, :) - REAL(ReKi), ALLOCATABLE :: FGR(:) - REAL(ReKi), ALLOCATABLE :: FGL(:) + REAL(ReKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array - INTEGER(IntKi) :: nM_Out, i + INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) + INTEGER(IntKi) :: nL, nM, nM_out INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility + character(*), parameter :: RoutineName = 'SD_Craig_Bampton' ErrStat = ErrID_None ErrMsg = "" IF(Init%CBMod) THEN ! C-B reduction ! check number of internal modes IF(p%nDOFM > p%nDOFL_L) THEN - CALL SetErrStat(ErrID_Fatal,'Number of internal modes is larger than number of internal DOFs. ',ErrStat,ErrMsg,'Craig_Bampton') - CALL CleanupCB() - RETURN + CALL Fatal('Number of internal modes is larger than number of internal DOFs.') + return ENDIF ELSE ! full FEM p%nDOFM = p%nDOFL_L @@ -1622,9 +1621,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) - CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - ! Temporary backward compatibility BC_Before_CB=p%nDOFC_L>0 ! if we have some free C DOFs if(BC_Before_CB) then @@ -1636,62 +1632,45 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CBparams, ErrStat, ErrMsg) nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system IDR => p%IDR__ endif - - ! NOTE: these below are either "R" or "Rb" matrices - CALL AllocAry( MRR, nR , nR , 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MLL, p%nDOF__L, p%nDOF__L, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( MRL, nR , p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRR, nR , nR , 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KLL, p%nDOF__L, p%nDOF__L, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( KRL, nR , p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGL, p%nDOF__L, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( FGR, nR , 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - - CALL AllocAry( CBparams%MBB, nR , nR , 'CBparams%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%MBM, nR , p%nDOFM , 'CBparams%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%KBB, nR , nR , 'CBparams%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiL, p%nDOF__L, p%nDOF__L, 'CBparams%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%PhiR, p%nDOF__L, nR , 'CBparams%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - CALL AllocAry( CBparams%OmegaL, p%nDOF__L, 'CBparams%OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - - ! Set MRR, MLL, MRL, KRR, KLL, KRL, FGR, FGL, based on M, K, FG and indices IDR and IDL - ! NOTE: generic FEM code - CALL BreakSysMtrx(Init%M, Init%K, IDR , p%ID__L, nR , p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL, Init%FG, FGR, FGL) - - !................................ - ! Sets the following values, as documented in the SubDyn Theory Guide: - ! CBparams%OmegaL (omega) and CBparams%PhiL from Eq. 2 - ! p%PhiL_T and p%PhiLInvOmgL2 for static improvement - ! CBparams%PhiR from Eq. 3 - ! CBparams%MBB, CBparams%MBM, and CBparams%KBB from Eq. 4. - !................................ - CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') + ! IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ELSE nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes ENDIF - CALL CraigBamptonReduction(MRR, MLL, MRL, KRR, KLL, KRL, nR, p%nDOF__L, p%nDOFM, nM_Out, & ! < inputs - CBparams%MBB, CBparams%MBM, CBparams%KBB, CBparams%PhiL, CBparams%PhiR, CBparams%OmegaL, ErrStat2, ErrMsg2) ! <- outputs + nL = p%nDOF__L + nM = p%nDOFM + + CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') + CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGR, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGB, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%PhiL, nL, nM_Out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%OmegaL, nM_Out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& + Init%FG, FGR, FGL, FGB, FGM) if(Failed()) return ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement IF (p%SttcSolve) THEN - p%PhiL_T=TRANSPOSE(CBparams%PhiL) !transpose of PhiL for static improvement + p%PhiL_T=TRANSPOSE(CB%PhiL) !transpose of PhiL for static improvement DO I = 1, nM_Out - p%PhiLInvOmgL2(:,I) = CBparams%PhiL(:,I)* (1./CBparams%OmegaL(I)**2) + p%PhiLInvOmgL2(:,I) = CB%PhiL(:,I)* (1./CB%OmegaL(I)**2) ENDDO END IF - ! TODO TODO TODO DAMPING MATRIX - - if(.not.BC_Before_CB) then ! We apply the BC now, removing unwanted DOFs - call applyConstr(CBParams, FGR) + call applyConstr(CB, FGB) endif - CALL SetParameters(Init, p, CBparams%MBB, CBparams%MBM, CBparams%KBB, FGR, CBparams%PhiR, CBparams%OmegaL, FGL, CBparams%PhiL, ErrStat2, ErrMsg2) + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, CB%PhiR, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1711,36 +1690,31 @@ logical function Failed() end function Failed subroutine CleanUpCB() - IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) - IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) - IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) - IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) - IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) - IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) - IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) + IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) + IF(ALLOCATED(FGM) ) DEALLOCATE(FGM) + IF(ALLOCATED(FGB) ) DEALLOCATE(FGB) end subroutine CleanUpCB !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system !! NOTE: PhiL and OmegaL are not modified - subroutine applyConstr(CBParams, FGR) + subroutine applyConstr(CBParams, FGB) TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGR(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) REAL(ReKi), ALLOCATABLE :: MBBb(:, :) REAL(ReKi), ALLOCATABLE :: MBMb(:, :) REAL(ReKi), ALLOCATABLE :: KBBb(:, :) REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: FGRb(:) + REAL(ReKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" - ! TODO TODO TODO this is wrong CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); - CALL AllocAry( FGRb, p%nDOF__Rb, 'array FGRb', ErrStat2, ErrMsg2 ); + CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); !................................ - ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGR to - ! MBBb, MBMb, KBBb, PHiRb, FGRb + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to + ! MBBb, MBMb, KBBb, PHiRb, FGBb ! (throw out rows/columns of first matrices to create second matrices) !................................ ! TODO avoid this all together @@ -1749,18 +1723,17 @@ subroutine applyConstr(CBParams, FGR) IF (p%nDOFM > 0) THEN MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) END IF - FGRb = FGR (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) + FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) deallocate(CBparams%MBB) deallocate(CBparams%KBB) deallocate(CBparams%MBM) deallocate(CBparams%PhiR) - deallocate(FGR) call move_alloc(MBBb, CBparams%MBB) call move_alloc(KBBb, CBparams%KBB) call move_alloc(MBMb, CBparams%MBM) call move_alloc(PhiRb, CBparams%PhiR) - call move_alloc(FGRb, FGR) + call move_alloc(FGBb, FGB) end subroutine applyConstr END SUBROUTINE SD_Craig_Bampton @@ -1773,14 +1746,7 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) real(ReKi), allocatable, intent(out) :: MBB(:,:) !< MBB integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< error message if errstat /= errid_none - ! integer(IntKi) :: nM, nR, nL, nM_out - real(ReKi), allocatable :: MRR(:, :) - real(ReKi), allocatable :: MLL(:, :) - real(ReKi), allocatable :: MRL(:, :) - real(ReKi), allocatable :: KRR(:, :) - real(ReKi), allocatable :: KLL(:, :) - real(ReKi), allocatable :: KRL(:, :) real(ReKi), allocatable :: MBM(:, :) real(ReKi), allocatable :: KBB(:, :) real(ReKi), allocatable :: PhiL(:, :) @@ -1793,19 +1759,9 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) ! --- Remove SSI from Mass and stiffness matrix CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.True.); - ! --- Break system + ! --- Perform CB reduction to get MBB nR = p%nDOFR__ nL = p%nDOF__L - CALL AllocAry( MRR, p%nDOFR__, p%nDOFR__, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( MLL, p%nDOF__L, p%nDOF__L, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( MRL, p%nDOFR__, p%nDOF__L, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( KRR, p%nDOFR__, p%nDOFR__, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( KLL, p%nDOF__L, p%nDOF__L, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( KRL, p%nDOFR__, p%nDOF__L, 'matrix KRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - - CALL BreakSysMtrx(Init%M, Init%K, p%IDR__, p%ID__L, p%nDOFR__, p%nDOF__L, MRR, MLL, MRL, KRR, KLL, KRL) - - ! --- Perform CB reduction to get MBB nM = 0 nM_out = 0 ! TODO nM_out is not well implemented if(allocated(MBB)) deallocate(MBB) @@ -1814,16 +1770,11 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) CALL AllocAry( KBB, nR, nR, 'KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( PhiL, nL, nL, 'PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( PhiR, nL, nR, 'PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( OmegaL, nL, 'OmegaL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL CraigBamptonReduction(MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_out, & ! < inputs - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) ! <- outputs - - if(allocated(MRR) ) deallocate(MRR) - if(allocated(MLL) ) deallocate(MLL) - if(allocated(MRL) ) deallocate(MRL) - if(allocated(KRR) ) deallocate(KRR) - if(allocated(KLL) ) deallocate(KLL) - if(allocated(KRL) ) deallocate(KRL) + CALL AllocAry( OmegaL, nL, 'OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL CraigBamptonReduction(Init%M, Init%K, p%IDR__, nR, p%ID__L, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) + if(Failed()) return + if(allocated(KBB) ) deallocate(KBB) if(allocated(MBM) ) deallocate(MBM) if(allocated(PhiR) ) deallocate(PhiR) @@ -1831,13 +1782,17 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) if(allocated(OmegaL)) deallocate(OmegaL) ! --- Insert SSI from Mass and stiffness matrix again - CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.False.); + CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed END SUBROUTINE SD_Guyan_RigidBodyMass - - !------------------------------------------------------------------------------------------------------ -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, PhiL, ErrStat, ErrMsg) +!> Set parameters to compute state and output equations +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters @@ -1847,8 +1802,9 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, p%nDOF__L) REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOF__L) - REAL(ReKi), INTENT(IN ) :: FGRb(p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: FGB(p%nDOF__Rb) REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) + REAL(ReKi), INTENT(IN ) :: FGM(p%nDOFM) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -1868,7 +1824,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph if(Failed()) return endif - + ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) + CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return TI_transpose = TRANSPOSE(p%TI) ! Store FGL for later processes @@ -1901,9 +1858,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! B_23, B_24 !p%PhiM_T = TRANSPOSE( p%PhiM ) - ! FX - ! p%FX = MATMUL( p%PhiM_T, FGL ) != MATMUL( TRANSPOSE(PhiM), FGL ) - p%FX = MATMUL( FGL, p%PhiM ) != MATMUL( TRANSPOSE(PhiM), FGL ) because FGL is 1-D + ! FX = matmul( transpose(PhiM), FGL ) (output of CraigBamptonReduction) + p%FX = FGM ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped @@ -1926,7 +1882,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph ! FY (with retained modes) p%FY = MATMUL( p%MBM, p%FX ) & - - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) + - MATMUL( TI_transpose, FGB ) ! C2_21, C2_42 ! C2_61, C2_62 @@ -1980,7 +1936,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, FGRb, PhiRb, OmegaL, FGL, Ph p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) ! FY (with 0 retained modes) - p%FY = - MATMUL( TI_transpose, ( FGRb + MATMUL( TRANSPOSE(PhiRb), FGL) ) ) + p%FY = - MATMUL( TI_transpose, FGB ) END IF From 3aac1e87fe9c8850375c48109826db6927f10fac Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 4 May 2020 23:14:17 -0600 Subject: [PATCH 198/377] FlexSub: temporarily keeping constrained modes for Summary file --- modules/subdyn/src/SubDyn.f90 | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 9924d32e7..80b43b145 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1591,6 +1591,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables REAL(ReKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) + REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) @@ -1665,12 +1666,15 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) ENDDO END IF + CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if(.not.BC_Before_CB) then ! We apply the BC now, removing unwanted DOFs - call applyConstr(CB, FGB) + call applyConstr(CB, FGB, PhiRb) + else + PhiRb=CB%PhiR ! Remove me in the future endif - - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, CB%PhiR, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1694,24 +1698,26 @@ subroutine CleanUpCB() IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) IF(ALLOCATED(FGM) ) DEALLOCATE(FGM) IF(ALLOCATED(FGB) ) DEALLOCATE(FGB) + IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) end subroutine CleanUpCB !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system !! NOTE: PhiL and OmegaL are not modified - subroutine applyConstr(CBParams, FGB) + subroutine applyConstr(CBParams, FGB, PhiRb) TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) + !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(ReKi), ALLOCATABLE :: MBBb(:, :) REAL(ReKi), ALLOCATABLE :: MBMb(:, :) REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(ReKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); + !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); !................................ ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to ! MBBb, MBMb, KBBb, PHiRb, FGBb @@ -1728,12 +1734,12 @@ subroutine applyConstr(CBParams, FGB) deallocate(CBparams%MBB) deallocate(CBparams%KBB) deallocate(CBparams%MBM) - deallocate(CBparams%PhiR) + !deallocate(CBparams%PhiR) call move_alloc(MBBb, CBparams%MBB) call move_alloc(KBBb, CBparams%KBB) call move_alloc(MBMb, CBparams%MBM) - call move_alloc(PhiRb, CBparams%PhiR) call move_alloc(FGBb, FGB) + !call move_alloc(PhiRb, CBparams%PhiR) end subroutine applyConstr END SUBROUTINE SD_Craig_Bampton From c03308fa1e706b957c02fe0e0309474de9c6991d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 5 May 2020 15:21:24 -0600 Subject: [PATCH 199/377] FlexSub: boundary conditions are now applied before CB reductions (in practice, DOF are not included) --- modules/subdyn/src/SubDyn.f90 | 85 ++++++----------------------------- 1 file changed, 13 insertions(+), 72 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 80b43b145..622f47caf 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1596,10 +1596,8 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) INTEGER(IntKi) :: nL, nM, nM_out - INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility character(*), parameter :: RoutineName = 'SD_Craig_Bampton' ErrStat = ErrID_None ErrMsg = "" @@ -1622,18 +1620,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - ! Temporary backward compatibility - BC_Before_CB=p%nDOFC_L>0 ! if we have some free C DOFs - if(BC_Before_CB) then - print*,' > Boundary conditions will be applied before Craig-Bampton (New)' - nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction - IDR => p%ID__Rb - else - print*,' > Craig-Bampton will be applied before boundary conditions (Legacy)' - nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system - IDR => p%IDR__ - endif - ! IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ELSE @@ -1641,6 +1627,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) ENDIF nL = p%nDOF__L nM = p%nDOFM + nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1654,7 +1641,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%OmegaL, nM_Out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& + CALL CraigBamptonReduction(Init%M, Init%K, p%ID__Rb, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& Init%FG, FGR, FGL, FGB, FGM) if(Failed()) return @@ -1667,12 +1654,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) END IF CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if(.not.BC_Before_CB) then - ! We apply the BC now, removing unwanted DOFs - call applyConstr(CB, FGB, PhiRb) - else - PhiRb=CB%PhiR ! Remove me in the future - endif + PhiRb=CB%PhiR ! Remove me in the future ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') @@ -1701,47 +1683,6 @@ subroutine CleanUpCB() IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) end subroutine CleanUpCB - !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system - !! NOTE: PhiL and OmegaL are not modified - subroutine applyConstr(CBParams, FGB, PhiRb) - TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) - !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: MBBb(:, :) - REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: FGBb(:) - ! "b" stands for "bar" - CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); - CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); - !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); - !................................ - ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to - ! MBBb, MBMb, KBBb, PHiRb, FGBb - ! (throw out rows/columns of first matrices to create second matrices) - !................................ - ! TODO avoid this all together - MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - IF (p%nDOFM > 0) THEN - MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) - END IF - FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) - PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - deallocate(CBparams%MBB) - deallocate(CBparams%KBB) - deallocate(CBparams%MBM) - !deallocate(CBparams%PhiR) - call move_alloc(MBBb, CBparams%MBB) - call move_alloc(KBBb, CBparams%KBB) - call move_alloc(MBMb, CBparams%MBM) - call move_alloc(FGBb, FGB) - !call move_alloc(PhiRb, CBparams%PhiR) - end subroutine applyConstr - END SUBROUTINE SD_Craig_Bampton !> Extract rigid body mass without SSI @@ -1765,12 +1706,12 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) ! --- Remove SSI from Mass and stiffness matrix CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.True.); - ! --- Perform CB reduction to get MBB - nR = p%nDOFR__ - nL = p%nDOF__L - nM = 0 - nM_out = 0 ! TODO nM_out is not well implemented - if(allocated(MBB)) deallocate(MBB) + ! --- Perform Guyan reduction to get MBB + nR = p%nDOFR__ ! Using interface + reaction nodes + nL = p%nDOF__L + nM = 0 ! No CB modes (Guyan) + nM_out = 0 + if(allocated(MBB)) deallocate(MBB) CALL AllocAry( MBB, nR, nR, 'MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( MBM, nR, nM, 'MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( KBB, nR, nR, 'KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2312,7 +2253,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%nDOFL_L) + real(ReKi) , intent(out) :: UFL(p%nDOF__L) integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes integer :: nMembers real(ReKi), parameter :: myNaN = -9999998.989_ReKi @@ -2338,7 +2279,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) ! --- Reduced vector of external force m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL=0 - UFL= m%Fext_red(p%IDL_L) + UFL= m%Fext_red(p%ID__L) END SUBROUTINE ConstructUFL @@ -2533,7 +2474,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (no constraint applied)' + WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide IF (p%nDOFM > 0) THEN @@ -2623,7 +2564,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Additional CB Matrices (MBB,MBM,KBB) (no constraint applied)' + WRITE(UnSum, '(A)') 'Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide CALL WrMatrix( CBparams%MBB, UnSum, 'e15.6', 'MBB' ) From ac7d02ca303da6a4de7ed23b71e173c16fcaed56 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 May 2020 12:02:54 -0600 Subject: [PATCH 200/377] FlexSub: Deleting makefile --- Makefile | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index cb07b2b06..000000000 --- a/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -MAKE=make --no-print-directory -MAKE_ARGS=VERBOSE=1 -CMAKE_ARGS=-DCMAKE_BUILD_TYPE=Debug -DDOUBLE_PRECISION:BOOL=OFF -DGENERATE_TYPES:BOOL=ON -suffix=-single-db -ifeq ($(OS),Windows_NT) - OS=Windows - suffix=-nmake$(suffix) - CMAKE_ARGS=$(CMAKE_ARGS) -G"NMake Makefiles" - MAKE=nmake - RMDIR=rmdir /S /Q - LIBEXT='.dll' - EXEEXT='.exe' -else - OS=$(shell uname -s) - ifeq ($(OS),Linux) - # ISSUE WITH CMAKE PICKING UP F95 TODO - FC=/usr/bin/gfortran -# FC=/usr/bin/gfortran-7 - LIBEXT='.so' - LIBPRE='lib' - else ifeq ($(OS),Darwin) - LIBEXT='.dylib' - endif - RMDIR=rm -rf -endif -BUILD_DIR=build$(suffix) -TEST_DIR=../tcf-test - - -all: compile copy test - - -$(BUILD_DIR): - @echo "------------------------------------------------------------" - mkdir $(BUILD_DIR) - -compile: $(BUILD_DIR) - @echo "------------------------------------------------------------" - cd $(BUILD_DIR) && cmake $(CMAKE_ARGS) .. && $(MAKE) $(MAKE_ARGS) - -clean: - cd $(BUILD_DIR) && $(MAKE) clean - -copy: - cp $(BUILD_DIR)/glue-codes/openfast/openfast$(EXEEXT) $(TEST_DIR) - -test: - cd $(TEST_DIR) && $(MAKE) - From 72f942f1ec2b15a305f29d6bb685e338f3a6c79e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 May 2020 16:34:26 -0600 Subject: [PATCH 201/377] FlexSub: bug fix, typo in pretension cable stiffness --- modules/subdyn/src/FEM.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index dc87f5242..0ae3d6c43 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -895,7 +895,7 @@ SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) Eps0 = T0/(E*A) L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 - EAL0 = E*A*L0 + EAL0 = E*A/L0 EE = EAL0* Eps0/(1+Eps0) K(1:12,1:12)=0 From 299c1b7b1563b1354e7e03648690d17295de1f6f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 May 2020 18:23:45 -0600 Subject: [PATCH 202/377] FlexSub: fix static solve with 0 modes --- modules/subdyn/src/FEM.f90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 0ae3d6c43..890e40ca7 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -397,7 +397,7 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR endif ! --- Compute CB modes (PhiL) and eigenvalues (OmegaL) - IF ( nM > 0 ) THEN + if ( nM_out > 0 ) then ! bCheckSingularity = True CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return ! --- Normalize PhiL @@ -414,7 +414,10 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) ENDDO DEALLOCATE(MU) - END IF + else + PhiL = 0.0_ReKi + OmegaL = 0.0_ReKi + end if ! --- Compute Guyan Modes (PhiR) ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) From 8b2b2dc963817e09e48ae81443474c528564c74b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 May 2020 19:00:26 -0600 Subject: [PATCH 203/377] FlexSub: CB reduction with no internal DOF --- modules/subdyn/src/FEM.f90 | 55 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 890e40ca7..a9dc6bcf0 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -418,33 +418,40 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR PhiL = 0.0_ReKi OmegaL = 0.0_ReKi end if + + if (nL>0) then + ! --- Compute Guyan Modes (PhiR) + ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) + ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** + CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Compute Guyan Modes (PhiR) - ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) - ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** - CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return - - PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return - - ! --- Set MBB, MBM, and KBB from Eq. 4: - CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) + CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return - PhiR_T_MLL = TRANSPOSE(PhiR) - PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) - MBB = MATMUL(MRL, PhiR) - MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) + ! --- Set MBB, MBM, and KBB from Eq. 4: + CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + + PhiR_T_MLL = TRANSPOSE(PhiR) + PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) + MBB = MATMUL(MRL, PhiR) + MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) + + IF ( nM == 0) THEN + MBM = 0.0_ReKi + ELSE + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM + ENDIF - IF ( nM == 0) THEN - MBM = 0.0_ReKi - ELSE - MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation - MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM - ENDIF - - KBB = MATMUL(KRL, PhiR) - KBB = KBB + KRR - + KBB = MATMUL(KRL, PhiR) + KBB = KBB + KRR + else + PhiR(1:nL,1:nR) = 0.0_ReKi ! Empty + MBM (1:nR,1:nM) = 0.0_ReKi ! Empty + MBB = MRR + KBB = KRR + endif + call CleanUp() CONTAINS From 2b4e6ffa396a830e6ecac8f757a966ddc57fc2f0 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 7 May 2020 19:00:51 -0600 Subject: [PATCH 204/377] FlexSub: cleanup of SubDyn driver --- modules/subdyn/src/SubDyn.f90 | 4 + modules/subdyn/src/SubDyn_Driver.f90 | 721 +++++---------------------- 2 files changed, 139 insertions(+), 586 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 622f47caf..223625d0e 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -804,6 +804,10 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! Extract fields from first line DO I = 1, nColumns bNumeric = is_numeric(StrArray(I), Init%Joints(1,I)) ! Convert from string to float + if (.not.bNumeric) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non numeric character found in Joints line. Problematic line: "'//trim(Line)//'"') + return + endif ENDDO deallocate(StrArray) ! Read remaining lines diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index 83f0b428f..372928e4b 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -77,12 +77,12 @@ PROGRAM TestSubDyn CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. TYPE(SD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program - INTEGER(IntKi) :: UnInp ! Inputs file identifier + INTEGER :: UnIn ! Unit number for the input file + INTEGER :: UnEcho ! The local unit number for this module's echo file INTEGER(IntKi) :: UnSD_Out ! Output file identifier REAL(ReKi), ALLOCATABLE :: SDin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for SubDyn inputs INTEGER(IntKi) :: J ! Generic loop counter REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). - REAL(DbKi) :: maxAngle ! For debugging, see what the largest rotational angle input is for the simulation CHARACTER(10) :: AngleMsg ! For debugging, a string version of the largest rotation input ! Other/Misc variables @@ -97,320 +97,163 @@ PROGRAM TestSubDyn !............................................................................................................................... ! Routines called in initialization !............................................................................................................................... - - + ErrMsg = "" + ErrStat = ErrID_None + UnEcho=-1 + UnIn =-1 - ! Get the current time - + ! Get the current time CALL DATE_AND_TIME ( Values=StrtTime ) ! Let's time the whole simulation CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) PrevClockTime = TimeValues2Seconds( StrtTime ) ! We'll use this time for the SimStats routine TiLstPrn = 0.0_DbKi ! The first value of ZTime, used to write simulation stats to screen (s) - - ! Initialize the NWTC Subroutine Library - + ! Initialize the NWTC Subroutine Library CALL NWTC_Init( ) - ! Display the copyright notice + ! Display the copyright notice CALL DispCopyrightLicense( version%Name ) - ! Obtain OpenFAST git commit hash + ! Obtain OpenFAST git commit hash git_commit = QueryGitVersion() - ! Tell our users what they're running + ! Tell our users what they're running CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) - - - ! Set the abort error level to a fatal error + ! Set the abort error level to a fatal error AbortErrLev = ErrID_Fatal - IF ( command_argument_count() > 1 ) CALL print_help() + IF ( command_argument_count() /= 1 ) then + CALL print_help() + STOP + endif - ! Parse the driver input file and run the simulation based on that file - + ! Parse the driver input file and run the simulation based on that file IF ( command_argument_count() == 1 ) THEN - CALL get_command_argument(1, drvrFilename) - CALL ReadDriverInputFile( drvrFilename, drvrInitInp, ErrStat, ErrMsg ) - IF ( ErrStat /= 0 ) THEN - CALL WrScr( ErrMsg ) - STOP - END IF + + CALL ReadDriverInputFile( drvrFilename, drvrInitInp); InitInData%g = drvrInitInp%Gravity - !InitInData%UseInputFile = .TRUE. InitInData%SDInputFile = drvrInitInp%SDInputFile - InitInData%RootName = drvrInitInp%OutRootName + InitInData%RootName = drvrInitInp%OutRootName InitInData%TP_RefPoint = drvrInitInp%TP_RefPoint InitInData%SubRotateZ = drvrInitInp%SubRotateZ TimeInterval = drvrInitInp%TimeInterval InitInData%WtrDpth = drvrInitInp%WtrDpth - ELSE - ! Called without a driver input file! - CALL WrScr( 'Running SubDyn without a driver file! This is for SubDyn developers only.' ) - ! InitInData%SDInputFile = '..\BeamFEM\IOFiles\TestBeam2.txt' - InitInData%SDInputFile = '..\MergedSubDyn\IOFiles\TestBeam3.txt' - ! InitInData%SDInputFile = '..\BeamFEM\IOFiles\TestFrame.txt' - InitInData%g = 9.80665 - !InitInData%TP_RefPoint = (/0.0, 0.0, 100.0/) !testbeam2 - InitInData%TP_RefPoint = (/50.0, 0.0, 50.0/) !testbeam3 - InitInData%SubRotateZ = 0.0 - InitInData%WtrDpth = 20.0 - !InitInData%TP_RefPoint = (/0.0, 0.0, 40.0/) !testframe - ! Set the driver's request for time interval here: - TimeInterval = 0.001 ! Glue code's request for delta time (likely based on information from other modules) END IF + + TMax = TimeInterval * drvrInitInp%NSteps - - TMax = TimeInterval * drvrInitInp%NSteps - - ! Initialize the module - - CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat1, ErrMsg1 ) - IF ( ErrStat1 /= 0 ) THEN - CALL WrScr( ErrMsg1 ) - STOP - END IF + ! Initialize the module + CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() + CALL AllocAry(SDin, drvrInitInp%NSteps, 13, 'SDinput array', ErrStat2, ErrMsg2); call AbortIfFailed() + SDin(:,:)=0.0_ReKi - ! Read Input time series data from a file - + ! Read Input time series data from a file IF ( drvrInitInp%InputsMod == 2 ) THEN - - ! Open the inputs data file - CALL GetNewUnit( UnInp ) - CALL OpenFInpFile ( UnInp, drvrInitInp%InputsFile, ErrStat, ErrMsg ) ! Open inputs file. - IF (ErrStat >= AbortErrLev) THEN - CALL WrScr( 'SubDyn input timeseries file not found.') - CALL WrScr( trim(ErrMsg) ) - STOP - END IF - - ALLOCATE ( SDin(drvrInitInp%NSteps, 13), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for SDin array.' - CALL WrScr( ErrMsg ) - CLOSE( UnInp ) - STOP - END IF - + ! Open the inputs data file + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile ( UnIn, drvrInitInp%InputsFile, ErrStat2, ErrMsg2); Call AbortIfFailed() DO n = 1,drvrInitInp%NSteps - READ (UnInp,*,IOSTAT=ErrStat) (SDin (n,J), J=1,13) - - IF ( ErrStat /= 0 ) THEN - ErrMsg = 'File not found' - CALL WrScr( ErrMsg ) - CLOSE ( UnInp ) - STOP - END IF + READ (UnIn,*,IOSTAT=ErrStat2) (SDin (n,J), J=1,13) + ErrMsg2 = ' Error reading line '//trim(Num2LStr(n))//' of file: '//trim(drvrInitInp%InputsFile) + call AbortIfFailed() END DO - - ! Close the inputs file - CLOSE ( UnInp ) - END IF + CLOSE ( UnIn ) + else + ! We fill an array with constant values + do n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 + SDin(n+1,1) = n*TimeInterval + SDin(n+1,2:7 ) = drvrInitInp%uTPInSteady(1:6) ! Displacements + SDin(n+1,8:13) = drvrInitInp%uDotTPInSteady(1:6) ! Velocities + !SDin(n+1,14:19) = drvrInitInp%uDotDotTPInSteady(1:6) ! Accelerations + enddo + end if - ! Destroy initialization data - - CALL SD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ) - CALL SD_DestroyInitOutput( InitOutData, ErrStat3, ErrMsg3 ) - - - ! Handle the initialization error after destroying the data structures - - IF ( ErrStat1 /= ErrID_None .OR. ErrStat2 /=0 .OR. ErrStat3 /= 0) THEN ! Check if there was an error and do something about it if necessary - CALL WrScr( ErrMsg1 ) - STOP - END IF - - IF ( ErrStat2 /=0 .OR. ErrStat3 /= 0) THEN ! Check if there was an error and do something about it if necessary - CALL WrScr( 'Error destroying SubDyn intialization data' ) - STOP - END IF + ! Destroy initialization data + CALL SD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ); call AbortIfFailed() + CALL SD_DestroyInitOutput( InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() !............................................................................................................................... ! Routines called in loose coupling -- the glue code may implement this in various ways !............................................................................................................................... - ! Force the displacement of the interface node in the global Z direction to be the sag of the column under it's own weight - - !u(1)%UFL(3) = -0.001821207 !-0.001821235 !This is for testbeam.txt - ! u(1)%UFL(3)=-12.958 !this is for testbeam3 - - call wrscr('') - DO n = 0,drvrInitInp%NSteps-1 + ! u(1)%UFL(3) =-12.958 !this is for testbeam3 + call WrScr('') + DO n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 Time = n*TimeInterval InputTime(1) = Time - ! Modify u (likely from the outputs of another module or a set of test conditions) here: - + ! Set module inputs u (likely from the outputs of another module or a set of test conditions) here: IF ( u(1)%TPMesh%Initialized ) THEN - ! For now, set all hydrodynamic load inputs to 0.0 u(1)%LMesh%Force (:,:) = 0.0 - !u(1)%LMesh%Force (3,5:8) = 1.e7 !DEBUGGING - !u(1)%LMesh%Force(3,5) = 1.e7 - !u(1)%LMesh%Force(3,6) = 1.e7 - !u(1)%LMesh%Force(3,7) = 1.e7 - !u(1)%LMesh%Force(3,8) = 1.e7 u(1)%LMesh%Moment (:,:) = 0.0 + ! Input displacements, velocities and potentially accelerations + u(1)%TPMesh%TranslationDisp(:,1) = SDin(n+1,2:4) + CALL SmllRotTrans( 'InputRotation', REAL(SDin(n+1,5),reki), REAL(SDin(n+1,6),reki), REAL(SDin(n+1,7),reki), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%TPMesh%Orientation(:,:,1) = dcm + u(1)%TPMesh%TranslationVel(:,1) = SDin(n+1,8:10) + u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) + IF ( drvrInitInp%InputsMod == 2 ) THEN - - - - u(1)%TPMesh%TranslationDisp(:,1) = SDin(n+1,2:4) - - - ! Compute direction cosine matrix from the rotation angles - - IF ( abs(SDin(n+1,5)) > maxAngle ) maxAngle = abs(SDin(n+1,5)) - IF ( abs(SDin(n+1,6)) > maxAngle ) maxAngle = abs(SDin(n+1,6)) - IF ( abs(SDin(n+1,7)) > maxAngle ) maxAngle = abs(SDin(n+1,7)) - - CALL SmllRotTrans( 'InputRotation', REAL(SDin(n+1,5),reki), REAL(SDin(n+1,6),reki), REAL(SDin(n+1,7),reki), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%TPMesh%Orientation(:,:,1) = dcm - - - u(1)%TPMesh%TranslationVel(:,1) = SDin(n+1,8:10) - u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) - - ELSE - - u(1)%TPMesh%TranslationDisp(:,1) = drvrInitInp%uTPInSteady(1:3) - - - ! Compute direction cosine matrix from the rotation angles - CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uTPInSteady(4),reki), REAL(drvrInitInp%uTPInSteady(5),reki), REAL(drvrInitInp%uTPInSteady(6),reki), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%TPMesh%Orientation(:,:,1) = dcm - - u(1)%TPMesh%TranslationVel(:,1) = drvrInitInp%uDotTPInSteady(1:3) - u(1)%TPMesh%RotationVel(:,1) = drvrInitInp%uDotTPInSteady(4:6) - + ! User time series have no acceleration for now.. + u(1)%TPMesh%TranslationAcc(:,1) = 0.0_ReKi + u(1)%TPMesh%RotationAcc(:,1) = 0.0_ReKi + ELSE ! constant inputs u(1)%TPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(1:3) u(1)%TPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(4:6) - END IF - END IF - ! Calculate outputs at n - - CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary - CALL WrScr( ErrMsg ) - IF ( ErrStat >= AbortErrLev) STOP - END IF - - ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 - - CALL SD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN ! Check if there was an error and do something about it if necessary - CALL WrScr( ErrMsg ) - IF ( ErrStat >= AbortErrLev) STOP - END IF - - !..................................................... + ! Calculate outputs at n + CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2); call AbortIfFailed() + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + CALL SD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2); call AbortIfFailed() ! Display simulation status every SttsTime-seconds: - !..................................................... - IF ( Time - TiLstPrn >= 1 ) THEN - CALL SimStatus( TiLstPrn, PrevClockTime, Time, TMax ) - ENDIF - END DO + END DO ! Loop on n, time steps - !............................................................................................................................... ! Routine to terminate program execution - !............................................................................................................................... - - CALL SD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + CALL SD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2) IF ( ErrStat /= ErrID_None ) THEN CALL WrScr( ErrMsg ) END IF - - !............................................................................................................................ - ! Write simulation times and stop - !............................................................................................................................ - + ! Write simulation times and stop CALL RunTimes( StrtTime, UsrTime1, StrtTime, UsrTime1, Time ) CONTAINS + SUBROUTINE AbortIfFailed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SubDyn_Driver') + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + if (ErrStat >= AbortErrLev) then + call CleanUp() + STOP + endif + END SUBROUTINE AbortIfFailed - !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE CleanupEchoFile( EchoFlag, UnEcho) - ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to - ! any existing echo information - !............................................................................................................................... - LOGICAL, INTENT( IN ) :: EchoFlag ! local version of echo flag - INTEGER, INTENT( IN ) :: UnEcho ! echo unit number - - - ! Close this module's echo file - - IF ( EchoFlag ) THEN - CLOSE(UnEcho) - END IF - - - - END SUBROUTINE CleanupEchoFile - - - !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE CheckError(ErrID,Msg) - ! This subroutine sets the error message and level and cleans up if the error is >= AbortErrLev - !............................................................................................................................... - - ! Passed arguments - INTEGER(IntKi), INTENT(IN) :: ErrID ! The error identifier (ErrStat) - CHARACTER(*), INTENT(IN) :: Msg ! The error message (ErrMsg) - - INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) - CHARACTER(1024) :: ErrMsg3 ! The error message (ErrMsg) - - !............................................................................................................................ - ! Set error status/message; - !............................................................................................................................ - - IF ( ErrID /= ErrID_None ) THEN - - IF ( LEN_TRIM(ErrMsg) > 0 ) ErrMsg = TRIM(ErrMsg)//NewLine - ErrMsg = TRIM(ErrMsg)//' '//TRIM(Msg) - ErrStat = MAX(ErrStat, ErrID) - - !......................................................................................................................... - ! Clean up if we're going to return on error: close files, deallocate local arrays - !......................................................................................................................... - IF ( ErrStat >= AbortErrLev ) THEN - ! CALL CleanupInit(InputFileData, ErrStat3, ErrMsg3 ) - - END IF - - END IF - - - END SUBROUTINE CheckError + SUBROUTINE CleanUp() + if(UnEcho>0) CLOSE(UnEcho) + if(UnEcho>0) CLOSE( UnIn) + if(allocated(SDin)) deallocate(SDin) + END SUBROUTINE CleanUp !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) - ! - !............................................................................................................................... + SUBROUTINE ReadDriverInputFile( inputFile, InitInp) CHARACTER(*), INTENT( IN ) :: inputFile TYPE(SD_Drvr_InitInput), INTENT( OUT ) :: InitInp - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables - + ! Local variables INTEGER :: I ! generic integer for counting INTEGER :: J ! generic integer for counting CHARACTER( 2) :: strI ! string version of the loop counter - INTEGER :: UnIn ! Unit number for the input file - INTEGER :: UnEchoLocal ! The local unit number for this module's echo file CHARACTER(1024) :: EchoFile ! Name of SubDyn echo file CHARACTER(1024) :: Line ! String to temporarially hold value of read line CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name @@ -418,365 +261,73 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) CHARACTER(1024) :: FileName ! Name of SubDyn input file CHARACTER(1024) :: FilePath ! Path Name of SubDyn input file - UnEChoLocal=-1 + UnEcho=-1 + UnIn =-1 FileName = TRIM(inputFile) CALL GetNewUnit( UnIn ) - CALL OpenFInpFile( UnIn, FileName, ErrStat, ErrMsg ) - - IF ( ErrStat >= AbortErrLev ) THEN - CALL WrScr( 'Failed to open SubDyn Driver input file.') - ErrStat = ErrID_Fatal - CLOSE( UnIn ) - RETURN - END IF - + CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2); + call AbortIfFailed() CALL WrScr( 'Opening SubDyn Driver input file: '//FileName ) - - - !------------------------------------------------------------------------------------------------- - ! File header - !------------------------------------------------------------------------------------------------- - - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat, ErrMsg ) - - IF ( ErrStat >= AbortErrLev ) THEN - ErrStat = ErrID_Fatal - CLOSE( UnIn ) - RETURN - END IF - - - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat, ErrMsg ) - - IF ( ErrStat >= AbortErrLev ) THEN - ErrStat = ErrID_Fatal - CLOSE( UnIn ) - RETURN - END IF - - - ! Echo Input Files. - - CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat, ErrMsg ) - - IF ( ErrStat >= AbortErrLev ) THEN - ErrStat = ErrID_Fatal - CLOSE( UnIn ) - RETURN - END IF - - - ! If we are Echoing the input then we should re-read the first three lines so that we can echo them - ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable - ! which we must store, set, and then replace on error or completion. + ! Read until "echo" + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2); call AbortIfFailed() + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2); call AbortIfFailed() + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat2, ErrMsg2); call AbortIfFailed() + ! If we echo, we rewind IF ( InitInp%Echo ) THEN - EchoFile = TRIM(FileName)//'.echo' - CALL GetNewUnit( UnEchoLocal ) - CALL OpenEcho ( UnEchoLocal, EchoFile, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN - !ErrMsg = ' Failed to open Echo file.' - ErrStat = ErrID_Fatal - CLOSE( UnIn ) - RETURN - END IF - + CALL GetNewUnit( UnEcho ) + CALL OpenEcho ( UnEcho, EchoFile, ErrStat, ErrMsg ); call AbortIfFailed() REWIND(UnIn) - - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read SubDyn Driver input file header line 1.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read SubDyn Driver input file header line 2.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. - - CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat, ErrMsg, UnEchoLocal ) - !WRITE (UnEchoLocal,Frmt ) InitInp%Echo, 'Echo', 'Echo input file' - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Echo parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - END IF - !------------------------------------------------------------------------------------------------- - ! Environmental conditions section - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! Gravity - Gravity. - - CALL ReadVar ( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Gravity parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! WtrDpth - Gravity. - - CALL ReadVar ( UnIn, FileName, InitInp%WtrDpth, 'WtrDpth', 'WtrDpth', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read WtrDpth parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() END IF - !------------------------------------------------------------------------------------------------- - ! SubDyn section - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'SubDyn header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN + !---------------------- ENVIRONMENTAL CONDITIONS ------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%WtrDpth, 'WtrDpth', 'WtrDpth', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- SubDyn ------------------------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'SubDyn header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%SDInputFile, 'HDInputFile', 'SubDyn input filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%OutRootName, 'OutRootName', 'SubDyn output root filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%NSteps , 'NSteps', 'Number of time steps in the SubDyn simulation', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', 'Time interval for any SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadAry( UnIn, FileName, InitInp%TP_RefPoint, 3, 'TP reference point', 'TP reference point', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%SubRotateZ, 'SubRotateZ', 'Rotation angle in degrees about Z axis.', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- INPUTS ------------------------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%InputsMod , 'InputsMod', 'Model for the inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%InputsFile, 'InputsFile', 'Filename for the SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- STEADY INPUTS (for InputsMod = 1) ---------------------------------------- + CALL ReadCom( UnIn, FileName, 'STEADY STATE INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + IF ( InitInp%InputsMod == 1 ) THEN + CALL ReadAry ( UnIn, FileName, InitInp%uTPInSteady , 6, 'uInSteady', 'Steady-state TP displacements and rotations.', ErrStat2, ErrMsg2, UnEcho) + CALL ReadAry ( UnIn, FileName, InitInp%uDotTPInSteady , 6, 'uDotTPInSteady', 'Steady-state TP translational and rotational velocities.', ErrStat2, ErrMsg2, UnEcho) + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotTPInSteady, 6, 'uDotDotTPInSteady', 'Steady-state TP translational and rotational accelerations.', ErrStat2, ErrMsg2, UnEcho) + ELSE + InitInp%uTPInSteady = 0.0 + InitInp%uDotTPInSteady = 0.0 + InitInp%uDotDotTPInSteady = 0.0 END IF + if(UnEcho>0) CLOSE( UnEcho ) + if(UnIn>0) CLOSE( UnIn ) - - ! HDInputFile - - CALL ReadVar ( UnIn, FileName, InitInp%SDInputFile, 'HDInputFile', & - 'SubDyn input filename', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read SDInputFile parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF + ! Perform input checks and triggers + CALL GetPath( FileName, FilePath ) IF ( PathIsRelative( InitInp%SDInputFile ) ) then - CALL GetPath( FileName, FilePath ) InitInp%SDInputFile = TRIM(FilePath)//TRIM(InitInp%SDInputFile) END IF - - ! OutRootName - - CALL ReadVar ( UnIn, FileName, InitInp%OutRootName, 'OutRootName', & - 'SubDyn output root filename', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read OutRootName parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! NSteps - - CALL ReadVar ( UnIn, FileName, InitInp%NSteps, 'NSteps', & - 'Number of time steps in the SubDyn simulation', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read NSteps parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! TimeInterval - - CALL ReadVar ( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', & - 'Time interval for any SubDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read TimeInterval parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - ! TP_RefPoint - - CALL ReadAry ( UnIn, FileName, InitInp%TP_RefPoint, 3, 'TP reference point', & - 'TP reference point', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read TP_RefPoint parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - ! SubRotateZ - - CALL ReadVar ( UnIn, FileName, InitInp%SubRotateZ, 'SubRotateZ', & - 'Rotation angle in degrees about Z axis.', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read SubRotateZ parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - !------------------------------------------------------------------------------------------------- - ! INPUTS section - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - - ! InputsMod - - CALL ReadVar ( UnIn, FileName, InitInp%InputsMod, 'InputsMod', & - 'Model for the inputs', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read InputsMod parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! InputsFile - - CALL ReadVar ( UnIn, FileName, InitInp%InputsFile, 'InputsFile', & - 'Filename for the SubDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read InputsFile parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - !------------------------------------------------------------------------------------------------- - ! STEADY STATE INPUTS section - !------------------------------------------------------------------------------------------------- + IF ( PathIsRelative( InitInp%OutRootName ) ) then + InitInp%OutRootName = TRIM(FilePath)//TRIM(InitInp%OutRootName) + endif + IF ( PathIsRelative( InitInp%InputsFile ) ) then + InitInp%InputsFile = TRIM(FilePath)//TRIM(InitInp%InputsFile) + endif - ! Header - - CALL ReadCom( UnIn, FileName, 'STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - IF ( InitInp%InputsMod == 1 ) THEN - - ! uTPInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uTPInSteady, 6, 'uInSteady', & - 'Steady-state TP displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uTPInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! uDotTPInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uDotTPInSteady, 6, 'uDotTPInSteady', & - ' Steady-state TP translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotTPInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! uDotDotTPInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uDotDotTPInSteady, 6, 'uDotDotTPInSteady', & - ' Steady-state TP translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotDotTPInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - ELSE - InitInp%uTPInSteady = 0.0 - InitInp%uDotTPInSteady = 0.0 - InitInp%uDotDotTPInSteady = 0.0 - END IF - - - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - END SUBROUTINE ReadDriverInputFile subroutine print_help() @@ -787,7 +338,5 @@ subroutine print_help() print '(a)', 'Where driverfilename is the name of the SubDyn driver input file.' print '(a)', '' end subroutine print_help - !---------------------------------------------------------------------------------------------------------------------------------- - END PROGRAM TestSubDyn From 51b4bd936aa59a7a77cc75b67da6b6bd03f67151 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 8 May 2020 12:33:43 -0600 Subject: [PATCH 205/377] FlexSub: reintroducing BC after CB option, but not active (see c03308f) --- modules/subdyn/src/SubDyn.f90 | 64 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 223625d0e..8c3f72445 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -1600,6 +1600,8 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) INTEGER(IntKi) :: nL, nM, nM_out + INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb + LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 character(*), parameter :: RoutineName = 'SD_Craig_Bampton' @@ -1623,6 +1625,17 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) ENDIF CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + ! Switch between BC before or after CB, KEEP ME + BC_Before_CB=.true. + if(BC_Before_CB) then + !print*,' > Boundary conditions will be applied before Craig-Bampton (New)' + nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction + IDR => p%ID__Rb + else + !print*,' > Craig-Bampton will be applied before boundary conditions (Legacy)' + nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system + IDR => p%IDR__ + endif IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below @@ -1631,7 +1644,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) ENDIF nL = p%nDOF__L nM = p%nDOFM - nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1645,7 +1657,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%OmegaL, nM_Out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL CraigBamptonReduction(Init%M, Init%K, p%ID__Rb, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& + CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& Init%FG, FGR, FGL, FGB, FGM) if(Failed()) return @@ -1658,7 +1670,12 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) END IF CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - PhiRb=CB%PhiR ! Remove me in the future + if(.not.BC_Before_CB) then + ! We apply the BC now, removing unwanted DOFs + call applyConstr(CB, FGB, PhiRb) + else + PhiRb=CB%PhiR ! Remove me in the future + endif ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') @@ -1687,6 +1704,47 @@ subroutine CleanUpCB() IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) end subroutine CleanUpCB + !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system + !! NOTE: PhiL and OmegaL are not modified + subroutine applyConstr(CBParams, FGB, PhiRb) + TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) + !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) + REAL(ReKi), ALLOCATABLE :: MBBb(:, :) + REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: KBBb(:, :) + REAL(ReKi), ALLOCATABLE :: FGBb(:) + ! "b" stands for "bar" + CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); + CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); + !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); + !................................ + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to + ! MBBb, MBMb, KBBb, PHiRb, FGBb + ! (throw out rows/columns of first matrices to create second matrices) + !................................ + ! TODO avoid this all together + MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + IF (p%nDOFM > 0) THEN + MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) + END IF + FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) + PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + deallocate(CBparams%MBB) + deallocate(CBparams%KBB) + deallocate(CBparams%MBM) + !deallocate(CBparams%PhiR) + call move_alloc(MBBb, CBparams%MBB) + call move_alloc(KBBb, CBparams%KBB) + call move_alloc(MBMb, CBparams%MBM) + call move_alloc(FGBb, FGB) + !call move_alloc(PhiRb, CBparams%PhiR) + end subroutine applyConstr + END SUBROUTINE SD_Craig_Bampton !> Extract rigid body mass without SSI From ade19c6605e09f1d9be44a13f1c3c7e84876fef8 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 13:38:31 -0600 Subject: [PATCH 206/377] Merge cleanup --- modules/hydrodyn/src/Conv_Radiation_Types.f90 | 166 +- modules/hydrodyn/src/Current_Types.f90 | 24 +- modules/hydrodyn/src/HydroDyn.txt | 2 +- modules/hydrodyn/src/HydroDyn_Types.f90 | 1189 +++++-- modules/hydrodyn/src/Morison.txt | 4 +- modules/hydrodyn/src/Morison_Types.f90 | 3114 +++++++++-------- modules/hydrodyn/src/SS_Excitation.txt | 2 +- modules/hydrodyn/src/SS_Excitation_Types.f90 | 354 +- modules/hydrodyn/src/SS_Radiation.txt | 4 +- modules/hydrodyn/src/SS_Radiation_Types.f90 | 416 ++- modules/hydrodyn/src/WAMIT2_Types.f90 | 376 +- modules/hydrodyn/src/WAMIT_Types.f90 | 787 +++-- modules/hydrodyn/src/Waves2_Types.f90 | 24 +- modules/hydrodyn/src/Waves_Types.f90 | 60 +- 14 files changed, 4129 insertions(+), 2393 deletions(-) diff --git a/modules/hydrodyn/src/Conv_Radiation_Types.f90 b/modules/hydrodyn/src/Conv_Radiation_Types.f90 index 8d0e7e6dd..d9188b01d 100644 --- a/modules/hydrodyn/src/Conv_Radiation_Types.f90 +++ b/modules/hydrodyn/src/Conv_Radiation_Types.f90 @@ -282,6 +282,8 @@ SUBROUTINE Conv_Rdtn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf(Int_Xferred) = ICHAR(InData%RdtnDTChr(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 ReKiBuf(Re_Xferred) = InData%HighFreq Re_Xferred = Re_Xferred + 1 DO I = 1, LEN(InData%WAMITFile) @@ -304,10 +306,12 @@ SUBROUTINE Conv_Rdtn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroAddMs,3) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%HdroAddMs,2), UBOUND(InData%HdroAddMs,2) - DO i1 = LBOUND(InData%HdroAddMs,1), UBOUND(InData%HdroAddMs,1) - ReKiBuf(Re_Xferred) = InData%HdroAddMs(i1,i2) - Re_Xferred = Re_Xferred + 1 + DO i3 = LBOUND(InData%HdroAddMs,3), UBOUND(InData%HdroAddMs,3) + DO i2 = LBOUND(InData%HdroAddMs,2), UBOUND(InData%HdroAddMs,2) + DO i1 = LBOUND(InData%HdroAddMs,1), UBOUND(InData%HdroAddMs,1) + ReKiBuf(Re_Xferred) = InData%HdroAddMs(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO END DO END DO END IF @@ -342,10 +346,12 @@ SUBROUTINE Conv_Rdtn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroDmpng,3) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%HdroDmpng,2), UBOUND(InData%HdroDmpng,2) - DO i1 = LBOUND(InData%HdroDmpng,1), UBOUND(InData%HdroDmpng,1) - ReKiBuf(Re_Xferred) = InData%HdroDmpng(i1,i2) - Re_Xferred = Re_Xferred + 1 + DO i3 = LBOUND(InData%HdroDmpng,3), UBOUND(InData%HdroDmpng,3) + DO i2 = LBOUND(InData%HdroDmpng,2), UBOUND(InData%HdroDmpng,2) + DO i1 = LBOUND(InData%HdroDmpng,1), UBOUND(InData%HdroDmpng,1) + ReKiBuf(Re_Xferred) = InData%HdroDmpng(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO END DO END DO END IF @@ -392,6 +398,8 @@ SUBROUTINE Conv_Rdtn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt OutData%RdtnDTChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%HighFreq = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 DO I = 1, LEN(OutData%WAMITFile) @@ -417,10 +425,12 @@ SUBROUTINE Conv_Rdtn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroAddMs.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%HdroAddMs,2), UBOUND(OutData%HdroAddMs,2) - DO i1 = LBOUND(OutData%HdroAddMs,1), UBOUND(OutData%HdroAddMs,1) - OutData%HdroAddMs(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 + DO i3 = LBOUND(OutData%HdroAddMs,3), UBOUND(OutData%HdroAddMs,3) + DO i2 = LBOUND(OutData%HdroAddMs,2), UBOUND(OutData%HdroAddMs,2) + DO i1 = LBOUND(OutData%HdroAddMs,1), UBOUND(OutData%HdroAddMs,1) + OutData%HdroAddMs(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO END DO END DO END IF @@ -461,10 +471,12 @@ SUBROUTINE Conv_Rdtn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroDmpng.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%HdroDmpng,2), UBOUND(OutData%HdroDmpng,2) - DO i1 = LBOUND(OutData%HdroDmpng,1), UBOUND(OutData%HdroDmpng,1) - OutData%HdroDmpng(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 + DO i3 = LBOUND(OutData%HdroDmpng,3), UBOUND(OutData%HdroDmpng,3) + DO i2 = LBOUND(OutData%HdroDmpng,2), UBOUND(OutData%HdroDmpng,2) + DO i1 = LBOUND(OutData%HdroDmpng,1), UBOUND(OutData%HdroDmpng,1) + OutData%HdroDmpng(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO END DO END DO END IF @@ -1425,6 +1437,8 @@ SUBROUTINE Conv_Rdtn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = Db_Xferred + 1 DbKiBuf(Db_Xferred) = InData%RdtnDT Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%RdtnKrnl) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1489,6 +1503,8 @@ SUBROUTINE Conv_Rdtn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Db_Xferred = Db_Xferred + 1 OutData%RdtnDT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RdtnKrnl not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -1633,10 +1649,21 @@ SUBROUTINE Conv_Rdtn_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%Velocity,1), UBOUND(InData%Velocity,1) - ReKiBuf(Re_Xferred) = InData%Velocity(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%Velocity) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Velocity,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Velocity,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Velocity,1), UBOUND(InData%Velocity,1) + ReKiBuf(Re_Xferred) = InData%Velocity(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE Conv_Rdtn_PackInput SUBROUTINE Conv_Rdtn_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1666,12 +1693,24 @@ SUBROUTINE Conv_Rdtn_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%Velocity,1) - i1_u = UBOUND(OutData%Velocity,1) - DO i1 = LBOUND(OutData%Velocity,1), UBOUND(OutData%Velocity,1) - OutData%Velocity(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Velocity not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Velocity)) DEALLOCATE(OutData%Velocity) + ALLOCATE(OutData%Velocity(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Velocity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Velocity,1), UBOUND(OutData%Velocity,1) + OutData%Velocity(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE Conv_Rdtn_UnPackInput SUBROUTINE Conv_Rdtn_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -1784,10 +1823,21 @@ SUBROUTINE Conv_Rdtn_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) - ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%F_Rdtn) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_Rdtn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Rdtn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) + ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE Conv_Rdtn_PackOutput SUBROUTINE Conv_Rdtn_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1817,12 +1867,24 @@ SUBROUTINE Conv_Rdtn_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%F_Rdtn,1) - i1_u = UBOUND(OutData%F_Rdtn,1) - DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) - OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_Rdtn not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_Rdtn)) DEALLOCATE(OutData%F_Rdtn) + ALLOCATE(OutData%F_Rdtn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_Rdtn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) + OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE Conv_Rdtn_UnPackOutput @@ -1842,7 +1904,7 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1889,8 +1951,8 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, E ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u2 ! Input at t2 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1920,10 +1982,12 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, E END IF ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%Velocity) .AND. ALLOCATED(u1%Velocity)) THEN DO i1 = LBOUND(u_out%Velocity,1),UBOUND(u_out%Velocity,1) b = -(u1%Velocity(i1) - u2%Velocity(i1)) u_out%Velocity(i1) = u1%Velocity(i1) + b * ScaleFactor END DO +END IF ! check if allocated END SUBROUTINE Conv_Rdtn_Input_ExtrapInterp1 @@ -1941,9 +2005,9 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrSta ! !.................................................................................................................................. - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u3 ! Input at t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Conv_Rdtn_InputType), INTENT(IN) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Conv_Rdtn_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1981,11 +2045,13 @@ SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrSta END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%Velocity) .AND. ALLOCATED(u1%Velocity)) THEN DO i1 = LBOUND(u_out%Velocity,1),UBOUND(u_out%Velocity,1) b = (t(3)**2*(u1%Velocity(i1) - u2%Velocity(i1)) + t(2)**2*(-u1%Velocity(i1) + u3%Velocity(i1)))* scaleFactor c = ( (t(2)-t(3))*u1%Velocity(i1) + t(3)*u2%Velocity(i1) - t(2)*u3%Velocity(i1) ) * scaleFactor u_out%Velocity(i1) = u1%Velocity(i1) + b + c * t_out END DO +END IF ! check if allocated END SUBROUTINE Conv_Rdtn_Input_ExtrapInterp2 @@ -2005,7 +2071,7 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2052,8 +2118,8 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2083,10 +2149,12 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, END IF ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%F_Rdtn) .AND. ALLOCATED(y1%F_Rdtn)) THEN DO i1 = LBOUND(y_out%F_Rdtn,1),UBOUND(y_out%F_Rdtn,1) b = -(y1%F_Rdtn(i1) - y2%F_Rdtn(i1)) y_out%F_Rdtn(i1) = y1%F_Rdtn(i1) + b * ScaleFactor END DO +END IF ! check if allocated END SUBROUTINE Conv_Rdtn_Output_ExtrapInterp1 @@ -2104,9 +2172,9 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSt ! !.................................................................................................................................. - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Conv_Rdtn_OutputType), INTENT(IN) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Conv_Rdtn_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2144,11 +2212,13 @@ SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSt END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%F_Rdtn) .AND. ALLOCATED(y1%F_Rdtn)) THEN DO i1 = LBOUND(y_out%F_Rdtn,1),UBOUND(y_out%F_Rdtn,1) b = (t(3)**2*(y1%F_Rdtn(i1) - y2%F_Rdtn(i1)) + t(2)**2*(-y1%F_Rdtn(i1) + y3%F_Rdtn(i1)))* scaleFactor c = ( (t(2)-t(3))*y1%F_Rdtn(i1) + t(3)*y2%F_Rdtn(i1) - t(2)*y3%F_Rdtn(i1) ) * scaleFactor y_out%F_Rdtn(i1) = y1%F_Rdtn(i1) + b + c * t_out END DO +END IF ! check if allocated END SUBROUTINE Conv_Rdtn_Output_ExtrapInterp2 END MODULE Conv_Radiation_Types diff --git a/modules/hydrodyn/src/Current_Types.f90 b/modules/hydrodyn/src/Current_Types.f90 index ba5c64334..f262434bc 100644 --- a/modules/hydrodyn/src/Current_Types.f90 +++ b/modules/hydrodyn/src/Current_Types.f90 @@ -1609,7 +1609,7 @@ SUBROUTINE Current_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Current_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1656,8 +1656,8 @@ SUBROUTINE Current_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(Current_InputType), INTENT(INOUT) :: u2 ! Input at t2 + TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1704,9 +1704,9 @@ SUBROUTINE Current_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Current_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(Current_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(Current_InputType), INTENT(INOUT) :: u3 ! Input at t3 + TYPE(Current_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Current_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Current_InputType), INTENT(IN) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Current_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1764,7 +1764,7 @@ SUBROUTINE Current_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Current_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -1811,8 +1811,8 @@ SUBROUTINE Current_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Er ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(Current_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -1859,9 +1859,9 @@ SUBROUTINE Current_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat ! !.................................................................................................................................. - TYPE(Current_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(Current_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(Current_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + TYPE(Current_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Current_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Current_OutputType), INTENT(IN) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Current_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 65ae09f45..f9abb2da0 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -67,7 +67,7 @@ typedef ^ ^ CHARACTER(C typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files]" - typedef ^ ^ LOGICAL OutAll - - - "Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F]" - typedef ^ ^ INTEGER NumOuts - - - "The number of outputs for this module as requested in the input file" - -typedef ^ ^ CHARACTER(ChanLen) OutList {54} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - +typedef ^ ^ CHARACTER(ChanLen) OutList {:} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - typedef ^ ^ LOGICAL HDSum - - - "Generate a HydroDyn summary file [T/F]" - typedef ^ ^ INTEGER UnSum - - - "File unit for the HydroDyn summary file [-1 = no summary file]" - typedef ^ ^ CHARACTER(20) OutFmt - - - "Output format for numerical results" - diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 3cc19a030..0782dca33 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -87,7 +87,7 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: OutSwtch !< Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files] [-] LOGICAL :: OutAll !< Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F] [-] INTEGER(IntKi) :: NumOuts !< The number of outputs for this module as requested in the input file [-] - CHARACTER(ChanLen) , DIMENSION(1:54) :: OutList !< The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts [-] LOGICAL :: HDSum !< Generate a HydroDyn summary file [T/F] [-] INTEGER(IntKi) :: UnSum !< File unit for the HydroDyn summary file [-1 = no summary file] [-] CHARACTER(20) :: OutFmt !< Output format for numerical results [-] @@ -171,7 +171,6 @@ MODULE HydroDyn_Types TYPE(WAMIT_InputType) , DIMENSION(:), ALLOCATABLE :: u_WAMIT !< WAMIT module inputs [-] TYPE(WAMIT2_InputType) , DIMENSION(:), ALLOCATABLE :: u_WAMIT2 !< WAMIT2 module inputs [-] TYPE(Waves2_InputType) :: u_Waves2 !< Waves2 module inputs [-] - LOGICAL :: IgnoreMod !< whether to ignore the modulo in ED outputs (necessary for linearization perturbations) [-] END TYPE HydroDyn_MiscVarType ! ======================= ! ========= HydroDyn_ParameterType ======= @@ -191,11 +190,12 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: NWaveElev !< Number of wave elevation outputs [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< Total wave elevation [-] REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev1 !< First order wave elevation [-] + REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev2 !< Second order wave elevation [-] REAL(ReKi) :: WtrDpth !< Water depth [(m)] - REAL(ReKi) , DIMENSION(1:6) :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] - REAL(ReKi) , DIMENSION(1:6,1:6) :: AddCLin !< Additional stiffness matrix [-] - REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBLin !< Additional linear damping matrix [-] - REAL(ReKi) , DIMENSION(1:6,1:6) :: AddBQuad !< Additional quadratic damping (drag) matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AddF0 !< Additional pre-load forces and moments (N,N,N,N-m,N-m,N-m) [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddCLin !< Additional stiffness matrix [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddBLin !< Additional linear damping matrix [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: AddBQuad !< Additional quadratic damping (drag) matrix [-] REAL(DbKi) :: DT !< Time step in seconds for integration of continuous states (if a fixed-step integrator is used) and update of discrete states [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] INTEGER(IntKi) :: NumOuts !< Number of HydroDyn module-level outputs (not the total number including sub-modules [-] @@ -879,64 +879,101 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%PtfmLocationY Re_Xferred = Re_Xferred + 1 - DO I = 1, LEN(InData%PtfmSgFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSgFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF, IntKiBuf(1)) + IF ( .NOT. ALLOCATED(InData%AddF0) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmSwFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmSwFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF, IntKiBuf(1)) + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmHvFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmHvFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF, IntKiBuf(1)) + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddF0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddF0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddF0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddF0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AddF0,2), UBOUND(InData%AddF0,2) + DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) + ReKiBuf(Re_Xferred) = InData%AddF0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AddCLin) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmRFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmRFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF, IntKiBuf(1)) + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmPFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmPFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF, IntKiBuf(1)) + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddCLin,3), UBOUND(InData%AddCLin,3) + DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) + DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) + ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AddBLin) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%PtfmYFChr) - IntKiBuf(Int_Xferred) = ICHAR(InData%PtfmYFChr(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF, IntKiBuf(1)) + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) - ReKiBuf(Re_Xferred) = InData%AddF0(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) - DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) - ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) - DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) - ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2) - Re_Xferred = Re_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddBLin,3), UBOUND(InData%AddBLin,3) + DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) + DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) + ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO - DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) - DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) - ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( .NOT. ALLOCATED(InData%AddBQuad) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddBQuad,3), UBOUND(InData%AddBQuad,3) + DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) + DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) + ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO + END IF CALL Waves_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%Waves, ErrStat2, ErrMsg2, OnlySize ) ! Waves CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1021,10 +1058,153 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - DO I = 1, LEN(InData%PotFile) - IntKiBuf(Int_Xferred) = ICHAR(InData%PotFile(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I + IF ( .NOT. ALLOCATED(InData%PotFile) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PotFile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PotFile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PotFile,1), UBOUND(InData%PotFile,1) + DO I = 1, LEN(InData%PotFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%PotFile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IntKiBuf(Int_Xferred) = InData%nWAMITObj + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%vecMultiplier + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmVol0) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmVol0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmVol0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmVol0,1), UBOUND(InData%PtfmVol0,1) + ReKiBuf(Re_Xferred) = InData%PtfmVol0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%HasWAMIT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%WAMITULEN) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMITULEN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMITULEN,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMITULEN,1), UBOUND(InData%WAMITULEN,1) + ReKiBuf(Re_Xferred) = InData%WAMITULEN(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefxt,1), UBOUND(InData%PtfmRefxt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefyt,1), UBOUND(InData%PtfmRefyt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefyt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefzt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefzt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefzt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefzt,1), UBOUND(InData%PtfmRefzt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefzt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefztRot,1), UBOUND(InData%PtfmRefztRot,1) + DbKiBuf(Db_Xferred) = InData%PtfmRefztRot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmCOBxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmCOBxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmCOBxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmCOBxt,1), UBOUND(InData%PtfmCOBxt,1) + ReKiBuf(Re_Xferred) = InData%PtfmCOBxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmCOByt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmCOByt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmCOByt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmCOByt,1), UBOUND(InData%PtfmCOByt,1) + ReKiBuf(Re_Xferred) = InData%PtfmCOByt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF CALL WAMIT_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1138,12 +1318,23 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NumOuts Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) - DO I = 1, LEN(InData%OutList) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + IF ( .NOT. ALLOCATED(InData%OutList) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) + DO I = 1, LEN(InData%OutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF IntKiBuf(Int_Xferred) = TRANSFER(InData%HDSum, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%UnSum @@ -1234,78 +1425,113 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%PtfmLocationY = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - DO I = 1, LEN(OutData%PtfmSgFChr) - OutData%PtfmSgFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmSgF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddF0 not allocated Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmSwFChr) - OutData%PtfmSwFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmSwF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF) + ELSE Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmHvFChr) - OutData%PtfmHvFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmHvF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF) + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddF0)) DEALLOCATE(OutData%AddF0) + ALLOCATE(OutData%AddF0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddF0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AddF0,2), UBOUND(OutData%AddF0,2) + DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) + OutData%AddF0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddCLin not allocated Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmRFChr) - OutData%PtfmRFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmRF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF) + ELSE Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmPFChr) - OutData%PtfmPFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmPF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF) + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddCLin)) DEALLOCATE(OutData%AddCLin) + ALLOCATE(OutData%AddCLin(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddCLin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddCLin,3), UBOUND(OutData%AddCLin,3) + DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) + DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) + OutData%AddCLin(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddBLin not allocated Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%PtfmYFChr) - OutData%PtfmYFChr(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%PtfmYF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF) + ELSE Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%AddF0,1) - i1_u = UBOUND(OutData%AddF0,1) - DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) - OutData%AddF0(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%AddCLin,1) - i1_u = UBOUND(OutData%AddCLin,1) - i2_l = LBOUND(OutData%AddCLin,2) - i2_u = UBOUND(OutData%AddCLin,2) - DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) - DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) - OutData%AddCLin(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - i1_l = LBOUND(OutData%AddBLin,1) - i1_u = UBOUND(OutData%AddBLin,1) - i2_l = LBOUND(OutData%AddBLin,2) - i2_u = UBOUND(OutData%AddBLin,2) - DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) - DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) - OutData%AddBLin(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddBLin)) DEALLOCATE(OutData%AddBLin) + ALLOCATE(OutData%AddBLin(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddBLin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddBLin,3), UBOUND(OutData%AddBLin,3) + DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) + DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) + OutData%AddBLin(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO - i1_l = LBOUND(OutData%AddBQuad,1) - i1_u = UBOUND(OutData%AddBQuad,1) - i2_l = LBOUND(OutData%AddBQuad,2) - i2_u = UBOUND(OutData%AddBQuad,2) - DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) - DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) - OutData%AddBQuad(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddBQuad not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddBQuad)) DEALLOCATE(OutData%AddBQuad) + ALLOCATE(OutData%AddBQuad(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddBQuad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddBQuad,3), UBOUND(OutData%AddBQuad,3) + DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) + DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) + OutData%AddBQuad(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -1426,10 +1652,180 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - DO I = 1, LEN(OutData%PotFile) - OutData%PotFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PotFile not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PotFile)) DEALLOCATE(OutData%PotFile) + ALLOCATE(OutData%PotFile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PotFile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PotFile,1), UBOUND(OutData%PotFile,1) + DO I = 1, LEN(OutData%PotFile) + OutData%PotFile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + OutData%nWAMITObj = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%vecMultiplier = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmVol0 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmVol0)) DEALLOCATE(OutData%PtfmVol0) + ALLOCATE(OutData%PtfmVol0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmVol0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmVol0,1), UBOUND(OutData%PtfmVol0,1) + OutData%PtfmVol0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%HasWAMIT = TRANSFER(IntKiBuf(Int_Xferred), OutData%HasWAMIT) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMITULEN not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMITULEN)) DEALLOCATE(OutData%WAMITULEN) + ALLOCATE(OutData%WAMITULEN(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMITULEN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMITULEN,1), UBOUND(OutData%WAMITULEN,1) + OutData%WAMITULEN(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) + ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefxt,1), UBOUND(OutData%PtfmRefxt,1) + OutData%PtfmRefxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) + ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefyt,1), UBOUND(OutData%PtfmRefyt,1) + OutData%PtfmRefyt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefzt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefzt)) DEALLOCATE(OutData%PtfmRefzt) + ALLOCATE(OutData%PtfmRefzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefzt,1), UBOUND(OutData%PtfmRefzt,1) + OutData%PtfmRefzt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefztRot,1), UBOUND(OutData%PtfmRefztRot,1) + OutData%PtfmRefztRot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmCOBxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmCOBxt)) DEALLOCATE(OutData%PtfmCOBxt) + ALLOCATE(OutData%PtfmCOBxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmCOBxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmCOBxt,1), UBOUND(OutData%PtfmCOBxt,1) + OutData%PtfmCOBxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmCOByt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmCOByt)) DEALLOCATE(OutData%PtfmCOByt) + ALLOCATE(OutData%PtfmCOByt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmCOByt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmCOByt,1), UBOUND(OutData%PtfmCOByt,1) + OutData%PtfmCOByt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -1582,14 +1978,26 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = Int_Xferred + 1 OutData%NumOuts = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%OutList,1) - i1_u = UBOUND(OutData%OutList,1) - DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) - DO I = 1, LEN(OutData%OutList) - OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutList not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%OutList)) DEALLOCATE(OutData%OutList) + ALLOCATE(OutData%OutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) + DO I = 1, LEN(OutData%OutList) + OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF OutData%HDSum = TRANSFER(IntKiBuf(Int_Xferred), OutData%HDSum) Int_Xferred = Int_Xferred + 1 OutData%UnSum = IntKiBuf(Int_Xferred) @@ -1605,7 +2013,7 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta END SUBROUTINE HydroDyn_UnPackInitInput SUBROUTINE HydroDyn_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(HydroDyn_InitOutputType), INTENT(INOUT) :: SrcInitOutputData + TYPE(HydroDyn_InitOutputType), INTENT(IN) :: SrcInitOutputData TYPE(HydroDyn_InitOutputType), INTENT(INOUT) :: DstInitOutputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat @@ -3516,6 +3924,7 @@ SUBROUTINE HydroDyn_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_UnPackContState' @@ -4099,6 +4508,7 @@ SUBROUTINE HydroDyn_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_UnPackDiscState' @@ -5158,6 +5568,7 @@ SUBROUTINE HydroDyn_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'HydroDyn_UnPackOtherState' @@ -5490,7 +5901,6 @@ SUBROUTINE HydroDyn_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMs CALL Waves2_CopyInput( SrcMiscData%u_Waves2, DstMiscData%u_Waves2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - DstMiscData%IgnoreMod = SrcMiscData%IgnoreMod END SUBROUTINE HydroDyn_CopyMisc SUBROUTINE HydroDyn_DestroyMisc( MiscData, ErrStat, ErrMsg ) @@ -5784,7 +6194,6 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! IgnoreMod IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -5902,19 +6311,52 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = Db_Xferred + 1 IntKiBuf(Int_Xferred) = InData%LastIndWave Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%F_PtfmAdd,1), UBOUND(InData%F_PtfmAdd,1) - ReKiBuf(Re_Xferred) = InData%F_PtfmAdd(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%F_PtfmAdd) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_PtfmAdd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_PtfmAdd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_PtfmAdd,1), UBOUND(InData%F_PtfmAdd,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAdd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF DO i1 = LBOUND(InData%F_Hydro,1), UBOUND(InData%F_Hydro,1) ReKiBuf(Re_Xferred) = InData%F_Hydro(i1) Re_Xferred = Re_Xferred + 1 END DO - DO i1 = LBOUND(InData%F_Waves,1), UBOUND(InData%F_Waves,1) - ReKiBuf(Re_Xferred) = InData%F_Waves(i1) - Re_Xferred = Re_Xferred + 1 - END DO - CALL WAMIT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT, ErrStat2, ErrMsg2, OnlySize ) ! WAMIT + IF ( .NOT. ALLOCATED(InData%F_Waves) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_Waves,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Waves,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_Waves,1), UBOUND(InData%F_Waves,1) + ReKiBuf(Re_Xferred) = InData%F_Waves(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WAMIT) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WAMIT,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WAMIT,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WAMIT,1), UBOUND(InData%WAMIT,1) + CALL WAMIT_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%WAMIT(i1), ErrStat2, ErrMsg2, OnlySize ) ! WAMIT CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -6151,8 +6593,6 @@ SUBROUTINE HydroDyn_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%IgnoreMod , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 END SUBROUTINE HydroDyn_PackMisc SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -6308,24 +6748,62 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Db_Xferred = Db_Xferred + 1 OutData%LastIndWave = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%F_PtfmAdd,1) - i1_u = UBOUND(OutData%F_PtfmAdd,1) - DO i1 = LBOUND(OutData%F_PtfmAdd,1), UBOUND(OutData%F_PtfmAdd,1) - OutData%F_PtfmAdd(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_PtfmAdd not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_PtfmAdd)) DEALLOCATE(OutData%F_PtfmAdd) + ALLOCATE(OutData%F_PtfmAdd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_PtfmAdd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_PtfmAdd,1), UBOUND(OutData%F_PtfmAdd,1) + OutData%F_PtfmAdd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF i1_l = LBOUND(OutData%F_Hydro,1) i1_u = UBOUND(OutData%F_Hydro,1) DO i1 = LBOUND(OutData%F_Hydro,1), UBOUND(OutData%F_Hydro,1) OutData%F_Hydro(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - i1_l = LBOUND(OutData%F_Waves,1) - i1_u = UBOUND(OutData%F_Waves,1) - DO i1 = LBOUND(OutData%F_Waves,1), UBOUND(OutData%F_Waves,1) - OutData%F_Waves(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_Waves not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_Waves)) DEALLOCATE(OutData%F_Waves) + ALLOCATE(OutData%F_Waves(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_Waves.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_Waves,1), UBOUND(OutData%F_Waves,1) + OutData%F_Waves(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WAMIT)) DEALLOCATE(OutData%WAMIT) + ALLOCATE(OutData%WAMIT(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WAMIT.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WAMIT,1), UBOUND(OutData%WAMIT,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -6656,8 +7134,6 @@ SUBROUTINE HydroDyn_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - OutData%IgnoreMod = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 END SUBROUTINE HydroDyn_UnPackMisc SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) @@ -6762,8 +7238,34 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er END IF END IF DstParamData%WaveElev1 = SrcParamData%WaveElev1 +ENDIF +IF (ALLOCATED(SrcParamData%WaveElev2)) THEN + i1_l = LBOUND(SrcParamData%WaveElev2,1) + i1_u = UBOUND(SrcParamData%WaveElev2,1) + i2_l = LBOUND(SrcParamData%WaveElev2,2) + i2_u = UBOUND(SrcParamData%WaveElev2,2) + IF (.NOT. ALLOCATED(DstParamData%WaveElev2)) THEN + ALLOCATE(DstParamData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%WaveElev2 = SrcParamData%WaveElev2 ENDIF DstParamData%WtrDpth = SrcParamData%WtrDpth +IF (ALLOCATED(SrcParamData%AddF0)) THEN + i1_l = LBOUND(SrcParamData%AddF0,1) + i1_u = UBOUND(SrcParamData%AddF0,1) + i2_l = LBOUND(SrcParamData%AddF0,2) + i2_u = UBOUND(SrcParamData%AddF0,2) + IF (.NOT. ALLOCATED(DstParamData%AddF0)) THEN + ALLOCATE(DstParamData%AddF0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AddF0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstParamData%AddF0 = SrcParamData%AddF0 ENDIF IF (ALLOCATED(SrcParamData%AddCLin)) THEN @@ -7082,8 +7584,16 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM IF ( ALLOCATED(InData%WaveElev1) ) THEN Int_BufSz = Int_BufSz + 2*2 ! WaveElev1 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WaveElev1) ! WaveElev1 + END IF + Int_BufSz = Int_BufSz + 1 ! WaveElev2 allocated yes/no + IF ( ALLOCATED(InData%WaveElev2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WaveElev2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WaveElev2) ! WaveElev2 END IF Re_BufSz = Re_BufSz + 1 ! WtrDpth + Int_BufSz = Int_BufSz + 1 ! AddF0 allocated yes/no + IF ( ALLOCATED(InData%AddF0) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AddF0 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%AddF0) ! AddF0 END IF Int_BufSz = Int_BufSz + 1 ! AddCLin allocated yes/no @@ -7176,10 +7686,10 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nWAMITObj - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%vecMultiplier - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nWAMITObj + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%vecMultiplier + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WAMIT) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -7262,8 +7772,8 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ENDIF END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%WAMIT2used , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%WAMIT2used, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 CALL Waves2_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%Waves2, ErrStat2, ErrMsg2, OnlySize ) ! Waves2 CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -7322,6 +7832,10 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM ENDIF IntKiBuf(Int_Xferred) = InData%PotMod Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveTime) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -7380,31 +7894,124 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Re_Xferred = Re_Xferred + 1 END DO END DO + END IF + IF ( .NOT. ALLOCATED(InData%WaveElev2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WaveElev2,2), UBOUND(InData%WaveElev2,2) + DO i1 = LBOUND(InData%WaveElev2,1), UBOUND(InData%WaveElev2,1) + ReKiBuf(Re_Xferred) = InData%WaveElev2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF ReKiBuf(Re_Xferred) = InData%WtrDpth Re_Xferred = Re_Xferred + 1 - DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) - ReKiBuf(Re_Xferred) = InData%AddF0(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) - DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) - ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2) - Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%AddF0) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddF0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddF0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddF0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddF0,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AddF0,2), UBOUND(InData%AddF0,2) + DO i1 = LBOUND(InData%AddF0,1), UBOUND(InData%AddF0,1) + ReKiBuf(Re_Xferred) = InData%AddF0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO - END DO - DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) - DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) - ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( .NOT. ALLOCATED(InData%AddCLin) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddCLin,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddCLin,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddCLin,3), UBOUND(InData%AddCLin,3) + DO i2 = LBOUND(InData%AddCLin,2), UBOUND(InData%AddCLin,2) + DO i1 = LBOUND(InData%AddCLin,1), UBOUND(InData%AddCLin,1) + ReKiBuf(Re_Xferred) = InData%AddCLin(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO - DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) - DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) - ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( .NOT. ALLOCATED(InData%AddBLin) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBLin,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBLin,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddBLin,3), UBOUND(InData%AddBLin,3) + DO i2 = LBOUND(InData%AddBLin,2), UBOUND(InData%AddBLin,2) + DO i1 = LBOUND(InData%AddBLin,1), UBOUND(InData%AddBLin,1) + ReKiBuf(Re_Xferred) = InData%AddBLin(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO + END IF + IF ( .NOT. ALLOCATED(InData%AddBQuad) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AddBQuad,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AddBQuad,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AddBQuad,3), UBOUND(InData%AddBQuad,3) + DO i2 = LBOUND(InData%AddBQuad,2), UBOUND(InData%AddBQuad,2) + DO i1 = LBOUND(InData%AddBQuad,1), UBOUND(InData%AddBQuad,1) + ReKiBuf(Re_Xferred) = InData%AddBQuad(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN @@ -7553,10 +8160,10 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%nWAMITObj = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%vecMultiplier = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%nWAMITObj = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%vecMultiplier = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WAMIT not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7669,8 +8276,8 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%WAMIT2used = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + OutData%WAMIT2used = TRANSFER(IntKiBuf(Int_Xferred), OutData%WAMIT2used) + Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -7753,6 +8360,10 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) OutData%PotMod = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7820,45 +8431,139 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E Re_Xferred = Re_Xferred + 1 END DO END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WaveElev2)) DEALLOCATE(OutData%WaveElev2) + ALLOCATE(OutData%WaveElev2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WaveElev2,2), UBOUND(OutData%WaveElev2,2) + DO i1 = LBOUND(OutData%WaveElev2,1), UBOUND(OutData%WaveElev2,1) + OutData%WaveElev2(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF OutData%WtrDpth = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%AddF0,1) - i1_u = UBOUND(OutData%AddF0,1) - DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) - OutData%AddF0(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%AddCLin,1) - i1_u = UBOUND(OutData%AddCLin,1) - i2_l = LBOUND(OutData%AddCLin,2) - i2_u = UBOUND(OutData%AddCLin,2) - DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) - DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) - OutData%AddCLin(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddF0 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddF0)) DEALLOCATE(OutData%AddF0) + ALLOCATE(OutData%AddF0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddF0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AddF0,2), UBOUND(OutData%AddF0,2) + DO i1 = LBOUND(OutData%AddF0,1), UBOUND(OutData%AddF0,1) + OutData%AddF0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END DO - END DO - i1_l = LBOUND(OutData%AddBLin,1) - i1_u = UBOUND(OutData%AddBLin,1) - i2_l = LBOUND(OutData%AddBLin,2) - i2_u = UBOUND(OutData%AddBLin,2) - DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) - DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) - OutData%AddBLin(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddCLin not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddCLin)) DEALLOCATE(OutData%AddCLin) + ALLOCATE(OutData%AddCLin(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddCLin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddCLin,3), UBOUND(OutData%AddCLin,3) + DO i2 = LBOUND(OutData%AddCLin,2), UBOUND(OutData%AddCLin,2) + DO i1 = LBOUND(OutData%AddCLin,1), UBOUND(OutData%AddCLin,1) + OutData%AddCLin(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO - i1_l = LBOUND(OutData%AddBQuad,1) - i1_u = UBOUND(OutData%AddBQuad,1) - i2_l = LBOUND(OutData%AddBQuad,2) - i2_u = UBOUND(OutData%AddBQuad,2) - DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) - DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) - OutData%AddBQuad(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddBLin not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddBLin)) DEALLOCATE(OutData%AddBLin) + ALLOCATE(OutData%AddBLin(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddBLin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddBLin,3), UBOUND(OutData%AddBLin,3) + DO i2 = LBOUND(OutData%AddBLin,2), UBOUND(OutData%AddBLin,2) + DO i1 = LBOUND(OutData%AddBLin,1), UBOUND(OutData%AddBLin,1) + OutData%AddBLin(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END DO - END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AddBQuad not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AddBQuad)) DEALLOCATE(OutData%AddBQuad) + ALLOCATE(OutData%AddBQuad(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AddBQuad.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AddBQuad,3), UBOUND(OutData%AddBQuad,3) + DO i2 = LBOUND(OutData%AddBQuad,2), UBOUND(OutData%AddBQuad,2) + DO i1 = LBOUND(OutData%AddBQuad,1), UBOUND(OutData%AddBQuad,1) + OutData%AddBQuad(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF OutData%DT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated @@ -9372,13 +10077,15 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, E END IF ScaleFactor = t_out / t(2) - CALL WAMIT_Output_ExtrapInterp1( y1%WAMIT, y2%WAMIT, tin, y_out%WAMIT, tin_out, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(y_out%WAMIT) .AND. ALLOCATED(y1%WAMIT)) THEN + DO i1 = LBOUND(y_out%WAMIT,1),UBOUND(y_out%WAMIT,1) + CALL WAMIT_Output_ExtrapInterp1( y1%WAMIT(i1), y2%WAMIT(i1), tin, y_out%WAMIT(i1), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated IF (ALLOCATED(y_out%WAMIT2) .AND. ALLOCATED(y1%WAMIT2)) THEN - DO i01 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) - CALL WAMIT2_Output_ExtrapInterp1( y1%WAMIT2(i01), y2%WAMIT2(i01), tin, y_out%WAMIT2(i01), tin_out, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) + CALL WAMIT2_Output_ExtrapInterp1( y1%WAMIT2(i1), y2%WAMIT2(i1), tin, y_out%WAMIT2(i1), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated @@ -9451,13 +10158,15 @@ SUBROUTINE HydroDyn_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrSta END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) - CALL WAMIT_Output_ExtrapInterp2( y1%WAMIT, y2%WAMIT, y3%WAMIT, tin, y_out%WAMIT, tin_out, ErrStat2, ErrMsg2 ) +IF (ALLOCATED(y_out%WAMIT) .AND. ALLOCATED(y1%WAMIT)) THEN + DO i1 = LBOUND(y_out%WAMIT,1),UBOUND(y_out%WAMIT,1) + CALL WAMIT_Output_ExtrapInterp2( y1%WAMIT(i1), y2%WAMIT(i1), y3%WAMIT(i1), tin, y_out%WAMIT(i1), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated IF (ALLOCATED(y_out%WAMIT2) .AND. ALLOCATED(y1%WAMIT2)) THEN - DO i01 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) - CALL WAMIT2_Output_ExtrapInterp2( y1%WAMIT2(i01), y2%WAMIT2(i01), y3%WAMIT2(i01), tin, y_out%WAMIT2(i01), tin_out, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(y_out%WAMIT2,1),UBOUND(y_out%WAMIT2,1) + CALL WAMIT2_Output_ExtrapInterp2( y1%WAMIT2(i1), y2%WAMIT2(i1), y3%WAMIT2(i1), tin, y_out%WAMIT2(i1), tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) ENDDO END IF ! check if allocated diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 7e240d2d4..4bb584d4d 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -246,8 +246,8 @@ typedef ^ ^ INTEGER # #typedef ^ InitOutputType MeshType Mesh - - - "Unused?" - #typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m) -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "User-requested Output channel names" - -typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "User-requested Output channel names" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" - # # # ..... States .................................................................................................................... diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index c2f9be796..5ebf023a5 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -304,10 +304,7 @@ MODULE Morison_Types ! ======================= ! ========= Morison_InitOutputType ======= TYPE, PUBLIC :: Morison_InitOutputType - TYPE(MeshType) :: DistribMesh !< [-] - TYPE(MeshType) :: LumpedMesh !< [-] - REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: Morison_Rad !< radius of node (for FAST visualization) [(m)] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< User-requested Output channel names [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] END TYPE Morison_InitOutputType ! ======================= @@ -513,8 +510,8 @@ SUBROUTINE Morison_PackJointType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E IntKiBuf(Int_Xferred) = InData%JointID Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%JointPos,1), UBOUND(InData%JointPos,1) - ReKiBuf(Re_Xferred) = InData%JointPos(i1) + DO i1 = LBOUND(InData%Position,1), UBOUND(InData%Position,1) + ReKiBuf(Re_Xferred) = InData%Position(i1) Re_Xferred = Re_Xferred + 1 END DO IntKiBuf(Int_Xferred) = InData%JointAxID @@ -562,10 +559,10 @@ SUBROUTINE Morison_UnPackJointType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Int_Xferred = 1 OutData%JointID = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%JointPos,1) - i1_u = UBOUND(OutData%JointPos,1) - DO i1 = LBOUND(OutData%JointPos,1), UBOUND(OutData%JointPos,1) - OutData%JointPos(i1) = ReKiBuf(Re_Xferred) + i1_l = LBOUND(OutData%Position,1) + i1_u = UBOUND(OutData%Position,1) + DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) + OutData%Position(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO OutData%JointAxID = IntKiBuf(Int_Xferred) @@ -1052,6 +1049,10 @@ SUBROUTINE Morison_PackCoefDpths( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%DpthCpMG Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%DpthAxCdMG + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%DpthAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%DpthAxCaMG @@ -1102,6 +1103,10 @@ SUBROUTINE Morison_UnPackCoefDpths( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = Re_Xferred + 1 OutData%DpthCpMG = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DpthAxCdMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%DpthAxCa = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%DpthAxCaMG = ReKiBuf(Re_Xferred) @@ -1401,6 +1406,21 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS IntKiBuf(Int_Xferred) = InData%MemberID Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeIndx) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodeIndx,1), UBOUND(InData%NodeIndx,1) + IntKiBuf(Int_Xferred) = InData%NodeIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF IntKiBuf(Int_Xferred) = InData%MJointID1 Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%MJointID2 @@ -1427,18 +1447,12 @@ SUBROUTINE Morison_PackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumSplits + IntKiBuf(Int_Xferred) = InData%NElements Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%Splits,1), UBOUND(InData%Splits,1) - ReKiBuf(Re_Xferred) = InData%Splits(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) - DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) - ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dl + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_PackMemberInputType SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1470,6 +1484,24 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%MemberID = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIndx not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIndx)) DEALLOCATE(OutData%NodeIndx) + ALLOCATE(OutData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeIndx,1), UBOUND(OutData%NodeIndx,1) + OutData%NodeIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF OutData%MJointID1 = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 OutData%MJointID2 = IntKiBuf(Int_Xferred) @@ -1496,24 +1528,12 @@ SUBROUTINE Morison_UnPackMemberInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = Int_Xferred + 1 OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) Int_Xferred = Int_Xferred + 1 - OutData%NumSplits = IntKiBuf(Int_Xferred) + OutData%NElements = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Splits,1) - i1_u = UBOUND(OutData%Splits,1) - DO i1 = LBOUND(OutData%Splits,1), UBOUND(OutData%Splits,1) - OutData%Splits(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) - DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) - OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dl = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_UnPackMemberInputType SUBROUTINE Morison_CopyNodeType( SrcNodeTypeData, DstNodeTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -1630,12 +1650,10 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%NodeType - Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%JointIndx Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%JointPos,1), UBOUND(InData%JointPos,1) - ReKiBuf(Re_Xferred) = InData%JointPos(i1) + DO i1 = LBOUND(InData%Position,1), UBOUND(InData%Position,1) + ReKiBuf(Re_Xferred) = InData%Position(i1) Re_Xferred = Re_Xferred + 1 END DO IntKiBuf(Int_Xferred) = InData%JointOvrlp @@ -1648,62 +1666,18 @@ SUBROUTINE Morison_PackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IntKiBuf(Int_Xferred) = InData%ConnectionList(i1) Int_Xferred = Int_Xferred + 1 END DO - IntKiBuf(Int_Xferred) = InData%NConnectPreSplit - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cd - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CdMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Ca - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CaMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CpMG - Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%JAxCd Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%JAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%JAxCp Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCa - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCaMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCpMG - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%R - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%t + ReKiBuf(Re_Xferred) = InData%FillDensity Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%tMG Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dRdz - Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%MGdensity Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FillFSLoc - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%FillFlag, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FillDensity - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%InpMbrIndx - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InpMbrDist - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) - DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) - ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO END SUBROUTINE Morison_PackNodeType SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1733,14 +1707,12 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%NodeType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 OutData%JointIndx = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%JointPos,1) - i1_u = UBOUND(OutData%JointPos,1) - DO i1 = LBOUND(OutData%JointPos,1), UBOUND(OutData%JointPos,1) - OutData%JointPos(i1) = ReKiBuf(Re_Xferred) + i1_l = LBOUND(OutData%Position,1) + i1_u = UBOUND(OutData%Position,1) + DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) + OutData%Position(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO OutData%JointOvrlp = IntKiBuf(Int_Xferred) @@ -1755,66 +1727,18 @@ SUBROUTINE Morison_UnPackNodeType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%ConnectionList(i1) = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END DO - OutData%NConnectPreSplit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%Cd = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%CdMG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Ca = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%CaMG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Cp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%CpMG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 OutData%JAxCd = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%JAxCa = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%JAxCp = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%AxCa = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%AxCp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%R = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%t = ReKiBuf(Re_Xferred) + OutData%FillDensity = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%tMG = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%dRdz = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 OutData%MGdensity = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%FillFSLoc = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%FillFlag = TRANSFER(IntKiBuf(Int_Xferred), OutData%FillFlag) - Int_Xferred = Int_Xferred + 1 - OutData%FillDensity = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%InpMbrIndx = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%InpMbrDist = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) - DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) - OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO END SUBROUTINE Morison_UnPackNodeType SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -2700,210 +2624,1375 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%Node1Indx + IF ( .NOT. ALLOCATED(InData%NodeIndx) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%Node2Indx + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%R1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%t1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%R2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%t2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cd1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CdMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Ca1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCa1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cd2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CdMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Ca2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%CpMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCa2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%AxCpMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InpMbrDist1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIndx,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodeIndx,1), UBOUND(InData%NodeIndx,1) + IntKiBuf(Int_Xferred) = InData%NodeIndx(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NElements + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InpMbrDist2 + ReKiBuf(Re_Xferred) = InData%cosPhi_ref Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InpMbrLen + ReKiBuf(Re_Xferred) = InData%dl Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%InpMbrIndx - Int_Xferred = Int_Xferred + 1 - DO i2 = LBOUND(InData%R_LToG,2), UBOUND(InData%R_LToG,2) - DO i1 = LBOUND(InData%R_LToG,1), UBOUND(InData%R_LToG,1) - ReKiBuf(Re_Xferred) = InData%R_LToG(i1,i2) + DO i1 = LBOUND(InData%k,1), UBOUND(InData%k,1) + ReKiBuf(Re_Xferred) = InData%k(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%kkt,2), UBOUND(InData%kkt,2) + DO i1 = LBOUND(InData%kkt,1), UBOUND(InData%kkt,1) + ReKiBuf(Re_Xferred) = InData%kkt(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO - IntKiBuf(Int_Xferred) = InData%NumSplits - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%Splits,1), UBOUND(InData%Splits,1) - ReKiBuf(Re_Xferred) = InData%Splits(i1) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%Ak,2), UBOUND(InData%Ak,2) + DO i1 = LBOUND(InData%Ak,1), UBOUND(InData%Ak,1) + ReKiBuf(Re_Xferred) = InData%Ak(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO - ReKiBuf(Re_Xferred) = InData%MGvolume - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MDivSize - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%MCoefMod + IF ( .NOT. ALLOCATED(InData%R) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%MmbrCoefIDIndx + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%MmbrFilledIDIndx + IntKiBuf( Int_Xferred ) = LBOUND(InData%R,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%R,1), UBOUND(InData%R,1) + ReKiBuf(Re_Xferred) = InData%R(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%RMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FillFSLoc - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FillDens - Re_Xferred = Re_Xferred + 1 - DO i1 = LBOUND(InData%F_Bouy,1), UBOUND(InData%F_Bouy,1) - ReKiBuf(Re_Xferred) = InData%F_Bouy(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%F_DP,1), UBOUND(InData%F_DP,1) - ReKiBuf(Re_Xferred) = InData%F_DP(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - END SUBROUTINE Morison_PackMemberType + IntKiBuf( Int_Xferred ) = LBOUND(InData%RMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RMG,1) + Int_Xferred = Int_Xferred + 2 - SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Morison_MemberType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Node1Indx = IntKiBuf(Int_Xferred) + DO i1 = LBOUND(InData%RMG,1), UBOUND(InData%RMG,1) + ReKiBuf(Re_Xferred) = InData%RMG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Rin) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - OutData%Node2Indx = IntKiBuf(Int_Xferred) + ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - OutData%R1 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%t1 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%R2 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%t2 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Cd1 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%CdMG1 = ReKiBuf(Re_Xferred) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Rin,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Rin,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Rin,1), UBOUND(InData%Rin,1) + ReKiBuf(Re_Xferred) = InData%Rin(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%tMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%tMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tMG,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%tMG,1), UBOUND(InData%tMG,1) + ReKiBuf(Re_Xferred) = InData%tMG(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MGdensity) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MGdensity,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MGdensity,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MGdensity,1), UBOUND(InData%MGdensity,1) + ReKiBuf(Re_Xferred) = InData%MGdensity(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dRdl_mg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dRdl_mg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dRdl_mg,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dRdl_mg,1), UBOUND(InData%dRdl_mg,1) + ReKiBuf(Re_Xferred) = InData%dRdl_mg(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%dRdl_in) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dRdl_in,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dRdl_in,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dRdl_in,1), UBOUND(InData%dRdl_in,1) + ReKiBuf(Re_Xferred) = InData%dRdl_in(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%Vinner Re_Xferred = Re_Xferred + 1 - OutData%Ca1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%Vouter Re_Xferred = Re_Xferred + 1 - OutData%CaMG1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%Vballast Re_Xferred = Re_Xferred + 1 - OutData%Cp1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%Vsubmerged Re_Xferred = Re_Xferred + 1 - OutData%CpMG1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%l_fill Re_Xferred = Re_Xferred + 1 - OutData%AxCa1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%h_fill Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%z_overfill Re_Xferred = Re_Xferred + 1 - OutData%AxCp1 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%h_floor Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG1 = ReKiBuf(Re_Xferred) + IntKiBuf(Int_Xferred) = InData%i_floor + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%memfloodstatus + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%floodstatus) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%floodstatus,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%floodstatus,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%floodstatus,1), UBOUND(InData%floodstatus,1) + IntKiBuf(Int_Xferred) = InData%floodstatus(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alpha) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%alpha,1), UBOUND(InData%alpha,1) + ReKiBuf(Re_Xferred) = InData%alpha(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alpha_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_fb,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%alpha_fb,1), UBOUND(InData%alpha_fb,1) + ReKiBuf(Re_Xferred) = InData%alpha_fb(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%alpha_fb_star) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%alpha_fb_star,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%alpha_fb_star,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%alpha_fb_star,1), UBOUND(InData%alpha_fb_star,1) + ReKiBuf(Re_Xferred) = InData%alpha_fb_star(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cd) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Cd,1), UBOUND(InData%Cd,1) + ReKiBuf(Re_Xferred) = InData%Cd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Ca) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ca,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ca,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Ca,1), UBOUND(InData%Ca,1) + ReKiBuf(Re_Xferred) = InData%Ca(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cp) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Cp,1), UBOUND(InData%Cp,1) + ReKiBuf(Re_Xferred) = InData%Cp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxCd) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCd,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCd,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AxCd,1), UBOUND(InData%AxCd,1) + ReKiBuf(Re_Xferred) = InData%AxCd(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxCa) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCa,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCa,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AxCa,1), UBOUND(InData%AxCa,1) + ReKiBuf(Re_Xferred) = InData%AxCa(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AxCp) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AxCp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AxCp,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AxCp,1), UBOUND(InData%AxCp,1) + ReKiBuf(Re_Xferred) = InData%AxCp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m_fb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_fb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_fb_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m_fb_l,1), UBOUND(InData%m_fb_l,1) + ReKiBuf(Re_Xferred) = InData%m_fb_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m_fb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_fb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_fb_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m_fb_u,1), UBOUND(InData%m_fb_u,1) + ReKiBuf(Re_Xferred) = InData%m_fb_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%h_cfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cfb_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%h_cfb_l,1), UBOUND(InData%h_cfb_l,1) + ReKiBuf(Re_Xferred) = InData%h_cfb_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%h_cfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cfb_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%h_cfb_u,1), UBOUND(InData%h_cfb_u,1) + ReKiBuf(Re_Xferred) = InData%h_cfb_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_lfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lfb_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_lfb_l,1), UBOUND(InData%I_lfb_l,1) + ReKiBuf(Re_Xferred) = InData%I_lfb_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_lfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lfb_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_lfb_u,1), UBOUND(InData%I_lfb_u,1) + ReKiBuf(Re_Xferred) = InData%I_lfb_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_rfb_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rfb_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rfb_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_rfb_l,1), UBOUND(InData%I_rfb_l,1) + ReKiBuf(Re_Xferred) = InData%I_rfb_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_rfb_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rfb_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rfb_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_rfb_u,1), UBOUND(InData%I_rfb_u,1) + ReKiBuf(Re_Xferred) = InData%I_rfb_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m_mg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_mg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_mg_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m_mg_l,1), UBOUND(InData%m_mg_l,1) + ReKiBuf(Re_Xferred) = InData%m_mg_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%m_mg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%m_mg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%m_mg_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%m_mg_u,1), UBOUND(InData%m_mg_u,1) + ReKiBuf(Re_Xferred) = InData%m_mg_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%h_cmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cmg_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%h_cmg_l,1), UBOUND(InData%h_cmg_l,1) + ReKiBuf(Re_Xferred) = InData%h_cmg_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%h_cmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%h_cmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%h_cmg_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%h_cmg_u,1), UBOUND(InData%h_cmg_u,1) + ReKiBuf(Re_Xferred) = InData%h_cmg_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_lmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lmg_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_lmg_l,1), UBOUND(InData%I_lmg_l,1) + ReKiBuf(Re_Xferred) = InData%I_lmg_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_lmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_lmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_lmg_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_lmg_u,1), UBOUND(InData%I_lmg_u,1) + ReKiBuf(Re_Xferred) = InData%I_lmg_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_rmg_l) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rmg_l,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rmg_l,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_rmg_l,1), UBOUND(InData%I_rmg_l,1) + ReKiBuf(Re_Xferred) = InData%I_rmg_l(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%I_rmg_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%I_rmg_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_rmg_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%I_rmg_u,1), UBOUND(InData%I_rmg_u,1) + ReKiBuf(Re_Xferred) = InData%I_rmg_u(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cfl_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cfl_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cfl_fb,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Cfl_fb,1), UBOUND(InData%Cfl_fb,1) + ReKiBuf(Re_Xferred) = InData%Cfl_fb(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Cfr_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Cfr_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Cfr_fb,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Cfr_fb,1), UBOUND(InData%Cfr_fb,1) + ReKiBuf(Re_Xferred) = InData%Cfr_fb(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%CM0_fb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CM0_fb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CM0_fb,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%CM0_fb,1), UBOUND(InData%CM0_fb,1) + ReKiBuf(Re_Xferred) = InData%CM0_fb(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + ReKiBuf(Re_Xferred) = InData%MGvolume + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MDivSize Re_Xferred = Re_Xferred + 1 - OutData%Cd2 = ReKiBuf(Re_Xferred) + IntKiBuf(Int_Xferred) = InData%MCoefMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrCoefIDIndx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%MmbrFilledIDIndx + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%FillFSLoc Re_Xferred = Re_Xferred + 1 - OutData%CdMG2 = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%FillDens Re_Xferred = Re_Xferred + 1 - OutData%Ca2 = ReKiBuf(Re_Xferred) + IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackMemberType + + SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Morison_MemberType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIndx not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIndx)) DEALLOCATE(OutData%NodeIndx) + ALLOCATE(OutData%NodeIndx(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIndx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeIndx,1), UBOUND(OutData%NodeIndx,1) + OutData%NodeIndx(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NElements = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%CaMG2 = ReKiBuf(Re_Xferred) + OutData%cosPhi_ref = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%Cp2 = ReKiBuf(Re_Xferred) + OutData%dl = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%CpMG2 = ReKiBuf(Re_Xferred) + i1_l = LBOUND(OutData%k,1) + i1_u = UBOUND(OutData%k,1) + DO i1 = LBOUND(OutData%k,1), UBOUND(OutData%k,1) + OutData%k(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%kkt,1) + i1_u = UBOUND(OutData%kkt,1) + i2_l = LBOUND(OutData%kkt,2) + i2_u = UBOUND(OutData%kkt,2) + DO i2 = LBOUND(OutData%kkt,2), UBOUND(OutData%kkt,2) + DO i1 = LBOUND(OutData%kkt,1), UBOUND(OutData%kkt,1) + OutData%kkt(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%Ak,1) + i1_u = UBOUND(OutData%Ak,1) + i2_l = LBOUND(OutData%Ak,2) + i2_u = UBOUND(OutData%Ak,2) + DO i2 = LBOUND(OutData%Ak,2), UBOUND(OutData%Ak,2) + DO i1 = LBOUND(OutData%Ak,1), UBOUND(OutData%Ak,1) + OutData%Ak(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! R not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%R)) DEALLOCATE(OutData%R) + ALLOCATE(OutData%R(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%R.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%R,1), UBOUND(OutData%R,1) + OutData%R(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RMG)) DEALLOCATE(OutData%RMG) + ALLOCATE(OutData%RMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%RMG,1), UBOUND(OutData%RMG,1) + OutData%RMG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Rin not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Rin)) DEALLOCATE(OutData%Rin) + ALLOCATE(OutData%Rin(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Rin.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Rin,1), UBOUND(OutData%Rin,1) + OutData%Rin(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%tMG)) DEALLOCATE(OutData%tMG) + ALLOCATE(OutData%tMG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%tMG,1), UBOUND(OutData%tMG,1) + OutData%tMG(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MGdensity not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MGdensity)) DEALLOCATE(OutData%MGdensity) + ALLOCATE(OutData%MGdensity(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MGdensity.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MGdensity,1), UBOUND(OutData%MGdensity,1) + OutData%MGdensity(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dRdl_mg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dRdl_mg)) DEALLOCATE(OutData%dRdl_mg) + ALLOCATE(OutData%dRdl_mg(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dRdl_mg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dRdl_mg,1), UBOUND(OutData%dRdl_mg,1) + OutData%dRdl_mg(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dRdl_in not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dRdl_in)) DEALLOCATE(OutData%dRdl_in) + ALLOCATE(OutData%dRdl_in(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dRdl_in.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dRdl_in,1), UBOUND(OutData%dRdl_in,1) + OutData%dRdl_in(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%Vinner = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%AxCa2 = ReKiBuf(Re_Xferred) + OutData%Vouter = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%AxCaMG2 = ReKiBuf(Re_Xferred) + OutData%Vballast = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%AxCp2 = ReKiBuf(Re_Xferred) + OutData%Vsubmerged = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%AxCpMG2 = ReKiBuf(Re_Xferred) + OutData%l_fill = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%InpMbrDist1 = ReKiBuf(Re_Xferred) + OutData%h_fill = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%InpMbrDist2 = ReKiBuf(Re_Xferred) + OutData%z_overfill = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%InpMbrLen = ReKiBuf(Re_Xferred) + OutData%h_floor = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%InpMbrIndx = IntKiBuf(Int_Xferred) + OutData%i_floor = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%memfloodstatus = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! floodstatus not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%floodstatus)) DEALLOCATE(OutData%floodstatus) + ALLOCATE(OutData%floodstatus(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%floodstatus.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%floodstatus,1), UBOUND(OutData%floodstatus,1) + OutData%floodstatus(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha)) DEALLOCATE(OutData%alpha) + ALLOCATE(OutData%alpha(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%alpha,1), UBOUND(OutData%alpha,1) + OutData%alpha(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha_fb)) DEALLOCATE(OutData%alpha_fb) + ALLOCATE(OutData%alpha_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%alpha_fb,1), UBOUND(OutData%alpha_fb,1) + OutData%alpha_fb(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! alpha_fb_star not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%alpha_fb_star)) DEALLOCATE(OutData%alpha_fb_star) + ALLOCATE(OutData%alpha_fb_star(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%alpha_fb_star.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%alpha_fb_star,1), UBOUND(OutData%alpha_fb_star,1) + OutData%alpha_fb_star(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cd not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cd)) DEALLOCATE(OutData%Cd) + ALLOCATE(OutData%Cd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Cd,1), UBOUND(OutData%Cd,1) + OutData%Cd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ca not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Ca)) DEALLOCATE(OutData%Ca) + ALLOCATE(OutData%Ca(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ca.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Ca,1), UBOUND(OutData%Ca,1) + OutData%Ca(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cp not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cp)) DEALLOCATE(OutData%Cp) + ALLOCATE(OutData%Cp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Cp,1), UBOUND(OutData%Cp,1) + OutData%Cp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCd not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCd)) DEALLOCATE(OutData%AxCd) + ALLOCATE(OutData%AxCd(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCd.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AxCd,1), UBOUND(OutData%AxCd,1) + OutData%AxCd(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCa not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCa)) DEALLOCATE(OutData%AxCa) + ALLOCATE(OutData%AxCa(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCa.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AxCa,1), UBOUND(OutData%AxCa,1) + OutData%AxCa(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxCp not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AxCp)) DEALLOCATE(OutData%AxCp) + ALLOCATE(OutData%AxCp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AxCp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AxCp,1), UBOUND(OutData%AxCp,1) + OutData%AxCp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_fb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_fb_l)) DEALLOCATE(OutData%m_fb_l) + ALLOCATE(OutData%m_fb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_fb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m_fb_l,1), UBOUND(OutData%m_fb_l,1) + OutData%m_fb_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_fb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_fb_u)) DEALLOCATE(OutData%m_fb_u) + ALLOCATE(OutData%m_fb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_fb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m_fb_u,1), UBOUND(OutData%m_fb_u,1) + OutData%m_fb_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cfb_l)) DEALLOCATE(OutData%h_cfb_l) + ALLOCATE(OutData%h_cfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%h_cfb_l,1), UBOUND(OutData%h_cfb_l,1) + OutData%h_cfb_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cfb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cfb_u)) DEALLOCATE(OutData%h_cfb_u) + ALLOCATE(OutData%h_cfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%h_cfb_u,1), UBOUND(OutData%h_cfb_u,1) + OutData%h_cfb_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%R_LToG,1) - i1_u = UBOUND(OutData%R_LToG,1) - i2_l = LBOUND(OutData%R_LToG,2) - i2_u = UBOUND(OutData%R_LToG,2) - DO i2 = LBOUND(OutData%R_LToG,2), UBOUND(OutData%R_LToG,2) - DO i1 = LBOUND(OutData%R_LToG,1), UBOUND(OutData%R_LToG,1) - OutData%R_LToG(i1,i2) = ReKiBuf(Re_Xferred) + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lfb_l)) DEALLOCATE(OutData%I_lfb_l) + ALLOCATE(OutData%I_lfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_lfb_l,1), UBOUND(OutData%I_lfb_l,1) + OutData%I_lfb_l(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - END DO - OutData%NumSplits = IntKiBuf(Int_Xferred) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lfb_u not allocated Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Splits,1) - i1_u = UBOUND(OutData%Splits,1) - DO i1 = LBOUND(OutData%Splits,1), UBOUND(OutData%Splits,1) - OutData%Splits(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lfb_u)) DEALLOCATE(OutData%I_lfb_u) + ALLOCATE(OutData%I_lfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_lfb_u,1), UBOUND(OutData%I_lfb_u,1) + OutData%I_lfb_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rfb_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rfb_l)) DEALLOCATE(OutData%I_rfb_l) + ALLOCATE(OutData%I_rfb_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rfb_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_rfb_l,1), UBOUND(OutData%I_rfb_l,1) + OutData%I_rfb_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rfb_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rfb_u)) DEALLOCATE(OutData%I_rfb_u) + ALLOCATE(OutData%I_rfb_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rfb_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_rfb_u,1), UBOUND(OutData%I_rfb_u,1) + OutData%I_rfb_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_mg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_mg_l)) DEALLOCATE(OutData%m_mg_l) + ALLOCATE(OutData%m_mg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_mg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m_mg_l,1), UBOUND(OutData%m_mg_l,1) + OutData%m_mg_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! m_mg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%m_mg_u)) DEALLOCATE(OutData%m_mg_u) + ALLOCATE(OutData%m_mg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%m_mg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%m_mg_u,1), UBOUND(OutData%m_mg_u,1) + OutData%m_mg_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cmg_l)) DEALLOCATE(OutData%h_cmg_l) + ALLOCATE(OutData%h_cmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%h_cmg_l,1), UBOUND(OutData%h_cmg_l,1) + OutData%h_cmg_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! h_cmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%h_cmg_u)) DEALLOCATE(OutData%h_cmg_u) + ALLOCATE(OutData%h_cmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%h_cmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%h_cmg_u,1), UBOUND(OutData%h_cmg_u,1) + OutData%h_cmg_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lmg_l)) DEALLOCATE(OutData%I_lmg_l) + ALLOCATE(OutData%I_lmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_lmg_l,1), UBOUND(OutData%I_lmg_l,1) + OutData%I_lmg_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_lmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_lmg_u)) DEALLOCATE(OutData%I_lmg_u) + ALLOCATE(OutData%I_lmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_lmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_lmg_u,1), UBOUND(OutData%I_lmg_u,1) + OutData%I_lmg_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rmg_l not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rmg_l)) DEALLOCATE(OutData%I_rmg_l) + ALLOCATE(OutData%I_rmg_l(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rmg_l.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_rmg_l,1), UBOUND(OutData%I_rmg_l,1) + OutData%I_rmg_l(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_rmg_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%I_rmg_u)) DEALLOCATE(OutData%I_rmg_u) + ALLOCATE(OutData%I_rmg_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_rmg_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%I_rmg_u,1), UBOUND(OutData%I_rmg_u,1) + OutData%I_rmg_u(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cfl_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cfl_fb)) DEALLOCATE(OutData%Cfl_fb) + ALLOCATE(OutData%Cfl_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cfl_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Cfl_fb,1), UBOUND(OutData%Cfl_fb,1) + OutData%Cfl_fb(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Cfr_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Cfr_fb)) DEALLOCATE(OutData%Cfr_fb) + ALLOCATE(OutData%Cfr_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Cfr_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Cfr_fb,1), UBOUND(OutData%Cfr_fb,1) + OutData%Cfr_fb(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CM0_fb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CM0_fb)) DEALLOCATE(OutData%CM0_fb) + ALLOCATE(OutData%CM0_fb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CM0_fb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%CM0_fb,1), UBOUND(OutData%CM0_fb,1) + OutData%CM0_fb(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF OutData%MGvolume = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%MDivSize = ReKiBuf(Re_Xferred) @@ -2918,18 +4007,6 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%FillDens = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%F_Bouy,1) - i1_u = UBOUND(OutData%F_Bouy,1) - DO i1 = LBOUND(OutData%F_Bouy,1), UBOUND(OutData%F_Bouy,1) - OutData%F_Bouy(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%F_DP,1) - i1_u = UBOUND(OutData%F_DP,1) - DO i1 = LBOUND(OutData%F_DP,1), UBOUND(OutData%F_DP,1) - OutData%F_DP(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_UnPackMemberType @@ -3099,6 +4176,14 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%MemberCpMG2 Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCdMG2 + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%MemberAxCa1 Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%MemberAxCa2 @@ -3169,6 +4254,14 @@ SUBROUTINE Morison_UnPackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt Re_Xferred = Re_Xferred + 1 OutData%MemberCpMG2 = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCd1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCd2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCdMG1 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MemberAxCdMG2 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%MemberAxCa1 = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%MemberAxCa2 = ReKiBuf(Re_Xferred) @@ -3772,12 +4865,6 @@ SUBROUTINE Morison_PackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%JointIDIndx Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumMarkers - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%Markers,1), UBOUND(InData%Markers,1) - IntKiBuf(Int_Xferred) = InData%Markers(i1) - Int_Xferred = Int_Xferred + 1 - END DO END SUBROUTINE Morison_PackJOutput SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -3793,7 +4880,6 @@ SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackJOutput' @@ -3811,14 +4897,6 @@ SUBROUTINE Morison_UnPackJOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%JointIDIndx = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%NumMarkers = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%Markers,1) - i1_u = UBOUND(OutData%Markers,1) - DO i1 = LBOUND(OutData%Markers,1), UBOUND(OutData%Markers,1) - OutData%Markers(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO END SUBROUTINE Morison_UnPackJOutput SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) @@ -4621,67 +5699,24 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%WtrDpth Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MSL2SWL - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NJoints - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NNodes - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%TotalPossibleSuperMembers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%InpJoints) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%InpJoints,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpJoints,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%InpJoints,1), UBOUND(InData%InpJoints,1) - CALL Morison_Packjointtype( Re_Buf, Db_Buf, Int_Buf, InData%InpJoints(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpJoints - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN + ReKiBuf(Re_Xferred) = InData%MSL2SWL + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%InpJoints) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%InpJoints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%InpJoints,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) - CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, OnlySize ) ! Nodes + DO i1 = LBOUND(InData%InpJoints,1), UBOUND(InData%InpJoints,1) + CALL Morison_Packjointtype( Re_Buf, Db_Buf, Int_Buf, InData%InpJoints(i1), ErrStat2, ErrMsg2, OnlySize ) ! InpJoints CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4711,20 +5746,18 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E ENDIF END DO END IF - IntKiBuf(Int_Xferred) = InData%NElements - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Elements) ) THEN + IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elements,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elements,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Elements,1), UBOUND(InData%Elements,1) - CALL Morison_Packmembertype( Re_Buf, Db_Buf, Int_Buf, InData%Elements(i1), ErrStat2, ErrMsg2, OnlySize ) ! Elements + DO i1 = LBOUND(InData%Nodes,1), UBOUND(InData%Nodes,1) + CALL Morison_Packnodetype( Re_Buf, Db_Buf, Int_Buf, InData%Nodes(i1), ErrStat2, ErrMsg2, OnlySize ) ! Nodes CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4852,6 +5885,10 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%SimplCpMG Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCd + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SimplAxCdMG + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%SimplAxCa Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%SimplAxCaMG @@ -5350,8 +6387,6 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Int_Xferred = Int_Xferred + 1 OutData%NNodes = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%TotalPossibleSuperMembers = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InpJoints not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -5464,64 +6499,6 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%NElements = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elements not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Elements)) DEALLOCATE(OutData%Elements) - ALLOCATE(OutData%Elements(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elements.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%Elements,1), UBOUND(OutData%Elements,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL Morison_Unpackmembertype( Re_Buf, Db_Buf, Int_Buf, OutData%Elements(i1), ErrStat2, ErrMsg2 ) ! Elements - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF OutData%NAxCoefs = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AxialCoefs not allocated @@ -5650,6 +6627,10 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = Re_Xferred + 1 OutData%SimplCpMG = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCd = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SimplAxCdMG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%SimplAxCa = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%SimplAxCaMG = ReKiBuf(Re_Xferred) @@ -6362,77 +7343,6 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - CALL MeshPack( InData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LumpedMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF ( .NOT. ALLOCATED(InData%Morison_Rad) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Morison_Rad,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Morison_Rad,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%Morison_Rad,1), UBOUND(InData%Morison_Rad,1) - ReKiBuf(Re_Xferred) = InData%Morison_Rad(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6473,127 +7383,29 @@ SUBROUTINE Morison_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Morison_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LumpedMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Morison_Rad not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Morison_Rad)) DEALLOCATE(OutData%Morison_Rad) - ALLOCATE(OutData%Morison_Rad(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Morison_Rad.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%Morison_Rad,1), UBOUND(OutData%Morison_Rad,1) - OutData%Morison_Rad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END DO - END IF + TYPE(Morison_InitOutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackInitOutput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7678,9 +8490,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_D,2), UBOUND(InData%D_F_D,2) - DO i1 = LBOUND(InData%D_F_D,1), UBOUND(InData%D_F_D,1) - ReKiBuf(Re_Xferred) = InData%D_F_D(i1,i2) + DO i2 = LBOUND(InData%F_D,2), UBOUND(InData%F_D,2) + DO i1 = LBOUND(InData%F_D,1), UBOUND(InData%F_D,1) + ReKiBuf(Re_Xferred) = InData%F_D(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7698,9 +8510,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_I,2), UBOUND(InData%D_F_I,2) - DO i1 = LBOUND(InData%D_F_I,1), UBOUND(InData%D_F_I,1) - ReKiBuf(Re_Xferred) = InData%D_F_I(i1,i2) + DO i2 = LBOUND(InData%F_I,2), UBOUND(InData%F_I,2) + DO i1 = LBOUND(InData%F_I,1), UBOUND(InData%F_I,1) + ReKiBuf(Re_Xferred) = InData%F_I(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7718,9 +8530,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_B,2), UBOUND(InData%D_F_B,2) - DO i1 = LBOUND(InData%D_F_B,1), UBOUND(InData%D_F_B,1) - ReKiBuf(Re_Xferred) = InData%D_F_B(i1,i2) + DO i2 = LBOUND(InData%F_A,2), UBOUND(InData%F_A,2) + DO i1 = LBOUND(InData%F_A,1), UBOUND(InData%F_A,1) + ReKiBuf(Re_Xferred) = InData%F_A(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7738,9 +8550,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_AM,2), UBOUND(InData%D_F_AM,2) - DO i1 = LBOUND(InData%D_F_AM,1), UBOUND(InData%D_F_AM,1) - ReKiBuf(Re_Xferred) = InData%D_F_AM(i1,i2) + DO i2 = LBOUND(InData%F_B,2), UBOUND(InData%F_B,2) + DO i1 = LBOUND(InData%F_B,1), UBOUND(InData%F_B,1) + ReKiBuf(Re_Xferred) = InData%F_B(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7758,9 +8570,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_AM_M,2), UBOUND(InData%D_F_AM_M,2) - DO i1 = LBOUND(InData%D_F_AM_M,1), UBOUND(InData%D_F_AM_M,1) - ReKiBuf(Re_Xferred) = InData%D_F_AM_M(i1,i2) + DO i2 = LBOUND(InData%F_BF,2), UBOUND(InData%F_BF,2) + DO i1 = LBOUND(InData%F_BF,1), UBOUND(InData%F_BF,1) + ReKiBuf(Re_Xferred) = InData%F_BF(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7778,9 +8590,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_AM_MG,2), UBOUND(InData%D_F_AM_MG,2) - DO i1 = LBOUND(InData%D_F_AM_MG,1), UBOUND(InData%D_F_AM_MG,1) - ReKiBuf(Re_Xferred) = InData%D_F_AM_MG(i1,i2) + DO i2 = LBOUND(InData%F_If,2), UBOUND(InData%F_If,2) + DO i1 = LBOUND(InData%F_If,1), UBOUND(InData%F_If,1) + ReKiBuf(Re_Xferred) = InData%F_If(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7798,9 +8610,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_AM_F,2), UBOUND(InData%D_F_AM_F,2) - DO i1 = LBOUND(InData%D_F_AM_F,1), UBOUND(InData%D_F_AM_F,1) - ReKiBuf(Re_Xferred) = InData%D_F_AM_F(i1,i2) + DO i2 = LBOUND(InData%F_WMG,2), UBOUND(InData%F_WMG,2) + DO i1 = LBOUND(InData%F_WMG,1), UBOUND(InData%F_WMG,1) + ReKiBuf(Re_Xferred) = InData%F_WMG(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7818,9 +8630,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_FV,2), UBOUND(InData%D_FV,2) - DO i1 = LBOUND(InData%D_FV,1), UBOUND(InData%D_FV,1) - ReKiBuf(Re_Xferred) = InData%D_FV(i1,i2) + DO i2 = LBOUND(InData%F_IMG,2), UBOUND(InData%F_IMG,2) + DO i1 = LBOUND(InData%F_IMG,1), UBOUND(InData%F_IMG,1) + ReKiBuf(Re_Xferred) = InData%F_IMG(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7838,9 +8650,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FV,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_FA,2), UBOUND(InData%D_FA,2) - DO i1 = LBOUND(InData%D_FA,1), UBOUND(InData%D_FA,1) - ReKiBuf(Re_Xferred) = InData%D_FA(i1,i2) + DO i2 = LBOUND(InData%FV,2), UBOUND(InData%FV,2) + DO i1 = LBOUND(InData%FV,1), UBOUND(InData%FV,1) + ReKiBuf(Re_Xferred) = InData%FV(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7858,9 +8670,11 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FA,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%D_FDynP,1), UBOUND(InData%D_FDynP,1) - ReKiBuf(Re_Xferred) = InData%D_FDynP(i1) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%FA,2), UBOUND(InData%FA,2) + DO i1 = LBOUND(InData%FA,1), UBOUND(InData%FA,1) + ReKiBuf(Re_Xferred) = InData%FA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF IF ( .NOT. ALLOCATED(InData%FDynP) ) THEN @@ -7873,8 +8687,10 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FDynP,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%FDynP)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FDynP))-1 ) = PACK(InData%FDynP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FDynP) + DO i1 = LBOUND(InData%FDynP,1), UBOUND(InData%FDynP,1) + ReKiBuf(Re_Xferred) = InData%FDynP(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%F_DP) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -7889,9 +8705,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_B,2), UBOUND(InData%L_F_B,2) - DO i1 = LBOUND(InData%L_F_B,1), UBOUND(InData%L_F_B,1) - ReKiBuf(Re_Xferred) = InData%L_F_B(i1,i2) + DO i2 = LBOUND(InData%F_DP,2), UBOUND(InData%F_DP,2) + DO i1 = LBOUND(InData%F_DP,1), UBOUND(InData%F_DP,1) + ReKiBuf(Re_Xferred) = InData%F_DP(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7909,9 +8725,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%vrel,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_D,2), UBOUND(InData%L_F_D,2) - DO i1 = LBOUND(InData%L_F_D,1), UBOUND(InData%L_F_D,1) - ReKiBuf(Re_Xferred) = InData%L_F_D(i1,i2) + DO i2 = LBOUND(InData%vrel,2), UBOUND(InData%vrel,2) + DO i1 = LBOUND(InData%vrel,1), UBOUND(InData%vrel,1) + ReKiBuf(Re_Xferred) = InData%vrel(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7926,8 +8742,10 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%nodeInWater)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%nodeInWater))-1 ) = PACK(InData%nodeInWater,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%nodeInWater) + DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) + IntKiBuf(Int_Xferred) = InData%nodeInWater(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -7942,9 +8760,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_I,2), UBOUND(InData%L_F_I,2) - DO i1 = LBOUND(InData%L_F_I,1), UBOUND(InData%L_F_I,1) - ReKiBuf(Re_Xferred) = InData%L_F_I(i1,i2) + DO i2 = LBOUND(InData%F_B_End,2), UBOUND(InData%F_B_End,2) + DO i1 = LBOUND(InData%F_B_End,1), UBOUND(InData%F_B_End,1) + ReKiBuf(Re_Xferred) = InData%F_B_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7962,9 +8780,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_DP,2), UBOUND(InData%L_F_DP,2) - DO i1 = LBOUND(InData%L_F_DP,1), UBOUND(InData%L_F_DP,1) - ReKiBuf(Re_Xferred) = InData%L_F_DP(i1,i2) + DO i2 = LBOUND(InData%F_D_End,2), UBOUND(InData%F_D_End,2) + DO i1 = LBOUND(InData%F_D_End,1), UBOUND(InData%F_D_End,1) + ReKiBuf(Re_Xferred) = InData%F_D_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -7982,9 +8800,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_AM,2), UBOUND(InData%L_F_AM,2) - DO i1 = LBOUND(InData%L_F_AM,1), UBOUND(InData%L_F_AM,1) - ReKiBuf(Re_Xferred) = InData%L_F_AM(i1,i2) + DO i2 = LBOUND(InData%F_I_End,2), UBOUND(InData%F_I_End,2) + DO i1 = LBOUND(InData%F_I_End,1), UBOUND(InData%F_I_End,1) + ReKiBuf(Re_Xferred) = InData%F_I_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8002,9 +8820,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_FV,2), UBOUND(InData%L_FV,2) - DO i1 = LBOUND(InData%L_FV,1), UBOUND(InData%L_FV,1) - ReKiBuf(Re_Xferred) = InData%L_FV(i1,i2) + DO i2 = LBOUND(InData%F_IMG_End,2), UBOUND(InData%F_IMG_End,2) + DO i1 = LBOUND(InData%F_IMG_End,1), UBOUND(InData%F_IMG_End,1) + ReKiBuf(Re_Xferred) = InData%F_IMG_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8022,9 +8840,9 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_FA,2), UBOUND(InData%L_FA,2) - DO i1 = LBOUND(InData%L_FA,1), UBOUND(InData%L_FA,1) - ReKiBuf(Re_Xferred) = InData%L_FA(i1,i2) + DO i2 = LBOUND(InData%F_A_End,2), UBOUND(InData%F_A_End,2) + DO i1 = LBOUND(InData%F_A_End,1), UBOUND(InData%F_A_End,1) + ReKiBuf(Re_Xferred) = InData%F_A_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8042,9 +8860,11 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%L_FDynP,1), UBOUND(InData%L_FDynP,1) - ReKiBuf(Re_Xferred) = InData%L_FDynP(i1) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%F_BF_End,2), UBOUND(InData%F_BF_End,2) + DO i1 = LBOUND(InData%F_BF_End,1), UBOUND(InData%F_BF_End,1) + ReKiBuf(Re_Xferred) = InData%F_BF_End(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF IntKiBuf(Int_Xferred) = InData%LastIndWave @@ -8095,9 +8915,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_D,2), UBOUND(OutData%D_F_D,2) - DO i1 = LBOUND(OutData%D_F_D,1), UBOUND(OutData%D_F_D,1) - OutData%D_F_D(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_D,2), UBOUND(OutData%F_D,2) + DO i1 = LBOUND(OutData%F_D,1), UBOUND(OutData%F_D,1) + OutData%F_D(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8118,9 +8938,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_I,2), UBOUND(OutData%D_F_I,2) - DO i1 = LBOUND(OutData%D_F_I,1), UBOUND(OutData%D_F_I,1) - OutData%D_F_I(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_I,2), UBOUND(OutData%F_I,2) + DO i1 = LBOUND(OutData%F_I,1), UBOUND(OutData%F_I,1) + OutData%F_I(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8141,9 +8961,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_B,2), UBOUND(OutData%D_F_B,2) - DO i1 = LBOUND(OutData%D_F_B,1), UBOUND(OutData%D_F_B,1) - OutData%D_F_B(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_A,2), UBOUND(OutData%F_A,2) + DO i1 = LBOUND(OutData%F_A,1), UBOUND(OutData%F_A,1) + OutData%F_A(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8164,9 +8984,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_AM,2), UBOUND(OutData%D_F_AM,2) - DO i1 = LBOUND(OutData%D_F_AM,1), UBOUND(OutData%D_F_AM,1) - OutData%D_F_AM(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_B,2), UBOUND(OutData%F_B,2) + DO i1 = LBOUND(OutData%F_B,1), UBOUND(OutData%F_B,1) + OutData%F_B(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8187,9 +9007,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_AM_M,2), UBOUND(OutData%D_F_AM_M,2) - DO i1 = LBOUND(OutData%D_F_AM_M,1), UBOUND(OutData%D_F_AM_M,1) - OutData%D_F_AM_M(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_BF,2), UBOUND(OutData%F_BF,2) + DO i1 = LBOUND(OutData%F_BF,1), UBOUND(OutData%F_BF,1) + OutData%F_BF(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8210,9 +9030,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_If.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_AM_MG,2), UBOUND(OutData%D_F_AM_MG,2) - DO i1 = LBOUND(OutData%D_F_AM_MG,1), UBOUND(OutData%D_F_AM_MG,1) - OutData%D_F_AM_MG(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_If,2), UBOUND(OutData%F_If,2) + DO i1 = LBOUND(OutData%F_If,1), UBOUND(OutData%F_If,1) + OutData%F_If(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8233,9 +9053,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_F_AM_F,2), UBOUND(OutData%D_F_AM_F,2) - DO i1 = LBOUND(OutData%D_F_AM_F,1), UBOUND(OutData%D_F_AM_F,1) - OutData%D_F_AM_F(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_WMG,2), UBOUND(OutData%F_WMG,2) + DO i1 = LBOUND(OutData%F_WMG,1), UBOUND(OutData%F_WMG,1) + OutData%F_WMG(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8256,9 +9076,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_FV,2), UBOUND(OutData%D_FV,2) - DO i1 = LBOUND(OutData%D_FV,1), UBOUND(OutData%D_FV,1) - OutData%D_FV(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_IMG,2), UBOUND(OutData%F_IMG,2) + DO i1 = LBOUND(OutData%F_IMG,1), UBOUND(OutData%F_IMG,1) + OutData%F_IMG(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8279,9 +9099,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FV.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D_FA,2), UBOUND(OutData%D_FA,2) - DO i1 = LBOUND(OutData%D_FA,1), UBOUND(OutData%D_FA,1) - OutData%D_FA(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%FV,2), UBOUND(OutData%FV,2) + DO i1 = LBOUND(OutData%FV,1), UBOUND(OutData%FV,1) + OutData%FV(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8302,8 +9122,28 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FA.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%D_FDynP,1), UBOUND(OutData%D_FDynP,1) - OutData%D_FDynP(i1) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%FA,2), UBOUND(OutData%FA,2) + DO i1 = LBOUND(OutData%FA,1), UBOUND(OutData%FA,1) + OutData%FA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FDynP not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FDynP)) DEALLOCATE(OutData%FDynP) + ALLOCATE(OutData%FDynP(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FDynP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FDynP,1), UBOUND(OutData%FDynP,1) + OutData%FDynP(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -8323,9 +9163,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_B,2), UBOUND(OutData%L_F_B,2) - DO i1 = LBOUND(OutData%L_F_B,1), UBOUND(OutData%L_F_B,1) - OutData%L_F_B(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_DP,2), UBOUND(OutData%F_DP,2) + DO i1 = LBOUND(OutData%F_DP,1), UBOUND(OutData%F_DP,1) + OutData%F_DP(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8346,9 +9186,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%vrel.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_D,2), UBOUND(OutData%L_F_D,2) - DO i1 = LBOUND(OutData%L_F_D,1), UBOUND(OutData%L_F_D,1) - OutData%L_F_D(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%vrel,2), UBOUND(OutData%vrel,2) + DO i1 = LBOUND(OutData%vrel,1), UBOUND(OutData%vrel,1) + OutData%vrel(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8366,15 +9206,10 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%nodeInWater.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%nodeInWater)>0) OutData%nodeInWater = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%nodeInWater))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%nodeInWater) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%nodeInWater,1), UBOUND(OutData%nodeInWater,1) + OutData%nodeInWater(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B_End not allocated Int_Xferred = Int_Xferred + 1 @@ -8392,9 +9227,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_I,2), UBOUND(OutData%L_F_I,2) - DO i1 = LBOUND(OutData%L_F_I,1), UBOUND(OutData%L_F_I,1) - OutData%L_F_I(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_B_End,2), UBOUND(OutData%F_B_End,2) + DO i1 = LBOUND(OutData%F_B_End,1), UBOUND(OutData%F_B_End,1) + OutData%F_B_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8415,9 +9250,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_DP,2), UBOUND(OutData%L_F_DP,2) - DO i1 = LBOUND(OutData%L_F_DP,1), UBOUND(OutData%L_F_DP,1) - OutData%L_F_DP(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_D_End,2), UBOUND(OutData%F_D_End,2) + DO i1 = LBOUND(OutData%F_D_End,1), UBOUND(OutData%F_D_End,1) + OutData%F_D_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8438,9 +9273,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_AM,2), UBOUND(OutData%L_F_AM,2) - DO i1 = LBOUND(OutData%L_F_AM,1), UBOUND(OutData%L_F_AM,1) - OutData%L_F_AM(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_I_End,2), UBOUND(OutData%F_I_End,2) + DO i1 = LBOUND(OutData%F_I_End,1), UBOUND(OutData%F_I_End,1) + OutData%F_I_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8461,9 +9296,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_FV,2), UBOUND(OutData%L_FV,2) - DO i1 = LBOUND(OutData%L_FV,1), UBOUND(OutData%L_FV,1) - OutData%L_FV(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_IMG_End,2), UBOUND(OutData%F_IMG_End,2) + DO i1 = LBOUND(OutData%F_IMG_End,1), UBOUND(OutData%F_IMG_End,1) + OutData%F_IMG_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8484,9 +9319,9 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_FA,2), UBOUND(OutData%L_FA,2) - DO i1 = LBOUND(OutData%L_FA,1), UBOUND(OutData%L_FA,1) - OutData%L_FA(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_A_End,2), UBOUND(OutData%F_A_End,2) + DO i1 = LBOUND(OutData%F_A_End,1), UBOUND(OutData%F_A_End,1) + OutData%F_A_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -8507,9 +9342,11 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%L_FDynP,1), UBOUND(OutData%L_FDynP,1) - OutData%L_FDynP(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(OutData%F_BF_End,2), UBOUND(OutData%F_BF_End,2) + DO i1 = LBOUND(OutData%F_BF_End,1), UBOUND(OutData%F_BF_End,1) + OutData%F_BF_End(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF OutData%LastIndWave = IntKiBuf(Int_Xferred) @@ -9091,11 +9928,15 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%WtrDens Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NNodes + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NMembers Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN + IF ( .NOT. ALLOCATED(InData%Members) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE @@ -9136,10 +9977,10 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ENDIF END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NNodes - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NJoints + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%I_MG_End) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9156,10 +9997,10 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%I_MG_End,3) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%D_F_I,3), UBOUND(InData%D_F_I,3) - DO i2 = LBOUND(InData%D_F_I,2), UBOUND(InData%D_F_I,2) - DO i1 = LBOUND(InData%D_F_I,1), UBOUND(InData%D_F_I,1) - ReKiBuf(Re_Xferred) = InData%D_F_I(i1,i2,i3) + DO i3 = LBOUND(InData%I_MG_End,3), UBOUND(InData%I_MG_End,3) + DO i2 = LBOUND(InData%I_MG_End,2), UBOUND(InData%I_MG_End,2) + DO i1 = LBOUND(InData%I_MG_End,1), UBOUND(InData%I_MG_End,1) + ReKiBuf(Re_Xferred) = InData%I_MG_End(i1,i2,i3) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -9178,12 +10019,10 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%An_End,2) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%D_F_DP,3), UBOUND(InData%D_F_DP,3) - DO i2 = LBOUND(InData%D_F_DP,2), UBOUND(InData%D_F_DP,2) - DO i1 = LBOUND(InData%D_F_DP,1), UBOUND(InData%D_F_DP,1) - ReKiBuf(Re_Xferred) = InData%D_F_DP(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO + DO i2 = LBOUND(InData%An_End,2), UBOUND(InData%An_End,2) + DO i1 = LBOUND(InData%An_End,1), UBOUND(InData%An_End,1) + ReKiBuf(Re_Xferred) = InData%An_End(i1,i2) + Re_Xferred = Re_Xferred + 1 END DO END DO END IF @@ -9197,8 +10036,8 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DragConst_End,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%D_dragConst,1), UBOUND(InData%D_dragConst,1) - ReKiBuf(Re_Xferred) = InData%D_dragConst(i1) + DO i1 = LBOUND(InData%DragConst_End,1), UBOUND(InData%DragConst_End,1) + ReKiBuf(Re_Xferred) = InData%DragConst_End(i1) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -9215,9 +10054,9 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_An,2), UBOUND(InData%L_An,2) - DO i1 = LBOUND(InData%L_An,1), UBOUND(InData%L_An,1) - ReKiBuf(Re_Xferred) = InData%L_An(i1,i2) + DO i2 = LBOUND(InData%F_WMG_End,2), UBOUND(InData%F_WMG_End,2) + DO i1 = LBOUND(InData%F_WMG_End,1), UBOUND(InData%F_WMG_End,1) + ReKiBuf(Re_Xferred) = InData%F_WMG_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -9235,9 +10074,9 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP_Const_End,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%L_F_B,2), UBOUND(InData%L_F_B,2) - DO i1 = LBOUND(InData%L_F_B,1), UBOUND(InData%L_F_B,1) - ReKiBuf(Re_Xferred) = InData%L_F_B(i1,i2) + DO i2 = LBOUND(InData%DP_Const_End,2), UBOUND(InData%DP_Const_End,2) + DO i1 = LBOUND(InData%DP_Const_End,1), UBOUND(InData%DP_Const_End,1) + ReKiBuf(Re_Xferred) = InData%DP_Const_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -9252,13 +10091,9 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Mass_MG_End,1) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%L_F_I,3), UBOUND(InData%L_F_I,3) - DO i2 = LBOUND(InData%L_F_I,2), UBOUND(InData%L_F_I,2) - DO i1 = LBOUND(InData%L_F_I,1), UBOUND(InData%L_F_I,1) - ReKiBuf(Re_Xferred) = InData%L_F_I(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + DO i1 = LBOUND(InData%Mass_MG_End,1), UBOUND(InData%Mass_MG_End,1) + ReKiBuf(Re_Xferred) = InData%Mass_MG_End(i1) + Re_Xferred = Re_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%AM_End) ) THEN @@ -9277,109 +10112,15 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM_End,3) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%L_F_DP,3), UBOUND(InData%L_F_DP,3) - DO i2 = LBOUND(InData%L_F_DP,2), UBOUND(InData%L_F_DP,2) - DO i1 = LBOUND(InData%L_F_DP,1), UBOUND(InData%L_F_DP,1) - ReKiBuf(Re_Xferred) = InData%L_F_DP(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%L_F_BF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_BF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_F_BF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_F_BF,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%L_F_BF,2), UBOUND(InData%L_F_BF,2) - DO i1 = LBOUND(InData%L_F_BF,1), UBOUND(InData%L_F_BF,1) - ReKiBuf(Re_Xferred) = InData%L_F_BF(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%L_AM_M) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_AM_M,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_AM_M,3) - Int_Xferred = Int_Xferred + 2 - - DO i3 = LBOUND(InData%L_AM_M,3), UBOUND(InData%L_AM_M,3) - DO i2 = LBOUND(InData%L_AM_M,2), UBOUND(InData%L_AM_M,2) - DO i1 = LBOUND(InData%L_AM_M,1), UBOUND(InData%L_AM_M,1) - ReKiBuf(Re_Xferred) = InData%L_AM_M(i1,i2,i3) + DO i3 = LBOUND(InData%AM_End,3), UBOUND(InData%AM_End,3) + DO i2 = LBOUND(InData%AM_End,2), UBOUND(InData%AM_End,2) + DO i1 = LBOUND(InData%AM_End,1), UBOUND(InData%AM_End,1) + ReKiBuf(Re_Xferred) = InData%AM_End(i1,i2,i3) Re_Xferred = Re_Xferred + 1 END DO END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%L_dragConst) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%L_dragConst,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%L_dragConst,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%L_dragConst,1), UBOUND(InData%L_dragConst,1) - ReKiBuf(Re_Xferred) = InData%L_dragConst(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IntKiBuf(Int_Xferred) = InData%NDistribMarkers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%distribToNodeIndx) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%distribToNodeIndx,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%distribToNodeIndx,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%distribToNodeIndx,1), UBOUND(InData%distribToNodeIndx,1) - IntKiBuf(Int_Xferred) = InData%distribToNodeIndx(i1) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IntKiBuf(Int_Xferred) = InData%NLumpedMarkers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%lumpedToNodeIndx) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%lumpedToNodeIndx,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%lumpedToNodeIndx,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%lumpedToNodeIndx,1), UBOUND(InData%lumpedToNodeIndx,1) - IntKiBuf(Int_Xferred) = InData%lumpedToNodeIndx(i1) - Int_Xferred = Int_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%WaveVel) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9405,234 +10146,84 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%WaveAcc) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,3) - Int_Xferred = Int_Xferred + 2 - - DO i3 = LBOUND(InData%WaveAcc,3), UBOUND(InData%WaveAcc,3) - DO i2 = LBOUND(InData%WaveAcc,2), UBOUND(InData%WaveAcc,2) - DO i1 = LBOUND(InData%WaveAcc,1), UBOUND(InData%WaveAcc,1) - ReKiBuf(Re_Xferred) = InData%WaveAcc(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%WaveDynP) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%WaveDynP,2), UBOUND(InData%WaveDynP,2) - DO i1 = LBOUND(InData%WaveDynP,1), UBOUND(InData%WaveDynP,1) - ReKiBuf(Re_Xferred) = InData%WaveDynP(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%WaveTime) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveTime,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) - ReKiBuf(Re_Xferred) = InData%WaveTime(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%elementWaterState) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementWaterState,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementWaterState,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementWaterState,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%elementWaterState,2), UBOUND(InData%elementWaterState,2) - DO i1 = LBOUND(InData%elementWaterState,1), UBOUND(InData%elementWaterState,1) - IntKiBuf(Int_Xferred) = InData%elementWaterState(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%elementFillState) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%elementFillState,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%elementFillState,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%elementFillState,1), UBOUND(InData%elementFillState,1) - IntKiBuf(Int_Xferred) = InData%elementFillState(i1) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%nodeInWater) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%nodeInWater,2), UBOUND(InData%nodeInWater,2) - DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) - IntKiBuf(Int_Xferred) = InData%nodeInWater(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%D_F_B) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_B,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%D_F_B,2), UBOUND(InData%D_F_B,2) - DO i1 = LBOUND(InData%D_F_B,1), UBOUND(InData%D_F_B,1) - ReKiBuf(Re_Xferred) = InData%D_F_B(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%D_F_BF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_BF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_BF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_BF,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%D_F_BF,2), UBOUND(InData%D_F_BF,2) - DO i1 = LBOUND(InData%D_F_BF,1), UBOUND(InData%D_F_BF,1) - ReKiBuf(Re_Xferred) = InData%D_F_BF(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%D_F_MG) ) THEN + IF ( .NOT. ALLOCATED(InData%WaveAcc) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_MG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,2) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_F_MG,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_F_MG,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveAcc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveAcc,3) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D_F_MG,2), UBOUND(InData%D_F_MG,2) - DO i1 = LBOUND(InData%D_F_MG,1), UBOUND(InData%D_F_MG,1) - ReKiBuf(Re_Xferred) = InData%D_F_MG(i1,i2) - Re_Xferred = Re_Xferred + 1 + DO i3 = LBOUND(InData%WaveAcc,3), UBOUND(InData%WaveAcc,3) + DO i2 = LBOUND(InData%WaveAcc,2), UBOUND(InData%WaveAcc,2) + DO i1 = LBOUND(InData%WaveAcc,1), UBOUND(InData%WaveAcc,1) + ReKiBuf(Re_Xferred) = InData%WaveAcc(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%D_AM_M) ) THEN + IF ( .NOT. ALLOCATED(InData%WaveDynP) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_M,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_M,3) + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveDynP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveDynP,2) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%D_AM_M,3), UBOUND(InData%D_AM_M,3) - DO i2 = LBOUND(InData%D_AM_M,2), UBOUND(InData%D_AM_M,2) - DO i1 = LBOUND(InData%D_AM_M,1), UBOUND(InData%D_AM_M,1) - ReKiBuf(Re_Xferred) = InData%D_AM_M(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO + DO i2 = LBOUND(InData%WaveDynP,2), UBOUND(InData%WaveDynP,2) + DO i1 = LBOUND(InData%WaveDynP,1), UBOUND(InData%WaveDynP,1) + ReKiBuf(Re_Xferred) = InData%WaveDynP(i1,i2) + Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%D_AM_MG) ) THEN + IF ( .NOT. ALLOCATED(InData%WaveTime) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_MG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_MG,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveTime,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%D_AM_MG,1), UBOUND(InData%D_AM_MG,1) - ReKiBuf(Re_Xferred) = InData%D_AM_MG(i1) + DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) + ReKiBuf(Re_Xferred) = InData%WaveTime(i1) Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%D_AM_F) ) THEN + IF ( .NOT. ALLOCATED(InData%nodeInWater) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D_AM_F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D_AM_F,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%nodeInWater,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%nodeInWater,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%D_AM_F,1), UBOUND(InData%D_AM_F,1) - ReKiBuf(Re_Xferred) = InData%D_AM_F(i1) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%nodeInWater,2), UBOUND(InData%nodeInWater,2) + DO i1 = LBOUND(InData%nodeInWater,1), UBOUND(InData%nodeInWater,1) + IntKiBuf(Int_Xferred) = InData%nodeInWater(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO END DO END IF IntKiBuf(Int_Xferred) = InData%NStepWave @@ -9817,11 +10408,15 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Xferred = 1 OutData%DT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%WtrDens = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%NNodes = IntKiBuf(Int_Xferred) + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NMembers = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9877,10 +10472,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%NNodes = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NJoints = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%NNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NJoints = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! I_MG_End not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9900,10 +10495,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%I_MG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i3 = LBOUND(OutData%D_F_I,3), UBOUND(OutData%D_F_I,3) - DO i2 = LBOUND(OutData%D_F_I,2), UBOUND(OutData%D_F_I,2) - DO i1 = LBOUND(OutData%D_F_I,1), UBOUND(OutData%D_F_I,1) - OutData%D_F_I(i1,i2,i3) = ReKiBuf(Re_Xferred) + DO i3 = LBOUND(OutData%I_MG_End,3), UBOUND(OutData%I_MG_End,3) + DO i2 = LBOUND(OutData%I_MG_End,2), UBOUND(OutData%I_MG_End,2) + DO i1 = LBOUND(OutData%I_MG_End,1), UBOUND(OutData%I_MG_End,1) + OutData%I_MG_End(i1,i2,i3) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -9925,12 +10520,10 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%An_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i3 = LBOUND(OutData%D_F_DP,3), UBOUND(OutData%D_F_DP,3) - DO i2 = LBOUND(OutData%D_F_DP,2), UBOUND(OutData%D_F_DP,2) - DO i1 = LBOUND(OutData%D_F_DP,1), UBOUND(OutData%D_F_DP,1) - OutData%D_F_DP(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + DO i2 = LBOUND(OutData%An_End,2), UBOUND(OutData%An_End,2) + DO i1 = LBOUND(OutData%An_End,1), UBOUND(OutData%An_End,1) + OutData%An_End(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END DO END DO END IF @@ -9947,8 +10540,8 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DragConst_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%D_dragConst,1), UBOUND(OutData%D_dragConst,1) - OutData%D_dragConst(i1) = ReKiBuf(Re_Xferred) + DO i1 = LBOUND(OutData%DragConst_End,1), UBOUND(OutData%DragConst_End,1) + OutData%DragConst_End(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -9968,9 +10561,9 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_An,2), UBOUND(OutData%L_An,2) - DO i1 = LBOUND(OutData%L_An,1), UBOUND(OutData%L_An,1) - OutData%L_An(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%F_WMG_End,2), UBOUND(OutData%F_WMG_End,2) + DO i1 = LBOUND(OutData%F_WMG_End,1), UBOUND(OutData%F_WMG_End,1) + OutData%F_WMG_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -9991,9 +10584,9 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP_Const_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%L_F_B,2), UBOUND(OutData%L_F_B,2) - DO i1 = LBOUND(OutData%L_F_B,1), UBOUND(OutData%L_F_B,1) - OutData%L_F_B(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%DP_Const_End,2), UBOUND(OutData%DP_Const_End,2) + DO i1 = LBOUND(OutData%DP_Const_End,1), UBOUND(OutData%DP_Const_End,1) + OutData%DP_Const_End(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -10011,13 +10604,9 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Mass_MG_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i3 = LBOUND(OutData%L_F_I,3), UBOUND(OutData%L_F_I,3) - DO i2 = LBOUND(OutData%L_F_I,2), UBOUND(OutData%L_F_I,2) - DO i1 = LBOUND(OutData%L_F_I,1), UBOUND(OutData%L_F_I,1) - OutData%L_F_I(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + DO i1 = LBOUND(OutData%Mass_MG_End,1), UBOUND(OutData%Mass_MG_End,1) + OutData%Mass_MG_End(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM_End not allocated @@ -10039,124 +10628,15 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM_End.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i3 = LBOUND(OutData%L_F_DP,3), UBOUND(OutData%L_F_DP,3) - DO i2 = LBOUND(OutData%L_F_DP,2), UBOUND(OutData%L_F_DP,2) - DO i1 = LBOUND(OutData%L_F_DP,1), UBOUND(OutData%L_F_DP,1) - OutData%L_F_DP(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_F_BF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_F_BF)) DEALLOCATE(OutData%L_F_BF) - ALLOCATE(OutData%L_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%L_F_BF,2), UBOUND(OutData%L_F_BF,2) - DO i1 = LBOUND(OutData%L_F_BF,1), UBOUND(OutData%L_F_BF,1) - OutData%L_F_BF(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_AM_M not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_AM_M)) DEALLOCATE(OutData%L_AM_M) - ALLOCATE(OutData%L_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_AM_M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i3 = LBOUND(OutData%L_AM_M,3), UBOUND(OutData%L_AM_M,3) - DO i2 = LBOUND(OutData%L_AM_M,2), UBOUND(OutData%L_AM_M,2) - DO i1 = LBOUND(OutData%L_AM_M,1), UBOUND(OutData%L_AM_M,1) - OutData%L_AM_M(i1,i2,i3) = ReKiBuf(Re_Xferred) + DO i3 = LBOUND(OutData%AM_End,3), UBOUND(OutData%AM_End,3) + DO i2 = LBOUND(OutData%AM_End,2), UBOUND(OutData%AM_End,2) + DO i1 = LBOUND(OutData%AM_End,1), UBOUND(OutData%AM_End,1) + OutData%AM_End(i1,i2,i3) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! L_dragConst not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%L_dragConst)) DEALLOCATE(OutData%L_dragConst) - ALLOCATE(OutData%L_dragConst(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%L_dragConst.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%L_dragConst,1), UBOUND(OutData%L_dragConst,1) - OutData%L_dragConst(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - OutData%NDistribMarkers = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! distribToNodeIndx not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%distribToNodeIndx)) DEALLOCATE(OutData%distribToNodeIndx) - ALLOCATE(OutData%distribToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%distribToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%distribToNodeIndx,1), UBOUND(OutData%distribToNodeIndx,1) - OutData%distribToNodeIndx(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - OutData%NLumpedMarkers = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lumpedToNodeIndx not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%lumpedToNodeIndx)) DEALLOCATE(OutData%lumpedToNodeIndx) - ALLOCATE(OutData%lumpedToNodeIndx(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%lumpedToNodeIndx.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%lumpedToNodeIndx,1), UBOUND(OutData%lumpedToNodeIndx,1) - OutData%lumpedToNodeIndx(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10254,47 +10734,6 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementWaterState not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%elementWaterState)) DEALLOCATE(OutData%elementWaterState) - ALLOCATE(OutData%elementWaterState(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementWaterState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%elementWaterState,2), UBOUND(OutData%elementWaterState,2) - DO i1 = LBOUND(OutData%elementWaterState,1), UBOUND(OutData%elementWaterState,1) - OutData%elementWaterState(i1,i2) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! elementFillState not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%elementFillState)) DEALLOCATE(OutData%elementFillState) - ALLOCATE(OutData%elementFillState(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%elementFillState.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%elementFillState,1), UBOUND(OutData%elementFillState,1) - OutData%elementFillState(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! nodeInWater not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10317,139 +10756,6 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Xferred = Int_Xferred + 1 END DO END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_B not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_B)) DEALLOCATE(OutData%D_F_B) - ALLOCATE(OutData%D_F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_B.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%D_F_B,2), UBOUND(OutData%D_F_B,2) - DO i1 = LBOUND(OutData%D_F_B,1), UBOUND(OutData%D_F_B,1) - OutData%D_F_B(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_BF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_BF)) DEALLOCATE(OutData%D_F_BF) - ALLOCATE(OutData%D_F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%D_F_BF,2), UBOUND(OutData%D_F_BF,2) - DO i1 = LBOUND(OutData%D_F_BF,1), UBOUND(OutData%D_F_BF,1) - OutData%D_F_BF(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_F_MG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_F_MG)) DEALLOCATE(OutData%D_F_MG) - ALLOCATE(OutData%D_F_MG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_F_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%D_F_MG,2), UBOUND(OutData%D_F_MG,2) - DO i1 = LBOUND(OutData%D_F_MG,1), UBOUND(OutData%D_F_MG,1) - OutData%D_F_MG(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_M not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_M)) DEALLOCATE(OutData%D_AM_M) - ALLOCATE(OutData%D_AM_M(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i3 = LBOUND(OutData%D_AM_M,3), UBOUND(OutData%D_AM_M,3) - DO i2 = LBOUND(OutData%D_AM_M,2), UBOUND(OutData%D_AM_M,2) - DO i1 = LBOUND(OutData%D_AM_M,1), UBOUND(OutData%D_AM_M,1) - OutData%D_AM_M(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_MG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_MG)) DEALLOCATE(OutData%D_AM_MG) - ALLOCATE(OutData%D_AM_MG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_MG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%D_AM_MG,1), UBOUND(OutData%D_AM_MG,1) - OutData%D_AM_MG(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D_AM_F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D_AM_F)) DEALLOCATE(OutData%D_AM_F) - ALLOCATE(OutData%D_AM_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D_AM_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%D_AM_F,1), UBOUND(OutData%D_AM_F,1) - OutData%D_AM_F(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO END IF OutData%NStepWave = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 @@ -11213,7 +11519,7 @@ SUBROUTINE Morison_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err END IF ScaleFactor = t_out / t(2) - CALL MeshExtrapInterp1(u1%DistribMesh, u2%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE Morison_Input_ExtrapInterp1 @@ -11270,7 +11576,7 @@ SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) - CALL MeshExtrapInterp2(u1%DistribMesh, u2%DistribMesh, u3%DistribMesh, tin, u_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) END SUBROUTINE Morison_Input_ExtrapInterp2 @@ -11369,7 +11675,7 @@ SUBROUTINE Morison_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Er END IF ScaleFactor = t_out / t(2) - CALL MeshExtrapInterp1(y1%DistribMesh, y2%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) @@ -11434,7 +11740,7 @@ SUBROUTINE Morison_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) - CALL MeshExtrapInterp2(y1%DistribMesh, y2%DistribMesh, y3%DistribMesh, tin, y_out%DistribMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) diff --git a/modules/hydrodyn/src/SS_Excitation.txt b/modules/hydrodyn/src/SS_Excitation.txt index 6efd072bc..72bd6e193 100644 --- a/modules/hydrodyn/src/SS_Excitation.txt +++ b/modules/hydrodyn/src/SS_Excitation.txt @@ -26,7 +26,7 @@ typedef ^ ^ SiKi typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "Header of the output" - typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {:} - - "Units of the output" - -typedef ^ ContinuousStateType ReKi x {:} - - "Continuous States" - +typedef ^ ContinuousStateType R8Ki x {:} - - "Continuous States" - typedef ^ DiscreteStateType SiKi DummyDiscState - - - "" - diff --git a/modules/hydrodyn/src/SS_Excitation_Types.f90 b/modules/hydrodyn/src/SS_Excitation_Types.f90 index 10966b9c6..2ed4153ec 100644 --- a/modules/hydrodyn/src/SS_Excitation_Types.f90 +++ b/modules/hydrodyn/src/SS_Excitation_Types.f90 @@ -36,16 +36,18 @@ MODULE SS_Excitation_Types ! ========= SS_Exc_InitInputType ======= TYPE, PUBLIC :: SS_Exc_InitInputType CHARACTER(1024) :: InputFile !< Name of the input file [-] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] REAL(ReKi) :: WaveDir !< Wave direction [rad] INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: PtfmRefztRot !< The rotation about zt of the body reference frame(s) from xt/yt [radians] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] END TYPE SS_Exc_InitInputType ! ======================= ! ========= SS_Exc_InitOutputType ======= TYPE, PUBLIC :: SS_Exc_InitOutputType - CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] - CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Header of the output [-] + CHARACTER(10) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output [-] END TYPE SS_Exc_InitOutputType ! ======================= ! ========= SS_Exc_ContinuousStateType ======= @@ -77,12 +79,13 @@ MODULE SS_Excitation_Types ! ========= SS_Exc_ParameterType ======= TYPE, PUBLIC :: SS_Exc_ParameterType REAL(DbKi) :: DT !< Time step [s] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] INTEGER(IntKi) :: NStepWave !< Number of timesteps in the WaveTime array [-] INTEGER(IntKi) , DIMENSION(1:6) :: spDOF !< States per DOF [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: N !< Number of states [-] + INTEGER(IntKi) :: numStates !< Number of states [-] REAL(DbKi) :: Tc !< Time shift [s] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] @@ -95,8 +98,8 @@ MODULE SS_Excitation_Types ! ======================= ! ========= SS_Exc_OutputType ======= TYPE, PUBLIC :: SS_Exc_OutputType - REAL(ReKi) , DIMENSION(1:6) :: y !< Force/Moments [-] - REAL(ReKi) , DIMENSION(1:7) :: WriteOutput !< output Data [kN] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: y !< Force/Moments [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< output Data [kN] END TYPE SS_Exc_OutputType ! ======================= CONTAINS @@ -117,8 +120,21 @@ SUBROUTINE SS_Exc_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, E ErrStat = ErrID_None ErrMsg = "" DstInitInputData%InputFile = SrcInitInputData%InputFile + DstInitInputData%NBody = SrcInitInputData%NBody DstInitInputData%WaveDir = SrcInitInputData%WaveDir DstInitInputData%NStepWave = SrcInitInputData%NStepWave +IF (ALLOCATED(SrcInitInputData%PtfmRefztRot)) THEN + i1_l = LBOUND(SrcInitInputData%PtfmRefztRot,1) + i1_u = UBOUND(SrcInitInputData%PtfmRefztRot,1) + IF (.NOT. ALLOCATED(DstInitInputData%PtfmRefztRot)) THEN + ALLOCATE(DstInitInputData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%PtfmRefztRot = SrcInitInputData%PtfmRefztRot +ENDIF IF (ALLOCATED(SrcInitInputData%WaveElev0)) THEN i1_l = LBOUND(SrcInitInputData%WaveElev0,1) i1_u = UBOUND(SrcInitInputData%WaveElev0,1) @@ -154,6 +170,9 @@ SUBROUTINE SS_Exc_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitInputData%PtfmRefztRot)) THEN + DEALLOCATE(InitInputData%PtfmRefztRot) +ENDIF IF (ALLOCATED(InitInputData%WaveElev0)) THEN DEALLOCATE(InitInputData%WaveElev0) ENDIF @@ -198,8 +217,14 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1*LEN(InData%InputFile) ! InputFile + Int_BufSz = Int_BufSz + 1 ! NBody Re_BufSz = Re_BufSz + 1 ! WaveDir Int_BufSz = Int_BufSz + 1 ! NStepWave + Int_BufSz = Int_BufSz + 1 ! PtfmRefztRot allocated yes/no + IF ( ALLOCATED(InData%PtfmRefztRot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! PtfmRefztRot upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PtfmRefztRot) ! PtfmRefztRot + END IF Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no IF ( ALLOCATED(InData%WaveElev0) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WaveElev0 upper/lower bounds for each dimension @@ -241,10 +266,27 @@ SUBROUTINE SS_Exc_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 ReKiBuf(Re_Xferred) = InData%WaveDir Re_Xferred = Re_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NStepWave Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefztRot,1), UBOUND(InData%PtfmRefztRot,1) + DbKiBuf(Db_Xferred) = InData%PtfmRefztRot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%WaveElev0) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -309,10 +351,30 @@ SUBROUTINE SS_Exc_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%WaveDir = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%NStepWave = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefztRot,1), UBOUND(OutData%PtfmRefztRot,1) + OutData%PtfmRefztRot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -366,8 +428,30 @@ SUBROUTINE SS_Exc_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF END SUBROUTINE SS_Exc_CopyInitOutput SUBROUTINE SS_Exc_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -379,6 +463,12 @@ SUBROUTINE SS_Exc_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF END SUBROUTINE SS_Exc_DestroyInitOutput SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -416,8 +506,16 @@ SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -445,18 +543,40 @@ SUBROUTINE SS_Exc_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF END SUBROUTINE SS_Exc_PackInitOutput SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -486,22 +606,46 @@ SUBROUTINE SS_Exc_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%WriteOutputHdr,1) - i1_u = UBOUND(OutData%WriteOutputHdr,1) - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - i1_l = LBOUND(OutData%WriteOutputUnt,1) - i1_u = UBOUND(OutData%WriteOutputUnt,1) - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF END SUBROUTINE SS_Exc_UnPackInitOutput SUBROUTINE SS_Exc_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -1299,6 +1443,7 @@ SUBROUTINE SS_Exc_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM ErrStat = ErrID_None ErrMsg = "" DstParamData%DT = SrcParamData%DT + DstParamData%NBody = SrcParamData%NBody DstParamData%NStepWave = SrcParamData%NStepWave DstParamData%spDOF = SrcParamData%spDOF IF (ALLOCATED(SrcParamData%A)) THEN @@ -1341,7 +1486,7 @@ SUBROUTINE SS_Exc_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM END IF DstParamData%C = SrcParamData%C ENDIF - DstParamData%N = SrcParamData%N + DstParamData%numStates = SrcParamData%numStates DstParamData%Tc = SrcParamData%Tc IF (ALLOCATED(SrcParamData%WaveElev0)) THEN i1_l = LBOUND(SrcParamData%WaveElev0,1) @@ -1431,6 +1576,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_BufSz = 0 Int_BufSz = 0 Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NBody Int_BufSz = Int_BufSz + 1 ! NStepWave Int_BufSz = Int_BufSz + SIZE(InData%spDOF) ! spDOF Int_BufSz = Int_BufSz + 1 ! A allocated yes/no @@ -1448,7 +1594,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C) ! C END IF - Int_BufSz = Int_BufSz + 1 ! N + Int_BufSz = Int_BufSz + 1 ! numStates Db_BufSz = Db_BufSz + 1 ! Tc Int_BufSz = Int_BufSz + 1 ! WaveElev0 allocated yes/no IF ( ALLOCATED(InData%WaveElev0) ) THEN @@ -1489,6 +1635,8 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NStepWave Int_Xferred = Int_Xferred + 1 DO i1 = LBOUND(InData%spDOF,1), UBOUND(InData%spDOF,1) @@ -1550,7 +1698,7 @@ SUBROUTINE SS_Exc_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg END DO END DO END IF - IntKiBuf(Int_Xferred) = InData%N + IntKiBuf(Int_Xferred) = InData%numStates Int_Xferred = Int_Xferred + 1 DbKiBuf(Db_Xferred) = InData%Tc Db_Xferred = Db_Xferred + 1 @@ -1616,6 +1764,8 @@ SUBROUTINE SS_Exc_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Int_Xferred = 1 OutData%DT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%NStepWave = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%spDOF,1) @@ -1688,7 +1838,7 @@ SUBROUTINE SS_Exc_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err END DO END DO END IF - OutData%N = IntKiBuf(Int_Xferred) + OutData%numStates = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 OutData%Tc = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 @@ -1870,8 +2020,30 @@ SUBROUTINE SS_Exc_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, E ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(SrcOutputData%y)) THEN + i1_l = LBOUND(SrcOutputData%y,1) + i1_u = UBOUND(SrcOutputData%y,1) + IF (.NOT. ALLOCATED(DstOutputData%y)) THEN + ALLOCATE(DstOutputData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%y = SrcOutputData%y +ENDIF +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF END SUBROUTINE SS_Exc_CopyOutput SUBROUTINE SS_Exc_DestroyOutput( OutputData, ErrStat, ErrMsg ) @@ -1883,6 +2055,12 @@ SUBROUTINE SS_Exc_DestroyOutput( OutputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(OutputData%y)) THEN + DEALLOCATE(OutputData%y) +ENDIF +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF END SUBROUTINE SS_Exc_DestroyOutput SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1920,8 +2098,16 @@ SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! y allocated yes/no + IF ( ALLOCATED(InData%y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! y upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%y) ! y + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1949,14 +2135,36 @@ SUBROUTINE SS_Exc_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) - ReKiBuf(Re_Xferred) = InData%y(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) - ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + ReKiBuf(Re_Xferred) = InData%y(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Exc_PackOutput SUBROUTINE SS_Exc_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1986,18 +2194,42 @@ SUBROUTINE SS_Exc_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%y,1) - i1_u = UBOUND(OutData%y,1) - DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) - OutData%y(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%WriteOutput,1) - i1_u = UBOUND(OutData%WriteOutput,1) - DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) - OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Exc_UnPackOutput @@ -2250,14 +2482,18 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err END IF ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) b = -(y1%y(i1) - y2%y(i1)) y_out%y(i1) = y1%y(i1) + b * ScaleFactor END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor END DO +END IF ! check if allocated END SUBROUTINE SS_Exc_Output_ExtrapInterp1 @@ -2315,16 +2551,20 @@ SUBROUTINE SS_Exc_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) b = (t(3)**2*(y1%y(i1) - y2%y(i1)) + t(2)**2*(-y1%y(i1) + y3%y(i1)))* scaleFactor c = ( (t(2)-t(3))*y1%y(i1) + t(3)*y2%y(i1) - t(2)*y3%y(i1) ) * scaleFactor y_out%y(i1) = y1%y(i1) + b + c * t_out END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out END DO +END IF ! check if allocated END SUBROUTINE SS_Exc_Output_ExtrapInterp2 END MODULE SS_Excitation_Types diff --git a/modules/hydrodyn/src/SS_Radiation.txt b/modules/hydrodyn/src/SS_Radiation.txt index 508e597c1..eead37a5c 100644 --- a/modules/hydrodyn/src/SS_Radiation.txt +++ b/modules/hydrodyn/src/SS_Radiation.txt @@ -16,8 +16,8 @@ typedef ^ ^ ReKi enabledDOFs typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - typedef ^ ^ R8Ki PtfmRefztRot {:} - - "The rotation about zt of the body reference frame(s) from xt/yt" radians -typedef ^ InitOutputType CHARACTER(10) WriteOutputHdr {:} - - "Header of the output" - -typedef ^ InitOutputType CHARACTER(10) WriteOutputUnt {:} - - "Units of the output" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Header of the output" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output" - typedef ^ ContinuousStateType R8Ki x {:} - - "Continuous States" - diff --git a/modules/hydrodyn/src/SS_Radiation_Types.f90 b/modules/hydrodyn/src/SS_Radiation_Types.f90 index b343bc94e..8822320c3 100644 --- a/modules/hydrodyn/src/SS_Radiation_Types.f90 +++ b/modules/hydrodyn/src/SS_Radiation_Types.f90 @@ -43,8 +43,8 @@ MODULE SS_Radiation_Types ! ======================= ! ========= SS_Rad_InitOutputType ======= TYPE, PUBLIC :: SS_Rad_InitOutputType - CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputHdr !< Header of the output [-] - CHARACTER(ChanLen) , DIMENSION(1:7) :: WriteOutputUnt !< Units of the output [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Header of the output [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output [-] END TYPE SS_Rad_InitOutputType ! ======================= ! ========= SS_Rad_ContinuousStateType ======= @@ -79,8 +79,9 @@ MODULE SS_Radiation_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: N !< Number of states [-] - INTEGER(IntKi) , DIMENSION(1:6) :: spdof !< States per dof [-] + INTEGER(IntKi) :: numStates !< Number of states [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: spdof !< States per dof [-] + INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] END TYPE SS_Rad_ParameterType ! ======================= ! ========= SS_Rad_InputType ======= @@ -234,12 +235,38 @@ SUBROUTINE SS_Rad_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IntKiBuf(Int_Xferred) = ICHAR(InData%InputFile(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I - DO i2 = LBOUND(InData%DOFs,2), UBOUND(InData%DOFs,2) - DO i1 = LBOUND(InData%DOFs,1), UBOUND(InData%DOFs,1) - ReKiBuf(Re_Xferred) = InData%DOFs(i1,i2) + IF ( .NOT. ALLOCATED(InData%enabledDOFs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%enabledDOFs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%enabledDOFs,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%enabledDOFs,1), UBOUND(InData%enabledDOFs,1) + ReKiBuf(Re_Xferred) = InData%enabledDOFs(i1) Re_Xferred = Re_Xferred + 1 END DO - END DO + END IF + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefztRot,1), UBOUND(InData%PtfmRefztRot,1) + DbKiBuf(Db_Xferred) = InData%PtfmRefztRot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_PackInitInput SUBROUTINE SS_Rad_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -274,16 +301,44 @@ SUBROUTINE SS_Rad_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, OutData%InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I - i1_l = LBOUND(OutData%DOFs,1) - i1_u = UBOUND(OutData%DOFs,1) - i2_l = LBOUND(OutData%DOFs,2) - i2_u = UBOUND(OutData%DOFs,2) - DO i2 = LBOUND(OutData%DOFs,2), UBOUND(OutData%DOFs,2) - DO i1 = LBOUND(OutData%DOFs,1), UBOUND(OutData%DOFs,1) - OutData%DOFs(i1,i2) = ReKiBuf(Re_Xferred) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! enabledDOFs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%enabledDOFs)) DEALLOCATE(OutData%enabledDOFs) + ALLOCATE(OutData%enabledDOFs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%enabledDOFs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%enabledDOFs,1), UBOUND(OutData%enabledDOFs,1) + OutData%enabledDOFs(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - END DO + END IF + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefztRot,1), UBOUND(OutData%PtfmRefztRot,1) + OutData%PtfmRefztRot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_UnPackInitInput SUBROUTINE SS_Rad_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -426,18 +481,30 @@ SUBROUTINE SS_Rad_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF END SUBROUTINE SS_Rad_PackInitOutput SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -467,22 +534,46 @@ SUBROUTINE SS_Rad_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%WriteOutputHdr,1) - i1_u = UBOUND(OutData%WriteOutputHdr,1) - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - i1_l = LBOUND(OutData%WriteOutputUnt,1) - i1_u = UBOUND(OutData%WriteOutputUnt,1) - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF END SUBROUTINE SS_Rad_UnPackInitOutput SUBROUTINE SS_Rad_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -1322,8 +1413,20 @@ SUBROUTINE SS_Rad_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM END IF DstParamData%C = SrcParamData%C ENDIF - DstParamData%N = SrcParamData%N + DstParamData%numStates = SrcParamData%numStates +IF (ALLOCATED(SrcParamData%spdof)) THEN + i1_l = LBOUND(SrcParamData%spdof,1) + i1_u = UBOUND(SrcParamData%spdof,1) + IF (.NOT. ALLOCATED(DstParamData%spdof)) THEN + ALLOCATE(DstParamData%spdof(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%spdof.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF DstParamData%spdof = SrcParamData%spdof +ENDIF + DstParamData%NBody = SrcParamData%NBody END SUBROUTINE SS_Rad_CopyParam SUBROUTINE SS_Rad_DestroyParam( ParamData, ErrStat, ErrMsg ) @@ -1400,8 +1503,13 @@ SUBROUTINE SS_Rad_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*2 ! C upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C) ! C END IF - Int_BufSz = Int_BufSz + 1 ! N + Int_BufSz = Int_BufSz + 1 ! numStates + Int_BufSz = Int_BufSz + 1 ! spdof allocated yes/no + IF ( ALLOCATED(InData%spdof) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! spdof upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%spdof) ! spdof + END IF + Int_BufSz = Int_BufSz + 1 ! NBody IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1491,12 +1599,25 @@ SUBROUTINE SS_Rad_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg END DO END DO END IF - IntKiBuf(Int_Xferred) = InData%N + IntKiBuf(Int_Xferred) = InData%numStates + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%spdof) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%spdof,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%spdof,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%spdof,1), UBOUND(InData%spdof,1) + IntKiBuf(Int_Xferred) = InData%spdof(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NBody Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%spdof,1), UBOUND(InData%spdof,1) - IntKiBuf(Int_Xferred) = InData%spdof(i1) - Int_Xferred = Int_Xferred + 1 - END DO END SUBROUTINE SS_Rad_PackParam SUBROUTINE SS_Rad_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1598,14 +1719,28 @@ SUBROUTINE SS_Rad_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err END DO END DO END IF - OutData%N = IntKiBuf(Int_Xferred) + OutData%numStates = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! spdof not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%spdof)) DEALLOCATE(OutData%spdof) + ALLOCATE(OutData%spdof(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%spdof.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%spdof,1), UBOUND(OutData%spdof,1) + OutData%spdof(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + OutData%NBody = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%spdof,1) - i1_u = UBOUND(OutData%spdof,1) - DO i1 = LBOUND(OutData%spdof,1), UBOUND(OutData%spdof,1) - OutData%spdof(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO END SUBROUTINE SS_Rad_UnPackParam SUBROUTINE SS_Rad_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) @@ -1718,10 +1853,21 @@ SUBROUTINE SS_Rad_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%dq,1), UBOUND(InData%dq,1) - ReKiBuf(Re_Xferred) = InData%dq(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%dq) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%dq,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%dq,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%dq,1), UBOUND(InData%dq,1) + ReKiBuf(Re_Xferred) = InData%dq(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_PackInput SUBROUTINE SS_Rad_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1751,12 +1897,24 @@ SUBROUTINE SS_Rad_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%dq,1) - i1_u = UBOUND(OutData%dq,1) - DO i1 = LBOUND(OutData%dq,1), UBOUND(OutData%dq,1) - OutData%dq(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! dq not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%dq)) DEALLOCATE(OutData%dq) + ALLOCATE(OutData%dq(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%dq.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%dq,1), UBOUND(OutData%dq,1) + OutData%dq(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_UnPackInput SUBROUTINE SS_Rad_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -1889,14 +2047,36 @@ SUBROUTINE SS_Rad_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) - ReKiBuf(Re_Xferred) = InData%y(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) - ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%y,1), UBOUND(InData%y,1) + ReKiBuf(Re_Xferred) = InData%y(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) + ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_PackOutput SUBROUTINE SS_Rad_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1926,18 +2106,42 @@ SUBROUTINE SS_Rad_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%y,1) - i1_u = UBOUND(OutData%y,1) - DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) - OutData%y(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%WriteOutput,1) - i1_u = UBOUND(OutData%WriteOutput,1) - DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) - OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%y)) DEALLOCATE(OutData%y) + ALLOCATE(OutData%y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%y,1), UBOUND(OutData%y,1) + OutData%y(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) + OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE SS_Rad_UnPackOutput @@ -1957,7 +2161,7 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2004,8 +2208,8 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u2 ! Input at t2 + TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2035,10 +2239,12 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM END IF ScaleFactor = t_out / t(2) +IF (ALLOCATED(u_out%dq) .AND. ALLOCATED(u1%dq)) THEN DO i1 = LBOUND(u_out%dq,1),UBOUND(u_out%dq,1) b = -(u1%dq(i1) - u2%dq(i1)) u_out%dq(i1) = u1%dq(i1) + b * ScaleFactor END DO +END IF ! check if allocated END SUBROUTINE SS_Rad_Input_ExtrapInterp1 @@ -2056,9 +2262,9 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(SS_Rad_InputType), INTENT(INOUT) :: u3 ! Input at t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(SS_Rad_InputType), INTENT(IN) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(SS_Rad_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2096,11 +2302,13 @@ SUBROUTINE SS_Rad_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(u_out%dq) .AND. ALLOCATED(u1%dq)) THEN DO i1 = LBOUND(u_out%dq,1),UBOUND(u_out%dq,1) b = (t(3)**2*(u1%dq(i1) - u2%dq(i1)) + t(2)**2*(-u1%dq(i1) + u3%dq(i1)))* scaleFactor c = ( (t(2)-t(3))*u1%dq(i1) + t(3)*u2%dq(i1) - t(2)*u3%dq(i1) ) * scaleFactor u_out%dq(i1) = u1%dq(i1) + b + c * t_out END DO +END IF ! check if allocated END SUBROUTINE SS_Rad_Input_ExtrapInterp2 @@ -2120,7 +2328,7 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -2167,8 +2375,8 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2198,14 +2406,18 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err END IF ScaleFactor = t_out / t(2) +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) b = -(y1%y(i1) - y2%y(i1)) y_out%y(i1) = y1%y(i1) + b * ScaleFactor END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor END DO +END IF ! check if allocated END SUBROUTINE SS_Rad_Output_ExtrapInterp1 @@ -2223,9 +2435,9 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(SS_Rad_OutputType), INTENT(IN) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(SS_Rad_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -2263,16 +2475,20 @@ SUBROUTINE SS_Rad_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, END IF ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) +IF (ALLOCATED(y_out%y) .AND. ALLOCATED(y1%y)) THEN DO i1 = LBOUND(y_out%y,1),UBOUND(y_out%y,1) b = (t(3)**2*(y1%y(i1) - y2%y(i1)) + t(2)**2*(-y1%y(i1) + y3%y(i1)))* scaleFactor c = ( (t(2)-t(3))*y1%y(i1) + t(3)*y2%y(i1) - t(2)*y3%y(i1) ) * scaleFactor y_out%y(i1) = y1%y(i1) + b + c * t_out END DO +END IF ! check if allocated +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out END DO +END IF ! check if allocated END SUBROUTINE SS_Rad_Output_ExtrapInterp2 END MODULE SS_Radiation_Types diff --git a/modules/hydrodyn/src/WAMIT2_Types.f90 b/modules/hydrodyn/src/WAMIT2_Types.f90 index d0a96fe90..27627976a 100644 --- a/modules/hydrodyn/src/WAMIT2_Types.f90 +++ b/modules/hydrodyn/src/WAMIT2_Types.f90 @@ -60,10 +60,6 @@ MODULE WAMIT2_Types REAL(SiKi) :: WaveDirMin !< Minimum wave direction from Waves module [-] REAL(SiKi) :: WaveDirMax !< Maximum wave direction from Waves module [-] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Simulation times at which the instantaneous second order loads associated with the incident waves are determined [sec] - CHARACTER(ChanLen) , DIMENSION(1:27) :: OutList !< This should really be dimensioned with MaxOutPts [-] - LOGICAL :: OutAll !< [-] - INTEGER(IntKi) :: NumOuts !< [-] - INTEGER(IntKi) :: NumOutAll !< [-] INTEGER(IntKi) :: WaveMod !< The wave model to use. This is for error checking -- ideally this would be done in the main calling routine, not here. [-] INTEGER(IntKi) :: MnDrift !< Calculate the mean drift force {0: no mean drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] INTEGER(IntKi) :: NewmanApp !< Slow drift forces computed with Newman approximation from WAMIT file:{0: No slow drift; [7,8,9,10,11, or 12]: WAMIT file to use} [-] @@ -83,8 +79,7 @@ MODULE WAMIT2_Types ! ======================= ! ========= WAMIT2_InitOutputType ======= TYPE, PUBLIC :: WAMIT2_InitOutputType - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + REAL(ReKi) :: NULLVAL !< [-] END TYPE WAMIT2_InitOutputType ! ======================= ! ========= WAMIT2_ContinuousStateType ======= @@ -454,6 +449,70 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO ! I IntKiBuf(Int_Xferred) = InData%UnSum Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefxt,1), UBOUND(InData%PtfmRefxt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefyt,1), UBOUND(InData%PtfmRefyt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefyt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefzt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefzt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefzt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefzt,1), UBOUND(InData%PtfmRefzt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefzt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefztRot,1), UBOUND(InData%PtfmRefztRot,1) + DbKiBuf(Db_Xferred) = InData%PtfmRefztRot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF ReKiBuf(Re_Xferred) = InData%WAMITULEN Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%RhoXg @@ -466,6 +525,10 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%WtrDens Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveElevC0) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -524,32 +587,8 @@ SUBROUTINE WAMIT2_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 END DO END IF - DO i1 = LBOUND(InData%OutList,1), UBOUND(InData%OutList,1) - DO I = 1, LEN(InData%OutList) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutList(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumOuts - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumOutAll - Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%WaveMod Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF2, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%MnDrift Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NewmanApp @@ -616,6 +655,82 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO ! I OutData%UnSum = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) + ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefxt,1), UBOUND(OutData%PtfmRefxt,1) + OutData%PtfmRefxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) + ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefyt,1), UBOUND(OutData%PtfmRefyt,1) + OutData%PtfmRefyt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefzt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefzt)) DEALLOCATE(OutData%PtfmRefzt) + ALLOCATE(OutData%PtfmRefzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefzt,1), UBOUND(OutData%PtfmRefzt,1) + OutData%PtfmRefzt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefztRot,1), UBOUND(OutData%PtfmRefztRot,1) + OutData%PtfmRefztRot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF OutData%WAMITULEN = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%RhoXg = ReKiBuf(Re_Xferred) @@ -628,6 +743,10 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%WtrDens = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevC0 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -695,34 +814,8 @@ SUBROUTINE WAMIT2_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 END DO END IF - i1_l = LBOUND(OutData%OutList,1) - i1_u = UBOUND(OutData%OutList,1) - DO i1 = LBOUND(OutData%OutList,1), UBOUND(OutData%OutList,1) - DO I = 1, LEN(OutData%OutList) - OutData%OutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) - Int_Xferred = Int_Xferred + 1 - OutData%NumOuts = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NumOutAll = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 OutData%WaveMod = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%PtfmSgF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF2) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmSwF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF2) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmHvF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF2) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmRF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF2) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmPF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF2) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmYF2 = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF2) - Int_Xferred = Int_Xferred + 1 OutData%MnDrift = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 OutData%NewmanApp = IntKiBuf(Int_Xferred) @@ -844,40 +937,8 @@ SUBROUTINE WAMIT2_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF + ReKiBuf(Re_Xferred) = InData%NULLVAL + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT2_PackInitOutput SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -893,7 +954,6 @@ SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_UnPackInitOutput' @@ -907,46 +967,8 @@ SUBROUTINE WAMIT2_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF + OutData%NULLVAL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT2_UnPackInitOutput SUBROUTINE WAMIT2_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -1561,8 +1583,21 @@ SUBROUTINE WAMIT2_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%LastIndWave + IF ( .NOT. ALLOCATED(InData%LastIndWave) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LastIndWave,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LastIndWave,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LastIndWave,1), UBOUND(InData%LastIndWave,1) + IntKiBuf(Int_Xferred) = InData%LastIndWave(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF DO i1 = LBOUND(InData%F_Waves2,1), UBOUND(InData%F_Waves2,1) ReKiBuf(Re_Xferred) = InData%F_Waves2(i1) Re_Xferred = Re_Xferred + 1 @@ -1596,8 +1631,24 @@ SUBROUTINE WAMIT2_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%LastIndWave = IntKiBuf(Int_Xferred) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LastIndWave not allocated + Int_Xferred = Int_Xferred + 1 + ELSE Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LastIndWave)) DEALLOCATE(OutData%LastIndWave) + ALLOCATE(OutData%LastIndWave(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LastIndWave.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LastIndWave,1), UBOUND(OutData%LastIndWave,1) + OutData%LastIndWave(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF i1_l = LBOUND(OutData%F_Waves2,1) i1_u = UBOUND(OutData%F_Waves2,1) DO i1 = LBOUND(OutData%F_Waves2,1), UBOUND(OutData%F_Waves2,1) @@ -1840,6 +1891,10 @@ SUBROUTINE WAMIT2_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveExctn2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1995,6 +2050,10 @@ SUBROUTINE WAMIT2_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Int_Xferred = Int_Xferred + 1 OutData%DT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn2 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2474,21 +2533,6 @@ SUBROUTINE WAMIT2_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) - ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF END SUBROUTINE WAMIT2_PackOutput SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2504,7 +2548,6 @@ SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_UnPackOutput' @@ -2558,24 +2601,6 @@ SUBROUTINE WAMIT2_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) - ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) - OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF END SUBROUTINE WAMIT2_UnPackOutput @@ -2811,8 +2836,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts - INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -2829,12 +2852,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ScaleFactor = t_out / t(2) CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) - b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) - y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor - END DO -END IF ! check if allocated END SUBROUTINE WAMIT2_Output_ExtrapInterp1 @@ -2870,8 +2887,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT2_Output_ExtrapInterp2' - INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts - INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -2894,13 +2909,6 @@ SUBROUTINE WAMIT2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) - b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor - c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor - y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out - END DO -END IF ! check if allocated END SUBROUTINE WAMIT2_Output_ExtrapInterp2 END MODULE WAMIT2_Types diff --git a/modules/hydrodyn/src/WAMIT_Types.f90 b/modules/hydrodyn/src/WAMIT_Types.f90 index b257970cc..d5f86e17d 100644 --- a/modules/hydrodyn/src/WAMIT_Types.f90 +++ b/modules/hydrodyn/src/WAMIT_Types.f90 @@ -78,8 +78,7 @@ MODULE WAMIT_Types ! ======================= ! ========= WAMIT_InitOutputType ======= TYPE, PUBLIC :: WAMIT_InitOutputType - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-] + REAL(ReKi) :: NULLVAL !< [-] END TYPE WAMIT_InitOutputType ! ======================= ! ========= WAMIT_ContinuousStateType ======= @@ -542,16 +541,123 @@ SUBROUTINE WAMIT_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf(Re_Xferred) = InData%PtfmVol0 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Gravity Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmVol0) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmVol0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmVol0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmVol0,1), UBOUND(InData%PtfmVol0,1) + ReKiBuf(Re_Xferred) = InData%PtfmVol0(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IntKiBuf(Int_Xferred) = TRANSFER(InData%HasWAMIT, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 ReKiBuf(Re_Xferred) = InData%WAMITULEN Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PtfmCOBxt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PtfmCOByt - Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%PtfmRefxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefxt,1), UBOUND(InData%PtfmRefxt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefyt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefyt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefyt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefyt,1), UBOUND(InData%PtfmRefyt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefyt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefzt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefzt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefzt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefzt,1), UBOUND(InData%PtfmRefzt,1) + ReKiBuf(Re_Xferred) = InData%PtfmRefzt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmRefztRot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmRefztRot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmRefztRot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmRefztRot,1), UBOUND(InData%PtfmRefztRot,1) + DbKiBuf(Db_Xferred) = InData%PtfmRefztRot(i1) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmCOBxt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmCOBxt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmCOBxt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmCOBxt,1), UBOUND(InData%PtfmCOBxt,1) + ReKiBuf(Re_Xferred) = InData%PtfmCOBxt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%PtfmCOByt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PtfmCOByt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PtfmCOByt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%PtfmCOByt,1), UBOUND(InData%PtfmCOByt,1) + ReKiBuf(Re_Xferred) = InData%PtfmCOByt(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IntKiBuf(Int_Xferred) = InData%RdtnMod Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%ExctnMod @@ -713,16 +819,144 @@ SUBROUTINE WAMIT_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%PtfmVol0 = ReKiBuf(Re_Xferred) + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Gravity = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = REAL(ReKiBuf(Re_Xferred), SiKi) Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmVol0 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmVol0)) DEALLOCATE(OutData%PtfmVol0) + ALLOCATE(OutData%PtfmVol0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmVol0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmVol0,1), UBOUND(OutData%PtfmVol0,1) + OutData%PtfmVol0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF OutData%HasWAMIT = TRANSFER(IntKiBuf(Int_Xferred), OutData%HasWAMIT) Int_Xferred = Int_Xferred + 1 OutData%WAMITULEN = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%PtfmCOBxt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PtfmCOByt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefxt)) DEALLOCATE(OutData%PtfmRefxt) + ALLOCATE(OutData%PtfmRefxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefxt,1), UBOUND(OutData%PtfmRefxt,1) + OutData%PtfmRefxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefyt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefyt)) DEALLOCATE(OutData%PtfmRefyt) + ALLOCATE(OutData%PtfmRefyt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefyt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefyt,1), UBOUND(OutData%PtfmRefyt,1) + OutData%PtfmRefyt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefzt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefzt)) DEALLOCATE(OutData%PtfmRefzt) + ALLOCATE(OutData%PtfmRefzt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefzt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefzt,1), UBOUND(OutData%PtfmRefzt,1) + OutData%PtfmRefzt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmRefztRot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmRefztRot)) DEALLOCATE(OutData%PtfmRefztRot) + ALLOCATE(OutData%PtfmRefztRot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmRefztRot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmRefztRot,1), UBOUND(OutData%PtfmRefztRot,1) + OutData%PtfmRefztRot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmCOBxt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmCOBxt)) DEALLOCATE(OutData%PtfmCOBxt) + ALLOCATE(OutData%PtfmCOBxt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmCOBxt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmCOBxt,1), UBOUND(OutData%PtfmCOBxt,1) + OutData%PtfmCOBxt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PtfmCOByt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PtfmCOByt)) DEALLOCATE(OutData%PtfmCOByt) + ALLOCATE(OutData%PtfmCOByt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PtfmCOByt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%PtfmCOByt,1), UBOUND(OutData%PtfmCOByt,1) + OutData%PtfmCOByt(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF OutData%RdtnMod = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 OutData%ExctnMod = IntKiBuf(Int_Xferred) @@ -973,40 +1207,8 @@ SUBROUTINE WAMIT_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF + ReKiBuf(Re_Xferred) = InData%NULLVAL + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT_PackInitOutput SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1022,7 +1224,6 @@ SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_UnPackInitOutput' @@ -1036,46 +1237,8 @@ SUBROUTINE WAMIT_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF + OutData%NULLVAL = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END SUBROUTINE WAMIT_UnPackInitOutput SUBROUTINE WAMIT_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) @@ -2990,26 +3153,66 @@ SUBROUTINE WAMIT_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf(Int_Xferred) = InData%LastIndWave Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%F_HS,1), UBOUND(InData%F_HS,1) - ReKiBuf(Re_Xferred) = InData%F_HS(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%F_Waves1,1), UBOUND(InData%F_Waves1,1) - ReKiBuf(Re_Xferred) = InData%F_Waves1(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) - ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%F_PtfmAdd,1), UBOUND(InData%F_PtfmAdd,1) - ReKiBuf(Re_Xferred) = InData%F_PtfmAdd(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%F_PtfmAM,1), UBOUND(InData%F_PtfmAM,1) - ReKiBuf(Re_Xferred) = InData%F_PtfmAM(i1) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( .NOT. ALLOCATED(InData%F_HS) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_HS,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_HS,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_HS,1), UBOUND(InData%F_HS,1) + ReKiBuf(Re_Xferred) = InData%F_HS(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_Waves1) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_Waves1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Waves1,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_Waves1,1), UBOUND(InData%F_Waves1,1) + ReKiBuf(Re_Xferred) = InData%F_Waves1(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_Rdtn) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_Rdtn,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_Rdtn,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_Rdtn,1), UBOUND(InData%F_Rdtn,1) + ReKiBuf(Re_Xferred) = InData%F_Rdtn(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_PtfmAM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_PtfmAM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_PtfmAM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%F_PtfmAM,1), UBOUND(InData%F_PtfmAM,1) + ReKiBuf(Re_Xferred) = InData%F_PtfmAM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF CALL SS_Rad_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%SS_Rdtn, ErrStat2, ErrMsg2, OnlySize ) ! SS_Rdtn CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3293,36 +3496,78 @@ SUBROUTINE WAMIT_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs Int_Xferred = 1 OutData%LastIndWave = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%F_HS,1) - i1_u = UBOUND(OutData%F_HS,1) - DO i1 = LBOUND(OutData%F_HS,1), UBOUND(OutData%F_HS,1) - OutData%F_HS(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%F_Waves1,1) - i1_u = UBOUND(OutData%F_Waves1,1) - DO i1 = LBOUND(OutData%F_Waves1,1), UBOUND(OutData%F_Waves1,1) - OutData%F_Waves1(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%F_Rdtn,1) - i1_u = UBOUND(OutData%F_Rdtn,1) - DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) - OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%F_PtfmAdd,1) - i1_u = UBOUND(OutData%F_PtfmAdd,1) - DO i1 = LBOUND(OutData%F_PtfmAdd,1), UBOUND(OutData%F_PtfmAdd,1) - OutData%F_PtfmAdd(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%F_PtfmAM,1) - i1_u = UBOUND(OutData%F_PtfmAM,1) - DO i1 = LBOUND(OutData%F_PtfmAM,1), UBOUND(OutData%F_PtfmAM,1) - OutData%F_PtfmAM(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_HS not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_HS)) DEALLOCATE(OutData%F_HS) + ALLOCATE(OutData%F_HS(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_HS.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_HS,1), UBOUND(OutData%F_HS,1) + OutData%F_HS(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_Waves1 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_Waves1)) DEALLOCATE(OutData%F_Waves1) + ALLOCATE(OutData%F_Waves1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_Waves1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_Waves1,1), UBOUND(OutData%F_Waves1,1) + OutData%F_Waves1(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_Rdtn not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_Rdtn)) DEALLOCATE(OutData%F_Rdtn) + ALLOCATE(OutData%F_Rdtn(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_Rdtn.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_Rdtn,1), UBOUND(OutData%F_Rdtn,1) + OutData%F_Rdtn(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_PtfmAM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_PtfmAM)) DEALLOCATE(OutData%F_PtfmAM) + ALLOCATE(OutData%F_PtfmAM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_PtfmAM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%F_PtfmAM,1), UBOUND(OutData%F_PtfmAM,1) + OutData%F_PtfmAM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -3997,24 +4242,70 @@ SUBROUTINE WAMIT_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Db_Xferred = 1 Int_Xferred = 1 - DO i2 = LBOUND(InData%HdroAdMsI,2), UBOUND(InData%HdroAdMsI,2) - DO i1 = LBOUND(InData%HdroAdMsI,1), UBOUND(InData%HdroAdMsI,1) - ReKiBuf(Re_Xferred) = InData%HdroAdMsI(i1,i2) - Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBody + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NBodyMod + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%F_HS_Moment_Offset) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_HS_Moment_Offset,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_HS_Moment_Offset,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_HS_Moment_Offset,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_HS_Moment_Offset,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_HS_Moment_Offset,2), UBOUND(InData%F_HS_Moment_Offset,2) + DO i1 = LBOUND(InData%F_HS_Moment_Offset,1), UBOUND(InData%F_HS_Moment_Offset,1) + ReKiBuf(Re_Xferred) = InData%F_HS_Moment_Offset(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO - END DO - DO i2 = LBOUND(InData%HdroSttc,2), UBOUND(InData%HdroSttc,2) - DO i1 = LBOUND(InData%HdroSttc,1), UBOUND(InData%HdroSttc,1) - ReKiBuf(Re_Xferred) = InData%HdroSttc(i1,i2) - Re_Xferred = Re_Xferred + 1 + END IF + IF ( .NOT. ALLOCATED(InData%HdroAdMsI) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroAdMsI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroAdMsI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroAdMsI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroAdMsI,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%HdroAdMsI,2), UBOUND(InData%HdroAdMsI,2) + DO i1 = LBOUND(InData%HdroAdMsI,1), UBOUND(InData%HdroAdMsI,1) + ReKiBuf(Re_Xferred) = InData%HdroAdMsI(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO - END DO - ReKiBuf(Re_Xferred) = InData%PtfmVol0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PtfmCOBxt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PtfmCOByt - Re_Xferred = Re_Xferred + 1 + END IF + IF ( .NOT. ALLOCATED(InData%HdroSttc) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroSttc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroSttc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%HdroSttc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HdroSttc,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%HdroSttc,2), UBOUND(InData%HdroSttc,2) + DO i1 = LBOUND(InData%HdroSttc,1), UBOUND(InData%HdroSttc,1) + ReKiBuf(Re_Xferred) = InData%HdroSttc(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF IntKiBuf(Int_Xferred) = InData%RdtnMod Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%ExctnMod @@ -4038,23 +4329,6 @@ SUBROUTINE WAMIT_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Re_Xferred = Re_Xferred + 1 END DO END DO - END IF - ReKiBuf(Re_Xferred) = InData%RhoXg - Re_Xferred = Re_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%WaveTime) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveTime,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveTime,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WaveTime,1), UBOUND(InData%WaveTime,1) - ReKiBuf(Re_Xferred) = InData%WaveTime(i1) - Re_Xferred = Re_Xferred + 1 - END DO END IF IntKiBuf(Int_Xferred) = InData%NStepWave Int_Xferred = Int_Xferred + 1 @@ -4144,18 +4418,6 @@ SUBROUTINE WAMIT_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, ENDIF DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSgF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmSwF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmHvF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmRF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmPF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%PtfmYF, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4245,37 +4507,57 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - i1_l = LBOUND(OutData%HdroAdMsI,1) - i1_u = UBOUND(OutData%HdroAdMsI,1) - i2_l = LBOUND(OutData%HdroAdMsI,2) - i2_u = UBOUND(OutData%HdroAdMsI,2) - DO i2 = LBOUND(OutData%HdroAdMsI,2), UBOUND(OutData%HdroAdMsI,2) - DO i1 = LBOUND(OutData%HdroAdMsI,1), UBOUND(OutData%HdroAdMsI,1) - OutData%HdroAdMsI(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - i1_l = LBOUND(OutData%HdroSttc,1) - i1_u = UBOUND(OutData%HdroSttc,1) - i2_l = LBOUND(OutData%HdroSttc,2) - i2_u = UBOUND(OutData%HdroSttc,2) - DO i2 = LBOUND(OutData%HdroSttc,2), UBOUND(OutData%HdroSttc,2) - DO i1 = LBOUND(OutData%HdroSttc,1), UBOUND(OutData%HdroSttc,1) - OutData%HdroSttc(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%NBody = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NBodyMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_HS_Moment_Offset not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_HS_Moment_Offset)) DEALLOCATE(OutData%F_HS_Moment_Offset) + ALLOCATE(OutData%F_HS_Moment_Offset(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_HS_Moment_Offset.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_HS_Moment_Offset,2), UBOUND(OutData%F_HS_Moment_Offset,2) + DO i1 = LBOUND(OutData%F_HS_Moment_Offset,1), UBOUND(OutData%F_HS_Moment_Offset,1) + OutData%F_HS_Moment_Offset(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END DO - END DO - OutData%PtfmVol0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PtfmCOBxt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PtfmCOByt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RdtnMod = IntKiBuf(Int_Xferred) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HdroAdMsI not allocated Int_Xferred = Int_Xferred + 1 - OutData%ExctnMod = IntKiBuf(Int_Xferred) + ELSE Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn not allocated + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%HdroAdMsI)) DEALLOCATE(OutData%HdroAdMsI) + ALLOCATE(OutData%HdroAdMsI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroAdMsI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%HdroAdMsI,2), UBOUND(OutData%HdroAdMsI,2) + DO i1 = LBOUND(OutData%HdroAdMsI,1), UBOUND(OutData%HdroAdMsI,1) + OutData%HdroAdMsI(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HdroSttc not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -4291,16 +4573,18 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HdroSttc.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%WaveExctn,2), UBOUND(OutData%WaveExctn,2) - DO i1 = LBOUND(OutData%WaveExctn,1), UBOUND(OutData%WaveExctn,1) - OutData%WaveExctn(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + DO i2 = LBOUND(OutData%HdroSttc,2), UBOUND(OutData%HdroSttc,2) + DO i1 = LBOUND(OutData%HdroSttc,1), UBOUND(OutData%HdroSttc,1) + OutData%HdroSttc(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - OutData%RhoXg = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime not allocated + OutData%RdtnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ExctnMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveExctn not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -4316,9 +4600,11 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveExctn.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%WaveTime,1), UBOUND(OutData%WaveTime,1) - OutData%WaveTime(i1) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(OutData%WaveExctn,2), UBOUND(OutData%WaveExctn,2) + DO i1 = LBOUND(OutData%WaveExctn,1), UBOUND(OutData%WaveExctn,1) + OutData%WaveExctn(i1,i2) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF OutData%NStepWave = IntKiBuf(Int_Xferred) @@ -4445,18 +4731,6 @@ SUBROUTINE WAMIT_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) OutData%DT = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 - OutData%PtfmSgF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSgF) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmSwF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmSwF) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmHvF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmHvF) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmRF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmRF) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmPF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmPF) - Int_Xferred = Int_Xferred + 1 - OutData%PtfmYF = TRANSFER(IntKiBuf(Int_Xferred), OutData%PtfmYF) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4881,21 +5155,6 @@ SUBROUTINE WAMIT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutput,1), UBOUND(InData%WriteOutput,1) - ReKiBuf(Re_Xferred) = InData%WriteOutput(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF END SUBROUTINE WAMIT_PackOutput SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -4911,7 +5170,6 @@ SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_UnPackOutput' @@ -4965,24 +5223,6 @@ SUBROUTINE WAMIT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) - ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%WriteOutput,1), UBOUND(OutData%WriteOutput,1) - OutData%WriteOutput(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF END SUBROUTINE WAMIT_UnPackOutput @@ -5218,8 +5458,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM REAL(DbKi) :: ScaleFactor ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts - INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -5236,12 +5474,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM ScaleFactor = t_out / t(2) CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) - b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) - y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor - END DO -END IF ! check if allocated END SUBROUTINE WAMIT_Output_ExtrapInterp1 @@ -5277,8 +5509,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'WAMIT_Output_ExtrapInterp2' - INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts - INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -5301,13 +5531,6 @@ SUBROUTINE WAMIT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3))) CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) - b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor - c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor - y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out - END DO -END IF ! check if allocated END SUBROUTINE WAMIT_Output_ExtrapInterp2 END MODULE WAMIT_Types diff --git a/modules/hydrodyn/src/Waves2_Types.f90 b/modules/hydrodyn/src/Waves2_Types.f90 index b3eb88cfd..affe3fdc4 100644 --- a/modules/hydrodyn/src/Waves2_Types.f90 +++ b/modules/hydrodyn/src/Waves2_Types.f90 @@ -3493,7 +3493,7 @@ SUBROUTINE Waves2_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Waves2_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3540,8 +3540,8 @@ SUBROUTINE Waves2_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(Waves2_InputType), INTENT(INOUT) :: u2 ! Input at t2 + TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3588,9 +3588,9 @@ SUBROUTINE Waves2_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves2_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(Waves2_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(Waves2_InputType), INTENT(INOUT) :: u3 ! Input at t3 + TYPE(Waves2_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves2_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Waves2_InputType), INTENT(IN) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Waves2_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3648,7 +3648,7 @@ SUBROUTINE Waves2_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3695,8 +3695,8 @@ SUBROUTINE Waves2_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Err ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(Waves2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3749,9 +3749,9 @@ SUBROUTINE Waves2_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves2_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(Waves2_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(Waves2_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Waves2_OutputType), INTENT(IN) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Waves2_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to diff --git a/modules/hydrodyn/src/Waves_Types.f90 b/modules/hydrodyn/src/Waves_Types.f90 index 11b8cfdf9..ede51633d 100644 --- a/modules/hydrodyn/src/Waves_Types.f90 +++ b/modules/hydrodyn/src/Waves_Types.f90 @@ -1593,19 +1593,6 @@ SUBROUTINE Waves_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%WaveElev0) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WaveElev0,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WaveElev0,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%WaveElev0)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WaveElev0))-1 ) = PACK(InData%WaveElev0,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%WaveElev0) - END IF IF ( .NOT. ALLOCATED(InData%WaveElevSeries) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1970,29 +1957,6 @@ SUBROUTINE Waves_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElev0 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WaveElev0)) DEALLOCATE(OutData%WaveElev0) - ALLOCATE(OutData%WaveElev0(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WaveElev0.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%WaveElev0)>0) OutData%WaveElev0 = REAL( UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WaveElev0))-1 ), mask1, 0.0_ReKi ), SiKi) - Re_Xferred = Re_Xferred + SIZE(OutData%WaveElev0) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveElevSeries not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -3108,7 +3072,7 @@ SUBROUTINE Waves_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + TYPE(Waves_InputType), INTENT(IN) :: u(:) ! Input at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3155,8 +3119,8 @@ SUBROUTINE Waves_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMs ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(Waves_InputType), INTENT(INOUT) :: u2 ! Input at t2 + TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3203,9 +3167,9 @@ SUBROUTINE Waves_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, E ! !.................................................................................................................................. - TYPE(Waves_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(Waves_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(Waves_InputType), INTENT(INOUT) :: u3 ! Input at t3 + TYPE(Waves_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(Waves_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(Waves_InputType), INTENT(IN) :: u3 ! Input at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs TYPE(Waves_InputType), INTENT(INOUT) :: u_out ! Input at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3263,7 +3227,7 @@ SUBROUTINE Waves_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + TYPE(Waves_OutputType), INTENT(IN) :: y(:) ! Output at t1 > t2 > t3 REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to @@ -3310,8 +3274,8 @@ SUBROUTINE Waves_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrM ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(Waves_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to @@ -3358,9 +3322,9 @@ SUBROUTINE Waves_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ! !.................................................................................................................................. - TYPE(Waves_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(Waves_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(Waves_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + TYPE(Waves_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(Waves_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(Waves_OutputType), INTENT(IN) :: y3 ! Output at t3 REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs TYPE(Waves_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to From ca253da2582e21d5b6e1744b6984932932de3281 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 13:40:26 -0600 Subject: [PATCH 207/377] Bug fix for case where vector is vertical, pointing downward --- modules/hydrodyn/src/Morison.f90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index f4bd7e5ea..148d976d5 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2172,7 +2172,11 @@ SUBROUTINE RodrigMat(a, R, errStat, errMsg) ! errStat = ErrID_Fatal errMsg = 'RodrigMat encountered vector of zero length' - + else IF ( EqualRealNos(a(1), 0.0) .AND. EqualRealNos(a(2), 0.0) ) THEN ! return identity if vertical + CALL EYE(R, errStat,errMsg) + IF (a(3) < 0) THEN + R = -R + END IF else vec = a/SQRT(factor) ! normalize a vec(3) = vec(3) + 1 From 9c1173c66e66bab68d0b058ec73729ad1949c8c6 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 15:03:23 -0600 Subject: [PATCH 208/377] Changes to mesh mapping structures for new solver approach --- .../openfast-library/src/FAST_Registry.txt | 32 ++- modules/openfast-library/src/FAST_Types.f90 | 271 +++++------------- 2 files changed, 96 insertions(+), 207 deletions(-) diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index 973e9e6f9..2e512d665 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -556,28 +556,29 @@ typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" # ..... FAST_ModuleMapType data ....................................................................................................... # ! Data structures for mapping and coupling the various modules together # ED <-> BD -typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P {:} - - "Map ElastoDyn BladeRootMotion meshes to BeamDyn RootMotion point meshes" -typedef FAST FAST_ModuleMapType MeshMapType BD_P_2_ED_P {:} - - "Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh" -typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_BD_P_Hub {:} - - "ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_BD_P {:} - - "Map ElastoDyn BladeRootMotion meshes to BeamDyn RootMotion point meshes" +typedef ^ FAST_ModuleMapType MeshMapType BD_P_2_ED_P {:} - - "Map BeamDyn ReactionForce loads point meshes to ElastoDyn HubPtLoad point mesh" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_BD_P_Hub {:} - - "ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator" # ED <-> HD -typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_PRP_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn platform reference Point" -typedef FAST FAST_ModuleMapType MeshMapType ED_P_2_HD_W_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point" -typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point (from either y%WAMITMesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_PRP_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn platform reference Point" +typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_W_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point" +typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_ED_P - - - "Map HydroDyn WAMIT Point from y%WAMITMesh to ElastoDyn PlatformPtMesh" typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_P - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point" typedef ^ FAST_ModuleMapType MeshMapType HD_M_P_2_ED_P - - - "Map HydroDyn Morison Point to ElastoDyn PlatformPtMesh" -typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_HD_M_L - - - "Map ElastoDyn PlatformPtMesh to HydroDyn Morison Line2" -typedef ^ FAST_ModuleMapType MeshMapType HD_M_L_2_ED_P - - - "Map HydroDyn Morison Line2 to ElastoDyn PlatformPtMesh" # ED <-> Mooring (MAP, FEAM, MoorDyn, OrcaFlex) typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_Mooring_P - - - "Map ElastoDyn PlatformPtMesh to MAP/FEAM/MoorDyn/OrcaFlex point mesh" typedef ^ FAST_ModuleMapType MeshMapType Mooring_P_2_ED_P - - - "Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to ElastoDyn PlatformPtMesh" +# SD <-> Mooring (MAP, FEAM, MoorDyn, OrcaFlex) +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_Mooring_P - - - "Map SD Motions (y2Mesh) to MAP/FEAM/MoorDyn/OrcaFlex point mesh" +typedef ^ FAST_ModuleMapType MeshMapType Mooring_P_2_SD_P - - - "Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to SD point loads (LMesh) mesh" # ED <-> SD or User-Platform (ExtPtfm_MCKF) typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_SD_TP - - - "Map ElastoDyn PlatformPtMesh to SubDyn transition-piece point mesh" typedef ^ FAST_ModuleMapType MeshMapType SD_TP_2_ED_P - - - "Map SubDyn transition-piece point mesh to ElastoDyn PlatformPtMesh" # SD <-> HD typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_HD_M_P - - - "Map SubDyn y2Mesh Point to HydroDyn Morison Point" typedef ^ FAST_ModuleMapType MeshMapType HD_M_P_2_SD_P - - - "Map HydroDyn Morison Point to SubDyn y2Mesh Point" -typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_HD_M_L - - - "Map SubDyn y2Mesh Point to HydroDyn Morison Line2" -typedef ^ FAST_ModuleMapType MeshMapType HD_M_L_2_SD_P - - - "Map HydroDyn Morison Line2 to SubDyn y2Mesh Point" +typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_HD_W_P - - - "Map SubDyn y2Mesh Point to HydroDyn WAMIT Point" +typedef ^ FAST_ModuleMapType MeshMapType HD_W_P_2_SD_P - - - "Map HydroDyn WAMIT Point to SubDyn y2Mesh Point" # ED <-> SrvD/TMD typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_SrvD_P_N - - - "Map ElastoDyn Nacelle point mesh to ServoDyn/TMD point mesh" typedef ^ FAST_ModuleMapType MeshMapType SrvD_P_2_ED_P_N - - - "Map ServoDyn nacelle point mesh to ElastoDyn point mesh on the nacelle" @@ -593,10 +594,10 @@ typedef ^ FAST_ModuleMapType MeshMapType AD_L_2_ED_P_T - - - "Map AeroDyn14 Twr_ typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_AD_P_R {:} - - "Map ElastoDyn BladeRootMotion point meshes to AeroDyn BladeRootMotion point meshes" typedef ^ FAST_ModuleMapType MeshMapType ED_P_2_AD_P_H - - - "Map ElastoDyn HubPtMotion point mesh to AeroDyn HubMotion point mesh" # IceF <-> SD -typedef ^ FAST_ModuleMapType MeshMapType IceF_P_2_SD_P - - - "Map IceFloe point mesh to SubDyn y2Mesh point mesh" +typedef ^ FAST_ModuleMapType MeshMapType IceF_P_2_SD_P - - - "Map IceFloe point mesh to SubDyn LMesh point mesh" typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_IceF_P - - - "Map SubDyn y2Mesh point mesh to IceFloe point mesh" # IceD <-> SD -typedef ^ FAST_ModuleMapType MeshMapType IceD_P_2_SD_P {:} - - "Map IceDyn point mesh to SubDyn y2Mesh point mesh" +typedef ^ FAST_ModuleMapType MeshMapType IceD_P_2_SD_P {:} - - "Map IceDyn point mesh to SubDyn LMesh point mesh" typedef ^ FAST_ModuleMapType MeshMapType SD_P_2_IceD_P {:} - - "Map SubDyn y2Mesh point mesh to IceDyn point mesh" # Stored Jacobians: typedef ^ FAST_ModuleMapType ReKi Jacobian_Opt1 {:}{:} - - "Stored Jacobian in ED_HD_InputOutputSolve or FullOpt1_InputOutputSolve" @@ -608,9 +609,10 @@ typedef ^ FAST_ModuleMapType MeshType u_ED_PlatformPtMesh_2 - - - "copy of ED in typedef ^ FAST_ModuleMapType MeshType u_SD_TPMesh - - - "copy of SD input mesh" typedef ^ FAST_ModuleMapType MeshType u_SD_LMesh - - - "copy of SD input mesh" typedef ^ FAST_ModuleMapType MeshType u_SD_LMesh_2 - - - "copy of SD input mesh (used only for temporary storage)" -typedef ^ FAST_ModuleMapType MeshType u_HD_M_LumpedMesh - - - "copy of HD input mesh" -typedef ^ FAST_ModuleMapType MeshType u_HD_M_DistribMesh - - - "copy of HD input mesh" -typedef ^ FAST_ModuleMapType MeshType u_HD_Mesh - - - "copy of HD input mesh" +#typedef ^ FAST_ModuleMapType MeshType u_HD_M_LumpedMesh - - - "copy of HD input mesh" +typedef ^ FAST_ModuleMapType MeshType u_HD_M_Mesh - - - "copy of HD morison input mesh" +typedef ^ FAST_ModuleMapType MeshType u_HD_W_Mesh - - - "copy of HD wamit input mesh" +#typedef ^ FAST_ModuleMapType MeshType u_HD_PRP_Mesh - - - "copy of HD PRP input mesh" typedef ^ FAST_ModuleMapType MeshType u_ED_HubPtLoad - - - "copy of ED input mesh" typedef ^ FAST_ModuleMapType MeshType u_ED_HubPtLoad_2 - - - "copy of ED input mesh" typedef ^ FAST_ModuleMapType MeshType u_BD_RootMotion {:} - - "copy of BD input meshes" diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index 2c40dc1ca..fc1240c6b 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -615,19 +615,19 @@ MODULE FAST_Types TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_BD_P_Hub !< ElastoDyn hub to BeamDyn for hub orientation necessary for pitch actuator [-] TYPE(MeshMapType) :: ED_P_2_HD_PRP_P !< Map ElastoDyn PlatformPtMesh to HydroDyn platform reference Point [-] TYPE(MeshMapType) :: ED_P_2_HD_W_P !< Map ElastoDyn PlatformPtMesh to HydroDyn WAMIT Point [-] - TYPE(MeshMapType) :: HD_W_P_2_ED_P !< Map HydroDyn WAMIT Point (from either y%WAMITMesh or y%AllHydroOrigin) to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: HD_W_P_2_ED_P !< Map HydroDyn WAMIT Point from y%WAMITMesh to ElastoDyn PlatformPtMesh [-] TYPE(MeshMapType) :: ED_P_2_HD_M_P !< Map ElastoDyn PlatformPtMesh to HydroDyn Morison Point [-] TYPE(MeshMapType) :: HD_M_P_2_ED_P !< Map HydroDyn Morison Point to ElastoDyn PlatformPtMesh [-] - TYPE(MeshMapType) :: ED_P_2_HD_M_L !< Map ElastoDyn PlatformPtMesh to HydroDyn Morison Line2 [-] - TYPE(MeshMapType) :: HD_M_L_2_ED_P !< Map HydroDyn Morison Line2 to ElastoDyn PlatformPtMesh [-] TYPE(MeshMapType) :: ED_P_2_Mooring_P !< Map ElastoDyn PlatformPtMesh to MAP/FEAM/MoorDyn/OrcaFlex point mesh [-] TYPE(MeshMapType) :: Mooring_P_2_ED_P !< Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to ElastoDyn PlatformPtMesh [-] + TYPE(MeshMapType) :: SD_P_2_Mooring_P !< Map SD Motions (y2Mesh) to MAP/FEAM/MoorDyn/OrcaFlex point mesh [-] + TYPE(MeshMapType) :: Mooring_P_2_SD_P !< Map FEAM/MAP/MoorDyn/OrcaFlex point mesh to SD point loads (LMesh) mesh [-] TYPE(MeshMapType) :: ED_P_2_SD_TP !< Map ElastoDyn PlatformPtMesh to SubDyn transition-piece point mesh [-] TYPE(MeshMapType) :: SD_TP_2_ED_P !< Map SubDyn transition-piece point mesh to ElastoDyn PlatformPtMesh [-] TYPE(MeshMapType) :: SD_P_2_HD_M_P !< Map SubDyn y2Mesh Point to HydroDyn Morison Point [-] TYPE(MeshMapType) :: HD_M_P_2_SD_P !< Map HydroDyn Morison Point to SubDyn y2Mesh Point [-] - TYPE(MeshMapType) :: SD_P_2_HD_M_L !< Map SubDyn y2Mesh Point to HydroDyn Morison Line2 [-] - TYPE(MeshMapType) :: HD_M_L_2_SD_P !< Map HydroDyn Morison Line2 to SubDyn y2Mesh Point [-] + TYPE(MeshMapType) :: SD_P_2_HD_W_P !< Map SubDyn y2Mesh Point to HydroDyn WAMIT Point [-] + TYPE(MeshMapType) :: HD_W_P_2_SD_P !< Map HydroDyn WAMIT Point to SubDyn y2Mesh Point [-] TYPE(MeshMapType) :: ED_P_2_SrvD_P_N !< Map ElastoDyn Nacelle point mesh to ServoDyn/TMD point mesh [-] TYPE(MeshMapType) :: SrvD_P_2_ED_P_N !< Map ServoDyn nacelle point mesh to ElastoDyn point mesh on the nacelle [-] TYPE(MeshMapType) :: ED_L_2_SrvD_P_T !< Map ElastoDyn tower line2 mesh to ServoDyn/TTMD point mesh [-] @@ -639,9 +639,9 @@ MODULE FAST_Types TYPE(MeshMapType) :: AD_L_2_ED_P_T !< Map AeroDyn14 Twr_InputMarkers or AeroDyn TowerLoad line2 mesh to ElastoDyn TowerPtLoads point mesh [-] TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: ED_P_2_AD_P_R !< Map ElastoDyn BladeRootMotion point meshes to AeroDyn BladeRootMotion point meshes [-] TYPE(MeshMapType) :: ED_P_2_AD_P_H !< Map ElastoDyn HubPtMotion point mesh to AeroDyn HubMotion point mesh [-] - TYPE(MeshMapType) :: IceF_P_2_SD_P !< Map IceFloe point mesh to SubDyn y2Mesh point mesh [-] + TYPE(MeshMapType) :: IceF_P_2_SD_P !< Map IceFloe point mesh to SubDyn LMesh point mesh [-] TYPE(MeshMapType) :: SD_P_2_IceF_P !< Map SubDyn y2Mesh point mesh to IceFloe point mesh [-] - TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: IceD_P_2_SD_P !< Map IceDyn point mesh to SubDyn y2Mesh point mesh [-] + TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: IceD_P_2_SD_P !< Map IceDyn point mesh to SubDyn LMesh point mesh [-] TYPE(MeshMapType) , DIMENSION(:), ALLOCATABLE :: SD_P_2_IceD_P !< Map SubDyn y2Mesh point mesh to IceDyn point mesh [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Jacobian_Opt1 !< Stored Jacobian in ED_HD_InputOutputSolve or FullOpt1_InputOutputSolve [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Jacobian_pivot !< Pivot array used for LU decomposition of Jacobian_Opt1 [-] @@ -651,9 +651,8 @@ MODULE FAST_Types TYPE(MeshType) :: u_SD_TPMesh !< copy of SD input mesh [-] TYPE(MeshType) :: u_SD_LMesh !< copy of SD input mesh [-] TYPE(MeshType) :: u_SD_LMesh_2 !< copy of SD input mesh (used only for temporary storage) [-] - TYPE(MeshType) :: u_HD_M_LumpedMesh !< copy of HD input mesh [-] - TYPE(MeshType) :: u_HD_M_DistribMesh !< copy of HD input mesh [-] - TYPE(MeshType) :: u_HD_Mesh !< copy of HD input mesh [-] + TYPE(MeshType) :: u_HD_M_Mesh !< copy of HD morison input mesh [-] + TYPE(MeshType) :: u_HD_W_Mesh !< copy of HD wamit input mesh [-] TYPE(MeshType) :: u_ED_HubPtLoad !< copy of ED input mesh [-] TYPE(MeshType) :: u_ED_HubPtLoad_2 !< copy of ED input mesh [-] TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: u_BD_RootMotion !< copy of BD input meshes [-] @@ -14004,29 +14003,6 @@ SUBROUTINE FAST_UnPackLinType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) - ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) - DEALLOCATE(mask1) END IF i1_l = LBOUND(OutData%SizeLin,1) i1_u = UBOUND(OutData%SizeLin,1) @@ -35603,16 +35579,16 @@ SUBROUTINE FAST_CopyModuleMapType( SrcModuleMapTypeData, DstModuleMapTypeData, C CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_P_2_ED_P, DstModuleMapTypeData%HD_M_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_HD_M_L, DstModuleMapTypeData%ED_P_2_HD_M_L, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_Mooring_P, DstModuleMapTypeData%ED_P_2_Mooring_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_L_2_ED_P, DstModuleMapTypeData%HD_M_L_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%Mooring_P_2_ED_P, DstModuleMapTypeData%Mooring_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_Mooring_P, DstModuleMapTypeData%ED_P_2_Mooring_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_Mooring_P, DstModuleMapTypeData%SD_P_2_Mooring_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%Mooring_P_2_ED_P, DstModuleMapTypeData%Mooring_P_2_ED_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%Mooring_P_2_SD_P, DstModuleMapTypeData%Mooring_P_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_SD_TP, DstModuleMapTypeData%ED_P_2_SD_TP, CtrlCode, ErrStat2, ErrMsg2 ) @@ -35627,10 +35603,10 @@ SUBROUTINE FAST_CopyModuleMapType( SrcModuleMapTypeData, DstModuleMapTypeData, C CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_P_2_SD_P, DstModuleMapTypeData%HD_M_P_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_HD_M_L, DstModuleMapTypeData%SD_P_2_HD_M_L, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%SD_P_2_HD_W_P, DstModuleMapTypeData%SD_P_2_HD_W_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_M_L_2_SD_P, DstModuleMapTypeData%HD_M_L_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%HD_W_P_2_SD_P, DstModuleMapTypeData%HD_W_P_2_SD_P, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL NWTC_Library_Copymeshmaptype( SrcModuleMapTypeData%ED_P_2_SrvD_P_N, DstModuleMapTypeData%ED_P_2_SrvD_P_N, CtrlCode, ErrStat2, ErrMsg2 ) @@ -35811,13 +35787,10 @@ SUBROUTINE FAST_CopyModuleMapType( SrcModuleMapTypeData, DstModuleMapTypeData, C CALL MeshCopy( SrcModuleMapTypeData%u_SD_LMesh_2, DstModuleMapTypeData%u_SD_LMesh_2, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcModuleMapTypeData%u_HD_M_LumpedMesh, DstModuleMapTypeData%u_HD_M_LumpedMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcModuleMapTypeData%u_HD_M_Mesh, DstModuleMapTypeData%u_HD_M_Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcModuleMapTypeData%u_HD_M_DistribMesh, DstModuleMapTypeData%u_HD_M_DistribMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcModuleMapTypeData%u_HD_Mesh, DstModuleMapTypeData%u_HD_Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL MeshCopy( SrcModuleMapTypeData%u_HD_W_Mesh, DstModuleMapTypeData%u_HD_W_Mesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL MeshCopy( SrcModuleMapTypeData%u_ED_HubPtLoad, DstModuleMapTypeData%u_ED_HubPtLoad, CtrlCode, ErrStat2, ErrMsg2 ) @@ -35898,16 +35871,16 @@ SUBROUTINE FAST_DestroyModuleMapType( ModuleMapTypeData, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_W_P_2_ED_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_M_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_P_2_ED_P, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_HD_M_L, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_L_2_ED_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%Mooring_P_2_ED_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%Mooring_P_2_SD_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_SD_TP, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_TP_2_ED_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_HD_M_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_P_2_SD_P, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_HD_M_L, ErrStat, ErrMsg ) - CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_M_L_2_SD_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SD_P_2_HD_W_P, ErrStat, ErrMsg ) + CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%HD_W_P_2_SD_P, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_P_2_SrvD_P_N, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%SrvD_P_2_ED_P_N, ErrStat, ErrMsg ) CALL NWTC_Library_Destroymeshmaptype( ModuleMapTypeData%ED_L_2_SrvD_P_T, ErrStat, ErrMsg ) @@ -35967,9 +35940,8 @@ SUBROUTINE FAST_DestroyModuleMapType( ModuleMapTypeData, ErrStat, ErrMsg ) CALL MeshDestroy( ModuleMapTypeData%u_SD_TPMesh, ErrStat, ErrMsg ) CALL MeshDestroy( ModuleMapTypeData%u_SD_LMesh, ErrStat, ErrMsg ) CALL MeshDestroy( ModuleMapTypeData%u_SD_LMesh_2, ErrStat, ErrMsg ) - CALL MeshDestroy( ModuleMapTypeData%u_HD_M_LumpedMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( ModuleMapTypeData%u_HD_M_DistribMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( ModuleMapTypeData%u_HD_Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_HD_M_Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( ModuleMapTypeData%u_HD_W_Mesh, ErrStat, ErrMsg ) CALL MeshDestroy( ModuleMapTypeData%u_ED_HubPtLoad, ErrStat, ErrMsg ) CALL MeshDestroy( ModuleMapTypeData%u_ED_HubPtLoad_2, ErrStat, ErrMsg ) IF (ALLOCATED(ModuleMapTypeData%u_BD_RootMotion)) THEN @@ -36178,71 +36150,71 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ED_P_2_HD_M_L: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_HD_M_L + Int_BufSz = Int_BufSz + 3 ! ED_P_2_Mooring_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_HD_M_L + IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_Mooring_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_HD_M_L + IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_Mooring_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_HD_M_L + IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_Mooring_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! HD_M_L_2_ED_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_L_2_ED_P + Int_BufSz = Int_BufSz + 3 ! Mooring_P_2_ED_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! Mooring_P_2_ED_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! HD_M_L_2_ED_P + IF(ALLOCATED(Re_Buf)) THEN ! Mooring_P_2_ED_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! HD_M_L_2_ED_P + IF(ALLOCATED(Db_Buf)) THEN ! Mooring_P_2_ED_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! HD_M_L_2_ED_P + IF(ALLOCATED(Int_Buf)) THEN ! Mooring_P_2_ED_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ED_P_2_Mooring_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, .TRUE. ) ! ED_P_2_Mooring_P + Int_BufSz = Int_BufSz + 3 ! SD_P_2_Mooring_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ED_P_2_Mooring_P + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_Mooring_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ED_P_2_Mooring_P + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_Mooring_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ED_P_2_Mooring_P + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_Mooring_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! Mooring_P_2_ED_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, .TRUE. ) ! Mooring_P_2_ED_P + Int_BufSz = Int_BufSz + 3 ! Mooring_P_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! Mooring_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Mooring_P_2_ED_P + IF(ALLOCATED(Re_Buf)) THEN ! Mooring_P_2_SD_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Mooring_P_2_ED_P + IF(ALLOCATED(Db_Buf)) THEN ! Mooring_P_2_SD_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Mooring_P_2_ED_P + IF(ALLOCATED(Int_Buf)) THEN ! Mooring_P_2_SD_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -36314,37 +36286,37 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! SD_P_2_HD_M_L: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_HD_M_L + Int_BufSz = Int_BufSz + 3 ! SD_P_2_HD_W_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2, .TRUE. ) ! SD_P_2_HD_W_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_HD_M_L + IF(ALLOCATED(Re_Buf)) THEN ! SD_P_2_HD_W_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_HD_M_L + IF(ALLOCATED(Db_Buf)) THEN ! SD_P_2_HD_W_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_HD_M_L + IF(ALLOCATED(Int_Buf)) THEN ! SD_P_2_HD_W_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! HD_M_L_2_SD_P: size of buffers for each call to pack subtype - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_M_L_2_SD_P + Int_BufSz = Int_BufSz + 3 ! HD_W_P_2_SD_P: size of buffers for each call to pack subtype + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2, .TRUE. ) ! HD_W_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! HD_M_L_2_SD_P + IF(ALLOCATED(Re_Buf)) THEN ! HD_W_P_2_SD_P Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! HD_M_L_2_SD_P + IF(ALLOCATED(Db_Buf)) THEN ! HD_W_P_2_SD_P Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! HD_M_L_2_SD_P + IF(ALLOCATED(Int_Buf)) THEN ! HD_W_P_2_SD_P Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -36739,54 +36711,37 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! u_HD_M_LumpedMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_M_LumpedMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! u_HD_M_LumpedMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! u_HD_M_LumpedMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! u_HD_M_LumpedMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! u_HD_M_DistribMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_M_DistribMesh + Int_BufSz = Int_BufSz + 3 ! u_HD_M_Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_HD_M_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_M_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! u_HD_M_DistribMesh + IF(ALLOCATED(Re_Buf)) THEN ! u_HD_M_Mesh Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! u_HD_M_DistribMesh + IF(ALLOCATED(Db_Buf)) THEN ! u_HD_M_Mesh Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! u_HD_M_DistribMesh + IF(ALLOCATED(Int_Buf)) THEN ! u_HD_M_Mesh Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! u_HD_Mesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_Mesh + Int_BufSz = Int_BufSz + 3 ! u_HD_W_Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%u_HD_W_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! u_HD_W_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! u_HD_Mesh + IF(ALLOCATED(Re_Buf)) THEN ! u_HD_W_Mesh Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! u_HD_Mesh + IF(ALLOCATED(Db_Buf)) THEN ! u_HD_W_Mesh Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! u_HD_Mesh + IF(ALLOCATED(Int_Buf)) THEN ! u_HD_W_Mesh Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -37194,7 +37149,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_HD_M_L + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -37222,7 +37177,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_L_2_ED_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! Mooring_P_2_ED_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -37250,7 +37205,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2, OnlySize ) ! ED_P_2_Mooring_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -37278,7 +37233,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, OnlySize ) ! Mooring_P_2_ED_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! Mooring_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -37418,7 +37373,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_HD_M_L + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2, OnlySize ) ! SD_P_2_HD_W_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -37446,7 +37401,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_M_L_2_SD_P + CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2, OnlySize ) ! HD_W_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38167,7 +38122,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL MeshPack( InData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_M_LumpedMesh + CALL MeshPack( InData%u_HD_M_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_M_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38195,35 +38150,7 @@ SUBROUTINE FAST_PackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL MeshPack( InData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_M_DistribMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_Mesh + CALL MeshPack( InData%u_HD_W_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! u_HD_W_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38876,7 +38803,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) ! ED_P_2_HD_M_L + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) ! ED_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38916,7 +38843,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_L_2_ED_P, ErrStat2, ErrMsg2 ) ! HD_M_L_2_ED_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) ! Mooring_P_2_ED_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38956,7 +38883,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) ! ED_P_2_Mooring_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2 ) ! SD_P_2_Mooring_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -38996,7 +38923,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) ! Mooring_P_2_ED_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2 ) ! Mooring_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -39196,7 +39123,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) ! SD_P_2_HD_M_L + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2 ) ! SD_P_2_HD_W_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -39236,7 +39163,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2 ) ! HD_M_L_2_SD_P + CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2 ) ! HD_W_P_2_SD_P CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -40236,47 +40163,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%u_HD_M_LumpedMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_M_LumpedMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%u_HD_M_DistribMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_M_DistribMesh + CALL MeshUnpack( OutData%u_HD_M_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_M_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -40316,7 +40203,7 @@ SUBROUTINE FAST_UnPackModuleMapType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL MeshUnpack( OutData%u_HD_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_Mesh + CALL MeshUnpack( OutData%u_HD_W_Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! u_HD_W_Mesh CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN From c2e4faee8beeec83c760a1561a6565291d86bd5b Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 15:04:38 -0600 Subject: [PATCH 209/377] This file needs to still be updated for HD changes --- modules/openfast-library/src/FAST_Lin.f90 | 144 +++++++--------------- 1 file changed, 47 insertions(+), 97 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 60ef9a59d..f4257cf6c 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -2669,60 +2669,41 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} !=================================================== - ! y_ED%PlatformPtMesh and u_HD%Morison%DistribMesh + ! y_ED%PlatformPtMesh and u_HD%Morison%Mesh !=================================================== - +!TODO-LIN: Check for new Morison GJH 4/23/20 NOw could depend on SD, right? GJH 5/11/2020 + ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): - - call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - + ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} HD_Start_td = y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) - HD_Start_tr = HD_Start_td + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field - - ! translational velocity: - if (allocated(MeshMapData%ED_P_2_HD_M_L%dM%tv_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_L%dM%tv_ud, HD_Start_tr, HD_Start_td ) - end if - - ! translational acceleration: - HD_Start_tr = HD_Start_tr + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) - if (allocated(MeshMapData%ED_P_2_HD_M_L%dM%ta_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_L%dM%ta_ud, HD_Start_tr, HD_Start_td ) - end if - - !=================================================== - ! y_ED%PlatformPtMesh and u_HD%Morison%LumpedMesh - !=================================================== - - call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} - HD_Start_td = HD_Start_tr + u_HD%Morison%DistribMesh%NNodes * 6 ! skip 1 field ( TranslationAcc and RotationAcc) - HD_Start_tr = HD_Start_td + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + HD_Start_tr = HD_Start_td + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + ! translational velocity: if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%tv_uD )) then call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) end if - + ! translational acceleration: - HD_Start_tr = HD_Start_tr + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) - - if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then + HD_Start_tr = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) end if + !=================================================== - ! y_ED%PlatformPtMesh and u_HD%Mesh + ! y_ED%PlatformPtMesh and u_HD%WAMITMesh !=================================================== - +!TODO-LIN: Check for new Morison+WAMIT GJH 4/23/20 +! Should this potentially be between SD and HD for some cases? call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - HD_Start_td = HD_Start_tr + u_HD%Morison%LumpedMesh%NNodes * 6 ! skip 2 field ( TranslationalAcc and RotationAcc) + HD_Start_td = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 field ( TranslationalAcc and RotationAcc) HD_Start_tr = HD_Start_td + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field ! translational velocity: if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%tv_uD )) then @@ -2768,32 +2749,17 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd !................................... - ! Distributed Morison Mesh + ! Morison Mesh !................................... - IF (u_HD%Morison%DistribMesh%Committed) THEN + IF (u_HD%Morison%Mesh%Committed) THEN !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices !!! ! while forming dUdy, too. - !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) + !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - HD_Start = Indx_u_HD_Distrib_Start(u_HD, y_FAST) ! start of u_HD%Morison%DistribMesh%TranslationDisp field + HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, HD_Start, ED_Out_Start, dUdy, .false.) - END IF - - !................................... - ! Lumped Morison Mesh - !................................... - IF (u_HD%Morison%LumpedMesh%Committed) THEN - - !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices - !!! ! while forming dUdy, too. - !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - - HD_Start = Indx_u_HD_Lumped_Start(u_HD, y_FAST) ! start of u_HD%Morison%LumpedMesh%TranslationDisp field - - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy, .false.) + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy, .false.) END IF !................................... @@ -2907,7 +2873,7 @@ END SUBROUTINE Linear_MAP_InputSolve_dy ! if ( p_FAST%CompMooring == Module_MAP ) then ! MAP- ElastoDyn ! ! !=================================================== -! ! y_ED%PlatformPtMesh and u_MAP%Morison%DistribMesh +! ! y_ED%PlatformPtMesh and u_MAP%Morison%Mesh ! !=================================================== ! ! ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): @@ -3801,8 +3767,8 @@ FUNCTION Indx_u_AD_BladeInflow_Start(u_AD, y_FAST) RESULT(AD_Start) END FUNCTION Indx_u_AD_BladeInflow_Start !---------------------------------------------------------------------------------------------------------------------------------- !---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the u_HD%Morison%DistribMesh mesh in the FAST linearization inputs. -FUNCTION Indx_u_HD_Distrib_Start(u_HD, y_FAST) RESULT(HD_Start) +!> This routine returns the starting index for the u_HD%Morison%Mesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_HD_Morison_Start(u_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t @@ -3810,34 +3776,22 @@ FUNCTION Indx_u_HD_Distrib_Start(u_HD, y_FAST) RESULT(HD_Start) HD_Start = y_FAST%Lin%Modules(Module_HD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) -END FUNCTION Indx_u_HD_Distrib_Start -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the u_HD%Morison%LumpedMesh mesh in the FAST linearization inputs. -FUNCTION Indx_u_HD_Lumped_Start(u_HD, y_FAST) RESULT(HD_Start) - TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) - TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t - - INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs - - HD_Start = Indx_u_HD_Distrib_Start(u_HD, y_FAST) - if (u_HD%Morison%DistribMesh%committed) HD_Start = HD_Start + u_HD%Morison%DistribMesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components - -END FUNCTION Indx_u_HD_Lumped_Start +END FUNCTION Indx_u_HD_Morison_Start !---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the u_HD%Mesh mesh in the FAST linearization inputs. +!> This routine returns the starting index for the u_HD%WAMITMesh mesh in the FAST linearization inputs. FUNCTION Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs - HD_Start = Indx_u_HD_Lumped_Start(u_HD, y_FAST) - if (u_HD%Morison%LumpedMesh%committed) HD_Start = HD_Start + u_HD%Morison%LumpedMesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components + HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) + if (u_HD%Morison%Mesh%committed) HD_Start = HD_Start + u_HD%Morison%Mesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components END FUNCTION Indx_u_HD_PlatformRef_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the y_HD%Morison%DistribMesh mesh in the FAST linearization outputs. -FUNCTION Indx_y_HD_Distrib_Start(y_HD, y_FAST) RESULT(HD_Start) +FUNCTION Indx_y_HD_Morison_Start(y_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t @@ -3845,19 +3799,7 @@ FUNCTION Indx_y_HD_Distrib_Start(y_HD, y_FAST) RESULT(HD_Start) HD_Start = y_FAST%Lin%Modules(Module_HD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) -END FUNCTION Indx_y_HD_Distrib_Start -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the y_HD%Morison%LumpedMesh mesh in the FAST linearization outputs. -FUNCTION Indx_y_HD_Lumped_Start(y_HD, y_FAST) RESULT(HD_Start) - TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) - TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t - - INTEGER :: HD_Start !< starting index of this mesh in HydroDyn Outputs - - HD_Start = Indx_y_HD_Distrib_Start(y_HD, y_FAST) - if (y_HD%Morison%DistribMesh%committed) HD_Start = HD_Start + y_HD%Morison%DistribMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components - -END FUNCTION Indx_y_HD_Lumped_Start +END FUNCTION Indx_y_HD_Morison_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the y_HD%Mesh mesh in the FAST linearization outputs. FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) @@ -3868,8 +3810,8 @@ FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) !< starting index of this mesh in HydroDyn Outputs - HD_Start = Indx_y_HD_Lumped_Start(y_HD, y_FAST) - if (y_HD%Morison%LumpedMesh%committed) HD_Start = HD_Start + y_HD%Morison%LumpedMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + HD_Start = Indx_y_HD_Morison_Start(y_HD, y_FAST) + if (y_HD%Morison%Mesh%committed) HD_Start = HD_Start + y_HD%Morison%Mesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components END FUNCTION Indx_y_HD_PlatformRef_Start !---------------------------------------------------------------------------------------------------------------------------------- @@ -4365,6 +4307,7 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, ! local variables INTEGER(IntKi) :: k ! generic loop counters INTEGER(IntKi) :: i ! generic loop counters + INTEGER(IntKi) :: iBody ! WAMIT body loop counter INTEGER(IntKi) :: j ! generic loop counters INTEGER(IntKi) :: indx ! generic loop counters INTEGER(IntKi) :: indx_last ! generic loop counters @@ -4460,13 +4403,20 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, IF ( p_FAST%CompHydro == Module_HD ) THEN ThisModule = Module_HD if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then - nStates = HD%p%WAMIT%SS_Exctn%N - if (nStates > 0) then - call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT%SS_Exctn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) - end if - if (nStates < size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then - call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT%SS_Rdtn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) - end if + ! TODO: WAMIT parameter and continuous states are now an arrays of length NBody, so we need to modify this following code to handle that + ! We will try to loop over NBody and add each to the state array + do iBody = 1, HD%p%NBody + nStates = HD%p%WAMIT(iBody)%SS_Exctn%numStates + if (nStates > 0) then + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Exctn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) + end if + end do + do iBody = 1, HD%p%NBody + nStates = HD%p%WAMIT(iBody)%SS_Rdtn%numStates + if (nStates < size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Rdtn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) + end if + end do end if END IF From 4398988e97ce67cb23d72dac4860cf97198c946a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 15:06:22 -0600 Subject: [PATCH 210/377] The file needs to be updated for VTK and MeshWrBin for new HD meshes --- modules/openfast-library/src/FAST_Subs.f90 | 58 +++++++++++----------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 3f47dba49..55251e60a 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -3351,9 +3351,9 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_AD, InitInData_H ! morison surfaces !....................... - IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN - - call move_alloc(InitOutData_HD%Morison%Morison_Rad, p_FAST%VTK_Surface%MorisonRad) + IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN + !TODO: FIX for visualization GJH 4/23/20 + ! call move_alloc(InitOutData_HD%Morison%Morison_Rad, p_FAST%VTK_Surface%MorisonRad) END IF @@ -5320,21 +5320,20 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, H END IF ! HydroDyn - IF ( p_FAST%CompHydro == Module_HD .and. allocated(HD%Input)) THEN + IF ( p_FAST%CompHydro == Module_HD .and. allocated(HD%Input)) THEN + !TODO: Fix for Visualizaton GJH 4/23/20 !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%LumpedMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonLumped_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) +!TODO call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) outputFields = .false. else - call MeshWrVTK(p_FAST%TurbinePos, HD%y%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WamitMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh ) outputFields = p_FAST%VTK_fields end if - call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%LumpedMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonLumped', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%LumpedMesh ) - call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%DistribMesh ) - + call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh ) END IF @@ -5478,14 +5477,14 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, IF ( p_FAST%CompHydro == Module_HD ) THEN if (p_FAST%CompSub == Module_NONE) then - call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WAMITMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh ) outputFields = .false. else OutputFields = p_FAST%VTK_fields end if - - call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', & - y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=HD%y%Morison%DistribMesh ) + !TODO: Fix for Visualization GJH 4/23/20 + ! call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', & + ! y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=HD%y%Morison%DistribMesh ) END IF @@ -5585,19 +5584,20 @@ SUBROUTINE WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW ! IF ( p_FAST%CompSub == Module_SD ) THEN ! call MeshWrVTK(p_FAST%TurbinePos, SD%Input(1)%TPMesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_TPMesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) ! call MeshWrVTK(p_FAST%TurbinePos, SD%y%y2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y2Mesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 ) -! END IF - - IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN - !if ( p_FAST%CompSub == Module_NONE ) then ! floating - ! OutputFields = .false. - !else - ! OutputFields = p_FAST%VTK_fields - !end if - - call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', & - y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, & - p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%DistribMesh ) - END IF +! END IF +!TODO: Fix below section for new Morison GJH 4/23/20 + ! + !IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN + ! !if ( p_FAST%CompSub == Module_NONE ) then ! floating + ! ! OutputFields = .false. + ! !else + ! ! OutputFields = p_FAST%VTK_fields + ! !end if + ! + ! call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', & + ! y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, & + ! p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%DistribMesh ) + !END IF ! Mooring Lines? @@ -5811,8 +5811,7 @@ SUBROUTINE WriteInputMeshesToFile(u_ED, u_AD, u_SD, u_HD, u_MAP, u_BD, FileName, CALL MeshWrBin( unOut, u_ED%PlatformPtMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_SD%LMesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) ! Add how many BD blade meshes there are: @@ -5894,8 +5893,7 @@ SUBROUTINE WriteMotionMeshesToFile(time, y_ED, u_SD, y_SD, u_HD, u_MAP, y_BD, u_ CALL MeshWrBin( unOut, y_ED%PlatformPtMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, y_SD%y2Mesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Morison%distribMesh, ErrStat, ErrMsg ) - CALL MeshWrBin( unOut, u_HD%Morison%lumpedMesh, ErrStat, ErrMsg ) + CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg ) CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg ) DO K_local = 1,SIZE(y_BD,1) From 42a72a8744fb7c292e32c11856f0d8f9fd7eb1f2 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 20 May 2020 15:07:53 -0600 Subject: [PATCH 211/377] First attempt at reworking glue-code for new TCF module solve --- modules/openfast-library/src/FAST_Solver.f90 | 859 +++++++++---------- 1 file changed, 413 insertions(+), 446 deletions(-) diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index a56426a7f..3b0e6cee9 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -942,11 +942,11 @@ SUBROUTINE SrvD_SetExternalInputs( p_FAST, m_FAST, u_SrvD ) END SUBROUTINE SrvD_SetExternalInputs !---------------------------------------------------------------------------------------------------------------------------------- !> This routine transfers the SD outputs into inputs required for HD -SUBROUTINE Transfer_SD_to_HD( y_SD, u_HD_M_LumpedMesh, u_HD_M_DistribMesh, MeshMapData, ErrStat, ErrMsg ) +SUBROUTINE Transfer_SD_to_HD( y_SD, u_HD_W_Mesh, u_HD_M_Mesh, MeshMapData, ErrStat, ErrMsg ) !.................................................................................................................................. TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< The outputs of the structural dynamics module - TYPE(MeshType), INTENT(INOUT) :: u_HD_M_LumpedMesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) - TYPE(MeshType), INTENT(INOUT) :: u_HD_M_DistribMesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) + TYPE(MeshType), INTENT(INOUT) :: u_HD_W_Mesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) + TYPE(MeshType), INTENT(INOUT) :: u_HD_M_Mesh !< HydroDyn input mesh (separated here so that we can use temp meshes in ED_SD_HD_InputSolve) TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation @@ -960,20 +960,19 @@ SUBROUTINE Transfer_SD_to_HD( y_SD, u_HD_M_LumpedMesh, u_HD_M_DistribMesh, MeshM ErrStat = ErrID_None ErrMsg = "" - - IF ( u_HD_M_LumpedMesh%Committed ) THEN + IF ( u_HD_W_Mesh%Committed ) THEN ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body - CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_HD_M_LumpedMesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%Morison%LumpedMesh)' ) + CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_HD_W_Mesh, MeshMapData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%WAMITMesh)' ) - END IF - - IF ( u_HD_M_DistribMesh%Committed ) THEN + END IF + IF ( u_HD_M_Mesh%Committed ) THEN + + ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body + CALL Transfer_Point_to_Point( y_SD%y2Mesh, u_HD_M_Mesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%Morison%Mesh)' ) - ! These are the motions for the HD line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body - CALL Transfer_Point_to_Line2( y_SD%y2Mesh, u_HD_M_DistribMesh, MeshMapData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_SD_to_HD (u_HD%Morison%DistribMesh)' ) END IF END SUBROUTINE Transfer_SD_to_HD @@ -997,40 +996,34 @@ SUBROUTINE Transfer_PlatformMotion_to_HD( PlatformMotion, u_HD, MeshMapData, Err ErrStat = ErrID_None ErrMsg = "" + ! This is for case of rigid substructure + !bjj: We do this without all the extra meshcopy/destroy calls with u_mapped because these inputs are only from one mesh - IF ( u_HD%WAMITMesh%Committed ) THEN - - ! Transfer the ED outputs of the platform motions to the HD input of which represents the same data - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + ! Transfer the ED outputs of the platform motions to the HD input of which represents the same data + CALL Transfer_Point_to_Point( PlatformMotion, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,'Transfer_ED_to_HD (u_HD%PRPMesh)' ) + IF ( u_HD%WAMITMesh%Committed ) THEN + ! These are the motions for the lumped point loads associated the WAMIT body(ies) and include: hydrostatics, radiation memory effect, ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, ! hydrodynamic added mass - CALL Transfer_Point_to_Point( PlatformMotion, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Mesh)' ) + CALL Transfer_Point_to_Point( PlatformMotion, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%WAMITMesh)' ) END IF !WAMIT - IF ( u_HD%Morison%LumpedMesh%Committed ) THEN + IF ( u_HD%Morison%Mesh%Committed ) THEN ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body - CALL Transfer_Point_to_Point( PlatformMotion, u_HD%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Morison%LumpedMesh)' ) + CALL Transfer_Point_to_Point( PlatformMotion, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Morison%Mesh)' ) END IF - IF ( u_HD%Morison%DistribMesh%Committed ) THEN - - ! These are the motions for the line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body - CALL Transfer_Point_to_Line2( PlatformMotion, u_HD%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Morison%DistribMesh)' ) - - END IF - END SUBROUTINE Transfer_PlatformMotion_to_HD !---------------------------------------------------------------------------------------------------------------------------------- !> This routine transfers the ED outputs into inputs required for HD, SD, ExtPtfm, BD, MAP, and/or FEAM @@ -1067,7 +1060,7 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_SD%TPMesh' ) - IF ( p_FAST%CompHydro == Module_HD ) call TransferFixedBottomToHD() + IF ( p_FAST%CompHydro == Module_HD ) call TransferEDToHD_PRP() ELSEIF ( p_FAST%CompSub == Module_ExtPtfm ) THEN @@ -1075,7 +1068,14 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_ExtPtfm%PtfmMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//':u_ExtPtfm%PtfmMesh' ) - IF ( p_FAST%CompHydro == Module_HD ) call TransferFixedBottomToHD() + if ( p_FAST%CompHydro == Module_HD ) then + ! Map ED outputs to HD inputs: + CALL Transfer_PlatformMotion_to_HD( y_ED%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName ) + ! TODO: GJH Used to be the following GJH 5/13/2020 + ! call TransferFixedBottomToHD() + end if + ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN ! Map ED outputs to HD inputs: @@ -1096,7 +1096,7 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, IF ( p_FAST%CompMooring == Module_MAP ) THEN - +!TODO: GJH Need to check for SD, if present, then SD will transfer to these Mooring modules, NOT ED! GJH 5/11/2020 ! motions: CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MAP%PtFairDisplacement' ) @@ -1118,85 +1118,31 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, END IF contains - subroutine TransferFixedBottomToHD() - IF ( u_HD%Mesh%Committed ) THEN + subroutine TransferEDToHD_PRP() + + ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, + ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, + ! hydrodynamic added mass + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%PRPMesh)' ) + + end subroutine + + subroutine TransferFixedBottomToHD() + IF ( u_HD%WAMITMesh%Committed ) THEN +!TODO: GJH Do we still need this? ExtPtfm ? GJH 5/11/2020 ! These are the motions for the lumped point loads associated the WAMIT body and include: hydrostatics, radiation memory effect, ! wave kinematics, additional preload, additional stiffness, additional linear damping, additional quadratic damping, ! hydrodynamic added mass - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName//' (u_HD%Mesh)' ) END IF !WAMIT end subroutine END SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine sets the inputs required for MAP. -SUBROUTINE MAP_InputSolve( u_MAP, y_ED, MeshMapData, ErrStat, ErrMsg ) -!.................................................................................................................................. - - ! Passed variables - TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< MAP input - TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module - TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - !---------------------------------------------------------------------------------------------------- - ! Map ED outputs to MAP inputs - !---------------------------------------------------------------------------------------------------- - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) - - -END SUBROUTINE MAP_InputSolve -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine sets the inputs required for FEAM. -SUBROUTINE FEAM_InputSolve( u_FEAM, y_ED, MeshMapData, ErrStat, ErrMsg ) -!.................................................................................................................................. - - ! Passed variables - TYPE(FEAM_InputType), INTENT(INOUT) :: u_FEAM !< FEAM input - TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module - TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - !---------------------------------------------------------------------------------------------------- - ! Map ED outputs to FEAM inputs - !---------------------------------------------------------------------------------------------------- - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) - - -END SUBROUTINE FEAM_InputSolve -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine sets the inputs required for MoorDyn. -SUBROUTINE MD_InputSolve( u_MD, y_ED, MeshMapData, ErrStat, ErrMsg ) -!.................................................................................................................................. - - ! Passed variables - TYPE(MD_InputType), INTENT(INOUT) :: u_MD !< MoorDyn input - TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< The outputs of the structural dynamics module - TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< data for mapping meshes between modules - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - !---------------------------------------------------------------------------------------------------- - ! Map ED outputs to MoorDyn inputs - !---------------------------------------------------------------------------------------------------- - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) - - -END SUBROUTINE MD_InputSolve !---------------------------------------------------------------------------------------------------------------------------------- !> This routine sets the inputs required for IceFloe. SUBROUTINE IceFloe_InputSolve( u_IceF, y_SD, MeshMapData, ErrStat, ErrMsg ) @@ -1320,14 +1266,14 @@ END SUBROUTINE Transfer_ED_to_BD_tmp !---------------------------------------------------------------------------------------------------------------------------------- !> This routine transfers the HD outputs into inputs required for ED. Note that this *adds* to the values already in !! u_SD_LMesh (so initialize it before calling this routine). -SUBROUTINE Transfer_HD_to_SD( u_mapped, u_SD_LMesh, u_mapped_positions, y_HD, u_HD_M_LumpedMesh, u_HD_M_DistribMesh, MeshMapData, ErrStat, ErrMsg ) +SUBROUTINE Transfer_HD_to_SD( u_mapped, u_SD_LMesh, u_mapped_positions, y_HD, u_HD_W_Mesh, u_HD_M_Mesh, MeshMapData, ErrStat, ErrMsg ) !.................................................................................................................................. TYPE(MeshType), INTENT(INOUT) :: u_mapped !< temporary copy of SD mesh (an argument to avoid another temporary mesh copy) TYPE(MeshType), INTENT(INOUT) :: u_SD_LMesh !< SD Inputs on LMesh at t (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) TYPE(MeshType), INTENT(IN ) :: u_mapped_positions !< Mesh sibling of u_mapped, with displaced positions TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HydroDyn outputs - TYPE(MeshType), INTENT(IN ) :: u_HD_M_LumpedMesh !< HydroDyn input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) - TYPE(MeshType), INTENT(IN ) :: u_HD_M_DistribMesh !< HydroDyn input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) + TYPE(MeshType), INTENT(IN ) :: u_HD_W_Mesh !< HydroDyn WAMIT input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) + TYPE(MeshType), INTENT(IN ) :: u_HD_M_Mesh !< HydroDyn Morison input mesh (separate so we can call from FullOpt1_InputOutputSolve with temp meshes) TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status @@ -1343,10 +1289,9 @@ SUBROUTINE Transfer_HD_to_SD( u_mapped, u_SD_LMesh, u_mapped_positions, y_HD, u_ ErrMsg = "" !assumes u_SD%LMesh%Committed (i.e., u_SD_LMesh%Committed) - - IF ( y_HD%Morison%LumpedMesh%Committed ) THEN + IF ( y_HD%WAMITMesh%Committed ) THEN ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD%Morison%LumpedMesh, u_mapped, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, u_HD_M_LumpedMesh, u_mapped_positions ) + CALL Transfer_Point_to_Point( y_HD%WAMITMesh, u_mapped, MeshMapData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2, u_HD_W_Mesh, u_mapped_positions ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1355,39 +1300,40 @@ SUBROUTINE Transfer_HD_to_SD( u_mapped, u_SD_LMesh, u_mapped_positions, y_HD, u_ #ifdef DEBUG_MESH_TRANSFER CALL WrScr('********************************************************') - CALL WrScr('**** SD to HD point-to-point (morison lumped) *****') + CALL WrScr('**** SD to HD point-to-point (WAMIT) *****') CALL WrScr('********************************************************') - CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_M_LumpedMesh, y_HD%Morison%LumpedMesh,& - MeshMapData%SD_P_2_HD_M_P, MeshMapData%HD_M_P_2_SD_P, & - 'SD_y2_HD_ML_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) + CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_W_Mesh, y_HD%WAMITMesh,& + MeshMapData%SD_P_2_HD_W_P, MeshMapData%HD_M_P_2_SD_P, & + 'SD_y2_HD_WP_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) !print * !pause -#endif - - END IF +#endif + END IF - IF ( y_HD%Morison%DistribMesh%Committed ) THEN + IF ( y_HD%Morison%Mesh%Committed ) THEN ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Line2_to_Point( y_HD%Morison%DistribMesh, u_mapped, MeshMapData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2, u_HD_M_DistribMesh, u_mapped_positions ) + CALL Transfer_Point_to_Point( y_HD%Morison%Mesh, u_mapped, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, u_HD_M_Mesh, u_mapped_positions ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN u_SD_LMesh%Force = u_SD_LMesh%Force + u_mapped%Force - u_SD_LMesh%Moment = u_SD_LMesh%Moment + u_mapped%Moment - -#ifdef DEBUG_MESH_TRANSFER + u_SD_LMesh%Moment = u_SD_LMesh%Moment + u_mapped%Moment + +#ifdef DEBUG_MESH_TRANSFER CALL WrScr('********************************************************') - CALL WrScr('**** SD to HD point-to-line2 (morison distributed) *****') + CALL WrScr('**** SD to HD point-to-point (morison) *****') CALL WrScr('********************************************************') - CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_M_DistribMesh,y_HD%Morison%DistribMesh,& - MeshMapData%SD_P_2_HD_M_L, MeshMapData%HD_M_L_2_SD_P, & - 'SD_y2_HD_MD_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) + CALL WriteMappingTransferToFile(u_mapped, u_mapped_positions, u_HD_M_Mesh, y_HD%Morison%Mesh,& + MeshMapData%SD_P_2_HD_M_P, MeshMapData%HD_M_P_2_SD_P, & + 'SD_y2_HD_MP_Meshes_t'//TRIM(Num2LStr(0))//'.bin' ) !print * - ! pause + !pause + #endif END IF + END SUBROUTINE Transfer_HD_to_SD !---------------------------------------------------------------------------------------------------------------------------------- @@ -1403,6 +1349,7 @@ END FUNCTION GetPerturb !---------------------------------------------------------------------------------------------------------------------------------- !> This routine performs the Input-Output solve for ED and HD. !! Note that this has been customized for the physics in the problems and is not a general solution. +!! This is only called is there is no substructure model (RIGID substructure) SUBROUTINE ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & , u_ED, p_ED, x_ED, xd_ED, z_ED, OtherSt_ED, y_ED, m_ED & , u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD & @@ -1772,16 +1719,18 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) PlatformMotions => y_ED2%PlatformPtMesh + ! This is only called is there is no flexible substructure model (RIGID substructure) + ! ! Transfer motions: - + !.................. ! Set mooring line inputs (which don't have acceleration fields) !.................. IF ( p_FAST%CompMooring == Module_MAP ) THEN - ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MAP_InputSolve( u_map, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations @@ -1789,8 +1738,8 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN - ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MD_InputSolve( u_MD, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations @@ -1798,8 +1747,8 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN - ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL FEAM_InputSolve( u_FEAM, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations @@ -1815,18 +1764,30 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) ! we use copies of the input meshes (we don't need to update values in the original data structures): !bjj: why don't we update u_HD2 here? shouldn't we update before using it to transfer the loads? - - CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if ( y_HD2%WAMITMesh%Committed ) then + ! Need to transfer motions first + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_W_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_W_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force - MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment - - + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if + if ( y_HD2%Morison%Mesh%Committed ) then + ! Need to transfer motions first + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_M_Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! we're mapping loads, so we also need the sibling meshes' displacements: + CALL Transfer_Point_to_Point( y_HD2%Morison%Mesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_M_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if U_Resid( 1: 3) = u_in( 1: 3) - MeshMapData%u_ED_PlatformPtMesh%Force(:,1) / p_FAST%UJacSclFact U_Resid( 4: 6) = u_in( 4: 6) - MeshMapData%u_ED_PlatformPtMesh%Moment(:,1) / p_FAST%UJacSclFact @@ -2096,8 +2057,8 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) END DO - CALL Create_FullOpt1_UVector(u, u_ED%PlatformPtMesh, u_SD%TPMesh, u_SD%LMesh, u_HD%Morison%LumpedMesh, & - u_HD%Morison%DistribMesh, u_HD%WAMITMesh, u_ED%HubPtLoad, MeshMapData%u_BD_RootMotion, u_Orca%PtfmMesh, & + CALL Create_FullOpt1_UVector(u, u_ED%PlatformPtMesh, u_SD%TPMesh, u_SD%LMesh, & + u_HD%Morison%Mesh, u_HD%WAMITMesh, u_ED%HubPtLoad, MeshMapData%u_BD_RootMotion, u_Orca%PtfmMesh, & u_ExtPtfm%PtfmMesh, p_FAST ) K = 0 @@ -2411,37 +2372,26 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & END DO END IF - DO TmpIndx=1,u_HD%Morison%LumpedMesh%NNodes - CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Lumped_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + DO TmpIndx=1,u_HD%Morison%Mesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Mesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Mesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Mesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO - DO TmpIndx=1,u_HD%Morison%LumpedMesh%NNodes - CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Lumped_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + DO TmpIndx=1,u_HD%Morison%Mesh%NNodes + CALL WrFileNR(UnJac, ' HD_M_Mesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Mesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_M_Mesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO - - DO TmpIndx=1,u_HD%Morison%DistribMesh%NNodes - CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Distrib_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) - END DO - DO TmpIndx=1,u_HD%Morison%DistribMesh%NNodes - CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_M_Distrib_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) - END DO DO TmpIndx=1,u_HD%WAMITMesh%NNodes - CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_Mesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_TranslationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_TranslationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_TranslationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO DO TmpIndx=1,u_HD%WAMITMesh%NNodes - CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) - CALL WrFileNR(UnJac, ' HD_Mesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_RotationAcc_X_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_RotationAcc_Y_'//TRIM(Num2LStr(TmpIndx))) + CALL WrFileNR(UnJac, ' HD_W_Mesh_RotationAcc_Z_'//TRIM(Num2LStr(TmpIndx))) END DO DO nb=1,p_FAST%nBeams @@ -2554,17 +2504,14 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & IF (p_FAST%CompHydro == Module_HD ) THEN ! Make copies of the accelerations we just solved for (so we don't overwrite them) - IF (MeshMapData%u_HD_M_LumpedMesh%Committed) THEN - MeshMapData%u_HD_M_LumpedMesh%RotationAcc = u_HD%Morison%LumpedMesh%RotationAcc - MeshMapData%u_HD_M_LumpedMesh%TranslationAcc = u_HD%Morison%LumpedMesh%TranslationAcc - ENDIF - IF (MeshMapData%u_HD_M_DistribMesh%Committed) THEN - MeshMapData%u_HD_M_DistribMesh%RotationAcc = u_HD%Morison%DistribMesh%RotationAcc - MeshMapData%u_HD_M_DistribMesh%TranslationAcc = u_HD%Morison%DistribMesh%TranslationAcc + IF (MeshMapData%u_HD_M_Mesh%Committed) THEN + MeshMapData%u_HD_M_Mesh%RotationAcc = u_HD%Morison%Mesh%RotationAcc + MeshMapData%u_HD_M_Mesh%TranslationAcc = u_HD%Morison%Mesh%TranslationAcc ENDIF - IF (MeshMapData%u_HD_Mesh%Committed) THEN - MeshMapData%u_HD_Mesh%RotationAcc = u_HD%WAMITMesh%RotationAcc - MeshMapData%u_HD_Mesh%TranslationAcc = u_HD%WAMITMesh%TranslationAcc + + IF (MeshMapData%u_HD_W_Mesh%Committed) THEN + MeshMapData%u_HD_W_Mesh%RotationAcc = u_HD%WAMITMesh%RotationAcc + MeshMapData%u_HD_W_Mesh%TranslationAcc = u_HD%WAMITMesh%TranslationAcc ENDIF ! transfer the output data to inputs @@ -2572,18 +2519,14 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & IF ( p_FAST%CompSub == Module_SD ) THEN ! Map SD outputs to HD inputs (keeping the accelerations we just calculated) - CALL Transfer_SD_to_HD( y_SD, u_HD%Morison%LumpedMesh, u_HD%Morison%DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL Transfer_SD_to_HD( y_SD, u_HD%WAMITMesh, u_HD%Morison%Mesh, MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ! Map ED outputs to HD inputs (keeping the accelerations we just calculated): ! Transfer the ED outputs of the platform motions to the HD input of which represents the same data - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL Transfer_Point_to_Point( PlatformMotionMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg, RoutineName ) - - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL Transfer_Point_to_Point( PlatformMotionMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSE @@ -2594,17 +2537,14 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & ! put the acceleration data (calucluted in this routine) back - IF (MeshMapData%u_HD_M_LumpedMesh%Committed) THEN - u_HD%Morison%LumpedMesh%RotationAcc = MeshMapData%u_HD_M_LumpedMesh%RotationAcc - u_HD%Morison%LumpedMesh%TranslationAcc = MeshMapData%u_HD_M_LumpedMesh%TranslationAcc - ENDIF - IF (MeshMapData%u_HD_M_DistribMesh%Committed) THEN - u_HD%Morison%DistribMesh%RotationAcc = MeshMapData%u_HD_M_DistribMesh%RotationAcc - u_HD%Morison%DistribMesh%TranslationAcc = MeshMapData%u_HD_M_DistribMesh%TranslationAcc + IF (MeshMapData%u_HD_M_Mesh%Committed) THEN + u_HD%Morison%Mesh%RotationAcc = MeshMapData%u_HD_M_Mesh%RotationAcc + u_HD%Morison%Mesh%TranslationAcc = MeshMapData%u_HD_M_Mesh%TranslationAcc ENDIF - IF (MeshMapData%u_HD_Mesh%Committed) THEN - u_HD%WAMITMesh%RotationAcc = MeshMapData%u_HD_Mesh%RotationAcc - u_HD%WAMITMesh%TranslationAcc = MeshMapData%u_HD_Mesh%TranslationAcc + + IF (MeshMapData%u_HD_W_Mesh%Committed) THEN + u_HD%WAMITMesh%RotationAcc = MeshMapData%u_HD_W_Mesh%RotationAcc + u_HD%WAMITMesh%TranslationAcc = MeshMapData%u_HD_W_Mesh%TranslationAcc ENDIF !...... @@ -2689,24 +2629,41 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, ! Set mooring line and ice inputs (which don't have acceleration fields and aren't used elsewhere in this routine, thus we're using the actual inputs (not a copy) ! Note that these values get overwritten at the completion of this routine.) !.................. + +!TODO: GJH Need to determine if mooring is connected to ED or SD GJH 5/11/2020 IF ( p_FAST%CompMooring == Module_MAP ) THEN ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MAP_InputSolve( u_map, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_SD2%y2Mesh, u_MAP%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN - ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MD_InputSolve( u_MD, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_SD2%y2Mesh, u_MD%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN - ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL FEAM_InputSolve( u_FEAM, y_ED2, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_SD2%y2Mesh, u_FEAM%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN @@ -2764,25 +2721,25 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, !.................. - ! Get HD inputs on Morison%LumpedMesh and Morison%DistribMesh + ! Get HD inputs on Morison%Mesh and WAMITMesh !.................. ! SD motions to HD: - CALL Transfer_SD_to_HD( y_SD2, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL Transfer_SD_to_HD( y_SD2, MeshMapData%u_HD_W_Mesh, MeshMapData%u_HD_M_Mesh, MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - - ! Map ED motion output to HD inputs: - CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) +!TODO: GJH I don't believe we need the following GJH 5/12/2020 + ! ! Map ED motion output to HD PRP inputs: + !CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_PRP_Mesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + ! CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) !.................. - ! Get SD loads inputs (MeshMapData%u_HD_M_LumpedMesh and MeshMapData%u_HD_M_DistribMesh meshes must be set first) + ! Get SD loads inputs (MeshMapData%u_HD_W_Mesh and MeshMapData%u_HD_M_Mesh meshes must be set first) !.................. ! Loads (outputs) from HD meshes transfered to SD LMesh (zero them out first because they get summed in Transfer_HD_to_SD) - CALL Transfer_HD_to_SD( MeshMapData%u_SD_LMesh_2, MeshMapData%u_SD_LMesh, y_SD2%Y2Mesh, y_HD2, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData, ErrStat2, ErrMsg2 ) + CALL Transfer_HD_to_SD( MeshMapData%u_SD_LMesh_2, MeshMapData%u_SD_LMesh, y_SD2%Y2Mesh, y_HD2, MeshMapData%u_HD_W_Mesh, MeshMapData%u_HD_M_Mesh, MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2852,22 +2809,10 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, ! we're mapping loads, so we also need the sibling meshes' displacements: CALL Transfer_Point_to_Point( y_SD2%Y1Mesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_SD_TPMesh, PlatformMotions ) !MeshMapData%u_SD_TPMesh contains the orientations needed for moment calculations CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - - ! WAMIT loads from HD get added to this load: - IF ( y_HD2%WAMITMesh%Committed ) THEN - - ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh ) !u_SD contains the orientations needed for moment calculations - CALL Transfer_Point_to_Point( y_HD2%Mesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions ) !u_SD contains the orientations needed for moment calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - - MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force - MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment - - END IF + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN - + !.................. ! Get ExtPtfm motions input !.................. @@ -2887,6 +2832,8 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, ELSE IF ( p_FAST%CompHydro == Module_HD ) THEN + ! Rigid Substructure case + !.................. ! Get HD inputs on 3 meshes !.................. @@ -2896,32 +2843,40 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, ! CALL Transfer_PlatformMotion_to_HD( y_ED2%PlatformPtMesh, u_HD, MeshMapData, ErrStat2, ErrMsg2 ) ! so, here are the transfers, again. - + ! Motions from ED to HD for mesh mapping + ! These are the motions for the lumped point loads associated the WAMIT body: - CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - + if (MeshMapData%u_HD_W_Mesh%Committed) then + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_W_Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + ! These are the motions for the lumped point loads associated viscous drag on the WAMIT body and/or filled/flooded lumped forces of the WAMIT body - if (MeshMapData%u_HD_M_LumpedMesh%Committed) then - CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_M_LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + if (MeshMapData%u_HD_M_Mesh%Committed) then + CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_M_Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) endif - ! These are the motions for the line2 (distributed) loads associated viscous drag on the WAMIT body and/or filled/flooded distributed forces of the WAMIT body - if (MeshMapData%u_HD_M_DistribMesh%Committed) then - CALL Transfer_Point_to_Line2( PlatformMotions, MeshMapData%u_HD_M_DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - endif + !.................. ! Get ED loads input (from HD only) !.................. ! we're mapping loads, so we also need the sibling meshes' displacements: - CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, y_ED2%PlatformPtMesh) !u_HD and u_mapped_positions contain the displaced positions for load calculations - CALL Transfer_Point_to_Point( y_HD2%AllHdroOrigin, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - + if ( y_HD2%WAMITMesh%Committed) then + CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_W_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + if ( y_HD2%Morison%Mesh%Committed ) then + CALL Transfer_Point_to_Point( y_HD2%Morison%Mesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_M_Mesh, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if + ELSE ! When using OrcaFlex, we need to zero this out @@ -2931,32 +2886,57 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, END IF !.................. - ! Get remaining portion of ED loads input on MeshMapData%u_ED_PlatformPtMesh (must do this after MeshMapData%u_SD_TPMesh and MeshMapData%u_HD_Mesh are set) + ! Get remaining portion of ED loads input on MeshMapData%u_ED_PlatformPtMesh (must do this after MeshMapData%u_SD_TPMesh and MeshMapData%u_HD_W_Mesh are set) ! at this point, MeshMapData%u_ED_PlatformPtMesh contains the portion of loads from SD and/or HD !.................. - + + !TODO: GJH This is no longer added to ED if SD is present, instead these are sent to SD GJH 5/11/2020 ! Get the loads for ED from a mooring module and add them: IF ( p_FAST%CompMooring == Module_MAP ) THEN - CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_SD_LMesh_2, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, y_SD2%Y2Mesh ) !u_MAP and y_SD contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force - MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + MeshMapData%u_SD_LMesh%Force = MeshMapData%u_SD_LMesh%Force + MeshMapData%u_SD_LMesh_2%Force + MeshMapData%u_SD_LMesh%Moment = MeshMapData%u_SD_LMesh%Moment + MeshMapData%u_SD_LMesh_2%Moment + else + CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN - CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_SD_LMesh_2, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, y_SD2%Y2Mesh ) !u_MD and y_SD contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force - MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment - + MeshMapData%u_SD_LMesh%Force = MeshMapData%u_SD_LMesh%Force + MeshMapData%u_SD_LMesh_2%Force + MeshMapData%u_SD_LMesh%Moment = MeshMapData%u_SD_LMesh%Moment + MeshMapData%u_SD_LMesh_2%Moment + else + CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN - CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_SD_LMesh_2, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, y_SD2%Y2Mesh ) !u_FEAM and y_SD contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force - MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + MeshMapData%u_SD_LMesh%Force = MeshMapData%u_SD_LMesh%Force + MeshMapData%u_SD_LMesh_2%Force + MeshMapData%u_SD_LMesh%Moment = MeshMapData%u_SD_LMesh%Moment + MeshMapData%u_SD_LMesh_2%Moment + else + CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + MeshMapData%u_ED_PlatformPtMesh%Force = MeshMapData%u_ED_PlatformPtMesh%Force + MeshMapData%u_ED_PlatformPtMesh_2%Force + MeshMapData%u_ED_PlatformPtMesh%Moment = MeshMapData%u_ED_PlatformPtMesh%Moment + MeshMapData%u_ED_PlatformPtMesh_2%Moment + end if ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN CALL Transfer_Point_to_Point( y_Orca2%PtfmMesh, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_Orca_PtfmMesh, PlatformMotions ) !u_Orca_PtfmMesh and y_ED contain the displacements needed for moment calculations @@ -2971,7 +2951,7 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, !.................. CALL Create_FullOpt1_UVector(U_Resid, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%u_SD_TPMesh, MeshMapData%u_SD_LMesh, & - MeshMapData%u_HD_M_LumpedMesh, MeshMapData%u_HD_M_DistribMesh, MeshMapData%u_HD_Mesh, & + MeshMapData%u_HD_M_Mesh, MeshMapData%u_HD_W_Mesh, & MeshMapData%u_ED_HubPtLoad, MeshMapData%u_BD_RootMotion, MeshMapData%u_Orca_PtfmMesh, & MeshMapData%u_ExtPtfm_PtfmMesh, p_FAST ) @@ -3030,7 +3010,7 @@ END SUBROUTINE FullOpt1_InputOutputSolve !---------------------------------------------------------------------------------------------------------------------------------- !> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. !! Do not change the order of this packing without changing subroutine Create_FullOpt1_UVector()! -SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_LumpedMesh, HD_M_DistribMesh, & +SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_Mesh, & HD_WAMIT_Mesh, ED_HubPtLoad, u_BD, Orca_PtfmMesh, ExtPtfm_PtfmMesh, ErrStat, ErrMsg) TYPE(FAST_ParameterType) , INTENT(INOUT) :: p_FAST !< FAST parameters @@ -3041,8 +3021,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP TYPE(MeshType) , INTENT(IN ) :: ED_HubPtLoad !< ElastoDyn's HubPtLoad mesh TYPE(MeshType) , INTENT(IN ) :: SD_TPMesh !< SubDyn's TP (transition piece) mesh TYPE(MeshType) , INTENT(IN ) :: SD_LMesh !< SubDyn's LMesh - TYPE(MeshType) , INTENT(IN ) :: HD_M_LumpedMesh !< HydroDyn's Morison Lumped Mesh - TYPE(MeshType) , INTENT(IN ) :: HD_M_DistribMesh !< HydroDyn's Morison Distributed Mesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_Mesh !< HydroDyn's Morison Lumped Mesh TYPE(MeshType) , INTENT(IN ) :: HD_WAMIT_Mesh !< HydroDyn's WAMIT mesh TYPE(BD_InputType) , INTENT(IN ) :: u_BD(:) !< inputs for each instance of the BeamDyn module (for the RootMotion meshes) TYPE(MeshType) , INTENT(IN ) :: Orca_PtfmMesh !< OrcaFlex interface PtfmMesh @@ -3075,8 +3054,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP + SD_LMesh%NNodes *6 ! SD inputs: 6 loads per node (size of SD input from HD) END IF - p_FAST%SizeJac_Opt1(4) = HD_M_LumpedMesh%NNodes *6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) - + HD_M_DistribMesh%NNodes*6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + p_FAST%SizeJac_Opt1(4) = HD_M_Mesh%NNodes *6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + HD_WAMIT_Mesh%NNodes*6 ! HD inputs: 6 accelerations per node (on the WAMIT mesh) IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN @@ -3227,19 +3205,19 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP ! HD inputs: !............... - !(Morison%LumpedMesh) - do i=1,HD_M_LumpedMesh%NNodes + !(Morison%Mesh) + do i=1,HD_M_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 9 !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 + MeshMapData%Jac_u_indx(index,1) = 9 !Module/Mesh/Field: u_HD%Morison%Mesh%TranslationAcc = 9 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 end do !j end do !i - do i=1,HD_M_LumpedMesh%NNodes + do i=1,HD_M_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 10 !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 + MeshMapData%Jac_u_indx(index,1) = 10 !Module/Mesh/Field: u_HD%Morison%Mesh%RotationAcc = 10 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3247,25 +3225,6 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP end do !i - !(Morison%DistribMesh) - do i=1,HD_M_DistribMesh%NNodes - do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 11 !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 - MeshMapData%Jac_u_indx(index,2) = j !index: j - MeshMapData%Jac_u_indx(index,3) = i !Node: i - index = index + 1 - end do !j - end do !i - - do i=1,HD_M_DistribMesh%NNodes - do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 12 !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 - MeshMapData%Jac_u_indx(index,2) = j !index: j - MeshMapData%Jac_u_indx(index,3) = i !Node: i - index = index + 1 - end do !j - end do !i - !(Mesh) do i=1,HD_WAMIT_Mesh%NNodes do j=1,3 @@ -3366,7 +3325,7 @@ END SUBROUTINE Init_FullOpt1_Jacobian !---------------------------------------------------------------------------------------------------------------------------------- !> This routine basically packs the relevant parts of the modules' input meshes for use in this InputOutput solve. !! Do not change the order of this packing without changing subroutine Init_FullOpt1_Jacobian()! -SUBROUTINE Create_FullOpt1_UVector(u, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_LumpedMesh, HD_M_DistribMesh, HD_WAMIT_Mesh, & +SUBROUTINE Create_FullOpt1_UVector(u, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD_M_Mesh, HD_WAMIT_Mesh, & ED_HubPtLoad, BD_RootMotion, Orca_PtfmMesh, ExtPtfm_PtfmMesh, p_FAST ) !.................................................................................................................................. @@ -3376,8 +3335,7 @@ SUBROUTINE Create_FullOpt1_UVector(u, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD TYPE(MeshType) , INTENT(IN ) :: ED_PlatformPtMesh !< ElastoDyn PlatformPt mesh TYPE(MeshType) , INTENT(IN ) :: SD_TPMesh !< SubDyn TP mesh TYPE(MeshType) , INTENT(IN ) :: SD_LMesh !< SubDyn Lmesh - TYPE(MeshType) , INTENT(IN ) :: HD_M_LumpedMesh !< HydroDyn Morison Lumped mesh - TYPE(MeshType) , INTENT(IN ) :: HD_M_DistribMesh !< HydroDyn Morison distributed mesh + TYPE(MeshType) , INTENT(IN ) :: HD_M_Mesh !< HydroDyn Morison Lumped mesh TYPE(MeshType) , INTENT(IN ) :: HD_WAMIT_Mesh !< HydroDyn WAMIT mesh TYPE(MeshType) , INTENT(IN ) :: ED_HubPtLoad !< ElastoDyn HubPt mesh TYPE(MeshType) , INTENT(IN ) :: BD_RootMotion(:) !< BeamDyn RootMotion meshes @@ -3450,30 +3408,17 @@ SUBROUTINE Create_FullOpt1_UVector(u, ED_PlatformPtMesh, SD_TPMesh, SD_LMesh, HD end if !............... - ! HD inputs (Morison%LumpedMesh): + ! HD inputs (Morison%Mesh): !............... - do i=1,HD_M_LumpedMesh%NNodes - indx_last = indx_first + 2 - u(indx_first:indx_last) = HD_M_LumpedMesh%TranslationAcc(:,i) - indx_first = indx_last + 1 - end do - - do i=1,HD_M_LumpedMesh%NNodes - indx_last = indx_first + 2 - u(indx_first:indx_last) = HD_M_LumpedMesh%RotationAcc(:,i) - indx_first = indx_last + 1 - end do - - ! HD inputs (Morison%DistribMesh): - do i=1,HD_M_DistribMesh%NNodes + do i=1,HD_M_Mesh%NNodes indx_last = indx_first + 2 - u(indx_first:indx_last) = HD_M_DistribMesh%TranslationAcc(:,i) + u(indx_first:indx_last) = HD_M_Mesh%TranslationAcc(:,i) indx_first = indx_last + 1 end do - do i=1,HD_M_DistribMesh%NNodes + do i=1,HD_M_Mesh%NNodes indx_last = indx_first + 2 - u(indx_first:indx_last) = HD_M_DistribMesh%RotationAcc(:,i) + u(indx_first:indx_last) = HD_M_Mesh%RotationAcc(:,i) indx_first = indx_last + 1 end do @@ -3591,40 +3536,37 @@ SUBROUTINE Add_FullOpt1_u_delta( p_FAST, Jac_u_indx, u_delta, u_ED, u_SD, u_HD, CASE ( 8) !Module/Mesh/Field: u_SD%LMesh%Moment = 8 u_SD%LMesh%Moment(fieldIndx,node) = u_SD%LMesh%Moment(fieldIndx,node) + u_delta(n) * p_FAST%UJacSclFact - CASE ( 9) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 - u_HD%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) + u_delta(n) - CASE (10) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 - u_HD%Morison%LumpedMesh%RotationAcc( fieldIndx,node) = u_HD%Morison%LumpedMesh%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (11) !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 - u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%DistribMesh%TranslationAcc(fieldIndx,node) + u_delta(n) - CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 - u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD%Morison%DistribMesh%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (13) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 + CASE ( 9) !Module/Mesh/Field: u_HD%Morison%Mesh%TranslationAcc = 9 + u_HD%Morison%Mesh%TranslationAcc(fieldIndx,node) = u_HD%Morison%Mesh%TranslationAcc(fieldIndx,node) + u_delta(n) + CASE (10) !Module/Mesh/Field: u_HD%Morison%Mesh%RotationAcc = 10 + u_HD%Morison%Mesh%RotationAcc( fieldIndx,node) = u_HD%Morison%Mesh%RotationAcc( fieldIndx,node) + u_delta(n) + + CASE (11) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 11 u_HD%WAMITMesh%TranslationAcc( fieldIndx,node) = u_HD%WAMITMesh%TranslationAcc( fieldIndx,node) + u_delta(n) - CASE (14) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 + CASE (12) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 12 u_HD%WAMITMesh%RotationAcc( fieldIndx,node) = u_HD%WAMITMesh%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) + CASE (13) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 13 (k=1) u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(1)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) - CASE (16) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 16 (k=1) + CASE (14) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 14 (k=1) u_BD(1)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(1)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (17) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 17 (k=2) + CASE (15) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 15 (k=2) u_BD(2)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(2)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) - CASE (18) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 18 (k=2) + CASE (16) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 16 (k=2) u_BD(2)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(2)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (19) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 19 (k=3) + CASE (17) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 17 (k=3) u_BD(3)%RootMotion%TranslationAcc(fieldIndx,node) = u_BD(3)%RootMotion%TranslationAcc(fieldIndx,node) + u_delta(n) - CASE (20) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 20 (k=3) + CASE (18) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 18 (k=3) u_BD(3)%RootMotion%RotationAcc( fieldIndx,node) = u_BD(3)%RootMotion%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (21) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + CASE (19) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 19 u_Orca%PtfmMesh%TranslationAcc( fieldIndx,node) = u_Orca%PtfmMesh%TranslationAcc( fieldIndx,node) + u_delta(n) - CASE (22) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + CASE (20) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 20 u_Orca%PtfmMesh%RotationAcc( fieldIndx,node) = u_Orca%PtfmMesh%RotationAcc( fieldIndx,node) + u_delta(n) - CASE (23) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 23 + CASE (21) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 21 u_ExtPtfm%PtfmMesh%TranslationAcc( fieldIndx,node) = u_ExtPtfm%PtfmMesh%TranslationAcc( fieldIndx,node) + u_delta(n) - CASE (24) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 24 + CASE (22) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 22 u_ExtPtfm%PtfmMesh%RotationAcc( fieldIndx,node) = u_ExtPtfm%PtfmMesh%RotationAcc( fieldIndx,node) + u_delta(n) END SELECT @@ -3686,55 +3628,50 @@ SUBROUTINE Perturb_u_FullOpt1( p_FAST, Jac_u_indx, n, u_perturb, u_ED_perturb, u perturb = GetPerturb( u_SD_perturb%LMesh%Moment(fieldIndx , node) ) u_SD_perturb%LMesh%Moment(fieldIndx,node) = u_SD_perturb%LMesh%Moment(fieldIndx,node) + perturb * p_FAST%UJacSclFact - CASE ( 9) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%TranslationAcc = 9 - perturb = GetPerturb( u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx , node) ) - u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Morison%LumpedMesh%TranslationAcc(fieldIndx,node) + perturb - CASE ( 10) !Module/Mesh/Field: u_HD%Morison%LumpedMesh%RotationAcc = 10 - perturb = GetPerturb( u_HD_perturb%Morison%LumpedMesh%RotationAcc(fieldIndx , node) ) - u_HD_perturb%Morison%LumpedMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%LumpedMesh%RotationAcc( fieldIndx,node) + perturb - CASE (11) !Module/Mesh/Field: u_HD%Morison%DistribMesh%TranslationAcc = 11 - perturb = GetPerturb( u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx , node) ) - u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Morison%DistribMesh%TranslationAcc(fieldIndx,node) + perturb - CASE (12) !Module/Mesh/Field: u_HD%Morison%DistribMesh%RotationAcc = 12 - perturb = GetPerturb( u_HD_perturb%Morison%DistribMesh%RotationAcc(fieldIndx , node) ) - u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%DistribMesh%RotationAcc( fieldIndx,node) + perturb - CASE (13) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 + CASE ( 9) !Module/Mesh/Field: u_HD%Morison%Mesh%TranslationAcc = 9 + perturb = GetPerturb( u_HD_perturb%Morison%Mesh%TranslationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%Mesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%Morison%Mesh%TranslationAcc(fieldIndx,node) + perturb + CASE ( 10) !Module/Mesh/Field: u_HD%Morison%Mesh%RotationAcc = 10 + perturb = GetPerturb( u_HD_perturb%Morison%Mesh%RotationAcc(fieldIndx , node) ) + u_HD_perturb%Morison%Mesh%RotationAcc( fieldIndx,node) = u_HD_perturb%Morison%Mesh%RotationAcc( fieldIndx,node) + perturb + + CASE (11) !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 11 perturb = GetPerturb( u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx , node) ) u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx,node) = u_HD_perturb%WAMITMesh%TranslationAcc(fieldIndx,node) + perturb - CASE (14) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 + CASE (12) !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 12 perturb = GetPerturb( u_HD_perturb%WAMITMesh%RotationAcc(fieldIndx , node) ) u_HD_perturb%WAMITMesh%RotationAcc( fieldIndx,node) = u_HD_perturb%WAMITMesh%RotationAcc( fieldIndx,node) + perturb - CASE (15) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 15 (k=1) + CASE (13) !Module/Mesh/Field: u_BD(1)%RootMotion%TranslationAcc = 13 (k=1) perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb - CASE (16) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 16 (k=1) + CASE (14) !Module/Mesh/Field: u_BD(1)%RootMotion%RotationAcc = 14 (k=1) perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb - CASE (17) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 17 (k=2) + CASE (15) !Module/Mesh/Field: u_BD(2)%RootMotion%TranslationAcc = 15 (k=2) perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb - CASE (18) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 18 (k=2) + CASE (16) !Module/Mesh/Field: u_BD(2)%RootMotion%RotationAcc = 16 (k=2) perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb - CASE (19) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 19 (k=3) + CASE (17) !Module/Mesh/Field: u_BD(3)%RootMotion%TranslationAcc = 17 (k=3) perturb = GetPerturb( u_BD_perturb%RootMotion%TranslationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) = u_BD_perturb%RootMotion%TranslationAcc(fieldIndx,node) + perturb - CASE (20) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 20 (k=3) + CASE (18) !Module/Mesh/Field: u_BD(3)%RootMotion%RotationAcc = 18 (k=3) perturb = GetPerturb( u_BD_perturb%RootMotion%RotationAcc(fieldIndx , node) ) u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) = u_BD_perturb%RootMotion%RotationAcc( fieldIndx,node) + perturb - CASE (21) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + CASE (19) !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 19 perturb = GetPerturb( u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx , node) ) u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) = u_Orca_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) + perturb - CASE (22) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + CASE (20) !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 20 perturb = GetPerturb( u_Orca_perturb%PtfmMesh%RotationAcc(fieldIndx , node) ) u_Orca_perturb%PtfmMesh%RotationAcc( fieldIndx,node) = u_Orca_perturb%PtfmMesh%RotationAcc( fieldIndx,node) + perturb - CASE (23) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 21 + CASE (21) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 21 perturb = GetPerturb( u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx , node) ) u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) = u_ExtPtfm_perturb%PtfmMesh%TranslationAcc(fieldIndx,node) + perturb - CASE (24) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 22 + CASE (22) !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 22 perturb = GetPerturb( u_ExtPtfm_perturb%PtfmMesh%RotationAcc(fieldIndx , node) ) u_ExtPtfm_perturb%PtfmMesh%RotationAcc( fieldIndx,node) = u_ExtPtfm_perturb%PtfmMesh%RotationAcc( fieldIndx,node) + perturb @@ -3862,14 +3799,11 @@ SUBROUTINE ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp HD%y%WAMITMesh%RemapFlag = .FALSE. HD%y%WAMITMesh%RemapFlag = .FALSE. END IF - IF (HD%Input(1)%Morison%LumpedMesh%Committed) THEN - HD%Input(1)%Morison%LumpedMesh%RemapFlag = .FALSE. - HD%y%Morison%LumpedMesh%RemapFlag = .FALSE. - END IF - IF (HD%Input(1)%Morison%DistribMesh%Committed) THEN - HD%Input(1)%Morison%DistribMesh%RemapFlag = .FALSE. - HD%y%Morison%DistribMesh%RemapFlag = .FALSE. + IF (HD%Input(1)%Morison%Mesh%Committed) THEN + HD%Input(1)%Morison%Mesh%RemapFlag = .FALSE. + HD%y%Morison%Mesh%RemapFlag = .FALSE. END IF + END IF ! SubDyn @@ -4176,74 +4110,60 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M IF ( p_FAST%CompHydro == Module_HD ) THEN ! HydroDyn-{ElastoDyn or SubDyn} - + + ! Regardless of the offshore configuration, ED platform motions will be mapped to the PRPMesh of HD + ! we're just going to assume PlatformLoads and PlatformMotion are committed + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_PRP_P' ) !------------------------- ! HydroDyn <-> ElastoDyn !------------------------- - IF ( p_FAST%CompSub /= Module_SD ) THEN ! all of these get mapped to ElastoDyn ! (offshore floating) + IF ( p_FAST%CompSub /= Module_SD ) THEN ! all of these get mapped to ElastoDyn ! (offshore floating with rigid substructure) - ! we're just going to assume PlatformLoads and PlatformMotion are committed - IF ( HD%y%WAMITMesh%Committed ) THEN ! meshes for floating ! HydroDyn WAMIT point mesh to/from ElastoDyn point mesh - CALL MeshMapCreate( HD%y%WAMITMesh, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_PRP_P' ) - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( HD%y%WAMITMesh, PlatformLoads, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) END IF ! ElastoDyn point mesh HydroDyn Morison point mesh (ED sets inputs, but gets outputs from HD%y%WAMITMesh in floating case) - IF ( HD%Input(1)%Morison%LumpedMesh%Committed ) THEN - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%Morison%LumpedMesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN + !TODO: HD Changes: Need to transfer Morison Loads to PlatformLoads + CALL MeshMapCreate( HD%y%Morison%Mesh, PlatformLoads, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_P_2_ED_P' ) + CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_M_P' ) END IF - - ! ElastoDyn point mesh to HydroDyn Morison line mesh (ED sets inputs, but gets outputs from HD%y%WAMITMesh in floating case) - IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN - CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Morison%DistribMesh, MeshMapData%ED_P_2_HD_M_L, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_HD_M_L' ) - END IF - - ELSE ! these get mapped to ElastoDyn AND SubDyn (in ED_SD_HD coupling) ! offshore fixed - - ! HydroDyn WAMIT mesh to ElastoDyn point mesh - IF ( HD%y%WAMITMesh%Committed ) THEN - - ! HydroDyn WAMIT point mesh to ElastoDyn point mesh ! meshes for fixed-bottom - CALL MeshMapCreate( HD%y%WAMITMesh, ED%Input(1)%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_ED_P' ) - CALL MeshMapCreate( ED%Output(1)%PlatformPtMesh, HD%Input(1)%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':ED_P_2_HD_W_P' ) - END IF + ELSE ! these get mapped to ElastoDyn AND SubDyn (in ED_SD_HD coupling) ! offshore with substructure flexibility + + !------------------------- ! HydroDyn <-> SubDyn !------------------------- ! HydroDyn Morison point mesh to SubDyn point mesh - IF ( HD%y%Morison%LumpedMesh%Committed ) THEN + IF ( HD%y%Morison%Mesh%Committed ) THEN - CALL MeshMapCreate( HD%y%Morison%LumpedMesh, SD%Input(1)%LMesh, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL MeshMapCreate( HD%y%Morison%Mesh, SD%Input(1)%LMesh, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_P_2_SD_P' ) - CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%Morison%LumpedMesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_M_P' ) - + CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%Morison%Mesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_M_P' ) END IF - - ! HydroDyn Morison line mesh to SubDyn point mesh - IF ( HD%y%Morison%DistribMesh%Committed ) THEN - - CALL MeshMapCreate( HD%y%Morison%DistribMesh, SD%Input(1)%LMesh, MeshMapData%HD_M_L_2_SD_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_L_2_SD_P' ) - CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%Morison%DistribMesh, MeshMapData%SD_P_2_HD_M_L, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_M_L' ) + + ! HydroDyn WAMIT point mesh to SD point mesh + IF ( HD%y%WAMITMesh%Committed ) THEN + + CALL MeshMapCreate( HD%y%WAMITMesh, SD%Input(1)%LMesh, MeshMapData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_W_P_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, HD%Input(1)%WAMITMesh, MeshMapData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_HD_W_P' ) - END IF - + END IF END IF ! HydroDyn-SubDyn @@ -4282,39 +4202,71 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M IF ( p_FAST%CompMooring == Module_MAP ) THEN + + IF ( p_FAST%CompSub == Module_SD ) THEN +!------------------------- +! SubDyn <-> MAP +!------------------------- + ! MAP point mesh to/from SubDyn point mesh + CALL MeshMapCreate( MAPp%y%PtFairleadLoad, SD%Input(1)%LMesh, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, MAPp%Input(1)%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_Mooring_P' ) + ELSE !------------------------- ! ElastoDyn <-> MAP -!------------------------- +!------------------------- + ! MAP point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( MAPp%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, MAPp%Input(1)%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + END IF ! p_FAST%CompSub == Module_SD - ! MAP point mesh to/from ElastoDyn point mesh - CALL MeshMapCreate( MAPp%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) - CALL MeshMapCreate( PlatformMotion, MAPp%Input(1)%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) - ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + IF ( p_FAST%CompSub == Module_SD ) THEN +!------------------------- +! SubDyn <-> MoorDyn +!------------------------- + ! MoorDyn point mesh to/from SubDyn point mesh + CALL MeshMapCreate( MD%y%PtFairleadLoad, SD%Input(1)%LMesh, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, MD%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_Mooring_P' ) + ELSE !------------------------- ! ElastoDyn <-> MoorDyn -!------------------------- +!------------------------- + ! MoorDyn point mesh to/from ElastoDyn point mesh + CALL MeshMapCreate( MD%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, MD%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + END IF ! p_FAST%CompSub == Module_SD - ! MoorDyn point mesh to/from ElastoDyn point mesh - CALL MeshMapCreate( MD%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) - CALL MeshMapCreate( PlatformMotion, MD%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) - ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + IF ( p_FAST%CompSub == Module_SD ) THEN +!------------------------- +! SubDyn <-> FEAMooring +!------------------------- + ! FEAMooring point mesh to/from SubDyn point mesh + CALL MeshMapCreate( FEAM%y%PtFairleadLoad, SD%Input(1)%LMesh, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_SD_P' ) + CALL MeshMapCreate( SD%y%y2Mesh, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':SD_P_2_Mooring_P' ) + ELSE !------------------------- ! ElastoDyn <-> FEAMooring -!------------------------- - +!------------------------- ! FEAMooring point mesh to/from ElastoDyn point mesh - CALL MeshMapCreate( FEAM%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) - CALL MeshMapCreate( PlatformMotion, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) - + CALL MeshMapCreate( FEAM%y%PtFairleadLoad, PlatformLoads, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Mooring_P_2_Ptfm' ) + CALL MeshMapCreate( PlatformMotion, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':Ptfm_2_Mooring_P' ) + END IF ! p_FAST%CompSub == Module_SD + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + !------------------------- ! ElastoDyn <-> OrcaFlex !------------------------- @@ -4375,7 +4327,7 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M !IF ( p_FAST%TurbineType == Type_Offshore_Fixed ) THEN IF ( p_FAST%CompSub /= Module_None .OR. (p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) .or. p_FAST%CompMooring == Module_Orca) THEN !.OR. p_FAST%CompHydro == Module_HD ) THEN CALL Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED%Input(1)%PlatformPtMesh, SD%Input(1)%TPMesh, SD%Input(1)%LMesh, & - HD%Input(1)%Morison%LumpedMesh, HD%Input(1)%Morison%DistribMesh, HD%Input(1)%WAMITMesh, & + HD%Input(1)%Morison%Mesh, HD%Input(1)%WAMITMesh, & ED%Input(1)%HubPtLoad, BD%Input(1,:), Orca%Input(1)%PtfmMesh, ExtPtfm%Input(1)%PtfmMesh, ErrStat2, ErrMsg2) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN @@ -4456,15 +4408,16 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M END IF IF ( p_FAST%CompHydro == Module_HD ) THEN + + !TODO: GJH Is this needed, I created it as a place holder, 5/11/2020 + !CALL MeshCopy ( HD%Input(1)%PRPMesh, MeshMapData%u_HD_PRP_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_PRP_Mesh' ) - CALL MeshCopy ( HD%Input(1)%WAMITMesh, MeshMapData%u_HD_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_Mesh' ) + CALL MeshCopy ( HD%Input(1)%WAMITMesh, MeshMapData%u_HD_W_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_W_Mesh' ) - CALL MeshCopy ( HD%Input(1)%Morison%LumpedMesh, MeshMapData%u_HD_M_LumpedMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_M_LumpedMesh' ) - - CALL MeshCopy ( HD%Input(1)%Morison%DistribMesh, MeshMapData%u_HD_M_DistribMesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_M_DistribMesh' ) + CALL MeshCopy ( HD%Input(1)%Morison%Mesh, MeshMapData%u_HD_M_Mesh, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':u_HD_M_Mesh' ) END IF @@ -4754,7 +4707,7 @@ SUBROUTINE SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN + ELSEIF ( p_FAST%CompHydro == Module_HD ) THEN ! No substructure model CALL ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & , ED%Input(1), ED%p, ED%x(this_state), ED%xd(this_state), ED%z(this_state), ED%OtherSt(this_state), ED%y, ED%m & @@ -4768,24 +4721,41 @@ SUBROUTINE SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, !.................. ! Set mooring line and ice inputs (which don't have acceleration fields) !.................. + +!TODO: GJH Need to check whether SD or ED sends output to Mooring GJH 5/11/2020 IF ( p_FAST%CompMooring == Module_MAP ) THEN - ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MAP_InputSolve( MAPp%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! note: MAP_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( SD%y%y2Mesh, MAPp%Input(1)%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( ED%y%PlatformPtMesh, MAPp%Input(1)%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN - ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL MD_InputSolve( MD%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! note: MD_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( SD%y%y2Mesh, MD%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( ED%y%PlatformPtMesh, MD%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + endif ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN - ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) - CALL FEAM_InputSolve( FEAM%Input(1), ED%y, MeshMapData, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! note: FEAM_InputSolve must be called before setting ED loads inputs (so that motions are known for loads [moment] mapping) + if ( p_FAST%CompSub == Module_SD ) then + CALL Transfer_Point_to_Point( SD%y%y2Mesh, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + CALL Transfer_Point_to_Point( ED%y%PlatformPtMesh, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + end if END IF @@ -4814,13 +4784,10 @@ SUBROUTINE SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, 'SD_y2_IceF_Meshes_t'//TRIM(Num2LStr(0))//'.PI.bin' ) - CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, HD%Input(1)%Morison%LumpedMesh, HD%y%Morison%LumpedMesh,& + CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, HD%Input(1)%Morison%Mesh, HD%y%Morison%Mesh,& MeshMapData%SD_P_2_HD_M_P, MeshMapData%HD_M_P_2_SD_P, & 'SD_y2_HD_M_L_Meshes_t'//TRIM(Num2LStr(0))//'.PHL.bin' ) - - CALL WriteMappingTransferToFile(SD%Input(1)%LMesh, SD%y%Y2Mesh, HD%Input(1)%Morison%DistribMesh, HD%y%Morison%DistribMesh,& - MeshMapData%SD_P_2_HD_M_L, MeshMapData%HD_M_L_2_SD_P, & - 'SD_y2_HD_M_D_Meshes_t'//TRIM(Num2LStr(0))//'.PHD.bin' ) + !print * From 23feb4862a0b8925c2dabcf5c3e270037cbb501b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 22 May 2020 11:02:51 -0600 Subject: [PATCH 212/377] FlexSub: summary file in yaml format (partial support) --- modules/subdyn/src/SubDyn.f90 | 210 +++++++++++---------------- modules/subdyn/src/SubDyn_Output.f90 | 124 +++++++++++++++- 2 files changed, 207 insertions(+), 127 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 8c3f72445..a86b6b7d9 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2366,15 +2366,15 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) REAL(ReKi) :: MRB(6,6) ! REDUCED SYSTEM Kmatrix, equivalent mass matrix REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length - CHARACTER(*),PARAMETER :: SectionDivide = '____________________________________________________________________________________________________' - CHARACTER(*),PARAMETER :: SubSectionDivide = '__________' - CHARACTER(2), DIMENSION(6), PARAMETER :: MatHds= (/'X ', 'Y ', 'Z ', 'XX', 'YY', 'ZZ'/) !Headers for the columns and rows of 6x6 matrices + CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' + CHARACTER(*),PARAMETER :: SubSectionDivide = '#__________' real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega real(ReKi), dimension(:,:), allocatable :: Modes real(ReKi), dimension(:) , allocatable :: Omega logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) + character(len=*),parameter :: ReFmt='E15.6' ! ErrStat = ErrID_None ErrMsg = "" @@ -2407,71 +2407,76 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) !------------------------------------------------------------------------------------------------------------- !bjj: for debugging, i recommend using the p% versions of all these variables whenever possible in this summary file: ! (it helps in debugging) - WRITE(UnSum, '(A)') 'Unless specified, units are consistent with Input units, [SI] system is advised.' + WRITE(UnSum, '(A)') '#Unless specified, units are consistent with Input units, [SI] system is advised.' WRITE(UnSum, '(A)') SectionDivide !write(UnSum,'(A)')'Nodes_I',p%Nodes_I(:,1) !write(UnSum,'(A)')'Nodes_C',p%Nodes_C(:,1) !write(UnSum,'(A)')'Nodes_L',p%Nodes_L - write(UnSum,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ - write(UnSum,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb - write(UnSum,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F - write(UnSum,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ - write(UnSum,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb - write(UnSum,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L - write(UnSum,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F - write(UnSum,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ - write(UnSum,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L - write(UnSum,'(A,I0)')'Number of DOFs: total retained (__B): ',p%nDOF__Rb - write(UnSum,'(A,I0)')'Number of DOFs: total internal (__L): ',p%nDOF__L - write(UnSum,'(A,I0)')'Number of DOFs: total fixed (__F): ',p%nDOF__F - write(UnSum,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red - write(UnSum,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I - write(UnSum,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C - write(UnSum,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L - write(UnSum,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes - write(UnSum,'(A,3(E15.6))')'TP reference point:',InitInput%TP_RefPoint(1:3) + write(UnSum,'(A,I0)')'#Number of DOFs: "interface" (I__): ',p%nDOFI__ + write(UnSum,'(A,I0)')'#Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb + write(UnSum,'(A,I0)')'#Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F + write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" (C__): ',p%nDOFC__ + write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb + write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L + write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F + write(UnSum,'(A,I0)')'#Number of DOFs: "intf+react" (__R): ',p%nDOFR__ + write(UnSum,'(A,I0)')'#Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L + write(UnSum,'(A,I0)')'#Number of DOFs: total retained (__B): ',p%nDOF__Rb + write(UnSum,'(A,I0)')'#Number of DOFs: total internal (__L): ',p%nDOF__L + write(UnSum,'(A,I0)')'#Number of DOFs: total fixed (__F): ',p%nDOF__F + write(UnSum,'(A,I0)')'#Number of DOFs: total : ',p%nDOF_red + write(UnSum,'(A,I0)')'#Number of Nodes: "interface" (I): ',p%nNodes_I + write(UnSum,'(A,I0)')'#Number of Nodes: "reactions" (C): ',p%nNodes_C + write(UnSum,'(A,I0)')'#Number of Nodes: "internal" (L): ',p%nNodes_L + write(UnSum,'(A,I0)')'#Number of Nodes: total (I+C+L): ',p%nNodes + write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of nodes (nNodes):',p%nNodes - WRITE(UnSum, '(A8,1x,A11,9(1x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' , 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' - WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & - (NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol), i = 1, p%nNodes) + WRITE(UnSum, '(A,I6)') '#Number of nodes (nNodes):',p%nNodes + WRITE(UnSum, '(A8,1x,A11,9(1x,A15))') '#Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' , 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' + + do i = 1, p%nNodes + WRITE(UnSum, '("#",'//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & + NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol) + enddo WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of elements (NElems):',Init%NElem - WRITE(UnSum, '(A10,5(A10))') 'Elem No.','Node_I','Node_J','Prop_I','Prop_J','Type' - WRITE(UnSum, '(6(I10))') ((p%Elems(i, j), j = 1, MembersCol), i = 1, Init%NElem) + WRITE(UnSum, '(A,I6)') '#Number of elements (NElems):',Init%NElem + WRITE(UnSum, '("#",A10,5(A10))') 'Elem No.','Node_I','Node_J','Prop_I','Prop_J','Type' + do i=1, Init%nElem + WRITE(UnSum, '("#",6(I10))') (p%Elems(i, j), j = 1, MembersCol) + enddo WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of properties (NProps):',Init%NPropB - WRITE(UnSum, '(A8,5(A15))') 'Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' - WRITE(UnSum, '(I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) + WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB + WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' + WRITE(UnSum, '("#",I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Reaction DOFs:',p%nDOFC__ - WRITE(UnSum, '(A, A6)') 'React. DOF_ID', 'BC' - do i = 1, size(p%IDC_F ); WRITE(UnSum, '(I10, A10)') p%IDC_F(i) , ' Fixed' ; enddo - do i = 1, size(p%IDC_L ); WRITE(UnSum, '(I10, A10)') p%IDC_L(i) , ' Free' ; enddo - do i = 1, size(p%IDC_Rb); WRITE(UnSum, '(I10, A10)') p%IDC_Rb(i), ' Leader'; enddo + WRITE(UnSum, '(A,I6)') '#No. of Reaction DOFs:',p%nDOFC__ + WRITE(UnSum, '(A, A6)') '#React. DOF_ID', 'BC' + do i = 1, size(p%IDC_F ); WRITE(UnSum, '("#",I10, A10)') p%IDC_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDC_L ); WRITE(UnSum, '("#",I10, A10)') p%IDC_L(i) , ' Free' ; enddo + do i = 1, size(p%IDC_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDC_Rb(i), ' Leader'; enddo WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'No. of Interface DOFs:',p%nDOFI__ - WRITE(UnSum, '(A,A6)') 'Interf. DOF_ID', 'BC' - do i = 1, size(p%IDI_F ); WRITE(UnSum, '(I10, A10)') p%IDI_F(i) , ' Fixed' ; enddo - do i = 1, size(p%IDI_Rb); WRITE(UnSum, '(I10, A10)') p%IDI_Rb(i), ' Leader'; enddo + WRITE(UnSum, '(A,I6)') '#No. of Interface DOFs:',p%nDOFI__ + WRITE(UnSum, '(A,A6)') '#Interf. DOF_ID', 'BC' + do i = 1, size(p%IDI_F ); WRITE(UnSum, '("#",I10, A10)') p%IDI_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDI_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDI_Rb(i), ' Leader'; enddo WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of concentrated masses (NCMass):',Init%NCMass - WRITE(UnSum, '(A10,10(A15))') 'JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' - WRITE(UnSum, '(F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) + WRITE(UnSum, '(A,I6)') '#Number of concentrated masses (NCMass):',Init%NCMass + WRITE(UnSum, '(A10,10(A15))') '#JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' + WRITE(UnSum, '("#",F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') 'Number of members',p%NMembers - WRITE(UnSum, '(A,I6)') 'Number of nodes per member:', Init%Ndiv+1 - WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') 'Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' + WRITE(UnSum, '(A,I6)') '#Number of members',p%NMembers + WRITE(UnSum, '(A,I6)') '#Number of nodes per member:', Init%Ndiv+1 + WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') '#Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' DO i=1,p%NMembers !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS @@ -2485,10 +2490,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, .TRUE.) - WRITE(UnSum, '(I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) else - WRITE(UnSum, '(A)') 'TODO, member mass for non-beam elements' + WRITE(UnSum, '(A)') '#TODO, member mass for non-beam elements' endif ELSE RETURN @@ -2498,8 +2503,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write Cosine matrix for all members to a txt file !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') 'Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers - WRITE(UnSum, '(A9,9(A15))') 'Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' + WRITE(UnSum, '(A, I6)') '#Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers + WRITE(UnSum, '(A9,9(A15))') '#Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' DO i=1,p%NMembers iNode1 = FINDLOCI(Init%Joints(:,1), Init%Members(i,2)) ! index of joint 1 of member i iNode2 = FINDLOCI(Init%Joints(:,1), Init%Members(i,3)) ! index of joint 2 of member i @@ -2507,65 +2512,49 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) XYZ2 = Init%Joints(iNode2,2:4) CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) DirCos=TRANSPOSE(DirCos) !This is now global to local - WRITE(UnSum, '(I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + WRITE(UnSum, '("#",I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO !------------------------------------------------------------------------------------------------------------- ! write Eigenvalues of full SYstem and CB reduced System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Eigenvalues' + WRITE(UnSum, '(A)') '#Eigenvalues' WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A, I6)') "FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega - WRITE(UnSum, '(I6, e15.6)') ( i, Omega(i)/2.0/pi, i = 1, nOmega ) + WRITE(UnSum, '(A, I6)') "#FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega + WRITE(UnSum, '("#",I6, e15.6)') ( i, Omega(i)/2.0/pi, i = 1, nOmega ) WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A, I6)') "CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM - WRITE(UnSum, '(I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, p%nDOFM ) + WRITE(UnSum, '(A, I6)') "#CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM + WRITE(UnSum, '("#",I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, p%nDOFM ) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') ('FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& + WRITE(UnSum, '(A, I6)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega - WRITE(UnSum, '(6x,'//Num2LStr(nOmega)//'(I15))') (i, i = 1, nOmega )!HEADERS - WRITE(UnSum, '(I6,'//Num2LStr(nOmega)//'e15.6)') ( i, (Modes(i,j), j = 1, nOmega ),i = 1, p%nDOF_red) + call yaml_write_array(UnSum, 'PhiM', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'CB Matrices (PhiM,PhiR) (constraint applied)' - + WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide - IF (p%nDOFM > 0) THEN - CALL WrMatrix( CBparams%PhiL(:,1:p%nDOFM ), UnSum, 'e15.6', 'PhiM' ) - ELSE - WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "PhiM", TRIM(Num2LStr(p%nDOFL_L)), '0' - END IF - + call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A)') SubSectionDivide - CALL WrMatrix( CBparams%PhiR, UnSum, 'e15.6', 'PhiR' ) + call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') "SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" + WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') 'KBBt' !Note p%KBB stores KBBt - WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) - !tried implicit loop unsuccessfully - DO i=1,6 - WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%KBB(i,j), j = 1, 6) - ENDDO + call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') ('MBBt')!Note p%MBB stores MBBt - WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) - DO i=1,6 - WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (p%MBB(i,j), j = 1, 6) - ENDDO + call yaml_write_array(UnSum, 'KBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) ! Set TI2, transformation matrix from R DOFs to SubDyn Origin CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -2578,78 +2567,53 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body endif WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' + WRITE(UnSum, '(A)') '#Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') 'MRB' - WRITE(UnSum, '(7(A15))') ' ', (MatHds(i), i = 1, 6 ) - DO i=1,6 - WRITE(UnSum, '(A15, 6(e15.6))') MatHds(i), (MRB(i,j), j = 1, 6) - ENDDO - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,E15.6)') "SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) - WRITE(UnSum, '(A,3(E15.6))') "SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + call yaml_write_array(UnSum, 'MRB', MRB, ReFmt, ErrStat2, ErrMsg2) + WRITE(UnSum, '(A,E15.6)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(E15.6))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) deallocate(TI2) #ifdef SD_SUMMARY_DEBUG WRITE(UnSum, '()') WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '**** Additional Debugging Information ****' + WRITE(UnSum, '(A)') '#**** Additional Debugging Information ****' !------------------------------------------------------------------------------------------------------------- ! write assembed K M to a txt file !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') 'FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF - WRITE(UnSum, '(A)') ('Stiffness matrix K' ) - WRITE(UnSum, '(15x,'//TRIM(Num2LStr(p%nDOF))//'(I15))') (i, i = 1, p%nDOF ) - DO i=1,p%nDOF - WRITE(UnSum, '(I15, '//TRIM(Num2LStr(p%nDOF))//'(e15.6))') i, (Init%K(i, j), j = 1, p%nDOF) - ENDDO - + WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF + call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') WRITE(UnSum, '(A)') SubSectionDivide - WRITE(UnSum, '(A)') ('Mass matrix M' ) - WRITE(UnSum, '(15x,'//TRIM(Num2LStr(p%nDOF))//'(I15))') (i, i = 1, p%nDOF ) - DO i=1,p%nDOF - WRITE(UnSum, '(I15, '//TRIM(Num2LStr(p%nDOF))//'(e15.6))') i, (Init%M(i, j), j = 1, p%nDOF) - ENDDO - + call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') !------------------------------------------------------------------------------------------------------------- ! write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Gravity force vector FG applied at each node of the full system' - WRITE(UnSum, '(I6, e15.6)') (i, Init%FG(i), i = 1, p%nDOF) + WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' + WRITE(UnSum, '("#",I6, e15.6)') (i, Init%FG(i), i = 1, p%nDOF) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' - + WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' WRITE(UnSum, '(A)') SubSectionDivide - CALL WrMatrix( CBparams%MBB, UnSum, 'e15.6', 'MBB' ) - + call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') WRITE(UnSum, '(A)') SubSectionDivide - IF ( p%nDOFM > 0 ) THEN - CALL WrMatrix( CBparams%MBM, UnSum, 'e15.6', 'MBM' ) - ELSE - WRITE( UnSum, '(A,": ",A," x ",A)', IOSTAT=ErrStat ) "MBM", '6', '0' - END IF - + call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') WRITE(UnSum, '(A)') SubSectionDivide - CALL WrMatrix( CBparams%KBB, UnSum, 'e15.6', 'KBB' ) - + call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') WRITE(UnSum, '(A)') SubSectionDivide - CALL WrMatrix( CBparams%OmegaL**2, UnSum, 'e15.6','KMM (diagonal)' ) - + ! TODO TODO TODO + !CALL WrMatrix( CBparams%OmegaL**2, UnSum, 'e15.6','#KMM (diagonal)' ) !------------------------------------------------------------------------------------------------------------- ! write TP TI matrix !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') 'TP refpoint Transformation Matrix TI ' - CALL WrMatrix( p%TI, UnSum, 'e15.6', 'TI' ) + call yaml_write_array(UnSum, 'TI', p%TI, ReFmt, ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') #endif call CleanUp() diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 003a8ea0f..679a13fa0 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -28,6 +28,17 @@ MODULE SubDyn_Output ! The maximum number of output channels which can be output by the code. INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 + integer(IntKi), parameter :: INDENT_SPACES = 2 + + !> + interface yaml_write_array + !module procedure yaml_write_array1R4 ! Single dimension array (Ary) of SiKi + module procedure yaml_write_array2R4 ! Two dimension array of SiKi + !module procedure yaml_write_array1R8 ! Single dimension array (Ary) of R8Ki + module procedure yaml_write_array2R8 ! Two dimension array of R8Ki + !module procedure yaml_write_array1R16 ! Single dimension array (Ary) of QuKi + !module procedure yaml_write_array2R16 ! Two dimension array of QuKi + end interface PRIVATE ! ..... Public Subroutines ................................................................................................... @@ -41,6 +52,10 @@ MODULE SubDyn_Output PUBLIC :: SDOut_WriteOutputs PUBLIC :: SDOut_Init + PUBLIC :: yaml_write_array + + + CONTAINS @@ -478,7 +493,7 @@ SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) ErrMsg = "" ! Write any closing information in the summary file IF ( UnSum > 0 ) THEN - WRITE (UnSum,'(/,A/)', IOSTAT=Stat) 'This summary file was closed on '//CurDate()//' at '//CurTime()//'.' + WRITE (UnSum,'(/,A/)', IOSTAT=Stat) '#This summary file was closed on '//CurDate()//' at '//CurTime()//'.' IF (Stat /= 0) THEN ErrStat = ErrID_FATAL ErrMsg = ' Problem writing to summary file.' @@ -512,7 +527,7 @@ SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) END IF ! Write the summary file header - WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) 'This summary file was generated by '//TRIM( SD_Prog%Name )//& + WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) '#This summary file was generated by '//TRIM( SD_Prog%Name )//& ' '//TRIM( SD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' END SUBROUTINE SDOut_OpenSum @@ -616,10 +631,8 @@ SUBROUTINE SDOut_WriteOutputUnits( UnJckF, p, ErrStat, ErrMsg ) TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - CHARACTER(200) :: Frmt ! a string to hold a format statement INTEGER :: I ! Generic loop counter - ErrStat = ErrID_None ErrMsg = "" @@ -643,6 +656,8 @@ SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) ! Local variables INTEGER :: I ! Generic loop counter CHARACTER(200) :: Frmt ! a string to hold a format statement + ErrStat = ErrID_None + ErrMsg = "" ! Initialize ErrStat and determine if it makes any sense to write output IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnJckF < 0 ) THEN @@ -682,6 +697,8 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) CHARACTER(ChanLen), DIMENSION(24) :: ToTUnits,ToTNames,ToTNames0 LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration LOGICAL :: CheckOutListAgain + ErrStat = ErrID_None + ErrMsg = "" InvalidOutput = .FALSE. @@ -802,5 +819,104 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) END SUBROUTINE SDOut_ChkOutLst !==================================================================================================== +! TODO put this into NWTC LIB as YAML.f90 + +subroutine yaml_write_array2R4(fid, key, A, ReFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(SiKi), dimension(:,:), intent(in ) :: A !< Array + character(*), intent(in ) :: ReFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//ReFmt//',","),"]")' + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array'//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R4 + +subroutine yaml_write_array2R8(fid, key, A, ReFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(R8Ki), dimension(:,:), intent(in ) :: A !< Array + character(*), intent(in ) :: ReFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//ReFmt//',","),"]")' + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array'//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R8 END MODULE SubDyn_Output From 4c744521ac891e7d980eceb21725564d9f42343a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 30 May 2020 19:48:42 -0600 Subject: [PATCH 213/377] FlexSub: more yaml for summary file --- modules/subdyn/CMakeLists.txt | 1 + modules/subdyn/src/SubDyn.f90 | 112 +++--- modules/subdyn/src/SubDyn_Output.f90 | 118 +----- modules/subdyn/src/Yaml.f90 | 582 +++++++++++++++++++++++++++ vs-build/FASTlib/FASTlib.vfproj | 1 + vs-build/SubDyn/SubDyn.vfproj | 1 + 6 files changed, 647 insertions(+), 168 deletions(-) create mode 100644 modules/subdyn/src/Yaml.f90 diff --git a/modules/subdyn/CMakeLists.txt b/modules/subdyn/CMakeLists.txt index 0f88349d3..8ab62a8c3 100644 --- a/modules/subdyn/CMakeLists.txt +++ b/modules/subdyn/CMakeLists.txt @@ -27,6 +27,7 @@ set(SUBDYN_SOURCES src/qsort_c_module.f90 src/SubDyn_Tests.f90 src/IntegerList.f90 + src/Yaml.f90 src/SubDyn_Types.f90 ) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a86b6b7d9..3ff755b8b 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2348,6 +2348,7 @@ END SUBROUTINE ConstructUFL !------------------------------------------------------------------------------------------------------ !> Output the summary file SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) + use Yaml TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine @@ -2367,7 +2368,6 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' - CHARACTER(*),PARAMETER :: SubSectionDivide = '#__________' real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega @@ -2375,6 +2375,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) real(ReKi), dimension(:) , allocatable :: Omega logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) character(len=*),parameter :: ReFmt='E15.6' + character(len=*),parameter :: IFmt='I7' ! ErrStat = ErrID_None ErrMsg = "" @@ -2397,11 +2398,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) !------------------------------------------------------------------------------------------------------------- ! open txt file !------------------------------------------------------------------------------------------------------------- - SummaryName = TRIM(Init%RootName)//'.sum' + SummaryName = TRIM(Init%RootName)//'.sum.yaml' UnSum = -1 ! we haven't opened the summary file, yet. CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ); if(Failed()) return - !------------------------------------------------------------------------------------------------------------- ! write discretized data to a txt file !------------------------------------------------------------------------------------------------------------- @@ -2409,40 +2409,59 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! (it helps in debugging) WRITE(UnSum, '(A)') '#Unless specified, units are consistent with Input units, [SI] system is advised.' WRITE(UnSum, '(A)') SectionDivide - - !write(UnSum,'(A)')'Nodes_I',p%Nodes_I(:,1) - !write(UnSum,'(A)')'Nodes_C',p%Nodes_C(:,1) - !write(UnSum,'(A)')'Nodes_L',p%Nodes_L - write(UnSum,'(A,I0)')'#Number of DOFs: "interface" (I__): ',p%nDOFI__ - write(UnSum,'(A,I0)')'#Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb - write(UnSum,'(A,I0)')'#Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F - write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" (C__): ',p%nDOFC__ - write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb - write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L - write(UnSum,'(A,I0)')'#Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F - write(UnSum,'(A,I0)')'#Number of DOFs: "intf+react" (__R): ',p%nDOFR__ - write(UnSum,'(A,I0)')'#Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L - write(UnSum,'(A,I0)')'#Number of DOFs: total retained (__B): ',p%nDOF__Rb - write(UnSum,'(A,I0)')'#Number of DOFs: total internal (__L): ',p%nDOF__L - write(UnSum,'(A,I0)')'#Number of DOFs: total fixed (__F): ',p%nDOF__F - write(UnSum,'(A,I0)')'#Number of DOFs: total : ',p%nDOF_red - write(UnSum,'(A,I0)')'#Number of Nodes: "interface" (I): ',p%nNodes_I - write(UnSum,'(A,I0)')'#Number of Nodes: "reactions" (C): ',p%nNodes_C - write(UnSum,'(A,I0)')'#Number of Nodes: "internal" (L): ',p%nNodes_L - write(UnSum,'(A,I0)')'#Number of Nodes: total (I+C+L): ',p%nNodes - write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) + call yaml_write_var(UnSum, 'nNodes_I', p%nNodes_I,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "interface" (I)') + call yaml_write_var(UnSum, 'nNodes_C', p%nNodes_C,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "reactions" (C)') + call yaml_write_var(UnSum, 'nNodes_L', p%nNodes_L,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "internal" (L)') + call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') +#ifdef SD_SUMMARY_DEBUG + call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') + call yaml_write_var(UnSum, 'nDOFI_Rb', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') + call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') + call yaml_write_var(UnSum, 'nDOFC__ ', p%nDOFC__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" (C__)') + call yaml_write_var(UnSum, 'nDOFC_Rb', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') + call yaml_write_var(UnSum, 'nDOFC_L ', p%nDOFC_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" internal (C_L)') + call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') + call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') + call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') +#endif + call yaml_write_var(UnSum, 'nDOF__Rb', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total retained (__B)') + call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total internal (__L)') + call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total fixed (__F)') + call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total ') +#ifdef SD_SUMMARY_DEBUG + call yaml_write_array(UnSum, 'Nodes_I', p%Nodes_I(:,1), IFmt, ErrStat2, ErrMsg2, comment='"interface" nodes"') + call yaml_write_array(UnSum, 'Nodes_C', p%Nodes_C(:,1), IFmt, ErrStat2, ErrMsg2, comment='"reaction" nodes"') + call yaml_write_array(UnSum, 'Nodes_L', p%Nodes_L(:,1), IFmt, ErrStat2, ErrMsg2, comment='"internal" nodes"') + call yaml_write_array(UnSum, 'DOF_I__', p%IDI__ , IFmt, ErrStat2, ErrMsg2, comment='"interface" DOFs"') + call yaml_write_array(UnSum, 'DOF_I_B', p%IDI_Rb, IFmt, ErrStat2, ErrMsg2, comment='"interface" retained DOFs') + call yaml_write_array(UnSum, 'DOF_I_F', p%IDI_F , IFmt, ErrStat2, ErrMsg2, comment='"interface" fixed DOFs') + call yaml_write_array(UnSum, 'DOF_C__', p%IDC__ , IFmt, ErrStat2, ErrMsg2, comment='"reaction" DOFs"') + call yaml_write_array(UnSum, 'DOF_C_B', p%IDC_Rb, IFmt, ErrStat2, ErrMsg2, comment='"reaction" retained DOFs') + call yaml_write_array(UnSum, 'DOF_C_L', p%IDC_L , IFmt, ErrStat2, ErrMsg2, comment='"reaction" internal DOFs') + call yaml_write_array(UnSum, 'DOF_C_F', p%IDC_F , IFmt, ErrStat2, ErrMsg2, comment='"reaction" fixed DOFs') + call yaml_write_array(UnSum, 'DOF_L_L', p%IDL_L , IFmt, ErrStat2, ErrMsg2, comment='"internal" internal DOFs') + call yaml_write_array(UnSum, 'DOF_L_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') +#endif + call yaml_write_array(UnSum, 'DOF___B', p%ID__Rb, IFmt, ErrStat2, ErrMsg2, comment='all retained DOFs') + call yaml_write_array(UnSum, 'DOF___F', p%ID__F , IFmt, ErrStat2, ErrMsg2, comment='all fixed DOFs') + call yaml_write_array(UnSum, 'DOF___L', p%ID__L , IFmt, ErrStat2, ErrMsg2, comment='all internal DOFs') + write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '()') + + WRITE(UnSum, '(A)') '#Index map from DOF to nodes' + WRITE(UnSum, '(A)') '# Node No., DOF/Node, NodalDOF' + call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) + + WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of nodes (nNodes):',p%nNodes - WRITE(UnSum, '(A8,1x,A11,9(1x,A15))') '#Node No.', 'Y2Mesh Node', 'X (m)', 'Y (m)', 'Z (m)' , 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' - + WRITE(UnSum, '("#",4x,A8,1x,A11,9(2x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)','Y (m)','Z (m)', 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' + WRITE(UnSum, '(A)') 'Nodes:' do i = 1, p%nNodes - WRITE(UnSum, '("#",'//Num2LStr(p%nNodes)//'(I8,3x,I9,'//Num2lstr(JointsCol-1)//'(1x,F15.4),:,/))') & + WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(" - [ ",I8,",",I9,","'//Num2lstr(JointsCol-1)//'(1x,F15.4,","),"]",:,/))') & NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol) enddo - WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of elements (NElems):',Init%NElem WRITE(UnSum, '("#",A10,5(A10))') 'Elem No.','Node_I','Node_J','Prop_I','Prop_J','Type' @@ -2519,14 +2538,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write Eigenvalues of full SYstem and CB reduced System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Eigenvalues' - WRITE(UnSum, '(A)') SubSectionDivide WRITE(UnSum, '(A, I6)') "#FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega - WRITE(UnSum, '("#",I6, e15.6)') ( i, Omega(i)/2.0/pi, i = 1, nOmega ) - - WRITE(UnSum, '(A)') SubSectionDivide + call yaml_write_array(UnSum, 'Full_Eigenvalues', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A, I6)') "#CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM - WRITE(UnSum, '("#",I6, e15.6)') ( i, CBparams%OmegaL(i)/2.0/pi, i = 1, p%nDOFM ) + call yaml_write_array(UnSum, 'CB_Eigenvalues', CBparams%OmegaL/(TwoPi), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full System @@ -2534,16 +2549,14 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A, I6)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega - call yaml_write_array(UnSum, 'PhiM', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'Full_Modes', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- @@ -2551,9 +2564,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'KBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) ! Set TI2, transformation matrix from R DOFs to SubDyn Origin @@ -2568,7 +2579,6 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) endif WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'MRB', MRB, ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A,E15.6)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) WRITE(UnSum, '(A,3(E15.6))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) @@ -2586,29 +2596,29 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') - WRITE(UnSum, '(A)') SubSectionDivide - call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') + call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') !------------------------------------------------------------------------------------------------------------- ! write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' - WRITE(UnSum, '("#",I6, e15.6)') (i, Init%FG(i), i = 1, p%nDOF) + call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') !------------------------------------------------------------------------------------------------------------- ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') - WRITE(UnSum, '(A)') SubSectionDivide call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') - WRITE(UnSum, '(A)') SubSectionDivide - ! TODO TODO TODO - !CALL WrMatrix( CBparams%OmegaL**2, UnSum, 'e15.6','#KMM (diagonal)' ) + call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') + IF (p%SttcSolve) THEN + call yaml_write_array(UnSum, 'PhiL', transpose(p%PhiL_T), ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'KLL^-1', MATMUL(p%PhiLInvOmgL2,p%PhiL_T ), ReFmt, ErrStat2, ErrMsg2, comment='') + endif + !------------------------------------------------------------------------------------------------------------- ! write TP TI matrix !------------------------------------------------------------------------------------------------------------- diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 679a13fa0..41dd02fd7 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -28,18 +28,7 @@ MODULE SubDyn_Output ! The maximum number of output channels which can be output by the code. INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 - integer(IntKi), parameter :: INDENT_SPACES = 2 - - !> - interface yaml_write_array - !module procedure yaml_write_array1R4 ! Single dimension array (Ary) of SiKi - module procedure yaml_write_array2R4 ! Two dimension array of SiKi - !module procedure yaml_write_array1R8 ! Single dimension array (Ary) of R8Ki - module procedure yaml_write_array2R8 ! Two dimension array of R8Ki - !module procedure yaml_write_array1R16 ! Single dimension array (Ary) of QuKi - !module procedure yaml_write_array2R16 ! Two dimension array of QuKi - end interface - + PRIVATE ! ..... Public Subroutines ................................................................................................... PUBLIC :: SDOut_CloseSum @@ -52,10 +41,6 @@ MODULE SubDyn_Output PUBLIC :: SDOut_WriteOutputs PUBLIC :: SDOut_Init - PUBLIC :: yaml_write_array - - - CONTAINS @@ -818,105 +803,4 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) END SUBROUTINE SDOut_ChkOutLst !==================================================================================================== - -! TODO put this into NWTC LIB as YAML.f90 - -subroutine yaml_write_array2R4(fid, key, A, ReFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(SiKi), dimension(:,:), intent(in ) :: A !< Array - character(*), intent(in ) :: ReFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//ReFmt//',","),"]")' - do i=1,nr - write(fid, Fmt, iostat=ErrStat) A(i,:) - if (ErrStat /= 0) then - ErrMsg='Error writting array'//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2R4 - -subroutine yaml_write_array2R8(fid, key, A, ReFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(R8Ki), dimension(:,:), intent(in ) :: A !< Array - character(*), intent(in ) :: ReFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//ReFmt//',","),"]")' - do i=1,nr - write(fid, Fmt, iostat=ErrStat) A(i,:) - if (ErrStat /= 0) then - ErrMsg='Error writting array'//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2R8 - END MODULE SubDyn_Output diff --git a/modules/subdyn/src/Yaml.f90 b/modules/subdyn/src/Yaml.f90 new file mode 100644 index 000000000..12dd6ce22 --- /dev/null +++ b/modules/subdyn/src/Yaml.f90 @@ -0,0 +1,582 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** +module YAML + use NWTC_Library + + implicit none + + integer(IntKi), parameter :: INDENT_SPACES = 2 + + !> Write 1D or 2D array to file + interface yaml_write_array + module procedure yaml_write_array1I ! Single dimension array (Ary) of IntKi + module procedure yaml_write_array1R4 ! Single dimension array (Ary) of SiKi + module procedure yaml_write_array2R4 ! Two dimension array of SiKi + module procedure yaml_write_array1R8 ! Single dimension array (Ary) of R8Ki + module procedure yaml_write_array2R8 ! Two dimension array of R8Ki + module procedure yaml_write_array2I ! Two dimension array of IntKi + module procedure yaml_write_array1R16 ! Single dimension array (Ary) of QuKi + module procedure yaml_write_array2R16 ! Two dimension array of QuKi + end interface + + !> Write variable to file + interface yaml_write_var + module procedure yaml_write_varC ! Character + module procedure yaml_write_varI ! IntKi + module procedure yaml_write_varR4 ! SiKi + module procedure yaml_write_varR8 ! R8Ki + module procedure yaml_write_varR16 ! QuKi + end interface + private + + public :: yaml_write_var + public :: yaml_write_array + +contains + +! -------------------------------------------------------------------------------- +! --- Write variable +! -------------------------------------------------------------------------------- +!> Write simple key/variable to yaml file +subroutine yaml_write_varC(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + character(len=*), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varC + +subroutine yaml_write_varI(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + integer(IntKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varI + +subroutine yaml_write_varR4(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(SiKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR4 + +subroutine yaml_write_varR8(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(R8Ki), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR8 + +subroutine yaml_write_varR16(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(QuKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR16 + +! -------------------------------------------------------------------------------- +! --- Write array +! -------------------------------------------------------------------------------- +!> Write 1D or 2D array to file +subroutine yaml_write_array1I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + integer(IntKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1I + +subroutine yaml_write_array1R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(SiKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R4 + +subroutine yaml_write_array1R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(R8Ki), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R8 + +subroutine yaml_write_array1R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(QuKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R16 + +subroutine yaml_write_array2I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, label) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + integer(IntKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + logical, optional, intent(in ) :: label !< If present, add a index label at end of line + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + if (present(label)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"] # ",I0)' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + endif + do i=1,nr + if (present(label)) then + write(fid, Fmt, iostat=ErrStat) A(i,:), i + else + write(fid, Fmt, iostat=ErrStat) A(i,:) + endif + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2I + +subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(SiKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R4 + +subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(R8Ki), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R8 + +subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(QuKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R16 + + +end module YAML diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index c9003bd09..a903da5ad 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -1651,6 +1651,7 @@ + diff --git a/vs-build/SubDyn/SubDyn.vfproj b/vs-build/SubDyn/SubDyn.vfproj index 4cb323d69..ff937857a 100644 --- a/vs-build/SubDyn/SubDyn.vfproj +++ b/vs-build/SubDyn/SubDyn.vfproj @@ -174,6 +174,7 @@ + From 40ec663f6dc68b79a178fc60dc74e31a10cb259c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 2 Jun 2020 15:50:41 -0600 Subject: [PATCH 214/377] FlexSub: more yaml outputs and support for line format --- modules/subdyn/src/SubDyn.f90 | 94 +++++++++++++++++++++++------------ modules/subdyn/src/Yaml.f90 | 39 ++++++++++----- 2 files changed, 89 insertions(+), 44 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 3ff755b8b..7d4bfa40d 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2369,12 +2369,15 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix + real(ReKi) :: Ke(12,12), Me(12, 12), FCe(12), FGe(12) ! element stiffness and mass matrices gravity force vector + real(ReKi), dimension(:,:), allocatable :: DummyArray ! ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega real(ReKi), dimension(:,:), allocatable :: Modes real(ReKi), dimension(:) , allocatable :: Omega logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) character(len=*),parameter :: ReFmt='E15.6' + character(len=*),parameter :: SFmt='A15,1x' ! Need +1 for comma compared to ReFmt character(len=*),parameter :: IFmt='I7' ! ErrStat = ErrID_None @@ -2409,22 +2412,27 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! (it helps in debugging) WRITE(UnSum, '(A)') '#Unless specified, units are consistent with Input units, [SI] system is advised.' WRITE(UnSum, '(A)') SectionDivide + write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) + + ! --- Internal FEM representation + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '# Internal FEM representation' call yaml_write_var(UnSum, 'nNodes_I', p%nNodes_I,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "interface" (I)') call yaml_write_var(UnSum, 'nNodes_C', p%nNodes_C,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "reactions" (C)') call yaml_write_var(UnSum, 'nNodes_L', p%nNodes_L,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "internal" (L)') call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') #ifdef SD_SUMMARY_DEBUG call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') - call yaml_write_var(UnSum, 'nDOFI_Rb', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') + call yaml_write_var(UnSum, 'nDOFI_B', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') call yaml_write_var(UnSum, 'nDOFC__ ', p%nDOFC__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" (C__)') - call yaml_write_var(UnSum, 'nDOFC_Rb', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') + call yaml_write_var(UnSum, 'nDOFC_B', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') call yaml_write_var(UnSum, 'nDOFC_L ', p%nDOFC_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" internal (C_L)') call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') #endif - call yaml_write_var(UnSum, 'nDOF__Rb', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total retained (__B)') + call yaml_write_var(UnSum, 'nDOF__B', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total retained (__B)') call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total internal (__L)') call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total fixed (__F)') call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total ') @@ -2440,35 +2448,55 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'DOF_C_L', p%IDC_L , IFmt, ErrStat2, ErrMsg2, comment='"reaction" internal DOFs') call yaml_write_array(UnSum, 'DOF_C_F', p%IDC_F , IFmt, ErrStat2, ErrMsg2, comment='"reaction" fixed DOFs') call yaml_write_array(UnSum, 'DOF_L_L', p%IDL_L , IFmt, ErrStat2, ErrMsg2, comment='"internal" internal DOFs') - call yaml_write_array(UnSum, 'DOF_L_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') + call yaml_write_array(UnSum, 'DOF_R_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') #endif call yaml_write_array(UnSum, 'DOF___B', p%ID__Rb, IFmt, ErrStat2, ErrMsg2, comment='all retained DOFs') call yaml_write_array(UnSum, 'DOF___F', p%ID__F , IFmt, ErrStat2, ErrMsg2, comment='all fixed DOFs') call yaml_write_array(UnSum, 'DOF___L', p%ID__L , IFmt, ErrStat2, ErrMsg2, comment='all internal DOFs') - write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) - - WRITE(UnSum, '(A)') SectionDivide - + WRITE(UnSum, '()') WRITE(UnSum, '(A)') '#Index map from DOF to nodes' WRITE(UnSum, '(A)') '# Node No., DOF/Node, NodalDOF' call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of nodes (nNodes):',p%nNodes - WRITE(UnSum, '("#",4x,A8,1x,A11,9(2x,A15))') 'Node No.', 'Y2Mesh Node', 'X (m)','Y (m)','Z (m)', 'JType (-)', 'JDirX (-)','JDirY (-)','JDirZ (-)','JStff (Nm/rad)','JDmp (Nm/rad.s)' - WRITE(UnSum, '(A)') 'Nodes:' + ! Nodes properties + CALL AllocAry( DummyArray, size(Init%Nodes,1), JointsCol+1, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return do i = 1, p%nNodes - WRITE(UnSum, '('//Num2LStr(p%nNodes)//'(" - [ ",I8,",",I9,","'//Num2lstr(JointsCol-1)//'(1x,F15.4,","),"]",:,/))') & - NINT(Init%Nodes(i, 1)), p%INodes_SD_to_Mesh(i), (Init%Nodes(i, j), j = 2, JointsCol) + DummyArray(i,1) = Init%Nodes(i, 1) + DummyArray(i,2) = p%INodes_SD_to_Mesh(i) + DummyArray(i,3:JointsCol+1) = Init%Nodes(i, 2:JointsCol) enddo - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of elements (NElems):',Init%NElem - WRITE(UnSum, '("#",A10,5(A10))') 'Elem No.','Node_I','Node_J','Prop_I','Prop_J','Type' - do i=1, Init%nElem - WRITE(UnSum, '("#",6(I10))') (p%Elems(i, j), j = 1, MembersCol) + write(UnSum, '("#",4x,2(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'Y2Node', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' + call yaml_write_array(UnSum, 'Nodes', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='2(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) + deallocate(DummyArray) + + ! Element properties + CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return + do i=1,size(p%ElemProps) + DummyArray(i,1) = p%Elems(i,1) ! Should be == i + DummyArray(i,2) = p%Elems(i,2) ! Node 1 + DummyArray(i,3) = p%Elems(i,3) ! Node 2 + DummyArray(i,4) = p%Elems(i,4) ! Prop 1 + DummyArray(i,5) = p%Elems(i,5) ! Prop 2 + DummyArray(i,6) = p%ElemProps(i)%eType ! Type + DummyArray(i,7) = p%ElemProps(i)%Length !Length + DummyArray(i,8) = p%ElemProps(i)%Area ! Area m^2 + DummyArray(i,9) = p%ElemProps(i)%Rho ! density kg/m^3 + DummyArray(i,10) = p%ElemProps(i)%YoungE ! Young modulus + DummyArray(i,11) = p%ElemProps(i)%ShearG ! G + DummyArray(i,12) = p%ElemProps(i)%Kappa ! Shear coefficient + DummyArray(i,13) = p%ElemProps(i)%Ixx ! Moment of inertia + DummyArray(i,14) = p%ElemProps(i)%Iyy ! Moment of inertia + DummyArray(i,15) = p%ElemProps(i)%Jzz ! Moment of inertia + DummyArray(i,16) = p%ElemProps(i)%T0 ! Pretension [N] enddo + write(UnSum, '("#",4x,6(A9),10('//trim(SFmt)//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' + call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),7(E15.6,",")') !, comment='',label=.true.) + deallocate(DummyArray) + ! --- User inputs (less interesting, repeat of input file) + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#User inputs' WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' @@ -2541,7 +2569,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A, I6)') "#FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega call yaml_write_array(UnSum, 'Full_Eigenvalues', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A, I6)') "#CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM - call yaml_write_array(UnSum, 'CB_Eigenvalues', CBparams%OmegaL/(TwoPi), ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'CB_Eigenvalues', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full System @@ -2590,23 +2618,27 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#**** Additional Debugging Information ****' - !------------------------------------------------------------------------------------------------------------- - ! write assembed K M to a txt file - !------------------------------------------------------------------------------------------------------------- + ! --- Element Me,Ke,Fg, Fce + CALL ElemM(p%ElemProps(1), Me) + CALL ElemK(p%ElemProps(1), Ke) + CALL ElemF(p%ElemProps(1), Init%g, FGe, FCe) + call yaml_write_array(UnSum, 'Ke',Ke, ReFmt, ErrStat2, ErrMsg2, comment='First element stiffness matrix') + call yaml_write_array(UnSum, 'Me',Me, ReFmt, ErrStat2, ErrMsg2, comment='First element mass matrix') + call yaml_write_array(UnSum, 'FGe',FGe, ReFmt, ErrStat2, ErrMsg2, comment='First element gravity vector') + call yaml_write_array(UnSum, 'FCe',FCe, ReFmt, ErrStat2, ErrMsg2, comment='First element cable pretension') + + ! --- Write assembed K M to a txt file WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') - !------------------------------------------------------------------------------------------------------------- - ! write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system - !------------------------------------------------------------------------------------------------------------- + + ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') - !------------------------------------------------------------------------------------------------------------- - ! write CB system matrices - !------------------------------------------------------------------------------------------------------------- + ! --- write CB system matrices WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') @@ -2619,9 +2651,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'KLL^-1', MATMUL(p%PhiLInvOmgL2,p%PhiL_T ), ReFmt, ErrStat2, ErrMsg2, comment='') endif - !------------------------------------------------------------------------------------------------------------- - ! write TP TI matrix - !------------------------------------------------------------------------------------------------------------- + ! --- write TP TI matrix WRITE(UnSum, '(A)') SectionDivide call yaml_write_array(UnSum, 'TI', p%TI, ReFmt, ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') diff --git a/modules/subdyn/src/Yaml.f90 b/modules/subdyn/src/Yaml.f90 index 12dd6ce22..2be2d1bab 100644 --- a/modules/subdyn/src/Yaml.f90 +++ b/modules/subdyn/src/Yaml.f90 @@ -232,7 +232,7 @@ subroutine yaml_write_array1I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comme if (nc==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' write(fid, Fmt, iostat=ErrStat) A(:) if (ErrStat /= 0) then ErrMsg='Error writting array '//trim(key)//' to YAML file' @@ -279,7 +279,7 @@ subroutine yaml_write_array1R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nc==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' write(fid, Fmt, iostat=ErrStat) A(:) if (ErrStat /= 0) then ErrMsg='Error writting array '//trim(key)//' to YAML file' @@ -325,7 +325,7 @@ subroutine yaml_write_array1R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nc==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' write(fid, Fmt, iostat=ErrStat) A(:) if (ErrStat /= 0) then ErrMsg='Error writting array '//trim(key)//' to YAML file' @@ -372,7 +372,7 @@ subroutine yaml_write_array1R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, com if (nc==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' write(fid, Fmt, iostat=ErrStat) A(:) if (ErrStat /= 0) then ErrMsg='Error writting array '//trim(key)//' to YAML file' @@ -417,9 +417,9 @@ subroutine yaml_write_array2I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comme write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else if (present(label)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"] # ",I0)' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"] # ",I0)' else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' endif do i=1,nr if (present(label)) then @@ -435,7 +435,7 @@ subroutine yaml_write_array2I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comme endif end subroutine yaml_write_array2I -subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) +subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) integer(IntKi), intent(in ) :: fid !< File Unit character(len=*), intent(in ) :: key !< Array name real(SiKi), dimension(:,:), intent(in ) :: A !< Array @@ -444,6 +444,7 @@ subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none integer(IntKi), optional, intent(in ) :: level !< indentation level character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line integer :: nr, nc, i ! size (rows and columns) of A integer :: nSpaces ! number of indentation spaces character(256) :: Fmt @@ -474,7 +475,11 @@ subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) if (ErrStat /= 0) then @@ -485,7 +490,7 @@ subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm endif end subroutine yaml_write_array2R4 -subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) +subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) integer(IntKi), intent(in ) :: fid !< File Unit character(len=*), intent(in ) :: key !< Array name real(R8Ki), dimension(:,:), intent(in ) :: A !< Array @@ -494,6 +499,7 @@ subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none integer(IntKi), optional, intent(in ) :: level !< indentation level character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line integer :: nr, nc, i ! size (rows and columns) of A integer :: nSpaces ! number of indentation spaces character(256) :: Fmt @@ -522,7 +528,11 @@ subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) if (ErrStat /= 0) then @@ -533,7 +543,7 @@ subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm endif end subroutine yaml_write_array2R8 -subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) +subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) integer(IntKi), intent(in ) :: fid !< File Unit character(len=*), intent(in ) :: key !< Array name real(QuKi), dimension(:,:), intent(in ) :: A !< Array @@ -542,6 +552,7 @@ subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, com character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none integer(IntKi), optional, intent(in ) :: level !< indentation level character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line integer :: nr, nc, i ! size (rows and columns) of A integer :: nSpaces ! number of indentation spaces character(256) :: Fmt @@ -567,7 +578,11 @@ subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, com if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'(1x,'//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) if (ErrStat /= 0) then From 1cd707ca0a605b69b4a01e640236793e3f852301 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 2 Jun 2020 17:54:09 -0600 Subject: [PATCH 215/377] FlexSub: implemented SttcSolve=0,1,2, with 2 gravity only --- modules/subdyn/src/SD_FEM.f90 | 7 ++ modules/subdyn/src/SubDyn.f90 | 128 ++++++++++++++++--------- modules/subdyn/src/SubDyn_Registry.txt | 4 +- modules/subdyn/src/SubDyn_Types.f90 | 128 ++++++++++++++++++++++++- 4 files changed, 217 insertions(+), 50 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index f2df149f6..cdcdcef71 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -64,9 +64,16 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 INTEGER(IntKi), PARAMETER :: idBC_Leader = 13 ! TODO, and maybe "BC" not appropriate here + + ! Types of Static Improvement Methods + INTEGER(IntKi), PARAMETER :: idSIM_None = 0 + INTEGER(IntKi), PARAMETER :: idSIM_Full = 1 + INTEGER(IntKi), PARAMETER :: idSIM_GravOnly = 2 + INTEGER(IntKi) :: idSIM_Valid(3) = (/idSIM_None, idSIM_Full, idSIM_GravOnly /) INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) + INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi MODULE PROCEDURE FINDLOCI_IntKi diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 7d4bfa40d..3481ec672 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -431,16 +431,28 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END IF !STATIC IMPROVEMENT METHOD ( modify UL ) - IF (p%SttcSolve) THEN - FLt = MATMUL(p%PhiL_T, m%UFL + p%FGL) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? no (solution: don't call this routine thousands of time to calculate the jacobian) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! -> bjj: todo: this line takes up A LOT of time. is PhiL sparse???? + if (p%SttcSolve/=idSIM_None) then + if (p%SttcSolve==idSIM_Full) then + FLt = MATMUL(p%PhiL_T , m%UFL + p%FGL) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) + ! TODO New + !ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) + elseif (p%SttcSolve==idSIM_GravOnly) then + FLt = MATMUL(p%PhiL_T , p%FGL) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) + ! TODO New + !ULS = p%UL_st_g + else + STOP ! Should never happen + endif m%UL = m%UL + ULS - - IF ( p%nDOFM > 0) THEN + if ( p%nDOFM > 0) then UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) + ! TODO new + ! <<< m%UL = m%UL - UL0M - END IF - ENDIF + end if + endif ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar m%U_red (p%ID__L) = m%UL @@ -620,8 +632,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable for input and output -CHARACTER(1024) :: PriPath ! The path to the primary input file -CHARACTER(1024) :: Line ! String to temporarially hold value of read line +CHARACTER(1024) :: PriPath ! The path to the primary input file +CHARACTER(1024) :: Line, Dummy_Str ! String to temporarially hold value of read line INTEGER :: Sttus CHARACTER(64), ALLOCATABLE :: StrArray(:) ! Array of strings, for better control of table inputs LOGICAL :: Echo @@ -631,12 +643,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) INTEGER(IntKi) :: nColumns, nColValid, nColNumeric INTEGER(IntKi) :: IOS INTEGER(IntKi) :: UnEc !Echo file ID - REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings - INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf -REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat +REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) +LOGICAL :: Dummy_Bool INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ! Initialize ErrStat @@ -697,7 +708,18 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) END IF CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadLVar(UnIn, SDInputFile, p%SttcSolve, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +p%SttcSolve = idSIM_None +if (is_numeric(Dummy_Str, DummyFloat)) then + p%SttcSolve = int(DummyFloat) +else if (is_logical(Dummy_Str, Dummy_Bool)) then + if (Dummy_Bool) p%SttcSolve = idSIM_Full +else + call Fatal('SttcSolve should be an integer or a logical, received: '//trim(Dummy_Str)) + return +endif +IF (Check(.not.(any(idSIM_Valid==p%SttcSolve)), 'Invalid value entered for SttcSolve')) return + !-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko @@ -1637,10 +1659,10 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) IDR => p%IDR__ endif - IF (p%SttcSolve) THEN ! STATIC TREATMENT IMPROVEMENT - nM_Out=p%nDOF__L ! Selecting all CB modes for outputs to the function below + IF (p%SttcSolve/=idSIM_None) THEN ! STATIC TREATMENT IMPROVEMENT + nM_out=p%nDOF__L ! Selecting all CB modes for outputs to the function below ELSE - nM_Out=p%nDOFM ! Selecting only the requrested number of CB modes + nM_out=p%nDOFM ! Selecting only the requrested number of CB modes ENDIF nL = p%nDOF__L nM = p%nDOFM @@ -1653,31 +1675,23 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%PhiL, nL, nM_Out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%PhiL, nL, nM_out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%OmegaL, nM_Out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_Out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& + CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& Init%FG, FGR, FGL, FGB, FGM) if(Failed()) return - ! Set p%PhiL_T and p%PhiLInvOmgL2 for static improvement - IF (p%SttcSolve) THEN - p%PhiL_T=TRANSPOSE(CB%PhiL) !transpose of PhiL for static improvement - DO I = 1, nM_Out - p%PhiLInvOmgL2(:,I) = CB%PhiL(:,I)* (1./CB%OmegaL(I)**2) - ENDDO - END IF - CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if(.not.BC_Before_CB) then ! We apply the BC now, removing unwanted DOFs - call applyConstr(CB, FGB, PhiRb) + call applyConstr(CB, FGB, PhiRb) ! Reduces size of CB%MBB, CB%KBB, CB%MBM, FGB, NOTE: "L" unaffected else PhiRb=CB%PhiR ! Remove me in the future endif ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1801,16 +1815,17 @@ END SUBROUTINE SD_Guyan_RigidBodyMass !------------------------------------------------------------------------------------------------------ !> Set parameters to compute state and output equations -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, p%nDOF__L) + integer(IntKi), INTENT(IN ) :: nM_out + REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: OmegaL(p%nDOF__L) + REAL(ReKi), INTENT(IN ) :: OmegaL(nM_out) REAL(ReKi), INTENT(IN ) :: FGB(p%nDOF__Rb) REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) REAL(ReKi), INTENT(IN ) :: FGM(p%nDOFM) @@ -1837,10 +1852,28 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, OmegaL, PhiL, FGL, FG CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return TI_transpose = TRANSPOSE(p%TI) - ! Store FGL for later processes - IF (p%SttcSolve) THEN - p%FGL = FGL - ENDIF + ! Store Static Improvement Method constants + if (p%SttcSolve /= idSIM_None) then + if (p%SttcSolve == idSIM_Full) then + CALL WrScr(' Using static improvement method for gravity and ext. loads') + else + CALL WrScr(' Using static improvement method for gravity only') + endif + ! Allocations + CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%KLLm1 , p%nDOF__L, p%nDOF__L, 'p%KLLm1', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%UL_st_g, p%nDOF__L, 'p%UL_st_g', ErrStat2, ErrMsg2 ); if(Failed())return + ! TODO PhiL_T and PhiLInvOmgL2 may not be needed if KLLm1 is stored. + p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement + do I = 1, nM_out + p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) + enddo + p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t + p%FGL = FGL + p%UL_st_g = MATMUL(p%KLLm1, FGL) + endif ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) p%PhiRb_TI = MATMUL(PhiRb, p%TI) @@ -1997,12 +2030,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if -if ( p%SttcSolve ) THEN - CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') -end if - END SUBROUTINE AllocParameters !------------------------------------------------------------------------------------------------------ @@ -2340,7 +2367,6 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) endif ! --- Reduced vector of external force m%Fext_red = matmul(transpose(p%T_red), m%Fext) - UFL=0 UFL= m%Fext_red(p%ID__L) END SUBROUTINE ConstructUFL @@ -2645,10 +2671,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') - IF (p%SttcSolve) THEN + IF (p%SttcSolve/= idSIM_None) THEN call yaml_write_array(UnSum, 'PhiL', transpose(p%PhiL_T), ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'KLL^-1', MATMUL(p%PhiLInvOmgL2,p%PhiL_T ), ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'KLL^-1' , p%KLLm1 , ReFmt, ErrStat2, ErrMsg2, comment='') endif ! --- write TP TI matrix @@ -2811,7 +2837,6 @@ FUNCTION is_numeric(string, x) CHARACTER(len=*), INTENT(IN) :: string REAL(ReKi), INTENT(OUT) :: x LOGICAL :: is_numeric - INTEGER :: e,n CHARACTER(len=12) :: fmt x = 0.0_ReKi @@ -2820,6 +2845,17 @@ FUNCTION is_numeric(string, x) READ(string,fmt,IOSTAT=e) x is_numeric = e == 0 END FUNCTION is_numeric +FUNCTION is_logical(string, b) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + Logical, INTENT(OUT) :: b + LOGICAL :: is_logical + INTEGER :: e,n + b = .false. + n=LEN_TRIM(string) + READ(string,*,IOSTAT=e) b + is_logical = e == 0 +END FUNCTION is_logical !> Parses a file for Kxx,Kxy,..Kxthtx,..Kxtz, Kytx, Kyty,..Kztz SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 918bbae44..163142973 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -176,7 +176,7 @@ typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indic typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" # --- CB reduction typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" -typedef ^ ParameterType Logical SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" @@ -196,8 +196,10 @@ typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" typedef ^ ParameterType ReKi MBB {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi UL_st_g {:} - - "Motion of internal DOFs due to static gravitational force, for static improvement" typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" +typedef ^ ParameterType ReKi KLLm1 {:}{:} - - "KLL^{-1}, inverse of matrix KLL, for static solve only" typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 800200e62..65ba513b0 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -214,7 +214,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] - LOGICAL :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] + INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -234,8 +234,10 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_st_g !< Motion of internal DOFs due to static gravitational force, for static improvement [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KLLm1 !< KLL^{-1}, inverse of matrix KLL, for static solve only [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AM2Jac !< Jacobian (factored) for Adams-Boulton 2nd order Integration [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AM2JacPiv !< Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI !< Matrix to calculate TP reference point reaction at top of structure [-] @@ -6720,6 +6722,18 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%MBM = SrcParamData%MBM ENDIF +IF (ALLOCATED(SrcParamData%UL_st_g)) THEN + i1_l = LBOUND(SrcParamData%UL_st_g,1) + i1_u = UBOUND(SrcParamData%UL_st_g,1) + IF (.NOT. ALLOCATED(DstParamData%UL_st_g)) THEN + ALLOCATE(DstParamData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%UL_st_g.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%UL_st_g = SrcParamData%UL_st_g +ENDIF IF (ALLOCATED(SrcParamData%PhiL_T)) THEN i1_l = LBOUND(SrcParamData%PhiL_T,1) i1_u = UBOUND(SrcParamData%PhiL_T,1) @@ -6748,6 +6762,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%PhiLInvOmgL2 = SrcParamData%PhiLInvOmgL2 ENDIF +IF (ALLOCATED(SrcParamData%KLLm1)) THEN + i1_l = LBOUND(SrcParamData%KLLm1,1) + i1_u = UBOUND(SrcParamData%KLLm1,1) + i2_l = LBOUND(SrcParamData%KLLm1,2) + i2_u = UBOUND(SrcParamData%KLLm1,2) + IF (.NOT. ALLOCATED(DstParamData%KLLm1)) THEN + ALLOCATE(DstParamData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KLLm1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KLLm1 = SrcParamData%KLLm1 +ENDIF IF (ALLOCATED(SrcParamData%AM2Jac)) THEN i1_l = LBOUND(SrcParamData%AM2Jac,1) i1_u = UBOUND(SrcParamData%AM2Jac,1) @@ -7196,12 +7224,18 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%MBM)) THEN DEALLOCATE(ParamData%MBM) ENDIF +IF (ALLOCATED(ParamData%UL_st_g)) THEN + DEALLOCATE(ParamData%UL_st_g) +ENDIF IF (ALLOCATED(ParamData%PhiL_T)) THEN DEALLOCATE(ParamData%PhiL_T) ENDIF IF (ALLOCATED(ParamData%PhiLInvOmgL2)) THEN DEALLOCATE(ParamData%PhiLInvOmgL2) ENDIF +IF (ALLOCATED(ParamData%KLLm1)) THEN + DEALLOCATE(ParamData%KLLm1) +ENDIF IF (ALLOCATED(ParamData%AM2Jac)) THEN DEALLOCATE(ParamData%AM2Jac) ENDIF @@ -7525,6 +7559,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM END IF + Int_BufSz = Int_BufSz + 1 ! UL_st_g allocated yes/no + IF ( ALLOCATED(InData%UL_st_g) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_st_g upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_st_g) ! UL_st_g + END IF Int_BufSz = Int_BufSz + 1 ! PhiL_T allocated yes/no IF ( ALLOCATED(InData%PhiL_T) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiL_T upper/lower bounds for each dimension @@ -7535,6 +7574,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! PhiLInvOmgL2 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%PhiLInvOmgL2) ! PhiLInvOmgL2 END IF + Int_BufSz = Int_BufSz + 1 ! KLLm1 allocated yes/no + IF ( ALLOCATED(InData%KLLm1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KLLm1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KLLm1) ! KLLm1 + END IF Int_BufSz = Int_BufSz + 1 ! AM2Jac allocated yes/no IF ( ALLOCATED(InData%AM2Jac) ) THEN Int_BufSz = Int_BufSz + 2*2 ! AM2Jac upper/lower bounds for each dimension @@ -8007,7 +8051,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SttcSolve , IntKiBuf(1), 1) + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%SttcSolve Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8298,6 +8342,19 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%MBM) END IF + IF ( .NOT. ALLOCATED(InData%UL_st_g) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_st_g,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_st_g,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UL_st_g)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_st_g))-1 ) = PACK(InData%UL_st_g,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UL_st_g) + END IF IF ( .NOT. ALLOCATED(InData%PhiL_T) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8330,6 +8387,22 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%PhiLInvOmgL2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiLInvOmgL2))-1 ) = PACK(InData%PhiLInvOmgL2,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%PhiLInvOmgL2) END IF + IF ( .NOT. ALLOCATED(InData%KLLm1) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%KLLm1)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KLLm1))-1 ) = PACK(InData%KLLm1,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%KLLm1) + END IF IF ( .NOT. ALLOCATED(InData%AM2Jac) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9200,7 +9273,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END IF OutData%nDOFM = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 - OutData%SttcSolve = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + OutData%SttcSolve = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated Int_Xferred = Int_Xferred + 1 @@ -9681,6 +9754,29 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%MBM) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_st_g not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UL_st_g)) DEALLOCATE(OutData%UL_st_g) + ALLOCATE(OutData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_st_g.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UL_st_g)>0) OutData%UL_st_g = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_st_g))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UL_st_g) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9733,6 +9829,32 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%PhiLInvOmgL2) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KLLm1 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%KLLm1)) DEALLOCATE(OutData%KLLm1) + ALLOCATE(OutData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KLLm1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%KLLm1)>0) OutData%KLLm1 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KLLm1))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%KLLm1) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac not allocated Int_Xferred = Int_Xferred + 1 ELSE From f24e0edca9924b1ca496fba37735a48242d6cda6 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 9 Jun 2020 10:50:59 -0600 Subject: [PATCH 216/377] Morison Bug fixes Correctly test for valid submerged region of buoyancy end effects Now accumulating ballasted and buoyancy side-effect loads for a given node --- modules/hydrodyn/src/Morison.f90 | 40 +++++++++++++++----------- modules/hydrodyn/src/Morison.txt | 1 + modules/hydrodyn/src/Morison_Types.f90 | 7 +++++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 148d976d5..e251294be 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1556,6 +1556,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! calculate h_floor if seabed-piercing member%h_floor = 0.0_ReKi member%i_floor = member%NElements+1 ! Default to entire member is below the seabed + member%doEndBuoyancy = .false. if (Za < -WtrDepth) then do i= 2, member%NElements+1 Za = InitInp%Nodes(member%NodeIndx(i))%Position(3) @@ -1567,7 +1568,10 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%h_floor = (-WtrDepth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) member%i_floor = i-1 ! record the number of the element that pierces the seabed + member%doEndBuoyancy = .true. exit + else if ( EqualRealNos(Za, -WtrDepth ) ) then + member%doEndBuoyancy = .true. end if end do else @@ -2243,8 +2247,8 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) call AllocAry( p%DragConst_End, p%NJoints, 'p%DragConst_End', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_I_End , 3, p%NJoints, 'm%F_I_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_BF_End , 6, p%NJoints, 'm%F_BF_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_A_End , 6, p%NJoints, 'm%F_A_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_D_End , 6, p%NJoints, 'm%F_D_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_A_End , 3, p%NJoints, 'm%F_A_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_D_End , 3, p%NJoints, 'm%F_D_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_B_End , 6, p%NJoints, 'm%F_B_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_IMG_End , 6, p%NJoints, 'm%F_IMG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%I_MG_End , 3, 3, p%NJoints, 'p%I_MG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) @@ -2547,10 +2551,13 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! so they need to be zeroed out before the summations happen) m%F_WMG = 0.0_ReKi m%F_IMG = 0.0_ReKi + m%F_BF_End= 0.0_ReKi m%F_If = 0.0_ReKi m%F_D = 0.0_ReKi m%F_A = 0.0_ReKi m%F_I = 0.0_ReKi + m%F_B = 0.0_ReKi + m%F_BF = 0.0_ReKi m%F_B_End = 0.0_ReKi ! Loop through each member @@ -2966,8 +2973,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, else ! Entire member is above the still water line end if - - elseif ( mem%i_floor < mem%NElements) then ! The member crosses the seabed line + + ! elseif ( (mem%i_floor < mem%NElements) .and. (z2<= 0.0_ReKi) ) then ! The member crosses the seabed line so only the upper end could have bouyancy effects, if at or below free surface + elseif ( (mem%doEndBuoyancy) .and. (z2<= 0.0_ReKi) ) then ! The member crosses the seabed line so only the upper end could have bouyancy effects, if at or below free surface ! Only compute the buoyancy contribution from the upper end Fl = p%WtrDens * g * pi *mem%RMG(N+1)**2*z2 Moment = p%WtrDens * g * pi *0.25*mem%RMG(N+1)**4*sinPhi @@ -3094,19 +3102,19 @@ SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, a REAL(ReKi), INTENT ( OUT ) :: F2(6) ! (N, Nm) force/moment vector for the other node (whether i+1, or i-1) - F1(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - F1(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - F1(3) = (Fl*cosPhi - Fr*sinPhi)*alpha - F1(4) = sinBeta * M *alpha - F1(5) = cosBeta * M *alpha - F1(6) = 0.0 + F1(1) = F1(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(2) = F1(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(3) = F1(3) + (Fl*cosPhi - Fr*sinPhi)*alpha + F1(4) = F1(4) + sinBeta * M *alpha + F1(5) = F1(5) + cosBeta * M *alpha + !F1(6) = F1(6) + 0.0 - F2(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - F2(2) = -sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - F2(3) = (Fl*cosPhi - Fr*sinPhi)*(1-alpha) - F2(4) = sinBeta * M *(1-alpha) - F2(5) = cosBeta * M *(1-alpha) - F2(6) = 0.0 + F2(1) = F2(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(2) = F2(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(3) = F2(3) + (Fl*cosPhi - Fr*sinPhi)*(1-alpha) + F2(4) = F2(4) + sinBeta * M *(1-alpha) + F2(5) = F2(5) + cosBeta * M *(1-alpha) + !F2(6) = F2(6) + 0.0 END SUBROUTINE DistributeElementLoads diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 4bb584d4d..c3bd0ae60 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -106,6 +106,7 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi z_overfill - - - "if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled." m typedef ^ ^ ReKi h_floor - - - "the distance from the node to the seabed along the member axis (negative value)" m typedef ^ ^ INTEGER i_floor - - - "the number of the element that pierces the seabed (zero if the member doesn't pierce it)" - +typedef ^ ^ LOGICAL doEndBuoyancy - - - "compute the end plate effect for the hightest node of this member" - typedef ^ ^ INTEGER memfloodstatus - - - "Member-level flooded status for each elemen: 0 unflooded or fully below seabed, 2 partially flooded, 1 fully flooded " - typedef ^ ^ INTEGER floodstatus {:} - - "flooded status for each element: 0 unflooded or fully below seabed, 1 fully flooded, 2 partially flooded" - typedef ^ ^ ReKi alpha {:} - - "relative volume centroid of each element including marine growth, from node i to node i+1" - diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index 5ebf023a5..afd977d40 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -151,6 +151,7 @@ MODULE Morison_Types REAL(ReKi) :: z_overfill !< if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled. [m] REAL(ReKi) :: h_floor !< the distance from the node to the seabed along the member axis (negative value) [m] INTEGER(IntKi) :: i_floor !< the number of the element that pierces the seabed (zero if the member doesn't pierce it) [-] + LOGICAL :: doEndBuoyancy !< compute the end plate effect for the hightest node of this member [-] INTEGER(IntKi) :: memfloodstatus !< Member-level flooded status for each elemen: 0 unflooded or fully below seabed, 2 partially flooded, 1 fully flooded [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: floodstatus !< flooded status for each element: 0 unflooded or fully below seabed, 1 fully flooded, 2 partially flooded [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: alpha !< relative volume centroid of each element including marine growth, from node i to node i+1 [-] @@ -1870,6 +1871,7 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod DstMemberTypeData%z_overfill = SrcMemberTypeData%z_overfill DstMemberTypeData%h_floor = SrcMemberTypeData%h_floor DstMemberTypeData%i_floor = SrcMemberTypeData%i_floor + DstMemberTypeData%doEndBuoyancy = SrcMemberTypeData%doEndBuoyancy DstMemberTypeData%memfloodstatus = SrcMemberTypeData%memfloodstatus IF (ALLOCATED(SrcMemberTypeData%floodstatus)) THEN i1_l = LBOUND(SrcMemberTypeData%floodstatus,1) @@ -2443,6 +2445,7 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = Re_BufSz + 1 ! z_overfill Re_BufSz = Re_BufSz + 1 ! h_floor Int_BufSz = Int_BufSz + 1 ! i_floor + Int_BufSz = Int_BufSz + 1 ! doEndBuoyancy Int_BufSz = Int_BufSz + 1 ! memfloodstatus Int_BufSz = Int_BufSz + 1 ! floodstatus allocated yes/no IF ( ALLOCATED(InData%floodstatus) ) THEN @@ -2788,6 +2791,8 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 IntKiBuf(Int_Xferred) = InData%i_floor Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%doEndBuoyancy, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%memfloodstatus Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%floodstatus) ) THEN @@ -3469,6 +3474,8 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%i_floor = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%doEndBuoyancy = TRANSFER(IntKiBuf(Int_Xferred), OutData%doEndBuoyancy) + Int_Xferred = Int_Xferred + 1 OutData%memfloodstatus = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! floodstatus not allocated From 611537384fb2ec183740ae175d8c991f7cc0a31c Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 9 Jun 2020 10:53:24 -0600 Subject: [PATCH 217/377] Fixed bug with mappingMooring and HD loads to ED --- modules/openfast-library/src/FAST_Solver.f90 | 33 +++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 3b0e6cee9..f757d012c 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -1496,7 +1496,8 @@ SUBROUTINE ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & CALL HydroDyn_CalcOutput( this_time, u_HD, p_HD, x_HD, xd_HD, z_HD, OtherSt_HD, y_HD, m_HD, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - + !write(*,*) 'y_HD%Morison%Mesh%Force', y_HD%Morison%Mesh%Force + !write(*,*) 'y_HD%Morison%Mesh%Moment', y_HD%Morison%Mesh%Moment IF (ErrStat >= AbortErrLev) THEN CALL CleanUp() RETURN @@ -1733,7 +1734,7 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations + CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, PlatformMotions ) !u_MAP and y_ED contain the displacements needed for moment calculations CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN @@ -1742,7 +1743,7 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations + CALL Transfer_Point_to_Point( y_MD%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_MD%PtFairleadDisplacement, PlatformMotions ) !u_MD and y_ED contain the displacements needed for moment calculations CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN @@ -1751,13 +1752,13 @@ SUBROUTINE U_ED_HD_Residual( y_ED2, y_HD2, u_IN, U_Resid) CALL Transfer_Point_to_Point( y_ED2%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat, ErrMsg ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh_2, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations + CALL Transfer_Point_to_Point( y_FEAM%PtFairleadLoad, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, u_FEAM%PtFairleadDisplacement, PlatformMotions ) !u_FEAM and y_ED contain the displacements needed for moment calculations CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ELSE - MeshMapData%u_ED_PlatformPtMesh_2%Force = 0.0_ReKi - MeshMapData%u_ED_PlatformPtMesh_2%Moment = 0.0_ReKi + MeshMapData%u_ED_PlatformPtMesh%Force = 0.0_ReKi + MeshMapData%u_ED_PlatformPtMesh%Moment = 0.0_ReKi END IF @@ -2862,7 +2863,9 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, !.................. ! Get ED loads input (from HD only) !.................. - + MeshMapData%u_ED_PlatformPtMesh%Force = 0.0_ReKi + MeshMapData%u_ED_PlatformPtMesh%Moment = 0.0_ReKi + ! we're mapping loads, so we also need the sibling meshes' displacements: if ( y_HD2%WAMITMesh%Committed) then CALL Transfer_Point_to_Point( y_HD2%WAMITMesh, MeshMapData%u_ED_PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, MeshMapData%u_HD_W_Mesh, PlatformMotions) !u_HD and u_mapped_positions contain the displaced positions for load calculations @@ -3794,16 +3797,15 @@ SUBROUTINE ResetRemapFlags(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, MAPp ! HydroDyn IF ( p_FAST%CompHydro == Module_HD ) THEN + HD%Input(1)%PRPMesh%RemapFlag = .FALSE. IF (HD%Input(1)%WAMITMesh%Committed) THEN - HD%Input(1)%WAMITMesh%RemapFlag = .FALSE. - HD%y%WAMITMesh%RemapFlag = .FALSE. - HD%y%WAMITMesh%RemapFlag = .FALSE. + HD%Input(1)%WAMITMesh%RemapFlag = .FALSE. + HD%y%WAMITMesh%RemapFlag = .FALSE. END IF IF (HD%Input(1)%Morison%Mesh%Committed) THEN - HD%Input(1)%Morison%Mesh%RemapFlag = .FALSE. - HD%y%Morison%Mesh%RemapFlag = .FALSE. + HD%Input(1)%Morison%Mesh%RemapFlag = .FALSE. + HD%y%Morison%Mesh%RemapFlag = .FALSE. END IF - END IF ! SubDyn @@ -5532,9 +5534,12 @@ SUBROUTINE FAST_ExtrapInterpMods( t_global_next, p_FAST, m_FAST, ED, BD, SrvD, A ErrMsg = "" ! ElastoDyn + !write(*,*) 'ED%Input(1)%PLATFORMPTMESH%Force', ED%Input(1)%PLATFORMPTMESH%Force + !write(*,*) 'ED%Input(2)%PLATFORMPTMESH%Force', ED%Input(2)%PLATFORMPTMESH%Force + !write(*,*) 'ED%Input(3)%PLATFORMPTMESH%Force', ED%Input(3)%PLATFORMPTMESH%Force CALL ED_Input_ExtrapInterp(ED%Input, ED%InputTimes, ED%u, t_global_next, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) - + !write(*,*) 'ED%u%PLATFORMPTMESH%Force', ED%u%PLATFORMPTMESH%Force DO j = p_FAST%InterpOrder, 1, -1 CALL ED_CopyInput (ED%Input(j), ED%Input(j+1), MESH_UPDATECOPY, Errstat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) From 34d9c6824a07f03c4deccdac1468b9b8f2e91822 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 11 Jun 2020 11:58:04 -0600 Subject: [PATCH 218/377] FlexSub: adding input file option for ExtraLeverArm --- modules/subdyn/src/SubDyn.f90 | 22 +++++++++++++++++----- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 7 +++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 3481ec672..cae21757e 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -516,13 +516,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Y1(:3) = -f_TP ! MExtra = -u_TP x f_TP ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + if (p%ExtraMoment) then + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) + Y1_ExtraMoment + y%Y1Mesh%Moment(:,1) = Y1(4:6) !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE @@ -720,8 +723,17 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif IF (Check(.not.(any(idSIM_Valid==p%SttcSolve)), 'Invalid value entered for SttcSolve')) return +! ExtraMoment - For legacy, allowing this line to be a comment +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'ExtraMoment', 'Add extra lever arm contribution to interface loads', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +if (is_logical(Dummy_Str, Dummy_Bool)) then ! the parameter was present + p%ExtraMoment=Dummy_Bool + ! We still need to read the comment on the next line + CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +else ! we have a actually read a comment line, we do nothing. + p%ExtraMoment=.False. ! For Legacy, ExtraMoment is False +endif + !-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- -CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv , 'NDiv' , 'Number of divisions per member',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod , 'CBMod' , 'C-B mod flag' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 163142973..859b2d0dc 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -177,6 +177,7 @@ typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, # --- CB reduction typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 65ba513b0..a60295d4a 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -215,6 +215,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] + LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -6466,6 +6467,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve + DstParamData%ExtraMoment = SrcParamData%ExtraMoment IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN i1_l = LBOUND(SrcParamData%NOmegaM2,1) i1_u = UBOUND(SrcParamData%NOmegaM2,1) @@ -7464,6 +7466,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve + Int_BufSz = Int_BufSz + 1 ! ExtraMoment Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no IF ( ALLOCATED(InData%NOmegaM2) ) THEN Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension @@ -8053,6 +8056,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%SttcSolve Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%ExtraMoment , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9275,6 +9280,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%SttcSolve = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + OutData%ExtraMoment = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated Int_Xferred = Int_Xferred + 1 ELSE From 6a1c3be9ce5d13909fd8d1f0df0bba901ea2e311 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 12 Jun 2020 21:23:06 -0600 Subject: [PATCH 219/377] FlexSub: safety for large omega, reinit of Elems, misc summary outputs --- modules/subdyn/src/FEM.f90 | 6 +++++- modules/subdyn/src/SD_FEM.f90 | 1 + modules/subdyn/src/SubDyn.f90 | 29 +++++++++++++++-------------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index a9dc6bcf0..1a240df86 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -523,7 +523,11 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! --- Setting up Phi, and type conversion do i = 1, NOmega - Om2 = real(Omega2_LaKi(i), ReKi) + if (abs(Omega2_LaKi(i))>huge(1.0_ReKi)) then + Om2 = sign(huge(1.0_ReKi), Omega2_LaKi(i)) + else + Om2 = real(Omega2_LaKi(i), ReKi) + endif if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics Omega(i)=0.0_ReKi elseif (Om2>0) then diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index cdcdcef71..366a3f945 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -454,6 +454,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) TempProps = -9999. TempMembers = p%Elems(1:p%NMembers,:) TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB + p%Elems(:,:) = -9999. ! Reinitialized. Elements will be ordered by member subdivisions (see setNewElem) kelem = 0 knode = Init%NJoints diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index cae21757e..3343ffbfc 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2316,9 +2316,9 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L - write(*,'(A,I0)')'Number of DOFs: total retained (__B): ',p%nDOF__Rb - write(*,'(A,I0)')'Number of DOFs: total internal (__L): ',p%nDOF__L - write(*,'(A,I0)')'Number of DOFs: total fixed (__F): ',p%nDOF__F + write(*,'(A,I0)')'Number of DOFs: retained (__B): ',p%nDOF__Rb + write(*,'(A,I0)')'Number of DOFs: internal (__L): ',p%nDOF__L + write(*,'(A,I0)')'Number of DOFs: fixed (__F): ',p%nDOF__F write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C @@ -2470,10 +2470,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') #endif - call yaml_write_var(UnSum, 'nDOF__B', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total retained (__B)') - call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total internal (__L)') - call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total fixed (__F)') - call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total ') + call yaml_write_var(UnSum, 'nDOF__B ', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: retained (__B)') + call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: internal (__L)') + call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: fixed (__F)') + call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total') #ifdef SD_SUMMARY_DEBUG call yaml_write_array(UnSum, 'Nodes_I', p%Nodes_I(:,1), IFmt, ErrStat2, ErrMsg2, comment='"interface" nodes"') call yaml_write_array(UnSum, 'Nodes_C', p%Nodes_C(:,1), IFmt, ErrStat2, ErrMsg2, comment='"reaction" nodes"') @@ -2604,10 +2604,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write Eigenvalues of full SYstem and CB reduced System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') "#FEM Eigenvalues [Hz]. Number of shown eigenvalues (total # of DOFs minus restrained nodes' DOFs):", NOmega - call yaml_write_array(UnSum, 'Full_Eigenvalues', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A, I6)') "#CB Reduced Eigenvalues [Hz]. Number of retained modes' eigenvalues:", p%nDOFM - call yaml_write_array(UnSum, 'CB_Eigenvalues', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) + WRITE(UnSum, '(A, I6)') "#Eigenfrequencies for full system (no constraint) [Hz]" + call yaml_write_array(UnSum, 'Full_frequencies', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) + WRITE(UnSum, '(A, I6)') "#CB frequencies [Hz]" + call yaml_write_array(UnSum, 'CB_frequencies', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write Eigenvectors of full System @@ -2622,8 +2622,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' - call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2, comment='(CB modes)') + call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2, comment='(Guyan modes)') !------------------------------------------------------------------------------------------------------------- ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point @@ -2691,7 +2691,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! --- write TP TI matrix WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'TI', p%TI, ReFmt, ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') + call yaml_write_array(UnSum, 'TI' , p%TI, ReFmt, ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') + call yaml_write_array(UnSum, 'TIReact', p%TIReact, ReFmt, ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') #endif call CleanUp() From ce1aac8a41ac5d33d051041b04f81e350d3bbe69 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 12 Jun 2020 22:32:17 -0600 Subject: [PATCH 220/377] FlexSub: wrong kind in sign intrinsic (fix previous commit) --- modules/subdyn/src/FEM.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 1a240df86..d96fac91e 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -524,7 +524,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! --- Setting up Phi, and type conversion do i = 1, NOmega if (abs(Omega2_LaKi(i))>huge(1.0_ReKi)) then - Om2 = sign(huge(1.0_ReKi), Omega2_LaKi(i)) + Om2 = huge(1.0_ReKi) * sign(1.0_LaKi, Omega2_LaKi(i)) else Om2 = real(Omega2_LaKi(i), ReKi) endif From 94856c9e1b0fa5fbbabb5be93dc803c7115a3dd8 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 13 Jun 2020 00:42:25 -0600 Subject: [PATCH 221/377] FlexSub: starting to remove SD to Y2 mapping --- modules/subdyn/src/SubDyn.f90 | 141 ++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 58 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 3343ffbfc..65aae6912 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -46,6 +46,7 @@ Module SubDyn PUBLIC :: SD_CalcOutput ! Routine for computing outputs PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + LOGICAL, parameter :: NO_Y2_MAP = .False. CONTAINS SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) @@ -100,34 +101,43 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh INTEGER :: I, iOffset, iNode ! generic counter variable INTEGER :: nodeIndx - CALL MeshCreate( BlankMesh = inputMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = size(INodes_I) + size(INodes_L) + size(INodes_C) & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - ! --- Interface nodes - iOffset = 0 - DO I = 1,size(INodes_I) - Point = Nodes(INodes_I(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - ENDDO - ! --- Interior nodes - iOffset = size(INodes_I) - DO I = 1,size(INodes_L) - Point = Nodes(INodes_L(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - END DO - ! --- Base Reaction nodes - iOffset = size(INodes_I) + size(INodes_L) - DO I = 1,size(INodes_C) - Point = Nodes(INodes_C(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - END DO + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = size(Nodes,1) & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + if (NO_Y2_MAP) then + DO I = 1,size(Nodes,1) + Point = Nodes(I, 2:4) + CALL MeshPositionNode(inputMesh, I, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I) + ENDDO + else + ! --- Interface nodes + iOffset = 0 + DO I = 1,size(INodes_I) + Point = Nodes(INodes_I(I), 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) + ENDDO + ! --- Interior nodes + iOffset = size(INodes_I) + DO I = 1,size(INodes_L) + Point = Nodes(INodes_L(I), 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) + END DO + ! --- Base Reaction nodes + iOffset = size(INodes_I) + size(INodes_L) + DO I = 1,size(INodes_C) + Point = Nodes(INodes_C(I), 2:4) + CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) + END DO + endif CALL MeshCommit ( inputMesh, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN ! Create the Interior Points output mesh as a sibling copy of the input mesh @@ -408,7 +418,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) ! Inputs on interior nodes: - CALL ConstructUFL( u, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) !________________________________________ ! Set motion outputs on y%Y2mesh @@ -497,9 +507,11 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !Aggregate the forces and moments at the interface nodes to the reference point !TODO: where are these HydroTP, HydroForces documented? DO I = 1, p%nNodes_I + iSDNode = p%Nodes_I(I,1) + iY2Node = p%INodes_SD_to_Mesh(iSDNode) startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes !Take care of Hydrodynamic Forces that will go into INterface Forces later - HydroForces(startDOF:startDOF+5 ) = (/u%LMesh%Force(:,I),u%LMesh%Moment(:,I)/) !(6,NNODES_I) + HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) ENDDO !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below @@ -615,7 +627,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! form u(4) in Eq. 10: - CALL ConstructUFL( u, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot @@ -938,7 +950,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) nColumns = MembersCol endif DO I = 1, p%NMembers - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members', 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members line '//Num2LStr(I), 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) ENDDO IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return @@ -1581,12 +1593,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL ) ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL ConstructUFL( u_interp, p, m, UFL2 ) + CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2 ) ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2350,7 +2362,7 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE ConstructUFL( u, p, m, UFL ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red @@ -2381,7 +2393,7 @@ SUBROUTINE ConstructUFL( u, p, m, UFL ) m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL= m%Fext_red(p%ID__L) -END SUBROUTINE ConstructUFL +END SUBROUTINE GetExtForceOnInternalDOF !------------------------------------------------------------------------------------------------------ !> Output the summary file @@ -2721,33 +2733,46 @@ SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) INTEGER(IntKi) :: i INTEGER(IntKi) :: SDnode INTEGER(IntKi) :: y2Node - y2Node = 0 - ! Interface nodes (IDI) - DO I = 1,SIZE(p%Nodes_I,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_I(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Interior nodes (IDL) - DO I = 1,SIZE(p%Nodes_L,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_L(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Base Reaction nodes (IDC) - DO I = 1,SIZE(p%Nodes_C,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_C(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO + if (NO_Y2_MAP) then + DO I = 1,SIZE(SDtoMesh) + SDtoMesh( I ) = I + END DO + else + y2Node = 0 + ! Interface nodes (IDI) + DO I = 1,SIZE(p%Nodes_I,1) + y2Node = y2Node + 1 + SDnode = p%Nodes_I(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Interior nodes (IDL) + DO I = 1,SIZE(p%Nodes_L,1) + y2Node = y2Node + 1 + SDnode = p%Nodes_L(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + ! Base Reaction nodes (IDC) + DO I = 1,SIZE(p%Nodes_C,1) + y2Node = y2Node + 1 + SDnode = p%Nodes_C(I,1) + SDtoMesh( SDnode ) = y2Node ! TODO add safety check + END DO + endif END SUBROUTINE SD_Y2Mesh_Mapping !> SUBROUTINE Y2Mesh_SD_Mapping(p, MeshtoSD) TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters INTEGER(IntKi), INTENT( OUT) :: MeshtoSD(:) !< index/mapping of mesh nodes with SD mesh - MeshtoSD( 1:p%nNodes_I) = p%Nodes_I(:,1) - MeshtoSD(p%nNodes_I+ 1:p%nNodes_I+p%nNodes_L) = p%Nodes_L(:,1) - MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nNodes_C) = p%Nodes_C(:,1) + INTEGER(IntKi) :: I + if (NO_Y2_MAP) then + DO I = 1,SIZE(MeshtoSD) + MeshtoSD( I ) = I + END DO + else + MeshtoSD( 1:p%nNodes_I) = p%Nodes_I(:,1) + MeshtoSD(p%nNodes_I+ 1:p%nNodes_I+p%nNodes_L) = p%Nodes_L(:,1) + MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nNodes_C) = p%Nodes_C(:,1) + endif END SUBROUTINE Y2Mesh_SD_Mapping !------------------------------------------------------------------------------------------------------ From 1d8132ec4540b02af1f5e706bf32505e2e793e62 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 17 Jun 2020 19:04:40 -0600 Subject: [PATCH 222/377] FlexSub: Bug fix: count of internal DOF was wrong since introduction of SSI (onlya affect joints and rigid links) --- modules/subdyn/src/SD_FEM.f90 | 22 +++++---- modules/subdyn/src/SubDyn.f90 | 89 +++++++++++++++++++++++++++++------ modules/subdyn/src/Yaml.f90 | 30 ++++++++---- 3 files changed, 107 insertions(+), 34 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 366a3f945..9c6c5572e 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1059,9 +1059,10 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM !> Add soil stiffness and mass to global system matrices -SUBROUTINE InsertSoilMatrices(M, K, Init, p, ErrStat, ErrMsg, Substract) +SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) real(ReKi), dimension(:,:), intent(inout) :: M real(ReKi), dimension(:,:), intent(inout) :: K + type(IList),dimension(:), intent(in ) :: NodesDOF !< Map from Node Index to DOF lists type(SD_InitType), intent(in ) :: Init type(SD_ParameterType), intent(in ) :: p integer(IntKi), intent( out) :: ErrStat ! Error status of the operation @@ -1085,9 +1086,9 @@ SUBROUTINE InsertSoilMatrices(M, K, Init, p, ErrStat, ErrMsg, Substract) endif endif do I = 1, 6 - iDOF = p%NodesDOF(iNode)%List(I) ! DOF index + iDOF = NodesDOF(iNode)%List(I) ! DOF index do J = 1, 6 - jDOF = p%NodesDOF(iNode)%List(J) ! DOF index + jDOF = NodesDOF(iNode)%List(J) ! DOF index K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) M(iDOF, jDOF) = M(iDOF, jDOF) + M_soil(I,J) enddo @@ -1179,14 +1180,16 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call Fatal('No rigid assembly attributed to node'//trim(Num2LStr(iNode))//'. RAm1 wrong'); return endif ia = find(IRA, aID, ErrStat2, ErrMsg2); if(Failed()) return - print*,'Node',iNode, 'is involved in RA', aID, ia + print*,'Node',iNode, 'is involved in RA:', aID, '. Index in list of RA to process', ia if ( ia <= 0) then ! This rigid assembly has already been processed - ! The DOF list is taken from the stored RA DOF list - call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) + ! OLD: The DOF list is taken from the stored RA DOF list + ! call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) + ! NEW: this node has no DOFs + call init_list(p%NodesDOFtilde(iNode), 0, 0, ErrStat2, ErrMsg2) print*,'The RA',aID,', has already been processed!' print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) - print*,'N',iNode,'It',p%NodesDOFtilde(iNode)%List + print*,'N',iNode,'It',RA_DOFtilde(aID)%List cycle ! We pass to the next joint else call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; @@ -1222,8 +1225,8 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - !print*,'N',iNode,'I ',IDOFOld - !print*,'N',iNode,'It',IDOFNew + print*,'N',iNode,'I ',IDOFOld + print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc iPrev = iPrev + nc enddo @@ -1762,7 +1765,6 @@ SUBROUTINE ElemM(ep, Me) if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then Me=0.0_ReKi else - print*,'FEM: Mass matrix for rigid members rho/=0 TODO' CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) !CALL ElemM_(A, L, rho, DirCos, Me) endif diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 65aae6912..35640ad73 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -241,10 +241,10 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Assemble Stiffness and mass matrix CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - ! Insert soil stiffness and mass matrix - CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! Insert soil stiffness and mass matrix (NOTE: using NodesDOF, unreduced matrix) + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOF, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - ! --- Elimination of constraints (reset M, K, D, and BCs IntFc ) + ! --- Elimination of constraints (reset M, K, D, to lower size, and BCs IntFc ) CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! --- Additional Damping and stiffness at pin/ball/universal joints @@ -301,6 +301,8 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call AllocAry( p%INodes_SD_to_Mesh, p%nNodes, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') call Y2Mesh_SD_Mapping(p, p%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices call SD_Y2Mesh_Mapping(p, p%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices + !print*,'I_SD_to_Mesh',p%INodes_SD_to_Mesh + !print*,'I_Mesh_to_SD',p%INodes_Mesh_to_SD ! --- Write the summary file IF ( Init%SSSum ) THEN @@ -360,7 +362,18 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m ErrStat = ErrID_None ! no error has occurred ErrMsg = "" + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' + !print*,'UpdateState',t,n + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' + !print*,'------------------------------------------------------' IF ( p%nDOFM == 0) RETURN ! no retained modes = no states + !print*,'x%qm (in)',x%qm + !print*,'x%qmd (in)',x%qmdot IF (p%IntMethod .eq. 1) THEN CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) @@ -371,6 +384,8 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m ELSE CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) END IF + !print*,'x%qm (out)',x%qm + !print*,'x%qmd(out)',x%qmdot END SUBROUTINE SD_UpdateStates @@ -406,6 +421,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + logical:: LinDetected ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -417,6 +433,20 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + + !print*,'-----------------------------------------' + !print*,'CalCoutput',t + + LinDetected=.false. + DO iY2Node = 1,p%nNodes + if (any(abs(u%LMesh%Force (:,iY2Node) - 1000000)<1)) LinDetected = .true. + if (any(abs(u%LMesh%Moment (:,iY2Node) - 1000000)<1)) LinDetected = .true. + enddo + !if (.not. LinDetected) print*,'>>>> TRUE CALL' + !if ( LinDetected) print*,'>>>> LIN CALL' + + !print*,'uTP',m%u_TP + ! Inputs on interior nodes: CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) @@ -439,6 +469,11 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] END IF + !if (.not. LinDetected) print*,'UL',m%UL + + !if (t>0.010) then + ! STOP + !endif !STATIC IMPROVEMENT METHOD ( modify UL ) if (p%SttcSolve/=idSIM_None) then @@ -463,6 +498,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = m%UL - UL0M end if endif + !print*,'UL',m%UL ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar m%U_red (p%ID__L) = m%UL @@ -495,7 +531,13 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + !if (.not. LinDetected)print*,'Ufull ',iSDNode, m%U_full (DOFList(1:6)) + !if (.not. LinDetected)print*,'Ufulld ',iSDNode, m%U_full_dot (DOFList(1:6)) + !if (.not. LinDetected)print*,'Ufulldd',iSDNode, m%U_full_dotdot (DOFList(1:6)) enddo +! DO iY2Node = 1,p%nNodes +! print*,'Y2Disp',iY2Node,y%Y2mesh%TranslationDisp (:,iY2Node) +! enddo !________________________________________ ! Set loads outputs on y%Y1Mesh !________________________________________ @@ -513,6 +555,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) ENDDO + !print*,'HydroForces',HydroForces !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D @@ -528,6 +571,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Y1(:3) = -f_TP ! MExtra = -u_TP x f_TP ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs + !if (.not. LinDetected)print*,'Y1',Y1 if (p%ExtraMoment) then Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) @@ -1803,8 +1847,8 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 - ! --- Remove SSI from Mass and stiffness matrix - CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.True.); + ! --- Remove SSI from Mass and stiffness matrix (NOTE: use NodesDOFtilde, reduced matrix) + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.True.); ! --- Perform Guyan reduction to get MBB nR = p%nDOFR__ ! Using interface + reaction nodes @@ -1829,7 +1873,7 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) if(allocated(OmegaL)) deallocate(OmegaL) ! --- Insert SSI from Mass and stiffness matrix again - CALL InsertSoilMatrices(Init%M, Init%K, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return contains logical function Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2158,7 +2202,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) p%nDOFI_F = p%nDOFI_F + count(p%Nodes_I(iiNode, 2:7)==idBC_Fixed) ! assumes 6 DOFs enddo if (p%nDOFI__/=p%nDOFI_Rb+p%nDOFI_F) then - call Fatal('Error in distributing interface DOFs, total number of DOF does not equal number of leader and fixed DOF'); return + call Fatal('Error in distributing interface DOFs, total number of interface DOF('//num2lstr(p%nDOFI__)//') does not equal sum of: leader ('//num2lstr(p%nDOFI_Rb)//'), fixed ('//num2lstr(p%nDOFI_F)//')'); return endif ! DOFs of reaction nodes @@ -2173,7 +2217,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) p%nDOFC_L = p%nDOFC_L + count(p%Nodes_C(iiNode, 2:7)==idBC_Internal) ! assumes 6 DOFs enddo if (p%nDOFC__/=p%nDOFC_Rb+p%nDOFC_F+p%nDOFC_L) then - call Fatal('Error in distributing reaction DOFs, total number of DOF does not equal number of leader, fixed and internal DOF'); return + call Fatal('Error in distributing reaction DOFs, total number of reaction DOF('//num2lstr(p%nDOFC__)//') does not equal sum of: leader ('//num2lstr(p%nDOFC_Rb)//'), fixed ('//num2lstr(p%nDOFC_F)//'), internal ('//num2lstr(p%nDOFC_L)//')'); return endif ! DOFs of reaction + interface nodes p%nDOFR__ = p%nDOFI__ + p%nDOFC__ ! Total number, used to be called "nDOFR" @@ -2181,10 +2225,12 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) ! DOFs of internal nodes p%nDOFL_L=0 do iiNode= 1,p%nNodes_L + print*,'NodeL',p%Nodes_L(iiNode,1), 'DOF:',p%NodesDOFtilde( p%Nodes_L(iiNode,1) )%List p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) enddo + print*,'L_L',p%nDOFL_L,'red',p%nDOF_red,'R__',p%nDOFR__ if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then - call Fatal('Error in distributing internal DOFs, total number of DOF does not equal total number of DOF minus interface and reaction'); return + call Fatal('Error in distributing internal DOFs, total number of internal DOF('//num2lstr(p%nDOFL_L)//') does not equal total number of DOF('//num2lstr(p%nDOF_red)//') minus interface and reaction ('//num2lstr(p%nDOFR__)//')'); return endif ! Total number of DOFs in each category: @@ -2271,7 +2317,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) c_L=0; ! Counters over L dofs do iiNode= 1,p%nNodes_L !Loop on interface nodes iNode = p%Nodes_L(iiNode,1) - do J = 1, 6 ! DOFs + do J = 1, size(p%NodesDOFtilde(iNode)%List) ! DOFs c_L=c_L+1 p%IDL_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number enddo @@ -2375,6 +2421,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) ! --- Build vector of external force m%Fext= myNaN DO iMeshNode = 1,p%nNodes + !print*,'iMN',iMeshNode,u%LMesh%Force (:,iMeshNode),u%LMesh%Moment(:,iMeshNode) iSDNode = p%INodes_Mesh_to_SD(iMeshNode) nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs @@ -2384,6 +2431,12 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers enddo + !print*,'----' + !DO iSDNode = 1,p%nNodes + ! iMeshNode = p%INodes_SD_to_Mesh(iSDNode) + ! print*,'iSD',iSDNode,u%LMesh%Force (:,iMeshNode),u%LMesh%Moment(:,iMeshNode) + !enddo + ! TODO: remove test below in the future if (any(m%Fext == myNaN)) then print*,'Error in setting up Fext' @@ -2392,6 +2445,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) ! --- Reduced vector of external force m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL= m%Fext_red(p%ID__L) + !print*,'UFL',UFL END SUBROUTINE GetExtForceOnInternalDOF @@ -2473,10 +2527,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') #ifdef SD_SUMMARY_DEBUG call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') - call yaml_write_var(UnSum, 'nDOFI_B', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') + call yaml_write_var(UnSum, 'nDOFI_B ', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') call yaml_write_var(UnSum, 'nDOFC__ ', p%nDOFC__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" (C__)') - call yaml_write_var(UnSum, 'nDOFC_B', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') + call yaml_write_var(UnSum, 'nDOFC_B ', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') call yaml_write_var(UnSum, 'nDOFC_L ', p%nDOFC_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" internal (C_L)') call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') @@ -2700,13 +2754,18 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'KLL^-1' , p%KLLm1 , ReFmt, ErrStat2, ErrMsg2, comment='') endif + ! --- Reduction info + WRITE(UnSum, '(A)') SectionDivide + call yaml_write_array(UnSum, 'T_red', p%T_red, 'E9.2', ErrStat2, ErrMsg2, comment='(Constraint elimination matrix)') +#endif ! --- write TP TI matrix WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'TI' , p%TI, ReFmt, ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') - call yaml_write_array(UnSum, 'TIReact', p%TIReact, ReFmt, ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') + call yaml_write_array(UnSum, 'TI' , p%TI , 'E9.2', ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') + if (allocated(p%TIReact)) then + call yaml_write_array(UnSum, 'TIReact', p%TIReact, 'E9.2', ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') + endif -#endif call CleanUp() contains diff --git a/modules/subdyn/src/Yaml.f90 b/modules/subdyn/src/Yaml.f90 index 2be2d1bab..ec3043c23 100644 --- a/modules/subdyn/src/Yaml.f90 +++ b/modules/subdyn/src/Yaml.f90 @@ -475,10 +475,14 @@ subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) @@ -528,10 +532,14 @@ subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comm if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) @@ -578,10 +586,14 @@ subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, com if (nr==0) then write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif endif do i=1,nr write(fid, Fmt, iostat=ErrStat) A(i,:) From 514978f740fa5b4ff06158439fe956683d4afa31 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 17 Jun 2020 20:14:13 -0600 Subject: [PATCH 223/377] FlexSub: removing some print statements --- modules/subdyn/src/SD_FEM.f90 | 75 +++++++++++++++------- modules/subdyn/src/SubDyn.f90 | 113 ++++++++-------------------------- 2 files changed, 80 insertions(+), 108 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 9c6c5572e..58a46f9d4 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -73,6 +73,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) + LOGICAL, PARAMETER :: DEV_VERSION = .false. INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi @@ -170,7 +171,9 @@ TYPE(IList) FUNCTION NodesList(p, Elements) ! Sorting required by find function call sort(NodesList, ErrStat2, ErrMsg2) enddo - call print_list(NodesList, 'Joint list') + if (DEV_VERSION) then + call print_list(NodesList, 'Joint list') + endif END FUNCTION NodesList !------------------------------------------------------------------------------------------------------ !> Returns list of rigid link elements (Er) @@ -193,7 +196,9 @@ TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) call append(RigidLinkElements, ie, ErrStat, ErrMsg); endif end do - call print_list(RigidLinkElements,'Rigid element list') + if (DEV_VERSION) then + call print_list(RigidLinkElements,'Rigid element list') + endif END FUNCTION RigidLinkElements !------------------------------------------------------------------------------------------------------ @@ -757,14 +762,18 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%Rho = rho else if (eType==idMemberCable) then - print*,'Member',I,'eType',eType,'Ps',P1,P2 + if (DEV_VERSION) then + print*,'Member',I,'is a cable' + endif p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] else if (eType==idMemberRigid) then - print*,'Member',I,'eType',eType,'Ps',P1,P2 + if (DEV_VERSION) then + print*,'Member',I,'is a rigid link' + endif p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 p%ElemProps(i)%Rho = Init%PropsR(P1, 2) @@ -963,7 +972,9 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) ! total unconstrained degrees of freedom of the system p%nDOF = nDOF_Unconstrained() - print*,'nDOF_unconstrained:',p%nDOF, ' (if all Cantilever, it would be: ',6*p%nNodes,')' + if (DEV_VERSION) then + print*,'nDOF_unconstrained:',p%nDOF, ' (if all Cantilever, it would be: ',6*p%nNodes,')' + endif CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix @@ -1156,12 +1167,16 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) allocate(RA_DOFtilde(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system p%nDOF_red = nDOF_ConstraintReduced() - print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF + if (DEV_VERSION) then + print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF + endif CALL AllocAry( Tred, p%nDOF, p%nDOF_red, 'p%T_red', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix Tred=0 call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) - call print_list(IRA, 'List of RA indices') + if (DEV_VERSION) then + call print_list(IRA, 'List of RA indices') + endif ! --- For each node: ! - create list of indices I in the assembled vector of DOF @@ -1180,16 +1195,20 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call Fatal('No rigid assembly attributed to node'//trim(Num2LStr(iNode))//'. RAm1 wrong'); return endif ia = find(IRA, aID, ErrStat2, ErrMsg2); if(Failed()) return - print*,'Node',iNode, 'is involved in RA:', aID, '. Index in list of RA to process', ia + if (DEV_VERSION) then + print*,'Node',iNode, 'is involved in RA:', aID, '. Index in list of RA to process', ia + endif if ( ia <= 0) then ! This rigid assembly has already been processed ! OLD: The DOF list is taken from the stored RA DOF list ! call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) ! NEW: this node has no DOFs call init_list(p%NodesDOFtilde(iNode), 0, 0, ErrStat2, ErrMsg2) - print*,'The RA',aID,', has already been processed!' - print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) - print*,'N',iNode,'It',RA_DOFtilde(aID)%List + if (DEV_VERSION) then + print*,'The RA',aID,', has already been processed!' + print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) + print*,'N',iNode,'It',RA_DOFtilde(aID)%List + endif cycle ! We pass to the next joint else call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; @@ -1225,8 +1244,8 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - print*,'N',iNode,'I ',IDOFOld - print*,'N',iNode,'It',IDOFNew + !print*,'N',iNode,'I ',IDOFOld + !print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc iPrev = iPrev + nc enddo @@ -1289,7 +1308,7 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() elseif(NodeType == idJointCantilever ) then if ( NodeHasRigidElem(iNode, Init, p, er)) then ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - print*,'Node',iNode, 'is involved in a RA' + print*,'Node',iNode, 'is involved in a Rigid assembly' else ! That's a regular Cantilever joint nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 @@ -1438,9 +1457,13 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) ! --- List of nodes stored first in LINodes than moved to INodes LNodesID = NodesList(p, Elements) - print*,'Nodes involved in assembly (bfr1) ',LNodesID%List + if (DEV_VERSION) then + print*,'Nodes involved in assembly (bfr1) ',LNodesID%List + endif call unique(LNodesID, ErrStat2, ErrMsg2); - print*,'Nodes involved in assembly (bfr2) ',LNodesID%List + if (DEV_VERSION) then + print*,'Nodes involved in assembly (bfr2) ',LNodesID%List + endif !--- Look for potential interface node call init_list(LNodesInterf, 0, 0, ErrStat2, ErrMsg2); @@ -1477,7 +1500,9 @@ SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) iTmp = INodesID(1) INodesID(1) = INodesID(iiMainNode) INodesID(iiMainNode) = iTmp - print*,'Nodes involved in assembly (after)',INodesID + if (DEV_VERSION) then + print*,'Nodes involved in assembly (after)',INodesID + endif ! --- Building Transformation matrix nNodes =size(INodesID) @@ -1637,7 +1662,9 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) e0 = pop(Er, ErrStat2, ErrMsg2); call append(Ea, e0, ErrStat2, ErrMsg2); call AddNeighbors(e0, Er, Ea) - call print_list(Ea,'Rigid assembly (loop 1)') + if (DEV_VERSION) then + call print_list(Ea,'Rigid assembly (loop 1)') + endif do ie = 1, len(Ea) e0 = get(Ea, ie, ErrStat2, ErrMsg2) RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to @@ -1658,9 +1685,11 @@ SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) call append(RA(ia), ie, ErrStat2, ErrMsg2) endif enddo - do ia = 1, nRA - call print_list(RA(ia),'Rigid assembly (loop 2)') - enddo + if (DEV_VERSION) then + do ia = 1, nRA + call print_list(RA(ia),'Rigid assembly (loop 2)') + enddo + endif CONTAINS !> The neighbor-elements of element e0 (that are found within the list Er) are added to the list Ea RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) @@ -1678,7 +1707,9 @@ RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) ik=ik+1 ek = Er%List(ik) if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then - print*,'Element ',ek,'is connected to element',e0,'via its node',iWhichNode_ek + if (DEV_VERSION) then + print*,'Element ',ek,'is connected to element',e0,'via its node',iWhichNode_ek + endif ! Remove element from Er (a rigid element can belong to only one assembly) ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before ik=ik-1 diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 35640ad73..743d7e798 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -201,7 +201,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO InitOut%Ver = SD_ProgDesc ! --- Test TODO remove me in the future - CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return + if (DEV_VERSION) then + CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return + endif ! transfer glue-code information to data structure for SubDyn initialization: Init%g = InitInput%g @@ -362,18 +364,7 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m ErrStat = ErrID_None ! no error has occurred ErrMsg = "" - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' - !print*,'UpdateState',t,n - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' - !print*,'------------------------------------------------------' IF ( p%nDOFM == 0) RETURN ! no retained modes = no states - !print*,'x%qm (in)',x%qm - !print*,'x%qmd (in)',x%qmdot IF (p%IntMethod .eq. 1) THEN CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) @@ -384,8 +375,6 @@ SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m ELSE CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) END IF - !print*,'x%qm (out)',x%qm - !print*,'x%qmd(out)',x%qmdot END SUBROUTINE SD_UpdateStates @@ -421,7 +410,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None - logical:: LinDetected ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" @@ -434,19 +422,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - !print*,'-----------------------------------------' - !print*,'CalCoutput',t - - LinDetected=.false. - DO iY2Node = 1,p%nNodes - if (any(abs(u%LMesh%Force (:,iY2Node) - 1000000)<1)) LinDetected = .true. - if (any(abs(u%LMesh%Moment (:,iY2Node) - 1000000)<1)) LinDetected = .true. - enddo - !if (.not. LinDetected) print*,'>>>> TRUE CALL' - !if ( LinDetected) print*,'>>>> LIN CALL' - - !print*,'uTP',m%u_TP - ! Inputs on interior nodes: CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) @@ -469,11 +444,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] END IF - !if (.not. LinDetected) print*,'UL',m%UL - - !if (t>0.010) then - ! STOP - !endif !STATIC IMPROVEMENT METHOD ( modify UL ) if (p%SttcSolve/=idSIM_None) then @@ -498,7 +468,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = m%UL - UL0M end if endif - !print*,'UL',m%UL ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar m%U_red (p%ID__L) = m%UL @@ -531,13 +500,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) - !if (.not. LinDetected)print*,'Ufull ',iSDNode, m%U_full (DOFList(1:6)) - !if (.not. LinDetected)print*,'Ufulld ',iSDNode, m%U_full_dot (DOFList(1:6)) - !if (.not. LinDetected)print*,'Ufulldd',iSDNode, m%U_full_dotdot (DOFList(1:6)) enddo -! DO iY2Node = 1,p%nNodes -! print*,'Y2Disp',iY2Node,y%Y2mesh%TranslationDisp (:,iY2Node) -! enddo !________________________________________ ! Set loads outputs on y%Y1Mesh !________________________________________ @@ -555,7 +518,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) ENDDO - !print*,'HydroForces',HydroForces !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D @@ -571,7 +533,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Y1(:3) = -f_TP ! MExtra = -u_TP x f_TP ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs - !if (.not. LinDetected)print*,'Y1',Y1 if (p%ExtraMoment) then Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) @@ -2225,10 +2186,8 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) ! DOFs of internal nodes p%nDOFL_L=0 do iiNode= 1,p%nNodes_L - print*,'NodeL',p%Nodes_L(iiNode,1), 'DOF:',p%NodesDOFtilde( p%Nodes_L(iiNode,1) )%List p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) enddo - print*,'L_L',p%nDOFL_L,'red',p%nDOF_red,'R__',p%nDOFR__ if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then call Fatal('Error in distributing internal DOFs, total number of internal DOF('//num2lstr(p%nDOFL_L)//') does not equal total number of DOF('//num2lstr(p%nDOF_red)//') minus interface and reaction ('//num2lstr(p%nDOFR__)//')'); return endif @@ -2350,38 +2309,25 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) endif enddo - !print*,'DOFI__ ',p%IDI__ - !print*,'DOFI_Rb ',p%IDI_Rb - !print*,'DOFI_F ',p%IDI_F - !print*,'DOFC__ ',p%IDC__ - !print*,'DOFC_Rb ',p%IDC_Rb - !print*,'DOFC_F ',p%IDC_F - !print*,'DOFC_L ',p%IDC_L - !print*,'DOFR__ ',p%IDR__ - !print*,'DOFL_L ',p%IDL_L - !print*,'DOF__Rb ',p%ID__Rb - !print*,'DOF__F ',p%ID__F - !print*,'DOF__L ',p%ID__L - !print*,'Nodes_C',p%Nodes_C(:,1) - !print*,'Nodes_L',p%Nodes_L(:,1) - !print*,'Nodes_I',p%Nodes_I(:,1) - write(*,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ - write(*,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb - write(*,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F - write(*,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ - write(*,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb - write(*,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L - write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F - write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ - write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L - write(*,'(A,I0)')'Number of DOFs: retained (__B): ',p%nDOF__Rb - write(*,'(A,I0)')'Number of DOFs: internal (__L): ',p%nDOF__L - write(*,'(A,I0)')'Number of DOFs: fixed (__F): ',p%nDOF__F - write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red - write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I - write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C - write(*,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L - write(*,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes + if(DEV_VERSION) then + write(*,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ + write(*,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb + write(*,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F + write(*,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ + write(*,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb + write(*,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L + write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F + write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ + write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L + write(*,'(A,I0)')'Number of DOFs: retained (__B): ',p%nDOF__Rb + write(*,'(A,I0)')'Number of DOFs: internal (__L): ',p%nDOF__L + write(*,'(A,I0)')'Number of DOFs: fixed (__F): ',p%nDOF__F + write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red + write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I + write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C + write(*,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L + write(*,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes + endif call CleanUp() @@ -2421,7 +2367,6 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) ! --- Build vector of external force m%Fext= myNaN DO iMeshNode = 1,p%nNodes - !print*,'iMN',iMeshNode,u%LMesh%Force (:,iMeshNode),u%LMesh%Moment(:,iMeshNode) iSDNode = p%INodes_Mesh_to_SD(iMeshNode) nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs @@ -2431,21 +2376,17 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers enddo - !print*,'----' - !DO iSDNode = 1,p%nNodes - ! iMeshNode = p%INodes_SD_to_Mesh(iSDNode) - ! print*,'iSD',iSDNode,u%LMesh%Force (:,iMeshNode),u%LMesh%Moment(:,iMeshNode) - !enddo ! TODO: remove test below in the future - if (any(m%Fext == myNaN)) then - print*,'Error in setting up Fext' - STOP + if (DEV_VERSION) then + if (any(m%Fext == myNaN)) then + print*,'Error in setting up Fext' + STOP + endif endif ! --- Reduced vector of external force m%Fext_red = matmul(transpose(p%T_red), m%Fext) UFL= m%Fext_red(p%ID__L) - !print*,'UFL',UFL END SUBROUTINE GetExtForceOnInternalDOF From 4f64b4dd7394298f1b78a771ccd732eb309f10e4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 17 Jun 2020 20:27:15 -0600 Subject: [PATCH 224/377] FlexSub: input/output meshes now same as subdyn mesh --- modules/subdyn/src/SubDyn.f90 | 124 +++---------------------- modules/subdyn/src/SubDyn_Output.f90 | 8 +- modules/subdyn/src/SubDyn_Registry.txt | 2 - modules/subdyn/src/SubDyn_Types.f90 | 114 ----------------------- 4 files changed, 18 insertions(+), 230 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 743d7e798..92f4366ab 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -46,7 +46,6 @@ Module SubDyn PUBLIC :: SD_CalcOutput ! Routine for computing outputs PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states - LOGICAL, parameter :: NO_Y2_MAP = .False. CONTAINS SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) @@ -85,13 +84,10 @@ SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) END SUBROUTINE CreateTPMeshes !--------------------------------------------------------------------------- !> Create output (Y2, for motion) and input (u, for forces)meshes, based on SubDyn nodes -!! Ordering of nodes is: I (interface), L (internal), C (bottom) -SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh, outputMesh, ErrStat, ErrMsg ) +!! Ordering of nodes is the same as SubDyn (used to be : I L C) +SUBROUTINE CreateInputOutputMeshes( NNode, Nodes, inputMesh, outputMesh, ErrStat, ErrMsg ) INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) - INTEGER(IntKi), INTENT( IN ) :: INodes_I(:) !< Indices of interface nodes - INTEGER(IntKi), INTENT( IN ) :: INodes_L(:) !< Indices of interior nodes - INTEGER(IntKi), INTENT( IN ) :: INodes_C(:) !< Indices of reaction nodes TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%LMesh TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y2Mesh INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation @@ -109,35 +105,11 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh ,Force = .TRUE. & ,Moment = .TRUE. ) - if (NO_Y2_MAP) then - DO I = 1,size(Nodes,1) - Point = Nodes(I, 2:4) - CALL MeshPositionNode(inputMesh, I, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I) - ENDDO - else - ! --- Interface nodes - iOffset = 0 - DO I = 1,size(INodes_I) - Point = Nodes(INodes_I(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - ENDDO - ! --- Interior nodes - iOffset = size(INodes_I) - DO I = 1,size(INodes_L) - Point = Nodes(INodes_L(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - END DO - ! --- Base Reaction nodes - iOffset = size(INodes_I) + size(INodes_L) - DO I = 1,size(INodes_C) - Point = Nodes(INodes_C(I), 2:4) - CALL MeshPositionNode(inputMesh, I+iOffSet, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I+iOffset) - END DO - endif + DO I = 1,size(Nodes,1) + Point = Nodes(I, 2:4) + CALL MeshPositionNode(inputMesh, I, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I) + ENDDO CALL MeshCommit ( inputMesh, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN ! Create the Interior Points output mesh as a sibling copy of the input mesh @@ -158,7 +130,7 @@ SUBROUTINE CreateY2Meshes( NNode, Nodes, INodes_I, INodes_L, INodes_C, inputMesh !Identity should mean no rotation, which is our first guess at the output -RRD CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) -END SUBROUTINE CreateY2Meshes +END SUBROUTINE CreateInputOutputMeshes !--------------------------------------------------------------------------- !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -297,14 +269,8 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Create the input and output meshes associated with Transition Piece reference point CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - ! Construct the input mesh for the interior nodes which result from the Craig-Bampton reduction - CALL CreateY2Meshes( p%nNodes, Init%Nodes, p%Nodes_I(:,1), p%Nodes_L(:,1), p%Nodes_C(:,1), u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry( p%INodes_Mesh_to_SD, p%nNodes, 'INodes_Mesh_to_SD', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - call AllocAry( p%INodes_SD_to_Mesh, p%nNodes, 'INodes_SD_to_Mesh', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - call Y2Mesh_SD_Mapping(p, p%INodes_Mesh_to_SD) ! Store mapping from y2/u mesh to Subdyn nodes indices - call SD_Y2Mesh_Mapping(p, p%INodes_SD_to_Mesh) ! Store mapping from Subdyn to y2/u-mesh nodes indices - !print*,'I_SD_to_Mesh',p%INodes_SD_to_Mesh - !print*,'I_Mesh_to_SD',p%INodes_Mesh_to_SD + ! Construct the input mesh (u%LMesh, force on nodes) and output mesh (y%Y2Mesh, displacements) + CALL CreateInputOutputMeshes( p%nNodes, Init%Nodes, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return ! --- Write the summary file IF ( Init%SSSum ) THEN @@ -488,7 +454,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Place displacement/velocity/acceleration into Y2 output mesh DO iSDNode = 1,p%nNodes - iY2Node = p%INodes_SD_to_Mesh(iSDNode) + iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles @@ -513,7 +479,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !TODO: where are these HydroTP, HydroForces documented? DO I = 1, p%nNodes_I iSDNode = p%Nodes_I(I,1) - iY2Node = p%INodes_SD_to_Mesh(iSDNode) + iY2Node = iSDNode startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes !Take care of Hydrodynamic Forces that will go into INterface Forces later HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) @@ -2367,7 +2333,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) ! --- Build vector of external force m%Fext= myNaN DO iMeshNode = 1,p%nNodes - iSDNode = p%INodes_Mesh_to_SD(iMeshNode) + iSDNode = iMeshNode nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList ! Force - All nodes have only 3 translational DOFs m%Fext( p%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) @@ -2505,15 +2471,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) ! Nodes properties - CALL AllocAry( DummyArray, size(Init%Nodes,1), JointsCol+1, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return - do i = 1, p%nNodes - DummyArray(i,1) = Init%Nodes(i, 1) - DummyArray(i,2) = p%INodes_SD_to_Mesh(i) - DummyArray(i,3:JointsCol+1) = Init%Nodes(i, 2:JointsCol) - enddo - write(UnSum, '("#",4x,2(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'Y2Node', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' - call yaml_write_array(UnSum, 'Nodes', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='2(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) - deallocate(DummyArray) + write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' + call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) ! Element properties CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -2722,59 +2681,6 @@ SUBROUTINE CleanUp() END SUBROUTINE CleanUp END SUBROUTINE OutSummary -!------------------------------------------------------------------------------------------------------ -!> Set the index array that maps SD internal nodes to the Y2Mesh nodes. -!! NOTE: SDtoMesh is not checked for size, nor are the index array values checked for validity, -!! so this routine could easily have segmentation faults if any errors exist. -SUBROUTINE SD_Y2Mesh_Mapping(p, SDtoMesh) - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT( OUT) :: SDtoMesh(:) !< index/mapping of mesh nodes with SD mesh - ! locals - INTEGER(IntKi) :: i - INTEGER(IntKi) :: SDnode - INTEGER(IntKi) :: y2Node - if (NO_Y2_MAP) then - DO I = 1,SIZE(SDtoMesh) - SDtoMesh( I ) = I - END DO - else - y2Node = 0 - ! Interface nodes (IDI) - DO I = 1,SIZE(p%Nodes_I,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_I(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Interior nodes (IDL) - DO I = 1,SIZE(p%Nodes_L,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_L(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - ! Base Reaction nodes (IDC) - DO I = 1,SIZE(p%Nodes_C,1) - y2Node = y2Node + 1 - SDnode = p%Nodes_C(I,1) - SDtoMesh( SDnode ) = y2Node ! TODO add safety check - END DO - endif -END SUBROUTINE SD_Y2Mesh_Mapping -!> -SUBROUTINE Y2Mesh_SD_Mapping(p, MeshtoSD) - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - INTEGER(IntKi), INTENT( OUT) :: MeshtoSD(:) !< index/mapping of mesh nodes with SD mesh - INTEGER(IntKi) :: I - if (NO_Y2_MAP) then - DO I = 1,SIZE(MeshtoSD) - MeshtoSD( I ) = I - END DO - else - MeshtoSD( 1:p%nNodes_I) = p%Nodes_I(:,1) - MeshtoSD(p%nNodes_I+ 1:p%nNodes_I+p%nNodes_L) = p%Nodes_L(:,1) - MeshtoSD(p%nNodes_I+p%nNodes_L+1:p%nNodes_I+p%nNodes_L+p%nNodes_C) = p%Nodes_C(:,1) - endif -END SUBROUTINE Y2Mesh_SD_Mapping - !------------------------------------------------------------------------------------------------------ !> Calculate length of a member as given in input file !! Joints and Members ID have not been reindexed (Elems and Nodes have) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 41dd02fd7..2c68d3b49 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -395,11 +395,9 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ENDDO ENDDO ! FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise - !NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES - ! The joind iD of the reaction, i.e. thre reaction node ID is within p%MOutLst3(I)%Noutcnt - !Since constrained nodes are ordered as given in the input file and so as in the order of y2mesh, i Can do: - iSDNode = p%Nodes_C(I,1) - iMeshNode = p%INodes_SD_to_Mesh(iSDNode) + ! NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES + iSDNode = p%Nodes_C(I,1) + iMeshNode = iSDNode ! input and Y2 mesh nodes are the same as subdyn Fext = (/ u%LMesh%Force(:,iMeshNode), u%LMesh%Moment(:,iMeshNode) /) ReactNs((I-1)*6+1:6*I) = FK_elm2 - Fext !Accumulate reactions from all nodes in GLOBAL COORDINATES ENDDO diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 859b2d0dc..12cde65d3 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -170,8 +170,6 @@ typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properti typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" -typedef ^ ^ IntKi INodes_Mesh_to_SD {:} - - "Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) " "-" -typedef ^ ^ IntKi INodes_SD_to_Mesh {:} - - "Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" # --- CB reduction diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a60295d4a..c87d586df 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -209,8 +209,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_Mesh_to_SD !< Nodes indices from Y2/U-mesh to subdyn iSDNode = INodes_Mesh_to_SD(iMeshNode) [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: INodes_SD_to_Mesh !< Nodes indices from subdyn nodes to U/Y2-Mesh iMeshNode = INodes_SD_to_Mesh(iSDNode) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] @@ -6413,30 +6411,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF -IF (ALLOCATED(SrcParamData%INodes_Mesh_to_SD)) THEN - i1_l = LBOUND(SrcParamData%INodes_Mesh_to_SD,1) - i1_u = UBOUND(SrcParamData%INodes_Mesh_to_SD,1) - IF (.NOT. ALLOCATED(DstParamData%INodes_Mesh_to_SD)) THEN - ALLOCATE(DstParamData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%INodes_Mesh_to_SD = SrcParamData%INodes_Mesh_to_SD -ENDIF -IF (ALLOCATED(SrcParamData%INodes_SD_to_Mesh)) THEN - i1_l = LBOUND(SrcParamData%INodes_SD_to_Mesh,1) - i1_u = UBOUND(SrcParamData%INodes_SD_to_Mesh,1) - IF (.NOT. ALLOCATED(DstParamData%INodes_SD_to_Mesh)) THEN - ALLOCATE(DstParamData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%INodes_SD_to_Mesh = SrcParamData%INodes_SD_to_Mesh -ENDIF IF (ALLOCATED(SrcParamData%ElemsDOF)) THEN i1_l = LBOUND(SrcParamData%ElemsDOF,1) i1_u = UBOUND(SrcParamData%ElemsDOF,1) @@ -7157,12 +7131,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%NodesDOFtilde) ENDIF -IF (ALLOCATED(ParamData%INodes_Mesh_to_SD)) THEN - DEALLOCATE(ParamData%INodes_Mesh_to_SD) -ENDIF -IF (ALLOCATED(ParamData%INodes_SD_to_Mesh)) THEN - DEALLOCATE(ParamData%INodes_SD_to_Mesh) -ENDIF IF (ALLOCATED(ParamData%ElemsDOF)) THEN DEALLOCATE(ParamData%ElemsDOF) ENDIF @@ -7444,16 +7412,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! INodes_Mesh_to_SD allocated yes/no - IF ( ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! INodes_Mesh_to_SD upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%INodes_Mesh_to_SD) ! INodes_Mesh_to_SD - END IF - Int_BufSz = Int_BufSz + 1 ! INodes_SD_to_Mesh allocated yes/no - IF ( ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! INodes_SD_to_Mesh upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%INodes_SD_to_Mesh) ! INodes_SD_to_Mesh - END IF Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no IF ( ALLOCATED(InData%ElemsDOF) ) THEN Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension @@ -7994,32 +7952,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%INodes_Mesh_to_SD) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_Mesh_to_SD,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_Mesh_to_SD,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%INodes_Mesh_to_SD)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_Mesh_to_SD))-1 ) = PACK(InData%INodes_Mesh_to_SD,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%INodes_Mesh_to_SD) - END IF - IF ( .NOT. ALLOCATED(InData%INodes_SD_to_Mesh) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%INodes_SD_to_Mesh,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%INodes_SD_to_Mesh,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%INodes_SD_to_Mesh)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%INodes_SD_to_Mesh))-1 ) = PACK(InData%INodes_SD_to_Mesh,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%INodes_SD_to_Mesh) - END IF IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9178,52 +9110,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_Mesh_to_SD not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%INodes_Mesh_to_SD)) DEALLOCATE(OutData%INodes_Mesh_to_SD) - ALLOCATE(OutData%INodes_Mesh_to_SD(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_Mesh_to_SD.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%INodes_Mesh_to_SD)>0) OutData%INodes_Mesh_to_SD = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_Mesh_to_SD))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%INodes_Mesh_to_SD) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! INodes_SD_to_Mesh not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%INodes_SD_to_Mesh)) DEALLOCATE(OutData%INodes_SD_to_Mesh) - ALLOCATE(OutData%INodes_SD_to_Mesh(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%INodes_SD_to_Mesh.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%INodes_SD_to_Mesh)>0) OutData%INodes_SD_to_Mesh = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%INodes_SD_to_Mesh))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%INodes_SD_to_Mesh) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE From 7ac811be4b99e928303420235f1e3b8d795a0d67 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 19 Jun 2020 08:24:21 -0600 Subject: [PATCH 225/377] Altered storage/bookeeping of Member loads + bug fixes Member-level loads are stored in miscvars at the member level for output channel reporting. Fix bugs for marine growth weight calcs. Fixed bug in side-effects Hydrodynamic inertia load equation. Fixed bugs with location of the ballasted end-effect equations [z2 location, overfill check]. Fixed sign errors in the DistributeElementLoads() routine. --- modules/hydrodyn/src/HydroDyn_Input.f90 | 21 +- modules/hydrodyn/src/Morison.f90 | 451 ++++++++++++++---------- modules/hydrodyn/src/Morison.txt | 41 ++- modules/hydrodyn/src/Morison_Output.f90 | 78 ++-- 4 files changed, 368 insertions(+), 223 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 94444fa73..5d0095299 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -2063,20 +2063,31 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) END IF - ALLOCATE ( InitInp%Morison%MOutLst(I)%Marker1(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + ALLOCATE ( InitInp%Morison%MOutLst(I)%MeshIndx1(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating space for Marker1 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for %MeshIndx1 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL CleanUp() RETURN END IF + ALLOCATE ( InitInp%Morison%MOutLst(I)%MemberIndx1(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for %MemberIndx1 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF - - ALLOCATE ( InitInp%Morison%MOutLst(I)%Marker2(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + ALLOCATE ( InitInp%Morison%MOutLst(I)%MeshIndx2(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error allocating space for Marker2 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for %MeshIndx2 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) CALL CleanUp() RETURN END IF + ALLOCATE ( InitInp%Morison%MOutLst(I)%MemberIndx2(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + CALL SetErrStat( ErrID_Fatal, 'Error allocating space for %MemberIndx2 array.', ErrStat, ErrMsg, 'HydroDynInput_GetInput' ) + CALL CleanUp() + RETURN + END IF ALLOCATE ( InitInp%Morison%MOutLst(I)%s(InitInp%Morison%MOutLst(I)%NOutLoc), STAT = ErrStat2 ) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index e251294be..0951860a7 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -346,63 +346,6 @@ FUNCTION InterpWrappedStpLogical( XValIn, XAry, YAry, Ind, AryLen ) RETURN END FUNCTION InterpWrappedStpLogical ! ( XVal, XAry, YAry, Ind, AryLen ) -SUBROUTINE LumpDragConst( densWater, Cd, R, tMG, DragConst ) - - ! This is used to minimize the computations which occur at each timestep - - REAL(ReKi), INTENT ( IN ) :: Cd - REAL(ReKi), INTENT ( IN ) :: densWater - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - REAL(ReKi), INTENT ( OUT ) :: DragConst - - DragConst = 0.5*Cd*densWater*(R+tMG)*(R+tMG) - -END SUBROUTINE LumpDragConst - - -SUBROUTINE LumpDynPressure( nodeIndx, Cp, k, R, tMG, NStepWave, WaveDynP, F_DP, errStat, errMsg ) - - - INTEGER, INTENT ( IN ) :: nodeIndx - REAL(ReKi), INTENT ( IN ) :: Cp - REAL(ReKi), INTENT ( IN ) :: k(3) - REAL(ReKi), INTENT ( IN ) :: R - REAL(ReKi), INTENT ( IN ) :: tMG - INTEGER, INTENT ( IN ) :: NStepWave - REAL(SiKi), INTENT ( IN ) :: WaveDynP(0:,:) - REAL(ReKi),ALLOCATABLE, INTENT ( OUT ) :: F_DP(:,:) - INTEGER, INTENT ( OUT ) :: errStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT ( OUT ) :: errMsg ! Error message if errStat /= ErrID_None - - INTEGER :: I - - ! Initialize errStat - - errStat = ErrID_None - errMsg = "" - - - ! Allocate F_DP - - ALLOCATE ( F_DP(0:NStepWave,6), STAT = errStat ) - IF ( errStat /= ErrID_None ) THEN - errMsg = ' Error allocating distributed dynamic pressure loads array.' - errStat = ErrID_Fatal - RETURN - END IF - - DO I=0,NStepWave - F_DP(I,1) = Cp*k(1)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) - F_DP(I,2) = Cp*k(2)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) - F_DP(I,3) = Cp*k(3)*Pi*(R+tMG)*(R+tMG)*WaveDynP(I,nodeIndx) - F_DP(I,4) = 0.0 - F_DP(I,5) = 0.0 - F_DP(I,6) = 0.0 - END DO - - -END SUBROUTINE LumpDynPressure subroutine GetOrientationAngles(p1, p2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat, errMsg) real(ReKi), intent(in ) :: p1(3),p2(3) real(ReKi), intent( out) :: phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat(3) @@ -531,11 +474,11 @@ SUBROUTINE MarineGrowthPartSegment(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, call TaperCalc(Rmg1, Rmg2, L, Vouter, cVouter) ! get mass and CV specific to marine growth thickness - m_mg = (cVouter - cVinner)*rho + m_mg = (Vouter - Vinner)*rho if ( EqualRealNos(m_mg, 0.0_ReKi) ) then h_c = 0.0 else - h_c = (cVouter*cVouter - Vinner*cVinner)/(Vouter - Vinner) + h_c = (cVouter*Vouter - Vinner*cVinner)/(Vouter - Vinner) end if ! get two moments of inertia for marine growth as if solid... @@ -631,7 +574,7 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no logical :: fillFlag type(Morison_MemberType) :: mem REAL(ReKi) :: Cd1, Cd2, Ca1, Ca2, Cp1, Cp2, AxCd1, AxCd2, AxCa1, AxCa2, AxCp1, AxCp2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 ! tmp coefs - + real(ReKi) :: F_B(6, numNodes), F_BF(6, numNodes), F_WMG(6, numNodes) ! Initialize data errStat = ErrID_None errMsg = "" @@ -643,6 +586,9 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no totalFillVol = 0.0 totalMGMass = 0.0 COB = 0.0 + F_B = 0.0 + F_BF = 0.0 + F_WMG = 0.0 ! Create identity matrix CALL EYE(ident,errStat,errMsg) @@ -663,7 +609,11 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no totalMGMass = totalMGMass + mem%m_mg_l(i) totalMGMass = totalMGMass + mem%m_mg_u(i) end do - + do i = 1, mem%NElements+1 + F_B (:,mem%NodeIndx(i)) = F_B (:,mem%NodeIndx(i)) + m%memberLoads(j)%F_B (:,i) + F_BF (:,mem%NodeIndx(i)) = F_BF (:,mem%NodeIndx(i)) + m%memberLoads(j)%F_BF (:,i) + F_WMG(:,mem%NodeIndx(i)) = F_WMG(:,mem%NodeIndx(i)) + m%memberLoads(j)%F_WMG(:,i) + end do end do @@ -739,9 +689,9 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no if ( yMesh%Position(3,J) <= 0.0 ) then if (J <= numJoints) then - ptLoad = m%F_B(:,J) + m%F_B_end(:,J) + ptLoad = F_B(:,J) + m%F_B_end(:,J) else - ptLoad = m%F_B(:,J) + ptLoad = F_B(:,J) end if yMesh%Force(:,J) = ptLoad(1:3) yMesh%Moment(:,J) = ptLoad(4:6) @@ -777,9 +727,9 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no DO J = 1, yMesh%Nnodes if (J <= numJoints) then - ptLoad = m%F_BF(:,J) + m%F_BF_end(:,J) + ptLoad = F_BF(:,J) + m%F_BF_end(:,J) else - ptLoad = m%F_BF(:,J) + ptLoad = F_BF(:,J) end if yMesh%Force(:,J) = ptLoad(1:3) yMesh%Moment(:,J) = ptLoad(4:6) @@ -805,12 +755,12 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no DO J = 1, yMesh%Nnodes if (J <= numJoints) then - yMesh%Force(:,J) = m%F_WMG(1:3,J) + p%F_WMG_End(:,J) + yMesh%Force(:,J) = F_WMG(1:3,J) + p%F_WMG_End(:,J) else - yMesh%Force(:,J) = m%F_WMG(1:3,J) + yMesh%Force(:,J) = F_WMG(1:3,J) end if - yMesh%Moment(:,J) = m%F_WMG(4:6,J) + yMesh%Moment(:,J) = F_WMG(4:6,J) END DO ! DO J @@ -1288,8 +1238,9 @@ END SUBROUTINE SetNodeMG -subroutine AllocateMemberDataArrays( member, errStat, errMsg ) +subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) type(Morison_MemberType), intent (inout) :: member + type(Morison_MemberLoads), intent (inout) :: memberLoads integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None @@ -1336,6 +1287,14 @@ subroutine AllocateMemberDataArrays( member, errStat, errMsg ) call AllocAry(member%AxCd , member%NElements+1, 'member%AxCd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%AxCa , member%NElements+1, 'member%AxCa ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%AxCp , member%NElements+1, 'member%AxCp ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_D , 6, member%NElements+1, 'memberLoads%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_A , 6, member%NElements+1, 'memberLoads%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_B , 6, member%NElements+1, 'memberLoads%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_BF , 6, member%NElements+1, 'memberLoads%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_I , 6, member%NElements+1, 'memberLoads%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_If , 6, member%NElements+1, 'memberLoads%F_If' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_WMG , 6, member%NElements+1, 'memberLoads%F_WMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_IMG , 6, member%NElements+1, 'memberLoads%F_IMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) ! Initialize everything to zero member%NodeIndx = 0.0_ReKi @@ -1375,7 +1334,15 @@ subroutine AllocateMemberDataArrays( member, errStat, errMsg ) member%AxCd = 0.0_ReKi member%AxCa = 0.0_ReKi member%AxCp = 0.0_ReKi - + memberLoads%F_D = 0.0_ReKi + memberLoads%F_A = 0.0_ReKi + memberLoads%F_B = 0.0_ReKi + memberLoads%F_BF = 0.0_ReKi + memberLoads%F_I = 0.0_ReKi + memberLoads%F_If = 0.0_ReKi + memberLoads%F_WMG = 0.0_ReKi + memberLoads%F_IMG = 0.0_ReKi + end subroutine AllocateMemberDataArrays subroutine FlipMemberNodeData( member, nodes, doSwap, errStat, errMsg ) @@ -1736,9 +1703,10 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF end subroutine SetMemberProperties -subroutine SetupMembers( InitInp, p, errStat, errMsg ) +subroutine SetupMembers( InitInp, p, m, errStat, errMsg ) type(Morison_InitInputType), intent (inout) :: InitInp type(Morison_ParameterType), intent (inout) :: p + type(Morison_MiscVarType), intent (inout) :: m integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None @@ -1758,7 +1726,14 @@ subroutine SetupMembers( InitInp, p, errStat, errMsg ) errMsg = ' Error allocating space for the members array.' errStat = ErrID_Fatal RETURN - END IF + END IF + + ALLOCATE ( m%MemberLoads(p%NMembers), STAT = errStat ) + IF ( errStat /= ErrID_None ) THEN + errMsg = ' Error allocating space for the memberLoads array.' + errStat = ErrID_Fatal + RETURN + END IF do i = 1, p%NMembers p%Members(i)%MemberID = InitInp%InpMembers(i)%MemberID @@ -1767,7 +1742,7 @@ subroutine SetupMembers( InitInp, p, errStat, errMsg ) p%Members(i)%NElements = InitInp%InpMembers(i)%NElements p%Members(i)%PropPot = InitInp%InpMembers(i)%PropPot - call AllocateMemberDataArrays(p%Members(i), errStat2, errMsg2) ; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') + call AllocateMemberDataArrays(p%Members(i), m%MemberLoads(i), errStat2, errMsg2) ; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') p%Members(i)%NodeIndx = InitInp%InpMembers(i)%NodeIndx ! now that the parameter version is allocated, copy the data from the InitInp version @@ -1878,7 +1853,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In p%JOutLst = InitInp%JOutLst ! Joint output data ! ----------------------- set up the members ----------------------- - call SetupMembers( InitInp, p, errStat2, errMsg2 ) ; call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'Morison_Init' ) + call SetupMembers( InitInp, p, m, errStat2, errMsg2 ) ; call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'Morison_Init' ) if ( errStat >= AbortErrLev ) return !------------------------ set up joint (or joint-node) properties -- @@ -2232,14 +2207,14 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) call AllocAry( m%nodeInWater , NNodes , 'm%nodeInWater' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%vrel , 3, NNodes , 'm%vrel' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_D , 6, NNodes , 'm%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_A , 6, NNodes , 'm%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_B , 6, NNodes , 'm%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_BF , 6, NNodes , 'm%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_I , 6, NNodes , 'm%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_If , 6, NNodes , 'm%F_If' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_WMG , 6, NNodes , 'm%F_WMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( m%F_IMG , 6, NNodes , 'm%F_IMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_D , 6, NNodes , 'm%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_A , 6, NNodes , 'm%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_B , 6, NNodes , 'm%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_BF , 6, NNodes , 'm%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_I , 6, NNodes , 'm%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_If , 6, NNodes , 'm%F_If' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_WMG , 6, NNodes , 'm%F_WMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + !call AllocAry( m%F_IMG , 6, NNodes , 'm%F_IMG' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%FV , 3, NNodes , 'm%FV' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%FA , 3, NNodes , 'm%FA' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%FDynP , NNodes , 'm%FDynP' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) @@ -2260,14 +2235,14 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) m%nodeInWater = 0 m%vrel = 0.0_ReKi - m%F_D = 0.0_ReKi - m%F_A = 0.0_ReKi - m%F_B = 0.0 - m%F_BF = 0.0 - m%F_I = 0.0 - m%F_If = 0.0 - m%F_WMG = 0.0 - m%F_IMG = 0.0 + !m%F_D = 0.0_ReKi + !m%F_A = 0.0_ReKi + !m%F_B = 0.0 + !m%F_BF = 0.0 + !m%F_I = 0.0 + !m%F_If = 0.0 + !m%F_WMG = 0.0 + !m%F_IMG = 0.0 m%FV = 0.0_ReKi m%FA = 0.0_ReKi m%FDynP = 0.0_ReKi @@ -2447,14 +2422,13 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, INTEGER(IntKi) :: errStat2 ! Error status of the operation (occurs after initial error) CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None - REAL(ReKi) :: F_D(6), F_DP(6), D_F_I(3), kvec(3), v(3), vf(3), vrel(3), vmag + REAL(ReKi) :: F_DP(6), kvec(3), v(3), vf(3), vrel(3), vmag INTEGER :: I, J, K, nodeIndx REAL(ReKi) :: AllOuts(MaxMrsnOutputs) REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node REAL(ReKi) :: dragFactor ! The lumped drag factor REAL(ReKi) :: AnProd ! Dot product of the directional area of the joint - REAL(ReKi) :: F_B(6) REAL(ReKi) :: C(3,3) REAL(ReKi) :: sgn REAL(ReKi) :: D_AM_M(6,6) @@ -2516,6 +2490,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, real(ReKi) :: Imat(3,3) real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), am(3,3), lstar, deltal real(ReKi) :: C_1, C_2, a0b0, z1d, z2d, h + real(ReKi) :: F_WMG(6), F_IMG(6), F_If(6), F_A(6), F_I(6), F_D(6), F_B1(6), F_B2(6) + ! Initialize errStat errStat = ErrID_None @@ -2549,23 +2525,35 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Zero out previous time-steps loads (these are loads which are computed at the member-level and summed onto a node, ! so they need to be zeroed out before the summations happen) - m%F_WMG = 0.0_ReKi - m%F_IMG = 0.0_ReKi + !m%F_WMG = 0.0_ReKi + !m%F_IMG = 0.0_ReKi m%F_BF_End= 0.0_ReKi - m%F_If = 0.0_ReKi - m%F_D = 0.0_ReKi - m%F_A = 0.0_ReKi - m%F_I = 0.0_ReKi - m%F_B = 0.0_ReKi - m%F_BF = 0.0_ReKi + !m%F_If = 0.0_ReKi + !m%F_D = 0.0_ReKi + !m%F_A = 0.0_ReKi + !m%F_I = 0.0_ReKi + !m%F_B = 0.0_ReKi + !m%F_BF = 0.0_ReKi m%F_B_End = 0.0_ReKi + y%Mesh%Force = 0.0_ReKi + y%Mesh%Moment = 0.0_ReKi + F_WMG(1) = 0.0_ReKi + F_WMG(2) = 0.0_ReKi ! Loop through each member DO im = 1, p%NMembers N = p%Members(im)%NElements mem = p%Members(im) !@mhall: does this have much overhead? - + !zero member loads + m%memberLoads(im)%F_B = 0.0_ReKi + m%memberLoads(im)%F_BF = 0.0_ReKi + m%memberLoads(im)%F_D = 0.0_ReKi + m%memberLoads(im)%F_A = 0.0_ReKi + m%memberLoads(im)%F_I = 0.0_ReKi + m%memberLoads(im)%F_WMG = 0.0_ReKi + m%memberLoads(im)%F_IMG = 0.0_ReKi + m%memberLoads(im)%F_If = 0.0_ReKi DO i =1,N ! loop through member elements @@ -2600,15 +2588,28 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! ------------------ marine growth: Sides: Section 4.1.2 -------------------- ! lower node - m%F_WMG(3, mem%NodeIndx(i )) = m%F_WMG(3, mem%NodeIndx(i )) - mem%m_mg_l(i)*g ! weight force : Note: this is a constant - m%F_WMG(4, mem%NodeIndx(i )) = m%F_WMG(4, mem%NodeIndx(i )) - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force - m%F_WMG(5, mem%NodeIndx(i )) = m%F_WMG(5, mem%NodeIndx(i )) + mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force + !m%F_WMG(3, mem%NodeIndx(i )) = m%F_WMG(3, mem%NodeIndx(i )) - mem%m_mg_l(i)*g ! weight force : Note: this is a constant + !m%F_WMG(4, mem%NodeIndx(i )) = m%F_WMG(4, mem%NodeIndx(i )) - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force + !m%F_WMG(5, mem%NodeIndx(i )) = m%F_WMG(5, mem%NodeIndx(i )) + mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force + + F_WMG(3) = - mem%m_mg_l(i)*g ! weight force : Note: this is a constant + F_WMG(4) = - mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * sinBeta! weight force + F_WMG(5) = mem%m_mg_l(i)*g * mem%h_cmg_l(i)* sinPhi * cosBeta! weight force + m%memberLoads(im)%F_WMG(:,i) = m%memberLoads(im)%F_WMG(:,i) + F_WMG + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_WMG(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_WMG(4:6) + ! upper node - m%F_WMG(3, mem%NodeIndx(i+1)) = m%F_WMG(3, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g ! weight force : Note: this is a constant - m%F_WMG(4, mem%NodeIndx(i+1)) = m%F_WMG(4, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force - m%F_WMG(5, mem%NodeIndx(i+1)) = m%F_WMG(5, mem%NodeIndx(i+1)) + mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force - - + !m%F_WMG(3, mem%NodeIndx(i+1)) = m%F_WMG(3, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g ! weight force : Note: this is a constant + !m%F_WMG(4, mem%NodeIndx(i+1)) = m%F_WMG(4, mem%NodeIndx(i+1)) - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force + !m%F_WMG(5, mem%NodeIndx(i+1)) = m%F_WMG(5, mem%NodeIndx(i+1)) + mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force + F_WMG(3) = - mem%m_mg_u(i)*g ! weight force : Note: this is a constant + F_WMG(4) = - mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * sinBeta! weight force + F_WMG(5) = mem%m_mg_u(i)*g * mem%h_cmg_u(i)* sinPhi * cosBeta! weight force + m%memberLoads(im)%F_WMG(:,i+1) = m%memberLoads(im)%F_WMG(:,i+1) + F_WMG + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_WMG(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_WMG(4:6) + ! lower node Ioffset = mem%h_cmg_l(i)*mem%h_cmg_l(i)*mem%m_mg_l(i) Imat(1,1) = mem%I_rmg_l(i) - Ioffset @@ -2617,11 +2618,18 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Imat = matmul(matmul(CMatrix, Imat), CTrans) iArm = mem%h_cmg_l(i) * k_hat iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_mg_l(i) - m%F_IMG(1:3, mem%NodeIndx(i )) = m%F_IMG(1:3, mem%NodeIndx(i )) + iTerm - m%F_IMG(4:6, mem%NodeIndx(i )) = m%F_IMG(4:6, mem%NodeIndx(i )) & - - cross_product(a_s1 * mem%m_mg_l(i), mem%h_cmg_l(i) * k_hat) & - + matmul(Imat, alpha_s1) & - - cross_product(omega_s1,matmul(Imat,omega_s1)) + !m%F_IMG(1:3, mem%NodeIndx(i )) = m%F_IMG(1:3, mem%NodeIndx(i )) + iTerm + !m%F_IMG(4:6, mem%NodeIndx(i )) = m%F_IMG(4:6, mem%NodeIndx(i )) & + ! - cross_product(a_s1 * mem%m_mg_l(i), mem%h_cmg_l(i) * k_hat) & + ! + matmul(Imat, alpha_s1) & + ! - cross_product(omega_s1,matmul(Imat,omega_s1)) + F_IMG(1:3) = iTerm + F_IMG(4:6) = - cross_product(a_s1 * mem%m_mg_l(i), mem%h_cmg_l(i) * k_hat) + matmul(Imat, alpha_s1) & + - cross_product(omega_s1,matmul(Imat,omega_s1)) + m%memberLoads(im)%F_IMG(:,i) = m%memberLoads(im)%F_IMG(:,i) + F_IMG + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_IMG(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_IMG(4:6) + ! upper node Ioffset = mem%h_cmg_u(i)*mem%h_cmg_u(i)*mem%m_mg_u(i) Imat(1,1) = mem%I_rmg_u(i) - Ioffset @@ -2630,11 +2638,17 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Imat = matmul(matmul(CMatrix, Imat), CTrans) iArm = mem%h_cmg_u(i) * k_hat iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_mg_u(i) - m%F_IMG(1:3, mem%NodeIndx(i+1)) = m%F_IMG(1:3, mem%NodeIndx(i+1)) + iTerm - m%F_IMG(4:6, mem%NodeIndx(i+1)) = m%F_IMG(4:6, mem%NodeIndx(i+1)) & - - cross_product(a_s2 * mem%m_mg_u(i), mem%h_cmg_u(i) * k_hat) & - + matmul(Imat, alpha_s2) & - - cross_product(omega_s2,matmul(Imat,omega_s2)) + !m%F_IMG(1:3, mem%NodeIndx(i+1)) = m%F_IMG(1:3, mem%NodeIndx(i+1)) + iTerm + !m%F_IMG(4:6, mem%NodeIndx(i+1)) = m%F_IMG(4:6, mem%NodeIndx(i+1)) & + ! - cross_product(a_s2 * mem%m_mg_u(i), mem%h_cmg_u(i) * k_hat) & + ! + matmul(Imat, alpha_s2) & + ! - cross_product(omega_s2,matmul(Imat,omega_s2)) + F_IMG(1:3) = iTerm + F_IMG(4:6) = - cross_product(a_s2 * mem%m_mg_u(i), mem%h_cmg_u(i) * k_hat) + matmul(Imat, alpha_s2) & + - cross_product(omega_s2,matmul(Imat,omega_s2)) + m%memberLoads(im)%F_IMG(:,i+1) = m%memberLoads(im)%F_IMG(:,i+1) + F_IMG + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_IMG(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_IMG(4:6) ! ------------------- buoyancy loads: sides: Sections 3.1 and 3.2 ------------------------ @@ -2720,8 +2734,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! reduce taper-based moment to remove (not double count) radial force distribution to each node Moment = Moment + Fr*(1.0_ReKi-alpha)*dl - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i)), m%F_B(:, mem%NodeIndx(i-1))) - + !call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i)), m%F_B(:, mem%NodeIndx(i-1))) + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, F_B1, F_B2) + m%memberLoads(im)%F_B(:, i) = m%memberLoads(im)%F_B(:, i) + F_B1 ! alpha + m%memberLoads(im)%F_B(:, i-1) = m%memberLoads(im)%F_B(:, i-1) + F_B2 ! 1-alpha + y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B1(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B1(4:6) + y%Mesh%Force (:,mem%NodeIndx(i-1)) = y%Mesh%Force (:,mem%NodeIndx(i-1)) + F_B2(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i-1)) = y%Mesh%Moment(:,mem%NodeIndx(i-1)) + F_B2(4:6) else ! normal, fully submerged case Fl = -2.0*Pi*dRdl_mg*p%WtrDens*g*dl*( z1*r1 + 0.5*(z1*dRdl_mg + r1*cosPhi)*dl + 1/3*dRdl_mg*cosPhi*dl*dl ) ! from CylinderCalculationsR1.ipynb @@ -2733,13 +2753,22 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, !TODO: Review the below alpha eqn, GJH z1d = -min(0.0_ReKi,z1) z2d = -min(0.0_ReKi,z2) - - alpha = mem%alpha(i)*z2d/(mem%alpha(i)*z2d+(1-mem%alpha(i))*z1d) + + pwr = 1 + alpha = mem%alpha(i)*z2d**pwr/(mem%alpha(i)*z2d**pwr+(1-mem%alpha(i))*z1d**pwr) ! reduce moment to remove (not double count) radial force distribution to each node Moment = Moment - Fr*alpha*dl - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i+1)), m%F_B(:, mem%NodeIndx(i))) + ! TODO: Should the order be, i, i+1 GJH + !call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, m%F_B(:, mem%NodeIndx(i+1)), m%F_B(:, mem%NodeIndx(i))) + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, alpha, F_B1, F_B2) + m%memberLoads(im)%F_B(:,i+1) = m%memberLoads(im)%F_B(:,i+1) + F_B1 ! alpha + m%memberLoads(im)%F_B(:, i) = m%memberLoads(im)%F_B(:, i) + F_B2 ! 1-alpha + y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B2(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B2(4:6) + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_B1(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_B1(4:6) end if ! submergence cases end if ! element at least partially submerged @@ -2755,24 +2784,37 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Imat(3,3) = mem%I_lfb_l(i) - Ioffset iArm = mem%h_cfb_l(i) * k_hat iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_fb_l(i) - m%F_If(1:3, mem%NodeIndx(i )) = m%F_If(1:3, mem%NodeIndx(i )) + iTerm - m%F_If(4:6, mem%NodeIndx(i )) = m%F_If(4:6, mem%NodeIndx(i )) & - - cross_product(a_s1 * mem%m_fb_l(i), mem%h_cfb_l(i) * k_hat) & - + matmul(Imat, alpha_s1) & - - cross_product(omega_s1,matmul(Imat,omega_s1)) - ! upper node + !m%F_If(1:3, mem%NodeIndx(i )) = m%F_If(1:3, mem%NodeIndx(i )) + iTerm + !m%F_If(4:6, mem%NodeIndx(i )) = m%F_If(4:6, mem%NodeIndx(i )) & + ! - cross_product(a_s1 * mem%m_fb_l(i), mem%h_cfb_l(i) * k_hat) & + ! + matmul(Imat, alpha_s1) & + ! - cross_product(omega_s1,matmul(Imat,omega_s1)) + F_If(1:3) = iTerm + F_If(4:6) = - cross_product(a_s1 * mem%m_fb_l(i), mem%h_cfb_l(i) * k_hat) + matmul(Imat, alpha_s1) & + - cross_product(omega_s1,matmul(Imat,omega_s1)) + m%memberLoads(im)%F_If(:,i) = m%memberLoads(im)%F_If(:,i) + F_If + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_If(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_If(4:6) + + ! upper node Ioffset = mem%h_cfb_u(i)*mem%h_cfb_u(i)*mem%m_fb_u(i) Imat(1,1) = mem%I_rfb_u(i) - Ioffset Imat(2,2) = mem%I_rfb_u(i) - Ioffset Imat(3,3) = mem%I_lfb_u(i) - Ioffset iArm = mem%h_cfb_u(i) * k_hat iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_fb_u(i) - m%F_If(1:3, mem%NodeIndx(i+1)) = m%F_If(1:3, mem%NodeIndx(i+1)) + iTerm - m%F_If(4:6, mem%NodeIndx(i+1)) = m%F_If(4:6, mem%NodeIndx(i+1)) & - - cross_product(a_s2 * mem%m_fb_u(i), mem%h_cfb_u(i) * k_hat) & - + matmul(Imat, alpha_s2) & - - cross_product(omega_s2,matmul(Imat,omega_s2)) - + !m%F_If(1:3, mem%NodeIndx(i+1)) = m%F_If(1:3, mem%NodeIndx(i+1)) + iTerm + !m%F_If(4:6, mem%NodeIndx(i+1)) = m%F_If(4:6, mem%NodeIndx(i+1)) & + ! - cross_product(a_s2 * mem%m_fb_u(i), mem%h_cfb_u(i) * k_hat) & + ! + matmul(Imat, alpha_s2) & + ! - cross_product(omega_s2,matmul(Imat,omega_s2)) + F_If(1:3) = iTerm + F_If(4:6) = - cross_product(a_s2 * mem%m_fb_u(i), mem%h_cfb_u(i) * k_hat) + matmul(Imat, alpha_s2) & + - cross_product(omega_s2,matmul(Imat,omega_s2)) + m%memberLoads(im)%F_If(:,i+1) = m%memberLoads(im)%F_If(:,i+1) + F_If + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_If(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_If(4:6) + ! ------------------ flooded ballast weight : sides : Section 5.1.2 & 5.2.2 : Always compute regardless of PropPot setting --------------------- ! fully filled elements @@ -2796,8 +2838,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Moment = mem%CM0_fb(i)*sinPhi - Fr*mem%alpha_fb_star(i)*dl ! calculate full vector and distribute to nodes - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, (1-mem%alpha_fb_star(i)), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i+1))) - + !call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, (1-mem%alpha_fb_star(i)), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i+1))) + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, (1-mem%alpha_fb_star(i)), F_B1, F_B2) + m%memberLoads(im)%F_BF(:, i) = m%memberLoads(im)%F_BF(:, i) + F_B2 ! 1-alpha + m%memberLoads(im)%F_BF(:, i+1) = m%memberLoads(im)%F_BF(:, i+1) + F_B1 ! alpha + y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B2(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B2(4:6) + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_B1(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_B1(4:6) ! partially filled element else if (mem%floodstatus(i) == 2) then @@ -2808,8 +2856,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Moment = mem%CM0_fb(i)*sinPhi + Fr*(1 - mem%alpha_fb_star(i))*dl ! calculate full vector and distribute to nodes - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, mem%alpha_fb_star(i), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i-1))) - + !call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, mem%alpha_fb_star(i), m%F_BF(:, mem%NodeIndx(i)), m%F_BF(:, mem%NodeIndx(i-1))) + call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, mem%alpha_fb_star(i), F_B1, F_B2) + m%memberLoads(im)%F_BF(:, i) = m%memberLoads(im)%F_BF(:, i) + F_B1 ! alpha + m%memberLoads(im)%F_BF(:, i-1) = m%memberLoads(im)%F_BF(:, i-1) + F_B2 ! 1- alpha + y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B1(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B1(4:6) + y%Mesh%Force (:,mem%NodeIndx(i-1)) = y%Mesh%Force (:,mem%NodeIndx(i-1)) + F_B2(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i-1)) = y%Mesh%Moment(:,mem%NodeIndx(i-1)) + F_B2(4:6) ! no load for unflooded element or element fully below seabed @@ -2869,19 +2923,28 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) f_hydro = mem%Cd(i)*p%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & 0.5*mem%AxCd(i)*p%WtrDens*pi*mem%RMG(i)*dRdl_p * matmul( dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )*mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) - +! call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_D(:, i) ) + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(1:3, i) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(4:6, i) + if ( .not. mem%PropPot ) then ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ Am = mem%Ca(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) + !call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_A(:, i) ) + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(1:3, i) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(4:6, i) ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ - f_hydro=mem%Ca(i)*mem%Cp(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & + f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) + !call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_I(:, i) ) + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(1:3, i) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(4:6, i) end if end if ! ( i > mem%i_floor .and. Zi <= 0.0 ) @@ -2897,20 +2960,18 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, z1 = pos1(3) call GetOrientationAngles( pos1, pos2, phi1, sinPhi1, cosPhi1, tanPhi, sinBeta1, cosBeta1, k_hat1, errStat2, errMsg2 ) - if ( N == 1 ) then - + if ( N == 1 ) then sinPhi2 = sinPhi1 cosPhi2 = cosPhi1 sinBeta2 = sinBeta1 cosBeta2 = cosBeta1 - z2 = pos2(3) else pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N)) + u%Mesh%Position(:, mem%NodeIndx(N)) pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) + u%Mesh%Position(:, mem%NodeIndx(N+1)) - z2 = pos2(3) call GetOrientationAngles( pos1, pos2, phi2, sinPhi2, cosPhi2, tanPhi, sinBeta2, cosBeta2, k_hat2, errStat2, errMsg2 ) end if - + pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) + u%Mesh%Position(:, mem%NodeIndx(N+1)) + z2 = pos2(3) ! TODO: Do the equations below still work if z1 > z2 ? !TODO, should not have to test seabed crossing in time-marching loop @@ -2918,7 +2979,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, if ( mem%i_floor == 0 ) then ! both ends are above seabed !--- Water ballast buoyancy --- ! if member is fully flooded - if (mem%z_overfill > 0) then + if (mem%z_overfill >= 0) then Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0.0_ReKi)) Moment = mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) @@ -2936,8 +2997,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! no load if member is not flooded at all end if - elseif ( mem%i_floor < mem%NElements ) then ! upper node is still above the seabed - if (mem%z_overfill > 0) then + elseif ( mem%i_floor < mem%NElements ) then ! upper node is still above the seabed, but lower node is below seabed + if (mem%z_overfill >= 0) then Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) @@ -2988,16 +3049,16 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, end do ! im - looping through members - do j = 1, p%NNodes - ! Sum side load components onto output mesh - DO i=1,6 - IF (i < 4 ) THEN - y%Mesh%Force(I,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) - ELSE - y%Mesh%Moment(I-3,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) - END IF - END DO ! - end do + !do j = 1, p%NNodes + ! ! Sum side load components onto output mesh + ! DO i=1,6 + ! IF (i < 4 ) THEN + ! y%Mesh%Force(I,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) + ! ELSE + ! y%Mesh%Moment(I-3,J) = m%F_D(I,J) + m%F_A(I,J) + m%F_I(I,J) + m%F_B(I,J) + m%F_BF(I,J) + m%F_If(i,j) + m%F_WMG(i,j) + m%F_IMG(i,j) + ! END IF + ! END DO ! + !end do ! --- Hydrodynamic drag loads: joints @@ -3038,10 +3099,10 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, m%F_D_End(i,j) = p%An_End(i,j)*p%DragConst_End(j)*abs(vmag)*vmag ! Note: vmag is zero if node is not in the water !TODO: This needs to be reworked with new equations !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) - y%Mesh%Force(i,j) = m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) + y%Mesh%Force(i,j) = y%Mesh%Force(i,j) + m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) ELSE !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) - y%Mesh%Moment(i-3,j) = m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) + y%Mesh%Moment(i-3,j) = y%Mesh%Moment(i-3,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) END IF END DO ! I=1,6 ENDDO ! J = 1, p%NJoints @@ -3082,8 +3143,10 @@ subroutine LumpDistrHydroLoads( f_hydro, k_hat, dl, h_c, lumpedLoad ) real(ReKi), intent(in ) :: dl real(ReKi), intent(in ) :: h_c real(ReKi), intent(inout) :: lumpedLoad(6) - lumpedLoad(1:3) = lumpedLoad(1:3) + f_hydro*dl - lumpedLoad(4:6) = lumpedLoad(4:6) + cross_product(k_hat*h_c, f_hydro)*dl + !lumpedLoad(1:3) = lumpedLoad(1:3) + f_hydro*dl + !lumpedLoad(4:6) = lumpedLoad(4:6) + cross_product(k_hat*h_c, f_hydro)*dl + lumpedLoad(1:3) = f_hydro*dl + lumpedLoad(4:6) = cross_product(k_hat*h_c, f_hydro)*dl end subroutine LumpDistrHydroLoads ! Takes loads on node i in element tilted frame and converts to 6DOF loads at node i and adjacent node @@ -3102,19 +3165,47 @@ SUBROUTINE DistributeElementLoads(Fl, Fr, M, sinPhi, cosPhi, SinBeta, cosBeta, a REAL(ReKi), INTENT ( OUT ) :: F2(6) ! (N, Nm) force/moment vector for the other node (whether i+1, or i-1) - F1(1) = F1(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - F1(2) = F1(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha - F1(3) = F1(3) + (Fl*cosPhi - Fr*sinPhi)*alpha - F1(4) = F1(4) + sinBeta * M *alpha - F1(5) = F1(5) + cosBeta * M *alpha - !F1(6) = F1(6) + 0.0 - - F2(1) = F2(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - F2(2) = F2(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) - F2(3) = F2(3) + (Fl*cosPhi - Fr*sinPhi)*(1-alpha) - F2(4) = F2(4) + sinBeta * M *(1-alpha) - F2(5) = F2(5) + cosBeta * M *(1-alpha) - !F2(6) = F2(6) + 0.0 + !F1(1) = F1(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + !F1(2) = F1(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + !F1(3) = F1(3) + (Fl*cosPhi - Fr*sinPhi)*alpha + !F1(4) = F1(4) + sinBeta * M *alpha + !F1(5) = F1(5) + cosBeta * M *alpha + !!F1(6) = F1(6) + 0.0 + ! + !F2(1) = F2(1) + cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + !F2(2) = F2(2) - sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + !F2(3) = F2(3) + (Fl*cosPhi - Fr*sinPhi)*(1-alpha) + !F2(4) = F2(4) + sinBeta * M *(1-alpha) + !F2(5) = F2(5) + cosBeta * M *(1-alpha) + !!F2(6) = F2(6) + 0.0 + + F1(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(2) = sinBeta*(Fl*sinPhi + Fr*cosPhi)*alpha + F1(3) = (Fl*cosPhi - Fr*sinPhi)*alpha + F1(4) = -sinBeta * M *alpha + F1(5) = cosBeta * M *alpha + F1(6) = 0.0 + + F2(1) = cosBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(2) = sinBeta*(Fl*sinPhi + Fr*cosPhi)*(1-alpha) + F2(3) = (Fl*cosPhi - Fr*sinPhi)*(1-alpha) + F2(4) = -sinBeta * M *(1-alpha) + F2(5) = cosBeta * M *(1-alpha) + F2(6) = 0.0 + + !F1(1) = cosBeta*(-Fl*sinPhi + Fr*cosPhi)*alpha + !F1(2) = sinBeta*(-Fl*sinPhi + Fr*cosPhi)*alpha + !F1(3) = (Fl*cosPhi + Fr*sinPhi)*alpha + !F1(4) = -sinBeta * M *alpha + !F1(5) = cosBeta * M *alpha + !F1(6) = 0.0 + ! + !F2(1) = cosBeta*(-Fl*sinPhi + Fr*cosPhi)*(1-alpha) + !F2(2) = sinBeta*(-Fl*sinPhi + Fr*cosPhi)*(1-alpha) + !F2(3) = (Fl*cosPhi + Fr*sinPhi)*(1-alpha) + !F2(4) = -sinBeta * M *(1-alpha) + !F2(5) = cosBeta * M *(1-alpha) + !F2(6) = 0.0 END SUBROUTINE DistributeElementLoads diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index c3bd0ae60..1f717cdc7 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -146,6 +146,18 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - # +typedef ^ Morison_MemberLoads ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - +typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - +typedef ^ ^ ReKi F_A {:}{:} - - "Member-based (side-effects) Nodal added mass loads at time t" - +typedef ^ ^ ReKi F_B {:}{:} - - "Member-based (side-effects) Nodal buoyancy loads" - +typedef ^ ^ ReKi F_BF {:}{:} - - "Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads" - +typedef ^ ^ ReKi F_If {:}{:} - - "Member-based (side-effects) Nodal flooded ballast inertia loads" - +typedef ^ ^ ReKi F_WMG {:}{:} - - "Member-based (side-effects) Nodal marine growth weight loads" - +typedef ^ ^ ReKi F_IMG {:}{:} - - "Member-based (side-effects) Nodal marine growth inertia loads" - +typedef ^ ^ ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +# typedef ^ Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - @@ -178,9 +190,11 @@ typedef ^ Morison_MOutput INTEGER typedef ^ ^ INTEGER NOutLoc - - - "The number of requested output locations" - typedef ^ ^ ReKi NodeLocs {:} - - "Normalized locations along user-specified member for the outputs" - typedef ^ ^ INTEGER MemberIDIndx - - - "Index for member in the master list" - -typedef ^ ^ INTEGER Marker1 {:} - - "Index of node in DistribMesh for the start of the member" - -typedef ^ ^ INTEGER Marker2 {:} - - "Index of node in DistribMesh for the end of the member" - -typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between Marker1 and Marker2 for the output location" - +typedef ^ ^ INTEGER MeshIndx1 {:} - - "Index of node in Mesh for the start of the member element" - +typedef ^ ^ INTEGER MeshIndx2 {:} - - "Index of node in Mesh for the end of the member element" - +typedef ^ ^ INTEGER MemberIndx1 {:} - - "Index of Member nodes for the start of the member element" - +typedef ^ ^ INTEGER MemberIndx2 {:} - - "Index of Member nodes for the end of the member element" - +typedef ^ ^ ReKi s {:} - - "Linear interpolation factor between node1 and node2 for the output location" - typedef ^ Morison_JOutput INTEGER JointID - - - "Joint ID for the requested output" - typedef ^ ^ INTEGER JointIDIndx - - - "Joint index in the master list" - # ..... Initialization data ....................................................................................................... @@ -273,20 +287,21 @@ typedef ^ OtherStateType IntKi # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - -typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - -typedef ^ ^ ReKi F_A {:}{:} - - "Member-based (side-effects) Nodal added mass loads at time t" - -typedef ^ ^ ReKi F_B {:}{:} - - "Member-based (side-effects) Nodal buoyancy loads" - -typedef ^ ^ ReKi F_BF {:}{:} - - "Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads" - -typedef ^ ^ ReKi F_If {:}{:} - - "Member-based (side-effects) Nodal flooded ballast inertia loads" - -typedef ^ ^ ReKi F_WMG {:}{:} - - "Member-based (side-effects) Nodal marine growth weight loads" - -typedef ^ ^ ReKi F_IMG {:}{:} - - "Member-based (side-effects) Nodal marine growth inertia loads" - -typedef ^ ^ ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - +#typedef ^ MiscVarType ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - +#typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - +#typedef ^ ^ ReKi F_A {:}{:} - - "Member-based (side-effects) Nodal added mass loads at time t" - +#typedef ^ ^ ReKi F_B {:}{:} - - "Member-based (side-effects) Nodal buoyancy loads" - +#typedef ^ ^ ReKi F_BF {:}{:} - - "Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads" - +#typedef ^ ^ ReKi F_If {:}{:} - - "Member-based (side-effects) Nodal flooded ballast inertia loads" - +#typedef ^ ^ ReKi F_WMG {:}{:} - - "Member-based (side-effects) Nodal marine growth weight loads" - +#typedef ^ ^ ReKi F_IMG {:}{:} - - "Member-based (side-effects) Nodal marine growth inertia loads" - +#typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ MiscVarType ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi FDynP {:} - - "Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi vrel {:}{:} - - "velocity of structural node relative to the water" m/s^2 typedef ^ ^ INTEGER nodeInWater {:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" - +typedef ^ ^ Morison_MemberLoads memberLoads {:} - - "Array (NMembers long) of member-based side-effects load contributions" - typedef ^ ^ ReKi F_B_End {:}{:} - - "" - typedef ^ ^ ReKi F_D_End {:}{:} - - "Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_I_End {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - diff --git a/modules/hydrodyn/src/Morison_Output.f90 b/modules/hydrodyn/src/Morison_Output.f90 index 9443ff3d1..15d08168e 100644 --- a/modules/hydrodyn/src/Morison_Output.f90 +++ b/modules/hydrodyn/src/Morison_Output.f90 @@ -6441,7 +6441,7 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg INTEGER :: I, J - INTEGER :: m1, m2 ! Indices of the markers which surround the requested output location + INTEGER :: im, m1, m2, im1, im2 ! Indices of the markers which surround the requested output location real(ReKi) :: mult1, mult2 ! Load multiplier for joint nodes vs interior nodes real(ReKi) :: dl ! member element length (m) REAL(ReKi) :: s ! The linear interpolation factor for the requested location @@ -6453,12 +6453,15 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg ! Only generate member-based outputs for the number of user-requested member outputs IF ( p%NumOuts > 0 ) THEN - DO J=1,p%NMOutputs + DO J=1,p%NMOutputs + im = p%MOutLst(J)%MemberIDIndx DO I=1,p%MOutLst(J)%NOutLoc - m1 = p%MOutLst(J)%Marker1(I) - m2 = p%MOutLst(J)%Marker2(I) + m1 = p%MOutLst(J)%MeshIndx1(I) + m2 = p%MOutLst(J)%MeshIndx2(I) + im1 = p%MOutLst(J)%MemberIndx1(I) + im2 = p%MOutLst(J)%MemberIndx2(I) s = p%MOutLst(J)%s (I) dl = p%Members(p%MOutLst(J)%MemberIDIndx)%dl @@ -6488,29 +6491,53 @@ SUBROUTINE MrsnOut_MapOutputs( CurrentTime, y, p, u, m, AllOuts, ErrStat, ErrMsg AllOuts(MNSTAi(:,I,J)) = u%Mesh%TranslationAcc(: ,m1)*(1-s) + u%Mesh%TranslationAcc(: ,m2)*s ! AllOuts(MNSRAi(:,I,J)) = u%DistribMesh%RotationAcc (: ,m1)*(1-s) + u%DistribMesh%RotationAcc (: ,m2)*s + ! ! transverse drag force + !AllOuts(MNFDi (:,I,J)) =(mult1*m%F_D (1:3,m1)*(1-s) + mult2*m%F_D (1:3,m2)*s)/dl + ! ! inertial force + !AllOuts(MNFIi (:,I,J)) =(mult1*m%F_I (1:3,m1)*(1-s) + mult2*m%F_I (1:3,m2)*s)/dl + ! + ! ! marine growth weight + !AllOuts(MNFMGi(:,I,J)) =(mult1*m%F_WMG (1:3,m1)*(1-s) + mult2*m%F_WMG(1:3,m2)*s)/dl + !AllOuts(MNMMGi(:,I,J)) =(mult1*m%F_WMG (4:6,m1)*(1-s) + mult2*m%F_WMG(4:6,m2)*s)/dl + ! + ! ! buoyancy forces + !AllOuts(MNFBi (:,I,J)) =(mult1*m%F_B (1:3,m1)*(1-s) + mult2*m%F_B (1:3,m2)*s)/dl + !AllOuts(MNFBFi(:,I,J)) =(mult1*m%F_BF (1:3,m1)*(1-s) + mult2*m%F_BF (1:3,m2)*s)/dl + ! + ! ! buoyancy moments + !AllOuts(MNMBi (:,I,J)) =(mult1*m%F_B (4:6,m1)*(1-s) + mult2*m%F_B (4:6,m2)*s)/dl + !AllOuts(MNMBFi(:,I,J)) =(mult1*m%F_BF (4:6,m1)*(1-s) + mult2*m%F_BF (4:6,m2)*s)/dl + ! + ! ! added mass forces + !AllOuts(MNFAGi(:,I,J)) =(mult1*m%F_IMG (1:3,m1)*(1-s) + mult2*m%F_IMG(1:3,m2)*s)/dl ! due to marine growth + !AllOuts(MNMAGi(:,I,J)) =(mult1*m%F_IMG (4:6,m1)*(1-s) + mult2*m%F_IMG(4:6,m2)*s)/dl + !AllOuts(MNFAMi (:,I,J)) =(mult1*m%F_A (1:3,m1)*(1-s) + mult2*m%F_A (1:3,m2)*s)/dl ! due to the structural member moving the fluid + !AllOuts(MNFAFi (:,I,J)) =(mult1*m%F_If (1:3,m1)*(1-s) + mult2*m%F_If(1:3 ,m2)*s)/dl ! due to the ballasted/flooded fluid + !AllOuts(MNMAFi (:,I,J)) =(mult1*m%F_If (4:6,m1)*(1-s) + mult2*m%F_If(4:6 ,m2)*s)/dl + ! transverse drag force - AllOuts(MNFDi (:,I,J)) =(mult1*m%F_D (1:3,m1)*(1-s) + mult2*m%F_D (1:3,m2)*s)/dl + AllOuts(MNFDi (:,I,J)) =(mult1*m%memberLoads(im)%F_D (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_D (1:3,im2)*s)/dl ! inertial force - AllOuts(MNFIi (:,I,J)) =(mult1*m%F_I (1:3,m1)*(1-s) + mult2*m%F_I (1:3,m2)*s)/dl + AllOuts(MNFIi (:,I,J)) =(mult1*m%memberLoads(im)%F_I (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_I (1:3,im2)*s)/dl ! marine growth weight - AllOuts(MNFMGi(:,I,J)) =(mult1*m%F_WMG (1:3,m1)*(1-s) + mult2*m%F_WMG(1:3,m2)*s)/dl - AllOuts(MNMMGi(:,I,J)) =(mult1*m%F_WMG (4:6,m1)*(1-s) + mult2*m%F_WMG(4:6,m2)*s)/dl + AllOuts(MNFMGi(:,I,J)) =(mult1*m%memberLoads(im)%F_WMG (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_WMG(1:3,im2)*s)/dl + AllOuts(MNMMGi(:,I,J)) =(mult1*m%memberLoads(im)%F_WMG (4:6,im1)*(1-s) + mult2*m%memberLoads(im)%F_WMG(4:6,im2)*s)/dl ! buoyancy forces - AllOuts(MNFBi (:,I,J)) =(mult1*m%F_B (1:3,m1)*(1-s) + mult2*m%F_B (1:3,m2)*s)/dl - AllOuts(MNFBFi(:,I,J)) =(mult1*m%F_BF (1:3,m1)*(1-s) + mult2*m%F_BF (1:3,m2)*s)/dl + AllOuts(MNFBi (:,I,J)) =(mult1*m%memberLoads(im)%F_B (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_B (1:3,im2)*s)/dl + AllOuts(MNFBFi(:,I,J)) =(mult1*m%memberLoads(im)%F_BF (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_BF (1:3,im2)*s)/dl ! buoyancy moments - AllOuts(MNMBi (:,I,J)) =(mult1*m%F_B (4:6,m1)*(1-s) + mult2*m%F_B (4:6,m2)*s)/dl - AllOuts(MNMBFi(:,I,J)) =(mult1*m%F_BF (4:6,m1)*(1-s) + mult2*m%F_BF (4:6,m2)*s)/dl + AllOuts(MNMBi (:,I,J)) =(mult1*m%memberLoads(im)%F_B (4:6,im1)*(1-s) + mult2*m%memberLoads(im)%F_B (4:6,im2)*s)/dl + AllOuts(MNMBFi(:,I,J)) =(mult1*m%memberLoads(im)%F_BF (4:6,im1)*(1-s) + mult2*m%memberLoads(im)%F_BF (4:6,im2)*s)/dl ! added mass forces - AllOuts(MNFAGi(:,I,J)) =(mult1*m%F_IMG (1:3,m1)*(1-s) + mult2*m%F_IMG(1:3,m2)*s)/dl ! due to marine growth - AllOuts(MNMAGi(:,I,J)) =(mult1*m%F_IMG (4:6,m1)*(1-s) + mult2*m%F_IMG(4:6,m2)*s)/dl - AllOuts(MNFAMi (:,I,J)) =(mult1*m%F_A (1:3,m1)*(1-s) + mult2*m%F_A (1:3,m2)*s)/dl ! due to the structural member moving the fluid - AllOuts(MNFAFi (:,I,J)) =(mult1*m%F_If (1:3,m1)*(1-s) + mult2*m%F_If(1:3 ,m2)*s)/dl ! due to the ballasted/flooded fluid - AllOuts(MNMAFi (:,I,J)) =(mult1*m%F_If (4:6,m1)*(1-s) + mult2*m%F_If(4:6 ,m2)*s)/dl + AllOuts(MNFAGi(:,I,J)) =(mult1*m%memberLoads(im)%F_IMG (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_IMG(1:3,im2)*s)/dl ! due to marine growth + AllOuts(MNMAGi(:,I,J)) =(mult1*m%memberLoads(im)%F_IMG (4:6,im1)*(1-s) + mult2*m%memberLoads(im)%F_IMG(4:6,im2)*s)/dl + AllOuts(MNFAMi (:,I,J)) =(mult1*m%memberLoads(im)%F_A (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_A (1:3,im2)*s)/dl ! due to the structural member moving the fluid + AllOuts(MNFAFi (:,I,J)) =(mult1*m%memberLoads(im)%F_If (1:3,im1)*(1-s) + mult2*m%memberLoads(im)%F_If(1:3 ,im2)*s)/dl ! due to the ballasted/flooded fluid + AllOuts(MNMAFi (:,I,J)) =(mult1*m%memberLoads(im)%F_If (4:6,im1)*(1-s) + mult2*m%memberLoads(im)%F_If(4:6 ,im2)*s)/dl END DO END DO @@ -6762,18 +6789,17 @@ SUBROUTINE MrsnOut_WriteOutputs( UnOutFile, Time, y, p, ErrStat, ErrMsg ) END SUBROUTINE MrsnOut_WriteOutputs -SUBROUTINE GetNeighboringNodes(member, d, m1, m2, s, ErrStat, ErrMsg) +SUBROUTINE GetNeighboringNodes(member, d, m1, m2, i1, i2, s, ErrStat, ErrMsg) TYPE(Morison_MemberType), INTENT( IN ) :: member REAL(ReKi), INTENT( IN ) :: d INTEGER, INTENT( OUT ) :: m1 INTEGER, INTENT( OUT ) :: m2 + INTEGER, INTENT( OUT ) :: i1 + INTEGER, INTENT( OUT ) :: i2 REAL(ReKi), INTENT( OUT ) :: s INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - - INTEGER :: i1, i2 ErrStat = ErrID_None @@ -6824,7 +6850,7 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! INTEGER :: Indx ! Counts the current index into the WaveKinNd array ! CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. ! CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: m1, m2, memberIndx ! marker1, marker2, and member indices + INTEGER :: i1, i2, m1, m2, memberIndx ! marker1, marker2, and member indices REAL(ReKi) :: s ! interpolation factor ! INTEGER :: count ! node index @@ -6878,10 +6904,12 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! scale factor based on how far they are from the requested output location. ! Since this is being done on markers and not nodes, the subroutine must be called after the Morison_Init() subroutine is called - CALL GetNeighboringNodes(p%Members(memberIndx), p%MOutLst(I)%NodeLocs(J), m1, m2, s, ErrStat, ErrMsg) + CALL GetNeighboringNodes(p%Members(memberIndx), p%MOutLst(I)%NodeLocs(J), m1, m2, i1, i2, s, ErrStat, ErrMsg) - p%MOutLst(I)%Marker1(J) = m1 - p%MOutLst(I)%Marker2(J) = m2 ! The 2nd marker indx which is used to + p%MOutLst(I)%MeshIndx1(J) = m1 + p%MOutLst(I)%MeshIndx2(J) = m2 + p%MOutLst(I)%MemberIndx1(J) = i1 + p%MOutLst(I)%MemberIndx2(J) = i2 p%MOutLst(I)%s(J) = s ! linear interpolation factor END DO From 6318872b21b00c78dc09c3dd90f94aa7b8dc0529 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 25 Jun 2020 10:20:41 -0600 Subject: [PATCH 226/377] Summary file text fix --- modules/subdyn/src/SubDyn.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 3343ffbfc..7691e7397 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2631,7 +2631,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'KBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'MBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) ! Set TI2, transformation matrix from R DOFs to SubDyn Origin CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return From 48b44701e6e9624cac7486b261c7255555c31307 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 1 Jul 2020 19:46:48 -0600 Subject: [PATCH 227/377] FlexSub: summary file fix for Nodes --- modules/subdyn/src/SubDyn.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 17333baff..b17a61a69 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2472,7 +2472,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! Nodes properties write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' - call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) + call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),(F15.0,","),5(E15.6,",")') !, comment='',label=.true.) ! Element properties CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return From 48000332e12f372c3968c5dd940b43922e7f13d7 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 2 Jul 2020 08:03:45 -0600 Subject: [PATCH 228/377] Ballasting bug fixes replaced the use of z_overfill>=0 with memfloodstatus == 1 correct value of memfloodstatus fro partially flooded members (was using 1 now 2) corrected i_floor check for member with lower node in seabed, but upper is in the water --- modules/hydrodyn/src/Morison.f90 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 0951860a7..2b381c5f8 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2816,12 +2816,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_If(4:6) ! ------------------ flooded ballast weight : sides : Section 5.1.2 & 5.2.2 : Always compute regardless of PropPot setting --------------------- - + + ! NOTE: For memfloodstatus and floodstatus: 0 = fully buried or not ballasted, 1 = fully flooded, 2 = partially flooded + ! fully filled elements if (mem%floodstatus(i) == 1) then ! Compute lstar - if ( mem%memfloodstatus == 1) then + if ( mem%memfloodstatus == 2) then ! partially flooded MEMBER lstar = dl*(i-1) - mem%l_fill elseif (cosPhi >= 0.0 ) then @@ -2979,7 +2981,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, if ( mem%i_floor == 0 ) then ! both ends are above seabed !--- Water ballast buoyancy --- ! if member is fully flooded - if (mem%z_overfill >= 0) then + if (mem%memfloodstatus == 1) then + !if (mem%z_overfill >= 0) then Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0.0_ReKi)) Moment = mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) @@ -2997,8 +3000,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! no load if member is not flooded at all end if - elseif ( mem%i_floor < mem%NElements ) then ! upper node is still above the seabed, but lower node is below seabed - if (mem%z_overfill >= 0) then + elseif ( mem%i_floor < mem%NElements+1 ) then ! upper node is still above the seabed, but lower node is below seabed + !if (mem%z_overfill >= 0) then + if (mem%memfloodstatus == 1) then Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) From 2d6c9d6f1c1d9dad78332dd0febd9426efb94226 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 2 Jul 2020 08:04:57 -0600 Subject: [PATCH 229/377] Fixed mesh mapping bug for integrated HD loads --- modules/hydrodyn/src/HydroDyn.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index d31142d74..a42bd69c0 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -2358,7 +2358,7 @@ function CalcLoadsAtWRP( y, u, AllHdroOrigin, PRP_Position, MrsnMesh_Position, if ( y%Morison%Mesh%Committed ) then - call Transfer_Point_to_Point( y%Morison%Mesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, MrsnMesh_Position, PRP_Position ) + call Transfer_Point_to_Point( y%Morison%Mesh, AllHdroOrigin, MeshMapData%M_P_2_PRP_P, ErrStat2, ErrMsg2, u%Morison%Mesh, PRP_Position ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'CalcLoadsAtWRP') if (ErrStat >= AbortErrLev) return From 9f5677c6c48c1f67dd5943c22a29e0596a1d3c97 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 2 Jul 2020 08:06:02 -0600 Subject: [PATCH 230/377] Fixed symbol for N-m output channel units --- modules/hydrodyn/src/HydroDyn_Output.f90 | 98 ++++++++++++------------ 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index e719a1538..6245d57ec 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -826,77 +826,77 @@ MODULE HydroDyn_Output Wave7Elv1 , Wave7Elv2 , Wave8Elev , Wave8Elv1 , Wave8Elv2 , Wave9Elev , Wave9Elv1 , & Wave9Elv2 /) CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(519) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(m) ","(rad) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(m) ","(rad) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(rad) ","(N) ","(N) ", & - "(N) ","(N�m) ","(N�m) ","(N�m) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(rad) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & "(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ", & "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(rad) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ", & - "(N�m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(rad) ","(rad/s) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(rad) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(rad) ","(rad/s) ", & "(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(rad) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ", & - "(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(rad) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(m) ", & "(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ", & + "(N-m) ","(N-m) ","(N-m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ", & "(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ", & "(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(rad) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N) ","(N) ", & - "(N) ","(N�m) ","(N�m) ","(N�m) ","(m) ","(rad) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ", & - "(N�m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(rad) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(m) ","(rad) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ", & "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(rad) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(rad) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(rad) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(rad) ", & "(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ", & "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(rad) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ", & - "(N�m) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(rad) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", & + "(N-m) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & "(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ", & - "(N) ","(N�m) ","(N�m) ","(N�m) ","(rad) ","(rad/s) ","(rad/s) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(rad) ","(rad/s) ","(rad/s) ", & "(rad/s) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ", & "(m/s) ","(m/s) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(rad) ", & - "(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(m) ","(rad) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(rad) ", & + "(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(m) ","(rad) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ", & "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ", & "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(rad) ","(N) ","(N) ", & - "(N) ","(N�m) ","(N�m) ","(N�m) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(N) ","(N) ","(N) ","(N�m) ","(N�m) ","(N�m) ", & + "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(rad) ","(N) ","(N) ", & + "(N) ","(N-m) ","(N-m) ","(N-m) ","(N) ","(N) ","(N) ", & + "(N-m) ","(N-m) ","(N-m) ","(m) ","(rad) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ", & "(rad) ","(rad/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(N) ","(N) ", & "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ","(N�m) ", & - "(N�m) ","(N�m) ","(rad) ","(N) ","(N) ","(N) ","(N�m) ", & - "(N�m) ","(N�m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", & + "(N-m) ","(N-m) ","(rad) ","(N) ","(N) ","(N) ","(N-m) ", & + "(N-m) ","(N-m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & From 0f3f7cd7694174958b7add58c2645fcc48bcc4cf Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 2 Jul 2020 11:36:59 -0600 Subject: [PATCH 231/377] Corrected a sign error on Dynamic Pressure term --- modules/hydrodyn/src/Morison.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 2b381c5f8..52fe69676 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2066,7 +2066,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ! Constant part of the external hydrodynamic dynamic pressure force if ( Amag > 0.0 ) then - p%DP_Const_End(:,i) = InitInp%Nodes(i)%JAxCp*An + p%DP_Const_End(:,i) = -InitInp%Nodes(i)%JAxCp*An endif ! marine growth mass/inertia magnitudes @@ -3086,7 +3086,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, qdotdot = reshape((/u%Mesh%TranslationAcc(:,J),u%Mesh%RotationAcc(:,J)/),(/6/)) m%F_A_End(:,J) = m%nodeInWater(j) * matmul( p%AM_End(:,:,J) , ( - qdotdot) ) - m%F_I_End(:,J) = m%nodeInWater(j) * (p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j))) + ! TODO: The original code did not multiply by nodeInWater, but should we? GJH + m%F_I_End(:,J) = (p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j))) ! Marine growth inertia: ends: Section 4.2.2 m%F_IMG_End(1:3,j) = -m%nodeInWater(j) * p%Mass_MG_End(j)*qdotdot(1:3) From c4e6ce75c78d0f107cfacbb235155ccdcfcbd107 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 2 Jul 2020 16:48:59 -0600 Subject: [PATCH 232/377] FlexSub: fix damping for pin joint (adding cross couplings) --- modules/subdyn/src/SD_FEM.f90 | 37 +++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 58a46f9d4..1668feb0b 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1574,6 +1574,11 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) ! --- Forming Tc do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) + do i = 1,size(Tc,1); do ie = 1,size(Tc,2) + if (abs(Tc(i,ie))<1e-13) then + Tc(i,ie)=0.0_ReKi + endif; enddo; + enddo; deallocate(Tc_rot) deallocate(Tc_rot_m1) @@ -1769,11 +1774,39 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) ! Ball/Pin/Universal joints if(StifAdd>0) then print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot - Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd + if ( JType == idJointPin ) then + print*,'>>>>>> Adding stiffness' + print*,'K (before)',Init%K(Ifreerot(1),Ifreerot) + print*,'K (before)',Init%K(Ifreerot(2),Ifreerot) + Init%K(Ifreerot(1),Ifreerot(1)) = Init%K(Ifreerot(1),Ifreerot(1)) + StifAdd + Init%K(Ifreerot(2),Ifreerot(2)) = Init%K(Ifreerot(2),Ifreerot(2)) + StifAdd + Init%K(Ifreerot(1),Ifreerot(2)) = Init%K(Ifreerot(1),Ifreerot(2)) - StifAdd + Init%K(Ifreerot(2),Ifreerot(1)) = Init%K(Ifreerot(2),Ifreerot(1)) - StifAdd + print*,'K (after)',Init%K(Ifreerot(1),Ifreerot) + print*,'K (after)',Init%K(Ifreerot(2),Ifreerot) + else + print*,'NOT READY' + STOP + Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd + endif endif if(DampAdd>0) then print*,'DampAdd, Node',iNode,DampAdd, Ifreerot - Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd + if ( JType == idJointPin ) then + print*,'>>>>>> Adding Damping' + print*,'D (before)',Init%D(Ifreerot(1),Ifreerot) + print*,'D (before)',Init%D(Ifreerot(2),Ifreerot) + Init%D(Ifreerot(1),Ifreerot(1)) = Init%D(Ifreerot(1),Ifreerot(1)) + DampAdd + Init%D(Ifreerot(2),Ifreerot(2)) = Init%D(Ifreerot(2),Ifreerot(2)) + DampAdd + Init%D(Ifreerot(1),Ifreerot(2)) = Init%D(Ifreerot(1),Ifreerot(2)) - DampAdd + Init%D(Ifreerot(2),Ifreerot(1)) = Init%D(Ifreerot(2),Ifreerot(1)) - DampAdd + print*,'D (after)',Init%D(Ifreerot(1),Ifreerot) + print*,'D (after)',Init%D(Ifreerot(2),Ifreerot) + else + print*,'NOT READY' + STOP + Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd + endif endif endif enddo From 2ae10489d8f267013f7e3bc0443a672d6cdf92a6 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 2 Jul 2020 20:43:44 -0600 Subject: [PATCH 233/377] FlexSub: Bug fix driver was not reading acceleration --- modules/subdyn/src/SubDyn_Driver.f90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index 372928e4b..6d334ee61 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -145,7 +145,7 @@ PROGRAM TestSubDyn ! Initialize the module CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() - CALL AllocAry(SDin, drvrInitInp%NSteps, 13, 'SDinput array', ErrStat2, ErrMsg2); call AbortIfFailed() + CALL AllocAry(SDin, drvrInitInp%NSteps, 19, 'SDinput array', ErrStat2, ErrMsg2); call AbortIfFailed() SDin(:,:)=0.0_ReKi ! Read Input time series data from a file @@ -154,7 +154,8 @@ PROGRAM TestSubDyn CALL GetNewUnit( UnIn ) CALL OpenFInpFile ( UnIn, drvrInitInp%InputsFile, ErrStat2, ErrMsg2); Call AbortIfFailed() DO n = 1,drvrInitInp%NSteps - READ (UnIn,*,IOSTAT=ErrStat2) (SDin (n,J), J=1,13) + ! TODO Add safety for backward compatibility if only 13 columns + READ (UnIn,*,IOSTAT=ErrStat2) (SDin (n,J), J=1,19) ErrMsg2 = ' Error reading line '//trim(Num2LStr(n))//' of file: '//trim(drvrInitInp%InputsFile) call AbortIfFailed() END DO @@ -198,9 +199,8 @@ PROGRAM TestSubDyn u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) IF ( drvrInitInp%InputsMod == 2 ) THEN - ! User time series have no acceleration for now.. - u(1)%TPMesh%TranslationAcc(:,1) = 0.0_ReKi - u(1)%TPMesh%RotationAcc(:,1) = 0.0_ReKi + u(1)%TPMesh%TranslationAcc(:,1) = SDin(n+1,14:16) + u(1)%TPMesh%RotationAcc(:,1) = SDin(n+1,17:19) ELSE ! constant inputs u(1)%TPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(1:3) u(1)%TPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(4:6) From bf216e66df3ab7809bf05207cf44887a293b9bb3 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 6 Jul 2020 19:01:26 -0600 Subject: [PATCH 234/377] FlexSub: adding pre-TCF SubDyn implementation --- docs/source/user/index.rst | 1 + docs/source/user/subdyn/.gitignore | 1 + docs/source/user/subdyn/Makefile | 112 ++ docs/source/user/subdyn/appendixA.rst | 13 + docs/source/user/subdyn/appendixB.rst | 12 + docs/source/user/subdyn/appendixC.rst | 9 + docs/source/user/subdyn/appendixD.rst | 104 ++ docs/source/user/subdyn/appendixE.rst | 7 + docs/source/user/subdyn/appendixF.rst | 122 ++ docs/source/user/subdyn/conf.py | 218 +++ docs/source/user/subdyn/figs/element-CS.png | Bin 0 -> 22763 bytes docs/source/user/subdyn/figs/flowchart.png | Bin 0 -> 114443 bytes docs/source/user/subdyn/figs/flowchart2.png | Bin 0 -> 103029 bytes docs/source/user/subdyn/figs/global-cs.png | Bin 0 -> 1444752 bytes .../user/subdyn/figs/self-extractor.png | Bin 0 -> 23998 bytes docs/source/user/subdyn/future_work.rst | 42 + docs/source/user/subdyn/index.rst | 32 + docs/source/user/subdyn/input_files.rst | 490 +++++++ docs/source/user/subdyn/introduction.rst | 122 ++ docs/source/user/subdyn/modeling.rst | 312 ++++ docs/source/user/subdyn/notations.rst | 670 +++++++++ docs/source/user/subdyn/output_files.rst | 126 ++ docs/source/user/subdyn/references.bib | 119 ++ docs/source/user/subdyn/running_sd.rst | 109 ++ docs/source/user/subdyn/theory.rst | 1283 +++++++++++++++++ docs/source/user/subdyn/zrefs.rst | 9 + 26 files changed, 3913 insertions(+) create mode 100644 docs/source/user/subdyn/.gitignore create mode 100644 docs/source/user/subdyn/Makefile create mode 100644 docs/source/user/subdyn/appendixA.rst create mode 100644 docs/source/user/subdyn/appendixB.rst create mode 100644 docs/source/user/subdyn/appendixC.rst create mode 100644 docs/source/user/subdyn/appendixD.rst create mode 100644 docs/source/user/subdyn/appendixE.rst create mode 100644 docs/source/user/subdyn/appendixF.rst create mode 100644 docs/source/user/subdyn/conf.py create mode 100644 docs/source/user/subdyn/figs/element-CS.png create mode 100644 docs/source/user/subdyn/figs/flowchart.png create mode 100644 docs/source/user/subdyn/figs/flowchart2.png create mode 100644 docs/source/user/subdyn/figs/global-cs.png create mode 100644 docs/source/user/subdyn/figs/self-extractor.png create mode 100644 docs/source/user/subdyn/future_work.rst create mode 100644 docs/source/user/subdyn/index.rst create mode 100644 docs/source/user/subdyn/input_files.rst create mode 100644 docs/source/user/subdyn/introduction.rst create mode 100644 docs/source/user/subdyn/modeling.rst create mode 100644 docs/source/user/subdyn/notations.rst create mode 100644 docs/source/user/subdyn/output_files.rst create mode 100644 docs/source/user/subdyn/references.bib create mode 100644 docs/source/user/subdyn/running_sd.rst create mode 100644 docs/source/user/subdyn/theory.rst create mode 100644 docs/source/user/subdyn/zrefs.rst diff --git a/docs/source/user/index.rst b/docs/source/user/index.rst index 125a16da8..f29a8c664 100644 --- a/docs/source/user/index.rst +++ b/docs/source/user/index.rst @@ -15,6 +15,7 @@ Details on the transition from FAST v8 to OpenFAST may be found in :numref:`fast api_change.rst aerodyn/index.rst beamdyn/index.rst + subdyn/index.rst fast_to_openfast.rst cppapi/index.rst diff --git a/docs/source/user/subdyn/.gitignore b/docs/source/user/subdyn/.gitignore new file mode 100644 index 000000000..fe560c00f --- /dev/null +++ b/docs/source/user/subdyn/.gitignore @@ -0,0 +1 @@ +_build* diff --git a/docs/source/user/subdyn/Makefile b/docs/source/user/subdyn/Makefile new file mode 100644 index 000000000..081d13e38 --- /dev/null +++ b/docs/source/user/subdyn/Makefile @@ -0,0 +1,112 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +all: pdf + +doc2rst: + pandoc -F pandoc-crossref -F pandoc-citeproc -s -t rst --toc SubDyn_Manual_Rev037.docx -o output.rst --bibliography=references.bib + +# --wrap=preserve +# -F pandoc-crossref +# -F pandoc-eqnos +# --number-section + + +help: + @echo "Please use \`make ' where is one of" + @echo " pdf to make pdf from LaTeX files (uses latex)" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf _build/* + +pdf: latex + cd _build/latex && make all-pdf + +pdf-compile: + cd _build/latex && make all-pdf + +pdf-html: pdf html + cp _build/latex/sampledoc.pdf _build/html + + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml + @echo + @echo "Build finished. The HTML pages are in _build/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in _build/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in _build/qthelp, like this:" + @echo "# qcollectiongenerator _build/qthelp/sampledoc.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile _build/qthelp/sampledoc.qhc" + +latex: + cp -r figs _build/latex + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex + @echo + @echo "Build finished; the LaTeX files are in _build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes + @echo + @echo "The overview file is in _build/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in _build/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in _build/doctest/output.txt." + diff --git a/docs/source/user/subdyn/appendixA.rst b/docs/source/user/subdyn/appendixA.rst new file mode 100644 index 000000000..fbedf80d7 --- /dev/null +++ b/docs/source/user/subdyn/appendixA.rst @@ -0,0 +1,13 @@ +.. _sd_appendix_A: + +Appendix A. OC4 Jacket Input File +================================= + +SubDyn's primary input file +.. :download:`(OC4 Jacket SubDyn's Input File) <./examples/OC4_Jacket_SD_Input.txt>`: + +This file includes information on the integration method (e.g., Adams-Bashforth 4 :sup:`th`} order), +numerical-solution parameters (e.g., integration time interval, static solver flag, numer of modes to retain within the Craig-Bampton reduction), +finite element analysis information (beam element model, number of elements per member), +and the geometric definition of the beam members via joints, member connectivity, and member cross-sectional properties. +This file also specifies any SSI input files (soil/pile stiffness and mass matrices). diff --git a/docs/source/user/subdyn/appendixB.rst b/docs/source/user/subdyn/appendixB.rst new file mode 100644 index 000000000..f4d316669 --- /dev/null +++ b/docs/source/user/subdyn/appendixB.rst @@ -0,0 +1,12 @@ +.. _sd_appendix_B: + +Appendix B. OC4 Jacket Driver File +================================== + +SubDyn's Driver Input File +.. :download:`(OC4 Jacket Driver File) <./examples/OC4_Jacket_SD_Driver.txt>`: + +This file includes information on the environmental conditions (gravity and water depth), +numerical-solution parameters (e.g., integration time interval, numer of time-steps), TP reference point coordinates in global reference frame, +rotation angle of the structure geometry in degrees about the global Z axis, the input mode for the TP reference point displacements, velocities, and accelerations (steady-state or time-series from file) and any related input +file if not steady-state input. diff --git a/docs/source/user/subdyn/appendixC.rst b/docs/source/user/subdyn/appendixC.rst new file mode 100644 index 000000000..51b600e42 --- /dev/null +++ b/docs/source/user/subdyn/appendixC.rst @@ -0,0 +1,9 @@ +.. _sd_appendix_C: + +Appendix C. OC4 Jacket SSI Input File +===================================== + +SubDyn's SSI File +.. :download:`(OC4 Jacket SSI File) <./examples/OC4_Jacket_SD_SSI.txt>`: + +This file includes information on the stiffness of embedded-pile/soil combination. diff --git a/docs/source/user/subdyn/appendixD.rst b/docs/source/user/subdyn/appendixD.rst new file mode 100644 index 000000000..e2bcbab59 --- /dev/null +++ b/docs/source/user/subdyn/appendixD.rst @@ -0,0 +1,104 @@ +.. _sd_appendix_D: + +Appendix D. List of Output Channels +=================================== + +This is a list of all possible output parameters for the SubDyn module. +The names are grouped by meaning, but can be ordered in the OUTPUT +CHANNELS section of the SubDyn input file as the user sees fit. :math:`M \alpha N \beta`, +refers to node :math:`\beta` of member :math:`\alpha`, where :math:`\alpha` is a number in the range [1,9] and +corresponds to row :math:`\alpha` in the MEMBER OUTPUT LIST table (see Section ) and +:math:`\beta` is a number in the range [1,9] and corresponds to node :math:`\beta` in the +**NodeCnt** list of that table entry. + +Some outputs are in the SS reference coordinate system (global +inertial-frame coordinate system), and end with the suffix `ss`; others +refer to the local (member) reference system and they have suffixes +"Xe", "Ye", or "Ze" (see Section 7). + +Table C-1. List of Output Channels. + ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| Channel Name(s) | Units | Description | ++=======================================+==============================================================+=====================================================================================================================================+ +| *Base and Interface Reaction Loads* | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| ReactFXss, ReactFYss, ReactFZss, | (N), (N), (N), | Total base reaction forces and moments | +| | | | +| ReactMXss, ReactMYss, ReactMZss, | (Nm), (Nm), (Nm) | at the (0.,0.,-**WtrDpth**) location in SS coordinate system | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| IntfFXss, IntfFYss, IntfFZss, | (N), (N), (N), | Total interface reaction forces and moments | +| | | | +| IntfMXss, IntfMYss, IntfMZss, | (Nm), (Nm), (Nm) | at the TP reference point (platform reference point) location in SS coordinate system | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| Interface Kinematics | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| IntfTDXss, IntfTDYss, IntfTDZss, | (m), (m), (m), | Displacements and rotations of the TP reference point | +| | | | +| IntfRDXss, IntfRDYss IntfRDZss | (rad), (rad), (rad) | (platform reference point) location in SS coordinate system | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| IntfTAXss, IntfTAYss, IntfTAZss, | (:math:`{m/s^2}`), (:math:`{m/s^2}`), (:math:`{m/s^2}`), | Translational and rotational accelerations of the TP reference point | +| | | | +| IntfRAXss, IntfRAYss IntfRAZss | (:math:`{rad/s^2}`), (:math:`{rad/s^2}`), (:math:`{rad/s^2}`)| (platform reference point) location in SS coordinate system | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| *Modal Parameters* | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SSqm01-SSqm99 | (-) | C-B modal variables (up to first 99) | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SSqmd01-SSqmd99 | (1/s) | First time-derivatives of C-B modal variables (up to first 99) | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SSqmdd01-SSqmdd99 | (:math:`{1/s^2}`) | Second time-derivatives of C-B modal variables (up to first 99) | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| *Node Kinematics* | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` TDxss, | (m) | Nodal translational displacements of :math:`M \alpha N \beta` | +| | | | +| :math:`M \alpha N \beta` TDyss, | | | +| | | (up to 81 designated locations) in SS coordinate system | +| :math:`M \alpha N \beta` TDzss, | | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` RDxe, | (rad) | Nodal rotational displacements of :math:`M \alpha N \beta` | +| | | | +| :math:`{M \alpha N \beta}` RDye, | | | +| | | (up to 81 designated locations) in member local coordinate system | +| :math:`{M \alpha N \beta}` RDze | | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` TAxe, | (:math:`{m/s^2}`) | Nodal translational accelerations of :math:`M \alpha N \beta` | +| | | | +| :math:`{M \alpha N \beta}` TAye, | | | +| | | (up to 81 designated locations) in member local coordinate system | +| :math:`{M \alpha N \beta}` TAze | | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` RAxe, | (:math:`{rad/s^2}`) | Nodal rotational accelerations of :math:`M \alpha N \beta` | +| | | | +| :math:`{M \alpha N \beta}` RAye, | | | +| | | (up to 81 designated locations) in member local coordinate system | +| :math:`{M \alpha N \beta}` RAze | | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| *Node Forces and Moments* | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` FKxe, | (N), | Static (elastic) component of reaction forces and moments | +| | | | +| :math:`{M \alpha N \beta}` FKye, | (N), | at :math:`M \alpha N \beta` along local member coordinate system | +| | | | +| :math:`{M \alpha N \beta}` FKze | (N), | | +| | | | +| :math:`{M \alpha N \beta}` MKxe, | (Nm), | | +| | | | +| :math:`{M \alpha N \beta}` MKye, | (Nm), | | +| | | | +| :math:`{M \alpha N \beta}` MKze | (Nm) | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| :math:`{M \alpha N \beta}` FMxe, | (N), | Dynamic (inertial) component of reaction forces and moments | +| | | | +| :math:`{M \alpha N \beta}` FMye, | (N), | at :math:`M \alpha N \beta` along local member coordinate system | +| | | | +| :math:`{M \alpha N \beta}` FMze | (N), | | +| | | | +| :math:`{M \alpha N \beta}` MMxe, | (Nm), | | +| | | | +| :math:`{M \alpha N \beta}` MMye, | (Nm), | | +| | | | +| :math:`{M \alpha N \beta}` MMze | (Nm) | | ++---------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ + diff --git a/docs/source/user/subdyn/appendixE.rst b/docs/source/user/subdyn/appendixE.rst new file mode 100644 index 000000000..888f6e618 --- /dev/null +++ b/docs/source/user/subdyn/appendixE.rst @@ -0,0 +1,7 @@ +.. _sd_appendix_E: + +Appendix E. Compiling Stand-Alone SubDyn +======================================== + +See the FAST documentation for instructions on how to compile SubDyn coupled to FAST. +Future versions of the manual will include compiling instructions for building the stand-alone SubDyn program. diff --git a/docs/source/user/subdyn/appendixF.rst b/docs/source/user/subdyn/appendixF.rst new file mode 100644 index 000000000..2893f5b08 --- /dev/null +++ b/docs/source/user/subdyn/appendixF.rst @@ -0,0 +1,122 @@ +.. _sd_appendix_F: + +Appendix F. Major Changes in SubDyn +=================================== + +When first released, SubDyn (v0.4) was included as an undocumented +feature of FAST v8 and packaged as a stand-alone archive. Since v0.4, +SubDyn has been well integrated into FAST v8 and OpenFast, and the stand-alone form is +also available. This appendix outlines significant modifications to +SubDyn made since v0.4. Following are the main changes that the user may +notice, but for more information, refer to the *changelog.txt* text file +within the official archive and the GitHub log. + +V1.03.00a-rrd (September 2017) +------------------------------ + +- Version 1.03.00a-rrd integrates with the `OpenFast software `__. + +- Inclusion of soil-structure interaction (SSI) via flexible degrees of fixity at the restrained nodes and a new input file that allows for 6x6 stiffness and mass matrices that simulate boundary conditions at those nodes. + + +V1.01.01a-rrd (September 2014) +------------------------------ + +Version 1.01.01a-rrd integrates with the `FAST v8 +software `__ +v8.09.00a-bjj. + +- Finite-element eigenvalue bug fixes: the full system eigenvalues were + incorrectly reported in the summary file, although with no further + consequences on the results. This bug is now fixed. + +- Shear area correction factor improvement: the shear area correction + factor in the Timoshenko treatment is now aligned with Steinboeck et + al. (2013). + +- The formulation for the TP reaction has been rearranged to adhere to + the theory manual, with no consequences on the output results. + + +V1.01.00a-rrd (June 2014) +------------------------------ + +Version 1.00.01a-rrd integrates with the `FAST v8 software `__ +v8.08.00c-bjj. + +The new implementation has well-defined data exchange interfaces +(`following the FAST modularization +framework `__) +that should make integration of SubDyn into other multiphysics software +packages much simpler. + +Several improvements and bug fixes have been implemented since version +v0.4 and the module has undergone an extensive verification effort with +good results. + +- Eigensolver bug fixes: the LAPACK solver proved to be unstable in + single precision, and now it is solely run in double precision, + regardless of the precision used in other parts of the code. + +- The input file format has changed. Please refer to the sample input + file in Appendix A and the following notes: + + - First header line has been removed. + + - Simulation Control Section: + + - **SDeltaT**: The "DEFAULT" keyword (in place of 0.0) is now + used to indicate that the glue-code time step will be used for + time integration by SubDyn. + + - **IntMethod**: Allowed values are now 1-4 (in place of 0-3). + + - **SttcSolve**: New flag introduced. If set to TRUE, the + static-improvement method (SIM) will be used. + + - FEA and Craig-Bampton Parameters Section: + + - In v0.4, the damping coefficients had to be specified for all + retained Craig-Bampton modes, or just once for all the modes + (if **CBMod** = FALSE). In this version, the user can input + any number of damping coefficients. In case the number of + retained C-B modes (**NModes**) is larger than the input + number of damping coefficients (**JDampings**), the last + damping value will be replicated for all the remaining modes. + + - Base Reaction Joints, Interface Joints, Member, and Member Cosine + Matrices Sections: + + - One line with units, below the headers, is expected in all the + tables of the input file. + + - Output: Summary and Outfile Section: + + - This section now also contains the parameters previously + assigned under the Section titled "Output: Fast/Subdyn + Output-File Variables" + +- Some of the quantities in the summary file have been fixed. Some of + the output matrices were, in fact, being output with wrong values + because of an index mismatch. The new summary file is shorter and + does not contain some of the CB method matrices, unless the compiler + directive, DEBUG, is set. + +- SIM. This new implementation helps minimize the number of needed + modes to capture the contribution of certain loads (such as static + gravity and buoyancy loads or high-frequency loads transferred from + the turbine). In the previous version, a large number of internal + modes were needed to engage substructural modes excited by static and + high-frequency forces. These modes are no longer needed and fewer + modes can be retained while still achieving accurate results (see + also Section :ref:`_subdyn-theory`). With SIM enabled, all modes that are not considered + by the Craig-Bampton reduction are treated quasi-statically. + +- There is now the possibility of retaining no internal C-B modes, thus + relying solely only on SIM, in those cases where the substructure`s + first eigenfrequencies are much higher than the expected + energy-containing modes of the entire system. + +- The coupling of SubDyn within FAST now includes full hydro-elastic + coupling with the HydroDyn hydrodynamics module. + diff --git a/docs/source/user/subdyn/conf.py b/docs/source/user/subdyn/conf.py new file mode 100644 index 000000000..782fc254c --- /dev/null +++ b/docs/source/user/subdyn/conf.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +# +# OpenFAST documentation build configuration file, created by +# sphinx-quickstart on Wed Jan 25 13:52:07 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys +import subprocess +import re + +#sys.path.append(os.path.abspath('_extensions/')) + +readTheDocs = os.environ.get('READTHEDOCS', None) == 'True' +sourcedir = sys.argv[-2] +builddir = sys.argv[-1] + +# Use this to turn Doxygen on or off +useDoxygen=False + +# This function was adapted from https://gitlab.kitware.com/cmb/smtk +# Only run when on readthedocs +def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): + dx = open(os.path.join(sourcedir, doxyfileIn), 'r') + cfg = dx.read() + srcdir = os.path.abspath(os.path.join(os.getcwd(), '..')) + bindir = srcdir + c2 = re.sub('@CMAKE_SOURCE_DIR@', srcdir, \ + re.sub('@CMAKE_BINARY_DIR@', bindir, cfg)) + doxname = os.path.join(sourcedir, doxyfileOut) + dox = open(doxname, 'w') + print >>dox, c2 + dox.close() + print 'Running Doxygen on %s' % doxyfileOut + doxproc = subprocess.call(('doxygen', doxname)) + +if readTheDocs and useDoxygen: + runDoxygen(sourcedir, 'Doxyfile.in', 'Doxyfile') + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.5.2' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.mathjax', + 'sphinx.ext.intersphinx', + 'sphinxcontrib.doxylink', + 'sphinxcontrib.bibtex', + ] + +autodoc_default_flags = ['members','show-inheritance','undoc-members'] + +autoclass_content = 'both' + +mathjax_path = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' + +# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ['.rst'] + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'SubDyn' +copyright = u'2017, National Renewable Energy Laboratory' +author = u'OpenFAST Team' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'1.0' +# The full version, including alpha/beta/rc tags. +release = u'1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +#If true, figures, tables and code-blocks are automatically numbered if they +#have a caption. At same time, the numref role is enabled. For now, it works +#only with the HTML builder and LaTeX builder. Default is False. +numfig = True + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs +if useDoxygen: + if readTheDocs: + html_extra_path = [os.path.join(builddir, '..', '..', 'doxygen')] + else: + html_extra_path = [os.path.join(builddir, '..', 'doxygen')] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' +html_logo = '../../../_static/openfastlogo.jpg' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Openfastdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'SubDyn.tex', u'SubDyn Documentation', + u'National Renewable Energy Laboratory', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'subdyn', u'SubDyn Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'SunDyn', u'SunDyn Documentation', + author, 'SunDyn', 'One line description of project.', + 'Miscellaneous'), +] + +def setup(app): + app.add_object_type("confval", "confval", + objname="input file parameter", + indextemplate="pair: %s; input file parameter") + app.add_object_type("cmakeval", "cmakeval", + objname="CMake configuration value", + indextemplate="pair: %s; CMake configuration") + diff --git a/docs/source/user/subdyn/figs/element-CS.png b/docs/source/user/subdyn/figs/element-CS.png new file mode 100644 index 0000000000000000000000000000000000000000..08f7775e8acee5cfb7a55b8a438d89c5bd0c138b GIT binary patch literal 22763 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 Pazj@q_r2A-gDL+7j@H@Q literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/figs/flowchart.png b/docs/source/user/subdyn/figs/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..275441f20e594069133a297b1317a8238779f9f1 GIT binary patch literal 114443 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/figs/flowchart2.png b/docs/source/user/subdyn/figs/flowchart2.png new file mode 100644 index 0000000000000000000000000000000000000000..558465d425cf6ebbf4e64004a04acba6bb9136da GIT binary patch literal 103029 zcmZs@bzGED*EVXAA~hl+ATSIJl1ev%12V)QNJ=+IBQ>O?3?)NK3`j_~bP6Kf-5t^? zg4DT3pXYtQ@0{}oKOAP?d#`)#wO3r%+M-?|Ufv^oM0n%IjeBren97YCcU}NLPw{bY z+_;I{`AiLbar2$ZOQ{=0eKZ@uhdbtyijp^OlzzN>VTc2KCa{;)dUxXnB{}xzrg`cR zFvay3I80L2O>g_sWB;*Q!rr~}_)M2x1y6R&zW6Rpm*IyT54@B~JJEVXW!T!R&_f~% zr~UBA$OZo(s({q=3t1^|Vb;Y@%8|kTC>Gp1a2UZ&sc$c6WKs>Bh=h&XniG0Bt+G!z z^9vFWi*vot>xMMUe{JTU@9x$q&;%0N10r8+1y+~_`^9F z10pvEk|NP1QKUmSN9xuh4;8aY{H3DP45oXuYivGtmRp>6*?M?^nlDzhIluWjlN4c~ z!;z|Ydd%Z{wM$JYyPnz{YS?HQ#(zkZeAJ^`v!hj-pOh6RGPv-$Pq${(br7YXM%Z~f zZ8lUZ_Rg>h9Kta?Fte)d9WH7xv{;r7p&~pQxAxKEg$K_EQ!+w8>f}-#rvuTXv30gu z)EY#<$IWkzdCYhDp6(EbcVcaN!PS( zRE>I_jbQ5fT*=y5t+?I#tnX%b$jb;i30u}X5F`%|4|9X{WLZEV2m9B16Eo!|RdLUB-Cl;~-%$XzvZm8kUI zaFW=SrQhryyq+jY5x%O33eZB$EBoorX-2Ud&LSsbAqr(R8&UOgMq8~Y5Hnp99x;vV z1f!V8i8W7LYsyP&-oVwG>J*a=9CEXW$b{IvP{hqN#ji$qKy0kv}iSWqI&rsh0LgA=P`LhE7hzT zL#8L+s#7v8rStn+ZEPP#^FF8E;j!CCqs!Ic1Jhk{OHXXnqMll|u4S184b1?8ce#

Fp*!cUipModTpgTcQoKoza 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/figs/global-cs.png b/docs/source/user/subdyn/figs/global-cs.png new file mode 100644 index 0000000000000000000000000000000000000000..faca86ab9efbb5d1cda4644c88a342009bb417c0 GIT binary patch literal 1444752 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/Sd%DG-x6Y7 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%0DX1xLXCt- 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

*s1yqMABC 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 q`Nam!i8d%=c#*CxaqY;j^xejxj9AYCw$AhH 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

KR(B3fG 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

q9Q`%Q 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 ssQA=w%ro20(4Y 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%0A#4EVZ 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%0AaOWT#%973+ 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%0A!ipXWd*n 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


GbA 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∓G^8z-z#ujyX>``erq;Y6c|40 zE@1$xa=Odh=+U*jH`hHbHF5tFa;!Bj)%fEU9JPt@kYQ95$J-XGMP+|yM5@68=Kc7A7lVkPmS=YESn zCrZ^=Oy~vU>3;iIe7sR;^0lJGIK2`jM6|9CGn5My>!&J&-eJR?eg0qjlW|cV85HI!t61xTnYr-BHa-Sow3p1` zcMXmP8!NK0k)ZWC`isBrA8q1R9s>4w7dG2?{18CvJXSC&@fvIP)%ixOceqB`%$wNf zQzVUK0d>`Ru20vPAAXzy<@wnaG`MVvP%eJ`uy2uJReyOJf(eX(Kw)sDL z=WqQr$WB;o?I119k}4l~i(qi6qrSaH|5-0#1c6=%>8lbPe(j6=_4I8&cL6rIaZ|H@ zzfKQ@Eoi`dgRDCmFntKvD7OxKZCVMR$AsS6$v|55ydzk-N2=wz_oJ6adOk{Z!yS-9 z9fpuIfwq%Y<#}2@lmoi^DS6@+cS)Y~t4gr#$gQ_2Z$+7&+s6A_NMD}S0$NXe=ywpg zOe;Sz%-)0mNauesRAC%#KJhc!2sf}7TWH`D;q!+lZAtE$*Z-Xa|GcQZ|MO;ivNd@Q zwHuF`Sa`uf zVi1jB$g0^HzVcf4(rtGI)%`|l3-z9JPFdt(&iplwG<&wt`j2pLez_UaW)coEru zS%UlT5AVq#QMwybwQE<6mJQLvHOI%R<3e=fHjMGEIq#1?*K`~Cz|8kAoxFu78Sp<4 zMU1QC`QgB^_m1`6{R)vDlG0|Hny9%{YDu)_e6x3paRGL6K&-g^#0)=q>K*~Mg0<&u+8GX^i?_=uxINFvtMbcQ-#?S$-`lhV}9FzP6C^;ir2R;&h-w>>4pH4~aU zw)Vv#Flto#u*NaS?Gqfzs4P2N9r~;xn42@HQR(pxXUQHn2Z|ejXF!p2XFbVV*|gcT zewE^Ke@lVgpyzTLTp94}q9~D`@oRB_p8Tpy5ZShX{XIW*+*z%{wv>2DlI>!jTxHA% zA;EDM_w%B$ZG%b%(54?2@m!6gEeqt9H$OSLw8Bb*2DbpO7&x~EVRTElu0Qp=Dy|X! zt#X~hZPWYB$5iBYNKyevFthgar0fdkSKHFNt(M#?WUvTxbM zkl6Ptuacye)Q8fxNb&gC0>+!*9>M?($@yR{?5!lW=0?#kb-T`?sYKzP?M_5qV2OP= zSymREE)|{Gt}QeU^pODUYUS)`IWjGVx9k}97FBH1P+Qa@$2PoQ0Jg9|H?sBD`>U#NyB5f3?FgyG7?a2R#pNIRuQY@QzOw4*%b zZ?{16HLaew?%oYq--%IRxw1ABHQ$nzq9+%mYq&7VrY#WSx2|IjYE2w{M7_o;r+c{*fPU0*x1U>_92 zxQDbUTvHPbI3~UJD?eUQZOArV3tdpT*sL$|_-BKVb0!7iIJ8yQs~%OMWnvReSNtKD zy&pVY7RW25TXu#<3Va({SEL`7QlC6qg=0=4tf&txVG6ivz-}K(?s?l7E_V-m+US41 zA~|=597)`D3Kn|UU=`T+GBPrcD8KgQA%8|#?+A0yu}D~4+l5U*>AVsKyr!ka7LM6p z?akAQyk4>AV&`qRbB1B3aRz64GeBO?lovpE+@mSBYr{)EP^PM7`bvqy6)Shm zve#(;=B|gBPu;;t{5v}p468rvsM4ihdd`TeYsgD_aR=L9GyJ3JVyg?$<%0!Ze)2g4 zRFo{c%AVs!IREl>IPm-GxI6`-D2oL5Jl&MJ+7yE2$58mR7-qH4`32X*3N|R*thhiX z_fwT54E#_Wt`TX@mn%Xc!0RuSH+sHQClTNY==S>h(aO-YRR%9l76VTZ+!F|wn6zA) zO=9XvVH(#?P8E1-0r>3PH<2$Pg6wMG@*X14ld#$PoyafHth2JJImfK}@LxFZj@$F~ zz6jUKyBFSGR>G_J@K&y#pmx+$qSW5W{ImR0CaU4(-fkJ>KdYDv8L>|~0~fHwt95S7FS;s2ggV3$e=&;Y z^;YnCsIF?MmyU(YeqR^KAFUe@vGOKke%U#bCiJr%$$pKs+nKPk>>`G58-s%~5~*}L8sWNBx0Av) zr<`wC&qPbe(7)*|U*pnvP2Zp0lktkJbJzaggDt^;EX0c_WFjPutNL+f;Fos@LjO!d z`&N12!PCqKE}J$pH4kcQAPi&!U;Gbxy0<6h9>-+FKm8nwS~<2F;F;f99u+s>|K)eI z5YmGw-&pY@R$2g8EX0Z-7HujUa6a4lZ4z;=u$cc5JZ<4i#6Po?%Rse(gDsPIvD0bS zR+9*aOq)40cU@&;Z0g_t&@@D>O?Uj#VE#Okq?n)cp+tff5b-6+N#``d9++*xd^Sdp zFvgf1n=PG#k?gGlJ4J!@%$da#sY&R%u((0Clk{X=WAi1H)FV4961WT|H`YLqr{Bj? zBmo@kONp#7*77B(xTnmF&gNW0w{hCI_}tZ^cNCWB!l%!*x)BSNZ*DBErhV`)b@9bp z8Y}1^KujzyYL4eFgMSrAM`JPI&bL=#w|&-q7+rKnHl5qgA0@fCc2_vMIxVd6T!8aH zgsF9!w*UctpVlEPe}`Z5@l#q}9w7e%2vYpV#@)>q7^@iySf0wL^j1bMh(1vWSclEI zg|95Q_s{L)j7f}ky;K)X`n3`z$@p$x!glM9A=eF-+6nT-M07eo)>K2lvi=WzUwNAt z&S=XG^Bueq{^Qh>v4gR0T6B(`0!S0yT@RmmRn@Of7q?chMtzs~ZGNLFdSe559XiAL zEXr(bq)jSlrIP9lZ^pdnwUX#HNY|a1K8Nk!0!JS=kcU(avcCOS;%@pSyyc>UIGz!C zBl!u;=Hmn*)AVodIl+5ugPXQ~J(ytrvaGJ z9TOqm(|)za_fqnLyna1!;EQgtyvIGB=`MC0EGQ3+OptBEV1lCGGufvv-FJCG31b|d zMN}P4D>zm=e2bpx@zo22v{q`tRv4S_U{PKPkjG+3E)*R1oGrlg?{EM8!mc}Oek!3? zzEClTrHN4M9!>ztr&jK3dDz$6_-@>1#}WxQ=UDG1{_=ZUBE?qaNO1e0rjt_3gD&C}Fg|d8quMy|c?tvIHpXKHAk-L52Af1qQ}aja}{_EsXDP#~ydQ zxReRcu5dr|G?XGkQ^M;3fsqMUKbpxDGQ3^53HSzB1p%z^xHBc^@Oh@q|DuE2Z;;-z zMZV|~k>QK46-2ZC6R zui2SuFBV5wdC`f=&rU6adX?7+e=Ph2ZQr!Nk7_%|WK(dzgXFGb_50!vOt%nGn%Sb%8JIMiXR#X-7`3?CE11E2-Iz)E%6X7 zgS|t{pVe4~>$tMx1llE%lKMWWoLKKJ-s`<;#DrT@{z4CF+C9kizD&7fG_YQAWM%Q7 zFz83RScF=G1ofnRa%ap04b8C}Sjntqq6Ef{n`k>&C#s}K0T0Ai-R`l5@G;tpEgiKV z%c)uhTE3I>LUOIb!n=GSRp@0Cz_3Z={?^oAoztJ|ivJSqkN;chkIz22Ffgaimr9@Z zecQ6*%4e}x)LjpNlKyTVFWnq=A@20Y+aF!^LL@@Rpi!3P$8&05*ITns!uIYPUJ_42 zk8)K2N3!j?Ys5}hJ~wdFq_XPu3JP8C*0s*vYi5M&VR9%Axq3i>*@DL2lJ4D6;i6bm zEyjID|Ml@ZJN!&8FGm5Mfu8TNScP;ceRCf7UTC&r@?i$J7yak={mbvSJUOjy|7XqF z{*LQ;JI`Lm=K*KEmkS8V^SrgUPfRx}@UxAev9YHuq!g>bR!x9Uw{^Lb_N2IM2-;iW zu&xe+Wip(ycsEzkS4vy#QyD4heie1LP$&=oN+datxR5Hg3m(z7l(#2&;dQN0S{*$A zP~|cBy7b1#7#B`+B6oOLKa*9h0$^-#EsN=Z>2Az!lr?yOxz6Cxkth8@+IYU^Di*os z#!n{2?E0TJ^WO`eGs>yB-D9zSK>obMOIhbxeH)wVxhjW5%O`zLjPdb)+2SV>%63WB zohJurN_o!Q?hv zX(w}`zB2m`0mv`1TpMT0QVmr6_PD^4AGW6J57ZAUQc4xN>wRs@_+D|mVQlZKPu^%I zpV}WHg)|BS<=@WqpRP515^c{KMy{te8_yIdNB6h~0votKEb;t)Sm+;|LE*?c^7kma zmIMb=>{>}t!T}o9@&K6uV_=mA0c}G<7(NVTON{;|9`Zh+Q~)*)8sn<0h2n)q30yz*U{C^U+8&DK&~XdUaSOr_q*ZTdDpY zporhS3#tudPm3C07>XY9fq};59jsVI>nrc0?}73k2WNBDL=AR!gr|dk$jj_Q^3H7w z$v`CY-#LHxW+o>&SzK;usPv*0p5=O@C@kRTfpqh@;Y?3SU~P@Wms=M~Bui7h>Ta$c z-adT<8n#(Qa^@g39sZ&w1LhaYf1d9ezJB3>T98lb>KyUU`_kuZd`51oh?qeJi!oFG z^QnzW8BEVi>>B>-dwvHy5c+BX6OQn>%*Xr8gjiF2XX$B%P5kUwx3_~c&sxs2)xI}e zDKd(vnI`$RzMzE|{|o!xVhaSY<+Ukg3RgzotEg}uzDFC@U;7<@vc_zC-t-=mcI5|t z`?5UjVzU99!U^j!&_69$j}PXB{qUmNVWS`|(H_hR>ml))$(apLYy3>SvMMLyf+yah z^EIHNXR0I3w8kS*;$sh$*?{pI=R*)If8KL~ zlX~K|cX@sP);qUVi}Io0M!(9=)o4UuyeN*$DQBec9Q7)(aLrQ$Ak`vsUigN?lYv2NKbu!d-`GBpN|5=(+MXo9^D13YTfxS?P#maON zUCgRGHm*FgY+NRM?d}ejt@?o4z{|hBCP3ah#qK%MJ)|gC^PI^mn9iNEUeN_cu!o6r zn8%bPi>g9N?BcbBv&nJ)MH)vXIOLIb|F0|SwgYMb`u?6E11?=*X`{Xc)!o4P-7~Qd zyg+Oy=ICm8!hHI{$A64_Sw|$s<1m}*`E0&!2D#sCp7#JGn~6KdqCf992=K@cHhm2< zAzC_9IJx#s66Izky8^oqFP&5Pqy*sXpA3X9Jel0CNj%6fc=mLM(-w$AG;G-Ls|pO$ zAM!EpUXJMYJ9@sn$yFZhUX~5p`fU#UM1@mVFf{XZ#k@*@frZ-FrhZZrKU%r(tA>VQy!>d<+k_t@Ts6kMGq)yg<6mC` zPFIBUxUyO`ZxF&!Gloc|MR6HfD7Eb}hPa zjhvNfE{*Q=U|KiiN6t*OLM<3Zm1mpXQ~tZvxqg8_>%XlMh#m_65VOlOE3 z*OL`&^LY<}vJs|X8$Jj3;dub3VpZ#EI7{41;S%XP7Tm)SYP|E)kJ7{jg4$n6%>qsUA*XCf@(S)sEIK6kN+zA@EAJ0WEC&jBR4WEz9#nFd1G(Q>9WZR4mU zlSk`xr^tzbb-(J&xfdBe=g8i~if+f`##Yzk$K*Igt1KarG%`@^qyE3F#^ra7n)9RP zfim6e6;Dm2S+rRGX`fzM(6Jros-K&@mNt(lwWVN@goqG2pLk<}lV=t) zt(R$G`|OZ&U{OV7&U8Yh0Sx}F=c1WRXK_dP{S*pvN&aMurqosnG~`|774Ep;-u)>t zfr2J2TzsNyjn_v_qsM-3AC%t8ef{Lx!)Z1l^cpTV5RYM`))hR_#dmZM=5Fq)LYY8F?`8zi zG5hq=`tk4n2==xUS!3jqD{-+O{YTVj@1FQ}M{iALdh@YbHs)dc)!Ucvv!sHi-bm~n zWFI}f#XZ=LNu(Wc;4TlJd?oI5WHan$SAsL)K)kqB_-unbM&a-gkl^h3yC8Dob1Ua~ z1SSFXLEzbEHhj-Q$_;_g%imfbi1WUB%ojU9%~mom63UWS8!kWN&60<>FU~p1dI9}1 zB#zGPW<6daUC5AY6DXP6O%EiXLOnf;3e1Fyoh=P`!Z?y%ZV~!YO{c44?x&m$B>gUg zw<#O0@h{1Nt2m~5xzbFdw}Bu`3mKiR=hx-AWRNpzJ^+bhHI%1$319zQM1;xN;;&3aV(=aii!GzK7G*UZeix0|^Ha3Cn|CO}7 zx-7eJnk^w(pXBvypp)$n#oF6tEXB*F;$ln1MCN*u{&+pc3@&$919L2yH|P%}+_+qj z;YpNUNeMf(A%%_wsFiIGH&-TCWC5syI%dgwtlgwGqZ*Ks{1cLAS>mU9c24(4GX|-N zWwYhJUopph9eD<3kv+eL-+MBR6q|)2Wp|c}ttpUXkXv`n{{X{4Jipz~g{?*(yE4ph z5uJ(CT5juT1hN)M2=I1sfthX>8Ef8J`__m<6eqaKh8Zac*cy4@0&PB47*@&3&Yfqw zi9hH%@mL2}NY&k~PHEk_EyzvP20mw;VPP3n{Gr~lhj~fWN-T5u| zm&Yz!)RuK{ZQIK>8~EPFb3LwL2efPtpzY|^SvjJ>}1ex?!69XRLRtfuqEyUgPX z*OkRJx9hoDW5V;j=X$SKGLsR_9@n%asx@%mc<-Z>1~abk8u0s)eOKOkk9FQ1Ub22| zvbrA)ZwbJ_Y}dOf6IPnr5v@lNd@LBJBbos0d~<>mT@Z8yTVOO``^!&);LukPcw`KEkz5G0z)MNXf4*;Pyv=tvOlY)M!DE6R5dx z`vDNId;0-!`#y4-PH8{23WKg~f$gWi`pZCVz_ypbO5A`8xEJ(amluBFqeE?XRSOh^OA90zm&9_GhTW!_PM?cy~qb349ogDs(}z^6eG?^#*PdavIk z*Q=~$eU}b71+;=ibKm0HR?E_;fsSpz{qKRP17@H+`NZ>;x!KPJU*%SZAi#kqARH4& z=YWLZU`sQ%N0cqh-0m%a?cmX&_b4ZYBav|X4DbC62S??Vrub4dl9ivR~3z@q%IF zt49zjS6dA+JAv78EZJK2TOW`2v$n7Gi-z#38|#VN*g<41%bK5UE^U_gecs;G=L>R; zC+rh;S)u--!LCNzG?3;Z}Yxk z9@EEwTb$+ zWcLBN_cMI}-M?ZRfQ#bdHh_(O&ACP0)wQFSU|Ei8hu3moyOWzdZlDzK1%L}~3r_QV zhgf7svzp%wEGy>Ob^&f}Q;@zx@wz*KSz{GOC-RvhV0QG`oA^F8UtpUuV69WxLu;*V zJI#Nwi~nR7|4#$lmcQ*)6O1D0##;@;(dvw#Y%+>q2eQNwsuY-`lXb97Co(&7v2Qw% z!>pOx*0F4V>r{3?#}=^FmDRDe)K}p4($(n1rHUm8z7G5_eFWeNe)g*XrnIZxU6Zd0$Txy$&Z6&9W!E^{5TQ<(COq=t^y z!h>8}bB73^-NU(I3TT};avoR(SPye-0;YoN_Je1Kt$_I!KIb-p7Es^J<4rV5x7ax4 z@dV3v@LDy&YquXn2LyWLHdyAicX-ax>E)a?1LP`UH}isZRKROr1vPu-THIfk3&9#- zy0=!fx$unFqB46l+pN@7BbOD}_5mL3WcJECA7q3v*UQ~bSw;iVbzSGZ4^s>6G?~>*@aL>hf5z{`>uP$jS>kygIg@0INR+T7UA3Pvg>d$M#blTbBLU zN((L5hxA`8(*9;zyXF0#>xs@v=K0qZuHLv?5aQoF305Eu66!^dr^3oERC{Ao>n z{E;p#5c@+N-NY5f5{Qi-{Io%BuY-F-e(1UKf)AtwO1S6;Qo9-qluIh`6qLALAow}N z#lORChX?Gxch}YokzlK1+grMR*4%dIbLlcC=jjxUKneLc zby#UN3b^*3H|Q?po(6EO=bGM}LYondK$`y(|3Cjr&oi549*K1?d3&DarTTC4KkD+D zw*_pgxJ<#E6_jhO2lTmNq(3PNn|Huyj0 zKQ2(MK{)z0YrEC(a^I`{Gj)#rTztNY#qgMYu3#LXf8i~*&G#L_E&Dm!NNl3RE$g~W z`5v{O*81K7soxGrMR9mpHj>Mjx~|7h8ei^{{Krw|`JebNZJ2ml&ivQmi#D{(cnPaC zqF65A>eib3I_NDko;#r09R?d_LT>g;_P1ovJSpo+#DUe37=vuxwqv>TbL6OF*0${u zW{oR!;DgHf~UG8^Gm4*5~IswnFp{q?0uQ+kK}3wd;U^wGC?53$|!2 zaBENUg4!d)a=>;eP_bkO3fux10o((_!fm>@vjw;vZZ`q9=5Ed4woYck=eO=(3e;8& z+Y#9Q4N-(~=dnIOLkHX0IJV2T?j9aqv$L|Mt0smAR(9#yRy5&mZ`;S|G=B>WIxo=j zxCT`yNbKP2dggAs8=EMA&@kPR| z+2Fg92i95c4zr)J;9Li~YV{hoVA)a!r?68Q-iDQ3bykF+a68W zX7;vRTSuRBgfeRyJ0x>eMX1tWRzbMMyMb#Vbno$Gd>wjv^S+Y+>oLIf2#u{H z!zv(l<<7%#Z=GK?eRNo9!;8nu>=ZY3IQ#Pk_iy&|b$i*LeXMiK_H=FSMA-*Lv9ah~ zkb~!Rldl2Zg6xx{SU?Tz@>H&wp09G($oy&=-u2i!l4fU(OW7x+cM$Uqr?2x|A z{bx#+H{&=Lb_L)G&KHx%IS-vGpbgA=o>a{5^Zdr=I{?61F+rf+b@B?Iv*36Cd9Uey zPa}!I`ZL8K-nkB_qEreHRAKXNfiqxR(3-Mg0xS|}Q+Xk7u91aLh7Zw4%nPi7?T>y2-2VKh0OO~D*`NHf zrav~{`>C$%j|0$_FLMO7KCJKCY{#sxBcf#h3H0{Id_G;>7N2m4Uf0RM6uQg~F7YFl zBVz|2nz035REfXHOa9a+^3%S5)M<1a^aPjl$ z;t8^K%T_q3tYm@8^>W!LZ`mctKG&hOWqG=IPeHbNX!_pOLo<)yT)3oxs5%%Ast_&?KWFR;rza9V<#8h_>&^a_9YhyQ>;F&2u{2?x*|@c09{#TVsQDbzc)(@ICTAi0$Pw z^Vr6h|FI1iJN)$%eIf(dx1Qo+LZgcPCLoH0)86?(RpaPc^xSY59RzeO_2mh;#6HPu z_VL;oGiIEO&6#=P7A|dcd8;ju>pmJl6?{2iGcUAucQ!h&9K@ldvzuXeZ2-<)&T(*E z!~uEn>JTi{>dNd6*j^f@PZ(jS4rvqZR_S&wKsu;f6Aw6@n1IV2hS$-`j6bBq7eHDa zz|I1-!mUoO@rDMmOw%dtlob=q-(BXnsLb#*(7V&ylLD?6I9(i}n)gVjn*CfrxnQmn zaOXhonq9{N4J*)c!4{BMhL-F&G%N;g7XuKB1zfaf;=r%~z?~1^&IfQG-wNOca%U1z zsLo}30-N8ue+fYQYhe2~l>6#+Y|F8|9&Gmjwkx;o86E}Z9t3J1T8*3vc)Xv^?S0FE zza~LY$Q58KU#nXS%*M?v*S5eGS&cxTU8JjeJ=hAfmH@N#m&=6JtRt-EHRZrV|cK2Bui&9BME@5 zQ0u@AMiGo5IKYNg5rkSRUs%u9T&-oktYf?5;EBN+wtY0R)Usv&6I%D_+KvFX9Nd`` zh^e5fv%9BhFV73ORzpbHFCf=!t{uWA*|wDzte@=XSTzY?>ly>P4*lDQ|J`J@jux2_ zPAfv=odsZ*eO0g(YM0p1Vjo<>zG;I@*LFQntaIx+Mrzg>wb*xpW8gH$7oRtI_6y1L zTHE%BHE}I7*6QL~9#A<_;SpfB?nD->rs@jUN8Mb9=}k@CC!bIC1BcE%{e*Wr%c=Fe z;GG_iK^@mE2hR?hfY1$SJ>a@-FW?HuX1eDT4NEII2;??0OKWUwdN+mdBd~9_Hm~Or z&JAu;z}3+eYMr<79M|^f1;Cbb#mUP#PkN{Jkmt^rQa128kMUj7dCc=H@NPuGy5QZ_ z^_uVXKe2?X_Hi*L_j-(-kxTmyuxi%!Ltyazj}lR+j@z)<8*lR%papg_Om7>SSAhND zPkuCf@@dtYwYov#1_155acoQPp$|U!c=+%~0Id010QRFFJFm>)j^VbR`_b?*fcv9Q zk%0R%02jzLp3o~Q1Z)A>H~759BHno4=tP0+tLPOzqeBG?w~nNyn`D`drw1WT4#A za=7{hzvm-e-rZXr*T{Jkm=$2MUMU^Bgd?8U!SVv1+pk=-y_IVA)E)g8e|j>3W&=^R z-t2Apa&8j~wsYayk-@ANSDD3f=z7n0VK2}M>?N?ScwD!q3vzq!@{t0I&iCG&t%S)O zm6OZ1SjR|!S;o|k6+jzsq>#NAa(Ddf)B-|5!dSNW09wU5LPc&}@SGQY$LBw2tCs`Y zj%N8S_^pf@SURlAVDWj9BL(32JyiW3f}oHnH0q32Jz$~B3J(qqn^Cj8ovoAmqyqpH z;3@;}M{Q9*VQo~NXB{0~2P(J##9iUPbjag#%%66fD3I&_3e450aSn3~?6K@TpG6oJ zc8w#X>IDaM{?C9ctye+T|1KaqM}8Oo%Qh86dqYR()_J1|?hkSKU6y^MV706EW%e0V zFv@3Y3S6>mG|V#df@i8>JfU-7Y(pp9%jF^@c{dW)=ga5!**6R$(=vOKS09o>koY=eE#+iOufIY&HaXAHGBkX!C+2V6%b z6J#r%P*B?ewjMX2wK0gsojnSkeJ`O>pf#VHDho)!9D(g2E<9d*ngX^>!sf(5%X2lD zMZLpI#Jq58$1p1>B$^Oa88AEBB_YU*70JQ+s0^s)k6@cx%i^q=b z*YB89$M&~J5gu4D2HRhEZ1>C_99D0i8Ro46mIojy3McLXwEaytMyc>tIdWC2pawX2}^OrUljk0T)$ zn6>nmu&M*Q_XG_uUO#ovQSW-Wu#?$_k%L**b2@dTM#kG3M-~8OUt7a|wVHj(N*wF> zOm-AALa>3)wjLn0zH&Ob?K%SV9#3vo*j>%~D|p>X0NwbE@M>(qNWvxn*oe()z}6VU zYPPY71=M;RCFWzcm*d6E?ZLU?I6A~R;V{=bN5?ddkaL*l0L~dMKXLKN;WX#A zbUu6Xxs>=)=dPLk_q@e*(S|1H12eFj51bt~(vV%x=huZ@vj^=y#b;+a&2cv^tRLst zJI=9(CXeymj`H0R$Ksk@!tF`G_!JNe*qW_9av`wcE_C8>2^x^Ff%bgWsUwyZrJHrF(+J5*k zkoytKc-%U^efXntZjB|p|H)6{+P?n5#~DrSJ)RSGdo)3%+?UlBer^PzYT9OGvn;Ec zwtawxpE}R957ux)^|Tk*gu#MNA9wZTUV!6W zbD+tqwm;u7>XTVz$FZlPB{;lrA7+`oAglHqJ5Dk=)zRv#?j$>gJ4eqW){fNz>Q0-? zq~^N_3OZn@I#wy3&uc2{qmpGswj6Ci3cM*YEmSfUFpVVivLYjm;I_N9bpUjbRRs-* z^*c$Y4AXpF(V7#p(*yj84A9eAWbZ7l7g+IZ~tf?b`rK2A5_I|1pcwoF*krEH0 zL=*VE1hpzn)qj_gze~^Hx}K%05@Qhb_>HX(e3Ae15`cRVz!h#!vd$^DDG&m2rB@`j6E@ZgeEofGomV+Hf9rB=b$#S$K0H@Kz z{t@?+{Ux2Z0r{=e zDElh!so0;BiA9MfTu`3u1zREaDj-|av8&qw_ldx527Yi^E))%JPx1Nf*ulkY3JJE8 z$C`U;G=PhdnOA#kCr`(PPT8?5C5c$x%Zv%RMijaVdW|GhR3TYhwy%TR0e3Heo0_+1 z2C&V*69Tpo243%A4LZXUsbyQ*5y&-%cnZL^Jd$yR0)sWcg07d4y9~fB=k`#6tx(&* zHmg2Dr@D**0KkrDR&qYe`*ud_3b_rC7i|P?H;%y;-2>c~fLj5*!MdI1{GLt|!w_n%YYWuI ztp#i?{iR!LuGaX$iXA}h&e@Dcwqg3vuzAmsVf!plYvqH0YL)VGK!nt-HCo_u^hvt%Sxbg`S$(8a`qiZ zy|Y7`S_6ohpIrsCI@I&hZL=vYXSq2$yltfsmdYNpCo-MeP}`cu8uQ*2VZHS;-iZ); zk7j*4n_1&|hPOx6K4(n##cVnQ|#v=ebbuIo<97vOR4-6OBt-c98^b+H`hx*JwC!M*OwGM?jm zr5n%luA@VHSSJ@9Zjc)=c8cQk8dJDp-34tfJHe*UcwxNg4# z7rX<&zt4B!b?*Vi?|s7e1e)LdnAhqK|0wIf{=p~pnCUwo{TL9p`ogCGuh9F8!GRpC zyl_K?VQu-mlnc^%>heNu*$R91>0oiOom**><{P zRvEZzsVy@u;|^3^0bzEk-di*EKmiE>x7VNbyJp;L=Dj7XgF1#<-YcEFDuR%n;La(X!}QsbPKg^8*sg7)Pwg-2R@x~x>kPk7YTI)1)3vRE9jbwqea!zD z`P=t-qc4dexF54mR}4WXgT@d0jS@0*`<@f=E?_lsUQiWYozHVuhDjbzF;yLE^W4d+ z!0i*mE{?g~G_v+6_R*P)Ovb)x!>c#GJkhgHSHxy4!M0aZusTSFQ+hjd5i)OU#As1=gT&Bt4#<^{s&A5>1 z1e>L;+^vy?T5j2+bR;u(i;Ol1#crb<+EcB>*YP-DUhKC40ABF7^PJ_tw(S=fScmm= z$Ap8mdyd7)T?%Y0X}Me7TWr`@e|XJ~;oJ9(!B)5SZw0o$Es7x6 z&K?}r?btgk+&DEnqD$%RcfroGSF4RD>;U>EfI%HwbEtxCgIgeR6gvQ96G`Y$3rr?b zAgCe%HgN+1bbbR-m*@G70ou5=NXJ#kb-C+zaP{?Fz2ZW5bUWy}ezLY~r{V~}Y~Z_e z@A9p2q0JAMfLVdIxwQ`hwh!|=JPOp#6KXe?TWh9vMVwj(YuG=mMeC;o+k*wR`wBko z#I@(x=|l_yvLm296Sy@yyI+U44b0HB9}rf1X=FJ7$hHF~*q@IFYTbvdu3&9konf=Q z4i>S3eMAYc%h`9_UzSa=xa^J;6bduPmZuGe?_HpoGJ zP@FU99P{1*PP9!Eg=?#@n|il!iTxZLwJaUWIEVH-v|XN0;rg z2Nxi8WKXL;Sr7Ml2Yh(z-2iPy1!cK)arH+cN| zdsbjjJZB7oqKf*@-y_?36w4~Uxuei<-- zMW98-C|>5d#3@+!jh3$!RG)kEgW>8+Z|AyvO~8Ha-Qj5f_vzQ(2YBC&oOit!fZiA1 z`Qh*qu>0cMKSUq%ULOO`pRm0j@tGX44cPtBPlg+Wz%FwlhP%yzs2YJoca>JkMQ;!2 z9s!Ez49|PJRL53FFmMYf2(P_HYB{;3f~uDTQ}&1y40UWRkKs7=`}pI%a0dFgz^WOY zC`UPB>V-A6=X7?Pgxj2-AWpTW;jfD3pC zd5Z6(;$rexxGh&#@D*&UY*(rs2(}$&fsPD6+A^}bYhLjC#X8}06vxYpIM3~89W~3v zUZCwed$ke)0Jdeo-h8FbT?AOG4&NPy5={UAyDBSOw>muFl4IsSsqCiCxwq2&pZQNa ztkY7~CHDOUDuLc?u?}f!2Lp}ypOMgL>9!|cd2_f3WS>15xQu-xv61}t1$uGIS#Gt1%W-cT;Ie*h-M9U!#~1p^MQ|3N z1GP4$c<*z-jTZni_b&a>cti2Y|j`_+Dqg#(J?;ULF{kgJ<} z47km)!wIh+L(1VA?YL*ep%367KQxh<#HyqM7i z8=p3~Y6KpgW2XXbo%s8{Ur>9EbH#S?UJb#!%kd2EA@W2NV8 zBj$Zv%L;alDOffvw+|25`QuDMEdblcw(oT~jVtInMY^nUbI%4+yQ6D;+BmMdy?w~yBo0GI5j&g z+2W{Y)5rlL92`Q>os4_g;ns=?f!nyX1+%vYWVa3(&erHb1fVkQ9mYD?25tkm0%!qm z0d1*A2%OppEO4s?Tprg{kkz&AkUJ-mu%Nx4ujeylKnY_A0xh3e*VzgW5AZ#VSs1x6 zdhv+jdp@E|YlktRww3u>w7Cz`uoqz5%m1)HPOVU@HtN{!K0Is%I49!To@|}O%+Z!Z zE7&H6phJ7=Tx!);{n|d5!o`5D&+j^_V|sGfy4T7IM>2JP5+GOcembp=Sf`v{zTMH! z9NyRcTnO&GtcE#L(1R~vIyr%ujc}7kA8U`uDfJ)p7joHIl^@<)^PJ~qDGB(USE6nJ)lh& z6u<*yV;E{2YUaFHeTp3HC?kkE41UHAs1ZS5a-ght-if38D%*MG-5NyeMV32Y#EWm$ zsA#&t#vEP`5SIkvw*g+=UgHf81MD)_5m<#(!8?%x=3frL0=7Wy%WO->wz9Xnum!n3 zc73O=??|(DGJgu7eGzbd0dRfh%@2XxcLTbazWN@|^WEPPZVPCgKF|8kzr}0Ni|D0y z1Z*?E9}hQpQPK@fhZNxqz#XgpoKofV(hD2;=lLfJNm}r|98v0R>O}FJ7iC9D5~ey( zUGTOn%Y@03tRrL|GW#d2>dvBcXz@=!&IOnYvNh*+pI}Fb)8s|l3tV%ikl^cWQvrF_ zF`WhGk=Qn${{Y{`?-PjUv)e+lG*XA!4z~T4zw?PR02M|Px|6E}OLy|4&8_vf5n_eW zu9Qd;YUcp0?yR>p1cOvb;DUdU3%{RjmSuL_sobp>bz6=4n7JMG%;54Fc&-m~E9iO`#0H`+ zK;0>^98NV}EQ3?W55Jq=&Ha$&eLw|=f=ou0|0$VU_r2_I$VQ>Zj_&NSi-7ILVe*)_ z_5nj+*X4WA49AVf%qX4^u)Q)&HhJPTnxJ~8GEczCiF?9#A9p|TGw@m5U()%pfo=+? zvwv4j=9*R`kp15Ed0k3}p^7k+YFUpjl*2nZmd@C@OZOJIJ#I8%+?lM)&L0A=%Y|J_ z6&VfKri4*0mUY`zw}|yw?#0y}$B-yil!!CQ-9~#yIGi!G4k4yOI z8o>6xMZ@n0Y;PMmwtocF{`Qf_{$|H^)3n3=&J6Q6?HLwq+MU|1-hzJ&z!PrmOl7qI zGrr~8mW&`+Ld!u9ZbNwT|!zdHb0-`|d7y0s};X52ua1!j#~2($j4cAA?9&_2Fla+tqyDuXhl zq}SHn!;)=#hNat^Q@dlfGPP4oEidr(fMqXZ=kv>Sk7=M;WkG+}k_T}BY? zE7Y&U#uPQ9>_DDQ9se2%=d?PJ~GexeyaM!DD>LEdk3yrFQ(Ir_8F;|XzpYJy{>PR;kh>~GiGT{v%5XA z_y)_~9A0`G01o^Draj{D_Iu^(3aQA5#4CA@^@L^SUFK)ft+nHuQ{7qN)#$-HAOC20 z8(E^v$4-+YW*wd0t~WpYWO(z3KOSBIOrLrEy^Jz@KGsAv(?}U%?*9x*@DHuMS+HnW*=Z7 z@ZoE8Y;`xg8^wh=L3b|3c05UM@peIunC}3f0wuY~3)?mr{CwBaq0Cx&yS)`l>ru${ ze-SnhvYsGZuWP?E(h*CoTYm4;?ep7`%;&sXna#6 z2eWsq3drilw)lc^7MHue2fsk*{xjEk_dQQtvs2v5!wKDDz%tV(ULKCmnFdCIQgg9J z2$bvDaqa{XNPV2|!TTAvh+_-X9`x=7aB2s^pYvLQ*VicH zJr2KU{O3d(D(-u_vV0HzpE&ZuE#KuV4VA!q;MN9-`=9@L)rj=O+N*HH3FZGYduwAV z&aB5q2U<>`-UZR!HS%L4(vz=%8dre^r7;9SSJyUihLqW{@mLw#UbH-S9OlRqc<#9H z{VA-y5L}08$ z1-Pgh1K6ZH!$nMRwbP6}!_B|iV|)V_xb;9nNtdcFtiDd^#%>#_3h!IWN!cr1sNE8W ztum3DfD+}r@ak>q9jvzlXo=$7T8c^M)-p`x+zJ)eLfw$*A>gIl+O;~iz|_2TI}=6t z{Tl__>!S#NYp~sTJ=o3wwwtH-4=c9o#O(>x=~N1Mj|Xn2<75VIfk6S+fg-H=dN-hW z=kjgC9l&i|+YYoN0h%ffE)qyHFQD4dt2%onI-nZV3b%8mi+iWJ*~O*W&RD*#%hz`p zj$^ybOzk*+pi}#BoZ5-u5x~~pbpD2^jJ~#L^R8hDK)W2ET`@5O?CH?%ZL z2Y^{!Q7a$_vpTg$su4ruWvZ3yngM1@1-H7kDc@xT!ThaxT5r+w+-}xM4cZ2^Hh4C( zP4@v^`c)19fmSAB;Nx0moIto;-}Vt3LYwv+$^K?O*Jy$3ECXD1cOAOfQSJoU4A6j< zZEJ2X5L#JWfz;Zz`+>n(Ubn9tS|CxE)&WI?#;UQrYnZow_pp%1I=M@M<|R6#Xt}Tp z=q?9%1>BSuLv}oiv#YDivF6az9%mkZ8#vBVJ9l@hCSoT`wqccq`I~3wl)>9OJnHCt zfc2vr(E2^Y!*lcq&pqPEeN5+V1aN`hg}=Z@LgEbjEC+TnozONQbGw^3 zXILS@+SR?xpD_p{Ndj*T22mvoh2B}FHnzRCCsO74muqD;+P$O9IgxXzeIQb*?1V8Y z>+fC|wnyiOZA{hnBNvAqK(5g1_PyqMJ%}mAx!=2&-rc;$wb1@Fy0EXj_x|t#;Q8dM zZw_{j_j+C&rtu-4a1F_|w5~;(NTdEF-nnddI=!yi@1;tQ>GD=xT|2Y+IHSf2!-+g_ zz2}x1$+(zeuXvY>E8(}MjnT0N0>0J1>y#49HubxyX89<$^qA%f>&xgDpG5&cihoc01hKQ6~96c8v4_2flk)JG~Rx z>Edi5FXrj!X#yszs~2ETicEbKu6TOg#0+3WP`M*F8=20M4C;2c?d+>6V!a6i3R$zH7r5k%vXP3`vXE-4_4lPOtF_x#g z0;<6ks&k%0H0LD3cdgimIoon(~Co zu@+Ut#@lceU+{VMJ&y?+VjeqJj49Y?DphO&v5#g1qo~7efv%Mo%-+oawhpvlE-n=l zxByLb2Pn5V&D)*|%sLuajiRIzWa*2NRY9!kZ`KD zH%JvITqlsLSg%H&IzCKV{;9dP0*o%N&v~2Jp?5d%zA5exoG8JjTw4qOmoqqj!(_nr zp9XAi8-wk?%&~pwUjnwf3v4$|12_|Vhh6ml z3LWD2USRPa1>`1wi|z&_??OVQ<-p9{_NoMS;4&U?SD!BF;93xSH;?a8&LfxE5v;qj zw>dA|vd$g8wo8y5sq(dM-x6Q<@mU@KY#&^;eRyc~_Tk|*6Nz;^7N>S$M8$D*M7xVwvk?m0$8xO6S zOh>l|_%4sFog5Z#2FAC~4yys*wZN%v?`k0xcvU*Eb|8y;3xuu!Y**_3PSk5$zKmsy zf!}!>cLRquXr_mU*G*->iu+dCu<<=7GkApqhb#axbwh>5B>?EsK4sZ5=7rs5LM~d$ za?6Qjna(bdX}n>n5r??FW@O8a)n%Qx325CYsO|<>OAoHwHQc{eO{1wy?^A20`5l^g z{IEk%JE#etZ=tTPaO>yvv+O)Ptegh=E&XLFFgtc~{H@`fpgU}pg-x?9ldlc}x|~le zG1#L^>3GVyW*1Wjf~iiY4qsexDGj0Y572=HWQEy8r_fI8?;g95stZ&X-L4Ux^bzFd6{(0%zeuDjkfeU0<#GsOk)fp_4I zG!)p{!CsbYcOkhxp5YpJ8krT=XsXInZ^q4i0caLNUwq@;ial^`uWCWBa2?~i%XP0; zR;pN?*JNXSrHjV;UU+l3jIN+-fbJ77z6md|o#*V>tr=!1S(GYC?+niZsn5Of9`I~# z*evdcK>PcHwc#(aO}Fzra4hh?`^is+cRv2f2!3CF_lLtP=5AGD3O`It;RY{!7EAX6 zc@AjF55^ZYpJ}HZTMPZRypEC%W`>sqY!e$eT|cIfl@_QB$iOEpbmiEzV~$jJ>>0vVN;;1PF{8{^Fqt# z=i_rKYsnsFr#T4R>YDCv7jI!Pj%`yMw5HKTI?Ma_w8T+&q6#oo zzB8XUw?G63)Z+*pFh`FCeZH?5opRGk{Wlu@POdKqqd*A%vFbqFmzA5`oHgWcCfFqJ z+dw+-!ZIB=o#HA%MnmP=bL0iVm|SU3+1+ ziTQ$C=Zzr$>%EU;i}7JK#r zjWjd@Tb2vI$32jFFHZ~(NZ~D1@!eqI3hw%;}4q1F9TX22%iV(^1T*fzbm1 zcdKqKFsn->unLmi=8a>zt40ZPY6qE~72F793K@~m$?H1gDqUP5S5Osjh1)o~`+y*1 z96^}Ps8CJ?+qRzD$>$Jc@?ITmD~_;Xb%n3f!2t2?+EbqlDVK<&Ng9_H@`VDAECg*v@~jbN1-4 zQ<%;Fd19CbL}!3khsZsck-}P5_W0R2wt-jxcGuy8ShKggT@LJ;rM1SbP#m`wfHG@p zr!h0KacybLteZX<=v=xDNZULUm()^ZHYjXB+~e;oumkEgJ_Oul0PFGzU0H9#^FJaR zDY~``dH!+!M>E7mP6TE3I52Cz+HAGk*PXwQ|8yi8F*alzne9QKdS1ZR!9#R&E83uQ zyF_<%GgB1kZHoKb9AI5uUpv1KAB`McPnY%K2C@$Uu@3^)_w#w~1!C_5sDyf!MoioL^-b&-=Q!_C0SNw zCE+^jwvG1rK8~<<34qmU^_uDQB9H5?=4*Tp@66UUHGN*1gRFDx-Ct|=zU;_rK4 zvHpB@+NttbI#hLAzItaHJ9wH44;Qg>f|(aFoyT$s3uMdn%mvyDFc-d&axoSx5f|Cy zO_9!y7XRLE{c}Oh`0-q1BSDPUm%Gb_xh)e?3&iRoJ#)&79xbV}TnJe=h2oK~6>NQ7 zI;9vJU|#pCT&yu5c+ov^^(p>PA@>=8haHFSv5)Pgf`Qx2g<5d#^1FMHeiCS@&NE}M zsPCS#NPchL&)>lJON>F-3~=%rwC`gJuppwz)*v#IGim1_UF@T@20b8JmQq)H(u2&H z2Jo*uNTSvdNI57JaHTPDfJTW~&AE*LbG`fd%qc(Sb3nK-m0?`jA5OOY!It3(mI2EJ|aE?N}4I=aU4&o~0FT6Il^}nU10gLM_v{vL2`$VCJQd za-gPDAnGHlm0S;~6>bIH2DnGAycn0ZI)T~Iu&Nwb{UGZ#8BH*jAmIAmevS_60=Fld zst8hdIdq-_s>nMOPR(c=F)%ivOPfk0Gz=|g=N*mu{sp#{cgybz+y-hRI~Ek!*4>Ya z_;_rU1J7}XoKFL-?RO4wd6IRElAPeRa~qWIlY+6wYmO!M1^0iCEsq%+H#UxhTKBnK zx}@%Z?1$b}NTVyDYlG6`hu7v<2Cmtz(#4H~>q(c-=e}f4*LBBt8NAEkzE{BO$VEmE zJO=AH;TUdE8v(Yx=X82mTbk=s)uc^Hq@!n(i!}=yu$?^#h#D~vCJR^{+uz&&I%0_e zARRK}0LoHIc?@8vz-HjKq$`_v0+1T%&<1KtJ~uI2@qa0Bjvm%aOI379)Xg z5isj~jkvXESPt~6W!81w!t-WR*Y5r9=9V;I&G)v~FzGkG)sm4A^dt z?h$TvXaU-&L2bZRh}F66YU|v+6o6IBs`^31wtDT_0_UoP@W9G#`5bX;TLi&e?Sf5H z!y?^UzTdL#djR~IVa?>suzq^qu!-MgEC2h%-XlQmG5$N9_v3)-$;1q1Pn=1G12eOS z?F0tcTE5HYrdg+kxINh-3TKd=r_QF%?T!{bNCU@xh3&`1M^*j6y!9af`@pbjViw>A z6#32P@mcTZJ9L-)J{l7#!^UIdA_A(N$^_VX>@VpM*E#_TtG=d&8Roa5q2X(--&>>3 z?EolQ-wuRq$6=i31E7J=_0_3R2iFdEj{%;-t3jxdpO#5;jSOK<% zh-O>7{?WLr0_ij`4an-k0?mQf)jNl~n*`arqaDLteBZl)+PhZlU<%j*yuK#eV4Fg* zF$E(F^ML5l@YIU=`OU>O;$Wo&-R7k_%2rYUaxE8Tp4jNbDjT@~Zej~)J&oe^Mkdfk zVRxTp#~Sb&eKHDVN7iKfs}$i5z*U#ma$&nHPrVUVD9b>8-Z`xwnUB-_S^UBiBg{ADviZa2h~H^E7@m=xV^8 zu>z+k<_hao&N3Z< zYuhlrh#pq!!pWQ?p{6taghEkilow8ol=~lGey#DCE zU)`hf5c=K=t(?kO4tcg*b9LzTa!NEO#9F;`@UrQ>W_R@j7S?cw>yHbhYOl3k&8BVZ z8RlvmPf*J93D!uf29Kdk4jxGU*ahR9V|=(#7Xdy)LLcyswItptBLKt>Qy5+I7`L-X zQ;vN>{R$}zqhrfx!I|6dlkv5nd-TpMDh61K-`kwG#e6utJ-4zxMWRTHzchGizHp1+ zLfPhsgKpJy1xMBm1tQFqmCml7i{HP*%(wj*g&kuPLI+^FXSjC~QaZvFt!VVCQTp}A zhqyy7x{n&(k-L&~_l4ii_~1pPv?1fulj*eMl7?vTMub zKvLjrBCdut{4o5AM-2$~>3=*?QyN_4S_Qg(!BUdW%r{uDP{zMF1-^X*B61SZS8YAV zl-uo}*#m2sfp@L+r-r%+6ZhS<)n4F3rEH0`uG4Je(;}oBKqDSBk9yQ(%erNu=h0*b z{{!@R8;@;0v(kGd{3(D+kgqO6*}B~Sk}~Kj-1;_pWA{cA<+ta>uAz)toVIKKyN(S! zh_K`LRw&=>#tQ3F%k8dUvsFSsYRU@h3O``MqTd^1xz-g!L@^$GlIt|5s#RCb6jQdF zHx`@aY&^3x<)#bYotNxN`nE(vV)TTe3ZRB{4y_l(qHjPx{z1Vr@iw6ESOsI6CsL!D zHA)i>A#zrx*@XZ8J3Ko8y&jlp^>WxaVht;So>BvKv1qe)-No6fEhW4b0HceeJNSh# zyDul6GXN2kt`Zw7_4kCDFV6ijnWEaDdnm5l=MW>#2<;Rvoc`_kHS!!r|z#8?l#2`J+b^$t-3aFqcak0Da`aC__=-ND+b_LcU$XX z6vEqdQ-yB)!Ytquch79cW3b!~(%VPp@=!Wqm9BxcMq*2`E`0-IK-bG*VKQV_5Am>H zzFFED_@{|oOHPK~-i)z9X{P#<`(N6zHMC_tA~t&2O1yFeo86upax^+OF%}1GO3K)( zMgDv@%2U2$l&pRcCll*2^IvWtkTI39oqHO>noF3VdL+{6?fwVjj$*}B_pNfBWk~VV z637eDU6y8@u4c^vkzdI{MtfygiEKma^NnX-=EVKe z*n$1!V-sh!mJQ0LG2=tu2Iru%?aA_KKDc+lbD(s(tfY8X?P1y+2U2hM7Q*$^ZvO4E zo*LtS6rq$4_yb39@o_GvtrOJRwb7P%xA#NAkP&yOk5=5Z!yIcr#ODw%sJ-zk|La`9 z)R?3pGq_9rQqO}g<^JD_N(H%Ha7i$<^+h6uUrn)jOrS`)M4}=7g&0Skj7>(oO`W>s z7!{WBs|*aZkr+t~w|jPBn7e9r-Jw9FEh6Lc)v1V(@LP^@jB8=C9U-=| zLM5LRO`PB`lbGyDA}@#9Me&|oYn$_^YX1V-YEB8tf#9U3+^pX^T@cVSV0UYm3~CGn z#OmSS51|3X_Q3@&EBy`DYqmaJ2mWBJE0OkQu@y7J4VO>$_7eYU9so8QE*$IdFY6dz9<|)I z{`k;bQi#bLi+1ube zQwHlxm+nn2QbX0;XCnCC= z%Lk(6SxyIEj)_Jh@(HJGrZ94V%e+WkOI;0Hbun)z2koC2Ku^rDFrY+;Kh4QnnP+yf z5}bFL_-rv^H57o}%4U5R5)YM@m@4-mdPD0RYO^^5ODzRQ>->+D0mR^ml*E%3(aKhc zkJyh3@KBj=z1%CXG=5i(b2fvDZtzye)XpqHODZQGkHn;}Eq~>LnX$|&J}-;HmOhi6 z87Qc$7vXS_>dMtEk?2hP5>&f9IXC*-9{IRZI^*P_aMYHWVES@x(QW#oa%9cuRiwb! z&-tK1q(G?_VW%$XMUtgzqp$gx_F!4ZHJ{AWyoW;K60#CX$0~rTZJmCwL&`Mg-|BZa zd?XWiyWJm(*9X2-Enc$>L5xGHGsv9=fw^mA-wfsu1MZ?@hSyUm`D6N1BtL?)IcZ9y z;f;xw90Z#rlob!}yc$rt;C@$Hm?{37o8Z`hD`>M9u(|8ikjm<=#Wz6H4HvOLqw~@% z@UOCYeQ%Na%F4*f!na0}+rp(Gj>^`?W>^gS98Ye_RLu)w-4VIIK-)%U#3g;W#jSHM z#o7`4`;lc;keBP!HxV?mo$g!4YU{aV^dBoro`O+E^x21Ym57w=wh!)-b$!f}x-`Q&B4vMExCH#_ zXj?%VDsr2|FD)OCLYY)LM`?)~i?@X9n2>y1^Y^~%0|Q0?y@()x?>t--TCy}fs~w&$>)UDX4jfRjJn|_(}zR z9jXQ!^}bwITd<`VytV!z3CBvsz8K+olNX^6qVmAO<8H5ORqM)_>dgyQ+YDD$$!~U_Lpm$uNV<3T zH`j@g5+Z5`+WczE&B&m!mTu;r6xaldk>jEgm|#mqjrfF)gt%JdV5~<#SC4vFVe? zH3iNyd9B7xkk{y761_*+0ZsV0FuN}NtH?f%SUMheUd{)(q^e?>F6!H%X>#ucpLay- z?$PAacZ%LVRQUw1MqZ%=PC`zaLFkdb%I4=g=Q?XGy8*s@k5Dgdx!xj#;<$Lt;!}=t zJ!goE4NldE_lB9O9u(6>MyZ(nmPjOaTzJJ=#DyB*zau!u?}c2$EvbB2ms&n%`Ym>Q zpB&2VS?<${!DHKs2i7g|#!DnPA3VQxcE#Jc=&N9XY&qh+`QUly*i464#!R~B+7{E7 z1I49qv;cg`E4$g$Y)Q`FYR-7*s`KVj;FMYR!kS-UuSHqHGqJp#=HglaKOWra<<;YF zYthns!r(E%y6Jy!v*2UzUZd$YuL92p6qr&HRz40-nHHpS5~)+S-4u+D0gW;<&N7YMSK=C+M=XE ze$V0>%?I*rSlC5=R^!#Rm&5-^$c)iTl>1dl3P?KKP_kymW#7%J!0gSyS*$?Tm%C%y zVF>Hpw)n$ZXzZ21#SojF`1=W=@$RjEpWsS#`C%n#>HZZXcH{1T^_YEVaf~AvGvgHb zYAUEF-V;@5`!CCUmh0e=wLiMb5gpi@st|-;xTUmP%z0reahn0VNd$JfOU(RoA6Qnj zs=E%+I=mdj_@PnvD8kPWkfBck;)Z z55TFRSJ(^w)rO77LX*%UUL1d6d#tJE4n4khe{ZZx=t+mT&X`L}0uVyAIK%Jn4zvBf z13Xm?vmBE@AS3*Kcq-4pu+(gukc9U-TZgfzm&oBe;5-zG*Yg)6`=_e;*TbT^gYjXr z;@o{BmQs4dPyJTfKeg9Q5dfuEL~%l)l2?!m^K0WlSZu#TQw%#bT$hG^7W-Y~bMEhn z5pb*+Llt8>ifAyqCIwj5g|-9ByJ*@{__mNtTO}cJQ1d7YT)tsCtEPu4@5>7oqpk*o zXgIB5Dhq#I4U%mcCY!@$n8c)wL~in5>Cw_u_l)pd{nrJ?g_6c3 z>7kpfc6Ftd^<99Z?otMD;c*52^$#b`gv}BzPSiLcakc{!xPq zWa(a?gU&Bh17v8T%0;KAd#Bz?L_K+vV_W|FEbYaMK`HJ7yOYeQt-u<7p?%DMGMAK7 zJj8=Yle4c>A08x^|Kadbe^+gm-m-4i5!3MO_h#vxRsvLp)18;bbHh3I=TT&l5Pvt~ z+J6dgl8fu5Nru0RUNnE|C9JQO#?Geg1z#w|te{B>UJtLAzg{38dI*jHZlj=r`s!U( zdB$%?f64gQv+fP2JykXgb{tm>zM81am00auG%)q|%SF}4_p`Pha71S35B{J&JF2I3 z&&2lzqlETL&%w{kk1``}skU37UhWwIV{Pl7KYmY3lxR2I3^`H6QfVHV_3q0>Qrp9& z$92~yR7+_*&-2>T4=&tWkuA6 zqahu!I%&fD$LR&tpT^%<9mn(o(7IF{iu%Q_jR$mIJDIdU<6PLsUwfr&8C_ zR^`!7BSFOkQNKpk&ppeE8y7kvdhuh0LukN4NUe#-|WClgIqH2IuH3__F&ev4sO4IXd89Y6-{F4 ziEWnpSnASa`f-7>Bde18^4Qlj&*j}RZw<&^%vy%hKVR8xAUIeaE0|7hc3p5^8e4Ag z^6IoKg}4w1eHb`~Y!O%jE!{~k8(B)`P`Ve~q+8lb)pXJgpqKYAcF21LUz#lA7dxr5 zwl0gH6JD2}_wGa@q1QZBjh24lc1f=va23S|g#wVknJEzo*rb4U4a@p~RDYhT_{eFs zTk@Eux=HFNK2nIH_N4R5gMg38oFQ3-8phfc8d0npzGaR4t!(7Py z2d|0zGp~V+T=_0J@=4!IewH^a-hHr8Ocm8 z{}6Ak!yI#fGu`{Uy;~dI>|~N!>1JiI;3J(7oP_ijzxUPI`(VOgsjq{?wYOi$F4hV-i16sHw_Cj zx0z*y7{LpO97f}39sCN+CDz0qX zHblX3t-s!!pFHeJX#N2C?NQ1H-T9do|L!41>D7KtbIxljkKIDwrFvV+{h7H7Q>^#- z6*td6c(#Z5B_76=Af+XqyWP|{jT(o6uuXGak^sK~tNd*rV!T6Zy+pmd;Eh(C9M|we z@60(LHfRt}SLKH1SH|goWyQ29hik=d3|(~E?!}@E5zKd}Y}8IaA-V7wJUsueIcBm_jnbI-q;jzO{iY3 zIB<%fpjP5L#YeZCfOt(g*!FkqahO9~?~PUeW+K)6A>B;6!b*i;Wt~@_H3n=eG)2E% zC>bGg9@Nx!)Zqz@h&)=9=>dV&spvI!qL^kRLMP^C6Jy%xh65!gb9n{2OJJD^^q_i= zG*q{l@fh{Le94| zBqji|)|@oTnJX1V^u;H1c0l|e278P=FMepoeQ>{H^YBiF2%u{fE&u50r|pd5FU)u3 zlq=$?rMY$xe!k=Rzmp0&BL0vuCvD{sMDo4ZTjP(**3q{ucwt&sZp-_7E|Hw*WrSG} z5~@JUoL~Q@U+U$GU}pF}>_@NA{g)u|?NO%le*+WKPL#E@s{TW6=3rTl(bfv|z3$22)F-c~9uLF6kK4xKxPJYBg9&fwHeC zVoII`V$qvH&OuAaRFFpD(!4CvG4~SQ1Uba)XvK3Jtxvzl!`=3& zVgD~DE+H$YL0o7z2e5QqrQKRG$l_$favG;6`v!vP4T;UaJW>1rlW4+OMr8B;LGxil zVus32q$E=Qu5^fnU`o`OHoN}Hk8m`cGyVuGSg@`#HytzS!r7p}6ChZ&Wot@cYV}em z$qnXeJzjv%+gxnkNzs~_yO7A#UV%mbI-_+H+jPjA+Iyg~A2AYg&nueY#)&E_2A<)a z^!9D@7c4#PgzaUI1yV*7_~Hi2Kru$6;C`f^nZ2l=LTOq1G*gXYV_od3TKD;_((nFZ zzBi+FW@_3KunV59Gb6;g0?&1*ljI zIC#Ikwx?cPiO?|xK6JMHC!7LwIG@>Ma2QQ5eToV+ZGWrwfr+7^#lxo>;1V+l(PCX! zqb;>4@SEA@6Gbe)cFM|teL&Kb*8@$1hc-dZRyN%JdOt++r?ka+FKV|-uNPKr9bNL} zeMabO0fGQ{#8q&qneyxf5NCYg-HnssW{sVd$3H+s~++cDu{%$oasw$(6qRai1K(u=D%qa zM)^G2$`033V}GfwG+ht+!?>tCCWO?QLXJ~X!UqMjv;mZk&7(bnvJpiZYB=y7Lc~u-V(+_{jiL}RP?CxG2EE}uT<}Q`$wjFi4}|mM6!IjMRY&3 zf@Z8TnXbx;K^Uw@j&u-C&8p!G7iUSe)yI^WYkf29vsYEX6KWEM^i%Aj(Z<*Jk5}jc zrFDVR|K@@dFp#F>?uMula<}VMnSMlkrL;+seS=6y)bGvDV=8e}z&%eFN z%)kw2755zfCiLzpm|s}caMmnQw={CF?mvc^k40OQKWS0rZ|VEM{s)8?cCTLbgQar^ zoKs9HE!r`Ex@0<~Hev~c?Lb_T(q{1*pkTx6=t3=$BIdEEPA}(8e6ts~`nkfs%}x4G z={)EYLq5zlfkhnFtME(LL$OJ$AZzX4Z~5g0$`STCE%3l13pUY8*X;kbrXsuFW02ud zSp&A?<={z0JbRYglbjhnK2^ZuVNyoDBJLJ|H<8m-_+m14=8O6_;ksLTK|S>aY&utI zGA#4Wy>&NiNZs&!<3^rbNBn`NuC~ux*$6Z0)r3jz$85tz1``y0ZA$998^b@mdJUQy zi*W~Re7e`9LYf_4jgQ;d`pEn7_uTEH-yjV7-Nu`7jl%28ey_lmwru@DK=+=7AE%NF zAh}-6$3jXi4}fEW19doU{7})t$^Eu<^Y6qS@LpCT|67?}w=kSNT|peTP(G72yP+L` z(NP0)VMStnETsb0XR2`_u^L(tY1E3c^?%SlYN{M^*@AUBL!kO&Jl=Xvjj{h-86rpi z+O$tt4re?l1VM!+3C< zA(GAMqc=kY#t1y%^XvsHuPe6DG?6fUR=>SJ;zt1&Qz%3BS03vjVRNKGb6zL@OUiQM zu}tW;M8MsleGl?2yR};GiFelaBBILMNU^>infqiD{P0v&=URZdm7^M z%je@k@nAxTOST>^v^Ep(uk99io$}xb>p?~!i93d)@7hAkbMuN) zIqPQsOB@!bCv{7;o`b(c-)CAM`zt;P5*Pv~4Q~3b7P$b&$y)lsd*-$&U8y;kB|W8s zHg8VG8ieWVPNq#`UXuhywe&8Rqk&EitqDuQZq3#~g%+l(KK-9n&S!ZAM1ib=lu*AmszrEUV5JCn7Cv$8_COf_n7pbQ=E}(q0Iysy@;8lL9hK9$wrRVeqppcL4RgHP(}!m|cGW_VC}3F#UaCUfwS5 z8YAtMO>>!8P!b7X!Ywro ztYWXWWZwbWs_fU&qm0EQlqzt=l76+2(R@}(4%dsq)=ksi19k%R4}9^MPjx&cf?FVm zaJi#lwE0?E_EHVKwfSHKAE>gMp)Dxaw2$IbHVOQr`}xz_R{bltnwk>~t5|bBigHX; z+p5XBhUGLmLZ9>l2q*B9coPqHTj&-O4&wbxV{@Q%rUZI;>en?=o-jCj$EOn#6r%!^ zH+1y0cb}K6u4qeXM2!u!vO3pDkl3f@{f6K8{jL-++cf)O$e${sThuO0lceUPE`ehH z9CmPDXx|`jKWP*|U7LfkA!LR^zx~bD?&Un&Q2O59>mD(W?|9681VwGtL@ahwMaROk z5N7Al(oJ`GhBPNKnpmDsoU&CDh)cOAfv=Xt%!&>b#}KZ5Q^E6%8>h?l3@d(dTAO8O zWx6jzstoeMJ9PZlapOwNxL`VqV6rfc5A`9pH=Q?xrC+}Nqmk`O?No-%eMEp6*p~sz zD`js}@*N7R_CvSi*(Dp0E&_-UdXGWY%B*J&0-~4&9}Stad$%#Re(C{Jq9Wajl?B>L z?4Kw@wJj7@f=oqTREd(yL16aOXK{Bj(tYc8273Vk+UYVeZEjotl1^xb*s%~w{u+0I zg{i07YI6H|Q$w7i?{1z1Njxur9~TRij&Wqp>aOa`wYKX-9sr8X<;5g~Y#nnzxl*;>$h6^p~+xxyiOxyt1|Jq7wUfSq6FaSu&Va zsa00SKd^BF9gp}*$MPQWVamEFYeG%D;>(v_QSXd*IPida;2X>_hUI~m z!*@p(@;j@nd$C93JOjG|o3$OwM?k8>%z@dSyw1aS4&x3Z4kxj3=JDbD-$d@&EQRPR zM#Klpy>?h-@A~Mkv!An^Wp5DD;zQUz2=pjFX?MBjon;ftYVPp4i+<2@R;hivD4(d9 z-v856f@dl!C`)a%j*pvN<(Y`69ZF{0g)+m!G767#m5#y78NH(zK%5I9HnweSL}cF)ajsfhj4vq zyCCbIvgFF?g%H_XJxh)5#pARnPJQVNo*DlU!Kz@@=2xw2iV-GqIE4x=PEciOGmx<| z1;l&^YS3bTvGW|o=_=xS2~hnERCy~O0wki_5SsG8AFC~)xU+uPCC*gc;M?Ora55H_ zk7H;$Z&$0Qd2lCu_r3Y^__ghf5gi;iYVW-F0gBKi=|7DCQ~abx-i>C1U8O7dE3Rnz z48A8v+t`_|G;&T=u;*Fn>!QuATK9t`I=3Wj|H9bHc+W27NuUQV9&1CWTP`isny)gz zu}!8jr88;kT^+*lZA$2At4#ZtpqX;WUWD<*1lYe$F`;>2!Aq#Xrat%XVCbi@qntJ@ zifA>Hd1x8AQ)4b@yDVL|?mT-+542q1e3ayT{s<&fzo+ryUXkx3A=H2s&3c2&K$cGmK;uYPUhDRWN?Qx}G=WzycuW^66Llx!HDPJZ9 zW#!UGl!Gi@LS;x}Vy|K*&{lo?^4Mz!sE}Tz)ozUzA9&)gW}pV^mId)?in(*_<_j9H zK=ghF1=7X+<^uqoL`(lsU$4QHl^Z*1HG$ET7|&3BM%C6{HxN-+_4!Dj*wF7%B~(MI zyl-igS1 zd8KupLbGs!aSqp(6vU>$Mii@okNvC2FD7R13_^fE{rvQ-!Fd4D>n4SvOlqNgSmQP~ zAf|?S{Ecl1bB`=SJ$gh0HCJF0<`l3$Y8vBWP2+77Q_b#Kts zRi30QtN?p+!em*gnt3KDPPhIN`WF+J1b5zMgD}HveSR2c{zWwveBkC{UxT<57tumqDIyvlTLoe&Ukdd%!HHhf`eDXbDk>F-(42QyU*_I%< zTyikD%0Z+{nTRVdRKh6XO6+P#`ga;c|*{3 z;F{yMm8K^4?$eSOab8_jkQ7!L?;2*jw2WFiT`O{;bFPyJAeI4fHrM{Yh1hs1=O>uS zjH`EHy9B+WDOI3gSVJ(FdQmp;oKVae-}8!AP)-MkUy`>j09<$(eumJg14w?ZUFopd zc&a$5>eCW(&1Widj1`+e;~C0tV!}@10z^cv+vBRgO}*a)tcGOS0y8e8c^}L%zAyJ8 z91UQS$V;V>#Vy7B9|G3>8n^gkkTY02CI+n(;7GsBCovKRc!my!jS6`Hw$4BjLiIcn zJJR>7Rp3h=UFEOAAvl1ZM|Q?wF+R1*Y=&}M-{)sYfLwXIWBm^+-SY}W?7swf@Pu|9k^+# z>#{W@)PkQ`S`+{<`eNd;yu3rvoMvFtJ)OUC+DvNEV{e_(=^V#sjhe%*VS_e{=Q@K; zSZ$j8JGL(9Cl^+a;CbBbu z`163&;x5ZNqcsy6BJ5ovt9fxX`||MYtIn^z>B@`DfXlbm@piul^+=Ov#&2{07|8H# zaS1wD%k|DHvD!aw@{H|0!Hj&etoPqGd(>iP_D}GBb?!%UN0?x0*F*keh*-Zg%WLzL zKvP&$_e%QMolTI%SA$Qz@gDmUlQ+X#7>KdSz-klR6Y@h$Qc57ppS9_p4>A3Ja-xy| z{Ef-m zN{NeyrmE$4jsy9PGVa0W-LAn4ND#*qhY*+0eo7^bcb2J3xW%b{M7|BRQq`PKv
jU0&H)HV;l~2NNg54df66Wl&hAew zNwB;9rlnzkvM@xMID;8`Kche4>}|j9fHjlf6va=YpH0VUiWf+8P4&xZ65uo%m{cTu zsvO69lqpJCsYYQKo)CT_h8=hF=oTNY;7)b!n=nEW-$(US#lHx3$L}{qJG+;nq)BzvPAHPv7#V&ji$7u!*#n31xLQI$*R7 z|KM>OH>izG7~b9n_iAVFzSYJC^?Anp#yoEmMt88WgPt~@p}_43f$lRl$@@hM3iYxv zxs^7cbRPz2i}lFcU_I$O{b|=D>06`eJ0sC8!_jdg&^x24R}boUbOrqZ2Yv{BU|{h! z8!&5&_2GX5(PzWhCtW5P11yXOzSWl|0y1HBXDkkfMH4$UnKEbF6-(QE(L7`SGspIo zeq)@mj$Dg_jB^);F`r5soQ6X-O;Ec7hifNJ-HsbBjV?}Li(%KO$P}EN5TG^$U6=^4bK!3DU3$>G0EpowTe8|Z!m$N`tpz>2nGfkRI~ z#f_E%D4q*;J9zgLyw7Q}p@o}lKyJN#fc^X+bCnGOTt@-68e;C3waR*Dth9l^z@WS} z)+cj?o1ClJ^%F}q^B)K$Y3D$agqWSd=64@ zN}|z1H)_Z}?Y}MBHwj%3($7=LYqmrS3_hevF0f`BmGvKx;h&6HfQ411KOMviT z`hWvX!Ka)tzK3!S2kNwQH@e8a$+u+^*Hy4>9DUD|KIkjPs>HSnr~%*cv;{eV6Eu2= zXp~XqGzwlAPM;i1n;rz94^$vDABd$7^n~lWrLVNNQ)=w3o~RCUW_icS7H|0%h3z0W8^%0A!;7q7g(31W%gR)QtKRBX`SK1Hxidw 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

R0FNj6_43VwkJh}*Tp9( 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

#}jvzosIfJ*$XWb>(D;`E^W15OCVE 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/future_work.rst b/docs/source/user/subdyn/future_work.rst new file mode 100644 index 000000000..63e4f2325 --- /dev/null +++ b/docs/source/user/subdyn/future_work.rst @@ -0,0 +1,42 @@ +.. _future-work: + +Known Limitations and Future Work +================================= + + +The following list contains known current limitations in the code: + +- Tight coupling is not yet supported. + +- Only nontapered two-node Euler-Bernoulli (E-B) or Timoshenko (T) + element formulations are available. (In the future, tapered E-B and + tapered Timoshenko element formulations will be implemented.) + +- Only straight circular members are permitted. (In the future, a + generic cross section will be allowed.) + +- The number of elements per member (**NDiv**) is constant throughout + the structure. + +- Internal matrices are not stored in sparse form, limiting the total + number of possible nodes/DOFs to about 300/1800. + +- The dynamics system reduction is performed in the absence of external + loading (e.g., hydrodynamic added mass). + +- Gravitational loading does not impact the global substructure + stiffness. + +- Loads (gravitational, inertial, hydrodynamic) can only be applied as + concentrated loads at element nodes; distributed loads (per unit + length) are not yet supported. + +- The overlap of multiple members connected to a single joint is not + modeled with super-elements. + +- Member-level outputs are only available for up to nine nodes of up to + nine members (although the **OutAll** flag can generate further + outputs at the member end nodes). + +- No graphics/animation capability is yet available to visualize the + substructure geometry, modes, motion, and loads. diff --git a/docs/source/user/subdyn/index.rst b/docs/source/user/subdyn/index.rst new file mode 100644 index 000000000..d0ae506e5 --- /dev/null +++ b/docs/source/user/subdyn/index.rst @@ -0,0 +1,32 @@ +SubDyn User Guide and Theory Manual +====================================== + +.. only:: html + + This manual offers both a quick reference guide and a more in-depth theory guide for the SubDyn software program. + It is intended to be used by the general user in combination with the OpenFAST and HydroDyn manuals. + The documentation was started from :cite:`subdyn:manual` by Damiani et al. + The manual will be updated as new releases are issued and as needed to provide further information on advancements or modifications to the software. + + + The authors would like to acknowledge the following contributors: R. Damiani, E. Branlard, J. Jonkman, A. Robertson, F. Wendt and B. Barahona. Additional contributors may be found on github. + We also are grateful to the U.S. Department of Energy Wind and Water Power Program for supporting the development of this software. + + +.. toctree:: + :maxdepth: 2 + + introduction.rst + running_sd.rst + input_files.rst + output_files.rst + modeling.rst + theory.rst + future_work.rst + zrefs.rst + appendixA.rst + appendixB.rst + appendixC.rst + appendixD.rst + appendixE.rst + appendixF.rst diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst new file mode 100644 index 000000000..ea27764bd --- /dev/null +++ b/docs/source/user/subdyn/input_files.rst @@ -0,0 +1,490 @@ +.. _input-files: + +Input Files +=========== + +The user specifies the substructure model parameters, including its +geometry and properties, via a primary SubDyn input file. When used in +stand-alone mode, an additional driver input file is required. This +driver file specifies inputs normally provided to SubDyn by FAST, +including motions of the TP reference point. + +No lines should be added or removed from the input files, except in +tables where the number of rows is specified. + +Additional input files containing soil-structure information (*SSIfile*) +can be provided by the user specifying their paths in the main SubDyn +input file under the section titled *BASE REACTION JOINTS*. + +Units +----- + +SubDyn uses the SI system (kg, m, s, N). Angles are assumed to be in +radians unless otherwise specified. + +.. _driver-input-file: + +SubDyn Driver Input File +------------------------- + +The driver input file is only needed for the stand-alone version of +SubDyn and contains inputs that are normally set by FAST, and that are +necessary to control the simulation for uncoupled models. It is possible +to provide per-time-step inputs to SubDyn, even in stand-alone mode, by +tying the driver file to an additional input file containing +time-histories of the TP motion (displacements, velocities, and +accelerations). A sample SubDyn driver input file is given in Appendix +B. + +Users can set the **Echo** flag in this file to TRUE so that +*SubDyn\_win32.exe* echoes the contents of the driver input file (useful +for debugging errors in the driver file). The echo file has the naming +convention of **OutRootName.dvr.ech**. **OutRootName** is specified +in the SUBDYN section of the driver input file (see below). + +Set the gravity constant using the **Gravity** parameter. SubDyn +expects a magnitude, so in SI units this would be set to 9.80665 +:math:`\frac{m}{s^{2}}` for standard gravity. **WtrDpth** specifies +the water depth (depth of the seabed), based on the reference MSL, and +must be a value greater than zero. + +**SDInputFile** is the file name of the primary SubDyn input file. +This name should be in quotations and can contain an absolute path or a +relative path. All SubDyn-generated output files will be prefixed with +**OutRootName**. If this parameter includes a file path, the output +will be generated in that folder. **NSteps** specifies the number of +simulation time steps, and **TimeStep** specifies the time between +steps. Next, the user must specify the location of the TP reference +point **TP\_RefPoint** (in the global reference system). This is +normally set by FAST through the ElastoDyn input file, and it is the +so-called *platform* reference point location. When coupled to FAST, the +*platform* reference point location is identified by only one (*Z*) +coordinate. The interface joints, defined in SubDyn’s main input file, +are rigidly connected to this reference point. To utilize the same +geometry definition within SubDyn’s main input file, while still +allowing for different substructure orientations about the vertical, the +user can set **SubRotateZ** to a prescribed angle in degrees with +respect to the global *Z*-axis. The entire substructure will be rotated +by that angle. (This feature is only available in stand-alone mode.) + +Setting **InputsMod** = 0 sets all TP reference-point input motions to +zero for all time steps. Setting **InputsMod** = 1 allows the user to +provide steady (fixed) inputs for the TP motion in the STEADY INPUTS +section of the file—\ **uTPInSteady**, **uDotTPInSteady**, and +**uDotDotTPInSteady** following the same convention as Table 1 +(without time). Setting **InputsMod** = 2 allows the user to input a +time-series file whose name is specified via the **InputsFile** +parameter. The time-series input file is a text-formatted file. This +file has no header lines, **NSteps** rows, and each *i*\ :sup:`th` row +has the first column showing time as *t* = ( *i* – 1 )\*\ **TimeStep** +(the data will not be interpolated to other times). The remainder of +each row is made of white-space-separated columns of floating point +values representing the necessary motion inputs as shown in Table 1. All +motions are specified in the global, inertial-frame coordinate system. +SubDyn does not check for physical consistency between the displacement, +velocity, and acceleration motions specified for the TP reference point +in the driver file. + +Table 1. TP Reference Point Inputs Time-Series Data File Contents + ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| Column Number | Input | Units | ++=================+=======================================================================================================+==========================================+ +| 1 | Time step value | `s` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 2-4 | TP reference point translational displacements along *X*, *Y*, and *Z* | `m` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 5-7 | TP reference point rotational displacements about *X*, *Y*, and *Z* (small angle assumptions apply) | `rad/s` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 8-10 | TP reference point translational velocities along *X*, *Y*, and *Z* | `m/s` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 11-13 | TP reference point rotational velocities about *X*, *Y*, and *Z* | `rad/s` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 14-16 | TP reference point translational accelerations along *X*, *Y*, and *Z* | `m/s^2` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ +| 17-19 | TP reference point rotational accelerations about *X*, *Y*, and *Z* | `rad/s^2` | ++-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ + +.. _main-input-file: + +SubDyn Primary Input File +------------------------- +The SubDyn input file defines the substructure geometry, integration and +simulation options, finite-element parameters, and output channels. The +geometry of members is defined by joint coordinates of the undisplaced +substructure in the global reference system (inertial-frame coordinate +system), with the origin at the intersection of the undeflected tower +centerline with MSL or ground level for land-based structures. A member +connects two joints; multiple members can use a common joint. The +hydrodynamic and gravity loads are applied at the nodes, which are the +resultant of member refinement into multiple (**NDiv** input) elements +(nodes are located at the ends of each element), as calculated by the +module. Member properties include outer diameter, thickness, material +density, and Young’s and shear moduli. Member properties are specified +at the joints; if properties change from one joint to the other, they +will be linearly interpolated for the inner nodes. Unlike the geometric +properties, the material properties are not allowed to change within a +single member. + +Future releases will allow for members of different cross-sections, +i.e., noncircular members. For this reason, the input file has +(currently unused) sections dedicated to the identification of direction +cosines that in the future will allow the module to identify the correct +orientation of noncircular members. The current release only accepts +tubular (circular) members. + +The file is organized into several functional sections. Each section +corresponds to an aspect of the SubDyn model and substructure. + +If this manual refers to an ID in a table entry, it is an integer +identifier for the table entry and must be unique for a given table +entry. + +A sample SubDyn primary input file is given in Appendix A. + +The input file begins with two lines of header information, which is for +the user but is not used by the software. + + +Simulation Control Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Users can set the **Echo** flag to TRUE to have SubDyn echo the +contents of the SubDyn input file (useful for debugging errors in the +input file). The echo file has the naming convention of +**OutRootName.SD.ech**. **OutRootName** is either specified in the +SUBDYN section of the driver input file when running SubDyn standalone, +or by FAST, when running a coupled simulation, from FAST’s main input +file. + +**SDdeltaT** specifies the fixed time step of the integration in +seconds. The keyword ‘DEFAULT’ may be used to indicate that the module +should employ the time step prescribed by the driver code +(FAST/standalone driver program). + +**IntMethod** specifies the integration algorithm to use. There are +four options: 1) Runge-Kutta 4\ :sup:`th`-order explicit (RK4); 2) +Adams-Bashforth 4\ :sup:`th`-order explicit predictor (AB4); 3) +Adams-Bashforth-Moulton 4\ :sup:`th`-order explicit predictor-corrector +(ABM4); 4) Adams-Moulton implicit 2\ :sup:`nd`-order (AM2). See Section +on how to properly select this and the previous parameter values. + +**SttcSolve** is a flag that specifies whether SIM (see Sections 5 and +6) shall be employed. Through this method, all (higher frequency) modes +that are not considered by the C-B reduction are treated +quasi-statically (see Section for more details). This treatment helps +minimize the number of retained modes needed to capture effects such as +static gravity and buoyancy loads, and high-frequency loads transferred +from the turbine. + +FEA and Craig-Bampton Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**FEMMod** specifies one of the following options for finite-element +formulation: 1) Euler-Bernoulli; 3) Timoshenko. Tapered formulations (2 +and 4) have yet to be implemented and will be available in a future +release. + +**NDiv** specifies the number of elements per member. Analysis nodes +are located at the ends of elements and the number of analysis nodes per +member equals **NDiv** + 1. **NDiv** is applied uniformly to all +members regardless of the member’s length, hence it could result in +small elements in some members and long elements in other members. +Increasing the number of elements per member may increase accuracy, with +the trade-off of increased memory usage and computation time. We +recommend using **NDiv** > 1 when modeling tapered members. + +**CBMod** is a flag that specifies whether or not the C-B reduction +should be carried out by the module. If FALSE, then the full +finite-element model is retained and **Nmodes** is ignored. + +**Nmodes** sets the number of internal C-B modal DOFs to retain in the +C-B reduction. **Nmodes** = 0 corresponds to a Guyan (static) +reduction. **Nmodes** is ignored if **CBMod** is set to FALSE, +meaning the full finite-element model is retained by keeping all modes. + +**JDampings** specifies value(s) of damping coefficients as a +percentage of critical damping for the retained C-B modes. Distinct +damping coefficients for each retained mode should be listed on the same +line, separated by white space. If the number of **JDampings** is less +than the number of retained modes, the last value will be replicated for +all the remaining modes. + +For more information on these parameters and guidelines on how to set +them, see Sections 5 and 6. + +Structure Joints +~~~~~~~~~~~~~~~~ + +The finite-element model is based on a substructure composed of joints +interconnected by members. **NJoints** is the user-specified number of +joints, and determines the number of rows in the subsequent table. +Because a member connects two joints, **NJoints** must be greater than +or equal to two. Each joint listed in the table is identified by a +unique integer, **JointID**; each integer between one and +**NJoints** must be present in the table, but they need not be +sequential. The (*X*,\ *Y*,\ *Z*) coordinate of each joint is specified +in the substructure (SS) coordinate system, which coincides with the +global inertial-frame coordinate system via **JointXss**, +**JointYss**, and **JointZss**, respectively. This version of SubDyn +does not consider overlap when multiple members meet at a common joint, +therefore, it tends to overestimate the total substructure mass. Member +overlap and node offset calculations will be considered in a future +release of SubDyn. + +Note for HydroDyn coupling: modeling a fixed-bottom substructure +embedded into the seabed (e.g., through piles or suction buckets) +requires that the lowest member joint(s) in HydroDyn lie(s) below the +water depth. Placing a joint at or above the water depth will result in +static and dynamic pressure loads being applied at the joint. When +SubDyn is coupled to FAST, the joints and members need not match between +HydroDyn and SubDyn—FAST’s mesh-mapping utility handles transfer of +motion and loads across meshes in a physically relevant manner (Sprague +et al. 2014), but consistency between the joints and members in HydroDyn +and SubDyn is advised. + +Base Reaction Joints +~~~~~~~~~~~~~~~~~~~~~ + +SubDyn requires the user to specify the boundary joints. **NReact** +should be set equal to the number of joints (defined earlier) at the +bottom of the structure (i.e., seabed) that are fully constrained; +**NReact** also determines the number of rows in the subsequent table. +In SubDyn, **NReact** must be greater than or equal to one. Each joint +listed in the table is identified by a unique integer, **RJointID**, +which must correspond to the **JointID** value found in the STRUCTURE +JOINTS table. The flags **RctTDXss**, **RctTDYss**, **RctTDZss**, +**RctRDXss**, **RctRDYss**, **RctRDZss** indicate the fixity value +for the three translations (TD) and three rotations (RD) in the SS +coordinate system (global inertial-frame coordinate system). One denotes +fixed and zero denotes free (instead of TRUE/FALSE). **SSIfile** +points to the relative path and filename for an SSI information file. +This version of SubDyn can, in fact, handle partially restrained joints +by setting one or more DOF flags to 0 and providing the appropriate +stiffness and mass matrix elements for that DOF via the **SSIfile**. +If a DOF flag is set to 1, then the node DOF is considered restrained +and the associated matrix elements potentially provided in the +**SSIfile** will be ignored. + + +Interface Joints +~~~~~~~~~~~~~~~~ + +SubDyn requires the user to specify the interface joints. **NInterf** +should be set equal to the number of joints at the top of the structure +(i.e., TP); **NInterf** also determines the number of rows in the +subsequent table. In SubDyn, **NInterf** must be greater than or equal +to one. Note that these joints will be assumed to be rigidly connected +to the platform reference point of ElastoDyn (see FAST documentation) +when coupled to FAST, or to the TP reference point if SubDyn is run in +stand-alone mode. Each joint listed in the table is identified by a +unique integer, **IJointID**, which must correspond to the *JointID* +value found in the STRUCTURE JOINTS table. The flags **ItfTDXss**, +**ItfTDYss**, **ItfTDZss**, **ItfRDXss**, **ItfRDYss**, +**ItfRDZss** indicate the fixity value for the three translations (TD) +and three rotations (RD) in the SS coordinate system (global +inertial-frame coordinate system). One denotes fixed and zero denotes +free (instead of TRUE/FALSE). This version of SubDyn cannot handle +partially restrained joints, so all flags must be set to one; different +degrees of fixity will be considered in a future release. + +Members +~~~~~~~ + +**NMembers** is the user-specified number of members and determines +the number of rows in the subsequent table. Each member listed in the +table is identified by a unique integer, **MemberID**. Each integer +between one and **NMembers** must be present in the table, but they +need not be sequential. For each member distinguished by **MemberID**, +**MJointID1** specifies the starting joint and **MJointID2** +specifies the ending joint, corresponding to an identifier +(**JointID**) from the STRUCTURE JOINTS table. Likewise, +**MPropSetID1** corresponds to the identifier **PropSetID** from the +MEMBER X-SECTION PROPERTY table (discussed next) for starting +cross-section properties and **MPropSetID2** specifies the identifier +for ending cross-section properties, allowing for tapered members. +**COSMID** refers to the IDs of the members’ cosine matrices for +noncircular members; the current release ignores this column. + +Member Cross-Section Properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Members in SubDyn are assumed to be straight, circular, possibly +tapered, and hollow cylinders. Future releases will allow for generic +cross-sections to be employed. These special cross-section members will +be defined in the second of two tables in the input file (Member +X-Section Property data 2/2), which is currently ignored. + +For the circular cross-section members, properties needed by SubDyn are +material Young’s modulus, **YoungE**, shear modulus, **ShearG**, and +density, **MatDens**, member outer diameter, **XsecD**, and member +thickness, **XsecT**. Users will need to create an entry in the first +table within this section of the input file distinguished by +**PropSetID**, for each unique combination of these five properties. +The member property-set table contains **NPropSets** rows. The member +property sets are referred to by their **PropSetID** in the MEMBERS +table, as described in Section . Note, however, that although diameter +and thickness will be linearly interpolated within an individual member, +SubDyn will not allow *material* properties to change within an +individual member. + +The second table in this section of the input file (not to be used in +this release) will have **NXPropSets** rows (assumed to be zero for +this release), and have additional entries when compared to the previous +table, including: cross-sectional area (**XsecA**), cross-sectional +shear area along the local principal axes *x* and *y* (**XsecAsx**, +**XsecAsy**), cross-sectional area second moment of inertia about *x* +and *y* (**XsecJxx**, **XsecJyy**), and cross-sectional area polar +moment of inertia (**XsecJ0**). The member cosine matrix section (see +Section ) will help determine the correct orientation of the members +within the assembly. + +Member Cosine Matrices COSM (i,j) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This table is not currently used by SubDyn, but in future releases it +will need to be populated if members with cross-sections other than +circular will be employed. + +**NCOSMs** rows, one for each unique member orientation set, will need +to be provided. Each row of the table will list the nine entries of the +direction cosine matrices (COSM11, COSM12,…COSM33) for matrix elements +(1,1), (1,2),…(3,3) that establish the orientation of the local member +axes (*x*,\ *y* principal axes in the cross-sectional plane, *z* along +the member longitudinal axis) with respect to the SS coordinate system +(local-to-global transformation matrices). + +Joint Additional Concentrated Masses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SubDyn can accept **NCmass** lumped masses/inertias defined at the +joints. The subsequent table will have **NCmass** rows, in which for +each joint distinguished by **CMJointID** (corresponding to an +identifier, **JointID**, from the STRUCTURE JOINTS table), **JMass** +specifies the lumped mass value, and **JMXX**, **JMYY**, **JMZZ** +specify the mass second moments of inertia with respect to the SS +coordinate system. + +Output: Summary and Outfile +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In this section of the input file, the user sets flags and switches for +the desired output behavior. + +Specifying **SDSum** = TRUE causes SubDyn to generate a summary file +with name **OutRootName**.SD.sum*. **OutRootName** is either +specified in the SUBDYN section of the driver input file when running +SubDyn in stand-alone mode, or in the FAST input file when running a +coupled simulation. See Section 4.2 for summary file details. + +In this release, **OutCOSM** is ignored. In future releases, +specifying **OutCOSM** = TRUE will cause SubDyn to include direction +cosine matrices (undeflected) in the summary file for only those members +requested in the list of output channels. + +Specifying **OutAll** = TRUE causes SubDyn to output forces and +moments at all of the joints (not internal nodes). That is, the static +(elastic) and dynamic (inertia) components of the three forces and three +moments at the end node of each member connected to a given joint are +output for all joints. These outputs are included within the +**OutRootName**.SD.out* output file in addition to those directly +specified through the output channels section below. + +If **OutSwtch** is set to one, outputs are sent to a file with the +name **OutRootName**.SD.out*. If **OutSwtch** is set to two, outputs +are sent to the calling program (FAST) for writing in its main output +file (not available in stand-alone mode). If **OutSwtch** is set to +three, both file outputs occur. In stand-alone mode, setting +**OutSwtch** to two results in no output file being produced. + +If **TabDelim** is set to TRUE and **OutSwtch** is set to one, the +output file **OutRootName**.SD.out* will be tab-delimited. + +With **OutDec** set to an integer value greater than one, the output +file data rate will be decimated, and only every **OutDec**-th value +will be written to the file. This applies only to SubDyn’s output file +(**OutRootName**.SD.out*)—not FAST’s. + +The **OutFmt** and **OutSFmt** parameters control the formatting of +SubDyn’s output file for the output data and the channel headers, +respectively. SubDyn currently does not check the validity of these +format strings. They need to be valid Fortran format strings. +**OutSFmt** is used for the column header and **OutFmt** is used for +the channel data. Therefore, in order for the headers and channel data +to align properly, the width specification should match. For example: + +| "ES11.4" OutFmt +| "A11" OutSFmt. + +Member Output List +~~~~~~~~~~~~~~~~~~ + +SubDyn can output load and kinematic quantities at up to nine locations +for up to nine different members, for a total of 81 possible local +member output locations. **NMOutputs** specifies the number of members +that output is requested for. The user must create a table entry for +each requested member. Within a row of this table, **MemberID** is the +ID specified in the MEMBERS table, and **NOutCnt** specifies how many +nodes along the member will generate output. **NodeCnt** specifies +those node numbers (a separate entry on the same line for each node) for +output as an integer index from the start-joint (node 1) to the +end-joint (node **NDiv** + 1) of the member. The outputs specified in +the SDOutList section determines which quantities are actually output at +these locations. + +Output Channels- SDOutList Section +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This section specifies which quantities are output by SubDyn. Enter one +or more lines containing quoted strings that in turn contain one or more +output parameter names. Separate output parameter names by any +combination of commas, semicolons, spaces, and/or tabs. If a parameter +name is prefixed with a minus sign, “-â€, underscore, “\_â€, or the +characters “m†or “Mâ€, SubDyn will multiply the value for that channel +by –1 before writing the data. The parameters are written in the order +they are listed in the input file. SubDyn allows the use of multiple +lines so that users can break their lists into meaningful groups and so +the lines can be shorter. Comments may also be entered after the closing +quote on any of the lines. Entering a line with the string “END†at the +beginning of the line or at the beginning of a quoted string found at +the beginning of the line will cause SubDyn to quit scanning for more +lines of channel names. Modal kinematics and member-node-, base-, and +interface-related kinematic and load quantities can be selected. +Member-node-related data follow the organization described in Section . +If SubDyn encounters an unknown/invalid channel name, it prints an error +message and halts execution. Please refer to Appendix C for a complete +list of possible output parameters and their names. + +SSI Input File +-------------- + +Individual SSI files (*SSIfiles*) can be provided for each restrained +node, therefore the maximum number of SSIfiles is **NReact**. In an +SSIfile, up to 21 elements for the SSI mass matrix and up to 21 SSI +stiffness matrix elements can be provided. The mass and stiffness +elements account for both pile and soil effects. No additional damping +can be provided at this point. + +The order of the elements is not important, because each element value +is accompanied by a string label that identifies the actual element. The +stiffness matrix accepted labels are: 'Kxx', 'Kxy', 'Kyy', 'Kxz', 'Kyz’, +'Kzz’, 'Kxtx', 'Kytx', 'Kztx', 'Ktxtx', 'Kxty', 'Kyty','Kzty’, 'Ktxty', +'Ktyty', ‘Kxtz', 'Kytz', 'Kztz', 'Ktxtz', 'Ktytz', 'Ktztz'. + +If any matrix element is not provided it will be set to infinity (i.e., +machine ‘huge’) by default. + +For the mass matrix the accepted labels are: +'Mxx','Mxy','Myy','Mxz','Myz', 'Mzz','Mxtx','Mytx','Mztx', 'Mtxtx', +'Mxty', 'Myty', 'Mzty', 'Mtxty', 'Mtyty', 'Mxtz', 'Mytz', 'Mztz', +'Mtxtz', 'Mtytz', 'Mtztz'. If any matrix element is not provided it will +be set to 0 by default. The labels contain ‘K’ or ‘M’ to specify +stiffness or mass matrix elements, and then the directions they apply +to, e.g., ‘Kxy’ refers to the force along x due to a unit displacement +along y; the ‘t’ refers to the rotation about one of the ‘x’,’y’, or ’z’ +axes in the global coordinate system. + +Units are in SI system (N/m; N/m/rad; Nm/rad, Kg, kgm, kgm2). + +Note that by selecting fixities of 1 in the various DOFs of the +restrained nodes, the columns and rows associated with those DOFs will +be removed, therefore the associated matrix elements will be ignored. + +A sample SubDyn SSI input file is given in Appendix C. diff --git a/docs/source/user/subdyn/introduction.rst b/docs/source/user/subdyn/introduction.rst new file mode 100644 index 000000000..fff4932c1 --- /dev/null +++ b/docs/source/user/subdyn/introduction.rst @@ -0,0 +1,122 @@ +.. _sd_intro: + +Introduction +============ + +`SubDyn `__ is a time-domain +structural-dynamics module for multimember fixed-bottom substructures +created by the National Renewable Energy Laboratory (NREL) through U.S. +Department of Energy Wind and Water Power Program support. The module +has been coupled into the FAST aero-hydro-servo-elastic computer-aided +engineering (CAE) tool. Substructure types supported by SubDyn include +monopiles, tripods, jackets, and other non-floating lattice-type +substructures common for offshore wind installations in shallow and +transitional water depths. SubDyn can also be used to model lattice +support structures for land-based wind turbines. + +The new SubDyn module follows the requirements of the FAST +modularization framework, couples to +`OpenFAST `__, and +provides new capabilities (relative to prior released versions of the +software) for modeling the dynamic loading on multimember substructures. +(Refer to Appendix E and the *changelog.txt* file that is provided in +the archives for more details about changes among different versions.) +SubDyn can also be driven as a standalone code to compute the mode +shapes, natural frequencies, and time-domain responses of substructures +under prescribed motion at the interface to the tower, uncoupled from +FAST and in the absence of external loading other than gravity. + +SubDyn relies on two main engineering schematizations: (1) a linear +frame finite-element beam model (LFEB), and (2) a dynamics system +reduction via the Craig-Bampton(C-B) method, together with a +static-improvement method (SIM), greatly reducing the number of modes +needed to obtain an accurate solution. More details can be found in +Section 6, and in :cite:`song2013, damiani2013, damiani2013omae`. + +In SubDyn, the substructure is considered to be either clamped or +supported by springs at the seabed, and rigidly connected to the +transition piece (TP) at the substructure top nodes (interface nodes). +The spring constants are provided by the user to simulate +soil-structure-interaction (SSI). Other restraint formulations may be +implemented in the future. Only the substructure structural dynamics are +intended to be modeled within SubDyn. When integrated with FAST, the +structural dynamics of the TP, tower, and rotor-nacelle assembly (RNA) +are modeled within FAST’s ElastoDyn module and hydrodynamics are modeled +within FAST’s `HydroDyn `__ module. For +full lattice support structures or other structures with no transition +piece, however, the entire support structure up to the yaw bearing may +be modeled within SubDyn. Modeling the tower in SubDyn as opposed to +ElastoDyn, for example, allows for the possibility of including more +than the first two fore-aft and side-to-side bending modes, thus +accounting for more general flexibility of the tower and its segments. +However, for tubular towers, the structural model in ElastoDyn tends to +be more accurate because ElastoDyn considers geometric nonlinearities +not treated in SubDyn. + +Loads and responses are transferred between SubDyn, HydroDyn, and +ElastoDyn via the FAST driver program (glue code) to enable +hydro-elastic interaction at each coupling time step. At the interface +nodes, the TP six degree-of-freedom (DOF) displacements (three +translations and three rotations), velocities, and accelerations are +inputs to SubDyn from ElastoDyn; and the six reaction loads at the TP +(three forces and three moments) are outputs from SubDyn to ElastoDyn. +SubDyn also outputs the local substructure displacements, velocities, +and accelerations to HydroDyn in order to calculate the local +hydrodynamic loads that become inputs for SubDyn. In addition, SubDyn +can calculate member internal reaction loads, as requested by the user +(see Figure 1). + + +.. _flow-chart: + +.. figure:: figs/flowchart.png + :width: 100% + + SubDyn, HydroDyn, and FAST 8 coupled interaction + + +The input file defines the substructure geometry, material properties, +restraints and SSI data files, finite-element resolution, number of +retained modes in the dynamics system reduction, modal damping +coefficients, and auxiliary parameters. The geometry is defined by joint +coordinates in the global reference system (inertial-frame coordinate +system shown in ), with the origin at the intersection of the +undeflected tower centerline with mean sea level (MSL) or ground level +for land-based structures. A member connects two joints; multiple +members may use a common joint. Nodes are the result of the member +refinement into multiple (***NDiv*** input parameter) elements (nodes +are located at the ends of each element, as shown in ), and they are +calculated by the module. + +In the current release, the geometry of a member is defined by its outer +diameter and wall thickness (assuming a tubular geometry), and the +material properties are defined by its Young’s modulus, shear modulus, +and mass density. Member properties are specified at the joints; if +properties change from one joint to the other, they will be linearly +interpolated for the inner elements. Thus, a tapered member will be +treated as a cylindrical member with step-wise variation of its +properties. In a future release, a tapered finite-element formulation +will be implemented, and a more accurate representation of a tapered +member will become available. + +The hydrodynamic loads (including buoyancy) are computed by HydroDyn and +transferred by the glue code at those nodes that are underwater +(submerged nodes). Additionally, the self-weight distributed load +components (from gravity) are calculated by SubDyn and applied at all +the nodes. Note that other load and inertial properties may be input via +the HydroDyn module input file, where marine growth and +flooding/ballasting of the members can be specified. + +This document is organized as follows. Section :ref:`running-subdyn` details how to obtain +the SubDyn and FAST software archives and run either the stand-alone +version of SubDyn or SubDyn coupled to FAST. Section :ref:`input-files` describes the +SubDyn input files. Section 4 discusses the :ref:`output-files` generated by +SubDyn; these include echo files, a summary file, and the results file. +Section 5 provides modeling guidance when using SubDyn. The SubDyn +theory is covered in Section :ref:`subdyn-theory`. Section :ref:`future-work` outlines future work, and +Section 8 contains a list of references. Example input files are shown +in Appendices :numref:`sd_input_files` and B. A summary of available output channels are found +in Appendix :ref:`app-output-channel`. Instructions for compiling the stand-alone SubDyn program +are detailed in Appendix D. Appendix E tracks the major changes that +have been made to SubDyn for each public release. + diff --git a/docs/source/user/subdyn/modeling.rst b/docs/source/user/subdyn/modeling.rst new file mode 100644 index 000000000..92f059ebe --- /dev/null +++ b/docs/source/user/subdyn/modeling.rst @@ -0,0 +1,312 @@ +.. _modeling-considerations: + +Modeling Considerations +======================= + +SubDyn was designed as a flexible tool for modeling a wide range of +substructures for both land-based and offshore applications. This +section provides some general guidance to help construct models that are +compatible with SubDyn. + +Please refer to the theory in Section 6 for detailed information about +SubDyn’s coordinate systems, and the theoretical approach we have +followed in SubDyn. + +Model Discretization +-------------------- + +SubDyn allows for the specification of arbitrary multimember structure +geometries. The user defines the geometry of a structure in SubDyn using +joints and members. Specifically, the user specifies a list of joints +that represent the endpoints of beams, and the connectivity between one +or more members at each joint. Members and their cross-sectional +properties are then defined between two joints. Members can be further +subdivided into multiple (**NDiv**) elements to increase the model +resolution. Nodes, where the numerical calculations take place, are +located at the endpoints of each element. To keep the mesh as uniform as +possible when using **NDiv**, the initial member definition should +also have a roughly uniform mesh. For tapered members, we recommend +setting **NDiv** > 1. Improper discretization of the members may +decrease the accuracy of the model. + +When SubDyn is coupled to FAST, the joints and members need not match +between HydroDyn and SubDyn—FAST’s mesh-mapping utility handles the +transfer of motion and loads across meshes in a physically relevant +manner :cite:`sprague2014`, but consistency between the joints and +members in HydroDyn and SubDyn is advised. + +For offshore applications, because of the exponential decay of +hydrodynamic loads with depth, HydroDyn requires higher resolution near +the water free surface to properly capture loads as waves oscillate +about the still water level (SWL). We recommend that the HydroDyn +discretization not exceed element lengths of 0.5 m in the region of the +free surface (5 to 10 m above and below SWL), 1.0 m between 25- and 50-m +depth, and 2.0 m in deeper waters. + +When SubDyn is hydro-elastically coupled to HydroDyn through FAST for +the analysis of fixed-bottom offshore systems, we recommend that the +length ratio between elements of SubDyn and HydroDyn not exceed 10 to 1. +As such, we recommend that the SubDyn discretization not exceed element +lengths of 5 m in the region of the free surface, 10 m down to 25- to +50-m depth, and 20 m in deeper waters. These are not absolute rules, but +rather a good starting point that will likely require refinement for a +given substructure. Additional considerations for SubDyn discretization +include aspects that will impact structural accuracy, such as member +weight, substructure modes and/or natural frequencies, load transfer, +tapered members, and so on. + +Members in SubDyn are assumed to be straight circular (and possibly +tapered) cylinders. The use of more generic cross-sectional shapes will +be considered in a future release. + +Foundations +----------- + +There are two methods that can be used to model foundation flexibility +or soil-structure interaction in SubDyn. The first method makes us of +the SSI stiffness and mass matrices at the partially restrained bottom +joints as described in Sections 3.3.4, 3.4, and 6. The second method +mimics the flexibility of the foundation through the apparent (or +effective) fixity (AF) length approach, which idealizes a pile as a +cantilever beam that has properties that are different above and below +the mudline. The beam above the mudline should have the real properties +(i.e., diameter, thickness, and material) of the pile. The beam below +the mudline is specified with effective properties and a fictive length +(i.e., the distance from the mudline to the cantilevered base) that are +tuned to ensure that the overall response of the pile above the mudline +is the same as the reality. The response can only be identical under a +particular set of conditions; however, it is common for the properties +of the fictive beam to be tuned so that the mudline displacement and +rotation would be realistic when loaded by a mudline shear force and +bending moment that are representative of the loading that exists when +the offshore wind turbine is operating under normal conditions. + +Note that in HydroDyn, all members that are embedded into the seabed +(e.g., through piles or suction buckets) must have a joint that is +located below the water depth. In SubDyn, the bottom joint(s) will be +considered clamped or partially restrained and therefore need not be +located below the seabed when not applying the AF approach. For example, +if the water depth is set to 20 m, and the user is modeling a +fixed-bottom monopile with a rigid foundation, then the bottom-most +joint in SubDyn can be set at *Z* = -20 m; HydroDyn, however, needs to +have a Z-coordinate such that *Z* < -20 m. This configuration avoids +HydroDyn applying static and dynamic pressure loads from the water on +the bottom of the structure. When the AF approach is applied, the +bottom-most joint in SubDyn should be set at *Z* < -20 m. + + +Member Overlap +-------------- + +As mentioned earlier, the current version of SubDyn is incapable of +treating the overlap of members at the joints, resulting in an +overestimate of the mass and potentially of the structure stiffness. One +strategy to overcome this shortcoming employs virtual members to +simulate the portion of each member within the overlap at a joint. The +virtual members should be characterized by low self-mass and high +stiffness. This can be achieved by introducing virtual joints at the +approximate intersection of the finite-sized members, and then +specifying additional members from these new joints to the original +(centerline) joints. The new virtual members then use reduced material +density and increased Young’s and shear moduli. Care is advised in the +choice of these parameters as they may render the system matrix +singular. Inspection of the eigenvalue results in the summary file +should confirm whether acceptable approximations have been achieved. + +.. _TowerTurbineCpling + +Substructure Tower/Turbine Coupling +----------------------------------- + +When SubDyn is coupled to FAST, the 6 DOFs of the platform in ElastoDyn +must be enabled to couple loads and displacements between the turbine +and the substructure. The platform reference-point coordinates in +ElastoDyn should also be set equal to the TP reference-point’s +coordinates (commonly indicating either the tower-base flange location, +or TP centroid, or TP center of mass) that the user may have set in the +stand-alone mode for checking the SubDyn model. A rigid connection +between the SubDyn interface joints and TP reference point (:math:`{\equiv}` platform +reference point) is assumed. + +For full lattice support structures or other structures with no +transition piece, the entire support structure up to the yaw bearing may +be modeled within SubDyn. Modeling the tower in SubDyn as opposed to +ElastoDyn, for example, allows the ability to include more than the +first two fore-aft and side-to-side bending modes, thus accounting for +more general flexibility of the tower and its segments; however, for +tubular towers, the structural model in ElastoDyn tends to be more +accurate because ElastoDyn considers geometric nonlinearities not +treated in SubDyn. When modeling full-lattice towers using SubDyn, the +platform reference point in ElastoDyn can be located at the yaw bearing; +in this case, the tower-bending DOFs in ElastoDyn should be disabled. + +If FAST is run with SubDyn but not HydroDyn, the water depth will be +automatically set to 0 m. This will influence the calculation of the +reaction loads. Reactions are always provided at the assumed mudline, +therefore, they would not be correctly located for an offshore turbine +as a result. Thus, it is recommended that HydroDyn always be enabled +when modeling bottom-fixed offshore wind turbines. + +ElastoDyn also needs tower mode shapes specified (coefficients of +best-fit sixth-order polynomials), derived using appropriate tower-base +boundary conditions. They can be derived with an appropriate software +(finite-element analysis, energy methods, or analytically) and by making +use of the SubDyn-derived equivalent substructure stiffness and mass +matrices (the **KBBt** and **MBBt** matrices found in the SubDyn summary +file) to prescribe the boundary conditions at the base of the tower. + +For instance, using NREL’s BModes software, the SubDyn-obtained matrices +can be used in place of the hydrodynamic stiffness (**hydro\_K**) and mass +matrices (**hydro\_M**) (**mooring\_K** can be set to zero). By setting +the **hub\_conn** boundary condition to two (free-free), BModes will +calculate the mode shapes of the tower when tower cross-sectional +properties are supplied. To obtain eigenmodes that are compatible with +the FAST modal treatment of the tower (i.e., no axial or torsional modes +and no distributed rotational-inertia contribution to the eigenmodes), +the tower-distributed properties should be modified accordingly in +BModes (e.g., by reducing mass moments of inertia towards zero and by +increasing torsional and axial stiffness while assuring convergence of +the results; see also +`https://wind.nrel.gov/forum/wind/viewtopic.php?f=4&t=742 `__). + +The rotational inertia of the undeflected tower about its centerline is +not currently accounted for in ElastoDyn. Thus, when the nacelle-yaw DOF +is enabled in ElastoDyn there will not be any rotational inertia of the +platform-yaw DOF (which rotates the tower about its centerline) when +both the platform-yaw inertia in ElastoDyn is zero and the tower is +undeflected. To avoid a potential division-by-zero error in ElastoDyn +when coupled to SubDyn, we recommend setting the platform-yaw inertia +(**PtfmYIner**) in ElastoDyn equal to the total rotational inertia of +the undeflected tower about its centerline. Note that the platform mass +and inertia in ElastoDyn can be used to model heavy and rigid transition +pieces that one would not want to model as a flexible body in either the +ElastoDyn tower or SubDyn substructure models. + +The C-B method assumes no damping for the interface modes. This is +equivalent to having six undamped rigid-body DOFs at the TP reference +point in the absence of aerodynamic or hydrodynamic damping. Experience +has shown that negligible platform-heave damping can cause numerical +problems when SubDyn is coupled to FAST. One way to overcome this +problem is to augment overall system damping with an additional linear +damping for the platform-heave DOF. This augmentation can be achieved +quite easily by calculating the damping from Eq. :eq:`damping` and specifying this +as the (3,3) element of HydroDyn’s additional linear damping matrix, +**AddBLin**. Experience has shown that a damping ratio of 1% of +critical (:math:`{\zeta=0.01}`) is sufficient. In Eq. :eq:`damping`, :math:`{K_{33}^{(SD)}}` is the equivalent heave stiffness +of the substructure (the (3,3) element of the **KBBt** (i.e., :math:`{\tilde{K}_{BB}}`) matrix +found in the SubDyn summary file, see also Section 6), :math:`{M_{33}^{(SD)}}` is the equivalent +heave mass of the substructure (the (3,3) element of the **MBBt** +(i.e., :math:`{\tilde{M}_{BB}}`) matrix found in the SubDyn summary file, see also Section 6), +and :math:`{M^{(ED)}}` is the total mass of the rotor, nacelle, tower, and TP (found in the +ElastoDyn summary file). + +.. math:: :label: damping + + C_{33}^{(HD)} = 2 \zeta \sqrt{ K_{33}^{(SD)} \left( M_{33}^{(SD)}+M^{(ED)} \right)} + + +To minimize extraneous excitation of the platform-heave DOF, it is +useful to set the initial platform-heave displacement to its natural +static-equilibrium position, which can be approximated by Eq. :eq:`ptfmheave`, where +is the magnitude of gravity. *PtfmHeave* from Eq. :eq:`ptfmheave` should be +specified in the initial conditions section of the ElastoDyn input file. + +.. math:: :label: ptfmheave + + PtfmHeave = -\dfrac{ \left( M_{33}^{(SD)}+M^{(ED)} \right) g}{K_{33}^{(SD)}} + + + + + +Self-Weight Calculations +------------------------ + +SubDyn will calculate the self-weight of the members and apply +appropriate forces and moments at the element nodes. Lumped masses will +also be considered as concentrated gravity loads at prescribed joints. +The array of self-weight forces can be seen in the summary file if the +code is compiled with DEBUG compiler directives. In general, SubDyn +assumes that structural motions of the substructure are small, such that +(1) small-angle assumptions apply to structural rotations and (2) the +so-called P- :math:`{\Delta}` effect is negligible, and therefore undeflected node +locations are used for self-weight calculations. + +Note On Other Load Calculations +------------------------------- + +When SubDyn is coupled to HydroDyn through FAST, the hydrodynamic loads, +which include buoyancy, marine-growth weight, and wave and current +loads, will be applied to the effective, deflected location of the nodes +by the mesh-mapping routines in the glue code. Those loads, however, are +based on wave kinematics at the undeflected position (see Jonkman et al. +2014 for more information). + +.. _CBguide: + +Craig-Bampton Guidelines +------------------------ + +When SubDyn is coupled with FAST, it is important to choose a sufficient +number of C-B modes, ensuring that the vibrational modes of the coupled +system are properly captured by the coupled model. We recommend that all +modes up to at least 2-3 Hz be captured; wind, wave, and turbine +excitations are important for frequencies up to 2-3 Hz. Eigenanalysis of +the linearized, coupled system will make checking this condition +possible and aid in the selection of the number of retained modes; +however, the linearization process has yet to be implemented in FAST v8. +Until full-system linearization is made available, experience has shown +that it is sufficient to enable all C-B modes up to 10 Hz (the natural +frequencies of the C-B modes are written to the SubDyn summary file). If +SIM (see Section :numref:`sim`) is not enabled, in addition to capturing physical +modes up to a given frequency, the highest C-B mode must include the +substructure axial modes so that gravity loading from self-weight is +properly accounted for within SubDyn. This inclusion likely requires +enabling a high number of C-B modes, reducing the benefit of the C-B +reduction. Thus, we recommend employing the C-B reduction with SIM +enabled. Because of the fixed-fixed treatment of the substructure +boundary conditions in the C-B reduction, the C-B modes will always have +higher natural frequencies than the physical modes. + +Integration Time Step Guidelines +-------------------------------- + +Another consideration when creating SubDyn input files is the time step +size. SubDyn offers three explicit time-integrators --- the fourth-order +Runge-Kutta (RK4), fourth-order Adams-Bashforth (AB4), fourth-order +Adams-Bashforth-Moulton (ABM4) methods --- and the implicit second-order +Adams-Moulton (AM2) method. Users have the option of using the global +time step from the glue code or an alternative SubDyn-unique time step +that is an integer multiple smaller than the glue-code time step. +It is essential that a small enough time step is used to ensure solution +accuracy (by providing a sufficient sampling rate to characterize all +key frequencies of the system), numerical stability of the selected +explicit time-integrator, and that the coupling with FAST is numerically +stable. + +For the RK4 and ABM4 methods, we recommend that the SubDyn time step +follow the relationship shown in Eq. :eq:`dtmax`, where :math:`{f_{max}}` is the higher of (1) the +highest natural frequency of the retained C-B modes and (2) the highest +natural frequency of the physical modes when coupled to FAST. Although +the former can be obtained from the SubDyn summary file, the latter is +hard to estimate before the full-system linearization of the coupled +FAST model is realized. Until then, experience has shown that the +highest physical mode when SubDyn is coupled to FAST is often the +platform-heave mode of ElastoDyn, with a frequency given by Eq. :eq:`freq`, +where the variables are defined in Section 5.3. + +.. math:: :label: dtmax + + dt_{max} = \dfrac{1}{10 f_{max}} + +.. math:: :label: freq + + f= \dfrac{1}{2\pi} \sqrt{\dfrac{K_{33}^{(SD)}}{ M_{33}^{(SD)}+M^{(ED)}}} + +For the AB4 method, the recommended time step is half the value given by +Eq. :eq:`dtmax`. + +For AM2, being implicit, the required time step is not driven by natural +frequencies within SubDyn, but should still be chosen to ensure solution +accuracy and that the coupling to FAST is numerically stable. + diff --git a/docs/source/user/subdyn/notations.rst b/docs/source/user/subdyn/notations.rst new file mode 100644 index 000000000..2ef73db04 --- /dev/null +++ b/docs/source/user/subdyn/notations.rst @@ -0,0 +1,670 @@ + +.. contents:: + :depth: 3 +.. + +**NOTICE** + +This report was prepared as an account of work sponsored by an agency of +the United States government. Neither the United States government nor +any agency thereof, nor any of their employees, makes any warranty, +express or implied, or assumes any legal liability or responsibility for +the accuracy, completeness, or usefulness of any information, apparatus, +product, or process disclosed, or represents that its use would not +infringe privately owned rights. Reference herein to any specific +commercial product, process, or service by trade name, trademark, +manufacturer, or otherwise does not necessarily constitute or imply its +endorsement, recommendation, or favoring by the United States government +or any agency thereof. The views and opinions of authors expressed +herein do not necessarily state or reflect those of the United States +government or any agency thereof. + + | This report is available at no cost from the National Renewable + Energy + | Laboratory (NREL) at www.nrel.gov/publications. + + Available electronically at http://www.osti.gov/scitech + + | Available for a processing fee to U.S. Department of Energy + | and its contractors, in paper, from: + + | U.S. Department of Energy + | Office of Scientific and Technical Information + + | P.O. Box 62 + | Oak Ridge, TN 37831-0062 + | phone: 865.576.8401 + | fax: 865.576.5728 + | email: + `mailto:reports@adonis.osti.gov `__ + + Available for sale to the public, in paper, from: + + | U.S. Department of Commerce + | National Technical Information Service + | 5285 Port Royal Road + | Springfield, VA 22161 + | phone: 800.553.6847 + | fax: 703.605.6900 + | email: orders@ntis.fedworld.gov + | online ordering: http://www.ntis.gov/help/ordermethods.aspx + + *Cover Photos: (left to right) photo by Pat Corkery, NREL 16416, + photo from SunEdison, NREL 17423, photo by Pat Corkery, NREL 16560, + photo by Dennis Schroeder, NREL 17613, photo by Dean Armstrong, NREL + 17436, photo by Pat Corkery, NREL 17721.* + +|Recycle Logo| Printed on paper containing at least 50% wastepaper, +including 10% post consumer waste. + +Preface + +This manual offers both a quick reference guide and a more in-depth +theory guide for the SubDyn software program. It is intended to be used +by the general user in combination with the FAST and HydroDyn manuals. +The manual will be updated as new releases are issued and as needed to +provide further information on advancements or modifications to the +software. + +** +** + +Acknowledgments + +The authors would like to acknowledge Huimin Song, a post-doctoral +researcher at the National Renewable Energy Laboratory, for her +contribution to the development of SubDyn. Amy Robertson and Fabian +Wendt provided helpful feedback on the document, and Braulio Barahona +produced some of the graphics. We also are grateful to the U.S. +Department of Energy Wind and Water Power Program for supporting the +development of this software. + +Nomenclature + +:math:`\zeta` Damping ratio (percent of critical) or diagonal damping +matrix + +:math:`\omega` Eigenfrequency + +:math:`\rho` Material density + +:math:`\Phi_{L}` *L*\ ×\ *L* matrix representing the C-B eigenmodes + +:math:`\Phi_{m}` *L*\ ×\ *m* matrix representing the retained C-B +eigenmodes + +:math:`\Phi_{R}` *L*\ ×\ *R* matrix representing the interior nodal +displacements for a static, rigid-body motion of the boundary nodes + +:math:`{\bar{\Phi}}_{R}` Matrix representing the interior nodal +displacements for a static, rigid-body motion of the boundary nodes, +after the restrained degrees of freedoms are removed + +:math:`\Omega_{L}` *L*\ ×\ *L* diagonal matrix representing the +eigenfrequencies of all C-B eigenmodes + +:math:`\Omega_{m}` *m*\ ×\ *m* diagonal matrix representing the +eigenfrequencies of the retained C-B eigenmodes + +ν Poisson’s ratio + +*A* State matrix in state-space state equation + +AF Apparent fixity + +:math:`A_{\text{sx}}` Member shear area along local *x*-axis + +:math:`A_{\text{sy}}` Member shear area along local *y*-axis + +:math:`A_{z}` Member cross-sectional area, normal to local *z*-axis + +*B* Input matrix in state-space state equation + +C-B Craig Bampton + +:math:`C` System damping matrix + +:math:`C_{1}` State matrix in state-space output equation for ElastoDyn + +:math:`C_{2}` State matrix in state-space output equation for HydroDyn + +:math:`C_{\text{LL}}` Damping matrix partition referred to the *L* +interior degrees of freedom (*L*\ ×\ *L*) + +:math:`C_{\text{LR}}` Damping matrix partition referred to the *L* and +*R* degrees of freedom (*L*\ ×\ *R*) + +:math:`C_{\text{RL}}` Damping matrix partition referred to the *R* and +*L* boundary degrees of freedom (*R*\ ×\ *L*) + +:math:`C_{\text{RR}}` Damping matrix partition referred to the *R* +boundary degrees of freedom (*R*\ ×\ *R*) + +:math:`C_{33}^{\left( \text{HD} \right)}` HydroDyn’s linear damping +matrix heave element + +:math:`\text{dt}` Time step in the integration algorithm + +:math:`dt_{\max}` Maximum time-step recommended + +*D\ i* Member inner diameter + +*D\ o* Member outer diameter + +:math:`D_{1}` Input transmission matrix in state-space output equation +for ElastoDyn + +:math:`D_{2}` Input transmission matrix in state-space output equation +for HydroDyn + +DOF Degree of freedom + +:math:`\left\lbrack D_{C} \right\rbrack` Member direction cosine 3x3 +matrix, transforming local coordinates to global coordinates + +*E* Young’s modulus + +*f* Frequency + +:math:`f_{\max}` Maximum frequency + +*F* Vector of external forces and moments + +:math:`F_{G}` Array of self-weight forces and moments + +:math:`F_{L}` Array of external (hydrodynamic) forces and moments at the +interior nodes + +:math:`{\widetilde{F}}_{L}` Interior forces and moments (*L*\ ×1) array +accounting for all interior modes +=\ :math:`\Phi_{L}^{T}\left( F_{L} + F_{\text{Lg}} \right)` + +:math:`F_{\text{Lg}}` Array of self-weight gravity forces and moments at +the interior nodes + +:math:`{\widetilde{F}}_{m}` Interior forces and moments (*L*\ ×1) array +accounting for only the retained modes +=\ :math:`\Phi_{m}^{T}\left( F_{L} + F_{\text{Lg}} \right)` + +:math:`F_{R}` Array of external (hydrodynamic) forces and moments at the +boundary nodes + +:math:`{\bar{F}}_{R}` Array of external (hydrodynamic) forces and +moments at the interface nodes + +:math:`F_{\text{Re}a\text{ct}}` Substructure base reaction forces and +moments, applied to the substructure by the restraint + +:math:`F_{\text{Rg}}` Array of self-weight forces and moments at the +boundary nodes + +:math:`{\bar{F}}_{\text{Rg}}` Array of self-weight forces and moments at +the interface nodes + +:math:`F_{\text{TP}}` TP reaction forces and moments, applied to the +substructure by the remainder of the turbine system + +:math:`{\widetilde{F}}_{\text{TP}}` TP forces and moments after C-B +reduction, = +:math:`F_{\text{TP}} + T_{I}^{T}{\bar{F}}_{\text{Rg}} + T_{I}^{T}{\bar{\Phi}}_{R}^{T}\left( F_{L} + F_{\text{Lg}} \right)` + +*F\ X* Substructure base reaction force along global *X*-axis; or + +forcing vector in state-space state equation + +*F\ Y* Substructure base reaction force along global *Y*-axis + +*F\ Y1* Forcing vector in state-space output equation for ElastoDyn + +*F\ Y2* Forcing vector in state-space output equation for HydroDyn + +*F\ Z* Substructure base reaction force along global *Z*-axis + +:math:`F_{I}^{e}` Element inertia forces + +:math:`F_{S}^{e}` Element static forces + +FEA Finite-element analysis + +FEM Finite-element method + +:math:`g` Gravity, unsigned magnitude + +*G* Shear modulus + +:math:`i` Member or element index + +:math:`{\widehat{i}}_{e}` Unit vector along the element local *x*-axis + +:math:`I` Identity matrix + +:math:`\widehat{I}` Unit vector along the global *X*-axis + +:math:`{\widehat{j}}_{e}` Unit vector along the element local *y*-axis + +:math:`J` Generic second area moment of inertia + +:math:`\widehat{J}` Unit vector along the global *Y*-axis + +:math:`J_{x}` Second area moment of inertia about the local, principal +*x*-axis + +:math:`J_{\text{xx}}` Second area moment of inertia about the local +*x*-axis + +:math:`k` Element stiffness matrix (12x12) in global coordinate system + +:math:`k_{e}` Element stiffness matrix (12x12) + +:math:`{\widehat{k}}_{e}` Unit vector along the element local *z*-axis + +:math:`k_{\text{ax}}` Shear area factor along local *x*-axis + +:math:`k_{\text{ay}}` Shear area factor along local *y*-axis + +:math:`K` System stiffness matrix + +:math:`\widehat{K}` Unit vector along the global *Z*-axis + +:math:`K_{\text{BB}}` Matrix partition after C-B system reduction = +:math:`K_{\text{RR}} + K_{\text{RL}}\Phi_{R}` + +:math:`{\bar{K}}_{\text{BB}}` :math:`K_{\text{BB}}` after removal of +constrained DOF rows and columns + +:math:`{\widetilde{K}}_{\text{BB}}` Substructure equivalent stiffness +matrix referred to the TP reference point, = +:math:`T_{I}^{T}{\bar{K}}_{\text{BB}}T_{I}` + +:math:`K_{\text{LL}}` Stiffness matrix partition referred to the *L* +interior DOFs (*L*\ ×\ *L*) + +:math:`K_{\text{LR}}` Stiffness matrix partition referred to the *L* and +*R* DOFs (*L*\ ×\ *R*) + +:math:`K_{\text{RL}}` Stiffness matrix partition referred to the *R* and +*L* boundary DOFs (*R*\ ×\ *L*) + +:math:`K_{\text{RR}}` Stiffness matrix partition referred to the R +boundary DOFs (*R*\ ×\ *R*) + +:math:`K_{\text{sx}}` Shear correction factor along local *x*-axis + +:math:`K_{\text{sy}}` Shear correction factor along local *y*-axis + +:math:`K_{33}^{\left( \text{SD} \right)}` Substructure equivalent heave +stiffness + +*L* Interior nodes’ DOFs + +LFEB Linear frame finite-element beam model + +:math:`L_{e}` Length of element + +:math:`L_{\text{exy}}` Length of element projection in the global *XY* +plane + +:math:`m_{e}` Element stiffness matrix (12x12) + +:math:`m` Element stiffness matrix (12x12) in global coordinate system; +or + +number of retained C-B modes + +:math:`M` System mass matrix + +MSL Mean sea level + +:math:`M_{\text{BB}}` Matrix partition after C-B system reduction = +:math:`M_{\text{RR}} + M_{\text{RL}}\Phi_{R} + \Phi_{R}^{T}M_{\text{LR}} + \Phi_{R}^{T}M_{\text{LL}}\Phi_{R}` + +:math:`{\bar{M}}_{\text{BB}}` :math:`M_{\text{BB}}` after removal of +constrained DOF rows and columns + +:math:`{\widetilde{M}}_{\text{BB}}` Substructure equivalent mass matrix +referred to the TP reference point = +:math:`T_{I}^{T}{\bar{M}}_{\text{BB}}T_{I}` + +:math:`M_{\text{Bm}}` Matrix partition after C-B system reduction = +:math:`M_{\text{mB}}^{T}` + +:math:`{\bar{M}}_{\text{Bm}}` :math:`M_{\text{Bm}}` after removal of +constrained DOF rows and columns + +:math:`{\widetilde{M}}_{\text{Bm}}` Matrix partition = +:math:`T_{I}^{T}{\bar{M}}_{\text{Bm}}` + +:math:`M_{\text{LL}}` Mass matrix partition referred to the *L* interior +DOFs (*L*\ ×\ *L*) + +:math:`M_{\text{LR}}` Mass matrix partition referred to the *L* and *R* +DOFs (*L*\ ×\ *R*) + +:math:`M_{\text{mB}}` Matrix partition after C-B system reduction = +:math:`\Phi_{m}^{T}M_{\text{LR}} + \Phi_{m}^{T}M_{\text{LL}}\Phi_{R}` + +:math:`{\widetilde{M}}_{\text{mB}}` Matrix partition = +:math:`{\widetilde{M}}_{\text{Bm}}^{T}` + +:math:`M_{\text{RL}}` Mass matrix partition referred to the *R* and *L* +boundary DOFs (*R*\ ×\ *L*) + +:math:`M_{\text{RR}}` Mass matrix partition referred to the *R* boundary +DOFs (*R*\ ×\ *R*) + +*M\ X* Substructure base reaction moment along global *X*-axis + +*M\ Y* Substructure base reaction moment along global *Y*-axis + +*M\ Z* Substructure base reaction moment along global *Z*-axis + +:math:`M^{\left( \text{ED} \right)}` 6x6 mass matrix from ElastoDyn + +:math:`M_{33}^{(SD)}` Substructure equivalent heave mass + +:math:`n` The n\ :sup:`th` time step + +:math:`\text{NIN}` Number of interface nodes + +:math:`N_{\text{react}}` Number of restrained nodes + +*p* State-space parameters + +:math:`q_{L}` Modal coefficients for all interior nodes’ DOF modes + +:math:`q_{L0}` Modal coefficients for all interior nodes’ DOF modes +assumed operating in static fashion + +:math:`q_{m}` Modal coefficients for the retained modes + +:math:`q_{m0}` Modal coefficients for the retained modes assumed +operating in static fashion + +*R* Boundary nodes’ DOFs + +:math:`\overrightarrow{R}` Reaction forces at the base of the +substructure + +*SSI* Soil-structure interaction + +:math:`t` time; or + +thickness + +TP Transition piece + +:math:`T_{I}` Matrix to transform interface nodes’ DOFs to TP DOFs; +:math:`\left( 6 \cdot \text{NIN} \right) \times 6` matrix + +:math:`T_{\text{react}}` Auxiliary matrix +(:math:`6x(6 \cdot N_{\text{react}})`) to link restrained nodes’ forces +and moments to the substructure base reaction vector + +*u, u\ i* State-space formulation inputs, generic i-th input + +:math:`U` Vector of nodal displacements + +:math:`U_{e}` Vector of element nodes’ displacements (DOFs) + +:math:`U_{L}` Vector of interior nodes’ displacements (DOFs) + +:math:`{\widehat{U}}_{L}` Time-varying components of the interior nodes’ +displacements (DOFs) + +:math:`U_{L0}` Static components of the interior nodes’ displacements +(DOFs) (*L*\ ×1) + +:math:`U_{L0m}` Static components of the interior nodes’ displacements +(DOFs) (*L*\ ×1), but obtained considering the first *m* C-B eigenmodes +only + +:math:`U_{R}` Vector of boundary nodes’ displacements (DOFs) + +:math:`{\bar{U}}_{R}` Vector of interface nodes’ displacements (DOFs) + +:math:`U^{e}` Element nodes’ displacements (DOFs) + +:math:`{\widehat{U}}^{e}` Time-varying components of the element nodes’ +displacements (DOFs) + +:math:`U_{L0}^{e}` Static components of the element nodes’ displacements +(DOFs) + +:math:`U_{L0m}^{e}` Static components of the element nodes’ +displacements (DOFs), but obtained considering the first *m* C-B +eigenmodes only + +:math:`U_{\text{TP}}` TP reference point displacements (DOFs) + +:math:`{\widehat{U}}_{\text{TP}}` Time-varying components of the TP +reference point displacements (DOFs) + +:math:`U_{TP0}` Static components of the TP reference point +displacements (DOFs) + +*x, x*\ :sub:`i` State-space formulation states, generic i-th state; or + +generic local *x*-coordinate + +:math:`x_{e}` Element local *x*-coordinates + +*X* Global or substructure coordinate; or + +state-space state equation(s) + +:math:`X_{E}` Member end node *X*-coordinate in global coordinate system + +:math:`X_{S}` Member start node *X*-coordinate in global coordinate +system + +:math:`X_{\text{INi}}` *X*-coordinate in global coordinate system of the +generic interface node + +*X\ SS* Global or substructure coordinate + +:math:`X_{\text{TP}}` TP reference point *X*-coordinate in global +coordinate system + +*y, y\ i* State-space formulation outputs, generic i-th output; or + +generic *y*-coordinate + +:math:`y_{e}` Element local *y*-coordinates + +*Y* Global or substructure coordinates; or + +state-space output equation(s) + +:math:`Y_{E}` Member end node *Y*-coordinate in global coordinate system + +:math:`Y_{\text{INi}}` *Y*-coordinate in global coordinate system of the +generic interface node + +:math:`Y_{S}` Member start node *Y*-coordinate in global coordinate +system + +*Y\ SS* Global or substructure coordinates + +:math:`Y_{\text{TP}}` TP reference point *Y*-coordinate in global +coordinate system + +*Y\ 1* State-space output equation for ElastoDyn + +*Y\ 2* State-space output equation for HydroDyn + +:math:`z_{e}` Element local *z*-coordinate + +*Z* Global or substructure coordinate + +:math:`Z_{E}` Member end node *Z*-coordinate in global coordinate system + +:math:`Z_{\text{INi}}` *Z*-coordinate in global coordinate system of the +generic interface node + +:math:`Z_{S}` Member start node *Z*-coordinate in global coordinate +system + +*Z\ SS* Global or substructure coordinate + +:math:`Z_{\text{TP}}` TP reference point *Z*-coordinate in global +coordinate system + +Table of Contents + +`Preface 4 <#_Toc413741142>`__ + +`Acknowledgments 5 <#_Toc413741143>`__ + +`Nomenclature 6 <#_Toc413741144>`__ + +`1 Introduction 14 <#_Toc401565516>`__ + +`2 Running SubDyn 17 <#_Ref391919518>`__ + +`2.1 Downloading the SubDyn Software 17 <#_Toc381965029>`__ + +`2.1.1 Stand-Alone SubDyn Archive 17 <#_Toc401565519>`__ + +`2.1.2 FAST Archive 17 <#_Toc401565520>`__ + +`2.2 Running SubDyn 18 <#_Toc413741150>`__ + +`2.2.1 Running the Stand-Alone SubDyn Program 18 <#_Toc413741151>`__ + +`2.2.2 Running SubDyn Coupled to FAST 18 <#_Toc382336008>`__ + +`3 Input Files 19 <#_Ref391919668>`__ + +`3.1 Units 19 <#_Toc401565524>`__ + +`3.2 SubDyn Driver Input File 19 <#_Toc381965070>`__ + +`3.3 SubDyn Primary Input File 20 <#_Ref382059081>`__ + +`3.3.1 Simulation Controls 21 <#_Toc401565527>`__ + +`3.3.2 FEA and Craig-Bampton Parameters 21 <#_Toc401565528>`__ + +`3.3.3 Structure Joints 22 <#_Toc401565529>`__ + +`3.3.4 Base Reaction Joints 22 <#_Toc401565530>`__ + +`3.3.5 Interface Joints 23 <#_Toc401565531>`__ + +`3.3.6 Members 23 <#_Ref391919995>`__ + +`3.3.7 Member Cross-Section Properties 23 <#_Toc519676721>`__ + +`3.3.8 Member Cosine Matrices COSM (i,j) 24 <#_Ref393270930>`__ + +`3.3.9 Joint Additional Concentrated Masses 24 <#_Ref393289423>`__ + +`3.3.10 Output: Summary and Outfile 24 <#_Toc401565536>`__ + +`3.3.11 Member Output List 25 <#_Ref393272400>`__ + +`3.3.12 Output Channels- SDOutList Section 25 <#_Toc401565538>`__ + +`4 Output Files 26 <#_Ref391919685>`__ + +`4.1 Echo Files 26 <#_Toc401565540>`__ + +`4.2 Summary File 26 <#_Ref391920238>`__ + +`4.3 Results File 27 <#_Toc401565542>`__ + +`5 Modeling Considerations 28 <#_Toc381965090>`__ + +`5.1 Model Discretization 28 <#_Toc401565544>`__ + +`5.2 Foundations 29 <#_Toc413741175>`__ + +`5.3 Member Overlap 29 <#_Toc413741176>`__ + +`5.4 Substructure Tower/Turbine Coupling 29 <#_Ref413052060>`__ + +`5.5 Self-Weight Calculations 31 <#_Toc401565546>`__ + +`5.6 Note On Other Load Calculations 31 <#_Toc413741179>`__ + +`5.7 Craig-Bampton Guidelines 31 <#_Ref391971454>`__ + +`5.8 Integration Time Step Guidelines 32 <#_Ref399231319>`__ + +`6 SubDyn Theory 33 <#_Ref394401650>`__ + +`6.1 Overview 33 <#_Toc401565550>`__ + +`6.2 Integration with the FAST Modularization Framework +34 <#_Toc401565551>`__ + +`6.3 Coordinate Systems 35 <#_Toc401565552>`__ + +`6.3.1 Global and Substructure Coordinate System: or ( Figure 4) +36 <#_Toc401565553>`__ + +`6.3.2 Member or Element Local Coordinate System (Figure 5) +36 <#_Toc401565554>`__ + +`6.3.3 Local to Global Transformation 37 <#_Toc401565555>`__ + +`6.4 Linear Finite-Element Beam Model 38 <#_Toc401565556>`__ + +`6.4.1 Element Formulation 39 <#_Toc401565557>`__ + +`6.4.2 Self-Weight Loads 40 <#_Toc401565558>`__ + +`6.5 Dynamic System of Equations and C-B Reduction +42 <#_Toc401565559>`__ + +`6.5.1 State-Space Formulation 46 <#_Ref394398934>`__ + +`6.5.2 Member Force Calculation 48 <#_Toc401565561>`__ + +`6.5.3 Reaction Calculation 48 <#_Toc401565562>`__ + +`6.5.4 Time Integration 49 <#_Ref394398970>`__ + +`6.5.5 Static-Improvement Method 49 <#_Toc401565564>`__ + +`7 Known Limitations and Future Work 53 <#_Toc401565565>`__ + +`8 References 54 <#_Ref391919755>`__ + +`Appendix A. OC4 Jacket Input File (CertTest Test04) +55 <#_Toc401565567>`__ + +`Appendix B. OC4 Jacket Driver File 60 <#_Toc401565568>`__ + +`Appendix C. List of Output Channels 61 <#_Toc401565569>`__ + +`Appendix D. Compiling Stand-Alone SubDyn 63 <#_Toc401565570>`__ + +`Appendix E. Major Changes in SubDyn 64 <#_Toc401565571>`__ + +List of Figures + +`Figure 1. SubDyn, HydroDyn, and FAST 8 coupled interaction +15 <#_Ref408208410>`__ + +`Figure 2. WinZip Self-Extractor main window 17 <#_Toc413741206>`__ + +`Figure 3. SubDyn layout within the modularization framework +34 <#_Ref393719536>`__ + +`Figure 4. Global (coincident with the substructure) coordinate system. +Also shown are the DOFs associated with the TP reference point. +35 <#_Ref407623061>`__ + +`Figure 5. The element coordinate system. The sketched member contains +four elements, and the second element is called out with nodes S and E. +37 <#_Ref408218733>`__ + +List of Tables + +`Table 1. TP Reference Point Inputs Time-Series Data File Contents +20 <#_Toc401063869>`__ + +`Table C-1. List of Output Channels. 61 <#_Toc417640980>`__ + + diff --git a/docs/source/user/subdyn/output_files.rst b/docs/source/user/subdyn/output_files.rst new file mode 100644 index 000000000..f9ea6cb36 --- /dev/null +++ b/docs/source/user/subdyn/output_files.rst @@ -0,0 +1,126 @@ +.. _output-files: + +Output Files +============ + +SubDyn produces three types of output files: an echo file, a summary +file, and a time-series results file. The following sections detail the +purpose and contents of these files. + +Echo File +--------- + +If the user sets the **Echo** flag to TRUE in the SubDyn driver file +or the primary SubDyn input file, the contents of those files will be +echoed to a file with the naming conventions, **OutRootName.dvr.ech** +for the driver input file and **OutRootName.SD.ech** for the primary +SubDyn input file. **OutRootName** is either specified in the SUBDYN +section of the driver input file, or in the FAST input file. The echo +files are helpful for debugging the input files. The contents of an echo +file will be truncated if SubDyn encounters an error while parsing an +input file. The error usually corresponds to the line after the last +successfully echoed line. + +.. _sum-file: + +Summary File +------------ + +SubDyn generates a summary file with the naming convention, +**OutRootName.SD.sum** if the **SDSum** parameter is set to TRUE. +This file summarizes key information about the substructure model, +including: + +- Undisplaced node geometry: a list of all of the (**NNodes**) nodes + and the *X*,\ *Y*,\ *Z* coordinates in the global SS coordinate + system. Note that **NNodes** may be greater or equal to + **NJoints**, depending on **NDiv** (primary input file + parameters). + +- Element connectivity and properties at end nodes: a list of all + (**NElems**) elements, the start and end nodes (**Node\_I**, + **Node\_J**) and the ID of the property set (**Prop\_I**, + **Prop\_J**) at the start and end nodes. **NElems** may be + greater or equal to **NMembers**, depending on **NDiv** (primary + input file parameters). + +- Property sets. If tapered members are used, additional property sets + may be included beyond those specified in the main input file, based + on interpolated diameter and thickness values. Headers and their + meanings are identical to those described in Section . + +- Reaction DOFs and interface DOFs and their associated fixity; the + actual indices of the DOFs (**DOF\_ID**) associated with reaction + and interface nodes are listed together with the (1/0) flag to + distinguish the fixity level. + +- Concentrated mass schedule. This is an echo of the equivalent section + in the primary input file. Refer to Section . + +- Member schedule including connectivity to joints, nodes, and their + masses. A table lists all of the members by identifier + (**MemberID**), with their start and end nodes (**Joint1\_ID**, + **Joint2\_ID**), associated mass (**Mass**), and list of node + identifiers along the length of the members. + +- Direction cosine matrices for the members. Each row (columns 2-10) + corresponds to the direction cosine matrix entries (**DC(1,1)** + through **DC(3,3)**) for the member whose identifier is listed in + the first column. The direction cosine matrices specify the + transformation from the global reference to the local coordinate + system for each member. + +- Sorted eigenfrequencies [in Hertz (Hz)] for the full substructural + system (neglecting a possible coupling to ElastoDyn through FAST), + assuming the TP reference point is a free end. There are a total of + **NDOFs** eigenfrequencies and eigenvectors. + +- Sorted eigenfrequencies (in Hz) for the C-B reduced system, assuming + the TP reference point is a fixed end. There are a total of + **Nmodes** C-B reduced eigenfrequencies and eigenvectors. + +- Full substructural system eigenvectors. Each column represents an + eigenvector associated with the corresponding eigenfrequency + identified previously in the file. + +- C-B reduced system eigenvectors (**PhiM** matrix). Each column + represents an eigenvector associated with the corresponding + eigenfrequency identified previously in the file. + +- **PhiR** matrix or displacements of the internal nodes caused by + unit rigid body motions of the interface DOFs (see Section ). Each + column of the matrix represents the internal DOF displacements for a + given unit rigid-body motion along an interface DOF for each base and + interface joint. + +- Substructure equivalent stiffness and mass matrices referred to the + TP reference point (**KBBt** and **MBBt**), based on a Guyan + reduction. These are useful to calculate effects of substructure + flexibility while calculating tower eigenmodes for ElastoDyn. + +- Rigid-body-equivalent mass matrix relative to global origin + (**MRB**); a 6x6 mass matrix. + +- Substructure total (dry) mass. + +- Substructure center of mass coordinates in the global coordinate + system. + +The various sections of the summary file and variables are +self-explanatory and easily identifiable in the file. + +Results File +------------ + +The SubDyn time-series results are written to a text-based file with the +naming convention **OutRootName.SD.out** when **OutSwtch** is set to +either one or three. If SubDyn is coupled to FAST and **OutSwtch** is +set to two or three, then FAST will generate a master results file that +includes the SubDyn results. The results in **OutRootName.SD.out** are +in table format, where each column is a data channel (the first column +always being the simulation time), and each row corresponds to a +simulation time step. The data channels are specified in the SDOutList +section of the input file. The column format of the SubDyn-generated +file is specified using the **OutFmt** and **OutSFmt** parameters of +the input file. + diff --git a/docs/source/user/subdyn/references.bib b/docs/source/user/subdyn/references.bib new file mode 100644 index 000000000..5f4faa028 --- /dev/null +++ b/docs/source/user/subdyn/references.bib @@ -0,0 +1,119 @@ +%% This BibTeX bibliography file was created using BibDesk. +%% http://bibdesk.sourceforge.net/ + + +%% Created for Clifton, Andrew at 2014-07-30 18:45:30 -0600 + + +%% Saved with string encoding Unicode (UTF-8) + +@book{chapra2010, + author = "Chapra, S.C. and Canale, R.P. ", + title = "Numerical Methods for Engineers", + year = "2010", + publisher = "McGraw-Hill Science/Engineering/Mat" +} + +@inproceedings{song2013, + author = "Song, H. and Damiani, R. and Robertson, A. and Jonkman, J.", + title = "(2013). New Structural-Dynamics Module for Offshore Multimember Substructures within the Wind Turbine Computer-Aided Engineering Tool {FAST}", + month = "June 30 -- July 5", + year = "2013", + booktitle = "Proceedings of the 23rd International Ocean, Offshore and Polar Engineering Conference - ISOPE 2013", + address = "Anchorage, Alaska", + note = "https://www.nrel.gov/docs/fy15osti/63165.pdf" +} + +@inproceedings{jonkman2013, + author = "Jonkman, J.M.", + title = "The New Modularization Framework for the {FAST} Wind Turbine {CAE} Tool.", + month = "January 7 -- 10", + year = "2013", + booktitle = "Proceedings of the 51st AIAA Aerospace Sciences Meeting and 31st ASME Wind Energy Symposium", + address = "Grapevine, Texas" +} + +@inproceedings{Hurty1964, + author = "Hurty, W.C.", + title = "On the Dynamic Analysis of Structural Systems Using Component Modes", + month = "June 29--July 2", + year = "1964", + booktitle = "Proceedings of the 51st AIAA Annual Meeting", + address = "Washington, DC", + note = "AIAA Paper No. 64-487" +} + +@article{craig1968, + author = "Craig, R. and Bampton, M.", + title = "Coupling of Substructures for Dynamic Analyses", + year = "1968", + journal = "AIAA Journal", + volume = "6", + pages = "1313 -- 1319" +} + +@inproceedings{damiani2013omae, + author = "Damiani, R. and Song, H. and Robertson, A. and Jonkman, J.", + title = "Assessing the Importance of Nonlinear Structural Characteristics in the Development of a Jacket Model for the Wind Turbine {CAE} Tool {FAST}", + month = "Jne 9--14", + year = "2013", + booktitle = "Proceedings of the 32nd International Conference on Ocean, Offshore and Arctic Engineering (OMAE2013)", + address = "Nantes, France" +} + + +@inproceedings{sprague2014, + author = "Sprague, M.A. and Jonkman, J.M. and Jonkman, B.J.", + title = "{FAST} Modular Wind Turbine {CAE} Tool: Nonmatching Spatial and Temporal Meshes", + month = "January", + year = "2014", + booktitle = "Proceedings of the 32nd ASME Wind Energy Symposium", + address = "National Harbor, Maryland" +} + + +@techreport{panzer2009, + Author = "Panzer, H. and Hubele, J. and Eid, R. and Lohmann, B.", + Volume = "TRAC-4", + Institution = "Technische Universitat Munchen", + Title = "Generating a Parametric Finite Element Model of a 3D Cantilever Timoshenko Beam Using Matlab", + Year = "2009", + Note = "Technical Reports on Automatic Control" +} + +@techreport{iso19902, + Author = "{ISO}", + Title = "{19902:2007} - Petroleum and natural gas industries -- Fixed steel offshore structures", + Institution = "{ISO}", + Address = "Geneva, Switzerland", + Revision = "1st edition", + Year = "2007" +} + +@TECHREPORT{api2014, + title={Planning, Designing and Constructing Fixed Offshore Platforms - Working Stress Design}, + author={{API}}, + institution={{A}merican {P}etroleum {I}nstitute}, + number={{API} Recommended Practice {2A-WSD}, 22nd Edition}, + year=2014 +} + +@article{steinboeck2013, + author = "Steinboeck, A. and Kugi, A. and Mang, H", + title = "Energy-consistent shear coefficients for beams with circular cross sections and radially in homogeneous materials", + year = "2013", + journal = "International Journal of Solids and Structures", + volume = "50", + number = "11--12", + pages = "1859--1868" +} + +@TECHREPORT{subdyn:manual, + title={SubDyn User's Guide and Theory Manual}, + author={R. Damiani and J. Jonkman and G. Hayman}, + institution={National Renewable Energy Laboratory}, + number={NREL/TP-5000-63062}, + year=2015 +} + + diff --git a/docs/source/user/subdyn/running_sd.rst b/docs/source/user/subdyn/running_sd.rst new file mode 100644 index 000000000..d06081250 --- /dev/null +++ b/docs/source/user/subdyn/running_sd.rst @@ -0,0 +1,109 @@ +.. _running-subdyn: + +Running SubDyn +=============== + +This section discusses how to obtain and execute SubDyn from a personal +computer. Both the stand-alone version and the FAST-coupled version of +the software are considered. + +Downloading the SubDyn Software +-------------------------------- + +There are two forms of the SubDyn software to choose from: stand alone +and coupled to the FAST simulator. Although the user may not necessarily +need both forms, he/she would likely need to be familiar with and run +the stand-alone model if building a model of the substructure from +scratch. The stand-alone version is also helpful for model +troubleshooting and may benefit users who are interested in conducting +aero-hydro-servo-elastic simulations of an offshore wind turbine. For +this reason, SubDyn can be obtained from two different repositories: one +for the stand-alone SubDyn and one for the coupled solution through +FAST. + +Stand-Alone SubDyn Archive +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Users can refer to :numref:`installation` download the stand-alone SubDyn archive from our Web server at +`*https://nwtc.nrel.gov/SubDyn* `__. The +file has a name similar to *SD\_v1.03.00a-rrd.exe*, but may have a +different version number. The user can then download the self-extracting +archive (.exe) to expand the archive into a folder he/she specifies. + +.. _self-extractor: + +.. figure:: figs/self-extractor.png + :width: 40% + + WinZip Self-Extractor main window --TO REPLACE WITH CURRENT +ARCHIVE METHODS ETC. + +The archive contains the **bin**, **CertTest**, **Compiling**, +**Documentation**, and **Source** folders. The **bin** folder +includes the main executable file, *SubDyn\_win32.exe*, which is used to +execute the stand-alone SubDyn program. The **CertTest** folder +contains a collection of sample SubDyn input files and driver input +files that can be used as templates for the user’s own models. If the +user runs the *CertTest.bat* DOS script, he/she can compare the results +to the ones stored in the **NREL\_Results** subfolder. This manual may +be found in the **Documentation** folder. The **Compiling** folder +contains files for compiling the stand-alone *SubDyn\_win32.exe* file +with either Visual Studio or gFortran. The Fortran source code is +located in the **Source** folder. + +FAST Archive +~~~~~~~~~~~~ + +Download the FAST archive, which includes a coupling to SubDyn, from our +Web server at https://nwtc.nrel.gov/FAST8. The file has a name similar +to *FAST\_v8.08.00.exe*, but may have a different version number. Run +the downloaded self-extracting archive (*.exe*) to expand the archive +into a user-specified folder. The FAST executable file is located in the +archive’s **bin** folder. Example models using the NREL 5-MW reference +turbine and various substructures are located in the **CertTest** +folder. These include Test19: OC3-Monopile, Test20: OC3-Tripod, Test21: +OC4-jacket. + +Running SubDyn +--------------- + +Running the Stand-Alone SubDyn Program +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The stand-alone SubDyn program, *SubDyn\_win32.exe*, simulates +substructure dynamic responses of the user’s input model, without +coupling to FAST. Unlike the coupled version, the stand-alone software +requires the use of a driver file in addition to the primary SubDyn +input file. This driver file specifies inputs normally provided to +SubDyn by FAST, including motions of the TP reference point. Both the +SubDyn summary file and the results output file are available when using +the stand-alone SubDyn (see Section 4 for more information regarding the +SubDyn output files). + +Run the standalone SubDyn software from a DOS command prompt by typing, +for example: + +.. code-block:: bash + + >SubDyn_win32.exe MyDriverFile.dvr + +where, *MyDriverFile.dvr* is the name of the SubDyn driver file, as +described in Section :numref:`main-input-file`. The SubDyn primary input file is described in +Section :numref:`driver-input-file`. + + +Running SubDyn Coupled to FAST +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Run the coupled FAST software from a DOS command prompt by typing, for +example: + +.. code-block:: bash + + >FAST_Win32.exe Test21.fst + +where, *Test21.fst* is the name of the primary FAST input file. This +input file has a feature switch to enable or disable the SubDyn +capabilities within FAST, and a corresponding reference to the SubDyn +input file. See the documentation supplied with FAST for further +information. diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst new file mode 100644 index 000000000..644f6d416 --- /dev/null +++ b/docs/source/user/subdyn/theory.rst @@ -0,0 +1,1283 @@ +.. _subdyn-theory: + +SubDyn Theory +============== + +This section focuses on the theory behind the BeamDyn module. The +theoretical foundation, numerical tools, and some special handling in +the implementation will be introduced. References will be provided in +each section detailing the theories and numerical tools. + +In this chapter, matrix notation is used to denote vectorial or +vectorial-like quantities. For example, an underline denotes a vector +:math:`\underline{u}`, an over bar denotes unit vector :math:`\bar{n}`, +and a double underline denotes a tensor +:math:`\underline{\underline{\Delta}}`. Note that sometimes the +underlines only denote the dimension of the corresponding matrix. + +Overview +------------------ + +This section focuses on the theory behind the SubDyn module. + +SubDyn relies on two main engineering approaches: (1) a linear frame +finite-element beam model (LFEB), and (2) a dynamics system reduction +via the Craig-Bampton (C-B) method together with a static-improvement +method (SIM), greatly reducing the number of modes needed to obtain an +accurate solution. + +There are many nonlinearities present in offshore wind substructure +models, including material nonlinearity, axial shortening caused by +bending, large displacements, and so on. The material nonlinearity is +not considered here because most offshore multimember support structures +are designed to use steel and the maximum stress is intended to be below +the yield strength of the material. :cite:`damiani2013omae` demonstrate +that a linear finite-element method is suitable when analyzing wind +turbine substructures. In this work, several wind turbine configurations +that varied in base geometry, load paths, sizes, supported towers, and +turbine masses were analyzed under extreme loads using nonlinear and +linear models. The results revealed that the nonlinear behavior was +mainly caused by the mono-tower response and had little effect on the +multimember support structures. Therefore, an LFEB model for the +substructure is considered appropriate for wind turbine substructures. +The LFEB can accommodate different element types, including +Euler-Bernoulli and Timoshenko beam elements of either constant or +longitudinally tapered cross sections (Timoshenko beam elements account +for shear deformation and are better suited to represent low aspect +ratio beams that may be used within frames and to transfer the loads +within the frame). + +The large number of DOFs (~ :math:`{10^3}`) associated with a standard +finite-element analysis of a typical multimember structure would hamper +computational efficiency during wind turbine system dynamic simulations. +As a result, the C-B system reduction was implemented to speed up +processing time while retaining a high level of fidelity in the overall +system response. The C-B reduction is used to recharacterize the +substructure finite-element model into a reduced DOF model that +maintains the fundamental low-frequency response modes of the structure. +In the SubDyn initialization step, the large substructure physical DOFs +(displacements) are reduced to a small number of modal DOFs and +interface (boundary) DOFs, and during each time step, only the equations +of motion of these DOFs need to be solved. SubDyn only solves the +equations of motion for the modal DOFs, the motion of the interface +(boundary) DOFs are either prescribed when running SubDyn in stand-alone +mode or solved through equations of motion in ElastoDyn when SubDyn is +coupled to FAST. + +Retaining just a few DOFs may, however, lead to the exclusion of axial +modes (normally of very high frequencies), which are important to +capture static load effects, such as those caused by gravity and +buoyancy. The so-called SIM was implemented to mitigate this problem. +SIM computes two static solutions at each time step: one based on the +full system stiffness matrix and one based on the C-B reduced stiffness +matrix. At each time step the time-varying, C-B based, dynamic solution +is superimposed on the difference between the two static solutions, +which amounts to quasi-statically accounting for the contribution of +those modes not directly included within the dynamic solution. + +In SubDyn, the substructure is considered to be clamped, or connected +via linear spring-like elements, at the bottom nodes (normally at the +seabed) and rigidly connected to the TP at the substructure top nodes +(interface nodes). The user can provide 6x6, equivalent stiffness and +mass matrices for each of the bottom nodes to account for soil-pile +interaction. As described in other sections of this document, the input +file defines the substructure geometry, material properties, and +constraints. Users can define: element types; full finite-element mode +or C-B reduction; the number of modes to be retained in the C-B +reduction; modal damping coefficients; whether to take advantage of SIM; +and the number of elements for each member. + +The following sections discuss the integration of SubDyn within the FAST +framework, the main coordinate systems used in the module, and the +theory pertaining to the LFEB, the C-B reduction, and SIM. The +state-space formulations to be used in the time-domain simulation are +also presented. The last section discusses the calculation of the base +reaction calculation. For further details, see also :cite:`song2013`. + +Integration with the FAST Modularization Framework +-------------------------------------------------- + +Based on a new modularization framework :cite:`jonkman2013`, FAST joins an +aerodynamics module, a hydrodynamics module, a control and electrical +system (servo) module, and structural-dynamics (elastic) modules to +enable coupled nonlinear aero-hydro-servo-elastic analysis of land-based +and offshore wind turbines in the time domain. :numref:`flow-chart2` shows the basic +layout of the SubDyn module within the FAST modularization framework. + +.. _flow-chart2: + +.. figure:: figs/flowchart2.png + :width: 70% + + SubDyn layout within the modularization framework + + +In the existing loosely coupled time-integration scheme, the glue-code +transfers data at each time step. Such data includes hydrodynamic loads, +substructure response, loads transmitted to the TP, and TP response +among SubDyn, HydroDyn, and ElastoDyn. At the interface nodes, the TP +displacement, rotation, velocity, and acceleration are inputs to SubDyn +from ElastoDyn, and the reaction forces at the TP are outputs of SubDyn +for input to ElastoDyn. SubDyn also outputs the substructure +displacements, velocities, and accelerations for input to HydroDyn to +calculate the hydrodynamic loads that become inputs for SubDyn. In +addition, SubDyn can calculate the member forces, as requested by the +user. Within this scheme, SubDyn tracks its states and integrates its +equations through its own solver. + +In a tightly coupled time-integration scheme (yet to be implemented), +SubDyn sets up its own equations, but its states and those of other +modules are tracked and integrated by a solver within the glue-code that +is common to all of the modules. + +SubDyn is implemented in a state-space formulation that forms the +equation of motion of the substructure system with physical DOFs at the +boundaries and modal DOFs representing all interior motions. At each +time step, loads and motions are exchanged between modules through the +driver code; the modal responses are calculated inside SubDyn’s +state-space model; and the next time-step responses are calculated by +the SubDyn integrator for loose coupling and the global system +integrator for tight coupling. + +Coordinate Systems +------------------ + +.. _global-cs: + +.. figure:: figs/global-cs.png + :width: 40% + + Global (coincident with the substructure) coordinate system. + Also shown are the DOFs associated with the TP reference point. + +Global and Substructure Coordinate System: (*X*, *Y*, *Z*) or (:math:`{X_{SS}, Y_{SS}, Z_{SS}}`) (:numref:`global-cs`) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- The global axes are represented by the unit vectors :math:`{\hat{I}, \hat{J}}`, and :math:`{\hat{K}}`. + +- The origin is set at the intersection between the undeflected tower + centerline and the horizontal plane identified by the mean sea level + (MSL) for offshore systems or ground level for land-based systems. + +- The positive *Z* (:math:`{Z_{SS}}`) axis is vertical and pointing upward, opposite + gravity. + +- The positive *X* (:math:`{X_{SS}}`) axis is along the nominal (zero-degree) + wind and wave propagation direction. + +- The *Y* (:math:`{Y_{SS}}`) axis is transverse and can be found assuming a + right-handed Cartesian coordinate system (directed to the left when + looking in the nominal downwind direction). + +Member or Element Local Coordinate System (:math:`{x_e, y_e, z_e}`) (:numref:`element-cs`) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Axes are represented by the unit vectors :math:`{\hat{i}_e, \hat{j}_e, \hat{k}_e}`. + +- The origin is set at the shear center of the cross section at the + start node (S,MJointID1). + +- The local axis is along the elastic axis of the member, directed from + the start node (S) to the end node (E,MJointID2). Nodes are ordered + along the member main axis directed from start joint to end joint + (per user’s input definition). + +- The local axis is parallel to the global :math:`\text{XY}` plane, and + directed such that a positive, less than or equal to 180º rotation + about it, would bring the local axis parallel to the global *Z* axis. + +- The local axis can be found assuming a right-handed Cartesian + coordinate system. + +.. _element-cs: + +.. figure:: figs/element-cs.png + :width: 100% + + The element coordinate system. The sketched member contains four elements, and the second element is called out with nodes S and E. + + + +Local to Global Transformation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The transformation from local to global coordinate system can be +expressed by the following equation: + + .. math:: :label: loc2glb + + \begin{bmatrix} \Delta X \\ \Delta Y \\ \Delta Z \end{bmatrix} = [ \mathbf{D_c} ] \begin{bmatrix} \Delta x_e \\ \Delta y_e \\ \Delta z_e \end{bmatrix} + +where :math:`\begin{bmatrix} \Delta x_e \\ \Delta y_e \\ \Delta z_e \end{bmatrix}` is a generic vector in the local coordinate system, and +:math:`\begin{bmatrix} \Delta X \\ \Delta Y \\ \Delta Z \end{bmatrix}` the same +vector but in the global coordinate system; and :math:`[ \mathbf{D_c} ]` is the direction cosine +matrix of the member axes and can be obtained as follows: + + .. math:: :label: Dc + + [ \mathbf{D_c} ] = \begin{bmatrix} + \frac{Y_E-Y_S}{L_{exy}} & \frac{ \left ( X_E-X_S \right) \left ( Z_E-Z_S \right)}{L_{exy} L_{e}} & \frac{X_E-X_S}{L_{e}} \\ + \frac{-X_E+X_S}{L_{exy}} & \frac{ \left ( Y_E-Y_S \right) \left ( Z_E-Z_S \right)}{L_{exy} L_{e}} & \frac{Y_E-Y_S}{L_{e}} \\ + 0 & \frac{ -L_{exy} }{L_{e}} & \frac{Z_E-Z_S}{L_{e}} + \end{bmatrix} + +Where :math:`{\left ( X_s,Y_s,Z_s \right )}` and :math:`{\left ( X_E,Y_E,Z_E \right )}` +are the start and end joints of the member (or nodes of the element of interest) in global coordinate system ; +:math:`{L_{exy}= \sqrt{ \left ( X_E-X_S \right )^2 + \left ( Y_E-Y_S \right )^2}}` and :math:`{L_{e}= \sqrt{ \left ( X_E-X_S \right )^2 + \left ( Y_E-Y_S \right )^2 + \left ( Z_E-Z_S \right )^2}}`. + +If :math:`{X_E = X_S}` and :math:`{Z_E = Z_S}`, the :math:`{[ \mathbf{D_c} ]}` matrix can be found as follows: + +if :math:`{Z_E < Z_S}` then + + .. math:: :label: Dc_spec1 + + [ \mathbf{D_c} ] = \begin{bmatrix} + 1 & 0 & 0 \\ + 0 & 1 & 0 \\ + 0 & 0 & 1 + \end{bmatrix} + +else + + .. math:: :label: Dc_spec2 + + [ \mathbf{D_c} ] = \begin{bmatrix} + 1 & 0 & 0 \\ + 0 & -1 & 0 \\ + 0 & 0 & -1 + \end{bmatrix} + +In the current SubDyn release, the transpose (global to local) of these +direction cosine matrices for each member is returned in the summary +file. Given the circular shape of the member cross sections, the +direction cosine matrices have little importance on the member load +verification. To verify joints following the standards (e.g., :cite:`iso19902` :cite:`api2014` +), however, the bending moments need to be decomposed into +in-plane and out-of-plane components, where the plane is that defined by +either a pair of braces (for an X-joint), or by the pair brace(s) plus +leg (for a K-joint). It is therefore important to have the direction +cosines of the interested members readily available to properly +manipulate and transform the local shear forces and bending moments. + +When member cross sections other than circular are allowed in future +releases, the user will need to input cosine matrices to indicate the +final orientation of the member principal axes with respect to the +global reference frame. + +Linear Finite-Element Beam Model +-------------------------------- + +In SubDyn, the LFEB can accommodate different two-node beam element +types, including Euler-Bernoulli and Timoshenko beam elements, either of +constant or tapered cross sections. The tapered element formulation has +been derived, but has not been implemented in the current SubDyn +release. + +The uniform and tapered Euler-Bernoulli beam elements are +displacement-based and use third-order interpolation functions that +guarantee the displacement and rotation continuity between elements. The +uniform Timoshenko beam element is derived by introducing the shear +deformation into the uniform Euler-Bernoulli element, so the +displacements are represented by third-order interpolation functions as +well. + +Element Formulation +~~~~~~~~~~~~~~~~~~~ + +Following the classic Timoshenko beam theory, the generic two-node +element stiffness and consistent mass matrices can be written as follows +(see, for instance, :cite:`panzer2009`): + + +.. raw:: latex + + \renewcommand*{\arraystretch}{1.0} + + +.. math:: :label: ke + + \setcounter{MaxMatrixCols}{20} + + {\scriptstyle + [k_e]= + \begin{bmatrix} + \frac{12 E J_y} {L_e^3 \left( 1+ K_{sy} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sy} \right)} & 0 & -\frac{12 E J_y}{L_e^3 \left( 1+ K_{sy} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sy} \right)} & 0 \\ + & \frac{12 E J_x}{L_e^3 \left( 1+ K_{sx} \right)} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & -\frac{12 E J_x}{L_e^3 \left ( 1+ K_{sx} \right )} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & \frac{E A_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{E A_z}{L_e} & 0 & 0 & 0 \\ + & & & \frac{\left(4 + K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & \frac{\left( 2-K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & \frac{\left(4 + K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & \frac{\left( 2-K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & \frac{G J_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{G J_z}{L_e} \\ + & & & & & & k_{11} & 0 & 0 & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & & & k_{22} & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & & & & & k_{33} & 0 & 0 & 0 \\ + & & & & & & & & & k_{44} & 0 & 0 \\ + & & & & & & & & & & k_{55} & 0 \\ + & & & & & & & & & & & k_{66} \\ + \end{bmatrix} + } + + +.. math:: :label: me + + [m_e]= \rho \\ + \left[\begin{array}{*{12}c} + \frac{13 A_z L_e}{35}+\frac{6 J_y}{5 L_e} & 0 & 0 & 0 & \frac{11 A_z L_e^2}{210}+\frac{J_y}{5 L_e} & 0 & \frac{9 A_z L_e}{70}-\frac{6 J_y}{5 L_e} & 0 & 0 & 0 & -\frac{13 A_z L_e^2}{420}+\frac{J_y}{10} & 0 \\ + & \frac{12 E J_x}{L_e^3 \left ( 1+ K_{sx} \right )} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & -\frac{12 E J_x}{L_e^3 \left ( 1+ K_{sx} \right )} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & \frac{E A_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{E A_z}{L_e} & 0 & 0 & 0 \\ + & & & \frac{\left(4 + K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & \frac{\left( 2-K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & \frac{\left(4 + K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & \frac{\left( 2-K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & \frac{G J_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{G J_z}{L_e} \\ + & & & & & & \frac{12 E J_y}{L_e^3 \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & & & \frac{12 E J_x}{L_e^3 \left ( 1+ K_{sx} \right )} & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & & & & & \frac{E A_z}{L_e} & 0 & 0 & 0 \\ + & & & & & & & & & \frac{\left(4 + K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & & & & & & & \frac{\left(4 + K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & & & & & & & \frac{G J_z}{L_e}\\ + \end{array}\right] + +where :math:`A_z` is the element cross-section area, :math:`J_x, J_y, J_z` are the area second moments of +inertia with respect to principal axes of the cross section; :math:`L_e` is the +length of the undisplaced element from start-node to end-node; :math:`\rho, E, \textrm{and}\quad G` are material density, Young’s, and Shear moduli, respectively; +:math:`K_{sx}, K_{sy}` are shear correction factors as shown below (they are set to zero if +the E-B formulation is chosen): + +.. math:: :label: Ksxy + + K_{sx}= \frac{12 E J_y}{G A_{sx} L_e^2} + + K_{sy}= \frac{12 E J_x}{G A_{sy} L_e^2} + +where the shear areas along the local *x* and *y* (principal) axes are +defined as: + +.. math:: :label: Asxy + + A_{sx}= k_{ax} A_z + + A_{sy}= k_{ay} A_z + + + +and + +.. math:: :label: kaxy + + k_{ax} = k_{ay} = \dfrac{ 6 (1 + \mu)^2 \left(1 + \left( \frac{D_i}{D_o} \right)^2 \right)^2 } { \left(1+ \left( \frac{D_i}{D_o} \right)^2 \right)^2 (7 + 14 \mu + 8 \mu^2) + 4 \left( \frac{D_i}{D_o} \right)^2 (5+10 \mu +4 \mu^2)} + + + +Eq. :eq:`kaxy` is from :cite:`steinboeck2013` for hollow circular cross sections, +with :math:`\mu` denoting Poisson’s ratio. + +Before assembling the global system stiffness (*K*) and mass (*M*) +matrices, the individual :math:`{[k_e]}` and math:`{[m_e]}` are modified to the global coordinate +system via :math:`{[ \mathbf{D_c} ]}` as shown in the following equations: + +.. math:: :label: ke + + [k] = \begin{bmatrix} + [\mathbf{D_c}] & 0 & 0 & 0 \\ + & [\mathbf{D_c}] & 0 & 0 \\ + & & [\mathbf{D_c}] & 0 \\ + & & & [\mathbf{D_c}] + \end{bmatrix} [k_e] \begin{bmatrix} + [\mathbf{D_c}] & 0 & 0 & 0 \\ + & [\mathbf{D_c}] & 0 & 0 \\ + & & [\mathbf{D_c}] & 0 \\ + & & & [\mathbf{D_c}] + \end{bmatrix}^T + +.. math:: :label: me + + [m] = \begin{bmatrix} + [\mathbf{D_c}] & 0 & 0 & 0 \\ + & [\mathbf{D_c}] & 0 & 0 \\ + & & [\mathbf{D_c}] & 0 \\ + & & & [\mathbf{D_c}] + \end{bmatrix} [m_e] \begin{bmatrix} + [\mathbf{D_c}] & 0 & 0 & 0 \\ + & [\mathbf{D_c}] & 0 & 0 \\ + & & [\mathbf{D_c}] & 0 \\ + & & & [\mathbf{D_c}] + \end{bmatrix}^T + +where *m* and *k* are element matrices in the global coordinate system. + +Self-Weight Loads +~~~~~~~~~~~~~~~~~ +The loads caused by self-weight are precomputed during initialization +based on the undisplaced configuration. It is therefore assumed that the +displacements will be small and that P-delta effects are small for the +substructure. For a nontapered beam element, the lumped loads caused by +gravity to be applied at the end nodes are as follows (in the global +coordinate system): + +.. math:: :label: FG + + \left\{ F_G \right\} = \rho A_z g + \begin{bmatrix} 0 \\ + 0 \\ + -\frac{L_e}{2} \\ + -\frac{L_e^2}{12} D_{c2,3} \\ + \frac{L_e^2}{12} D_{c1,3} \\ + 0\\ + 0\\ + 0\\ + -\frac{L_e}{2}\\ + \frac{L_e^2}{12} D_{c2,3}\\ + -\frac{L_e^2}{12} D_{c1,3}\\ + 0 + \end{bmatrix} + +Note also that if lumped masses exist (selected by the user at +prescribed joints), their contribution will be included as concentrated +forces along global *Z* at the relevant nodes. + +.. _CBreduction: + +Dynamic System of Equations and C-B Reduction +--------------------------------------------- + +The main equations of motion of SubDyn are written as follows: + +.. math:: :label: main + + [M] \left\{ \ddot{U} \right\} +[C] \{ \dot{U} \} + [K] \{ U \} = \{ F \} + + +where :math:`{[M]}` and :math:`{[K]}` are the global mass and stiffness matrices of the substructure +beam frame, assembled from the element mass and stiffness matrices. +Additionally, :math:`{[M]}` and :math:`{[K]}` contain the contribution from any specified :math:`{[M_{SSI}]}` and :math:`{[K_{SSI}]}` that +are directly added to the proper partially restrained node DOF rows and +column indexed elements. + +:math:`{{U}}` and :math:`{{F}}` are the displacements and external forces along all of the DOFs of +the assembled system. The damping matrix :math:`{[C]}` is not assembled from the +element contributions, because those are normally unknown, but treated +from a system point of view as shown in the following paragraphs. A +derivative with respect to time is represented by a dot, so that :math:`{\dot{U}}` and :math:`{\ddot{U}}` are +the first- and second-time derivatives of :math:`{{U}}` , respectively. + +The number of DOFs associated with Eq. :eq:`main` can easily grow to the thousands +for typical beam frame substructures. That factor, combined with the +need for time-domain simulations of turbine dynamics, may seriously slow +down the computational efficiency of aeroelastic codes such as FAST +(note that a typical wind turbine system model in ElastoDyn has about 20 +DOFs). For this reason, a C-B methodology was used to recharacterize the +substructure finite-element model into a reduced DOF model that +maintains the fundamental low-frequency response modes of the structure. +With the C-B method, the DOFs of the substructure can be reduced to +about 10 (user defined, see also Section :ref:`_CBguide`). This system reduction method +was first introduced by :cite:`hurty1964` and later expanded by :cite:`craig1968`. + +In SubDyn’s C-B reduction, the substructure nodes are separated into two +groups: 1) the boundary nodes (identified with a subscript “\ *R*\ †in +what follows) that include the nodes fully restrained at the base of the +structure and the interface nodes; and 2) the interior nodes (or +leftover nodes, identified with a subscript “\ *L*\ â€). The interface +nodes are assumed rigidly connected among one another and to the TP +reference point. Note that the DOFs of partially restrained or “free†+nodes at the base of the structure are included in the “L†subset in +this version of SubDyn that contains SSI capabilities. + +The derivation of the system reduction is shown below. After the LFEB +assembly, the system equation of motion of Eq. :eq:`main` can be partitioned as +follows: + +.. math:: :label: main2 + + \begin{bmatrix} + M_{RR} & M_{RL} \\ + M_{LR} & M_{LL} + \end{bmatrix} + \begin{bmatrix} + \ddot{U_R} \\ + \ddot{U_L} + \end{bmatrix} + + \begin{bmatrix} + C_{RR} & C_{RL} \\ + C_{LR} & C_{LL} + \end{bmatrix} + \begin{bmatrix} + \dot{U_R} \\ + \dot{U_L} + \end{bmatrix} + + \begin{bmatrix} K_{RR} & K_{RL} \\ + K_{LR} & K_{LL} + \end{bmatrix} + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} F_R + F_{Rg} \\ + F_L + F_{Lg} + \end{bmatrix} + +where the subscript *R* denotes the boundary DOFs (there are *R* DOFs), and +the subscript *L* the interior DOFs (there are *L* DOFs). + +In Eq. :eq:`main2`, the applied forces include external forces (e.g., hydrodynamic +forces and those transmitted through the TP to the substructure) :math:`{(F_R,F_L)}` and +gravity forces :math:`{(F_{Rg},F_{L}g)}`, which are considered static forces lumped at each node. +The forces at the boundary nodes can be broken down into hydrodynamic +forces and those transferred to and from ElastoDyn via the TP, thus: + +.. math:: :label: FR + + F_R =F_{HDR} + F_{EDR} + +The fundamental assumption of the C-B method is that the contribution to +the displacement of the interior nodes can be simply approximated by a +subset :math:`q_m` ( :math:`{q_m \leq L}` ) of the interior generalized DOFs ( :math:`q_L` ). The relationship +between physical DOFs and generalized DOFs can be written as: + +.. math:: :label: CB1 + + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} + I & 0 \\ + \Phi_R & \Phi_L + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_L + \end{bmatrix} + +where *I* is the identity matrix; :math:`{\Phi_R}` (*L*\ ×\ *R* matrix) represents the +physical displacements of the interior nodes for static, rigid body +motions at the boundary (interface nodes’ DOFs, because the restrained +nodes’ DOFs are locked by definition). By considering the homogeneous, +static version of :eq:`main2`, the second row can be manipulated to yield: + +.. math:: :label: CB2 + + [K_{LR}] {U_R} + [K_{LL}]{U_L} ={0} + +Rearranging and considering yields: + +.. math:: :label: PhiR + + \Phi_R = -K_{LL}^{-1} K_{LR} + +where the brackets have been removed for simplicity. + +:math:`{\Phi_L}` (*L*\ ×\ *L* matrix) represents the internal eigenmodes, i.e., the +natural modes of the system restrained at the boundary (interface and +bottom nodes), and can be obtained by solving the eigenvalue problem: + +.. math:: :label: PhiL1 + + K_{LL} \Phi_L = \omega^2 M_{LL} \Phi_L + +The eigenvalue problem in Eq. :eq:`PhiL1` leads to the reduced basis of generalized +modal DOFs :math:`q_m`, which are chosen as the first few (*m*) eigenvectors that +are arranged by increasing eigenfrequencies. :math:`\Phi_L` is mass normalized, so +that: + +.. math:: :label: PhiL2 + + \Phi_L^T M_{LL} \Phi_L = I + +By then reducing the number of generalized DOFs to *m* ( :math:`{\le L}`), :math:`{\Phi_m}` is +chosen to denote the truncated set of :math:`{\Phi_L}` (keeping *m* of the total internal +modes, hence *m* columns), and :math:`{\Omega_m}` is the diagonal (*m*\ ×\ *m*) matrix +containing the corresponding eigenfrequencies. In SubDyn, the user +decides how many modes to retain, including possibly zero or all modes. +Retaining zero modes corresponds to a Guyan (static) reduction; +retaining all modes corresponds to keeping the full finite-element +model. + +The C-B transformation is therefore represented by: + +.. math:: :label: CB3 + + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} + I & 0 \\ + \Phi_R & \Phi_m + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_m + \end{bmatrix} + +By using Eq. :eq:`CB3`, the interior DOFs are hence transformed from physical +DOFs to modal DOFs, and by pre-multiplying both sides of Eq. :eq:`main2` by + +.. math:: + + \begin{bmatrix} + I & 0 \\ + \Phi_R & \Phi_m + \end{bmatrix}^T = + \begin{bmatrix} + I & \Phi_R^T \\ + 0 & \Phi_m^T + \end{bmatrix}^T + +and making use of Eq. :eq:`PhiL2`, Eq. :eq:`main2` can be rewritten as: + +.. math:: :label: main3 + + \begin{bmatrix} + M_{BB} & M_{Bm} \\ + M_{mB} & I + \end{bmatrix} + \begin{bmatrix} + \ddot{U_R} \\ + \ddot{q_m} + \end{bmatrix} + + \begin{bmatrix} + 0 & 0 \\ + 0 & 2\zeta \Omega_m + \end{bmatrix} + \begin{bmatrix} + \dot{U_R} \\ + \dot{q_m} + \end{bmatrix} + + \begin{bmatrix} K_{BB} & 0 \\ + 0 & \Omega_m^2 + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_m + \end{bmatrix} = + \begin{bmatrix} F_R + F_{Rg} + \Phi_R^T \left( F_L + F_{Lg} \right)\\ + \Phi_m^T \left( F_L + F_{Lg} \right) + \end{bmatrix} + +Eq. :eq:`main3` assumes that: + +.. math:: :label: damping + + \begin{bmatrix} + I & \Phi_R^T \\ + 0 & \Phi_m^T + \end{bmatrix} + \begin{bmatrix} + C_{RR} & C_{RL} \\ + C_{LR} & C_{LL} + \end{bmatrix} + \begin{bmatrix} + I & 0 \\ + \Phi_R & \Phi_m + \end{bmatrix} = + \begin{bmatrix} + C_{RR} + C_{RL} \Phi_R + \Phi_R^T C_{LL} \Phi_R & C_{RL} \Phi_m + \Phi_R^T C_{LL} \Phi_m \\ + \Phi_m^T C_{LR} + \Phi_m^T C_{LL} \Phi_R & \Phi_m^T C_{LL} \Phi_m + \end{bmatrix} = + \begin{bmatrix} + 0 & 0 \\ + 0 & \Phi_m^T C_{LL} \Phi_m + \end{bmatrix} = + + \begin{bmatrix} + 0 & 0 \\ + 0 & 2 \zeta \Omega_m + \end{bmatrix} + + +In other words, the only damping matrix term retained is the one +associated with internal DOF damping. This assumption has implications +on the damping at the interface with the turbine system, as discussed in +Section :ref:`_TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contains the modal +damping ratios corresponding to each retained internal mode. In SubDyn, +the user provides damping ratios (in percent of critical damping +coefficients) for the retained modes. + +The matrix partitions in Eq. are calculated as follows: + +.. math:: :label: partitions + + M_{BB} = M_{RR} + M_{RL} \Phi_R + \Phi_R^T M_{LR} + \Phi_R^T M_{LL} \Phi_R + + M_{mB} = \Phi_m^T M_{LR} + \Phi_m^T M_{LL} \Phi_R + + M_{Bm} = M_{mB}^T + + K_{BB} = K_{RR} + K_{RL} \Phi_R + +Next, the boundary nodes are partitioned into those at the interface, :math:`{\bar{U}_R}`, +and those at the bottom, which are fixed: + +.. math:: :label: UR + + U_R = \begin{bmatrix} + \bar{U}_R \\ + 0 + \end{bmatrix} + + +The overhead bar here and below denotes matrices/vectors after the +fixed-bottom boundary conditions are applied. The interface nodes are +treated as rigidly connected to the TP, hence it is convenient to use +rigid-body TP DOFs (one node with 6 DOFs at the TP reference point) in +place of the interface DOFs. The interface DOFs, :math:`{\bar{U}_R}`, and the TP DOFs are +related to each other as follows: + +.. math:: :label: UTP + + U_R = T_I U_{TP} + +where :math:`T_I` is a :math:`{\left(6 NIN \right) \times 6}` matrix, :math:`NIN` is the number of interface nodes, and :math:`{U_{TP}}` is the 6 DOFs +of the rigid transition piece. The matrix :math:`T_I` can be written as follows: + +.. math:: :label: TI + + T_I= \begin{bmatrix} + 1 & 0 & 0 & 0 & \Delta Z_1 & - \Delta Y_1 \\ + 0 & 1 & 0 & -\Delta Z_1 & 0 & - \Delta X_1 \\ + 0 & 0 & 1 & \Delta Y_1 & - \Delta X_1 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 \\ + \vdots & \vdots & \vdots & \vdots & \vdots & \vdots \\ + 1 & 0 & 0 & 0 & \Delta Z_i & - \Delta Y_i \\ + 0 & 1 & 0 & -\Delta Z_i & 0 & - \Delta X_i \\ + 0 & 0 & 1 & \Delta Y_i & - \Delta X_i & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 \\ + \vdots & \vdots & \vdots & \vdots & \vdots & \vdots \\ + \end{bmatrix}, \left( i= 1, 2, \cdots,NIN \right) + +with + +.. math:: :label: DXYZ + + \Delta X_i = X_{INi} - X_{TP} + + \Delta Y_i = Y_{INi} - Y_{TP} + + \Delta Z_i = Z_{INi} - Z_{TP} + + +where :math:`{ \left( X_{INi}, Y_{INi}, Z_{INi} \right) }` are the coordinates of the :math:`{i^{th}}` interface node and :math:`{ \left( X_{TP}, Y_{TP}, Z_{TP} \right) }`are the coordinates of +the TP reference point within the global coordinate system. + +In terms of TP DOFs, the system equation of motion :eq:`main3` after the boundary +constraints are applied (the rows and columns corresponding to the DOFs +of the nodes that are restrained at the seabed are removed from the +equation of motion) becomes: + +.. math:: :label: main4 + + \begin{bmatrix} + \tilde{M}_{BB} & \tilde{M}_{Bm} \\ + \tilde{M}_{mB} & I + \end{bmatrix} + \begin{bmatrix} + \ddot{U_{TP}} \\ + \ddot{q_m} + \end{bmatrix} + + \begin{bmatrix} + 0 & 0 \\ + 0 & 2\zeta \Omega_m + \end{bmatrix} + \begin{bmatrix} + \dot{U_{TP}} \\ + \dot{q_m} + \end{bmatrix} + + \begin{bmatrix} \tilde{K}_{BB} & 0 \\ + 0 & \Omega_m^2 + \end{bmatrix} + \begin{bmatrix} + U_{TP} \\ + q_m + \end{bmatrix} = + \begin{bmatrix} \tilde{F}_{TP} \\ + \tilde{F}_m + \end{bmatrix} + +with + +.. math:: :label: tilde_partitions + + \tilde{M}_{BB} = T_I^T \bar{M}_{BB} T_I + + \tilde{M}_{Bm} = T_I^T \bar{M}_{Bm} + + \tilde{M}_{mB} = \tilde{M}_{Bm}^T + + \tilde{K}_{BB} = T_I^T \bar{K}_{BB} T_I + + \tilde{F}_{TP} = F_{TP} + T_I^T \bar{F}_{HDR} + T_I^T \bar{F}_{Rg} + T_I^T \bar{\Phi}_{R}^T \left( F_L + F_{Lg} \right) + + \tilde{F}_{m} = \Phi_m^T \left( F_L + F_{Lg} \right) + + + +where the TP reaction force, i.e., the force applied to the substructure +through the TP, is denoted by: + +.. math:: :label: FTP + + F_{TP} = T_I^T F_{EDR} + +Equation :eq:`main4` represents the equations of motion of the substructure after +the C-B reduction. The total DOFs of the substructure are reduced from +(6 x total number of nodes) to (6 + *m*). + +During initialization, SubDyn calculates: the parameter matrices :math:`{\tilde{M}_{BB}, \tilde{M}_{mB}, \tilde{M}_{Bm}, \tilde{K}_{BB}, \Phi_m, \Phi_R, T_I}`; the +gravity arrays :math:`\bar{F}_{Rg}` and :math:`F_{Lg}` ; and the internal frequency matrix :math:`\Omega_m` . The +substructure response at each time step can then be obtained by using +the state-space formulation discussed in the next section. + + +.. _SSformulation: + +State-Space Formulation +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A state-space formulation of the substructure structural dynamics +problem was devised to integrate SubDyn within the FAST modularization +framework. The state-space formulation was developed in terms of inputs, +outputs, states, and parameters. The notations highlighted here are +consistent with those used in Jonkman (2013). Inputs (identified by *u*) +are a set of values supplied to SubDyn that, along with the states, are +needed to calculate future states and the system’s output. Outputs (*y*) +are a set of values calculated by and returned from SubDyn that depend +on the states, inputs, and/or parameters through output equations (with +functions *Y*). States are a set of internal values of SubDyn that are +influenced by the inputs and used to calculate future state values and +the output. In SubDyn, only continuous states are considered. Continuous +states (*x*) are states that are differentiable in time and +characterized by continuous time differential equations (with functions +*X*). Parameters (*p*) are a set of internal system values that are +independent of the states and inputs. Furthermore, parameters can be +fully defined at initialization and characterize the system’s state +equations and output equations. + +In SubDyn, the inputs are defined as: + +.. math:: :label: inputs + + u = \begin{bmatrix} + u1 \\ + u2 \\ + u3 \\ + u4 \\ + u5 \\ + \end{bmatrix} = \begin{bmatrix} + U_{TP} \\ + \dot{U}_{TP} \\ + \ddot{U}_{TP} \\ + F_{L} \\ + F_{HDR} \\ + \end{bmatrix} + + +where :math:`F_L` are the hydrodynamic forces on every interior node of the +substructure from HydroDyn, and `F_{HDR}` are the analogous forces at the boundary +nodes; :math:`{ U_{TP},\dot{U}_{TP}, and \ddot{U}_{TP}}` are TP deflections (6 DOFs), velocities, and +accelerations, respectively. For SubDyn in stand-alone mode (uncoupled +from FAST), :math:`F_{L}` and :math:`F_{HDR}` are assumed to be zero. + +In first-order form, the states are defined as: + +.. math:: :label: states + + x = \begin{bmatrix} + x1 \\ + x2 \\ + \end{bmatrix} = \begin{bmatrix} + q_m \\ + \dot{q}_m \\ + \end{bmatrix} + + +From the system equation of motion, the state equation corresponding to +Eq. :eq:`main4` can be written as a standard linear system state equation: + +.. math:: :label: state_eq + + \dot{x} = X = A x +Bu + F_X + +where + +.. math:: :label: ABFx + + A = \begin{bmatrix} + 0 & I \\ + -\Omega_m^2 & -2 \zeta \Omega_m + \end{bmatrix} + + B = \begin{bmatrix} + 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & -\tilde{M}_{mB} & \Phi_m^T & 0 + \end{bmatrix} + F_X = \begin{bmatrix} + 0 \\ + \Phi_m^T F_{Lg} + \end{bmatrix} + + +In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the transition piece :math:`F_{TP}`: + +.. math:: :label: y1 + + y1 = Y_1 =-F_{TP} + +By examining Eq. :eq:`main4` , the output equation for can be found as: + +.. math:: :label: Y1 + + -Y_1 =C_1 x + D_1 \bar{u} + F_{Y1} + +where + +.. math:: :label: C1D1FY1u + + C_1 = \begin{bmatrix} -\tilde{M}_{Bm} \Omega_m^2 & -2\tilde{M}_{Bm} \zeta \Omega_m \end{bmatrix} + + D_1 = \begin{bmatrix} \tilde{K}_{BB} & 0 & \tilde{M}_{BB} - \tilde{M}_{Bm} \tilde{M}_{mB} & \tilde{M}_{Bm} \Phi_m^T - T_I^T \bar{\Phi}_R^T & -T_I^T \end{bmatrix} + + F_{Y1} = \begin{bmatrix} \tilde{M}_{Bm} \Phi_m^T F_{Lg} - T_I^T \left( \bar{F}_{Rg} + \bar{\Phi}_R^T F_{Lg} \right) \end{bmatrix} + + u = \begin{bmatrix} + U_{TP} \\ + \dot{U}_{TP} \\ + \ddot{U}_{TP} \\ + F_{L} \\ + \bar{F}_{HDR} + \end{bmatrix} + + +Note that the overbar is used on the input vector to denote that the +forces apply to the interface nodes only. + +The outputs to HydroDyn and other modules are the deflections, +velocities, and accelerations of the substructure: + +.. math:: :label: y2 + + y_2= Y_2 = \begin{bmatrix} + \bar{U}_R \\ + U_L \\ + \dot{\bar{U}}_R \\ + \dot{U}_L \\ + \ddot{\bar{U}}_R \\ + \ddot{U}_L \\ + \end{bmatrix} + + +The output equation for :math:`y_2`: can then be written as: + +.. math:: :label: Y2 + + Y_2 = C_2 x + D_2 u + F_{Y2} + + +where + +.. math:: :label: C2D2FY2 + + C_2 = \begin{bmatrix} + 0 & 0 \\ + \Phi_m & 0 \\ + 0 & 0 \\ + 0 & \Phi_m \\ + 0 & 0 \\ + -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ + \end{bmatrix} + + D_2 = \begin{bmatrix} + T_I & 0 & 0 & 0 & 0 \\ + \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ + 0 & T_I & 0 & 0 & 0 \\ + 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ + 0 & 0 & T_I & 0 & 0 \\ + 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 + \end{bmatrix} + + F_{Y2} = \begin{bmatrix} + 0 \\ + 0 \\ + 0 \\ + 0 \\ + 0 \\ + \Phi_m \Phi_m^T F_{Lg} + \end{bmatrix} + + +Member Force Calculation +~~~~~~~~~~~~~~~~~~~~~~~~ + +SubDyn can also calculate member forces by starting from the forces +computed at the nodes of the elements that are contained in the member +as: + +.. math:: :label: el_loads + + \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e + + \text{Element Static load:} ~~ F_S^e = [k] U_e + +where [*k*] and [*m*] are element stiffness and mass matrices, respectively. And +:math:`U_e` and :math:`\ddot{U}_e` are element nodal deflections and accelerations respectively, +which can be obtained from Eq. :eq:`y2`. + +There is no good way to quantify the damping forces for each element, so +the element damping forces are not calculated. + +Reaction Calculation +~~~~~~~~~~~~~~~~~~~~ + +The reactions at the base of the structure are the member forces at the +base nodes. These are usually provided in member local reference frames. +Additionally, the user may request an overall reaction +:math:`\overrightarrow{R}` (six forces and moments) lumped at the center +of the substructure (tower centerline) and mudline, i.e., at the +reference point (0,0,-**WtrDpth**) in the global reference frame, with +**WtrDpth** denoting the water depth. :math:`\overrightarrow{R}` is a +six-element array that can be calculated in matrix form as follows: + +.. math:: :label: reaction + + \overrightarrow{R} = \begin{bmatrix} + F_{X} \\ + \vdots \\ + M_{Z} \\ + \end{bmatrix} = T_{\text{React}} F_{\text{React}} + + +where :math:`F_{\text{React}}` is a (6*N\ :sub:`React`) array +containing the forces and moments at the *N\ :sub:`react`* restrained +nodes in the global coordinate frame, and :math:`T_{\text{React}}` is a +( :math:`{6×6 N_{\text{React}}}` ) matrix, as follows: + +.. math:: :label: Treact + + T_{\text{React}} = \begin{bmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & \cdots & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & \cdots & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & \cdots & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & -\Delta Z_1 & \Delta Y_1 & 1 & 0 & 0 & \cdots & 0 & -\Delta Z_{Nreact} & \Delta Y_{Nreact} & 1 & 0 & 0 \\ + \Delta Z_1 & 0 & -\Delta X_1 & 0 & 1 & 0 & \cdots & \Delta Z_{Nreact} & 0 & -\Delta X_{Nreact} & 0 & 1 & 0 \\ + \Delta Y_1 & \Delta X_1 & 0 & 0 & 0 & 1 & \cdots & \Delta Y_{Nreact} & \Delta X_{Nreact} & 0 & 0 & 0 & 1 + \end{bmatrix} + +where :math:`{X_i,~Y_i}`, and :math:`Z_i` (:math:`{i = 1 .. N_{\text{React}}}`) are coordinates of +the boundary nodes with respect to the reference point. For each element +with a restrained node, :math:`F_{\text{React}}` is calculated starting +from :math:`F_S^e` --- see Eq. :eq:`el_loads` --- subtracting out the contributions of gravity --- :math:`F_G`, see Eq. :eq:`FG` +—and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct +element-level inertial or damping effect is therefore included in the +reaction calculation. + +.. _TimeIntegration: + +Time Integration +~~~~~~~~~~~~~~~~~ + +At time :math:`{t=0}`, the initial states are specified as initial conditions (all +assumed to be zero in SubDyn) and the initial inputs are supplied to +SubDyn. During each subsequent time step, the inputs and states are +known values, with the inputs :math:`u(t)` coming from ElastoDyn and HydroDyn, and +the states :math:`x(t)` known from the previous time-step integration. All of the +parameter matrices are calculated in the SubDyn initiation module. With +known :math:`u(t)` and :math:`x(t)`, :math:`{\dot{x}(t)}` can be calculated using the state equation :math:`{\dot{x}(t)=X(u,x,t)}` (see Eq. :eq:`state_eq`), and +the outputs :math:`y_1(t)` and :math:`y_2(t)` can be calculated solving Eqs. :eq:`Y1` and :eq:`Y2`. The element forces +can also be calculated using Eq. :eq:`el_loads`. The next time-step states :math:`{x(t + \Delta t)}` are +obtained by integration: + +.. math:: :label: integration + + \left [ u(t), \dot{x}(t), x(t) \right ] \xrightarrow[]{\text{Integrate}} x(t + \Delta t) + + +For loose coupling, SubDyn uses its own integrator, whereas for tight +coupling, the states from all the modules will be integrated +simultaneously using an integrator in the glue-code. SubDyn’s built-in +time integrator options for loose coupling are: + +- Fourth-order explicit Runge-Kutta + +- Fourth-order explicit Adams-Bashforth predictor + +- Fourth-order explicit Adams-Bashforth-Moulton predictor-corrector + +- Implicit second-order Adams-Moulton. + +For more information, consult any numerical methods reference, e.g., +:cite:`chapra2010`. + +.. _sim: + +Static-Improvement Method +~~~~~~~~~~~~~~~~~~~~~~~~~ +To account for the effects of static gravity (member self-weight) and +buoyancy forces, one would have to include all of the structural axial +modes in the C-B reduction. This inclusion often translates into +hundreds of modes to be retained for practical problems. An alternative +method is thus promoted to reduce this limitation and speed up SubDyn. +This method is denoted as SIM, and computes two static solutions at each +time step: one based on the full system stiffness matrix and one based +on the reduced stiffness matrix. The dynamic solution then proceeds as +described in the previous sections, and at each time step the +time-varying dynamic solution is superimposed on the difference between +the two static solutions, which amounts to quasi-statically accounting +for the contribution of those modes not directly included within the +dynamic solution. + +Recalling the previous C-B formulation :eq:`CB3`, and adding the total static +deflection of all the internal DOFs (:math:`U_{L0}`), and subtracting the static +deflection associated with C-B modes (:math:`U_{L0m}`), the SIM formulation is cast as +in :eq:`SIM`: + +.. math:: :label: SIM + + U_L = \hat{U}_L + U_{L0} - U_{L0m} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + U_{L0} - U_{L0m} + + +Eq. :eq:`SIM` can be rewritten as: + +.. math:: :label: SIM2 + + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} + I & 0 & 0 & 0 \\ + \Phi_R & \Phi_m & \Phi_L & -\Phi_m + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_m \\ + q_{L0} \\ + q_{m0} + \end{bmatrix} + +with: + +.. math:: :label: UL0 + + U_{L0} = \Phi_L q_{L0} + +.. math:: :label: UL0m + + U_{L0m} = \Phi_m q_{m0} + + +where :math:`{q_{m0}}` and :math:`{q_{L0}}` are the *m* and *L* modal coefficients that are assumed to be +operating in a static fashion. For Eqs. :eq:`SIM2` and :eq:`UL0` to be valid, and are +calculated under the C-B hypothesis that the boundary nodes are fixed. + +The static displacement vectors can also be calculated as follows: + + +.. math:: :label: SIM3 + + K_{LL} U_{L0} = F_L + F_{Lg} + +By making use of :eq:`UL0`, and by pre-multiplying both sides times , Eq. :eq:`SIM3` can be +rewritten as: :math:`{\Phi_L^T K_{LL} \Phi_L q_{L0} = \Phi_L^T \left( F_L + F_{Lg} \right) = \tilde{F}_L }` or, recalling that :math:`{\Phi_L^T K_{LL} \Phi_L = \Omega_L^2}`, as: :math:`{\Omega_L^2 q_{L0} =\tilde{F}_L }`, or equivalently in terms of :math:`U_{L0}`: + +.. math:: :label: UL02 + + U_{L0} = \Phi_L \left[ \Omega_L^2 \right]^{-1} \tilde{F}_L + +Similarly: + +.. math:: :label: UL0m2 + + U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m + +Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. + +The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R \end{bmatrix} }` is calculated following the usual procedure +described in Sections :ref:`_SSformulation` -- :ref:`_TimeIntegration`. For example, states are still +calculated and integrated as in Eq. :eq:`state_eq`, and the output to ElastoDyn, i.e., +the reaction provided by the substructure at the TP interface, is also +calculated as it was done previously in Eqs. :eq:`y1` and :eq:`Y1`. + +However, the state-space formulation is slightly modified to allow for +the calculation of the outputs to HydroDyn as: + +.. math:: :label: y2sim + + y_2= = \begin{bmatrix} + \bar{U}_R \\ + U_L \\ + \dot{\bar{U}}_R \\ + \dot{U}_L \\ + \ddot{\bar{U}}_R \\ + \ddot{U}_L \\ + \end{bmatrix} = \begin{bmatrix} + \bar{U}_R \\ + \hat{U}_L + U_{L0} - U_{L0m} \\ + \dot{\bar{U}}_R \\ + \dot{U}_L \\ + \ddot{\bar{U}}_R \\ + \ddot{U}_L \\ + \end{bmatrix} + +.. math:: :label: Y2sim + + Y_2 = C_2 x + D_2 u + F_{Y2} + +where the matrices now have the following meaning: + +.. math:: :label: C2D2FY2sim + + C_2 = \begin{bmatrix} + 0 & 0 \\ + \Phi_m & 0 \\ + 0 & 0 \\ + 0 & \Phi_m \\ + 0 & 0 \\ + -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ + \end{bmatrix} + + D_2 = \begin{bmatrix} + T_I & 0 & 0 & 0 & 0 \\ + \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ + 0 & T_I & 0 & 0 & 0 \\ + 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ + 0 & 0 & T_I & 0 & 0 \\ + 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 + \end{bmatrix} + + F_{Y2} = \begin{bmatrix} + 0 \\ + U_{L0} - U_{L0m} \\ + 0 \\ + 0 \\ + 0 \\ + \Phi_m \Phi_m^T F_{Lg} + \end{bmatrix} + + +Finally, the element forces can be calculated as: + +.. math:: :label: el_loads_sim + + \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e + + \text{Element Static load:} ~~ F_S^e = [k] U_e = [k] \left[ \hat{U}_e + U_{L0,e} - U_{L0m,e} \right] + +with the element node DOFs expressed as: + +.. math:: :label: Uesim + + U_e = \hat{U}_e + U_{L0,e} - U_{L0m,e} + +where the SIM decomposition is still used with :math:`\hat{U}_e` denoting the +time-varying components of the elements nodes’ displacements, and :math:`U_{L0,e}` and :math:`U_{L0m,e}` are +derived from the parent :math:`U_{L0}` and :math:`U_{L0m}` arrays of displacements, respectively. + + + + + + + + + diff --git a/docs/source/user/subdyn/zrefs.rst b/docs/source/user/subdyn/zrefs.rst new file mode 100644 index 000000000..c434bde8a --- /dev/null +++ b/docs/source/user/subdyn/zrefs.rst @@ -0,0 +1,9 @@ +.. only:: html + + References + ---------- + +.. bibliography:: references.bib + + + From 3f32b1a924a96ef85b2de6139e24657aa615314c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 6 Jul 2020 22:58:08 -0600 Subject: [PATCH 235/377] FlexSub: doc: starting TCF doc, more damping terms --- docs/source/user/aerodyn/input.rst | 2 +- docs/source/user/subdyn/.gitignore | 3 + docs/source/user/subdyn/Makefile | 15 +- docs/source/user/subdyn/appendixA.rst | 2 +- docs/source/user/subdyn/appendixB.rst | 2 +- docs/source/user/subdyn/appendixC.rst | 2 +- docs/source/user/subdyn/appendixF.rst | 24 +- docs/source/user/subdyn/conf.py | 2 +- .../subdyn/examples/OC4_Jacket_SD_Driver.dvr | 21 + .../subdyn/examples/OC4_Jacket_SD_Input.dat | 284 ++++++++ .../subdyn/examples/OC4_Jacket_SD_SSI.txt | 23 + .../figs/{element-CS.png => element-cs.png} | Bin docs/source/user/subdyn/future_work.rst | 2 +- docs/source/user/subdyn/input_files.rst | 33 +- docs/source/user/subdyn/introduction.rst | 14 +- docs/source/user/subdyn/modeling.rst | 15 +- docs/source/user/subdyn/notations.rst | 670 ------------------ docs/source/user/subdyn/output_files.rst | 4 +- .../{references.bib => references_SD.bib} | 45 +- docs/source/user/subdyn/running_sd.rst | 55 +- docs/source/user/subdyn/theory.rst | 498 ++++++++----- docs/source/user/subdyn/zrefs.rst | 2 +- 22 files changed, 761 insertions(+), 957 deletions(-) create mode 100644 docs/source/user/subdyn/examples/OC4_Jacket_SD_Driver.dvr create mode 100644 docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat create mode 100644 docs/source/user/subdyn/examples/OC4_Jacket_SD_SSI.txt rename docs/source/user/subdyn/figs/{element-CS.png => element-cs.png} (100%) delete mode 100644 docs/source/user/subdyn/notations.rst rename docs/source/user/subdyn/{references.bib => references_SD.bib} (81%) diff --git a/docs/source/user/aerodyn/input.rst b/docs/source/user/aerodyn/input.rst index 0cc938ee7..68463f23f 100644 --- a/docs/source/user/aerodyn/input.rst +++ b/docs/source/user/aerodyn/input.rst @@ -154,7 +154,7 @@ program). Set ``WakeMod`` to 0 if you want to disable rotor wake/induction effects or 1 to include these effects using the (quasi-steady) BEM theory model. When ``WakeMod`` is set to 2, a dynamic BEM theory model (DBEMT) is used (also referred to - as dynamic inflow or dynamic wake model). +as dynamic inflow or dynamic wake model). ``WakeMod`` cannot be set to 2 during linearization analyses. Set ``AFAeroMod`` to 1 to include steady blade airfoil aerodynamics or 2 diff --git a/docs/source/user/subdyn/.gitignore b/docs/source/user/subdyn/.gitignore index fe560c00f..ba08b4418 100644 --- a/docs/source/user/subdyn/.gitignore +++ b/docs/source/user/subdyn/.gitignore @@ -1 +1,4 @@ _build* +*.pdf +*.docx +_* diff --git a/docs/source/user/subdyn/Makefile b/docs/source/user/subdyn/Makefile index 081d13e38..da41c31a2 100644 --- a/docs/source/user/subdyn/Makefile +++ b/docs/source/user/subdyn/Makefile @@ -1,5 +1,6 @@ # Makefile for Sphinx documentation # +MAIN=SubDyn # You can set these variables from the command line. SPHINXOPTS = @@ -16,7 +17,7 @@ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . all: pdf doc2rst: - pandoc -F pandoc-crossref -F pandoc-citeproc -s -t rst --toc SubDyn_Manual_Rev037.docx -o output.rst --bibliography=references.bib + pandoc -F pandoc-crossref -F pandoc-citeproc -s -t rst --toc SubDyn_Manual_Rev037.docx -o output.rst --bibliography=references_SD.bib # --wrap=preserve # -F pandoc-crossref @@ -41,15 +42,21 @@ help: clean: -rm -rf _build/* -pdf: latex - cd _build/latex && make all-pdf +pdf: latex pdf-compile diff +# cd _build/latex && make all-pdf pdf-compile: - cd _build/latex && make all-pdf + cd _build/latex && pdflatex $(MAIN).tex +# cd _build/latex && make all-pdf pdf-html: pdf html cp _build/latex/sampledoc.pdf _build/html +diff: + cd _build/latex && latexdiff -p ../../LatexDiffPreamble.tex $(MAIN)-old.tex $(MAIN).tex > $(MAIN)-diff.tex + cd _build/latex && cp $(MAIN).aux $(MAIN)-diff.aux + cd _build/latex && pdflatex --interaction=nonstopmode $(MAIN)-diff.tex + html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html diff --git a/docs/source/user/subdyn/appendixA.rst b/docs/source/user/subdyn/appendixA.rst index fbedf80d7..898a38f2b 100644 --- a/docs/source/user/subdyn/appendixA.rst +++ b/docs/source/user/subdyn/appendixA.rst @@ -4,7 +4,7 @@ Appendix A. OC4 Jacket Input File ================================= SubDyn's primary input file -.. :download:`(OC4 Jacket SubDyn's Input File) <./examples/OC4_Jacket_SD_Input.txt>`: +:download:`(OC4 Jacket SubDyn's Input File) <./examples/OC4_Jacket_SD_Input.dat>`: This file includes information on the integration method (e.g., Adams-Bashforth 4 :sup:`th`} order), numerical-solution parameters (e.g., integration time interval, static solver flag, numer of modes to retain within the Craig-Bampton reduction), diff --git a/docs/source/user/subdyn/appendixB.rst b/docs/source/user/subdyn/appendixB.rst index f4d316669..02f21e901 100644 --- a/docs/source/user/subdyn/appendixB.rst +++ b/docs/source/user/subdyn/appendixB.rst @@ -4,7 +4,7 @@ Appendix B. OC4 Jacket Driver File ================================== SubDyn's Driver Input File -.. :download:`(OC4 Jacket Driver File) <./examples/OC4_Jacket_SD_Driver.txt>`: +:download:`(OC4 Jacket Driver File) <./examples/OC4_Jacket_SD_Driver.dvr>`: This file includes information on the environmental conditions (gravity and water depth), numerical-solution parameters (e.g., integration time interval, numer of time-steps), TP reference point coordinates in global reference frame, diff --git a/docs/source/user/subdyn/appendixC.rst b/docs/source/user/subdyn/appendixC.rst index 51b600e42..74af12f31 100644 --- a/docs/source/user/subdyn/appendixC.rst +++ b/docs/source/user/subdyn/appendixC.rst @@ -4,6 +4,6 @@ Appendix C. OC4 Jacket SSI Input File ===================================== SubDyn's SSI File -.. :download:`(OC4 Jacket SSI File) <./examples/OC4_Jacket_SD_SSI.txt>`: +:download:`(OC4 Jacket SSI File) <./examples/OC4_Jacket_SD_SSI.txt>`: This file includes information on the stiffness of embedded-pile/soil combination. diff --git a/docs/source/user/subdyn/appendixF.rst b/docs/source/user/subdyn/appendixF.rst index 2893f5b08..dd048dfa9 100644 --- a/docs/source/user/subdyn/appendixF.rst +++ b/docs/source/user/subdyn/appendixF.rst @@ -11,12 +11,32 @@ SubDyn made since v0.4. Following are the main changes that the user may notice, but for more information, refer to the *changelog.txt* text file within the official archive and the GitHub log. + +V1.04.00 (September 2020) +------------------------------ + +- Version 1.04.00 integrates with OpenFAST version 2.4 + +- Member types: beam, rigid link, pretension cable + +- Joint types: cantilever, universal, pin, ball + +- Input of all terms for concentrated mass + +- Guyan damping matrix + +- Extra lever arm + +- Coupling sith SoilDyn + +- Inclusion of soil-structure interaction (SSI) via flexible degrees of fixity at the restrained nodes and a new input file that allows for 6x6 stiffness and mass matrices that simulate boundary conditions at those nodes. + + V1.03.00a-rrd (September 2017) ------------------------------ - Version 1.03.00a-rrd integrates with the `OpenFast software `__. -- Inclusion of soil-structure interaction (SSI) via flexible degrees of fixity at the restrained nodes and a new input file that allows for 6x6 stiffness and mass matrices that simulate boundary conditions at those nodes. V1.01.01a-rrd (September 2014) @@ -109,7 +129,7 @@ good results. modes were needed to engage substructural modes excited by static and high-frequency forces. These modes are no longer needed and fewer modes can be retained while still achieving accurate results (see - also Section :ref:`_subdyn-theory`). With SIM enabled, all modes that are not considered + also :numref:`subdyn-theory`). With SIM enabled, all modes that are not considered by the Craig-Bampton reduction are treated quasi-statically. - There is now the possibility of retaining no internal C-B modes, thus diff --git a/docs/source/user/subdyn/conf.py b/docs/source/user/subdyn/conf.py index 782fc254c..50911aa13 100644 --- a/docs/source/user/subdyn/conf.py +++ b/docs/source/user/subdyn/conf.py @@ -149,7 +149,7 @@ def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ['../../../_static'] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Driver.dvr b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Driver.dvr new file mode 100644 index 000000000..1a9d5f4dc --- /dev/null +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Driver.dvr @@ -0,0 +1,21 @@ +--- SubDyn Driver file for Unit TestFrame. +Compatible with SubDyn v1.00.00 +TRUE Echo - Echo the input file data (flag) +---------------------- ENVIRONMENTAL CONDITIONS ------------------------------------------------- +9.81 Gravity - Gravity (m/s^2). +43.127 WtrDpth - Water Depth (m) positive value. +---------------------- SubDyn ------------------------------------------------------------------- +".\SubDyn_OC4Jacket.dat" SDInputFile - Absolute or relative path. +".\SubDyn_OC4Jacket" OutRootName - Basename for output files. +600 NSteps - Number of time steps in the simulations (-) +0.001 TimeInterval - TimeInterval for the simulation (sec) +0.0 0.0 18.15 TP_RefPoint - Location of the TP reference point in global coordinates (m) +0.0 SubRotateZ - Rotation angle of the structure geometry in degrees about the global Z axis. +---------------------- INPUTS ------------------------------------------------------------------- + 1 InputsMod - Inputs model {0: all inputs are zero for every timestep, 1: steady state inputs, 2: read inputs from a file (InputsFile)} (switch) +"" InputsFile - Name of the inputs file if InputsMod = 2. This file has to be defined as follows: i: No header. ii: It has NSteps+1 rows and each row (i) has in the first column the time: t = (i-1)*TimeInterval. The successive columns define the displacements ([m], [rad]), velocities ([m/s], [rad/s]) and accelerations ([m/s^2], [rad/s^2]) +---------------------- STEADY INPUTS (for InputsMod = 1) ---------------------------------------- +3.821E-02 1.656E-03 -4.325E-02 -1.339E-04 7.266E-02 -2.411E-03 uTPInSteady - input displacements and rotations ( m, rads ) +1.02 2.03 5.03 0.03 0.03 0.03 uDotTPInSteady - input translational and rotational velocities ( m/s, rads/s) +2.02 3.03 -9.03 0.3 0.03 0.3 uDotDotTPInSteady - input translational and rotational accelerations( m/s^2, rads/s^2) +END of driver input file diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat new file mode 100644 index 000000000..bf12bb0c6 --- /dev/null +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -0,0 +1,284 @@ +----------- SubDyn MultiMember Support Structure Input File ------------ +OC4 'Jacket' SubStructure Input File. The grouted connection is simulated with an equivalent tubular beam of enhanced properties. RRD 10/15/2013 +-------------------------- SIMULATION CONTROL --------------------------------- +False Echo - Echo input data to ".SD.ech" (flag) +"DEFAULT" SDdeltaT - Local Integration Step. If "default", the glue-code integration step will be used. + 3 IntMethod - Integration Method [1/2/3/4 = RK4/AB4/ABM4/AM2]. +True SttcSolve - Solve dynamics about static equilibrium point +True ExtraMoment - Include extra moment from lever arm at interface in interface reactions. +-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- + 3 FEMMod - FEM switch: element model in the FEM. [1= Euler-Bernoulli(E-B) ; 2=Tapered E-B (unavailable); 3= 2-node Timoshenko; 4= 2-node tapered Timoshenko (unavailable)] + 2 NDiv - Number of sub-elements per member +True CBMod - [T/F] If True perform C-B reduction, else full FEM dofs will be retained. If True, select Nmodes to retain in C-B reduced system. + 8 Nmodes - Number of internal modes to retain (ignored if CBMod=False). If Nmodes=0 --> Guyan Reduction. + 1 JDampings - Damping Ratios for each retained mode (% of critical) If Nmodes>0, list Nmodes structural damping ratios for each retained mode (% of critical), or a single damping ratio to be applied to all retained modes. (last entered value will be used for all remaining modes). + 0 GuyanDampMod - Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] + 0.000, 0.000 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] +Guyan damping matrix (6x6) [only if GuyanDampMod=2] + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 + 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 +---- STRUCTURE JOINTS: joints connect structure members (~Hydrodyn Input File)--- + 64 NJoints - Number of joints (-) +JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp + (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) + 1 6.00000 6.00000 -45.50000 + 2 6.00000 6.00000 -45.00000 + 3 5.96700 5.96700 -44.00100 + 4 5.93900 5.93900 -43.12700 + 5 5.33300 5.33300 -24.61400 + 6 -6.00000 6.00000 -45.50000 + 7 -6.00000 6.00000 -45.00000 + 8 -5.96700 5.96700 -44.00100 + 9 -5.93900 5.93900 -43.12700 + 10 -5.33300 5.33300 -24.61400 + 11 -6.00000 -6.00000 -45.50000 + 12 -6.00000 -6.00000 -45.00000 + 13 -5.96700 -5.96700 -44.00100 + 14 -5.93900 -5.93900 -43.12700 + 15 -5.33300 -5.33300 -24.61400 + 16 6.00000 -6.00000 -45.50000 + 17 6.00000 -6.00000 -45.00000 + 18 5.96700 -5.96700 -44.00100 + 19 5.93900 -5.93900 -43.12700 + 20 5.33300 -5.33300 -24.61400 + 21 4.82000 4.82000 -8.92200 + 22 4.38500 4.38500 4.37800 + 23 4.01600 4.01600 15.65100 + 24 4.00000 4.00000 16.15000 + 25 -4.82000 4.82000 -8.92200 + 26 -4.38500 4.38500 4.37800 + 27 -4.01600 4.01600 15.65100 + 28 -4.00000 4.00000 16.15000 + 29 -4.82000 -4.82000 -8.92200 + 30 -4.38500 -4.38500 4.37800 + 31 -4.01600 -4.01600 15.65100 + 32 -4.00000 -4.00000 16.15000 + 33 4.82000 -4.82000 -8.92200 + 34 4.38500 -4.38500 4.37800 + 35 4.01600 -4.01600 15.65100 + 36 4.00000 -4.00000 16.15000 + 37 5.62000 0.00000 -33.37300 + 38 -5.62000 0.00000 -33.37300 + 39 0.00000 5.62000 -33.37300 + 40 0.00000 -5.62000 -33.37300 + 41 5.06400 0.00000 -16.37100 + 42 -5.06400 0.00000 -16.37100 + 43 0.00000 5.06400 -16.37100 + 44 0.00000 -5.06400 -16.37100 + 45 4.59200 0.00000 -1.95800 + 46 -4.59200 0.00000 -1.95800 + 47 0.00000 4.59200 -1.95800 + 48 0.00000 -4.59200 -1.95800 + 49 4.19300 0.00000 10.26200 + 50 -4.19300 0.00000 10.26200 + 51 0.00000 4.19300 10.26200 + 52 0.00000 -4.19300 10.26200 + 53 4.00000 4.00000 20.15000 + 54 -4.00000 4.00000 20.15000 + 55 4.00000 -4.00000 20.15000 + 56 -4.00000 -4.00000 20.15000 + 57 6.00000 -6.00000 -49.50000 + 58 6.00000 6.00000 -49.50000 + 59 -6.00000 -6.00000 -49.50000 + 60 -6.00000 6.00000 -49.50000 + 61 6.00000 -6.00000 -50.00100 + 62 6.00000 6.00000 -50.00100 + 63 -6.00000 -6.00000 -50.00100 + 64 -6.00000 6.00000 -50.00100 +------------------- BASE REACTION JOINTS: 1/0 for Locked/Free DOF @ each Reaction Node --------------------- + 4 NReact - Number of Joints with reaction forces; be sure to remove all rigid motion DOFs of the structure (else det([K])=[0]) +RJointID RctTDXss RctTDYss RctTDZss RctRDXss RctRDYss RctRDZss SSIfile [Global Coordinate System] + (-) (flag) (flag) (flag) (flag) (flag) (flag) (string) + 61 1 1 1 1 1 1 "OC4_Jacket_SD_SSI.txt" + 62 1 1 1 1 1 1 "OC4_Jacket_SD_SSI.txt" + 63 1 1 1 1 1 1 "OC4_Jacket_SD_SSI.txt" + 64 1 1 1 1 1 1 "OC4_Jacket_SD_SSI.txt" +------- INTERFACE JOINTS: 1/0 for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- + 8 NInterf - Number of interface joints locked to the Transition Piece (TP): be sure to remove all rigid motion dofs +IJointID ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss [Global Coordinate System] + (-) (flag) (flag) (flag) (flag) (flag) (flag) + 24 1 1 1 1 1 1 + 28 1 1 1 1 1 1 + 32 1 1 1 1 1 1 + 36 1 1 1 1 1 1 + 53 1 1 1 1 1 1 + 54 1 1 1 1 1 1 + 55 1 1 1 1 1 1 + 56 1 1 1 1 1 1 +----------------------------------- MEMBERS -------------------------------------- + 112 NMembers - Number of frame members +MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID + (-) (-) (-) (-) (-) (-) (-) + 1 1 2 2 2 1 + 2 2 3 2 2 1 + 3 3 4 2 2 + 4 4 5 2 2 + 5 6 7 2 2 + 6 7 8 2 2 + 7 8 9 2 2 + 8 9 10 2 2 + 9 11 12 2 2 + 10 12 13 2 2 + 11 13 14 2 2 + 12 14 15 2 2 + 13 16 17 2 2 + 14 17 18 2 2 + 15 18 19 2 2 + 16 19 20 2 2 + 17 5 21 3 3 + 18 21 22 3 3 + 19 22 23 3 3 + 20 23 24 3 3 + 21 10 25 3 3 + 22 25 26 3 3 + 23 26 27 3 3 + 24 27 28 3 3 + 25 15 29 3 3 + 26 29 30 3 3 + 27 30 31 3 3 + 28 31 32 3 3 + 29 20 33 3 3 + 30 33 34 3 3 + 31 34 35 3 3 + 32 35 36 3 3 + 33 8 3 1 1 + 34 13 8 1 1 + 35 13 18 1 1 + 36 18 3 1 1 + 37 4 37 1 1 + 38 37 20 1 1 + 39 19 37 1 1 + 40 37 5 1 1 + 41 9 38 1 1 + 42 38 15 1 1 + 43 14 38 1 1 + 44 38 10 1 1 + 45 4 39 1 1 + 46 39 10 1 1 + 47 9 39 1 1 + 48 39 5 1 1 + 49 19 40 1 1 + 50 40 15 1 1 + 51 14 40 1 1 + 52 40 20 1 1 + 53 5 41 1 1 + 54 41 33 1 1 + 55 20 41 1 1 + 56 41 21 1 1 + 57 10 42 1 1 + 58 42 29 1 1 + 59 15 42 1 1 + 60 42 25 1 1 + 61 5 43 1 1 + 62 43 25 1 1 + 63 10 43 1 1 + 64 43 21 1 1 + 65 20 44 1 1 + 66 44 29 1 1 + 67 15 44 1 1 + 68 44 33 1 1 + 69 21 45 1 1 + 70 45 34 1 1 + 71 33 45 1 1 + 72 45 22 1 1 + 73 25 46 1 1 + 74 46 30 1 1 + 75 29 46 1 1 + 76 46 26 1 1 + 77 21 47 1 1 + 78 47 26 1 1 + 79 25 47 1 1 + 80 47 22 1 1 + 81 33 48 1 1 + 82 48 30 1 1 + 83 29 48 1 1 + 84 48 34 1 1 + 85 22 49 1 1 + 86 49 35 1 1 + 87 34 49 1 1 + 88 49 23 1 1 + 89 26 50 1 1 + 90 50 31 1 1 + 91 30 50 1 1 + 92 50 27 1 1 + 93 22 51 1 1 + 94 51 27 1 1 + 95 26 51 1 1 + 96 51 23 1 1 + 97 34 52 1 1 + 98 52 31 1 1 + 99 30 52 1 1 + 100 52 35 1 1 + 101 24 53 4 4 + 102 28 54 4 4 + 103 32 56 4 4 + 104 36 55 4 4 + 105 58 1 5 5 + 106 57 16 5 5 + 107 60 6 5 5 + 108 59 11 5 5 + 109 62 58 6 6 + 110 61 57 6 6 + 111 64 60 6 6 + 112 63 59 6 6 +------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table for circular-tubular elements] ------------------------ + 6 NPropSets - Number of structurally unique x-sections (i.e. how many groups of X-sectional properties are utilized throughout all of the members) +PropSetID YoungE ShearG MatDens XsecD XsecT + (-) (N/m2) (N/m2) (kg/m3) (m) (m) + 1 2.10000e+11 8.07690e+10 7850.00 0.800000 0.020000 + 2 2.10000e+11 8.07690e+10 7850.00 1.200000 0.050000 + 3 2.10000e+11 8.07690e+10 7850.00 1.200000 0.035000 + 4 2.10000e+11 8.07690e+10 7850.00 1.200000 0.040000 + 5 2.10000e+11 8.07690e+10 3339.12 2.082000 0.491000 + 6 2.10000e+11 8.07690e+10 7850.00 2.082000 0.060000 +------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below]- 0 NXPropSets - Number of structurally unique non-circular x-sections (if 0 the following table is ignored) +PropSetID YoungE ShearG MatDens XsecA XsecAsx XsecAsy XsecJxx XsecJyy XsecJ0 + (-) (N/m2) (N/m2) (kg/m3) (m2) (m2) (m2) (m4) (m4) (m4) +-------------------------- CABLE PROPERTIES ------------------------------------- + 0 NCablePropSets - Number of cable cable properties +PropSetID EA MatDens T0 + (-) (N) (kg/m) (N) +----------------------- RIGID LINK PROPERTIES ------------------------------------ + 0 NRigidPropSets - Number of rigid link properties +PropSetID MatDens + (-) (kg/m) +---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ + 0 NCOSMs - Number of unique cosine matrices (i.e., of unique member alignments including principal axis rotations); ignored if NXPropSets=0 or 9999 in any element below +COSMID COSM11 COSM12 COSM13 COSM21 COSM22 COSM23 COSM31 COSM32 COSM33 + (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) +------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- + 0 NCmass - Number of joints with concentrated masses; Global Coordinate System +CMJointID JMass JMXX JMYY JMZZ + (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) +---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ +True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. IT can also … +False OutCOSM - Output cosine matrices with the selected output member forces (flag) +False OutAll - [T/F] Output all members' end forces + 1 OutSwtch - [1/2/3] Output requested channels to: 1=.SD.out 2=.out (generated by FAST) 3=both files. +True TabDelim - Generate a tab-delimited output in the .SD.out file + 1 OutDec - Decimation of output in the .SD.out file +"ES11.4e2" OutFmt - Output format for numerical results in the .SD.out file +"A11" OutSFmt - Output format for header strings in the .SD.out file +------------------------- MEMBER OUTPUT LIST ------------------------------------------ + 8 NMOutputs - Number of members whose forces/displacements/velocities/accelerations will be output (-) [Must be <= 9]. +MemberID NOutCnt NodeCnt [NOutCnt=how many nodes to get output for [< 10]; NodeCnt are local ordinal numbers from the start of the member, and must be >=1 and … + (-) (-) (-) + 22 1 3 + 30 1 3 + 73 1 3 + 83 1 3 + 41 2 2 3 + 51 2 2 3 + 6 1 3 + 14 1 3 +------------------------- SDOutList: The next line(s) contains a list of output parameters that will be output in .SD.out or .out. ------ +"M1N1FKZe, M2N1FKZe" - Axial force in leg 2 at K1L2 and in leg 4 at K1L4 +"M3N1TDXss, M3N1TDYss, M3N1TDZss, M4N1TDXss, M4N1TDYss, M4N1TDZss" - Deflections at X2S2, X2S3: use cosdir matrix to get Out-of-plane (OOP) deflection +"M5N2TDXss, M5N2TDYss, M5N2TDZss, M6N2TDXss, M6N2TDYss, M6N2TDZss" - Deflections at X4S2, X4S3: use cosdir matrix to get OOP deflection +"M5N1FKXe,M5N1FKYe,M5N1FKZe,M6N1FKXe,M6N1FKYe,M6N1FKZe" - Forces OOP and Axial at mid brace points x,y, z >> *we will need to do some post-processing "M7N1FKZe, M8N1FKZe" - Axial force in leg 2 and leg 4 at mudbrace level: MudbraceL2, MudbraceL4 +"-ReactFXss, -ReactFYss, -ReactMXss, -ReactMYss, -ReactMZss, -ReactFZss" - Base reactions: fore-aft shear, side-to-side shear, side-to-side moment, fore-aft moment, … +END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line) diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_SSI.txt b/docs/source/user/subdyn/examples/OC4_Jacket_SD_SSI.txt new file mode 100644 index 000000000..86e6875ee --- /dev/null +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_SSI.txt @@ -0,0 +1,23 @@ +!---------------- Pile Head K and M elements -------------------! +!Equivalent Stiffness Constants: Kxx, Kyy, Kzz, Kxtx, Kxty..Kztx,Kzty,Kztz in any order; max 21 elements +-1.98E+09 Kxty +-6.83E-02 Kyty +0.00E+00 Kzty +-2.73E-01 Ktxty +1.35E+10 Ktyty +0.00E+00 Kxtz +0.00E+00 Kytz +0.00E+00 Kztz +0.00E+00 Ktxtz +0.00E+00 Ktytz +7.00E+08 Ktztz +5.04E+08 Kxx +3.11E-02 Kxy +5.06E+08 Kyy +0.00E+00 Kxz +0.00E+00 Kyz +2.54E+09 Kzz +6.83E-02 Kxtx +1.99E+09 Kytx +0.00E+00 Kztx +1.35E+10 Ktxtx \ No newline at end of file diff --git a/docs/source/user/subdyn/figs/element-CS.png b/docs/source/user/subdyn/figs/element-cs.png similarity index 100% rename from docs/source/user/subdyn/figs/element-CS.png rename to docs/source/user/subdyn/figs/element-cs.png diff --git a/docs/source/user/subdyn/future_work.rst b/docs/source/user/subdyn/future_work.rst index 63e4f2325..feb963d2f 100644 --- a/docs/source/user/subdyn/future_work.rst +++ b/docs/source/user/subdyn/future_work.rst @@ -1,4 +1,4 @@ -.. _future-work: +.. _sd_future-work: Known Limitations and Future Work ================================= diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst index ea27764bd..6189b9550 100644 --- a/docs/source/user/subdyn/input_files.rst +++ b/docs/source/user/subdyn/input_files.rst @@ -1,4 +1,4 @@ -.. _input-files: +.. _sd_input-files: Input Files =========== @@ -22,7 +22,7 @@ Units SubDyn uses the SI system (kg, m, s, N). Angles are assumed to be in radians unless otherwise specified. -.. _driver-input-file: +.. _sd_driver-input-file: SubDyn Driver Input File ------------------------- @@ -33,8 +33,8 @@ necessary to control the simulation for uncoupled models. It is possible to provide per-time-step inputs to SubDyn, even in stand-alone mode, by tying the driver file to an additional input file containing time-histories of the TP motion (displacements, velocities, and -accelerations). A sample SubDyn driver input file is given in Appendix -B. +accelerations). A sample SubDyn driver input file is given in +:numref:`sd_appendix_B`. Users can set the **Echo** flag in this file to TRUE so that *SubDyn\_win32.exe* echoes the contents of the driver input file (useful @@ -105,7 +105,7 @@ Table 1. TP Reference Point Inputs Time-Series Data File Contents | 17-19 | TP reference point rotational accelerations about *X*, *Y*, and *Z* | `rad/s^2` | +-----------------+-------------------------------------------------------------------------------------------------------+------------------------------------------+ -.. _main-input-file: +.. _sd_main-input-file: SubDyn Primary Input File ------------------------- @@ -140,7 +140,7 @@ If this manual refers to an ID in a table entry, it is an integer identifier for the table entry and must be unique for a given table entry. -A sample SubDyn primary input file is given in Appendix A. +A sample SubDyn primary input file is given in :numref:`sd_appendix_A`. The input file begins with two lines of header information, which is for the user but is not used by the software. @@ -176,6 +176,11 @@ minimize the number of retained modes needed to capture effects such as static gravity and buoyancy loads, and high-frequency loads transferred from the turbine. + +**ExtraMoment** is a flag to specify whether the extra moment due to +the interface lever arm is to be included in the interface reactions. + + FEA and Craig-Bampton Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -209,8 +214,18 @@ line, separated by white space. If the number of **JDampings** is less than the number of retained modes, the last value will be replicated for all the remaining modes. + +**GuyanDampMod** Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] + +**RayleighDamp** Mass and stiffness proportional damping coefficients (:math:`(\alpha,\beta)` Rayleigh damping) [only if GuyanDampMod=1] +Guyan damping matrix (6x6) [only if GuyanDamgMod=2] + +**Guyan damping matrix**: The 6 lines following this input line consits of the + 6x6 coefficients of the damping matrix to be applied at the interface. + + For more information on these parameters and guidelines on how to set -them, see Sections 5 and 6. +them, see Sections :numref:`sd_modeling-considerations` and :numref:`subdyn-theory`. Structure Joints ~~~~~~~~~~~~~~~~ @@ -449,7 +464,7 @@ lines of channel names. Modal kinematics and member-node-, base-, and interface-related kinematic and load quantities can be selected. Member-node-related data follow the organization described in Section . If SubDyn encounters an unknown/invalid channel name, it prints an error -message and halts execution. Please refer to Appendix C for a complete +message and halts execution. Please refer to :numref:`sd_appendix_C` for a complete list of possible output parameters and their names. SSI Input File @@ -487,4 +502,4 @@ Note that by selecting fixities of 1 in the various DOFs of the restrained nodes, the columns and rows associated with those DOFs will be removed, therefore the associated matrix elements will be ignored. -A sample SubDyn SSI input file is given in Appendix C. +A sample SubDyn SSI input file is given in :numref:`sd_appendix_C`. diff --git a/docs/source/user/subdyn/introduction.rst b/docs/source/user/subdyn/introduction.rst index fff4932c1..f86691ab4 100644 --- a/docs/source/user/subdyn/introduction.rst +++ b/docs/source/user/subdyn/introduction.rst @@ -31,7 +31,7 @@ frame finite-element beam model (LFEB), and (2) a dynamics system reduction via the Craig-Bampton(C-B) method, together with a static-improvement method (SIM), greatly reducing the number of modes needed to obtain an accurate solution. More details can be found in -Section 6, and in :cite:`song2013, damiani2013, damiani2013omae`. +Section 6, and in :cite:`song2013`, :cite:`damiani2013`, :cite:`damiani2013omae`. In SubDyn, the substructure is considered to be either clamped or supported by springs at the seabed, and rigidly connected to the @@ -67,7 +67,7 @@ can calculate member internal reaction loads, as requested by the user (see Figure 1). -.. _flow-chart: +.. _sd_flow-chart: .. figure:: figs/flowchart.png :width: 100% @@ -109,14 +109,14 @@ flooding/ballasting of the members can be specified. This document is organized as follows. Section :ref:`running-subdyn` details how to obtain the SubDyn and FAST software archives and run either the stand-alone -version of SubDyn or SubDyn coupled to FAST. Section :ref:`input-files` describes the -SubDyn input files. Section 4 discusses the :ref:`output-files` generated by +version of SubDyn or SubDyn coupled to FAST. Section :ref:`sd_input-files` describes the +SubDyn input files. Section 4 discusses the :ref:`sd_output-files` generated by SubDyn; these include echo files, a summary file, and the results file. Section 5 provides modeling guidance when using SubDyn. The SubDyn -theory is covered in Section :ref:`subdyn-theory`. Section :ref:`future-work` outlines future work, and +theory is covered in Section :ref:`subdyn-theory`. Section :ref:`sd_future-work` outlines future work, and Section 8 contains a list of references. Example input files are shown -in Appendices :numref:`sd_input_files` and B. A summary of available output channels are found -in Appendix :ref:`app-output-channel`. Instructions for compiling the stand-alone SubDyn program +in Appendices :numref:`sd_appendix_A` and B. A summary of available output channels are found +in Appendix :ref:`sd_appendix_D`. Instructions for compiling the stand-alone SubDyn program are detailed in Appendix D. Appendix E tracks the major changes that have been made to SubDyn for each public release. diff --git a/docs/source/user/subdyn/modeling.rst b/docs/source/user/subdyn/modeling.rst index 92f059ebe..08ed62abb 100644 --- a/docs/source/user/subdyn/modeling.rst +++ b/docs/source/user/subdyn/modeling.rst @@ -1,4 +1,4 @@ -.. _modeling-considerations: +.. _sd_modeling-considerations: Modeling Considerations ======================= @@ -113,7 +113,7 @@ choice of these parameters as they may render the system matrix singular. Inspection of the eigenvalue results in the summary file should confirm whether acceptable approximations have been achieved. -.. _TowerTurbineCpling +.. _TowerTurbineCpling: Substructure Tower/Turbine Coupling ----------------------------------- @@ -182,6 +182,17 @@ and inertia in ElastoDyn can be used to model heavy and rigid transition pieces that one would not want to model as a flexible body in either the ElastoDyn tower or SubDyn substructure models. +***Damping of the Guyan modes:*** + +There are three ways to specify the damping associated with the motion +of the interface node. + +1. SubDyn Guyan damping matrix using Rayleigh damping +2. SubDyn Guyan damping matrix using user defined 6x6 matrix +3. HydroDyn additional linear damping matrix (**AddBLin**) + +**Old:** + The C-B method assumes no damping for the interface modes. This is equivalent to having six undamped rigid-body DOFs at the TP reference point in the absence of aerodynamic or hydrodynamic damping. Experience diff --git a/docs/source/user/subdyn/notations.rst b/docs/source/user/subdyn/notations.rst deleted file mode 100644 index 2ef73db04..000000000 --- a/docs/source/user/subdyn/notations.rst +++ /dev/null @@ -1,670 +0,0 @@ - -.. contents:: - :depth: 3 -.. - -**NOTICE** - -This report was prepared as an account of work sponsored by an agency of -the United States government. Neither the United States government nor -any agency thereof, nor any of their employees, makes any warranty, -express or implied, or assumes any legal liability or responsibility for -the accuracy, completeness, or usefulness of any information, apparatus, -product, or process disclosed, or represents that its use would not -infringe privately owned rights. Reference herein to any specific -commercial product, process, or service by trade name, trademark, -manufacturer, or otherwise does not necessarily constitute or imply its -endorsement, recommendation, or favoring by the United States government -or any agency thereof. The views and opinions of authors expressed -herein do not necessarily state or reflect those of the United States -government or any agency thereof. - - | This report is available at no cost from the National Renewable - Energy - | Laboratory (NREL) at www.nrel.gov/publications. - - Available electronically at http://www.osti.gov/scitech - - | Available for a processing fee to U.S. Department of Energy - | and its contractors, in paper, from: - - | U.S. Department of Energy - | Office of Scientific and Technical Information - - | P.O. Box 62 - | Oak Ridge, TN 37831-0062 - | phone: 865.576.8401 - | fax: 865.576.5728 - | email: - `mailto:reports@adonis.osti.gov `__ - - Available for sale to the public, in paper, from: - - | U.S. Department of Commerce - | National Technical Information Service - | 5285 Port Royal Road - | Springfield, VA 22161 - | phone: 800.553.6847 - | fax: 703.605.6900 - | email: orders@ntis.fedworld.gov - | online ordering: http://www.ntis.gov/help/ordermethods.aspx - - *Cover Photos: (left to right) photo by Pat Corkery, NREL 16416, - photo from SunEdison, NREL 17423, photo by Pat Corkery, NREL 16560, - photo by Dennis Schroeder, NREL 17613, photo by Dean Armstrong, NREL - 17436, photo by Pat Corkery, NREL 17721.* - -|Recycle Logo| Printed on paper containing at least 50% wastepaper, -including 10% post consumer waste. - -Preface - -This manual offers both a quick reference guide and a more in-depth -theory guide for the SubDyn software program. It is intended to be used -by the general user in combination with the FAST and HydroDyn manuals. -The manual will be updated as new releases are issued and as needed to -provide further information on advancements or modifications to the -software. - -** -** - -Acknowledgments - -The authors would like to acknowledge Huimin Song, a post-doctoral -researcher at the National Renewable Energy Laboratory, for her -contribution to the development of SubDyn. Amy Robertson and Fabian -Wendt provided helpful feedback on the document, and Braulio Barahona -produced some of the graphics. We also are grateful to the U.S. -Department of Energy Wind and Water Power Program for supporting the -development of this software. - -Nomenclature - -:math:`\zeta` Damping ratio (percent of critical) or diagonal damping -matrix - -:math:`\omega` Eigenfrequency - -:math:`\rho` Material density - -:math:`\Phi_{L}` *L*\ ×\ *L* matrix representing the C-B eigenmodes - -:math:`\Phi_{m}` *L*\ ×\ *m* matrix representing the retained C-B -eigenmodes - -:math:`\Phi_{R}` *L*\ ×\ *R* matrix representing the interior nodal -displacements for a static, rigid-body motion of the boundary nodes - -:math:`{\bar{\Phi}}_{R}` Matrix representing the interior nodal -displacements for a static, rigid-body motion of the boundary nodes, -after the restrained degrees of freedoms are removed - -:math:`\Omega_{L}` *L*\ ×\ *L* diagonal matrix representing the -eigenfrequencies of all C-B eigenmodes - -:math:`\Omega_{m}` *m*\ ×\ *m* diagonal matrix representing the -eigenfrequencies of the retained C-B eigenmodes - -ν Poisson’s ratio - -*A* State matrix in state-space state equation - -AF Apparent fixity - -:math:`A_{\text{sx}}` Member shear area along local *x*-axis - -:math:`A_{\text{sy}}` Member shear area along local *y*-axis - -:math:`A_{z}` Member cross-sectional area, normal to local *z*-axis - -*B* Input matrix in state-space state equation - -C-B Craig Bampton - -:math:`C` System damping matrix - -:math:`C_{1}` State matrix in state-space output equation for ElastoDyn - -:math:`C_{2}` State matrix in state-space output equation for HydroDyn - -:math:`C_{\text{LL}}` Damping matrix partition referred to the *L* -interior degrees of freedom (*L*\ ×\ *L*) - -:math:`C_{\text{LR}}` Damping matrix partition referred to the *L* and -*R* degrees of freedom (*L*\ ×\ *R*) - -:math:`C_{\text{RL}}` Damping matrix partition referred to the *R* and -*L* boundary degrees of freedom (*R*\ ×\ *L*) - -:math:`C_{\text{RR}}` Damping matrix partition referred to the *R* -boundary degrees of freedom (*R*\ ×\ *R*) - -:math:`C_{33}^{\left( \text{HD} \right)}` HydroDyn’s linear damping -matrix heave element - -:math:`\text{dt}` Time step in the integration algorithm - -:math:`dt_{\max}` Maximum time-step recommended - -*D\ i* Member inner diameter - -*D\ o* Member outer diameter - -:math:`D_{1}` Input transmission matrix in state-space output equation -for ElastoDyn - -:math:`D_{2}` Input transmission matrix in state-space output equation -for HydroDyn - -DOF Degree of freedom - -:math:`\left\lbrack D_{C} \right\rbrack` Member direction cosine 3x3 -matrix, transforming local coordinates to global coordinates - -*E* Young’s modulus - -*f* Frequency - -:math:`f_{\max}` Maximum frequency - -*F* Vector of external forces and moments - -:math:`F_{G}` Array of self-weight forces and moments - -:math:`F_{L}` Array of external (hydrodynamic) forces and moments at the -interior nodes - -:math:`{\widetilde{F}}_{L}` Interior forces and moments (*L*\ ×1) array -accounting for all interior modes -=\ :math:`\Phi_{L}^{T}\left( F_{L} + F_{\text{Lg}} \right)` - -:math:`F_{\text{Lg}}` Array of self-weight gravity forces and moments at -the interior nodes - -:math:`{\widetilde{F}}_{m}` Interior forces and moments (*L*\ ×1) array -accounting for only the retained modes -=\ :math:`\Phi_{m}^{T}\left( F_{L} + F_{\text{Lg}} \right)` - -:math:`F_{R}` Array of external (hydrodynamic) forces and moments at the -boundary nodes - -:math:`{\bar{F}}_{R}` Array of external (hydrodynamic) forces and -moments at the interface nodes - -:math:`F_{\text{Re}a\text{ct}}` Substructure base reaction forces and -moments, applied to the substructure by the restraint - -:math:`F_{\text{Rg}}` Array of self-weight forces and moments at the -boundary nodes - -:math:`{\bar{F}}_{\text{Rg}}` Array of self-weight forces and moments at -the interface nodes - -:math:`F_{\text{TP}}` TP reaction forces and moments, applied to the -substructure by the remainder of the turbine system - -:math:`{\widetilde{F}}_{\text{TP}}` TP forces and moments after C-B -reduction, = -:math:`F_{\text{TP}} + T_{I}^{T}{\bar{F}}_{\text{Rg}} + T_{I}^{T}{\bar{\Phi}}_{R}^{T}\left( F_{L} + F_{\text{Lg}} \right)` - -*F\ X* Substructure base reaction force along global *X*-axis; or - -forcing vector in state-space state equation - -*F\ Y* Substructure base reaction force along global *Y*-axis - -*F\ Y1* Forcing vector in state-space output equation for ElastoDyn - -*F\ Y2* Forcing vector in state-space output equation for HydroDyn - -*F\ Z* Substructure base reaction force along global *Z*-axis - -:math:`F_{I}^{e}` Element inertia forces - -:math:`F_{S}^{e}` Element static forces - -FEA Finite-element analysis - -FEM Finite-element method - -:math:`g` Gravity, unsigned magnitude - -*G* Shear modulus - -:math:`i` Member or element index - -:math:`{\widehat{i}}_{e}` Unit vector along the element local *x*-axis - -:math:`I` Identity matrix - -:math:`\widehat{I}` Unit vector along the global *X*-axis - -:math:`{\widehat{j}}_{e}` Unit vector along the element local *y*-axis - -:math:`J` Generic second area moment of inertia - -:math:`\widehat{J}` Unit vector along the global *Y*-axis - -:math:`J_{x}` Second area moment of inertia about the local, principal -*x*-axis - -:math:`J_{\text{xx}}` Second area moment of inertia about the local -*x*-axis - -:math:`k` Element stiffness matrix (12x12) in global coordinate system - -:math:`k_{e}` Element stiffness matrix (12x12) - -:math:`{\widehat{k}}_{e}` Unit vector along the element local *z*-axis - -:math:`k_{\text{ax}}` Shear area factor along local *x*-axis - -:math:`k_{\text{ay}}` Shear area factor along local *y*-axis - -:math:`K` System stiffness matrix - -:math:`\widehat{K}` Unit vector along the global *Z*-axis - -:math:`K_{\text{BB}}` Matrix partition after C-B system reduction = -:math:`K_{\text{RR}} + K_{\text{RL}}\Phi_{R}` - -:math:`{\bar{K}}_{\text{BB}}` :math:`K_{\text{BB}}` after removal of -constrained DOF rows and columns - -:math:`{\widetilde{K}}_{\text{BB}}` Substructure equivalent stiffness -matrix referred to the TP reference point, = -:math:`T_{I}^{T}{\bar{K}}_{\text{BB}}T_{I}` - -:math:`K_{\text{LL}}` Stiffness matrix partition referred to the *L* -interior DOFs (*L*\ ×\ *L*) - -:math:`K_{\text{LR}}` Stiffness matrix partition referred to the *L* and -*R* DOFs (*L*\ ×\ *R*) - -:math:`K_{\text{RL}}` Stiffness matrix partition referred to the *R* and -*L* boundary DOFs (*R*\ ×\ *L*) - -:math:`K_{\text{RR}}` Stiffness matrix partition referred to the R -boundary DOFs (*R*\ ×\ *R*) - -:math:`K_{\text{sx}}` Shear correction factor along local *x*-axis - -:math:`K_{\text{sy}}` Shear correction factor along local *y*-axis - -:math:`K_{33}^{\left( \text{SD} \right)}` Substructure equivalent heave -stiffness - -*L* Interior nodes’ DOFs - -LFEB Linear frame finite-element beam model - -:math:`L_{e}` Length of element - -:math:`L_{\text{exy}}` Length of element projection in the global *XY* -plane - -:math:`m_{e}` Element stiffness matrix (12x12) - -:math:`m` Element stiffness matrix (12x12) in global coordinate system; -or - -number of retained C-B modes - -:math:`M` System mass matrix - -MSL Mean sea level - -:math:`M_{\text{BB}}` Matrix partition after C-B system reduction = -:math:`M_{\text{RR}} + M_{\text{RL}}\Phi_{R} + \Phi_{R}^{T}M_{\text{LR}} + \Phi_{R}^{T}M_{\text{LL}}\Phi_{R}` - -:math:`{\bar{M}}_{\text{BB}}` :math:`M_{\text{BB}}` after removal of -constrained DOF rows and columns - -:math:`{\widetilde{M}}_{\text{BB}}` Substructure equivalent mass matrix -referred to the TP reference point = -:math:`T_{I}^{T}{\bar{M}}_{\text{BB}}T_{I}` - -:math:`M_{\text{Bm}}` Matrix partition after C-B system reduction = -:math:`M_{\text{mB}}^{T}` - -:math:`{\bar{M}}_{\text{Bm}}` :math:`M_{\text{Bm}}` after removal of -constrained DOF rows and columns - -:math:`{\widetilde{M}}_{\text{Bm}}` Matrix partition = -:math:`T_{I}^{T}{\bar{M}}_{\text{Bm}}` - -:math:`M_{\text{LL}}` Mass matrix partition referred to the *L* interior -DOFs (*L*\ ×\ *L*) - -:math:`M_{\text{LR}}` Mass matrix partition referred to the *L* and *R* -DOFs (*L*\ ×\ *R*) - -:math:`M_{\text{mB}}` Matrix partition after C-B system reduction = -:math:`\Phi_{m}^{T}M_{\text{LR}} + \Phi_{m}^{T}M_{\text{LL}}\Phi_{R}` - -:math:`{\widetilde{M}}_{\text{mB}}` Matrix partition = -:math:`{\widetilde{M}}_{\text{Bm}}^{T}` - -:math:`M_{\text{RL}}` Mass matrix partition referred to the *R* and *L* -boundary DOFs (*R*\ ×\ *L*) - -:math:`M_{\text{RR}}` Mass matrix partition referred to the *R* boundary -DOFs (*R*\ ×\ *R*) - -*M\ X* Substructure base reaction moment along global *X*-axis - -*M\ Y* Substructure base reaction moment along global *Y*-axis - -*M\ Z* Substructure base reaction moment along global *Z*-axis - -:math:`M^{\left( \text{ED} \right)}` 6x6 mass matrix from ElastoDyn - -:math:`M_{33}^{(SD)}` Substructure equivalent heave mass - -:math:`n` The n\ :sup:`th` time step - -:math:`\text{NIN}` Number of interface nodes - -:math:`N_{\text{react}}` Number of restrained nodes - -*p* State-space parameters - -:math:`q_{L}` Modal coefficients for all interior nodes’ DOF modes - -:math:`q_{L0}` Modal coefficients for all interior nodes’ DOF modes -assumed operating in static fashion - -:math:`q_{m}` Modal coefficients for the retained modes - -:math:`q_{m0}` Modal coefficients for the retained modes assumed -operating in static fashion - -*R* Boundary nodes’ DOFs - -:math:`\overrightarrow{R}` Reaction forces at the base of the -substructure - -*SSI* Soil-structure interaction - -:math:`t` time; or - -thickness - -TP Transition piece - -:math:`T_{I}` Matrix to transform interface nodes’ DOFs to TP DOFs; -:math:`\left( 6 \cdot \text{NIN} \right) \times 6` matrix - -:math:`T_{\text{react}}` Auxiliary matrix -(:math:`6x(6 \cdot N_{\text{react}})`) to link restrained nodes’ forces -and moments to the substructure base reaction vector - -*u, u\ i* State-space formulation inputs, generic i-th input - -:math:`U` Vector of nodal displacements - -:math:`U_{e}` Vector of element nodes’ displacements (DOFs) - -:math:`U_{L}` Vector of interior nodes’ displacements (DOFs) - -:math:`{\widehat{U}}_{L}` Time-varying components of the interior nodes’ -displacements (DOFs) - -:math:`U_{L0}` Static components of the interior nodes’ displacements -(DOFs) (*L*\ ×1) - -:math:`U_{L0m}` Static components of the interior nodes’ displacements -(DOFs) (*L*\ ×1), but obtained considering the first *m* C-B eigenmodes -only - -:math:`U_{R}` Vector of boundary nodes’ displacements (DOFs) - -:math:`{\bar{U}}_{R}` Vector of interface nodes’ displacements (DOFs) - -:math:`U^{e}` Element nodes’ displacements (DOFs) - -:math:`{\widehat{U}}^{e}` Time-varying components of the element nodes’ -displacements (DOFs) - -:math:`U_{L0}^{e}` Static components of the element nodes’ displacements -(DOFs) - -:math:`U_{L0m}^{e}` Static components of the element nodes’ -displacements (DOFs), but obtained considering the first *m* C-B -eigenmodes only - -:math:`U_{\text{TP}}` TP reference point displacements (DOFs) - -:math:`{\widehat{U}}_{\text{TP}}` Time-varying components of the TP -reference point displacements (DOFs) - -:math:`U_{TP0}` Static components of the TP reference point -displacements (DOFs) - -*x, x*\ :sub:`i` State-space formulation states, generic i-th state; or - -generic local *x*-coordinate - -:math:`x_{e}` Element local *x*-coordinates - -*X* Global or substructure coordinate; or - -state-space state equation(s) - -:math:`X_{E}` Member end node *X*-coordinate in global coordinate system - -:math:`X_{S}` Member start node *X*-coordinate in global coordinate -system - -:math:`X_{\text{INi}}` *X*-coordinate in global coordinate system of the -generic interface node - -*X\ SS* Global or substructure coordinate - -:math:`X_{\text{TP}}` TP reference point *X*-coordinate in global -coordinate system - -*y, y\ i* State-space formulation outputs, generic i-th output; or - -generic *y*-coordinate - -:math:`y_{e}` Element local *y*-coordinates - -*Y* Global or substructure coordinates; or - -state-space output equation(s) - -:math:`Y_{E}` Member end node *Y*-coordinate in global coordinate system - -:math:`Y_{\text{INi}}` *Y*-coordinate in global coordinate system of the -generic interface node - -:math:`Y_{S}` Member start node *Y*-coordinate in global coordinate -system - -*Y\ SS* Global or substructure coordinates - -:math:`Y_{\text{TP}}` TP reference point *Y*-coordinate in global -coordinate system - -*Y\ 1* State-space output equation for ElastoDyn - -*Y\ 2* State-space output equation for HydroDyn - -:math:`z_{e}` Element local *z*-coordinate - -*Z* Global or substructure coordinate - -:math:`Z_{E}` Member end node *Z*-coordinate in global coordinate system - -:math:`Z_{\text{INi}}` *Z*-coordinate in global coordinate system of the -generic interface node - -:math:`Z_{S}` Member start node *Z*-coordinate in global coordinate -system - -*Z\ SS* Global or substructure coordinate - -:math:`Z_{\text{TP}}` TP reference point *Z*-coordinate in global -coordinate system - -Table of Contents - -`Preface 4 <#_Toc413741142>`__ - -`Acknowledgments 5 <#_Toc413741143>`__ - -`Nomenclature 6 <#_Toc413741144>`__ - -`1 Introduction 14 <#_Toc401565516>`__ - -`2 Running SubDyn 17 <#_Ref391919518>`__ - -`2.1 Downloading the SubDyn Software 17 <#_Toc381965029>`__ - -`2.1.1 Stand-Alone SubDyn Archive 17 <#_Toc401565519>`__ - -`2.1.2 FAST Archive 17 <#_Toc401565520>`__ - -`2.2 Running SubDyn 18 <#_Toc413741150>`__ - -`2.2.1 Running the Stand-Alone SubDyn Program 18 <#_Toc413741151>`__ - -`2.2.2 Running SubDyn Coupled to FAST 18 <#_Toc382336008>`__ - -`3 Input Files 19 <#_Ref391919668>`__ - -`3.1 Units 19 <#_Toc401565524>`__ - -`3.2 SubDyn Driver Input File 19 <#_Toc381965070>`__ - -`3.3 SubDyn Primary Input File 20 <#_Ref382059081>`__ - -`3.3.1 Simulation Controls 21 <#_Toc401565527>`__ - -`3.3.2 FEA and Craig-Bampton Parameters 21 <#_Toc401565528>`__ - -`3.3.3 Structure Joints 22 <#_Toc401565529>`__ - -`3.3.4 Base Reaction Joints 22 <#_Toc401565530>`__ - -`3.3.5 Interface Joints 23 <#_Toc401565531>`__ - -`3.3.6 Members 23 <#_Ref391919995>`__ - -`3.3.7 Member Cross-Section Properties 23 <#_Toc519676721>`__ - -`3.3.8 Member Cosine Matrices COSM (i,j) 24 <#_Ref393270930>`__ - -`3.3.9 Joint Additional Concentrated Masses 24 <#_Ref393289423>`__ - -`3.3.10 Output: Summary and Outfile 24 <#_Toc401565536>`__ - -`3.3.11 Member Output List 25 <#_Ref393272400>`__ - -`3.3.12 Output Channels- SDOutList Section 25 <#_Toc401565538>`__ - -`4 Output Files 26 <#_Ref391919685>`__ - -`4.1 Echo Files 26 <#_Toc401565540>`__ - -`4.2 Summary File 26 <#_Ref391920238>`__ - -`4.3 Results File 27 <#_Toc401565542>`__ - -`5 Modeling Considerations 28 <#_Toc381965090>`__ - -`5.1 Model Discretization 28 <#_Toc401565544>`__ - -`5.2 Foundations 29 <#_Toc413741175>`__ - -`5.3 Member Overlap 29 <#_Toc413741176>`__ - -`5.4 Substructure Tower/Turbine Coupling 29 <#_Ref413052060>`__ - -`5.5 Self-Weight Calculations 31 <#_Toc401565546>`__ - -`5.6 Note On Other Load Calculations 31 <#_Toc413741179>`__ - -`5.7 Craig-Bampton Guidelines 31 <#_Ref391971454>`__ - -`5.8 Integration Time Step Guidelines 32 <#_Ref399231319>`__ - -`6 SubDyn Theory 33 <#_Ref394401650>`__ - -`6.1 Overview 33 <#_Toc401565550>`__ - -`6.2 Integration with the FAST Modularization Framework -34 <#_Toc401565551>`__ - -`6.3 Coordinate Systems 35 <#_Toc401565552>`__ - -`6.3.1 Global and Substructure Coordinate System: or ( Figure 4) -36 <#_Toc401565553>`__ - -`6.3.2 Member or Element Local Coordinate System (Figure 5) -36 <#_Toc401565554>`__ - -`6.3.3 Local to Global Transformation 37 <#_Toc401565555>`__ - -`6.4 Linear Finite-Element Beam Model 38 <#_Toc401565556>`__ - -`6.4.1 Element Formulation 39 <#_Toc401565557>`__ - -`6.4.2 Self-Weight Loads 40 <#_Toc401565558>`__ - -`6.5 Dynamic System of Equations and C-B Reduction -42 <#_Toc401565559>`__ - -`6.5.1 State-Space Formulation 46 <#_Ref394398934>`__ - -`6.5.2 Member Force Calculation 48 <#_Toc401565561>`__ - -`6.5.3 Reaction Calculation 48 <#_Toc401565562>`__ - -`6.5.4 Time Integration 49 <#_Ref394398970>`__ - -`6.5.5 Static-Improvement Method 49 <#_Toc401565564>`__ - -`7 Known Limitations and Future Work 53 <#_Toc401565565>`__ - -`8 References 54 <#_Ref391919755>`__ - -`Appendix A. OC4 Jacket Input File (CertTest Test04) -55 <#_Toc401565567>`__ - -`Appendix B. OC4 Jacket Driver File 60 <#_Toc401565568>`__ - -`Appendix C. List of Output Channels 61 <#_Toc401565569>`__ - -`Appendix D. Compiling Stand-Alone SubDyn 63 <#_Toc401565570>`__ - -`Appendix E. Major Changes in SubDyn 64 <#_Toc401565571>`__ - -List of Figures - -`Figure 1. SubDyn, HydroDyn, and FAST 8 coupled interaction -15 <#_Ref408208410>`__ - -`Figure 2. WinZip Self-Extractor main window 17 <#_Toc413741206>`__ - -`Figure 3. SubDyn layout within the modularization framework -34 <#_Ref393719536>`__ - -`Figure 4. Global (coincident with the substructure) coordinate system. -Also shown are the DOFs associated with the TP reference point. -35 <#_Ref407623061>`__ - -`Figure 5. The element coordinate system. The sketched member contains -four elements, and the second element is called out with nodes S and E. -37 <#_Ref408218733>`__ - -List of Tables - -`Table 1. TP Reference Point Inputs Time-Series Data File Contents -20 <#_Toc401063869>`__ - -`Table C-1. List of Output Channels. 61 <#_Toc417640980>`__ - - diff --git a/docs/source/user/subdyn/output_files.rst b/docs/source/user/subdyn/output_files.rst index f9ea6cb36..f016ecfa1 100644 --- a/docs/source/user/subdyn/output_files.rst +++ b/docs/source/user/subdyn/output_files.rst @@ -1,4 +1,4 @@ -.. _output-files: +.. _sd_output-files: Output Files ============ @@ -21,7 +21,7 @@ file will be truncated if SubDyn encounters an error while parsing an input file. The error usually corresponds to the line after the last successfully echoed line. -.. _sum-file: +.. _sd_sum-file: Summary File ------------ diff --git a/docs/source/user/subdyn/references.bib b/docs/source/user/subdyn/references_SD.bib similarity index 81% rename from docs/source/user/subdyn/references.bib rename to docs/source/user/subdyn/references_SD.bib index 5f4faa028..a4f0e90fc 100644 --- a/docs/source/user/subdyn/references.bib +++ b/docs/source/user/subdyn/references_SD.bib @@ -24,8 +24,9 @@ @inproceedings{song2013 note = "https://www.nrel.gov/docs/fy15osti/63165.pdf" } -@inproceedings{jonkman2013, - author = "Jonkman, J.M.", +% NOTE: clash with beamdyn reference since sphinx will use [Jon13] for both +@inproceedings{jjonkman2013, + author = "JJonkman", title = "The New Modularization Framework for the {FAST} Wind Turbine {CAE} Tool.", month = "January 7 -- 10", year = "2013", @@ -33,7 +34,7 @@ @inproceedings{jonkman2013 address = "Grapevine, Texas" } -@inproceedings{Hurty1964, +@inproceedings{hurty1964, author = "Hurty, W.C.", title = "On the Dynamic Analysis of Structural Systems Using Component Modes", month = "June 29--July 2", @@ -52,18 +53,10 @@ @article{craig1968 pages = "1313 -- 1319" } -@inproceedings{damiani2013omae, - author = "Damiani, R. and Song, H. and Robertson, A. and Jonkman, J.", - title = "Assessing the Importance of Nonlinear Structural Characteristics in the Development of a Jacket Model for the Wind Turbine {CAE} Tool {FAST}", - month = "Jne 9--14", - year = "2013", - booktitle = "Proceedings of the 32nd International Conference on Ocean, Offshore and Arctic Engineering (OMAE2013)", - address = "Nantes, France" -} - +% NOTE: clashes with BeamDyn references @inproceedings{sprague2014, - author = "Sprague, M.A. and Jonkman, J.M. and Jonkman, B.J.", + author = "MSprague and Jonkman, J.M. and Jonkman, B.J.", title = "{FAST} Modular Wind Turbine {CAE} Tool: Nonmatching Spatial and Temporal Meshes", month = "January", year = "2014", @@ -116,4 +109,30 @@ @TECHREPORT{subdyn:manual year=2015 } +@article{damiani2013, + author={R. Damiani and H. Song}, + title={A Jacket Sizing Tool for Offshore Wind Turbines within the Systems Engineering Initiative}, + year=2013, + journal={Offshore Technology Conference}, + volume= 1, + number=1 +} +@article{damiani2013omae, + author={R. Damiani and H. Song and A. Robertson and J. Jonkman}, + title={Assessing the Importance of Nonlinear Structural Characteristics in the Development of a Jacket Model for the Wind Turbine CAE Tool FAST.}, + year=2013, + journal={32nd International Conference on Ocean, Offshore and Arctic Engineering}, + volume= 1, + number=1 +} + +@inproceedings{damiani2013omaeB, + author = "Damiani, R. and Song, H. and Robertson, A. and Jonkman, J.", + title = "Assessing the Importance of Nonlinear Structural Characteristics in the Development of a Jacket Model for the Wind Turbine {CAE} Tool {FAST}", + month = "Jne 9--14", + year = "2013", + booktitle = "Proceedings of the 32nd International Conference on Ocean, Offshore and Arctic Engineering (OMAE2013)", + address = "Nantes, France" +} + diff --git a/docs/source/user/subdyn/running_sd.rst b/docs/source/user/subdyn/running_sd.rst index d06081250..eb07718b9 100644 --- a/docs/source/user/subdyn/running_sd.rst +++ b/docs/source/user/subdyn/running_sd.rst @@ -16,53 +16,10 @@ need both forms, he/she would likely need to be familiar with and run the stand-alone model if building a model of the substructure from scratch. The stand-alone version is also helpful for model troubleshooting and may benefit users who are interested in conducting -aero-hydro-servo-elastic simulations of an offshore wind turbine. For -this reason, SubDyn can be obtained from two different repositories: one -for the stand-alone SubDyn and one for the coupled solution through -FAST. - -Stand-Alone SubDyn Archive -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Users can refer to :numref:`installation` download the stand-alone SubDyn archive from our Web server at -`*https://nwtc.nrel.gov/SubDyn* `__. The -file has a name similar to *SD\_v1.03.00a-rrd.exe*, but may have a -different version number. The user can then download the self-extracting -archive (.exe) to expand the archive into a folder he/she specifies. - -.. _self-extractor: - -.. figure:: figs/self-extractor.png - :width: 40% - - WinZip Self-Extractor main window --TO REPLACE WITH CURRENT -ARCHIVE METHODS ETC. - -The archive contains the **bin**, **CertTest**, **Compiling**, -**Documentation**, and **Source** folders. The **bin** folder -includes the main executable file, *SubDyn\_win32.exe*, which is used to -execute the stand-alone SubDyn program. The **CertTest** folder -contains a collection of sample SubDyn input files and driver input -files that can be used as templates for the user’s own models. If the -user runs the *CertTest.bat* DOS script, he/she can compare the results -to the ones stored in the **NREL\_Results** subfolder. This manual may -be found in the **Documentation** folder. The **Compiling** folder -contains files for compiling the stand-alone *SubDyn\_win32.exe* file -with either Visual Studio or gFortran. The Fortran source code is -located in the **Source** folder. - -FAST Archive -~~~~~~~~~~~~ - -Download the FAST archive, which includes a coupling to SubDyn, from our -Web server at https://nwtc.nrel.gov/FAST8. The file has a name similar -to *FAST\_v8.08.00.exe*, but may have a different version number. Run -the downloaded self-extracting archive (*.exe*) to expand the archive -into a user-specified folder. The FAST executable file is located in the -archive’s **bin** folder. Example models using the NREL 5-MW reference -turbine and various substructures are located in the **CertTest** -folder. These include Test19: OC3-Monopile, Test20: OC3-Tripod, Test21: -OC4-jacket. +aero-hydro-servo-elastic simulations of an offshore wind turbine. + +Users can refer to the OpenFAST installation to download and compile SubDyn. + Running SubDyn --------------- @@ -88,8 +45,8 @@ for example: >SubDyn_win32.exe MyDriverFile.dvr where, *MyDriverFile.dvr* is the name of the SubDyn driver file, as -described in Section :numref:`main-input-file`. The SubDyn primary input file is described in -Section :numref:`driver-input-file`. +described in :numref:`sd_main-input-file`. The SubDyn primary input file is described in +Section :numref:`sd_driver-input-file`. Running SubDyn Coupled to FAST diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 644f6d416..c4555b2b0 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -3,17 +3,6 @@ SubDyn Theory ============== -This section focuses on the theory behind the BeamDyn module. The -theoretical foundation, numerical tools, and some special handling in -the implementation will be introduced. References will be provided in -each section detailing the theories and numerical tools. - -In this chapter, matrix notation is used to denote vectorial or -vectorial-like quantities. For example, an underline denotes a vector -:math:`\underline{u}`, an over bar denotes unit vector :math:`\bar{n}`, -and a double underline denotes a tensor -:math:`\underline{\underline{\Delta}}`. Note that sometimes the -underlines only denote the dimension of the corresponding matrix. Overview ------------------ @@ -97,7 +86,7 @@ reaction calculation. For further details, see also :cite:`song2013`. Integration with the FAST Modularization Framework -------------------------------------------------- -Based on a new modularization framework :cite:`jonkman2013`, FAST joins an +Based on a new modularization framework :cite:`jjonkman2013`, FAST joins an aerodynamics module, a hydrodynamics module, a control and electrical system (servo) module, and structural-dynamics (elastic) modules to enable coupled nonlinear aero-hydro-servo-elastic analysis of land-based @@ -177,16 +166,16 @@ Member or Element Local Coordinate System (:math:`{x_e, y_e, z_e}`) (:numref:`el - The origin is set at the shear center of the cross section at the start node (S,MJointID1). -- The local axis is along the elastic axis of the member, directed from +- The local :math:`z_{e}` axis is along the elastic axis of the member, directed from the start node (S) to the end node (E,MJointID2). Nodes are ordered along the member main axis directed from start joint to end joint - (per user’s input definition). + (per user's input definition). -- The local axis is parallel to the global :math:`\text{XY}` plane, and - directed such that a positive, less than or equal to 180º rotation - about it, would bring the local axis parallel to the global *Z* axis. +- The local :math:`x_{e}` axis is parallel to the global :math:`\text{XY}` plane, and + directed such that a positive, less than or equal to 180:math:`^\circ` rotation + about it, would bring the local :math:`z_{e}` axis parallel to the global *Z* axis. -- The local axis can be found assuming a right-handed Cartesian +- The local :math:`y_{e}` axis can be found assuming a right-handed Cartesian coordinate system. .. _element-cs: @@ -294,7 +283,7 @@ element stiffness and consistent mass matrices can be written as follows \renewcommand*{\arraystretch}{1.0} -.. math:: :label: ke +.. math:: :label: ke0 \setcounter{MaxMatrixCols}{20} @@ -317,7 +306,7 @@ element stiffness and consistent mass matrices can be written as follows } -.. math:: :label: me +.. math:: :label: me0 [m_e]= \rho \\ \left[\begin{array}{*{12}c} @@ -373,7 +362,7 @@ Before assembling the global system stiffness (*K*) and mass (*M*) matrices, the individual :math:`{[k_e]}` and math:`{[m_e]}` are modified to the global coordinate system via :math:`{[ \mathbf{D_c} ]}` as shown in the following equations: -.. math:: :label: ke +.. math:: :label: ke1 [k] = \begin{bmatrix} [\mathbf{D_c}] & 0 & 0 & 0 \\ @@ -387,7 +376,7 @@ system via :math:`{[ \mathbf{D_c} ]}` as shown in the following equations: & & & [\mathbf{D_c}] \end{bmatrix}^T -.. math:: :label: me +.. math:: :label: me1 [m] = \begin{bmatrix} [\mathbf{D_c}] & 0 & 0 & 0 \\ @@ -467,7 +456,7 @@ DOFs). For this reason, a C-B methodology was used to recharacterize the substructure finite-element model into a reduced DOF model that maintains the fundamental low-frequency response modes of the structure. With the C-B method, the DOFs of the substructure can be reduced to -about 10 (user defined, see also Section :ref:`_CBguide`). This system reduction method +about 10 (user defined, see also Section :ref:`CBguide`). This system reduction method was first introduced by :cite:`hurty1964` and later expanded by :cite:`craig1968`. In SubDyn’s C-B reduction, the substructure nodes are separated into two @@ -546,10 +535,11 @@ between physical DOFs and generalized DOFs can be written as: q_L \end{bmatrix} -where *I* is the identity matrix; :math:`{\Phi_R}` (*L*\ ×\ *R* matrix) represents the +where *I* is the identity matrix; :math:`{\Phi_R}` is the (*L*\ ×\ *R*) matrix of Guyan modes, +which represents the physical displacements of the interior nodes for static, rigid body motions at the boundary (interface nodes’ DOFs, because the restrained -nodes’ DOFs are locked by definition). By considering the homogeneous, +nodes DOFs are locked by definition). By considering the homogeneous, static version of :eq:`main2`, the second row can be manipulated to yield: .. math:: :label: CB2 @@ -563,7 +553,10 @@ Rearranging and considering yields: \Phi_R = -K_{LL}^{-1} K_{LR} where the brackets have been removed for simplicity. - +If the structure is unconstrained, the matrix :math:`{\Phi_R}` +corresponds to rigid body modes, ensuring that the internal nodes follow the rigid body +displacements imposed by the interface DOFs. This has been verified analytically using the +stiffness matrix of a single beam element. :math:`{\Phi_L}` (*L*\ ×\ *L* matrix) represents the internal eigenmodes, i.e., the natural modes of the system restrained at the boundary (interface and bottom nodes), and can be obtained by solving the eigenvalue problem: @@ -581,10 +574,12 @@ that: \Phi_L^T M_{LL} \Phi_L = I -By then reducing the number of generalized DOFs to *m* ( :math:`{\le L}`), :math:`{\Phi_m}` is +By then reducing the number of generalized DOFs to *m* ( :math:`{\le L}`), +:math:`{\Phi_m}` is the matrix (:math:`{(L\times m)}` ) chosen to denote the truncated set of :math:`{\Phi_L}` (keeping *m* of the total internal modes, hence *m* columns), and :math:`{\Omega_m}` is the diagonal (*m*\ ×\ *m*) matrix -containing the corresponding eigenfrequencies. In SubDyn, the user +containing the corresponding eigenfrequencies (i.e., :math:`\Phi_m^T K_{LL} \Phi_m=\Omega_m^2`). +In SubDyn, the user decides how many modes to retain, including possibly zero or all modes. Retaining zero modes corresponds to a Guyan (static) reduction; retaining all modes corresponds to keeping the full finite-element @@ -630,19 +625,19 @@ and making use of Eq. :eq:`PhiL2`, Eq. :eq:`main2` can be rewritten as: M_{mB} & I \end{bmatrix} \begin{bmatrix} - \ddot{U_R} \\ - \ddot{q_m} + \ddot{U}_R \\ + \ddot{q}_m \end{bmatrix} + \begin{bmatrix} - 0 & 0 \\ - 0 & 2\zeta \Omega_m + C_{BB} & C_{Bm} \\ + C_{mB} & C_{mm} \end{bmatrix} \begin{bmatrix} - \dot{U_R} \\ - \dot{q_m} + \dot{U}_R \\ + \dot{q}_m \end{bmatrix} + \begin{bmatrix} K_{BB} & 0 \\ - 0 & \Omega_m^2 + 0 & K_{mm} \end{bmatrix} \begin{bmatrix} U_R \\ @@ -651,57 +646,43 @@ and making use of Eq. :eq:`PhiL2`, Eq. :eq:`main2` can be rewritten as: \begin{bmatrix} F_R + F_{Rg} + \Phi_R^T \left( F_L + F_{Lg} \right)\\ \Phi_m^T \left( F_L + F_{Lg} \right) \end{bmatrix} - -Eq. :eq:`main3` assumes that: -.. math:: :label: damping - - \begin{bmatrix} - I & \Phi_R^T \\ - 0 & \Phi_m^T - \end{bmatrix} - \begin{bmatrix} - C_{RR} & C_{RL} \\ - C_{LR} & C_{LL} - \end{bmatrix} - \begin{bmatrix} - I & 0 \\ - \Phi_R & \Phi_m - \end{bmatrix} = - \begin{bmatrix} - C_{RR} + C_{RL} \Phi_R + \Phi_R^T C_{LL} \Phi_R & C_{RL} \Phi_m + \Phi_R^T C_{LL} \Phi_m \\ - \Phi_m^T C_{LR} + \Phi_m^T C_{LL} \Phi_R & \Phi_m^T C_{LL} \Phi_m - \end{bmatrix} = - \begin{bmatrix} - 0 & 0 \\ - 0 & \Phi_m^T C_{LL} \Phi_m - \end{bmatrix} = - - \begin{bmatrix} - 0 & 0 \\ - 0 & 2 \zeta \Omega_m - \end{bmatrix} +where +.. math:: :label: partitions + :nowrap: + + \begin{align} + M_{BB} &= M_{RR} + M_{RL} \Phi_R + \Phi_R^T M_{LR} + \Phi_R^T M_{LL} \Phi_R \\ + C_{BB} &= C_{RR} + C_{RL} \Phi_R + \Phi_R^T C_{LR} + \Phi_R^T C_{LL} \Phi_R \nonumber \\ + K_{BB} &= K_{RR} + K_{RL} \Phi_R \nonumber \\ + M_{mB} &= \Phi_m^T M_{LR} + \Phi_m^T M_{LL} \Phi_R \nonumber \\ + C_{mB} &= \Phi_m^T C_{LR} + \Phi_m^T C_{LL} \Phi_R \nonumber \\ + M_{Bm} &= M_{mB}^T \nonumber \\ + C_{Bm} &= C_{mB}^T \nonumber \\ + K_{mm} & =\Phi_m^T K_{LL} \Phi_m = \Omega_m^2 \nonumber \\ + C_{mm} &= \Phi_m^T C_{LL} \Phi_m \nonumber + \end{align} + +Currently, SubDyn assumes: + +.. math:: :label: dampingassumptions + :nowrap: + + \begin{align} + C_{BB} = C_{Bm} =C_{mB}&\approx 0 \nonumber \\ + C_{mm} &\approx 2 \zeta \Omega_m + \end{align} In other words, the only damping matrix term retained is the one associated with internal DOF damping. This assumption has implications on the damping at the interface with the turbine system, as discussed in -Section :ref:`_TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contains the modal +Section :ref:`TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contains the modal damping ratios corresponding to each retained internal mode. In SubDyn, the user provides damping ratios (in percent of critical damping coefficients) for the retained modes. -The matrix partitions in Eq. are calculated as follows: - -.. math:: :label: partitions - M_{BB} = M_{RR} + M_{RL} \Phi_R + \Phi_R^T M_{LR} + \Phi_R^T M_{LL} \Phi_R - - M_{mB} = \Phi_m^T M_{LR} + \Phi_m^T M_{LL} \Phi_R - - M_{Bm} = M_{mB}^T - - K_{BB} = K_{RR} + K_{RL} \Phi_R Next, the boundary nodes are partitioned into those at the interface, :math:`{\bar{U}_R}`, and those at the bottom, which are fixed: @@ -750,16 +731,18 @@ of the rigid transition piece. The matrix :math:`T_I` can be written as follows: with .. math:: :label: DXYZ + :nowrap: - \Delta X_i = X_{INi} - X_{TP} - - \Delta Y_i = Y_{INi} - Y_{TP} - - \Delta Z_i = Z_{INi} - Z_{TP} + \begin{align} + \Delta X_i &= X_{INi} - X_{TP} \nonumber\\ + \Delta Y_i &= Y_{INi} - Y_{TP} \\ + \Delta Z_i &= Z_{INi} - Z_{TP} \nonumber + \end{align} -where :math:`{ \left( X_{INi}, Y_{INi}, Z_{INi} \right) }` are the coordinates of the :math:`{i^{th}}` interface node and :math:`{ \left( X_{TP}, Y_{TP}, Z_{TP} \right) }`are the coordinates of -the TP reference point within the global coordinate system. +where :math:`{ \left( X_{INi}, Y_{INi}, Z_{INi} \right) }` are the coordinates +of the :math:`{i^{th}}` interface node and :math:`{ \left( X_{TP}, Y_{TP}, Z_{TP} \right) }` +are the coordinates of the TP reference point within the global coordinate system. In terms of TP DOFs, the system equation of motion :eq:`main3` after the boundary constraints are applied (the rows and columns corresponding to the DOFs @@ -773,19 +756,19 @@ equation of motion) becomes: \tilde{M}_{mB} & I \end{bmatrix} \begin{bmatrix} - \ddot{U_{TP}} \\ - \ddot{q_m} + \ddot{U}_{TP} \\ + \ddot{q}_m \end{bmatrix} + \begin{bmatrix} - 0 & 0 \\ - 0 & 2\zeta \Omega_m + \tilde{C}_{BB} & \tilde{C}_{Bm} \\ + \tilde{C}_{mB} & \tilde{C}_{mm} \end{bmatrix} \begin{bmatrix} - \dot{U_{TP}} \\ - \dot{q_m} + \dot{U}_{TP} \\ + \dot{q}_m \end{bmatrix} + \begin{bmatrix} \tilde{K}_{BB} & 0 \\ - 0 & \Omega_m^2 + 0 & \tilde{K}_{mm} \end{bmatrix} \begin{bmatrix} U_{TP} \\ @@ -794,29 +777,43 @@ equation of motion) becomes: \begin{bmatrix} \tilde{F}_{TP} \\ \tilde{F}_m \end{bmatrix} - + + with -.. math:: :label: tilde_partitions +.. math:: :label: tilde_partitions0 + :nowrap: + + \begin{align} + \tilde{M}_{BB} &= T_I^T \bar{M}_{BB} T_I, \quad + \tilde{C}_{BB} = T_I^T \bar{C}_{BB} T_I, \quad + \tilde{K}_{BB} = T_I^T \bar{K}_{BB} T_I \\ + \tilde{M}_{Bm} &= T_I^T \bar{M}_{Bm}, \quad + \tilde{C}_{Bm} = T_I^T \bar{C}_{Bm} \nonumber \\ + \tilde{M}_{mB} &= \tilde{M}_{Bm}^T ,\quad + \tilde{C}_{mB} = \tilde{C}_{Bm}^T \nonumber \\ + \tilde{C}_{mm} &= C_{mm}, \quad + \tilde{K}_{mm} = K_{mm} = \Omega_m^2\nonumber \\ + \tilde{F}_{TP} &= F_{TP} + T_I^T \left[ \bar{F}_{HDR}+ \bar{F}_{Rg} + \bar{\Phi}_{R}^T \left( F_L + F_{Lg} \right) \right] \nonumber \\ + \tilde{F}_{m} &= \Phi_m^T \left( F_L + F_{Lg} \right) \nonumber + \end{align} - \tilde{M}_{BB} = T_I^T \bar{M}_{BB} T_I - - \tilde{M}_{Bm} = T_I^T \bar{M}_{Bm} - - \tilde{M}_{mB} = \tilde{M}_{Bm}^T - - \tilde{K}_{BB} = T_I^T \bar{K}_{BB} T_I + +and, for now, with: - \tilde{F}_{TP} = F_{TP} + T_I^T \bar{F}_{HDR} + T_I^T \bar{F}_{Rg} + T_I^T \bar{\Phi}_{R}^T \left( F_L + F_{Lg} \right) +.. math:: :label: tilde_partitions_assumptions + :nowrap: - \tilde{F}_{m} = \Phi_m^T \left( F_L + F_{Lg} \right) + \begin{align} + \tilde{C}_{BB} &= \tilde{C}_{Bm}=\tilde{C}_{mB}=0 \nonumber\\ + \tilde{C}_{mm} &= 2\zeta \Omega_m + \end{align} - -where the TP reaction force, i.e., the force applied to the substructure +and where the TP reaction force, i.e., the force applied to the substructure through the TP, is denoted by: -.. math:: :label: FTP +.. math:: :label: FTP1 F_{TP} = T_I^T F_{EDR} @@ -859,11 +856,11 @@ In SubDyn, the inputs are defined as: .. math:: :label: inputs u = \begin{bmatrix} - u1 \\ - u2 \\ - u3 \\ - u4 \\ - u5 \\ + u_1 \\ + u_2 \\ + u_3 \\ + u_4 \\ + u_5 \\ \end{bmatrix} = \begin{bmatrix} U_{TP} \\ \dot{U}_{TP} \\ @@ -874,8 +871,8 @@ In SubDyn, the inputs are defined as: where :math:`F_L` are the hydrodynamic forces on every interior node of the -substructure from HydroDyn, and `F_{HDR}` are the analogous forces at the boundary -nodes; :math:`{ U_{TP},\dot{U}_{TP}, and \ddot{U}_{TP}}` are TP deflections (6 DOFs), velocities, and +substructure from HydroDyn, and :math:`F_{HDR}` are the analogous forces at the boundary +nodes; :math:`{ U_{TP},\dot{U}_{TP},\text{ and } \ddot{U}_{TP}}` are TP deflections (6 DOFs), velocities, and accelerations, respectively. For SubDyn in stand-alone mode (uncoupled from FAST), :math:`F_{L}` and :math:`F_{HDR}` are assumed to be zero. @@ -884,8 +881,8 @@ In first-order form, the states are defined as: .. math:: :label: states x = \begin{bmatrix} - x1 \\ - x2 \\ + x_1 \\ + x_2 \\ \end{bmatrix} = \begin{bmatrix} q_m \\ \dot{q}_m \\ @@ -901,21 +898,23 @@ Eq. :eq:`main4` can be written as a standard linear system state equation: where -.. math:: :label: ABFx - A = \begin{bmatrix} - 0 & I \\ - -\Omega_m^2 & -2 \zeta \Omega_m - \end{bmatrix} +.. math:: :label: ABFx - B = \begin{bmatrix} - 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & -\tilde{M}_{mB} & \Phi_m^T & 0 - \end{bmatrix} - F_X = \begin{bmatrix} - 0 \\ - \Phi_m^T F_{Lg} - \end{bmatrix} + A = \begin{bmatrix} + 0 & I \\ + -\Omega_m^2 & -2 \zeta \Omega_m + \end{bmatrix} + ,\quad + B = \begin{bmatrix} + 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & -\tilde{M}_{mB} & \Phi_m^T & 0 + \end{bmatrix} + ,\qquad + F_X = \begin{bmatrix} + 0 \\ + \Phi_m^T F_{Lg} + \end{bmatrix} In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the transition piece :math:`F_{TP}`: @@ -924,31 +923,96 @@ In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the tr y1 = Y_1 =-F_{TP} -By examining Eq. :eq:`main4` , the output equation for can be found as: +By examining Eq. :eq:`main4` , the force is extracted from the first block row as: + + +.. math:: :label: FTP2 + :nowrap: + + \begin{align} + F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} + \tilde{M}_{Bm} \ddot{q}_m + \\ + &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m + + \tilde{K}_{BB} U_{TP} + - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_L + F_{Lg}) \right) + \nonumber + \end{align} + +The mode accelerations, :math:`\ddot{q}_m`, are extracted from the second block row as: + +.. math:: :label: ddotqm + :nowrap: + + \begin{align} + \ddot{q}_m = \Phi_m^T(F_L + F_{Lg}) + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mB} \dot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \end{align} + +Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: + +.. math:: :label: FTP3 + :nowrap: + + \begin{align} + F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} + + \tilde{M}_{Bm} \left[ + \Phi_m^T(F_L + F_{Lg}) + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mB} \dot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \right] + \nonumber\\ + &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m + + \tilde{K}_{BB} U_{TP} + - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_L + F_{Lg}) \right) + \nonumber\\ + F_{TP} =& + \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + +\left[\tilde{C}_{Bm}- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + \\ + &+\left[\tilde{K}_{BB} \right] U_{TP} + +\left[\tilde{C}_{BB} -\tilde{M}_{Bm} \tilde{C}_{mB} \right] \dot{U}_{TP} + +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} + \nonumber \\ + &+\left[\tilde{M}_{Bm}\Phi_m^T - T_I^T \bar{\Phi}_R^T \right] (F_L + F_{Lg}) + +\left[ -T_I^T \right]\bar{F}_{Rg} + \nonumber + \end{align} + + +The output equation for :math:`y_1` can now be identified as: .. math:: :label: Y1 - -Y_1 =C_1 x + D_1 \bar{u} + F_{Y1} + -Y_1 = F_{TP} = C_1 x + D_1 \bar{u} + F_{Y1} where .. math:: :label: C1D1FY1u - - C_1 = \begin{bmatrix} -\tilde{M}_{Bm} \Omega_m^2 & -2\tilde{M}_{Bm} \zeta \Omega_m \end{bmatrix} - - D_1 = \begin{bmatrix} \tilde{K}_{BB} & 0 & \tilde{M}_{BB} - \tilde{M}_{Bm} \tilde{M}_{mB} & \tilde{M}_{Bm} \Phi_m^T - T_I^T \bar{\Phi}_R^T & -T_I^T \end{bmatrix} - - F_{Y1} = \begin{bmatrix} \tilde{M}_{Bm} \Phi_m^T F_{Lg} - T_I^T \left( \bar{F}_{Rg} + \bar{\Phi}_R^T F_{Lg} \right) \end{bmatrix} - - u = \begin{bmatrix} - U_{TP} \\ - \dot{U}_{TP} \\ - \ddot{U}_{TP} \\ - F_{L} \\ - \bar{F}_{HDR} - \end{bmatrix} - - + :nowrap: + + \begin{align} + C_1 &= \begin{bmatrix} -\tilde{M}_{Bm} \Omega_m^2 & -2\tilde{M}_{Bm} \zeta \Omega_m \end{bmatrix} + \nonumber\\ + D_1 &= \begin{bmatrix} \tilde{K}_{BB} & 0 & \tilde{M}_{BB} - \tilde{M}_{Bm} \tilde{M}_{mB} & \tilde{M}_{Bm} \Phi_m^T - T_I^T \bar{\Phi}_R^T & -T_I^T \end{bmatrix} + \nonumber\\ + F_{Y1} &= \begin{bmatrix} \tilde{M}_{Bm} \Phi_m^T F_{Lg} - T_I^T \left( \bar{F}_{Rg} + \bar{\Phi}_R^T F_{Lg} \right) \end{bmatrix} + \\ + u &= \begin{bmatrix} + U_{TP} \\ + \dot{U}_{TP} \\ + \ddot{U}_{TP} \\ + F_{L} \\ + \bar{F}_{HDR} + \end{bmatrix} + \nonumber + \end{align} + + Note that the overbar is used on the input vector to denote that the forces apply to the interface nodes only. @@ -977,33 +1041,81 @@ The output equation for :math:`y_2`: can then be written as: where .. math:: :label: C2D2FY2 + + C_2 &= \begin{bmatrix} + 0 & 0 \\ + \Phi_m & 0 \\ + 0 & 0 \\ + 0 & \Phi_m \\ + 0 & 0 \\ + -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ + \end{bmatrix} + + D_2 &= \begin{bmatrix} + T_I & 0 & 0 & 0 & 0 \\ + \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ + 0 & T_I & 0 & 0 & 0 \\ + 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ + 0 & 0 & T_I & 0 & 0 \\ + 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 + \end{bmatrix} + + F_{Y2}& = \begin{bmatrix} + 0 \\ + 0 \\ + 0 \\ + 0 \\ + 0 \\ + \Phi_m \Phi_m^T F_{Lg} + \end{bmatrix} + + +The above neglected the influence of the lever arm introduced by the TP +displacements. The force and moments exchanged at the TP with ElastoDyn, +are written :math:`F_{TP0}=\left\{f_{TP0}, m_{TP0} \right\}^{T}`. They are related to +:math:`F_{TP}` as: + +.. math:: + + F_{TP}=\begin{Bmatrix} + f_{TP} \\ + m_{TP} \\ + \end{Bmatrix}=\begin{bmatrix} + I & 0 \\ + \left[u_{TP} \right]_{\times} & I \\ + \end{bmatrix}\begin{Bmatrix} + f_{TP0} \\ + m_{TP0} \\ + \end{Bmatrix} + +where :math:`\left[u_{TP} \right]_{\times}` is the skew symmetric +matrix representing the cross product with the vector +:math:`u_TP`. This equation is inverted as: + +.. math:: + + F_{TP0}=\begin{Bmatrix} + f_{TP0} \\ + m_{TP0} \\ + \end{Bmatrix}\begin{bmatrix} + I & 0 \\ + -\left[u_{TP} \right]_{\times}& I \\ + \end{bmatrix}\begin{Bmatrix} + f_{TP} \\ + m_{TP} \\ + \end{Bmatrix} + = F_{TP} + + + \begin{Bmatrix} + 0 \\ + -\left[u_{TP} \right]_{\times} f_{TP} \\ + \end{Bmatrix} + +The output equation is now rewritten such that :math:`y_1= -F_{TP0}`. +The input file flag **ExtraMom** is used to include the or omit the contribution from +:math:`-\left[u_{TP} \right]_{\times} f_{TP}` to the output equation. - C_2 = \begin{bmatrix} - 0 & 0 \\ - \Phi_m & 0 \\ - 0 & 0 \\ - 0 & \Phi_m \\ - 0 & 0 \\ - -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ - \end{bmatrix} - - D_2 = \begin{bmatrix} - T_I & 0 & 0 & 0 & 0 \\ - \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ - 0 & T_I & 0 & 0 & 0 \\ - 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ - 0 & 0 & T_I & 0 & 0 \\ - 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 - \end{bmatrix} - F_{Y2} = \begin{bmatrix} - 0 \\ - 0 \\ - 0 \\ - 0 \\ - 0 \\ - \Phi_m \Phi_m^T F_{Lg} - \end{bmatrix} Member Force Calculation @@ -1067,7 +1179,7 @@ where :math:`{X_i,~Y_i}`, and :math:`Z_i` (:math:`{i = 1 .. N_{\text{React}}}`) the boundary nodes with respect to the reference point. For each element with a restrained node, :math:`F_{\text{React}}` is calculated starting from :math:`F_S^e` --- see Eq. :eq:`el_loads` --- subtracting out the contributions of gravity --- :math:`F_G`, see Eq. :eq:`FG` -—and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct +and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct element-level inertial or damping effect is therefore included in the reaction calculation. @@ -1126,17 +1238,21 @@ the two static solutions, which amounts to quasi-statically accounting for the contribution of those modes not directly included within the dynamic solution. -Recalling the previous C-B formulation :eq:`CB3`, and adding the total static -deflection of all the internal DOFs (:math:`U_{L0}`), and subtracting the static -deflection associated with C-B modes (:math:`U_{L0m}`), the SIM formulation is cast as -in :eq:`SIM`: +The SIM formulation provides a correction for the displacements of the +internal nodes. The uncorrected displacements, as obtained from the +previous C-B formulation , are now noted :math:`{\hat{U}}_{L}`, while +the corrected displacements are noted :math:`_{}`. The SIM correction +consists in and adding the total static deflection of all the internal +DOFs (:math:`U_{L0}`), and subtracting the static deflection associated +with C-B modes (:math:`U_{L0m}`), as cast in :eq:`SIM` : .. math:: :label: SIM - U_L = \hat{U}_L + U_{L0} - U_{L0m} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + U_{L0} - U_{L0m} + U_L = \hat{U}_L + U_{L0} - U_{L0m} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} - -Eq. :eq:`SIM` can be rewritten as: + +where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. +will be derived in the next paragraph. Eq. :eq:`SIM` can be rewritten as: .. math:: :label: SIM2 @@ -1159,12 +1275,8 @@ with: .. math:: :label: UL0 - U_{L0} = \Phi_L q_{L0} - -.. math:: :label: UL0m + U_{L0} = \Phi_L q_{L0}, \qquad U_{L0m} = \Phi_m q_{m0} - U_{L0m} = \Phi_m q_{m0} - where :math:`{q_{m0}}` and :math:`{q_{L0}}` are the *m* and *L* modal coefficients that are assumed to be operating in a static fashion. For Eqs. :eq:`SIM2` and :eq:`UL0` to be valid, and are @@ -1188,18 +1300,20 @@ Similarly: .. math:: :label: UL0m2 - U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m + K_{LL} U_{L0m} = F_L + F_{Lg} \quad\rightarrow \quad U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m +with :math:`\tilde{F}_m =\Phi_m^T(F_L + F_{Lg})`. Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R \end{bmatrix} }` is calculated following the usual procedure -described in Sections :ref:`_SSformulation` -- :ref:`_TimeIntegration`. For example, states are still +described in :numref:`SSformulation` to :numref:`TimeIntegration`. For example, states are still calculated and integrated as in Eq. :eq:`state_eq`, and the output to ElastoDyn, i.e., the reaction provided by the substructure at the TP interface, is also calculated as it was done previously in Eqs. :eq:`y1` and :eq:`Y1`. -However, the state-space formulation is slightly modified to allow for -the calculation of the outputs to HydroDyn as: +However, the state-space formulation is slightly modified +(simply adding the contribution :math:`U_{L0}-U_{L0m}` to :math:`F_{Y2}` +when computing the outputs to HydroDyn as: .. math:: :label: y2sim @@ -1212,7 +1326,7 @@ the calculation of the outputs to HydroDyn as: \ddot{U}_L \\ \end{bmatrix} = \begin{bmatrix} \bar{U}_R \\ - \hat{U}_L + U_{L0} - U_{L0m} \\ + \hat{U}_L + \boldsymbol{U_{L0} - U_{L0m}} \\ \dot{\bar{U}}_R \\ \dot{U}_L \\ \ddot{\bar{U}}_R \\ @@ -1227,7 +1341,7 @@ where the matrices now have the following meaning: .. math:: :label: C2D2FY2sim - C_2 = \begin{bmatrix} + C_2 &= \begin{bmatrix} 0 & 0 \\ \Phi_m & 0 \\ 0 & 0 \\ @@ -1236,7 +1350,7 @@ where the matrices now have the following meaning: -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ \end{bmatrix} - D_2 = \begin{bmatrix} + D_2 &= \begin{bmatrix} T_I & 0 & 0 & 0 & 0 \\ \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ 0 & T_I & 0 & 0 & 0 \\ @@ -1245,7 +1359,7 @@ where the matrices now have the following meaning: 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 \end{bmatrix} - F_{Y2} = \begin{bmatrix} + F_{Y2} &= \begin{bmatrix} 0 \\ U_{L0} - U_{L0m} \\ 0 \\ @@ -1259,9 +1373,9 @@ Finally, the element forces can be calculated as: .. math:: :label: el_loads_sim - \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e + \text{Element Inertia load:} ~~ F_I^e &= [m] \ddot{U}_e - \text{Element Static load:} ~~ F_S^e = [k] U_e = [k] \left[ \hat{U}_e + U_{L0,e} - U_{L0m,e} \right] + \text{Element Static load:} ~~ F_S^e &= [k] U_e = [k] \left[ \hat{U}_e + U_{L0,e} - U_{L0m,e} \right] with the element node DOFs expressed as: @@ -1270,7 +1384,7 @@ with the element node DOFs expressed as: U_e = \hat{U}_e + U_{L0,e} - U_{L0m,e} where the SIM decomposition is still used with :math:`\hat{U}_e` denoting the -time-varying components of the elements nodes’ displacements, and :math:`U_{L0,e}` and :math:`U_{L0m,e}` are +time-varying components of the elements nodes' displacements, and :math:`U_{L0,e}` and :math:`U_{L0m,e}` are derived from the parent :math:`U_{L0}` and :math:`U_{L0m}` arrays of displacements, respectively. diff --git a/docs/source/user/subdyn/zrefs.rst b/docs/source/user/subdyn/zrefs.rst index c434bde8a..1139eba4b 100644 --- a/docs/source/user/subdyn/zrefs.rst +++ b/docs/source/user/subdyn/zrefs.rst @@ -3,7 +3,7 @@ References ---------- -.. bibliography:: references.bib +.. bibliography:: references_SD.bib From 68732e49943b84c17e4c414bec12405738715478 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 7 Jul 2020 13:54:10 -0600 Subject: [PATCH 236/377] FlexSub: doc: more damping considerations --- docs/source/user/subdyn/modeling.rst | 3 + docs/source/user/subdyn/theory.rst | 512 +++++++++++++++------------ 2 files changed, 292 insertions(+), 223 deletions(-) diff --git a/docs/source/user/subdyn/modeling.rst b/docs/source/user/subdyn/modeling.rst index 08ed62abb..0afc9cad0 100644 --- a/docs/source/user/subdyn/modeling.rst +++ b/docs/source/user/subdyn/modeling.rst @@ -191,6 +191,9 @@ of the interface node. 2. SubDyn Guyan damping matrix using user defined 6x6 matrix 3. HydroDyn additional linear damping matrix (**AddBLin**) +The specificaiton of the Guyan damping matrix in SubDyn is discussed in :numref:`SD_DampingSpecifications`. + + **Old:** The C-B method assumes no damping for the interface modes. This is diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index c4555b2b0..612f033db 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -172,7 +172,7 @@ Member or Element Local Coordinate System (:math:`{x_e, y_e, z_e}`) (:numref:`el (per user's input definition). - The local :math:`x_{e}` axis is parallel to the global :math:`\text{XY}` plane, and - directed such that a positive, less than or equal to 180:math:`^\circ` rotation + directed such that a positive, less than or equal to 180 :math:`^\circ` rotation about it, would bring the local :math:`z_{e}` axis parallel to the global *Z* axis. - The local :math:`y_{e}` axis can be found assuming a right-handed Cartesian @@ -431,7 +431,7 @@ The main equations of motion of SubDyn are written as follows: .. math:: :label: main - [M] \left\{ \ddot{U} \right\} +[C] \{ \dot{U} \} + [K] \{ U \} = \{ F \} + [M] \{ \ddot{U} \} +[C] \{ \dot{U} \} + [K] \{ U \} = \{ F \} where :math:`{[M]}` and :math:`{[K]}` are the global mass and stiffness matrices of the substructure @@ -442,10 +442,9 @@ column indexed elements. :math:`{{U}}` and :math:`{{F}}` are the displacements and external forces along all of the DOFs of the assembled system. The damping matrix :math:`{[C]}` is not assembled from the -element contributions, because those are normally unknown, but treated -from a system point of view as shown in the following paragraphs. A -derivative with respect to time is represented by a dot, so that :math:`{\dot{U}}` and :math:`{\ddot{U}}` are -the first- and second-time derivatives of :math:`{{U}}` , respectively. +element contributions, because those are normally unknown, but can be specified in different ways, as discussed in :numref:`SD_DampingSpecifications`. +A derivative with respect to time is represented by a dot, so that :math:`{\dot{U}}` and :math:`{\ddot{U}}` are +the first- and second-time derivatives of :math:`{{U}}`, respectively. The number of DOFs associated with Eq. :eq:`main` can easily grow to the thousands for typical beam frame substructures. That factor, combined with the @@ -459,61 +458,60 @@ With the C-B method, the DOFs of the substructure can be reduced to about 10 (user defined, see also Section :ref:`CBguide`). This system reduction method was first introduced by :cite:`hurty1964` and later expanded by :cite:`craig1968`. -In SubDyn’s C-B reduction, the substructure nodes are separated into two + +.. _GenericCBReduction: + +Craig-Bampton reduction +~~~~~~~~~~~~~~~~~~~~~~~ + +In this section we present the generic Craig-Bampton technique. +The specific application in SubDyn is presented in following sections. +In a C-B reduction, the structure nodes are separated into two groups: 1) the boundary nodes (identified with a subscript “\ *R*\ †in what follows) that include the nodes fully restrained at the base of the structure and the interface nodes; and 2) the interior nodes (or -leftover nodes, identified with a subscript “\ *L*\ â€). The interface -nodes are assumed rigidly connected among one another and to the TP -reference point. Note that the DOFs of partially restrained or “free†+leftover nodes, identified with a subscript “\ *L*\ â€). Note that the DOFs of partially restrained or “free†nodes at the base of the structure are included in the “L†subset in this version of SubDyn that contains SSI capabilities. -The derivation of the system reduction is shown below. After the LFEB -assembly, the system equation of motion of Eq. :eq:`main` can be partitioned as +The derivation of the system reduction is shown below. The system equation of motion of Eq. :eq:`main` can be partitioned as follows: .. math:: :label: main2 \begin{bmatrix} M_{RR} & M_{RL} \\ - M_{LR} & M_{LL} + M_{LR} & M_{LL} \end{bmatrix} \begin{bmatrix} - \ddot{U_R} \\ - \ddot{U_L} + \ddot{U}_R \\ + \ddot{U}_L \end{bmatrix} + \begin{bmatrix} C_{RR} & C_{RL} \\ - C_{LR} & C_{LL} + C_{LR} & C_{LL} \\ \end{bmatrix} \begin{bmatrix} - \dot{U_R} \\ - \dot{U_L} + \dot{U}_R \\ + \dot{U}_L \end{bmatrix} + - \begin{bmatrix} K_{RR} & K_{RL} \\ - K_{LR} & K_{LL} + \begin{bmatrix} + K_{RR} & K_{RL} \\ + K_{LR} & K_{LL} \\ \end{bmatrix} \begin{bmatrix} U_R \\ - U_L + U_L \\ \end{bmatrix} = - \begin{bmatrix} F_R + F_{Rg} \\ - F_L + F_{Lg} - \end{bmatrix} + \begin{bmatrix} + F_R \\ + F_L \\ + \end{bmatrix} where the subscript *R* denotes the boundary DOFs (there are *R* DOFs), and the subscript *L* the interior DOFs (there are *L* DOFs). - In Eq. :eq:`main2`, the applied forces include external forces (e.g., hydrodynamic -forces and those transmitted through the TP to the substructure) :math:`{(F_R,F_L)}` and -gravity forces :math:`{(F_{Rg},F_{L}g)}`, which are considered static forces lumped at each node. -The forces at the boundary nodes can be broken down into hydrodynamic -forces and those transferred to and from ElastoDyn via the TP, thus: - -.. math:: :label: FR - - F_R =F_{HDR} + F_{EDR} +forces and those transmitted through the TP to the substructure), gravity and pretension forces which are considered static forces lumped at each node. The fundamental assumption of the C-B method is that the contribution to the displacement of the interior nodes can be simply approximated by a @@ -524,7 +522,7 @@ between physical DOFs and generalized DOFs can be written as: \begin{bmatrix} U_R \\ - U_L + U_L \end{bmatrix} = \begin{bmatrix} I & 0 \\ @@ -532,7 +530,7 @@ between physical DOFs and generalized DOFs can be written as: \end{bmatrix} \begin{bmatrix} U_R \\ - q_L + q_L \end{bmatrix} where *I* is the identity matrix; :math:`{\Phi_R}` is the (*L*\ ×\ *R*) matrix of Guyan modes, @@ -585,67 +583,60 @@ Retaining zero modes corresponds to a Guyan (static) reduction; retaining all modes corresponds to keeping the full finite-element model. -The C-B transformation is therefore represented by: +The C-B transformation is therefore represented by the coordinate transformation matrix +:math:`T_{\Phi_m}` as: .. math:: :label: CB3 \begin{bmatrix} U_R \\ - U_L + U_L \\ \end{bmatrix} = - \begin{bmatrix} - I & 0 \\ - \Phi_R & \Phi_m - \end{bmatrix} + T_{\Phi_m} \begin{bmatrix} U_R \\ - q_m + q_m \\ \end{bmatrix} + ,\qquad + T_{\Phi_m} = + \begin{bmatrix} + I & 0 \\ + \Phi_R & \Phi_m + \end{bmatrix} By using Eq. :eq:`CB3`, the interior DOFs are hence transformed from physical -DOFs to modal DOFs, and by pre-multiplying both sides of Eq. :eq:`main2` by - -.. math:: - - \begin{bmatrix} - I & 0 \\ - \Phi_R & \Phi_m - \end{bmatrix}^T = - \begin{bmatrix} - I & \Phi_R^T \\ - 0 & \Phi_m^T - \end{bmatrix}^T - -and making use of Eq. :eq:`PhiL2`, Eq. :eq:`main2` can be rewritten as: +DOFs to modal DOFs. By pre-multiplying both sides of Eq. :eq:`main2` by :math:`T_{\Phi_m}^T` on the left and :math:`T_{\Phi_m}` on the right, and making use of Eq. :eq:`PhiL2`, Eq. :eq:`main2` can be rewritten as: .. math:: :label: main3 \begin{bmatrix} M_{BB} & M_{Bm} \\ - M_{mB} & I + M_{mB} & I \end{bmatrix} \begin{bmatrix} \ddot{U}_R \\ - \ddot{q}_m + \ddot{q}_m \end{bmatrix} + \begin{bmatrix} C_{BB} & C_{Bm} \\ C_{mB} & C_{mm} \end{bmatrix} \begin{bmatrix} - \dot{U}_R \\ - \dot{q}_m + \dot{U}_R \\ + \dot{q}_m \end{bmatrix} + - \begin{bmatrix} K_{BB} & 0 \\ - 0 & K_{mm} + \begin{bmatrix} + K_{BB} & 0 \\ + 0 & K_{mm} \end{bmatrix} \begin{bmatrix} U_R \\ - q_m + q_m \end{bmatrix} = - \begin{bmatrix} F_R + F_{Rg} + \Phi_R^T \left( F_L + F_{Lg} \right)\\ - \Phi_m^T \left( F_L + F_{Lg} \right) - \end{bmatrix} + \begin{bmatrix} + F_B \\ + F_m + \end{bmatrix} where @@ -658,33 +649,23 @@ where K_{BB} &= K_{RR} + K_{RL} \Phi_R \nonumber \\ M_{mB} &= \Phi_m^T M_{LR} + \Phi_m^T M_{LL} \Phi_R \nonumber \\ C_{mB} &= \Phi_m^T C_{LR} + \Phi_m^T C_{LL} \Phi_R \nonumber \\ - M_{Bm} &= M_{mB}^T \nonumber \\ - C_{Bm} &= C_{mB}^T \nonumber \\ K_{mm} & =\Phi_m^T K_{LL} \Phi_m = \Omega_m^2 \nonumber \\ - C_{mm} &= \Phi_m^T C_{LL} \Phi_m \nonumber + C_{mm} &= \Phi_m^T C_{LL} \Phi_m \nonumber \\ + F_B &= F_R +\Phi_R^T F_L \nonumber\\ + F_m &= \Phi_m^T F_L \nonumber \end{align} -Currently, SubDyn assumes: +and :math:`M_{Bm} = M_{mB}^T`, :math:`C_{Bm} =C_{mB}^T`. -.. math:: :label: dampingassumptions - :nowrap: - \begin{align} - C_{BB} = C_{Bm} =C_{mB}&\approx 0 \nonumber \\ - C_{mm} &\approx 2 \zeta \Omega_m - \end{align} - -In other words, the only damping matrix term retained is the one -associated with internal DOF damping. This assumption has implications -on the damping at the interface with the turbine system, as discussed in -Section :ref:`TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contains the modal -damping ratios corresponding to each retained internal mode. In SubDyn, -the user provides damping ratios (in percent of critical damping -coefficients) for the retained modes. +.. _TP2Interface: +Boundary nodes: fixed DOFs and rigid connection to TP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In this section we present the treatment of the boundary nodes: fixed DOFs are eliminated, and interface DOFs are condensed via a rigid connection to the TP reference point. -Next, the boundary nodes are partitioned into those at the interface, :math:`{\bar{U}_R}`, +The boundary nodes are partitioned into those at the interface, :math:`{\bar{U}_R}`, and those at the bottom, which are fixed: .. math:: :label: UR @@ -696,15 +677,17 @@ and those at the bottom, which are fixed: The overhead bar here and below denotes matrices/vectors after the -fixed-bottom boundary conditions are applied. The interface nodes are -treated as rigidly connected to the TP, hence it is convenient to use +fixed-bottom boundary conditions are applied. + +The interface nodes are +assumed to be rigidly connected among one another and to the TP reference point, hence it is convenient to use rigid-body TP DOFs (one node with 6 DOFs at the TP reference point) in place of the interface DOFs. The interface DOFs, :math:`{\bar{U}_R}`, and the TP DOFs are related to each other as follows: .. math:: :label: UTP - U_R = T_I U_{TP} + \bar{U}_R = T_I U_{TP} where :math:`T_I` is a :math:`{\left(6 NIN \right) \times 6}` matrix, :math:`NIN` is the number of interface nodes, and :math:`{U_{TP}}` is the 6 DOFs of the rigid transition piece. The matrix :math:`T_I` can be written as follows: @@ -753,7 +736,7 @@ equation of motion) becomes: \begin{bmatrix} \tilde{M}_{BB} & \tilde{M}_{Bm} \\ - \tilde{M}_{mB} & I + \tilde{M}_{mB} & I \end{bmatrix} \begin{bmatrix} \ddot{U}_{TP} \\ @@ -761,22 +744,24 @@ equation of motion) becomes: \end{bmatrix} + \begin{bmatrix} \tilde{C}_{BB} & \tilde{C}_{Bm} \\ - \tilde{C}_{mB} & \tilde{C}_{mm} + \tilde{C}_{mB} & C_{mm} \end{bmatrix} \begin{bmatrix} \dot{U}_{TP} \\ \dot{q}_m \end{bmatrix} + - \begin{bmatrix} \tilde{K}_{BB} & 0 \\ - 0 & \tilde{K}_{mm} + \begin{bmatrix} + \tilde{K}_{BB} & 0 \\ + 0 & K_{mm} \end{bmatrix} \begin{bmatrix} U_{TP} \\ - q_m + q_m \end{bmatrix} = - \begin{bmatrix} \tilde{F}_{TP} \\ - \tilde{F}_m - \end{bmatrix} + \begin{bmatrix} + \tilde{F}_{TP} \\ + F_m + \end{bmatrix} with @@ -790,41 +775,59 @@ with \tilde{K}_{BB} = T_I^T \bar{K}_{BB} T_I \\ \tilde{M}_{Bm} &= T_I^T \bar{M}_{Bm}, \quad \tilde{C}_{Bm} = T_I^T \bar{C}_{Bm} \nonumber \\ - \tilde{M}_{mB} &= \tilde{M}_{Bm}^T ,\quad - \tilde{C}_{mB} = \tilde{C}_{Bm}^T \nonumber \\ - \tilde{C}_{mm} &= C_{mm}, \quad - \tilde{K}_{mm} = K_{mm} = \Omega_m^2\nonumber \\ - \tilde{F}_{TP} &= F_{TP} + T_I^T \left[ \bar{F}_{HDR}+ \bar{F}_{Rg} + \bar{\Phi}_{R}^T \left( F_L + F_{Lg} \right) \right] \nonumber \\ - \tilde{F}_{m} &= \Phi_m^T \left( F_L + F_{Lg} \right) \nonumber + \tilde{F}_{TP} &= T_I^T F_B \nonumber \end{align} +.. \tilde{F}_{TP} &= F_{TP} + T_I^T \left[ \bar{F}_{HDR}+ \bar{F}_{Rg} + \bar{\Phi}_{R}^T \left( F_{L,e} + F_{L,g} \right) \right] \nonumber \\ +.. \tilde{C}_{mm} &= C_{mm}, \quad +.. \tilde{K}_{mm} = K_{mm} = \Omega_m^2\nonumber \\ +.. \tilde{F}_{m} &= \Phi_m^T \left( F_{L,e} + F_{L,g} \right) \nonumber -and, for now, with: +and :math:`\tilde{M}_{mB}= \tilde{M}_{Bm}^T`, :math:`\tilde{C}_{mB} = \tilde{C}_{Bm}^T`. -.. math:: :label: tilde_partitions_assumptions - :nowrap: +Equation :eq:`main4` represents the equations of motion of the substructure after +the C-B reduction. The total DOFs of the substructure are reduced from +(6 x total number of nodes) to (6 + *m*). - \begin{align} - \tilde{C}_{BB} &= \tilde{C}_{Bm}=\tilde{C}_{mB}=0 \nonumber\\ - \tilde{C}_{mm} &= 2\zeta \Omega_m - \end{align} +During initialization, SubDyn calculates: the parameter matrices :math:`{\tilde{M}_{BB}, \tilde{M}_{mB}, \tilde{M}_{Bm}, \tilde{K}_{BB}, \Phi_m, \Phi_R, T_I}`; constant load arrays ; and the internal frequency matrix :math:`\Omega_m` . The +substructure response at each time step can then be obtained by using +the state-space formulation discussed in the next section. + + +.. _Loads: + +Loads +~~~~~ +In this section we details the loads acting on the boundary (*R*), interior (*L*) and transition piece node (*TP*). External forces included in the FEM representation, such as the gravity forces, or the pretension forces are noted with the subscript *g*. +The forces at the boundary nodes can be broken down into external loads (*e*, e.g., hydrodynamic +forces, mooring forces), those transferred to and from ElastoDyn via the TP (ED), and the FEM loads: -and where the TP reaction force, i.e., the force applied to the substructure +.. math:: :label: FR + + F_R =F_{R,e} + F_{R, \text{ED}} + F_{R,g} + +The forces at the internal nodes are the external loads from other modules (e.g. hydrodynamic), and the FEM loads (e.g. gravity): + +.. math:: :label: FL + + F_L =F_{L,e} + F_{L,g} + +Conversely, the TP reaction force, i.e., the force applied to the substructure through the TP, is denoted by: .. math:: :label: FTP1 - F_{TP} = T_I^T F_{EDR} + F_{TP} = T_I^T F_{R,\textit{ED}} -Equation :eq:`main4` represents the equations of motion of the substructure after -the C-B reduction. The total DOFs of the substructure are reduced from -(6 x total number of nodes) to (6 + *m*). -During initialization, SubDyn calculates: the parameter matrices :math:`{\tilde{M}_{BB}, \tilde{M}_{mB}, \tilde{M}_{Bm}, \tilde{K}_{BB}, \Phi_m, \Phi_R, T_I}`; the -gravity arrays :math:`\bar{F}_{Rg}` and :math:`F_{Lg}` ; and the internal frequency matrix :math:`\Omega_m` . The -substructure response at each time step can then be obtained by using -the state-space formulation discussed in the next section. +The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given in Eq. :eq:`tilde_partitions0` is then given by: + +.. math:: :label: FTPtilde + + \tilde{F}_{TP} &= F_{TP} + T_I^T \left[ \bar{F}_{R,e}+ \bar{F}_{R,g} + \bar{\Phi}_{R}^T \left( F_{L,e} + F_{L,g} \right) \right] + + F_m & = \Phi_m^t \left(F_{L,e} + F_{L,g}\right) .. _SSformulation: @@ -865,8 +868,8 @@ In SubDyn, the inputs are defined as: U_{TP} \\ \dot{U}_{TP} \\ \ddot{U}_{TP} \\ - F_{L} \\ - F_{HDR} \\ + F_{L,e} \\ + F_{R,e} \\ \end{bmatrix} @@ -874,7 +877,7 @@ where :math:`F_L` are the hydrodynamic forces on every interior node of the substructure from HydroDyn, and :math:`F_{HDR}` are the analogous forces at the boundary nodes; :math:`{ U_{TP},\dot{U}_{TP},\text{ and } \ddot{U}_{TP}}` are TP deflections (6 DOFs), velocities, and accelerations, respectively. For SubDyn in stand-alone mode (uncoupled -from FAST), :math:`F_{L}` and :math:`F_{HDR}` are assumed to be zero. +from FAST), :math:`F_{L,e}` and :math:`F_{R,e}` are assumed to be zero. In first-order form, the states are defined as: @@ -883,10 +886,11 @@ In first-order form, the states are defined as: x = \begin{bmatrix} x_1 \\ x_2 \\ - \end{bmatrix} = \begin{bmatrix} - q_m \\ - \dot{q}_m \\ - \end{bmatrix} + \end{bmatrix} + = \begin{bmatrix} + q_m \\ + \dot{q}_m \\ + \end{bmatrix} From the system equation of motion, the state equation corresponding to @@ -896,24 +900,36 @@ Eq. :eq:`main4` can be written as a standard linear system state equation: \dot{x} = X = A x +Bu + F_X -where +These state matrices are obtained by isolating the mode accelerations, :math:`\ddot{q}_m` from the second block row of Eq. :eq:`main4` as: +.. math:: :label: ddotqm + :nowrap: + + \begin{align} + \ddot{q}_m = \underbrace{\Phi_m^T(F_{L,e} + F_{L,g})}_{F_m} + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mB} \dot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \end{align} + +leading to the following identification: .. math:: :label: ABFx A = \begin{bmatrix} 0 & I \\ - -\Omega_m^2 & -2 \zeta \Omega_m + -\tilde{K}_{mm} & -\tilde{C}_{mm} \end{bmatrix} ,\quad B = \begin{bmatrix} 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & -\tilde{M}_{mB} & \Phi_m^T & 0 + 0 & -\tilde{C}_{mB} & -\tilde{M}_{mB} & \Phi_m^T & 0 \end{bmatrix} ,\qquad F_X = \begin{bmatrix} 0 \\ - \Phi_m^T F_{Lg} + \Phi_m^T F_{L,g} \end{bmatrix} @@ -923,7 +939,7 @@ In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the tr y1 = Y_1 =-F_{TP} -By examining Eq. :eq:`main4` , the force is extracted from the first block row as: +By examining Eq. :eq:`main4` and Eq. :eq:`FTPtilde`, the force is extracted from the first block row as: .. math:: :label: FTP2 @@ -934,32 +950,16 @@ By examining Eq. :eq:`main4` , the force is extracted from the first block row a \\ &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m + \tilde{K}_{BB} U_{TP} - - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_L + F_{Lg}) \right) + - T_I^T \left(\bar{F}_{R,e} + \bar{F}_{R,g} + \bar{\Phi}_R(F_{L,e} + F_{L,g}) \right) \nonumber \end{align} -The mode accelerations, :math:`\ddot{q}_m`, are extracted from the second block row as: - -.. math:: :label: ddotqm - :nowrap: - - \begin{align} - \ddot{q}_m = \Phi_m^T(F_L + F_{Lg}) - - \tilde{M}_{mB} \ddot{U}_{TP} - - \tilde{C}_{mB} \dot{U}_{TP} - - \tilde{C}_{mm} \dot{q}_m - - \tilde{K}_{mm} q_m - \end{align} Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: -.. math:: :label: FTP3 - :nowrap: - - \begin{align} - F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} +.. F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} + \tilde{M}_{Bm} \left[ - \Phi_m^T(F_L + F_{Lg}) + \Phi_m^T(F_L + F_{L,g}) - \tilde{M}_{mB} \ddot{U}_{TP} - \tilde{C}_{mB} \dot{U}_{TP} - \tilde{C}_{mm} \dot{q}_m @@ -968,8 +968,12 @@ Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: \nonumber\\ &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m + \tilde{K}_{BB} U_{TP} - - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_L + F_{Lg}) \right) + - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_{L,e} + F_{L,g}) \right) \nonumber\\ +.. math:: :label: FTP3 + :nowrap: + + \begin{align} F_{TP} =& \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m +\left[\tilde{C}_{Bm}- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m @@ -978,8 +982,8 @@ Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: +\left[\tilde{C}_{BB} -\tilde{M}_{Bm} \tilde{C}_{mB} \right] \dot{U}_{TP} +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} \nonumber \\ - &+\left[\tilde{M}_{Bm}\Phi_m^T - T_I^T \bar{\Phi}_R^T \right] (F_L + F_{Lg}) - +\left[ -T_I^T \right]\bar{F}_{Rg} + &+\left[\tilde{M}_{Bm}\Phi_m^T - T_I^T \bar{\Phi}_R^T \right] \left(F_{L,e} + F_{L,g}\right) + +\left[ -T_I^T \right]\left(\bar{F}_{R,e} + \bar{F}_{R,g}\right) \nonumber \end{align} @@ -992,22 +996,27 @@ The output equation for :math:`y_1` can now be identified as: where + .. math:: :label: C1D1FY1u :nowrap: \begin{align} - C_1 &= \begin{bmatrix} -\tilde{M}_{Bm} \Omega_m^2 & -2\tilde{M}_{Bm} \zeta \Omega_m \end{bmatrix} - \nonumber\\ - D_1 &= \begin{bmatrix} \tilde{K}_{BB} & 0 & \tilde{M}_{BB} - \tilde{M}_{Bm} \tilde{M}_{mB} & \tilde{M}_{Bm} \Phi_m^T - T_I^T \bar{\Phi}_R^T & -T_I^T \end{bmatrix} + C_1 &= \begin{bmatrix} + -\tilde{M}_{Bm} \tilde{K}_{mm} & \tilde{C}_{Bm}-\tilde{M}_{Bm} \tilde{C}_{mm} + \end{bmatrix} + \nonumber\\ + D_1 &= \begin{bmatrix} + \tilde{K}_{BB} & \tilde{C}_{BB} -\tilde{M}_{Bm} \tilde{C}_{mB} & \tilde{M}_{BB} - \tilde{M}_{Bm} \tilde{M}_{mB} & \tilde{M}_{Bm} \Phi_m^T - T_I^T \bar{\Phi}_R^T & -T_I^T + \end{bmatrix} \nonumber\\ - F_{Y1} &= \begin{bmatrix} \tilde{M}_{Bm} \Phi_m^T F_{Lg} - T_I^T \left( \bar{F}_{Rg} + \bar{\Phi}_R^T F_{Lg} \right) \end{bmatrix} + F_{Y1} &= \begin{bmatrix} \tilde{M}_{Bm} \Phi_m^T F_{L,g} - T_I^T \left( \bar{F}_{R,g} + \bar{\Phi}_R^T F_{L,g} \right) \end{bmatrix} \\ - u &= \begin{bmatrix} + \bar{u} &= \begin{bmatrix} U_{TP} \\ \dot{U}_{TP} \\ \ddot{U}_{TP} \\ - F_{L} \\ - \bar{F}_{HDR} + F_{L,e} \\ + \bar{F}_{R,e} \end{bmatrix} \nonumber \end{align} @@ -1031,6 +1040,37 @@ velocities, and accelerations of the substructure: \end{bmatrix} + +From the CB coordinate transformation (Eq. :eq:`CB3`), and the link between boundary nodes and TP node (Eq. :eq:`UTP`) the motions are given as: + +.. math:: :label: y2motions + + \bar{U}_R &= T_I U_{TP} + ,\qquad + \bar{U}_L = \bar{\Phi}_R \bar{U}_R + \Phi_m q_m + + \dot{\bar{U}}_R &= T_I \dot{U}_{TP} + ,\qquad + \dot{\bar{U}}_L = \bar{\Phi}_R \dot{\bar{U}}_R + \Phi_m \dot{q}_m + + \ddot{\bar{U}}_R &= T_I \ddot{U}_{TP} + ,\qquad + \ddot{\bar{U}}_L = \bar{\Phi}_R \ddot{\bar{U}}_R + \Phi_m \ddot{q}_m + +Using the expression of :math:`\ddot{q}m` from Eq. :eq:`ddotqm`, the internal accelerations are: + + +.. math:: :label: y2internalacc + + \ddot{\bar{U}}_L = \bar{\Phi}_R T_I \ddot{U}_{TP} + \Phi_m\left[\Phi_m^T(F_{L,e} + F_{L,g}) + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mB} \dot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m \right] + + + + The output equation for :math:`y_2`: can then be written as: .. math:: :label: Y2 @@ -1048,7 +1088,7 @@ where 0 & 0 \\ 0 & \Phi_m \\ 0 & 0 \\ - -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ + -\Phi_m \tilde{K}_{mm} & -\Phi_m \tilde{C}_{mm} \\ \end{bmatrix} D_2 &= \begin{bmatrix} @@ -1057,7 +1097,7 @@ where 0 & T_I & 0 & 0 & 0 \\ 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ 0 & 0 & T_I & 0 & 0 \\ - 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 + 0 & -\Phi_m \tilde{C}_{mB} & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 \end{bmatrix} F_{Y2}& = \begin{bmatrix} @@ -1066,9 +1106,12 @@ where 0 \\ 0 \\ 0 \\ - \Phi_m \Phi_m^T F_{Lg} + \Phi_m \Phi_m^T F_{L,g} \end{bmatrix} +The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`Y2sim` is used instead. + + The above neglected the influence of the lever arm introduced by the TP displacements. The force and moments exchanged at the TP with ElastoDyn, @@ -1183,6 +1226,8 @@ and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct element-level inertial or damping effect is therefore included in the reaction calculation. + + .. _TimeIntegration: Time Integration @@ -1220,6 +1265,58 @@ time integrator options for loose coupling are: For more information, consult any numerical methods reference, e.g., :cite:`chapra2010`. + +.. _SD_DampingSpecifications: + +Damping specifications +~~~~~~~~~~~~~~~~~~~~~~ + + +There are three ways to specify the damping associated with the motion +of the interface node in SubDyn: no damping, Rayleigh damping or user defined 6x6 matrix. + +NOTE: Damping associated with joints is not documented yet and would change the developments below. + +When **GuyanDampMod=0**, SubDyn assumes zero damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: + +.. math:: :label: dampingassumptions + + C_{BB} = \tilde{C}_{BB} &=0 + + C_{Bm} =C_{mB} = \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 + + C_{mm} = \tilde{C}_{mm} &= 2\zeta \Omega_m + +In other words, the only damping matrix term retained is the one +associated with internal DOF damping. This assumption has implications +on the damping at the interface with the turbine system, as discussed in +Section :ref:`TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contans the modal +damping ratios corresponding to each retained internal mode. In SubDyn, +the user provides damping ratios (in percent of critical damping +coefficients) for the retained modes. + +When **GuyanDampMod=1**, SubDyn assumes Rayleigh Damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: + + +.. math:: :label: dampingRayleigh + + \tilde{C}_{BB}&=\alpha \tilde{M}_{BB} + \beta \tilde{K}_{BB} + + \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 + + \tilde{C}_{mm} &= 2\zeta \Omega_m + +where :math:`\alpha` and :math:`\beta` are the mass and stiffness proportional Rayleigh damping coefficients. The damping is directly applied to the tilde matrices, that is, the matrices related to the 6 DOF of the TP node. + +The case **GuyanDampMod=2**, is similar to the previous case, except that the user specifies the :math:`6\times6` terms of :math:`\tilde{C}_{BB}`. + + + + + + + + .. _sim: Static-Improvement Method @@ -1251,46 +1348,37 @@ with C-B modes (:math:`U_{L0m}`), as cast in :eq:`SIM` : U_L = \hat{U}_L + U_{L0} - U_{L0m} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} -where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. -will be derived in the next paragraph. Eq. :eq:`SIM` can be rewritten as: - -.. math:: :label: SIM2 - - \begin{bmatrix} - U_R \\ - U_L - \end{bmatrix} = - \begin{bmatrix} - I & 0 & 0 & 0 \\ - \Phi_R & \Phi_m & \Phi_L & -\Phi_m - \end{bmatrix} - \begin{bmatrix} - U_R \\ - q_m \\ - q_{L0} \\ - q_{m0} - \end{bmatrix} - -with: - -.. math:: :label: UL0 - - U_{L0} = \Phi_L q_{L0}, \qquad U_{L0m} = \Phi_m q_{m0} - +.. where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. + will be derived in the next paragraph. Eq. :eq:`SIM` can be rewritten as: + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} + I & 0 & 0 & 0 \\ + \Phi_R & \Phi_m & \Phi_L & -\Phi_m + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_m \\ + q_{L0} \\ + q_{m0} + \end{bmatrix} + with: + U_{L0} = \Phi_L q_{L0}, \qquad U_{L0m} = \Phi_m q_{m0} where :math:`{q_{m0}}` and :math:`{q_{L0}}` are the *m* and *L* modal coefficients that are assumed to be -operating in a static fashion. For Eqs. :eq:`SIM2` and :eq:`UL0` to be valid, and are +operating in a static fashion. These coefficients are calculated under the C-B hypothesis that the boundary nodes are fixed. - -The static displacement vectors can also be calculated as follows: +The static displacement vectors can be calculated as follows: .. math:: :label: SIM3 - K_{LL} U_{L0} = F_L + F_{Lg} + K_{LL} U_{L0} = F_{L,e} + F_{L,g} -By making use of :eq:`UL0`, and by pre-multiplying both sides times , Eq. :eq:`SIM3` can be -rewritten as: :math:`{\Phi_L^T K_{LL} \Phi_L q_{L0} = \Phi_L^T \left( F_L + F_{Lg} \right) = \tilde{F}_L }` or, recalling that :math:`{\Phi_L^T K_{LL} \Phi_L = \Omega_L^2}`, as: :math:`{\Omega_L^2 q_{L0} =\tilde{F}_L }`, or equivalently in terms of :math:`U_{L0}`: +By pre-multiplying both sides times , Eq. :eq:`SIM3` can be +rewritten as: :math:`{\Phi_L^T K_{LL} \Phi_L q_{L0} = \Phi_L^T \left( F_{L,e} + F_{L,g} \right) = \tilde{F}_L }` or, recalling that :math:`{\Phi_L^T K_{LL} \Phi_L = \Omega_L^2}`, as: :math:`{\Omega_L^2 q_{L0} =\tilde{F}_L }`, or equivalently in terms of :math:`U_{L0}`: .. math:: :label: UL02 @@ -1300,9 +1388,9 @@ Similarly: .. math:: :label: UL0m2 - K_{LL} U_{L0m} = F_L + F_{Lg} \quad\rightarrow \quad U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m + K_{LL} U_{L0m} = F_{L,e} + F_{L,g} \quad\rightarrow \quad U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m -with :math:`\tilde{F}_m =\Phi_m^T(F_L + F_{Lg})`. +with :math:`\tilde{F}_m =\Phi_m^T(F_{L,e} + F_{L,g})`. Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R \end{bmatrix} }` is calculated following the usual procedure @@ -1317,7 +1405,7 @@ when computing the outputs to HydroDyn as: .. math:: :label: y2sim - y_2= = \begin{bmatrix} + y_2= \begin{bmatrix} \bar{U}_R \\ U_L \\ \dot{\bar{U}}_R \\ @@ -1333,39 +1421,17 @@ when computing the outputs to HydroDyn as: \ddot{U}_L \\ \end{bmatrix} -.. math:: :label: Y2sim - - Y_2 = C_2 x + D_2 u + F_{Y2} - -where the matrices now have the following meaning: - -.. math:: :label: C2D2FY2sim +The array :math:`F_{Y2}` from Eq. :eq:`Y2` is now defined as follows: - C_2 &= \begin{bmatrix} - 0 & 0 \\ - \Phi_m & 0 \\ - 0 & 0 \\ - 0 & \Phi_m \\ - 0 & 0 \\ - -\Phi_m \Omega_m^2 & -2 \Phi_m \zeta \Omega_m \\ - \end{bmatrix} - - D_2 &= \begin{bmatrix} - T_I & 0 & 0 & 0 & 0 \\ - \bar{\Phi}_R T_I & 0 & 0 & 0 & 0 \\ - 0 & T_I & 0 & 0 & 0 \\ - 0 & \bar{\Phi}_R T_I & 0 & 0 & 0 \\ - 0 & 0 & T_I & 0 & 0 \\ - 0 & 0 & \bar{\Phi}_R T_I - \Phi_m \tilde{M}_{mB} & \Phi_m \Phi_m^T & 0 - \end{bmatrix} +.. math:: :label: Y2sim F_{Y2} &= \begin{bmatrix} 0 \\ - U_{L0} - U_{L0m} \\ + \boldsymbol{U_{L0} - U_{L0m}} \\ 0 \\ 0 \\ 0 \\ - \Phi_m \Phi_m^T F_{Lg} + \Phi_m \Phi_m^T F_{L,g} \end{bmatrix} From 2887b1932d5f9dd3cc6863f83cf8ca4ef7073798 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jul 2020 13:34:49 -0600 Subject: [PATCH 237/377] FlexSub: cross couplings for joint stiffness and damping --- modules/subdyn/src/FEM.f90 | 37 +++++++++++++++++ modules/subdyn/src/SD_FEM.f90 | 61 ++++++++++++----------------- modules/subdyn/src/SubDyn_Tests.f90 | 57 +++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 39 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index d96fac91e..ceb18fd0f 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -188,6 +188,43 @@ FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) endif END FUNCTION Determinant !------------------------------------------------------------------------------------------------------ +!> Create a chessboard-like matrix with `valBlack` on the "black" cases, starting with black at (1,1) +!! As a generalization, "black" values may be spaced every `nSpace` squares +!! For instance, blackVal=9, whiteVal=0, nSpace=2 +!! [9 0 0 9 0 0 9] +!! [0 9 0 0 9 0 0] +!! [0 0 9 0 0 9 0] +!! Diagonal values may be overriden by `diagVal` +!! Matrix M does not need to be square +subroutine ChessBoard(M, blackVal, whiteVal, nSpace, diagVal) + real(ReKi), dimension(:,:), intent( out) :: M !< Output matrix + real(ReKi), intent(in ) :: blackVal !< value for black squares + real(ReKi), intent(in ) :: whiteVal !< value for white squre + integer(IntKi), optional, intent(in ) :: nSpace !< spacing between black values, default 1 + real(ReKi), optional, intent(in ) :: diagVal !< Value to override diagonal + integer(IntKi) :: i, j, jFake, n + ! Default value for spacing is 1 if not provided + if (present(nSpace)) then; n=nSpace+1; else; n=2; endif + ! Default values are white values + M(:,:) = whiteVal + ! Setting black values everyother n values + do i=1,size(M,2) + do jFake=1,size(M,2),n ! everyother n values + j = mod(jFake+i-2, size(M,2)) +1 + !print*,'i,j',i,jFake,j + M(i,j) = blackVal + enddo + enddo + ! Forcing diagonal values + if (present(diagVal)) then + do i=1,size(M,1) + do j=1,size(M,2) ! Matrix not necessarily square + if (i==j) M(i,i) = diagVal + enddo + enddo + endif +end subroutine ChessBoard +!------------------------------------------------------------------------------------------------------ !> Partition matrices and vectors into Boundary (R) and internal (L) nodes !! M = [ MRR, MRL ] !! [ sym, MLL ] diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 1668feb0b..52b078fcf 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1745,8 +1745,12 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - integer(IntKi) :: iNode, JType, iStart + integer(IntKi) :: iNode, JType, iStart, i + integer(IntKi) :: nFreeRot ! Number of free rot DOF + integer(IntKi) :: nMembers ! Number of members attached to this node + integer(IntKi) :: nSpace ! Number of spaces between diagonal "bands" (0:pin, 1:univ, 2:ball) real(ReKi) :: StifAdd, DampAdd + real(ReKi), dimension(:,:), allocatable :: K_Add, D_Add ! Stiffness and damping matrix added to global system integer(IntKi), dimension(:), pointer :: Ifreerot ErrStat = ErrID_None ErrMsg = "" @@ -1766,47 +1770,32 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) endif else ! Ball/Univ/Pin joints have damping/stiffness inserted at indices of "free rotation" - if ( JType == idJointBall ) then; iStart=4; - else if ( JType == idJointUniversal ) then; iStart=5; - else if ( JType == idJointPin ) then; iStart=6; + nMembers = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + if ( JType == idJointBall ) then; iStart=4; nSpace=2; + else if ( JType == idJointUniversal ) then; iStart=5; nSpace=1; + else if ( JType == idJointPin ) then; iStart=6; nSpace=0; endif Ifreerot=>p%NodesDOFtilde(iNode)%List(iStart:) + nFreeRot = size(Ifreerot) + ! Creating matrices of 0, and -K and nK on diagonals + allocate(K_Add(1:nFreeRot,1:nFreeRot)); + allocate(D_Add(1:nFreeRot,1:nFreeRot)); + call ChessBoard(K_Add, -StifAdd, 0._ReKi, nSpace=nSpace, diagVal=(nMembers-1)*StifAdd) + call ChessBoard(D_Add, -DampAdd, 0._ReKi, nSpace=nSpace, diagVal=(nMembers-1)*DampAdd) ! Ball/Pin/Universal joints if(StifAdd>0) then - print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot - if ( JType == idJointPin ) then - print*,'>>>>>> Adding stiffness' - print*,'K (before)',Init%K(Ifreerot(1),Ifreerot) - print*,'K (before)',Init%K(Ifreerot(2),Ifreerot) - Init%K(Ifreerot(1),Ifreerot(1)) = Init%K(Ifreerot(1),Ifreerot(1)) + StifAdd - Init%K(Ifreerot(2),Ifreerot(2)) = Init%K(Ifreerot(2),Ifreerot(2)) + StifAdd - Init%K(Ifreerot(1),Ifreerot(2)) = Init%K(Ifreerot(1),Ifreerot(2)) - StifAdd - Init%K(Ifreerot(2),Ifreerot(1)) = Init%K(Ifreerot(2),Ifreerot(1)) - StifAdd - print*,'K (after)',Init%K(Ifreerot(1),Ifreerot) - print*,'K (after)',Init%K(Ifreerot(2),Ifreerot) - else - print*,'NOT READY' - STOP - Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd - endif + print*,'Stiffness Add, Node:',iNode,'DOF:', Ifreerot + do i=1,nFreeRot + print*,'K Add',K_Add(i,:) + enddo + Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + K_Add endif if(DampAdd>0) then - print*,'DampAdd, Node',iNode,DampAdd, Ifreerot - if ( JType == idJointPin ) then - print*,'>>>>>> Adding Damping' - print*,'D (before)',Init%D(Ifreerot(1),Ifreerot) - print*,'D (before)',Init%D(Ifreerot(2),Ifreerot) - Init%D(Ifreerot(1),Ifreerot(1)) = Init%D(Ifreerot(1),Ifreerot(1)) + DampAdd - Init%D(Ifreerot(2),Ifreerot(2)) = Init%D(Ifreerot(2),Ifreerot(2)) + DampAdd - Init%D(Ifreerot(1),Ifreerot(2)) = Init%D(Ifreerot(1),Ifreerot(2)) - DampAdd - Init%D(Ifreerot(2),Ifreerot(1)) = Init%D(Ifreerot(2),Ifreerot(1)) - DampAdd - print*,'D (after)',Init%D(Ifreerot(1),Ifreerot) - print*,'D (after)',Init%D(Ifreerot(2),Ifreerot) - else - print*,'NOT READY' - STOP - Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd - endif + print*,'Damping Add, Node:',iNode,'DOF:', Ifreerot + do i=1,nFreeRot + print*,'D Add',D_Add(i,:) + enddo + Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) + D_Add endif endif enddo diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index b80f476e3..99f7396dd 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -422,6 +422,51 @@ subroutine Test_lists(ErrStat,ErrMsg) call destroy_list(L2, ErrStat, ErrMsg) end subroutine Test_lists + !> Test CheckBoard (from FEM), useful for joint stiffness + subroutine Test_ChessBoard(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + real(ReKi), dimension(:,:), allocatable :: M, Mref + real(ReKi) :: L + integer(IntKi) :: I + ErrStat = ErrID_None + ErrMsg = "" + testname='ChessBoard' + allocate(M(1:6,1:6), Mref(1:6,1:6)) + ! Typical example for pin joint Stiffness add + Mref(1 , :)= (/4 , -1 , -1 , -1 , -1, -1/) + Mref(2 , :)= (/-1 , 4 , -1 , -1 , -1, -1/) + Mref(3 , :)= (/-1 , -1 , 4 , -1 , -1, -1/) + Mref(4 , :)= (/-1 , -1 , -1 , 4 , -1, -1/) + Mref(5 , :)= (/-1 , -1 , -1 , -1 , 4, -1/) + Mref(6 , :)= (/-1 , -1 , -1 , -1 , -1, 4/) + call ChessBoard(M, -1._ReKi, -10._ReKi, nSpace=0, diagVal=4._ReKi) + call test_almost_equal('ChessBoardPin', Mref, M, 1e-6_ReKi, .true., .true.) + + ! Typical example for universal joint Stiffness add + Mref=0.0_ReKi + Mref(1 , :)= (/2 , 0 , -1 , 0 , -1, 0 /) + Mref(2 , :)= (/0 , 2 , 0 , -1 , 0, -1 /) + Mref(3 , :)= (/-1 , 0 , 2 , 0 , -1, 0 /) + Mref(4 , :)= (/ 0 , -1 , 0 , 2 , 0, -1 /) + Mref(5 , :)= (/-1 , 0 , -1 , 0 , 2, 0 /) + Mref(6 , :)= (/ 0 , -1 , 0 , -1 , 0, 2 /) + call ChessBoard(M, -1._ReKi, 0._ReKi, nSpace=1, diagVal=2._ReKi) + call test_almost_equal('ChessBoardUnv', Mref, M, 1e-6_ReKi, .true., .true.) + + ! Typical example for ball joint Stiffness add + Mref(1 , :)= (/ 1 , 0 , 0 , -1 , 0, 0 /) + Mref(2 , :)= (/ 0 , 1 , 0 , 0 , -1, 0 /) + Mref(3 , :)= (/ 0 , 0 , 1 , 0 , 0, -1 /) + Mref(4 , :)= (/-1 , 0 , 0 , 1 , 0, 0 /) + Mref(5 , :)= (/ 0 , -1 , 0 , 0 , 1, 0 /) + Mref(6 , :)= (/ 0 , 0 , -1 , 0 , 0, 1 /) + call ChessBoard(M, -1._ReKi, 0._ReKi, nSpace=2, diagVal=1._ReKi) + call test_almost_equal('ChessBoardBll', Mref, M, 1e-6_ReKi, .true., .true.) + + deallocate(M,Mref) + end subroutine Test_ChessBoard + subroutine SD_Tests(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -431,9 +476,15 @@ subroutine SD_Tests(ErrStat,ErrMsg) ErrStat = ErrID_None ErrMsg = "" - call Test_lists(ErrStat2, ErrMsg2) - call Test_Transformations(ErrStat2, ErrMsg2) - call Test_Linalg(ErrStat2, ErrMsg2) + call Test_lists(ErrStat2, ErrMsg2); if(Failed()) return + call Test_Transformations(ErrStat2, ErrMsg2); if(Failed()) return + call Test_Linalg(ErrStat2, ErrMsg2); if(Failed()) return + call Test_ChessBoard(ErrStat2, ErrMsg2); if(Failed()) return + contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Tests') + Failed = ErrStat >= AbortErrLev + end function failed end subroutine SD_Tests From 62155df865d1013f24022f637fd1677141b6d587 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jul 2020 15:26:50 -0600 Subject: [PATCH 238/377] FlexSub: implemented Guyan damping (changes API) --- docs/source/user/api_change.rst | 46 + .../subdyn/examples/OC4_Jacket_SD_Input.dat | 356 +- modules/subdyn/src/SD_FEM.f90 | 8 +- modules/subdyn/src/SubDyn.f90 | 83 +- modules/subdyn/src/SubDyn_Registry.txt | 18 +- modules/subdyn/src/SubDyn_Types.f90 | 504 +- modules/subdyn/src_soildyn/FEM.f90 | 1215 ++ modules/subdyn/src_soildyn/IntegerList.f90 | 459 + modules/subdyn/src_soildyn/SD_FEM.f90 | 1897 +++ modules/subdyn/src_soildyn/SubDyn.f90 | 2885 ++++ modules/subdyn/src_soildyn/SubDyn_Driver.f90 | 342 + modules/subdyn/src_soildyn/SubDyn_Output.f90 | 804 ++ .../src_soildyn/SubDyn_Output_Params.f90 | 3723 +++++ .../subdyn/src_soildyn/SubDyn_Registry.txt | 269 + modules/subdyn/src_soildyn/SubDyn_Tests.f90 | 440 + modules/subdyn/src_soildyn/SubDyn_Types.f90 | 11876 ++++++++++++++++ modules/subdyn/src_soildyn/Yaml.f90 | 609 + modules/subdyn/src_soildyn/qsort_c_module.f90 | 61 + 18 files changed, 25391 insertions(+), 204 deletions(-) create mode 100644 modules/subdyn/src_soildyn/FEM.f90 create mode 100644 modules/subdyn/src_soildyn/IntegerList.f90 create mode 100644 modules/subdyn/src_soildyn/SD_FEM.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn_Driver.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn_Output.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn_Registry.txt create mode 100644 modules/subdyn/src_soildyn/SubDyn_Tests.f90 create mode 100644 modules/subdyn/src_soildyn/SubDyn_Types.f90 create mode 100644 modules/subdyn/src_soildyn/Yaml.f90 create mode 100644 modules/subdyn/src_soildyn/qsort_c_module.f90 diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index dfbc57dd9..a17515d64 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -9,6 +9,52 @@ The changes are tabulated according to the module input file, line number, and f The line number corresponds to the resulting line number after all changes are implemented. Thus, be sure to implement each in order so that subsequent line numbers are correct. +OpenFAST v2.3.0 to OpenFAST v2.4.0 +---------------------------------- + +Many changes were applied to SubDyn input file format. You may consult the following example: +:download:`(SubDyn's Input File) < subdyn/examples/OC4_Jacket_SD_Input.dat>`: +and the online SubDyn documentation. + +============================================= ==== =============== ======================================================================================================================================================================================================== +Added in OpenFAST v2.4.0 +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +============================================= ==== =============== ======================================================================================================================================================================================================== +SubDyn 8 ExtraMom False ExtraMoment - Include extra moment from lever arm at interface in interface reactions. +SubDyn 15 GuyanDampMod 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} +SubDyn 16 RayleighDamp 0.001, 0.003 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] +SubDyn 17 GuyanDampSize 6 GuyanDampSize - Guyan damping matrix size (square, 6x6) [only if GuyanDampMod=2] +SubDyn 18 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 +SubDyn -23 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 +SubDyn - CablesSection -------------------------- CABLE PROPERTIES ------------------------------------- +SubDyn - CablesSection 0 NCablePropSets - Number of cable cable properties +SubDyn - CablesSection PropSetID EA MatDens T0 +SubDyn - CablesSection (-) (N) (kg/m) (N) +SubDyn - RigidSection ---------------------- RIGID LINK PROPERTIES ------------------------------------ +SubDyn - RigidSection 0 NRigidPropSets - Number of rigid link properties +SubDyn - RigidSection PropSetID MatDens +SubDyn - RigidSection (-) (kg/m) +============================================= ==== =============== ======================================================================================================================================================================================================== + + +============================================= ==== =============== ======================================================================================================================================================================================================== +Changed in OpenFAST v2.4.0 +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +============================================= ==== =============== ======================================================================================================================================================================================================== +SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp +SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) +SubDyn - Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID +SubDyn - Members (-) (-) (-) (-) (-) (-) (-) +SubDyn - ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ +SubDyn - ConcentratedM (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) +============================================= ==== =============== ======================================================================================================================================================================================================== + + + + + OpenFAST v2.2.0 to OpenFAST v2.3.0 ---------------------------------- diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index bf12bb0c6..9e13f79d9 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -12,9 +12,9 @@ True ExtraMoment - Include extra moment from lever arm at interface True CBMod - [T/F] If True perform C-B reduction, else full FEM dofs will be retained. If True, select Nmodes to retain in C-B reduced system. 8 Nmodes - Number of internal modes to retain (ignored if CBMod=False). If Nmodes=0 --> Guyan Reduction. 1 JDampings - Damping Ratios for each retained mode (% of critical) If Nmodes>0, list Nmodes structural damping ratios for each retained mode (% of critical), or a single damping ratio to be applied to all retained modes. (last entered value will be used for all remaining modes). - 0 GuyanDampMod - Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] + 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} 0.000, 0.000 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] -Guyan damping matrix (6x6) [only if GuyanDampMod=2] + 6 GuyanDampMat - Guyan damping matrix (6x6) [only if GuyanDampMod=2] 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 @@ -23,72 +23,72 @@ Guyan damping matrix (6x6) [only if GuyanDampMod=2] 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 ---- STRUCTURE JOINTS: joints connect structure members (~Hydrodyn Input File)--- 64 NJoints - Number of joints (-) -JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp - (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) - 1 6.00000 6.00000 -45.50000 - 2 6.00000 6.00000 -45.00000 - 3 5.96700 5.96700 -44.00100 - 4 5.93900 5.93900 -43.12700 - 5 5.33300 5.33300 -24.61400 - 6 -6.00000 6.00000 -45.50000 - 7 -6.00000 6.00000 -45.00000 - 8 -5.96700 5.96700 -44.00100 - 9 -5.93900 5.93900 -43.12700 - 10 -5.33300 5.33300 -24.61400 - 11 -6.00000 -6.00000 -45.50000 - 12 -6.00000 -6.00000 -45.00000 - 13 -5.96700 -5.96700 -44.00100 - 14 -5.93900 -5.93900 -43.12700 - 15 -5.33300 -5.33300 -24.61400 - 16 6.00000 -6.00000 -45.50000 - 17 6.00000 -6.00000 -45.00000 - 18 5.96700 -5.96700 -44.00100 - 19 5.93900 -5.93900 -43.12700 - 20 5.33300 -5.33300 -24.61400 - 21 4.82000 4.82000 -8.92200 - 22 4.38500 4.38500 4.37800 - 23 4.01600 4.01600 15.65100 - 24 4.00000 4.00000 16.15000 - 25 -4.82000 4.82000 -8.92200 - 26 -4.38500 4.38500 4.37800 - 27 -4.01600 4.01600 15.65100 - 28 -4.00000 4.00000 16.15000 - 29 -4.82000 -4.82000 -8.92200 - 30 -4.38500 -4.38500 4.37800 - 31 -4.01600 -4.01600 15.65100 - 32 -4.00000 -4.00000 16.15000 - 33 4.82000 -4.82000 -8.92200 - 34 4.38500 -4.38500 4.37800 - 35 4.01600 -4.01600 15.65100 - 36 4.00000 -4.00000 16.15000 - 37 5.62000 0.00000 -33.37300 - 38 -5.62000 0.00000 -33.37300 - 39 0.00000 5.62000 -33.37300 - 40 0.00000 -5.62000 -33.37300 - 41 5.06400 0.00000 -16.37100 - 42 -5.06400 0.00000 -16.37100 - 43 0.00000 5.06400 -16.37100 - 44 0.00000 -5.06400 -16.37100 - 45 4.59200 0.00000 -1.95800 - 46 -4.59200 0.00000 -1.95800 - 47 0.00000 4.59200 -1.95800 - 48 0.00000 -4.59200 -1.95800 - 49 4.19300 0.00000 10.26200 - 50 -4.19300 0.00000 10.26200 - 51 0.00000 4.19300 10.26200 - 52 0.00000 -4.19300 10.26200 - 53 4.00000 4.00000 20.15000 - 54 -4.00000 4.00000 20.15000 - 55 4.00000 -4.00000 20.15000 - 56 -4.00000 -4.00000 20.15000 - 57 6.00000 -6.00000 -49.50000 - 58 6.00000 6.00000 -49.50000 - 59 -6.00000 -6.00000 -49.50000 - 60 -6.00000 6.00000 -49.50000 - 61 6.00000 -6.00000 -50.00100 - 62 6.00000 6.00000 -50.00100 - 63 -6.00000 -6.00000 -50.00100 - 64 -6.00000 6.00000 -50.00100 +JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp + (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) + 1 6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 + 2 6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 + 3 5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 + 4 5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 + 5 5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 + 6 -6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 + 7 -6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 + 8 -5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 + 9 -5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 + 10 -5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 + 11 -6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 + 12 -6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 + 13 -5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 + 14 -5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 + 15 -5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 + 16 6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 + 17 6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 + 18 5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 + 19 5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 + 20 5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 + 21 4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 + 22 4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 + 23 4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 + 24 4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 + 25 -4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 + 26 -4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 + 27 -4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 + 28 -4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 + 29 -4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 + 30 -4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 + 31 -4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 + 32 -4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 + 33 4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 + 34 4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 + 35 4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 + 36 4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 + 37 5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 + 38 -5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 + 39 0.00000 5.62000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 + 40 0.00000 -5.62000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 + 41 5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 0.0 + 42 -5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 0.0 + 43 0.00000 5.06400 -16.37100 1 0.0 0.0 0.0 0.0 0.0 + 44 0.00000 -5.06400 -16.37100 1 0.0 0.0 0.0 0.0 0.0 + 45 4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 0.0 + 46 -4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 0.0 + 47 0.00000 4.59200 -1.95800 1 0.0 0.0 0.0 0.0 0.0 + 48 0.00000 -4.59200 -1.95800 1 0.0 0.0 0.0 0.0 0.0 + 49 4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 0.0 + 50 -4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 0.0 + 51 0.00000 4.19300 10.26200 1 0.0 0.0 0.0 0.0 0.0 + 52 0.00000 -4.19300 10.26200 1 0.0 0.0 0.0 0.0 0.0 + 53 4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 + 54 -4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 + 55 4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 + 56 -4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 + 57 6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 + 58 6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 + 59 -6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 + 60 -6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 + 61 6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 + 62 6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 + 63 -6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 + 64 -6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 ------------------- BASE REACTION JOINTS: 1/0 for Locked/Free DOF @ each Reaction Node --------------------- 4 NReact - Number of Joints with reaction forces; be sure to remove all rigid motion DOFs of the structure (else det([K])=[0]) RJointID RctTDXss RctTDYss RctTDZss RctRDXss RctRDYss RctRDZss SSIfile [Global Coordinate System] @@ -115,116 +115,116 @@ MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID (-) (-) (-) (-) (-) (-) (-) 1 1 2 2 2 1 2 2 3 2 2 1 - 3 3 4 2 2 - 4 4 5 2 2 - 5 6 7 2 2 - 6 7 8 2 2 - 7 8 9 2 2 - 8 9 10 2 2 - 9 11 12 2 2 - 10 12 13 2 2 - 11 13 14 2 2 - 12 14 15 2 2 - 13 16 17 2 2 - 14 17 18 2 2 - 15 18 19 2 2 - 16 19 20 2 2 - 17 5 21 3 3 - 18 21 22 3 3 - 19 22 23 3 3 - 20 23 24 3 3 - 21 10 25 3 3 - 22 25 26 3 3 - 23 26 27 3 3 - 24 27 28 3 3 - 25 15 29 3 3 - 26 29 30 3 3 - 27 30 31 3 3 - 28 31 32 3 3 - 29 20 33 3 3 - 30 33 34 3 3 - 31 34 35 3 3 - 32 35 36 3 3 - 33 8 3 1 1 - 34 13 8 1 1 - 35 13 18 1 1 - 36 18 3 1 1 - 37 4 37 1 1 - 38 37 20 1 1 - 39 19 37 1 1 - 40 37 5 1 1 - 41 9 38 1 1 - 42 38 15 1 1 - 43 14 38 1 1 - 44 38 10 1 1 - 45 4 39 1 1 - 46 39 10 1 1 - 47 9 39 1 1 - 48 39 5 1 1 - 49 19 40 1 1 - 50 40 15 1 1 - 51 14 40 1 1 - 52 40 20 1 1 - 53 5 41 1 1 - 54 41 33 1 1 - 55 20 41 1 1 - 56 41 21 1 1 - 57 10 42 1 1 - 58 42 29 1 1 - 59 15 42 1 1 - 60 42 25 1 1 - 61 5 43 1 1 - 62 43 25 1 1 - 63 10 43 1 1 - 64 43 21 1 1 - 65 20 44 1 1 - 66 44 29 1 1 - 67 15 44 1 1 - 68 44 33 1 1 - 69 21 45 1 1 - 70 45 34 1 1 - 71 33 45 1 1 - 72 45 22 1 1 - 73 25 46 1 1 - 74 46 30 1 1 - 75 29 46 1 1 - 76 46 26 1 1 - 77 21 47 1 1 - 78 47 26 1 1 - 79 25 47 1 1 - 80 47 22 1 1 - 81 33 48 1 1 - 82 48 30 1 1 - 83 29 48 1 1 - 84 48 34 1 1 - 85 22 49 1 1 - 86 49 35 1 1 - 87 34 49 1 1 - 88 49 23 1 1 - 89 26 50 1 1 - 90 50 31 1 1 - 91 30 50 1 1 - 92 50 27 1 1 - 93 22 51 1 1 - 94 51 27 1 1 - 95 26 51 1 1 - 96 51 23 1 1 - 97 34 52 1 1 - 98 52 31 1 1 - 99 30 52 1 1 - 100 52 35 1 1 - 101 24 53 4 4 - 102 28 54 4 4 - 103 32 56 4 4 - 104 36 55 4 4 - 105 58 1 5 5 - 106 57 16 5 5 - 107 60 6 5 5 - 108 59 11 5 5 - 109 62 58 6 6 - 110 61 57 6 6 - 111 64 60 6 6 - 112 63 59 6 6 + 3 3 4 2 2 1 + 4 4 5 2 2 1 + 5 6 7 2 2 1 + 6 7 8 2 2 1 + 7 8 9 2 2 1 + 8 9 10 2 2 1 + 9 11 12 2 2 1 + 10 12 13 2 2 1 + 11 13 14 2 2 1 + 12 14 15 2 2 1 + 13 16 17 2 2 1 + 14 17 18 2 2 1 + 15 18 19 2 2 1 + 16 19 20 2 2 1 + 17 5 21 3 3 1 + 18 21 22 3 3 1 + 19 22 23 3 3 1 + 20 23 24 3 3 1 + 21 10 25 3 3 1 + 22 25 26 3 3 1 + 23 26 27 3 3 1 + 24 27 28 3 3 1 + 25 15 29 3 3 1 + 26 29 30 3 3 1 + 27 30 31 3 3 1 + 28 31 32 3 3 1 + 29 20 33 3 3 1 + 30 33 34 3 3 1 + 31 34 35 3 3 1 + 32 35 36 3 3 1 + 33 8 3 1 1 1 + 34 13 8 1 1 1 + 35 13 18 1 1 1 + 36 18 3 1 1 1 + 37 4 37 1 1 1 + 38 37 20 1 1 1 + 39 19 37 1 1 1 + 40 37 5 1 1 1 + 41 9 38 1 1 1 + 42 38 15 1 1 1 + 43 14 38 1 1 1 + 44 38 10 1 1 1 + 45 4 39 1 1 1 + 46 39 10 1 1 1 + 47 9 39 1 1 1 + 48 39 5 1 1 1 + 49 19 40 1 1 1 + 50 40 15 1 1 1 + 51 14 40 1 1 1 + 52 40 20 1 1 1 + 53 5 41 1 1 1 + 54 41 33 1 1 1 + 55 20 41 1 1 1 + 56 41 21 1 1 1 + 57 10 42 1 1 1 + 58 42 29 1 1 1 + 59 15 42 1 1 1 + 60 42 25 1 1 1 + 61 5 43 1 1 1 + 62 43 25 1 1 1 + 63 10 43 1 1 1 + 64 43 21 1 1 1 + 65 20 44 1 1 1 + 66 44 29 1 1 1 + 67 15 44 1 1 1 + 68 44 33 1 1 1 + 69 21 45 1 1 1 + 70 45 34 1 1 1 + 71 33 45 1 1 1 + 72 45 22 1 1 1 + 73 25 46 1 1 1 + 74 46 30 1 1 1 + 75 29 46 1 1 1 + 76 46 26 1 1 1 + 77 21 47 1 1 1 + 78 47 26 1 1 1 + 79 25 47 1 1 1 + 80 47 22 1 1 1 + 81 33 48 1 1 1 + 82 48 30 1 1 1 + 83 29 48 1 1 1 + 84 48 34 1 1 1 + 85 22 49 1 1 1 + 86 49 35 1 1 1 + 87 34 49 1 1 1 + 88 49 23 1 1 1 + 89 26 50 1 1 1 + 90 50 31 1 1 1 + 91 30 50 1 1 1 + 92 50 27 1 1 1 + 93 22 51 1 1 1 + 94 51 27 1 1 1 + 95 26 51 1 1 1 + 96 51 23 1 1 1 + 97 34 52 1 1 1 + 98 52 31 1 1 1 + 99 30 52 1 1 1 + 100 52 35 1 1 1 + 101 24 53 4 4 1 + 102 28 54 4 4 1 + 103 32 56 4 4 1 + 104 36 55 4 4 1 + 105 58 1 5 5 1 + 106 57 16 5 5 1 + 107 60 6 5 5 1 + 108 59 11 5 5 1 + 109 62 58 6 6 1 + 110 61 57 6 6 1 + 111 64 60 6 6 1 + 112 63 59 6 6 1 ------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table for circular-tubular elements] ------------------------ 6 NPropSets - Number of structurally unique x-sections (i.e. how many groups of X-sectional properties are utilized throughout all of the members) PropSetID YoungE ShearG MatDens XsecD XsecT diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 52b078fcf..b86614e7c 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -25,7 +25,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in - INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 ! 6 degrees of freedom (length of u subarray [UTP]) + INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 !TODO rename me ! 6 degrees of freedom (length of u subarray [UTP]) ! values of these parameters are ordered by their place in SubDyn input file: INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff JointDamp) @@ -70,6 +70,12 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idSIM_Full = 1 INTEGER(IntKi), PARAMETER :: idSIM_GravOnly = 2 INTEGER(IntKi) :: idSIM_Valid(3) = (/idSIM_None, idSIM_Full, idSIM_GravOnly /) + + ! Types of Guyan Damping + INTEGER(IntKi), PARAMETER :: idGuyanDamp_None = 0 + INTEGER(IntKi), PARAMETER :: idGuyanDamp_Rayleigh = 1 + INTEGER(IntKi), PARAMETER :: idGuyanDamp_66 = 2 + INTEGER(IntKi) :: idGuyanDamp_Valid(3) = (/idGuyanDamp_None, idGuyanDamp_Rayleigh, idGuyanDamp_66 /) INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b17a61a69..752da1e1a 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -489,10 +489,10 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D IF ( p%nDOFM > 0) THEN Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) - + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) ELSE ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) END IF ! Computing extra moments due to lever arm introduced by interface displacement @@ -713,6 +713,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! We still need to read the comment on the next line CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return else ! we have a actually read a comment line, we do nothing. + call LegacyWarning('ExtraMom line missing from input file. Assuming no extra moment.') p%ExtraMoment=.False. ! For Legacy, ExtraMoment is False endif @@ -785,8 +786,29 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings END IF +! --- Guyan damping +! For legacy, allowing these lines to be missing +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'GuyanDampMod', 'Guyan damping', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +if (is_numeric(Dummy_Str, DummyFloat)) then + Init%GuyanDampMod=int(DummyFloat) + CALL ReadAry( UnIn, SDInputFile, Init%RayleighDamp, 2, "RayleighDamp", "", ErrStat2, ErrMsg2, UnEc) + CALL ReadCom( UnIn, SDInputFile, 'Guyan damping matrix (6x6)' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(1,:), 6, "GuyanDampMat1", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(2,:), 6, "GuyanDampMat2", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(3,:), 6, "GuyanDampMat3", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(4,:), 6, "GuyanDampMat4", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(5,:), 6, "GuyanDampMat5", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(6,:), 6, "GuyanDampMat6", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) + CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +else + call LegacyWarning('GuyanDampMod and following lines missing from input file. Assuming 0 Guyan damping.') + Init%GuyanDampMod = idGuyanDamp_None + Init%RayleighDamp = 0.0_ReKi + Init%GuyanDampMat = 0.0_ReKi +endif +IF (Check(.not.(any(idGuyanDamp_Valid==Init%GuyanDampMod)), 'Invalid value entered for GuyanDampMod')) return + !--------------------- STRUCTURE JOINTS: joints connect structure members ------------------------------- -CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -804,13 +826,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) deallocate(StrArray) CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ); if(Failed()) return - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - print*,'Warning: Legacy joints table format detected in SubDyn input file!' - print*,' Some feature might be missing and only partial legacy support is provided.' - print*,' All joints are assumed cantilever, all members regular beams.' - print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' - print*,' Look at the SubDyn API changes to adapt your input files.' - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + call LegacyWarning('Joint table contains 4 columns instead of 10. All joints will be assumed cantilever, all members regular beams.') Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 @@ -860,7 +876,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); if (nColValid==1 .and. nColNumeric==1) then ! Temporary allowing this - print*,'Warning: SubDyn reaction line has only 1 column. Please use 7 or 8 values' + call LegacyWarning('SubDyn reaction line has only 1 column. Please use 7 or 8 values') else if (nColNumeric==7 .and.(nColValid==7.or.nColValid==8)) then ! This is fine. else @@ -1007,6 +1023,9 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Invalid concentrated mass JointID. Problematic line: "'//trim(Line)//'"') return endif + if (nColNumeric==5) then + call LegacyWarning('Using 5 values instead of 11 for concentrated mass. Off-diagonal terms will be assumed 0.') + endif ENDDO IF (Check( Init%nCMass < 0 , 'NCMass must be >=0')) return @@ -1109,6 +1128,15 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CONTAINS + subroutine LegacyWarning(Message) + character(len=*), intent(in) :: Message + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + print*,'Warning: the SubDyn input file is not at the latest format!' + print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' + print*,'> Issue: '//trim(Message) + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + end subroutine LegacyWarning + LOGICAL FUNCTION Check(Condition, ErrMsg_in) logical, intent(in) :: Condition character(len=*), intent(in) :: ErrMsg_in @@ -1879,6 +1907,22 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt + ! 6x6 Guyan Damping matrix + if (Init%GuyanDampMod == idGuyanDamp_None) then + ! No Damping + p%CBB=0.0_ReKi + elseif (Init%GuyanDampMod == idGuyanDamp_Rayleigh) then + ! Rayleigh Damping + p%CBB = Init%RayleighDamp(1) * p%MBB + Init%RayleighDamp(2) * p%KBB + elseif (Init%GuyanDampMod == idGuyanDamp_66) then + ! User 6x6 matrix + if (size(p%CBB,1)/=6) then + ErrMsg='Cannot use 6x6 Guyan Damping matrix, number of interface DOFs is'//num2lstr(size(p%CBB,1)); ErrStat=ErrID_Fatal; + return + endif + p%CBB = Init%GuyanDampMat + endif + !p%D1_15=-TI_transpose !this is 6x6NIN IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt @@ -1904,7 +1948,10 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) ENDDO - ! D1_13, D1_14 (with retained modes) + ! D1 Matrices + ! D1_12 = CBBt - MBmt*CmBt + p%D1_12 = p%CBB !TODO TODO cross coupling term + ! D1_13 = MBBt - MBmt*MmBt !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ) ! p%D1_13 = MATMUL( p%MBM, p%MMB ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -1967,9 +2014,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable - ! p%D1_13 = p%MBB in this case so we simplify the equations in the code, omitting storage of this variable - - ! D1_14 (with 0 retained modes) + p%D1_12 = p%CBB ! No cross couplings + p%D1_13 = p%MBB ! No cross couplings p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) ! FY (with 0 retained modes) @@ -2002,6 +2048,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%CBB, nDOFL_TP, nDOFL_TP, 'p%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2019,7 +2066,8 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D1_12, nDOFL_TP, nDOFL_TP , 'p%D1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 @@ -2595,9 +2643,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" + WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (Guyan DOFs)" call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) call yaml_write_array(UnSum, 'MBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'CBBt', p%CBB, 'E15.9', ErrStat2, ErrMsg2) ! Set TI2, transformation matrix from R DOFs to SubDyn Origin CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 12cde65d3..a3bb28f0e 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -41,6 +41,9 @@ typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector co typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi CBB {:}{:} - - "FULL CBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi CBM {:}{:} - - "FULL CBM ( no constraints applied)" +typedef ^ CB_MatArrays ReKi CMM {:}{:} - - "FULL CMM ( no constraints applied)" typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" @@ -84,6 +87,9 @@ typedef ^ ^ ReKi PropSetsX {:}{:} - - "Extended property sets" typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" +typedef ^ ^ IntKi GuyanDampMod - - - "Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix]" +typedef ^ ^ ReKi RayleighDamp {2} - - "Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1]" +typedef ^ ^ ReKi GuyanDampMat {6}{6} - - "Guyan Damping Matrix, see also CBB" typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" @@ -182,8 +188,9 @@ typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpo typedef ^ ParameterType ReKi FX {:} - - "Load components in X" typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of u in Y1" -typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of u in Y1" +typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" +typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" +typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" typedef ^ ParameterType ReKi FY {:} - - "Load Components in Y1" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" @@ -192,8 +199,11 @@ typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" -typedef ^ ParameterType ReKi MBB {:}{:} - - "Matrix after C-B reduction" -typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi MBB {:}{:} - - "Guyan Mass Matrix after C-B reduction" +typedef ^ ParameterType ReKi KBB {:}{:} - - "Guyan Stiffness Matrix after C-B reduction" +typedef ^ ParameterType ReKi CBB {:}{:} - - "Guyan Damping Matrix after C-B reduction" +typedef ^ ParameterType ReKi CBM {:}{:} - - "Cross coupling Guyan-CB damping matrix" +typedef ^ ParameterType ReKi CMM {:}{:} - - "CB damping matrix" typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi UL_st_g {:} - - "Motion of internal DOFs due to static gravitational force, for static improvement" typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index c87d586df..748c85bf1 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -73,6 +73,9 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< FULL CBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< FULL CBM ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< FULL CMM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] @@ -120,6 +123,9 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] + INTEGER(IntKi) :: GuyanDampMod !< Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] [-] + REAL(ReKi) , DIMENSION(1:2) :: RayleighDamp !< Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] [-] + REAL(ReKi) , DIMENSION(1:6,1:6) :: GuyanDampMat !< Guyan Damping Matrix, see also CBB [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] @@ -220,8 +226,9 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of u in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of u in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Load Components in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] @@ -230,8 +237,11 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_63 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_64 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F2_61 !< Load Component in Y2 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Guyan Mass Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Guyan Stiffness Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< Guyan Damping Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< Cross coupling Guyan-CB damping matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_st_g !< Motion of internal DOFs due to static gravitational force, for static improvement [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] @@ -1694,6 +1704,48 @@ SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCo END IF DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%CBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%CBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%CBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%CBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%CBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%CBB)) THEN + ALLOCATE(DstCB_MatArraysData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%CBB = SrcCB_MatArraysData%CBB +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%CBM)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%CBM,1) + i1_u = UBOUND(SrcCB_MatArraysData%CBM,1) + i2_l = LBOUND(SrcCB_MatArraysData%CBM,2) + i2_u = UBOUND(SrcCB_MatArraysData%CBM,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%CBM)) THEN + ALLOCATE(DstCB_MatArraysData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%CBM = SrcCB_MatArraysData%CBM +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%CMM)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%CMM,1) + i1_u = UBOUND(SrcCB_MatArraysData%CMM,1) + i2_l = LBOUND(SrcCB_MatArraysData%CMM,2) + i2_u = UBOUND(SrcCB_MatArraysData%CMM,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%CMM)) THEN + ALLOCATE(DstCB_MatArraysData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%CMM = SrcCB_MatArraysData%CMM +ENDIF IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) @@ -1754,6 +1806,15 @@ SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) IF (ALLOCATED(CB_MatArraysData%KBB)) THEN DEALLOCATE(CB_MatArraysData%KBB) ENDIF +IF (ALLOCATED(CB_MatArraysData%CBB)) THEN + DEALLOCATE(CB_MatArraysData%CBB) +ENDIF +IF (ALLOCATED(CB_MatArraysData%CBM)) THEN + DEALLOCATE(CB_MatArraysData%CBM) +ENDIF +IF (ALLOCATED(CB_MatArraysData%CMM)) THEN + DEALLOCATE(CB_MatArraysData%CMM) +ENDIF IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN DEALLOCATE(CB_MatArraysData%PhiL) ENDIF @@ -1815,6 +1876,21 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB END IF + Int_BufSz = Int_BufSz + 1 ! CBB allocated yes/no + IF ( ALLOCATED(InData%CBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBB) ! CBB + END IF + Int_BufSz = Int_BufSz + 1 ! CBM allocated yes/no + IF ( ALLOCATED(InData%CBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBM) ! CBM + END IF + Int_BufSz = Int_BufSz + 1 ! CMM allocated yes/no + IF ( ALLOCATED(InData%CMM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMM) ! CMM + END IF Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no IF ( ALLOCATED(InData%PhiL) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension @@ -1905,6 +1981,54 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%KBB) END IF + IF ( .NOT. ALLOCATED(InData%CBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBB))-1 ) = PACK(InData%CBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CBB) + END IF + IF ( .NOT. ALLOCATED(InData%CBM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBM))-1 ) = PACK(InData%CBM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CBM) + END IF + IF ( .NOT. ALLOCATED(InData%CMM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CMM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMM))-1 ) = PACK(InData%CMM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CMM) + END IF IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2064,6 +2188,84 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + SIZE(OutData%KBB) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CBB)) DEALLOCATE(OutData%CBB) + ALLOCATE(OutData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CBB)>0) OutData%CBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CBM)) DEALLOCATE(OutData%CBM) + ALLOCATE(OutData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CBM)>0) OutData%CBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CBM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CMM)) DEALLOCATE(OutData%CMM) + ALLOCATE(OutData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CMM)>0) OutData%CMM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CMM) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2500,6 +2702,9 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%JDampings = SrcInitTypeData%JDampings ENDIF + DstInitTypeData%GuyanDampMod = SrcInitTypeData%GuyanDampMod + DstInitTypeData%RayleighDamp = SrcInitTypeData%RayleighDamp + DstInitTypeData%GuyanDampMat = SrcInitTypeData%GuyanDampMat IF (ALLOCATED(SrcInitTypeData%Members)) THEN i1_l = LBOUND(SrcInitTypeData%Members,1) i1_u = UBOUND(SrcInitTypeData%Members,1) @@ -2966,6 +3171,9 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*1 ! JDampings upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%JDampings) ! JDampings END IF + Int_BufSz = Int_BufSz + 1 ! GuyanDampMod + Re_BufSz = Re_BufSz + SIZE(InData%RayleighDamp) ! RayleighDamp + Re_BufSz = Re_BufSz + SIZE(InData%GuyanDampMat) ! GuyanDampMat Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no IF ( ALLOCATED(InData%Members) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Members upper/lower bounds for each dimension @@ -3257,6 +3465,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%JDampings)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%JDampings))-1 ) = PACK(InData%JDampings,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%JDampings) END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%GuyanDampMod + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RayleighDamp))-1 ) = PACK(InData%RayleighDamp,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%RayleighDamp) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%GuyanDampMat))-1 ) = PACK(InData%GuyanDampMat,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%GuyanDampMat) IF ( .NOT. ALLOCATED(InData%Members) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3869,6 +4083,32 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%JDampings) DEALLOCATE(mask1) END IF + OutData%GuyanDampMod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RayleighDamp,1) + i1_u = UBOUND(OutData%RayleighDamp,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%RayleighDamp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RayleighDamp))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%RayleighDamp) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%GuyanDampMat,1) + i1_u = UBOUND(OutData%GuyanDampMat,1) + i2_l = LBOUND(OutData%GuyanDampMat,2) + i2_u = UBOUND(OutData%GuyanDampMat,2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + OutData%GuyanDampMat = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%GuyanDampMat))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%GuyanDampMat) + DEALLOCATE(mask2) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6520,6 +6760,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%C1_12 = SrcParamData%C1_12 ENDIF +IF (ALLOCATED(SrcParamData%D1_12)) THEN + i1_l = LBOUND(SrcParamData%D1_12,1) + i1_u = UBOUND(SrcParamData%D1_12,1) + i2_l = LBOUND(SrcParamData%D1_12,2) + i2_u = UBOUND(SrcParamData%D1_12,2) + IF (.NOT. ALLOCATED(DstParamData%D1_12)) THEN + ALLOCATE(DstParamData%D1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_12 = SrcParamData%D1_12 +ENDIF IF (ALLOCATED(SrcParamData%D1_13)) THEN i1_l = LBOUND(SrcParamData%D1_13,1) i1_u = UBOUND(SrcParamData%D1_13,1) @@ -6684,6 +6938,48 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%KBB = SrcParamData%KBB ENDIF +IF (ALLOCATED(SrcParamData%CBB)) THEN + i1_l = LBOUND(SrcParamData%CBB,1) + i1_u = UBOUND(SrcParamData%CBB,1) + i2_l = LBOUND(SrcParamData%CBB,2) + i2_u = UBOUND(SrcParamData%CBB,2) + IF (.NOT. ALLOCATED(DstParamData%CBB)) THEN + ALLOCATE(DstParamData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CBB = SrcParamData%CBB +ENDIF +IF (ALLOCATED(SrcParamData%CBM)) THEN + i1_l = LBOUND(SrcParamData%CBM,1) + i1_u = UBOUND(SrcParamData%CBM,1) + i2_l = LBOUND(SrcParamData%CBM,2) + i2_u = UBOUND(SrcParamData%CBM,2) + IF (.NOT. ALLOCATED(DstParamData%CBM)) THEN + ALLOCATE(DstParamData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CBM = SrcParamData%CBM +ENDIF +IF (ALLOCATED(SrcParamData%CMM)) THEN + i1_l = LBOUND(SrcParamData%CMM,1) + i1_u = UBOUND(SrcParamData%CMM,1) + i2_l = LBOUND(SrcParamData%CMM,2) + i2_u = UBOUND(SrcParamData%CMM,2) + IF (.NOT. ALLOCATED(DstParamData%CMM)) THEN + ALLOCATE(DstParamData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CMM = SrcParamData%CMM +ENDIF IF (ALLOCATED(SrcParamData%MBM)) THEN i1_l = LBOUND(SrcParamData%MBM,1) i1_u = UBOUND(SrcParamData%MBM,1) @@ -7155,6 +7451,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%C1_12)) THEN DEALLOCATE(ParamData%C1_12) ENDIF +IF (ALLOCATED(ParamData%D1_12)) THEN + DEALLOCATE(ParamData%D1_12) +ENDIF IF (ALLOCATED(ParamData%D1_13)) THEN DEALLOCATE(ParamData%D1_13) ENDIF @@ -7191,6 +7490,15 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%KBB)) THEN DEALLOCATE(ParamData%KBB) ENDIF +IF (ALLOCATED(ParamData%CBB)) THEN + DEALLOCATE(ParamData%CBB) +ENDIF +IF (ALLOCATED(ParamData%CBM)) THEN + DEALLOCATE(ParamData%CBM) +ENDIF +IF (ALLOCATED(ParamData%CMM)) THEN + DEALLOCATE(ParamData%CMM) +ENDIF IF (ALLOCATED(ParamData%MBM)) THEN DEALLOCATE(ParamData%MBM) ENDIF @@ -7455,6 +7763,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! C1_12 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C1_12) ! C1_12 END IF + Int_BufSz = Int_BufSz + 1 ! D1_12 allocated yes/no + IF ( ALLOCATED(InData%D1_12) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_12 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_12) ! D1_12 + END IF Int_BufSz = Int_BufSz + 1 ! D1_13 allocated yes/no IF ( ALLOCATED(InData%D1_13) ) THEN Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension @@ -7515,6 +7828,21 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB END IF + Int_BufSz = Int_BufSz + 1 ! CBB allocated yes/no + IF ( ALLOCATED(InData%CBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBB) ! CBB + END IF + Int_BufSz = Int_BufSz + 1 ! CBM allocated yes/no + IF ( ALLOCATED(InData%CBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CBM) ! CBM + END IF + Int_BufSz = Int_BufSz + 1 ! CMM allocated yes/no + IF ( ALLOCATED(InData%CMM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMM) ! CMM + END IF Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no IF ( ALLOCATED(InData%MBM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension @@ -8077,6 +8405,22 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%C1_12)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C1_12))-1 ) = PACK(InData%C1_12,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%C1_12) END IF + IF ( .NOT. ALLOCATED(InData%D1_12) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_12,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_12,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_12,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_12,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D1_12)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_12))-1 ) = PACK(InData%D1_12,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D1_12) + END IF IF ( .NOT. ALLOCATED(InData%D1_13) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8263,6 +8607,54 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%KBB) END IF + IF ( .NOT. ALLOCATED(InData%CBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBB))-1 ) = PACK(InData%CBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CBB) + END IF + IF ( .NOT. ALLOCATED(InData%CBM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBM))-1 ) = PACK(InData%CBM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CBM) + END IF + IF ( .NOT. ALLOCATED(InData%CMM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CMM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMM))-1 ) = PACK(InData%CMM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CMM) + END IF IF ( .NOT. ALLOCATED(InData%MBM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9315,6 +9707,32 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%C1_12) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_12 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_12)) DEALLOCATE(OutData%D1_12) + ALLOCATE(OutData%D1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D1_12)>0) OutData%D1_12 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_12))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D1_12) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9621,6 +10039,84 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%KBB) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CBB)) DEALLOCATE(OutData%CBB) + ALLOCATE(OutData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CBB)>0) OutData%CBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CBM)) DEALLOCATE(OutData%CBM) + ALLOCATE(OutData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CBM)>0) OutData%CBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CBM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CMM)) DEALLOCATE(OutData%CMM) + ALLOCATE(OutData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CMM)>0) OutData%CMM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CMM) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/subdyn/src_soildyn/FEM.f90 b/modules/subdyn/src_soildyn/FEM.f90 new file mode 100644 index 000000000..d96fac91e --- /dev/null +++ b/modules/subdyn/src_soildyn/FEM.f90 @@ -0,0 +1,1215 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +!********************************************************************************************************************************** +!> Standalone tools for beam-based finite element method (FEM) +!! No dependency with SubDyn types and representation +MODULE FEM + USE NWTC_Library + IMPLICIT NONE + + INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors + +CONTAINS +!------------------------------------------------------------------------------------------------------ +!> Return eigenvalues, Omega, and eigenvectors +SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) + USE NWTC_LAPACK, only: LAPACK_ggev + USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT + INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K + REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix + REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix + LOGICAL, INTENT(IN ) :: bCheckSingularity !< If True, check for singularities + REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors + REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! LOCALS + REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables + INTEGER :: i + INTEGER :: LWORK !variables for the eigensolver + INTEGER, ALLOCATABLE :: KEY(:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = '' + + ! allocate working arrays and return arrays for the eigensolver + LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine + !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out + CALL AllocAry( Work, LWORK, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAR, N, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( ALPHAI, N, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( BETA, N, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( VL, N, N, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( KEY, N, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! --- Eigenvalue analysis + ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. + ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 + ! bjj: This comes from the LAPACK documentation: + ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). + ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted + CALL LAPACK_ggev('N','V',N ,K, M, ALPHAR, ALPHAI, BETA, VL, EigVect, WORK, LWORK, ErrStat2, ErrMsg2) + if(Failed()) return + + ! --- Determinign and sorting eigen frequencies + DO I=1,N !Initialize the key and calculate Omega + KEY(I)=I + IF ( AlphaR(I)<0.0_LAKi ) THEN + !print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif + !ELSE IF ( .not.EqualRealNos(AlphaI(I),0.0_LAKi )) THEN + ! print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) + ! ErrStat2=ErrID_Fatal + ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' + ! if(Failed()) return + ELSE IF ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) THEN + Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif + ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_ReKi) ) THEN + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' + if(Failed()) return + endif + ELSE + Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) + END IF + ENDDO + ! Sorting + CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return + + ! --- Sorting eigen vectors + ! KEEP ME: scaling of the eigenvectors using generalized mass =identity criterion + ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) + ! result1 = matmul(M,EigVect) + ! result2 = matmul(transpose(EigVect),result1) + ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors + ! normcoeff=sqrt(matmul(transpose(EigVect),matmul(M,EigVect))) !This should be a diagonal matrix which contains the normalization factors + VL=EigVect !temporary storage for sorting EigVect + DO I=1,N + !EigVect(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized + EigVect(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one + ENDDO + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + CALL CleanupEigen() + RETURN + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + + SUBROUTINE CleanupEigen() + IF (ALLOCATED(Work) ) DEALLOCATE(Work) + IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) + IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) + IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) + IF (ALLOCATED(VL) ) DEALLOCATE(VL) + IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) + END SUBROUTINE CleanupEigen + +END SUBROUTINE EigenSolve + +!> Compute the determinant of a real matrix using an LU factorization +FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) + use NWTC_LAPACK, only: LAPACK_GETRF + REAL(LaKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(LaKi) :: det !< May easily overflow + integer(IntKi) :: i + integer :: n + integer, allocatable :: ipiv(:) + real(LaKi), allocatable :: PLU(:,:) + real(LaKi) :: ScaleVal + + n = size(A(1,:)) + allocate(PLU(n,n)) + allocate(ipiv(n)) + ScaleVal= 1.0_LaKi + PLU = A/ScaleVal + ! general matrix factorization: Factor matrix into A=PLU. + call LAPACK_GETRF( n, n, PLU, ipiv, ErrStat, ErrMsg ) !call dgetrf(n, n, PLU, n, ipiv, info) + if (ErrStat==ErrID_Fatal) then + print*,'Error in getrf' + det = 0 + deallocate(PLU) + deallocate(ipiv) + return + endif + ! PLU now contains the LU of the factorization A = PLU + ! As L has unit diagonal entries, the determinant can be computed + ! from the product of U's diagonal entries. Additional sign changes + ! stemming from the permutations P have to be taken into account as well. + det = 1.0_LaKi + do i = 1,n + if(ipiv(i) /= i) then ! additional sign change + det = -det*PLU(i,i) + else + det = det*PLU(i,i) + endif + end do + deallocate(PLU) + deallocate(ipiv) + IF ( EqualRealNos(real(det, ReKi), 0.0_ReKi) ) THEN + print*,'Det is zero' + return + else + det = det*(ScaleVal**n) + endif +END FUNCTION Determinant +!------------------------------------------------------------------------------------------------------ +!> Partition matrices and vectors into Boundary (R) and internal (L) nodes +!! M = [ MRR, MRL ] +!! [ sym, MLL ] +!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FR = F(IDR) +!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) +!! MRL = M(IDR, IDL), KRR = K(IDR, IDL) +!! NOTE: generic code +SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) + REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix + REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix + INTEGER(IntKi), INTENT(IN ) :: nR + INTEGER(IntKi), INTENT(IN ) :: nL + INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs + INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs + REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) + REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) + REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) + REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) + REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) + INTEGER(IntKi) :: I, J, II, JJ + + ! RR: Leader/Boundary DOFs + DO I = 1, nR + II = IDR(I) + DO J = 1, nR + JJ = IDR(J) + MRR(I, J) = MM(II, JJ) + KRR(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! LL: Interior/follower DOFs + DO I = 1, nL + II = IDL(I) + DO J = 1, nL + JJ = IDL(J) + MLL(I, J) = MM(II, JJ) + KLL(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! RL: cross terms + DO I = 1, nR + II = IDR(I) + DO J = 1, nL + JJ = IDL(J) + MRL(I, J) = MM(II, JJ) + KRL(I, J) = KK(II, JJ) + ENDDO + ENDDO + ! Forces + if (present(FG)) then + if (present(FGR)) then + do I = 1, nR + II = IDR(I) + FGR(I) = FG(II) + enddo + endif + if (present(FGL)) then + do I = 1, nL + II = IDL(I) + FGL(I) = FG(II) + enddo + endif + endif +END SUBROUTINE BreakSysMtrx + +!------------------------------------------------------------------------------------------------------ +!> Performs Craig-Bampton reduction of M and K matrices and optional Force vector +!! TODO: (Damping optional) +!! Convention is: +!! "R": leader DOF -> "B": reduced leader DOF +!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) +!! NOTE: +!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned +!! - Possibility to get more CB modes using the input nM_Out>nM +!! +!! NOTE: generic code +SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM) + REAL(ReKi), INTENT(IN ) :: MM(:, :) !< Mass matrix + REAL(ReKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix + INTEGER(IntKi), INTENT(IN ) :: nR + INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs + INTEGER(IntKi), INTENT(IN ) :: nL + INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs + INTEGER(IntKi), INTENT(IN ) :: nM !< Number of CB modes + INTEGER(IntKi), INTENT(IN ) :: nM_Out !< Number of modes returned for PhiL & OmegaL + REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) !< Reduced Guyan Mass Matrix + REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) !< Reduced Guyan Stiffness matrix + REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) !< Cross term + REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_out) !< Craig-Bampton modes + REAL(ReKi), INTENT( OUT) :: OmegaL(nM_out) !< Eigenvalues + REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector (typically a constant force, like gravity) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) !< Force vector partitioned for R DOFs (TODO remove me) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL + REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' + ! Partitioned variables + real(ReKi), allocatable :: MRR(:, :) + real(ReKi), allocatable :: MLL(:, :) + real(ReKi), allocatable :: MRL(:, :) + real(ReKi), allocatable :: KRR(:, :) + real(ReKi), allocatable :: KLL(:, :) + real(ReKi), allocatable :: KRL(:, :) + ! --- Break system + CALL AllocAry(MRR, nR, nR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(MLL, nL, nL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(MRL, nR, nL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KRR, nR, nR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KLL, nL, nL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(KRL, nR, nL, 'matrix KRL', ErrStat2, ErrMsg2 ); if(Failed()) return + if (present(FG).and.present(FGR).and.present(FGL)) then + call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) + else + call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL) + endif + ! --- CB reduction + call CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& !< Inputs + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) !< Outputs + if(Failed()) return + + ! --- Reduction of force if provided + if (present(FG).and.present(FGR).and.present(FGL)) then + if (present(FGM)) then + FGB = FGR + matmul( transpose(PhiR), FGL) + endif + if (present(FGB)) then + FGM = matmul( FGL, PhiL(:,1:nM) ) != matmul( transpose(PhiM), FGL ) because FGL is 1-D + endif + endif + call CleanUp() + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) + IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) + IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) + IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) + IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) + IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) + end subroutine +END SUBROUTINE CraigBamptonReduction + +!------------------------------------------------------------------------------------------------------ +!> Performs Craig-Bampton reduction based on partitioned matrices M and K +!! Convention is: +!! "R": leader DOF -> "B": reduced leader DOF +!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) +!! NOTE: +!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned +!! - Possibility to get more CB modes using the input nM_Out>nM (e.g. for static improvement) +!! +!! NOTE: generic code +SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) + USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf + INTEGER(IntKi), INTENT( in) :: nR + INTEGER(IntKi), INTENT( in) :: nL + INTEGER(IntKi), INTENT( in) :: nM_Out + INTEGER(IntKi), INTENT( in) :: nM + REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Paritioned matrices + REAL(ReKi), INTENT( IN) :: MLL( nL, nL) + REAL(ReKi), INTENT( IN) :: MRL( nR, nL) + REAL(ReKi), INTENT( IN) :: KRR( nR, nR) + REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) + REAL(ReKi), INTENT( IN) :: KRL( nR, nL) + REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) + REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) + REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) + REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes + REAL(ReKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! LOCAL VARIABLES + REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] + REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(nR,nL) = transpose of PhiR * MLL (temporary storage) + INTEGER :: I !counter + INTEGER :: ipiv(nL) ! length min(m,n) (See LAPACK documentation) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' + ErrStat = ErrID_None + ErrMsg = '' + + if (nM_out>nL) then + ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; + if(Failed()) return; + endif + if (nM_out 0 ) then + ! bCheckSingularity = True + CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return + ! --- Normalize PhiL + ! bjj: break up this equation to avoid as many temporary variables on the stack + ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) + CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , nM_out, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + MU = TRANSPOSE(PhiL) + Temp = MATMUL( MU, MLL ) + MU(1:nM_Out,1:nM_Out) = MATMUL( Temp, PhiL ) + DEALLOCATE(Temp) + ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) + DO I = 1, nM_out + PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) + ENDDO + DEALLOCATE(MU) + else + PhiL = 0.0_ReKi + OmegaL = 0.0_ReKi + end if + + if (nL>0) then + ! --- Compute Guyan Modes (PhiR) + ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) + ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** + CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return + + PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) + CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return + + ! --- Set MBB, MBM, and KBB from Eq. 4: + CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return + + PhiR_T_MLL = TRANSPOSE(PhiR) + PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) + MBB = MATMUL(MRL, PhiR) + MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) + + IF ( nM == 0) THEN + MBM = 0.0_ReKi + ELSE + MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation + MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM + ENDIF + + KBB = MATMUL(KRL, PhiR) + KBB = KBB + KRR + else + PhiR(1:nL,1:nR) = 0.0_ReKi ! Empty + MBM (1:nR,1:nM) = 0.0_ReKi ! Empty + MBB = MRR + KBB = KRR + endif + + call CleanUp() +CONTAINS + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction_FromPartition') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + if (allocated(Mu )) DEALLOCATE(Mu ) + if (allocated(Temp )) DEALLOCATE(Temp ) + if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) + end subroutine +END SUBROUTINE CraigBamptonReduction_FromPartition + +!------------------------------------------------------------------------------------------------------ +!> Wrapper function for eigen value analyses, for two cases: +!! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix +!! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system +SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) + INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system + REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix + REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix + INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues + LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present + REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors + REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) + + ! LOCALS + REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) + REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) + REAL(ReKi) :: Om2 + INTEGER(IntKi) :: N, i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = '' + + ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi + if (present(bDOF)) then + ! Remove unwanted DOFs + call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + else + N=size(K,1) + CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return + K_LaKi = real( K, LaKi ) + M_LaKi = real( M, LaKi ) + endif + N=size(K_LaKi,1) + + ! Note: NOmega must be <= N, which is the length of Omega2, Phi! + if ( NOmega > nDOF ) then + CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') + CALL CleanupEigen() + return + end if + + + ! --- Eigenvalue analysis + CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; + CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + + ! --- Setting up Phi, and type conversion + do i = 1, NOmega + if (abs(Omega2_LaKi(i))>huge(1.0_ReKi)) then + Om2 = huge(1.0_ReKi) * sign(1.0_LaKi, Omega2_LaKi(i)) + else + Om2 = real(Omega2_LaKi(i), ReKi) + endif + if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics + Omega(i)=0.0_ReKi + elseif (Om2>0) then + Omega(i)=sqrt(Om2) ! was getting floating invalid + else + print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 + Omega(i)= 0.0_ReKi + endif + enddo + if (present(bDOF)) then + ! Insert 0s where bDOF was false + CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return + else + EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors + endif + CALL CleanupEigen() + return +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpEigen() + END FUNCTION Failed + + SUBROUTINE CleanupEigen() + IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) + IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) + IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) + IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) + END SUBROUTINE CleanupEigen + +END SUBROUTINE EigenSolveWrap +!------------------------------------------------------------------------------------------------------ +!> Remove degrees of freedom from a matrix (lines and rows) +SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) + REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix + logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) + REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER :: I, J ! counters into full matrix + INTEGER :: Ir, Jr ! counters into reduced matrix + INTEGER :: nr ! number of reduced DOF + ErrStat = ErrID_None + ErrMsg = '' + + nr= count(bDOF) + CALL AllocAry(Ared, nr, nr, 'Ared', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return + + ! Remove rows and columns from A when bDOF is + Jr=0 + do J = 1, size(A,1) + if (bDOF(J)) then + Jr=Jr+1 + Ir=0 + do I = 1, size(A,1) + if (bDOF(I)) then + Ir=Ir+1 + Ared(Ir, Jr) = REAL( A(I, J), LAKi ) + end if + end do + endif + end do +END SUBROUTINE RemoveDOF + +!> Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) +SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) + REAL(LAKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix + logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) + REAL(ReKi), INTENT(IN ) :: DefaultVal ! Default value to fill the + REAL(ReKi) , INTENT(INOUT) :: A(:,:) ! Full matrix + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + INTEGER :: I ! counter into full matrix + INTEGER :: Ir ! counter into reduced matrix + INTEGER :: n ! number of DOF (fullsystem) + ErrStat = ErrID_None + ErrMsg = '' + n= size(bDOF) + IF ( size(Ared,1) > n) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'InsertDOFrows: Number of reduced rows needs to be lower than full system rows' + RETURN + END IF + IF ( size(Ared,2) /= size(A,2) ) THEN + ErrStat = ErrID_Fatal + ErrMsg = 'InsertDOFrows: Inconsistent number of columns between A and Ared' + RETURN + END IF + !CALL AllocAry(A, n, size(Ared,2), 'A', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return + + ! Use rows from Ared when bDOF is true, use default value otherwise + ir=0 ! initialize + do i=1,n + if (bDOF(i)) then + ir =ir +1 + A(i,:)=real( Ared(ir,:), ReKi ) + else + A(i,:)=DefaultVal + endif + enddo +END SUBROUTINE InsertDOFrows +!------------------------------------------------------------------------------------------------------ +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_ReKi(Array, Val) result(i) + real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == NINT(Array(i)) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION +!> Returns index of val in Array (val is an integer!) +! NOTE: in the future use intrinsinc function findloc +FUNCTION FINDLOCI_IntKi(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 +END FUNCTION +!------------------------------------------------------------------------------------------------------ +SUBROUTINE RigidTransformationLine(dx,dy,dz,iLine,Line) + real(ReKi), INTENT(IN) :: dx,dy,dz + integer(IntKi) , INTENT(IN) :: iLine + Real(ReKi), dimension(6), INTENT(OUT) :: Line + SELECT CASE (iLine) + CASE (1); Line = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) + CASE (2); Line = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) + CASE (3); Line = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) + CASE (4); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) + CASE (5); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) + CASE (6); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) + CASE DEFAULT + Line=-99999999_ReKi + print*,'Error in RigidTransformationLine' + STOP +! ErrStat = ErrID_Fatal +! ErrMsg = 'Error calculating transformation matrix TI ' +! return + END SELECT +END SUBROUTINE +!------------------------------------------------------------------------------------------------------ +!> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. +SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) + REAL(ReKi), INTENT(IN ) :: Pj(3) ! (x,y,z) positions of leader node + REAL(ReKi), INTENT(IN ) :: Pk(3) ! (x,y,z) positions of follower node + REAL(ReKi), INTENT( OUT) :: TRigid(6,6) ! Transformation matrix such that xk = T.xj + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local + !REAL(ReKi) :: L ! length of element + !REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrix + !REAL(ReKi) :: R0(3,3) + integer(IntKi) :: I + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Formulation using Delta of Global coordinates + Trigid=0; do I = 1,6; Trigid(I,I) = 1; enddo + Trigid ( 1, 5 ) = (Pk(3) - Pj(3)) + Trigid ( 1, 6 ) = -(Pk(2) - Pj(2)) + Trigid ( 2, 4 ) = -(Pk(3) - Pj(3)) + Trigid ( 2, 6 ) = (Pk(1) - Pj(1)) + Trigid ( 3, 4 ) = (Pk(2) - Pj(2)) + Trigid ( 3, 5 ) = -(Pk(1) - Pj(1)) + + ! --- Formulation bty transforming the "local" matrix into a global one + !call GetDirCos(Pj, Pk, R0, L, ErrStat, ErrMsg) + !TRigid = 0 ; do I = 1,6; TRigid(I,I) = 1; enddo + !TRigid (1, 5) = L + !TRigid (2, 4) = -L + !TRigid(1:3,4:6) = matmul( R0 , matmul(TRigid(1:3,4:6), transpose(R0)) ) + + ! --- Formulation using L and Rotation matrix + !TRigid = 0; do I = 1,6; TRigid(I,I) = 1; enddo + !TRigid ( 1, 5 ) = L*R0(3,3) + !TRigid ( 1, 6 ) = -L*R0(2,3) + !TRigid ( 2, 4 ) = -L*R0(3,3) + !TRigid ( 2, 6 ) = L*R0(1,3) + !TRigid ( 3, 4 ) = L*R0(2,3) + !TRigid ( 3, 5 ) = -L*R0(1,3) +END SUBROUTINE GetRigidTransformation +!------------------------------------------------------------------------------------------------------ +!> Computes directional cosine matrix DirCos +!! Transforms from element to global coordinates: xg = DC.xe, Kg = DC.Ke.DC^t +!! Assumes that the element main direction is along ze. +!! +!! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix +!! in the FAST framework. +SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) + REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element + REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix + REAL(ReKi) , INTENT( OUT) :: L ! length of element + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + REAL(ReKi) :: Dx, Dy, Dz, Dxy ! distances between nodes + ErrMsg = "" + ErrStat = ErrID_None + + Dx=P2(1)-P1(1) + Dy=P2(2)-P1(2) + Dz=P2(3)-P1(3) + Dxy = sqrt( Dx**2 + Dy**2 ) + L = sqrt( Dx**2 + Dy**2 + Dz**2) + + IF ( EqualRealNos(L, 0.0_ReKi) ) THEN + ErrMsg = ' Same starting and ending location in the element.' + ErrStat = ErrID_Fatal + RETURN + ENDIF + + IF ( EqualRealNos(Dxy, 0.0_ReKi) ) THEN + DirCos=0.0_ReKi ! whole matrix set to 0 + IF ( Dz < 0) THEN !x is kept along global x + DirCos(1, 1) = 1.0_ReKi + DirCos(2, 2) = -1.0_ReKi + DirCos(3, 3) = -1.0_ReKi + ELSE + DirCos(1, 1) = 1.0_ReKi + DirCos(2, 2) = 1.0_ReKi + DirCos(3, 3) = 1.0_ReKi + ENDIF + ELSE + DirCos(1, 1) = Dy/Dxy + DirCos(1, 2) = +Dx*Dz/(L*Dxy) + DirCos(1, 3) = Dx/L + + DirCos(2, 1) = -Dx/Dxy + DirCos(2, 2) = +Dz*Dy/(L*Dxy) + DirCos(2, 3) = Dy/L + + DirCos(3, 1) = 0.0_ReKi + DirCos(3, 2) = -Dxy/L + DirCos(3, 3) = +Dz/L + ENDIF + +END SUBROUTINE GetDirCos +!------------------------------------------------------------------------------------------------------ +!> Returns two vectors orthonormal to the input vector +SUBROUTINE GetOrthVectors(e1, e2, e3, ErrStat, ErrMsg) + real(ReKi) , intent(in ) :: e1(3) !< + real(ReKi) , intent( out) :: e2(3) !< + real(ReKi) , intent( out) :: e3(3) !< + integer(IntKi), intent( out) :: ErrStat ! error status of the operation + character(*), intent( out) :: ErrMsg ! error message if errstat /= errid_none + real(ReKi) :: min_norm + real(ReKi) :: e2_norm + real(ReKi) :: e1b(3) + ErrMsg = "" + ErrStat = ErrID_None + + min_norm = min( abs(e1(1)), abs(e1(2)), abs(e1(3)) ) + ! Finding a good candidate for orthogonality + if (min_norm == abs(e1(1))) then; e2 = (/ 0._ReKi, -e1(3), e1(2) /) + else if (min_norm == abs(e1(2))) then; e2 = (/ e1(3) , 0._ReKi, -e1(1) /) + else if (min_norm == abs(e1(3))) then; e2 = (/-e1(2) , e1(1), 0._ReKi /) + endif + ! Normalizing + e2_norm=sqrt(e2(1)**2 + e2(2)**2 + e2(3)**2) + if (abs(e2_norm)<1e-8) then + ErrStat=ErrID_Fatal + ErrMsg='Failed to determine orthogonal vector' + e2=-99999._ReKi + e3=-99999._ReKi + return + endif + e2 = e2/e2_norm + e1b= e1/sqrt(e1(1)**2 + e1(2)**2 + e1(3)**2) + ! Third + e3 = cross_product(e1b,e2) +END SUBROUTINE GetOrthVectors +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for classical beam elements +!! shear is true -- non-tapered Timoshenko beam +!! shear is false -- non-tapered Euler-Bernoulli beam +SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + LOGICAL , INTENT( IN) :: Shear + REAL(ReKi), INTENT(OUT) :: K(12, 12) + ! Local variables + REAL(ReKi) :: Ax, Ay, Kx, Ky + REAL(ReKi) :: DC(12, 12) + + Ax = kappa*A + Ay = kappa*A + + K(1:12,1:12) = 0 + + IF (Shear) THEN + Kx = 12.0*E*Iyy / (G*Ax*L*L) + Ky = 12.0*E*Ixx / (G*Ay*L*L) + ELSE + Kx = 0.0 + Ky = 0.0 + ENDIF + + K( 9, 9) = E*A/L + K( 7, 7) = 12.0*E*Iyy/( L*L*L*(1.0 + Kx) ) + K( 8, 8) = 12.0*E*Ixx/( L*L*L*(1.0 + Ky) ) + K(12, 12) = G*Jzz/L + K(10, 10) = (4.0 + Ky)*E*Ixx / ( L*(1.0+Ky) ) + K(11, 11) = (4.0 + Kx)*E*Iyy / ( L*(1.0+Kx) ) + K( 2, 4) = -6.*E*Ixx / ( L*L*(1.0+Ky) ) + K( 1, 5) = 6.*E*Iyy / ( L*L*(1.0+Kx) ) + K( 4, 10) = (2.0-Ky)*E*Ixx / ( L*(1.0+Ky) ) + K( 5, 11) = (2.0-Kx)*E*Iyy / ( L*(1.0+Kx) ) + + K( 3, 3) = K(9,9) + K( 1, 1) = K(7,7) + K( 2, 2) = K(8,8) + K( 6, 6) = K(12,12) + K( 4, 4) = K(10,10) + K(5,5) = K(11,11) + K(4,2) = K(2,4) + K(5,1) = K(1,5) + K(10,4) = K(4,10) + K(11,5) = K(5,11) + K(12,6)= -K(6,6) + K(10,2)= K(4,2) + K(11,1)= K(5,1) + K(9,3) = -K(3,3) + K(7,1) = -K(1,1) + K(8,2) = -K(2,2) + K(6, 12) = -K(6,6) + K(2, 10) = K(4,2) + K(1, 11) = K(5,1) + K(3, 9) = -K(3,3) + K(1, 7) = -K(1,1) + K(2, 8) = -K(2,2) + K(11,7) = -K(5,1) + K(10,8) = -K(4,2) + K(7,11) = -K(5,1) + K(8,10) = -K(4,2) + K(7,5) = -K(5,1) + K(5,7) = -K(5,1) + K(8,4) = -K(4,2) + K(4,8) = -K(4,2) + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed + +END SUBROUTINE ElemK_Beam +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for pretension cable +!! Element coordinate system: z along the cable! +SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) + REAL(ReKi), INTENT( IN) :: A, L, E + REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT(OUT) :: K(12, 12) + ! Local variables + REAL(ReKi) :: L0, Eps0, EAL0, EE + REAL(ReKi) :: DC(12, 12) + + Eps0 = T0/(E*A) + L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 + EAL0 = E*A/L0 + EE = EAL0* Eps0/(1+Eps0) + + K(1:12,1:12)=0 + + ! Note: only translatoinal DOF involved (1-3, 7-9) + K(1,1)= EE + K(2,2)= EE + K(3,3)= EAL0 + + K(1,7)= -EE + K(2,8)= -EE + K(3,9)= -EAL0 + + K(7,1)= -EE + K(8,2)= -EE + K(9,3)= -EAL0 + + K(7,7)= EE + K(8,8)= EE + K(9,9)= EAL0 + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed +END SUBROUTINE ElemK_Cable +!------------------------------------------------------------------------------------------------------ +!> Element mass matrix for classical beam elements +SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) + REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT(OUT) :: M(12, 12) + + REAL(ReKi) :: t, rx, ry, po + REAL(ReKi) :: DC(12, 12) + + t = rho*A*L; + rx = rho*Ixx; + ry = rho*Iyy; + po = rho*Jzz*L; + + M(1:12,1:12) = 0 + + M( 9, 9) = t/3.0 + M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) + M( 8, 8) = 13.0*t/35.0 + 6.0*rx/(5.0*L) + M(12, 12) = po/3.0 + M(10, 10) = t*L*L/105.0 + 2.0*L*rx/15.0 + M(11, 11) = t*L*L/105.0 + 2.0*L*ry/15.0 + M( 2, 4) = -11.0*t*L/210.0 - rx/10.0 + M( 1, 5) = 11.0*t*L/210.0 + ry/10.0 + M( 3, 9) = t/6.0 + M( 5, 7) = 13.*t*L/420. - ry/10. + M( 4, 8) = -13.*t*L/420. + rx/10. + M( 6, 12) = po/6. + M( 2, 10) = 13.*t*L/420. - rx/10. + M( 1, 11) = -13.*t*L/420. + ry/10. + M( 8, 10) = 11.*t*L/210. + rx/10. + M( 7, 11) = -11.*t*L/210. - ry/10. + M( 1, 7) = 9.*t/70. - 6.*ry/(5.*L) + M( 2, 8) = 9.*t/70. - 6.*rx/(5.*L) + M( 4, 10) = -L*L*t/140. - rx*L/30. + M( 5, 11) = -L*L*t/140. - ry*L/30. + + M( 3, 3) = M( 9, 9) + M( 1, 1) = M( 7, 7) + M( 2, 2) = M( 8, 8) + M( 6, 6) = M(12, 12) + M( 4, 4) = M(10, 10) + M( 5, 5) = M(11, 11) + M( 4, 2) = M( 2, 4) + M( 5, 1) = M( 1, 5) + M( 9, 3) = M( 3, 9) + M( 7, 5) = M( 5, 7) + M( 8, 4) = M( 4, 8) + M(12, 6) = M( 6, 12) + M(10, 2) = M( 2, 10) + M(11, 1) = M( 1, 11) + M(10, 8) = M( 8, 10) + M(11, 7) = M( 7, 11) + M( 7, 1) = M( 1, 7) + M( 8, 2) = M( 2, 8) + M(10, 4) = M( 4, 10) + M(11, 5) = M( 5, 11) + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed + +END SUBROUTINE ElemM_Beam +!------------------------------------------------------------------------------------------------------ +!> Element stiffness matrix for pretension cable +SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) + REAL(ReKi), INTENT( IN) :: A, L, rho + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT(OUT) :: M(12, 12) + ! Local variables + REAL(ReKi) :: DC(12, 12) + REAL(ReKi) :: t + + t = rho*A*L; + + M(1:12,1:12) = 0 + + M( 1, 1) = 13._ReKi/35._ReKi * t + M( 2, 2) = 13._ReKi/35._ReKi * t + M( 3, 3) = t/3.0_ReKi + + M( 7, 7) = 13._ReKi/35._ReKi * t + M( 8, 8) = 13._ReKi/35._ReKi * t + M( 9, 9) = t/3.0_ReKi + + M( 1, 7) = 9._ReKi/70._ReKi * t + M( 2, 8) = 9._ReKi/70._ReKi * t + M( 3, 9) = t/6.0_ReKi + + M( 7, 1) = 9._ReKi/70._ReKi * t + M( 8, 2) = 9._ReKi/70._ReKi * t + M( 9, 3) = t/6.0_ReKi + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed +END SUBROUTINE ElemM_Cable +!------------------------------------------------------------------------------------------------------ +!> calculates the lumped forces and moments due to gravity on a given element: +!! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: +!! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, +!! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 +SUBROUTINE ElemG(A, L, rho, DirCos, F, g) + REAL(ReKi), INTENT( IN ) :: A !< area + REAL(ReKi), INTENT( IN ) :: L !< element length + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1 ; 7-12 are loads for node 2. + REAL(ReKi) :: TempCoeff + REAL(ReKi) :: w ! weight per unit length + + F = 0 ! initialize whole array to zero, then set the non-zero portions + w = rho*A*g ! weight per unit length + + ! lumped forces on both nodes (z component only): + F(3) = -0.5*L*w + F(9) = F(3) + + ! lumped moments on node 1 (x and y components only): + ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary + ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. + TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice + F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12. !bjj: DirCos(2,3) = Dy/L + F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12. !bjj: DirCos(1,3) = Dx/L + + ! lumped moments on node 2: (note the opposite sign of node 1 moment) + F(10) = -F(4) + F(11) = -F(5) + !F(12) is 0 for g along z alone + +END SUBROUTINE ElemG +!------------------------------------------------------------------------------------------------------ +!> +SUBROUTINE ElemF_Cable(T0, DirCos, F) + REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. + ! Local variables + REAL(ReKi) :: DC(12, 12) + + F(1:12) = 0 ! init + F(3) = +T0 + F(9) = -T0 + + DC = 0 + DC( 1: 3, 1: 3) = DirCos + DC( 4: 6, 4: 6) = DirCos + DC( 7: 9, 7: 9) = DirCos + DC(10:12, 10:12) = DirCos + + F = MATMUL(DC, F)! TODO: change me if DirCos convention is transposed + +END SUBROUTINE ElemF_Cable +!------------------------------------------------------------------------------------------------------ +!> Calculates the lumped gravity forces at the nodes given the element geometry +!! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 +!! bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. +SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) + REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !< X-sectional areas at node 1 and node 2, t2/t1 thickness ratio + REAL(ReKi), INTENT( IN ) :: g !< gravity + REAL(ReKi), INTENT( IN ) :: L !< Length of element + REAL(ReKi), INTENT( IN ) :: rho !< density + REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces + !LOCALS + REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force + + !Calculate quadratic polynomial coefficients + a0 = a1 + print*,'Error: the function lumpforces is not ready to use' + STOP + + !Calculate quadratic polynomial coefficients + a0 = -99999 ! TODO: this is wrong + a2 = ( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. ! *x**2 + a1 = (Area2-Area1)/L -a2*L ! *x + + !Now calculate the Lumped Forces + F = 0 + F(3) = -(a0*L/2. +a1*L**2/6. +a2*L**3/12. )*rho*g !Forces along z (must be negative on earth) + F(9) = -(a0*L/2. +a1*L**2/3. +a2*L**3/4. )*rho*g !Forces along z (must be negative on earth) + + !Now calculate the Lumped Moments + !HERE TO BE COMPLETED FOR THE BELOW + TempCoeff = 1.0/12.0*g*L*L*rho*Area2 !RRD : I am changing this to >0 sign 6/10/13 + + !F(4) = TempCoeff*( DirCos(1, 3)*DirCos(2, 1) - DirCos(1, 1)*DirCos(2, 3) ) !These do not work if convnetion on z2>z1, x2>x1, y2>y1 are not followed as I have discovered 7/23 + !F(5) = TempCoeff*( DirCos(1, 3)*DirCos(2, 2) - DirCos(1, 2)*DirCos(2, 3) ) + + !RRD attempt at new dircos which keeps x in the X-Y plane + F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent + F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent + !RRD ends + F(10) = -F(4) + F(11) = -F(5) + !F(12) is 0 for g along z alone +END SUBROUTINE LumpForces + +!------------------------------------------------------------------------------------------------------ +!> +!! Method 1: pinv_A = A \ eye(m) (matlab) +!! call _GELSS to solve A.X=B +!! pinv(A) = B(1:n,1:m) +!! Method 2: [U,S,V] = svd(A); pinv_A = ( V / S ) * U'; (matlab) +! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' +SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) + use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM + real(LaKi), dimension(:,:), intent(in) :: A + real(LaKi), dimension(:,:), allocatable :: Ainv + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! < Error message if ErrStat / = ErrID_None + ! + real(LaKi), dimension(:), allocatable :: S + real(LaKi), dimension(:,:), allocatable :: U + real(LaKi), dimension(:,:), allocatable :: Vt + real(LaKi), dimension(:), allocatable :: WORK + real(LaKi), dimension(:,:), allocatable :: Acopy + integer :: i, j ! Loop indices + integer :: M !< The number of rows of the input matrix A + integer :: N !< The number of columns of the input matrix A + integer :: K !< + integer :: L !< + integer :: LWORK !< + integer :: INFO + real(ReKi) :: tol + M = size(A,1) + N = size(A,2) + K = min(M,N) + L = max(M,N) + LWORK = MAX(1,3*K +L,5*K) + allocate(S(K)); S = 0; + !! LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths + allocate(Work(LWORK)); Work=0 + allocate(U (M,K) ); U=0; + allocate(Vt(K,N) ); Vt=0; + allocate(Ainv(N,M)); Ainv=0; + allocate(Acopy(M,N)); Acopy=A; + + ! --- Compute the SVD of A + ! [U,S,V] = svd(A) + !call DGESVD ('S', 'S', M, N, A, M, S, U, M , Vt , K, WORK, LWORK, INFO) + call LAPACK_DGESVD('S', 'S', M, N, Acopy, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) + + !--- Compute PINV = V**T * SIGMA * U**T in two steps + ! SIGMA = S^(-1)=1/S(j), S is diagonal + do j = 1, K + U(:,j) = U(:,j)/S(j) + end do + ! Compute Ainv = 1.0*V^t * U^t + 0.0*Ainv V*(inv(S))*U' + !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) + call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) + ! --- Compute rank + !tol=maxval(shape(A))*epsilon(maxval(S)) + !rank=0 + !do i=1,K + ! if(S(i) .gt. tol)then + ! rank=rank+1 + ! end if + !end do + !print*,'Rank',rank + ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),Vt(1:r,:))) + END SUBROUTINE PseudoInverse + +END MODULE FEM diff --git a/modules/subdyn/src_soildyn/IntegerList.f90 b/modules/subdyn/src_soildyn/IntegerList.f90 new file mode 100644 index 000000000..299622368 --- /dev/null +++ b/modules/subdyn/src_soildyn/IntegerList.f90 @@ -0,0 +1,459 @@ +!> Module providing suport for an integer list stored as an array and not a chained list +!! Used since registry does not support pointer with recursive types. +module IntegerList + use SubDyn_Types, only: IList + use NWTC_Library, only: IntKi, ReKi, AllocAry, ErrID_None, ErrID_Fatal, num2lstr + + implicit none + + public :: IList + + public :: init_list + public :: destroy_list + public :: len + public :: append + public :: pop + public :: get + public :: find + public :: sort + public :: reverse + interface pop + module procedure pop_last + module procedure pop_item + end interface + interface init_list + module procedure init_list_n_def + module procedure init_list_vect + end interface + interface find + module procedure find_list + module procedure find_intarray + end interface + interface unique + module procedure unique_list + module procedure unique_intarray + module procedure unique_intarray_in_place + end interface +contains + + !> Concatenate lists: I3=[I1,I2] + subroutine concatenate_lists(I1,I2,I3, ErrStat, ErrMsg) + integer(intki), intent(in) :: i1(:), i2(:) + integer(intki), intent(out) :: i3(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat=ErrID_None + ErrMsg='' + I3(1:size(I1)) = I1 + I3(size(I1)+1:size(I1)+size(I2)) = I2 + endsubroutine + subroutine concatenate_3lists(I1,I2,I3,I4, ErrStat, ErrMsg) + integer(intki), intent(in) :: i1(:), i2(:), i3(:) + integer(intki), intent(out) :: i4(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat=ErrID_None + ErrMsg='' + I4( 1:size(I1) ) = I1 + I4(size(I1) +1:size(I1)+size(I2) ) = I2 + I4(size(I1)+size(I2)+1:size(I1)+size(I2)+size(I3)) = I3 + endsubroutine + + !> Set difference: I3=I1-I2 (assumes I1 is biggger than I2), elements of I1 not in I2 + subroutine lists_difference(I1, I2, I3, ErrStat, ErrMsg) + integer(IntKi), intent(in) :: I1(:), I2(:) + integer(IntKi), intent(out) :: I3(:) + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: I + logical, dimension(:), allocatable :: bUnique + ErrStat = ErrID_None + ErrMsg = "" + allocate(bUnique(1:size(I1))) + ! Then, remove DOFs on the boundaries: + DO i = 1, size(I1) !Boundary DOFs (Interface + Constraints) + if (find(I2,I1(i))>0) then + bUnique(I) = .false. + else + bUnique(I) = .true. + endif + ENDDO + if (count(bUnique) /= size(I3)) then + ErrStat=ErrID_Fatal; ErrMsg='Storage for list difference is of wrong size'; return + endif + I3 = pack(I1, bUnique) + deallocate(bUnique) + endsubroutine + + !> Initialize an integer list + subroutine init_list_n_def(L,n,default_val,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), intent(in) :: n !< number of initial values + integer(IntKi), intent(in) :: default_val !< default values + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + call AllocAry(L%List, n, 'L%List', ErrStat, ErrMsg) + if (ErrStat/=ErrID_None) return + L%List(1:n) = default_val + end subroutine init_list_n_def + + subroutine init_list_vect(L,vect,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), dimension(:), intent(in) :: vect !< number of initial values + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + call AllocAry(L%List, size(vect), 'L%List', ErrStat, ErrMsg) + if (ErrStat/=ErrID_None) return + L%List = vect + end subroutine init_list_vect + + !> Deallocate list + subroutine destroy_list(L,ErrStat,ErrMsg) + type(IList), intent(inout) :: L !< List + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) deallocate(L%List) + end subroutine destroy_list + + !> Returns list length + integer function len(L) + type(IList), intent(in) :: L + if (allocated(L%List)) then + len=size(L%List) + else + len=0 + endif + end function len + + !> Append element to list + subroutine append(L,e, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: e + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) then + call resize_array(L%List,len(L)+1,e) + else + call init_list(L, 1, e, ErrStat, ErrMsg) + endif + end subroutine append + + !> Get element i from list + integer function get(L,i, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: i + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + if ((i<=0).or.(i>len(L))) then + ErrStat=ErrID_Fatal + ErrMsg="Index out of bound "//trim(num2lstr(i))//", list length is "//trim(num2lstr(len(L))) + get=-9999 + else + ErrStat = ErrID_None + ErrMsg = "" + get = L%List(i) ! No error handling, throws "index array out of bound", like a regular array + endif + end function get + + !> Pop last element of the list and reduce list size by 1 + integer function pop_last(L,ErrStat,ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + pop_last = get(L, n, ErrStat, ErrMsg) ! index array out of bound will be thrown + call resize_array(L%List,n-1,0) + end function pop_last + + !> Pop element i from the list and reduce the size of the list by 1 + integer function pop_item(L,i,ErrStat,ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in) :: i + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + pop_item = get(L, i, ErrStat, ErrMsg) ! index array out of bound will be thrown + L%List(i:n-1)=L%List(i+1:n) + call resize_array(L%List,n-1,0) + end function pop_item + + !> Sort list + subroutine sort(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (allocated(L%List)) then + call sort_in_place(L%List) + else + ErrStat=ErrID_Fatal + ErrMsg="Cannot sort a list not allocated" + endif + end subroutine sort + + !> Reverse list + subroutine reverse(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + integer(IntKi) :: i + integer(IntKi) :: n + ErrStat = ErrID_None + ErrMsg = "" + n=len(L) + do i =1,int(n/2) + call swap(i, n-i+1) + enddo + contains + subroutine swap(i,j) + integer(IntKi), intent(in) :: i,j + integer(IntKi) :: tmp + tmp=L%List(i) + L%List(i) = L%List(j) + L%List(j) = tmp + end subroutine + end subroutine reverse + + + !> Returns index of element e in L, returns 0 if not found + !! NOTE: list but be sorted to call this function + integer(IntKi) function find_list(L, e, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent(in ) :: e + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (len(L)>0) then + find_list = binary_search(L%List, e) ! Binary search returns index for inequality List(i)<=e + if (find_list>0) then + if (L%List(find_list)/=e) then + find_list=-1 + endif + endif + else + find_list=-1 + endif + end function find_list + + !> Unique, in place + subroutine unique_list(L, ErrStat, ErrMsg) + type(IList), intent(inout) :: L + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None + ErrStat = ErrID_None + ErrMsg = "" + if (len(L)>0) then + call unique_intarray_in_place(L%List) + endif + end subroutine + + !> Print + subroutine print_list(L, varname, u_opt) + type(IList), intent(in) :: L + character(len=*),intent(in) :: varname + integer(IntKi), intent(in),optional :: u_opt + ! + character(len=*),parameter :: IFMT='I7.0' !< + integer(IntKi) :: u + integer(IntKi) :: n + character(len=20) :: fmt + ! Optional args + if (present(u_opt)) then + u=u_opt + else + u=6 + endif + n=len(L) + if (n>0) then + write(fmt,*) n + write(u,"(A,A,"// adjustl(fmt)//IFMT//",A)") varname,"=[",L%List,"];" + else + write(u,'(A,A)') varname,'=[];' + endif + end subroutine print_list + + ! -------------------------------------------------------------------------------- + ! --- Generic helper functions (should be part of NWTC library) + ! -------------------------------------------------------------------------------- + !> Sort integer array in place + pure subroutine sort_in_place(a) + integer(IntKi), intent(inout), dimension(:) :: a + integer(IntKi) :: temp + integer(IntKi) :: i, j + do i = 2, size(a) + j = i - 1 + temp = a(i) + do while (j>=1 .and. a(j)>temp) + a(j+1) = a(j) + j = j - 1 + if (j<1) then + exit + endif + end do + a(j+1) = temp + end do + end subroutine sort_in_place + + !> Performs binary search and return the largest index such that x(i) <= x0 + !! allows equlity + Integer(IntKi) function binary_search(x, x0) result(i_inf) + ! Arguments declarations + integer(IntKi), dimension(:),intent(in) :: x !< x *sorted* vector + integer(IntKi), intent(in) :: x0 !< + ! Variable declarations + integer(IntKi) :: i_sup !< + integer(IntKi) :: mid !< + i_inf=1 + i_sup=size(x) + ! Safety test + if (x0=x(i_sup)) then + i_inf=i_sup + return + end if + ! We loop until we narrow down to one index + do while (i_inf+1 Returns index of val in Array (val is an integer!) + ! NOTE: in the future use intrinsinc function findloc + function find_intarray(Array, Val) result(i) + integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in + integer(IntKi), intent(in) :: val !< Val + integer(IntKi) :: i !< Index of joint in joint table + logical :: found + i = 1 + do while ( i <= size(Array) ) + if ( Val == Array(i) ) THEN + return ! Exit when found + else + i = i + 1 + endif + enddo + i=-1 + end function + + !> return in res the unique values of v + subroutine unique_intarray(v,res) + ! Arguments + integer(IntKi),dimension(:),intent(in) :: v + integer(IntKi),dimension(:),allocatable::res + ! + integer(IntKi),dimension(:),pointer::tmp + integer :: k !< number of unique elements + integer :: i, j + if (allocated(res)) deallocate(res) + allocate(tmp(1:size(v))) + k = 1 + tmp(1) = v(1) + outer: do i=2,size(v) + do j=1,k + if (tmp(j) == v(i)) then + ! Found a match so start looking again + cycle outer + end if + end do + ! No match found so add it to the output + k = k + 1 + tmp(k) = v(i) + end do outer + allocate(res(1:k)) + res(1:k)=tmp(1:k) + deallocate(tmp) + end subroutine + + subroutine unique_intarray_in_place(v) + integer(IntKi),dimension(:),allocatable :: v + integer(IntKi),dimension(:),allocatable::res + integer :: k !< number of unique elements + integer :: i, j + allocate(res(1:size(v))) + k = 1 + res(1) = v(1) + outer: do i=2,size(v) + do j=1,k + if (res(j) == v(i)) then + ! Found a match so start looking again + cycle outer + end if + end do + ! No match found so add it to the output + k = k + 1 + res(k) = v(i) + end do outer + deallocate(v) + allocate(v(1:k)) + v(1:k)=res(1:k) + deallocate(res) + end subroutine + + !> Resize integer array of dimension 1 + subroutine resize_array(array,nNewSize,default_val) + integer(IntKi),dimension(:),allocatable,intent(inout) :: array + integer(IntKi) , intent(in) :: nNewSize + integer(IntKi), intent(in) :: default_val + ! Local variables + integer(IntKi),dimension(:),allocatable :: tmp !< backup of input + integer(IntKi) :: nDimTmp + integer(IntKi) :: AllocateStatus + ! To save memory, if nNewSize is below second dim, we take the min + nDimTmp= min(size(array,1),nNewSize) + ! Making of copy of the input + allocate(tmp(1:nDimTmp), STAT = AllocateStatus) + if (AllocateStatus /= 0) STOP "*** Not enough memory ***" + tmp(1:nDimTmp)=array(1:nDimTmp) + ! Reallocating the array + deallocate(array) + allocate(array(1:nNewSize), STAT = AllocateStatus) + if (AllocateStatus /= 0) STOP "*** Not enough memory ***" + ! We copy the original data into it + array(1:nDimTmp)=tmp(1:nDimTmp) + if(nDimTmp+1<=nNewSize) array(nDimTmp+1:nNewSize)=default_val + end subroutine + + !> Append two integer arrays of dimension 1 + subroutine append_arrays(array1,n1,array2,n2) + integer(IntKi), dimension(:), allocatable :: array1 + integer(IntKi), dimension(:) :: array2 + integer(IntKi), intent(inout) :: n1 !< SIDE EFFECTS + integer(IntKi), intent(in) :: n2 + ! Local variables + integer :: nNew + nNew=n1+n2 + ! --- Making enough space if needed + if(nNew>size(array1,1)) then + call resize_array(array1,nNew,0) + endif + ! --- Appending + array1((n1+1):(n1+n2))=array2(1:n2) + ! updating n1 + n1=n1+n2; + end subroutine + +end module IntegerList diff --git a/modules/subdyn/src_soildyn/SD_FEM.f90 b/modules/subdyn/src_soildyn/SD_FEM.f90 new file mode 100644 index 000000000..e931274c9 --- /dev/null +++ b/modules/subdyn/src_soildyn/SD_FEM.f90 @@ -0,0 +1,1897 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +!********************************************************************************************************************************** +MODULE SD_FEM + USE NWTC_Library + USE SubDyn_Types + USE FEM + IMPLICIT NONE + + + INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint + INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in + INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 ! 6 degrees of freedom (length of u subarray [UTP]) + + ! values of these parameters are ordered by their place in SubDyn input file: + INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff JointDamp) + INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) + INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) + INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) + INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) + INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs + INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) + INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) + INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) + INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) + INTEGER(IntKi), PARAMETER :: CMassCol = 11 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ, Optional:JMXY,JMXZ,JMYZ,CGX,CGY,CGZ) + ! Indices in Members table + INTEGER(IntKi), PARAMETER :: iMType= 6 ! Index in Members table where the type is stored + INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored + + ! Indices in Joints table + INTEGER(IntKi), PARAMETER :: iJointType= 5 ! Index in Joints where the joint type is stored + INTEGER(IntKi), PARAMETER :: iJointDir= 6 ! Index in Joints where the joint-direction are stored + INTEGER(IntKi), PARAMETER :: iJointStiff= 9 ! Index in Joints where the joint-stiffness is stored + INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored + + ! ID for joint types + INTEGER(IntKi), PARAMETER :: idJointCantilever = 1 + INTEGER(IntKi), PARAMETER :: idJointUniversal = 2 + INTEGER(IntKi), PARAMETER :: idJointPin = 3 + INTEGER(IntKi), PARAMETER :: idJointBall = 4 + + ! ID for member types + INTEGER(IntKi), PARAMETER :: idMemberBeam = 1 + INTEGER(IntKi), PARAMETER :: idMemberCable = 2 + INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 + + ! Types of Boundary Conditions + INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 + INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 + INTEGER(IntKi), PARAMETER :: idBC_Leader = 13 ! TODO, and maybe "BC" not appropriate here + + ! Types of Static Improvement Methods + INTEGER(IntKi), PARAMETER :: idSIM_None = 0 + INTEGER(IntKi), PARAMETER :: idSIM_Full = 1 + INTEGER(IntKi), PARAMETER :: idSIM_GravOnly = 2 + INTEGER(IntKi) :: idSIM_Valid(3) = (/idSIM_None, idSIM_Full, idSIM_GravOnly /) + + INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) + + LOGICAL, PARAMETER :: DEV_VERSION = .false. + + INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic + MODULE PROCEDURE FINDLOCI_ReKi + MODULE PROCEDURE FINDLOCI_IntKi + END INTERFACE + + +CONTAINS +!------------------------------------------------------------------------------------------------------ +! --- Helper functions +!------------------------------------------------------------------------------------------------------ +!> Maps nodes to elements +!! allocate NodesConnE and NodesConnN +SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT( INOUT ) :: Init + TYPE(SD_ParameterType), INTENT( IN ) :: p + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements + INTEGER(IntKi) :: I,J,K !counter + + ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) + CALL AllocAry(Init%NodesConnE, p%nNodes, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; + CALL AllocAry(Init%NodesConnN, p%nNodes, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; + Init%NodesConnE = 0 + Init%NodesConnN = -99999 ! Not Used + + ! find the node connectivity, nodes/elements that connect to a common node + DO I = 1, p%nNodes + !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array + k = 0 + DO J = 1, Init%NElem !This should be vectorized + IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element + k = k + 1 + if (k > MaxMemJnt+1) then + CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); + endif + Init%NodesConnE(I, k + 1) = p%Elems(J, 1) + ENDIF + ENDDO + Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column + ENDDO + +END SUBROUTINE NodeCon + +!---------------------------------------------------------------------------- +!> Check if two elements are connected +!! returns true if they are, and return which node (1 or 2) of each element is involved +LOGICAL FUNCTION ElementsConnected(p, ie1, ie2, iWhichNode_e1, iWhichNode_e2) + TYPE(SD_ParameterType), INTENT(IN) :: p + INTEGER(IntKi), INTENT(IN) :: ie1, ie2 ! Indices of elements + INTEGER(IntKi), INTENT(OUT) :: iWhichNode_e1, iWhichNode_e2 ! 1 or 2 if node 1 or node 2 + if ((p%Elems(ie1, 2) == p%Elems(ie2, 2))) then ! node 1 connected to node 1 + iWhichNode_e1=1 + iWhichNode_e2=1 + ElementsConnected=.True. + else if((p%Elems(ie1, 2) == p%Elems(ie2, 3))) then ! node 1 connected to node 2 + iWhichNode_e1=1 + iWhichNode_e2=2 + ElementsConnected=.True. + else if((p%Elems(ie1, 3) == p%Elems(ie2, 2))) then ! node 2 connected to node 1 + iWhichNode_e1=2 + iWhichNode_e2=1 + ElementsConnected=.True. + else if((p%Elems(ie1, 3) == p%Elems(ie2, 3))) then ! node 2 connected to node 2 + iWhichNode_e1=2 + iWhichNode_e2=2 + ElementsConnected=.True. + else + ElementsConnected=.False. + iWhichNode_e1=-1 + iWhichNode_e2=-1 + endif +END FUNCTION ElementsConnected + +!> Loop through a list of elements and returns a list of unique joints +TYPE(IList) FUNCTION NodesList(p, Elements) + use IntegerList, only: init_list, append, find, sort + use IntegerList, only: print_list + TYPE(SD_ParameterType), INTENT(IN) :: p + integer(IntKi), dimension(:), INTENT(IN) :: Elements + integer(IntKi) :: ie, ei, j1, j2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + call init_list(NodesList, 0, 0, ErrStat2, ErrMsg2) + do ie = 1, size(Elements) + ei = Elements(ie) ! Element index + j1 = p%Elems(ei,2) ! Joint 1 + j2 = p%Elems(ei,3) ! Joint 2 + ! Append joints indices if not in list already + if (find(NodesList, j1, ErrStat2, ErrMsg2)<=0) call append(NodesList, j1, ErrStat2, ErrMsg2) + if (find(NodesList, j2, ErrStat2, ErrMsg2)<=0) call append(NodesList, j2, ErrStat2, ErrMsg2) + ! Sorting required by find function + call sort(NodesList, ErrStat2, ErrMsg2) + enddo + if (DEV_VERSION) then + call print_list(NodesList, 'Joint list') + endif +END FUNCTION NodesList +!------------------------------------------------------------------------------------------------------ +!> Returns list of rigid link elements (Er) +TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, append + use IntegerList, only: print_list + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: ie !< Index on elements + ErrStat = ErrID_None + ErrMsg = "" + ! --- Establish a list of rigid link elements + call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); + + do ie = 1, Init%NElem + if (p%ElemProps(ie)%eType == idMemberRigid) then + call append(RigidLinkElements, ie, ErrStat, ErrMsg); + endif + end do + if (DEV_VERSION) then + call print_list(RigidLinkElements,'Rigid element list') + endif +END FUNCTION RigidLinkElements + +!------------------------------------------------------------------------------------------------------ +!> Returns true if one of the element connected to the node is a rigid link +LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p, ei) + integer(IntKi), intent(in) :: iJoint + type(SD_InitType), intent(in) :: Init + type(SD_ParameterType), intent(in) :: p + integer(IntKi), intent( out) :: ei !< Element index that connects do iJoint rigidly + ! Local variables + integer(IntKi) :: ie !< Loop index on elements + integer(IntKi) :: m ! Number of elements connected to a joint + + NodeHasRigidElem = .False. ! default return value + ! Loop through elements connected to node J + do ie = 1, Init%NodesConnE(iJoint, 1) + ei = Init%NodesConnE(iJoint, ie+1) + if (p%ElemProps(ei)%eType == idMemberRigid) then + NodeHasRigidElem = .True. + return ! we exit as soon as one rigid member is found + endif + enddo + ei=-1 +END FUNCTION NodeHasRigidElem +!------------------------------------------------------------------------------------------------------ +!> Returns a rigid body transformation matrix from nDOF to 6 reference DOF: T_ref (6 x nDOF), such that Uref = T_ref.U_subset +!! Typically called to get: +!! - the transformation from the interface points to the TP point +!! - the transformation from the bottom nodes to SubDyn origin (0,0,) +SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(IN ) :: p + REAL(ReKi), INTENT(IN ) :: RefPoint(3) ! Coordinate of the reference point + INTEGER(IntKi), INTENT(IN ) :: nDOF ! Number of DOFS + INTEGER(IntKi), INTENT(IN ) :: DOF(nDOF) ! DOF indices that are used to create the transformation matrix + REAL(ReKi), INTENT( OUT) :: T_ref(nDOF,6) ! matrix that relates the subset of DOFs to the reference point + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER :: I, iDOF, iiDOF, iNode, nDOFPerNode + REAL(ReKi) :: dx, dy, dz + REAL(ReKi), dimension(6) :: Line + ErrStat = ErrID_None + ErrMsg = "" + T_ref(:,:)=0 + DO I = 1, nDOF + iDOF = DOF(I) ! DOF index in constrained system + iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + + if ((iiDOF<1) .or. (iiDOF>6)) then + ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal + return + endif + if (nDOFPerNode/=6) then + ErrMsg = 'RigidTrnsf, node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal + return + endif + + dx = Init%Nodes(iNode, 2) - RefPoint(1) + dy = Init%Nodes(iNode, 3) - RefPoint(2) + dz = Init%Nodes(iNode, 4) - RefPoint(3) + + CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line + T_ref(I, 1:6) = Line + ENDDO +END SUBROUTINE RigidTrnsf + +!------------------------------------------------------------------------------------------------------ +! --- Main routines, more or less listed in order in which they are called +!------------------------------------------------------------------------------------------------------ +!> +! - Removes the notion of "ID" and use Index instead +! - Creates Nodes (use indices instead of ID), similar to Joints array +! - Creates Elems (use indices instead of ID) similar to Members array +! - Updates Reacts (use indices instead of ID) +! - Updates Interf (use indices instead of ID) +SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) ::Init + TYPE(SD_ParameterType), INTENT(INOUT) ::p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variable + INTEGER :: I, n, iMem, iNode, JointID + INTEGER(IntKi) :: mType !< Member Type + CHARACTER(1255) :: sType !< String for element type + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! TODO See if Elems is actually used elsewhere + + CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%Nodes, p%nNodes, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initialize Nodes + Init%Nodes = -999999 ! Init to unphysical values + do I = 1,Init%NJoints + Init%Nodes(I, 1) = I ! JointID replaced by index I + Init%Nodes(I, 2:JointsCol) = Init%Joints(I, 2:JointsCol) ! All the rest is copied + enddo + + ! --- Re-Initialize Reactions, pointing to index instead of JointID + do I = 1, p%nNodes_C + JointID=p%Nodes_C(I,1) + p%Nodes_C(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index + if (p%Nodes_C(I,1)<=0) then + CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! --- Re-Initialize interface joints, pointing to index instead of JointID + do I = 1, p%nNodes_I + JointID=p%Nodes_I(I,1) + p%Nodes_I(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (p%Nodes_I(I,1)<=0) then + CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + ! Change numbering in concentrated mass matrix + do I = 1, Init%NCMass + JointID = Init%CMass(I,1) + Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) + if (Init%CMass(I,1)<=0) then + CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') + return + endif + enddo + + + ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) + p%Elems = 0 + ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables + DO iMem = 1, p%NMembers + ! Column 1 : member index (instead of MemberID) + p%Elems(iMem, 1) = iMem + mType = Init%Members(iMem, iMType) ! + ! Column 2-3: Joint index (instead of JointIDs) + p%Elems(iMem, 1) = iMem ! NOTE: element/member number (not MemberID) + do iNode=2,3 + p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) + if (p%Elems(iMem,iNode)<=0) then + CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list!') + return + endif + enddo + ! Column 4-5: PropIndex 1-2 (instead of PropSetID1&2) + ! NOTE: this index has different meaning depending on the member type ! + DO n=iMProp,iMProp+1 + + if (mType==idMemberBeam) then + sType='Member x-section property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) + else if (mType==idMemberCable) then + sType='Cable property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) + else if (mType==idMemberRigid) then + sType='Rigid property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) + else + ! Should not happen + print*,'Element type unknown',mType + STOP + end if + + if (p%Elems(iMem,n)<=0) then + CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') + endif + END DO !n, loop through property ids + ! Column 6: member type + p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! + END DO !iMem, loop through members + + ! TODO in theory, we shouldn't need these anymore + ! deallocate(Init%Members) + ! deallocate(Init%Joints) +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems'); + END SUBROUTINE Fatal +END SUBROUTINE SD_ReIndex_CreateNodesAndElems + +!---------------------------------------------------------------------------- +SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) ::Init + TYPE(SD_ParameterType), INTENT(INOUT) ::p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variable + INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 + INTEGER :: NNE ! number of nodes per element + INTEGER :: MaxNProp + REAL(ReKi), ALLOCATABLE :: TempProps(:, :) + INTEGER, ALLOCATABLE :: TempMembers(:, :) + INTEGER :: knode, kelem, kprop, nprop + REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 + LOGICAL :: found, CreateNewProp + INTEGER(IntKi) :: eType !< Element Type + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! number of nodes per element + IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN + NNE = 2 + ELSE + CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.'); return + ENDIF + + ! Total number of element + Init%NElem = p%NMembers*Init%NDiv ! Note: This is a max since cable and rigid cannot be subdivided + ! Total number of nodes - Depends on division and number of nodes per element + p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers + p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! Note: Same as above. Can be improved by counting R&C + + ! check the number of interior modes + IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN + CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))); return + ENDIF + + CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different + + ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays + ! NOTE: need NNode and NElem + CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + + + Init%MemberNodes = 0 + ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) + if (Init%NDiv==1) then + ! NDiv = 1 + Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) + Init%NPropB = Init%NPropSetsB + + else if (Init%NDiv > 1) then + + ! Discretize structure according to NDiv + ! - Elems is fully reinitialized, connectivity needs to be done again using SetNewElem + ! - Nodes are not reinitialized, but appended to NNodes + ! + + ! Initialize Temp arrays that will contain user inputs + input from the subdivided members + ! We don't know how many properties will be needed, so allocated to size MaxNProp + MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempProps, MaxNProp, PropSetsBCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return + TempProps = -9999. + TempMembers = p%Elems(1:p%NMembers,:) + TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB + p%Elems(:,:) = -9999. ! Reinitialized. Elements will be ordered by member subdivisions (see setNewElem) + + kelem = 0 + knode = Init%NJoints + kprop = Init%NPropSetsB + DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information + ! Member data + Node1 = TempMembers(I, 2) + Node2 = TempMembers(I, 3) + Prop1 = TempMembers(I, iMProp ) + Prop2 = TempMembers(I, iMProp+1) + eType = TempMembers(I, iMType ) + + IF ( Node1==Node2 ) THEN + CALL Fatal(' Same starting and ending node in the member.') + RETURN + ENDIF + + if (eType/=idMemberBeam) then + ! --- Cables and rigid links are not subdivided + ! No need to create new properties or new nodes + Init%MemberNodes(I, 1) = Node1 + Init%MemberNodes(I, 2) = Node2 + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p) + cycle + endif + + ! --- Subdivision of beams + Init%MemberNodes(I, 1) = Node1 + Init%MemberNodes(I, Init%NDiv+1) = Node2 + + IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & + .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN + + CALL Fatal(' Material E,G and rho in a member must be the same') + RETURN + ENDIF + + x1 = Init%Nodes(Node1, 2) + y1 = Init%Nodes(Node1, 3) + z1 = Init%Nodes(Node1, 4) + + x2 = Init%Nodes(Node2, 2) + y2 = Init%Nodes(Node2, 3) + z2 = Init%Nodes(Node2, 4) + + dx = ( x2 - x1 )/Init%NDiv + dy = ( y2 - y1 )/Init%NDiv + dz = ( z2 - z1 )/Init%NDiv + + d1 = TempProps(Prop1, 5) + t1 = TempProps(Prop1, 6) + + d2 = TempProps(Prop2, 5) + t2 = TempProps(Prop2, 6) + + dd = ( d2 - d1 )/Init%NDiv + dt = ( t2 - t1 )/Init%NDiv + + ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node + CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) + + ! node connect to Node1 + knode = knode + 1 + Init%MemberNodes(I, 2) = knode + CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) ! Set Init%Nodes(knode,:) + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) + nprop = Prop1 + ENDIF + + ! interior nodes + DO J = 2, (Init%NDiv-1) + knode = knode + 1 + Init%MemberNodes(I, J+1) = knode + + CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) ! Set Init%Nodes(knode,:) + + IF ( CreateNewProp ) THEN + ! create a new property set + ! k, E, G, rho, d, t, Init + kprop = kprop + 1 + CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) + nprop = kprop + ELSE + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) + ENDIF + ENDDO + + ! the element connect to Node2 + kelem = kelem + 1 + CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) + ENDDO ! loop over all members + ! + Init%NPropB = kprop + Init%NElem = kelem ! TODO since not all members might have been divided + p%nNodes = knode ! TODO since not all members might have been divided + + ENDIF ! if NDiv is greater than 1 + + ! set the props in Init + CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return + + if (Init%NDiv==1) then + Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) + else if (Init%NDiv>1) then + Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempProps(1:Init%NPropB, 1:PropSetsBCol) + endif + + ! --- Cables and rigid link properties (these cannot be subdivided, so direct copy of inputs) + Init%NPropC = Init%NPropSetsC + Init%NPropR = Init%NPropSetsR + CALL AllocAry(Init%PropsC, Init%NPropC, PropSetsCCol, 'Init%PropsCable', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropsR, Init%NPropR, PropSetsRCol, 'Init%PropsRigid', ErrStat2, ErrMsg2); if(Failed()) return + Init%PropsC(1:Init%NPropC, 1:PropSetsCCol) = Init%PropSetsC(1:Init%NPropC, 1:PropSetsCCol) + Init%PropsR(1:Init%NPropR, 1:PropSetsRCol) = Init%PropSetsR(1:Init%NPropR, 1:PropSetsRCol) + + CALL CleanUp_Discrt() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') + Failed = ErrStat >= AbortErrLev + if (Failed) CALL CleanUp_Discrt() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); + CALL CleanUp_Discrt() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp_Discrt() + ! deallocate temp matrices + IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) + IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) + END SUBROUTINE CleanUp_Discrt + + !> Set properties of node k + SUBROUTINE SetNewNode(k, x, y, z, Init) + TYPE(SD_InitType), INTENT(INOUT) :: Init + INTEGER, INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: x, y, z + Init%Nodes(k, 1) = k + Init%Nodes(k, 2) = x + Init%Nodes(k, 3) = y + Init%Nodes(k, 4) = z + Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever + ! Properties below are for non-cantilever joints + Init%Nodes(k, iJointDir:iJointDir+2) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes + Init%Nodes(k, iJointStiff) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes + Init%Nodes(k, iJointDamp) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes + END SUBROUTINE SetNewNode + + !> Set properties of element k + SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) + INTEGER, INTENT(IN ) :: k + INTEGER, INTENT(IN ) :: n1 + INTEGER, INTENT(IN ) :: n2 + INTEGER, INTENT(IN ) :: eType + INTEGER, INTENT(IN ) :: p1 + INTEGER, INTENT(IN ) :: p2 + TYPE(SD_ParameterType), INTENT(INOUT) :: p + p%Elems(k, 1) = k + p%Elems(k, 2) = n1 + p%Elems(k, 3) = n2 + p%Elems(k, iMProp ) = p1 + p%Elems(k, iMProp+1) = p2 + p%Elems(k, iMType) = eType + END SUBROUTINE SetNewElem + + !> Set material properties of element k, NOTE: this is only for a beam + SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) + INTEGER , INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: E, G, rho, d, t + REAL(ReKi), INTENT(INOUT):: TempProps(:, :) + TempProps(k, 1) = k + TempProps(k, 2) = E + TempProps(k, 3) = G + TempProps(k, 4) = rho + TempProps(k, 5) = d + TempProps(k, 6) = t + END SUBROUTINE SetNewProp + +END SUBROUTINE SD_Discrt + +!------------------------------------------------------------------------------------------------------ +!> Set Element properties p%ElemProps, different properties are set depening on element type.. +SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K, iTmp + INTEGER :: N1, N2 ! starting node and ending node in the element + INTEGER :: P1, P2 ! property set numbers for starting and ending nodes + REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section + REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices + REAL(ReKi) :: L ! length of the element + REAL(ReKi) :: T0 ! pretension force in cable [N] + REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer + LOGICAL :: shear + INTEGER(IntKi) :: eType !< Member type + REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrMsg = "" + ErrStat = ErrID_None + + ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2); ErrMsg2='Error allocating p%ElemProps' + if(Failed()) return + + ! Loop over all elements and set ElementProperties + do I = 1, Init%NElem + N1 = p%Elems(I, 2) + N2 = p%Elems(I, 3) + + P1 = p%Elems(I, iMProp ) + P2 = p%Elems(I, iMProp+1) + eType = p%Elems(I, iMType) + + ! --- Properties common to all element types: L, DirCos (and Area and rho) + Point1 = Init%Nodes(N1,2:4) + Point2 = Init%Nodes(N2,2:4) + CALL GetDirCos(Point1, Point2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos + p%ElemProps(i)%eType = eType + p%ElemProps(i)%Length = L + p%ElemProps(i)%DirCos = DirCos + + ! Init to excessive values to detect any issue + p%ElemProps(i)%Ixx = -9.99e+36 + p%ElemProps(i)%Iyy = -9.99e+36 + p%ElemProps(i)%Jzz = -9.99e+36 + p%ElemProps(i)%Kappa = -9.99e+36 + p%ElemProps(i)%YoungE = -9.99e+36 + p%ElemProps(i)%ShearG = -9.99e+36 + p%ElemProps(i)%Area = -9.99e+36 + p%ElemProps(i)%Rho = -9.99e+36 + p%ElemProps(i)%T0 = -9.99e+36 + + ! --- Properties that are specific to some elements + if (eType==idMemberBeam) then + E = Init%PropsB(P1, 2) + G = Init%PropsB(P1, 3) + rho = Init%PropsB(P1, 4) + D1 = Init%PropsB(P1, 5) + t1 = Init%PropsB(P1, 6) + D2 = Init%PropsB(P2, 5) + t2 = Init%PropsB(P2, 6) + r1 = 0.25*(D1 + D2) + t = 0.5*(t1+t2) + if ( EqualRealNos(t, 0.0_ReKi) ) then + r2 = 0 + else + r2 = r1 - t + endif + A = Pi_D*(r1*r1-r2*r2) + Ixx = 0.25*Pi_D*(r1**4-r2**4) + Iyy = Ixx + Jzz = 2.0*Ixx + + if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli + Shear = .false. + kappa = 0 + elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko + Shear = .true. + ! kappa = 0.53 + ! equation 13 (Steinboeck et al) in SubDyn Theory Manual + nu = E / (2.0_ReKi*G) - 1.0_ReKi + D_outer = 2.0_ReKi * r1 ! average (outer) diameter + D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter + ratioSq = ( D_inner / D_outer)**2 + kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & + / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) + endif + ! Storing Beam specific properties + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%kappa = kappa + p%ElemProps(i)%YoungE = E + p%ElemProps(i)%ShearG = G + p%ElemProps(i)%Area = A + p%ElemProps(i)%Rho = rho + + else if (eType==idMemberCable) then + if (DEV_VERSION) then + print*,'Member',I,'is a cable' + endif + p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 + p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] + p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] + p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] + + else if (eType==idMemberRigid) then + if (DEV_VERSION) then + print*,'Member',I,'is a rigid link' + endif + p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 + p%ElemProps(i)%Rho = Init%PropsR(P1, 2) + + else + ! Should not happen + print*,'Element type unknown',eType + STOP + end if + enddo ! I end loop over elements +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed +END SUBROUTINE SetElementProperties + + +!> Distribute global DOF indices corresponding to Nodes, Elements, BCs, Reactions +!! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs +!! For other joint type -> Condensation of the 3 translational DOF +!! -> Keeping 3 rotational DOF for each memeber connected to the joint +SUBROUTINE DistributeDOF(Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, len + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer(IntKi) :: iNode, k + integer(IntKi) :: iPrev ! Cumulative counter over the global DOF + integer(IntKi) :: iElem ! + integer(IntKi) :: idElem + integer(IntKi) :: nRot ! Number of rotational DOFs (multiple of 3) to be used at the joint + integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 + integer(IntKi), dimension(6) :: DOFNode_Old + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + ErrMsg = "" + ErrStat = ErrID_None + + allocate(p%NodesDOF(1:p%nNodes), stat=ErrStat2) + ErrMsg2="Error allocating NodesDOF" + if(Failed()) return + + call AllocAry(p%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; + p%ElemsDOF=-9999 + + iPrev =0 + do iNode = 1, p%nNodes + ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) + if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then + nRot=3 + else + nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + endif + call init_list(p%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) + p%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) + + ! --- Distribute to members + do iElem = 1, Init%NodesConnE(iNode,1) ! members connected to joint iJ + idElem = Init%NodesConnE(iNode,iElem+1) + if (iNode == p%Elems(idElem, 2)) then ! Current joint is Elem node 1 + iOff = 0 + else ! Current joint is Elem node 2 + iOff = 6 + endif + p%ElemsDOF(iOff+1:iOff+3, idElem) = p%NodesDOF(iNode)%List(1:3) + if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then + p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(4:6) + else + p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) + endif + enddo ! iElem, loop on members connect to joint + iPrev = iPrev + len(p%NodesDOF(iNode)) + enddo ! iNode, loop on joints + + ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first + CALL AllocAry(Init%BCs, 6*p%nNodes_C, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitBCs(Init, p) + + ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first + CALL AllocAry(Init%IntFc, 6*p%nNodes_I,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return + CALL InitIntFc(Init, p) + + ! --- Safety check + if (any(p%ElemsDOF<0)) then + ErrStat=ErrID_Fatal + ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" + endif + + ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) + if (p%nNodes == count( Init%Nodes(:, iJointType) == idJointCantilever)) then + do idElem = 1, Init%NElem + iNode = p%Elems(idElem, 2) + DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) + if ( any( (p%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then + ErrStat=ErrID_Fatal + ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iElem="//trim(Num2LStr(idElem)) + return + endif + enddo + else + ! Safety check does not apply if some joints are non-cantilever + endif + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + + !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have + !! NOTE: need p%Nodes_C to have an updated first column that uses indices and not JointIDs + !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" + SUBROUTINE InitBCs(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(INOUT) :: p + INTEGER(IntKi) :: I, J, iNode + Init%BCs = -9999 + DO I = 1, p%nNodes_C + iNode = p%Nodes_C(I,1) ! Node index + DO J = 1, 6 + Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) + Init%BCs( (I-1)*6+J, 2) = idBC_Fixed + p%Nodes_C(I, J+1) = idBC_Fixed + else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF + Init%BCs( (I-1)*6+J, 2) = idBC_Internal + p%Nodes_C(I, J+1) = idBC_Internal + else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF + Init%BCs( (I-1)*6+J, 2) = idBC_Leader + p%Nodes_C(I, J+1) = idBC_Leader + print*,'BC 2 not allowed for now, node',iNode + STOP + else + print*,'Wrong boundary condition input for reaction node',iNode + STOP + endif + ENDDO + ENDDO + END SUBROUTINE InitBCs + + !> Sets a list of DOF indices and the value these DOF should have + !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs + !! TODO remove me and merge me with CraigBampton + SUBROUTINE InitIntFc(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(INOUT) :: p + INTEGER(IntKi) :: I, J, iNode + Init%IntFc = -9999 + DO I = 1, p%nNodes_I + iNode = p%Nodes_I(I,1) ! Node index + DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) + + if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF + Init%IntFc((I-1)*6+J, 2) = idBC_Leader + p%Nodes_I(I,J+1) = idBC_Leader + elseif (p%Nodes_I(I,J+1)==1) then ! User input 0=Fixed DOF + Init%IntFc( (I-1)*6+J, 2) = idBC_Fixed + p%Nodes_I(I,J+1) = idBC_Fixed + print*,'Fixed boundary condition not yet supported for interface nodes, node:',iNode + STOP + else + print*,'Wrong boundary condition input for interface node',iNode + STOP + endif + ENDDO + ENDDO + END SUBROUTINE InitIntFc + +END SUBROUTINE DistributeDOF + +!------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector +SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K + INTEGER :: iGlob + REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + REAL(ReKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: iNode !< Node index + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system + real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node + real(ReKi) :: m, x, y, z, Jxx, Jyy, Jzz, Jxy, Jxz, Jyz + INTEGER :: jGlob, kGlob + ErrMsg = "" + ErrStat = ErrID_None + + ! total unconstrained degrees of freedom of the system + p%nDOF = nDOF_Unconstrained() + if (DEV_VERSION) then + print*,'nDOF_unconstrained:',p%nDOF, ' (if all Cantilever, it would be: ',6*p%nNodes,')' + endif + + CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + Init%K = 0.0_ReKi + Init%M = 0.0_ReKi + Init%FG = 0.0_ReKi + + ! loop over all elements, compute element matrices and assemble into global matrices + DO i = 1, Init%NElem + ! --- Element Me,Ke,Fg, Fce + CALL ElemM(p%ElemProps(i), Me) + CALL ElemK(p%ElemProps(i), Ke) + CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) + + ! --- Assembly in global unconstrained system + IDOF = p%ElemsDOF(1:12, i) + Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces + Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) + Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) + ENDDO + + ! Add concentrated mass to mass matrix + DO I = 1, Init%nCMass + iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added + ! Safety check (otherwise we might have more than 6 DOF) + if (Init%Nodes(iNode,iJointType) /= idJointCantilever) then + ErrMsg2='Concentrated mass is only for cantilever joints. Problematic node: '//trim(Num2LStr(iNode)); ErrStat2=ErrID_Fatal; + if(Failed()) return + endif + ! Mass matrix of a rigid body + M66 = 0.0_ReKi + m = Init%CMass(I,2) + Jxx = Init%CMass(I,3 ); Jxy = Init%CMass(I,6 ); x = Init%CMass(I,9 ); + Jyy = Init%CMass(I,4 ); Jxz = Init%CMass(I,7 ); y = Init%CMass(I,10); + Jzz = Init%CMass(I,5 ); Jyz = Init%CMass(I,8 ); z = Init%CMass(I,11); + M66(1 , :)=(/ m , 0._ReKi , 0._ReKi , 0._ReKi , z*m , -y*m /) + M66(2 , :)=(/ 0._ReKi , m , 0._ReKi , -z*m , 0._ReKi , x*m /) + M66(3 , :)=(/ 0._ReKi , 0._ReKi , m , y*m , -x*m , 0._ReKi /) + M66(4 , :)=(/ 0._ReKi , -z*m , y*m , Jxx + m*(y**2+z**2) , Jxy - m*x*y , Jxz - m*x*z /) + M66(5 , :)=(/ z*m , 0._ReKi , -x*m , Jxy - m*x*y , Jyy + m*(x**2+z**2) , Jyz - m*y*z /) + M66(6 , :)=(/ -y*m , x*m , 0._ReKi , Jxz - m*x*z , Jyz - m*y*z , Jzz + m*(x**2+y**2) /) + ! Adding + DO J = 1, 6 + jGlob = p%NodesDOF(iNode)%List(J) + DO K = 1, 6 + kGlob = p%NodesDOF(iNode)%List(K) + Init%M(jGlob, kGlob) = Init%M(jGlob, kGlob) + M66(J,K) + ENDDO + ENDDO + ENDDO ! Loop on concentrated mass + + ! Add concentrated mass induced gravity force + DO I = 1, Init%nCMass + iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added + iGlob = p%NodesDOF(iNode)%List(3) ! uz + Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g + ENDDO + + CALL CleanUp_AssembleKM() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM') + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup_AssembleKM() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); + CALL CleanUp_AssembleKM() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp_AssembleKM() + !pass + END SUBROUTINE CleanUp_AssembleKM + + INTEGER(IntKi) FUNCTION nDOF_Unconstrained() + integer(IntKi) :: i + integer(IntKi) :: m + nDOF_Unconstrained=0 + do i = 1,p%nNodes + if (int(Init%Nodes(i,iJointType)) == idJointCantilever ) then + nDOF_Unconstrained = nDOF_Unconstrained + 6 + else + m = Init%NodesConnE(i,1) ! Col1: number of elements connected to this joint + nDOF_Unconstrained = nDOF_Unconstrained + 3 + 3*m + endif + end do + END FUNCTION + +END SUBROUTINE AssembleKM + +!> Add soil stiffness and mass to global system matrices +!! Soil stiffness can come from two sources: +!! - "SSI" matrices (specified at reaction nodes) +!! - "Soil" matrices (specified at Initalization) +SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) + real(ReKi), dimension(:,:), intent(inout) :: M + real(ReKi), dimension(:,:), intent(inout) :: K + type(IList),dimension(:), intent(in ) :: NodesDOF !< Map from Node Index to DOF lists + type(SD_InitType), intent(inout) :: Init !< TODO set it to in only + type(SD_ParameterType), intent(in ) :: p + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding + integer :: I, J, iiNode, nDOF + integer :: iDOF, jDOF, iNode !< DOF and node indices + real(ReKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil + real(ReKi) :: Dist + ErrMsg = "" + ErrStat = ErrID_None + ! --- SSI matrices + ! TODO consider doing the 21 -> 6x6 conversion while reading + ! 6x6 matrix goes to one node of one element only + do iiNode = 1, p%nNodes_C ! loop on constrained nodes + iNode = p%Nodes_C(iiNode,1) + nDOF=size(NodesDOF(iNode)%List) + if (nDOF/=6) then + ErrMsg='SSI soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; + ErrStat=ErrID_Fatal; return + endif + call Array21_to_6by6(Init%SSIK(:,iiNode), K_soil) + call Array21_to_6by6(Init%SSIM(:,iiNode), M_soil) + if (present(Substract)) then + if (Substract) then + K_soil = - K_soil + M_soil = - M_soil + endif + endif + do I = 1, 6 + iDOF = NodesDOF(iNode)%List(I) ! DOF index + do J = 1, 6 + jDOF = NodesDOF(iNode)%List(J) ! DOF index + K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) + M(iDOF, jDOF) = M(iDOF, jDOF) + M_soil(I,J) + enddo + enddo + enddo + ! --- "Soil" matrices + if (allocated(Init%Soil_K)) then + do iiNode = 1,size(Init%Soil_Points,2) + ! --- Find closest node + call FindClosestNodes(Init%Soil_Points(1:3,iiNode), Init%Nodes, iNode, Dist); + if (Dist>0.1_ReKi) then + ErrMsg='Closest SubDyn Node is node '//Num2LStr(iNode)//', which is more than 0.1m away from soildyn point '//num2lstr(iiNode); + ErrStat=ErrID_Fatal; return + endif + Init%Soil_Nodes(iiNode) = iNode + ! --- Insert/remove from matrices + nDOF=size(NodesDOF(iNode)%List) + if (nDOF/=6) then + ErrMsg='Soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; + ErrStat=ErrID_Fatal; return + endif + K_soil = Init%Soil_K(1:6,1:6,iiNode) + if (present(Substract)) then + if (Substract) then + K_soil = - K_soil + endif + endif + do I = 1, 6 + iDOF = NodesDOF(iNode)%List(I) ! DOF index + do J = 1, 6 + jDOF = NodesDOF(iNode)%List(J) ! DOF index + K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) + enddo + enddo + if (.not.present(Substract)) then + CALL WrScr(' Soil stiffness inserted at SubDyn node '//trim(Num2LStr(iNode))) + endif + enddo + endif +contains + !> Convert a flatten array of 21 values into a symmetric 6x6 matrix + SUBROUTINE Array21_to_6by6(A21, M66) + use NWTC_LAPACK, only: LAPACK_TPTTR + real(ReKi), dimension(21) , intent(in) :: A21 + real(ReKi), dimension(6,6), intent(out) :: M66 + integer :: j + M66 = 0.0_ReKi + ! Reconstruct from sparse elements + CALL LAPACK_TPTTR('U',6,A21,M66,6, ErrStat, ErrMsg) + ! Ensuring symmetry + do j=1,6 + M66(j,j) = M66(j,j)/2 + enddo + M66=M66+TRANSPOSE(M66) + END SUBROUTINE Array21_to_6by6 +END SUBROUTINE InsertSoilMatrices + +!------------------------------------------------------------------------------------------------------ +!> Find closest node index to a point, returns distance as well +SUBROUTINE FindClosestNodes(Point, Nodes, iNode, Dist) + real(ReKi), dimension(3), intent(IN ) :: Point !< Point coordinates + real(ReKi), dimension(:,:), intent(IN ) :: Nodes !< List of nodes, Positions are in columns 2-4... + integer(IntKi), intent( OUT) :: iNode !< Index of closest node + real(ReKi), intent( OUT) :: Dist !< Distance from Point to node iNode + integer(IntKi) :: I + real(ReKi) :: min_dist, loc_dist + ! + min_dist=999999._ReKi + iNode=-1 + do i = 1, size(Nodes,1) + loc_dist = sqrt((Point(1) - Nodes(i,2))**2 + (Point(2) - Nodes(i,3))**2+ (Point(3) - Nodes(i,4))**2) + if (loc_dist Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF +SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) + use IntegerList, only: init_list, find, pop, destroy_list, len + use IntegerList, only: print_list + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType),target,INTENT(INOUT) :: p + type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination + ! Local + real(ReKi), dimension(:,:), allocatable :: Tc + integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements + integer(IntKi), dimension(:), allocatable :: IDOFOld !< + integer(IntKi), dimension(:), pointer :: IDOFNew !< + real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 + integer(IntKi) :: iPrev + type(IList) :: IRA !< list of rigid assembly indices to process + integer(IntKi) :: aID, ia ! assembly ID, and index in IRA + integer(IntKi) :: iNode + integer(IntKi) :: er !< Index of one rigid element belong to a rigid assembly + integer(IntKi) :: JType + integer(IntKi) :: I + integer(IntKi) :: nc !< Number of DOF after constraints applied + integer(IntKi) :: nj + real(ReKi) :: phat(3) !< Directional vector of the joint + type(IList), dimension(:), allocatable :: RA_DOFtilde ! DOF indices for each rigid assembly, in reduced system + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Misc inits + nullify(IDOFNew) + I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) + allocate(p%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + allocate(RA_DOFtilde(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system + + p%nDOF_red = nDOF_ConstraintReduced() + if (DEV_VERSION) then + print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF + endif + CALL AllocAry( Tred, p%nDOF, p%nDOF_red, 'p%T_red', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + Tred=0 + call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; + IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) + if (DEV_VERSION) then + call print_list(IRA, 'List of RA indices') + endif + + ! --- For each node: + ! - create list of indices I in the assembled vector of DOF + ! - create list of indices Itilde in the reduced vector of DOF + ! - increment iPrev by the number of DOF of Itilde + iPrev =0 + do iNode = 1, p%nNodes + if (allocated(Tc)) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + JType = int(Init%Nodes(iNode,iJointType)) + if(JType == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p, er)) then + ! --- Joint involved in a rigid link assembly + aID = RAm1(er) + if (aID<0) then + call Fatal('No rigid assembly attributed to node'//trim(Num2LStr(iNode))//'. RAm1 wrong'); return + endif + ia = find(IRA, aID, ErrStat2, ErrMsg2); if(Failed()) return + if (DEV_VERSION) then + print*,'Node',iNode, 'is involved in RA:', aID, '. Index in list of RA to process', ia + endif + if ( ia <= 0) then + ! This rigid assembly has already been processed + ! OLD: The DOF list is taken from the stored RA DOF list + ! call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) + ! NEW: this node has no DOFs + call init_list(p%NodesDOFtilde(iNode), 0, 0, ErrStat2, ErrMsg2) + if (DEV_VERSION) then + print*,'The RA',aID,', has already been processed!' + print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) + print*,'N',iNode,'It',RA_DOFtilde(aID)%List + endif + cycle ! We pass to the next joint + else + call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; + aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed + nj = size(INodesID) + allocate(IDOFOld(1:6*nj)) + do I=1, nj + IDOFOld( (I-1)*6+1 : I*6 ) = p%NodesDOF(INodesID(I))%List(1:6) + enddo + + ! Storing DOF list for this RA (Note: same as NodesDOFtilde below) + nc=size(Tc,2) + call init_list(RA_DOFtilde(aID), (/ (iprev + i, i=1,nc) /), ErrStat2, ErrMsg2); + + endif + else + ! --- Regular cantilever joint + ! TODO/NOTE: We could apply fixed constraint/BC here, returning Tc as a 6xn matrix with n<6 + ! Extreme case would be Tc: 6*0, in which case NodesDOFtilde would be empty ([]) + allocate(Tc(1:6,1:6)) + allocate(IDOFOld(1:6)) + Tc=I6 + IDOFOld = p%NodesDOF(iNode)%List(1:6) + endif + else + ! --- Ball/Pin/Universal joint + allocate(IDOFOld(1:len(p%NodesDOF(iNode)))) + IDOFOld(:) = p%NodesDOF(iNode)%List(:) + phat = Init%Nodes(iNode, iJointDir:iJointDir+2) + call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return + endif + nc=size(Tc,2) + call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) + p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) + IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations + !print*,'N',iNode,'I ',IDOFOld + !print*,'N',iNode,'It',IDOFNew + Tred(IDOFOld, IDOFNew) = Tc + iPrev = iPrev + nc + enddo + ! --- Safety checks + if (len(IRA)>0) then + call Fatal('Not all rigid assemblies were processed'); return + endif + if (iPrev /= p%nDOF_red) then + call Fatal('Inconsistency in number of reduced DOF'); return + endif + call CleanUp_BuildTMatrix() +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'BuildTMatrix') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp_BuildTMatrix() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + CHARACTER(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'BuildTMatrix'); + END SUBROUTINE Fatal + + SUBROUTINE CleanUp_BuildTMatrix() + nullify(IDOFNew) + call destroy_list(IRA, ErrStat2, ErrMsg2) + if (allocated(Tc) ) deallocate(Tc) + if (allocated(IDOFOld)) deallocate(IDOFOld) + if (allocated(INodesID)) deallocate(INodesID) + END SUBROUTINE CleanUp_BuildTMatrix + + !> Returns number of DOF after constraint reduction (via the matrix T) + INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() + integer(IntKi) :: iNode + integer(IntKi) :: ia ! Index on rigid link assembly + integer(IntKi) :: m ! Number of elements connected to a joint + integer(IntKi) :: NodeType + nDOF_ConstraintReduced = 0 + + ! Rigid assemblies contribution + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) + + ! Contribution from all the other joints + do iNode = 1, p%nNodes + m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint + NodeType = Init%Nodes(iNode,iJointType) + + if (NodeType == idJointPin ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m + print*,'Node',iNode, 'is a pin joint, number of members involved: ', m + + elseif(NodeType == idJointUniversal ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m + print*,'Node',iNode, 'is an universal joint, number of members involved: ', m + + elseif(NodeType == idJointBall ) then + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 3 + 3*m + print*,'Node',iNode, 'is a ball joint, number of members involved: ', m + + elseif(NodeType == idJointCantilever ) then + if ( NodeHasRigidElem(iNode, Init, p, er)) then + ! This joint is involved in a rigid link assembly, we skip it (accounted for above) + print*,'Node',iNode, 'is involved in a Rigid assembly' + else + ! That's a regular Cantilever joint + nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 + !print*,'Node',iNode, 'is a regular cantilever' + endif + else + ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal + endif + end do + END FUNCTION nDOF_ConstraintReduced +END SUBROUTINE BuildTMatrix +!------------------------------------------------------------------------------------------------------ +!> Assemble stiffness and mass matrix, and gravity force vector +SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) + use IntegerList, only: len + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType),target,INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! Varaibles for rigid assembly + type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + real(ReKi), dimension(:,:), allocatable :: MM, KK + real(ReKi), dimension(:), allocatable :: FF + integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF + ErrStat = ErrID_None + ErrMsg = "" + + ! Setup list of rigid link assemblies (RA) and the inverse function RA^{-1} + call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return + + call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return + + ! --- DOF elimination for system matrices and RHS vector + ! Temporary backup of M and K of full system + call move_alloc(Init%M, MM) + call move_alloc(Init%K, KK) + call move_alloc(Init%FG, FF) + ! Reallocating + nDOF = p%nDOF_red + CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + ! Elimination + Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) + Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) + Init%FG = matmul(transpose(p%T_red), FF) + Init%D = 0 !< Used for additional stiffness + + ! --- Triggers for storage of DOF indices, replacing with indices in constrained system + CALL ReInitBCs(Init, p) + CALL ReInitIntFc(Init, p) + + ! --- Creating a convenient Map from DOF to Nodes + call AllocAry(p%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; + p%DOFtilde2Nodes=-999 + do iNode=1,p%nNodes + nDOFPerNode = len(p%NodesDOFtilde(iNode)) + do iiDOF = 1, nDOFPerNode + iDOF = p%NodesDOFtilde(iNode)%List(iiDOF) + p%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index + p%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node + p%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node + enddo + enddo + + call CleanUp_DirectElimination() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'DirectElimination') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp_DirectElimination() + END FUNCTION Failed + SUBROUTINE CleanUp_DirectElimination() + ! Cleaning up memory + if (allocated(MM )) deallocate(MM ) + if (allocated(KK )) deallocate(KK ) + if (allocated(FF )) deallocate(FF ) + if (allocated(RA )) deallocate(RA ) + if (allocated(RAm1)) deallocate(RAm1) + if (allocated(RA )) deallocate(RA ) + END SUBROUTINE CleanUp_DirectElimination + + !> Reset DOF indices after elimination, does not change the BC + SUBROUTINE ReInitBCs(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + DO I = 1, p%nNodes_C + iNode = p%Nodes_C(I,1) ! Node index + DO J = 1, 6 ! TODO NOTE here assumptions that 6 DOF are present + Init%BCs( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) + ENDDO + ENDDO + END SUBROUTINE ReInitBCs + + !> Reset DOF indices after elimination + SUBROUTINE ReInitIntFc(Init, p) + TYPE(SD_InitType ),INTENT(INOUT) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: I, J, iNode + DO I = 1, p%nNodes_I + iNode = p%Nodes_I(I,1) ! Node index + DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) + ENDDO + ENDDO + END SUBROUTINE ReInitIntFc +END SUBROUTINE DirectElimination + +!------------------------------------------------------------------------------------------------------ +!> Returns constraint matrix Tc for a rigid assembly (RA) formed by a set of elements. +!! x_c = Tc.x_c_tilde +!! where x_c are all the DOF of the rigid assembly, and x_c_tilde are the 6 reduced DOF (leader DOF) +SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get, unique, find + integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements + real(ReKi), dimension(:,:), allocatable :: Tc + integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + type(IList) :: LNodesID !< List of nodes id involved in element + type(IList) :: LNodesInterf !< List of nodes id involved in interface + integer(IntKi) :: NodeID !< NodeID + integer(IntKi) :: iTmp !< Temporary index + integer(IntKi) :: iNodeID !< Loop index on node ID list + integer(IntKi) :: iiMainNode !< Index of main node selected for rigid assembly within INodesID list + integer(IntKi) :: iMainNode !< Main node index + integer(IntKi) :: nNodes !< Number of Nodes involved in RA + integer(IntKi) :: iFound !< Loop index on node ID list + integer(IntKi) :: i !< Loop index + real(ReKi) :: TRigid(6,6) ! Transformation matrix such that xi = T.x1 + real(ReKi) :: P1(3), Pi(3) ! Nodal points + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! --- List of nodes stored first in LINodes than moved to INodes + LNodesID = NodesList(p, Elements) + if (DEV_VERSION) then + print*,'Nodes involved in assembly (bfr1) ',LNodesID%List + endif + call unique(LNodesID, ErrStat2, ErrMsg2); + if (DEV_VERSION) then + print*,'Nodes involved in assembly (bfr2) ',LNodesID%List + endif + + !--- Look for potential interface node + call init_list(LNodesInterf, 0, 0, ErrStat2, ErrMsg2); + do iNodeID = 1, len(LNodesID) + NodeID = LNodesID%List(iNodeID) + iFound = FINDLOCI( p%Nodes_I(:,1), NodeID) + if (iFound>0) then + call append(LNodesInterf, NodeID, ErrStat2, ErrMsg2) + ! This node is an interface node + print*,'Node',NodeID, 'is an interface node, selecting it for the rigid assembly' + endif + enddo + + ! --- Decide which node will be the main node of the rigid assembly + if (len(LNodesInterf)==0) then + iiMainNode = 1 ! By default we select the first node + else if (len(LNodesInterf)==1) then + ! Finding the index of the interface node + iMainNode = pop(LNodesInterf, ErrStat2, ErrMsg2) + iiMainNode = find(LNodesID, iMainNode, ErrStat2, ErrMsg2); + else + ErrStat=ErrID_Fatal + ErrMsg='Cannot have several interface nodes linked within a same rigid assembly' + return + endif + call destroy_list(LNodesInterf, ErrStat2, ErrMsg2) + + ! --- Extracting index array from list + if (allocated(INodesID)) deallocate(INodesID) + call move_alloc(LNodesID%List, INodesID) + call destroy_list(LNodesID, ErrStat2, ErrMsg2) + + ! --- Order list of joints with main node first (swapping iMainNode with INodes(1)) + iTmp = INodesID(1) + INodesID(1) = INodesID(iiMainNode) + INodesID(iiMainNode) = iTmp + if (DEV_VERSION) then + print*,'Nodes involved in assembly (after)',INodesID + endif + + ! --- Building Transformation matrix + nNodes =size(INodesID) + allocate(Tc(6*nNodes,6)) + Tc(:,:)=0 + ! I6 for first node + do i = 1,6 ; Tc(i,i)=1_ReKi; enddo ! I6 = eye(6) + ! Rigid transformation matrix for the other nodes + P1 = Init%Nodes(INodesID(1), 2:4) ! reference node coordinates + do i = 2, nNodes + Pi = Init%Nodes(INodesID(i), 2:4) ! follower node coordinates + call GetRigidTransformation(P1, Pi, TRigid, ErrStat2, ErrMsg2) + Tc( ((i-1)*6)+1:6*i, 1:6) = TRigid(1:6,1:6) + enddo +END SUBROUTINE RAElimination +!------------------------------------------------------------------------------------------------------ +!> Returns constraint matrix Tc for a joint involving several Elements +!! x_c = Tc.x_c_tilde +!! where +! x_c are all the DOF of the joint (3 translation + 3*m, m the number of elements) +! x_c_tilde are the nc reduced DOF +SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements involved at a joint + integer(IntKi), INTENT(IN ) :: JType !< Joint type + real(ReKi), INTENT(IN ) :: phat(3) !< Directional vector of the joint + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType), INTENT(IN ) :: p + real(ReKi), dimension(:,:), allocatable :: Tc !< Transformation matrix from eliminated to full + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Local variables + !type(IList) :: I !< List of indices for Nodes involved in interface + integer(IntKi) :: i, j, ie, ne !< Loop index + integer(IntKi) :: nDOFr !< Number of reduced DOF + integer(IntKi) :: nDOFt !< Number of total DOF *nreduced) + real(ReKi) :: e1(3), e2(3), e3(3) ! forming orthonormal basis with phat + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + real(LaKi), dimension(:,:), allocatable :: Tc_rot !< Part of Tc just for rotational DOF + real(LaKi), dimension(:,:), allocatable :: Tc_rot_m1 !< Inverse of Tc_rot + real(ReKi) :: ColMean + ErrStat = ErrID_None + ErrMsg = "" + + ne = Elements(1) ! TODO TODO + nDOFt = 3 + 3*ne + + ! The elements already share the same translational DOF + + if (JType == idJointPin ) then + nDOFr = 5 + 1*ne + allocate(Tc (nDOFt, nDOFr)); + allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); + Tc(:,:)=0 + Tc_rot_m1(:,:)=0 + + ! Normalizing + e3= phat/sqrt(phat(1)**2 + phat(2)**2 + phat(3)**2) + call GetOrthVectors(e3, e1, e2, ErrStat2, ErrMsg2); + ! Forming Tcm1, inverse of Tc + do ie=1,ne + Tc_rot_m1(1 , (ie-1)*3+1:ie*3 ) = e1(1:3)/ne + Tc_rot_m1(2 , (ie-1)*3+1:ie*3 ) = e2(1:3)/ne + Tc_rot_m1(ie+2, (ie-1)*3+1:ie*3 ) = e3(1:3) + enddo + ! Pseudo inverse: + call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) + ! --- Forming Tc + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) + deallocate(Tc_rot) + deallocate(Tc_rot_m1) + + elseif(JType == idJointUniversal ) then + if (ne/=2) then + ErrMsg='JointElimination: universal joints should only connect two elements.'; ErrStat=ErrID_Fatal + return + endif + nDOFr = 4 + 2*ne + allocate(Tc(nDOFt, nDOFr)); + allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); + Tc(:,:)=0 + Tc_rot_m1(:,:)=0 ! Important init + ! Forming the inverse of Tc_rot + Tc_rot_m1(1,1:3) = p%ElemProps(Elements(1))%DirCos(:,3)/2._ReKi + Tc_rot_m1(1,4:6) = p%ElemProps(Elements(2))%DirCos(:,3)/2._ReKi + Tc_rot_m1(2,1:3) = p%ElemProps(Elements(1))%DirCos(:,1) + Tc_rot_m1(3,1:3) = p%ElemProps(Elements(1))%DirCos(:,2) + Tc_rot_m1(4,4:6) = p%ElemProps(Elements(2))%DirCos(:,1) + Tc_rot_m1(5,4:6) = p%ElemProps(Elements(2))%DirCos(:,2) + ! Pseudo inverse + call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) + ! --- Forming Tc + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) + deallocate(Tc_rot) + deallocate(Tc_rot_m1) + + elseif(JType == idJointBall ) then + nDOFr = 3 + 3*ne + allocate(Tc(nDOFt, nDOFr)); + Tc(:,:)=0 + do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF + do i = 3,nDOFr; Tc(i,i)=1_ReKi; enddo ! Identity for other DOF as well + + else + ErrMsg='JointElimination: Wrong joint type'; ErrStat=ErrID_Fatal + endif + !do i=1,nDOFt + ! print*,'Tc',Tc(i,:) + !enddo + ! --- Safety check + do j =1, size(Tc,2) + ColMean=0; do i=1,size(Tc,1) ; ColMean = ColMean + abs(Tc(i,j)); enddo + ColMean = ColMean/size(Tc,1) + if (ColMean<1e-6) then + ErrMsg='JointElimination: a reduced degree of freedom has a singular mapping.'; ErrStat=ErrID_Fatal + return + endif + enddo + +END SUBROUTINE JointElimination + +!------------------------------------------------------------------------------------------------------ +!> Setup a list of rigid link assemblies (RA) +!! RA(a) = [e1,..,en] : list of elements that form the rigid assembly of index "a" +SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) + use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get + TYPE(SD_InitType), INTENT(INOUT) :: Init + TYPE(SD_ParameterType), INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly + integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly + ! Local variables + type(IList) :: Er !< List of rigid elements + type(IList) :: Ea !< List of elements in a rigid assembly + integer(IntKi) :: nRA !< Number of rigid assemblies + integer(IntKi) :: ie !< Index on elements + integer(IntKi) :: ia !< Index on assemblies + integer(IntKi) :: e0 !< Index of an element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + allocate(RAm1(1:Init%NElem)) + RAm1(1:Init%NElem) = -1 + + ! --- Establish a list of rigid link elements + Er = RigidLinkElements(Init, p, ErrStat2, ErrMsg2) + nRA=0 + do while (len(Er)>0) + nRA=nRA+1 + ! Creating List Ea of elements of a given assembly + call init_list(Ea, 0, 0, ErrStat2, ErrMsg2); + e0 = pop(Er, ErrStat2, ErrMsg2); + call append(Ea, e0, ErrStat2, ErrMsg2); + call AddNeighbors(e0, Er, Ea) + if (DEV_VERSION) then + call print_list(Ea,'Rigid assembly (loop 1)') + endif + do ie = 1, len(Ea) + e0 = get(Ea, ie, ErrStat2, ErrMsg2) + RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to + enddo + call destroy_list(Ea, ErrStat2, ErrMsg2) + enddo + call destroy_list(Er, ErrStat2, ErrMsg2) + + ! --- Creating RA, array of lists of assembly elements. + ! Note: exactly the same as all the Ea created above, but we didn't know the total number of RA + allocate(RA(1:nRA)) + do ia = 1, nRA + call init_list(RA(ia), 0, 0, ErrStat2, ErrMsg2) + enddo + do ie = 1, Init%NElem + ia = RAm1(ie) ! Index of the assembly the element belongs to: RA^{-1}(ie) = ia + if (ia>0) then + call append(RA(ia), ie, ErrStat2, ErrMsg2) + endif + enddo + if (DEV_VERSION) then + do ia = 1, nRA + call print_list(RA(ia),'Rigid assembly (loop 2)') + enddo + endif +CONTAINS + !> The neighbor-elements of element e0 (that are found within the list Er) are added to the list Ea + RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) + integer(IntKi), intent(in) :: e0 !< Index of an element + type(IList), intent(inout) :: Er !< List of rigid elements + type(IList), intent(inout) :: Ea !< List of elements in a rigid assembly + type(IList) :: En !< List of neighbors of e0 + integer (IntKi) :: ik + integer (IntKi) :: ek, ek2 + integer (IntKi) :: iWhichNode_e0, iWhichNode_ek + call init_list(En, 0, 0, ErrStat2, ErrMsg2) + ! Loop through all elements, setup list of e0-neighbors, add them to Ea, remove them from Er + ik=0 + do while (ik< len(Er)) + ik=ik+1 + ek = Er%List(ik) + if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then + if (DEV_VERSION) then + print*,'Element ',ek,'is connected to element',e0,'via its node',iWhichNode_ek + endif + ! Remove element from Er (a rigid element can belong to only one assembly) + ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before + ik=ik-1 + if (ek/=ek2) then + print*,'Problem in popping',ek,ek2 + STOP + endif + call append(En, ek, ErrStat2, ErrMsg2) + call append(Ea, ek, ErrStat2, ErrMsg2) + endif + enddo + ! Loop through neighbors and recursively add neighbors of neighbors + do ik = 1, len(En) + ek = En%List(ik) + call AddNeighbors(ek, Er, Ea) + enddo + call destroy_list(En, ErrStat2, ErrMsg2) + END SUBROUTINE AddNeighbors + +END SUBROUTINE RigidLinkAssemblies + + +!------------------------------------------------------------------------------------------------------ +!> Add stiffness and damping to some joints +SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) + TYPE(SD_ParameterType),target,INTENT(IN ) :: p + TYPE(SD_InitType), INTENT(INOUT) :: Init + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer(IntKi) :: iNode, JType, iStart + real(ReKi) :: StifAdd, DampAdd + integer(IntKi), dimension(:), pointer :: Ifreerot + ErrStat = ErrID_None + ErrMsg = "" + do iNode = 1, p%nNodes + JType = int(Init%Nodes(iNode,iJointType)) + StifAdd = Init%Nodes(iNode, iJointStiff) + DampAdd = Init%Nodes(iNode, iJointDamp ) + if(JType == idJointCantilever ) then + ! Cantilever joints should not have damping or stiffness + if(StifAdd>0) then + ErrMsg='InsertJointStiffDamp: Additional stiffness should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; + return + endif + if(DampAdd>0) then + ErrMsg='InsertJointStiffDamp: Additional damping should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; + return + endif + else + ! Ball/Univ/Pin joints have damping/stiffness inserted at indices of "free rotation" + if ( JType == idJointBall ) then; iStart=4; + else if ( JType == idJointUniversal ) then; iStart=5; + else if ( JType == idJointPin ) then; iStart=6; + endif + Ifreerot=>p%NodesDOFtilde(iNode)%List(iStart:) + ! Ball/Pin/Universal joints + if(StifAdd>0) then + print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot + Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd + endif + if(DampAdd>0) then + print*,'DampAdd, Node',iNode,DampAdd, Ifreerot + Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd + endif + endif + enddo +END SUBROUTINE InsertJointStiffDamp + +SUBROUTINE ElemM(ep, Me) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(OUT) :: Me(12, 12) + REAL(ReKi) :: L0, Eps0 + if (ep%eType==idMemberBeam) then + !Calculate Ke, Me to be used for output + CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) + + else if (ep%eType==idMemberCable) then + Eps0 = ep%T0/(ep%YoungE*ep%Area) + L0 = ep%Length/(1+Eps0) ! "rest length" for which pretension would be 0 + CALL ElemM_Cable(ep%Area, L0, ep%rho, ep%DirCos, Me) + + else if (ep%eType==idMemberRigid) then + if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then + Me=0.0_ReKi + else + CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) + !CALL ElemM_(A, L, rho, DirCos, Me) + endif + endif +END SUBROUTINE ElemM + +SUBROUTINE ElemK(ep, Ke) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(OUT) :: Ke(12, 12) + + if (ep%eType==idMemberBeam) then + CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) + + else if (ep%eType==idMemberCable) then + CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) + + else if (ep%eType==idMemberRigid) then + Ke = 0.0_ReKi + endif +END SUBROUTINE ElemK + +SUBROUTINE ElemF(ep, gravity, Fg, Fo) + TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property + REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity + REAL(ReKi), INTENT(OUT) :: Fg(12) + REAL(ReKi), INTENT(OUT) :: Fo(12) + if (ep%eType==idMemberBeam) then + Fo(1:12)=0 + else if (ep%eType==idMemberCable) then + CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) + else if (ep%eType==idMemberRigid) then + Fo(1:12)=0 + endif + CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) +END SUBROUTINE ElemF + +END MODULE SD_FEM diff --git a/modules/subdyn/src_soildyn/SubDyn.f90 b/modules/subdyn/src_soildyn/SubDyn.f90 new file mode 100644 index 000000000..75ae62056 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn.f90 @@ -0,0 +1,2885 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** +!> SubDyn is a time-domain structural-dynamics module for multi-member fixed-bottom substructures. +!! SubDyn relies on two main engineering schematizations: (1) a linear frame finite-element beam model (LFEB), and +!! (2) a dynamics system reduction via Craig-Bampton's (C-B) method, together with a Static-Improvement method, greatly reducing +!! the number of modes needed to obtain an accurate solution. +Module SubDyn + + USE NWTC_Library + USE SubDyn_Types + USE SubDyn_Output + USE SubDyn_Tests + USE SD_FEM + + IMPLICIT NONE + + PRIVATE + + !............................ + ! NOTE: for debugging, add preprocessor definition SD_SUMMARY_DEBUG + ! this will add additional matrices to the SubDyn summary file. + !............................ + TYPE(ProgDesc), PARAMETER :: SD_ProgDesc = ProgDesc( 'SubDyn', '', '' ) + + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: SD_Init ! Initialization routine + PUBLIC :: SD_End ! Ending routine (includes clean up) + PUBLIC :: SD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating + PUBLIC :: SD_CalcOutput ! Routine for computing outputs + PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + +CONTAINS + +SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) + REAL(ReKi), INTENT( IN ) :: TP_RefPoint(3) + TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%TPMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y1Mesh + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + ! NOTE: The initialization of the fields for these meshes is to be handled by FAST/Driver + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = 1 & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + ! Create the node and mesh element, note: assumes identiy matrix as reference orientation + CALL MeshPositionNode (inputMesh, 1, TP_RefPoint, ErrStat, ErrMsg); IF(ErrStat>=AbortErrLev) return + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1) + CALL MeshCommit( inputMesh, ErrStat, ErrMsg); if(ErrStat >= AbortErrLev) return + + ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh + CALL MeshCopy ( SrcMesh = inputMesh & + ,DestMesh = outputMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) +END SUBROUTINE CreateTPMeshes +!--------------------------------------------------------------------------- +!> Create output (Y2, for motion) and input (u, for forces)meshes, based on SubDyn nodes +!! Ordering of nodes is the same as SubDyn (used to be : I L C) +SUBROUTINE CreateInputOutputMeshes( NNode, Nodes, inputMesh, outputMesh, ErrStat, ErrMsg ) + INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows + REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) + TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%LMesh + TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y2Mesh + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + REAL(ReKi), dimension(3) :: Point + INTEGER :: I, iOffset, iNode ! generic counter variable + INTEGER :: nodeIndx + + CALL MeshCreate( BlankMesh = inputMesh & + ,IOS = COMPONENT_INPUT & + ,Nnodes = size(Nodes,1) & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,Force = .TRUE. & + ,Moment = .TRUE. ) + + DO I = 1,size(Nodes,1) + Point = Nodes(I, 2:4) + CALL MeshPositionNode(inputMesh, I, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I) + ENDDO + CALL MeshCommit ( inputMesh, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN + + ! Create the Interior Points output mesh as a sibling copy of the input mesh + CALL MeshCopy ( SrcMesh = inputMesh & + ,DestMesh = outputMesh & + ,CtrlCode = MESH_SIBLING & + ,IOS = COMPONENT_OUTPUT & + ,ErrStat = ErrStat & + ,ErrMess = ErrMsg & + ,TranslationDisp = .TRUE. & + ,Orientation = .TRUE. & + ,TranslationVel = .TRUE. & + ,RotationVel = .TRUE. & + ,TranslationAcc = .TRUE. & + ,RotationAcc = .TRUE. ) + + ! Set the Orientation (rotational) field for the nodes based on assumed 0 (rotational) deflections + !Identity should mean no rotation, which is our first guess at the output -RRD + CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) + +END SUBROUTINE CreateInputOutputMeshes +!--------------------------------------------------------------------------- +!> This routine is called at the start of the simulation to perform initialization steps. +!! The parameters are set here and not changed during the simulation. +!! The initial states and initial guess for the input are defined. +SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(IN ) :: InitInput !< Input data for initialization routine + TYPE(SD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined + TYPE(SD_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states + TYPE(SD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states + TYPE(SD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states + TYPE(SD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states + TYPE(SD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; + !! only the output mesh is initialized) + REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that + !! (1) Mod1_UpdateStates() is called in loose coupling & + !! (2) Mod1_UpdateDiscState() is called in tight coupling. + !! Input is the suggested time from the glue code; + !! Output is the actual coupling interval that will be used + !! by the glue code. + TYPE(SD_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables + TYPE(SD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_InitType) :: Init + TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + + ! Initialize variables + ErrStat = ErrID_None + ErrMsg = "" + + + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + ! Display the module information + CALL DispNVD( SD_ProgDesc ) + InitOut%Ver = SD_ProgDesc + + ! --- Test TODO remove me in the future + if (DEV_VERSION) then + CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return + endif + + ! transfer glue-code information to data structure for SubDyn initialization: + Init%g = InitInput%g + Init%TP_RefPoint = InitInput%TP_RefPoint + Init%SubRotateZ = InitInput%SubRotateZ + if ((allocated(InitInput%SoilStiffness)) .and. (InitInput%SoilMesh%Initialized)) then + ! Soil Mesh and Stiffness + ! SoilMesh has N points. Correspond in order to the SoilStiffness matrices passed in + ! %RefOrientation is the identity matrix (3,3,N) + ! %Position is the reference position (3,N) + ! Maybe some logic to make sure these points correspond roughly to nodes -- though this may not be true for a long pile into the soil with multiple connection points + ! Note: F = -kx whre k is the relevant 6x6 matrix from SoilStiffness + call AllocAry(Init%Soil_K, 6,6, size(InitInput%SoilStiffness,3), 'Soil_K', ErrStat2, ErrMsg2); + call AllocAry(Init%Soil_Points, 3, InitInput%SoilMesh%NNodes, 'Soil_Points', ErrStat2, ErrMsg2); + call AllocAry(Init%Soil_Nodes, InitInput%SoilMesh%NNodes, 'Soil_Nodes' , ErrStat2, ErrMsg2); + Init%Soil_K = InitInput%SoilStiffness ! SoilStiffness is dimensioned (6,6,N) + Init%Soil_Points = InitInput%SoilMesh%Position ! SoilStiffness is dimensioned (6,6,N) + Init%Soil_Nodes = -1 ! Will be determined in InsertSoilMatrices, Nodes not known yet + if (size(Init%Soil_K,3) /= size(Init%Soil_Points,2)) then + ErrStat2=ErrID_Fatal; ErrMsg2='Number of soil points inconsistent with number of soil stiffness matrix' + endif + if (Failed()) return + endif + + !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. + IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) + + ! Establish the GLUECODE requested/suggested time step. This may be overridden by SubDyn based on the SDdeltaT parameter of the SubDyn input file. + Init%DT = Interval + IF ( LEN_TRIM(Init%RootName) == 0 ) THEN + CALL GetRoot( InitInput%SDInputFile, Init%RootName ) + ELSE + Init%RootName = TRIM(InitInput%RootName)//'.SD' + END IF + + ! Parse the SubDyn inputs + CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! -------------------------------------------------------------------------------- + ! --- Manipulation of Init and parameters + ! -------------------------------------------------------------------------------- + ! Discretize the structure according to the division size + ! sets p%nNodes, Init%NElm + CALL SD_Discrt(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Set element properties (p%ElemProps) + CALL SetElementProperties(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + !Store mapping between nodes and elements + CALL NodeCon(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Allocate DOF indices to joints and members + call DistributeDOF(Init, p ,ErrStat2, ErrMsg2); if(Failed()) return; + + ! Assemble Stiffness and mass matrix + CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Insert soil stiffness and mass matrix (NOTE: using NodesDOF, unreduced matrix) + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOF, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Elimination of constraints (reset M, K, D, to lower size, and BCs IntFc ) + CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Additional Damping and stiffness at pin/ball/universal joints + CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return + + + ! -------------------------------------------------------------------------------- + ! --- CB, Misc + ! -------------------------------------------------------------------------------- + ! --- Partitioning + ! Nodes into (I,C,L,R): I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior + ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior + call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return + + ! --- Craig-Bampton reduction (sets many parameters) + CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Initial system states + IF ( p%nDOFM > 0 ) THEN + CALL AllocAry(x%qm, p%nDOFM, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(x%qmdot, p%nDOFM, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry(m%qmdotdot, p%nDOFM, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return + x%qm = 0.0_ReKi + x%qmdot = 0.0_ReKi + m%qmdotdot= 0.0_ReKi + END IF + + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + + ! Allocate OtherState%xdot if using multi-step method; initialize n + IF ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) THEN + !bjj: note that the way SD_UpdateStates is implemented, "n" doesn't need to be initialized here + Allocate( OtherState%xdot(4), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat ( ErrID_Fatal, 'Error allocating OtherState%xdot', ErrStat, ErrMsg, 'SD_Init' ) + CALL CleanUp() + RETURN + END IF + ENDIF + + ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time + CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return + + ! -------------------------------------------------------------------------------- + ! --- Initialize Inputs and Outputs + ! -------------------------------------------------------------------------------- + ! Create the input and output meshes associated with Transition Piece reference point + CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Construct the input mesh (u%LMesh, force on nodes) and output mesh (y%Y2Mesh, displacements) + CALL CreateInputOutputMeshes( p%nNodes, Init%Nodes, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! --- Write the summary file + IF ( Init%SSSum ) THEN + ! note p%KBB/MBB are KBBt/MBBt + ! Write a summary of the SubDyn Initialization + CALL OutSummary(Init, p, InitInput, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + ENDIF + + ! Initialize the outputs & Store mapping between nodes and elements + CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! Determine if we need to perform output file handling + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ); if(Failed()) return + END IF + + + ! Tell GLUECODE the SubDyn timestep interval + Interval = p%SDdeltaT + CALL CleanUp() + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE CleanUp() + CALL SD_DestroyInitType(Init, ErrStat2, ErrMsg2) + CALL SD_DestroyCB_MatArrays( CBparams, ErrStat2, ErrMsg2 ) ! local variables + END SUBROUTINE CleanUp + +END SUBROUTINE SD_Init + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. +!! Continuous, discrete, constraint, and other states are updated for t + Interval. +SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(SD_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at Times + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; + !! Output: Continuous states at t + Interval + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; + !! Output: Discrete states at t + Interval + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; + !! Output: Constraint states at t + Interval + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; + !! Output: Other states at t + Interval + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Initialize variables + ErrStat = ErrID_None ! no error has occurred + ErrMsg = "" + + IF ( p%nDOFM == 0) RETURN ! no retained modes = no states + + IF (p%IntMethod .eq. 1) THEN + CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSEIF (p%IntMethod .eq. 2) THEN + CALL SD_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSEIF (p%IntMethod .eq. 3) THEN + CALL SD_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + ELSE + CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + END IF + +END SUBROUTINE SD_UpdateStates + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine for computing outputs, used in both loose and tight coupling. +SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- + !! nectivity information does not have to be recalculated) + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + !locals + INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays + INTEGER(IntKi) :: I,J ! Counters + INTEGER(IntKi) :: iSDNode, iY2Node + REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) + REAL(ReKi) :: rotations(3) + REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method + REAL(ReKi) :: Y1(6) + REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement + INTEGER(IntKi), pointer :: DOFList(:) + INTEGER(IntKi) :: startDOF + REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) + REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) + TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Compute the small rotation angles given the input direction cosine matrix + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return + + ! Inputs at the transition piece: + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) + m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + + ! Inputs on interior nodes: + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) + + !________________________________________ + ! Set motion outputs on y%Y2mesh + !________________________________________ + ! Y2 = C2*x + D2*u + F2 (Eq. 17) + m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] + m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] + m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] + + IF ( p%nDOFM > 0) THEN + m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? + + p%F2_61 ! + F2(6) ] + ELSE ! There are no states when p%nDOFM=0 (i.e., no retained modes: p%nDOFM=0), so we omit those portions of the equations + m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT + m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] + m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] + END IF + + !STATIC IMPROVEMENT METHOD ( modify UL ) + if (p%SttcSolve/=idSIM_None) then + if (p%SttcSolve==idSIM_Full) then + FLt = MATMUL(p%PhiL_T , m%UFL + p%FGL) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) + ! TODO New + !ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) + elseif (p%SttcSolve==idSIM_GravOnly) then + FLt = MATMUL(p%PhiL_T , p%FGL) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) + ! TODO New + !ULS = p%UL_st_g + else + STOP ! Should never happen + endif + m%UL = m%UL + ULS + if ( p%nDOFM > 0) then + UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) + ! TODO new + ! <<< + m%UL = m%UL - UL0M + end if + endif + ! --- Build original DOF vectors (DOF before the CB reduction) + m%U_red (p%IDI__) = m%UR_bar + m%U_red (p%ID__L) = m%UL + m%U_red (p%IDC_Rb)= 0 ! TODO + m%U_red (p%ID__F) = 0 + m%U_red_dot (p%IDI__) = m%UR_bar_dot + m%U_red_dot (p%ID__L) = m%UL_dot + m%U_red_dot (p%IDC_Rb)= 0 ! TODO + m%U_red_dot (p%ID__F) = 0 + m%U_red_dotdot(p%IDI__) = m%UR_bar_dotdot + m%U_red_dotdot(p%ID__L) = m%UL_dotdot + m%U_red_dotdot(p%IDC_Rb)= 0 ! TODO + m%U_red_dotdot(p%ID__F) = 0 + + m%U_full = matmul(p%T_red, m%U_red) + m%U_full_dot = matmul(p%T_red, m%U_red_dot) + m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) + + ! --- Place displacement/velocity/acceleration into Y2 output mesh + DO iSDNode = 1,p%nNodes + iY2Node = iSDNode + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! TODO TODO which orientation to give for joints with more than 6 dofs? + ! Construct the direction cosine matrix given the output angles + CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + y%Y2mesh%Orientation (:,:,iY2Node) = DCM + y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + enddo + !________________________________________ + ! Set loads outputs on y%Y1Mesh + !________________________________________ + ! --------------------------------------------------------------------------------- + !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above + ! --------------------------------------------------------------------------------- + ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] + !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES + !Aggregate the forces and moments at the interface nodes to the reference point + !TODO: where are these HydroTP, HydroForces documented? + DO I = 1, p%nNodes_I + iSDNode = p%Nodes_I(I,1) + iY2Node = iSDNode + startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes + !Take care of Hydrodynamic Forces that will go into INterface Forces later + HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) + ENDDO + + !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below + ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D + IF ( p%nDOFM > 0) THEN + Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + ELSE ! No retained modes, so there are no states + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) + - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + END IF + ! Computing extra moments due to lever arm introduced by interface displacement + ! Y1(:3) = -f_TP + ! MExtra = -u_TP x f_TP + ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs + if (p%ExtraMoment) then + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif + + ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces + y%Y1Mesh%Force (:,1) = Y1(1:3) + y%Y1Mesh%Moment(:,1) = Y1(4:6) + + !________________________________________ + ! CALCULATE OUTPUT TO BE WRITTEN TO FILE + !________________________________________ + ! OutSwtch determines whether or not to actually output results via the WriteOutput array + ! 0 = No one needs the SubDyn outputs provided via the WriteOutput array. + ! 1 = SubDyn will generate an output file of its own. + ! 2 = the caller will handle the outputs, but SubDyn needs to provide them. + ! 3 = Both 1 and 2 + IF ( p%OutSwtch > 0 ) THEN + ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file + !find xdot at t + IF ( p%nDOFM > 0 ) THEN + ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() + CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return + !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear + m%qmdotdot=dxdt%qmdot + ! Destroy dxdt because it is not necessary for the rest of the subroutine + CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2); if(Failed()) return + END IF + + ! Write the previous output data into the output file + IF ( ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) .AND. ( t > m%LastOutTime ) ) THEN + IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN + m%Decimat=1 !reset counter + CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat2, ErrMsg2 ); if(Failed()) return + ELSE + m%Decimat=m%Decimat+1 + ENDIF + END IF + + ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations + CALL SDOut_MapOutputs(t, u, p, x, y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return + + ! Put the output data in the WriteOutput array + DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims + y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + m%SDWrOutput(I) = y%WriteOutput(I) + END IF + END DO + m%LastOutTime = t + ENDIF + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE CleanUp + CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2) + END SUBROUTINE CleanUp + +END SUBROUTINE SD_CalcOutput + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states +!! note that this also sets m%UFL and m%udotdot_TP +SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN) :: x !< Continuous states at t -WHY IS THIS INOUT and not JUST IN? RRD, changed to IN on2/19/14 check with Greg + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + TYPE(SD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here + CALL AllocAry(dxdt%qm, p%nDOFM, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + CALL AllocAry(dxdt%qmdot, p%nDOFM, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) + IF ( ErrStat >= AbortErrLev ) RETURN + + IF ( p%nDOFM == 0 ) RETURN + + ! form u(3) in Eq. 10: + m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) + + ! form u(4) in Eq. 10: + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) + + !Equation 12: X=A*x + B*u + Fx (Eq 12) + dxdt%qm= x%qmdot + + ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D + != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) + !dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX + dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX + +END SUBROUTINE SD_CalcContStateDeriv + +!----------------------------------------------------------------------------------------------------------------------- +SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) + CHARACTER(*), INTENT(IN) :: SDInputFile + TYPE(SD_InitType) , INTENT(INOUT) :: Init + TYPE(SD_ParameterType) , INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +! local variable for input and output +CHARACTER(1024) :: PriPath ! The path to the primary input file +CHARACTER(1024) :: Line, Dummy_Str ! String to temporarially hold value of read line +INTEGER :: Sttus +CHARACTER(64), ALLOCATABLE :: StrArray(:) ! Array of strings, for better control of table inputs +LOGICAL :: Echo +LOGICAL :: LegacyFormat +LOGICAL :: bNumeric +INTEGER(IntKi) :: UnIn +INTEGER(IntKi) :: nColumns, nColValid, nColNumeric +INTEGER(IntKi) :: IOS +INTEGER(IntKi) :: UnEc !Echo file ID +REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings +INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf +REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat +INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) +LOGICAL :: Dummy_Bool +INTEGER(IntKi) :: ErrStat2 +CHARACTER(ErrMsgLen) :: ErrMsg2 +! Initialize ErrStat +ErrStat = ErrID_None +ErrMsg = "" + +UnEc = -1 +Echo = .FALSE. + +CALL GetNewUnit( UnIn ) + +CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) + +IF ( ErrStat2 /= ErrID_None ) THEN + Call Fatal('Could not open SubDyn input file') + return +END IF + +CALL GetPath( SDInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + +!-------------------------- HEADER --------------------------------------------- +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ); if(Failed()) return + +!-------------------------- SIMULATION CONTROL PARAMETERS ---------------------- +CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat2, ErrMsg2 ); if(Failed()) return +CALL ReadVar(UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2); if(Failed()) return + +IF ( Echo ) THEN + CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat2, ErrMsg2) + IF ( ErrStat2 /= 0 ) THEN + CALL Fatal("Could not open SubDyn echo file") + return + END IF + REWIND(UnIn) + !bjj: note we don't need to do error checking here; it was already checked (this is just a repeat of above) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ) + CALL ReadCom( UnIn, SDInputFile, 'SIMULATION CONTROL PARAMETERS' , ErrStat2, ErrMsg2, UnEc ) + CALL ReadVar( UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2, UnEc ) +ENDIF + +! Read time step ("default" means use the glue-code default) +CALL ReadVar( UnIn, SDInputFile, Line, 'SDdeltaT', 'Subdyn Time Step',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +CALL Conv2UC( Line ) ! Convert Line to upper case. +IF ( TRIM(Line) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. + p%SDdeltaT=Init%DT +ELSE ! The input must have been specified numerically. + READ (Line,*,IOSTAT=IOS) p%SDdeltaT + CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat2,ErrMsg2 ); if(Failed()) return + + IF ( ( p%SDdeltaT <= 0 ) ) THEN + call Fatal('SDdeltaT must be greater than or equal to 0.') + return + END IF +END IF + +CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +p%SttcSolve = idSIM_None +if (is_numeric(Dummy_Str, DummyFloat)) then + p%SttcSolve = int(DummyFloat) +else if (is_logical(Dummy_Str, Dummy_Bool)) then + if (Dummy_Bool) p%SttcSolve = idSIM_Full +else + call Fatal('SttcSolve should be an integer or a logical, received: '//trim(Dummy_Str)) + return +endif +IF (Check(.not.(any(idSIM_Valid==p%SttcSolve)), 'Invalid value entered for SttcSolve')) return + +! ExtraMoment - For legacy, allowing this line to be a comment +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'ExtraMoment', 'Add extra lever arm contribution to interface loads', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +if (is_logical(Dummy_Str, Dummy_Bool)) then ! the parameter was present + p%ExtraMoment=Dummy_Bool + ! We still need to read the comment on the next line + CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +else ! we have a actually read a comment line, we do nothing. + p%ExtraMoment=.False. ! For Legacy, ExtraMoment is False +endif + +!-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- +CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko +CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv , 'NDiv' , 'Number of divisions per member',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod , 'CBMod' , 'C-B mod flag' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +IF (Check( (p%IntMethod < 1) .OR.(p%IntMethod > 4) , 'IntMethod must be 1 through 4.')) return +IF (Check( (Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) , 'FEMMod must be 0, 1, 2, or 3.')) return +IF (Check( Init%NDiv < 1 , 'NDiv must be a positive integer')) return +IF (Check( Init%FEMMod==2 , 'FEMMod = 2 (tapered Euler-Bernoulli) not implemented')) return +IF (Check( Init%FEMMod==4 , 'FEMMod = 4 (tapered Timoshenko) not implemented')) return + +IF (Init%CBMod) THEN + ! Nmodes - Number of interal modes to retain. + CALL ReadIVar ( UnIn, SDInputFile, p%nDOFM, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + + IF (Check( p%nDOFM < 0 , 'Nmodes must be a non-negative integer.')) return + + if ( p%nDOFM > 0 ) THEN + ! Damping ratios for retained modes + CALL AllocAry(Init%JDampings, p%nDOFM, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + Init%JDampings=WrongNo !Initialize + + CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%nDOFM, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); + ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the + ! last entry to fill in remaining values. + !Check 1st value, we need at least one good value from user or throw error + IF ((Init%JDampings(1) < 0 ) .OR. (Init%JDampings(1) >= 100.0)) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100') + return + ELSE + DO I = 2, p%nDOFM + IF ( Init%JDampings(I) .EQ. WrongNo ) THEN + Init%Jdampings(I:p%nDOFM)=Init%JDampings(I-1) + IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) + ErrStat = ErrID_Info + ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%nDOFM))//'.' + END IF + EXIT + ELSEIF ( ( Init%JDampings(I) < 0 ) .OR.( Init%JDampings(I) >= 100.0 ) ) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100') + return + ENDIF + ENDDO + ENDIF + IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings + WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%nDOFM,NWTC_MaxAryLen)) + END IF + ELSE + CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + END IF + +ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet + !note at this stage I do not know nDOFL yet; Nmodes will be updated later for the FULL FEM CASE. + p%nDOFM = -1 + !Ignore next line + CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + !Read 1 damping value for all modes + CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return + CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + IF ( ( Init%JDampings(1) < 0 ) .OR.( Init%JDampings(1) >= 100.0 ) ) THEN + CALL Fatal('Damping ratio should be larger than 0 and less than 100.') + RETURN + ENDIF +ENDIF + +IF ((p%nDOFM > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%nDOFM is undefined, but if Nmodes=0 then JDampings does not exist + Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings +END IF + +!--------------------- STRUCTURE JOINTS: joints connect structure members ------------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Joints, Init%NJoints, JointsCol, 'Joints', ErrStat2, ErrMsg2 ); if(Failed()) return +IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return +! --- Reading first line to detect file format +READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return +! --- Reading first line to detect file format based on number of columns +nColumns=JointsCol +CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return +CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ) +if (ErrStat2/=0) then + ! We try with 4 columns (legacy format) + nColumns = 4 + deallocate(StrArray) + CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return + CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ); if(Failed()) return + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + print*,'Warning: Legacy joints table format detected in SubDyn input file!' + print*,' Some feature might be missing and only partial legacy support is provided.' + print*,' All joints are assumed cantilever, all members regular beams.' + print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' + print*,' Look at the SubDyn API changes to adapt your input files.' + print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever + Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 + LegacyFormat=.True. ! Legacy format - Delete me in 2024 +else + ! New format + LegacyFormat=.False. +endif +! Extract fields from first line +DO I = 1, nColumns + bNumeric = is_numeric(StrArray(I), Init%Joints(1,I)) ! Convert from string to float + if (.not.bNumeric) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non numeric character found in Joints line. Problematic line: "'//trim(Line)//'"') + return + endif +ENDDO +deallocate(StrArray) +! Read remaining lines +DO I = 2, Init%NJoints + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, nColumns, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + Init%Joints(I,1:nColumns) = Dummy_ReAry(1:nColumns) +ENDDO +IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return + +!---------- GO AHEAD and ROTATE STRUCTURE IF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- +CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) + +!------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- +! The joints should be all clamped for now +CALL ReadCom ( UnIn, SDInputFile, 'BASE REACTION JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_C, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +CALL AllocAry(p%Nodes_C, p%nNodes_C, ReactCol , 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return +p%Nodes_C(:,:) = 1 ! Important: By default all DOFs are contrained +p%Nodes_C(:,1) = -1 ! First column is node, initalize to wrong value for safety + +call AllocAry(Init%SSIfile, p%nNodes_C, 'SSIFile', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIK, 21, p%nNodes_C, 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return +call AllocAry(Init%SSIM, 21, p%nNodes_C, 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return +Init%SSIfile(:) = '' +Init%SSIK = 0.0_ReKi ! Important init TODO: read these matrices on the fly in SD_FEM maybe? +Init%SSIM = 0.0_ReKi ! Important init +! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile +DO I = 1, p%nNodes_C + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading reaction line'; if (Failed()) return + call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); + if (nColValid==1 .and. nColNumeric==1) then + ! Temporary allowing this + print*,'Warning: SubDyn reaction line has only 1 column. Please use 7 or 8 values' + else if (nColNumeric==7 .and.(nColValid==7.or.nColValid==8)) then + ! This is fine. + else + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') + return + endif +ENDDO +IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return + + +! Reading SSI matrices if present +DO I = 1, p%nNodes_C + if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then + Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) + CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(:,I),Init%SSIM(:,I), ErrStat, ErrMsg, UnEc ); if(Failed()) return + endif +enddo + + + +!------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- +! Joints with reaction forces, joint number and locked/free dof +CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_I, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +CALL AllocAry(p%Nodes_I, p%nNodes_I, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return +p%Nodes_I(:,:) = 1 ! Important: By default all DOFs are contrained +p%Nodes_I(:,1) = -1 ! First column is node, initalize to wrong value for safety +! Reading interface lines one by one, allowing for 1 or 7 columns (cannot use ReadIAry) +DO I = 1, p%nNodes_I + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='Error reading interface line'; if (Failed()) return + call ReadIAryFromStr(Line, p%Nodes_I(I,:), 7, nColValid, nColNumeric); + if ((nColValid/=nColNumeric).or.((nColNumeric/=1).and.(nColNumeric/=7)) ) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 1 or 7 numerical values. Problematic line: "'//trim(Line)//'"') + return + endif + if (any(p%Nodes_I(I,:)<=0)) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for interface lines. Problematic line: "'//trim(Line)//'"') + return + endif +ENDDO +IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN + +!----------------------------------- MEMBERS -------------------------------------- +! One day we will need to take care of COSMIDs for non-circular members +CALL ReadCom ( UnIn, SDInputFile, 'Members ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) +Init%Members(:,:) = 0.0_ReKi +if (LegacyFormat) then + nColumns = 5 + Init%Members(:,iMType) = idMemberBeam ! Important, in legacy all members are beams +else + nColumns = MembersCol +endif +DO I = 1, p%NMembers + CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members line '//Num2LStr(I), 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return + Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) +ENDDO +IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return + +!------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ +CALL ReadCom ( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsB, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSetsB, Init%NPropSetsB, PropSetsBCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSetsB + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSetsB(I,:) = Dummy_ReAry(1:PropSetsBCol) +ENDDO +IF (Check( Init%NPropSetsB < 1 , 'NPropSets must be >0')) return + +!------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member X-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsX, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSetsX, Init%NPropSetsX, PropSetsXCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NPropSetsX + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsX(I,:), PropSetsXCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NPropSetsX < 0, 'NXPropSets must be >=0')) return + +if (.not. LegacyFormat) then + !-------------------------- CABLE PROPERTIES ------------------------------------- + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsC, 'NPropSetsC', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NPropSetsC + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsC(I,:), PropSetsCCol, 'PropSetsC', 'PropSetsC ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ENDDO + IF (Check( Init%NPropSetsC < 0, 'NPropSetsCable must be >=0')) return + !----------------------- RIGID LINK PROPERTIES ------------------------------------ + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsR, 'NPropSetsR', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return + DO I = 1, Init%NPropSetsR + CALL ReadAry( UnIn, SDInputFile, Init%PropSetsR(I,:), PropSetsRCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + ENDDO + IF (Check( Init%NPropSetsR < 0, 'NPropSetsRigid must be >=0')) return +else + Init%NPropSetsC=0 + Init%NPropSetsR=0 + CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return +endif + +!---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member direction cosine matrices ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%COSMs, Init%NCOSMs, COSMsCol, 'COSMs', ErrStat2, ErrMsg2); if(Failed()) return +DO I = 1, Init%NCOSMs + CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +ENDDO +IF (Check( Init%NCOSMs < 0 ,'NCOSMs must be >=0')) return + +!------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- +CALL ReadCom ( UnIn, SDInputFile, 'Additional concentrated masses at joints ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%nCMass, 'nCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%CMass, Init%nCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return +Init%CMass = 0.0 ! Important init since we allow user to only provide diagonal terms +DO I = 1, Init%nCMass + ! CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading concentrated mass line'; if (Failed()) return + call ReadFAryFromStr(Line, Init%CMass(I,:), CMassCol, nColValid, nColNumeric); + if ((nColValid/=nColNumeric).or.((nColNumeric/=5).and.(nColNumeric/=11)) ) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 5 or 11 numerical values. Problematic line: "'//trim(Line)//'"') + return + endif + if (Init%CMass(I,1)<=0) then ! Further checks in JointIDs are done in SD_FEM + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Invalid concentrated mass JointID. Problematic line: "'//trim(Line)//'"') + return + endif +ENDDO +IF (Check( Init%nCMass < 0 , 'NCMass must be >=0')) return + +!---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ +CALL ReadCom (UnIn, SDInputFile, 'OUTPUT' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. +CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +!Store an integer version of it +p%OutAllInt= 1 +IF ( .NOT. p%OutAll ) p%OutAllInt= 0 +CALL ReadIVar(UnIn, SDInputFile, p%OutSwtch, 'OutSwtch', 'Output to which file variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +IF (Check( ( p%OutSwtch < 1 ) .OR. ( p%OutSwtch > 3) ,'OutSwtch must be >0 and <4')) return + +Swtch: SELECT CASE (p%OutSwtch) + CASE (1, 3) Swtch + !p%OutJckF = TRIM(Init%RootName)//'.out' + CASE (2) Swtch + !pass to glue code + CASE DEFAULT Swtch + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') + return + END SELECT Swtch + +! TabDelim - Output format for tabular data. +CALL ReadLVar ( UnIn, SDInputFile, Init%TabDelim, 'TabDelim', 'Use Tab Delimitation for numerical outputs',ErrStat2, ErrMsg2, UnEc); if(Failed()) return +IF ( Init%TabDelim ) THEN + p%Delim = TAB +ELSE + p%Delim = ' ' +END IF + +CALL ReadIVar( UnIn, SDInputFile, p%OutDec , 'OutDec' , 'Output Decimation' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutFmt , 'OutFmt' , 'Format for numerical outputs' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadVar ( UnIn, SDInputFile, p%OutSFmt , 'OutSFmt' , 'Format for output column headers' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, ' Member Output List SECTION ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar( UnIn, SDInputFile, p%NMOutputs, 'NMOutputs', 'Number of Members whose output must go into OutJckF and/or FAST .out',ErrStat2, ErrMsg2, UnEc ) +if (Failed()) return +IF (Check ( (p%NMOutputs < 0) .OR. (p%NMOutputs > p%NMembers) .OR. (p%NMOutputs > 9), 'NMOutputs must be >=0 and <= minimim(NMembers,9)')) return + +CALL ReadCom( UnIn, SDInputFile, ' Output Member Headers',ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return +CALL ReadCom( UnIn, SDInputFile, ' Output Member Units' ,ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return + +IF ( p%NMOutputs > 0 ) THEN + ! Allocate memory for filled group arrays + ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat2 ) !this list contains different arrays for each of its elements + IF ( ErrStat2 /= ErrID_None ) THEN + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') + RETURN + END IF + + DO I = 1,p%NMOutputs + READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line + IF (ErrStat2 == 0) THEN + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt + IF ( ErrStat2 /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') + RETURN + END IF + CALL AllocAry( p%MOutLst(I)%NodeCnt, p%MOutLst(I)%NOutCnt, 'NodeCnt', ErrStat2, ErrMsg2); if(Failed()) return + + READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt, p%MOutLst(I)%NodeCnt + IF ( Check( ErrStat2 /= 0 , 'Failed to read member output list properties.')) return + + ! Check if MemberID is in the member list and the NodeCnt is a valid number + flg = 0 + DO J = 1, p%NMembers + IF(p%MOutLst(I)%MemberID .EQ. Init%Members(j, 1)) THEN + flg = flg + 1 ! flg could be greater than 1, when there are more than 9 internal nodes of a member. + IF( (p%MOutLst(I)%NOutCnt < 10) .and. ((p%MOutLst(I)%NOutCnt > 0)) ) THEN + DO K = 1,p%MOutLst(I)%NOutCnt + ! node number should be less than NDiv + 1 + IF( (p%MOutLst(I)%NodeCnt(k) > (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) < 1) ) THEN + CALL Fatal(' NodeCnt should be less than NDIV+1 and greater than 0. ') + RETURN + ENDIF + ENDDO + ELSE + CALL Fatal(' NOutCnt should be less than 10 and greater than 0. ') + RETURN + ENDIF + ENDIF + ENDDO + IF (Check (flg .EQ. 0 , ' MemberID is not in the Members list. ')) return + + IF ( Echo ) THEN + WRITE( UnEc, '(A)' ) TRIM(Line) + END IF + END IF + END DO +END IF + +! OutList - list of requested parameters to output to a file +CALL ReadCom( UnIn, SDInputFile, 'SSOutList',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + +ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat2) +If (Check( ErrStat2 /= ErrID_None ,'Error allocating SSOutList arrays')) return +CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL CleanUp() + +CONTAINS + + LOGICAL FUNCTION Check(Condition, ErrMsg_in) + logical, intent(in) :: Condition + character(len=*), intent(in) :: ErrMsg_in + Check=Condition + if (Check) call Fatal(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) + END FUNCTION Check + + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Input') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Input'); + CALL CleanUp() + END SUBROUTINE Fatal + + SUBROUTINE CleanUp() + CLOSE( UnIn ) + if(allocated(StrArray)) deallocate(StrArray) + IF (Echo) CLOSE( UnEc ) + END SUBROUTINE +END SUBROUTINE SD_Input + +!> Extract integers from a string (space delimited substrings) +!! If StrArrayOut is present, non numeric strings are also returned +!! Example Str="1 2 not_a_int 3" -> IntArray = (/1,2,3/) StrArrayOut=(/"not_a_int"/) +!! No need for error handling, the caller will check how many valid inputs were on the line +!! TODO, place me in NWTC LIb +SUBROUTINE ReadIAryFromStr(Str, IntArray, nColMax, nColValid, nColNumeric, StrArrayOut) + character(len=*), intent(in) :: Str !< + integer(IntKi), dimension(:), intent(inout) :: IntArray !< NOTE: inout, to allow for init values + integer(IntKi), intent(in) :: nColMax + integer(IntKi), intent(out) :: nColValid, nColNumeric !< + character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric + character(255), allocatable :: StrArray(:) ! Array of strings extracted from line + real(ReKi) :: DummyFloat + integer(IntKi) :: J, nColStr + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + nColValid = 0 ; + nColNumeric = 0 ; + nColStr = 0 ; + ! --- First extract the different sub strings + CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); + if (ErrStat2/=ErrID_None) then + return ! User should notice that there is 0 valid columns + endif + StrArray(:)=''; + CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! + ! --- Then look for numerical values + do J = 1, nColMax + if (len(trim(StrArray(J)))>0) then + nColValid=nColValid+1 + if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! + nColNumeric=nColNumeric+1 + if (nColNumeric<=size(IntArray)) then + IntArray(nColNumeric) = int(DummyFloat) + endif + else + nColStr = nColStr+1 + if (present(StrArrayOut)) then + if (nColStr <=size(StrArrayOut) )then + StrArrayOut(nColStr) = StrArray(J) + endif + endif + endif + endif + enddo + if(allocated(StrArray)) deallocate(StrArray) +END SUBROUTINE ReadIAryFromStr + +!> See ReadIAryFromStr, same but for floats +SUBROUTINE ReadFAryFromStr(Str, FloatArray, nColMax, nColValid, nColNumeric, StrArrayOut) + character(len=*), intent(in) :: Str !< + real(ReKi), dimension(:), intent(inout) :: FloatArray !< NOTE: inout, to allow for init values + integer(IntKi), intent(in) :: nColMax + integer(IntKi), intent(out) :: nColValid, nColNumeric !< + character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric + character(255), allocatable :: StrArray(:) ! Array of strings extracted from line + real(ReKi) :: DummyFloat + integer(IntKi) :: J, nColStr + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + nColValid = 0 ; + nColNumeric = 0 ; + nColStr = 0 ; + ! --- First extract the different sub strings + CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); + if (ErrStat2/=ErrID_None) then + return ! User should notice that there is 0 valid columns + endif + StrArray(:)=''; + CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! + ! --- Then look for numerical values + do J = 1, nColMax + if (len(trim(StrArray(J)))>0) then + nColValid=nColValid+1 + if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! + nColNumeric=nColNumeric+1 + if (nColNumeric<=size(FloatArray)) then + FloatArray(nColNumeric) = DummyFloat + endif + else + nColStr = nColStr+1 + if (present(StrArrayOut)) then + if (nColStr <=size(StrArrayOut) )then + StrArrayOut(nColStr) = StrArray(J) + endif + endif + endif + endif + enddo + if(allocated(StrArray)) deallocate(StrArray) +END SUBROUTINE ReadFAryFromStr + + + + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Rotate the joint coordinates with respect to global z +SUBROUTINE SubRotate(Joints,NJoints,SubRotZ) + REAL(ReKi), INTENT(IN) :: SubRotZ ! Rotational angle in degrees + INTEGER(IntKi), INTENT(IN) :: NJOINTS ! Row size of Joints + REAL(ReKi), DIMENSION(NJOINTS,3), INTENT(INOUT) :: JOINTS ! Rotational angle in degrees (Njoints,4) + !locals + REAL(ReKi) :: rot !angle in rad + REAL(ReKi), DIMENSION(2,2) :: ROTM !rotational matrix (cos matrix with -theta) + + rot=pi*SubRotz/180. + ROTM=transpose(reshape([ COS(rot), -SIN(rot) , & + SIN(rot) , COS(rot)], [2,2] )) + Joints(:,2:3)= transpose(matmul(ROTM,transpose(Joints(:,2:3)))) + +END SUBROUTINE SubRotate + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +SUBROUTINE SD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: u !< System inputs + TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states + TYPE(SD_OutputType), INTENT(INOUT) :: y !< System outputs + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Determine if we need to close the output file + IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN + IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN + ! Write out the last stored set of outputs before closing + CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat, ErrMsg ) + ENDIF + CALL SDOut_CloseOutput( p, ErrStat, ErrMsg ) + END IF + + ! Destroy data + CALL SD_DestroyInput( u, ErrStat, ErrMsg ) + CALL SD_DestroyParam( p, ErrStat, ErrMsg ) + CALL SD_DestroyContState( x, ErrStat, ErrMsg ) + CALL SD_DestroyDiscState( xd, ErrStat, ErrMsg ) + CALL SD_DestroyConstrState( z, ErrStat, ErrMsg ) + CALL SD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) + CALL SD_DestroyMisc( m, ErrStat, ErrMsg ) + CALL SD_DestroyOutput( y, ErrStat, ErrMsg ) + +END SUBROUTINE SD_End + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential +!! equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! See, e.g., +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_ContinuousStateType) :: xdot ! Continuous state derivs at t + TYPE(SD_InputType) :: u_interp + + ErrStat = ErrID_None + ErrMsg = "" + + ! need xdot at t + CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat, ErrMsg) + CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) ! initializes xdot + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! we don't need this local copy anymore + + if (n <= 2) then + OtherState%n = n + !OtherState%xdot ( 3 - n ) = xdot + CALL SD_CopyContState( xdot, OtherState%xdot ( 3 - n ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + else + if (OtherState%n < n) then + OtherState%n = n + CALL SD_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( OtherState%xdot ( 1 ), OtherState%xdot ( 2 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + !OtherState%xdot(4) = OtherState%xdot(3) + !OtherState%xdot(3) = OtherState%xdot(2) + !OtherState%xdot(2) = OtherState%xdot(1) + elseif (OtherState%n > n) then + ErrStat = ErrID_Fatal + ErrMsg = ' Backing up in time is not supported with a multistep method ' + RETURN + endif + CALL SD_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) + !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date + x%qm = x%qm + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qm - 59.*OtherState%xdot(2)%qm + 37.*OtherState%xdot(3)%qm & + - 9. * OtherState%xdot(4)%qm ) + x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qmdot - 59.*OtherState%xdot(2)%qmdot & + + 37.*OtherState%xdot(3)%qmdot - 9.*OtherState%xdot(4)%qmdot ) + endif + CALL SD_DestroyContState(xdot, ErrStat, ErrMsg) + CALL SD_DestroyInput(u_interp, ErrStat, ErrMsg) +END SUBROUTINE SD_AB4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary +!! differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! +!! Adams-Bashforth Predictor: +!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) +!! +!! Adams-Moulton Corrector: +!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) +!! +!! See, e.g., +!! - http://en.wikipedia.org/wiki/Linear_multistep_method +!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. +SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_InputType) :: u_interp ! Continuous states at t + TYPE(SD_ContinuousStateType) :: x_pred ! Continuous states at t + TYPE(SD_ContinuousStateType) :: xdot_pred ! Continuous states at t + + ErrStat = ErrID_None + ErrMsg = "" + + CALL SD_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) !initialize x_pred + CALL SD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) + + if (n > 2) then + CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) + + CALL SD_CalcContStateDeriv(t + p%SDDeltaT, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat, ErrMsg ) ! initializes xdot_pred + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! local copy no longer needed + + x%qm = x%qm + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qm + 19. * OtherState%xdot(1)%qm - 5. * OtherState%xdot(2)%qm & + + 1. * OtherState%xdot(3)%qm ) + + x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qmdot + 19. * OtherState%xdot(1)%qmdot - 5. * OtherState%xdot(2)%qmdot & + + 1. * OtherState%xdot(3)%qmdot ) + CALL SD_DestroyContState( xdot_pred, ErrStat, ErrMsg) ! local copy no longer needed + else + x%qm = x_pred%qm + x%qmdot = x_pred%qmdot + endif + + CALL SD_DestroyContState( x_pred, ErrStat, ErrMsg) ! local copy no longer needed + +END SUBROUTINE SD_ABM4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = dt * f(t , x_t ) +!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) +!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and +!! k4 = dt * f(t + dt , x_t + k3 ). +!! Then the continuous states at t = t + dt are +!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) +!! +!! For details, see: +!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for +!! Runge-Kutta." sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: +!! Cambridge University Press, pp. 704-716, 1992. +SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_ContinuousStateType) :: xdot ! time derivatives of continuous states + TYPE(SD_ContinuousStateType) :: k1 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k2 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k3 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: k4 ! RK4 constant; see above + TYPE(SD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + TYPE(SD_InputType) :: u_interp ! interpolated value of inputs + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + !bjj: the state type contains allocatable arrays, so we must first allocate space: + CALL SD_CopyContState( x, k1, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k2, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k3, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, k4, MESH_NEWCOPY, ErrStat, ErrMsg ) + CALL SD_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat, ErrMsg ) + + ! interpolate u to find u_interp = u(t) + CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat, ErrMsg ) + + ! find xdot at t + CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) !initializes xdot + k1%qm = p%SDDeltaT * xdot%qm + k1%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k1%qm + x_tmp%qmdot = x%qmdot + 0.5 * k1%qmdot + ! interpolate u to find u_interp = u(t + dt/2) + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%SDDeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt/2 + CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k2%qm = p%SDDeltaT * xdot%qm + k2%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + 0.5 * k2%qm + x_tmp%qmdot = x%qmdot + 0.5 * k2%qmdot + + ! find xdot at t + dt/2 + CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k3%qm = p%SDDeltaT * xdot%qm + k3%qmdot = p%SDDeltaT * xdot%qmdot + x_tmp%qm = x%qm + k3%qm + x_tmp%qmdot = x%qmdot + k3%qmdot + ! interpolate u to find u_interp = u(t + dt) + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) + + ! find xdot at t + dt + CALL SD_CalcContStateDeriv( t + p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) + k4%qm = p%SDDeltaT * xdot%qm + k4%qmdot = p%SDDeltaT * xdot%qmdot + x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. + x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. + + CALL CleanUp() + +CONTAINS + + SUBROUTINE CleanUp() + INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) + CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) + CALL SD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k1, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k2, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k3, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( k4, ErrStat3, ErrMsg3 ) + CALL SD_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) + CALL SD_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) + END SUBROUTINE CleanUp + +END SUBROUTINE SD_RK4 + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This subroutine implements the 2nd-order Adams-Moulton Implicit Method (AM2,Trapezoidal rule) for numerically integrating ordinary differential equations: +!! +!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). +!! Define constants k1, k2, k3, and k4 as +!! k1 = f(t , x_t ) +!! k2 = f(t + dt , x_t+dt ) +!! Then the continuous states at t = t + dt are +!! x_(t+dt) =x_n+1 = x_t + deltat/2*(k1 + k2) + O(dt^3) +!! Now this can be re-written as: 0=Z(x_n+1) = x_n - x_n+1 +dt/2 *(f_n + f_n+1) = 0 +!! f_n= A*x_n + B*u_n + Fx from Eq. 1.12 of the manual +!! So to solve this linear system, I can just use x(k)=x(k-1) -J^-1 * Z(x(k-1)) (this is a simple root solver of the linear equation) +!! with J=dZ/dx_n+1 = -I +dt/2*A +!! +!! Thus x_n+1 = x_n - J^-1 *dt/2 * (2*A*x_n + B *(u_n + u_n+1) +2*Fx) +!! or J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) +SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + USE NWTC_LAPACK, only: LAPACK_getrs + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< time step number + TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t + REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + TYPE(SD_InputType) :: u_interp ! interpolated value of inputs + REAL(ReKi) :: junk2(2*p%nDOFM) !temporary states (qm and qmdot only) + REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP + REAL(ReKi) :: UFL2(p%nDOF__L) ! temporary copy of UFL + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize interim vars + CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2,ErrMsg2);CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + + !Start by getting u_n and u_n+1 + ! interpolate u to find u_interp = u(t) = u_n + CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL ) + + ! extrapolate u to find u_interp = u(t + dt)=u_n+1 + CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2 ) + + ! calculate (u_n + u_n+1)/2 + udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) + UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) + + ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array + junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D + + !.................................................... + ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) + ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + !.................................................... + CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') + !IF ( ErrStat >= AbortErrLev ) RETURN + + ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: + x%qm = x%qm - junk2( 1: p%nDOFM) + x%qmdot = x%qmdot - junk2(p%nDOFM+1:2*p%nDOFM) + + ! clean up temporary variable(s) + CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) + +END SUBROUTINE SD_AM2 + +!------------------------------------------------------------------------------------------------------ +!> Perform Craig Bampton (CB) reduction and set parameters needed for States and Ouputs equations +!! Sets the following values, as documented in the SubDyn Theory Guide: +!! CB%OmegaL (omega) and CB%PhiL from Eq. 2 +!! p%PhiL_T and p%PhiLInvOmgL2 for static improvement +!! CB%PhiR from Eq. 3 +!! CB%MBB, CB%MBM, and CB%KBB from Eq. 4. +SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType),INTENT(INOUT),target::p ! Parameters + TYPE(CB_MatArrays), INTENT(INOUT) :: CB ! CB parameters that will be passed out for summary file use + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) + REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file + REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array + INTEGER(IntKi) :: i + INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) + INTEGER(IntKi) :: nL, nM, nM_out + INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb + LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'SD_Craig_Bampton' + ErrStat = ErrID_None + ErrMsg = "" + + IF(Init%CBMod) THEN ! C-B reduction + ! check number of internal modes + IF(p%nDOFM > p%nDOFL_L) THEN + CALL Fatal('Number of internal modes is larger than number of internal DOFs.') + return + ENDIF + ELSE ! full FEM + p%nDOFM = p%nDOFL_L + !Jdampings need to be reallocated here because nDOFL not known during Init + !So assign value to one temporary variable + JDamping1=Init%Jdampings(1) + DEALLOCATE(Init%JDampings) + CALL AllocAry( Init%JDampings, p%nDOFL_L, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return + Init%JDampings = JDamping1 ! set default values for all modes + ENDIF + + CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return + ! Switch between BC before or after CB, KEEP ME + BC_Before_CB=.true. + if(BC_Before_CB) then + !print*,' > Boundary conditions will be applied before Craig-Bampton (New)' + nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction + IDR => p%ID__Rb + else + !print*,' > Craig-Bampton will be applied before boundary conditions (Legacy)' + nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system + IDR => p%IDR__ + endif + + IF (p%SttcSolve/=idSIM_None) THEN ! STATIC TREATMENT IMPROVEMENT + nM_out=p%nDOF__L ! Selecting all CB modes for outputs to the function below + ELSE + nM_out=p%nDOFM ! Selecting only the requrested number of CB modes + ENDIF + nL = p%nDOF__L + nM = p%nDOFM + + CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') + CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGR, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGB, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%PhiL, nL, nM_out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& + Init%FG, FGR, FGL, FGB, FGM) + if(Failed()) return + + CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if(.not.BC_Before_CB) then + ! We apply the BC now, removing unwanted DOFs + call applyConstr(CB, FGB, PhiRb) ! Reduces size of CB%MBB, CB%KBB, CB%MBM, FGB, NOTE: "L" unaffected + else + PhiRb=CB%PhiR ! Remove me in the future + endif + ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') + + CALL CleanUpCB() + +contains + + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'Craig_Bampton'); + CALL CleanUpCB() + END SUBROUTINE Fatal + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUpCB() + end function Failed + + subroutine CleanUpCB() + IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) + IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) + IF(ALLOCATED(FGM) ) DEALLOCATE(FGM) + IF(ALLOCATED(FGB) ) DEALLOCATE(FGB) + IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) + end subroutine CleanUpCB + + !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system + !! NOTE: PhiL and OmegaL are not modified + subroutine applyConstr(CBParams, FGB, PhiRb) + TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) + !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) + REAL(ReKi), ALLOCATABLE :: MBBb(:, :) + REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: KBBb(:, :) + REAL(ReKi), ALLOCATABLE :: FGBb(:) + ! "b" stands for "bar" + CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); + CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); + !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); + !................................ + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to + ! MBBb, MBMb, KBBb, PHiRb, FGBb + ! (throw out rows/columns of first matrices to create second matrices) + !................................ + ! TODO avoid this all together + MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + IF (p%nDOFM > 0) THEN + MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) + END IF + FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) + PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + deallocate(CBparams%MBB) + deallocate(CBparams%KBB) + deallocate(CBparams%MBM) + !deallocate(CBparams%PhiR) + call move_alloc(MBBb, CBparams%MBB) + call move_alloc(KBBb, CBparams%KBB) + call move_alloc(MBMb, CBparams%MBM) + call move_alloc(FGBb, FGB) + !call move_alloc(PhiRb, CBparams%PhiR) + end subroutine applyConstr + +END SUBROUTINE SD_Craig_Bampton + +!> Extract rigid body mass without SSI +!! NOTE: performs a Guyan reduction +SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) + type(SD_InitType), intent(inout) :: Init ! NOTE: Mass and Stiffness are modified but then set back to original + type(SD_ParameterType), intent(in ) :: p ! Parameters + real(ReKi), allocatable, intent(out) :: MBB(:,:) !< MBB + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< error message if errstat /= errid_none + integer(IntKi) :: nM, nR, nL, nM_out + real(ReKi), allocatable :: MBM(:, :) + real(ReKi), allocatable :: KBB(:, :) + real(ReKi), allocatable :: PhiL(:, :) + real(ReKi), allocatable :: PhiR(:, :) + real(ReKi), allocatable :: OmegaL(:) + character(*), parameter :: RoutineName = 'SD_Guyan_RigidBodyMass' + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! --- Remove SSI from Mass and stiffness matrix (NOTE: use NodesDOFtilde, reduced matrix) + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.True.); + + ! --- Perform Guyan reduction to get MBB + nR = p%nDOFR__ ! Using interface + reaction nodes + nL = p%nDOF__L + nM = 0 ! No CB modes (Guyan) + nM_out = 0 + if(allocated(MBB)) deallocate(MBB) + CALL AllocAry( MBB, nR, nR, 'MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( MBM, nR, nM, 'MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( KBB, nR, nR, 'KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( PhiL, nL, nL, 'PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( PhiR, nL, nR, 'PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( OmegaL, nL, 'OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return + + CALL CraigBamptonReduction(Init%M, Init%K, p%IDR__, nR, p%ID__L, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) + if(Failed()) return + + if(allocated(KBB) ) deallocate(KBB) + if(allocated(MBM) ) deallocate(MBM) + if(allocated(PhiR) ) deallocate(PhiR) + if(allocated(PhiL) ) deallocate(PhiL) + if(allocated(OmegaL)) deallocate(OmegaL) + + ! --- Insert SSI from Mass and stiffness matrix again + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed +END SUBROUTINE SD_Guyan_RigidBodyMass + +!------------------------------------------------------------------------------------------------------ +!> Set parameters to compute state and output equations +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) + use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf + TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters + REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) + REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) + integer(IntKi), INTENT(IN ) :: nM_out + REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) + REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: OmegaL(nM_out) + REAL(ReKi), INTENT(IN ) :: FGB(p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) + REAL(ReKi), INTENT(IN ) :: FGM(p%nDOFM) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI__) !bjj: added this so we don't have to take the transpose 5+ times + INTEGER(IntKi) :: I + integer(IntKi) :: n ! size of jacobian in AM2 calculation + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' + ErrStat = ErrID_None + ErrMsg = '' + + if (p%nDOFI__/=p%nDOF__Rb) then + ! Limitation due to the TI matrix, on the input U_R to the module for now + ErrMsg2='For now number of leader DOF has to be the same a Rb DOF' + ErrStat2=ErrID_Fatal + if(Failed()) return + endif + + ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) + CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return + TI_transpose = TRANSPOSE(p%TI) + + ! Store Static Improvement Method constants + if (p%SttcSolve /= idSIM_None) then + if (p%SttcSolve == idSIM_Full) then + CALL WrScr(' Using static improvement method for gravity and ext. loads') + else + CALL WrScr(' Using static improvement method for gravity only') + endif + ! Allocations + CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%KLLm1 , p%nDOF__L, p%nDOF__L, 'p%KLLm1', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); if(Failed())return + CALL AllocAry( p%UL_st_g, p%nDOF__L, 'p%UL_st_g', ErrStat2, ErrMsg2 ); if(Failed())return + ! TODO PhiL_T and PhiLInvOmgL2 may not be needed if KLLm1 is stored. + p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement + do I = 1, nM_out + p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) + enddo + p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t + p%FGL = FGL + p%UL_st_g = MATMUL(p%KLLm1, FGL) + endif + + ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) + p%PhiRb_TI = MATMUL(PhiRb, p%TI) + + !............................... + ! equation 46-47 (used to be 9): + !............................... + p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt + p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt + + !p%D1_15=-TI_transpose !this is 6x6NIN + IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 + ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt + CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') + + p%MMB = TRANSPOSE( p%MBM ) != MMBt + p%PhiM = PhiL(:,1:p%nDOFM) + + ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) + p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array + p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array + + ! B_23, B_24 + !p%PhiM_T = TRANSPOSE( p%PhiM ) + + ! FX = matmul( transpose(PhiM), FGL ) (output of CraigBamptonReduction) + p%FX = FGM + + ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) + DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped + p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) + p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) + ENDDO + + ! D1_13, D1_14 (with retained modes) + !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ) ! p%D1_13 = MATMUL( p%MBM, p%MMB ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + p%D1_13 = p%MBB - p%D1_13 + + !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + + ! FY (with retained modes) + p%FY = MATMUL( p%MBM, p%FX ) & + - MATMUL( TI_transpose, FGB ) + + ! C2_21, C2_42 + ! C2_61, C2_62 + DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped + p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) + p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) + ENDDO + + ! D2_53, D2_63, D2_64 + p%D2_63 = MATMUL( p%PhiM, p%MMB ) + p%D2_63 = p%PhiRb_TI - p%D2_63 + + !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) !bjj: why does this use stack space? + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ) !bjj: replaced MATMUL with this routine to avoid issues with stack size + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! F2_61 + p%F2_61 = MATMUL( p%D2_64, FGL ) + + !Now calculate a Jacobian used when AM2 is called and store in parameters + IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%nDOFM > 0) + n=2*p%nDOFM + CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ); if(Failed()) return + + ! First we calculate the Jacobian: + ! (note the Jacobian is first stored as p%AM2InvJac) + p%AM2Jac=0. + DO i=1,p%nDOFM + p%AM2Jac(i+p%nDOFM,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 + p%AM2Jac(i+p%nDOFM,i+p%nDOFM)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize + END DO + + DO I=1,p%nDOFM + p%AM2Jac(I,I)=-1. !J11 + p%AM2Jac(I,p%nDOFM+I)=p%SDdeltaT/2. !J12 + p%AM2Jac(p%nDOFM+I,p%nDOFM+I)=p%AM2Jac(p%nDOFM+I,p%nDOFM+I)-1 !J22 complete + ENDDO + ! Now need to factor it: + !I think it could be improved and made more efficient if we can say the matrix is positive definite + CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2); if(Failed()) return + END IF + + ELSE ! no retained modes, so + ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case + ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables + ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable + ! p%D1_13 = p%MBB in this case so we simplify the equations in the code, omitting storage of this variable + + ! D1_14 (with 0 retained modes) + p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + + ! FY (with 0 retained modes) + p%FY = - MATMUL( TI_transpose, FGB ) + + END IF + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetParameters') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + +END SUBROUTINE SetParameters + +!------------------------------------------------------------------------------------------------------ +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. +SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) + TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters + INTEGER(IntKi), INTENT( in) :: nDOFM + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! initialize error handling: + ErrStat = ErrID_None + ErrMsg = "" + + ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. + + CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + +if (p%nDOFM > 0 ) THEN + CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%NOmegaM2, nDOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%N2OmegaMJDamp, nDOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 + CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 +end if + +END SUBROUTINE AllocParameters + +!------------------------------------------------------------------------------------------------------ +!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. +SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) + TYPE(SD_MiscVarType), INTENT(INOUT) :: Misc ! Miscellaneous values, used to avoid local copies and/or multiple allocation/deallocation of same variables each call + TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + ! initialize error handling: + ErrStat = ErrID_None + ErrMsg = "" + + ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. + CALL AllocAry( Misc%UFL, p%nDOF__L, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UR_bar, p%nDOFI__, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UR_bar_dot, p%nDOFI__, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI__, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb + CALL AllocAry( Misc%UL, p%nDOF__L, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dot, p%nDOF__L, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%UL_dotdot, p%nDOF__L, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + + CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + +END SUBROUTINE AllocMiscVars + +!------------------------------------------------------------------------------------------------------ +!> Partition DOFs and Nodes into sets: +!! Nodes are partitioned into the I,C,L (and R) sets, Nodes_I, Nodes_C, Nodes_L, with: +!! I="Interface" nodes +!! C="Reaction" nodes +!! L=Interior nodes +!! R=I+C +!! DOFs indices are partitioned into B, F, L +!! B=Leader DOFs (Rbar in SubDyn documentation) +!! F=Fixed DOFS +!! L=Interior DOFs +!! Subpartitions of both categories use the convention: "NodePartition_DOFPartition" +!! e.g. C_F : "reaction" nodes DOFs that are fixed +!! C_L : "reaction" nodes DOFs that will be counted as internal +!! I_B : "interface" nodes DOFs that are leader DOFs +SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) + use qsort_c_module, only: QsortC + use IntegerList, only: len, concatenate_lists, lists_difference, concatenate_3lists, sort_in_place + type(SD_Inittype), intent( in) :: Init !< Input data for initialization routine + type(SD_MiscVartype), intent( in) :: m !< Misc + type(SD_Parametertype), intent(inout) :: p !< Parameters + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + ! local variables + integer(IntKi) :: I, J, c_B, c_F, c_L, c__ ! counters + integer(IntKi) :: iNode, iiNode + integer(IntKi) :: nNodes_R + integer(IntKi), allocatable :: IDAll(:) + integer(IntKi), allocatable :: INodesAll(:) + integer(IntKi), allocatable :: Nodes_R(:) + integer(IntKi) :: ErrStat2 ! < Error status of the operation + character(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + ! --- Count nodes per types + p%nNodes_I = p%nNodes_I ! Number of interface nodes + nNodes_R = p%nNodes_I+p%nNodes_C ! I+C nodes + p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes + ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. + + CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + + ! -------------------------------------------------------------------------------- + ! --- Partition Nodes: Nodes_L = IAll - NodesR + ! -------------------------------------------------------------------------------- + allocate(INodesAll(1:p%nNodes)); + do iNode=1,p%nNodes + INodesAll(iNode)=iNode + enddo + ! Nodes_R = [Nodes_C Nodes_I] + call concatenate_lists(p%Nodes_C(:,1), p%Nodes_I(:,1), Nodes_R, ErrStat2, ErrMsg2); if(Failed()) return + ! Nodes_L = IAll - Nodes_R + call lists_difference(INodesAll, Nodes_R, p%Nodes_L(:,1), ErrStat2, ErrMsg2); if(Failed()) return + + ! -------------------------------------------------------------------------------- + ! --- Count DOFs - NOTE: we count node by node + ! -------------------------------------------------------------------------------- + ! DOFs of interface nodes + p%nDOFI__ =0 ! Total + p%nDOFI_Rb=0 ! Leader + p%nDOFI_F =0 ! Fixed + do iiNode= 1,p%nNodes_I + p%nDOFI__ = p%nDOFI__ + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) + p%nDOFI_Rb= p%nDOFI_Rb+ count(p%Nodes_I(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs + p%nDOFI_F = p%nDOFI_F + count(p%Nodes_I(iiNode, 2:7)==idBC_Fixed) ! assumes 6 DOFs + enddo + if (p%nDOFI__/=p%nDOFI_Rb+p%nDOFI_F) then + call Fatal('Error in distributing interface DOFs, total number of interface DOF('//num2lstr(p%nDOFI__)//') does not equal sum of: leader ('//num2lstr(p%nDOFI_Rb)//'), fixed ('//num2lstr(p%nDOFI_F)//')'); return + endif + + ! DOFs of reaction nodes + p%nDOFC__ =0 ! Total + p%nDOFC_Rb=0 ! Leader + p%nDOFC_F =0 ! Fixed + p%nDOFC_L =0 ! Internal + do iiNode= 1,p%nNodes_C + p%nDOFC__ = p%nDOFC__ + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) + p%nDOFC_Rb= p%nDOFC_Rb+ count(p%Nodes_C(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs + p%nDOFC_F = p%nDOFC_F + count(p%Nodes_C(iiNode, 2:7)==idBC_Fixed ) ! assumes 6 DOFs + p%nDOFC_L = p%nDOFC_L + count(p%Nodes_C(iiNode, 2:7)==idBC_Internal) ! assumes 6 DOFs + enddo + if (p%nDOFC__/=p%nDOFC_Rb+p%nDOFC_F+p%nDOFC_L) then + call Fatal('Error in distributing reaction DOFs, total number of reaction DOF('//num2lstr(p%nDOFC__)//') does not equal sum of: leader ('//num2lstr(p%nDOFC_Rb)//'), fixed ('//num2lstr(p%nDOFC_F)//'), internal ('//num2lstr(p%nDOFC_L)//')'); return + endif + ! DOFs of reaction + interface nodes + p%nDOFR__ = p%nDOFI__ + p%nDOFC__ ! Total number, used to be called "nDOFR" + + ! DOFs of internal nodes + p%nDOFL_L=0 + do iiNode= 1,p%nNodes_L + p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) + enddo + if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then + call Fatal('Error in distributing internal DOFs, total number of internal DOF('//num2lstr(p%nDOFL_L)//') does not equal total number of DOF('//num2lstr(p%nDOF_red)//') minus interface and reaction ('//num2lstr(p%nDOFR__)//')'); return + endif + + ! Total number of DOFs in each category: + p%nDOF__Rb = p%nDOFC_Rb + p%nDOFI_Rb ! OK, generic + p%nDOF__F = p%nDOFC_F + p%nDOFI_F ! OK, generic + p%nDOF__L = p%nDOFC_L + p%nDOFL_L ! OK, generic + + ! --- Safety checks ! TODO: these checks are temporary! + if (p%nDOFI_Rb /= p%nNodes_I*6) then + call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints or are fixed'); return + endif + + ! Set the index arrays + CALL AllocAry( p%IDI__, p%nDOFI__, 'p%IDI__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDI_Rb,p%nDOFI_Rb, 'p%IDI_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDI_F, p%nDOFI_F, 'p%IDI_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC__, p%nDOFC__, 'p%IDC__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_Rb,p%nDOFC_Rb, 'p%IDC_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_F, p%nDOFC_F, 'p%IDC_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDC_L, p%nDOFC_L, 'p%IDC_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDL_L, p%nDOFL_L, 'p%IDL_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%IDR__, p%nDOFR__, 'p%IDR__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__Rb,p%nDOF__Rb, 'p%ID__Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__F, p%nDOF__F, 'p%ID__F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + CALL AllocAry( p%ID__L, p%nDOF__L, 'p%ID__L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') ! TODO TODO + if(Failed()) return + + ! -------------------------------------------------------------------------------- + ! --- Distibutes the I, L, C nodal DOFs into B, F, L sub-categories + ! -------------------------------------------------------------------------------- + + ! Distribute the interface DOFs into R,F + c__=0; c_B=0; c_F=0 ! Counters over R and F dofs + do iiNode= 1,p%nNodes_I !Loop on interface nodes + iNode = p%Nodes_I(iiNode,1) + do J = 1, 6 ! DOFs: ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + c__=c__+1 + p%IDI__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + if (p%Nodes_I(iiNode, J+1)==idBC_Leader) then + c_B=c_B+1 + p%IDI_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_I(iiNode, J+1)==idBC_Fixed) then ! + c_F=c_F+1 + p%IDI_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + endif + enddo + enddo + ! Indices IDI__ = [IDI_B, IDI_F], interface + !call concatenate_lists(p%IDI_Rb, p%IDI_F, p%IDI__, ErrStat2, ErrMsg2); if(Failed()) return + + ! Distribute the reaction DOFs into R,F,L + c__=0; c_B=0; c_F=0; c_L=0; ! Counters over R, F, L dofs + do iiNode= 1,p%nNodes_C !Loop on interface nodes + iNode = p%Nodes_C(iiNode,1) + do J = 1, 6 ! DOFs + c__=c__+1 + p%IDC__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + if (p%Nodes_C(iiNode, J+1)==idBC_Leader) then + c_B=c_B+1 + p%IDC_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_C(iiNode, J+1)==idBC_Fixed) then ! + c_F=c_F+1 + p%IDC_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + + elseif (p%Nodes_C(iiNode, J+1)==idBC_Internal) then ! + c_L=c_L+1 + p%IDC_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + endif + enddo + enddo + ! Indices IDC__ = [IDC_B, IDC_F, IDC_L], interface + !call concatenate_3lists(p%IDC_Rb, p%IDC_F, p%IDC_L, p%IDC__, ErrStat2, ErrMsg2); if(Failed()) return + !call sort_in_place(p%IDC__) + + + ! Indices IDR__ = [IDI__, IDC__], interface + !call concatenate_lists(p%IDI__, p%IDC__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return + ! TODO, NOTE: Backward compatibility [IDC, IDI] + call concatenate_lists(p%IDC__, p%IDI__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return + + ! Distribute the internal DOFs + c_L=0; ! Counters over L dofs + do iiNode= 1,p%nNodes_L !Loop on interface nodes + iNode = p%Nodes_L(iiNode,1) + do J = 1, size(p%NodesDOFtilde(iNode)%List) ! DOFs + c_L=c_L+1 + p%IDL_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + enddo + enddo + + ! -------------------------------------------------------------------------------- + ! --- Total indices per partition B, F, L + ! -------------------------------------------------------------------------------- + ! Indices ID__Rb = [IDC_B, IDI_B], retained/leader DOFs + call concatenate_lists(p%IDC_Rb, p%IDI_Rb, p%ID__Rb, ErrStat2, ErrMsg2); if(Failed()) return + ! Indices ID__F = [IDC_F, IDI_F], fixed DOFs + call concatenate_lists(p%IDC_F, p%IDI_F, p%ID__F, ErrStat2, ErrMsg2); if(Failed()) return + ! Indices ID__L = [IDL_L, IDC_L], internal DOFs + call concatenate_lists(p%IDL_L, p%IDC_L, p%ID__L, ErrStat2, ErrMsg2); if(Failed()) return + + ! --- Check that partition is complete + if (any(p%ID__Rb<=0)) then + call Fatal('R - Partioning incorrect.'); return + elseif (any(p%ID__F<=0)) then + call Fatal('F - Partioning incorrect.'); return + elseif (any(p%ID__L<=0)) then + call Fatal('L - Partioning incorrect.'); return + endif + allocate(IDAll(1:p%nDOF_red)) + call concatenate_3lists(p%ID__Rb, p%ID__L, p%ID__F, IDAll, ErrStat2, ErrMsg2); if(Failed()) return + call sort_in_place(IDAll) + do I = 1, p%nDOF_red + if (IDAll(I)/=I) then + call Fatal('DOF '//trim(Num2LStr(I))//' missing, problem in R, L F partitioning'); return + endif + enddo + + if(DEV_VERSION) then + write(*,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ + write(*,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb + write(*,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F + write(*,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ + write(*,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb + write(*,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L + write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F + write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ + write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L + write(*,'(A,I0)')'Number of DOFs: retained (__B): ',p%nDOF__Rb + write(*,'(A,I0)')'Number of DOFs: internal (__L): ',p%nDOF__L + write(*,'(A,I0)')'Number of DOFs: fixed (__F): ',p%nDOF__F + write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red + write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I + write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C + write(*,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L + write(*,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes + endif + + call CleanUp() + +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'PartitionDOFNodes'); + CALL CleanUp() + END SUBROUTINE Fatal + SUBROUTINE CleanUp() + if(allocated(INodesAll)) deallocate(INodesAll) + if(allocated(IDAll)) deallocate(IDAll) + if(allocated(Nodes_R)) deallocate(Nodes_R) + END SUBROUTINE CleanUp + +END SUBROUTINE PartitionDOFNodes + +!------------------------------------------------------------------------------------------------------ +!> Construct force vector on internal DOF (L) from the values on the input mesh +!! First, the full vector of external forces is built on the non-reduced DOF +!! Then, the vector is reduced using the Tred matrix +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) + type(SD_InputType), intent(in ) :: u ! Inputs + type(SD_ParameterType), intent(in ) :: p ! Parameters + type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red + real(ReKi) , intent(out) :: UFL(p%nDOF__L) + integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes + integer :: nMembers + real(ReKi), parameter :: myNaN = -9999998.989_ReKi + ! TODO to save time, perform Tred multiplication only if Tred is not identity + + ! --- Build vector of external force + m%Fext= myNaN + DO iMeshNode = 1,p%nNodes + iSDNode = iMeshNode + nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + ! Force - All nodes have only 3 translational DOFs + m%Fext( p%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) + ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + m%Fext( p%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers + enddo + + ! TODO: remove test below in the future + if (DEV_VERSION) then + if (any(m%Fext == myNaN)) then + print*,'Error in setting up Fext' + STOP + endif + endif + ! --- Reduced vector of external force + m%Fext_red = matmul(transpose(p%T_red), m%Fext) + UFL= m%Fext_red(p%ID__L) + +END SUBROUTINE GetExtForceOnInternalDOF + +!------------------------------------------------------------------------------------------------------ +!> Output the summary file +SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) + use Yaml + TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file + TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file + TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine + TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use + INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !LOCALS + INTEGER(IntKi) :: UnSum ! unit number for this summary file + INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors + CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file + INTEGER(IntKi) :: i, j, k, propIDs(2), Iprop(2) !counter and temporary holders + INTEGER(IntKi) :: iNode1, iNode2 ! Node indices + INTEGER(IntKi) :: mType ! Member Type + Real(ReKi) :: mMass, mLength ! Member mass and length + REAL(ReKi) :: MRB(6,6) ! REDUCED SYSTEM Kmatrix, equivalent mass matrix + REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix + REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length + CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' + real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix + real(ReKi) :: Ke(12,12), Me(12, 12), FCe(12), FGe(12) ! element stiffness and mass matrices gravity force vector + real(ReKi), dimension(:,:), allocatable :: DummyArray ! + ! Variables for Eigenvalue analysis + integer(IntKi) :: nOmega + real(ReKi), dimension(:,:), allocatable :: Modes + real(ReKi), dimension(:) , allocatable :: Omega + logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) + character(len=*),parameter :: ReFmt='E15.6' + character(len=*),parameter :: SFmt='A15,1x' ! Need +1 for comma compared to ReFmt + character(len=*),parameter :: IFmt='I7' + ! + ErrStat = ErrID_None + ErrMsg = "" + + ! --- Eigen values of full system (for summary file output only) + ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) + ! M and K are reduced matrices, but Boundary conditions are not applied + ! We set bDOF, which is true if not a fixed Boundary conditions + ! NOTE: we don't check for singularities/rigig body modes here + CALL WrScr(' Calculating Full System Modes (for summary file output)') + CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return + bDOF(:) = .true. + bDOF(p%ID__F) = .false. + nOmega = count(bDOF) + CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2); if(Failed()) return + call EigenSolveWrap(Init%K, Init%M, p%nDOF_red, nOmega, .False., Modes, Omega, ErrStat2, ErrMsg2, bDOF); if(Failed()) return + IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) + + !------------------------------------------------------------------------------------------------------------- + ! open txt file + !------------------------------------------------------------------------------------------------------------- + SummaryName = TRIM(Init%RootName)//'.sum.yaml' + UnSum = -1 ! we haven't opened the summary file, yet. + + CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ); if(Failed()) return + !------------------------------------------------------------------------------------------------------------- + ! write discretized data to a txt file + !------------------------------------------------------------------------------------------------------------- +!bjj: for debugging, i recommend using the p% versions of all these variables whenever possible in this summary file: +! (it helps in debugging) + WRITE(UnSum, '(A)') '#Unless specified, units are consistent with Input units, [SI] system is advised.' + WRITE(UnSum, '(A)') SectionDivide + write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) + + ! --- Internal FEM representation + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '# Internal FEM representation' + call yaml_write_var(UnSum, 'nNodes_I', p%nNodes_I,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "interface" (I)') + call yaml_write_var(UnSum, 'nNodes_C', p%nNodes_C,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "reactions" (C)') + call yaml_write_var(UnSum, 'nNodes_L', p%nNodes_L,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "internal" (L)') + call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') +#ifdef SD_SUMMARY_DEBUG + call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') + call yaml_write_var(UnSum, 'nDOFI_B ', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') + call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') + call yaml_write_var(UnSum, 'nDOFC__ ', p%nDOFC__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" (C__)') + call yaml_write_var(UnSum, 'nDOFC_B ', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') + call yaml_write_var(UnSum, 'nDOFC_L ', p%nDOFC_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" internal (C_L)') + call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') + call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') + call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') +#endif + call yaml_write_var(UnSum, 'nDOF__B ', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: retained (__B)') + call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: internal (__L)') + call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: fixed (__F)') + call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total') +#ifdef SD_SUMMARY_DEBUG + call yaml_write_array(UnSum, 'Nodes_I', p%Nodes_I(:,1), IFmt, ErrStat2, ErrMsg2, comment='"interface" nodes"') + call yaml_write_array(UnSum, 'Nodes_C', p%Nodes_C(:,1), IFmt, ErrStat2, ErrMsg2, comment='"reaction" nodes"') + call yaml_write_array(UnSum, 'Nodes_L', p%Nodes_L(:,1), IFmt, ErrStat2, ErrMsg2, comment='"internal" nodes"') + call yaml_write_array(UnSum, 'DOF_I__', p%IDI__ , IFmt, ErrStat2, ErrMsg2, comment='"interface" DOFs"') + call yaml_write_array(UnSum, 'DOF_I_B', p%IDI_Rb, IFmt, ErrStat2, ErrMsg2, comment='"interface" retained DOFs') + call yaml_write_array(UnSum, 'DOF_I_F', p%IDI_F , IFmt, ErrStat2, ErrMsg2, comment='"interface" fixed DOFs') + call yaml_write_array(UnSum, 'DOF_C__', p%IDC__ , IFmt, ErrStat2, ErrMsg2, comment='"reaction" DOFs"') + call yaml_write_array(UnSum, 'DOF_C_B', p%IDC_Rb, IFmt, ErrStat2, ErrMsg2, comment='"reaction" retained DOFs') + call yaml_write_array(UnSum, 'DOF_C_L', p%IDC_L , IFmt, ErrStat2, ErrMsg2, comment='"reaction" internal DOFs') + call yaml_write_array(UnSum, 'DOF_C_F', p%IDC_F , IFmt, ErrStat2, ErrMsg2, comment='"reaction" fixed DOFs') + call yaml_write_array(UnSum, 'DOF_L_L', p%IDL_L , IFmt, ErrStat2, ErrMsg2, comment='"internal" internal DOFs') + call yaml_write_array(UnSum, 'DOF_R_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') +#endif + call yaml_write_array(UnSum, 'DOF___B', p%ID__Rb, IFmt, ErrStat2, ErrMsg2, comment='all retained DOFs') + call yaml_write_array(UnSum, 'DOF___F', p%ID__F , IFmt, ErrStat2, ErrMsg2, comment='all fixed DOFs') + call yaml_write_array(UnSum, 'DOF___L', p%ID__L , IFmt, ErrStat2, ErrMsg2, comment='all internal DOFs') + + WRITE(UnSum, '()') + WRITE(UnSum, '(A)') '#Index map from DOF to nodes' + WRITE(UnSum, '(A)') '# Node No., DOF/Node, NodalDOF' + call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) + + ! Nodes properties + write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' + call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) + + ! Element properties + CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return + do i=1,size(p%ElemProps) + DummyArray(i,1) = p%Elems(i,1) ! Should be == i + DummyArray(i,2) = p%Elems(i,2) ! Node 1 + DummyArray(i,3) = p%Elems(i,3) ! Node 2 + DummyArray(i,4) = p%Elems(i,4) ! Prop 1 + DummyArray(i,5) = p%Elems(i,5) ! Prop 2 + DummyArray(i,6) = p%ElemProps(i)%eType ! Type + DummyArray(i,7) = p%ElemProps(i)%Length !Length + DummyArray(i,8) = p%ElemProps(i)%Area ! Area m^2 + DummyArray(i,9) = p%ElemProps(i)%Rho ! density kg/m^3 + DummyArray(i,10) = p%ElemProps(i)%YoungE ! Young modulus + DummyArray(i,11) = p%ElemProps(i)%ShearG ! G + DummyArray(i,12) = p%ElemProps(i)%Kappa ! Shear coefficient + DummyArray(i,13) = p%ElemProps(i)%Ixx ! Moment of inertia + DummyArray(i,14) = p%ElemProps(i)%Iyy ! Moment of inertia + DummyArray(i,15) = p%ElemProps(i)%Jzz ! Moment of inertia + DummyArray(i,16) = p%ElemProps(i)%T0 ! Pretension [N] + enddo + write(UnSum, '("#",4x,6(A9),10('//trim(SFmt)//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' + call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),7(E15.6,",")') !, comment='',label=.true.) + deallocate(DummyArray) + + if (allocated(Init%Soil_K)) then + call yaml_write_array(UnSum, 'Soil_Nodes', Init%Soil_Nodes, IFmt, ErrStat2, ErrMsg2, comment='') + CALL AllocAry( DummyArray, 3, size(Init%Soil_Points,2), 'SoilP', ErrStat2, ErrMsg2 ); if(Failed()) return + do i=1,size(Init%Soil_K,3) + DummyArray(1:3,I) = Init%Nodes(Init%Soil_Nodes(I), 2:4) + call yaml_write_array(UnSum, 'Soil_K'//Num2LStr(I), Init%Soil_K(:,:,I), ReFmt, ErrStat2, ErrMsg2, comment='') + enddo + call yaml_write_array(UnSum, 'Soil_Points_SoilDyn', Init%Soil_Points, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'Soil_Points_SubDyn', DummyArray, ReFmt, ErrStat2, ErrMsg2, comment='') + deallocate(DummyArray) + endif + + ! --- User inputs (less interesting, repeat of input file) + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#User inputs' + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB + WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' + WRITE(UnSum, '("#",I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#No. of Reaction DOFs:',p%nDOFC__ + WRITE(UnSum, '(A, A6)') '#React. DOF_ID', 'BC' + do i = 1, size(p%IDC_F ); WRITE(UnSum, '("#",I10, A10)') p%IDC_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDC_L ); WRITE(UnSum, '("#",I10, A10)') p%IDC_L(i) , ' Free' ; enddo + do i = 1, size(p%IDC_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDC_Rb(i), ' Leader'; enddo + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#No. of Interface DOFs:',p%nDOFI__ + WRITE(UnSum, '(A,A6)') '#Interf. DOF_ID', 'BC' + do i = 1, size(p%IDI_F ); WRITE(UnSum, '("#",I10, A10)') p%IDI_F(i) , ' Fixed' ; enddo + do i = 1, size(p%IDI_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDI_Rb(i), ' Leader'; enddo + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of concentrated masses (NCMass):',Init%NCMass + WRITE(UnSum, '(A10,10(A15))') '#JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' + WRITE(UnSum, '("#",F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) + + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of members',p%NMembers + WRITE(UnSum, '(A,I6)') '#Number of nodes per member:', Init%Ndiv+1 + WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') '#Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' + DO i=1,p%NMembers + !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else + !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS + propIDs=Init%Members(i,iMProp:iMProp+1) + mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length + IF (ErrStat .EQ. ErrID_None) THEN + mType = Init%Members(I, iMType) ! + if (mType==idMemberBeam) then + iProp(1) = FINDLOCI(Init%PropSetsB(:,1), propIDs(1)) + iProp(2) = FINDLOCI(Init%PropSetsB(:,1), propIDs(2)) + mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & + Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, .TRUE.) + + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& + mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + else + WRITE(UnSum, '(A)') '#TODO, member mass for non-beam elements' + endif + ELSE + RETURN + ENDIF + ENDDO + !------------------------------------------------------------------------------------------------------------- + ! write Cosine matrix for all members to a txt file + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') '#Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers + WRITE(UnSum, '(A9,9(A15))') '#Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' + DO i=1,p%NMembers + iNode1 = FINDLOCI(Init%Joints(:,1), Init%Members(i,2)) ! index of joint 1 of member i + iNode2 = FINDLOCI(Init%Joints(:,1), Init%Members(i,3)) ! index of joint 2 of member i + XYZ1 = Init%Joints(iNode1,2:4) + XYZ2 = Init%Joints(iNode2,2:4) + CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) + DirCos=TRANSPOSE(DirCos) !This is now global to local + WRITE(UnSum, '("#",I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + ENDDO + + !------------------------------------------------------------------------------------------------------------- + ! write Eigenvalues of full SYstem and CB reduced System + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') "#Eigenfrequencies for full system (no constraint) [Hz]" + call yaml_write_array(UnSum, 'Full_frequencies', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) + WRITE(UnSum, '(A, I6)') "#CB frequencies [Hz]" + call yaml_write_array(UnSum, 'CB_frequencies', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) + + !------------------------------------------------------------------------------------------------------------- + ! write Eigenvectors of full System + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& + ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega + call yaml_write_array(UnSum, 'Full_Modes', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) + + !------------------------------------------------------------------------------------------------------------- + ! write CB system matrices + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' + call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2, comment='(CB modes)') + call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2, comment='(Guyan modes)') + + !------------------------------------------------------------------------------------------------------------- + ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point + !------------------------------------------------------------------------------------------------------------- + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" + call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'MBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) + + ! Set TI2, transformation matrix from R DOFs to SubDyn Origin + CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return + ! Compute Rigid body mass matrix (without Soil, and using both Interface and Reactions nodes as leader DOF) + if (p%nDOFR__/=p%nDOF__Rb) then + call SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat2, ErrMsg2); if(Failed()) return + MRB=matmul(TRANSPOSE(TI2),matmul(MBB,TI2)) !Equivalent mass matrix of the rigid body + else + MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body + endif + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' + call yaml_write_array(UnSum, 'MRB', MRB, ReFmt, ErrStat2, ErrMsg2) + WRITE(UnSum, '(A,E15.6)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(E15.6))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + deallocate(TI2) + +#ifdef SD_SUMMARY_DEBUG + + WRITE(UnSum, '()') + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#**** Additional Debugging Information ****' + + ! --- Element Me,Ke,Fg, Fce + CALL ElemM(p%ElemProps(1), Me) + CALL ElemK(p%ElemProps(1), Ke) + CALL ElemF(p%ElemProps(1), Init%g, FGe, FCe) + call yaml_write_array(UnSum, 'Ke',Ke, ReFmt, ErrStat2, ErrMsg2, comment='First element stiffness matrix') + call yaml_write_array(UnSum, 'Me',Me, ReFmt, ErrStat2, ErrMsg2, comment='First element mass matrix') + call yaml_write_array(UnSum, 'FGe',FGe, ReFmt, ErrStat2, ErrMsg2, comment='First element gravity vector') + call yaml_write_array(UnSum, 'FCe',FCe, ReFmt, ErrStat2, ErrMsg2, comment='First element cable pretension') + + ! --- Write assembed K M to a txt file + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF + call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') + call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') + + ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' + call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') + + ! --- write CB system matrices + WRITE(UnSum, '(A)') SectionDivide + WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' + call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') + IF (p%SttcSolve/= idSIM_None) THEN + call yaml_write_array(UnSum, 'PhiL', transpose(p%PhiL_T), ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'KLL^-1' , p%KLLm1 , ReFmt, ErrStat2, ErrMsg2, comment='') + endif + ! --- Reduction info + WRITE(UnSum, '(A)') SectionDivide + call yaml_write_array(UnSum, 'T_red', p%T_red, 'E9.2', ErrStat2, ErrMsg2, comment='(Constraint elimination matrix)') +#endif + + ! --- write TP TI matrix + WRITE(UnSum, '(A)') SectionDivide + call yaml_write_array(UnSum, 'TI' , p%TI , 'E9.2', ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') + if (allocated(p%TIReact)) then + call yaml_write_array(UnSum, 'TIReact', p%TIReact, 'E9.2', ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') + endif + + call CleanUp() + +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'OutSummary') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE CleanUp() + if(allocated(Omega)) deallocate(Omega) + if(allocated(Modes)) deallocate(Modes) + CALL SDOut_CloseSum( UnSum, ErrStat2, ErrMsg2 ) + END SUBROUTINE CleanUp +END SUBROUTINE OutSummary + +!------------------------------------------------------------------------------------------------------ +!> Calculate length of a member as given in input file +!! Joints and Members ID have not been reindexed (Elems and Nodes have) +FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) + TYPE(SD_InitType), INTENT(IN) :: Init !< Input data for initialization routine, this structure contains many variables needed for summary file + INTEGER(IntKi), INTENT(IN) :: MemberID !< Member ID # + REAL(ReKi) :: MemberLength !< Member Length + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + !Locals + REAL(Reki) :: xyz1(3),xyz2(3) ! Coordinates of joints in GLOBAL REF SYS + integer(IntKi) :: iMember !< Member index in Init%Members list + INTEGER(IntKi) :: Joint1,Joint2 ! JointID + CHARACTER(*), PARAMETER :: RoutineName = 'MemberLength' + ErrStat = ErrID_None + ErrMsg = '' + MemberLength=0.0 + + !Find the MemberID in the list + iMember = FINDLOCI(Init%Members(:,1), MemberID) + if (iMember<=0) then + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' not found in member list!', ErrStat,ErrMsg,RoutineName); + return + endif + ! Find joints ID for this member + Joint1 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,2)) + Joint2 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,3)) + xyz1= Init%Joints(Joint1,2:4) + xyz2= Init%Joints(Joint2,2:4) + MemberLength=SQRT( SUM((xyz2-xyz1)**2.) ) + if ( EqualRealNos(MemberLength, 0.0_ReKi) ) then + call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' has zero length!', ErrStat,ErrMsg,RoutineName); + return + endif +END FUNCTION MemberLength + +!------------------------------------------------------------------------------------------------------ +!> Calculate member mass, given properties at the ends, keep units consistent +!! For now it works only for circular pipes or for a linearly varying area +FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,ctube) + REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member + LOGICAL, INTENT(IN) :: ctube ! =TRUE for circular pipes, false elseshape + REAL(ReKi) :: BeamMass !mass + REAL(ReKi) :: a0,a1,a2,b0,b1,dd,dt !temporary coefficients + !Density allowed to vary linearly only + b0=rho1 + b1=(rho2-rho1)/L + !Here we will need to figure out what element it is for now circular pipes + IF (ctube) THEN !circular tube + a0=pi * (D1*t1-t1**2.) + dt=t2-t1 !thickness variation + dd=D2-D1 !OD variation + a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L + a2=pi * ( dd*dt-dt**2.)/L**2. + ELSE !linearly varying area + a0=D1 !This is an area + a1=(D2-D1)/L !Delta area + a2=0. + ENDIF + BeamMass= b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz +END FUNCTION BeamMass + +!------------------------------------------------------------------------------------------------------ +!> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR +SUBROUTINE SymMatDebug(M,MAT) + INTEGER(IntKi), INTENT(IN) :: M ! Number of rows and columns + REAL(ReKi),INTENT(IN) :: MAT(M ,M) !matrix to be checked + !LOCALS + REAL(ReKi) :: Error,MaxErr !element by element relative difference in (Transpose(MAT)-MAT)/MAT + INTEGER(IntKi) :: i, j, imax,jmax !counter and temporary holders + + MaxErr=0. + imax=0 + jmax=0 + DO j=1,M + DO i=1,M + Error=MAT(i,j)-MAT(j,i) + IF (MAT(i,j).NE.0) THEN + Error=ABS(Error)/MAT(i,j) + ENDIF + IF (Error > MaxErr) THEN + imax=i + jmax=j + MaxErr=Error + ENDIF + ENDDO + ENDDO + + !-------------------------------------- + ! write discretized data to a txt file + WRITE(*, '(A,e15.6)') 'Matrix Symmetry Check: Largest (abs) relative error is:', MaxErr + WRITE(*, '(A,I4,I4)') 'Matrix Symmetry Check: (I,J)=', imax,jmax + +END SUBROUTINE SymMatDebug + +FUNCTION is_numeric(string, x) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + REAL(ReKi), INTENT(OUT) :: x + LOGICAL :: is_numeric + INTEGER :: e,n + CHARACTER(len=12) :: fmt + x = 0.0_ReKi + n=LEN_TRIM(string) + WRITE(fmt,'("(F",I0,".0)")') n + READ(string,fmt,IOSTAT=e) x + is_numeric = e == 0 +END FUNCTION is_numeric +FUNCTION is_logical(string, b) + IMPLICIT NONE + CHARACTER(len=*), INTENT(IN) :: string + Logical, INTENT(OUT) :: b + LOGICAL :: is_logical + INTEGER :: e,n + b = .false. + n=LEN_TRIM(string) + READ(string,*,IOSTAT=e) b + is_logical = e == 0 +END FUNCTION is_logical + +!> Parses a file for Kxx,Kxy,..Kxthtx,..Kxtz, Kytx, Kyty,..Kztz +SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) + USE NWTC_IO + INTEGER, INTENT(IN) :: JointID !< ID of th ejoint for which we are reading SSI + INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc + INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error + CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message + INTEGER :: CurLine !< The current line to be parsed in the FileInfo structure. + REAL(ReKi), INTENT(INOUT) , dimension(21) :: SSIK, SSIM !< Matrices being filled by reading the file. + CHARACTER(*), INTENT(IN) :: Filename !< Name of the input file. + ! Local declarations: + CHARACTER(5), DIMENSION(21) :: Knames=(/'Kxx ','Kxy ','Kyy ','Kxz ','Kyz ', 'Kzz ','Kxtx ','Kytx ','Kztx ','Ktxtx', & + 'Kxty ','Kyty ','Kzty ','Ktxty','Ktyty', & + 'Kxtz ','Kytz ','Kztz ','Ktxtz','Ktytz','Ktztz'/) ! Dictionary of names by column for an Upper Triangular Matrix + CHARACTER(5), DIMENSION(21) :: Mnames=(/'Mxx ','Mxy ','Myy ','Mxz ','Myz ', 'Mzz ','Mxtx ','Mytx ','Mztx ','Mtxtx', & + 'Mxty ','Myty ','Mzty ','Mtxty','Mtyty', & + 'Mxtz ','Mytz ','Mztz ','Mtxtz','Mtytz','Mtztz'/) + TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. + INTEGER :: IOS ! I/O status returned from the read statement. + INTEGER(IntKi) :: i, j, imax !counters + CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: ErrStat2 ! Error status; if present, program does not abort on error + CHARACTER(*), PARAMETER :: RoutineName = 'ReadSSIfile' + + SSIK=0.0_ReKi + SSIM=0.0_ReKi + + CALL ProcessComFile ( Filename, FileInfo, ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); IF (ErrStat >= AbortErrLev) RETURN + CurLine = 1 + imax=21 + DO i=1, imax !This will search also for already hit up names, but that's ok, it should be pretty fast + DO j=1,FileInfo%NumLines + CurLine=j + CALL ParseVarWDefault ( FileInfo, CurLine, Knames(i), SSIK(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) + CALL ParseVarWDefault ( FileInfo, CurLine, Mnames(i), SSIM(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) + ENDDO + ENDDO + IF ( PRESENT(UnEc) ) THEN + IF ( UnEc .GT. 0 ) THEN + WRITE (UnEc,'(1X,A20," = ",I11)') 'JOINT ID',JointID + DO i=1,21 + WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIK(i), Knames(i) + WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIM(i), Mnames(i) + ENDDO + ENDIF + END IF + RETURN +END SUBROUTINE ReadSSIfile + + +end module SubDyn diff --git a/modules/subdyn/src_soildyn/SubDyn_Driver.f90 b/modules/subdyn/src_soildyn/SubDyn_Driver.f90 new file mode 100644 index 000000000..372928e4b --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Driver.f90 @@ -0,0 +1,342 @@ +!********************************************************************************************************************************** +! SubDyn_DriverCode: This code tests the SubDyn modules +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** +PROGRAM TestSubDyn + + USE NWTC_Library + USE SubDyn + USE SubDyn_Types + USE SubDyn_Output + USE VersionInfo + + IMPLICIT NONE + + INTEGER(IntKi), PARAMETER :: NumInp = 1 ! Number of inputs sent to SD_UpdateStates + + + TYPE SD_Drvr_InitInput + LOGICAL :: Echo + REAL(ReKi) :: Gravity + CHARACTER(1024) :: SDInputFile + REAL(ReKi) :: WtrDpth + CHARACTER(1024) :: OutRootName + INTEGER :: NSteps + REAL(DbKi) :: TimeInterval + REAL(ReKi) :: TP_RefPoint(3) + REAL(ReKi) :: SubRotateZ + INTEGER :: InputsMod + CHARACTER(1024) :: InputsFile + REAL(ReKi) :: uTPInSteady(6) + REAL(ReKi) :: uDotTPInSteady(6) + REAL(ReKi) :: uDotDotTPInSteady(6) + END TYPE SD_Drvr_InitInput + + + ! Program variables + + REAL(DbKi) :: Time ! Variable for storing time, in seconds + REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds + REAL(DbKi) :: InputTime(NumInp) ! Variable for storing time associated with inputs, in seconds + + TYPE(SD_InitInputType) :: InitInData ! Input data for initialization + TYPE(SD_InitOutputType) :: InitOutData ! Output data from initialization + + TYPE(SD_ContinuousStateType) :: x ! Continuous states + TYPE(SD_DiscreteStateType) :: xd ! Discrete states + TYPE(SD_ConstraintStateType) :: z ! Constraint states + TYPE(SD_OtherStateType) :: OtherState ! Other states + TYPE(SD_MiscVarType) :: m ! Misc/optimization variables + + TYPE(SD_ParameterType) :: p ! Parameters + TYPE(SD_InputType) :: u(NumInp) ! System inputs + TYPE(SD_OutputType) :: y ! System outputs + + + INTEGER(IntKi) :: n ! Loop counter (for time step) + INTEGER(IntKi) :: ErrStat, ErrStat1, ErrStat2, ErrStat3 ! Status of error message + CHARACTER(1024) :: ErrMsg, ErrMsg1, ErrMsg2, ErrMsg3 ! Error message if ErrStat /= ErrID_None + + + CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. + TYPE(SD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program + INTEGER :: UnIn ! Unit number for the input file + INTEGER :: UnEcho ! The local unit number for this module's echo file + INTEGER(IntKi) :: UnSD_Out ! Output file identifier + REAL(ReKi), ALLOCATABLE :: SDin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for SubDyn inputs + INTEGER(IntKi) :: J ! Generic loop counter + REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). + CHARACTER(10) :: AngleMsg ! For debugging, a string version of the largest rotation input + + ! Other/Misc variables + REAL(DbKi) :: TiLstPrn ! The time of the last print + REAL(DbKi) :: TMax + REAL(DbKi) :: OutTime ! Used to determine if output should be generated at this simulation time + REAL(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds + REAL(ReKi) :: UsrTime1 ! User CPU time for simulation initialization + INTEGER :: StrtTime (8) ! Start time of simulation + CHARACTER(200) :: git_commit ! String containing the current git commit hash + TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'SubDyn Driver', '', '' ) ! The version number of this program. + !............................................................................................................................... + ! Routines called in initialization + !............................................................................................................................... + ErrMsg = "" + ErrStat = ErrID_None + UnEcho=-1 + UnIn =-1 + + ! Get the current time + CALL DATE_AND_TIME ( Values=StrtTime ) ! Let's time the whole simulation + CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) + PrevClockTime = TimeValues2Seconds( StrtTime ) ! We'll use this time for the SimStats routine + TiLstPrn = 0.0_DbKi ! The first value of ZTime, used to write simulation stats to screen (s) + + ! Initialize the NWTC Subroutine Library + CALL NWTC_Init( ) + + ! Display the copyright notice + CALL DispCopyrightLicense( version%Name ) + ! Obtain OpenFAST git commit hash + git_commit = QueryGitVersion() + ! Tell our users what they're running + CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + + ! Set the abort error level to a fatal error + AbortErrLev = ErrID_Fatal + + IF ( command_argument_count() /= 1 ) then + CALL print_help() + STOP + endif + + ! Parse the driver input file and run the simulation based on that file + IF ( command_argument_count() == 1 ) THEN + CALL get_command_argument(1, drvrFilename) + + CALL ReadDriverInputFile( drvrFilename, drvrInitInp); + InitInData%g = drvrInitInp%Gravity + InitInData%SDInputFile = drvrInitInp%SDInputFile + InitInData%RootName = drvrInitInp%OutRootName + InitInData%TP_RefPoint = drvrInitInp%TP_RefPoint + InitInData%SubRotateZ = drvrInitInp%SubRotateZ + TimeInterval = drvrInitInp%TimeInterval + InitInData%WtrDpth = drvrInitInp%WtrDpth + END IF + + TMax = TimeInterval * drvrInitInp%NSteps + + ! Initialize the module + CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() + + CALL AllocAry(SDin, drvrInitInp%NSteps, 13, 'SDinput array', ErrStat2, ErrMsg2); call AbortIfFailed() + SDin(:,:)=0.0_ReKi + + ! Read Input time series data from a file + IF ( drvrInitInp%InputsMod == 2 ) THEN + ! Open the inputs data file + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile ( UnIn, drvrInitInp%InputsFile, ErrStat2, ErrMsg2); Call AbortIfFailed() + DO n = 1,drvrInitInp%NSteps + READ (UnIn,*,IOSTAT=ErrStat2) (SDin (n,J), J=1,13) + ErrMsg2 = ' Error reading line '//trim(Num2LStr(n))//' of file: '//trim(drvrInitInp%InputsFile) + call AbortIfFailed() + END DO + CLOSE ( UnIn ) + else + ! We fill an array with constant values + do n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 + SDin(n+1,1) = n*TimeInterval + SDin(n+1,2:7 ) = drvrInitInp%uTPInSteady(1:6) ! Displacements + SDin(n+1,8:13) = drvrInitInp%uDotTPInSteady(1:6) ! Velocities + !SDin(n+1,14:19) = drvrInitInp%uDotDotTPInSteady(1:6) ! Accelerations + enddo + end if + + ! Destroy initialization data + CALL SD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ); call AbortIfFailed() + CALL SD_DestroyInitOutput( InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() + + !............................................................................................................................... + ! Routines called in loose coupling -- the glue code may implement this in various ways + !............................................................................................................................... + ! Force the displacement of the interface node in the global Z direction to be the sag of the column under it's own weight + ! u(1)%UFL(3) =-12.958 !this is for testbeam3 + call WrScr('') + DO n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 + + Time = n*TimeInterval + InputTime(1) = Time + + ! Set module inputs u (likely from the outputs of another module or a set of test conditions) here: + IF ( u(1)%TPMesh%Initialized ) THEN + ! For now, set all hydrodynamic load inputs to 0.0 + u(1)%LMesh%Force (:,:) = 0.0 + u(1)%LMesh%Moment (:,:) = 0.0 + + ! Input displacements, velocities and potentially accelerations + u(1)%TPMesh%TranslationDisp(:,1) = SDin(n+1,2:4) + CALL SmllRotTrans( 'InputRotation', REAL(SDin(n+1,5),reki), REAL(SDin(n+1,6),reki), REAL(SDin(n+1,7),reki), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%TPMesh%Orientation(:,:,1) = dcm + u(1)%TPMesh%TranslationVel(:,1) = SDin(n+1,8:10) + u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) + + IF ( drvrInitInp%InputsMod == 2 ) THEN + ! User time series have no acceleration for now.. + u(1)%TPMesh%TranslationAcc(:,1) = 0.0_ReKi + u(1)%TPMesh%RotationAcc(:,1) = 0.0_ReKi + ELSE ! constant inputs + u(1)%TPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(1:3) + u(1)%TPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(4:6) + END IF + END IF + + ! Calculate outputs at n + CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2); call AbortIfFailed() + ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 + CALL SD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2); call AbortIfFailed() + ! Display simulation status every SttsTime-seconds: + IF ( Time - TiLstPrn >= 1 ) THEN + CALL SimStatus( TiLstPrn, PrevClockTime, Time, TMax ) + ENDIF + + END DO ! Loop on n, time steps + + ! Routine to terminate program execution + CALL SD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2) + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + + ! Write simulation times and stop + CALL RunTimes( StrtTime, UsrTime1, StrtTime, UsrTime1, Time ) + +CONTAINS + SUBROUTINE AbortIfFailed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SubDyn_Driver') + IF ( ErrStat /= ErrID_None ) THEN + CALL WrScr( ErrMsg ) + END IF + if (ErrStat >= AbortErrLev) then + call CleanUp() + STOP + endif + END SUBROUTINE AbortIfFailed + + SUBROUTINE CleanUp() + if(UnEcho>0) CLOSE(UnEcho) + if(UnEcho>0) CLOSE( UnIn) + if(allocated(SDin)) deallocate(SDin) + END SUBROUTINE CleanUp + + !------------------------------------------------------------------------------------------------------------------------------- + SUBROUTINE ReadDriverInputFile( inputFile, InitInp) + CHARACTER(*), INTENT( IN ) :: inputFile + TYPE(SD_Drvr_InitInput), INTENT( OUT ) :: InitInp + ! Local variables + INTEGER :: I ! generic integer for counting + INTEGER :: J ! generic integer for counting + CHARACTER( 2) :: strI ! string version of the loop counter + + CHARACTER(1024) :: EchoFile ! Name of SubDyn echo file + CHARACTER(1024) :: Line ! String to temporarially hold value of read line + CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name + CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement + CHARACTER(1024) :: FileName ! Name of SubDyn input file + CHARACTER(1024) :: FilePath ! Path Name of SubDyn input file + + UnEcho=-1 + UnIn =-1 + + FileName = TRIM(inputFile) + + CALL GetNewUnit( UnIn ) + CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2); + call AbortIfFailed() + + CALL WrScr( 'Opening SubDyn Driver input file: '//FileName ) + + ! Read until "echo" + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2); call AbortIfFailed() + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2); call AbortIfFailed() + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat2, ErrMsg2); call AbortIfFailed() + ! If we echo, we rewind + IF ( InitInp%Echo ) THEN + EchoFile = TRIM(FileName)//'.echo' + CALL GetNewUnit( UnEcho ) + CALL OpenEcho ( UnEcho, EchoFile, ErrStat, ErrMsg ); call AbortIfFailed() + REWIND(UnIn) + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + END IF + !---------------------- ENVIRONMENTAL CONDITIONS ------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%WtrDpth, 'WtrDpth', 'WtrDpth', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- SubDyn ------------------------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'SubDyn header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%SDInputFile, 'HDInputFile', 'SubDyn input filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%OutRootName, 'OutRootName', 'SubDyn output root filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%NSteps , 'NSteps', 'Number of time steps in the SubDyn simulation', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', 'Time interval for any SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadAry( UnIn, FileName, InitInp%TP_RefPoint, 3, 'TP reference point', 'TP reference point', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%SubRotateZ, 'SubRotateZ', 'Rotation angle in degrees about Z axis.', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- INPUTS ------------------------------------------------------------------- + CALL ReadCom( UnIn, FileName, 'INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%InputsMod , 'InputsMod', 'Model for the inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + CALL ReadVar( UnIn, FileName, InitInp%InputsFile, 'InputsFile', 'Filename for the SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + !---------------------- STEADY INPUTS (for InputsMod = 1) ---------------------------------------- + CALL ReadCom( UnIn, FileName, 'STEADY STATE INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() + IF ( InitInp%InputsMod == 1 ) THEN + CALL ReadAry ( UnIn, FileName, InitInp%uTPInSteady , 6, 'uInSteady', 'Steady-state TP displacements and rotations.', ErrStat2, ErrMsg2, UnEcho) + CALL ReadAry ( UnIn, FileName, InitInp%uDotTPInSteady , 6, 'uDotTPInSteady', 'Steady-state TP translational and rotational velocities.', ErrStat2, ErrMsg2, UnEcho) + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotTPInSteady, 6, 'uDotDotTPInSteady', 'Steady-state TP translational and rotational accelerations.', ErrStat2, ErrMsg2, UnEcho) + ELSE + InitInp%uTPInSteady = 0.0 + InitInp%uDotTPInSteady = 0.0 + InitInp%uDotDotTPInSteady = 0.0 + END IF + if(UnEcho>0) CLOSE( UnEcho ) + if(UnIn>0) CLOSE( UnIn ) + + ! Perform input checks and triggers + CALL GetPath( FileName, FilePath ) + IF ( PathIsRelative( InitInp%SDInputFile ) ) then + InitInp%SDInputFile = TRIM(FilePath)//TRIM(InitInp%SDInputFile) + END IF + IF ( PathIsRelative( InitInp%OutRootName ) ) then + InitInp%OutRootName = TRIM(FilePath)//TRIM(InitInp%OutRootName) + endif + IF ( PathIsRelative( InitInp%InputsFile ) ) then + InitInp%InputsFile = TRIM(FilePath)//TRIM(InitInp%InputsFile) + endif + + END SUBROUTINE ReadDriverInputFile + + subroutine print_help() + print '(a)', 'usage: ' + print '(a)', '' + print '(a)', 'SubDynDriver.exe driverfilename' + print '(a)', '' + print '(a)', 'Where driverfilename is the name of the SubDyn driver input file.' + print '(a)', '' + end subroutine print_help +!---------------------------------------------------------------------------------------------------------------------------------- +END PROGRAM TestSubDyn diff --git a/modules/subdyn/src_soildyn/SubDyn_Output.f90 b/modules/subdyn/src_soildyn/SubDyn_Output.f90 new file mode 100644 index 000000000..2c68d3b49 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Output.f90 @@ -0,0 +1,804 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** +MODULE SubDyn_Output + USE NWTC_Library + USE SubDyn_Types + USE SD_FEM + USE SubDyn_Output_Params, only: MNfmKe, MNfmMe, MNTDss, MNRDe, MNTRAe, IntfSS, IntfTRss, IntfTRAss, ReactSS + USE SubDyn_Output_Params, only: ParamIndxAry, ParamUnitsAry, ValidParamAry, SSqm01, SSqmd01, SSqmdd01 + + IMPLICIT NONE + + ! The maximum number of output channels which can be output by the code. + INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 + + PRIVATE + ! ..... Public Subroutines ................................................................................................... + PUBLIC :: SDOut_CloseSum + PUBLIC :: SDOut_OpenSum + PUBLIC :: SDOut_MapOutputs + PUBLIC :: SDOut_OpenOutput + PUBLIC :: SDOut_CloseOutput + PUBLIC :: SDOut_WriteOutputNames + PUBLIC :: SDOut_WriteOutputUnits + PUBLIC :: SDOut_WriteOutputs + PUBLIC :: SDOut_Init + +CONTAINS + + +!> This subroutine initializes the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module + TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data + TYPE(SD_ParameterType), target, INTENT( INOUT ) :: p ! SubDyn module paramters + TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables + TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data + REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: I,J,K2 !Counters + INTEGER(IntKi) :: iMember ! Member index (not member ID) + INTEGER(IntKi) :: iElem ! Index of element in Element List + INTEGER(IntKi) :: iNode ! Index of node in Node list + INTEGER(IntKi) :: iiElem ! Loop counter on element index + INTEGER(IntKi) :: nElemPerNode ! Number of elements connecting to a node + type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities + real(ReKi), allocatable :: T_TIreact(:,:) ! Transpose of TIreact, temporary + ErrStat = 0 + ErrMsg="" + + p%OutAllDims=12*p%NMembers*2 !size of AllOut Member Joint forces + + ! Check that the variables in OutList are valid + CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! --- Allocation (size 0 if not outputs) + !IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested + ! Allocate SDWrOuput which is used to store a time step's worth of output channels, prior to writing to a file. + CALL AllocAry(misc%SDWrOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'SDWrOutupt' , ErrStat2, ErrMsg2) ; if(Failed()) return + ! Allocate WriteOuput + CALL AllocAry(y%WriteOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return + ! Header, and Units, copy of data already available in the OutParam data structure ! TODO TODO TODO remove copy + CALL AllocAry(InitOut%WriteOutputHdr, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputHdr', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(InitOut%WriteOutputUnt, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputUnt', ErrStat2, ErrMsg2); if(Failed()) return + misc%SDWrOutput = 0.0_ReKi + misc%LastOutTime = 0.0_DbKi + misc%Decimat = 0 + y%WriteOutput = 0 + DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims + InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) + InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) + END DO + + !_________________________________ OUTPUT FOR REQUESTED MEMBERS _______________________________ + DO I=1,p%NMOutputs + pLst => p%MOutLst(I) ! Alias to shorten notations + CALL AllocAry(pLst%NodeIDs, pLst%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, pLst%NoutCnt, 2, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, pLst%NoutCnt, 2, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + + ! NOTE: len(MemberNodes) >2 if nDiv>1 + iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers + pLst%NodeIDs(1:pLst%NoutCnt)=Init%MemberNodes(iMember, pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting + pLst%ElmIDs=0 !Initialize to 0 + pLst%ElmNds=0 !Initialize to 0 + + DO J=1,pLst%NoutCnt ! loop on requested nodes for that member + iNode = pLst%NodeIDs(J) ! Index of requested node in node list + nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the j-th node + ! Finding 1 or max 2 elements that belong to the member and connect to the node + K2=0 ! Counter so that max 2 elements are included: NOTE: I belive more than 2 should be an error + DO iiElem = 1, nElemPerNode + iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number + IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN + IF (K2 == 2) EXIT ! we found both elements already, error... + K2=K2+1 + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=J, iStore=K2, NodeID2=iNode) + END IF + ENDDO ! iiElem, nElemPerNode + ENDDO !J, Noutcnt + ENDDO !I, NMOutputs + + !_________________________________ OUTPUT FOR ALL MEMBERS __________________________________ + IF (p%OutAll) THEN !I need to store all member end forces and moments + + ! MOutLst2: nodal output info by members, for all members, First and Last Node + ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat2 ); ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init'; if(Failed()) return + + DO iMember=1,p%NMembers + pLst => p%MOutLst2(iMember) ! Alias + CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + pLst%MemberID = Init%Members(iMember,1) + pLst%NodeIDs = Init%MemberNodes(iMember,1:Init%Ndiv+1) ! We are storing the actual node numbers in the member + !ElmIDs could contain the same element twice if Ndiv=1 + pLst%ElmIDs=0 !Initialize to 0 + DO J=1,Init%Ndiv+1,Init%Ndiv ! loop on first and last node of member + iNode = pLst%NodeIDs(J) ! Index of requested node in node list + nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the 1st or last node of the member + K2= J/(Init%Ndiv+1)+1 ! 1 (first node) or 2 (last node) depending on J + DO iiElem=1, nElemPerNode + iElem = Init%NodesConnE(iNode,iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node + IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=K2, iStore=1, NodeID2=iNode) + EXIT !We found the element for that node, exit loop on elements + ENDIF + ENDDO + ENDDO ! Loop on divisions + ENDDO ! Loop on members + ENDIF ! OutAll + !_____________________________________REACTIONS_____________________________________________ + ! --- Check if reaction requested by user + p%OutReact = .FALSE. + DO I=1,p%NumOuts + if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" + p%OutReact =.TRUE. + EXIT + ENDIF + ENDDO + IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being + ! MOutLst3: nodal output info by members, for the members involved in reaction + ALLOCATE(p%MOutLst3(p%nNodes_C), STAT = ErrStat2); ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init'; if(Failed()) return + + DO I=1,p%nNodes_C !For all constrained node + pLst => p%MOutLst3(I) + iNode = p%Nodes_C(I,1) ! Note: Nodes_C has been reindexed + nElemPerNode = Init%NodesConnE(iNode,1) ! Number of elements connecting to the joint + CALL AllocAry(pLst%ElmIDs, 1, nElemPerNode, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%ElmNds, 1, nElemPerNode, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Me, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Ke, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(pLst%Fg, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return + DO iiElem = 1, nElemPerNode + iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node + call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=1, iStore=iiElem, NodeID2=iNode) + ENDDO + ENDDO + ! Compute p%TIreact, rigid transf. matrix from reaction DOFs to base structure point (0,0,-WD) + CALL AllocAry(p%TIreact, 6, p%nDOFC__, 'TIReact ', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(T_TIreact, p%nDOFC__, 6, 'TIReact_T', ErrStat2, ErrMsg2); if(Failed()) return + call RigidTrnsf(Init, p, (/0.0_Reki, 0.0_ReKi, -WtrDpth /), p%IDC__, p%nDOFC__, T_TIreact, ErrStat2, ErrMsg2); if(Failed()) return + p%TIreact=transpose(T_TIreact) + deallocate(T_TIreact) + ENDIF + RETURN + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SDOut_Init') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + + !> Returns true if an element is connected to node iNode, and along member iMember + LOGICAL FUNCTION ThisElementIsAlongMember(iElem, iNode, iMember) + integer(IntKi), intent(in) :: iElem !< Element index + integer(IntKi), intent(in) :: iNode !< Node index + integer(IntKi), intent(in) :: iMember !< Member index + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + integer(IntKi) :: iOtherNode ! Other node than iNode for element iElem + ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the element + ! Check that the other node belongs to the member + IF (ElemNodes(1) == iNode) then + iOtherNode=ElemNodes(2) + else if (ElemNodes(2) == iNode) then + iOtherNode=ElemNodes(1) + else + ThisElementIsAlongMember=.false. ! Not along member since nodes don't match + return + endif + ! Being along the member means the second node of the element is in the node list of the member + ThisElementIsAlongMember= ANY(Init%MemberNodes(iMember,:) == iOtherNode) + END FUNCTION + + !> Set different "data" for a given output node, and possibly store more than one "data" per node: + !! The "data" is: + !! - Mass, stiffness matrices and constant element force (gravity and cable) + !! - A flag whether the node is the 1st or second node of an element + !! The "data" is stored at the index (iiNode,iStore): + !! - iiNode: node index within the list of nodes that are to be used for output for this member + !! - iStore: index over the number of "data" stored per node. E.g. Member1 and 2 connecting to a node + SUBROUTINE ConfigOutputNode_MKF_ID(pLst, iElem, iiNode, iStore, NodeID2) + type(MeshAuxDataType), intent(inout) :: pLst !< Info for one member output + integer(IntKi) , intent(in) :: iElem !< Element index to which the node belong + integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) + integer(IntKi) , intent(in) :: iStore !< Storage index, used several informations are stored per node + integer(IntKi) , intent(in) :: NodeID2 !< If ElemNode(2) == NodeID2, then it's the second node + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + pLst%ElmIDs(iiNode,iStore) = iElem ! This array has for each joint requested the elements' ID to get results for + ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the k-th element + if (ElemNodes(2) == NodeID2) then + pLst%ElmNds(iiNode,iStore) = 2 ! store whether first or second node of element + else + pLst%ElmNds(iiNode,iStore) = 1 ! store whether first or second node of element + endif + ! --- Element Me, Ke, Fg, Fce + CALL ElemM(p%ElemProps(iElem), pLst%Me(:,:,iiNode,iStore)) + CALL ElemK(p%ElemProps(iElem), pLst%Ke(:,:,iiNode,iStore)) + CALL ElemF(p%ElemProps(iElem), Init%g, pLst%Fg(:,iiNode,iStore), FCe) + pLst%Fg(:,iiNode,iStore) = pLst%Fg(:,iiNode,iStore) + FCe(1:12) ! Adding cable element force + END SUBROUTINE ConfigOutputNode_MKF_ID + + +END SUBROUTINE SDOut_Init +!------------------------------------------------------------------------------------------------------ +!> Writes the data stored in the y variable to the correct indexed postions in WriteOutput +!! This is called by SD_CalcOutput() at each time step. +!! This routine does fill Allouts +!! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling +!! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) +SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) + real(DbKi), intent( in ) :: CurrentTime ! Current simulation time in seconds + type(SD_InputType), intent( in ) :: u ! SubDyn module's input data + type(SD_ContinuousStateType), intent( in ) :: x ! SubDyn module's states data + type(SD_OutputType), intent( inout ) :: y ! SubDyn module's output data + type(SD_ParameterType), target,intent( in ) :: p ! SubDyn module's parameter data + type(SD_MiscVarType), intent( inout ) :: m ! Misc/optimization variables + real(ReKi), intent( out ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs + integer(IntKi), intent( out ) :: ErrStat ! Error status of the operation + character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + !locals + integer(IntKi) :: iMemberOutput, iiNode, iSDNode, iMeshNode, I, J, L, L2 ! Counters + integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM + real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments + real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments + real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions + integer(IntKi) :: sgn !+1/-1 for node force calculations + type(MeshAuxDataType), pointer :: pLst !< Info for a given member-output (Alias to shorten notation) + integer(IntKi), pointer :: DOFList(:) !< List of DOF indices for a given Nodes (Alias to shorten notation) + ErrStat = ErrID_None + ErrMsg = "" + + AllOuts = 0.0_ReKi ! initialize for those outputs that aren't valid (and thus aren't set in this routine) + + ! -------------------------------------------------------------------------------- + ! --- Requested member-outputs (Node kinematics and loads) + ! -------------------------------------------------------------------------------- + ! p%MOutLst has the mapping for the member, node, elements per node, to be used + ! MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) + if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 + ! Loop over member-outputs requested + DO iMemberOutput=1,p%NMOutputs + pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output + DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member + ! --- Forces (potentially averaged on 2 elements) + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) + FM_elm2=sgn*FM_elm + FK_elm2=sgn*FK_elm + IF (pLst%ElmIDs(iiNode,2) .NE. 0) THEN ! Second element exist + ! NOTE: forces are computed in the coordinate system of the first element for averaging + call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above + FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average + FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average + ENDIF + ! Static (elastic) component of reaction forces and moments at MαNβ along local member coordinate system + ! "MαNβFKxe, MαNβFKye, MαNβFKze, MαNβMKxe, MαNβMKye, MαNβMKze" + AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref + ! Dynamic (inertial) component of reaction forces and moments at MαNβ along local member coordinate system + ! "MαNβFMxe, MαNβFMye, MαNβFMze, MαNβMMxe, MαNβMMye, MαNβMMze" + AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref + + ! --- Displacements and acceleration + DOFList => p%NodesDOF(pLst%NodeIDs(iiNode))%List + ! Displacement- Translational -no need for averaging since it is a node translation - In global reference SS + ! "MαNβTDxss, MαNβTDyss, MαNβTDzss" + AllOuts(MNTDss (:,iiNode,iMemberOutput)) = m%U_full(DOFList(1:3)) + ! Displacement- Rotational - need direction cosine matrix to tranform rotations - In Local reference Element Ref Sys + ! "MαNβRDxss, MαNβRDye, MαNβRDze" + AllOuts(MNRDe (:,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full(DOFList(4:6))) !local ref + ! Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations + ! "MαNβTAxe, MαNβTAye, MαNβTAze" + ! "MαNβRAxe, MαNβRAye, MαNβRAze" + AllOuts(MNTRAe (1:3,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(1:3))) ! translational accel local ref + AllOuts(MNTRAe (4:6,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(4:6))) ! rotational accel local ref + ENDDO ! iiNode, Loop on requested nodes for that member + ENDDO ! iMemberOutput, Loop on member outputs + END IF + + ! -------------------------------------------------------------------------------- + ! --- All nodal loads from stiffness and mass matrix + ! -------------------------------------------------------------------------------- + ! "MaaaJbFKxe, MaaaJbMKxe MaaaJbFMxe, MaaaJbMMxe for member aaa and node b." + IF (p%OutAll) THEN + DO iMemberOutput=1,p%NMembers !Cycle on all members + pLst=>p%MOutLst2(iMemberOutput) + DO iiNode=1,2 !Iterate on requested nodes for that member (first and last) + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) + ! Store in All Outs + L = MaxOutPts+(iMemberOutput-1)*24+(iiNode-1)*12+1 + L2 = L+11 + AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) + ENDDO !iiNode, nodes 1 and 2 + ENDDO ! iMemberOutput, Loop on members + ENDIF + + ! -------------------------------------------------------------------------------- + ! --- Interface kinematics and loads (TP/platform reference point) + ! -------------------------------------------------------------------------------- + ! Total interface reaction forces and moments in SS coordinate system + ! "IntfFXss, IntfFYss, IntfFZss, IntfMXss, IntfMYss, IntfMZss," + AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign + ! Interface translations and rotations in SS coordinate system + ! "IntfTDXss, IntfTDYss, IntfTDZss, IntfRDXss, IntfRDYss IntfRDZss" + AllOuts(IntfTRss(1:nDOFL_TP))=m%u_TP + ! Interface Translational and rotational accelerations in SS coordinate system + ! "IntfTAXss, IntfTAYss, IntfTAZss, IntfRAXss, IntfRAYss IntfRAZss" + AllOuts(IntfTRAss(1:nDOFL_TP))= m%udotdot_TP + + ! -------------------------------------------------------------------------------- + ! --- Modal parameters "SSqmXX, SSqmdotXX, SSqmddXX" amplitude, speed and acceleration + ! -------------------------------------------------------------------------------- + maxOutModes = min(p%nDOFM,99) ! We only have space for the first 99 values + IF ( maxOutModes > 0 ) THEN + !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) + AllOuts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) + AllOuts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) + AllOuts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) + END IF + + ! --------------------------------------------------------------------------------} + ! --- Base reaction loads + ! --------------------------------------------------------------------------------{ + ! Total base reaction forces and moments at the (0.,0.,-WtrDpth) location in SS coordinate system + ! "ReactFXss, ReactFYss, ReactFZss, ReactMXss, ReactMYss, ReactMZss" + IF (p%OutReact) THEN + ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) + IF ( ErrStat /= ErrID_None ) THEN + ErrMsg = ' Error allocating space for ReactNs array.' + ErrStat = ErrID_Fatal + RETURN + END IF + ReactNs = 0.0_ReKi !Initialize + DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh + FK_elm2=0._ReKi !Initialize for cumulative force + FM_elm2=0._ReKi !Initialize + pLst => p%MOutLst3(I) + !Find the joint forces + DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) + iiNode = 1 + call ElementForce(pLst, iiNode, J, FM_elm, FK_elm, sgn, DIRCOS, .false.) + !transform back to global, need to do 3 at a time since cosine matrix is 3x3 + DO L=1,2 + FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF + FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; + ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 + ENDDO + ENDDO + ! FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise + ! NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES + iSDNode = p%Nodes_C(I,1) + iMeshNode = iSDNode ! input and Y2 mesh nodes are the same as subdyn + Fext = (/ u%LMesh%Force(:,iMeshNode), u%LMesh%Moment(:,iMeshNode) /) + ReactNs((I-1)*6+1:6*I) = FK_elm2 - Fext !Accumulate reactions from all nodes in GLOBAL COORDINATES + ENDDO + ! Store into AllOuts + AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) + ENDIF + if (allocated(ReactNs)) deallocate(ReactNs) +contains + + subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInputDirCos) + type(MeshAuxDataType), intent(in) :: pLst !< Info for one member output + integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) + integer(IntKi) , intent(in) :: JJ !< TODO: interpretation: index over other member connected to the current member (for averaging) + real(ReKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(ReKi), dimension (6), intent(out) :: FM_elm, FK_elm !output static and dynamic forces and moments + integer(IntKi), intent(out) :: sgn !+1/-1 for node force calculations + logical, intent(in) :: bUseInputDirCos !< If True, use DIRCOS from input, otherwise, use element DirCos + ! Local + integer(IntKi) :: iElem !< Element index/number + integer(IntKi) :: FirstOrSecond !< 1 or 2 if first node or second node + integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) + real(ReKi) , dimension(12) :: X_e, Xdd_e ! Displacement and acceleration for an element + integer(IntKi), dimension(2), parameter :: NodeNumber_To_Sign = (/-1, +1/) + + iElem = pLst%ElmIDs(iiNode,JJ) ! element number + FirstOrSecond = pLst%ElmNds(iiNode,JJ) ! first or second node of the element to be considered + sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node + ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element iElem + X_e(1:6) = m%U_full (p%NodesDOF(ElemNodes(1))%List(1:6)) + X_e(7:12) = m%U_full (p%NodesDOF(ElemNodes(2))%List(1:6)) + Xdd_e(1:6) = m%U_full_dotdot(p%NodesDOF(ElemNodes(1))%List(1:6)) + Xdd_e(7:12) = m%U_full_dotdot(p%NodesDOF(ElemNodes(2))%List(1:6)) + if (.not. bUseInputDirCos) then + DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local + endif + CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,JJ),pLst%Ke(:,:,iiNode,JJ), Xdd_e, X_e, pLst%Fg(:,iiNode,JJ), FirstOrSecond, FM_elm, FK_elm) + end subroutine ElementForce + + !==================================================================================================== + !> Calculates static and dynamic forces for a given element, using K and M of the element, and + !output quantities Udotdot and Y2 containing the + !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked + !---------------------------------------------------------------------------------------------------- + SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) + Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) + Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces + Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest + REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments + !Locals + INTEGER(IntKi) :: L !counter + REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage + + FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE + FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE + FF_glb = FF_glb - Fg ! GLOBAL REFERENCE + DO L=1,4 ! Transforming coordinates 3 at a time + FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) + FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) + ENDDO + FM_nod = FM_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) ! k2=1, 1:6, k2=2 7:12 + FK_nod = FF_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) + + END SUBROUTINE CALC_NODE_FORCES +END SUBROUTINE SDOut_MapOutputs + + +!==================================================================================================== +SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) + INTEGER, INTENT( IN ) :: UnSum ! the unit number for the SubDyn summary file + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: Stat ! status from I/) operation + ErrStat = ErrID_None + ErrMsg = "" + ! Write any closing information in the summary file + IF ( UnSum > 0 ) THEN + WRITE (UnSum,'(/,A/)', IOSTAT=Stat) '#This summary file was closed on '//CurDate()//' at '//CurTime()//'.' + IF (Stat /= 0) THEN + ErrStat = ErrID_FATAL + ErrMsg = ' Problem writing to summary file.' + END IF + ! Close the file + CLOSE( UnSum, IOSTAT=Stat ) + IF (Stat /= 0) THEN + ErrStat = ErrID_FATAL + ErrMsg = TRIM(ErrMsg)//' Problem closing summary file.' + END IF + IF ( ErrStat /= ErrID_None ) ErrMsg = 'SDOut_CloseSum'//TRIM(ErrMsg) + END IF +END SUBROUTINE SDOut_CloseSum + +!==================================================================================================== +SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) + INTEGER, INTENT( OUT ) :: UnSum ! the unit number for the SubDyn summary file + CHARACTER(*), INTENT( IN ) :: SummaryName ! the name of the SubDyn summary file + TYPE(ProgDesc), INTENT( IN ) :: SD_Prog ! the name/version/date of the program + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer :: ErrStat2 + ErrStat = ErrID_None + ErrMsg = "" + + CALL GetNewUnit( UnSum ) + CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + ErrMsg = 'Failed to open SubDyn summary file: '//TRIM(ErrMsg) + RETURN + END IF + + ! Write the summary file header + WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) '#This summary file was generated by '//TRIM( SD_Prog%Name )//& + ' '//TRIM( SD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' +END SUBROUTINE SDOut_OpenSum + +!==================================================================================================== +SUBROUTINE SDOut_OpenOutput( ProgVer, OutRootName, p, InitOut, ErrStat, ErrMsg ) +! This subroutine initialized the output module, checking if the output parameter list (OutList) +! contains valid names, and opening the output file if there are any requested outputs +!---------------------------------------------------------------------------------------------------- + ! Passed variables + TYPE(ProgDesc), INTENT( IN ) :: ProgVer + CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file + TYPE(SD_ParameterType), INTENT( INOUT ) :: p + TYPE(SD_InitOutPutType ), INTENT( IN ) :: InitOut ! + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I ! Generic loop counter + CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: ErrStat2 + ErrStat = ErrID_None + ErrMsg = "" + ! Open the output file, if necessary, and write the header + IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + ! Open the file for output + OutFileName = TRIM(OutRootName)//'.out' + CALL GetNewUnit( p%UnJckF ) + + CALL OpenFOutFile ( p%UnJckF, OutFileName, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + ErrMsg = ' Error opening SubDyn-level output file: '//TRIM(ErrMsg) + RETURN + END IF + + ! Write the output file header + WRITE (p%UnJckF,'(/,A/)', IOSTAT=ErrStat2) 'These predictions were generated by '//TRIM(GETNVD(ProgVer))//& + ' on '//CurDate()//' at '//CurTime()//'.' + + WRITE(p%UnJckF, '(//)') ! add 3 lines to make file format consistant with FAST v8 (headers on line 7; units on line 8) [this allows easier post-processing] + + ! Write the names of the output parameters: + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 'Time' ), ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + + ! Write the units of the output parameters: + WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 's'), ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + END IF ! there are any requested outputs +END SUBROUTINE SDOut_OpenOutput + +!==================================================================================================== + + +!==================================================================================================== +SUBROUTINE SDOut_CloseOutput ( p, ErrStat, ErrMsg ) +! This function cleans up after running the SubDyn output module. It closes the output file, +! releases memory, and resets the number of outputs requested to 0. +!---------------------------------------------------------------------------------------------------- + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + LOGICAL :: Err + + ErrStat = 0 + ErrMsg = "" + Err = .FALSE. + + ! Close our output file + CLOSE( p%UnJckF, IOSTAT = ErrStat ) + IF ( ErrStat /= 0 ) Err = .TRUE. + + ! Make sure ErrStat is non-zero if an error occurred + IF ( Err ) ErrStat = ErrID_Fatal + RETURN + +END SUBROUTINE SDOut_CloseOutput +!==================================================================================================== + +SUBROUTINE SDOut_WriteOutputNames( UnJckF, p, ErrStat, ErrMsg ) + + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Name ), ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + +END SUBROUTINE SDOut_WriteOutputNames + +!==================================================================================================== + +SUBROUTINE SDOut_WriteOutputUnits( UnJckF, p, ErrStat, ErrMsg ) + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + CHARACTER(200) :: Frmt ! a string to hold a format statement + INTEGER :: I ! Generic loop counter + ErrStat = ErrID_None + ErrMsg = "" + + Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' + + WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Units ), ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + +END SUBROUTINE SDOut_WriteOutputUnits + +!==================================================================================================== +SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) +! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file +! opened in SDOut_Init() +!---------------------------------------------------------------------------------------------------- + INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file + REAL(DbKi), INTENT( IN ) :: Time ! Time for this output + REAL(ReKi), INTENT( IN ) :: SDWrOutput(:) ! SubDyn module's output data + TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data + INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I ! Generic loop counter + CHARACTER(200) :: Frmt ! a string to hold a format statement + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize ErrStat and determine if it makes any sense to write output + IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnJckF < 0 ) THEN + ErrStat = ErrID_Fatal + ErrMsg = ' To write outputs for SubDyn there must be a valid file ID and OutParam must be allocated.' + RETURN + ELSE + ErrStat = ErrID_None + END IF + + ! Write the output parameters to the file + Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutFmt )//'))' + + WRITE(UnJckF,Frmt) Time, ( p%Delim, SDWrOutput(I), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) + +END SUBROUTINE SDOut_WriteOutputs + +!==================================================================================================== + + +!==================================================================================================== +SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) +! This routine checks the names of inputted output channels, checks to see if any of them are ill- +! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, +! name, and units of the output channels). +! NOTE OutParam is populated here +!---------------------------------------------------------------------------------------------------- + TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module parameter data + CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. + INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables. + INTEGER :: I,J,K ! Generic loop-counting index. + INTEGER :: INDX ! Index for valid arrays + CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). + !CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. + CHARACTER(ChanLen), DIMENSION(24) :: ToTUnits,ToTNames,ToTNames0 + LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration + LOGICAL :: CheckOutListAgain + ErrStat = ErrID_None + ErrMsg = "" + + InvalidOutput = .FALSE. + + ! mark invalid output channels: + DO k=p%nDOFM+1,99 + InvalidOutput(SSqm01 +k-1) = .true. + InvalidOutput(SSqmd01 +k-1) = .true. + InvalidOutput(SSqmdd01+k-1) = .true. + END DO + + DO I=1,9 + !I know el # and whether it is 1st node or second node + if (I <= p%NMOutputs) then + INDX=p%MOutLst(I)%NOutCnt+1 + else + INDX = 1 + end if + + DO J=INDX,9 !Iterate on requested nodes for that member + !Forces and moments + InvalidOutput(MNfmKe (:,J,I)) = .true. !static forces and moments (6) Local Ref + InvalidOutput(MNfmMe (:,J,I)) = .true. !dynamic forces and moments (6) Local Ref + !Displacement + InvalidOutput(MNTDss (:,J,I)) = .true. !Translational + InvalidOutput(MNRDe (:,J,I)) = .true. !Rotational + !Accelerations + InvalidOutput(MNTRAe (:,J,I)) = .true. !translational accel local ref + END DO + END DO + + !------------------------------------------------------------------------------------------------- + ! ALLOCATE the OutParam array + !------------------------------------------------------------------------------------------------- + ALLOCATE ( p%OutParam(1:p%NumOuts+p%OutAllInt*p%OutAllDims) , STAT=ErrStat ) + IF ( ErrStat /= 0 ) THEN + ErrMsg = ' Error allocating memory for the OutParam array.' + ErrStat = ErrID_Fatal + RETURN + END IF + + + !------------------------------------------------------------------------------------------------- + ! Set index, name, and units for the output channels + ! If a selected output channel is not available in this module, set error flag and return. + !------------------------------------------------------------------------------------------------- + !!!p%OutParam(0)%Name = 'Time' ! OutData(0) is the time channel by default. + !!!p%OutParam(0)%Units = '(sec)' ! + !!!p%OutParam(0)%Indx = Time + !!!p%OutParam(0)%SignM = 1 + + DO I = 1,p%NumOuts + + p%OutParam(I)%Name = OutList(I) + OutListTmp = OutList(I) + + + ! Reverse the sign (+/-) of the output channel if the user prefixed the + ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". + + CheckOutListAgain = .FALSE. + + IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN + p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) + CheckOutListAgain = .TRUE. + p%OutParam(I)%SignM = 1 + ELSE + p%OutParam(I)%SignM = 1 + END IF + + CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case + + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + + IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again + p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. + OutListTmp = OutListTmp(2:) + + Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) + END IF + + IF ( Indx > 0 ) THEN + p%OutParam(I)%Indx = ParamIndxAry(Indx) + IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%SignM = 0 + ELSE + p%OutParam(I)%Units = ParamUnitsAry(Indx) + END IF + ELSE + ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' + ErrStat = ErrID_Fatal + p%OutParam(I)%Units = 'INVALID' + p%OutParam(I)%Indx = 0 + p%OutParam(I)%SignM = 0 ! this will print all zeros + END IF + + END DO + + IF (p%OutAll) THEN !Finish populating the OutParam with all the joint forces and moments + ToTNames0=RESHAPE(SPREAD( (/"FKxe", "FKye", "FKze", "MKxe", "MKye", "MKze", "FMxe", "FMye", "FMze", "MMxe", "MMye", "MMze"/), 2, 2), (/24/) ) + ToTUnits=RESHAPE(SPREAD( (/"(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)", "(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)"/), 2, 2), (/24/) ) + DO I=1,p%NMembers + DO K=1,2 + DO J=1,12 + TotNames(J+(K-1)*12)=TRIM("M"//Int2Lstr(I))//TRIM("J"//Int2Lstr(K))//TRIM(TotNames0(J)) + ENDDO + ENDDO + p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Name = ToTNames + p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Units = ToTUnits + ENDDO + p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%SignM = 1 + p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%Indx= MaxOutPts+(/(J, J=1, p%OutAllDims)/) + ENDIF + +END SUBROUTINE SDOut_ChkOutLst +!==================================================================================================== +END MODULE SubDyn_Output diff --git a/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 b/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 new file mode 100644 index 000000000..4844a51f1 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 @@ -0,0 +1,3723 @@ +module SubDyn_Output_Params + use NWTC_Library + + ! Indices for computing output channels: + ! NOTES: + ! (1) These parameters are in the order stored in "OutListParameters.xlsx" + ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter + IMPLICIT NONE + + PUBLIC + + ! Time: + INTEGER, PARAMETER :: Time = 0 + + ! Member Forces: + + INTEGER(IntKi), PARAMETER :: M1N1FKxe = 1 + INTEGER(IntKi), PARAMETER :: M1N2FKxe = 2 + INTEGER(IntKi), PARAMETER :: M1N3FKxe = 3 + INTEGER(IntKi), PARAMETER :: M1N4FKxe = 4 + INTEGER(IntKi), PARAMETER :: M1N5FKxe = 5 + INTEGER(IntKi), PARAMETER :: M1N6FKxe = 6 + INTEGER(IntKi), PARAMETER :: M1N7FKxe = 7 + INTEGER(IntKi), PARAMETER :: M1N8FKxe = 8 + INTEGER(IntKi), PARAMETER :: M1N9FKxe = 9 + INTEGER(IntKi), PARAMETER :: M2N1FKxe = 10 + INTEGER(IntKi), PARAMETER :: M2N2FKxe = 11 + INTEGER(IntKi), PARAMETER :: M2N3FKxe = 12 + INTEGER(IntKi), PARAMETER :: M2N4FKxe = 13 + INTEGER(IntKi), PARAMETER :: M2N5FKxe = 14 + INTEGER(IntKi), PARAMETER :: M2N6FKxe = 15 + INTEGER(IntKi), PARAMETER :: M2N7FKxe = 16 + INTEGER(IntKi), PARAMETER :: M2N8FKxe = 17 + INTEGER(IntKi), PARAMETER :: M2N9FKxe = 18 + INTEGER(IntKi), PARAMETER :: M3N1FKxe = 19 + INTEGER(IntKi), PARAMETER :: M3N2FKxe = 20 + INTEGER(IntKi), PARAMETER :: M3N3FKxe = 21 + INTEGER(IntKi), PARAMETER :: M3N4FKxe = 22 + INTEGER(IntKi), PARAMETER :: M3N5FKxe = 23 + INTEGER(IntKi), PARAMETER :: M3N6FKxe = 24 + INTEGER(IntKi), PARAMETER :: M3N7FKxe = 25 + INTEGER(IntKi), PARAMETER :: M3N8FKxe = 26 + INTEGER(IntKi), PARAMETER :: M3N9FKxe = 27 + INTEGER(IntKi), PARAMETER :: M4N1FKxe = 28 + INTEGER(IntKi), PARAMETER :: M4N2FKxe = 29 + INTEGER(IntKi), PARAMETER :: M4N3FKxe = 30 + INTEGER(IntKi), PARAMETER :: M4N4FKxe = 31 + INTEGER(IntKi), PARAMETER :: M4N5FKxe = 32 + INTEGER(IntKi), PARAMETER :: M4N6FKxe = 33 + INTEGER(IntKi), PARAMETER :: M4N7FKxe = 34 + INTEGER(IntKi), PARAMETER :: M4N8FKxe = 35 + INTEGER(IntKi), PARAMETER :: M4N9FKxe = 36 + INTEGER(IntKi), PARAMETER :: M5N1FKxe = 37 + INTEGER(IntKi), PARAMETER :: M5N2FKxe = 38 + INTEGER(IntKi), PARAMETER :: M5N3FKxe = 39 + INTEGER(IntKi), PARAMETER :: M5N4FKxe = 40 + INTEGER(IntKi), PARAMETER :: M5N5FKxe = 41 + INTEGER(IntKi), PARAMETER :: M5N6FKxe = 42 + INTEGER(IntKi), PARAMETER :: M5N7FKxe = 43 + INTEGER(IntKi), PARAMETER :: M5N8FKxe = 44 + INTEGER(IntKi), PARAMETER :: M5N9FKxe = 45 + INTEGER(IntKi), PARAMETER :: M6N1FKxe = 46 + INTEGER(IntKi), PARAMETER :: M6N2FKxe = 47 + INTEGER(IntKi), PARAMETER :: M6N3FKxe = 48 + INTEGER(IntKi), PARAMETER :: M6N4FKxe = 49 + INTEGER(IntKi), PARAMETER :: M6N5FKxe = 50 + INTEGER(IntKi), PARAMETER :: M6N6FKxe = 51 + INTEGER(IntKi), PARAMETER :: M6N7FKxe = 52 + INTEGER(IntKi), PARAMETER :: M6N8FKxe = 53 + INTEGER(IntKi), PARAMETER :: M6N9FKxe = 54 + INTEGER(IntKi), PARAMETER :: M7N1FKxe = 55 + INTEGER(IntKi), PARAMETER :: M7N2FKxe = 56 + INTEGER(IntKi), PARAMETER :: M7N3FKxe = 57 + INTEGER(IntKi), PARAMETER :: M7N4FKxe = 58 + INTEGER(IntKi), PARAMETER :: M7N5FKxe = 59 + INTEGER(IntKi), PARAMETER :: M7N6FKxe = 60 + INTEGER(IntKi), PARAMETER :: M7N7FKxe = 61 + INTEGER(IntKi), PARAMETER :: M7N8FKxe = 62 + INTEGER(IntKi), PARAMETER :: M7N9FKxe = 63 + INTEGER(IntKi), PARAMETER :: M8N1FKxe = 64 + INTEGER(IntKi), PARAMETER :: M8N2FKxe = 65 + INTEGER(IntKi), PARAMETER :: M8N3FKxe = 66 + INTEGER(IntKi), PARAMETER :: M8N4FKxe = 67 + INTEGER(IntKi), PARAMETER :: M8N5FKxe = 68 + INTEGER(IntKi), PARAMETER :: M8N6FKxe = 69 + INTEGER(IntKi), PARAMETER :: M8N7FKxe = 70 + INTEGER(IntKi), PARAMETER :: M8N8FKxe = 71 + INTEGER(IntKi), PARAMETER :: M8N9FKxe = 72 + INTEGER(IntKi), PARAMETER :: M9N1FKxe = 73 + INTEGER(IntKi), PARAMETER :: M9N2FKxe = 74 + INTEGER(IntKi), PARAMETER :: M9N3FKxe = 75 + INTEGER(IntKi), PARAMETER :: M9N4FKxe = 76 + INTEGER(IntKi), PARAMETER :: M9N5FKxe = 77 + INTEGER(IntKi), PARAMETER :: M9N6FKxe = 78 + INTEGER(IntKi), PARAMETER :: M9N7FKxe = 79 + INTEGER(IntKi), PARAMETER :: M9N8FKxe = 80 + INTEGER(IntKi), PARAMETER :: M9N9FKxe = 81 + INTEGER(IntKi), PARAMETER :: M1N1FKye = 82 + INTEGER(IntKi), PARAMETER :: M1N2FKye = 83 + INTEGER(IntKi), PARAMETER :: M1N3FKye = 84 + INTEGER(IntKi), PARAMETER :: M1N4FKye = 85 + INTEGER(IntKi), PARAMETER :: M1N5FKye = 86 + INTEGER(IntKi), PARAMETER :: M1N6FKye = 87 + INTEGER(IntKi), PARAMETER :: M1N7FKye = 88 + INTEGER(IntKi), PARAMETER :: M1N8FKye = 89 + INTEGER(IntKi), PARAMETER :: M1N9FKye = 90 + INTEGER(IntKi), PARAMETER :: M2N1FKye = 91 + INTEGER(IntKi), PARAMETER :: M2N2FKye = 92 + INTEGER(IntKi), PARAMETER :: M2N3FKye = 93 + INTEGER(IntKi), PARAMETER :: M2N4FKye = 94 + INTEGER(IntKi), PARAMETER :: M2N5FKye = 95 + INTEGER(IntKi), PARAMETER :: M2N6FKye = 96 + INTEGER(IntKi), PARAMETER :: M2N7FKye = 97 + INTEGER(IntKi), PARAMETER :: M2N8FKye = 98 + INTEGER(IntKi), PARAMETER :: M2N9FKye = 99 + INTEGER(IntKi), PARAMETER :: M3N1FKye = 100 + INTEGER(IntKi), PARAMETER :: M3N2FKye = 101 + INTEGER(IntKi), PARAMETER :: M3N3FKye = 102 + INTEGER(IntKi), PARAMETER :: M3N4FKye = 103 + INTEGER(IntKi), PARAMETER :: M3N5FKye = 104 + INTEGER(IntKi), PARAMETER :: M3N6FKye = 105 + INTEGER(IntKi), PARAMETER :: M3N7FKye = 106 + INTEGER(IntKi), PARAMETER :: M3N8FKye = 107 + INTEGER(IntKi), PARAMETER :: M3N9FKye = 108 + INTEGER(IntKi), PARAMETER :: M4N1FKye = 109 + INTEGER(IntKi), PARAMETER :: M4N2FKye = 110 + INTEGER(IntKi), PARAMETER :: M4N3FKye = 111 + INTEGER(IntKi), PARAMETER :: M4N4FKye = 112 + INTEGER(IntKi), PARAMETER :: M4N5FKye = 113 + INTEGER(IntKi), PARAMETER :: M4N6FKye = 114 + INTEGER(IntKi), PARAMETER :: M4N7FKye = 115 + INTEGER(IntKi), PARAMETER :: M4N8FKye = 116 + INTEGER(IntKi), PARAMETER :: M4N9FKye = 117 + INTEGER(IntKi), PARAMETER :: M5N1FKye = 118 + INTEGER(IntKi), PARAMETER :: M5N2FKye = 119 + INTEGER(IntKi), PARAMETER :: M5N3FKye = 120 + INTEGER(IntKi), PARAMETER :: M5N4FKye = 121 + INTEGER(IntKi), PARAMETER :: M5N5FKye = 122 + INTEGER(IntKi), PARAMETER :: M5N6FKye = 123 + INTEGER(IntKi), PARAMETER :: M5N7FKye = 124 + INTEGER(IntKi), PARAMETER :: M5N8FKye = 125 + INTEGER(IntKi), PARAMETER :: M5N9FKye = 126 + INTEGER(IntKi), PARAMETER :: M6N1FKye = 127 + INTEGER(IntKi), PARAMETER :: M6N2FKye = 128 + INTEGER(IntKi), PARAMETER :: M6N3FKye = 129 + INTEGER(IntKi), PARAMETER :: M6N4FKye = 130 + INTEGER(IntKi), PARAMETER :: M6N5FKye = 131 + INTEGER(IntKi), PARAMETER :: M6N6FKye = 132 + INTEGER(IntKi), PARAMETER :: M6N7FKye = 133 + INTEGER(IntKi), PARAMETER :: M6N8FKye = 134 + INTEGER(IntKi), PARAMETER :: M6N9FKye = 135 + INTEGER(IntKi), PARAMETER :: M7N1FKye = 136 + INTEGER(IntKi), PARAMETER :: M7N2FKye = 137 + INTEGER(IntKi), PARAMETER :: M7N3FKye = 138 + INTEGER(IntKi), PARAMETER :: M7N4FKye = 139 + INTEGER(IntKi), PARAMETER :: M7N5FKye = 140 + INTEGER(IntKi), PARAMETER :: M7N6FKye = 141 + INTEGER(IntKi), PARAMETER :: M7N7FKye = 142 + INTEGER(IntKi), PARAMETER :: M7N8FKye = 143 + INTEGER(IntKi), PARAMETER :: M7N9FKye = 144 + INTEGER(IntKi), PARAMETER :: M8N1FKye = 145 + INTEGER(IntKi), PARAMETER :: M8N2FKye = 146 + INTEGER(IntKi), PARAMETER :: M8N3FKye = 147 + INTEGER(IntKi), PARAMETER :: M8N4FKye = 148 + INTEGER(IntKi), PARAMETER :: M8N5FKye = 149 + INTEGER(IntKi), PARAMETER :: M8N6FKye = 150 + INTEGER(IntKi), PARAMETER :: M8N7FKye = 151 + INTEGER(IntKi), PARAMETER :: M8N8FKye = 152 + INTEGER(IntKi), PARAMETER :: M8N9FKye = 153 + INTEGER(IntKi), PARAMETER :: M9N1FKye = 154 + INTEGER(IntKi), PARAMETER :: M9N2FKye = 155 + INTEGER(IntKi), PARAMETER :: M9N3FKye = 156 + INTEGER(IntKi), PARAMETER :: M9N4FKye = 157 + INTEGER(IntKi), PARAMETER :: M9N5FKye = 158 + INTEGER(IntKi), PARAMETER :: M9N6FKye = 159 + INTEGER(IntKi), PARAMETER :: M9N7FKye = 160 + INTEGER(IntKi), PARAMETER :: M9N8FKye = 161 + INTEGER(IntKi), PARAMETER :: M9N9FKye = 162 + INTEGER(IntKi), PARAMETER :: M1N1FKze = 163 + INTEGER(IntKi), PARAMETER :: M1N2FKze = 164 + INTEGER(IntKi), PARAMETER :: M1N3FKze = 165 + INTEGER(IntKi), PARAMETER :: M1N4FKze = 166 + INTEGER(IntKi), PARAMETER :: M1N5FKze = 167 + INTEGER(IntKi), PARAMETER :: M1N6FKze = 168 + INTEGER(IntKi), PARAMETER :: M1N7FKze = 169 + INTEGER(IntKi), PARAMETER :: M1N8FKze = 170 + INTEGER(IntKi), PARAMETER :: M1N9FKze = 171 + INTEGER(IntKi), PARAMETER :: M2N1FKze = 172 + INTEGER(IntKi), PARAMETER :: M2N2FKze = 173 + INTEGER(IntKi), PARAMETER :: M2N3FKze = 174 + INTEGER(IntKi), PARAMETER :: M2N4FKze = 175 + INTEGER(IntKi), PARAMETER :: M2N5FKze = 176 + INTEGER(IntKi), PARAMETER :: M2N6FKze = 177 + INTEGER(IntKi), PARAMETER :: M2N7FKze = 178 + INTEGER(IntKi), PARAMETER :: M2N8FKze = 179 + INTEGER(IntKi), PARAMETER :: M2N9FKze = 180 + INTEGER(IntKi), PARAMETER :: M3N1FKze = 181 + INTEGER(IntKi), PARAMETER :: M3N2FKze = 182 + INTEGER(IntKi), PARAMETER :: M3N3FKze = 183 + INTEGER(IntKi), PARAMETER :: M3N4FKze = 184 + INTEGER(IntKi), PARAMETER :: M3N5FKze = 185 + INTEGER(IntKi), PARAMETER :: M3N6FKze = 186 + INTEGER(IntKi), PARAMETER :: M3N7FKze = 187 + INTEGER(IntKi), PARAMETER :: M3N8FKze = 188 + INTEGER(IntKi), PARAMETER :: M3N9FKze = 189 + INTEGER(IntKi), PARAMETER :: M4N1FKze = 190 + INTEGER(IntKi), PARAMETER :: M4N2FKze = 191 + INTEGER(IntKi), PARAMETER :: M4N3FKze = 192 + INTEGER(IntKi), PARAMETER :: M4N4FKze = 193 + INTEGER(IntKi), PARAMETER :: M4N5FKze = 194 + INTEGER(IntKi), PARAMETER :: M4N6FKze = 195 + INTEGER(IntKi), PARAMETER :: M4N7FKze = 196 + INTEGER(IntKi), PARAMETER :: M4N8FKze = 197 + INTEGER(IntKi), PARAMETER :: M4N9FKze = 198 + INTEGER(IntKi), PARAMETER :: M5N1FKze = 199 + INTEGER(IntKi), PARAMETER :: M5N2FKze = 200 + INTEGER(IntKi), PARAMETER :: M5N3FKze = 201 + INTEGER(IntKi), PARAMETER :: M5N4FKze = 202 + INTEGER(IntKi), PARAMETER :: M5N5FKze = 203 + INTEGER(IntKi), PARAMETER :: M5N6FKze = 204 + INTEGER(IntKi), PARAMETER :: M5N7FKze = 205 + INTEGER(IntKi), PARAMETER :: M5N8FKze = 206 + INTEGER(IntKi), PARAMETER :: M5N9FKze = 207 + INTEGER(IntKi), PARAMETER :: M6N1FKze = 208 + INTEGER(IntKi), PARAMETER :: M6N2FKze = 209 + INTEGER(IntKi), PARAMETER :: M6N3FKze = 210 + INTEGER(IntKi), PARAMETER :: M6N4FKze = 211 + INTEGER(IntKi), PARAMETER :: M6N5FKze = 212 + INTEGER(IntKi), PARAMETER :: M6N6FKze = 213 + INTEGER(IntKi), PARAMETER :: M6N7FKze = 214 + INTEGER(IntKi), PARAMETER :: M6N8FKze = 215 + INTEGER(IntKi), PARAMETER :: M6N9FKze = 216 + INTEGER(IntKi), PARAMETER :: M7N1FKze = 217 + INTEGER(IntKi), PARAMETER :: M7N2FKze = 218 + INTEGER(IntKi), PARAMETER :: M7N3FKze = 219 + INTEGER(IntKi), PARAMETER :: M7N4FKze = 220 + INTEGER(IntKi), PARAMETER :: M7N5FKze = 221 + INTEGER(IntKi), PARAMETER :: M7N6FKze = 222 + INTEGER(IntKi), PARAMETER :: M7N7FKze = 223 + INTEGER(IntKi), PARAMETER :: M7N8FKze = 224 + INTEGER(IntKi), PARAMETER :: M7N9FKze = 225 + INTEGER(IntKi), PARAMETER :: M8N1FKze = 226 + INTEGER(IntKi), PARAMETER :: M8N2FKze = 227 + INTEGER(IntKi), PARAMETER :: M8N3FKze = 228 + INTEGER(IntKi), PARAMETER :: M8N4FKze = 229 + INTEGER(IntKi), PARAMETER :: M8N5FKze = 230 + INTEGER(IntKi), PARAMETER :: M8N6FKze = 231 + INTEGER(IntKi), PARAMETER :: M8N7FKze = 232 + INTEGER(IntKi), PARAMETER :: M8N8FKze = 233 + INTEGER(IntKi), PARAMETER :: M8N9FKze = 234 + INTEGER(IntKi), PARAMETER :: M9N1FKze = 235 + INTEGER(IntKi), PARAMETER :: M9N2FKze = 236 + INTEGER(IntKi), PARAMETER :: M9N3FKze = 237 + INTEGER(IntKi), PARAMETER :: M9N4FKze = 238 + INTEGER(IntKi), PARAMETER :: M9N5FKze = 239 + INTEGER(IntKi), PARAMETER :: M9N6FKze = 240 + INTEGER(IntKi), PARAMETER :: M9N7FKze = 241 + INTEGER(IntKi), PARAMETER :: M9N8FKze = 242 + INTEGER(IntKi), PARAMETER :: M9N9FKze = 243 + INTEGER(IntKi), PARAMETER :: M1N1FMxe = 244 + INTEGER(IntKi), PARAMETER :: M1N2FMxe = 245 + INTEGER(IntKi), PARAMETER :: M1N3FMxe = 246 + INTEGER(IntKi), PARAMETER :: M1N4FMxe = 247 + INTEGER(IntKi), PARAMETER :: M1N5FMxe = 248 + INTEGER(IntKi), PARAMETER :: M1N6FMxe = 249 + INTEGER(IntKi), PARAMETER :: M1N7FMxe = 250 + INTEGER(IntKi), PARAMETER :: M1N8FMxe = 251 + INTEGER(IntKi), PARAMETER :: M1N9FMxe = 252 + INTEGER(IntKi), PARAMETER :: M2N1FMxe = 253 + INTEGER(IntKi), PARAMETER :: M2N2FMxe = 254 + INTEGER(IntKi), PARAMETER :: M2N3FMxe = 255 + INTEGER(IntKi), PARAMETER :: M2N4FMxe = 256 + INTEGER(IntKi), PARAMETER :: M2N5FMxe = 257 + INTEGER(IntKi), PARAMETER :: M2N6FMxe = 258 + INTEGER(IntKi), PARAMETER :: M2N7FMxe = 259 + INTEGER(IntKi), PARAMETER :: M2N8FMxe = 260 + INTEGER(IntKi), PARAMETER :: M2N9FMxe = 261 + INTEGER(IntKi), PARAMETER :: M3N1FMxe = 262 + INTEGER(IntKi), PARAMETER :: M3N2FMxe = 263 + INTEGER(IntKi), PARAMETER :: M3N3FMxe = 264 + INTEGER(IntKi), PARAMETER :: M3N4FMxe = 265 + INTEGER(IntKi), PARAMETER :: M3N5FMxe = 266 + INTEGER(IntKi), PARAMETER :: M3N6FMxe = 267 + INTEGER(IntKi), PARAMETER :: M3N7FMxe = 268 + INTEGER(IntKi), PARAMETER :: M3N8FMxe = 269 + INTEGER(IntKi), PARAMETER :: M3N9FMxe = 270 + INTEGER(IntKi), PARAMETER :: M4N1FMxe = 271 + INTEGER(IntKi), PARAMETER :: M4N2FMxe = 272 + INTEGER(IntKi), PARAMETER :: M4N3FMxe = 273 + INTEGER(IntKi), PARAMETER :: M4N4FMxe = 274 + INTEGER(IntKi), PARAMETER :: M4N5FMxe = 275 + INTEGER(IntKi), PARAMETER :: M4N6FMxe = 276 + INTEGER(IntKi), PARAMETER :: M4N7FMxe = 277 + INTEGER(IntKi), PARAMETER :: M4N8FMxe = 278 + INTEGER(IntKi), PARAMETER :: M4N9FMxe = 279 + INTEGER(IntKi), PARAMETER :: M5N1FMxe = 280 + INTEGER(IntKi), PARAMETER :: M5N2FMxe = 281 + INTEGER(IntKi), PARAMETER :: M5N3FMxe = 282 + INTEGER(IntKi), PARAMETER :: M5N4FMxe = 283 + INTEGER(IntKi), PARAMETER :: M5N5FMxe = 284 + INTEGER(IntKi), PARAMETER :: M5N6FMxe = 285 + INTEGER(IntKi), PARAMETER :: M5N7FMxe = 286 + INTEGER(IntKi), PARAMETER :: M5N8FMxe = 287 + INTEGER(IntKi), PARAMETER :: M5N9FMxe = 288 + INTEGER(IntKi), PARAMETER :: M6N1FMxe = 289 + INTEGER(IntKi), PARAMETER :: M6N2FMxe = 290 + INTEGER(IntKi), PARAMETER :: M6N3FMxe = 291 + INTEGER(IntKi), PARAMETER :: M6N4FMxe = 292 + INTEGER(IntKi), PARAMETER :: M6N5FMxe = 293 + INTEGER(IntKi), PARAMETER :: M6N6FMxe = 294 + INTEGER(IntKi), PARAMETER :: M6N7FMxe = 295 + INTEGER(IntKi), PARAMETER :: M6N8FMxe = 296 + INTEGER(IntKi), PARAMETER :: M6N9FMxe = 297 + INTEGER(IntKi), PARAMETER :: M7N1FMxe = 298 + INTEGER(IntKi), PARAMETER :: M7N2FMxe = 299 + INTEGER(IntKi), PARAMETER :: M7N3FMxe = 300 + INTEGER(IntKi), PARAMETER :: M7N4FMxe = 301 + INTEGER(IntKi), PARAMETER :: M7N5FMxe = 302 + INTEGER(IntKi), PARAMETER :: M7N6FMxe = 303 + INTEGER(IntKi), PARAMETER :: M7N7FMxe = 304 + INTEGER(IntKi), PARAMETER :: M7N8FMxe = 305 + INTEGER(IntKi), PARAMETER :: M7N9FMxe = 306 + INTEGER(IntKi), PARAMETER :: M8N1FMxe = 307 + INTEGER(IntKi), PARAMETER :: M8N2FMxe = 308 + INTEGER(IntKi), PARAMETER :: M8N3FMxe = 309 + INTEGER(IntKi), PARAMETER :: M8N4FMxe = 310 + INTEGER(IntKi), PARAMETER :: M8N5FMxe = 311 + INTEGER(IntKi), PARAMETER :: M8N6FMxe = 312 + INTEGER(IntKi), PARAMETER :: M8N7FMxe = 313 + INTEGER(IntKi), PARAMETER :: M8N8FMxe = 314 + INTEGER(IntKi), PARAMETER :: M8N9FMxe = 315 + INTEGER(IntKi), PARAMETER :: M9N1FMxe = 316 + INTEGER(IntKi), PARAMETER :: M9N2FMxe = 317 + INTEGER(IntKi), PARAMETER :: M9N3FMxe = 318 + INTEGER(IntKi), PARAMETER :: M9N4FMxe = 319 + INTEGER(IntKi), PARAMETER :: M9N5FMxe = 320 + INTEGER(IntKi), PARAMETER :: M9N6FMxe = 321 + INTEGER(IntKi), PARAMETER :: M9N7FMxe = 322 + INTEGER(IntKi), PARAMETER :: M9N8FMxe = 323 + INTEGER(IntKi), PARAMETER :: M9N9FMxe = 324 + INTEGER(IntKi), PARAMETER :: M1N1FMye = 325 + INTEGER(IntKi), PARAMETER :: M1N2FMye = 326 + INTEGER(IntKi), PARAMETER :: M1N3FMye = 327 + INTEGER(IntKi), PARAMETER :: M1N4FMye = 328 + INTEGER(IntKi), PARAMETER :: M1N5FMye = 329 + INTEGER(IntKi), PARAMETER :: M1N6FMye = 330 + INTEGER(IntKi), PARAMETER :: M1N7FMye = 331 + INTEGER(IntKi), PARAMETER :: M1N8FMye = 332 + INTEGER(IntKi), PARAMETER :: M1N9FMye = 333 + INTEGER(IntKi), PARAMETER :: M2N1FMye = 334 + INTEGER(IntKi), PARAMETER :: M2N2FMye = 335 + INTEGER(IntKi), PARAMETER :: M2N3FMye = 336 + INTEGER(IntKi), PARAMETER :: M2N4FMye = 337 + INTEGER(IntKi), PARAMETER :: M2N5FMye = 338 + INTEGER(IntKi), PARAMETER :: M2N6FMye = 339 + INTEGER(IntKi), PARAMETER :: M2N7FMye = 340 + INTEGER(IntKi), PARAMETER :: M2N8FMye = 341 + INTEGER(IntKi), PARAMETER :: M2N9FMye = 342 + INTEGER(IntKi), PARAMETER :: M3N1FMye = 343 + INTEGER(IntKi), PARAMETER :: M3N2FMye = 344 + INTEGER(IntKi), PARAMETER :: M3N3FMye = 345 + INTEGER(IntKi), PARAMETER :: M3N4FMye = 346 + INTEGER(IntKi), PARAMETER :: M3N5FMye = 347 + INTEGER(IntKi), PARAMETER :: M3N6FMye = 348 + INTEGER(IntKi), PARAMETER :: M3N7FMye = 349 + INTEGER(IntKi), PARAMETER :: M3N8FMye = 350 + INTEGER(IntKi), PARAMETER :: M3N9FMye = 351 + INTEGER(IntKi), PARAMETER :: M4N1FMye = 352 + INTEGER(IntKi), PARAMETER :: M4N2FMye = 353 + INTEGER(IntKi), PARAMETER :: M4N3FMye = 354 + INTEGER(IntKi), PARAMETER :: M4N4FMye = 355 + INTEGER(IntKi), PARAMETER :: M4N5FMye = 356 + INTEGER(IntKi), PARAMETER :: M4N6FMye = 357 + INTEGER(IntKi), PARAMETER :: M4N7FMye = 358 + INTEGER(IntKi), PARAMETER :: M4N8FMye = 359 + INTEGER(IntKi), PARAMETER :: M4N9FMye = 360 + INTEGER(IntKi), PARAMETER :: M5N1FMye = 361 + INTEGER(IntKi), PARAMETER :: M5N2FMye = 362 + INTEGER(IntKi), PARAMETER :: M5N3FMye = 363 + INTEGER(IntKi), PARAMETER :: M5N4FMye = 364 + INTEGER(IntKi), PARAMETER :: M5N5FMye = 365 + INTEGER(IntKi), PARAMETER :: M5N6FMye = 366 + INTEGER(IntKi), PARAMETER :: M5N7FMye = 367 + INTEGER(IntKi), PARAMETER :: M5N8FMye = 368 + INTEGER(IntKi), PARAMETER :: M5N9FMye = 369 + INTEGER(IntKi), PARAMETER :: M6N1FMye = 370 + INTEGER(IntKi), PARAMETER :: M6N2FMye = 371 + INTEGER(IntKi), PARAMETER :: M6N3FMye = 372 + INTEGER(IntKi), PARAMETER :: M6N4FMye = 373 + INTEGER(IntKi), PARAMETER :: M6N5FMye = 374 + INTEGER(IntKi), PARAMETER :: M6N6FMye = 375 + INTEGER(IntKi), PARAMETER :: M6N7FMye = 376 + INTEGER(IntKi), PARAMETER :: M6N8FMye = 377 + INTEGER(IntKi), PARAMETER :: M6N9FMye = 378 + INTEGER(IntKi), PARAMETER :: M7N1FMye = 379 + INTEGER(IntKi), PARAMETER :: M7N2FMye = 380 + INTEGER(IntKi), PARAMETER :: M7N3FMye = 381 + INTEGER(IntKi), PARAMETER :: M7N4FMye = 382 + INTEGER(IntKi), PARAMETER :: M7N5FMye = 383 + INTEGER(IntKi), PARAMETER :: M7N6FMye = 384 + INTEGER(IntKi), PARAMETER :: M7N7FMye = 385 + INTEGER(IntKi), PARAMETER :: M7N8FMye = 386 + INTEGER(IntKi), PARAMETER :: M7N9FMye = 387 + INTEGER(IntKi), PARAMETER :: M8N1FMye = 388 + INTEGER(IntKi), PARAMETER :: M8N2FMye = 389 + INTEGER(IntKi), PARAMETER :: M8N3FMye = 390 + INTEGER(IntKi), PARAMETER :: M8N4FMye = 391 + INTEGER(IntKi), PARAMETER :: M8N5FMye = 392 + INTEGER(IntKi), PARAMETER :: M8N6FMye = 393 + INTEGER(IntKi), PARAMETER :: M8N7FMye = 394 + INTEGER(IntKi), PARAMETER :: M8N8FMye = 395 + INTEGER(IntKi), PARAMETER :: M8N9FMye = 396 + INTEGER(IntKi), PARAMETER :: M9N1FMye = 397 + INTEGER(IntKi), PARAMETER :: M9N2FMye = 398 + INTEGER(IntKi), PARAMETER :: M9N3FMye = 399 + INTEGER(IntKi), PARAMETER :: M9N4FMye = 400 + INTEGER(IntKi), PARAMETER :: M9N5FMye = 401 + INTEGER(IntKi), PARAMETER :: M9N6FMye = 402 + INTEGER(IntKi), PARAMETER :: M9N7FMye = 403 + INTEGER(IntKi), PARAMETER :: M9N8FMye = 404 + INTEGER(IntKi), PARAMETER :: M9N9FMye = 405 + INTEGER(IntKi), PARAMETER :: M1N1FMze = 406 + INTEGER(IntKi), PARAMETER :: M1N2FMze = 407 + INTEGER(IntKi), PARAMETER :: M1N3FMze = 408 + INTEGER(IntKi), PARAMETER :: M1N4FMze = 409 + INTEGER(IntKi), PARAMETER :: M1N5FMze = 410 + INTEGER(IntKi), PARAMETER :: M1N6FMze = 411 + INTEGER(IntKi), PARAMETER :: M1N7FMze = 412 + INTEGER(IntKi), PARAMETER :: M1N8FMze = 413 + INTEGER(IntKi), PARAMETER :: M1N9FMze = 414 + INTEGER(IntKi), PARAMETER :: M2N1FMze = 415 + INTEGER(IntKi), PARAMETER :: M2N2FMze = 416 + INTEGER(IntKi), PARAMETER :: M2N3FMze = 417 + INTEGER(IntKi), PARAMETER :: M2N4FMze = 418 + INTEGER(IntKi), PARAMETER :: M2N5FMze = 419 + INTEGER(IntKi), PARAMETER :: M2N6FMze = 420 + INTEGER(IntKi), PARAMETER :: M2N7FMze = 421 + INTEGER(IntKi), PARAMETER :: M2N8FMze = 422 + INTEGER(IntKi), PARAMETER :: M2N9FMze = 423 + INTEGER(IntKi), PARAMETER :: M3N1FMze = 424 + INTEGER(IntKi), PARAMETER :: M3N2FMze = 425 + INTEGER(IntKi), PARAMETER :: M3N3FMze = 426 + INTEGER(IntKi), PARAMETER :: M3N4FMze = 427 + INTEGER(IntKi), PARAMETER :: M3N5FMze = 428 + INTEGER(IntKi), PARAMETER :: M3N6FMze = 429 + INTEGER(IntKi), PARAMETER :: M3N7FMze = 430 + INTEGER(IntKi), PARAMETER :: M3N8FMze = 431 + INTEGER(IntKi), PARAMETER :: M3N9FMze = 432 + INTEGER(IntKi), PARAMETER :: M4N1FMze = 433 + INTEGER(IntKi), PARAMETER :: M4N2FMze = 434 + INTEGER(IntKi), PARAMETER :: M4N3FMze = 435 + INTEGER(IntKi), PARAMETER :: M4N4FMze = 436 + INTEGER(IntKi), PARAMETER :: M4N5FMze = 437 + INTEGER(IntKi), PARAMETER :: M4N6FMze = 438 + INTEGER(IntKi), PARAMETER :: M4N7FMze = 439 + INTEGER(IntKi), PARAMETER :: M4N8FMze = 440 + INTEGER(IntKi), PARAMETER :: M4N9FMze = 441 + INTEGER(IntKi), PARAMETER :: M5N1FMze = 442 + INTEGER(IntKi), PARAMETER :: M5N2FMze = 443 + INTEGER(IntKi), PARAMETER :: M5N3FMze = 444 + INTEGER(IntKi), PARAMETER :: M5N4FMze = 445 + INTEGER(IntKi), PARAMETER :: M5N5FMze = 446 + INTEGER(IntKi), PARAMETER :: M5N6FMze = 447 + INTEGER(IntKi), PARAMETER :: M5N7FMze = 448 + INTEGER(IntKi), PARAMETER :: M5N8FMze = 449 + INTEGER(IntKi), PARAMETER :: M5N9FMze = 450 + INTEGER(IntKi), PARAMETER :: M6N1FMze = 451 + INTEGER(IntKi), PARAMETER :: M6N2FMze = 452 + INTEGER(IntKi), PARAMETER :: M6N3FMze = 453 + INTEGER(IntKi), PARAMETER :: M6N4FMze = 454 + INTEGER(IntKi), PARAMETER :: M6N5FMze = 455 + INTEGER(IntKi), PARAMETER :: M6N6FMze = 456 + INTEGER(IntKi), PARAMETER :: M6N7FMze = 457 + INTEGER(IntKi), PARAMETER :: M6N8FMze = 458 + INTEGER(IntKi), PARAMETER :: M6N9FMze = 459 + INTEGER(IntKi), PARAMETER :: M7N1FMze = 460 + INTEGER(IntKi), PARAMETER :: M7N2FMze = 461 + INTEGER(IntKi), PARAMETER :: M7N3FMze = 462 + INTEGER(IntKi), PARAMETER :: M7N4FMze = 463 + INTEGER(IntKi), PARAMETER :: M7N5FMze = 464 + INTEGER(IntKi), PARAMETER :: M7N6FMze = 465 + INTEGER(IntKi), PARAMETER :: M7N7FMze = 466 + INTEGER(IntKi), PARAMETER :: M7N8FMze = 467 + INTEGER(IntKi), PARAMETER :: M7N9FMze = 468 + INTEGER(IntKi), PARAMETER :: M8N1FMze = 469 + INTEGER(IntKi), PARAMETER :: M8N2FMze = 470 + INTEGER(IntKi), PARAMETER :: M8N3FMze = 471 + INTEGER(IntKi), PARAMETER :: M8N4FMze = 472 + INTEGER(IntKi), PARAMETER :: M8N5FMze = 473 + INTEGER(IntKi), PARAMETER :: M8N6FMze = 474 + INTEGER(IntKi), PARAMETER :: M8N7FMze = 475 + INTEGER(IntKi), PARAMETER :: M8N8FMze = 476 + INTEGER(IntKi), PARAMETER :: M8N9FMze = 477 + INTEGER(IntKi), PARAMETER :: M9N1FMze = 478 + INTEGER(IntKi), PARAMETER :: M9N2FMze = 479 + INTEGER(IntKi), PARAMETER :: M9N3FMze = 480 + INTEGER(IntKi), PARAMETER :: M9N4FMze = 481 + INTEGER(IntKi), PARAMETER :: M9N5FMze = 482 + INTEGER(IntKi), PARAMETER :: M9N6FMze = 483 + INTEGER(IntKi), PARAMETER :: M9N7FMze = 484 + INTEGER(IntKi), PARAMETER :: M9N8FMze = 485 + INTEGER(IntKi), PARAMETER :: M9N9FMze = 486 + INTEGER(IntKi), PARAMETER :: M1N1MKxe = 487 + INTEGER(IntKi), PARAMETER :: M1N2MKxe = 488 + INTEGER(IntKi), PARAMETER :: M1N3MKxe = 489 + INTEGER(IntKi), PARAMETER :: M1N4MKxe = 490 + INTEGER(IntKi), PARAMETER :: M1N5MKxe = 491 + INTEGER(IntKi), PARAMETER :: M1N6MKxe = 492 + INTEGER(IntKi), PARAMETER :: M1N7MKxe = 493 + INTEGER(IntKi), PARAMETER :: M1N8MKxe = 494 + INTEGER(IntKi), PARAMETER :: M1N9MKxe = 495 + INTEGER(IntKi), PARAMETER :: M2N1MKxe = 496 + INTEGER(IntKi), PARAMETER :: M2N2MKxe = 497 + INTEGER(IntKi), PARAMETER :: M2N3MKxe = 498 + INTEGER(IntKi), PARAMETER :: M2N4MKxe = 499 + INTEGER(IntKi), PARAMETER :: M2N5MKxe = 500 + INTEGER(IntKi), PARAMETER :: M2N6MKxe = 501 + INTEGER(IntKi), PARAMETER :: M2N7MKxe = 502 + INTEGER(IntKi), PARAMETER :: M2N8MKxe = 503 + INTEGER(IntKi), PARAMETER :: M2N9MKxe = 504 + INTEGER(IntKi), PARAMETER :: M3N1MKxe = 505 + INTEGER(IntKi), PARAMETER :: M3N2MKxe = 506 + INTEGER(IntKi), PARAMETER :: M3N3MKxe = 507 + INTEGER(IntKi), PARAMETER :: M3N4MKxe = 508 + INTEGER(IntKi), PARAMETER :: M3N5MKxe = 509 + INTEGER(IntKi), PARAMETER :: M3N6MKxe = 510 + INTEGER(IntKi), PARAMETER :: M3N7MKxe = 511 + INTEGER(IntKi), PARAMETER :: M3N8MKxe = 512 + INTEGER(IntKi), PARAMETER :: M3N9MKxe = 513 + INTEGER(IntKi), PARAMETER :: M4N1MKxe = 514 + INTEGER(IntKi), PARAMETER :: M4N2MKxe = 515 + INTEGER(IntKi), PARAMETER :: M4N3MKxe = 516 + INTEGER(IntKi), PARAMETER :: M4N4MKxe = 517 + INTEGER(IntKi), PARAMETER :: M4N5MKxe = 518 + INTEGER(IntKi), PARAMETER :: M4N6MKxe = 519 + INTEGER(IntKi), PARAMETER :: M4N7MKxe = 520 + INTEGER(IntKi), PARAMETER :: M4N8MKxe = 521 + INTEGER(IntKi), PARAMETER :: M4N9MKxe = 522 + INTEGER(IntKi), PARAMETER :: M5N1MKxe = 523 + INTEGER(IntKi), PARAMETER :: M5N2MKxe = 524 + INTEGER(IntKi), PARAMETER :: M5N3MKxe = 525 + INTEGER(IntKi), PARAMETER :: M5N4MKxe = 526 + INTEGER(IntKi), PARAMETER :: M5N5MKxe = 527 + INTEGER(IntKi), PARAMETER :: M5N6MKxe = 528 + INTEGER(IntKi), PARAMETER :: M5N7MKxe = 529 + INTEGER(IntKi), PARAMETER :: M5N8MKxe = 530 + INTEGER(IntKi), PARAMETER :: M5N9MKxe = 531 + INTEGER(IntKi), PARAMETER :: M6N1MKxe = 532 + INTEGER(IntKi), PARAMETER :: M6N2MKxe = 533 + INTEGER(IntKi), PARAMETER :: M6N3MKxe = 534 + INTEGER(IntKi), PARAMETER :: M6N4MKxe = 535 + INTEGER(IntKi), PARAMETER :: M6N5MKxe = 536 + INTEGER(IntKi), PARAMETER :: M6N6MKxe = 537 + INTEGER(IntKi), PARAMETER :: M6N7MKxe = 538 + INTEGER(IntKi), PARAMETER :: M6N8MKxe = 539 + INTEGER(IntKi), PARAMETER :: M6N9MKxe = 540 + INTEGER(IntKi), PARAMETER :: M7N1MKxe = 541 + INTEGER(IntKi), PARAMETER :: M7N2MKxe = 542 + INTEGER(IntKi), PARAMETER :: M7N3MKxe = 543 + INTEGER(IntKi), PARAMETER :: M7N4MKxe = 544 + INTEGER(IntKi), PARAMETER :: M7N5MKxe = 545 + INTEGER(IntKi), PARAMETER :: M7N6MKxe = 546 + INTEGER(IntKi), PARAMETER :: M7N7MKxe = 547 + INTEGER(IntKi), PARAMETER :: M7N8MKxe = 548 + INTEGER(IntKi), PARAMETER :: M7N9MKxe = 549 + INTEGER(IntKi), PARAMETER :: M8N1MKxe = 550 + INTEGER(IntKi), PARAMETER :: M8N2MKxe = 551 + INTEGER(IntKi), PARAMETER :: M8N3MKxe = 552 + INTEGER(IntKi), PARAMETER :: M8N4MKxe = 553 + INTEGER(IntKi), PARAMETER :: M8N5MKxe = 554 + INTEGER(IntKi), PARAMETER :: M8N6MKxe = 555 + INTEGER(IntKi), PARAMETER :: M8N7MKxe = 556 + INTEGER(IntKi), PARAMETER :: M8N8MKxe = 557 + INTEGER(IntKi), PARAMETER :: M8N9MKxe = 558 + INTEGER(IntKi), PARAMETER :: M9N1MKxe = 559 + INTEGER(IntKi), PARAMETER :: M9N2MKxe = 560 + INTEGER(IntKi), PARAMETER :: M9N3MKxe = 561 + INTEGER(IntKi), PARAMETER :: M9N4MKxe = 562 + INTEGER(IntKi), PARAMETER :: M9N5MKxe = 563 + INTEGER(IntKi), PARAMETER :: M9N6MKxe = 564 + INTEGER(IntKi), PARAMETER :: M9N7MKxe = 565 + INTEGER(IntKi), PARAMETER :: M9N8MKxe = 566 + INTEGER(IntKi), PARAMETER :: M9N9MKxe = 567 + INTEGER(IntKi), PARAMETER :: M1N1MKye = 568 + INTEGER(IntKi), PARAMETER :: M1N2MKye = 569 + INTEGER(IntKi), PARAMETER :: M1N3MKye = 570 + INTEGER(IntKi), PARAMETER :: M1N4MKye = 571 + INTEGER(IntKi), PARAMETER :: M1N5MKye = 572 + INTEGER(IntKi), PARAMETER :: M1N6MKye = 573 + INTEGER(IntKi), PARAMETER :: M1N7MKye = 574 + INTEGER(IntKi), PARAMETER :: M1N8MKye = 575 + INTEGER(IntKi), PARAMETER :: M1N9MKye = 576 + INTEGER(IntKi), PARAMETER :: M2N1MKye = 577 + INTEGER(IntKi), PARAMETER :: M2N2MKye = 578 + INTEGER(IntKi), PARAMETER :: M2N3MKye = 579 + INTEGER(IntKi), PARAMETER :: M2N4MKye = 580 + INTEGER(IntKi), PARAMETER :: M2N5MKye = 581 + INTEGER(IntKi), PARAMETER :: M2N6MKye = 582 + INTEGER(IntKi), PARAMETER :: M2N7MKye = 583 + INTEGER(IntKi), PARAMETER :: M2N8MKye = 584 + INTEGER(IntKi), PARAMETER :: M2N9MKye = 585 + INTEGER(IntKi), PARAMETER :: M3N1MKye = 586 + INTEGER(IntKi), PARAMETER :: M3N2MKye = 587 + INTEGER(IntKi), PARAMETER :: M3N3MKye = 588 + INTEGER(IntKi), PARAMETER :: M3N4MKye = 589 + INTEGER(IntKi), PARAMETER :: M3N5MKye = 590 + INTEGER(IntKi), PARAMETER :: M3N6MKye = 591 + INTEGER(IntKi), PARAMETER :: M3N7MKye = 592 + INTEGER(IntKi), PARAMETER :: M3N8MKye = 593 + INTEGER(IntKi), PARAMETER :: M3N9MKye = 594 + INTEGER(IntKi), PARAMETER :: M4N1MKye = 595 + INTEGER(IntKi), PARAMETER :: M4N2MKye = 596 + INTEGER(IntKi), PARAMETER :: M4N3MKye = 597 + INTEGER(IntKi), PARAMETER :: M4N4MKye = 598 + INTEGER(IntKi), PARAMETER :: M4N5MKye = 599 + INTEGER(IntKi), PARAMETER :: M4N6MKye = 600 + INTEGER(IntKi), PARAMETER :: M4N7MKye = 601 + INTEGER(IntKi), PARAMETER :: M4N8MKye = 602 + INTEGER(IntKi), PARAMETER :: M4N9MKye = 603 + INTEGER(IntKi), PARAMETER :: M5N1MKye = 604 + INTEGER(IntKi), PARAMETER :: M5N2MKye = 605 + INTEGER(IntKi), PARAMETER :: M5N3MKye = 606 + INTEGER(IntKi), PARAMETER :: M5N4MKye = 607 + INTEGER(IntKi), PARAMETER :: M5N5MKye = 608 + INTEGER(IntKi), PARAMETER :: M5N6MKye = 609 + INTEGER(IntKi), PARAMETER :: M5N7MKye = 610 + INTEGER(IntKi), PARAMETER :: M5N8MKye = 611 + INTEGER(IntKi), PARAMETER :: M5N9MKye = 612 + INTEGER(IntKi), PARAMETER :: M6N1MKye = 613 + INTEGER(IntKi), PARAMETER :: M6N2MKye = 614 + INTEGER(IntKi), PARAMETER :: M6N3MKye = 615 + INTEGER(IntKi), PARAMETER :: M6N4MKye = 616 + INTEGER(IntKi), PARAMETER :: M6N5MKye = 617 + INTEGER(IntKi), PARAMETER :: M6N6MKye = 618 + INTEGER(IntKi), PARAMETER :: M6N7MKye = 619 + INTEGER(IntKi), PARAMETER :: M6N8MKye = 620 + INTEGER(IntKi), PARAMETER :: M6N9MKye = 621 + INTEGER(IntKi), PARAMETER :: M7N1MKye = 622 + INTEGER(IntKi), PARAMETER :: M7N2MKye = 623 + INTEGER(IntKi), PARAMETER :: M7N3MKye = 624 + INTEGER(IntKi), PARAMETER :: M7N4MKye = 625 + INTEGER(IntKi), PARAMETER :: M7N5MKye = 626 + INTEGER(IntKi), PARAMETER :: M7N6MKye = 627 + INTEGER(IntKi), PARAMETER :: M7N7MKye = 628 + INTEGER(IntKi), PARAMETER :: M7N8MKye = 629 + INTEGER(IntKi), PARAMETER :: M7N9MKye = 630 + INTEGER(IntKi), PARAMETER :: M8N1MKye = 631 + INTEGER(IntKi), PARAMETER :: M8N2MKye = 632 + INTEGER(IntKi), PARAMETER :: M8N3MKye = 633 + INTEGER(IntKi), PARAMETER :: M8N4MKye = 634 + INTEGER(IntKi), PARAMETER :: M8N5MKye = 635 + INTEGER(IntKi), PARAMETER :: M8N6MKye = 636 + INTEGER(IntKi), PARAMETER :: M8N7MKye = 637 + INTEGER(IntKi), PARAMETER :: M8N8MKye = 638 + INTEGER(IntKi), PARAMETER :: M8N9MKye = 639 + INTEGER(IntKi), PARAMETER :: M9N1MKye = 640 + INTEGER(IntKi), PARAMETER :: M9N2MKye = 641 + INTEGER(IntKi), PARAMETER :: M9N3MKye = 642 + INTEGER(IntKi), PARAMETER :: M9N4MKye = 643 + INTEGER(IntKi), PARAMETER :: M9N5MKye = 644 + INTEGER(IntKi), PARAMETER :: M9N6MKye = 645 + INTEGER(IntKi), PARAMETER :: M9N7MKye = 646 + INTEGER(IntKi), PARAMETER :: M9N8MKye = 647 + INTEGER(IntKi), PARAMETER :: M9N9MKye = 648 + INTEGER(IntKi), PARAMETER :: M1N1MKze = 649 + INTEGER(IntKi), PARAMETER :: M1N2MKze = 650 + INTEGER(IntKi), PARAMETER :: M1N3MKze = 651 + INTEGER(IntKi), PARAMETER :: M1N4MKze = 652 + INTEGER(IntKi), PARAMETER :: M1N5MKze = 653 + INTEGER(IntKi), PARAMETER :: M1N6MKze = 654 + INTEGER(IntKi), PARAMETER :: M1N7MKze = 655 + INTEGER(IntKi), PARAMETER :: M1N8MKze = 656 + INTEGER(IntKi), PARAMETER :: M1N9MKze = 657 + INTEGER(IntKi), PARAMETER :: M2N1MKze = 658 + INTEGER(IntKi), PARAMETER :: M2N2MKze = 659 + INTEGER(IntKi), PARAMETER :: M2N3MKze = 660 + INTEGER(IntKi), PARAMETER :: M2N4MKze = 661 + INTEGER(IntKi), PARAMETER :: M2N5MKze = 662 + INTEGER(IntKi), PARAMETER :: M2N6MKze = 663 + INTEGER(IntKi), PARAMETER :: M2N7MKze = 664 + INTEGER(IntKi), PARAMETER :: M2N8MKze = 665 + INTEGER(IntKi), PARAMETER :: M2N9MKze = 666 + INTEGER(IntKi), PARAMETER :: M3N1MKze = 667 + INTEGER(IntKi), PARAMETER :: M3N2MKze = 668 + INTEGER(IntKi), PARAMETER :: M3N3MKze = 669 + INTEGER(IntKi), PARAMETER :: M3N4MKze = 670 + INTEGER(IntKi), PARAMETER :: M3N5MKze = 671 + INTEGER(IntKi), PARAMETER :: M3N6MKze = 672 + INTEGER(IntKi), PARAMETER :: M3N7MKze = 673 + INTEGER(IntKi), PARAMETER :: M3N8MKze = 674 + INTEGER(IntKi), PARAMETER :: M3N9MKze = 675 + INTEGER(IntKi), PARAMETER :: M4N1MKze = 676 + INTEGER(IntKi), PARAMETER :: M4N2MKze = 677 + INTEGER(IntKi), PARAMETER :: M4N3MKze = 678 + INTEGER(IntKi), PARAMETER :: M4N4MKze = 679 + INTEGER(IntKi), PARAMETER :: M4N5MKze = 680 + INTEGER(IntKi), PARAMETER :: M4N6MKze = 681 + INTEGER(IntKi), PARAMETER :: M4N7MKze = 682 + INTEGER(IntKi), PARAMETER :: M4N8MKze = 683 + INTEGER(IntKi), PARAMETER :: M4N9MKze = 684 + INTEGER(IntKi), PARAMETER :: M5N1MKze = 685 + INTEGER(IntKi), PARAMETER :: M5N2MKze = 686 + INTEGER(IntKi), PARAMETER :: M5N3MKze = 687 + INTEGER(IntKi), PARAMETER :: M5N4MKze = 688 + INTEGER(IntKi), PARAMETER :: M5N5MKze = 689 + INTEGER(IntKi), PARAMETER :: M5N6MKze = 690 + INTEGER(IntKi), PARAMETER :: M5N7MKze = 691 + INTEGER(IntKi), PARAMETER :: M5N8MKze = 692 + INTEGER(IntKi), PARAMETER :: M5N9MKze = 693 + INTEGER(IntKi), PARAMETER :: M6N1MKze = 694 + INTEGER(IntKi), PARAMETER :: M6N2MKze = 695 + INTEGER(IntKi), PARAMETER :: M6N3MKze = 696 + INTEGER(IntKi), PARAMETER :: M6N4MKze = 697 + INTEGER(IntKi), PARAMETER :: M6N5MKze = 698 + INTEGER(IntKi), PARAMETER :: M6N6MKze = 699 + INTEGER(IntKi), PARAMETER :: M6N7MKze = 700 + INTEGER(IntKi), PARAMETER :: M6N8MKze = 701 + INTEGER(IntKi), PARAMETER :: M6N9MKze = 702 + INTEGER(IntKi), PARAMETER :: M7N1MKze = 703 + INTEGER(IntKi), PARAMETER :: M7N2MKze = 704 + INTEGER(IntKi), PARAMETER :: M7N3MKze = 705 + INTEGER(IntKi), PARAMETER :: M7N4MKze = 706 + INTEGER(IntKi), PARAMETER :: M7N5MKze = 707 + INTEGER(IntKi), PARAMETER :: M7N6MKze = 708 + INTEGER(IntKi), PARAMETER :: M7N7MKze = 709 + INTEGER(IntKi), PARAMETER :: M7N8MKze = 710 + INTEGER(IntKi), PARAMETER :: M7N9MKze = 711 + INTEGER(IntKi), PARAMETER :: M8N1MKze = 712 + INTEGER(IntKi), PARAMETER :: M8N2MKze = 713 + INTEGER(IntKi), PARAMETER :: M8N3MKze = 714 + INTEGER(IntKi), PARAMETER :: M8N4MKze = 715 + INTEGER(IntKi), PARAMETER :: M8N5MKze = 716 + INTEGER(IntKi), PARAMETER :: M8N6MKze = 717 + INTEGER(IntKi), PARAMETER :: M8N7MKze = 718 + INTEGER(IntKi), PARAMETER :: M8N8MKze = 719 + INTEGER(IntKi), PARAMETER :: M8N9MKze = 720 + INTEGER(IntKi), PARAMETER :: M9N1MKze = 721 + INTEGER(IntKi), PARAMETER :: M9N2MKze = 722 + INTEGER(IntKi), PARAMETER :: M9N3MKze = 723 + INTEGER(IntKi), PARAMETER :: M9N4MKze = 724 + INTEGER(IntKi), PARAMETER :: M9N5MKze = 725 + INTEGER(IntKi), PARAMETER :: M9N6MKze = 726 + INTEGER(IntKi), PARAMETER :: M9N7MKze = 727 + INTEGER(IntKi), PARAMETER :: M9N8MKze = 728 + INTEGER(IntKi), PARAMETER :: M9N9MKze = 729 + INTEGER(IntKi), PARAMETER :: M1N1MMxe = 730 + INTEGER(IntKi), PARAMETER :: M1N2MMxe = 731 + INTEGER(IntKi), PARAMETER :: M1N3MMxe = 732 + INTEGER(IntKi), PARAMETER :: M1N4MMxe = 733 + INTEGER(IntKi), PARAMETER :: M1N5MMxe = 734 + INTEGER(IntKi), PARAMETER :: M1N6MMxe = 735 + INTEGER(IntKi), PARAMETER :: M1N7MMxe = 736 + INTEGER(IntKi), PARAMETER :: M1N8MMxe = 737 + INTEGER(IntKi), PARAMETER :: M1N9MMxe = 738 + INTEGER(IntKi), PARAMETER :: M2N1MMxe = 739 + INTEGER(IntKi), PARAMETER :: M2N2MMxe = 740 + INTEGER(IntKi), PARAMETER :: M2N3MMxe = 741 + INTEGER(IntKi), PARAMETER :: M2N4MMxe = 742 + INTEGER(IntKi), PARAMETER :: M2N5MMxe = 743 + INTEGER(IntKi), PARAMETER :: M2N6MMxe = 744 + INTEGER(IntKi), PARAMETER :: M2N7MMxe = 745 + INTEGER(IntKi), PARAMETER :: M2N8MMxe = 746 + INTEGER(IntKi), PARAMETER :: M2N9MMxe = 747 + INTEGER(IntKi), PARAMETER :: M3N1MMxe = 748 + INTEGER(IntKi), PARAMETER :: M3N2MMxe = 749 + INTEGER(IntKi), PARAMETER :: M3N3MMxe = 750 + INTEGER(IntKi), PARAMETER :: M3N4MMxe = 751 + INTEGER(IntKi), PARAMETER :: M3N5MMxe = 752 + INTEGER(IntKi), PARAMETER :: M3N6MMxe = 753 + INTEGER(IntKi), PARAMETER :: M3N7MMxe = 754 + INTEGER(IntKi), PARAMETER :: M3N8MMxe = 755 + INTEGER(IntKi), PARAMETER :: M3N9MMxe = 756 + INTEGER(IntKi), PARAMETER :: M4N1MMxe = 757 + INTEGER(IntKi), PARAMETER :: M4N2MMxe = 758 + INTEGER(IntKi), PARAMETER :: M4N3MMxe = 759 + INTEGER(IntKi), PARAMETER :: M4N4MMxe = 760 + INTEGER(IntKi), PARAMETER :: M4N5MMxe = 761 + INTEGER(IntKi), PARAMETER :: M4N6MMxe = 762 + INTEGER(IntKi), PARAMETER :: M4N7MMxe = 763 + INTEGER(IntKi), PARAMETER :: M4N8MMxe = 764 + INTEGER(IntKi), PARAMETER :: M4N9MMxe = 765 + INTEGER(IntKi), PARAMETER :: M5N1MMxe = 766 + INTEGER(IntKi), PARAMETER :: M5N2MMxe = 767 + INTEGER(IntKi), PARAMETER :: M5N3MMxe = 768 + INTEGER(IntKi), PARAMETER :: M5N4MMxe = 769 + INTEGER(IntKi), PARAMETER :: M5N5MMxe = 770 + INTEGER(IntKi), PARAMETER :: M5N6MMxe = 771 + INTEGER(IntKi), PARAMETER :: M5N7MMxe = 772 + INTEGER(IntKi), PARAMETER :: M5N8MMxe = 773 + INTEGER(IntKi), PARAMETER :: M5N9MMxe = 774 + INTEGER(IntKi), PARAMETER :: M6N1MMxe = 775 + INTEGER(IntKi), PARAMETER :: M6N2MMxe = 776 + INTEGER(IntKi), PARAMETER :: M6N3MMxe = 777 + INTEGER(IntKi), PARAMETER :: M6N4MMxe = 778 + INTEGER(IntKi), PARAMETER :: M6N5MMxe = 779 + INTEGER(IntKi), PARAMETER :: M6N6MMxe = 780 + INTEGER(IntKi), PARAMETER :: M6N7MMxe = 781 + INTEGER(IntKi), PARAMETER :: M6N8MMxe = 782 + INTEGER(IntKi), PARAMETER :: M6N9MMxe = 783 + INTEGER(IntKi), PARAMETER :: M7N1MMxe = 784 + INTEGER(IntKi), PARAMETER :: M7N2MMxe = 785 + INTEGER(IntKi), PARAMETER :: M7N3MMxe = 786 + INTEGER(IntKi), PARAMETER :: M7N4MMxe = 787 + INTEGER(IntKi), PARAMETER :: M7N5MMxe = 788 + INTEGER(IntKi), PARAMETER :: M7N6MMxe = 789 + INTEGER(IntKi), PARAMETER :: M7N7MMxe = 790 + INTEGER(IntKi), PARAMETER :: M7N8MMxe = 791 + INTEGER(IntKi), PARAMETER :: M7N9MMxe = 792 + INTEGER(IntKi), PARAMETER :: M8N1MMxe = 793 + INTEGER(IntKi), PARAMETER :: M8N2MMxe = 794 + INTEGER(IntKi), PARAMETER :: M8N3MMxe = 795 + INTEGER(IntKi), PARAMETER :: M8N4MMxe = 796 + INTEGER(IntKi), PARAMETER :: M8N5MMxe = 797 + INTEGER(IntKi), PARAMETER :: M8N6MMxe = 798 + INTEGER(IntKi), PARAMETER :: M8N7MMxe = 799 + INTEGER(IntKi), PARAMETER :: M8N8MMxe = 800 + INTEGER(IntKi), PARAMETER :: M8N9MMxe = 801 + INTEGER(IntKi), PARAMETER :: M9N1MMxe = 802 + INTEGER(IntKi), PARAMETER :: M9N2MMxe = 803 + INTEGER(IntKi), PARAMETER :: M9N3MMxe = 804 + INTEGER(IntKi), PARAMETER :: M9N4MMxe = 805 + INTEGER(IntKi), PARAMETER :: M9N5MMxe = 806 + INTEGER(IntKi), PARAMETER :: M9N6MMxe = 807 + INTEGER(IntKi), PARAMETER :: M9N7MMxe = 808 + INTEGER(IntKi), PARAMETER :: M9N8MMxe = 809 + INTEGER(IntKi), PARAMETER :: M9N9MMxe = 810 + INTEGER(IntKi), PARAMETER :: M1N1MMye = 811 + INTEGER(IntKi), PARAMETER :: M1N2MMye = 812 + INTEGER(IntKi), PARAMETER :: M1N3MMye = 813 + INTEGER(IntKi), PARAMETER :: M1N4MMye = 814 + INTEGER(IntKi), PARAMETER :: M1N5MMye = 815 + INTEGER(IntKi), PARAMETER :: M1N6MMye = 816 + INTEGER(IntKi), PARAMETER :: M1N7MMye = 817 + INTEGER(IntKi), PARAMETER :: M1N8MMye = 818 + INTEGER(IntKi), PARAMETER :: M1N9MMye = 819 + INTEGER(IntKi), PARAMETER :: M2N1MMye = 820 + INTEGER(IntKi), PARAMETER :: M2N2MMye = 821 + INTEGER(IntKi), PARAMETER :: M2N3MMye = 822 + INTEGER(IntKi), PARAMETER :: M2N4MMye = 823 + INTEGER(IntKi), PARAMETER :: M2N5MMye = 824 + INTEGER(IntKi), PARAMETER :: M2N6MMye = 825 + INTEGER(IntKi), PARAMETER :: M2N7MMye = 826 + INTEGER(IntKi), PARAMETER :: M2N8MMye = 827 + INTEGER(IntKi), PARAMETER :: M2N9MMye = 828 + INTEGER(IntKi), PARAMETER :: M3N1MMye = 829 + INTEGER(IntKi), PARAMETER :: M3N2MMye = 830 + INTEGER(IntKi), PARAMETER :: M3N3MMye = 831 + INTEGER(IntKi), PARAMETER :: M3N4MMye = 832 + INTEGER(IntKi), PARAMETER :: M3N5MMye = 833 + INTEGER(IntKi), PARAMETER :: M3N6MMye = 834 + INTEGER(IntKi), PARAMETER :: M3N7MMye = 835 + INTEGER(IntKi), PARAMETER :: M3N8MMye = 836 + INTEGER(IntKi), PARAMETER :: M3N9MMye = 837 + INTEGER(IntKi), PARAMETER :: M4N1MMye = 838 + INTEGER(IntKi), PARAMETER :: M4N2MMye = 839 + INTEGER(IntKi), PARAMETER :: M4N3MMye = 840 + INTEGER(IntKi), PARAMETER :: M4N4MMye = 841 + INTEGER(IntKi), PARAMETER :: M4N5MMye = 842 + INTEGER(IntKi), PARAMETER :: M4N6MMye = 843 + INTEGER(IntKi), PARAMETER :: M4N7MMye = 844 + INTEGER(IntKi), PARAMETER :: M4N8MMye = 845 + INTEGER(IntKi), PARAMETER :: M4N9MMye = 846 + INTEGER(IntKi), PARAMETER :: M5N1MMye = 847 + INTEGER(IntKi), PARAMETER :: M5N2MMye = 848 + INTEGER(IntKi), PARAMETER :: M5N3MMye = 849 + INTEGER(IntKi), PARAMETER :: M5N4MMye = 850 + INTEGER(IntKi), PARAMETER :: M5N5MMye = 851 + INTEGER(IntKi), PARAMETER :: M5N6MMye = 852 + INTEGER(IntKi), PARAMETER :: M5N7MMye = 853 + INTEGER(IntKi), PARAMETER :: M5N8MMye = 854 + INTEGER(IntKi), PARAMETER :: M5N9MMye = 855 + INTEGER(IntKi), PARAMETER :: M6N1MMye = 856 + INTEGER(IntKi), PARAMETER :: M6N2MMye = 857 + INTEGER(IntKi), PARAMETER :: M6N3MMye = 858 + INTEGER(IntKi), PARAMETER :: M6N4MMye = 859 + INTEGER(IntKi), PARAMETER :: M6N5MMye = 860 + INTEGER(IntKi), PARAMETER :: M6N6MMye = 861 + INTEGER(IntKi), PARAMETER :: M6N7MMye = 862 + INTEGER(IntKi), PARAMETER :: M6N8MMye = 863 + INTEGER(IntKi), PARAMETER :: M6N9MMye = 864 + INTEGER(IntKi), PARAMETER :: M7N1MMye = 865 + INTEGER(IntKi), PARAMETER :: M7N2MMye = 866 + INTEGER(IntKi), PARAMETER :: M7N3MMye = 867 + INTEGER(IntKi), PARAMETER :: M7N4MMye = 868 + INTEGER(IntKi), PARAMETER :: M7N5MMye = 869 + INTEGER(IntKi), PARAMETER :: M7N6MMye = 870 + INTEGER(IntKi), PARAMETER :: M7N7MMye = 871 + INTEGER(IntKi), PARAMETER :: M7N8MMye = 872 + INTEGER(IntKi), PARAMETER :: M7N9MMye = 873 + INTEGER(IntKi), PARAMETER :: M8N1MMye = 874 + INTEGER(IntKi), PARAMETER :: M8N2MMye = 875 + INTEGER(IntKi), PARAMETER :: M8N3MMye = 876 + INTEGER(IntKi), PARAMETER :: M8N4MMye = 877 + INTEGER(IntKi), PARAMETER :: M8N5MMye = 878 + INTEGER(IntKi), PARAMETER :: M8N6MMye = 879 + INTEGER(IntKi), PARAMETER :: M8N7MMye = 880 + INTEGER(IntKi), PARAMETER :: M8N8MMye = 881 + INTEGER(IntKi), PARAMETER :: M8N9MMye = 882 + INTEGER(IntKi), PARAMETER :: M9N1MMye = 883 + INTEGER(IntKi), PARAMETER :: M9N2MMye = 884 + INTEGER(IntKi), PARAMETER :: M9N3MMye = 885 + INTEGER(IntKi), PARAMETER :: M9N4MMye = 886 + INTEGER(IntKi), PARAMETER :: M9N5MMye = 887 + INTEGER(IntKi), PARAMETER :: M9N6MMye = 888 + INTEGER(IntKi), PARAMETER :: M9N7MMye = 889 + INTEGER(IntKi), PARAMETER :: M9N8MMye = 890 + INTEGER(IntKi), PARAMETER :: M9N9MMye = 891 + INTEGER(IntKi), PARAMETER :: M1N1MMze = 892 + INTEGER(IntKi), PARAMETER :: M1N2MMze = 893 + INTEGER(IntKi), PARAMETER :: M1N3MMze = 894 + INTEGER(IntKi), PARAMETER :: M1N4MMze = 895 + INTEGER(IntKi), PARAMETER :: M1N5MMze = 896 + INTEGER(IntKi), PARAMETER :: M1N6MMze = 897 + INTEGER(IntKi), PARAMETER :: M1N7MMze = 898 + INTEGER(IntKi), PARAMETER :: M1N8MMze = 899 + INTEGER(IntKi), PARAMETER :: M1N9MMze = 900 + INTEGER(IntKi), PARAMETER :: M2N1MMze = 901 + INTEGER(IntKi), PARAMETER :: M2N2MMze = 902 + INTEGER(IntKi), PARAMETER :: M2N3MMze = 903 + INTEGER(IntKi), PARAMETER :: M2N4MMze = 904 + INTEGER(IntKi), PARAMETER :: M2N5MMze = 905 + INTEGER(IntKi), PARAMETER :: M2N6MMze = 906 + INTEGER(IntKi), PARAMETER :: M2N7MMze = 907 + INTEGER(IntKi), PARAMETER :: M2N8MMze = 908 + INTEGER(IntKi), PARAMETER :: M2N9MMze = 909 + INTEGER(IntKi), PARAMETER :: M3N1MMze = 910 + INTEGER(IntKi), PARAMETER :: M3N2MMze = 911 + INTEGER(IntKi), PARAMETER :: M3N3MMze = 912 + INTEGER(IntKi), PARAMETER :: M3N4MMze = 913 + INTEGER(IntKi), PARAMETER :: M3N5MMze = 914 + INTEGER(IntKi), PARAMETER :: M3N6MMze = 915 + INTEGER(IntKi), PARAMETER :: M3N7MMze = 916 + INTEGER(IntKi), PARAMETER :: M3N8MMze = 917 + INTEGER(IntKi), PARAMETER :: M3N9MMze = 918 + INTEGER(IntKi), PARAMETER :: M4N1MMze = 919 + INTEGER(IntKi), PARAMETER :: M4N2MMze = 920 + INTEGER(IntKi), PARAMETER :: M4N3MMze = 921 + INTEGER(IntKi), PARAMETER :: M4N4MMze = 922 + INTEGER(IntKi), PARAMETER :: M4N5MMze = 923 + INTEGER(IntKi), PARAMETER :: M4N6MMze = 924 + INTEGER(IntKi), PARAMETER :: M4N7MMze = 925 + INTEGER(IntKi), PARAMETER :: M4N8MMze = 926 + INTEGER(IntKi), PARAMETER :: M4N9MMze = 927 + INTEGER(IntKi), PARAMETER :: M5N1MMze = 928 + INTEGER(IntKi), PARAMETER :: M5N2MMze = 929 + INTEGER(IntKi), PARAMETER :: M5N3MMze = 930 + INTEGER(IntKi), PARAMETER :: M5N4MMze = 931 + INTEGER(IntKi), PARAMETER :: M5N5MMze = 932 + INTEGER(IntKi), PARAMETER :: M5N6MMze = 933 + INTEGER(IntKi), PARAMETER :: M5N7MMze = 934 + INTEGER(IntKi), PARAMETER :: M5N8MMze = 935 + INTEGER(IntKi), PARAMETER :: M5N9MMze = 936 + INTEGER(IntKi), PARAMETER :: M6N1MMze = 937 + INTEGER(IntKi), PARAMETER :: M6N2MMze = 938 + INTEGER(IntKi), PARAMETER :: M6N3MMze = 939 + INTEGER(IntKi), PARAMETER :: M6N4MMze = 940 + INTEGER(IntKi), PARAMETER :: M6N5MMze = 941 + INTEGER(IntKi), PARAMETER :: M6N6MMze = 942 + INTEGER(IntKi), PARAMETER :: M6N7MMze = 943 + INTEGER(IntKi), PARAMETER :: M6N8MMze = 944 + INTEGER(IntKi), PARAMETER :: M6N9MMze = 945 + INTEGER(IntKi), PARAMETER :: M7N1MMze = 946 + INTEGER(IntKi), PARAMETER :: M7N2MMze = 947 + INTEGER(IntKi), PARAMETER :: M7N3MMze = 948 + INTEGER(IntKi), PARAMETER :: M7N4MMze = 949 + INTEGER(IntKi), PARAMETER :: M7N5MMze = 950 + INTEGER(IntKi), PARAMETER :: M7N6MMze = 951 + INTEGER(IntKi), PARAMETER :: M7N7MMze = 952 + INTEGER(IntKi), PARAMETER :: M7N8MMze = 953 + INTEGER(IntKi), PARAMETER :: M7N9MMze = 954 + INTEGER(IntKi), PARAMETER :: M8N1MMze = 955 + INTEGER(IntKi), PARAMETER :: M8N2MMze = 956 + INTEGER(IntKi), PARAMETER :: M8N3MMze = 957 + INTEGER(IntKi), PARAMETER :: M8N4MMze = 958 + INTEGER(IntKi), PARAMETER :: M8N5MMze = 959 + INTEGER(IntKi), PARAMETER :: M8N6MMze = 960 + INTEGER(IntKi), PARAMETER :: M8N7MMze = 961 + INTEGER(IntKi), PARAMETER :: M8N8MMze = 962 + INTEGER(IntKi), PARAMETER :: M8N9MMze = 963 + INTEGER(IntKi), PARAMETER :: M9N1MMze = 964 + INTEGER(IntKi), PARAMETER :: M9N2MMze = 965 + INTEGER(IntKi), PARAMETER :: M9N3MMze = 966 + INTEGER(IntKi), PARAMETER :: M9N4MMze = 967 + INTEGER(IntKi), PARAMETER :: M9N5MMze = 968 + INTEGER(IntKi), PARAMETER :: M9N6MMze = 969 + INTEGER(IntKi), PARAMETER :: M9N7MMze = 970 + INTEGER(IntKi), PARAMETER :: M9N8MMze = 971 + INTEGER(IntKi), PARAMETER :: M9N9MMze = 972 + + + ! Displacements: + + INTEGER(IntKi), PARAMETER :: M1N1TDxss = 973 + INTEGER(IntKi), PARAMETER :: M1N2TDxss = 974 + INTEGER(IntKi), PARAMETER :: M1N3TDxss = 975 + INTEGER(IntKi), PARAMETER :: M1N4TDxss = 976 + INTEGER(IntKi), PARAMETER :: M1N5TDxss = 977 + INTEGER(IntKi), PARAMETER :: M1N6TDxss = 978 + INTEGER(IntKi), PARAMETER :: M1N7TDxss = 979 + INTEGER(IntKi), PARAMETER :: M1N8TDxss = 980 + INTEGER(IntKi), PARAMETER :: M1N9TDxss = 981 + INTEGER(IntKi), PARAMETER :: M2N1TDxss = 982 + INTEGER(IntKi), PARAMETER :: M2N2TDxss = 983 + INTEGER(IntKi), PARAMETER :: M2N3TDxss = 984 + INTEGER(IntKi), PARAMETER :: M2N4TDxss = 985 + INTEGER(IntKi), PARAMETER :: M2N5TDxss = 986 + INTEGER(IntKi), PARAMETER :: M2N6TDxss = 987 + INTEGER(IntKi), PARAMETER :: M2N7TDxss = 988 + INTEGER(IntKi), PARAMETER :: M2N8TDxss = 989 + INTEGER(IntKi), PARAMETER :: M2N9TDxss = 990 + INTEGER(IntKi), PARAMETER :: M3N1TDxss = 991 + INTEGER(IntKi), PARAMETER :: M3N2TDxss = 992 + INTEGER(IntKi), PARAMETER :: M3N3TDxss = 993 + INTEGER(IntKi), PARAMETER :: M3N4TDxss = 994 + INTEGER(IntKi), PARAMETER :: M3N5TDxss = 995 + INTEGER(IntKi), PARAMETER :: M3N6TDxss = 996 + INTEGER(IntKi), PARAMETER :: M3N7TDxss = 997 + INTEGER(IntKi), PARAMETER :: M3N8TDxss = 998 + INTEGER(IntKi), PARAMETER :: M3N9TDxss = 999 + INTEGER(IntKi), PARAMETER :: M4N1TDxss = 1000 + INTEGER(IntKi), PARAMETER :: M4N2TDxss = 1001 + INTEGER(IntKi), PARAMETER :: M4N3TDxss = 1002 + INTEGER(IntKi), PARAMETER :: M4N4TDxss = 1003 + INTEGER(IntKi), PARAMETER :: M4N5TDxss = 1004 + INTEGER(IntKi), PARAMETER :: M4N6TDxss = 1005 + INTEGER(IntKi), PARAMETER :: M4N7TDxss = 1006 + INTEGER(IntKi), PARAMETER :: M4N8TDxss = 1007 + INTEGER(IntKi), PARAMETER :: M4N9TDxss = 1008 + INTEGER(IntKi), PARAMETER :: M5N1TDxss = 1009 + INTEGER(IntKi), PARAMETER :: M5N2TDxss = 1010 + INTEGER(IntKi), PARAMETER :: M5N3TDxss = 1011 + INTEGER(IntKi), PARAMETER :: M5N4TDxss = 1012 + INTEGER(IntKi), PARAMETER :: M5N5TDxss = 1013 + INTEGER(IntKi), PARAMETER :: M5N6TDxss = 1014 + INTEGER(IntKi), PARAMETER :: M5N7TDxss = 1015 + INTEGER(IntKi), PARAMETER :: M5N8TDxss = 1016 + INTEGER(IntKi), PARAMETER :: M5N9TDxss = 1017 + INTEGER(IntKi), PARAMETER :: M6N1TDxss = 1018 + INTEGER(IntKi), PARAMETER :: M6N2TDxss = 1019 + INTEGER(IntKi), PARAMETER :: M6N3TDxss = 1020 + INTEGER(IntKi), PARAMETER :: M6N4TDxss = 1021 + INTEGER(IntKi), PARAMETER :: M6N5TDxss = 1022 + INTEGER(IntKi), PARAMETER :: M6N6TDxss = 1023 + INTEGER(IntKi), PARAMETER :: M6N7TDxss = 1024 + INTEGER(IntKi), PARAMETER :: M6N8TDxss = 1025 + INTEGER(IntKi), PARAMETER :: M6N9TDxss = 1026 + INTEGER(IntKi), PARAMETER :: M7N1TDxss = 1027 + INTEGER(IntKi), PARAMETER :: M7N2TDxss = 1028 + INTEGER(IntKi), PARAMETER :: M7N3TDxss = 1029 + INTEGER(IntKi), PARAMETER :: M7N4TDxss = 1030 + INTEGER(IntKi), PARAMETER :: M7N5TDxss = 1031 + INTEGER(IntKi), PARAMETER :: M7N6TDxss = 1032 + INTEGER(IntKi), PARAMETER :: M7N7TDxss = 1033 + INTEGER(IntKi), PARAMETER :: M7N8TDxss = 1034 + INTEGER(IntKi), PARAMETER :: M7N9TDxss = 1035 + INTEGER(IntKi), PARAMETER :: M8N1TDxss = 1036 + INTEGER(IntKi), PARAMETER :: M8N2TDxss = 1037 + INTEGER(IntKi), PARAMETER :: M8N3TDxss = 1038 + INTEGER(IntKi), PARAMETER :: M8N4TDxss = 1039 + INTEGER(IntKi), PARAMETER :: M8N5TDxss = 1040 + INTEGER(IntKi), PARAMETER :: M8N6TDxss = 1041 + INTEGER(IntKi), PARAMETER :: M8N7TDxss = 1042 + INTEGER(IntKi), PARAMETER :: M8N8TDxss = 1043 + INTEGER(IntKi), PARAMETER :: M8N9TDxss = 1044 + INTEGER(IntKi), PARAMETER :: M9N1TDxss = 1045 + INTEGER(IntKi), PARAMETER :: M9N2TDxss = 1046 + INTEGER(IntKi), PARAMETER :: M9N3TDxss = 1047 + INTEGER(IntKi), PARAMETER :: M9N4TDxss = 1048 + INTEGER(IntKi), PARAMETER :: M9N5TDxss = 1049 + INTEGER(IntKi), PARAMETER :: M9N6TDxss = 1050 + INTEGER(IntKi), PARAMETER :: M9N7TDxss = 1051 + INTEGER(IntKi), PARAMETER :: M9N8TDxss = 1052 + INTEGER(IntKi), PARAMETER :: M9N9TDxss = 1053 + INTEGER(IntKi), PARAMETER :: M1N1TDyss = 1054 + INTEGER(IntKi), PARAMETER :: M1N2TDyss = 1055 + INTEGER(IntKi), PARAMETER :: M1N3TDyss = 1056 + INTEGER(IntKi), PARAMETER :: M1N4TDyss = 1057 + INTEGER(IntKi), PARAMETER :: M1N5TDyss = 1058 + INTEGER(IntKi), PARAMETER :: M1N6TDyss = 1059 + INTEGER(IntKi), PARAMETER :: M1N7TDyss = 1060 + INTEGER(IntKi), PARAMETER :: M1N8TDyss = 1061 + INTEGER(IntKi), PARAMETER :: M1N9TDyss = 1062 + INTEGER(IntKi), PARAMETER :: M2N1TDyss = 1063 + INTEGER(IntKi), PARAMETER :: M2N2TDyss = 1064 + INTEGER(IntKi), PARAMETER :: M2N3TDyss = 1065 + INTEGER(IntKi), PARAMETER :: M2N4TDyss = 1066 + INTEGER(IntKi), PARAMETER :: M2N5TDyss = 1067 + INTEGER(IntKi), PARAMETER :: M2N6TDyss = 1068 + INTEGER(IntKi), PARAMETER :: M2N7TDyss = 1069 + INTEGER(IntKi), PARAMETER :: M2N8TDyss = 1070 + INTEGER(IntKi), PARAMETER :: M2N9TDyss = 1071 + INTEGER(IntKi), PARAMETER :: M3N1TDyss = 1072 + INTEGER(IntKi), PARAMETER :: M3N2TDyss = 1073 + INTEGER(IntKi), PARAMETER :: M3N3TDyss = 1074 + INTEGER(IntKi), PARAMETER :: M3N4TDyss = 1075 + INTEGER(IntKi), PARAMETER :: M3N5TDyss = 1076 + INTEGER(IntKi), PARAMETER :: M3N6TDyss = 1077 + INTEGER(IntKi), PARAMETER :: M3N7TDyss = 1078 + INTEGER(IntKi), PARAMETER :: M3N8TDyss = 1079 + INTEGER(IntKi), PARAMETER :: M3N9TDyss = 1080 + INTEGER(IntKi), PARAMETER :: M4N1TDyss = 1081 + INTEGER(IntKi), PARAMETER :: M4N2TDyss = 1082 + INTEGER(IntKi), PARAMETER :: M4N3TDyss = 1083 + INTEGER(IntKi), PARAMETER :: M4N4TDyss = 1084 + INTEGER(IntKi), PARAMETER :: M4N5TDyss = 1085 + INTEGER(IntKi), PARAMETER :: M4N6TDyss = 1086 + INTEGER(IntKi), PARAMETER :: M4N7TDyss = 1087 + INTEGER(IntKi), PARAMETER :: M4N8TDyss = 1088 + INTEGER(IntKi), PARAMETER :: M4N9TDyss = 1089 + INTEGER(IntKi), PARAMETER :: M5N1TDyss = 1090 + INTEGER(IntKi), PARAMETER :: M5N2TDyss = 1091 + INTEGER(IntKi), PARAMETER :: M5N3TDyss = 1092 + INTEGER(IntKi), PARAMETER :: M5N4TDyss = 1093 + INTEGER(IntKi), PARAMETER :: M5N5TDyss = 1094 + INTEGER(IntKi), PARAMETER :: M5N6TDyss = 1095 + INTEGER(IntKi), PARAMETER :: M5N7TDyss = 1096 + INTEGER(IntKi), PARAMETER :: M5N8TDyss = 1097 + INTEGER(IntKi), PARAMETER :: M5N9TDyss = 1098 + INTEGER(IntKi), PARAMETER :: M6N1TDyss = 1099 + INTEGER(IntKi), PARAMETER :: M6N2TDyss = 1100 + INTEGER(IntKi), PARAMETER :: M6N3TDyss = 1101 + INTEGER(IntKi), PARAMETER :: M6N4TDyss = 1102 + INTEGER(IntKi), PARAMETER :: M6N5TDyss = 1103 + INTEGER(IntKi), PARAMETER :: M6N6TDyss = 1104 + INTEGER(IntKi), PARAMETER :: M6N7TDyss = 1105 + INTEGER(IntKi), PARAMETER :: M6N8TDyss = 1106 + INTEGER(IntKi), PARAMETER :: M6N9TDyss = 1107 + INTEGER(IntKi), PARAMETER :: M7N1TDyss = 1108 + INTEGER(IntKi), PARAMETER :: M7N2TDyss = 1109 + INTEGER(IntKi), PARAMETER :: M7N3TDyss = 1110 + INTEGER(IntKi), PARAMETER :: M7N4TDyss = 1111 + INTEGER(IntKi), PARAMETER :: M7N5TDyss = 1112 + INTEGER(IntKi), PARAMETER :: M7N6TDyss = 1113 + INTEGER(IntKi), PARAMETER :: M7N7TDyss = 1114 + INTEGER(IntKi), PARAMETER :: M7N8TDyss = 1115 + INTEGER(IntKi), PARAMETER :: M7N9TDyss = 1116 + INTEGER(IntKi), PARAMETER :: M8N1TDyss = 1117 + INTEGER(IntKi), PARAMETER :: M8N2TDyss = 1118 + INTEGER(IntKi), PARAMETER :: M8N3TDyss = 1119 + INTEGER(IntKi), PARAMETER :: M8N4TDyss = 1120 + INTEGER(IntKi), PARAMETER :: M8N5TDyss = 1121 + INTEGER(IntKi), PARAMETER :: M8N6TDyss = 1122 + INTEGER(IntKi), PARAMETER :: M8N7TDyss = 1123 + INTEGER(IntKi), PARAMETER :: M8N8TDyss = 1124 + INTEGER(IntKi), PARAMETER :: M8N9TDyss = 1125 + INTEGER(IntKi), PARAMETER :: M9N1TDyss = 1126 + INTEGER(IntKi), PARAMETER :: M9N2TDyss = 1127 + INTEGER(IntKi), PARAMETER :: M9N3TDyss = 1128 + INTEGER(IntKi), PARAMETER :: M9N4TDyss = 1129 + INTEGER(IntKi), PARAMETER :: M9N5TDyss = 1130 + INTEGER(IntKi), PARAMETER :: M9N6TDyss = 1131 + INTEGER(IntKi), PARAMETER :: M9N7TDyss = 1132 + INTEGER(IntKi), PARAMETER :: M9N8TDyss = 1133 + INTEGER(IntKi), PARAMETER :: M9N9TDyss = 1134 + INTEGER(IntKi), PARAMETER :: M1N1TDzss = 1135 + INTEGER(IntKi), PARAMETER :: M1N2TDzss = 1136 + INTEGER(IntKi), PARAMETER :: M1N3TDzss = 1137 + INTEGER(IntKi), PARAMETER :: M1N4TDzss = 1138 + INTEGER(IntKi), PARAMETER :: M1N5TDzss = 1139 + INTEGER(IntKi), PARAMETER :: M1N6TDzss = 1140 + INTEGER(IntKi), PARAMETER :: M1N7TDzss = 1141 + INTEGER(IntKi), PARAMETER :: M1N8TDzss = 1142 + INTEGER(IntKi), PARAMETER :: M1N9TDzss = 1143 + INTEGER(IntKi), PARAMETER :: M2N1TDzss = 1144 + INTEGER(IntKi), PARAMETER :: M2N2TDzss = 1145 + INTEGER(IntKi), PARAMETER :: M2N3TDzss = 1146 + INTEGER(IntKi), PARAMETER :: M2N4TDzss = 1147 + INTEGER(IntKi), PARAMETER :: M2N5TDzss = 1148 + INTEGER(IntKi), PARAMETER :: M2N6TDzss = 1149 + INTEGER(IntKi), PARAMETER :: M2N7TDzss = 1150 + INTEGER(IntKi), PARAMETER :: M2N8TDzss = 1151 + INTEGER(IntKi), PARAMETER :: M2N9TDzss = 1152 + INTEGER(IntKi), PARAMETER :: M3N1TDzss = 1153 + INTEGER(IntKi), PARAMETER :: M3N2TDzss = 1154 + INTEGER(IntKi), PARAMETER :: M3N3TDzss = 1155 + INTEGER(IntKi), PARAMETER :: M3N4TDzss = 1156 + INTEGER(IntKi), PARAMETER :: M3N5TDzss = 1157 + INTEGER(IntKi), PARAMETER :: M3N6TDzss = 1158 + INTEGER(IntKi), PARAMETER :: M3N7TDzss = 1159 + INTEGER(IntKi), PARAMETER :: M3N8TDzss = 1160 + INTEGER(IntKi), PARAMETER :: M3N9TDzss = 1161 + INTEGER(IntKi), PARAMETER :: M4N1TDzss = 1162 + INTEGER(IntKi), PARAMETER :: M4N2TDzss = 1163 + INTEGER(IntKi), PARAMETER :: M4N3TDzss = 1164 + INTEGER(IntKi), PARAMETER :: M4N4TDzss = 1165 + INTEGER(IntKi), PARAMETER :: M4N5TDzss = 1166 + INTEGER(IntKi), PARAMETER :: M4N6TDzss = 1167 + INTEGER(IntKi), PARAMETER :: M4N7TDzss = 1168 + INTEGER(IntKi), PARAMETER :: M4N8TDzss = 1169 + INTEGER(IntKi), PARAMETER :: M4N9TDzss = 1170 + INTEGER(IntKi), PARAMETER :: M5N1TDzss = 1171 + INTEGER(IntKi), PARAMETER :: M5N2TDzss = 1172 + INTEGER(IntKi), PARAMETER :: M5N3TDzss = 1173 + INTEGER(IntKi), PARAMETER :: M5N4TDzss = 1174 + INTEGER(IntKi), PARAMETER :: M5N5TDzss = 1175 + INTEGER(IntKi), PARAMETER :: M5N6TDzss = 1176 + INTEGER(IntKi), PARAMETER :: M5N7TDzss = 1177 + INTEGER(IntKi), PARAMETER :: M5N8TDzss = 1178 + INTEGER(IntKi), PARAMETER :: M5N9TDzss = 1179 + INTEGER(IntKi), PARAMETER :: M6N1TDzss = 1180 + INTEGER(IntKi), PARAMETER :: M6N2TDzss = 1181 + INTEGER(IntKi), PARAMETER :: M6N3TDzss = 1182 + INTEGER(IntKi), PARAMETER :: M6N4TDzss = 1183 + INTEGER(IntKi), PARAMETER :: M6N5TDzss = 1184 + INTEGER(IntKi), PARAMETER :: M6N6TDzss = 1185 + INTEGER(IntKi), PARAMETER :: M6N7TDzss = 1186 + INTEGER(IntKi), PARAMETER :: M6N8TDzss = 1187 + INTEGER(IntKi), PARAMETER :: M6N9TDzss = 1188 + INTEGER(IntKi), PARAMETER :: M7N1TDzss = 1189 + INTEGER(IntKi), PARAMETER :: M7N2TDzss = 1190 + INTEGER(IntKi), PARAMETER :: M7N3TDzss = 1191 + INTEGER(IntKi), PARAMETER :: M7N4TDzss = 1192 + INTEGER(IntKi), PARAMETER :: M7N5TDzss = 1193 + INTEGER(IntKi), PARAMETER :: M7N6TDzss = 1194 + INTEGER(IntKi), PARAMETER :: M7N7TDzss = 1195 + INTEGER(IntKi), PARAMETER :: M7N8TDzss = 1196 + INTEGER(IntKi), PARAMETER :: M7N9TDzss = 1197 + INTEGER(IntKi), PARAMETER :: M8N1TDzss = 1198 + INTEGER(IntKi), PARAMETER :: M8N2TDzss = 1199 + INTEGER(IntKi), PARAMETER :: M8N3TDzss = 1200 + INTEGER(IntKi), PARAMETER :: M8N4TDzss = 1201 + INTEGER(IntKi), PARAMETER :: M8N5TDzss = 1202 + INTEGER(IntKi), PARAMETER :: M8N6TDzss = 1203 + INTEGER(IntKi), PARAMETER :: M8N7TDzss = 1204 + INTEGER(IntKi), PARAMETER :: M8N8TDzss = 1205 + INTEGER(IntKi), PARAMETER :: M8N9TDzss = 1206 + INTEGER(IntKi), PARAMETER :: M9N1TDzss = 1207 + INTEGER(IntKi), PARAMETER :: M9N2TDzss = 1208 + INTEGER(IntKi), PARAMETER :: M9N3TDzss = 1209 + INTEGER(IntKi), PARAMETER :: M9N4TDzss = 1210 + INTEGER(IntKi), PARAMETER :: M9N5TDzss = 1211 + INTEGER(IntKi), PARAMETER :: M9N6TDzss = 1212 + INTEGER(IntKi), PARAMETER :: M9N7TDzss = 1213 + INTEGER(IntKi), PARAMETER :: M9N8TDzss = 1214 + INTEGER(IntKi), PARAMETER :: M9N9TDzss = 1215 + INTEGER(IntKi), PARAMETER :: M1N1RDxe = 1216 + INTEGER(IntKi), PARAMETER :: M1N2RDxe = 1217 + INTEGER(IntKi), PARAMETER :: M1N3RDxe = 1218 + INTEGER(IntKi), PARAMETER :: M1N4RDxe = 1219 + INTEGER(IntKi), PARAMETER :: M1N5RDxe = 1220 + INTEGER(IntKi), PARAMETER :: M1N6RDxe = 1221 + INTEGER(IntKi), PARAMETER :: M1N7RDxe = 1222 + INTEGER(IntKi), PARAMETER :: M1N8RDxe = 1223 + INTEGER(IntKi), PARAMETER :: M1N9RDxe = 1224 + INTEGER(IntKi), PARAMETER :: M2N1RDxe = 1225 + INTEGER(IntKi), PARAMETER :: M2N2RDxe = 1226 + INTEGER(IntKi), PARAMETER :: M2N3RDxe = 1227 + INTEGER(IntKi), PARAMETER :: M2N4RDxe = 1228 + INTEGER(IntKi), PARAMETER :: M2N5RDxe = 1229 + INTEGER(IntKi), PARAMETER :: M2N6RDxe = 1230 + INTEGER(IntKi), PARAMETER :: M2N7RDxe = 1231 + INTEGER(IntKi), PARAMETER :: M2N8RDxe = 1232 + INTEGER(IntKi), PARAMETER :: M2N9RDxe = 1233 + INTEGER(IntKi), PARAMETER :: M3N1RDxe = 1234 + INTEGER(IntKi), PARAMETER :: M3N2RDxe = 1235 + INTEGER(IntKi), PARAMETER :: M3N3RDxe = 1236 + INTEGER(IntKi), PARAMETER :: M3N4RDxe = 1237 + INTEGER(IntKi), PARAMETER :: M3N5RDxe = 1238 + INTEGER(IntKi), PARAMETER :: M3N6RDxe = 1239 + INTEGER(IntKi), PARAMETER :: M3N7RDxe = 1240 + INTEGER(IntKi), PARAMETER :: M3N8RDxe = 1241 + INTEGER(IntKi), PARAMETER :: M3N9RDxe = 1242 + INTEGER(IntKi), PARAMETER :: M4N1RDxe = 1243 + INTEGER(IntKi), PARAMETER :: M4N2RDxe = 1244 + INTEGER(IntKi), PARAMETER :: M4N3RDxe = 1245 + INTEGER(IntKi), PARAMETER :: M4N4RDxe = 1246 + INTEGER(IntKi), PARAMETER :: M4N5RDxe = 1247 + INTEGER(IntKi), PARAMETER :: M4N6RDxe = 1248 + INTEGER(IntKi), PARAMETER :: M4N7RDxe = 1249 + INTEGER(IntKi), PARAMETER :: M4N8RDxe = 1250 + INTEGER(IntKi), PARAMETER :: M4N9RDxe = 1251 + INTEGER(IntKi), PARAMETER :: M5N1RDxe = 1252 + INTEGER(IntKi), PARAMETER :: M5N2RDxe = 1253 + INTEGER(IntKi), PARAMETER :: M5N3RDxe = 1254 + INTEGER(IntKi), PARAMETER :: M5N4RDxe = 1255 + INTEGER(IntKi), PARAMETER :: M5N5RDxe = 1256 + INTEGER(IntKi), PARAMETER :: M5N6RDxe = 1257 + INTEGER(IntKi), PARAMETER :: M5N7RDxe = 1258 + INTEGER(IntKi), PARAMETER :: M5N8RDxe = 1259 + INTEGER(IntKi), PARAMETER :: M5N9RDxe = 1260 + INTEGER(IntKi), PARAMETER :: M6N1RDxe = 1261 + INTEGER(IntKi), PARAMETER :: M6N2RDxe = 1262 + INTEGER(IntKi), PARAMETER :: M6N3RDxe = 1263 + INTEGER(IntKi), PARAMETER :: M6N4RDxe = 1264 + INTEGER(IntKi), PARAMETER :: M6N5RDxe = 1265 + INTEGER(IntKi), PARAMETER :: M6N6RDxe = 1266 + INTEGER(IntKi), PARAMETER :: M6N7RDxe = 1267 + INTEGER(IntKi), PARAMETER :: M6N8RDxe = 1268 + INTEGER(IntKi), PARAMETER :: M6N9RDxe = 1269 + INTEGER(IntKi), PARAMETER :: M7N1RDxe = 1270 + INTEGER(IntKi), PARAMETER :: M7N2RDxe = 1271 + INTEGER(IntKi), PARAMETER :: M7N3RDxe = 1272 + INTEGER(IntKi), PARAMETER :: M7N4RDxe = 1273 + INTEGER(IntKi), PARAMETER :: M7N5RDxe = 1274 + INTEGER(IntKi), PARAMETER :: M7N6RDxe = 1275 + INTEGER(IntKi), PARAMETER :: M7N7RDxe = 1276 + INTEGER(IntKi), PARAMETER :: M7N8RDxe = 1277 + INTEGER(IntKi), PARAMETER :: M7N9RDxe = 1278 + INTEGER(IntKi), PARAMETER :: M8N1RDxe = 1279 + INTEGER(IntKi), PARAMETER :: M8N2RDxe = 1280 + INTEGER(IntKi), PARAMETER :: M8N3RDxe = 1281 + INTEGER(IntKi), PARAMETER :: M8N4RDxe = 1282 + INTEGER(IntKi), PARAMETER :: M8N5RDxe = 1283 + INTEGER(IntKi), PARAMETER :: M8N6RDxe = 1284 + INTEGER(IntKi), PARAMETER :: M8N7RDxe = 1285 + INTEGER(IntKi), PARAMETER :: M8N8RDxe = 1286 + INTEGER(IntKi), PARAMETER :: M8N9RDxe = 1287 + INTEGER(IntKi), PARAMETER :: M9N1RDxe = 1288 + INTEGER(IntKi), PARAMETER :: M9N2RDxe = 1289 + INTEGER(IntKi), PARAMETER :: M9N3RDxe = 1290 + INTEGER(IntKi), PARAMETER :: M9N4RDxe = 1291 + INTEGER(IntKi), PARAMETER :: M9N5RDxe = 1292 + INTEGER(IntKi), PARAMETER :: M9N6RDxe = 1293 + INTEGER(IntKi), PARAMETER :: M9N7RDxe = 1294 + INTEGER(IntKi), PARAMETER :: M9N8RDxe = 1295 + INTEGER(IntKi), PARAMETER :: M9N9RDxe = 1296 + INTEGER(IntKi), PARAMETER :: M1N1RDye = 1297 + INTEGER(IntKi), PARAMETER :: M1N2RDye = 1298 + INTEGER(IntKi), PARAMETER :: M1N3RDye = 1299 + INTEGER(IntKi), PARAMETER :: M1N4RDye = 1300 + INTEGER(IntKi), PARAMETER :: M1N5RDye = 1301 + INTEGER(IntKi), PARAMETER :: M1N6RDye = 1302 + INTEGER(IntKi), PARAMETER :: M1N7RDye = 1303 + INTEGER(IntKi), PARAMETER :: M1N8RDye = 1304 + INTEGER(IntKi), PARAMETER :: M1N9RDye = 1305 + INTEGER(IntKi), PARAMETER :: M2N1RDye = 1306 + INTEGER(IntKi), PARAMETER :: M2N2RDye = 1307 + INTEGER(IntKi), PARAMETER :: M2N3RDye = 1308 + INTEGER(IntKi), PARAMETER :: M2N4RDye = 1309 + INTEGER(IntKi), PARAMETER :: M2N5RDye = 1310 + INTEGER(IntKi), PARAMETER :: M2N6RDye = 1311 + INTEGER(IntKi), PARAMETER :: M2N7RDye = 1312 + INTEGER(IntKi), PARAMETER :: M2N8RDye = 1313 + INTEGER(IntKi), PARAMETER :: M2N9RDye = 1314 + INTEGER(IntKi), PARAMETER :: M3N1RDye = 1315 + INTEGER(IntKi), PARAMETER :: M3N2RDye = 1316 + INTEGER(IntKi), PARAMETER :: M3N3RDye = 1317 + INTEGER(IntKi), PARAMETER :: M3N4RDye = 1318 + INTEGER(IntKi), PARAMETER :: M3N5RDye = 1319 + INTEGER(IntKi), PARAMETER :: M3N6RDye = 1320 + INTEGER(IntKi), PARAMETER :: M3N7RDye = 1321 + INTEGER(IntKi), PARAMETER :: M3N8RDye = 1322 + INTEGER(IntKi), PARAMETER :: M3N9RDye = 1323 + INTEGER(IntKi), PARAMETER :: M4N1RDye = 1324 + INTEGER(IntKi), PARAMETER :: M4N2RDye = 1325 + INTEGER(IntKi), PARAMETER :: M4N3RDye = 1326 + INTEGER(IntKi), PARAMETER :: M4N4RDye = 1327 + INTEGER(IntKi), PARAMETER :: M4N5RDye = 1328 + INTEGER(IntKi), PARAMETER :: M4N6RDye = 1329 + INTEGER(IntKi), PARAMETER :: M4N7RDye = 1330 + INTEGER(IntKi), PARAMETER :: M4N8RDye = 1331 + INTEGER(IntKi), PARAMETER :: M4N9RDye = 1332 + INTEGER(IntKi), PARAMETER :: M5N1RDye = 1333 + INTEGER(IntKi), PARAMETER :: M5N2RDye = 1334 + INTEGER(IntKi), PARAMETER :: M5N3RDye = 1335 + INTEGER(IntKi), PARAMETER :: M5N4RDye = 1336 + INTEGER(IntKi), PARAMETER :: M5N5RDye = 1337 + INTEGER(IntKi), PARAMETER :: M5N6RDye = 1338 + INTEGER(IntKi), PARAMETER :: M5N7RDye = 1339 + INTEGER(IntKi), PARAMETER :: M5N8RDye = 1340 + INTEGER(IntKi), PARAMETER :: M5N9RDye = 1341 + INTEGER(IntKi), PARAMETER :: M6N1RDye = 1342 + INTEGER(IntKi), PARAMETER :: M6N2RDye = 1343 + INTEGER(IntKi), PARAMETER :: M6N3RDye = 1344 + INTEGER(IntKi), PARAMETER :: M6N4RDye = 1345 + INTEGER(IntKi), PARAMETER :: M6N5RDye = 1346 + INTEGER(IntKi), PARAMETER :: M6N6RDye = 1347 + INTEGER(IntKi), PARAMETER :: M6N7RDye = 1348 + INTEGER(IntKi), PARAMETER :: M6N8RDye = 1349 + INTEGER(IntKi), PARAMETER :: M6N9RDye = 1350 + INTEGER(IntKi), PARAMETER :: M7N1RDye = 1351 + INTEGER(IntKi), PARAMETER :: M7N2RDye = 1352 + INTEGER(IntKi), PARAMETER :: M7N3RDye = 1353 + INTEGER(IntKi), PARAMETER :: M7N4RDye = 1354 + INTEGER(IntKi), PARAMETER :: M7N5RDye = 1355 + INTEGER(IntKi), PARAMETER :: M7N6RDye = 1356 + INTEGER(IntKi), PARAMETER :: M7N7RDye = 1357 + INTEGER(IntKi), PARAMETER :: M7N8RDye = 1358 + INTEGER(IntKi), PARAMETER :: M7N9RDye = 1359 + INTEGER(IntKi), PARAMETER :: M8N1RDye = 1360 + INTEGER(IntKi), PARAMETER :: M8N2RDye = 1361 + INTEGER(IntKi), PARAMETER :: M8N3RDye = 1362 + INTEGER(IntKi), PARAMETER :: M8N4RDye = 1363 + INTEGER(IntKi), PARAMETER :: M8N5RDye = 1364 + INTEGER(IntKi), PARAMETER :: M8N6RDye = 1365 + INTEGER(IntKi), PARAMETER :: M8N7RDye = 1366 + INTEGER(IntKi), PARAMETER :: M8N8RDye = 1367 + INTEGER(IntKi), PARAMETER :: M8N9RDye = 1368 + INTEGER(IntKi), PARAMETER :: M9N1RDye = 1369 + INTEGER(IntKi), PARAMETER :: M9N2RDye = 1370 + INTEGER(IntKi), PARAMETER :: M9N3RDye = 1371 + INTEGER(IntKi), PARAMETER :: M9N4RDye = 1372 + INTEGER(IntKi), PARAMETER :: M9N5RDye = 1373 + INTEGER(IntKi), PARAMETER :: M9N6RDye = 1374 + INTEGER(IntKi), PARAMETER :: M9N7RDye = 1375 + INTEGER(IntKi), PARAMETER :: M9N8RDye = 1376 + INTEGER(IntKi), PARAMETER :: M9N9RDye = 1377 + INTEGER(IntKi), PARAMETER :: M1N1RDze = 1378 + INTEGER(IntKi), PARAMETER :: M1N2RDze = 1379 + INTEGER(IntKi), PARAMETER :: M1N3RDze = 1380 + INTEGER(IntKi), PARAMETER :: M1N4RDze = 1381 + INTEGER(IntKi), PARAMETER :: M1N5RDze = 1382 + INTEGER(IntKi), PARAMETER :: M1N6RDze = 1383 + INTEGER(IntKi), PARAMETER :: M1N7RDze = 1384 + INTEGER(IntKi), PARAMETER :: M1N8RDze = 1385 + INTEGER(IntKi), PARAMETER :: M1N9RDze = 1386 + INTEGER(IntKi), PARAMETER :: M2N1RDze = 1387 + INTEGER(IntKi), PARAMETER :: M2N2RDze = 1388 + INTEGER(IntKi), PARAMETER :: M2N3RDze = 1389 + INTEGER(IntKi), PARAMETER :: M2N4RDze = 1390 + INTEGER(IntKi), PARAMETER :: M2N5RDze = 1391 + INTEGER(IntKi), PARAMETER :: M2N6RDze = 1392 + INTEGER(IntKi), PARAMETER :: M2N7RDze = 1393 + INTEGER(IntKi), PARAMETER :: M2N8RDze = 1394 + INTEGER(IntKi), PARAMETER :: M2N9RDze = 1395 + INTEGER(IntKi), PARAMETER :: M3N1RDze = 1396 + INTEGER(IntKi), PARAMETER :: M3N2RDze = 1397 + INTEGER(IntKi), PARAMETER :: M3N3RDze = 1398 + INTEGER(IntKi), PARAMETER :: M3N4RDze = 1399 + INTEGER(IntKi), PARAMETER :: M3N5RDze = 1400 + INTEGER(IntKi), PARAMETER :: M3N6RDze = 1401 + INTEGER(IntKi), PARAMETER :: M3N7RDze = 1402 + INTEGER(IntKi), PARAMETER :: M3N8RDze = 1403 + INTEGER(IntKi), PARAMETER :: M3N9RDze = 1404 + INTEGER(IntKi), PARAMETER :: M4N1RDze = 1405 + INTEGER(IntKi), PARAMETER :: M4N2RDze = 1406 + INTEGER(IntKi), PARAMETER :: M4N3RDze = 1407 + INTEGER(IntKi), PARAMETER :: M4N4RDze = 1408 + INTEGER(IntKi), PARAMETER :: M4N5RDze = 1409 + INTEGER(IntKi), PARAMETER :: M4N6RDze = 1410 + INTEGER(IntKi), PARAMETER :: M4N7RDze = 1411 + INTEGER(IntKi), PARAMETER :: M4N8RDze = 1412 + INTEGER(IntKi), PARAMETER :: M4N9RDze = 1413 + INTEGER(IntKi), PARAMETER :: M5N1RDze = 1414 + INTEGER(IntKi), PARAMETER :: M5N2RDze = 1415 + INTEGER(IntKi), PARAMETER :: M5N3RDze = 1416 + INTEGER(IntKi), PARAMETER :: M5N4RDze = 1417 + INTEGER(IntKi), PARAMETER :: M5N5RDze = 1418 + INTEGER(IntKi), PARAMETER :: M5N6RDze = 1419 + INTEGER(IntKi), PARAMETER :: M5N7RDze = 1420 + INTEGER(IntKi), PARAMETER :: M5N8RDze = 1421 + INTEGER(IntKi), PARAMETER :: M5N9RDze = 1422 + INTEGER(IntKi), PARAMETER :: M6N1RDze = 1423 + INTEGER(IntKi), PARAMETER :: M6N2RDze = 1424 + INTEGER(IntKi), PARAMETER :: M6N3RDze = 1425 + INTEGER(IntKi), PARAMETER :: M6N4RDze = 1426 + INTEGER(IntKi), PARAMETER :: M6N5RDze = 1427 + INTEGER(IntKi), PARAMETER :: M6N6RDze = 1428 + INTEGER(IntKi), PARAMETER :: M6N7RDze = 1429 + INTEGER(IntKi), PARAMETER :: M6N8RDze = 1430 + INTEGER(IntKi), PARAMETER :: M6N9RDze = 1431 + INTEGER(IntKi), PARAMETER :: M7N1RDze = 1432 + INTEGER(IntKi), PARAMETER :: M7N2RDze = 1433 + INTEGER(IntKi), PARAMETER :: M7N3RDze = 1434 + INTEGER(IntKi), PARAMETER :: M7N4RDze = 1435 + INTEGER(IntKi), PARAMETER :: M7N5RDze = 1436 + INTEGER(IntKi), PARAMETER :: M7N6RDze = 1437 + INTEGER(IntKi), PARAMETER :: M7N7RDze = 1438 + INTEGER(IntKi), PARAMETER :: M7N8RDze = 1439 + INTEGER(IntKi), PARAMETER :: M7N9RDze = 1440 + INTEGER(IntKi), PARAMETER :: M8N1RDze = 1441 + INTEGER(IntKi), PARAMETER :: M8N2RDze = 1442 + INTEGER(IntKi), PARAMETER :: M8N3RDze = 1443 + INTEGER(IntKi), PARAMETER :: M8N4RDze = 1444 + INTEGER(IntKi), PARAMETER :: M8N5RDze = 1445 + INTEGER(IntKi), PARAMETER :: M8N6RDze = 1446 + INTEGER(IntKi), PARAMETER :: M8N7RDze = 1447 + INTEGER(IntKi), PARAMETER :: M8N8RDze = 1448 + INTEGER(IntKi), PARAMETER :: M8N9RDze = 1449 + INTEGER(IntKi), PARAMETER :: M9N1RDze = 1450 + INTEGER(IntKi), PARAMETER :: M9N2RDze = 1451 + INTEGER(IntKi), PARAMETER :: M9N3RDze = 1452 + INTEGER(IntKi), PARAMETER :: M9N4RDze = 1453 + INTEGER(IntKi), PARAMETER :: M9N5RDze = 1454 + INTEGER(IntKi), PARAMETER :: M9N6RDze = 1455 + INTEGER(IntKi), PARAMETER :: M9N7RDze = 1456 + INTEGER(IntKi), PARAMETER :: M9N8RDze = 1457 + INTEGER(IntKi), PARAMETER :: M9N9RDze = 1458 + + + ! Accelerations: + + INTEGER(IntKi), PARAMETER :: M1N1TAxe = 1459 + INTEGER(IntKi), PARAMETER :: M1N2TAxe = 1460 + INTEGER(IntKi), PARAMETER :: M1N3TAxe = 1461 + INTEGER(IntKi), PARAMETER :: M1N4TAxe = 1462 + INTEGER(IntKi), PARAMETER :: M1N5TAxe = 1463 + INTEGER(IntKi), PARAMETER :: M1N6TAxe = 1464 + INTEGER(IntKi), PARAMETER :: M1N7TAxe = 1465 + INTEGER(IntKi), PARAMETER :: M1N8TAxe = 1466 + INTEGER(IntKi), PARAMETER :: M1N9TAxe = 1467 + INTEGER(IntKi), PARAMETER :: M2N1TAxe = 1468 + INTEGER(IntKi), PARAMETER :: M2N2TAxe = 1469 + INTEGER(IntKi), PARAMETER :: M2N3TAxe = 1470 + INTEGER(IntKi), PARAMETER :: M2N4TAxe = 1471 + INTEGER(IntKi), PARAMETER :: M2N5TAxe = 1472 + INTEGER(IntKi), PARAMETER :: M2N6TAxe = 1473 + INTEGER(IntKi), PARAMETER :: M2N7TAxe = 1474 + INTEGER(IntKi), PARAMETER :: M2N8TAxe = 1475 + INTEGER(IntKi), PARAMETER :: M2N9TAxe = 1476 + INTEGER(IntKi), PARAMETER :: M3N1TAxe = 1477 + INTEGER(IntKi), PARAMETER :: M3N2TAxe = 1478 + INTEGER(IntKi), PARAMETER :: M3N3TAxe = 1479 + INTEGER(IntKi), PARAMETER :: M3N4TAxe = 1480 + INTEGER(IntKi), PARAMETER :: M3N5TAxe = 1481 + INTEGER(IntKi), PARAMETER :: M3N6TAxe = 1482 + INTEGER(IntKi), PARAMETER :: M3N7TAxe = 1483 + INTEGER(IntKi), PARAMETER :: M3N8TAxe = 1484 + INTEGER(IntKi), PARAMETER :: M3N9TAxe = 1485 + INTEGER(IntKi), PARAMETER :: M4N1TAxe = 1486 + INTEGER(IntKi), PARAMETER :: M4N2TAxe = 1487 + INTEGER(IntKi), PARAMETER :: M4N3TAxe = 1488 + INTEGER(IntKi), PARAMETER :: M4N4TAxe = 1489 + INTEGER(IntKi), PARAMETER :: M4N5TAxe = 1490 + INTEGER(IntKi), PARAMETER :: M4N6TAxe = 1491 + INTEGER(IntKi), PARAMETER :: M4N7TAxe = 1492 + INTEGER(IntKi), PARAMETER :: M4N8TAxe = 1493 + INTEGER(IntKi), PARAMETER :: M4N9TAxe = 1494 + INTEGER(IntKi), PARAMETER :: M5N1TAxe = 1495 + INTEGER(IntKi), PARAMETER :: M5N2TAxe = 1496 + INTEGER(IntKi), PARAMETER :: M5N3TAxe = 1497 + INTEGER(IntKi), PARAMETER :: M5N4TAxe = 1498 + INTEGER(IntKi), PARAMETER :: M5N5TAxe = 1499 + INTEGER(IntKi), PARAMETER :: M5N6TAxe = 1500 + INTEGER(IntKi), PARAMETER :: M5N7TAxe = 1501 + INTEGER(IntKi), PARAMETER :: M5N8TAxe = 1502 + INTEGER(IntKi), PARAMETER :: M5N9TAxe = 1503 + INTEGER(IntKi), PARAMETER :: M6N1TAxe = 1504 + INTEGER(IntKi), PARAMETER :: M6N2TAxe = 1505 + INTEGER(IntKi), PARAMETER :: M6N3TAxe = 1506 + INTEGER(IntKi), PARAMETER :: M6N4TAxe = 1507 + INTEGER(IntKi), PARAMETER :: M6N5TAxe = 1508 + INTEGER(IntKi), PARAMETER :: M6N6TAxe = 1509 + INTEGER(IntKi), PARAMETER :: M6N7TAxe = 1510 + INTEGER(IntKi), PARAMETER :: M6N8TAxe = 1511 + INTEGER(IntKi), PARAMETER :: M6N9TAxe = 1512 + INTEGER(IntKi), PARAMETER :: M7N1TAxe = 1513 + INTEGER(IntKi), PARAMETER :: M7N2TAxe = 1514 + INTEGER(IntKi), PARAMETER :: M7N3TAxe = 1515 + INTEGER(IntKi), PARAMETER :: M7N4TAxe = 1516 + INTEGER(IntKi), PARAMETER :: M7N5TAxe = 1517 + INTEGER(IntKi), PARAMETER :: M7N6TAxe = 1518 + INTEGER(IntKi), PARAMETER :: M7N7TAxe = 1519 + INTEGER(IntKi), PARAMETER :: M7N8TAxe = 1520 + INTEGER(IntKi), PARAMETER :: M7N9TAxe = 1521 + INTEGER(IntKi), PARAMETER :: M8N1TAxe = 1522 + INTEGER(IntKi), PARAMETER :: M8N2TAxe = 1523 + INTEGER(IntKi), PARAMETER :: M8N3TAxe = 1524 + INTEGER(IntKi), PARAMETER :: M8N4TAxe = 1525 + INTEGER(IntKi), PARAMETER :: M8N5TAxe = 1526 + INTEGER(IntKi), PARAMETER :: M8N6TAxe = 1527 + INTEGER(IntKi), PARAMETER :: M8N7TAxe = 1528 + INTEGER(IntKi), PARAMETER :: M8N8TAxe = 1529 + INTEGER(IntKi), PARAMETER :: M8N9TAxe = 1530 + INTEGER(IntKi), PARAMETER :: M9N1TAxe = 1531 + INTEGER(IntKi), PARAMETER :: M9N2TAxe = 1532 + INTEGER(IntKi), PARAMETER :: M9N3TAxe = 1533 + INTEGER(IntKi), PARAMETER :: M9N4TAxe = 1534 + INTEGER(IntKi), PARAMETER :: M9N5TAxe = 1535 + INTEGER(IntKi), PARAMETER :: M9N6TAxe = 1536 + INTEGER(IntKi), PARAMETER :: M9N7TAxe = 1537 + INTEGER(IntKi), PARAMETER :: M9N8TAxe = 1538 + INTEGER(IntKi), PARAMETER :: M9N9TAxe = 1539 + INTEGER(IntKi), PARAMETER :: M1N1TAye = 1540 + INTEGER(IntKi), PARAMETER :: M1N2TAye = 1541 + INTEGER(IntKi), PARAMETER :: M1N3TAye = 1542 + INTEGER(IntKi), PARAMETER :: M1N4TAye = 1543 + INTEGER(IntKi), PARAMETER :: M1N5TAye = 1544 + INTEGER(IntKi), PARAMETER :: M1N6TAye = 1545 + INTEGER(IntKi), PARAMETER :: M1N7TAye = 1546 + INTEGER(IntKi), PARAMETER :: M1N8TAye = 1547 + INTEGER(IntKi), PARAMETER :: M1N9TAye = 1548 + INTEGER(IntKi), PARAMETER :: M2N1TAye = 1549 + INTEGER(IntKi), PARAMETER :: M2N2TAye = 1550 + INTEGER(IntKi), PARAMETER :: M2N3TAye = 1551 + INTEGER(IntKi), PARAMETER :: M2N4TAye = 1552 + INTEGER(IntKi), PARAMETER :: M2N5TAye = 1553 + INTEGER(IntKi), PARAMETER :: M2N6TAye = 1554 + INTEGER(IntKi), PARAMETER :: M2N7TAye = 1555 + INTEGER(IntKi), PARAMETER :: M2N8TAye = 1556 + INTEGER(IntKi), PARAMETER :: M2N9TAye = 1557 + INTEGER(IntKi), PARAMETER :: M3N1TAye = 1558 + INTEGER(IntKi), PARAMETER :: M3N2TAye = 1559 + INTEGER(IntKi), PARAMETER :: M3N3TAye = 1560 + INTEGER(IntKi), PARAMETER :: M3N4TAye = 1561 + INTEGER(IntKi), PARAMETER :: M3N5TAye = 1562 + INTEGER(IntKi), PARAMETER :: M3N6TAye = 1563 + INTEGER(IntKi), PARAMETER :: M3N7TAye = 1564 + INTEGER(IntKi), PARAMETER :: M3N8TAye = 1565 + INTEGER(IntKi), PARAMETER :: M3N9TAye = 1566 + INTEGER(IntKi), PARAMETER :: M4N1TAye = 1567 + INTEGER(IntKi), PARAMETER :: M4N2TAye = 1568 + INTEGER(IntKi), PARAMETER :: M4N3TAye = 1569 + INTEGER(IntKi), PARAMETER :: M4N4TAye = 1570 + INTEGER(IntKi), PARAMETER :: M4N5TAye = 1571 + INTEGER(IntKi), PARAMETER :: M4N6TAye = 1572 + INTEGER(IntKi), PARAMETER :: M4N7TAye = 1573 + INTEGER(IntKi), PARAMETER :: M4N8TAye = 1574 + INTEGER(IntKi), PARAMETER :: M4N9TAye = 1575 + INTEGER(IntKi), PARAMETER :: M5N1TAye = 1576 + INTEGER(IntKi), PARAMETER :: M5N2TAye = 1577 + INTEGER(IntKi), PARAMETER :: M5N3TAye = 1578 + INTEGER(IntKi), PARAMETER :: M5N4TAye = 1579 + INTEGER(IntKi), PARAMETER :: M5N5TAye = 1580 + INTEGER(IntKi), PARAMETER :: M5N6TAye = 1581 + INTEGER(IntKi), PARAMETER :: M5N7TAye = 1582 + INTEGER(IntKi), PARAMETER :: M5N8TAye = 1583 + INTEGER(IntKi), PARAMETER :: M5N9TAye = 1584 + INTEGER(IntKi), PARAMETER :: M6N1TAye = 1585 + INTEGER(IntKi), PARAMETER :: M6N2TAye = 1586 + INTEGER(IntKi), PARAMETER :: M6N3TAye = 1587 + INTEGER(IntKi), PARAMETER :: M6N4TAye = 1588 + INTEGER(IntKi), PARAMETER :: M6N5TAye = 1589 + INTEGER(IntKi), PARAMETER :: M6N6TAye = 1590 + INTEGER(IntKi), PARAMETER :: M6N7TAye = 1591 + INTEGER(IntKi), PARAMETER :: M6N8TAye = 1592 + INTEGER(IntKi), PARAMETER :: M6N9TAye = 1593 + INTEGER(IntKi), PARAMETER :: M7N1TAye = 1594 + INTEGER(IntKi), PARAMETER :: M7N2TAye = 1595 + INTEGER(IntKi), PARAMETER :: M7N3TAye = 1596 + INTEGER(IntKi), PARAMETER :: M7N4TAye = 1597 + INTEGER(IntKi), PARAMETER :: M7N5TAye = 1598 + INTEGER(IntKi), PARAMETER :: M7N6TAye = 1599 + INTEGER(IntKi), PARAMETER :: M7N7TAye = 1600 + INTEGER(IntKi), PARAMETER :: M7N8TAye = 1601 + INTEGER(IntKi), PARAMETER :: M7N9TAye = 1602 + INTEGER(IntKi), PARAMETER :: M8N1TAye = 1603 + INTEGER(IntKi), PARAMETER :: M8N2TAye = 1604 + INTEGER(IntKi), PARAMETER :: M8N3TAye = 1605 + INTEGER(IntKi), PARAMETER :: M8N4TAye = 1606 + INTEGER(IntKi), PARAMETER :: M8N5TAye = 1607 + INTEGER(IntKi), PARAMETER :: M8N6TAye = 1608 + INTEGER(IntKi), PARAMETER :: M8N7TAye = 1609 + INTEGER(IntKi), PARAMETER :: M8N8TAye = 1610 + INTEGER(IntKi), PARAMETER :: M8N9TAye = 1611 + INTEGER(IntKi), PARAMETER :: M9N1TAye = 1612 + INTEGER(IntKi), PARAMETER :: M9N2TAye = 1613 + INTEGER(IntKi), PARAMETER :: M9N3TAye = 1614 + INTEGER(IntKi), PARAMETER :: M9N4TAye = 1615 + INTEGER(IntKi), PARAMETER :: M9N5TAye = 1616 + INTEGER(IntKi), PARAMETER :: M9N6TAye = 1617 + INTEGER(IntKi), PARAMETER :: M9N7TAye = 1618 + INTEGER(IntKi), PARAMETER :: M9N8TAye = 1619 + INTEGER(IntKi), PARAMETER :: M9N9TAye = 1620 + INTEGER(IntKi), PARAMETER :: M1N1TAze = 1621 + INTEGER(IntKi), PARAMETER :: M1N2TAze = 1622 + INTEGER(IntKi), PARAMETER :: M1N3TAze = 1623 + INTEGER(IntKi), PARAMETER :: M1N4TAze = 1624 + INTEGER(IntKi), PARAMETER :: M1N5TAze = 1625 + INTEGER(IntKi), PARAMETER :: M1N6TAze = 1626 + INTEGER(IntKi), PARAMETER :: M1N7TAze = 1627 + INTEGER(IntKi), PARAMETER :: M1N8TAze = 1628 + INTEGER(IntKi), PARAMETER :: M1N9TAze = 1629 + INTEGER(IntKi), PARAMETER :: M2N1TAze = 1630 + INTEGER(IntKi), PARAMETER :: M2N2TAze = 1631 + INTEGER(IntKi), PARAMETER :: M2N3TAze = 1632 + INTEGER(IntKi), PARAMETER :: M2N4TAze = 1633 + INTEGER(IntKi), PARAMETER :: M2N5TAze = 1634 + INTEGER(IntKi), PARAMETER :: M2N6TAze = 1635 + INTEGER(IntKi), PARAMETER :: M2N7TAze = 1636 + INTEGER(IntKi), PARAMETER :: M2N8TAze = 1637 + INTEGER(IntKi), PARAMETER :: M2N9TAze = 1638 + INTEGER(IntKi), PARAMETER :: M3N1TAze = 1639 + INTEGER(IntKi), PARAMETER :: M3N2TAze = 1640 + INTEGER(IntKi), PARAMETER :: M3N3TAze = 1641 + INTEGER(IntKi), PARAMETER :: M3N4TAze = 1642 + INTEGER(IntKi), PARAMETER :: M3N5TAze = 1643 + INTEGER(IntKi), PARAMETER :: M3N6TAze = 1644 + INTEGER(IntKi), PARAMETER :: M3N7TAze = 1645 + INTEGER(IntKi), PARAMETER :: M3N8TAze = 1646 + INTEGER(IntKi), PARAMETER :: M3N9TAze = 1647 + INTEGER(IntKi), PARAMETER :: M4N1TAze = 1648 + INTEGER(IntKi), PARAMETER :: M4N2TAze = 1649 + INTEGER(IntKi), PARAMETER :: M4N3TAze = 1650 + INTEGER(IntKi), PARAMETER :: M4N4TAze = 1651 + INTEGER(IntKi), PARAMETER :: M4N5TAze = 1652 + INTEGER(IntKi), PARAMETER :: M4N6TAze = 1653 + INTEGER(IntKi), PARAMETER :: M4N7TAze = 1654 + INTEGER(IntKi), PARAMETER :: M4N8TAze = 1655 + INTEGER(IntKi), PARAMETER :: M4N9TAze = 1656 + INTEGER(IntKi), PARAMETER :: M5N1TAze = 1657 + INTEGER(IntKi), PARAMETER :: M5N2TAze = 1658 + INTEGER(IntKi), PARAMETER :: M5N3TAze = 1659 + INTEGER(IntKi), PARAMETER :: M5N4TAze = 1660 + INTEGER(IntKi), PARAMETER :: M5N5TAze = 1661 + INTEGER(IntKi), PARAMETER :: M5N6TAze = 1662 + INTEGER(IntKi), PARAMETER :: M5N7TAze = 1663 + INTEGER(IntKi), PARAMETER :: M5N8TAze = 1664 + INTEGER(IntKi), PARAMETER :: M5N9TAze = 1665 + INTEGER(IntKi), PARAMETER :: M6N1TAze = 1666 + INTEGER(IntKi), PARAMETER :: M6N2TAze = 1667 + INTEGER(IntKi), PARAMETER :: M6N3TAze = 1668 + INTEGER(IntKi), PARAMETER :: M6N4TAze = 1669 + INTEGER(IntKi), PARAMETER :: M6N5TAze = 1670 + INTEGER(IntKi), PARAMETER :: M6N6TAze = 1671 + INTEGER(IntKi), PARAMETER :: M6N7TAze = 1672 + INTEGER(IntKi), PARAMETER :: M6N8TAze = 1673 + INTEGER(IntKi), PARAMETER :: M6N9TAze = 1674 + INTEGER(IntKi), PARAMETER :: M7N1TAze = 1675 + INTEGER(IntKi), PARAMETER :: M7N2TAze = 1676 + INTEGER(IntKi), PARAMETER :: M7N3TAze = 1677 + INTEGER(IntKi), PARAMETER :: M7N4TAze = 1678 + INTEGER(IntKi), PARAMETER :: M7N5TAze = 1679 + INTEGER(IntKi), PARAMETER :: M7N6TAze = 1680 + INTEGER(IntKi), PARAMETER :: M7N7TAze = 1681 + INTEGER(IntKi), PARAMETER :: M7N8TAze = 1682 + INTEGER(IntKi), PARAMETER :: M7N9TAze = 1683 + INTEGER(IntKi), PARAMETER :: M8N1TAze = 1684 + INTEGER(IntKi), PARAMETER :: M8N2TAze = 1685 + INTEGER(IntKi), PARAMETER :: M8N3TAze = 1686 + INTEGER(IntKi), PARAMETER :: M8N4TAze = 1687 + INTEGER(IntKi), PARAMETER :: M8N5TAze = 1688 + INTEGER(IntKi), PARAMETER :: M8N6TAze = 1689 + INTEGER(IntKi), PARAMETER :: M8N7TAze = 1690 + INTEGER(IntKi), PARAMETER :: M8N8TAze = 1691 + INTEGER(IntKi), PARAMETER :: M8N9TAze = 1692 + INTEGER(IntKi), PARAMETER :: M9N1TAze = 1693 + INTEGER(IntKi), PARAMETER :: M9N2TAze = 1694 + INTEGER(IntKi), PARAMETER :: M9N3TAze = 1695 + INTEGER(IntKi), PARAMETER :: M9N4TAze = 1696 + INTEGER(IntKi), PARAMETER :: M9N5TAze = 1697 + INTEGER(IntKi), PARAMETER :: M9N6TAze = 1698 + INTEGER(IntKi), PARAMETER :: M9N7TAze = 1699 + INTEGER(IntKi), PARAMETER :: M9N8TAze = 1700 + INTEGER(IntKi), PARAMETER :: M9N9TAze = 1701 + INTEGER(IntKi), PARAMETER :: M1N1RAxe = 1702 + INTEGER(IntKi), PARAMETER :: M1N2RAxe = 1703 + INTEGER(IntKi), PARAMETER :: M1N3RAxe = 1704 + INTEGER(IntKi), PARAMETER :: M1N4RAxe = 1705 + INTEGER(IntKi), PARAMETER :: M1N5RAxe = 1706 + INTEGER(IntKi), PARAMETER :: M1N6RAxe = 1707 + INTEGER(IntKi), PARAMETER :: M1N7RAxe = 1708 + INTEGER(IntKi), PARAMETER :: M1N8RAxe = 1709 + INTEGER(IntKi), PARAMETER :: M1N9RAxe = 1710 + INTEGER(IntKi), PARAMETER :: M2N1RAxe = 1711 + INTEGER(IntKi), PARAMETER :: M2N2RAxe = 1712 + INTEGER(IntKi), PARAMETER :: M2N3RAxe = 1713 + INTEGER(IntKi), PARAMETER :: M2N4RAxe = 1714 + INTEGER(IntKi), PARAMETER :: M2N5RAxe = 1715 + INTEGER(IntKi), PARAMETER :: M2N6RAxe = 1716 + INTEGER(IntKi), PARAMETER :: M2N7RAxe = 1717 + INTEGER(IntKi), PARAMETER :: M2N8RAxe = 1718 + INTEGER(IntKi), PARAMETER :: M2N9RAxe = 1719 + INTEGER(IntKi), PARAMETER :: M3N1RAxe = 1720 + INTEGER(IntKi), PARAMETER :: M3N2RAxe = 1721 + INTEGER(IntKi), PARAMETER :: M3N3RAxe = 1722 + INTEGER(IntKi), PARAMETER :: M3N4RAxe = 1723 + INTEGER(IntKi), PARAMETER :: M3N5RAxe = 1724 + INTEGER(IntKi), PARAMETER :: M3N6RAxe = 1725 + INTEGER(IntKi), PARAMETER :: M3N7RAxe = 1726 + INTEGER(IntKi), PARAMETER :: M3N8RAxe = 1727 + INTEGER(IntKi), PARAMETER :: M3N9RAxe = 1728 + INTEGER(IntKi), PARAMETER :: M4N1RAxe = 1729 + INTEGER(IntKi), PARAMETER :: M4N2RAxe = 1730 + INTEGER(IntKi), PARAMETER :: M4N3RAxe = 1731 + INTEGER(IntKi), PARAMETER :: M4N4RAxe = 1732 + INTEGER(IntKi), PARAMETER :: M4N5RAxe = 1733 + INTEGER(IntKi), PARAMETER :: M4N6RAxe = 1734 + INTEGER(IntKi), PARAMETER :: M4N7RAxe = 1735 + INTEGER(IntKi), PARAMETER :: M4N8RAxe = 1736 + INTEGER(IntKi), PARAMETER :: M4N9RAxe = 1737 + INTEGER(IntKi), PARAMETER :: M5N1RAxe = 1738 + INTEGER(IntKi), PARAMETER :: M5N2RAxe = 1739 + INTEGER(IntKi), PARAMETER :: M5N3RAxe = 1740 + INTEGER(IntKi), PARAMETER :: M5N4RAxe = 1741 + INTEGER(IntKi), PARAMETER :: M5N5RAxe = 1742 + INTEGER(IntKi), PARAMETER :: M5N6RAxe = 1743 + INTEGER(IntKi), PARAMETER :: M5N7RAxe = 1744 + INTEGER(IntKi), PARAMETER :: M5N8RAxe = 1745 + INTEGER(IntKi), PARAMETER :: M5N9RAxe = 1746 + INTEGER(IntKi), PARAMETER :: M6N1RAxe = 1747 + INTEGER(IntKi), PARAMETER :: M6N2RAxe = 1748 + INTEGER(IntKi), PARAMETER :: M6N3RAxe = 1749 + INTEGER(IntKi), PARAMETER :: M6N4RAxe = 1750 + INTEGER(IntKi), PARAMETER :: M6N5RAxe = 1751 + INTEGER(IntKi), PARAMETER :: M6N6RAxe = 1752 + INTEGER(IntKi), PARAMETER :: M6N7RAxe = 1753 + INTEGER(IntKi), PARAMETER :: M6N8RAxe = 1754 + INTEGER(IntKi), PARAMETER :: M6N9RAxe = 1755 + INTEGER(IntKi), PARAMETER :: M7N1RAxe = 1756 + INTEGER(IntKi), PARAMETER :: M7N2RAxe = 1757 + INTEGER(IntKi), PARAMETER :: M7N3RAxe = 1758 + INTEGER(IntKi), PARAMETER :: M7N4RAxe = 1759 + INTEGER(IntKi), PARAMETER :: M7N5RAxe = 1760 + INTEGER(IntKi), PARAMETER :: M7N6RAxe = 1761 + INTEGER(IntKi), PARAMETER :: M7N7RAxe = 1762 + INTEGER(IntKi), PARAMETER :: M7N8RAxe = 1763 + INTEGER(IntKi), PARAMETER :: M7N9RAxe = 1764 + INTEGER(IntKi), PARAMETER :: M8N1RAxe = 1765 + INTEGER(IntKi), PARAMETER :: M8N2RAxe = 1766 + INTEGER(IntKi), PARAMETER :: M8N3RAxe = 1767 + INTEGER(IntKi), PARAMETER :: M8N4RAxe = 1768 + INTEGER(IntKi), PARAMETER :: M8N5RAxe = 1769 + INTEGER(IntKi), PARAMETER :: M8N6RAxe = 1770 + INTEGER(IntKi), PARAMETER :: M8N7RAxe = 1771 + INTEGER(IntKi), PARAMETER :: M8N8RAxe = 1772 + INTEGER(IntKi), PARAMETER :: M8N9RAxe = 1773 + INTEGER(IntKi), PARAMETER :: M9N1RAxe = 1774 + INTEGER(IntKi), PARAMETER :: M9N2RAxe = 1775 + INTEGER(IntKi), PARAMETER :: M9N3RAxe = 1776 + INTEGER(IntKi), PARAMETER :: M9N4RAxe = 1777 + INTEGER(IntKi), PARAMETER :: M9N5RAxe = 1778 + INTEGER(IntKi), PARAMETER :: M9N6RAxe = 1779 + INTEGER(IntKi), PARAMETER :: M9N7RAxe = 1780 + INTEGER(IntKi), PARAMETER :: M9N8RAxe = 1781 + INTEGER(IntKi), PARAMETER :: M9N9RAxe = 1782 + INTEGER(IntKi), PARAMETER :: M1N1RAye = 1783 + INTEGER(IntKi), PARAMETER :: M1N2RAye = 1784 + INTEGER(IntKi), PARAMETER :: M1N3RAye = 1785 + INTEGER(IntKi), PARAMETER :: M1N4RAye = 1786 + INTEGER(IntKi), PARAMETER :: M1N5RAye = 1787 + INTEGER(IntKi), PARAMETER :: M1N6RAye = 1788 + INTEGER(IntKi), PARAMETER :: M1N7RAye = 1789 + INTEGER(IntKi), PARAMETER :: M1N8RAye = 1790 + INTEGER(IntKi), PARAMETER :: M1N9RAye = 1791 + INTEGER(IntKi), PARAMETER :: M2N1RAye = 1792 + INTEGER(IntKi), PARAMETER :: M2N2RAye = 1793 + INTEGER(IntKi), PARAMETER :: M2N3RAye = 1794 + INTEGER(IntKi), PARAMETER :: M2N4RAye = 1795 + INTEGER(IntKi), PARAMETER :: M2N5RAye = 1796 + INTEGER(IntKi), PARAMETER :: M2N6RAye = 1797 + INTEGER(IntKi), PARAMETER :: M2N7RAye = 1798 + INTEGER(IntKi), PARAMETER :: M2N8RAye = 1799 + INTEGER(IntKi), PARAMETER :: M2N9RAye = 1800 + INTEGER(IntKi), PARAMETER :: M3N1RAye = 1801 + INTEGER(IntKi), PARAMETER :: M3N2RAye = 1802 + INTEGER(IntKi), PARAMETER :: M3N3RAye = 1803 + INTEGER(IntKi), PARAMETER :: M3N4RAye = 1804 + INTEGER(IntKi), PARAMETER :: M3N5RAye = 1805 + INTEGER(IntKi), PARAMETER :: M3N6RAye = 1806 + INTEGER(IntKi), PARAMETER :: M3N7RAye = 1807 + INTEGER(IntKi), PARAMETER :: M3N8RAye = 1808 + INTEGER(IntKi), PARAMETER :: M3N9RAye = 1809 + INTEGER(IntKi), PARAMETER :: M4N1RAye = 1810 + INTEGER(IntKi), PARAMETER :: M4N2RAye = 1811 + INTEGER(IntKi), PARAMETER :: M4N3RAye = 1812 + INTEGER(IntKi), PARAMETER :: M4N4RAye = 1813 + INTEGER(IntKi), PARAMETER :: M4N5RAye = 1814 + INTEGER(IntKi), PARAMETER :: M4N6RAye = 1815 + INTEGER(IntKi), PARAMETER :: M4N7RAye = 1816 + INTEGER(IntKi), PARAMETER :: M4N8RAye = 1817 + INTEGER(IntKi), PARAMETER :: M4N9RAye = 1818 + INTEGER(IntKi), PARAMETER :: M5N1RAye = 1819 + INTEGER(IntKi), PARAMETER :: M5N2RAye = 1820 + INTEGER(IntKi), PARAMETER :: M5N3RAye = 1821 + INTEGER(IntKi), PARAMETER :: M5N4RAye = 1822 + INTEGER(IntKi), PARAMETER :: M5N5RAye = 1823 + INTEGER(IntKi), PARAMETER :: M5N6RAye = 1824 + INTEGER(IntKi), PARAMETER :: M5N7RAye = 1825 + INTEGER(IntKi), PARAMETER :: M5N8RAye = 1826 + INTEGER(IntKi), PARAMETER :: M5N9RAye = 1827 + INTEGER(IntKi), PARAMETER :: M6N1RAye = 1828 + INTEGER(IntKi), PARAMETER :: M6N2RAye = 1829 + INTEGER(IntKi), PARAMETER :: M6N3RAye = 1830 + INTEGER(IntKi), PARAMETER :: M6N4RAye = 1831 + INTEGER(IntKi), PARAMETER :: M6N5RAye = 1832 + INTEGER(IntKi), PARAMETER :: M6N6RAye = 1833 + INTEGER(IntKi), PARAMETER :: M6N7RAye = 1834 + INTEGER(IntKi), PARAMETER :: M6N8RAye = 1835 + INTEGER(IntKi), PARAMETER :: M6N9RAye = 1836 + INTEGER(IntKi), PARAMETER :: M7N1RAye = 1837 + INTEGER(IntKi), PARAMETER :: M7N2RAye = 1838 + INTEGER(IntKi), PARAMETER :: M7N3RAye = 1839 + INTEGER(IntKi), PARAMETER :: M7N4RAye = 1840 + INTEGER(IntKi), PARAMETER :: M7N5RAye = 1841 + INTEGER(IntKi), PARAMETER :: M7N6RAye = 1842 + INTEGER(IntKi), PARAMETER :: M7N7RAye = 1843 + INTEGER(IntKi), PARAMETER :: M7N8RAye = 1844 + INTEGER(IntKi), PARAMETER :: M7N9RAye = 1845 + INTEGER(IntKi), PARAMETER :: M8N1RAye = 1846 + INTEGER(IntKi), PARAMETER :: M8N2RAye = 1847 + INTEGER(IntKi), PARAMETER :: M8N3RAye = 1848 + INTEGER(IntKi), PARAMETER :: M8N4RAye = 1849 + INTEGER(IntKi), PARAMETER :: M8N5RAye = 1850 + INTEGER(IntKi), PARAMETER :: M8N6RAye = 1851 + INTEGER(IntKi), PARAMETER :: M8N7RAye = 1852 + INTEGER(IntKi), PARAMETER :: M8N8RAye = 1853 + INTEGER(IntKi), PARAMETER :: M8N9RAye = 1854 + INTEGER(IntKi), PARAMETER :: M9N1RAye = 1855 + INTEGER(IntKi), PARAMETER :: M9N2RAye = 1856 + INTEGER(IntKi), PARAMETER :: M9N3RAye = 1857 + INTEGER(IntKi), PARAMETER :: M9N4RAye = 1858 + INTEGER(IntKi), PARAMETER :: M9N5RAye = 1859 + INTEGER(IntKi), PARAMETER :: M9N6RAye = 1860 + INTEGER(IntKi), PARAMETER :: M9N7RAye = 1861 + INTEGER(IntKi), PARAMETER :: M9N8RAye = 1862 + INTEGER(IntKi), PARAMETER :: M9N9RAye = 1863 + INTEGER(IntKi), PARAMETER :: M1N1RAze = 1864 + INTEGER(IntKi), PARAMETER :: M1N2RAze = 1865 + INTEGER(IntKi), PARAMETER :: M1N3RAze = 1866 + INTEGER(IntKi), PARAMETER :: M1N4RAze = 1867 + INTEGER(IntKi), PARAMETER :: M1N5RAze = 1868 + INTEGER(IntKi), PARAMETER :: M1N6RAze = 1869 + INTEGER(IntKi), PARAMETER :: M1N7RAze = 1870 + INTEGER(IntKi), PARAMETER :: M1N8RAze = 1871 + INTEGER(IntKi), PARAMETER :: M1N9RAze = 1872 + INTEGER(IntKi), PARAMETER :: M2N1RAze = 1873 + INTEGER(IntKi), PARAMETER :: M2N2RAze = 1874 + INTEGER(IntKi), PARAMETER :: M2N3RAze = 1875 + INTEGER(IntKi), PARAMETER :: M2N4RAze = 1876 + INTEGER(IntKi), PARAMETER :: M2N5RAze = 1877 + INTEGER(IntKi), PARAMETER :: M2N6RAze = 1878 + INTEGER(IntKi), PARAMETER :: M2N7RAze = 1879 + INTEGER(IntKi), PARAMETER :: M2N8RAze = 1880 + INTEGER(IntKi), PARAMETER :: M2N9RAze = 1881 + INTEGER(IntKi), PARAMETER :: M3N1RAze = 1882 + INTEGER(IntKi), PARAMETER :: M3N2RAze = 1883 + INTEGER(IntKi), PARAMETER :: M3N3RAze = 1884 + INTEGER(IntKi), PARAMETER :: M3N4RAze = 1885 + INTEGER(IntKi), PARAMETER :: M3N5RAze = 1886 + INTEGER(IntKi), PARAMETER :: M3N6RAze = 1887 + INTEGER(IntKi), PARAMETER :: M3N7RAze = 1888 + INTEGER(IntKi), PARAMETER :: M3N8RAze = 1889 + INTEGER(IntKi), PARAMETER :: M3N9RAze = 1890 + INTEGER(IntKi), PARAMETER :: M4N1RAze = 1891 + INTEGER(IntKi), PARAMETER :: M4N2RAze = 1892 + INTEGER(IntKi), PARAMETER :: M4N3RAze = 1893 + INTEGER(IntKi), PARAMETER :: M4N4RAze = 1894 + INTEGER(IntKi), PARAMETER :: M4N5RAze = 1895 + INTEGER(IntKi), PARAMETER :: M4N6RAze = 1896 + INTEGER(IntKi), PARAMETER :: M4N7RAze = 1897 + INTEGER(IntKi), PARAMETER :: M4N8RAze = 1898 + INTEGER(IntKi), PARAMETER :: M4N9RAze = 1899 + INTEGER(IntKi), PARAMETER :: M5N1RAze = 1900 + INTEGER(IntKi), PARAMETER :: M5N2RAze = 1901 + INTEGER(IntKi), PARAMETER :: M5N3RAze = 1902 + INTEGER(IntKi), PARAMETER :: M5N4RAze = 1903 + INTEGER(IntKi), PARAMETER :: M5N5RAze = 1904 + INTEGER(IntKi), PARAMETER :: M5N6RAze = 1905 + INTEGER(IntKi), PARAMETER :: M5N7RAze = 1906 + INTEGER(IntKi), PARAMETER :: M5N8RAze = 1907 + INTEGER(IntKi), PARAMETER :: M5N9RAze = 1908 + INTEGER(IntKi), PARAMETER :: M6N1RAze = 1909 + INTEGER(IntKi), PARAMETER :: M6N2RAze = 1910 + INTEGER(IntKi), PARAMETER :: M6N3RAze = 1911 + INTEGER(IntKi), PARAMETER :: M6N4RAze = 1912 + INTEGER(IntKi), PARAMETER :: M6N5RAze = 1913 + INTEGER(IntKi), PARAMETER :: M6N6RAze = 1914 + INTEGER(IntKi), PARAMETER :: M6N7RAze = 1915 + INTEGER(IntKi), PARAMETER :: M6N8RAze = 1916 + INTEGER(IntKi), PARAMETER :: M6N9RAze = 1917 + INTEGER(IntKi), PARAMETER :: M7N1RAze = 1918 + INTEGER(IntKi), PARAMETER :: M7N2RAze = 1919 + INTEGER(IntKi), PARAMETER :: M7N3RAze = 1920 + INTEGER(IntKi), PARAMETER :: M7N4RAze = 1921 + INTEGER(IntKi), PARAMETER :: M7N5RAze = 1922 + INTEGER(IntKi), PARAMETER :: M7N6RAze = 1923 + INTEGER(IntKi), PARAMETER :: M7N7RAze = 1924 + INTEGER(IntKi), PARAMETER :: M7N8RAze = 1925 + INTEGER(IntKi), PARAMETER :: M7N9RAze = 1926 + INTEGER(IntKi), PARAMETER :: M8N1RAze = 1927 + INTEGER(IntKi), PARAMETER :: M8N2RAze = 1928 + INTEGER(IntKi), PARAMETER :: M8N3RAze = 1929 + INTEGER(IntKi), PARAMETER :: M8N4RAze = 1930 + INTEGER(IntKi), PARAMETER :: M8N5RAze = 1931 + INTEGER(IntKi), PARAMETER :: M8N6RAze = 1932 + INTEGER(IntKi), PARAMETER :: M8N7RAze = 1933 + INTEGER(IntKi), PARAMETER :: M8N8RAze = 1934 + INTEGER(IntKi), PARAMETER :: M8N9RAze = 1935 + INTEGER(IntKi), PARAMETER :: M9N1RAze = 1936 + INTEGER(IntKi), PARAMETER :: M9N2RAze = 1937 + INTEGER(IntKi), PARAMETER :: M9N3RAze = 1938 + INTEGER(IntKi), PARAMETER :: M9N4RAze = 1939 + INTEGER(IntKi), PARAMETER :: M9N5RAze = 1940 + INTEGER(IntKi), PARAMETER :: M9N6RAze = 1941 + INTEGER(IntKi), PARAMETER :: M9N7RAze = 1942 + INTEGER(IntKi), PARAMETER :: M9N8RAze = 1943 + INTEGER(IntKi), PARAMETER :: M9N9RAze = 1944 + + + ! Reactions: + + INTEGER(IntKi), PARAMETER :: ReactFXss = 1945 + INTEGER(IntKi), PARAMETER :: ReactFYss = 1946 + INTEGER(IntKi), PARAMETER :: ReactFZss = 1947 + INTEGER(IntKi), PARAMETER :: ReactMXss = 1948 + INTEGER(IntKi), PARAMETER :: ReactMYss = 1949 + INTEGER(IntKi), PARAMETER :: ReactMZss = 1950 + INTEGER(IntKi), PARAMETER :: IntfFXss = 1951 + INTEGER(IntKi), PARAMETER :: IntfFYss = 1952 + INTEGER(IntKi), PARAMETER :: IntfFZss = 1953 + INTEGER(IntKi), PARAMETER :: IntfMXss = 1954 + INTEGER(IntKi), PARAMETER :: IntfMYss = 1955 + INTEGER(IntKi), PARAMETER :: IntfMZss = 1956 + + + ! Interface Deflections: + + INTEGER(IntKi), PARAMETER :: IntfTDXss = 1957 + INTEGER(IntKi), PARAMETER :: IntfTDYss = 1958 + INTEGER(IntKi), PARAMETER :: IntfTDZss = 1959 + INTEGER(IntKi), PARAMETER :: IntfRDXss = 1960 + INTEGER(IntKi), PARAMETER :: IntfRDYss = 1961 + INTEGER(IntKi), PARAMETER :: IntfRDZss = 1962 + + + ! Interface Accelerations: + + INTEGER(IntKi), PARAMETER :: IntfTAXss = 1963 + INTEGER(IntKi), PARAMETER :: IntfTAYss = 1964 + INTEGER(IntKi), PARAMETER :: IntfTAZss = 1965 + INTEGER(IntKi), PARAMETER :: IntfRAXss = 1966 + INTEGER(IntKi), PARAMETER :: IntfRAYss = 1967 + INTEGER(IntKi), PARAMETER :: IntfRAZss = 1968 + + + ! Modal Parameters: + + INTEGER(IntKi), PARAMETER :: SSqm01 = 1969 + INTEGER(IntKi), PARAMETER :: SSqm02 = 1970 + INTEGER(IntKi), PARAMETER :: SSqm03 = 1971 + INTEGER(IntKi), PARAMETER :: SSqm04 = 1972 + INTEGER(IntKi), PARAMETER :: SSqm05 = 1973 + INTEGER(IntKi), PARAMETER :: SSqm06 = 1974 + INTEGER(IntKi), PARAMETER :: SSqm07 = 1975 + INTEGER(IntKi), PARAMETER :: SSqm08 = 1976 + INTEGER(IntKi), PARAMETER :: SSqm09 = 1977 + INTEGER(IntKi), PARAMETER :: SSqm10 = 1978 + INTEGER(IntKi), PARAMETER :: SSqm11 = 1979 + INTEGER(IntKi), PARAMETER :: SSqm12 = 1980 + INTEGER(IntKi), PARAMETER :: SSqm13 = 1981 + INTEGER(IntKi), PARAMETER :: SSqm14 = 1982 + INTEGER(IntKi), PARAMETER :: SSqm15 = 1983 + INTEGER(IntKi), PARAMETER :: SSqm16 = 1984 + INTEGER(IntKi), PARAMETER :: SSqm17 = 1985 + INTEGER(IntKi), PARAMETER :: SSqm18 = 1986 + INTEGER(IntKi), PARAMETER :: SSqm19 = 1987 + INTEGER(IntKi), PARAMETER :: SSqm20 = 1988 + INTEGER(IntKi), PARAMETER :: SSqm21 = 1989 + INTEGER(IntKi), PARAMETER :: SSqm22 = 1990 + INTEGER(IntKi), PARAMETER :: SSqm23 = 1991 + INTEGER(IntKi), PARAMETER :: SSqm24 = 1992 + INTEGER(IntKi), PARAMETER :: SSqm25 = 1993 + INTEGER(IntKi), PARAMETER :: SSqm26 = 1994 + INTEGER(IntKi), PARAMETER :: SSqm27 = 1995 + INTEGER(IntKi), PARAMETER :: SSqm28 = 1996 + INTEGER(IntKi), PARAMETER :: SSqm29 = 1997 + INTEGER(IntKi), PARAMETER :: SSqm30 = 1998 + INTEGER(IntKi), PARAMETER :: SSqm31 = 1999 + INTEGER(IntKi), PARAMETER :: SSqm32 = 2000 + INTEGER(IntKi), PARAMETER :: SSqm33 = 2001 + INTEGER(IntKi), PARAMETER :: SSqm34 = 2002 + INTEGER(IntKi), PARAMETER :: SSqm35 = 2003 + INTEGER(IntKi), PARAMETER :: SSqm36 = 2004 + INTEGER(IntKi), PARAMETER :: SSqm37 = 2005 + INTEGER(IntKi), PARAMETER :: SSqm38 = 2006 + INTEGER(IntKi), PARAMETER :: SSqm39 = 2007 + INTEGER(IntKi), PARAMETER :: SSqm40 = 2008 + INTEGER(IntKi), PARAMETER :: SSqm41 = 2009 + INTEGER(IntKi), PARAMETER :: SSqm42 = 2010 + INTEGER(IntKi), PARAMETER :: SSqm43 = 2011 + INTEGER(IntKi), PARAMETER :: SSqm44 = 2012 + INTEGER(IntKi), PARAMETER :: SSqm45 = 2013 + INTEGER(IntKi), PARAMETER :: SSqm46 = 2014 + INTEGER(IntKi), PARAMETER :: SSqm47 = 2015 + INTEGER(IntKi), PARAMETER :: SSqm48 = 2016 + INTEGER(IntKi), PARAMETER :: SSqm49 = 2017 + INTEGER(IntKi), PARAMETER :: SSqm50 = 2018 + INTEGER(IntKi), PARAMETER :: SSqm51 = 2019 + INTEGER(IntKi), PARAMETER :: SSqm52 = 2020 + INTEGER(IntKi), PARAMETER :: SSqm53 = 2021 + INTEGER(IntKi), PARAMETER :: SSqm54 = 2022 + INTEGER(IntKi), PARAMETER :: SSqm55 = 2023 + INTEGER(IntKi), PARAMETER :: SSqm56 = 2024 + INTEGER(IntKi), PARAMETER :: SSqm57 = 2025 + INTEGER(IntKi), PARAMETER :: SSqm58 = 2026 + INTEGER(IntKi), PARAMETER :: SSqm59 = 2027 + INTEGER(IntKi), PARAMETER :: SSqm60 = 2028 + INTEGER(IntKi), PARAMETER :: SSqm61 = 2029 + INTEGER(IntKi), PARAMETER :: SSqm62 = 2030 + INTEGER(IntKi), PARAMETER :: SSqm63 = 2031 + INTEGER(IntKi), PARAMETER :: SSqm64 = 2032 + INTEGER(IntKi), PARAMETER :: SSqm65 = 2033 + INTEGER(IntKi), PARAMETER :: SSqm66 = 2034 + INTEGER(IntKi), PARAMETER :: SSqm67 = 2035 + INTEGER(IntKi), PARAMETER :: SSqm68 = 2036 + INTEGER(IntKi), PARAMETER :: SSqm69 = 2037 + INTEGER(IntKi), PARAMETER :: SSqm70 = 2038 + INTEGER(IntKi), PARAMETER :: SSqm71 = 2039 + INTEGER(IntKi), PARAMETER :: SSqm72 = 2040 + INTEGER(IntKi), PARAMETER :: SSqm73 = 2041 + INTEGER(IntKi), PARAMETER :: SSqm74 = 2042 + INTEGER(IntKi), PARAMETER :: SSqm75 = 2043 + INTEGER(IntKi), PARAMETER :: SSqm76 = 2044 + INTEGER(IntKi), PARAMETER :: SSqm77 = 2045 + INTEGER(IntKi), PARAMETER :: SSqm78 = 2046 + INTEGER(IntKi), PARAMETER :: SSqm79 = 2047 + INTEGER(IntKi), PARAMETER :: SSqm80 = 2048 + INTEGER(IntKi), PARAMETER :: SSqm81 = 2049 + INTEGER(IntKi), PARAMETER :: SSqm82 = 2050 + INTEGER(IntKi), PARAMETER :: SSqm83 = 2051 + INTEGER(IntKi), PARAMETER :: SSqm84 = 2052 + INTEGER(IntKi), PARAMETER :: SSqm85 = 2053 + INTEGER(IntKi), PARAMETER :: SSqm86 = 2054 + INTEGER(IntKi), PARAMETER :: SSqm87 = 2055 + INTEGER(IntKi), PARAMETER :: SSqm88 = 2056 + INTEGER(IntKi), PARAMETER :: SSqm89 = 2057 + INTEGER(IntKi), PARAMETER :: SSqm90 = 2058 + INTEGER(IntKi), PARAMETER :: SSqm91 = 2059 + INTEGER(IntKi), PARAMETER :: SSqm92 = 2060 + INTEGER(IntKi), PARAMETER :: SSqm93 = 2061 + INTEGER(IntKi), PARAMETER :: SSqm94 = 2062 + INTEGER(IntKi), PARAMETER :: SSqm95 = 2063 + INTEGER(IntKi), PARAMETER :: SSqm96 = 2064 + INTEGER(IntKi), PARAMETER :: SSqm97 = 2065 + INTEGER(IntKi), PARAMETER :: SSqm98 = 2066 + INTEGER(IntKi), PARAMETER :: SSqm99 = 2067 + INTEGER(IntKi), PARAMETER :: SSqmd01 = 2068 + INTEGER(IntKi), PARAMETER :: SSqmd02 = 2069 + INTEGER(IntKi), PARAMETER :: SSqmd03 = 2070 + INTEGER(IntKi), PARAMETER :: SSqmd04 = 2071 + INTEGER(IntKi), PARAMETER :: SSqmd05 = 2072 + INTEGER(IntKi), PARAMETER :: SSqmd06 = 2073 + INTEGER(IntKi), PARAMETER :: SSqmd07 = 2074 + INTEGER(IntKi), PARAMETER :: SSqmd08 = 2075 + INTEGER(IntKi), PARAMETER :: SSqmd09 = 2076 + INTEGER(IntKi), PARAMETER :: SSqmd10 = 2077 + INTEGER(IntKi), PARAMETER :: SSqmd11 = 2078 + INTEGER(IntKi), PARAMETER :: SSqmd12 = 2079 + INTEGER(IntKi), PARAMETER :: SSqmd13 = 2080 + INTEGER(IntKi), PARAMETER :: SSqmd14 = 2081 + INTEGER(IntKi), PARAMETER :: SSqmd15 = 2082 + INTEGER(IntKi), PARAMETER :: SSqmd16 = 2083 + INTEGER(IntKi), PARAMETER :: SSqmd17 = 2084 + INTEGER(IntKi), PARAMETER :: SSqmd18 = 2085 + INTEGER(IntKi), PARAMETER :: SSqmd19 = 2086 + INTEGER(IntKi), PARAMETER :: SSqmd20 = 2087 + INTEGER(IntKi), PARAMETER :: SSqmd21 = 2088 + INTEGER(IntKi), PARAMETER :: SSqmd22 = 2089 + INTEGER(IntKi), PARAMETER :: SSqmd23 = 2090 + INTEGER(IntKi), PARAMETER :: SSqmd24 = 2091 + INTEGER(IntKi), PARAMETER :: SSqmd25 = 2092 + INTEGER(IntKi), PARAMETER :: SSqmd26 = 2093 + INTEGER(IntKi), PARAMETER :: SSqmd27 = 2094 + INTEGER(IntKi), PARAMETER :: SSqmd28 = 2095 + INTEGER(IntKi), PARAMETER :: SSqmd29 = 2096 + INTEGER(IntKi), PARAMETER :: SSqmd30 = 2097 + INTEGER(IntKi), PARAMETER :: SSqmd31 = 2098 + INTEGER(IntKi), PARAMETER :: SSqmd32 = 2099 + INTEGER(IntKi), PARAMETER :: SSqmd33 = 2100 + INTEGER(IntKi), PARAMETER :: SSqmd34 = 2101 + INTEGER(IntKi), PARAMETER :: SSqmd35 = 2102 + INTEGER(IntKi), PARAMETER :: SSqmd36 = 2103 + INTEGER(IntKi), PARAMETER :: SSqmd37 = 2104 + INTEGER(IntKi), PARAMETER :: SSqmd38 = 2105 + INTEGER(IntKi), PARAMETER :: SSqmd39 = 2106 + INTEGER(IntKi), PARAMETER :: SSqmd40 = 2107 + INTEGER(IntKi), PARAMETER :: SSqmd41 = 2108 + INTEGER(IntKi), PARAMETER :: SSqmd42 = 2109 + INTEGER(IntKi), PARAMETER :: SSqmd43 = 2110 + INTEGER(IntKi), PARAMETER :: SSqmd44 = 2111 + INTEGER(IntKi), PARAMETER :: SSqmd45 = 2112 + INTEGER(IntKi), PARAMETER :: SSqmd46 = 2113 + INTEGER(IntKi), PARAMETER :: SSqmd47 = 2114 + INTEGER(IntKi), PARAMETER :: SSqmd48 = 2115 + INTEGER(IntKi), PARAMETER :: SSqmd49 = 2116 + INTEGER(IntKi), PARAMETER :: SSqmd50 = 2117 + INTEGER(IntKi), PARAMETER :: SSqmd51 = 2118 + INTEGER(IntKi), PARAMETER :: SSqmd52 = 2119 + INTEGER(IntKi), PARAMETER :: SSqmd53 = 2120 + INTEGER(IntKi), PARAMETER :: SSqmd54 = 2121 + INTEGER(IntKi), PARAMETER :: SSqmd55 = 2122 + INTEGER(IntKi), PARAMETER :: SSqmd56 = 2123 + INTEGER(IntKi), PARAMETER :: SSqmd57 = 2124 + INTEGER(IntKi), PARAMETER :: SSqmd58 = 2125 + INTEGER(IntKi), PARAMETER :: SSqmd59 = 2126 + INTEGER(IntKi), PARAMETER :: SSqmd60 = 2127 + INTEGER(IntKi), PARAMETER :: SSqmd61 = 2128 + INTEGER(IntKi), PARAMETER :: SSqmd62 = 2129 + INTEGER(IntKi), PARAMETER :: SSqmd63 = 2130 + INTEGER(IntKi), PARAMETER :: SSqmd64 = 2131 + INTEGER(IntKi), PARAMETER :: SSqmd65 = 2132 + INTEGER(IntKi), PARAMETER :: SSqmd66 = 2133 + INTEGER(IntKi), PARAMETER :: SSqmd67 = 2134 + INTEGER(IntKi), PARAMETER :: SSqmd68 = 2135 + INTEGER(IntKi), PARAMETER :: SSqmd69 = 2136 + INTEGER(IntKi), PARAMETER :: SSqmd70 = 2137 + INTEGER(IntKi), PARAMETER :: SSqmd71 = 2138 + INTEGER(IntKi), PARAMETER :: SSqmd72 = 2139 + INTEGER(IntKi), PARAMETER :: SSqmd73 = 2140 + INTEGER(IntKi), PARAMETER :: SSqmd74 = 2141 + INTEGER(IntKi), PARAMETER :: SSqmd75 = 2142 + INTEGER(IntKi), PARAMETER :: SSqmd76 = 2143 + INTEGER(IntKi), PARAMETER :: SSqmd77 = 2144 + INTEGER(IntKi), PARAMETER :: SSqmd78 = 2145 + INTEGER(IntKi), PARAMETER :: SSqmd79 = 2146 + INTEGER(IntKi), PARAMETER :: SSqmd80 = 2147 + INTEGER(IntKi), PARAMETER :: SSqmd81 = 2148 + INTEGER(IntKi), PARAMETER :: SSqmd82 = 2149 + INTEGER(IntKi), PARAMETER :: SSqmd83 = 2150 + INTEGER(IntKi), PARAMETER :: SSqmd84 = 2151 + INTEGER(IntKi), PARAMETER :: SSqmd85 = 2152 + INTEGER(IntKi), PARAMETER :: SSqmd86 = 2153 + INTEGER(IntKi), PARAMETER :: SSqmd87 = 2154 + INTEGER(IntKi), PARAMETER :: SSqmd88 = 2155 + INTEGER(IntKi), PARAMETER :: SSqmd89 = 2156 + INTEGER(IntKi), PARAMETER :: SSqmd90 = 2157 + INTEGER(IntKi), PARAMETER :: SSqmd91 = 2158 + INTEGER(IntKi), PARAMETER :: SSqmd92 = 2159 + INTEGER(IntKi), PARAMETER :: SSqmd93 = 2160 + INTEGER(IntKi), PARAMETER :: SSqmd94 = 2161 + INTEGER(IntKi), PARAMETER :: SSqmd95 = 2162 + INTEGER(IntKi), PARAMETER :: SSqmd96 = 2163 + INTEGER(IntKi), PARAMETER :: SSqmd97 = 2164 + INTEGER(IntKi), PARAMETER :: SSqmd98 = 2165 + INTEGER(IntKi), PARAMETER :: SSqmd99 = 2166 + INTEGER(IntKi), PARAMETER :: SSqmdd01 = 2167 + INTEGER(IntKi), PARAMETER :: SSqmdd02 = 2168 + INTEGER(IntKi), PARAMETER :: SSqmdd03 = 2169 + INTEGER(IntKi), PARAMETER :: SSqmdd04 = 2170 + INTEGER(IntKi), PARAMETER :: SSqmdd05 = 2171 + INTEGER(IntKi), PARAMETER :: SSqmdd06 = 2172 + INTEGER(IntKi), PARAMETER :: SSqmdd07 = 2173 + INTEGER(IntKi), PARAMETER :: SSqmdd08 = 2174 + INTEGER(IntKi), PARAMETER :: SSqmdd09 = 2175 + INTEGER(IntKi), PARAMETER :: SSqmdd10 = 2176 + INTEGER(IntKi), PARAMETER :: SSqmdd11 = 2177 + INTEGER(IntKi), PARAMETER :: SSqmdd12 = 2178 + INTEGER(IntKi), PARAMETER :: SSqmdd13 = 2179 + INTEGER(IntKi), PARAMETER :: SSqmdd14 = 2180 + INTEGER(IntKi), PARAMETER :: SSqmdd15 = 2181 + INTEGER(IntKi), PARAMETER :: SSqmdd16 = 2182 + INTEGER(IntKi), PARAMETER :: SSqmdd17 = 2183 + INTEGER(IntKi), PARAMETER :: SSqmdd18 = 2184 + INTEGER(IntKi), PARAMETER :: SSqmdd19 = 2185 + INTEGER(IntKi), PARAMETER :: SSqmdd20 = 2186 + INTEGER(IntKi), PARAMETER :: SSqmdd21 = 2187 + INTEGER(IntKi), PARAMETER :: SSqmdd22 = 2188 + INTEGER(IntKi), PARAMETER :: SSqmdd23 = 2189 + INTEGER(IntKi), PARAMETER :: SSqmdd24 = 2190 + INTEGER(IntKi), PARAMETER :: SSqmdd25 = 2191 + INTEGER(IntKi), PARAMETER :: SSqmdd26 = 2192 + INTEGER(IntKi), PARAMETER :: SSqmdd27 = 2193 + INTEGER(IntKi), PARAMETER :: SSqmdd28 = 2194 + INTEGER(IntKi), PARAMETER :: SSqmdd29 = 2195 + INTEGER(IntKi), PARAMETER :: SSqmdd30 = 2196 + INTEGER(IntKi), PARAMETER :: SSqmdd31 = 2197 + INTEGER(IntKi), PARAMETER :: SSqmdd32 = 2198 + INTEGER(IntKi), PARAMETER :: SSqmdd33 = 2199 + INTEGER(IntKi), PARAMETER :: SSqmdd34 = 2200 + INTEGER(IntKi), PARAMETER :: SSqmdd35 = 2201 + INTEGER(IntKi), PARAMETER :: SSqmdd36 = 2202 + INTEGER(IntKi), PARAMETER :: SSqmdd37 = 2203 + INTEGER(IntKi), PARAMETER :: SSqmdd38 = 2204 + INTEGER(IntKi), PARAMETER :: SSqmdd39 = 2205 + INTEGER(IntKi), PARAMETER :: SSqmdd40 = 2206 + INTEGER(IntKi), PARAMETER :: SSqmdd41 = 2207 + INTEGER(IntKi), PARAMETER :: SSqmdd42 = 2208 + INTEGER(IntKi), PARAMETER :: SSqmdd43 = 2209 + INTEGER(IntKi), PARAMETER :: SSqmdd44 = 2210 + INTEGER(IntKi), PARAMETER :: SSqmdd45 = 2211 + INTEGER(IntKi), PARAMETER :: SSqmdd46 = 2212 + INTEGER(IntKi), PARAMETER :: SSqmdd47 = 2213 + INTEGER(IntKi), PARAMETER :: SSqmdd48 = 2214 + INTEGER(IntKi), PARAMETER :: SSqmdd49 = 2215 + INTEGER(IntKi), PARAMETER :: SSqmdd50 = 2216 + INTEGER(IntKi), PARAMETER :: SSqmdd51 = 2217 + INTEGER(IntKi), PARAMETER :: SSqmdd52 = 2218 + INTEGER(IntKi), PARAMETER :: SSqmdd53 = 2219 + INTEGER(IntKi), PARAMETER :: SSqmdd54 = 2220 + INTEGER(IntKi), PARAMETER :: SSqmdd55 = 2221 + INTEGER(IntKi), PARAMETER :: SSqmdd56 = 2222 + INTEGER(IntKi), PARAMETER :: SSqmdd57 = 2223 + INTEGER(IntKi), PARAMETER :: SSqmdd58 = 2224 + INTEGER(IntKi), PARAMETER :: SSqmdd59 = 2225 + INTEGER(IntKi), PARAMETER :: SSqmdd60 = 2226 + INTEGER(IntKi), PARAMETER :: SSqmdd61 = 2227 + INTEGER(IntKi), PARAMETER :: SSqmdd62 = 2228 + INTEGER(IntKi), PARAMETER :: SSqmdd63 = 2229 + INTEGER(IntKi), PARAMETER :: SSqmdd64 = 2230 + INTEGER(IntKi), PARAMETER :: SSqmdd65 = 2231 + INTEGER(IntKi), PARAMETER :: SSqmdd66 = 2232 + INTEGER(IntKi), PARAMETER :: SSqmdd67 = 2233 + INTEGER(IntKi), PARAMETER :: SSqmdd68 = 2234 + INTEGER(IntKi), PARAMETER :: SSqmdd69 = 2235 + INTEGER(IntKi), PARAMETER :: SSqmdd70 = 2236 + INTEGER(IntKi), PARAMETER :: SSqmdd71 = 2237 + INTEGER(IntKi), PARAMETER :: SSqmdd72 = 2238 + INTEGER(IntKi), PARAMETER :: SSqmdd73 = 2239 + INTEGER(IntKi), PARAMETER :: SSqmdd74 = 2240 + INTEGER(IntKi), PARAMETER :: SSqmdd75 = 2241 + INTEGER(IntKi), PARAMETER :: SSqmdd76 = 2242 + INTEGER(IntKi), PARAMETER :: SSqmdd77 = 2243 + INTEGER(IntKi), PARAMETER :: SSqmdd78 = 2244 + INTEGER(IntKi), PARAMETER :: SSqmdd79 = 2245 + INTEGER(IntKi), PARAMETER :: SSqmdd80 = 2246 + INTEGER(IntKi), PARAMETER :: SSqmdd81 = 2247 + INTEGER(IntKi), PARAMETER :: SSqmdd82 = 2248 + INTEGER(IntKi), PARAMETER :: SSqmdd83 = 2249 + INTEGER(IntKi), PARAMETER :: SSqmdd84 = 2250 + INTEGER(IntKi), PARAMETER :: SSqmdd85 = 2251 + INTEGER(IntKi), PARAMETER :: SSqmdd86 = 2252 + INTEGER(IntKi), PARAMETER :: SSqmdd87 = 2253 + INTEGER(IntKi), PARAMETER :: SSqmdd88 = 2254 + INTEGER(IntKi), PARAMETER :: SSqmdd89 = 2255 + INTEGER(IntKi), PARAMETER :: SSqmdd90 = 2256 + INTEGER(IntKi), PARAMETER :: SSqmdd91 = 2257 + INTEGER(IntKi), PARAMETER :: SSqmdd92 = 2258 + INTEGER(IntKi), PARAMETER :: SSqmdd93 = 2259 + INTEGER(IntKi), PARAMETER :: SSqmdd94 = 2260 + INTEGER(IntKi), PARAMETER :: SSqmdd95 = 2261 + INTEGER(IntKi), PARAMETER :: SSqmdd96 = 2262 + INTEGER(IntKi), PARAMETER :: SSqmdd97 = 2263 + INTEGER(IntKi), PARAMETER :: SSqmdd98 = 2264 + INTEGER(IntKi), PARAMETER :: SSqmdd99 = 2265 + + + ! The maximum number of output channels which can be output by the code. + !INTEGER(IntKi), PARAMETER :: MaxOutPts = 2265 + +!End of code generated by Matlab script + + INTEGER, PARAMETER :: MNfmKe(6,9,9) = reshape((/ M1N1FKxe,M1N1FKye,M1N1FKze,M1N1MKxe,M1N1MKye,M1N1MKze, & + M1N2FKxe,M1N2FKye,M1N2FKze,M1N2MKxe,M1N2MKye,M1N2MKze, & + M1N3FKxe,M1N3FKye,M1N3FKze,M1N3MKxe,M1N3MKye,M1N3MKze, & + M1N4FKxe,M1N4FKye,M1N4FKze,M1N4MKxe,M1N4MKye,M1N4MKze, & + M1N5FKxe,M1N5FKye,M1N5FKze,M1N5MKxe,M1N5MKye,M1N5MKze, & + M1N6FKxe,M1N6FKye,M1N6FKze,M1N6MKxe,M1N6MKye,M1N6MKze, & + M1N7FKxe,M1N7FKye,M1N7FKze,M1N7MKxe,M1N7MKye,M1N7MKze, & + M1N8FKxe,M1N8FKye,M1N8FKze,M1N8MKxe,M1N8MKye,M1N8MKze, & + M1N9FKxe,M1N9FKye,M1N9FKze,M1N9MKxe,M1N9MKye,M1N9MKze, & + M2N1FKxe,M2N1FKye,M2N1FKze,M2N1MKxe,M2N1MKye,M2N1MKze, & + M2N2FKxe,M2N2FKye,M2N2FKze,M2N2MKxe,M2N2MKye,M2N2MKze, & + M2N3FKxe,M2N3FKye,M2N3FKze,M2N3MKxe,M2N3MKye,M2N3MKze, & + M2N4FKxe,M2N4FKye,M2N4FKze,M2N4MKxe,M2N4MKye,M2N4MKze, & + M2N5FKxe,M2N5FKye,M2N5FKze,M2N5MKxe,M2N5MKye,M2N5MKze, & + M2N6FKxe,M2N6FKye,M2N6FKze,M2N6MKxe,M2N6MKye,M2N6MKze, & + M2N7FKxe,M2N7FKye,M2N7FKze,M2N7MKxe,M2N7MKye,M2N7MKze, & + M2N8FKxe,M2N8FKye,M2N8FKze,M2N8MKxe,M2N8MKye,M2N8MKze, & + M2N9FKxe,M2N9FKye,M2N9FKze,M2N9MKxe,M2N9MKye,M2N9MKze, & + M3N1FKxe,M3N1FKye,M3N1FKze,M3N1MKxe,M3N1MKye,M3N1MKze, & + M3N2FKxe,M3N2FKye,M3N2FKze,M3N2MKxe,M3N2MKye,M3N2MKze, & + M3N3FKxe,M3N3FKye,M3N3FKze,M3N3MKxe,M3N3MKye,M3N3MKze, & + M3N4FKxe,M3N4FKye,M3N4FKze,M3N4MKxe,M3N4MKye,M3N4MKze, & + M3N5FKxe,M3N5FKye,M3N5FKze,M3N5MKxe,M3N5MKye,M3N5MKze, & + M3N6FKxe,M3N6FKye,M3N6FKze,M3N6MKxe,M3N6MKye,M3N6MKze, & + M3N7FKxe,M3N7FKye,M3N7FKze,M3N7MKxe,M3N7MKye,M3N7MKze, & + M3N8FKxe,M3N8FKye,M3N8FKze,M3N8MKxe,M3N8MKye,M3N8MKze, & + M3N9FKxe,M3N9FKye,M3N9FKze,M3N9MKxe,M3N9MKye,M3N9MKze, & + M4N1FKxe,M4N1FKye,M4N1FKze,M4N1MKxe,M4N1MKye,M4N1MKze, & + M4N2FKxe,M4N2FKye,M4N2FKze,M4N2MKxe,M4N2MKye,M4N2MKze, & + M4N3FKxe,M4N3FKye,M4N3FKze,M4N3MKxe,M4N3MKye,M4N3MKze, & + M4N4FKxe,M4N4FKye,M4N4FKze,M4N4MKxe,M4N4MKye,M4N4MKze, & + M4N5FKxe,M4N5FKye,M4N5FKze,M4N5MKxe,M4N5MKye,M4N5MKze, & + M4N6FKxe,M4N6FKye,M4N6FKze,M4N6MKxe,M4N6MKye,M4N6MKze, & + M4N7FKxe,M4N7FKye,M4N7FKze,M4N7MKxe,M4N7MKye,M4N7MKze, & + M4N8FKxe,M4N8FKye,M4N8FKze,M4N8MKxe,M4N8MKye,M4N8MKze, & + M4N9FKxe,M4N9FKye,M4N9FKze,M4N9MKxe,M4N9MKye,M4N9MKze, & + M5N1FKxe,M5N1FKye,M5N1FKze,M5N1MKxe,M5N1MKye,M5N1MKze, & + M5N2FKxe,M5N2FKye,M5N2FKze,M5N2MKxe,M5N2MKye,M5N2MKze, & + M5N3FKxe,M5N3FKye,M5N3FKze,M5N3MKxe,M5N3MKye,M5N3MKze, & + M5N4FKxe,M5N4FKye,M5N4FKze,M5N4MKxe,M5N4MKye,M5N4MKze, & + M5N5FKxe,M5N5FKye,M5N5FKze,M5N5MKxe,M5N5MKye,M5N5MKze, & + M5N6FKxe,M5N6FKye,M5N6FKze,M5N6MKxe,M5N6MKye,M5N6MKze, & + M5N7FKxe,M5N7FKye,M5N7FKze,M5N7MKxe,M5N7MKye,M5N7MKze, & + M5N8FKxe,M5N8FKye,M5N8FKze,M5N8MKxe,M5N8MKye,M5N8MKze, & + M5N9FKxe,M5N9FKye,M5N9FKze,M5N9MKxe,M5N9MKye,M5N9MKze, & + M6N1FKxe,M6N1FKye,M6N1FKze,M6N1MKxe,M6N1MKye,M6N1MKze, & + M6N2FKxe,M6N2FKye,M6N2FKze,M6N2MKxe,M6N2MKye,M6N2MKze, & + M6N3FKxe,M6N3FKye,M6N3FKze,M6N3MKxe,M6N3MKye,M6N3MKze, & + M6N4FKxe,M6N4FKye,M6N4FKze,M6N4MKxe,M6N4MKye,M6N4MKze, & + M6N5FKxe,M6N5FKye,M6N5FKze,M6N5MKxe,M6N5MKye,M6N5MKze, & + M6N6FKxe,M6N6FKye,M6N6FKze,M6N6MKxe,M6N6MKye,M6N6MKze, & + M6N7FKxe,M6N7FKye,M6N7FKze,M6N7MKxe,M6N7MKye,M6N7MKze, & + M6N8FKxe,M6N8FKye,M6N8FKze,M6N8MKxe,M6N8MKye,M6N8MKze, & + M6N9FKxe,M6N9FKye,M6N9FKze,M6N9MKxe,M6N9MKye,M6N9MKze, & + M7N1FKxe,M7N1FKye,M7N1FKze,M7N1MKxe,M7N1MKye,M7N1MKze, & + M7N2FKxe,M7N2FKye,M7N2FKze,M7N2MKxe,M7N2MKye,M7N2MKze, & + M7N3FKxe,M7N3FKye,M7N3FKze,M7N3MKxe,M7N3MKye,M7N3MKze, & + M7N4FKxe,M7N4FKye,M7N4FKze,M7N4MKxe,M7N4MKye,M7N4MKze, & + M7N5FKxe,M7N5FKye,M7N5FKze,M7N5MKxe,M7N5MKye,M7N5MKze, & + M7N6FKxe,M7N6FKye,M7N6FKze,M7N6MKxe,M7N6MKye,M7N6MKze, & + M7N7FKxe,M7N7FKye,M7N7FKze,M7N7MKxe,M7N7MKye,M7N7MKze, & + M7N8FKxe,M7N8FKye,M7N8FKze,M7N8MKxe,M7N8MKye,M7N8MKze, & + M7N9FKxe,M7N9FKye,M7N9FKze,M7N9MKxe,M7N9MKye,M7N9MKze, & + M8N1FKxe,M8N1FKye,M8N1FKze,M8N1MKxe,M8N1MKye,M8N1MKze, & + M8N2FKxe,M8N2FKye,M8N2FKze,M8N2MKxe,M8N2MKye,M8N2MKze, & + M8N3FKxe,M8N3FKye,M8N3FKze,M8N3MKxe,M8N3MKye,M8N3MKze, & + M8N4FKxe,M8N4FKye,M8N4FKze,M8N4MKxe,M8N4MKye,M8N4MKze, & + M8N5FKxe,M8N5FKye,M8N5FKze,M8N5MKxe,M8N5MKye,M8N5MKze, & + M8N6FKxe,M8N6FKye,M8N6FKze,M8N6MKxe,M8N6MKye,M8N6MKze, & + M8N7FKxe,M8N7FKye,M8N7FKze,M8N7MKxe,M8N7MKye,M8N7MKze, & + M8N8FKxe,M8N8FKye,M8N8FKze,M8N8MKxe,M8N8MKye,M8N8MKze, & + M8N9FKxe,M8N9FKye,M8N9FKze,M8N9MKxe,M8N9MKye,M8N9MKze, & + M9N1FKxe,M9N1FKye,M9N1FKze,M9N1MKxe,M9N1MKye,M9N1MKze, & + M9N2FKxe,M9N2FKye,M9N2FKze,M9N2MKxe,M9N2MKye,M9N2MKze, & + M9N3FKxe,M9N3FKye,M9N3FKze,M9N3MKxe,M9N3MKye,M9N3MKze, & + M9N4FKxe,M9N4FKye,M9N4FKze,M9N4MKxe,M9N4MKye,M9N4MKze, & + M9N5FKxe,M9N5FKye,M9N5FKze,M9N5MKxe,M9N5MKye,M9N5MKze, & + M9N6FKxe,M9N6FKye,M9N6FKze,M9N6MKxe,M9N6MKye,M9N6MKze, & + M9N7FKxe,M9N7FKye,M9N7FKze,M9N7MKxe,M9N7MKye,M9N7MKze, & + M9N8FKxe,M9N8FKye,M9N8FKze,M9N8MKxe,M9N8MKye,M9N8MKze, & + M9N9FKxe,M9N9FKye,M9N9FKze,M9N9MKxe,M9N9MKye,M9N9MKze /),(/6,9,9/)) + + + + INTEGER, PARAMETER :: MNfmMe(6,9,9) = reshape((/ M1N1FMxe,M1N1FMye,M1N1FMze,M1N1MMxe,M1N1MMye,M1N1MMze, & + M1N2FMxe,M1N2FMye,M1N2FMze,M1N2MMxe,M1N2MMye,M1N2MMze, & + M1N3FMxe,M1N3FMye,M1N3FMze,M1N3MMxe,M1N3MMye,M1N3MMze, & + M1N4FMxe,M1N4FMye,M1N4FMze,M1N4MMxe,M1N4MMye,M1N4MMze, & + M1N5FMxe,M1N5FMye,M1N5FMze,M1N5MMxe,M1N5MMye,M1N5MMze, & + M1N6FMxe,M1N6FMye,M1N6FMze,M1N6MMxe,M1N6MMye,M1N6MMze, & + M1N7FMxe,M1N7FMye,M1N7FMze,M1N7MMxe,M1N7MMye,M1N7MMze, & + M1N8FMxe,M1N8FMye,M1N8FMze,M1N8MMxe,M1N8MMye,M1N8MMze, & + M1N9FMxe,M1N9FMye,M1N9FMze,M1N9MMxe,M1N9MMye,M1N9MMze, & + M2N1FMxe,M2N1FMye,M2N1FMze,M2N1MMxe,M2N1MMye,M2N1MMze, & + M2N2FMxe,M2N2FMye,M2N2FMze,M2N2MMxe,M2N2MMye,M2N2MMze, & + M2N3FMxe,M2N3FMye,M2N3FMze,M2N3MMxe,M2N3MMye,M2N3MMze, & + M2N4FMxe,M2N4FMye,M2N4FMze,M2N4MMxe,M2N4MMye,M2N4MMze, & + M2N5FMxe,M2N5FMye,M2N5FMze,M2N5MMxe,M2N5MMye,M2N5MMze, & + M2N6FMxe,M2N6FMye,M2N6FMze,M2N6MMxe,M2N6MMye,M2N6MMze, & + M2N7FMxe,M2N7FMye,M2N7FMze,M2N7MMxe,M2N7MMye,M2N7MMze, & + M2N8FMxe,M2N8FMye,M2N8FMze,M2N8MMxe,M2N8MMye,M2N8MMze, & + M2N9FMxe,M2N9FMye,M2N9FMze,M2N9MMxe,M2N9MMye,M2N9MMze, & + M3N1FMxe,M3N1FMye,M3N1FMze,M3N1MMxe,M3N1MMye,M3N1MMze, & + M3N2FMxe,M3N2FMye,M3N2FMze,M3N2MMxe,M3N2MMye,M3N2MMze, & + M3N3FMxe,M3N3FMye,M3N3FMze,M3N3MMxe,M3N3MMye,M3N3MMze, & + M3N4FMxe,M3N4FMye,M3N4FMze,M3N4MMxe,M3N4MMye,M3N4MMze, & + M3N5FMxe,M3N5FMye,M3N5FMze,M3N5MMxe,M3N5MMye,M3N5MMze, & + M3N6FMxe,M3N6FMye,M3N6FMze,M3N6MMxe,M3N6MMye,M3N6MMze, & + M3N7FMxe,M3N7FMye,M3N7FMze,M3N7MMxe,M3N7MMye,M3N7MMze, & + M3N8FMxe,M3N8FMye,M3N8FMze,M3N8MMxe,M3N8MMye,M3N8MMze, & + M3N9FMxe,M3N9FMye,M3N9FMze,M3N9MMxe,M3N9MMye,M3N9MMze, & + M4N1FMxe,M4N1FMye,M4N1FMze,M4N1MMxe,M4N1MMye,M4N1MMze, & + M4N2FMxe,M4N2FMye,M4N2FMze,M4N2MMxe,M4N2MMye,M4N2MMze, & + M4N3FMxe,M4N3FMye,M4N3FMze,M4N3MMxe,M4N3MMye,M4N3MMze, & + M4N4FMxe,M4N4FMye,M4N4FMze,M4N4MMxe,M4N4MMye,M4N4MMze, & + M4N5FMxe,M4N5FMye,M4N5FMze,M4N5MMxe,M4N5MMye,M4N5MMze, & + M4N6FMxe,M4N6FMye,M4N6FMze,M4N6MMxe,M4N6MMye,M4N6MMze, & + M4N7FMxe,M4N7FMye,M4N7FMze,M4N7MMxe,M4N7MMye,M4N7MMze, & + M4N8FMxe,M4N8FMye,M4N8FMze,M4N8MMxe,M4N8MMye,M4N8MMze, & + M4N9FMxe,M4N9FMye,M4N9FMze,M4N9MMxe,M4N9MMye,M4N9MMze, & + M5N1FMxe,M5N1FMye,M5N1FMze,M5N1MMxe,M5N1MMye,M5N1MMze, & + M5N2FMxe,M5N2FMye,M5N2FMze,M5N2MMxe,M5N2MMye,M5N2MMze, & + M5N3FMxe,M5N3FMye,M5N3FMze,M5N3MMxe,M5N3MMye,M5N3MMze, & + M5N4FMxe,M5N4FMye,M5N4FMze,M5N4MMxe,M5N4MMye,M5N4MMze, & + M5N5FMxe,M5N5FMye,M5N5FMze,M5N5MMxe,M5N5MMye,M5N5MMze, & + M5N6FMxe,M5N6FMye,M5N6FMze,M5N6MMxe,M5N6MMye,M5N6MMze, & + M5N7FMxe,M5N7FMye,M5N7FMze,M5N7MMxe,M5N7MMye,M5N7MMze, & + M5N8FMxe,M5N8FMye,M5N8FMze,M5N8MMxe,M5N8MMye,M5N8MMze, & + M5N9FMxe,M5N9FMye,M5N9FMze,M5N9MMxe,M5N9MMye,M5N9MMze, & + M6N1FMxe,M6N1FMye,M6N1FMze,M6N1MMxe,M6N1MMye,M6N1MMze, & + M6N2FMxe,M6N2FMye,M6N2FMze,M6N2MMxe,M6N2MMye,M6N2MMze, & + M6N3FMxe,M6N3FMye,M6N3FMze,M6N3MMxe,M6N3MMye,M6N3MMze, & + M6N4FMxe,M6N4FMye,M6N4FMze,M6N4MMxe,M6N4MMye,M6N4MMze, & + M6N5FMxe,M6N5FMye,M6N5FMze,M6N5MMxe,M6N5MMye,M6N5MMze, & + M6N6FMxe,M6N6FMye,M6N6FMze,M6N6MMxe,M6N6MMye,M6N6MMze, & + M6N7FMxe,M6N7FMye,M6N7FMze,M6N7MMxe,M6N7MMye,M6N7MMze, & + M6N8FMxe,M6N8FMye,M6N8FMze,M6N8MMxe,M6N8MMye,M6N8MMze, & + M6N9FMxe,M6N9FMye,M6N9FMze,M6N9MMxe,M6N9MMye,M6N9MMze, & + M7N1FMxe,M7N1FMye,M7N1FMze,M7N1MMxe,M7N1MMye,M7N1MMze, & + M7N2FMxe,M7N2FMye,M7N2FMze,M7N2MMxe,M7N2MMye,M7N2MMze, & + M7N3FMxe,M7N3FMye,M7N3FMze,M7N3MMxe,M7N3MMye,M7N3MMze, & + M7N4FMxe,M7N4FMye,M7N4FMze,M7N4MMxe,M7N4MMye,M7N4MMze, & + M7N5FMxe,M7N5FMye,M7N5FMze,M7N5MMxe,M7N5MMye,M7N5MMze, & + M7N6FMxe,M7N6FMye,M7N6FMze,M7N6MMxe,M7N6MMye,M7N6MMze, & + M7N7FMxe,M7N7FMye,M7N7FMze,M7N7MMxe,M7N7MMye,M7N7MMze, & + M7N8FMxe,M7N8FMye,M7N8FMze,M7N8MMxe,M7N8MMye,M7N8MMze, & + M7N9FMxe,M7N9FMye,M7N9FMze,M7N9MMxe,M7N9MMye,M7N9MMze, & + M8N1FMxe,M8N1FMye,M8N1FMze,M8N1MMxe,M8N1MMye,M8N1MMze, & + M8N2FMxe,M8N2FMye,M8N2FMze,M8N2MMxe,M8N2MMye,M8N2MMze, & + M8N3FMxe,M8N3FMye,M8N3FMze,M8N3MMxe,M8N3MMye,M8N3MMze, & + M8N4FMxe,M8N4FMye,M8N4FMze,M8N4MMxe,M8N4MMye,M8N4MMze, & + M8N5FMxe,M8N5FMye,M8N5FMze,M8N5MMxe,M8N5MMye,M8N5MMze, & + M8N6FMxe,M8N6FMye,M8N6FMze,M8N6MMxe,M8N6MMye,M8N6MMze, & + M8N7FMxe,M8N7FMye,M8N7FMze,M8N7MMxe,M8N7MMye,M8N7MMze, & + M8N8FMxe,M8N8FMye,M8N8FMze,M8N8MMxe,M8N8MMye,M8N8MMze, & + M8N9FMxe,M8N9FMye,M8N9FMze,M8N9MMxe,M8N9MMye,M8N9MMze, & + M9N1FMxe,M9N1FMye,M9N1FMze,M9N1MMxe,M9N1MMye,M9N1MMze, & + M9N2FMxe,M9N2FMye,M9N2FMze,M9N2MMxe,M9N2MMye,M9N2MMze, & + M9N3FMxe,M9N3FMye,M9N3FMze,M9N3MMxe,M9N3MMye,M9N3MMze, & + M9N4FMxe,M9N4FMye,M9N4FMze,M9N4MMxe,M9N4MMye,M9N4MMze, & + M9N5FMxe,M9N5FMye,M9N5FMze,M9N5MMxe,M9N5MMye,M9N5MMze, & + M9N6FMxe,M9N6FMye,M9N6FMze,M9N6MMxe,M9N6MMye,M9N6MMze, & + M9N7FMxe,M9N7FMye,M9N7FMze,M9N7MMxe,M9N7MMye,M9N7MMze, & + M9N8FMxe,M9N8FMye,M9N8FMze,M9N8MMxe,M9N8MMye,M9N8MMze, & + M9N9FMxe,M9N9FMye,M9N9FMze,M9N9MMxe,M9N9MMye,M9N9MMze /),(/6,9,9/)) + + INTEGER, PARAMETER :: MNTDss(3,9,9) = reshape((/M1N1TDxss,M1N1TDyss,M1N1TDzss, & + M1N2TDxss,M1N2TDyss,M1N2TDzss, & + M1N3TDxss,M1N3TDyss,M1N3TDzss, & + M1N4TDxss,M1N4TDyss,M1N4TDzss, & + M1N5TDxss,M1N5TDyss,M1N5TDzss, & + M1N6TDxss,M1N6TDyss,M1N6TDzss, & + M1N7TDxss,M1N7TDyss,M1N7TDzss, & + M1N8TDxss,M1N8TDyss,M1N8TDzss, & + M1N9TDxss,M1N9TDyss,M1N9TDzss, & + M2N1TDxss,M2N1TDyss,M2N1TDzss, & + M2N2TDxss,M2N2TDyss,M2N2TDzss, & + M2N3TDxss,M2N3TDyss,M2N3TDzss, & + M2N4TDxss,M2N4TDyss,M2N4TDzss, & + M2N5TDxss,M2N5TDyss,M2N5TDzss, & + M2N6TDxss,M2N6TDyss,M2N6TDzss, & + M2N7TDxss,M2N7TDyss,M2N7TDzss, & + M2N8TDxss,M2N8TDyss,M2N8TDzss, & + M2N9TDxss,M2N9TDyss,M2N9TDzss, & + M3N1TDxss,M3N1TDyss,M3N1TDzss, & + M3N2TDxss,M3N2TDyss,M3N2TDzss, & + M3N3TDxss,M3N3TDyss,M3N3TDzss, & + M3N4TDxss,M3N4TDyss,M3N4TDzss, & + M3N5TDxss,M3N5TDyss,M3N5TDzss, & + M3N6TDxss,M3N6TDyss,M3N6TDzss, & + M3N7TDxss,M3N7TDyss,M3N7TDzss, & + M3N8TDxss,M3N8TDyss,M3N8TDzss, & + M3N9TDxss,M3N9TDyss,M3N9TDzss, & + M4N1TDxss,M4N1TDyss,M4N1TDzss, & + M4N2TDxss,M4N2TDyss,M4N2TDzss, & + M4N3TDxss,M4N3TDyss,M4N3TDzss, & + M4N4TDxss,M4N4TDyss,M4N4TDzss, & + M4N5TDxss,M4N5TDyss,M4N5TDzss, & + M4N6TDxss,M4N6TDyss,M4N6TDzss, & + M4N7TDxss,M4N7TDyss,M4N7TDzss, & + M4N8TDxss,M4N8TDyss,M4N8TDzss, & + M4N9TDxss,M4N9TDyss,M4N9TDzss, & + M5N1TDxss,M5N1TDyss,M5N1TDzss, & + M5N2TDxss,M5N2TDyss,M5N2TDzss, & + M5N3TDxss,M5N3TDyss,M5N3TDzss, & + M5N4TDxss,M5N4TDyss,M5N4TDzss, & + M5N5TDxss,M5N5TDyss,M5N5TDzss, & + M5N6TDxss,M5N6TDyss,M5N6TDzss, & + M5N7TDxss,M5N7TDyss,M5N7TDzss, & + M5N8TDxss,M5N8TDyss,M5N8TDzss, & + M5N9TDxss,M5N9TDyss,M5N9TDzss, & + M6N1TDxss,M6N1TDyss,M6N1TDzss, & + M6N2TDxss,M6N2TDyss,M6N2TDzss, & + M6N3TDxss,M6N3TDyss,M6N3TDzss, & + M6N4TDxss,M6N4TDyss,M6N4TDzss, & + M6N5TDxss,M6N5TDyss,M6N5TDzss, & + M6N6TDxss,M6N6TDyss,M6N6TDzss, & + M6N7TDxss,M6N7TDyss,M6N7TDzss, & + M6N8TDxss,M6N8TDyss,M6N8TDzss, & + M6N9TDxss,M6N9TDyss,M6N9TDzss, & + M7N1TDxss,M7N1TDyss,M7N1TDzss, & + M7N2TDxss,M7N2TDyss,M7N2TDzss, & + M7N3TDxss,M7N3TDyss,M7N3TDzss, & + M7N4TDxss,M7N4TDyss,M7N4TDzss, & + M7N5TDxss,M7N5TDyss,M7N5TDzss, & + M7N6TDxss,M7N6TDyss,M7N6TDzss, & + M7N7TDxss,M7N7TDyss,M7N7TDzss, & + M7N8TDxss,M7N8TDyss,M7N8TDzss, & + M7N9TDxss,M7N9TDyss,M7N9TDzss, & + M8N1TDxss,M8N1TDyss,M8N1TDzss, & + M8N2TDxss,M8N2TDyss,M8N2TDzss, & + M8N3TDxss,M8N3TDyss,M8N3TDzss, & + M8N4TDxss,M8N4TDyss,M8N4TDzss, & + M8N5TDxss,M8N5TDyss,M8N5TDzss, & + M8N6TDxss,M8N6TDyss,M8N6TDzss, & + M8N7TDxss,M8N7TDyss,M8N7TDzss, & + M8N8TDxss,M8N8TDyss,M8N8TDzss, & + M8N9TDxss,M8N9TDyss,M8N9TDzss, & + M9N1TDxss,M9N1TDyss,M9N1TDzss, & + M9N2TDxss,M9N2TDyss,M9N2TDzss, & + M9N3TDxss,M9N3TDyss,M9N3TDzss, & + M9N4TDxss,M9N4TDyss,M9N4TDzss, & + M9N5TDxss,M9N5TDyss,M9N5TDzss, & + M9N6TDxss,M9N6TDyss,M9N6TDzss, & + M9N7TDxss,M9N7TDyss,M9N7TDzss, & + M9N8TDxss,M9N8TDyss,M9N8TDzss, & + M9N9TDxss,M9N9TDyss,M9N9TDzss/), (/3,9,9/)) + +INTEGER, PARAMETER :: MNRDe (3,9,9) = reshape((/M1N1RDxe,M1N1RDye,M1N1RDze, & + M1N2RDxe,M1N2RDye,M1N2RDze, & + M1N3RDxe,M1N3RDye,M1N3RDze, & + M1N4RDxe,M1N4RDye,M1N4RDze, & + M1N5RDxe,M1N5RDye,M1N5RDze, & + M1N6RDxe,M1N6RDye,M1N6RDze, & + M1N7RDxe,M1N7RDye,M1N7RDze, & + M1N8RDxe,M1N8RDye,M1N8RDze, & + M1N9RDxe,M1N9RDye,M1N9RDze, & + M2N1RDxe,M2N1RDye,M2N1RDze, & + M2N2RDxe,M2N2RDye,M2N2RDze, & + M2N3RDxe,M2N3RDye,M2N3RDze, & + M2N4RDxe,M2N4RDye,M2N4RDze, & + M2N5RDxe,M2N5RDye,M2N5RDze, & + M2N6RDxe,M2N6RDye,M2N6RDze, & + M2N7RDxe,M2N7RDye,M2N7RDze, & + M2N8RDxe,M2N8RDye,M2N8RDze, & + M2N9RDxe,M2N9RDye,M2N9RDze, & + M3N1RDxe,M3N1RDye,M3N1RDze, & + M3N2RDxe,M3N2RDye,M3N2RDze, & + M3N3RDxe,M3N3RDye,M3N3RDze, & + M3N4RDxe,M3N4RDye,M3N4RDze, & + M3N5RDxe,M3N5RDye,M3N5RDze, & + M3N6RDxe,M3N6RDye,M3N6RDze, & + M3N7RDxe,M3N7RDye,M3N7RDze, & + M3N8RDxe,M3N8RDye,M3N8RDze, & + M3N9RDxe,M3N9RDye,M3N9RDze, & + M4N1RDxe,M4N1RDye,M4N1RDze, & + M4N2RDxe,M4N2RDye,M4N2RDze, & + M4N3RDxe,M4N3RDye,M4N3RDze, & + M4N4RDxe,M4N4RDye,M4N4RDze, & + M4N5RDxe,M4N5RDye,M4N5RDze, & + M4N6RDxe,M4N6RDye,M4N6RDze, & + M4N7RDxe,M4N7RDye,M4N7RDze, & + M4N8RDxe,M4N8RDye,M4N8RDze, & + M4N9RDxe,M4N9RDye,M4N9RDze, & + M5N1RDxe,M5N1RDye,M5N1RDze, & + M5N2RDxe,M5N2RDye,M5N2RDze, & + M5N3RDxe,M5N3RDye,M5N3RDze, & + M5N4RDxe,M5N4RDye,M5N4RDze, & + M5N5RDxe,M5N5RDye,M5N5RDze, & + M5N6RDxe,M5N6RDye,M5N6RDze, & + M5N7RDxe,M5N7RDye,M5N7RDze, & + M5N8RDxe,M5N8RDye,M5N8RDze, & + M5N9RDxe,M5N9RDye,M5N9RDze, & + M6N1RDxe,M6N1RDye,M6N1RDze, & + M6N2RDxe,M6N2RDye,M6N2RDze, & + M6N3RDxe,M6N3RDye,M6N3RDze, & + M6N4RDxe,M6N4RDye,M6N4RDze, & + M6N5RDxe,M6N5RDye,M6N5RDze, & + M6N6RDxe,M6N6RDye,M6N6RDze, & + M6N7RDxe,M6N7RDye,M6N7RDze, & + M6N8RDxe,M6N8RDye,M6N8RDze, & + M6N9RDxe,M6N9RDye,M6N9RDze, & + M7N1RDxe,M7N1RDye,M7N1RDze, & + M7N2RDxe,M7N2RDye,M7N2RDze, & + M7N3RDxe,M7N3RDye,M7N3RDze, & + M7N4RDxe,M7N4RDye,M7N4RDze, & + M7N5RDxe,M7N5RDye,M7N5RDze, & + M7N6RDxe,M7N6RDye,M7N6RDze, & + M7N7RDxe,M7N7RDye,M7N7RDze, & + M7N8RDxe,M7N8RDye,M7N8RDze, & + M7N9RDxe,M7N9RDye,M7N9RDze, & + M8N1RDxe,M8N1RDye,M8N1RDze, & + M8N2RDxe,M8N2RDye,M8N2RDze, & + M8N3RDxe,M8N3RDye,M8N3RDze, & + M8N4RDxe,M8N4RDye,M8N4RDze, & + M8N5RDxe,M8N5RDye,M8N5RDze, & + M8N6RDxe,M8N6RDye,M8N6RDze, & + M8N7RDxe,M8N7RDye,M8N7RDze, & + M8N8RDxe,M8N8RDye,M8N8RDze, & + M8N9RDxe,M8N9RDye,M8N9RDze, & + M9N1RDxe,M9N1RDye,M9N1RDze, & + M9N2RDxe,M9N2RDye,M9N2RDze, & + M9N3RDxe,M9N3RDye,M9N3RDze, & + M9N4RDxe,M9N4RDye,M9N4RDze, & + M9N5RDxe,M9N5RDye,M9N5RDze, & + M9N6RDxe,M9N6RDye,M9N6RDze, & + M9N7RDxe,M9N7RDye,M9N7RDze, & + M9N8RDxe,M9N8RDye,M9N8RDze, & + M9N9RDxe,M9N9RDye,M9N9RDze/), (/3,9,9/)) + + + INTEGER, PARAMETER :: MNTRAe(6,9,9) = reshape( (/M1N1TAxe,M1N1TAye,M1N1TAze,M1N1RAxe,M1N1RAye,M1N1RAze, & + M1N2TAxe,M1N2TAye,M1N2TAze,M1N2RAxe,M1N2RAye,M1N2RAze, & + M1N3TAxe,M1N3TAye,M1N3TAze,M1N3RAxe,M1N3RAye,M1N3RAze, & + M1N4TAxe,M1N4TAye,M1N4TAze,M1N4RAxe,M1N4RAye,M1N4RAze, & + M1N5TAxe,M1N5TAye,M1N5TAze,M1N5RAxe,M1N5RAye,M1N5RAze, & + M1N6TAxe,M1N6TAye,M1N6TAze,M1N6RAxe,M1N6RAye,M1N6RAze, & + M1N7TAxe,M1N7TAye,M1N7TAze,M1N7RAxe,M1N7RAye,M1N7RAze, & + M1N8TAxe,M1N8TAye,M1N8TAze,M1N8RAxe,M1N8RAye,M1N8RAze, & + M1N9TAxe,M1N9TAye,M1N9TAze,M1N9RAxe,M1N9RAye,M1N9RAze, & + M2N1TAxe,M2N1TAye,M2N1TAze,M2N1RAxe,M2N1RAye,M2N1RAze, & + M2N2TAxe,M2N2TAye,M2N2TAze,M2N2RAxe,M2N2RAye,M2N2RAze, & + M2N3TAxe,M2N3TAye,M2N3TAze,M2N3RAxe,M2N3RAye,M2N3RAze, & + M2N4TAxe,M2N4TAye,M2N4TAze,M2N4RAxe,M2N4RAye,M2N4RAze, & + M2N5TAxe,M2N5TAye,M2N5TAze,M2N5RAxe,M2N5RAye,M2N5RAze, & + M2N6TAxe,M2N6TAye,M2N6TAze,M2N6RAxe,M2N6RAye,M2N6RAze, & + M2N7TAxe,M2N7TAye,M2N7TAze,M2N7RAxe,M2N7RAye,M2N7RAze, & + M2N8TAxe,M2N8TAye,M2N8TAze,M2N8RAxe,M2N8RAye,M2N8RAze, & + M2N9TAxe,M2N9TAye,M2N9TAze,M2N9RAxe,M2N9RAye,M2N9RAze, & + M3N1TAxe,M3N1TAye,M3N1TAze,M3N1RAxe,M3N1RAye,M3N1RAze, & + M3N2TAxe,M3N2TAye,M3N2TAze,M3N2RAxe,M3N2RAye,M3N2RAze, & + M3N3TAxe,M3N3TAye,M3N3TAze,M3N3RAxe,M3N3RAye,M3N3RAze, & + M3N4TAxe,M3N4TAye,M3N4TAze,M3N4RAxe,M3N4RAye,M3N4RAze, & + M3N5TAxe,M3N5TAye,M3N5TAze,M3N5RAxe,M3N5RAye,M3N5RAze, & + M3N6TAxe,M3N6TAye,M3N6TAze,M3N6RAxe,M3N6RAye,M3N6RAze, & + M3N7TAxe,M3N7TAye,M3N7TAze,M3N7RAxe,M3N7RAye,M3N7RAze, & + M3N8TAxe,M3N8TAye,M3N8TAze,M3N8RAxe,M3N8RAye,M3N8RAze, & + M3N9TAxe,M3N9TAye,M3N9TAze,M3N9RAxe,M3N9RAye,M3N9RAze, & + M4N1TAxe,M4N1TAye,M4N1TAze,M4N1RAxe,M4N1RAye,M4N1RAze, & + M4N2TAxe,M4N2TAye,M4N2TAze,M4N2RAxe,M4N2RAye,M4N2RAze, & + M4N3TAxe,M4N3TAye,M4N3TAze,M4N3RAxe,M4N3RAye,M4N3RAze, & + M4N4TAxe,M4N4TAye,M4N4TAze,M4N4RAxe,M4N4RAye,M4N4RAze, & + M4N5TAxe,M4N5TAye,M4N5TAze,M4N5RAxe,M4N5RAye,M4N5RAze, & + M4N6TAxe,M4N6TAye,M4N6TAze,M4N6RAxe,M4N6RAye,M4N6RAze, & + M4N7TAxe,M4N7TAye,M4N7TAze,M4N7RAxe,M4N7RAye,M4N7RAze, & + M4N8TAxe,M4N8TAye,M4N8TAze,M4N8RAxe,M4N8RAye,M4N8RAze, & + M4N9TAxe,M4N9TAye,M4N9TAze,M4N9RAxe,M4N9RAye,M4N9RAze, & + M5N1TAxe,M5N1TAye,M5N1TAze,M5N1RAxe,M5N1RAye,M5N1RAze, & + M5N2TAxe,M5N2TAye,M5N2TAze,M5N2RAxe,M5N2RAye,M5N2RAze, & + M5N3TAxe,M5N3TAye,M5N3TAze,M5N3RAxe,M5N3RAye,M5N3RAze, & + M5N4TAxe,M5N4TAye,M5N4TAze,M5N4RAxe,M5N4RAye,M5N4RAze, & + M5N5TAxe,M5N5TAye,M5N5TAze,M5N5RAxe,M5N5RAye,M5N5RAze, & + M5N6TAxe,M5N6TAye,M5N6TAze,M5N6RAxe,M5N6RAye,M5N6RAze, & + M5N7TAxe,M5N7TAye,M5N7TAze,M5N7RAxe,M5N7RAye,M5N7RAze, & + M5N8TAxe,M5N8TAye,M5N8TAze,M5N8RAxe,M5N8RAye,M5N8RAze, & + M5N9TAxe,M5N9TAye,M5N9TAze,M5N9RAxe,M5N9RAye,M5N9RAze, & + M6N1TAxe,M6N1TAye,M6N1TAze,M6N1RAxe,M6N1RAye,M6N1RAze, & + M6N2TAxe,M6N2TAye,M6N2TAze,M6N2RAxe,M6N2RAye,M6N2RAze, & + M6N3TAxe,M6N3TAye,M6N3TAze,M6N3RAxe,M6N3RAye,M6N3RAze, & + M6N4TAxe,M6N4TAye,M6N4TAze,M6N4RAxe,M6N4RAye,M6N4RAze, & + M6N5TAxe,M6N5TAye,M6N5TAze,M6N5RAxe,M6N5RAye,M6N5RAze, & + M6N6TAxe,M6N6TAye,M6N6TAze,M6N6RAxe,M6N6RAye,M6N6RAze, & + M6N7TAxe,M6N7TAye,M6N7TAze,M6N7RAxe,M6N7RAye,M6N7RAze, & + M6N8TAxe,M6N8TAye,M6N8TAze,M6N8RAxe,M6N8RAye,M6N8RAze, & + M6N9TAxe,M6N9TAye,M6N9TAze,M6N9RAxe,M6N9RAye,M6N9RAze, & + M7N1TAxe,M7N1TAye,M7N1TAze,M7N1RAxe,M7N1RAye,M7N1RAze, & + M7N2TAxe,M7N2TAye,M7N2TAze,M7N2RAxe,M7N2RAye,M7N2RAze, & + M7N3TAxe,M7N3TAye,M7N3TAze,M7N3RAxe,M7N3RAye,M7N3RAze, & + M7N4TAxe,M7N4TAye,M7N4TAze,M7N4RAxe,M7N4RAye,M7N4RAze, & + M7N5TAxe,M7N5TAye,M7N5TAze,M7N5RAxe,M7N5RAye,M7N5RAze, & + M7N6TAxe,M7N6TAye,M7N6TAze,M7N6RAxe,M7N6RAye,M7N6RAze, & + M7N7TAxe,M7N7TAye,M7N7TAze,M7N7RAxe,M7N7RAye,M7N7RAze, & + M7N8TAxe,M7N8TAye,M7N8TAze,M7N8RAxe,M7N8RAye,M7N8RAze, & + M7N9TAxe,M7N9TAye,M7N9TAze,M7N9RAxe,M7N9RAye,M7N9RAze, & + M8N1TAxe,M8N1TAye,M8N1TAze,M8N1RAxe,M8N1RAye,M8N1RAze, & + M8N2TAxe,M8N2TAye,M8N2TAze,M8N2RAxe,M8N2RAye,M8N2RAze, & + M8N3TAxe,M8N3TAye,M8N3TAze,M8N3RAxe,M8N3RAye,M8N3RAze, & + M8N4TAxe,M8N4TAye,M8N4TAze,M8N4RAxe,M8N4RAye,M8N4RAze, & + M8N5TAxe,M8N5TAye,M8N5TAze,M8N5RAxe,M8N5RAye,M8N5RAze, & + M8N6TAxe,M8N6TAye,M8N6TAze,M8N6RAxe,M8N6RAye,M8N6RAze, & + M8N7TAxe,M8N7TAye,M8N7TAze,M8N7RAxe,M8N7RAye,M8N7RAze, & + M8N8TAxe,M8N8TAye,M8N8TAze,M8N8RAxe,M8N8RAye,M8N8RAze, & + M8N9TAxe,M8N9TAye,M8N9TAze,M8N9RAxe,M8N9RAye,M8N9RAze, & + M9N1TAxe,M9N1TAye,M9N1TAze,M9N1RAxe,M9N1RAye,M9N1RAze, & + M9N2TAxe,M9N2TAye,M9N2TAze,M9N2RAxe,M9N2RAye,M9N2RAze, & + M9N3TAxe,M9N3TAye,M9N3TAze,M9N3RAxe,M9N3RAye,M9N3RAze, & + M9N4TAxe,M9N4TAye,M9N4TAze,M9N4RAxe,M9N4RAye,M9N4RAze, & + M9N5TAxe,M9N5TAye,M9N5TAze,M9N5RAxe,M9N5RAye,M9N5RAze, & + M9N6TAxe,M9N6TAye,M9N6TAze,M9N6RAxe,M9N6RAye,M9N6RAze, & + M9N7TAxe,M9N7TAye,M9N7TAze,M9N7RAxe,M9N7RAye,M9N7RAze, & + M9N8TAxe,M9N8TAye,M9N8TAze,M9N8RAxe,M9N8RAye,M9N8RAze, & + M9N9TAxe,M9N9TAye,M9N9TAze,M9N9RAxe,M9N9RAye,M9N9RAze/), (/6,9,9/)) + + INTEGER, PARAMETER :: ReactSS(6) = (/ReactFXss, ReactFYss, ReactFZss , & + ReactMXss, ReactMYss, ReactMZss/) + + INTEGER, PARAMETER :: IntfSS(6) = (/IntfFXss, IntfFYss, IntfFZss , & + IntfMXss, IntfMYss, IntfMZss/) + + + INTEGER, PARAMETER :: IntfTRss(6) = (/IntfTDXss, IntfTDYss, IntfTDZss , & + IntfRDXss, IntfRDYss, IntfRDZss/) + + INTEGER, PARAMETER :: IntfTRAss(6) = (/IntfTAXss, IntfTAYss, IntfTAZss , & + IntfRAXss, IntfRAYss, IntfRAZss/) + + + + + + + + CHARACTER(10), PARAMETER :: ValidParamAry(2265) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "INTFFXSS ","INTFFYSS ","INTFFZSS ","INTFMXSS ","INTFMYSS ","INTFMZSS ","INTFRAXSS", & + "INTFRAYSS","INTFRAZSS","INTFRDXSS","INTFRDYSS","INTFRDZSS","INTFTAXSS","INTFTAYSS", & + "INTFTAZSS","INTFTDXSS","INTFTDYSS","INTFTDZSS","M1N1FKXE ","M1N1FKYE ","M1N1FKZE ", & + "M1N1FMXE ","M1N1FMYE ","M1N1FMZE ","M1N1MKXE ","M1N1MKYE ","M1N1MKZE ","M1N1MMXE ", & + "M1N1MMYE ","M1N1MMZE ","M1N1RAXE ","M1N1RAYE ","M1N1RAZE ","M1N1RDXE ","M1N1RDYE ", & + "M1N1RDZE ","M1N1TAXE ","M1N1TAYE ","M1N1TAZE ","M1N1TDXSS","M1N1TDYSS","M1N1TDZSS", & + "M1N2FKXE ","M1N2FKYE ","M1N2FKZE ","M1N2FMXE ","M1N2FMYE ","M1N2FMZE ","M1N2MKXE ", & + "M1N2MKYE ","M1N2MKZE ","M1N2MMXE ","M1N2MMYE ","M1N2MMZE ","M1N2RAXE ","M1N2RAYE ", & + "M1N2RAZE ","M1N2RDXE ","M1N2RDYE ","M1N2RDZE ","M1N2TAXE ","M1N2TAYE ","M1N2TAZE ", & + "M1N2TDXSS","M1N2TDYSS","M1N2TDZSS","M1N3FKXE ","M1N3FKYE ","M1N3FKZE ","M1N3FMXE ", & + "M1N3FMYE ","M1N3FMZE ","M1N3MKXE ","M1N3MKYE ","M1N3MKZE ","M1N3MMXE ","M1N3MMYE ", & + "M1N3MMZE ","M1N3RAXE ","M1N3RAYE ","M1N3RAZE ","M1N3RDXE ","M1N3RDYE ","M1N3RDZE ", & + "M1N3TAXE ","M1N3TAYE ","M1N3TAZE ","M1N3TDXSS","M1N3TDYSS","M1N3TDZSS","M1N4FKXE ", & + "M1N4FKYE ","M1N4FKZE ","M1N4FMXE ","M1N4FMYE ","M1N4FMZE ","M1N4MKXE ","M1N4MKYE ", & + "M1N4MKZE ","M1N4MMXE ","M1N4MMYE ","M1N4MMZE ","M1N4RAXE ","M1N4RAYE ","M1N4RAZE ", & + "M1N4RDXE ","M1N4RDYE ","M1N4RDZE ","M1N4TAXE ","M1N4TAYE ","M1N4TAZE ","M1N4TDXSS", & + "M1N4TDYSS","M1N4TDZSS","M1N5FKXE ","M1N5FKYE ","M1N5FKZE ","M1N5FMXE ","M1N5FMYE ", & + "M1N5FMZE ","M1N5MKXE ","M1N5MKYE ","M1N5MKZE ","M1N5MMXE ","M1N5MMYE ","M1N5MMZE ", & + "M1N5RAXE ","M1N5RAYE ","M1N5RAZE ","M1N5RDXE ","M1N5RDYE ","M1N5RDZE ","M1N5TAXE ", & + "M1N5TAYE ","M1N5TAZE ","M1N5TDXSS","M1N5TDYSS","M1N5TDZSS","M1N6FKXE ","M1N6FKYE ", & + "M1N6FKZE ","M1N6FMXE ","M1N6FMYE ","M1N6FMZE ","M1N6MKXE ","M1N6MKYE ","M1N6MKZE ", & + "M1N6MMXE ","M1N6MMYE ","M1N6MMZE ","M1N6RAXE ","M1N6RAYE ","M1N6RAZE ","M1N6RDXE ", & + "M1N6RDYE ","M1N6RDZE ","M1N6TAXE ","M1N6TAYE ","M1N6TAZE ","M1N6TDXSS","M1N6TDYSS", & + "M1N6TDZSS","M1N7FKXE ","M1N7FKYE ","M1N7FKZE ","M1N7FMXE ","M1N7FMYE ","M1N7FMZE ", & + "M1N7MKXE ","M1N7MKYE ","M1N7MKZE ","M1N7MMXE ","M1N7MMYE ","M1N7MMZE ","M1N7RAXE ", & + "M1N7RAYE ","M1N7RAZE ","M1N7RDXE ","M1N7RDYE ","M1N7RDZE ","M1N7TAXE ","M1N7TAYE ", & + "M1N7TAZE ","M1N7TDXSS","M1N7TDYSS","M1N7TDZSS","M1N8FKXE ","M1N8FKYE ","M1N8FKZE ", & + "M1N8FMXE ","M1N8FMYE ","M1N8FMZE ","M1N8MKXE ","M1N8MKYE ","M1N8MKZE ","M1N8MMXE ", & + "M1N8MMYE ","M1N8MMZE ","M1N8RAXE ","M1N8RAYE ","M1N8RAZE ","M1N8RDXE ","M1N8RDYE ", & + "M1N8RDZE ","M1N8TAXE ","M1N8TAYE ","M1N8TAZE ","M1N8TDXSS","M1N8TDYSS","M1N8TDZSS", & + "M1N9FKXE ","M1N9FKYE ","M1N9FKZE ","M1N9FMXE ","M1N9FMYE ","M1N9FMZE ","M1N9MKXE ", & + "M1N9MKYE ","M1N9MKZE ","M1N9MMXE ","M1N9MMYE ","M1N9MMZE ","M1N9RAXE ","M1N9RAYE ", & + "M1N9RAZE ","M1N9RDXE ","M1N9RDYE ","M1N9RDZE ","M1N9TAXE ","M1N9TAYE ","M1N9TAZE ", & + "M1N9TDXSS","M1N9TDYSS","M1N9TDZSS","M2N1FKXE ","M2N1FKYE ","M2N1FKZE ","M2N1FMXE ", & + "M2N1FMYE ","M2N1FMZE ","M2N1MKXE ","M2N1MKYE ","M2N1MKZE ","M2N1MMXE ","M2N1MMYE ", & + "M2N1MMZE ","M2N1RAXE ","M2N1RAYE ","M2N1RAZE ","M2N1RDXE ","M2N1RDYE ","M2N1RDZE ", & + "M2N1TAXE ","M2N1TAYE ","M2N1TAZE ","M2N1TDXSS","M2N1TDYSS","M2N1TDZSS","M2N2FKXE ", & + "M2N2FKYE ","M2N2FKZE ","M2N2FMXE ","M2N2FMYE ","M2N2FMZE ","M2N2MKXE ","M2N2MKYE ", & + "M2N2MKZE ","M2N2MMXE ","M2N2MMYE ","M2N2MMZE ","M2N2RAXE ","M2N2RAYE ","M2N2RAZE ", & + "M2N2RDXE ","M2N2RDYE ","M2N2RDZE ","M2N2TAXE ","M2N2TAYE ","M2N2TAZE ","M2N2TDXSS", & + "M2N2TDYSS","M2N2TDZSS","M2N3FKXE ","M2N3FKYE ","M2N3FKZE ","M2N3FMXE ","M2N3FMYE ", & + "M2N3FMZE ","M2N3MKXE ","M2N3MKYE ","M2N3MKZE ","M2N3MMXE ","M2N3MMYE ","M2N3MMZE ", & + "M2N3RAXE ","M2N3RAYE ","M2N3RAZE ","M2N3RDXE ","M2N3RDYE ","M2N3RDZE ","M2N3TAXE ", & + "M2N3TAYE ","M2N3TAZE ","M2N3TDXSS","M2N3TDYSS","M2N3TDZSS","M2N4FKXE ","M2N4FKYE ", & + "M2N4FKZE ","M2N4FMXE ","M2N4FMYE ","M2N4FMZE ","M2N4MKXE ","M2N4MKYE ","M2N4MKZE ", & + "M2N4MMXE ","M2N4MMYE ","M2N4MMZE ","M2N4RAXE ","M2N4RAYE ","M2N4RAZE ","M2N4RDXE ", & + "M2N4RDYE ","M2N4RDZE ","M2N4TAXE ","M2N4TAYE ","M2N4TAZE ","M2N4TDXSS","M2N4TDYSS", & + "M2N4TDZSS","M2N5FKXE ","M2N5FKYE ","M2N5FKZE ","M2N5FMXE ","M2N5FMYE ","M2N5FMZE ", & + "M2N5MKXE ","M2N5MKYE ","M2N5MKZE ","M2N5MMXE ","M2N5MMYE ","M2N5MMZE ","M2N5RAXE ", & + "M2N5RAYE ","M2N5RAZE ","M2N5RDXE ","M2N5RDYE ","M2N5RDZE ","M2N5TAXE ","M2N5TAYE ", & + "M2N5TAZE ","M2N5TDXSS","M2N5TDYSS","M2N5TDZSS","M2N6FKXE ","M2N6FKYE ","M2N6FKZE ", & + "M2N6FMXE ","M2N6FMYE ","M2N6FMZE ","M2N6MKXE ","M2N6MKYE ","M2N6MKZE ","M2N6MMXE ", & + "M2N6MMYE ","M2N6MMZE ","M2N6RAXE ","M2N6RAYE ","M2N6RAZE ","M2N6RDXE ","M2N6RDYE ", & + "M2N6RDZE ","M2N6TAXE ","M2N6TAYE ","M2N6TAZE ","M2N6TDXSS","M2N6TDYSS","M2N6TDZSS", & + "M2N7FKXE ","M2N7FKYE ","M2N7FKZE ","M2N7FMXE ","M2N7FMYE ","M2N7FMZE ","M2N7MKXE ", & + "M2N7MKYE ","M2N7MKZE ","M2N7MMXE ","M2N7MMYE ","M2N7MMZE ","M2N7RAXE ","M2N7RAYE ", & + "M2N7RAZE ","M2N7RDXE ","M2N7RDYE ","M2N7RDZE ","M2N7TAXE ","M2N7TAYE ","M2N7TAZE ", & + "M2N7TDXSS","M2N7TDYSS","M2N7TDZSS","M2N8FKXE ","M2N8FKYE ","M2N8FKZE ","M2N8FMXE ", & + "M2N8FMYE ","M2N8FMZE ","M2N8MKXE ","M2N8MKYE ","M2N8MKZE ","M2N8MMXE ","M2N8MMYE ", & + "M2N8MMZE ","M2N8RAXE ","M2N8RAYE ","M2N8RAZE ","M2N8RDXE ","M2N8RDYE ","M2N8RDZE ", & + "M2N8TAXE ","M2N8TAYE ","M2N8TAZE ","M2N8TDXSS","M2N8TDYSS","M2N8TDZSS","M2N9FKXE ", & + "M2N9FKYE ","M2N9FKZE ","M2N9FMXE ","M2N9FMYE ","M2N9FMZE ","M2N9MKXE ","M2N9MKYE ", & + "M2N9MKZE ","M2N9MMXE ","M2N9MMYE ","M2N9MMZE ","M2N9RAXE ","M2N9RAYE ","M2N9RAZE ", & + "M2N9RDXE ","M2N9RDYE ","M2N9RDZE ","M2N9TAXE ","M2N9TAYE ","M2N9TAZE ","M2N9TDXSS", & + "M2N9TDYSS","M2N9TDZSS","M3N1FKXE ","M3N1FKYE ","M3N1FKZE ","M3N1FMXE ","M3N1FMYE ", & + "M3N1FMZE ","M3N1MKXE ","M3N1MKYE ","M3N1MKZE ","M3N1MMXE ","M3N1MMYE ","M3N1MMZE ", & + "M3N1RAXE ","M3N1RAYE ","M3N1RAZE ","M3N1RDXE ","M3N1RDYE ","M3N1RDZE ","M3N1TAXE ", & + "M3N1TAYE ","M3N1TAZE ","M3N1TDXSS","M3N1TDYSS","M3N1TDZSS","M3N2FKXE ","M3N2FKYE ", & + "M3N2FKZE ","M3N2FMXE ","M3N2FMYE ","M3N2FMZE ","M3N2MKXE ","M3N2MKYE ","M3N2MKZE ", & + "M3N2MMXE ","M3N2MMYE ","M3N2MMZE ","M3N2RAXE ","M3N2RAYE ","M3N2RAZE ","M3N2RDXE ", & + "M3N2RDYE ","M3N2RDZE ","M3N2TAXE ","M3N2TAYE ","M3N2TAZE ","M3N2TDXSS","M3N2TDYSS", & + "M3N2TDZSS","M3N3FKXE ","M3N3FKYE ","M3N3FKZE ","M3N3FMXE ","M3N3FMYE ","M3N3FMZE ", & + "M3N3MKXE ","M3N3MKYE ","M3N3MKZE ","M3N3MMXE ","M3N3MMYE ","M3N3MMZE ","M3N3RAXE ", & + "M3N3RAYE ","M3N3RAZE ","M3N3RDXE ","M3N3RDYE ","M3N3RDZE ","M3N3TAXE ","M3N3TAYE ", & + "M3N3TAZE ","M3N3TDXSS","M3N3TDYSS","M3N3TDZSS","M3N4FKXE ","M3N4FKYE ","M3N4FKZE ", & + "M3N4FMXE ","M3N4FMYE ","M3N4FMZE ","M3N4MKXE ","M3N4MKYE ","M3N4MKZE ","M3N4MMXE ", & + "M3N4MMYE ","M3N4MMZE ","M3N4RAXE ","M3N4RAYE ","M3N4RAZE ","M3N4RDXE ","M3N4RDYE ", & + "M3N4RDZE ","M3N4TAXE ","M3N4TAYE ","M3N4TAZE ","M3N4TDXSS","M3N4TDYSS","M3N4TDZSS", & + "M3N5FKXE ","M3N5FKYE ","M3N5FKZE ","M3N5FMXE ","M3N5FMYE ","M3N5FMZE ","M3N5MKXE ", & + "M3N5MKYE ","M3N5MKZE ","M3N5MMXE ","M3N5MMYE ","M3N5MMZE ","M3N5RAXE ","M3N5RAYE ", & + "M3N5RAZE ","M3N5RDXE ","M3N5RDYE ","M3N5RDZE ","M3N5TAXE ","M3N5TAYE ","M3N5TAZE ", & + "M3N5TDXSS","M3N5TDYSS","M3N5TDZSS","M3N6FKXE ","M3N6FKYE ","M3N6FKZE ","M3N6FMXE ", & + "M3N6FMYE ","M3N6FMZE ","M3N6MKXE ","M3N6MKYE ","M3N6MKZE ","M3N6MMXE ","M3N6MMYE ", & + "M3N6MMZE ","M3N6RAXE ","M3N6RAYE ","M3N6RAZE ","M3N6RDXE ","M3N6RDYE ","M3N6RDZE ", & + "M3N6TAXE ","M3N6TAYE ","M3N6TAZE ","M3N6TDXSS","M3N6TDYSS","M3N6TDZSS","M3N7FKXE ", & + "M3N7FKYE ","M3N7FKZE ","M3N7FMXE ","M3N7FMYE ","M3N7FMZE ","M3N7MKXE ","M3N7MKYE ", & + "M3N7MKZE ","M3N7MMXE ","M3N7MMYE ","M3N7MMZE ","M3N7RAXE ","M3N7RAYE ","M3N7RAZE ", & + "M3N7RDXE ","M3N7RDYE ","M3N7RDZE ","M3N7TAXE ","M3N7TAYE ","M3N7TAZE ","M3N7TDXSS", & + "M3N7TDYSS","M3N7TDZSS","M3N8FKXE ","M3N8FKYE ","M3N8FKZE ","M3N8FMXE ","M3N8FMYE ", & + "M3N8FMZE ","M3N8MKXE ","M3N8MKYE ","M3N8MKZE ","M3N8MMXE ","M3N8MMYE ","M3N8MMZE ", & + "M3N8RAXE ","M3N8RAYE ","M3N8RAZE ","M3N8RDXE ","M3N8RDYE ","M3N8RDZE ","M3N8TAXE ", & + "M3N8TAYE ","M3N8TAZE ","M3N8TDXSS","M3N8TDYSS","M3N8TDZSS","M3N9FKXE ","M3N9FKYE ", & + "M3N9FKZE ","M3N9FMXE ","M3N9FMYE ","M3N9FMZE ","M3N9MKXE ","M3N9MKYE ","M3N9MKZE ", & + "M3N9MMXE ","M3N9MMYE ","M3N9MMZE ","M3N9RAXE ","M3N9RAYE ","M3N9RAZE ","M3N9RDXE ", & + "M3N9RDYE ","M3N9RDZE ","M3N9TAXE ","M3N9TAYE ","M3N9TAZE ","M3N9TDXSS","M3N9TDYSS", & + "M3N9TDZSS","M4N1FKXE ","M4N1FKYE ","M4N1FKZE ","M4N1FMXE ","M4N1FMYE ","M4N1FMZE ", & + "M4N1MKXE ","M4N1MKYE ","M4N1MKZE ","M4N1MMXE ","M4N1MMYE ","M4N1MMZE ","M4N1RAXE ", & + "M4N1RAYE ","M4N1RAZE ","M4N1RDXE ","M4N1RDYE ","M4N1RDZE ","M4N1TAXE ","M4N1TAYE ", & + "M4N1TAZE ","M4N1TDXSS","M4N1TDYSS","M4N1TDZSS","M4N2FKXE ","M4N2FKYE ","M4N2FKZE ", & + "M4N2FMXE ","M4N2FMYE ","M4N2FMZE ","M4N2MKXE ","M4N2MKYE ","M4N2MKZE ","M4N2MMXE ", & + "M4N2MMYE ","M4N2MMZE ","M4N2RAXE ","M4N2RAYE ","M4N2RAZE ","M4N2RDXE ","M4N2RDYE ", & + "M4N2RDZE ","M4N2TAXE ","M4N2TAYE ","M4N2TAZE ","M4N2TDXSS","M4N2TDYSS","M4N2TDZSS", & + "M4N3FKXE ","M4N3FKYE ","M4N3FKZE ","M4N3FMXE ","M4N3FMYE ","M4N3FMZE ","M4N3MKXE ", & + "M4N3MKYE ","M4N3MKZE ","M4N3MMXE ","M4N3MMYE ","M4N3MMZE ","M4N3RAXE ","M4N3RAYE ", & + "M4N3RAZE ","M4N3RDXE ","M4N3RDYE ","M4N3RDZE ","M4N3TAXE ","M4N3TAYE ","M4N3TAZE ", & + "M4N3TDXSS","M4N3TDYSS","M4N3TDZSS","M4N4FKXE ","M4N4FKYE ","M4N4FKZE ","M4N4FMXE ", & + "M4N4FMYE ","M4N4FMZE ","M4N4MKXE ","M4N4MKYE ","M4N4MKZE ","M4N4MMXE ","M4N4MMYE ", & + "M4N4MMZE ","M4N4RAXE ","M4N4RAYE ","M4N4RAZE ","M4N4RDXE ","M4N4RDYE ","M4N4RDZE ", & + "M4N4TAXE ","M4N4TAYE ","M4N4TAZE ","M4N4TDXSS","M4N4TDYSS","M4N4TDZSS","M4N5FKXE ", & + "M4N5FKYE ","M4N5FKZE ","M4N5FMXE ","M4N5FMYE ","M4N5FMZE ","M4N5MKXE ","M4N5MKYE ", & + "M4N5MKZE ","M4N5MMXE ","M4N5MMYE ","M4N5MMZE ","M4N5RAXE ","M4N5RAYE ","M4N5RAZE ", & + "M4N5RDXE ","M4N5RDYE ","M4N5RDZE ","M4N5TAXE ","M4N5TAYE ","M4N5TAZE ","M4N5TDXSS", & + "M4N5TDYSS","M4N5TDZSS","M4N6FKXE ","M4N6FKYE ","M4N6FKZE ","M4N6FMXE ","M4N6FMYE ", & + "M4N6FMZE ","M4N6MKXE ","M4N6MKYE ","M4N6MKZE ","M4N6MMXE ","M4N6MMYE ","M4N6MMZE ", & + "M4N6RAXE ","M4N6RAYE ","M4N6RAZE ","M4N6RDXE ","M4N6RDYE ","M4N6RDZE ","M4N6TAXE ", & + "M4N6TAYE ","M4N6TAZE ","M4N6TDXSS","M4N6TDYSS","M4N6TDZSS","M4N7FKXE ","M4N7FKYE ", & + "M4N7FKZE ","M4N7FMXE ","M4N7FMYE ","M4N7FMZE ","M4N7MKXE ","M4N7MKYE ","M4N7MKZE ", & + "M4N7MMXE ","M4N7MMYE ","M4N7MMZE ","M4N7RAXE ","M4N7RAYE ","M4N7RAZE ","M4N7RDXE ", & + "M4N7RDYE ","M4N7RDZE ","M4N7TAXE ","M4N7TAYE ","M4N7TAZE ","M4N7TDXSS","M4N7TDYSS", & + "M4N7TDZSS","M4N8FKXE ","M4N8FKYE ","M4N8FKZE ","M4N8FMXE ","M4N8FMYE ","M4N8FMZE ", & + "M4N8MKXE ","M4N8MKYE ","M4N8MKZE ","M4N8MMXE ","M4N8MMYE ","M4N8MMZE ","M4N8RAXE ", & + "M4N8RAYE ","M4N8RAZE ","M4N8RDXE ","M4N8RDYE ","M4N8RDZE ","M4N8TAXE ","M4N8TAYE ", & + "M4N8TAZE ","M4N8TDXSS","M4N8TDYSS","M4N8TDZSS","M4N9FKXE ","M4N9FKYE ","M4N9FKZE ", & + "M4N9FMXE ","M4N9FMYE ","M4N9FMZE ","M4N9MKXE ","M4N9MKYE ","M4N9MKZE ","M4N9MMXE ", & + "M4N9MMYE ","M4N9MMZE ","M4N9RAXE ","M4N9RAYE ","M4N9RAZE ","M4N9RDXE ","M4N9RDYE ", & + "M4N9RDZE ","M4N9TAXE ","M4N9TAYE ","M4N9TAZE ","M4N9TDXSS","M4N9TDYSS","M4N9TDZSS", & + "M5N1FKXE ","M5N1FKYE ","M5N1FKZE ","M5N1FMXE ","M5N1FMYE ","M5N1FMZE ","M5N1MKXE ", & + "M5N1MKYE ","M5N1MKZE ","M5N1MMXE ","M5N1MMYE ","M5N1MMZE ","M5N1RAXE ","M5N1RAYE ", & + "M5N1RAZE ","M5N1RDXE ","M5N1RDYE ","M5N1RDZE ","M5N1TAXE ","M5N1TAYE ","M5N1TAZE ", & + "M5N1TDXSS","M5N1TDYSS","M5N1TDZSS","M5N2FKXE ","M5N2FKYE ","M5N2FKZE ","M5N2FMXE ", & + "M5N2FMYE ","M5N2FMZE ","M5N2MKXE ","M5N2MKYE ","M5N2MKZE ","M5N2MMXE ","M5N2MMYE ", & + "M5N2MMZE ","M5N2RAXE ","M5N2RAYE ","M5N2RAZE ","M5N2RDXE ","M5N2RDYE ","M5N2RDZE ", & + "M5N2TAXE ","M5N2TAYE ","M5N2TAZE ","M5N2TDXSS","M5N2TDYSS","M5N2TDZSS","M5N3FKXE ", & + "M5N3FKYE ","M5N3FKZE ","M5N3FMXE ","M5N3FMYE ","M5N3FMZE ","M5N3MKXE ","M5N3MKYE ", & + "M5N3MKZE ","M5N3MMXE ","M5N3MMYE ","M5N3MMZE ","M5N3RAXE ","M5N3RAYE ","M5N3RAZE ", & + "M5N3RDXE ","M5N3RDYE ","M5N3RDZE ","M5N3TAXE ","M5N3TAYE ","M5N3TAZE ","M5N3TDXSS", & + "M5N3TDYSS","M5N3TDZSS","M5N4FKXE ","M5N4FKYE ","M5N4FKZE ","M5N4FMXE ","M5N4FMYE ", & + "M5N4FMZE ","M5N4MKXE ","M5N4MKYE ","M5N4MKZE ","M5N4MMXE ","M5N4MMYE ","M5N4MMZE ", & + "M5N4RAXE ","M5N4RAYE ","M5N4RAZE ","M5N4RDXE ","M5N4RDYE ","M5N4RDZE ","M5N4TAXE ", & + "M5N4TAYE ","M5N4TAZE ","M5N4TDXSS","M5N4TDYSS","M5N4TDZSS","M5N5FKXE ","M5N5FKYE ", & + "M5N5FKZE ","M5N5FMXE ","M5N5FMYE ","M5N5FMZE ","M5N5MKXE ","M5N5MKYE ","M5N5MKZE ", & + "M5N5MMXE ","M5N5MMYE ","M5N5MMZE ","M5N5RAXE ","M5N5RAYE ","M5N5RAZE ","M5N5RDXE ", & + "M5N5RDYE ","M5N5RDZE ","M5N5TAXE ","M5N5TAYE ","M5N5TAZE ","M5N5TDXSS","M5N5TDYSS", & + "M5N5TDZSS","M5N6FKXE ","M5N6FKYE ","M5N6FKZE ","M5N6FMXE ","M5N6FMYE ","M5N6FMZE ", & + "M5N6MKXE ","M5N6MKYE ","M5N6MKZE ","M5N6MMXE ","M5N6MMYE ","M5N6MMZE ","M5N6RAXE ", & + "M5N6RAYE ","M5N6RAZE ","M5N6RDXE ","M5N6RDYE ","M5N6RDZE ","M5N6TAXE ","M5N6TAYE ", & + "M5N6TAZE ","M5N6TDXSS","M5N6TDYSS","M5N6TDZSS","M5N7FKXE ","M5N7FKYE ","M5N7FKZE ", & + "M5N7FMXE ","M5N7FMYE ","M5N7FMZE ","M5N7MKXE ","M5N7MKYE ","M5N7MKZE ","M5N7MMXE ", & + "M5N7MMYE ","M5N7MMZE ","M5N7RAXE ","M5N7RAYE ","M5N7RAZE ","M5N7RDXE ","M5N7RDYE ", & + "M5N7RDZE ","M5N7TAXE ","M5N7TAYE ","M5N7TAZE ","M5N7TDXSS","M5N7TDYSS","M5N7TDZSS", & + "M5N8FKXE ","M5N8FKYE ","M5N8FKZE ","M5N8FMXE ","M5N8FMYE ","M5N8FMZE ","M5N8MKXE ", & + "M5N8MKYE ","M5N8MKZE ","M5N8MMXE ","M5N8MMYE ","M5N8MMZE ","M5N8RAXE ","M5N8RAYE ", & + "M5N8RAZE ","M5N8RDXE ","M5N8RDYE ","M5N8RDZE ","M5N8TAXE ","M5N8TAYE ","M5N8TAZE ", & + "M5N8TDXSS","M5N8TDYSS","M5N8TDZSS","M5N9FKXE ","M5N9FKYE ","M5N9FKZE ","M5N9FMXE ", & + "M5N9FMYE ","M5N9FMZE ","M5N9MKXE ","M5N9MKYE ","M5N9MKZE ","M5N9MMXE ","M5N9MMYE ", & + "M5N9MMZE ","M5N9RAXE ","M5N9RAYE ","M5N9RAZE ","M5N9RDXE ","M5N9RDYE ","M5N9RDZE ", & + "M5N9TAXE ","M5N9TAYE ","M5N9TAZE ","M5N9TDXSS","M5N9TDYSS","M5N9TDZSS","M6N1FKXE ", & + "M6N1FKYE ","M6N1FKZE ","M6N1FMXE ","M6N1FMYE ","M6N1FMZE ","M6N1MKXE ","M6N1MKYE ", & + "M6N1MKZE ","M6N1MMXE ","M6N1MMYE ","M6N1MMZE ","M6N1RAXE ","M6N1RAYE ","M6N1RAZE ", & + "M6N1RDXE ","M6N1RDYE ","M6N1RDZE ","M6N1TAXE ","M6N1TAYE ","M6N1TAZE ","M6N1TDXSS", & + "M6N1TDYSS","M6N1TDZSS","M6N2FKXE ","M6N2FKYE ","M6N2FKZE ","M6N2FMXE ","M6N2FMYE ", & + "M6N2FMZE ","M6N2MKXE ","M6N2MKYE ","M6N2MKZE ","M6N2MMXE ","M6N2MMYE ","M6N2MMZE ", & + "M6N2RAXE ","M6N2RAYE ","M6N2RAZE ","M6N2RDXE ","M6N2RDYE ","M6N2RDZE ","M6N2TAXE ", & + "M6N2TAYE ","M6N2TAZE ","M6N2TDXSS","M6N2TDYSS","M6N2TDZSS","M6N3FKXE ","M6N3FKYE ", & + "M6N3FKZE ","M6N3FMXE ","M6N3FMYE ","M6N3FMZE ","M6N3MKXE ","M6N3MKYE ","M6N3MKZE ", & + "M6N3MMXE ","M6N3MMYE ","M6N3MMZE ","M6N3RAXE ","M6N3RAYE ","M6N3RAZE ","M6N3RDXE ", & + "M6N3RDYE ","M6N3RDZE ","M6N3TAXE ","M6N3TAYE ","M6N3TAZE ","M6N3TDXSS","M6N3TDYSS", & + "M6N3TDZSS","M6N4FKXE ","M6N4FKYE ","M6N4FKZE ","M6N4FMXE ","M6N4FMYE ","M6N4FMZE ", & + "M6N4MKXE ","M6N4MKYE ","M6N4MKZE ","M6N4MMXE ","M6N4MMYE ","M6N4MMZE ","M6N4RAXE ", & + "M6N4RAYE ","M6N4RAZE ","M6N4RDXE ","M6N4RDYE ","M6N4RDZE ","M6N4TAXE ","M6N4TAYE ", & + "M6N4TAZE ","M6N4TDXSS","M6N4TDYSS","M6N4TDZSS","M6N5FKXE ","M6N5FKYE ","M6N5FKZE ", & + "M6N5FMXE ","M6N5FMYE ","M6N5FMZE ","M6N5MKXE ","M6N5MKYE ","M6N5MKZE ","M6N5MMXE ", & + "M6N5MMYE ","M6N5MMZE ","M6N5RAXE ","M6N5RAYE ","M6N5RAZE ","M6N5RDXE ","M6N5RDYE ", & + "M6N5RDZE ","M6N5TAXE ","M6N5TAYE ","M6N5TAZE ","M6N5TDXSS","M6N5TDYSS","M6N5TDZSS", & + "M6N6FKXE ","M6N6FKYE ","M6N6FKZE ","M6N6FMXE ","M6N6FMYE ","M6N6FMZE ","M6N6MKXE ", & + "M6N6MKYE ","M6N6MKZE ","M6N6MMXE ","M6N6MMYE ","M6N6MMZE ","M6N6RAXE ","M6N6RAYE ", & + "M6N6RAZE ","M6N6RDXE ","M6N6RDYE ","M6N6RDZE ","M6N6TAXE ","M6N6TAYE ","M6N6TAZE ", & + "M6N6TDXSS","M6N6TDYSS","M6N6TDZSS","M6N7FKXE ","M6N7FKYE ","M6N7FKZE ","M6N7FMXE ", & + "M6N7FMYE ","M6N7FMZE ","M6N7MKXE ","M6N7MKYE ","M6N7MKZE ","M6N7MMXE ","M6N7MMYE ", & + "M6N7MMZE ","M6N7RAXE ","M6N7RAYE ","M6N7RAZE ","M6N7RDXE ","M6N7RDYE ","M6N7RDZE ", & + "M6N7TAXE ","M6N7TAYE ","M6N7TAZE ","M6N7TDXSS","M6N7TDYSS","M6N7TDZSS","M6N8FKXE ", & + "M6N8FKYE ","M6N8FKZE ","M6N8FMXE ","M6N8FMYE ","M6N8FMZE ","M6N8MKXE ","M6N8MKYE ", & + "M6N8MKZE ","M6N8MMXE ","M6N8MMYE ","M6N8MMZE ","M6N8RAXE ","M6N8RAYE ","M6N8RAZE ", & + "M6N8RDXE ","M6N8RDYE ","M6N8RDZE ","M6N8TAXE ","M6N8TAYE ","M6N8TAZE ","M6N8TDXSS", & + "M6N8TDYSS","M6N8TDZSS","M6N9FKXE ","M6N9FKYE ","M6N9FKZE ","M6N9FMXE ","M6N9FMYE ", & + "M6N9FMZE ","M6N9MKXE ","M6N9MKYE ","M6N9MKZE ","M6N9MMXE ","M6N9MMYE ","M6N9MMZE ", & + "M6N9RAXE ","M6N9RAYE ","M6N9RAZE ","M6N9RDXE ","M6N9RDYE ","M6N9RDZE ","M6N9TAXE ", & + "M6N9TAYE ","M6N9TAZE ","M6N9TDXSS","M6N9TDYSS","M6N9TDZSS","M7N1FKXE ","M7N1FKYE ", & + "M7N1FKZE ","M7N1FMXE ","M7N1FMYE ","M7N1FMZE ","M7N1MKXE ","M7N1MKYE ","M7N1MKZE ", & + "M7N1MMXE ","M7N1MMYE ","M7N1MMZE ","M7N1RAXE ","M7N1RAYE ","M7N1RAZE ","M7N1RDXE ", & + "M7N1RDYE ","M7N1RDZE ","M7N1TAXE ","M7N1TAYE ","M7N1TAZE ","M7N1TDXSS","M7N1TDYSS", & + "M7N1TDZSS","M7N2FKXE ","M7N2FKYE ","M7N2FKZE ","M7N2FMXE ","M7N2FMYE ","M7N2FMZE ", & + "M7N2MKXE ","M7N2MKYE ","M7N2MKZE ","M7N2MMXE ","M7N2MMYE ","M7N2MMZE ","M7N2RAXE ", & + "M7N2RAYE ","M7N2RAZE ","M7N2RDXE ","M7N2RDYE ","M7N2RDZE ","M7N2TAXE ","M7N2TAYE ", & + "M7N2TAZE ","M7N2TDXSS","M7N2TDYSS","M7N2TDZSS","M7N3FKXE ","M7N3FKYE ","M7N3FKZE ", & + "M7N3FMXE ","M7N3FMYE ","M7N3FMZE ","M7N3MKXE ","M7N3MKYE ","M7N3MKZE ","M7N3MMXE ", & + "M7N3MMYE ","M7N3MMZE ","M7N3RAXE ","M7N3RAYE ","M7N3RAZE ","M7N3RDXE ","M7N3RDYE ", & + "M7N3RDZE ","M7N3TAXE ","M7N3TAYE ","M7N3TAZE ","M7N3TDXSS","M7N3TDYSS","M7N3TDZSS", & + "M7N4FKXE ","M7N4FKYE ","M7N4FKZE ","M7N4FMXE ","M7N4FMYE ","M7N4FMZE ","M7N4MKXE ", & + "M7N4MKYE ","M7N4MKZE ","M7N4MMXE ","M7N4MMYE ","M7N4MMZE ","M7N4RAXE ","M7N4RAYE ", & + "M7N4RAZE ","M7N4RDXE ","M7N4RDYE ","M7N4RDZE ","M7N4TAXE ","M7N4TAYE ","M7N4TAZE ", & + "M7N4TDXSS","M7N4TDYSS","M7N4TDZSS","M7N5FKXE ","M7N5FKYE ","M7N5FKZE ","M7N5FMXE ", & + "M7N5FMYE ","M7N5FMZE ","M7N5MKXE ","M7N5MKYE ","M7N5MKZE ","M7N5MMXE ","M7N5MMYE ", & + "M7N5MMZE ","M7N5RAXE ","M7N5RAYE ","M7N5RAZE ","M7N5RDXE ","M7N5RDYE ","M7N5RDZE ", & + "M7N5TAXE ","M7N5TAYE ","M7N5TAZE ","M7N5TDXSS","M7N5TDYSS","M7N5TDZSS","M7N6FKXE ", & + "M7N6FKYE ","M7N6FKZE ","M7N6FMXE ","M7N6FMYE ","M7N6FMZE ","M7N6MKXE ","M7N6MKYE ", & + "M7N6MKZE ","M7N6MMXE ","M7N6MMYE ","M7N6MMZE ","M7N6RAXE ","M7N6RAYE ","M7N6RAZE ", & + "M7N6RDXE ","M7N6RDYE ","M7N6RDZE ","M7N6TAXE ","M7N6TAYE ","M7N6TAZE ","M7N6TDXSS", & + "M7N6TDYSS","M7N6TDZSS","M7N7FKXE ","M7N7FKYE ","M7N7FKZE ","M7N7FMXE ","M7N7FMYE ", & + "M7N7FMZE ","M7N7MKXE ","M7N7MKYE ","M7N7MKZE ","M7N7MMXE ","M7N7MMYE ","M7N7MMZE ", & + "M7N7RAXE ","M7N7RAYE ","M7N7RAZE ","M7N7RDXE ","M7N7RDYE ","M7N7RDZE ","M7N7TAXE ", & + "M7N7TAYE ","M7N7TAZE ","M7N7TDXSS","M7N7TDYSS","M7N7TDZSS","M7N8FKXE ","M7N8FKYE ", & + "M7N8FKZE ","M7N8FMXE ","M7N8FMYE ","M7N8FMZE ","M7N8MKXE ","M7N8MKYE ","M7N8MKZE ", & + "M7N8MMXE ","M7N8MMYE ","M7N8MMZE ","M7N8RAXE ","M7N8RAYE ","M7N8RAZE ","M7N8RDXE ", & + "M7N8RDYE ","M7N8RDZE ","M7N8TAXE ","M7N8TAYE ","M7N8TAZE ","M7N8TDXSS","M7N8TDYSS", & + "M7N8TDZSS","M7N9FKXE ","M7N9FKYE ","M7N9FKZE ","M7N9FMXE ","M7N9FMYE ","M7N9FMZE ", & + "M7N9MKXE ","M7N9MKYE ","M7N9MKZE ","M7N9MMXE ","M7N9MMYE ","M7N9MMZE ","M7N9RAXE ", & + "M7N9RAYE ","M7N9RAZE ","M7N9RDXE ","M7N9RDYE ","M7N9RDZE ","M7N9TAXE ","M7N9TAYE ", & + "M7N9TAZE ","M7N9TDXSS","M7N9TDYSS","M7N9TDZSS","M8N1FKXE ","M8N1FKYE ","M8N1FKZE ", & + "M8N1FMXE ","M8N1FMYE ","M8N1FMZE ","M8N1MKXE ","M8N1MKYE ","M8N1MKZE ","M8N1MMXE ", & + "M8N1MMYE ","M8N1MMZE ","M8N1RAXE ","M8N1RAYE ","M8N1RAZE ","M8N1RDXE ","M8N1RDYE ", & + "M8N1RDZE ","M8N1TAXE ","M8N1TAYE ","M8N1TAZE ","M8N1TDXSS","M8N1TDYSS","M8N1TDZSS", & + "M8N2FKXE ","M8N2FKYE ","M8N2FKZE ","M8N2FMXE ","M8N2FMYE ","M8N2FMZE ","M8N2MKXE ", & + "M8N2MKYE ","M8N2MKZE ","M8N2MMXE ","M8N2MMYE ","M8N2MMZE ","M8N2RAXE ","M8N2RAYE ", & + "M8N2RAZE ","M8N2RDXE ","M8N2RDYE ","M8N2RDZE ","M8N2TAXE ","M8N2TAYE ","M8N2TAZE ", & + "M8N2TDXSS","M8N2TDYSS","M8N2TDZSS","M8N3FKXE ","M8N3FKYE ","M8N3FKZE ","M8N3FMXE ", & + "M8N3FMYE ","M8N3FMZE ","M8N3MKXE ","M8N3MKYE ","M8N3MKZE ","M8N3MMXE ","M8N3MMYE ", & + "M8N3MMZE ","M8N3RAXE ","M8N3RAYE ","M8N3RAZE ","M8N3RDXE ","M8N3RDYE ","M8N3RDZE ", & + "M8N3TAXE ","M8N3TAYE ","M8N3TAZE ","M8N3TDXSS","M8N3TDYSS","M8N3TDZSS","M8N4FKXE ", & + "M8N4FKYE ","M8N4FKZE ","M8N4FMXE ","M8N4FMYE ","M8N4FMZE ","M8N4MKXE ","M8N4MKYE ", & + "M8N4MKZE ","M8N4MMXE ","M8N4MMYE ","M8N4MMZE ","M8N4RAXE ","M8N4RAYE ","M8N4RAZE ", & + "M8N4RDXE ","M8N4RDYE ","M8N4RDZE ","M8N4TAXE ","M8N4TAYE ","M8N4TAZE ","M8N4TDXSS", & + "M8N4TDYSS","M8N4TDZSS","M8N5FKXE ","M8N5FKYE ","M8N5FKZE ","M8N5FMXE ","M8N5FMYE ", & + "M8N5FMZE ","M8N5MKXE ","M8N5MKYE ","M8N5MKZE ","M8N5MMXE ","M8N5MMYE ","M8N5MMZE ", & + "M8N5RAXE ","M8N5RAYE ","M8N5RAZE ","M8N5RDXE ","M8N5RDYE ","M8N5RDZE ","M8N5TAXE ", & + "M8N5TAYE ","M8N5TAZE ","M8N5TDXSS","M8N5TDYSS","M8N5TDZSS","M8N6FKXE ","M8N6FKYE ", & + "M8N6FKZE ","M8N6FMXE ","M8N6FMYE ","M8N6FMZE ","M8N6MKXE ","M8N6MKYE ","M8N6MKZE ", & + "M8N6MMXE ","M8N6MMYE ","M8N6MMZE ","M8N6RAXE ","M8N6RAYE ","M8N6RAZE ","M8N6RDXE ", & + "M8N6RDYE ","M8N6RDZE ","M8N6TAXE ","M8N6TAYE ","M8N6TAZE ","M8N6TDXSS","M8N6TDYSS", & + "M8N6TDZSS","M8N7FKXE ","M8N7FKYE ","M8N7FKZE ","M8N7FMXE ","M8N7FMYE ","M8N7FMZE ", & + "M8N7MKXE ","M8N7MKYE ","M8N7MKZE ","M8N7MMXE ","M8N7MMYE ","M8N7MMZE ","M8N7RAXE ", & + "M8N7RAYE ","M8N7RAZE ","M8N7RDXE ","M8N7RDYE ","M8N7RDZE ","M8N7TAXE ","M8N7TAYE ", & + "M8N7TAZE ","M8N7TDXSS","M8N7TDYSS","M8N7TDZSS","M8N8FKXE ","M8N8FKYE ","M8N8FKZE ", & + "M8N8FMXE ","M8N8FMYE ","M8N8FMZE ","M8N8MKXE ","M8N8MKYE ","M8N8MKZE ","M8N8MMXE ", & + "M8N8MMYE ","M8N8MMZE ","M8N8RAXE ","M8N8RAYE ","M8N8RAZE ","M8N8RDXE ","M8N8RDYE ", & + "M8N8RDZE ","M8N8TAXE ","M8N8TAYE ","M8N8TAZE ","M8N8TDXSS","M8N8TDYSS","M8N8TDZSS", & + "M8N9FKXE ","M8N9FKYE ","M8N9FKZE ","M8N9FMXE ","M8N9FMYE ","M8N9FMZE ","M8N9MKXE ", & + "M8N9MKYE ","M8N9MKZE ","M8N9MMXE ","M8N9MMYE ","M8N9MMZE ","M8N9RAXE ","M8N9RAYE ", & + "M8N9RAZE ","M8N9RDXE ","M8N9RDYE ","M8N9RDZE ","M8N9TAXE ","M8N9TAYE ","M8N9TAZE ", & + "M8N9TDXSS","M8N9TDYSS","M8N9TDZSS","M9N1FKXE ","M9N1FKYE ","M9N1FKZE ","M9N1FMXE ", & + "M9N1FMYE ","M9N1FMZE ","M9N1MKXE ","M9N1MKYE ","M9N1MKZE ","M9N1MMXE ","M9N1MMYE ", & + "M9N1MMZE ","M9N1RAXE ","M9N1RAYE ","M9N1RAZE ","M9N1RDXE ","M9N1RDYE ","M9N1RDZE ", & + "M9N1TAXE ","M9N1TAYE ","M9N1TAZE ","M9N1TDXSS","M9N1TDYSS","M9N1TDZSS","M9N2FKXE ", & + "M9N2FKYE ","M9N2FKZE ","M9N2FMXE ","M9N2FMYE ","M9N2FMZE ","M9N2MKXE ","M9N2MKYE ", & + "M9N2MKZE ","M9N2MMXE ","M9N2MMYE ","M9N2MMZE ","M9N2RAXE ","M9N2RAYE ","M9N2RAZE ", & + "M9N2RDXE ","M9N2RDYE ","M9N2RDZE ","M9N2TAXE ","M9N2TAYE ","M9N2TAZE ","M9N2TDXSS", & + "M9N2TDYSS","M9N2TDZSS","M9N3FKXE ","M9N3FKYE ","M9N3FKZE ","M9N3FMXE ","M9N3FMYE ", & + "M9N3FMZE ","M9N3MKXE ","M9N3MKYE ","M9N3MKZE ","M9N3MMXE ","M9N3MMYE ","M9N3MMZE ", & + "M9N3RAXE ","M9N3RAYE ","M9N3RAZE ","M9N3RDXE ","M9N3RDYE ","M9N3RDZE ","M9N3TAXE ", & + "M9N3TAYE ","M9N3TAZE ","M9N3TDXSS","M9N3TDYSS","M9N3TDZSS","M9N4FKXE ","M9N4FKYE ", & + "M9N4FKZE ","M9N4FMXE ","M9N4FMYE ","M9N4FMZE ","M9N4MKXE ","M9N4MKYE ","M9N4MKZE ", & + "M9N4MMXE ","M9N4MMYE ","M9N4MMZE ","M9N4RAXE ","M9N4RAYE ","M9N4RAZE ","M9N4RDXE ", & + "M9N4RDYE ","M9N4RDZE ","M9N4TAXE ","M9N4TAYE ","M9N4TAZE ","M9N4TDXSS","M9N4TDYSS", & + "M9N4TDZSS","M9N5FKXE ","M9N5FKYE ","M9N5FKZE ","M9N5FMXE ","M9N5FMYE ","M9N5FMZE ", & + "M9N5MKXE ","M9N5MKYE ","M9N5MKZE ","M9N5MMXE ","M9N5MMYE ","M9N5MMZE ","M9N5RAXE ", & + "M9N5RAYE ","M9N5RAZE ","M9N5RDXE ","M9N5RDYE ","M9N5RDZE ","M9N5TAXE ","M9N5TAYE ", & + "M9N5TAZE ","M9N5TDXSS","M9N5TDYSS","M9N5TDZSS","M9N6FKXE ","M9N6FKYE ","M9N6FKZE ", & + "M9N6FMXE ","M9N6FMYE ","M9N6FMZE ","M9N6MKXE ","M9N6MKYE ","M9N6MKZE ","M9N6MMXE ", & + "M9N6MMYE ","M9N6MMZE ","M9N6RAXE ","M9N6RAYE ","M9N6RAZE ","M9N6RDXE ","M9N6RDYE ", & + "M9N6RDZE ","M9N6TAXE ","M9N6TAYE ","M9N6TAZE ","M9N6TDXSS","M9N6TDYSS","M9N6TDZSS", & + "M9N7FKXE ","M9N7FKYE ","M9N7FKZE ","M9N7FMXE ","M9N7FMYE ","M9N7FMZE ","M9N7MKXE ", & + "M9N7MKYE ","M9N7MKZE ","M9N7MMXE ","M9N7MMYE ","M9N7MMZE ","M9N7RAXE ","M9N7RAYE ", & + "M9N7RAZE ","M9N7RDXE ","M9N7RDYE ","M9N7RDZE ","M9N7TAXE ","M9N7TAYE ","M9N7TAZE ", & + "M9N7TDXSS","M9N7TDYSS","M9N7TDZSS","M9N8FKXE ","M9N8FKYE ","M9N8FKZE ","M9N8FMXE ", & + "M9N8FMYE ","M9N8FMZE ","M9N8MKXE ","M9N8MKYE ","M9N8MKZE ","M9N8MMXE ","M9N8MMYE ", & + "M9N8MMZE ","M9N8RAXE ","M9N8RAYE ","M9N8RAZE ","M9N8RDXE ","M9N8RDYE ","M9N8RDZE ", & + "M9N8TAXE ","M9N8TAYE ","M9N8TAZE ","M9N8TDXSS","M9N8TDYSS","M9N8TDZSS","M9N9FKXE ", & + "M9N9FKYE ","M9N9FKZE ","M9N9FMXE ","M9N9FMYE ","M9N9FMZE ","M9N9MKXE ","M9N9MKYE ", & + "M9N9MKZE ","M9N9MMXE ","M9N9MMYE ","M9N9MMZE ","M9N9RAXE ","M9N9RAYE ","M9N9RAZE ", & + "M9N9RDXE ","M9N9RDYE ","M9N9RDZE ","M9N9TAXE ","M9N9TAYE ","M9N9TAZE ","M9N9TDXSS", & + "M9N9TDYSS","M9N9TDZSS","REACTFXSS","REACTFYSS","REACTFZSS","REACTMXSS","REACTMYSS", & + "REACTMZSS","SSQM01 ","SSQM02 ","SSQM03 ","SSQM04 ","SSQM05 ","SSQM06 ", & + "SSQM07 ","SSQM08 ","SSQM09 ","SSQM10 ","SSQM11 ","SSQM12 ","SSQM13 ", & + "SSQM14 ","SSQM15 ","SSQM16 ","SSQM17 ","SSQM18 ","SSQM19 ","SSQM20 ", & + "SSQM21 ","SSQM22 ","SSQM23 ","SSQM24 ","SSQM25 ","SSQM26 ","SSQM27 ", & + "SSQM28 ","SSQM29 ","SSQM30 ","SSQM31 ","SSQM32 ","SSQM33 ","SSQM34 ", & + "SSQM35 ","SSQM36 ","SSQM37 ","SSQM38 ","SSQM39 ","SSQM40 ","SSQM41 ", & + "SSQM42 ","SSQM43 ","SSQM44 ","SSQM45 ","SSQM46 ","SSQM47 ","SSQM48 ", & + "SSQM49 ","SSQM50 ","SSQM51 ","SSQM52 ","SSQM53 ","SSQM54 ","SSQM55 ", & + "SSQM56 ","SSQM57 ","SSQM58 ","SSQM59 ","SSQM60 ","SSQM61 ","SSQM62 ", & + "SSQM63 ","SSQM64 ","SSQM65 ","SSQM66 ","SSQM67 ","SSQM68 ","SSQM69 ", & + "SSQM70 ","SSQM71 ","SSQM72 ","SSQM73 ","SSQM74 ","SSQM75 ","SSQM76 ", & + "SSQM77 ","SSQM78 ","SSQM79 ","SSQM80 ","SSQM81 ","SSQM82 ","SSQM83 ", & + "SSQM84 ","SSQM85 ","SSQM86 ","SSQM87 ","SSQM88 ","SSQM89 ","SSQM90 ", & + "SSQM91 ","SSQM92 ","SSQM93 ","SSQM94 ","SSQM95 ","SSQM96 ","SSQM97 ", & + "SSQM98 ","SSQM99 ","SSQMD01 ","SSQMD02 ","SSQMD03 ","SSQMD04 ","SSQMD05 ", & + "SSQMD06 ","SSQMD07 ","SSQMD08 ","SSQMD09 ","SSQMD10 ","SSQMD11 ","SSQMD12 ", & + "SSQMD13 ","SSQMD14 ","SSQMD15 ","SSQMD16 ","SSQMD17 ","SSQMD18 ","SSQMD19 ", & + "SSQMD20 ","SSQMD21 ","SSQMD22 ","SSQMD23 ","SSQMD24 ","SSQMD25 ","SSQMD26 ", & + "SSQMD27 ","SSQMD28 ","SSQMD29 ","SSQMD30 ","SSQMD31 ","SSQMD32 ","SSQMD33 ", & + "SSQMD34 ","SSQMD35 ","SSQMD36 ","SSQMD37 ","SSQMD38 ","SSQMD39 ","SSQMD40 ", & + "SSQMD41 ","SSQMD42 ","SSQMD43 ","SSQMD44 ","SSQMD45 ","SSQMD46 ","SSQMD47 ", & + "SSQMD48 ","SSQMD49 ","SSQMD50 ","SSQMD51 ","SSQMD52 ","SSQMD53 ","SSQMD54 ", & + "SSQMD55 ","SSQMD56 ","SSQMD57 ","SSQMD58 ","SSQMD59 ","SSQMD60 ","SSQMD61 ", & + "SSQMD62 ","SSQMD63 ","SSQMD64 ","SSQMD65 ","SSQMD66 ","SSQMD67 ","SSQMD68 ", & + "SSQMD69 ","SSQMD70 ","SSQMD71 ","SSQMD72 ","SSQMD73 ","SSQMD74 ","SSQMD75 ", & + "SSQMD76 ","SSQMD77 ","SSQMD78 ","SSQMD79 ","SSQMD80 ","SSQMD81 ","SSQMD82 ", & + "SSQMD83 ","SSQMD84 ","SSQMD85 ","SSQMD86 ","SSQMD87 ","SSQMD88 ","SSQMD89 ", & + "SSQMD90 ","SSQMD91 ","SSQMD92 ","SSQMD93 ","SSQMD94 ","SSQMD95 ","SSQMD96 ", & + "SSQMD97 ","SSQMD98 ","SSQMD99 ","SSQMDD01 ","SSQMDD02 ","SSQMDD03 ","SSQMDD04 ", & + "SSQMDD05 ","SSQMDD06 ","SSQMDD07 ","SSQMDD08 ","SSQMDD09 ","SSQMDD10 ","SSQMDD11 ", & + "SSQMDD12 ","SSQMDD13 ","SSQMDD14 ","SSQMDD15 ","SSQMDD16 ","SSQMDD17 ","SSQMDD18 ", & + "SSQMDD19 ","SSQMDD20 ","SSQMDD21 ","SSQMDD22 ","SSQMDD23 ","SSQMDD24 ","SSQMDD25 ", & + "SSQMDD26 ","SSQMDD27 ","SSQMDD28 ","SSQMDD29 ","SSQMDD30 ","SSQMDD31 ","SSQMDD32 ", & + "SSQMDD33 ","SSQMDD34 ","SSQMDD35 ","SSQMDD36 ","SSQMDD37 ","SSQMDD38 ","SSQMDD39 ", & + "SSQMDD40 ","SSQMDD41 ","SSQMDD42 ","SSQMDD43 ","SSQMDD44 ","SSQMDD45 ","SSQMDD46 ", & + "SSQMDD47 ","SSQMDD48 ","SSQMDD49 ","SSQMDD50 ","SSQMDD51 ","SSQMDD52 ","SSQMDD53 ", & + "SSQMDD54 ","SSQMDD55 ","SSQMDD56 ","SSQMDD57 ","SSQMDD58 ","SSQMDD59 ","SSQMDD60 ", & + "SSQMDD61 ","SSQMDD62 ","SSQMDD63 ","SSQMDD64 ","SSQMDD65 ","SSQMDD66 ","SSQMDD67 ", & + "SSQMDD68 ","SSQMDD69 ","SSQMDD70 ","SSQMDD71 ","SSQMDD72 ","SSQMDD73 ","SSQMDD74 ", & + "SSQMDD75 ","SSQMDD76 ","SSQMDD77 ","SSQMDD78 ","SSQMDD79 ","SSQMDD80 ","SSQMDD81 ", & + "SSQMDD82 ","SSQMDD83 ","SSQMDD84 ","SSQMDD85 ","SSQMDD86 ","SSQMDD87 ","SSQMDD88 ", & + "SSQMDD89 ","SSQMDD90 ","SSQMDD91 ","SSQMDD92 ","SSQMDD93 ","SSQMDD94 ","SSQMDD95 ", & + "SSQMDD96 ","SSQMDD97 ","SSQMDD98 ","SSQMDD99 "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(2265) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + IntfFXss , IntfFYss , IntfFZss , IntfMXss , IntfMYss , IntfMZss , IntfRAXss , & + IntfRAYss , IntfRAZss , IntfRDXss , IntfRDYss , IntfRDZss , IntfTAXss , IntfTAYss , & + IntfTAZss , IntfTDXss , IntfTDYss , IntfTDZss , M1N1FKxe , M1N1FKye , M1N1FKze , & + M1N1FMxe , M1N1FMye , M1N1FMze , M1N1MKxe , M1N1MKye , M1N1MKze , M1N1MMxe , & + M1N1MMye , M1N1MMze , M1N1RAxe , M1N1RAye , M1N1RAze , M1N1RDxe , M1N1RDye , & + M1N1RDze , M1N1TAxe , M1N1TAye , M1N1TAze , M1N1TDxss , M1N1TDyss , M1N1TDzss , & + M1N2FKxe , M1N2FKye , M1N2FKze , M1N2FMxe , M1N2FMye , M1N2FMze , M1N2MKxe , & + M1N2MKye , M1N2MKze , M1N2MMxe , M1N2MMye , M1N2MMze , M1N2RAxe , M1N2RAye , & + M1N2RAze , M1N2RDxe , M1N2RDye , M1N2RDze , M1N2TAxe , M1N2TAye , M1N2TAze , & + M1N2TDxss , M1N2TDyss , M1N2TDzss , M1N3FKxe , M1N3FKye , M1N3FKze , M1N3FMxe , & + M1N3FMye , M1N3FMze , M1N3MKxe , M1N3MKye , M1N3MKze , M1N3MMxe , M1N3MMye , & + M1N3MMze , M1N3RAxe , M1N3RAye , M1N3RAze , M1N3RDxe , M1N3RDye , M1N3RDze , & + M1N3TAxe , M1N3TAye , M1N3TAze , M1N3TDxss , M1N3TDyss , M1N3TDzss , M1N4FKxe , & + M1N4FKye , M1N4FKze , M1N4FMxe , M1N4FMye , M1N4FMze , M1N4MKxe , M1N4MKye , & + M1N4MKze , M1N4MMxe , M1N4MMye , M1N4MMze , M1N4RAxe , M1N4RAye , M1N4RAze , & + M1N4RDxe , M1N4RDye , M1N4RDze , M1N4TAxe , M1N4TAye , M1N4TAze , M1N4TDxss , & + M1N4TDyss , M1N4TDzss , M1N5FKxe , M1N5FKye , M1N5FKze , M1N5FMxe , M1N5FMye , & + M1N5FMze , M1N5MKxe , M1N5MKye , M1N5MKze , M1N5MMxe , M1N5MMye , M1N5MMze , & + M1N5RAxe , M1N5RAye , M1N5RAze , M1N5RDxe , M1N5RDye , M1N5RDze , M1N5TAxe , & + M1N5TAye , M1N5TAze , M1N5TDxss , M1N5TDyss , M1N5TDzss , M1N6FKxe , M1N6FKye , & + M1N6FKze , M1N6FMxe , M1N6FMye , M1N6FMze , M1N6MKxe , M1N6MKye , M1N6MKze , & + M1N6MMxe , M1N6MMye , M1N6MMze , M1N6RAxe , M1N6RAye , M1N6RAze , M1N6RDxe , & + M1N6RDye , M1N6RDze , M1N6TAxe , M1N6TAye , M1N6TAze , M1N6TDxss , M1N6TDyss , & + M1N6TDzss , M1N7FKxe , M1N7FKye , M1N7FKze , M1N7FMxe , M1N7FMye , M1N7FMze , & + M1N7MKxe , M1N7MKye , M1N7MKze , M1N7MMxe , M1N7MMye , M1N7MMze , M1N7RAxe , & + M1N7RAye , M1N7RAze , M1N7RDxe , M1N7RDye , M1N7RDze , M1N7TAxe , M1N7TAye , & + M1N7TAze , M1N7TDxss , M1N7TDyss , M1N7TDzss , M1N8FKxe , M1N8FKye , M1N8FKze , & + M1N8FMxe , M1N8FMye , M1N8FMze , M1N8MKxe , M1N8MKye , M1N8MKze , M1N8MMxe , & + M1N8MMye , M1N8MMze , M1N8RAxe , M1N8RAye , M1N8RAze , M1N8RDxe , M1N8RDye , & + M1N8RDze , M1N8TAxe , M1N8TAye , M1N8TAze , M1N8TDxss , M1N8TDyss , M1N8TDzss , & + M1N9FKxe , M1N9FKye , M1N9FKze , M1N9FMxe , M1N9FMye , M1N9FMze , M1N9MKxe , & + M1N9MKye , M1N9MKze , M1N9MMxe , M1N9MMye , M1N9MMze , M1N9RAxe , M1N9RAye , & + M1N9RAze , M1N9RDxe , M1N9RDye , M1N9RDze , M1N9TAxe , M1N9TAye , M1N9TAze , & + M1N9TDxss , M1N9TDyss , M1N9TDzss , M2N1FKxe , M2N1FKye , M2N1FKze , M2N1FMxe , & + M2N1FMye , M2N1FMze , M2N1MKxe , M2N1MKye , M2N1MKze , M2N1MMxe , M2N1MMye , & + M2N1MMze , M2N1RAxe , M2N1RAye , M2N1RAze , M2N1RDxe , M2N1RDye , M2N1RDze , & + M2N1TAxe , M2N1TAye , M2N1TAze , M2N1TDxss , M2N1TDyss , M2N1TDzss , M2N2FKxe , & + M2N2FKye , M2N2FKze , M2N2FMxe , M2N2FMye , M2N2FMze , M2N2MKxe , M2N2MKye , & + M2N2MKze , M2N2MMxe , M2N2MMye , M2N2MMze , M2N2RAxe , M2N2RAye , M2N2RAze , & + M2N2RDxe , M2N2RDye , M2N2RDze , M2N2TAxe , M2N2TAye , M2N2TAze , M2N2TDxss , & + M2N2TDyss , M2N2TDzss , M2N3FKxe , M2N3FKye , M2N3FKze , M2N3FMxe , M2N3FMye , & + M2N3FMze , M2N3MKxe , M2N3MKye , M2N3MKze , M2N3MMxe , M2N3MMye , M2N3MMze , & + M2N3RAxe , M2N3RAye , M2N3RAze , M2N3RDxe , M2N3RDye , M2N3RDze , M2N3TAxe , & + M2N3TAye , M2N3TAze , M2N3TDxss , M2N3TDyss , M2N3TDzss , M2N4FKxe , M2N4FKye , & + M2N4FKze , M2N4FMxe , M2N4FMye , M2N4FMze , M2N4MKxe , M2N4MKye , M2N4MKze , & + M2N4MMxe , M2N4MMye , M2N4MMze , M2N4RAxe , M2N4RAye , M2N4RAze , M2N4RDxe , & + M2N4RDye , M2N4RDze , M2N4TAxe , M2N4TAye , M2N4TAze , M2N4TDxss , M2N4TDyss , & + M2N4TDzss , M2N5FKxe , M2N5FKye , M2N5FKze , M2N5FMxe , M2N5FMye , M2N5FMze , & + M2N5MKxe , M2N5MKye , M2N5MKze , M2N5MMxe , M2N5MMye , M2N5MMze , M2N5RAxe , & + M2N5RAye , M2N5RAze , M2N5RDxe , M2N5RDye , M2N5RDze , M2N5TAxe , M2N5TAye , & + M2N5TAze , M2N5TDxss , M2N5TDyss , M2N5TDzss , M2N6FKxe , M2N6FKye , M2N6FKze , & + M2N6FMxe , M2N6FMye , M2N6FMze , M2N6MKxe , M2N6MKye , M2N6MKze , M2N6MMxe , & + M2N6MMye , M2N6MMze , M2N6RAxe , M2N6RAye , M2N6RAze , M2N6RDxe , M2N6RDye , & + M2N6RDze , M2N6TAxe , M2N6TAye , M2N6TAze , M2N6TDxss , M2N6TDyss , M2N6TDzss , & + M2N7FKxe , M2N7FKye , M2N7FKze , M2N7FMxe , M2N7FMye , M2N7FMze , M2N7MKxe , & + M2N7MKye , M2N7MKze , M2N7MMxe , M2N7MMye , M2N7MMze , M2N7RAxe , M2N7RAye , & + M2N7RAze , M2N7RDxe , M2N7RDye , M2N7RDze , M2N7TAxe , M2N7TAye , M2N7TAze , & + M2N7TDxss , M2N7TDyss , M2N7TDzss , M2N8FKxe , M2N8FKye , M2N8FKze , M2N8FMxe , & + M2N8FMye , M2N8FMze , M2N8MKxe , M2N8MKye , M2N8MKze , M2N8MMxe , M2N8MMye , & + M2N8MMze , M2N8RAxe , M2N8RAye , M2N8RAze , M2N8RDxe , M2N8RDye , M2N8RDze , & + M2N8TAxe , M2N8TAye , M2N8TAze , M2N8TDxss , M2N8TDyss , M2N8TDzss , M2N9FKxe , & + M2N9FKye , M2N9FKze , M2N9FMxe , M2N9FMye , M2N9FMze , M2N9MKxe , M2N9MKye , & + M2N9MKze , M2N9MMxe , M2N9MMye , M2N9MMze , M2N9RAxe , M2N9RAye , M2N9RAze , & + M2N9RDxe , M2N9RDye , M2N9RDze , M2N9TAxe , M2N9TAye , M2N9TAze , M2N9TDxss , & + M2N9TDyss , M2N9TDzss , M3N1FKxe , M3N1FKye , M3N1FKze , M3N1FMxe , M3N1FMye , & + M3N1FMze , M3N1MKxe , M3N1MKye , M3N1MKze , M3N1MMxe , M3N1MMye , M3N1MMze , & + M3N1RAxe , M3N1RAye , M3N1RAze , M3N1RDxe , M3N1RDye , M3N1RDze , M3N1TAxe , & + M3N1TAye , M3N1TAze , M3N1TDxss , M3N1TDyss , M3N1TDzss , M3N2FKxe , M3N2FKye , & + M3N2FKze , M3N2FMxe , M3N2FMye , M3N2FMze , M3N2MKxe , M3N2MKye , M3N2MKze , & + M3N2MMxe , M3N2MMye , M3N2MMze , M3N2RAxe , M3N2RAye , M3N2RAze , M3N2RDxe , & + M3N2RDye , M3N2RDze , M3N2TAxe , M3N2TAye , M3N2TAze , M3N2TDxss , M3N2TDyss , & + M3N2TDzss , M3N3FKxe , M3N3FKye , M3N3FKze , M3N3FMxe , M3N3FMye , M3N3FMze , & + M3N3MKxe , M3N3MKye , M3N3MKze , M3N3MMxe , M3N3MMye , M3N3MMze , M3N3RAxe , & + M3N3RAye , M3N3RAze , M3N3RDxe , M3N3RDye , M3N3RDze , M3N3TAxe , M3N3TAye , & + M3N3TAze , M3N3TDxss , M3N3TDyss , M3N3TDzss , M3N4FKxe , M3N4FKye , M3N4FKze , & + M3N4FMxe , M3N4FMye , M3N4FMze , M3N4MKxe , M3N4MKye , M3N4MKze , M3N4MMxe , & + M3N4MMye , M3N4MMze , M3N4RAxe , M3N4RAye , M3N4RAze , M3N4RDxe , M3N4RDye , & + M3N4RDze , M3N4TAxe , M3N4TAye , M3N4TAze , M3N4TDxss , M3N4TDyss , M3N4TDzss , & + M3N5FKxe , M3N5FKye , M3N5FKze , M3N5FMxe , M3N5FMye , M3N5FMze , M3N5MKxe , & + M3N5MKye , M3N5MKze , M3N5MMxe , M3N5MMye , M3N5MMze , M3N5RAxe , M3N5RAye , & + M3N5RAze , M3N5RDxe , M3N5RDye , M3N5RDze , M3N5TAxe , M3N5TAye , M3N5TAze , & + M3N5TDxss , M3N5TDyss , M3N5TDzss , M3N6FKxe , M3N6FKye , M3N6FKze , M3N6FMxe , & + M3N6FMye , M3N6FMze , M3N6MKxe , M3N6MKye , M3N6MKze , M3N6MMxe , M3N6MMye , & + M3N6MMze , M3N6RAxe , M3N6RAye , M3N6RAze , M3N6RDxe , M3N6RDye , M3N6RDze , & + M3N6TAxe , M3N6TAye , M3N6TAze , M3N6TDxss , M3N6TDyss , M3N6TDzss , M3N7FKxe , & + M3N7FKye , M3N7FKze , M3N7FMxe , M3N7FMye , M3N7FMze , M3N7MKxe , M3N7MKye , & + M3N7MKze , M3N7MMxe , M3N7MMye , M3N7MMze , M3N7RAxe , M3N7RAye , M3N7RAze , & + M3N7RDxe , M3N7RDye , M3N7RDze , M3N7TAxe , M3N7TAye , M3N7TAze , M3N7TDxss , & + M3N7TDyss , M3N7TDzss , M3N8FKxe , M3N8FKye , M3N8FKze , M3N8FMxe , M3N8FMye , & + M3N8FMze , M3N8MKxe , M3N8MKye , M3N8MKze , M3N8MMxe , M3N8MMye , M3N8MMze , & + M3N8RAxe , M3N8RAye , M3N8RAze , M3N8RDxe , M3N8RDye , M3N8RDze , M3N8TAxe , & + M3N8TAye , M3N8TAze , M3N8TDxss , M3N8TDyss , M3N8TDzss , M3N9FKxe , M3N9FKye , & + M3N9FKze , M3N9FMxe , M3N9FMye , M3N9FMze , M3N9MKxe , M3N9MKye , M3N9MKze , & + M3N9MMxe , M3N9MMye , M3N9MMze , M3N9RAxe , M3N9RAye , M3N9RAze , M3N9RDxe , & + M3N9RDye , M3N9RDze , M3N9TAxe , M3N9TAye , M3N9TAze , M3N9TDxss , M3N9TDyss , & + M3N9TDzss , M4N1FKxe , M4N1FKye , M4N1FKze , M4N1FMxe , M4N1FMye , M4N1FMze , & + M4N1MKxe , M4N1MKye , M4N1MKze , M4N1MMxe , M4N1MMye , M4N1MMze , M4N1RAxe , & + M4N1RAye , M4N1RAze , M4N1RDxe , M4N1RDye , M4N1RDze , M4N1TAxe , M4N1TAye , & + M4N1TAze , M4N1TDxss , M4N1TDyss , M4N1TDzss , M4N2FKxe , M4N2FKye , M4N2FKze , & + M4N2FMxe , M4N2FMye , M4N2FMze , M4N2MKxe , M4N2MKye , M4N2MKze , M4N2MMxe , & + M4N2MMye , M4N2MMze , M4N2RAxe , M4N2RAye , M4N2RAze , M4N2RDxe , M4N2RDye , & + M4N2RDze , M4N2TAxe , M4N2TAye , M4N2TAze , M4N2TDxss , M4N2TDyss , M4N2TDzss , & + M4N3FKxe , M4N3FKye , M4N3FKze , M4N3FMxe , M4N3FMye , M4N3FMze , M4N3MKxe , & + M4N3MKye , M4N3MKze , M4N3MMxe , M4N3MMye , M4N3MMze , M4N3RAxe , M4N3RAye , & + M4N3RAze , M4N3RDxe , M4N3RDye , M4N3RDze , M4N3TAxe , M4N3TAye , M4N3TAze , & + M4N3TDxss , M4N3TDyss , M4N3TDzss , M4N4FKxe , M4N4FKye , M4N4FKze , M4N4FMxe , & + M4N4FMye , M4N4FMze , M4N4MKxe , M4N4MKye , M4N4MKze , M4N4MMxe , M4N4MMye , & + M4N4MMze , M4N4RAxe , M4N4RAye , M4N4RAze , M4N4RDxe , M4N4RDye , M4N4RDze , & + M4N4TAxe , M4N4TAye , M4N4TAze , M4N4TDxss , M4N4TDyss , M4N4TDzss , M4N5FKxe , & + M4N5FKye , M4N5FKze , M4N5FMxe , M4N5FMye , M4N5FMze , M4N5MKxe , M4N5MKye , & + M4N5MKze , M4N5MMxe , M4N5MMye , M4N5MMze , M4N5RAxe , M4N5RAye , M4N5RAze , & + M4N5RDxe , M4N5RDye , M4N5RDze , M4N5TAxe , M4N5TAye , M4N5TAze , M4N5TDxss , & + M4N5TDyss , M4N5TDzss , M4N6FKxe , M4N6FKye , M4N6FKze , M4N6FMxe , M4N6FMye , & + M4N6FMze , M4N6MKxe , M4N6MKye , M4N6MKze , M4N6MMxe , M4N6MMye , M4N6MMze , & + M4N6RAxe , M4N6RAye , M4N6RAze , M4N6RDxe , M4N6RDye , M4N6RDze , M4N6TAxe , & + M4N6TAye , M4N6TAze , M4N6TDxss , M4N6TDyss , M4N6TDzss , M4N7FKxe , M4N7FKye , & + M4N7FKze , M4N7FMxe , M4N7FMye , M4N7FMze , M4N7MKxe , M4N7MKye , M4N7MKze , & + M4N7MMxe , M4N7MMye , M4N7MMze , M4N7RAxe , M4N7RAye , M4N7RAze , M4N7RDxe , & + M4N7RDye , M4N7RDze , M4N7TAxe , M4N7TAye , M4N7TAze , M4N7TDxss , M4N7TDyss , & + M4N7TDzss , M4N8FKxe , M4N8FKye , M4N8FKze , M4N8FMxe , M4N8FMye , M4N8FMze , & + M4N8MKxe , M4N8MKye , M4N8MKze , M4N8MMxe , M4N8MMye , M4N8MMze , M4N8RAxe , & + M4N8RAye , M4N8RAze , M4N8RDxe , M4N8RDye , M4N8RDze , M4N8TAxe , M4N8TAye , & + M4N8TAze , M4N8TDxss , M4N8TDyss , M4N8TDzss , M4N9FKxe , M4N9FKye , M4N9FKze , & + M4N9FMxe , M4N9FMye , M4N9FMze , M4N9MKxe , M4N9MKye , M4N9MKze , M4N9MMxe , & + M4N9MMye , M4N9MMze , M4N9RAxe , M4N9RAye , M4N9RAze , M4N9RDxe , M4N9RDye , & + M4N9RDze , M4N9TAxe , M4N9TAye , M4N9TAze , M4N9TDxss , M4N9TDyss , M4N9TDzss , & + M5N1FKxe , M5N1FKye , M5N1FKze , M5N1FMxe , M5N1FMye , M5N1FMze , M5N1MKxe , & + M5N1MKye , M5N1MKze , M5N1MMxe , M5N1MMye , M5N1MMze , M5N1RAxe , M5N1RAye , & + M5N1RAze , M5N1RDxe , M5N1RDye , M5N1RDze , M5N1TAxe , M5N1TAye , M5N1TAze , & + M5N1TDxss , M5N1TDyss , M5N1TDzss , M5N2FKxe , M5N2FKye , M5N2FKze , M5N2FMxe , & + M5N2FMye , M5N2FMze , M5N2MKxe , M5N2MKye , M5N2MKze , M5N2MMxe , M5N2MMye , & + M5N2MMze , M5N2RAxe , M5N2RAye , M5N2RAze , M5N2RDxe , M5N2RDye , M5N2RDze , & + M5N2TAxe , M5N2TAye , M5N2TAze , M5N2TDxss , M5N2TDyss , M5N2TDzss , M5N3FKxe , & + M5N3FKye , M5N3FKze , M5N3FMxe , M5N3FMye , M5N3FMze , M5N3MKxe , M5N3MKye , & + M5N3MKze , M5N3MMxe , M5N3MMye , M5N3MMze , M5N3RAxe , M5N3RAye , M5N3RAze , & + M5N3RDxe , M5N3RDye , M5N3RDze , M5N3TAxe , M5N3TAye , M5N3TAze , M5N3TDxss , & + M5N3TDyss , M5N3TDzss , M5N4FKxe , M5N4FKye , M5N4FKze , M5N4FMxe , M5N4FMye , & + M5N4FMze , M5N4MKxe , M5N4MKye , M5N4MKze , M5N4MMxe , M5N4MMye , M5N4MMze , & + M5N4RAxe , M5N4RAye , M5N4RAze , M5N4RDxe , M5N4RDye , M5N4RDze , M5N4TAxe , & + M5N4TAye , M5N4TAze , M5N4TDxss , M5N4TDyss , M5N4TDzss , M5N5FKxe , M5N5FKye , & + M5N5FKze , M5N5FMxe , M5N5FMye , M5N5FMze , M5N5MKxe , M5N5MKye , M5N5MKze , & + M5N5MMxe , M5N5MMye , M5N5MMze , M5N5RAxe , M5N5RAye , M5N5RAze , M5N5RDxe , & + M5N5RDye , M5N5RDze , M5N5TAxe , M5N5TAye , M5N5TAze , M5N5TDxss , M5N5TDyss , & + M5N5TDzss , M5N6FKxe , M5N6FKye , M5N6FKze , M5N6FMxe , M5N6FMye , M5N6FMze , & + M5N6MKxe , M5N6MKye , M5N6MKze , M5N6MMxe , M5N6MMye , M5N6MMze , M5N6RAxe , & + M5N6RAye , M5N6RAze , M5N6RDxe , M5N6RDye , M5N6RDze , M5N6TAxe , M5N6TAye , & + M5N6TAze , M5N6TDxss , M5N6TDyss , M5N6TDzss , M5N7FKxe , M5N7FKye , M5N7FKze , & + M5N7FMxe , M5N7FMye , M5N7FMze , M5N7MKxe , M5N7MKye , M5N7MKze , M5N7MMxe , & + M5N7MMye , M5N7MMze , M5N7RAxe , M5N7RAye , M5N7RAze , M5N7RDxe , M5N7RDye , & + M5N7RDze , M5N7TAxe , M5N7TAye , M5N7TAze , M5N7TDxss , M5N7TDyss , M5N7TDzss , & + M5N8FKxe , M5N8FKye , M5N8FKze , M5N8FMxe , M5N8FMye , M5N8FMze , M5N8MKxe , & + M5N8MKye , M5N8MKze , M5N8MMxe , M5N8MMye , M5N8MMze , M5N8RAxe , M5N8RAye , & + M5N8RAze , M5N8RDxe , M5N8RDye , M5N8RDze , M5N8TAxe , M5N8TAye , M5N8TAze , & + M5N8TDxss , M5N8TDyss , M5N8TDzss , M5N9FKxe , M5N9FKye , M5N9FKze , M5N9FMxe , & + M5N9FMye , M5N9FMze , M5N9MKxe , M5N9MKye , M5N9MKze , M5N9MMxe , M5N9MMye , & + M5N9MMze , M5N9RAxe , M5N9RAye , M5N9RAze , M5N9RDxe , M5N9RDye , M5N9RDze , & + M5N9TAxe , M5N9TAye , M5N9TAze , M5N9TDxss , M5N9TDyss , M5N9TDzss , M6N1FKxe , & + M6N1FKye , M6N1FKze , M6N1FMxe , M6N1FMye , M6N1FMze , M6N1MKxe , M6N1MKye , & + M6N1MKze , M6N1MMxe , M6N1MMye , M6N1MMze , M6N1RAxe , M6N1RAye , M6N1RAze , & + M6N1RDxe , M6N1RDye , M6N1RDze , M6N1TAxe , M6N1TAye , M6N1TAze , M6N1TDxss , & + M6N1TDyss , M6N1TDzss , M6N2FKxe , M6N2FKye , M6N2FKze , M6N2FMxe , M6N2FMye , & + M6N2FMze , M6N2MKxe , M6N2MKye , M6N2MKze , M6N2MMxe , M6N2MMye , M6N2MMze , & + M6N2RAxe , M6N2RAye , M6N2RAze , M6N2RDxe , M6N2RDye , M6N2RDze , M6N2TAxe , & + M6N2TAye , M6N2TAze , M6N2TDxss , M6N2TDyss , M6N2TDzss , M6N3FKxe , M6N3FKye , & + M6N3FKze , M6N3FMxe , M6N3FMye , M6N3FMze , M6N3MKxe , M6N3MKye , M6N3MKze , & + M6N3MMxe , M6N3MMye , M6N3MMze , M6N3RAxe , M6N3RAye , M6N3RAze , M6N3RDxe , & + M6N3RDye , M6N3RDze , M6N3TAxe , M6N3TAye , M6N3TAze , M6N3TDxss , M6N3TDyss , & + M6N3TDzss , M6N4FKxe , M6N4FKye , M6N4FKze , M6N4FMxe , M6N4FMye , M6N4FMze , & + M6N4MKxe , M6N4MKye , M6N4MKze , M6N4MMxe , M6N4MMye , M6N4MMze , M6N4RAxe , & + M6N4RAye , M6N4RAze , M6N4RDxe , M6N4RDye , M6N4RDze , M6N4TAxe , M6N4TAye , & + M6N4TAze , M6N4TDxss , M6N4TDyss , M6N4TDzss , M6N5FKxe , M6N5FKye , M6N5FKze , & + M6N5FMxe , M6N5FMye , M6N5FMze , M6N5MKxe , M6N5MKye , M6N5MKze , M6N5MMxe , & + M6N5MMye , M6N5MMze , M6N5RAxe , M6N5RAye , M6N5RAze , M6N5RDxe , M6N5RDye , & + M6N5RDze , M6N5TAxe , M6N5TAye , M6N5TAze , M6N5TDxss , M6N5TDyss , M6N5TDzss , & + M6N6FKxe , M6N6FKye , M6N6FKze , M6N6FMxe , M6N6FMye , M6N6FMze , M6N6MKxe , & + M6N6MKye , M6N6MKze , M6N6MMxe , M6N6MMye , M6N6MMze , M6N6RAxe , M6N6RAye , & + M6N6RAze , M6N6RDxe , M6N6RDye , M6N6RDze , M6N6TAxe , M6N6TAye , M6N6TAze , & + M6N6TDxss , M6N6TDyss , M6N6TDzss , M6N7FKxe , M6N7FKye , M6N7FKze , M6N7FMxe , & + M6N7FMye , M6N7FMze , M6N7MKxe , M6N7MKye , M6N7MKze , M6N7MMxe , M6N7MMye , & + M6N7MMze , M6N7RAxe , M6N7RAye , M6N7RAze , M6N7RDxe , M6N7RDye , M6N7RDze , & + M6N7TAxe , M6N7TAye , M6N7TAze , M6N7TDxss , M6N7TDyss , M6N7TDzss , M6N8FKxe , & + M6N8FKye , M6N8FKze , M6N8FMxe , M6N8FMye , M6N8FMze , M6N8MKxe , M6N8MKye , & + M6N8MKze , M6N8MMxe , M6N8MMye , M6N8MMze , M6N8RAxe , M6N8RAye , M6N8RAze , & + M6N8RDxe , M6N8RDye , M6N8RDze , M6N8TAxe , M6N8TAye , M6N8TAze , M6N8TDxss , & + M6N8TDyss , M6N8TDzss , M6N9FKxe , M6N9FKye , M6N9FKze , M6N9FMxe , M6N9FMye , & + M6N9FMze , M6N9MKxe , M6N9MKye , M6N9MKze , M6N9MMxe , M6N9MMye , M6N9MMze , & + M6N9RAxe , M6N9RAye , M6N9RAze , M6N9RDxe , M6N9RDye , M6N9RDze , M6N9TAxe , & + M6N9TAye , M6N9TAze , M6N9TDxss , M6N9TDyss , M6N9TDzss , M7N1FKxe , M7N1FKye , & + M7N1FKze , M7N1FMxe , M7N1FMye , M7N1FMze , M7N1MKxe , M7N1MKye , M7N1MKze , & + M7N1MMxe , M7N1MMye , M7N1MMze , M7N1RAxe , M7N1RAye , M7N1RAze , M7N1RDxe , & + M7N1RDye , M7N1RDze , M7N1TAxe , M7N1TAye , M7N1TAze , M7N1TDxss , M7N1TDyss , & + M7N1TDzss , M7N2FKxe , M7N2FKye , M7N2FKze , M7N2FMxe , M7N2FMye , M7N2FMze , & + M7N2MKxe , M7N2MKye , M7N2MKze , M7N2MMxe , M7N2MMye , M7N2MMze , M7N2RAxe , & + M7N2RAye , M7N2RAze , M7N2RDxe , M7N2RDye , M7N2RDze , M7N2TAxe , M7N2TAye , & + M7N2TAze , M7N2TDxss , M7N2TDyss , M7N2TDzss , M7N3FKxe , M7N3FKye , M7N3FKze , & + M7N3FMxe , M7N3FMye , M7N3FMze , M7N3MKxe , M7N3MKye , M7N3MKze , M7N3MMxe , & + M7N3MMye , M7N3MMze , M7N3RAxe , M7N3RAye , M7N3RAze , M7N3RDxe , M7N3RDye , & + M7N3RDze , M7N3TAxe , M7N3TAye , M7N3TAze , M7N3TDxss , M7N3TDyss , M7N3TDzss , & + M7N4FKxe , M7N4FKye , M7N4FKze , M7N4FMxe , M7N4FMye , M7N4FMze , M7N4MKxe , & + M7N4MKye , M7N4MKze , M7N4MMxe , M7N4MMye , M7N4MMze , M7N4RAxe , M7N4RAye , & + M7N4RAze , M7N4RDxe , M7N4RDye , M7N4RDze , M7N4TAxe , M7N4TAye , M7N4TAze , & + M7N4TDxss , M7N4TDyss , M7N4TDzss , M7N5FKxe , M7N5FKye , M7N5FKze , M7N5FMxe , & + M7N5FMye , M7N5FMze , M7N5MKxe , M7N5MKye , M7N5MKze , M7N5MMxe , M7N5MMye , & + M7N5MMze , M7N5RAxe , M7N5RAye , M7N5RAze , M7N5RDxe , M7N5RDye , M7N5RDze , & + M7N5TAxe , M7N5TAye , M7N5TAze , M7N5TDxss , M7N5TDyss , M7N5TDzss , M7N6FKxe , & + M7N6FKye , M7N6FKze , M7N6FMxe , M7N6FMye , M7N6FMze , M7N6MKxe , M7N6MKye , & + M7N6MKze , M7N6MMxe , M7N6MMye , M7N6MMze , M7N6RAxe , M7N6RAye , M7N6RAze , & + M7N6RDxe , M7N6RDye , M7N6RDze , M7N6TAxe , M7N6TAye , M7N6TAze , M7N6TDxss , & + M7N6TDyss , M7N6TDzss , M7N7FKxe , M7N7FKye , M7N7FKze , M7N7FMxe , M7N7FMye , & + M7N7FMze , M7N7MKxe , M7N7MKye , M7N7MKze , M7N7MMxe , M7N7MMye , M7N7MMze , & + M7N7RAxe , M7N7RAye , M7N7RAze , M7N7RDxe , M7N7RDye , M7N7RDze , M7N7TAxe , & + M7N7TAye , M7N7TAze , M7N7TDxss , M7N7TDyss , M7N7TDzss , M7N8FKxe , M7N8FKye , & + M7N8FKze , M7N8FMxe , M7N8FMye , M7N8FMze , M7N8MKxe , M7N8MKye , M7N8MKze , & + M7N8MMxe , M7N8MMye , M7N8MMze , M7N8RAxe , M7N8RAye , M7N8RAze , M7N8RDxe , & + M7N8RDye , M7N8RDze , M7N8TAxe , M7N8TAye , M7N8TAze , M7N8TDxss , M7N8TDyss , & + M7N8TDzss , M7N9FKxe , M7N9FKye , M7N9FKze , M7N9FMxe , M7N9FMye , M7N9FMze , & + M7N9MKxe , M7N9MKye , M7N9MKze , M7N9MMxe , M7N9MMye , M7N9MMze , M7N9RAxe , & + M7N9RAye , M7N9RAze , M7N9RDxe , M7N9RDye , M7N9RDze , M7N9TAxe , M7N9TAye , & + M7N9TAze , M7N9TDxss , M7N9TDyss , M7N9TDzss , M8N1FKxe , M8N1FKye , M8N1FKze , & + M8N1FMxe , M8N1FMye , M8N1FMze , M8N1MKxe , M8N1MKye , M8N1MKze , M8N1MMxe , & + M8N1MMye , M8N1MMze , M8N1RAxe , M8N1RAye , M8N1RAze , M8N1RDxe , M8N1RDye , & + M8N1RDze , M8N1TAxe , M8N1TAye , M8N1TAze , M8N1TDxss , M8N1TDyss , M8N1TDzss , & + M8N2FKxe , M8N2FKye , M8N2FKze , M8N2FMxe , M8N2FMye , M8N2FMze , M8N2MKxe , & + M8N2MKye , M8N2MKze , M8N2MMxe , M8N2MMye , M8N2MMze , M8N2RAxe , M8N2RAye , & + M8N2RAze , M8N2RDxe , M8N2RDye , M8N2RDze , M8N2TAxe , M8N2TAye , M8N2TAze , & + M8N2TDxss , M8N2TDyss , M8N2TDzss , M8N3FKxe , M8N3FKye , M8N3FKze , M8N3FMxe , & + M8N3FMye , M8N3FMze , M8N3MKxe , M8N3MKye , M8N3MKze , M8N3MMxe , M8N3MMye , & + M8N3MMze , M8N3RAxe , M8N3RAye , M8N3RAze , M8N3RDxe , M8N3RDye , M8N3RDze , & + M8N3TAxe , M8N3TAye , M8N3TAze , M8N3TDxss , M8N3TDyss , M8N3TDzss , M8N4FKxe , & + M8N4FKye , M8N4FKze , M8N4FMxe , M8N4FMye , M8N4FMze , M8N4MKxe , M8N4MKye , & + M8N4MKze , M8N4MMxe , M8N4MMye , M8N4MMze , M8N4RAxe , M8N4RAye , M8N4RAze , & + M8N4RDxe , M8N4RDye , M8N4RDze , M8N4TAxe , M8N4TAye , M8N4TAze , M8N4TDxss , & + M8N4TDyss , M8N4TDzss , M8N5FKxe , M8N5FKye , M8N5FKze , M8N5FMxe , M8N5FMye , & + M8N5FMze , M8N5MKxe , M8N5MKye , M8N5MKze , M8N5MMxe , M8N5MMye , M8N5MMze , & + M8N5RAxe , M8N5RAye , M8N5RAze , M8N5RDxe , M8N5RDye , M8N5RDze , M8N5TAxe , & + M8N5TAye , M8N5TAze , M8N5TDxss , M8N5TDyss , M8N5TDzss , M8N6FKxe , M8N6FKye , & + M8N6FKze , M8N6FMxe , M8N6FMye , M8N6FMze , M8N6MKxe , M8N6MKye , M8N6MKze , & + M8N6MMxe , M8N6MMye , M8N6MMze , M8N6RAxe , M8N6RAye , M8N6RAze , M8N6RDxe , & + M8N6RDye , M8N6RDze , M8N6TAxe , M8N6TAye , M8N6TAze , M8N6TDxss , M8N6TDyss , & + M8N6TDzss , M8N7FKxe , M8N7FKye , M8N7FKze , M8N7FMxe , M8N7FMye , M8N7FMze , & + M8N7MKxe , M8N7MKye , M8N7MKze , M8N7MMxe , M8N7MMye , M8N7MMze , M8N7RAxe , & + M8N7RAye , M8N7RAze , M8N7RDxe , M8N7RDye , M8N7RDze , M8N7TAxe , M8N7TAye , & + M8N7TAze , M8N7TDxss , M8N7TDyss , M8N7TDzss , M8N8FKxe , M8N8FKye , M8N8FKze , & + M8N8FMxe , M8N8FMye , M8N8FMze , M8N8MKxe , M8N8MKye , M8N8MKze , M8N8MMxe , & + M8N8MMye , M8N8MMze , M8N8RAxe , M8N8RAye , M8N8RAze , M8N8RDxe , M8N8RDye , & + M8N8RDze , M8N8TAxe , M8N8TAye , M8N8TAze , M8N8TDxss , M8N8TDyss , M8N8TDzss , & + M8N9FKxe , M8N9FKye , M8N9FKze , M8N9FMxe , M8N9FMye , M8N9FMze , M8N9MKxe , & + M8N9MKye , M8N9MKze , M8N9MMxe , M8N9MMye , M8N9MMze , M8N9RAxe , M8N9RAye , & + M8N9RAze , M8N9RDxe , M8N9RDye , M8N9RDze , M8N9TAxe , M8N9TAye , M8N9TAze , & + M8N9TDxss , M8N9TDyss , M8N9TDzss , M9N1FKxe , M9N1FKye , M9N1FKze , M9N1FMxe , & + M9N1FMye , M9N1FMze , M9N1MKxe , M9N1MKye , M9N1MKze , M9N1MMxe , M9N1MMye , & + M9N1MMze , M9N1RAxe , M9N1RAye , M9N1RAze , M9N1RDxe , M9N1RDye , M9N1RDze , & + M9N1TAxe , M9N1TAye , M9N1TAze , M9N1TDxss , M9N1TDyss , M9N1TDzss , M9N2FKxe , & + M9N2FKye , M9N2FKze , M9N2FMxe , M9N2FMye , M9N2FMze , M9N2MKxe , M9N2MKye , & + M9N2MKze , M9N2MMxe , M9N2MMye , M9N2MMze , M9N2RAxe , M9N2RAye , M9N2RAze , & + M9N2RDxe , M9N2RDye , M9N2RDze , M9N2TAxe , M9N2TAye , M9N2TAze , M9N2TDxss , & + M9N2TDyss , M9N2TDzss , M9N3FKxe , M9N3FKye , M9N3FKze , M9N3FMxe , M9N3FMye , & + M9N3FMze , M9N3MKxe , M9N3MKye , M9N3MKze , M9N3MMxe , M9N3MMye , M9N3MMze , & + M9N3RAxe , M9N3RAye , M9N3RAze , M9N3RDxe , M9N3RDye , M9N3RDze , M9N3TAxe , & + M9N3TAye , M9N3TAze , M9N3TDxss , M9N3TDyss , M9N3TDzss , M9N4FKxe , M9N4FKye , & + M9N4FKze , M9N4FMxe , M9N4FMye , M9N4FMze , M9N4MKxe , M9N4MKye , M9N4MKze , & + M9N4MMxe , M9N4MMye , M9N4MMze , M9N4RAxe , M9N4RAye , M9N4RAze , M9N4RDxe , & + M9N4RDye , M9N4RDze , M9N4TAxe , M9N4TAye , M9N4TAze , M9N4TDxss , M9N4TDyss , & + M9N4TDzss , M9N5FKxe , M9N5FKye , M9N5FKze , M9N5FMxe , M9N5FMye , M9N5FMze , & + M9N5MKxe , M9N5MKye , M9N5MKze , M9N5MMxe , M9N5MMye , M9N5MMze , M9N5RAxe , & + M9N5RAye , M9N5RAze , M9N5RDxe , M9N5RDye , M9N5RDze , M9N5TAxe , M9N5TAye , & + M9N5TAze , M9N5TDxss , M9N5TDyss , M9N5TDzss , M9N6FKxe , M9N6FKye , M9N6FKze , & + M9N6FMxe , M9N6FMye , M9N6FMze , M9N6MKxe , M9N6MKye , M9N6MKze , M9N6MMxe , & + M9N6MMye , M9N6MMze , M9N6RAxe , M9N6RAye , M9N6RAze , M9N6RDxe , M9N6RDye , & + M9N6RDze , M9N6TAxe , M9N6TAye , M9N6TAze , M9N6TDxss , M9N6TDyss , M9N6TDzss , & + M9N7FKxe , M9N7FKye , M9N7FKze , M9N7FMxe , M9N7FMye , M9N7FMze , M9N7MKxe , & + M9N7MKye , M9N7MKze , M9N7MMxe , M9N7MMye , M9N7MMze , M9N7RAxe , M9N7RAye , & + M9N7RAze , M9N7RDxe , M9N7RDye , M9N7RDze , M9N7TAxe , M9N7TAye , M9N7TAze , & + M9N7TDxss , M9N7TDyss , M9N7TDzss , M9N8FKxe , M9N8FKye , M9N8FKze , M9N8FMxe , & + M9N8FMye , M9N8FMze , M9N8MKxe , M9N8MKye , M9N8MKze , M9N8MMxe , M9N8MMye , & + M9N8MMze , M9N8RAxe , M9N8RAye , M9N8RAze , M9N8RDxe , M9N8RDye , M9N8RDze , & + M9N8TAxe , M9N8TAye , M9N8TAze , M9N8TDxss , M9N8TDyss , M9N8TDzss , M9N9FKxe , & + M9N9FKye , M9N9FKze , M9N9FMxe , M9N9FMye , M9N9FMze , M9N9MKxe , M9N9MKye , & + M9N9MKze , M9N9MMxe , M9N9MMye , M9N9MMze , M9N9RAxe , M9N9RAye , M9N9RAze , & + M9N9RDxe , M9N9RDye , M9N9RDze , M9N9TAxe , M9N9TAye , M9N9TAze , M9N9TDxss , & + M9N9TDyss , M9N9TDzss , ReactFXss , ReactFYss , ReactFZss , ReactMXss , ReactMYss , & + ReactMZss , SSqm01 , SSqm02 , SSqm03 , SSqm04 , SSqm05 , SSqm06 , & + SSqm07 , SSqm08 , SSqm09 , SSqm10 , SSqm11 , SSqm12 , SSqm13 , & + SSqm14 , SSqm15 , SSqm16 , SSqm17 , SSqm18 , SSqm19 , SSqm20 , & + SSqm21 , SSqm22 , SSqm23 , SSqm24 , SSqm25 , SSqm26 , SSqm27 , & + SSqm28 , SSqm29 , SSqm30 , SSqm31 , SSqm32 , SSqm33 , SSqm34 , & + SSqm35 , SSqm36 , SSqm37 , SSqm38 , SSqm39 , SSqm40 , SSqm41 , & + SSqm42 , SSqm43 , SSqm44 , SSqm45 , SSqm46 , SSqm47 , SSqm48 , & + SSqm49 , SSqm50 , SSqm51 , SSqm52 , SSqm53 , SSqm54 , SSqm55 , & + SSqm56 , SSqm57 , SSqm58 , SSqm59 , SSqm60 , SSqm61 , SSqm62 , & + SSqm63 , SSqm64 , SSqm65 , SSqm66 , SSqm67 , SSqm68 , SSqm69 , & + SSqm70 , SSqm71 , SSqm72 , SSqm73 , SSqm74 , SSqm75 , SSqm76 , & + SSqm77 , SSqm78 , SSqm79 , SSqm80 , SSqm81 , SSqm82 , SSqm83 , & + SSqm84 , SSqm85 , SSqm86 , SSqm87 , SSqm88 , SSqm89 , SSqm90 , & + SSqm91 , SSqm92 , SSqm93 , SSqm94 , SSqm95 , SSqm96 , SSqm97 , & + SSqm98 , SSqm99 , SSqmd01 , SSqmd02 , SSqmd03 , SSqmd04 , SSqmd05 , & + SSqmd06 , SSqmd07 , SSqmd08 , SSqmd09 , SSqmd10 , SSqmd11 , SSqmd12 , & + SSqmd13 , SSqmd14 , SSqmd15 , SSqmd16 , SSqmd17 , SSqmd18 , SSqmd19 , & + SSqmd20 , SSqmd21 , SSqmd22 , SSqmd23 , SSqmd24 , SSqmd25 , SSqmd26 , & + SSqmd27 , SSqmd28 , SSqmd29 , SSqmd30 , SSqmd31 , SSqmd32 , SSqmd33 , & + SSqmd34 , SSqmd35 , SSqmd36 , SSqmd37 , SSqmd38 , SSqmd39 , SSqmd40 , & + SSqmd41 , SSqmd42 , SSqmd43 , SSqmd44 , SSqmd45 , SSqmd46 , SSqmd47 , & + SSqmd48 , SSqmd49 , SSqmd50 , SSqmd51 , SSqmd52 , SSqmd53 , SSqmd54 , & + SSqmd55 , SSqmd56 , SSqmd57 , SSqmd58 , SSqmd59 , SSqmd60 , SSqmd61 , & + SSqmd62 , SSqmd63 , SSqmd64 , SSqmd65 , SSqmd66 , SSqmd67 , SSqmd68 , & + SSqmd69 , SSqmd70 , SSqmd71 , SSqmd72 , SSqmd73 , SSqmd74 , SSqmd75 , & + SSqmd76 , SSqmd77 , SSqmd78 , SSqmd79 , SSqmd80 , SSqmd81 , SSqmd82 , & + SSqmd83 , SSqmd84 , SSqmd85 , SSqmd86 , SSqmd87 , SSqmd88 , SSqmd89 , & + SSqmd90 , SSqmd91 , SSqmd92 , SSqmd93 , SSqmd94 , SSqmd95 , SSqmd96 , & + SSqmd97 , SSqmd98 , SSqmd99 , SSqmdd01 , SSqmdd02 , SSqmdd03 , SSqmdd04 , & + SSqmdd05 , SSqmdd06 , SSqmdd07 , SSqmdd08 , SSqmdd09 , SSqmdd10 , SSqmdd11 , & + SSqmdd12 , SSqmdd13 , SSqmdd14 , SSqmdd15 , SSqmdd16 , SSqmdd17 , SSqmdd18 , & + SSqmdd19 , SSqmdd20 , SSqmdd21 , SSqmdd22 , SSqmdd23 , SSqmdd24 , SSqmdd25 , & + SSqmdd26 , SSqmdd27 , SSqmdd28 , SSqmdd29 , SSqmdd30 , SSqmdd31 , SSqmdd32 , & + SSqmdd33 , SSqmdd34 , SSqmdd35 , SSqmdd36 , SSqmdd37 , SSqmdd38 , SSqmdd39 , & + SSqmdd40 , SSqmdd41 , SSqmdd42 , SSqmdd43 , SSqmdd44 , SSqmdd45 , SSqmdd46 , & + SSqmdd47 , SSqmdd48 , SSqmdd49 , SSqmdd50 , SSqmdd51 , SSqmdd52 , SSqmdd53 , & + SSqmdd54 , SSqmdd55 , SSqmdd56 , SSqmdd57 , SSqmdd58 , SSqmdd59 , SSqmdd60 , & + SSqmdd61 , SSqmdd62 , SSqmdd63 , SSqmdd64 , SSqmdd65 , SSqmdd66 , SSqmdd67 , & + SSqmdd68 , SSqmdd69 , SSqmdd70 , SSqmdd71 , SSqmdd72 , SSqmdd73 , SSqmdd74 , & + SSqmdd75 , SSqmdd76 , SSqmdd77 , SSqmdd78 , SSqmdd79 , SSqmdd80 , SSqmdd81 , & + SSqmdd82 , SSqmdd83 , SSqmdd84 , SSqmdd85 , SSqmdd86 , SSqmdd87 , SSqmdd88 , & + SSqmdd89 , SSqmdd90 , SSqmdd91 , SSqmdd92 , SSqmdd93 , SSqmdd94 , SSqmdd95 , & + SSqmdd96 , SSqmdd97 , SSqmdd98 , SSqmdd99 /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(2265) = (/ & ! This lists the units corresponding to the allowed parameters + "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & + "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & + "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & + "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & + "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & + "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & + "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & + "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & + "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & + "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & + "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & + "(m) ","(m) ","(N) ","(N) ","(N) ","(Nm) ","(Nm) ", & + "(Nm) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & + "(--) ","(--) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & + "(1/s) ","(1/s) ","(1/s) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & + "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) "/) + + +!End of code generated by Matlab script +end module SubDyn_Output_Params diff --git a/modules/subdyn/src_soildyn/SubDyn_Registry.txt b/modules/subdyn/src_soildyn/SubDyn_Registry.txt new file mode 100644 index 000000000..adca6cee0 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Registry.txt @@ -0,0 +1,269 @@ +##################### Registry for SubDyn ################## +# +# +# Use ^ as a shortcut for the value in the same column from the previous line. +################################################################################################################################### +# ...... Include files (definitions from NWTC Library) ............................................................................ +include Registry_NWTC_Library.txt + +# +# Keyword ModuleName/ModName Derived data type Field type Variable name Dimemsion of the variable Initial value not used Description Units + +typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" + +! integer, dimension(:), pointer :: data => null() +! type(IList), pointer :: next => null() + +# ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ +typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" +typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ InitInputType ReKi g - - - "Gravity acceleration" +typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" +typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ InitInputType ReKi SoilStiffness ::: - - "Soil stiffness matrices from SoilDyn" '(N/m, N-m/rad)' +typedef ^ InitInputType MeshType SoilMesh - - - "Mesh for soil stiffness locations" - + +# ============================== Define Initialization outputs here: ============================================================================================================================================ +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - + +# ============================== Define Internal data types here: ============================================================================================================================================ +typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" +typedef ^ MeshAuxDataType INTEGER NOutCnt - - - "Number of Nodes for the output member" +typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" +typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" +typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" +# CB_MatArrays: Matrices and arrays for CB summary +typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" +typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" +typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" +typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" +typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" +# +typedef ^ ElemPropType IntKi eType - - - "Element Type" +typedef ^ ^ ReKi Length - - - "Length of an element" +typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" +typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" +typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" +typedef ^ ^ ReKi Kappa - - - "Shear coefficient" +typedef ^ ^ ReKi YoungE - - - "Young's modulus" +typedef ^ ^ ReKi ShearG - - - "Shear modulus" N/m^2 +# Properties common to all element types: +typedef ^ ^ ReKi Area - - - "Area of an element" m^2 +typedef ^ ^ ReKi Rho - - - "Density" kg/m^3 +typedef ^ ^ ReKi T0 - - - "Pretension " N +typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" +# ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ +#--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- +typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ ^ ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ ^ ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ ^ ReKi g - - - "Gravity acceleration" +typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds +typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" +typedef ^ ^ INTEGER NPropSetsX - - - "Number of extended property sets" +typedef ^ ^ INTEGER NPropSetsB - - - "Number of property sets for beams" +typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" +typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" +typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" +typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" +typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" +typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" +typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" +typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" +typedef ^ ^ ReKi PropSetsB {:}{:} - - "Property sets number and values" +typedef ^ ^ ReKi PropSetsC {:}{:} - - "Property ID and values for cables" +typedef ^ ^ ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" +typedef ^ ^ ReKi PropSetsX {:}{:} - - "Extended property sets" +typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" +typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" +typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" +typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" +typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" +typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" +typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" +typedef ^ ^ ReKi SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" +typedef ^ ^ ReKi SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" +typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" +typedef ^ ^ ReKi Soil_K {:}{:}{:} - - "Soil stiffness (at passed at Init, not in input file) 6x6xn" +typedef ^ ^ ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added" +typedef ^ ^ Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added" +#-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +typedef ^ ^ INTEGER NElem - - - "Total number of elements" +typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" +typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" +typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" +typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" +typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" +typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" +typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" +typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" +typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" +typedef ^ ^ ReKi D {:}{:} - - "System damping matrix" +typedef ^ ^ ReKi F {:} - - "System force vector" N +typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N +typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" +typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" +typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" +typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" +typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" +typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" +typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" + +# ============================== States ============================================================================================================================================ +# Define continuous (differentiable) states here: +typedef ^ ContinuousStateType ReKi qm {:} - - "Virtual states, Nmod elements" +typedef ^ ContinuousStateType ReKi qmdot {:} - - "Derivative of states, Nmod elements" +# Define discrete (nondifferentiable) states here: +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" +# Define constraint states here: +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" + +# Define any other states, including integer or logical states here: +typedef SubDyn/SD OtherStateType SD_ContinuousStateType xdot {:} - - "previous state derivs for m-step time integrator" +typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated last" + + +# ..... Misc/Optimization variables................................................................................................. +# Define any data that are used only for efficiency purposes (these variables are not associated with time): +# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. +typedef ^ MiscVarType ReKi qmdotdot {:} - - "2nd Derivative of states, used only for output-file purposes" +typedef ^ ^ ReKi u_TP 6 - - +typedef ^ ^ ReKi udot_TP 6 - - +typedef ^ ^ ReKi udotdot_TP 6 - - +typedef ^ ^ ReKi UFL {:} - - +typedef ^ ^ ReKi UR_bar {:} - - +typedef ^ ^ ReKi UR_bar_dot {:} - - +typedef ^ ^ ReKi UR_bar_dotdot {:} - - +typedef ^ ^ ReKi UL {:} - - +typedef ^ ^ ReKi UL_dot {:} - - +typedef ^ ^ ReKi UL_dotdot {:} - - +typedef ^ ^ ReKi U_full {:} - - +typedef ^ ^ ReKi U_full_dot {:} - - +typedef ^ ^ ReKi U_full_dotdot {:} - - +typedef ^ ^ ReKi U_red {:} - - +typedef ^ ^ ReKi U_red_dot {:} - - +typedef ^ ^ ReKi U_red_dotdot {:} - - +### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### +typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" +typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" +typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" +typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" +typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" + + + +# ============================== Parameters ============================================================================================================================================ +# --- Algo +typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds +typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" +# --- FEM +typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" +typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" +typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" +typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" +typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +# --- Constraints reduction +typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" +typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" +typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" +# --- CB reduction +typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" +typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" +typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" +typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" +typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" +typedef ^ ParameterType ReKi FX {:} - - "Load components in X" +typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of u in Y1" +typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of u in Y1" +typedef ^ ParameterType ReKi FY {:} - - "Load Components in Y1" +typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" +typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R bar * TI)" +typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" +typedef ^ ParameterType ReKi MBB {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi UL_st_g {:} - - "Motion of internal DOFs due to static gravitational force, for static improvement" +typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" +typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" +typedef ^ ParameterType ReKi KLLm1 {:}{:} - - "KLL^{-1}, inverse of matrix KLL, for static solve only" +typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" +typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" +typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" +typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" +# --- Partitioning I L C Y, R=[C I] +typedef ^ ParameterType IntKi nNodes - - - "Total number of nodes" +typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" +typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" +typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" +typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" +typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" +typedef ^ ParameterType IntKi nDOFI__ - - - "Size of IDI__" +typedef ^ ParameterType IntKi nDOFI_Rb - - - "Size of IDI_Rb" +typedef ^ ParameterType IntKi nDOFI_F - - - "Size of IDI_F" +typedef ^ ParameterType IntKi nDOFL_L - - - "Size of IDL_L" +typedef ^ ParameterType IntKi nDOFC__ - - - "Size of IDC__" +typedef ^ ParameterType IntKi nDOFC_Rb - - - "Size of IDC_Rb" +typedef ^ ParameterType IntKi nDOFC_L - - - "Size of IDC_L" +typedef ^ ParameterType IntKi nDOFC_F - - - "Size of IDC_F" +typedef ^ ParameterType IntKi nDOFR__ - - - "Size of IDR__" +typedef ^ ParameterType IntKi nDOF__Rb - - - "Size of ID__Rb" +typedef ^ ParameterType IntKi nDOF__L - - - "Size of ID__L" +typedef ^ ParameterType IntKi nDOF__F - - - "Size of ID__F" +typedef ^ ParameterType IntKi IDI__ {:} - - "Index of all Interface DOFs" +typedef ^ ParameterType IntKi IDI_Rb {:} - - "Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs" +typedef ^ ParameterType IntKi IDI_F {:} - - "Index array of the interface (nodes connect to TP) dofs that are fixed DOF" +typedef ^ ParameterType IntKi IDL_L {:} - - "Index array of the internal dofs coming from internal nodes" +typedef ^ ParameterType IntKi IDC__ {:} - - "Index of all bottom DOF" +typedef ^ ParameterType IntKi IDC_Rb {:} - - "Index array of the contraint dofs that are retained/master/follower DOF" +typedef ^ ParameterType IntKi IDC_L {:} - - "Index array of the contraint dofs that are follower/internal DOF" +typedef ^ ParameterType IntKi IDC_F {:} - - "Index array of the contraint dofs that are fixd DOF" +typedef ^ ParameterType IntKi IDR__ {:} - - "Index array of the interface and restraint dofs" +typedef ^ ParameterType IntKi ID__Rb {:} - - "Index array of all the retained/leader/master dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__L {:} - - "Index array of all the follower/internal dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__F {:} - - "Index array of the DOF that are fixed (from any nodes of the structure)" +typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" +# --- Outputs +typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" +typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" +typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" +typedef ^ ParameterType IntKi UnJckF - - - "Unit of SD ouput file" +typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" +typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format for Output" +typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" +typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" +typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" +typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" +typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" +typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" + +# ============================== Inputs ============================================================================================================================================ +typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" +typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" + +# ============================== Outputs ============================================================================================================================================ +typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" +typedef ^ OutputType MeshType Y2Mesh - - - "Interior+Interface nodes outputs on a point mesh" +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file" diff --git a/modules/subdyn/src_soildyn/SubDyn_Tests.f90 b/modules/subdyn/src_soildyn/SubDyn_Tests.f90 new file mode 100644 index 000000000..b80f476e3 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Tests.f90 @@ -0,0 +1,440 @@ +module SubDyn_Tests + use NWTC_Library + use SubDyn_Types + use SD_FEM + use IntegerList + + implicit none + + public :: SD_Tests + private + + character(len=255),save :: testname + interface test_equal; module procedure & + test_equal_i1, & + test_equal_i0 + end interface + interface test_almost_equal; module procedure & + test_almost_equal_0, & + test_almost_equal_1, & + test_almost_equal_2 + end interface +contains + + ! -------------------------------------------------------------------------------- + ! --- Helper functions (should be part of NWTC library) + ! -------------------------------------------------------------------------------- + subroutine test_success(info,bPrint_in) + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) + endif + end subroutine + + subroutine test_fail(info,bPrint_in,bStop_in) + character(len=*), intent(in) :: info + logical, intent(in), optional :: bPrint_in + logical, intent(in), optional :: bStop_in + if(present(bPrint_in)) then + if(bPrint_in) then + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + else + write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) + endif + if(present(bStop_in)) then + if(bStop_in) then + STOP + endif + else + STOP + endif + end subroutine + + subroutine test_equal_i0(Var,iTry,iRef) + ! Arguments + character(len=*), intent(in) :: Var + integer, intent(in) :: iTry !< + integer, intent(in) :: iRef !< + ! Variables + character(len=255) :: InfoAbs + if(iRef/=iTry) then + write(InfoAbs,'(A,I0,A,I0)') trim(Var),iRef,'/',iTry + call test_fail(InfoAbs) + STOP + else + write(InfoAbs,'(A,A,I0)') trim(Var),' ok ',iRef + call test_success(InfoAbs) + endif + end subroutine + + subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + integer, dimension(:), intent(in) :: VecTry !< + integer, dimension(:), intent(in) :: VecRef !< + logical, intent(in) :: bTest + logical, intent(in) :: bPrintOnly + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + ! + cpt=0 + do i=1,size(VecRef) + if(VecRef(i)/=VecTry(i)) then + cpt=cpt+1 + endif + enddo + if(cpt>0) then + write(InfoAbs,'(A,I0)') trim(Var)//' Elements different: ',cpt + if(present(bPassed)) then + bPassed=.false. + endif + else + write(InfoAbs,'(A)') trim(Var)//' reproduced to identity' + if(present(bPassed)) then + bPassed=.true. + endif + endif + if(bPrintOnly) then + print'(A)',trim(InfoAbs) + endif + if(bTest) then + if(cpt>0) then + call test_fail(InfoAbs) + STOP + else + call test_success(InfoAbs) + endif + endif + end subroutine + + subroutine test_almost_equal_0(Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), intent(in) :: Ref !< + real(ReKi), intent(in) :: Try !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + real(ReKi) :: delta + integer :: cpt + ! + cpt=0 + delta=abs(Ref-Try) + if(delta>MINNORM) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta,' - Failed:',cpt + call test_fail(InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta + call test_success(InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=delta>MINNORM + endif + end subroutine + subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), dimension(:), intent(in) :: VecRef !< + real(ReKi), dimension(:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + real(ReKi) :: delta + real(ReKi) :: delta_cum + ! + cpt=0 + delta_cum=0.0_ReKi + do i=1,size(VecRef,1) + delta=abs(VecRef(i)-VecTry(i)) + delta_cum=delta_cum+delta + if(delta>MINNORM) then + cpt=cpt+1 + endif + enddo + delta_cum=delta_cum/size(VecRef) + + if(cpt>0) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum,' - Failed:',cpt + call test_fail(InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum + call test_success(InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=(cpt==0) + endif + end subroutine + subroutine test_almost_equal_2(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(ReKi), dimension(:,:), intent(in) :: VecRef !< + real(ReKi), dimension(:,:), intent(in) :: VecTry !< + real(ReKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + real(ReKi), dimension(:),allocatable :: VecRef2 !< + real(ReKi), dimension(:),allocatable :: VecTry2 !< + integer :: p, i,j,n1,n2,nCPs + ! + n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 + allocate ( VecRef2 (n1*n2) ) ; allocate ( VecTry2 (n1*n2) ) + p=0 + do j=1,n2; do i=1,n1 + p=p+1 + VecRef2(p)=VecRef(i,j) + VecTry2(p)=VecTry(i,j) + enddo; enddo; + call test_almost_equal(Var,VecRef2,VecTry2,MINNORM,bStop,bPrint,bPassed) + end subroutine + + + + ! --------------------------------------------------------------------------------} + ! --- Specific SubDyn tests + ! --------------------------------------------------------------------------------{ + subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg, Init, p) + TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters + INTEGER(IntKi) :: DOFTP, DOFM + REAL(ReKi) :: MBBt(DOFTP, DOFTP) + REAL(ReKi) :: MBmt(DOFTP, DOFM) + REAL(ReKi) :: KBBt(DOFTP, DOFTP) + REAL(ReKi) :: OmegaM(DOFM) + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: DOFT, NM, i + REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) + REAL(ReKi), Allocatable :: K(:, :) + REAL(ReKi), Allocatable :: M(:, :) + Character(1024) :: rootname + ErrStat = ErrID_None + ErrMsg = '' + print*,'This test is not a unit test' + + DOFT = DOFTP + DOFM + NM = DOFT - 3 + Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) + K = 0.0 + M = 0.0 + OmegaCB = 0.0 + PhiCB = 0.0 + + M(1:DOFTP, 1:DOFTP) = MBBt + M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt + M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) + + DO i = 1, DOFM + K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) + M(DOFTP+i, DOFTP+i) = 1.0 + ENDDO + + K(1:DOFTP, 1:DOFTP) = KBBt + + ! temporary rootname + rootname = './test_assemble_C-B_out' + + ! NOTE: Eigensolve is in SubDyn + !CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) + IF ( ErrStat /= 0 ) RETURN + end subroutine Test_CB_Results + + !> Transformation matrices tests + subroutine Test_Transformations(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + + real(ReKi), dimension(3) :: P1, P2, e1, e2, e3 + real(ReKi), dimension(3,3) :: DirCos, A, R0, Ref + real(ReKi), dimension(6,6) :: T, Tref + real(ReKi) :: L + integer(IntKi) :: I + testname='Transf' + + ! --- DirCos + P1=(/0,0,0/) + P2=(/2,0,0/) + call GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) + Ref = reshape( (/0_ReKi,-1_ReKi,0_ReKi, 0_ReKi, 0_ReKi, -1_ReKi, 1_ReKi, 0_ReKi, 0_ReKi/) , (/3,3/)) + call test_almost_equal('DirCos',Ref,DirCos,1e-8_ReKi,.true.,.true.) + + ! --- Rigid Transo + P1=(/1,2,-1/) + P2=(/2,5,5/) + call GetRigidTransformation(P1, P2, T, ErrStat, ErrMsg) + Tref = 0; do I=1,6; Tref(I,I) =1_ReKi; enddo + Tref(1,5) = 6._ReKi; Tref(1,6) =-3._ReKi; + Tref(2,4) =-6._ReKi; Tref(2,6) = 1._ReKi; + Tref(3,4) = 3._ReKi; Tref(3,5) =-1._ReKi; + call test_almost_equal('TRigid',Tref,T,1e-8_ReKi,.true.,.true.) + + + ! --- Orthogonal vectors + e1 = (/10,0,0/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi,-1._ReKi/),1e-8_ReKi,.true.,.true.) + call test_almost_equal('orth',e3,(/0._ReKi,1._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) + e1 = (/0,10,0/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi, 1._ReKi/),1e-8_ReKi,.true.,.true.) + call test_almost_equal('orth',e3,(/1._ReKi,0._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) + e1 = (/1,2,4/) + call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e2), 1e-8_ReKi, .true., .true.) + call test_almost_equal('dot', 0._ReKi, dot_product(e1,e3), 1e-8_ReKi, .true., .true.) + end subroutine Test_Transformations + + + !> Linear algebra tests + subroutine Test_Linalg(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref + real(DbKi) :: det + integer(IntKi) :: I, J + testname='Linalg' + + ! --- Determinant of a singular matrix + ! Commented since might lead to floating invalid + !allocate(A(3,3)); + !A(1,1) = 0 ; A(1,2) = 0 ; A(1,3) = 1 ; + !A(2,1) = 0 ; A(2,2) = 0 ; A(2,3) = -1 ; + !A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; + !det = Determinant(A,ErrStat, ErrMsg) + !call test_almost_equal('Det of singular 3x3 matrix', real(det,ReKi), 0.0_ReKi, 1e-8_ReKi, .true. , .true.) + !deallocate(A ) + + ! --- Inverse and determinant of a 3x3 matrix + allocate(A(3,3)); allocate(Aref(3,3)) + A(1,1) = 7 ; A(1,2) = 2 ; A(1,3) = 1 ; + A(2,1) = 0 ; A(2,2) = 3 ; A(2,3) = -1 ; + A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; + Aref(1,1) =-2 ; Aref(1,2) = 8 ; Aref(1,3) = -5 ; + Aref(2,1) = 3 ; Aref(2,2) =-11; Aref(2,3) = 7 ; + Aref(3,1) = 9 ; Aref(3,2) =-34; Aref(3,3) = 21; + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + ! Determinant test + det = Determinant(A,ErrStat, ErrMsg) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) + det = Determinant(Ainv,ErrStat, ErrMsg) + call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) + ! Inverse test + call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8_ReKi, .true., .true.) + deallocate(A ) + deallocate(Ainv) + deallocate(Aref) + + ! --- Inverse of a 3x6 matrix + allocate(A(3,6)) + allocate(Aref(6,3)) + A(1,:) = (/ 0, 1, 2, 0, 1, 2 /) + A(2,:) = (/ -1, 1, 2, -0, 0, 0 /) + A(3,:) = (/ -0, 0, 0, -1, 1, 2 /) + Aref(:,:) = transpose(reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /))) + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + call test_almost_equal('Inverse of 3x6 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) + deallocate(A ) + deallocate(Ainv) + deallocate(Aref) + + ! --- Inverse of a 6x3 matrix + allocate(A(6,3)) + allocate(Aref(3,6)) + A(:,1) = (/ 0, 1, 2, 0, 1, 2 /) + A(:,2) = (/ -1, 1, 2, -0, 0, 0 /) + A(:,3) = (/ -0, 0, 0, -1, 1, 2 /) + Aref(:,:) = reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /)) + call PseudoInverse(A, Ainv, ErrStat, ErrMsg) + call test_almost_equal('Inverse of 6x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) + end subroutine Test_Linalg + + !> Series of tests for integer lists + subroutine Test_lists(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat + character(ErrMsgLen), intent(out) :: ErrMsg + type(IList) :: L1 + type(IList) :: L2 + integer(IntKi) :: e + ErrStat = ErrID_None + ErrMsg = "" + testname='Lists' + + call init_list(L1, 0, 0 ,ErrStat, ErrMsg) + call init_list(L2, 10, 12,ErrStat, ErrMsg) + + ! test len + call test_equal('length',0 ,len(L1)) + call test_equal('length',10,len(L2)) + + ! test append + call append(L1, 5, ErrStat, ErrMsg) + call append(L1, 3, ErrStat, ErrMsg) + call append(L1, 1, ErrStat, ErrMsg) + call test_equal('appnd',L1%List, (/5,3,1/) , .true. , .false.) + + ! test get + call test_equal('get ',get(L1,2, ErrStat, ErrMsg), 3) + e = get(L1,0, ErrStat, ErrMsg) + call test_equal('get <0 ', ErrStat, ErrID_Fatal) + e = get(L1,7, ErrStat, ErrMsg) + call test_equal('get >n ', ErrStat, ErrID_Fatal) + + ! test sort + call sort(L1, ErrStat, ErrMsg) + call test_equal('sort ',L1%List, (/1,3,5/) , .true. , .false.) + + ! test reverse + call reverse(L1, ErrStat, ErrMsg) + call test_equal('rev ',L1%List, (/5,3,1/) , .true. , .false.) + + ! test pop + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 1) + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 3) + e = pop(L1, ErrStat, ErrMsg) + call test_equal('pop ',e , 5) + call destroy_list(L1, ErrStat, ErrMsg) + + ! test unique + call init_list(L1,(/5,3,2,3,8/),ErrStat, ErrMsg) + call unique(L1, ErrStat, ErrMsg) + call test_equal('uniq ',L1%List, (/5,3,2,8/) , .true. , .false.) + + call destroy_list(L1, ErrStat, ErrMsg) + call destroy_list(L2, ErrStat, ErrMsg) + end subroutine Test_lists + + subroutine SD_Tests(ErrStat,ErrMsg) + integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation + character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + + call Test_lists(ErrStat2, ErrMsg2) + call Test_Transformations(ErrStat2, ErrMsg2) + call Test_Linalg(ErrStat2, ErrMsg2) + end subroutine SD_Tests + + +end module SubDyn_Tests diff --git a/modules/subdyn/src_soildyn/SubDyn_Types.f90 b/modules/subdyn/src_soildyn/SubDyn_Types.f90 new file mode 100644 index 000000000..16bb630f3 --- /dev/null +++ b/modules/subdyn/src_soildyn/SubDyn_Types.f90 @@ -0,0 +1,11876 @@ +!STARTOFREGISTRYGENERATEDFILE 'SubDyn_Types.f90' +! +! WARNING This file is generated automatically by the FAST registry. +! Do not edit. Your changes to this file will be lost. +! +! FAST Registry +!********************************************************************************************************************************* +! SubDyn_Types +!................................................................................................................................. +! This file is part of SubDyn. +! +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +! +! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. +! +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in SubDyn. It also contains copy, destroy, pack, and +!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. +MODULE SubDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= IList ======= + TYPE, PUBLIC :: IList + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: List !< List of integers [-] + END TYPE IList +! ======================= +! ========= SD_InitInputType ======= + TYPE, PUBLIC :: SD_InitInputType + CHARACTER(1024) :: SDInputFile !< Name of the input file [-] + CHARACTER(1024) :: RootName !< SubDyn rootname [-] + REAL(ReKi) :: g !< Gravity acceleration [-] + REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] + REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] + REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SoilStiffness !< Soil stiffness matrices from SoilDyn ['(N/m,] + TYPE(MeshType) :: SoilMesh !< Mesh for soil stiffness locations [-] + END TYPE SD_InitInputType +! ======================= +! ========= SD_InitOutputType ======= + TYPE, PUBLIC :: SD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + END TYPE SD_InitOutputType +! ======================= +! ========= MeshAuxDataType ======= + TYPE, PUBLIC :: MeshAuxDataType + INTEGER(IntKi) :: MemberID !< Member ID for Output [-] + INTEGER(IntKi) :: NOutCnt !< Number of Nodes for the output member [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeCnt !< Node ordinal numbers for the output member [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIDs !< Node IDs associated with ordinal numbers for the output member [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmIDs !< Element IDs connected to each NodeIDs; max 10 elements [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmNds !< Flag to indicate 1st or 2nd node of element for each ElmIDs [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] + END TYPE MeshAuxDataType +! ======================= +! ========= CB_MatArrays ======= + TYPE, PUBLIC :: CB_MatArrays + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] + END TYPE CB_MatArrays +! ======================= +! ========= ElemPropType ======= + TYPE, PUBLIC :: ElemPropType + INTEGER(IntKi) :: eType !< Element Type [-] + REAL(ReKi) :: Length !< Length of an element [-] + REAL(ReKi) :: Ixx !< Moment of inertia of an element [-] + REAL(ReKi) :: Iyy !< Moment of inertia of an element [-] + REAL(ReKi) :: Jzz !< Moment of inertia of an element [-] + LOGICAL :: Shear !< Use timoshenko (true) E-B (false) [-] + REAL(ReKi) :: Kappa !< Shear coefficient [-] + REAL(ReKi) :: YoungE !< Young's modulus [-] + REAL(ReKi) :: ShearG !< Shear modulus [N/m^2] + REAL(ReKi) :: Area !< Area of an element [m^2] + REAL(ReKi) :: Rho !< Density [kg/m^3] + REAL(ReKi) :: T0 !< Pretension [N] + REAL(ReKi) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] + END TYPE ElemPropType +! ======================= +! ========= SD_InitType ======= + TYPE, PUBLIC :: SD_InitType + CHARACTER(1024) :: RootName !< SubDyn rootname [-] + REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] + REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + REAL(ReKi) :: g !< Gravity acceleration [-] + REAL(DbKi) :: DT !< Time step from Glue Code [seconds] + INTEGER(IntKi) :: NJoints !< Number of joints of the sub structure [-] + INTEGER(IntKi) :: NPropSetsX !< Number of extended property sets [-] + INTEGER(IntKi) :: NPropSetsB !< Number of property sets for beams [-] + INTEGER(IntKi) :: NPropSetsC !< Number of property sets for cables [-] + INTEGER(IntKi) :: NPropSetsR !< Number of property sets for rigid links [-] + INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] + INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] + INTEGER(IntKi) :: FEMMod !< FEM switch: element model in the FEM [-] + INTEGER(IntKi) :: NDiv !< Number of divisions for each member [-] + LOGICAL :: CBMod !< Perform C-B flag [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsB !< Property sets number and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsC !< Property ID and values for cables [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsR !< Property ID and values for rigid link [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsX !< Extended property sets [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] + LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] + LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Soil_K !< Soil stiffness (at passed at Init, not in input file) 6x6xn [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] + INTEGER(IntKi) :: NElem !< Total number of elements [-] + INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] + INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] + INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D !< System damping matrix [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and list of nodes making up a member (>2 if subdivided) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] + LOGICAL :: SSSum !< SubDyn Summary File Flag [-] + END TYPE SD_InitType +! ======================= +! ========= SD_ContinuousStateType ======= + TYPE, PUBLIC :: SD_ContinuousStateType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qm !< Virtual states, Nmod elements [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdot !< Derivative of states, Nmod elements [-] + END TYPE SD_ContinuousStateType +! ======================= +! ========= SD_DiscreteStateType ======= + TYPE, PUBLIC :: SD_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE SD_DiscreteStateType +! ======================= +! ========= SD_ConstraintStateType ======= + TYPE, PUBLIC :: SD_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE SD_ConstraintStateType +! ======================= +! ========= SD_OtherStateType ======= + TYPE, PUBLIC :: SD_OtherStateType + TYPE(SD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< previous state derivs for m-step time integrator [-] + INTEGER(IntKi) :: n !< tracks time step for which OtherState was updated last [-] + END TYPE SD_OtherStateType +! ======================= +! ========= SD_MiscVarType ======= + TYPE, PUBLIC :: SD_MiscVarType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdotdot !< 2nd Derivative of states, used only for output-file purposes [-] + REAL(ReKi) , DIMENSION(1:6) :: u_TP + REAL(ReKi) , DIMENSION(1:6) :: udot_TP + REAL(ReKi) , DIMENSION(1:6) :: udotdot_TP + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UFL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] + REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] + INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads on unconstrained DOFs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext_red !< External loads on constrained DOFs, Fext_red= T^t Fext [-] + END TYPE SD_MiscVarType +! ======================= +! ========= SD_ParameterType ======= + TYPE, PUBLIC :: SD_ParameterType + REAL(DbKi) :: SDDeltaT !< Time step (for integration of continuous states) [seconds] + INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] + INTEGER(IntKi) :: nDOF !< Total degree of freedom [-] + INTEGER(IntKi) :: nDOF_red !< Total degree of freedom after constraint reduction [-] + INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] + TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] + INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] + INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] + LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of u in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of u in Y1 [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Load Components in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiRb_TI !< Coefficient of u in Y2 (Phi_R bar * TI) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_63 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_64 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F2_61 !< Load Component in Y2 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_st_g !< Motion of internal DOFs due to static gravitational force, for static improvement [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KLLm1 !< KLL^{-1}, inverse of matrix KLL, for static solve only [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AM2Jac !< Jacobian (factored) for Adams-Boulton 2nd order Integration [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AM2JacPiv !< Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI !< Matrix to calculate TP reference point reaction at top of structure [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIreact !< Matrix to calculate single point reaction at base of structure [-] + INTEGER(IntKi) :: nNodes !< Total number of nodes [-] + INTEGER(IntKi) :: nNodes_I !< Number of Interface nodes [-] + INTEGER(IntKi) :: nNodes_L !< Number of Internal nodes [-] + INTEGER(IntKi) :: nNodes_C !< Number of joints with reactions [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_I !< Interface degree of freedoms [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_C !< React degree of freedoms [-] + INTEGER(IntKi) :: nDOFI__ !< Size of IDI__ [-] + INTEGER(IntKi) :: nDOFI_Rb !< Size of IDI_Rb [-] + INTEGER(IntKi) :: nDOFI_F !< Size of IDI_F [-] + INTEGER(IntKi) :: nDOFL_L !< Size of IDL_L [-] + INTEGER(IntKi) :: nDOFC__ !< Size of IDC__ [-] + INTEGER(IntKi) :: nDOFC_Rb !< Size of IDC_Rb [-] + INTEGER(IntKi) :: nDOFC_L !< Size of IDC_L [-] + INTEGER(IntKi) :: nDOFC_F !< Size of IDC_F [-] + INTEGER(IntKi) :: nDOFR__ !< Size of IDR__ [-] + INTEGER(IntKi) :: nDOF__Rb !< Size of ID__Rb [-] + INTEGER(IntKi) :: nDOF__L !< Size of ID__L [-] + INTEGER(IntKi) :: nDOF__F !< Size of ID__F [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI__ !< Index of all Interface DOFs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_Rb !< Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_F !< Index array of the interface (nodes connect to TP) dofs that are fixed DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL_L !< Index array of the internal dofs coming from internal nodes [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC__ !< Index of all bottom DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_Rb !< Index array of the contraint dofs that are retained/master/follower DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_L !< Index array of the contraint dofs that are follower/internal DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_F !< Index array of the contraint dofs that are fixd DOF [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR__ !< Index array of the interface and restraint dofs [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__Rb !< Index array of all the retained/leader/master dofs (from any nodes of the structure) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__L !< Index array of all the follower/internal dofs (from any nodes of the structure) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__F !< Index array of the DOF that are fixed (from any nodes of the structure) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] + INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] + INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] + INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] + INTEGER(IntKi) :: UnJckF !< Unit of SD ouput file [-] + CHARACTER(1) :: Delim !< Column delimiter for output text files [-] + CHARACTER(20) :: OutFmt !< Format for Output [-] + CHARACTER(20) :: OutSFmt !< Format for Output Headers [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst !< List of user requested members and nodes [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst2 !< List of all member joint nodes and elements for output [-] + TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst3 !< List of all member joint nodes and elements for output [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< An array holding names, units, and indices of all of the selected output channels. logical [-] + LOGICAL :: OutAll !< Flag to output or not all joint forces [-] + LOGICAL :: OutReact !< Flag to check whether reactions are requested [-] + INTEGER(IntKi) :: OutAllInt !< Integer version of OutAll [-] + INTEGER(IntKi) :: OutAllDims !< Integer version of OutAll [-] + INTEGER(IntKi) :: OutDec !< Output Decimation for Requested Channels [-] + END TYPE SD_ParameterType +! ======================= +! ========= SD_InputType ======= + TYPE, PUBLIC :: SD_InputType + TYPE(MeshType) :: TPMesh !< Transition piece inputs on a point mesh [-] + TYPE(MeshType) :: LMesh !< Point mesh for interior node inputs [-] + END TYPE SD_InputType +! ======================= +! ========= SD_OutputType ======= + TYPE, PUBLIC :: SD_OutputType + TYPE(MeshType) :: Y1Mesh !< Transition piece outputs on a point mesh [-] + TYPE(MeshType) :: Y2Mesh !< Interior+Interface nodes outputs on a point mesh [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file [-] + END TYPE SD_OutputType +! ======================= +CONTAINS + SUBROUTINE SD_CopyIList( SrcIListData, DstIListData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IList), INTENT(IN) :: SrcIListData + TYPE(IList), INTENT(INOUT) :: DstIListData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyIList' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcIListData%List)) THEN + i1_l = LBOUND(SrcIListData%List,1) + i1_u = UBOUND(SrcIListData%List,1) + IF (.NOT. ALLOCATED(DstIListData%List)) THEN + ALLOCATE(DstIListData%List(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIListData%List.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstIListData%List = SrcIListData%List +ENDIF + END SUBROUTINE SD_CopyIList + + SUBROUTINE SD_DestroyIList( IListData, ErrStat, ErrMsg ) + TYPE(IList), INTENT(INOUT) :: IListData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyIList' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(IListData%List)) THEN + DEALLOCATE(IListData%List) +ENDIF + END SUBROUTINE SD_DestroyIList + + SUBROUTINE SD_PackIList( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IList), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackIList' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! List allocated yes/no + IF ( ALLOCATED(InData%List) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! List upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%List) ! List + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%List) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%List,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%List,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%List)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%List))-1 ) = PACK(InData%List,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%List) + END IF + END SUBROUTINE SD_PackIList + + SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IList), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackIList' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! List not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%List)) DEALLOCATE(OutData%List) + ALLOCATE(OutData%List(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%List.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%List)>0) OutData%List = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%List))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%List) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackIList + + SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(INOUT) :: SrcInitInputData + TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%SDInputFile = SrcInitInputData%SDInputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%g = SrcInitInputData%g + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint + DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ +IF (ALLOCATED(SrcInitInputData%SoilStiffness)) THEN + i1_l = LBOUND(SrcInitInputData%SoilStiffness,1) + i1_u = UBOUND(SrcInitInputData%SoilStiffness,1) + i2_l = LBOUND(SrcInitInputData%SoilStiffness,2) + i2_u = UBOUND(SrcInitInputData%SoilStiffness,2) + i3_l = LBOUND(SrcInitInputData%SoilStiffness,3) + i3_u = UBOUND(SrcInitInputData%SoilStiffness,3) + IF (.NOT. ALLOCATED(DstInitInputData%SoilStiffness)) THEN + ALLOCATE(DstInitInputData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%SoilStiffness = SrcInitInputData%SoilStiffness +ENDIF + CALL MeshCopy( SrcInitInputData%SoilMesh, DstInitInputData%SoilMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SD_CopyInitInput + + SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%SoilStiffness)) THEN + DEALLOCATE(InitInputData%SoilStiffness) +ENDIF + CALL MeshDestroy( InitInputData%SoilMesh, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInitInput + + SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitInput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%SDInputFile) ! SDInputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! g + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint + Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Int_BufSz = Int_BufSz + 1 ! SoilStiffness allocated yes/no + IF ( ALLOCATED(InData%SoilStiffness) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SoilStiffness upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SoilStiffness) ! SoilStiffness + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SoilMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SoilMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SoilMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SoilMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%SDInputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SoilStiffness) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SoilStiffness)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SoilStiffness))-1 ) = PACK(InData%SoilStiffness,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SoilStiffness) + END IF + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE SD_PackInitInput + + SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%SDInputFile) + OutData%SDInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%g = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%TP_RefPoint,1) + i1_u = UBOUND(OutData%TP_RefPoint,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) + DEALLOCATE(mask1) + OutData%SubRotateZ = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SoilStiffness not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SoilStiffness)) DEALLOCATE(OutData%SoilStiffness) + ALLOCATE(OutData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%SoilStiffness)>0) OutData%SoilStiffness = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SoilStiffness))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SoilStiffness) + DEALLOCATE(mask3) + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE SD_UnPackInitInput + + SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SD_InitOutputType), INTENT(INOUT) :: DstInitOutputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr +ENDIF +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt +ENDIF + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SD_CopyInitOutput + + SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) +ENDIF +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) +ENDIF + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInitOutput + + SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_InitOutputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitOutput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Ver + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Ver + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Ver + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE SD_PackInitOutput + + SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_InitOutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitOutput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE SD_UnPackInitOutput + + SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(IN) :: SrcMeshAuxDataTypeData + TYPE(MeshAuxDataType), INTENT(INOUT) :: DstMeshAuxDataTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMeshAuxDataType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMeshAuxDataTypeData%MemberID = SrcMeshAuxDataTypeData%MemberID + DstMeshAuxDataTypeData%NOutCnt = SrcMeshAuxDataTypeData%NOutCnt +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeCnt)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeCnt)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeCnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%NodeCnt = SrcMeshAuxDataTypeData%NodeCnt +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%NodeIDs = SrcMeshAuxDataTypeData%NodeIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmIDs = SrcMeshAuxDataTypeData%ElmIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmNds)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmNds)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Me,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Me,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Me,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Me,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Me,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Me,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Me)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Me.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Me = SrcMeshAuxDataTypeData%Me +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Ke)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Ke,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Ke,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Ke,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Ke,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Ke,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Ke,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Ke,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Ke,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Ke)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Ke = SrcMeshAuxDataTypeData%Ke +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Fg)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Fg,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Fg,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Fg,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Fg,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Fg,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Fg,3) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Fg)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg +ENDIF + END SUBROUTINE SD_CopyMeshAuxDataType + + SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(INOUT) :: MeshAuxDataTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMeshAuxDataType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MeshAuxDataTypeData%NodeCnt)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeCnt) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%NodeIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmNds)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmNds) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Me)) THEN + DEALLOCATE(MeshAuxDataTypeData%Me) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Ke)) THEN + DEALLOCATE(MeshAuxDataTypeData%Ke) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Fg)) THEN + DEALLOCATE(MeshAuxDataTypeData%Fg) +ENDIF + END SUBROUTINE SD_DestroyMeshAuxDataType + + SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(MeshAuxDataType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMeshAuxDataType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NOutCnt + Int_BufSz = Int_BufSz + 1 ! NodeCnt allocated yes/no + IF ( ALLOCATED(InData%NodeCnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeCnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeCnt) ! NodeCnt + END IF + Int_BufSz = Int_BufSz + 1 ! NodeIDs allocated yes/no + IF ( ALLOCATED(InData%NodeIDs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeIDs) ! NodeIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmIDs allocated yes/no + IF ( ALLOCATED(InData%ElmIDs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmIDs) ! ElmIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmNds allocated yes/no + IF ( ALLOCATED(InData%ElmNds) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds + END IF + Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no + IF ( ALLOCATED(InData%Me) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Me) ! Me + END IF + Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no + IF ( ALLOCATED(InData%Ke) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Ke) ! Ke + END IF + Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no + IF ( ALLOCATED(InData%Fg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fg) ! Fg + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NOutCnt + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeCnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeCnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeCnt,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodeCnt)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeCnt))-1 ) = PACK(InData%NodeCnt,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodeCnt) + END IF + IF ( .NOT. ALLOCATED(InData%NodeIDs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIDs,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodeIDs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeIDs))-1 ) = PACK(InData%NodeIDs,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodeIDs) + END IF + IF ( .NOT. ALLOCATED(InData%ElmIDs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ElmIDs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmIDs))-1 ) = PACK(InData%ElmIDs,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ElmIDs) + END IF + IF ( .NOT. ALLOCATED(InData%ElmNds) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ElmNds)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmNds))-1 ) = PACK(InData%ElmNds,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ElmNds) + END IF + IF ( .NOT. ALLOCATED(InData%Me) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Me)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Me))-1 ) = PACK(InData%Me,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Me) + END IF + IF ( .NOT. ALLOCATED(InData%Ke) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Ke)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ke))-1 ) = PACK(InData%Ke,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Ke) + END IF + IF ( .NOT. ALLOCATED(InData%Fg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Fg)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fg))-1 ) = PACK(InData%Fg,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fg) + END IF + END SUBROUTINE SD_PackMeshAuxDataType + + SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(MeshAuxDataType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMeshAuxDataType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%MemberID = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NOutCnt = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeCnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeCnt)) DEALLOCATE(OutData%NodeCnt) + ALLOCATE(OutData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeCnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NodeCnt)>0) OutData%NodeCnt = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeCnt))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodeCnt) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIDs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIDs)) DEALLOCATE(OutData%NodeIDs) + ALLOCATE(OutData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NodeIDs)>0) OutData%NodeIDs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeIDs))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodeIDs) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmIDs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElmIDs)) DEALLOCATE(OutData%ElmIDs) + ALLOCATE(OutData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%ElmIDs)>0) OutData%ElmIDs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmIDs))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ElmIDs) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmNds not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElmNds)) DEALLOCATE(OutData%ElmNds) + ALLOCATE(OutData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%ElmNds)>0) OutData%ElmNds = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmNds))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ElmNds) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Me)) DEALLOCATE(OutData%Me) + ALLOCATE(OutData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Me.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask4(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask4.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask4 = .TRUE. + IF (SIZE(OutData%Me)>0) OutData%Me = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Me))-1 ), mask4, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Me) + DEALLOCATE(mask4) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Ke)) DEALLOCATE(OutData%Ke) + ALLOCATE(OutData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask4(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask4.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask4 = .TRUE. + IF (SIZE(OutData%Ke)>0) OutData%Ke = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ke))-1 ), mask4, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Ke) + DEALLOCATE(mask4) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fg)) DEALLOCATE(OutData%Fg) + ALLOCATE(OutData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%Fg)>0) OutData%Fg = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fg))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Fg) + DEALLOCATE(mask3) + END IF + END SUBROUTINE SD_UnPackMeshAuxDataType + + SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(IN) :: SrcCB_MatArraysData + TYPE(CB_MatArrays), INTENT(INOUT) :: DstCB_MatArraysData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyCB_MatArrays' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBB)) THEN + ALLOCATE(DstCB_MatArraysData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%MBB = SrcCB_MatArraysData%MBB +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%MBM)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBM,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBM,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBM,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBM,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBM)) THEN + ALLOCATE(DstCB_MatArraysData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%MBM = SrcCB_MatArraysData%MBM +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%KBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%KBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%KBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%KBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%KBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%KBB)) THEN + ALLOCATE(DstCB_MatArraysData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiL,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiL,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiL)) THEN + ALLOCATE(DstCB_MatArraysData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%PhiL = SrcCB_MatArraysData%PhiL +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%PhiR)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiR,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiR,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiR,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiR,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiR)) THEN + ALLOCATE(DstCB_MatArraysData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%PhiR = SrcCB_MatArraysData%PhiR +ENDIF +IF (ALLOCATED(SrcCB_MatArraysData%OmegaL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%OmegaL,1) + i1_u = UBOUND(SrcCB_MatArraysData%OmegaL,1) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%OmegaL)) THEN + ALLOCATE(DstCB_MatArraysData%OmegaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%OmegaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstCB_MatArraysData%OmegaL = SrcCB_MatArraysData%OmegaL +ENDIF + END SUBROUTINE SD_CopyCB_MatArrays + + SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(INOUT) :: CB_MatArraysData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyCB_MatArrays' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(CB_MatArraysData%MBB)) THEN + DEALLOCATE(CB_MatArraysData%MBB) +ENDIF +IF (ALLOCATED(CB_MatArraysData%MBM)) THEN + DEALLOCATE(CB_MatArraysData%MBM) +ENDIF +IF (ALLOCATED(CB_MatArraysData%KBB)) THEN + DEALLOCATE(CB_MatArraysData%KBB) +ENDIF +IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN + DEALLOCATE(CB_MatArraysData%PhiL) +ENDIF +IF (ALLOCATED(CB_MatArraysData%PhiR)) THEN + DEALLOCATE(CB_MatArraysData%PhiR) +ENDIF +IF (ALLOCATED(CB_MatArraysData%OmegaL)) THEN + DEALLOCATE(CB_MatArraysData%OmegaL) +ENDIF + END SUBROUTINE SD_DestroyCB_MatArrays + + SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(CB_MatArrays), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackCB_MatArrays' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no + IF ( ALLOCATED(InData%MBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB + END IF + Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no + IF ( ALLOCATED(InData%MBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM + END IF + Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no + IF ( ALLOCATED(InData%KBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB + END IF + Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no + IF ( ALLOCATED(InData%PhiL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiL) ! PhiL + END IF + Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no + IF ( ALLOCATED(InData%PhiR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiR) ! PhiR + END IF + Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no + IF ( ALLOCATED(InData%OmegaL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%OmegaL) ! OmegaL + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%MBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MBB) + END IF + IF ( .NOT. ALLOCATED(InData%MBM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MBM) + END IF + IF ( .NOT. ALLOCATED(InData%KBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%KBB) + END IF + IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiL))-1 ) = PACK(InData%PhiL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiL) + END IF + IF ( .NOT. ALLOCATED(InData%PhiR) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiR))-1 ) = PACK(InData%PhiR,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiR) + END IF + IF ( .NOT. ALLOCATED(InData%OmegaL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OmegaL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%OmegaL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%OmegaL))-1 ) = PACK(InData%OmegaL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%OmegaL) + END IF + END SUBROUTINE SD_PackCB_MatArrays + + SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(CB_MatArrays), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackCB_MatArrays' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) + ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MBB)>0) OutData%MBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) + ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MBM)>0) OutData%MBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MBM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) + ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%KBB)>0) OutData%KBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%KBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiL)) DEALLOCATE(OutData%PhiL) + ALLOCATE(OutData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiL)>0) OutData%PhiL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiL))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiL) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiR)) DEALLOCATE(OutData%PhiR) + ALLOCATE(OutData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiR)>0) OutData%PhiR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiR))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiR) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%OmegaL)) DEALLOCATE(OutData%OmegaL) + ALLOCATE(OutData%OmegaL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OmegaL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%OmegaL)>0) OutData%OmegaL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%OmegaL))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%OmegaL) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackCB_MatArrays + + SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData + TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyElemPropType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstElemPropTypeData%eType = SrcElemPropTypeData%eType + DstElemPropTypeData%Length = SrcElemPropTypeData%Length + DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx + DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy + DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz + DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear + DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa + DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE + DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG + DstElemPropTypeData%Area = SrcElemPropTypeData%Area + DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho + DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 + DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos + END SUBROUTINE SD_CopyElemPropType + + SUBROUTINE SD_DestroyElemPropType( ElemPropTypeData, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(INOUT) :: ElemPropTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyElemPropType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyElemPropType + + SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(ElemPropType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackElemPropType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! eType + Re_BufSz = Re_BufSz + 1 ! Length + Re_BufSz = Re_BufSz + 1 ! Ixx + Re_BufSz = Re_BufSz + 1 ! Iyy + Re_BufSz = Re_BufSz + 1 ! Jzz + Int_BufSz = Int_BufSz + 1 ! Shear + Re_BufSz = Re_BufSz + 1 ! Kappa + Re_BufSz = Re_BufSz + 1 ! YoungE + Re_BufSz = Re_BufSz + 1 ! ShearG + Re_BufSz = Re_BufSz + 1 ! Area + Re_BufSz = Re_BufSz + 1 ! Rho + Re_BufSz = Re_BufSz + 1 ! T0 + Re_BufSz = Re_BufSz + SIZE(InData%DirCos) ! DirCos + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%eType + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Length + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ixx + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Iyy + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Jzz + Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Shear , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Kappa + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%YoungE + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%ShearG + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Area + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Rho + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%T0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%DirCos) + END SUBROUTINE SD_PackElemPropType + + SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(ElemPropType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackElemPropType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%eType = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%Length = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Ixx = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Iyy = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Jzz = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Shear = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + OutData%Kappa = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%YoungE = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%ShearG = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Area = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%Rho = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%T0 = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%DirCos,1) + i1_u = UBOUND(OutData%DirCos,1) + i2_l = LBOUND(OutData%DirCos,2) + i2_u = UBOUND(OutData%DirCos,2) + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + OutData%DirCos = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DirCos))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%DirCos) + DEALLOCATE(mask2) + END SUBROUTINE SD_UnPackElemPropType + + SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT(IN) :: SrcInitTypeData + TYPE(SD_InitType), INTENT(INOUT) :: DstInitTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitTypeData%RootName = SrcInitTypeData%RootName + DstInitTypeData%TP_RefPoint = SrcInitTypeData%TP_RefPoint + DstInitTypeData%SubRotateZ = SrcInitTypeData%SubRotateZ + DstInitTypeData%g = SrcInitTypeData%g + DstInitTypeData%DT = SrcInitTypeData%DT + DstInitTypeData%NJoints = SrcInitTypeData%NJoints + DstInitTypeData%NPropSetsX = SrcInitTypeData%NPropSetsX + DstInitTypeData%NPropSetsB = SrcInitTypeData%NPropSetsB + DstInitTypeData%NPropSetsC = SrcInitTypeData%NPropSetsC + DstInitTypeData%NPropSetsR = SrcInitTypeData%NPropSetsR + DstInitTypeData%NCMass = SrcInitTypeData%NCMass + DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs + DstInitTypeData%FEMMod = SrcInitTypeData%FEMMod + DstInitTypeData%NDiv = SrcInitTypeData%NDiv + DstInitTypeData%CBMod = SrcInitTypeData%CBMod +IF (ALLOCATED(SrcInitTypeData%Joints)) THEN + i1_l = LBOUND(SrcInitTypeData%Joints,1) + i1_u = UBOUND(SrcInitTypeData%Joints,1) + i2_l = LBOUND(SrcInitTypeData%Joints,2) + i2_u = UBOUND(SrcInitTypeData%Joints,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Joints)) THEN + ALLOCATE(DstInitTypeData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Joints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Joints = SrcInitTypeData%Joints +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropSetsB)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsB,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsB,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsB,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsB,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsB)) THEN + ALLOCATE(DstInitTypeData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropSetsB = SrcInitTypeData%PropSetsB +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropSetsC)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsC,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsC,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsC,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsC,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsC)) THEN + ALLOCATE(DstInitTypeData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropSetsC = SrcInitTypeData%PropSetsC +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropSetsR)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsR,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsR,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsR,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsR,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsR)) THEN + ALLOCATE(DstInitTypeData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropSetsR = SrcInitTypeData%PropSetsR +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropSetsX)) THEN + i1_l = LBOUND(SrcInitTypeData%PropSetsX,1) + i1_u = UBOUND(SrcInitTypeData%PropSetsX,1) + i2_l = LBOUND(SrcInitTypeData%PropSetsX,2) + i2_u = UBOUND(SrcInitTypeData%PropSetsX,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsX)) THEN + ALLOCATE(DstInitTypeData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropSetsX = SrcInitTypeData%PropSetsX +ENDIF +IF (ALLOCATED(SrcInitTypeData%COSMs)) THEN + i1_l = LBOUND(SrcInitTypeData%COSMs,1) + i1_u = UBOUND(SrcInitTypeData%COSMs,1) + i2_l = LBOUND(SrcInitTypeData%COSMs,2) + i2_u = UBOUND(SrcInitTypeData%COSMs,2) + IF (.NOT. ALLOCATED(DstInitTypeData%COSMs)) THEN + ALLOCATE(DstInitTypeData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%COSMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%COSMs = SrcInitTypeData%COSMs +ENDIF +IF (ALLOCATED(SrcInitTypeData%CMass)) THEN + i1_l = LBOUND(SrcInitTypeData%CMass,1) + i1_u = UBOUND(SrcInitTypeData%CMass,1) + i2_l = LBOUND(SrcInitTypeData%CMass,2) + i2_u = UBOUND(SrcInitTypeData%CMass,2) + IF (.NOT. ALLOCATED(DstInitTypeData%CMass)) THEN + ALLOCATE(DstInitTypeData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%CMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%CMass = SrcInitTypeData%CMass +ENDIF +IF (ALLOCATED(SrcInitTypeData%JDampings)) THEN + i1_l = LBOUND(SrcInitTypeData%JDampings,1) + i1_u = UBOUND(SrcInitTypeData%JDampings,1) + IF (.NOT. ALLOCATED(DstInitTypeData%JDampings)) THEN + ALLOCATE(DstInitTypeData%JDampings(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%JDampings.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%JDampings = SrcInitTypeData%JDampings +ENDIF +IF (ALLOCATED(SrcInitTypeData%Members)) THEN + i1_l = LBOUND(SrcInitTypeData%Members,1) + i1_u = UBOUND(SrcInitTypeData%Members,1) + i2_l = LBOUND(SrcInitTypeData%Members,2) + i2_u = UBOUND(SrcInitTypeData%Members,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Members)) THEN + ALLOCATE(DstInitTypeData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Members.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Members = SrcInitTypeData%Members +ENDIF +IF (ALLOCATED(SrcInitTypeData%SSOutList)) THEN + i1_l = LBOUND(SrcInitTypeData%SSOutList,1) + i1_u = UBOUND(SrcInitTypeData%SSOutList,1) + IF (.NOT. ALLOCATED(DstInitTypeData%SSOutList)) THEN + ALLOCATE(DstInitTypeData%SSOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSOutList = SrcInitTypeData%SSOutList +ENDIF + DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM + DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim +IF (ALLOCATED(SrcInitTypeData%SSIK)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIK,1) + i1_u = UBOUND(SrcInitTypeData%SSIK,1) + i2_l = LBOUND(SrcInitTypeData%SSIK,2) + i2_u = UBOUND(SrcInitTypeData%SSIK,2) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIK)) THEN + ALLOCATE(DstInitTypeData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIK = SrcInitTypeData%SSIK +ENDIF +IF (ALLOCATED(SrcInitTypeData%SSIM)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIM,1) + i1_u = UBOUND(SrcInitTypeData%SSIM,1) + i2_l = LBOUND(SrcInitTypeData%SSIM,2) + i2_u = UBOUND(SrcInitTypeData%SSIM,2) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIM)) THEN + ALLOCATE(DstInitTypeData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIM = SrcInitTypeData%SSIM +ENDIF +IF (ALLOCATED(SrcInitTypeData%SSIfile)) THEN + i1_l = LBOUND(SrcInitTypeData%SSIfile,1) + i1_u = UBOUND(SrcInitTypeData%SSIfile,1) + IF (.NOT. ALLOCATED(DstInitTypeData%SSIfile)) THEN + ALLOCATE(DstInitTypeData%SSIfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%SSIfile = SrcInitTypeData%SSIfile +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_K)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_K,1) + i1_u = UBOUND(SrcInitTypeData%Soil_K,1) + i2_l = LBOUND(SrcInitTypeData%Soil_K,2) + i2_u = UBOUND(SrcInitTypeData%Soil_K,2) + i3_l = LBOUND(SrcInitTypeData%Soil_K,3) + i3_u = UBOUND(SrcInitTypeData%Soil_K,3) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_K)) THEN + ALLOCATE(DstInitTypeData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_K = SrcInitTypeData%Soil_K +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_Points)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_Points,1) + i1_u = UBOUND(SrcInitTypeData%Soil_Points,1) + i2_l = LBOUND(SrcInitTypeData%Soil_Points,2) + i2_u = UBOUND(SrcInitTypeData%Soil_Points,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Points)) THEN + ALLOCATE(DstInitTypeData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Points.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_Points = SrcInitTypeData%Soil_Points +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_Nodes)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_Nodes,1) + i1_u = UBOUND(SrcInitTypeData%Soil_Nodes,1) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Nodes)) THEN + ALLOCATE(DstInitTypeData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_Nodes = SrcInitTypeData%Soil_Nodes +ENDIF + DstInitTypeData%NElem = SrcInitTypeData%NElem + DstInitTypeData%NPropB = SrcInitTypeData%NPropB + DstInitTypeData%NPropC = SrcInitTypeData%NPropC + DstInitTypeData%NPropR = SrcInitTypeData%NPropR +IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN + i1_l = LBOUND(SrcInitTypeData%Nodes,1) + i1_u = UBOUND(SrcInitTypeData%Nodes,1) + i2_l = LBOUND(SrcInitTypeData%Nodes,2) + i2_u = UBOUND(SrcInitTypeData%Nodes,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Nodes)) THEN + ALLOCATE(DstInitTypeData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Nodes = SrcInitTypeData%Nodes +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropsB)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsB,1) + i1_u = UBOUND(SrcInitTypeData%PropsB,1) + i2_l = LBOUND(SrcInitTypeData%PropsB,2) + i2_u = UBOUND(SrcInitTypeData%PropsB,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsB)) THEN + ALLOCATE(DstInitTypeData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropsB = SrcInitTypeData%PropsB +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropsC)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsC,1) + i1_u = UBOUND(SrcInitTypeData%PropsC,1) + i2_l = LBOUND(SrcInitTypeData%PropsC,2) + i2_u = UBOUND(SrcInitTypeData%PropsC,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsC)) THEN + ALLOCATE(DstInitTypeData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropsC = SrcInitTypeData%PropsC +ENDIF +IF (ALLOCATED(SrcInitTypeData%PropsR)) THEN + i1_l = LBOUND(SrcInitTypeData%PropsR,1) + i1_u = UBOUND(SrcInitTypeData%PropsR,1) + i2_l = LBOUND(SrcInitTypeData%PropsR,2) + i2_u = UBOUND(SrcInitTypeData%PropsR,2) + IF (.NOT. ALLOCATED(DstInitTypeData%PropsR)) THEN + ALLOCATE(DstInitTypeData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%PropsR = SrcInitTypeData%PropsR +ENDIF +IF (ALLOCATED(SrcInitTypeData%K)) THEN + i1_l = LBOUND(SrcInitTypeData%K,1) + i1_u = UBOUND(SrcInitTypeData%K,1) + i2_l = LBOUND(SrcInitTypeData%K,2) + i2_u = UBOUND(SrcInitTypeData%K,2) + IF (.NOT. ALLOCATED(DstInitTypeData%K)) THEN + ALLOCATE(DstInitTypeData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%K = SrcInitTypeData%K +ENDIF +IF (ALLOCATED(SrcInitTypeData%M)) THEN + i1_l = LBOUND(SrcInitTypeData%M,1) + i1_u = UBOUND(SrcInitTypeData%M,1) + i2_l = LBOUND(SrcInitTypeData%M,2) + i2_u = UBOUND(SrcInitTypeData%M,2) + IF (.NOT. ALLOCATED(DstInitTypeData%M)) THEN + ALLOCATE(DstInitTypeData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%M = SrcInitTypeData%M +ENDIF +IF (ALLOCATED(SrcInitTypeData%D)) THEN + i1_l = LBOUND(SrcInitTypeData%D,1) + i1_u = UBOUND(SrcInitTypeData%D,1) + i2_l = LBOUND(SrcInitTypeData%D,2) + i2_u = UBOUND(SrcInitTypeData%D,2) + IF (.NOT. ALLOCATED(DstInitTypeData%D)) THEN + ALLOCATE(DstInitTypeData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%D = SrcInitTypeData%D +ENDIF +IF (ALLOCATED(SrcInitTypeData%F)) THEN + i1_l = LBOUND(SrcInitTypeData%F,1) + i1_u = UBOUND(SrcInitTypeData%F,1) + IF (.NOT. ALLOCATED(DstInitTypeData%F)) THEN + ALLOCATE(DstInitTypeData%F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%F = SrcInitTypeData%F +ENDIF +IF (ALLOCATED(SrcInitTypeData%FG)) THEN + i1_l = LBOUND(SrcInitTypeData%FG,1) + i1_u = UBOUND(SrcInitTypeData%FG,1) + IF (.NOT. ALLOCATED(DstInitTypeData%FG)) THEN + ALLOCATE(DstInitTypeData%FG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%FG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%FG = SrcInitTypeData%FG +ENDIF +IF (ALLOCATED(SrcInitTypeData%ElemProps)) THEN + i1_l = LBOUND(SrcInitTypeData%ElemProps,1) + i1_u = UBOUND(SrcInitTypeData%ElemProps,1) + i2_l = LBOUND(SrcInitTypeData%ElemProps,2) + i2_u = UBOUND(SrcInitTypeData%ElemProps,2) + IF (.NOT. ALLOCATED(DstInitTypeData%ElemProps)) THEN + ALLOCATE(DstInitTypeData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%ElemProps = SrcInitTypeData%ElemProps +ENDIF +IF (ALLOCATED(SrcInitTypeData%BCs)) THEN + i1_l = LBOUND(SrcInitTypeData%BCs,1) + i1_u = UBOUND(SrcInitTypeData%BCs,1) + i2_l = LBOUND(SrcInitTypeData%BCs,2) + i2_u = UBOUND(SrcInitTypeData%BCs,2) + IF (.NOT. ALLOCATED(DstInitTypeData%BCs)) THEN + ALLOCATE(DstInitTypeData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%BCs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%BCs = SrcInitTypeData%BCs +ENDIF +IF (ALLOCATED(SrcInitTypeData%IntFc)) THEN + i1_l = LBOUND(SrcInitTypeData%IntFc,1) + i1_u = UBOUND(SrcInitTypeData%IntFc,1) + i2_l = LBOUND(SrcInitTypeData%IntFc,2) + i2_u = UBOUND(SrcInitTypeData%IntFc,2) + IF (.NOT. ALLOCATED(DstInitTypeData%IntFc)) THEN + ALLOCATE(DstInitTypeData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%IntFc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%IntFc = SrcInitTypeData%IntFc +ENDIF +IF (ALLOCATED(SrcInitTypeData%MemberNodes)) THEN + i1_l = LBOUND(SrcInitTypeData%MemberNodes,1) + i1_u = UBOUND(SrcInitTypeData%MemberNodes,1) + i2_l = LBOUND(SrcInitTypeData%MemberNodes,2) + i2_u = UBOUND(SrcInitTypeData%MemberNodes,2) + IF (.NOT. ALLOCATED(DstInitTypeData%MemberNodes)) THEN + ALLOCATE(DstInitTypeData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%MemberNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%MemberNodes = SrcInitTypeData%MemberNodes +ENDIF +IF (ALLOCATED(SrcInitTypeData%NodesConnN)) THEN + i1_l = LBOUND(SrcInitTypeData%NodesConnN,1) + i1_u = UBOUND(SrcInitTypeData%NodesConnN,1) + i2_l = LBOUND(SrcInitTypeData%NodesConnN,2) + i2_u = UBOUND(SrcInitTypeData%NodesConnN,2) + IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnN)) THEN + ALLOCATE(DstInitTypeData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%NodesConnN = SrcInitTypeData%NodesConnN +ENDIF +IF (ALLOCATED(SrcInitTypeData%NodesConnE)) THEN + i1_l = LBOUND(SrcInitTypeData%NodesConnE,1) + i1_u = UBOUND(SrcInitTypeData%NodesConnE,1) + i2_l = LBOUND(SrcInitTypeData%NodesConnE,2) + i2_u = UBOUND(SrcInitTypeData%NodesConnE,2) + IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnE)) THEN + ALLOCATE(DstInitTypeData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%NodesConnE = SrcInitTypeData%NodesConnE +ENDIF + DstInitTypeData%SSSum = SrcInitTypeData%SSSum + END SUBROUTINE SD_CopyInitType + + SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) + TYPE(SD_InitType), INTENT(INOUT) :: InitTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitType' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitTypeData%Joints)) THEN + DEALLOCATE(InitTypeData%Joints) +ENDIF +IF (ALLOCATED(InitTypeData%PropSetsB)) THEN + DEALLOCATE(InitTypeData%PropSetsB) +ENDIF +IF (ALLOCATED(InitTypeData%PropSetsC)) THEN + DEALLOCATE(InitTypeData%PropSetsC) +ENDIF +IF (ALLOCATED(InitTypeData%PropSetsR)) THEN + DEALLOCATE(InitTypeData%PropSetsR) +ENDIF +IF (ALLOCATED(InitTypeData%PropSetsX)) THEN + DEALLOCATE(InitTypeData%PropSetsX) +ENDIF +IF (ALLOCATED(InitTypeData%COSMs)) THEN + DEALLOCATE(InitTypeData%COSMs) +ENDIF +IF (ALLOCATED(InitTypeData%CMass)) THEN + DEALLOCATE(InitTypeData%CMass) +ENDIF +IF (ALLOCATED(InitTypeData%JDampings)) THEN + DEALLOCATE(InitTypeData%JDampings) +ENDIF +IF (ALLOCATED(InitTypeData%Members)) THEN + DEALLOCATE(InitTypeData%Members) +ENDIF +IF (ALLOCATED(InitTypeData%SSOutList)) THEN + DEALLOCATE(InitTypeData%SSOutList) +ENDIF +IF (ALLOCATED(InitTypeData%SSIK)) THEN + DEALLOCATE(InitTypeData%SSIK) +ENDIF +IF (ALLOCATED(InitTypeData%SSIM)) THEN + DEALLOCATE(InitTypeData%SSIM) +ENDIF +IF (ALLOCATED(InitTypeData%SSIfile)) THEN + DEALLOCATE(InitTypeData%SSIfile) +ENDIF +IF (ALLOCATED(InitTypeData%Soil_K)) THEN + DEALLOCATE(InitTypeData%Soil_K) +ENDIF +IF (ALLOCATED(InitTypeData%Soil_Points)) THEN + DEALLOCATE(InitTypeData%Soil_Points) +ENDIF +IF (ALLOCATED(InitTypeData%Soil_Nodes)) THEN + DEALLOCATE(InitTypeData%Soil_Nodes) +ENDIF +IF (ALLOCATED(InitTypeData%Nodes)) THEN + DEALLOCATE(InitTypeData%Nodes) +ENDIF +IF (ALLOCATED(InitTypeData%PropsB)) THEN + DEALLOCATE(InitTypeData%PropsB) +ENDIF +IF (ALLOCATED(InitTypeData%PropsC)) THEN + DEALLOCATE(InitTypeData%PropsC) +ENDIF +IF (ALLOCATED(InitTypeData%PropsR)) THEN + DEALLOCATE(InitTypeData%PropsR) +ENDIF +IF (ALLOCATED(InitTypeData%K)) THEN + DEALLOCATE(InitTypeData%K) +ENDIF +IF (ALLOCATED(InitTypeData%M)) THEN + DEALLOCATE(InitTypeData%M) +ENDIF +IF (ALLOCATED(InitTypeData%D)) THEN + DEALLOCATE(InitTypeData%D) +ENDIF +IF (ALLOCATED(InitTypeData%F)) THEN + DEALLOCATE(InitTypeData%F) +ENDIF +IF (ALLOCATED(InitTypeData%FG)) THEN + DEALLOCATE(InitTypeData%FG) +ENDIF +IF (ALLOCATED(InitTypeData%ElemProps)) THEN + DEALLOCATE(InitTypeData%ElemProps) +ENDIF +IF (ALLOCATED(InitTypeData%BCs)) THEN + DEALLOCATE(InitTypeData%BCs) +ENDIF +IF (ALLOCATED(InitTypeData%IntFc)) THEN + DEALLOCATE(InitTypeData%IntFc) +ENDIF +IF (ALLOCATED(InitTypeData%MemberNodes)) THEN + DEALLOCATE(InitTypeData%MemberNodes) +ENDIF +IF (ALLOCATED(InitTypeData%NodesConnN)) THEN + DEALLOCATE(InitTypeData%NodesConnN) +ENDIF +IF (ALLOCATED(InitTypeData%NodesConnE)) THEN + DEALLOCATE(InitTypeData%NodesConnE) +ENDIF + END SUBROUTINE SD_DestroyInitType + + SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_InitType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint + Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Re_BufSz = Re_BufSz + 1 ! g + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NJoints + Int_BufSz = Int_BufSz + 1 ! NPropSetsX + Int_BufSz = Int_BufSz + 1 ! NPropSetsB + Int_BufSz = Int_BufSz + 1 ! NPropSetsC + Int_BufSz = Int_BufSz + 1 ! NPropSetsR + Int_BufSz = Int_BufSz + 1 ! NCMass + Int_BufSz = Int_BufSz + 1 ! NCOSMs + Int_BufSz = Int_BufSz + 1 ! FEMMod + Int_BufSz = Int_BufSz + 1 ! NDiv + Int_BufSz = Int_BufSz + 1 ! CBMod + Int_BufSz = Int_BufSz + 1 ! Joints allocated yes/no + IF ( ALLOCATED(InData%Joints) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Joints upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Joints) ! Joints + END IF + Int_BufSz = Int_BufSz + 1 ! PropSetsB allocated yes/no + IF ( ALLOCATED(InData%PropSetsB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsB) ! PropSetsB + END IF + Int_BufSz = Int_BufSz + 1 ! PropSetsC allocated yes/no + IF ( ALLOCATED(InData%PropSetsC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsC) ! PropSetsC + END IF + Int_BufSz = Int_BufSz + 1 ! PropSetsR allocated yes/no + IF ( ALLOCATED(InData%PropSetsR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsR) ! PropSetsR + END IF + Int_BufSz = Int_BufSz + 1 ! PropSetsX allocated yes/no + IF ( ALLOCATED(InData%PropSetsX) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropSetsX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropSetsX) ! PropSetsX + END IF + Int_BufSz = Int_BufSz + 1 ! COSMs allocated yes/no + IF ( ALLOCATED(InData%COSMs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! COSMs upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%COSMs) ! COSMs + END IF + Int_BufSz = Int_BufSz + 1 ! CMass allocated yes/no + IF ( ALLOCATED(InData%CMass) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMass upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMass) ! CMass + END IF + Int_BufSz = Int_BufSz + 1 ! JDampings allocated yes/no + IF ( ALLOCATED(InData%JDampings) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! JDampings upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%JDampings) ! JDampings + END IF + Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no + IF ( ALLOCATED(InData%Members) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Members upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Members) ! Members + END IF + Int_BufSz = Int_BufSz + 1 ! SSOutList allocated yes/no + IF ( ALLOCATED(InData%SSOutList) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SSOutList upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SSOutList)*LEN(InData%SSOutList) ! SSOutList + END IF + Int_BufSz = Int_BufSz + 1 ! OutCOSM + Int_BufSz = Int_BufSz + 1 ! TabDelim + Int_BufSz = Int_BufSz + 1 ! SSIK allocated yes/no + IF ( ALLOCATED(InData%SSIK) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SSIK upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SSIK) ! SSIK + END IF + Int_BufSz = Int_BufSz + 1 ! SSIM allocated yes/no + IF ( ALLOCATED(InData%SSIM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! SSIM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SSIM) ! SSIM + END IF + Int_BufSz = Int_BufSz + 1 ! SSIfile allocated yes/no + IF ( ALLOCATED(InData%SSIfile) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SSIfile upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%SSIfile)*LEN(InData%SSIfile) ! SSIfile + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_K allocated yes/no + IF ( ALLOCATED(InData%Soil_K) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Soil_K upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Soil_K) ! Soil_K + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_Points allocated yes/no + IF ( ALLOCATED(InData%Soil_Points) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Soil_Points upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Soil_Points) ! Soil_Points + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_Nodes allocated yes/no + IF ( ALLOCATED(InData%Soil_Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Soil_Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Soil_Nodes) ! Soil_Nodes + END IF + Int_BufSz = Int_BufSz + 1 ! NElem + Int_BufSz = Int_BufSz + 1 ! NPropB + Int_BufSz = Int_BufSz + 1 ! NPropC + Int_BufSz = Int_BufSz + 1 ! NPropR + Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no + IF ( ALLOCATED(InData%Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Nodes) ! Nodes + END IF + Int_BufSz = Int_BufSz + 1 ! PropsB allocated yes/no + IF ( ALLOCATED(InData%PropsB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsB) ! PropsB + END IF + Int_BufSz = Int_BufSz + 1 ! PropsC allocated yes/no + IF ( ALLOCATED(InData%PropsC) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsC upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsC) ! PropsC + END IF + Int_BufSz = Int_BufSz + 1 ! PropsR allocated yes/no + IF ( ALLOCATED(InData%PropsR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PropsR upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PropsR) ! PropsR + END IF + Int_BufSz = Int_BufSz + 1 ! K allocated yes/no + IF ( ALLOCATED(InData%K) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K) ! K + END IF + Int_BufSz = Int_BufSz + 1 ! M allocated yes/no + IF ( ALLOCATED(InData%M) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + END IF + Int_BufSz = Int_BufSz + 1 ! D allocated yes/no + IF ( ALLOCATED(InData%D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D) ! D + END IF + Int_BufSz = Int_BufSz + 1 ! F allocated yes/no + IF ( ALLOCATED(InData%F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + END IF + Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no + IF ( ALLOCATED(InData%FG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FG) ! FG + END IF + Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no + IF ( ALLOCATED(InData%ElemProps) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElemProps upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ElemProps) ! ElemProps + END IF + Int_BufSz = Int_BufSz + 1 ! BCs allocated yes/no + IF ( ALLOCATED(InData%BCs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! BCs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%BCs) ! BCs + END IF + Int_BufSz = Int_BufSz + 1 ! IntFc allocated yes/no + IF ( ALLOCATED(InData%IntFc) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! IntFc upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IntFc) ! IntFc + END IF + Int_BufSz = Int_BufSz + 1 ! MemberNodes allocated yes/no + IF ( ALLOCATED(InData%MemberNodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MemberNodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MemberNodes) ! MemberNodes + END IF + Int_BufSz = Int_BufSz + 1 ! NodesConnN allocated yes/no + IF ( ALLOCATED(InData%NodesConnN) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! NodesConnN upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodesConnN) ! NodesConnN + END IF + Int_BufSz = Int_BufSz + 1 ! NodesConnE allocated yes/no + IF ( ALLOCATED(InData%NodesConnE) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! NodesConnE upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodesConnE) ! NodesConnE + END IF + Int_BufSz = Int_BufSz + 1 ! SSSum + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g + Re_Xferred = Re_Xferred + 1 + DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsX + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsB + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsC + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsR + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCMass + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCOSMs + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%FEMMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NDiv + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%CBMod , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Joints) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Joints,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Joints,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Joints)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Joints))-1 ) = PACK(InData%Joints,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Joints) + END IF + IF ( .NOT. ALLOCATED(InData%PropSetsB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropSetsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsB))-1 ) = PACK(InData%PropSetsB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsB) + END IF + IF ( .NOT. ALLOCATED(InData%PropSetsC) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropSetsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsC))-1 ) = PACK(InData%PropSetsC,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsC) + END IF + IF ( .NOT. ALLOCATED(InData%PropSetsR) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropSetsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsR))-1 ) = PACK(InData%PropSetsR,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsR) + END IF + IF ( .NOT. ALLOCATED(InData%PropSetsX) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropSetsX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsX))-1 ) = PACK(InData%PropSetsX,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropSetsX) + END IF + IF ( .NOT. ALLOCATED(InData%COSMs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%COSMs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%COSMs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%COSMs)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%COSMs))-1 ) = PACK(InData%COSMs,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%COSMs) + END IF + IF ( .NOT. ALLOCATED(InData%CMass) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMass,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMass,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CMass)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMass))-1 ) = PACK(InData%CMass,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CMass) + END IF + IF ( .NOT. ALLOCATED(InData%JDampings) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%JDampings,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JDampings,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%JDampings)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%JDampings))-1 ) = PACK(InData%JDampings,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%JDampings) + END IF + IF ( .NOT. ALLOCATED(InData%Members) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Members)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Members))-1 ) = PACK(InData%Members,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Members) + END IF + IF ( .NOT. ALLOCATED(InData%SSOutList) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSOutList,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSOutList,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SSOutList,1), UBOUND(InData%SSOutList,1) + DO I = 1, LEN(InData%SSOutList) + IntKiBuf(Int_Xferred) = ICHAR(InData%SSOutList(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutCOSM , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SSIK) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SSIK)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SSIK) + END IF + IF ( .NOT. ALLOCATED(InData%SSIM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SSIM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SSIM) + END IF + IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIfile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIfile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%SSIfile,1), UBOUND(InData%SSIfile,1) + DO I = 1, LEN(InData%SSIfile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SSIfile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%Soil_K) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,3) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Soil_K)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Soil_K))-1 ) = PACK(InData%Soil_K,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Soil_K) + END IF + IF ( .NOT. ALLOCATED(InData%Soil_Points) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Soil_Points)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Soil_Points))-1 ) = PACK(InData%Soil_Points,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Soil_Points) + END IF + IF ( .NOT. ALLOCATED(InData%Soil_Nodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Nodes,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Soil_Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Soil_Nodes))-1 ) = PACK(InData%Soil_Nodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Soil_Nodes) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropC + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropR + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Nodes)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Nodes))-1 ) = PACK(InData%Nodes,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Nodes) + END IF + IF ( .NOT. ALLOCATED(InData%PropsB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsB))-1 ) = PACK(InData%PropsB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsB) + END IF + IF ( .NOT. ALLOCATED(InData%PropsC) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsC))-1 ) = PACK(InData%PropsC,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsC) + END IF + IF ( .NOT. ALLOCATED(InData%PropsR) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PropsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsR))-1 ) = PACK(InData%PropsR,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PropsR) + END IF + IF ( .NOT. ALLOCATED(InData%K) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%K)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%K))-1 ) = PACK(InData%K,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%K) + END IF + IF ( .NOT. ALLOCATED(InData%M) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%M,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%M) + END IF + IF ( .NOT. ALLOCATED(InData%D) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D))-1 ) = PACK(InData%D,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D) + END IF + IF ( .NOT. ALLOCATED(InData%F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%F)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F))-1 ) = PACK(InData%F,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F) + END IF + IF ( .NOT. ALLOCATED(InData%FG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FG))-1 ) = PACK(InData%FG,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FG) + END IF + IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ElemProps)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%ElemProps))-1 ) = PACK(InData%ElemProps,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%ElemProps) + END IF + IF ( .NOT. ALLOCATED(InData%BCs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%BCs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%BCs))-1 ) = PACK(InData%BCs,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%BCs) + END IF + IF ( .NOT. ALLOCATED(InData%IntFc) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IntFc)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IntFc))-1 ) = PACK(InData%IntFc,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IntFc) + END IF + IF ( .NOT. ALLOCATED(InData%MemberNodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberNodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberNodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MemberNodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%MemberNodes))-1 ) = PACK(InData%MemberNodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%MemberNodes) + END IF + IF ( .NOT. ALLOCATED(InData%NodesConnN) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnN,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnN,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodesConnN)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodesConnN))-1 ) = PACK(InData%NodesConnN,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodesConnN) + END IF + IF ( .NOT. ALLOCATED(InData%NodesConnE) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnE,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnE,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NodesConnE)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodesConnE))-1 ) = PACK(InData%NodesConnE,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%NodesConnE) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SSSum , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackInitType + + SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_InitType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + i1_l = LBOUND(OutData%TP_RefPoint,1) + i1_u = UBOUND(OutData%TP_RefPoint,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) + DEALLOCATE(mask1) + OutData%SubRotateZ = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%g = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + OutData%DT = DbKiBuf( Db_Xferred ) + Db_Xferred = Db_Xferred + 1 + OutData%NJoints = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsX = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsB = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsC = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsR = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NCMass = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NCOSMs = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%FEMMod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NDiv = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%CBMod = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Joints not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Joints)) DEALLOCATE(OutData%Joints) + ALLOCATE(OutData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Joints.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Joints)>0) OutData%Joints = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Joints))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Joints) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropSetsB)) DEALLOCATE(OutData%PropSetsB) + ALLOCATE(OutData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropSetsB)>0) OutData%PropSetsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsC not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropSetsC)) DEALLOCATE(OutData%PropSetsC) + ALLOCATE(OutData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropSetsC)>0) OutData%PropSetsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsC))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsC) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsR not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropSetsR)) DEALLOCATE(OutData%PropSetsR) + ALLOCATE(OutData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropSetsR)>0) OutData%PropSetsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsR))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsR) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsX not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropSetsX)) DEALLOCATE(OutData%PropSetsX) + ALLOCATE(OutData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropSetsX)>0) OutData%PropSetsX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsX))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsX) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%COSMs)) DEALLOCATE(OutData%COSMs) + ALLOCATE(OutData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%COSMs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%COSMs)>0) OutData%COSMs = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%COSMs))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%COSMs) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMass not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CMass)) DEALLOCATE(OutData%CMass) + ALLOCATE(OutData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMass.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CMass)>0) OutData%CMass = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMass))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CMass) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JDampings not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%JDampings)) DEALLOCATE(OutData%JDampings) + ALLOCATE(OutData%JDampings(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JDampings.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%JDampings)>0) OutData%JDampings = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%JDampings))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%JDampings) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Members)) DEALLOCATE(OutData%Members) + ALLOCATE(OutData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Members)>0) OutData%Members = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Members))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Members) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSOutList not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSOutList)) DEALLOCATE(OutData%SSOutList) + ALLOCATE(OutData%SSOutList(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSOutList.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%SSOutList,1), UBOUND(OutData%SSOutList,1) + DO I = 1, LEN(OutData%SSOutList) + OutData%SSOutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + OutData%OutCOSM = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIK not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIK)) DEALLOCATE(OutData%SSIK) + ALLOCATE(OutData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIK.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%SSIK)>0) OutData%SSIK = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SSIK) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIM)) DEALLOCATE(OutData%SSIM) + ALLOCATE(OutData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%SSIM)>0) OutData%SSIM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SSIM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SSIfile)) DEALLOCATE(OutData%SSIfile) + ALLOCATE(OutData%SSIfile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIfile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%SSIfile,1), UBOUND(OutData%SSIfile,1) + DO I = 1, LEN(OutData%SSIfile) + OutData%SSIfile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_K not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_K)) DEALLOCATE(OutData%Soil_K) + ALLOCATE(OutData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask3 = .TRUE. + IF (SIZE(OutData%Soil_K)>0) OutData%Soil_K = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Soil_K))-1 ), mask3, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Soil_K) + DEALLOCATE(mask3) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Points not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_Points)) DEALLOCATE(OutData%Soil_Points) + ALLOCATE(OutData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Points.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Soil_Points)>0) OutData%Soil_Points = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Soil_Points))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Soil_Points) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_Nodes)) DEALLOCATE(OutData%Soil_Nodes) + ALLOCATE(OutData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Soil_Nodes)>0) OutData%Soil_Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Soil_Nodes))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Soil_Nodes) + DEALLOCATE(mask1) + END IF + OutData%NElem = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropB = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropC = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NPropR = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes)) DEALLOCATE(OutData%Nodes) + ALLOCATE(OutData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Nodes)>0) OutData%Nodes = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Nodes))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Nodes) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropsB)) DEALLOCATE(OutData%PropsB) + ALLOCATE(OutData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropsB)>0) OutData%PropsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsC not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropsC)) DEALLOCATE(OutData%PropsC) + ALLOCATE(OutData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsC.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropsC)>0) OutData%PropsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsC))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsC) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsR not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PropsR)) DEALLOCATE(OutData%PropsR) + ALLOCATE(OutData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsR.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PropsR)>0) OutData%PropsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsR))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PropsR) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%K)) DEALLOCATE(OutData%K) + ALLOCATE(OutData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%K)>0) OutData%K = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%K))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%K) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%M)) DEALLOCATE(OutData%M) + ALLOCATE(OutData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%M)>0) OutData%M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%M))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%M) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D)) DEALLOCATE(OutData%D) + ALLOCATE(OutData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D)>0) OutData%D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F)) DEALLOCATE(OutData%F) + ALLOCATE(OutData%F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%F)>0) OutData%F = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FG)) DEALLOCATE(OutData%FG) + ALLOCATE(OutData%FG(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FG)>0) OutData%FG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FG))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FG) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) + ALLOCATE(OutData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%ElemProps)>0) OutData%ElemProps = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%ElemProps))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%ElemProps) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BCs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%BCs)) DEALLOCATE(OutData%BCs) + ALLOCATE(OutData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BCs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%BCs)>0) OutData%BCs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%BCs))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%BCs) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IntFc not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IntFc)) DEALLOCATE(OutData%IntFc) + ALLOCATE(OutData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IntFc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%IntFc)>0) OutData%IntFc = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IntFc))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IntFc) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberNodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MemberNodes)) DEALLOCATE(OutData%MemberNodes) + ALLOCATE(OutData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MemberNodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MemberNodes)>0) OutData%MemberNodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%MemberNodes))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%MemberNodes) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnN not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesConnN)) DEALLOCATE(OutData%NodesConnN) + ALLOCATE(OutData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnN.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%NodesConnN)>0) OutData%NodesConnN = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodesConnN))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodesConnN) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnE not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesConnE)) DEALLOCATE(OutData%NodesConnE) + ALLOCATE(OutData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnE.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%NodesConnE)>0) OutData%NodesConnE = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodesConnE))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%NodesConnE) + DEALLOCATE(mask2) + END IF + OutData%SSSum = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackInitType + + SUBROUTINE SD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: DstContStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcContStateData%qm)) THEN + i1_l = LBOUND(SrcContStateData%qm,1) + i1_u = UBOUND(SrcContStateData%qm,1) + IF (.NOT. ALLOCATED(DstContStateData%qm)) THEN + ALLOCATE(DstContStateData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qm = SrcContStateData%qm +ENDIF +IF (ALLOCATED(SrcContStateData%qmdot)) THEN + i1_l = LBOUND(SrcContStateData%qmdot,1) + i1_u = UBOUND(SrcContStateData%qmdot,1) + IF (.NOT. ALLOCATED(DstContStateData%qmdot)) THEN + ALLOCATE(DstContStateData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstContStateData%qmdot = SrcContStateData%qmdot +ENDIF + END SUBROUTINE SD_CopyContState + + SUBROUTINE SD_DestroyContState( ContStateData, ErrStat, ErrMsg ) + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyContState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ContStateData%qm)) THEN + DEALLOCATE(ContStateData%qm) +ENDIF +IF (ALLOCATED(ContStateData%qmdot)) THEN + DEALLOCATE(ContStateData%qmdot) +ENDIF + END SUBROUTINE SD_DestroyContState + + SUBROUTINE SD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_ContinuousStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackContState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! qm allocated yes/no + IF ( ALLOCATED(InData%qm) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qm upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qm) ! qm + END IF + Int_BufSz = Int_BufSz + 1 ! qmdot allocated yes/no + IF ( ALLOCATED(InData%qmdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qmdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qmdot) ! qmdot + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%qm) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%qm,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qm,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%qm)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qm))-1 ) = PACK(InData%qm,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%qm) + END IF + IF ( .NOT. ALLOCATED(InData%qmdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%qmdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%qmdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qmdot))-1 ) = PACK(InData%qmdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%qmdot) + END IF + END SUBROUTINE SD_PackContState + + SUBROUTINE SD_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackContState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qm not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%qm)) DEALLOCATE(OutData%qm) + ALLOCATE(OutData%qm(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qm.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%qm)>0) OutData%qm = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qm))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%qm) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%qmdot)) DEALLOCATE(OutData%qmdot) + ALLOCATE(OutData%qmdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%qmdot)>0) OutData%qmdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qmdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%qmdot) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackContState + + SUBROUTINE SD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE SD_CopyDiscState + + SUBROUTINE SD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyDiscState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyDiscState + + SUBROUTINE SD_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_DiscreteStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackDiscState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyDiscState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DummyDiscState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_PackDiscState + + SUBROUTINE SD_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_DiscreteStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackDiscState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyDiscState = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_UnPackDiscState + + SUBROUTINE SD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE SD_CopyConstrState + + SUBROUTINE SD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyConstrState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE SD_DestroyConstrState + + SUBROUTINE SD_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_ConstraintStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackConstrState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyConstrState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DummyConstrState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_PackConstrState + + SUBROUTINE SD_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_ConstraintStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackConstrState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyConstrState = ReKiBuf( Re_Xferred ) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE SD_UnPackConstrState + + SUBROUTINE SD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(SD_OtherStateType), INTENT(INOUT) :: DstOtherStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcOtherStateData%xdot)) THEN + i1_l = LBOUND(SrcOtherStateData%xdot,1) + i1_u = UBOUND(SrcOtherStateData%xdot,1) + IF (.NOT. ALLOCATED(DstOtherStateData%xdot)) THEN + ALLOCATE(DstOtherStateData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) + CALL SD_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstOtherStateData%n = SrcOtherStateData%n + END SUBROUTINE SD_CopyOtherState + + SUBROUTINE SD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOtherState' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(OtherStateData%xdot)) THEN +DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) + CALL SD_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(OtherStateData%xdot) +ENDIF + END SUBROUTINE SD_DestroyOtherState + + SUBROUTINE SD_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_OtherStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackOtherState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! xdot allocated yes/no + IF ( ALLOCATED(InData%xdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! xdot upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! xdot + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! xdot + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! xdot + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! n + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%xdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%xdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) + CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%n + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackOtherState + + SUBROUTINE SD_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_OtherStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackOtherState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%xdot)) DEALLOCATE(OutData%xdot) + ALLOCATE(OutData%xdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + OutData%n = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackOtherState + + SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(SD_MiscVarType), INTENT(INOUT) :: DstMiscData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcMiscData%qmdotdot)) THEN + i1_l = LBOUND(SrcMiscData%qmdotdot,1) + i1_u = UBOUND(SrcMiscData%qmdotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%qmdotdot)) THEN + ALLOCATE(DstMiscData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%qmdotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%qmdotdot = SrcMiscData%qmdotdot +ENDIF + DstMiscData%u_TP = SrcMiscData%u_TP + DstMiscData%udot_TP = SrcMiscData%udot_TP + DstMiscData%udotdot_TP = SrcMiscData%udotdot_TP +IF (ALLOCATED(SrcMiscData%UFL)) THEN + i1_l = LBOUND(SrcMiscData%UFL,1) + i1_u = UBOUND(SrcMiscData%UFL,1) + IF (.NOT. ALLOCATED(DstMiscData%UFL)) THEN + ALLOCATE(DstMiscData%UFL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UFL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UFL = SrcMiscData%UFL +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar,1) + i1_u = UBOUND(SrcMiscData%UR_bar,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar)) THEN + ALLOCATE(DstMiscData%UR_bar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar = SrcMiscData%UR_bar +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar_dot)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar_dot,1) + i1_u = UBOUND(SrcMiscData%UR_bar_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dot)) THEN + ALLOCATE(DstMiscData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar_dot = SrcMiscData%UR_bar_dot +ENDIF +IF (ALLOCATED(SrcMiscData%UR_bar_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%UR_bar_dotdot,1) + i1_u = UBOUND(SrcMiscData%UR_bar_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dotdot)) THEN + ALLOCATE(DstMiscData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UR_bar_dotdot = SrcMiscData%UR_bar_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%UL)) THEN + i1_l = LBOUND(SrcMiscData%UL,1) + i1_u = UBOUND(SrcMiscData%UL,1) + IF (.NOT. ALLOCATED(DstMiscData%UL)) THEN + ALLOCATE(DstMiscData%UL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL = SrcMiscData%UL +ENDIF +IF (ALLOCATED(SrcMiscData%UL_dot)) THEN + i1_l = LBOUND(SrcMiscData%UL_dot,1) + i1_u = UBOUND(SrcMiscData%UL_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%UL_dot)) THEN + ALLOCATE(DstMiscData%UL_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL_dot = SrcMiscData%UL_dot +ENDIF +IF (ALLOCATED(SrcMiscData%UL_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%UL_dotdot,1) + i1_u = UBOUND(SrcMiscData%UL_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%UL_dotdot)) THEN + ALLOCATE(DstMiscData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%UL_dotdot = SrcMiscData%UL_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%U_full)) THEN + i1_l = LBOUND(SrcMiscData%U_full,1) + i1_u = UBOUND(SrcMiscData%U_full,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full)) THEN + ALLOCATE(DstMiscData%U_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full = SrcMiscData%U_full +ENDIF +IF (ALLOCATED(SrcMiscData%U_full_dot)) THEN + i1_l = LBOUND(SrcMiscData%U_full_dot,1) + i1_u = UBOUND(SrcMiscData%U_full_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_dot)) THEN + ALLOCATE(DstMiscData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_dot = SrcMiscData%U_full_dot +ENDIF +IF (ALLOCATED(SrcMiscData%U_full_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%U_full_dotdot,1) + i1_u = UBOUND(SrcMiscData%U_full_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_dotdot)) THEN + ALLOCATE(DstMiscData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_dotdot = SrcMiscData%U_full_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%U_red)) THEN + i1_l = LBOUND(SrcMiscData%U_red,1) + i1_u = UBOUND(SrcMiscData%U_red,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red)) THEN + ALLOCATE(DstMiscData%U_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red = SrcMiscData%U_red +ENDIF +IF (ALLOCATED(SrcMiscData%U_red_dot)) THEN + i1_l = LBOUND(SrcMiscData%U_red_dot,1) + i1_u = UBOUND(SrcMiscData%U_red_dot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red_dot)) THEN + ALLOCATE(DstMiscData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red_dot = SrcMiscData%U_red_dot +ENDIF +IF (ALLOCATED(SrcMiscData%U_red_dotdot)) THEN + i1_l = LBOUND(SrcMiscData%U_red_dotdot,1) + i1_u = UBOUND(SrcMiscData%U_red_dotdot,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red_dotdot)) THEN + ALLOCATE(DstMiscData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot +ENDIF +IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN + i1_l = LBOUND(SrcMiscData%SDWrOutput,1) + i1_u = UBOUND(SrcMiscData%SDWrOutput,1) + IF (.NOT. ALLOCATED(DstMiscData%SDWrOutput)) THEN + ALLOCATE(DstMiscData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%SDWrOutput = SrcMiscData%SDWrOutput +ENDIF + DstMiscData%LastOutTime = SrcMiscData%LastOutTime + DstMiscData%Decimat = SrcMiscData%Decimat +IF (ALLOCATED(SrcMiscData%Fext)) THEN + i1_l = LBOUND(SrcMiscData%Fext,1) + i1_u = UBOUND(SrcMiscData%Fext,1) + IF (.NOT. ALLOCATED(DstMiscData%Fext)) THEN + ALLOCATE(DstMiscData%Fext(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Fext = SrcMiscData%Fext +ENDIF +IF (ALLOCATED(SrcMiscData%Fext_red)) THEN + i1_l = LBOUND(SrcMiscData%Fext_red,1) + i1_u = UBOUND(SrcMiscData%Fext_red,1) + IF (.NOT. ALLOCATED(DstMiscData%Fext_red)) THEN + ALLOCATE(DstMiscData%Fext_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%Fext_red = SrcMiscData%Fext_red +ENDIF + END SUBROUTINE SD_CopyMisc + + SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) + TYPE(SD_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMisc' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(MiscData%qmdotdot)) THEN + DEALLOCATE(MiscData%qmdotdot) +ENDIF +IF (ALLOCATED(MiscData%UFL)) THEN + DEALLOCATE(MiscData%UFL) +ENDIF +IF (ALLOCATED(MiscData%UR_bar)) THEN + DEALLOCATE(MiscData%UR_bar) +ENDIF +IF (ALLOCATED(MiscData%UR_bar_dot)) THEN + DEALLOCATE(MiscData%UR_bar_dot) +ENDIF +IF (ALLOCATED(MiscData%UR_bar_dotdot)) THEN + DEALLOCATE(MiscData%UR_bar_dotdot) +ENDIF +IF (ALLOCATED(MiscData%UL)) THEN + DEALLOCATE(MiscData%UL) +ENDIF +IF (ALLOCATED(MiscData%UL_dot)) THEN + DEALLOCATE(MiscData%UL_dot) +ENDIF +IF (ALLOCATED(MiscData%UL_dotdot)) THEN + DEALLOCATE(MiscData%UL_dotdot) +ENDIF +IF (ALLOCATED(MiscData%U_full)) THEN + DEALLOCATE(MiscData%U_full) +ENDIF +IF (ALLOCATED(MiscData%U_full_dot)) THEN + DEALLOCATE(MiscData%U_full_dot) +ENDIF +IF (ALLOCATED(MiscData%U_full_dotdot)) THEN + DEALLOCATE(MiscData%U_full_dotdot) +ENDIF +IF (ALLOCATED(MiscData%U_red)) THEN + DEALLOCATE(MiscData%U_red) +ENDIF +IF (ALLOCATED(MiscData%U_red_dot)) THEN + DEALLOCATE(MiscData%U_red_dot) +ENDIF +IF (ALLOCATED(MiscData%U_red_dotdot)) THEN + DEALLOCATE(MiscData%U_red_dotdot) +ENDIF +IF (ALLOCATED(MiscData%SDWrOutput)) THEN + DEALLOCATE(MiscData%SDWrOutput) +ENDIF +IF (ALLOCATED(MiscData%Fext)) THEN + DEALLOCATE(MiscData%Fext) +ENDIF +IF (ALLOCATED(MiscData%Fext_red)) THEN + DEALLOCATE(MiscData%Fext_red) +ENDIF + END SUBROUTINE SD_DestroyMisc + + SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_MiscVarType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMisc' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! qmdotdot allocated yes/no + IF ( ALLOCATED(InData%qmdotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! qmdotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%qmdotdot) ! qmdotdot + END IF + Re_BufSz = Re_BufSz + SIZE(InData%u_TP) ! u_TP + Re_BufSz = Re_BufSz + SIZE(InData%udot_TP) ! udot_TP + Re_BufSz = Re_BufSz + SIZE(InData%udotdot_TP) ! udotdot_TP + Int_BufSz = Int_BufSz + 1 ! UFL allocated yes/no + IF ( ALLOCATED(InData%UFL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UFL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UFL) ! UFL + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar allocated yes/no + IF ( ALLOCATED(InData%UR_bar) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar) ! UR_bar + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar_dot allocated yes/no + IF ( ALLOCATED(InData%UR_bar_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dot) ! UR_bar_dot + END IF + Int_BufSz = Int_BufSz + 1 ! UR_bar_dotdot allocated yes/no + IF ( ALLOCATED(InData%UR_bar_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dotdot) ! UR_bar_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! UL allocated yes/no + IF ( ALLOCATED(InData%UL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL) ! UL + END IF + Int_BufSz = Int_BufSz + 1 ! UL_dot allocated yes/no + IF ( ALLOCATED(InData%UL_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_dot) ! UL_dot + END IF + Int_BufSz = Int_BufSz + 1 ! UL_dotdot allocated yes/no + IF ( ALLOCATED(InData%UL_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_dotdot) ! UL_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! U_full allocated yes/no + IF ( ALLOCATED(InData%U_full) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full) ! U_full + END IF + Int_BufSz = Int_BufSz + 1 ! U_full_dot allocated yes/no + IF ( ALLOCATED(InData%U_full_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_dot) ! U_full_dot + END IF + Int_BufSz = Int_BufSz + 1 ! U_full_dotdot allocated yes/no + IF ( ALLOCATED(InData%U_full_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_dotdot) ! U_full_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! U_red allocated yes/no + IF ( ALLOCATED(InData%U_red) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red) ! U_red + END IF + Int_BufSz = Int_BufSz + 1 ! U_red_dot allocated yes/no + IF ( ALLOCATED(InData%U_red_dot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red_dot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red_dot) ! U_red_dot + END IF + Int_BufSz = Int_BufSz + 1 ! U_red_dotdot allocated yes/no + IF ( ALLOCATED(InData%U_red_dotdot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot + END IF + Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no + IF ( ALLOCATED(InData%SDWrOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! SDWrOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SDWrOutput) ! SDWrOutput + END IF + Db_BufSz = Db_BufSz + 1 ! LastOutTime + Int_BufSz = Int_BufSz + 1 ! Decimat + Int_BufSz = Int_BufSz + 1 ! Fext allocated yes/no + IF ( ALLOCATED(InData%Fext) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fext upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fext) ! Fext + END IF + Int_BufSz = Int_BufSz + 1 ! Fext_red allocated yes/no + IF ( ALLOCATED(InData%Fext_red) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Fext_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Fext_red) ! Fext_red + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%qmdotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%qmdotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%qmdotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qmdotdot))-1 ) = PACK(InData%qmdotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%qmdotdot) + END IF + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%u_TP))-1 ) = PACK(InData%u_TP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%u_TP) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%udot_TP))-1 ) = PACK(InData%udot_TP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%udot_TP) + ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%udotdot_TP))-1 ) = PACK(InData%udotdot_TP,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%udotdot_TP) + IF ( .NOT. ALLOCATED(InData%UFL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UFL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UFL,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UFL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UFL))-1 ) = PACK(InData%UFL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UFL) + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UR_bar)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar))-1 ) = PACK(InData%UR_bar,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UR_bar) + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UR_bar_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar_dot))-1 ) = PACK(InData%UR_bar_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UR_bar_dot) + END IF + IF ( .NOT. ALLOCATED(InData%UR_bar_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UR_bar_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar_dotdot))-1 ) = PACK(InData%UR_bar_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UR_bar_dotdot) + END IF + IF ( .NOT. ALLOCATED(InData%UL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL))-1 ) = PACK(InData%UL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UL) + END IF + IF ( .NOT. ALLOCATED(InData%UL_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UL_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_dot))-1 ) = PACK(InData%UL_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UL_dot) + END IF + IF ( .NOT. ALLOCATED(InData%UL_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UL_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_dotdot))-1 ) = PACK(InData%UL_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UL_dotdot) + END IF + IF ( .NOT. ALLOCATED(InData%U_full) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full))-1 ) = PACK(InData%U_full,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full) + END IF + IF ( .NOT. ALLOCATED(InData%U_full_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dot))-1 ) = PACK(InData%U_full_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full_dot) + END IF + IF ( .NOT. ALLOCATED(InData%U_full_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_full_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dotdot))-1 ) = PACK(InData%U_full_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_full_dotdot) + END IF + IF ( .NOT. ALLOCATED(InData%U_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red))-1 ) = PACK(InData%U_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red) + END IF + IF ( .NOT. ALLOCATED(InData%U_red_dot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dot))-1 ) = PACK(InData%U_red_dot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red_dot) + END IF + IF ( .NOT. ALLOCATED(InData%U_red_dotdot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dotdot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dotdot,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%U_red_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dotdot))-1 ) = PACK(InData%U_red_dotdot,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%U_red_dotdot) + END IF + IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SDWrOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SDWrOutput,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%SDWrOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SDWrOutput))-1 ) = PACK(InData%SDWrOutput,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%SDWrOutput) + END IF + DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%LastOutTime + Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Fext) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext) + END IF + IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) + END IF + END SUBROUTINE SD_PackMisc + + SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_MiscVarType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMisc' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%qmdotdot)) DEALLOCATE(OutData%qmdotdot) + ALLOCATE(OutData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%qmdotdot)>0) OutData%qmdotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qmdotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%qmdotdot) + DEALLOCATE(mask1) + END IF + i1_l = LBOUND(OutData%u_TP,1) + i1_u = UBOUND(OutData%u_TP,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%u_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%u_TP))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%u_TP) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%udot_TP,1) + i1_u = UBOUND(OutData%udot_TP,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%udot_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%udot_TP))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%udot_TP) + DEALLOCATE(mask1) + i1_l = LBOUND(OutData%udotdot_TP,1) + i1_u = UBOUND(OutData%udotdot_TP,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%udotdot_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%udotdot_TP))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%udotdot_TP) + DEALLOCATE(mask1) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UFL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UFL)) DEALLOCATE(OutData%UFL) + ALLOCATE(OutData%UFL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UFL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UFL)>0) OutData%UFL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UFL))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UFL) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UR_bar)) DEALLOCATE(OutData%UR_bar) + ALLOCATE(OutData%UR_bar(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UR_bar)>0) OutData%UR_bar = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UR_bar_dot)) DEALLOCATE(OutData%UR_bar_dot) + ALLOCATE(OutData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UR_bar_dot)>0) OutData%UR_bar_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UR_bar_dotdot)) DEALLOCATE(OutData%UR_bar_dotdot) + ALLOCATE(OutData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UR_bar_dotdot)>0) OutData%UR_bar_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar_dotdot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UL)) DEALLOCATE(OutData%UL) + ALLOCATE(OutData%UL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UL)>0) OutData%UL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UL) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UL_dot)) DEALLOCATE(OutData%UL_dot) + ALLOCATE(OutData%UL_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UL_dot)>0) OutData%UL_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UL_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UL_dotdot)) DEALLOCATE(OutData%UL_dotdot) + ALLOCATE(OutData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UL_dotdot)>0) OutData%UL_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UL_dotdot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full)) DEALLOCATE(OutData%U_full) + ALLOCATE(OutData%U_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full)>0) OutData%U_full = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_dot)) DEALLOCATE(OutData%U_full_dot) + ALLOCATE(OutData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full_dot)>0) OutData%U_full_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_dotdot)) DEALLOCATE(OutData%U_full_dotdot) + ALLOCATE(OutData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_full_dotdot)>0) OutData%U_full_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dotdot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red)) DEALLOCATE(OutData%U_red) + ALLOCATE(OutData%U_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red)>0) OutData%U_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red_dot)) DEALLOCATE(OutData%U_red_dot) + ALLOCATE(OutData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red_dot)>0) OutData%U_red_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dotdot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red_dotdot)) DEALLOCATE(OutData%U_red_dotdot) + ALLOCATE(OutData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%U_red_dotdot)>0) OutData%U_red_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dotdot))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dotdot) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SDWrOutput)) DEALLOCATE(OutData%SDWrOutput) + ALLOCATE(OutData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%SDWrOutput)>0) OutData%SDWrOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SDWrOutput))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%SDWrOutput) + DEALLOCATE(mask1) + END IF + OutData%LastOutTime = DbKiBuf( Db_Xferred ) + Db_Xferred = Db_Xferred + 1 + OutData%Decimat = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fext)) DEALLOCATE(OutData%Fext) + ALLOCATE(OutData%Fext(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Fext)>0) OutData%Fext = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Fext) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fext_red)) DEALLOCATE(OutData%Fext_red) + ALLOCATE(OutData%Fext_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%Fext_red)>0) OutData%Fext_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext_red))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%Fext_red) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackMisc + + SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_ParameterType), INTENT(IN) :: SrcParamData + TYPE(SD_ParameterType), INTENT(INOUT) :: DstParamData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyParam' +! + ErrStat = ErrID_None + ErrMsg = "" + DstParamData%SDDeltaT = SrcParamData%SDDeltaT + DstParamData%IntMethod = SrcParamData%IntMethod + DstParamData%nDOF = SrcParamData%nDOF + DstParamData%nDOF_red = SrcParamData%nDOF_red + DstParamData%Nmembers = SrcParamData%Nmembers +IF (ALLOCATED(SrcParamData%Elems)) THEN + i1_l = LBOUND(SrcParamData%Elems,1) + i1_u = UBOUND(SrcParamData%Elems,1) + i2_l = LBOUND(SrcParamData%Elems,2) + i2_u = UBOUND(SrcParamData%Elems,2) + IF (.NOT. ALLOCATED(DstParamData%Elems)) THEN + ALLOCATE(DstParamData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Elems = SrcParamData%Elems +ENDIF +IF (ALLOCATED(SrcParamData%ElemProps)) THEN + i1_l = LBOUND(SrcParamData%ElemProps,1) + i1_u = UBOUND(SrcParamData%ElemProps,1) + IF (.NOT. ALLOCATED(DstParamData%ElemProps)) THEN + ALLOCATE(DstParamData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) + CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%T_red)) THEN + i1_l = LBOUND(SrcParamData%T_red,1) + i1_u = UBOUND(SrcParamData%T_red,1) + i2_l = LBOUND(SrcParamData%T_red,2) + i2_u = UBOUND(SrcParamData%T_red,2) + IF (.NOT. ALLOCATED(DstParamData%T_red)) THEN + ALLOCATE(DstParamData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%T_red = SrcParamData%T_red +ENDIF +IF (ALLOCATED(SrcParamData%NodesDOF)) THEN + i1_l = LBOUND(SrcParamData%NodesDOF,1) + i1_u = UBOUND(SrcParamData%NodesDOF,1) + IF (.NOT. ALLOCATED(DstParamData%NodesDOF)) THEN + ALLOCATE(DstParamData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%NodesDOF,1), UBOUND(SrcParamData%NodesDOF,1) + CALL SD_Copyilist( SrcParamData%NodesDOF(i1), DstParamData%NodesDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%NodesDOFtilde)) THEN + i1_l = LBOUND(SrcParamData%NodesDOFtilde,1) + i1_u = UBOUND(SrcParamData%NodesDOFtilde,1) + IF (.NOT. ALLOCATED(DstParamData%NodesDOFtilde)) THEN + ALLOCATE(DstParamData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%NodesDOFtilde,1), UBOUND(SrcParamData%NodesDOFtilde,1) + CALL SD_Copyilist( SrcParamData%NodesDOFtilde(i1), DstParamData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%ElemsDOF)) THEN + i1_l = LBOUND(SrcParamData%ElemsDOF,1) + i1_u = UBOUND(SrcParamData%ElemsDOF,1) + i2_l = LBOUND(SrcParamData%ElemsDOF,2) + i2_u = UBOUND(SrcParamData%ElemsDOF,2) + IF (.NOT. ALLOCATED(DstParamData%ElemsDOF)) THEN + ALLOCATE(DstParamData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ElemsDOF = SrcParamData%ElemsDOF +ENDIF +IF (ALLOCATED(SrcParamData%DOFtilde2Nodes)) THEN + i1_l = LBOUND(SrcParamData%DOFtilde2Nodes,1) + i1_u = UBOUND(SrcParamData%DOFtilde2Nodes,1) + i2_l = LBOUND(SrcParamData%DOFtilde2Nodes,2) + i2_u = UBOUND(SrcParamData%DOFtilde2Nodes,2) + IF (.NOT. ALLOCATED(DstParamData%DOFtilde2Nodes)) THEN + ALLOCATE(DstParamData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DOFtilde2Nodes = SrcParamData%DOFtilde2Nodes +ENDIF + DstParamData%nDOFM = SrcParamData%nDOFM + DstParamData%SttcSolve = SrcParamData%SttcSolve + DstParamData%ExtraMoment = SrcParamData%ExtraMoment +IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN + i1_l = LBOUND(SrcParamData%NOmegaM2,1) + i1_u = UBOUND(SrcParamData%NOmegaM2,1) + IF (.NOT. ALLOCATED(DstParamData%NOmegaM2)) THEN + ALLOCATE(DstParamData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%NOmegaM2 = SrcParamData%NOmegaM2 +ENDIF +IF (ALLOCATED(SrcParamData%N2OmegaMJDamp)) THEN + i1_l = LBOUND(SrcParamData%N2OmegaMJDamp,1) + i1_u = UBOUND(SrcParamData%N2OmegaMJDamp,1) + IF (.NOT. ALLOCATED(DstParamData%N2OmegaMJDamp)) THEN + ALLOCATE(DstParamData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%N2OmegaMJDamp = SrcParamData%N2OmegaMJDamp +ENDIF +IF (ALLOCATED(SrcParamData%MMB)) THEN + i1_l = LBOUND(SrcParamData%MMB,1) + i1_u = UBOUND(SrcParamData%MMB,1) + i2_l = LBOUND(SrcParamData%MMB,2) + i2_u = UBOUND(SrcParamData%MMB,2) + IF (.NOT. ALLOCATED(DstParamData%MMB)) THEN + ALLOCATE(DstParamData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MMB = SrcParamData%MMB +ENDIF +IF (ALLOCATED(SrcParamData%FX)) THEN + i1_l = LBOUND(SrcParamData%FX,1) + i1_u = UBOUND(SrcParamData%FX,1) + IF (.NOT. ALLOCATED(DstParamData%FX)) THEN + ALLOCATE(DstParamData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FX = SrcParamData%FX +ENDIF +IF (ALLOCATED(SrcParamData%C1_11)) THEN + i1_l = LBOUND(SrcParamData%C1_11,1) + i1_u = UBOUND(SrcParamData%C1_11,1) + i2_l = LBOUND(SrcParamData%C1_11,2) + i2_u = UBOUND(SrcParamData%C1_11,2) + IF (.NOT. ALLOCATED(DstParamData%C1_11)) THEN + ALLOCATE(DstParamData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C1_11 = SrcParamData%C1_11 +ENDIF +IF (ALLOCATED(SrcParamData%C1_12)) THEN + i1_l = LBOUND(SrcParamData%C1_12,1) + i1_u = UBOUND(SrcParamData%C1_12,1) + i2_l = LBOUND(SrcParamData%C1_12,2) + i2_u = UBOUND(SrcParamData%C1_12,2) + IF (.NOT. ALLOCATED(DstParamData%C1_12)) THEN + ALLOCATE(DstParamData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C1_12 = SrcParamData%C1_12 +ENDIF +IF (ALLOCATED(SrcParamData%D1_13)) THEN + i1_l = LBOUND(SrcParamData%D1_13,1) + i1_u = UBOUND(SrcParamData%D1_13,1) + i2_l = LBOUND(SrcParamData%D1_13,2) + i2_u = UBOUND(SrcParamData%D1_13,2) + IF (.NOT. ALLOCATED(DstParamData%D1_13)) THEN + ALLOCATE(DstParamData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_13.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_13 = SrcParamData%D1_13 +ENDIF +IF (ALLOCATED(SrcParamData%D1_14)) THEN + i1_l = LBOUND(SrcParamData%D1_14,1) + i1_u = UBOUND(SrcParamData%D1_14,1) + i2_l = LBOUND(SrcParamData%D1_14,2) + i2_u = UBOUND(SrcParamData%D1_14,2) + IF (.NOT. ALLOCATED(DstParamData%D1_14)) THEN + ALLOCATE(DstParamData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_14.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_14 = SrcParamData%D1_14 +ENDIF +IF (ALLOCATED(SrcParamData%FY)) THEN + i1_l = LBOUND(SrcParamData%FY,1) + i1_u = UBOUND(SrcParamData%FY,1) + IF (.NOT. ALLOCATED(DstParamData%FY)) THEN + ALLOCATE(DstParamData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FY = SrcParamData%FY +ENDIF +IF (ALLOCATED(SrcParamData%PhiM)) THEN + i1_l = LBOUND(SrcParamData%PhiM,1) + i1_u = UBOUND(SrcParamData%PhiM,1) + i2_l = LBOUND(SrcParamData%PhiM,2) + i2_u = UBOUND(SrcParamData%PhiM,2) + IF (.NOT. ALLOCATED(DstParamData%PhiM)) THEN + ALLOCATE(DstParamData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiM = SrcParamData%PhiM +ENDIF +IF (ALLOCATED(SrcParamData%C2_61)) THEN + i1_l = LBOUND(SrcParamData%C2_61,1) + i1_u = UBOUND(SrcParamData%C2_61,1) + i2_l = LBOUND(SrcParamData%C2_61,2) + i2_u = UBOUND(SrcParamData%C2_61,2) + IF (.NOT. ALLOCATED(DstParamData%C2_61)) THEN + ALLOCATE(DstParamData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C2_61 = SrcParamData%C2_61 +ENDIF +IF (ALLOCATED(SrcParamData%C2_62)) THEN + i1_l = LBOUND(SrcParamData%C2_62,1) + i1_u = UBOUND(SrcParamData%C2_62,1) + i2_l = LBOUND(SrcParamData%C2_62,2) + i2_u = UBOUND(SrcParamData%C2_62,2) + IF (.NOT. ALLOCATED(DstParamData%C2_62)) THEN + ALLOCATE(DstParamData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_62.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%C2_62 = SrcParamData%C2_62 +ENDIF +IF (ALLOCATED(SrcParamData%PhiRb_TI)) THEN + i1_l = LBOUND(SrcParamData%PhiRb_TI,1) + i1_u = UBOUND(SrcParamData%PhiRb_TI,1) + i2_l = LBOUND(SrcParamData%PhiRb_TI,2) + i2_u = UBOUND(SrcParamData%PhiRb_TI,2) + IF (.NOT. ALLOCATED(DstParamData%PhiRb_TI)) THEN + ALLOCATE(DstParamData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiRb_TI = SrcParamData%PhiRb_TI +ENDIF +IF (ALLOCATED(SrcParamData%D2_63)) THEN + i1_l = LBOUND(SrcParamData%D2_63,1) + i1_u = UBOUND(SrcParamData%D2_63,1) + i2_l = LBOUND(SrcParamData%D2_63,2) + i2_u = UBOUND(SrcParamData%D2_63,2) + IF (.NOT. ALLOCATED(DstParamData%D2_63)) THEN + ALLOCATE(DstParamData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_63.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D2_63 = SrcParamData%D2_63 +ENDIF +IF (ALLOCATED(SrcParamData%D2_64)) THEN + i1_l = LBOUND(SrcParamData%D2_64,1) + i1_u = UBOUND(SrcParamData%D2_64,1) + i2_l = LBOUND(SrcParamData%D2_64,2) + i2_u = UBOUND(SrcParamData%D2_64,2) + IF (.NOT. ALLOCATED(DstParamData%D2_64)) THEN + ALLOCATE(DstParamData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_64.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D2_64 = SrcParamData%D2_64 +ENDIF +IF (ALLOCATED(SrcParamData%F2_61)) THEN + i1_l = LBOUND(SrcParamData%F2_61,1) + i1_u = UBOUND(SrcParamData%F2_61,1) + IF (.NOT. ALLOCATED(DstParamData%F2_61)) THEN + ALLOCATE(DstParamData%F2_61(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%F2_61 = SrcParamData%F2_61 +ENDIF +IF (ALLOCATED(SrcParamData%MBB)) THEN + i1_l = LBOUND(SrcParamData%MBB,1) + i1_u = UBOUND(SrcParamData%MBB,1) + i2_l = LBOUND(SrcParamData%MBB,2) + i2_u = UBOUND(SrcParamData%MBB,2) + IF (.NOT. ALLOCATED(DstParamData%MBB)) THEN + ALLOCATE(DstParamData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MBB = SrcParamData%MBB +ENDIF +IF (ALLOCATED(SrcParamData%KBB)) THEN + i1_l = LBOUND(SrcParamData%KBB,1) + i1_u = UBOUND(SrcParamData%KBB,1) + i2_l = LBOUND(SrcParamData%KBB,2) + i2_u = UBOUND(SrcParamData%KBB,2) + IF (.NOT. ALLOCATED(DstParamData%KBB)) THEN + ALLOCATE(DstParamData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KBB = SrcParamData%KBB +ENDIF +IF (ALLOCATED(SrcParamData%MBM)) THEN + i1_l = LBOUND(SrcParamData%MBM,1) + i1_u = UBOUND(SrcParamData%MBM,1) + i2_l = LBOUND(SrcParamData%MBM,2) + i2_u = UBOUND(SrcParamData%MBM,2) + IF (.NOT. ALLOCATED(DstParamData%MBM)) THEN + ALLOCATE(DstParamData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MBM = SrcParamData%MBM +ENDIF +IF (ALLOCATED(SrcParamData%UL_st_g)) THEN + i1_l = LBOUND(SrcParamData%UL_st_g,1) + i1_u = UBOUND(SrcParamData%UL_st_g,1) + IF (.NOT. ALLOCATED(DstParamData%UL_st_g)) THEN + ALLOCATE(DstParamData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%UL_st_g.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%UL_st_g = SrcParamData%UL_st_g +ENDIF +IF (ALLOCATED(SrcParamData%PhiL_T)) THEN + i1_l = LBOUND(SrcParamData%PhiL_T,1) + i1_u = UBOUND(SrcParamData%PhiL_T,1) + i2_l = LBOUND(SrcParamData%PhiL_T,2) + i2_u = UBOUND(SrcParamData%PhiL_T,2) + IF (.NOT. ALLOCATED(DstParamData%PhiL_T)) THEN + ALLOCATE(DstParamData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiL_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiL_T = SrcParamData%PhiL_T +ENDIF +IF (ALLOCATED(SrcParamData%PhiLInvOmgL2)) THEN + i1_l = LBOUND(SrcParamData%PhiLInvOmgL2,1) + i1_u = UBOUND(SrcParamData%PhiLInvOmgL2,1) + i2_l = LBOUND(SrcParamData%PhiLInvOmgL2,2) + i2_u = UBOUND(SrcParamData%PhiLInvOmgL2,2) + IF (.NOT. ALLOCATED(DstParamData%PhiLInvOmgL2)) THEN + ALLOCATE(DstParamData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PhiLInvOmgL2 = SrcParamData%PhiLInvOmgL2 +ENDIF +IF (ALLOCATED(SrcParamData%KLLm1)) THEN + i1_l = LBOUND(SrcParamData%KLLm1,1) + i1_u = UBOUND(SrcParamData%KLLm1,1) + i2_l = LBOUND(SrcParamData%KLLm1,2) + i2_u = UBOUND(SrcParamData%KLLm1,2) + IF (.NOT. ALLOCATED(DstParamData%KLLm1)) THEN + ALLOCATE(DstParamData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KLLm1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%KLLm1 = SrcParamData%KLLm1 +ENDIF +IF (ALLOCATED(SrcParamData%AM2Jac)) THEN + i1_l = LBOUND(SrcParamData%AM2Jac,1) + i1_u = UBOUND(SrcParamData%AM2Jac,1) + i2_l = LBOUND(SrcParamData%AM2Jac,2) + i2_u = UBOUND(SrcParamData%AM2Jac,2) + IF (.NOT. ALLOCATED(DstParamData%AM2Jac)) THEN + ALLOCATE(DstParamData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AM2Jac = SrcParamData%AM2Jac +ENDIF +IF (ALLOCATED(SrcParamData%AM2JacPiv)) THEN + i1_l = LBOUND(SrcParamData%AM2JacPiv,1) + i1_u = UBOUND(SrcParamData%AM2JacPiv,1) + IF (.NOT. ALLOCATED(DstParamData%AM2JacPiv)) THEN + ALLOCATE(DstParamData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%AM2JacPiv = SrcParamData%AM2JacPiv +ENDIF +IF (ALLOCATED(SrcParamData%TI)) THEN + i1_l = LBOUND(SrcParamData%TI,1) + i1_u = UBOUND(SrcParamData%TI,1) + i2_l = LBOUND(SrcParamData%TI,2) + i2_u = UBOUND(SrcParamData%TI,2) + IF (.NOT. ALLOCATED(DstParamData%TI)) THEN + ALLOCATE(DstParamData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TI = SrcParamData%TI +ENDIF +IF (ALLOCATED(SrcParamData%TIreact)) THEN + i1_l = LBOUND(SrcParamData%TIreact,1) + i1_u = UBOUND(SrcParamData%TIreact,1) + i2_l = LBOUND(SrcParamData%TIreact,2) + i2_u = UBOUND(SrcParamData%TIreact,2) + IF (.NOT. ALLOCATED(DstParamData%TIreact)) THEN + ALLOCATE(DstParamData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TIreact.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%TIreact = SrcParamData%TIreact +ENDIF + DstParamData%nNodes = SrcParamData%nNodes + DstParamData%nNodes_I = SrcParamData%nNodes_I + DstParamData%nNodes_L = SrcParamData%nNodes_L + DstParamData%nNodes_C = SrcParamData%nNodes_C +IF (ALLOCATED(SrcParamData%Nodes_I)) THEN + i1_l = LBOUND(SrcParamData%Nodes_I,1) + i1_u = UBOUND(SrcParamData%Nodes_I,1) + i2_l = LBOUND(SrcParamData%Nodes_I,2) + i2_u = UBOUND(SrcParamData%Nodes_I,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_I)) THEN + ALLOCATE(DstParamData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Nodes_I = SrcParamData%Nodes_I +ENDIF +IF (ALLOCATED(SrcParamData%Nodes_L)) THEN + i1_l = LBOUND(SrcParamData%Nodes_L,1) + i1_u = UBOUND(SrcParamData%Nodes_L,1) + i2_l = LBOUND(SrcParamData%Nodes_L,2) + i2_u = UBOUND(SrcParamData%Nodes_L,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_L)) THEN + ALLOCATE(DstParamData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Nodes_L = SrcParamData%Nodes_L +ENDIF +IF (ALLOCATED(SrcParamData%Nodes_C)) THEN + i1_l = LBOUND(SrcParamData%Nodes_C,1) + i1_u = UBOUND(SrcParamData%Nodes_C,1) + i2_l = LBOUND(SrcParamData%Nodes_C,2) + i2_u = UBOUND(SrcParamData%Nodes_C,2) + IF (.NOT. ALLOCATED(DstParamData%Nodes_C)) THEN + ALLOCATE(DstParamData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Nodes_C = SrcParamData%Nodes_C +ENDIF + DstParamData%nDOFI__ = SrcParamData%nDOFI__ + DstParamData%nDOFI_Rb = SrcParamData%nDOFI_Rb + DstParamData%nDOFI_F = SrcParamData%nDOFI_F + DstParamData%nDOFL_L = SrcParamData%nDOFL_L + DstParamData%nDOFC__ = SrcParamData%nDOFC__ + DstParamData%nDOFC_Rb = SrcParamData%nDOFC_Rb + DstParamData%nDOFC_L = SrcParamData%nDOFC_L + DstParamData%nDOFC_F = SrcParamData%nDOFC_F + DstParamData%nDOFR__ = SrcParamData%nDOFR__ + DstParamData%nDOF__Rb = SrcParamData%nDOF__Rb + DstParamData%nDOF__L = SrcParamData%nDOF__L + DstParamData%nDOF__F = SrcParamData%nDOF__F +IF (ALLOCATED(SrcParamData%IDI__)) THEN + i1_l = LBOUND(SrcParamData%IDI__,1) + i1_u = UBOUND(SrcParamData%IDI__,1) + IF (.NOT. ALLOCATED(DstParamData%IDI__)) THEN + ALLOCATE(DstParamData%IDI__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDI__ = SrcParamData%IDI__ +ENDIF +IF (ALLOCATED(SrcParamData%IDI_Rb)) THEN + i1_l = LBOUND(SrcParamData%IDI_Rb,1) + i1_u = UBOUND(SrcParamData%IDI_Rb,1) + IF (.NOT. ALLOCATED(DstParamData%IDI_Rb)) THEN + ALLOCATE(DstParamData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDI_Rb = SrcParamData%IDI_Rb +ENDIF +IF (ALLOCATED(SrcParamData%IDI_F)) THEN + i1_l = LBOUND(SrcParamData%IDI_F,1) + i1_u = UBOUND(SrcParamData%IDI_F,1) + IF (.NOT. ALLOCATED(DstParamData%IDI_F)) THEN + ALLOCATE(DstParamData%IDI_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDI_F = SrcParamData%IDI_F +ENDIF +IF (ALLOCATED(SrcParamData%IDL_L)) THEN + i1_l = LBOUND(SrcParamData%IDL_L,1) + i1_u = UBOUND(SrcParamData%IDL_L,1) + IF (.NOT. ALLOCATED(DstParamData%IDL_L)) THEN + ALLOCATE(DstParamData%IDL_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDL_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDL_L = SrcParamData%IDL_L +ENDIF +IF (ALLOCATED(SrcParamData%IDC__)) THEN + i1_l = LBOUND(SrcParamData%IDC__,1) + i1_u = UBOUND(SrcParamData%IDC__,1) + IF (.NOT. ALLOCATED(DstParamData%IDC__)) THEN + ALLOCATE(DstParamData%IDC__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC__ = SrcParamData%IDC__ +ENDIF +IF (ALLOCATED(SrcParamData%IDC_Rb)) THEN + i1_l = LBOUND(SrcParamData%IDC_Rb,1) + i1_u = UBOUND(SrcParamData%IDC_Rb,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_Rb)) THEN + ALLOCATE(DstParamData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_Rb = SrcParamData%IDC_Rb +ENDIF +IF (ALLOCATED(SrcParamData%IDC_L)) THEN + i1_l = LBOUND(SrcParamData%IDC_L,1) + i1_u = UBOUND(SrcParamData%IDC_L,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_L)) THEN + ALLOCATE(DstParamData%IDC_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_L = SrcParamData%IDC_L +ENDIF +IF (ALLOCATED(SrcParamData%IDC_F)) THEN + i1_l = LBOUND(SrcParamData%IDC_F,1) + i1_u = UBOUND(SrcParamData%IDC_F,1) + IF (.NOT. ALLOCATED(DstParamData%IDC_F)) THEN + ALLOCATE(DstParamData%IDC_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDC_F = SrcParamData%IDC_F +ENDIF +IF (ALLOCATED(SrcParamData%IDR__)) THEN + i1_l = LBOUND(SrcParamData%IDR__,1) + i1_u = UBOUND(SrcParamData%IDR__,1) + IF (.NOT. ALLOCATED(DstParamData%IDR__)) THEN + ALLOCATE(DstParamData%IDR__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%IDR__ = SrcParamData%IDR__ +ENDIF +IF (ALLOCATED(SrcParamData%ID__Rb)) THEN + i1_l = LBOUND(SrcParamData%ID__Rb,1) + i1_u = UBOUND(SrcParamData%ID__Rb,1) + IF (.NOT. ALLOCATED(DstParamData%ID__Rb)) THEN + ALLOCATE(DstParamData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__Rb = SrcParamData%ID__Rb +ENDIF +IF (ALLOCATED(SrcParamData%ID__L)) THEN + i1_l = LBOUND(SrcParamData%ID__L,1) + i1_u = UBOUND(SrcParamData%ID__L,1) + IF (.NOT. ALLOCATED(DstParamData%ID__L)) THEN + ALLOCATE(DstParamData%ID__L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__L = SrcParamData%ID__L +ENDIF +IF (ALLOCATED(SrcParamData%ID__F)) THEN + i1_l = LBOUND(SrcParamData%ID__F,1) + i1_u = UBOUND(SrcParamData%ID__F,1) + IF (.NOT. ALLOCATED(DstParamData%ID__F)) THEN + ALLOCATE(DstParamData%ID__F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%ID__F = SrcParamData%ID__F +ENDIF +IF (ALLOCATED(SrcParamData%FGL)) THEN + i1_l = LBOUND(SrcParamData%FGL,1) + i1_u = UBOUND(SrcParamData%FGL,1) + IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN + ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FGL = SrcParamData%FGL +ENDIF + DstParamData%NMOutputs = SrcParamData%NMOutputs + DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%OutSwtch = SrcParamData%OutSwtch + DstParamData%UnJckF = SrcParamData%UnJckF + DstParamData%Delim = SrcParamData%Delim + DstParamData%OutFmt = SrcParamData%OutFmt + DstParamData%OutSFmt = SrcParamData%OutSFmt +IF (ALLOCATED(SrcParamData%MoutLst)) THEN + i1_l = LBOUND(SrcParamData%MoutLst,1) + i1_u = UBOUND(SrcParamData%MoutLst,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst)) THEN + ALLOCATE(DstParamData%MoutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst,1), UBOUND(SrcParamData%MoutLst,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst(i1), DstParamData%MoutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%MoutLst2)) THEN + i1_l = LBOUND(SrcParamData%MoutLst2,1) + i1_u = UBOUND(SrcParamData%MoutLst2,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst2)) THEN + ALLOCATE(DstParamData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst2,1), UBOUND(SrcParamData%MoutLst2,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst2(i1), DstParamData%MoutLst2(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%MoutLst3)) THEN + i1_l = LBOUND(SrcParamData%MoutLst3,1) + i1_u = UBOUND(SrcParamData%MoutLst3,1) + IF (.NOT. ALLOCATED(DstParamData%MoutLst3)) THEN + ALLOCATE(DstParamData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%MoutLst3,1), UBOUND(SrcParamData%MoutLst3,1) + CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst3(i1), DstParamData%MoutLst3(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%OutParam)) THEN + i1_l = LBOUND(SrcParamData%OutParam,1) + i1_u = UBOUND(SrcParamData%OutParam,1) + IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN + ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) + CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + DstParamData%OutAll = SrcParamData%OutAll + DstParamData%OutReact = SrcParamData%OutReact + DstParamData%OutAllInt = SrcParamData%OutAllInt + DstParamData%OutAllDims = SrcParamData%OutAllDims + DstParamData%OutDec = SrcParamData%OutDec + END SUBROUTINE SD_CopyParam + + SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) + TYPE(SD_ParameterType), INTENT(INOUT) :: ParamData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyParam' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(ParamData%Elems)) THEN + DEALLOCATE(ParamData%Elems) +ENDIF +IF (ALLOCATED(ParamData%ElemProps)) THEN +DO i1 = LBOUND(ParamData%ElemProps,1), UBOUND(ParamData%ElemProps,1) + CALL SD_Destroyelemproptype( ParamData%ElemProps(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%ElemProps) +ENDIF +IF (ALLOCATED(ParamData%T_red)) THEN + DEALLOCATE(ParamData%T_red) +ENDIF +IF (ALLOCATED(ParamData%NodesDOF)) THEN +DO i1 = LBOUND(ParamData%NodesDOF,1), UBOUND(ParamData%NodesDOF,1) + CALL SD_Destroyilist( ParamData%NodesDOF(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%NodesDOF) +ENDIF +IF (ALLOCATED(ParamData%NodesDOFtilde)) THEN +DO i1 = LBOUND(ParamData%NodesDOFtilde,1), UBOUND(ParamData%NodesDOFtilde,1) + CALL SD_Destroyilist( ParamData%NodesDOFtilde(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%NodesDOFtilde) +ENDIF +IF (ALLOCATED(ParamData%ElemsDOF)) THEN + DEALLOCATE(ParamData%ElemsDOF) +ENDIF +IF (ALLOCATED(ParamData%DOFtilde2Nodes)) THEN + DEALLOCATE(ParamData%DOFtilde2Nodes) +ENDIF +IF (ALLOCATED(ParamData%NOmegaM2)) THEN + DEALLOCATE(ParamData%NOmegaM2) +ENDIF +IF (ALLOCATED(ParamData%N2OmegaMJDamp)) THEN + DEALLOCATE(ParamData%N2OmegaMJDamp) +ENDIF +IF (ALLOCATED(ParamData%MMB)) THEN + DEALLOCATE(ParamData%MMB) +ENDIF +IF (ALLOCATED(ParamData%FX)) THEN + DEALLOCATE(ParamData%FX) +ENDIF +IF (ALLOCATED(ParamData%C1_11)) THEN + DEALLOCATE(ParamData%C1_11) +ENDIF +IF (ALLOCATED(ParamData%C1_12)) THEN + DEALLOCATE(ParamData%C1_12) +ENDIF +IF (ALLOCATED(ParamData%D1_13)) THEN + DEALLOCATE(ParamData%D1_13) +ENDIF +IF (ALLOCATED(ParamData%D1_14)) THEN + DEALLOCATE(ParamData%D1_14) +ENDIF +IF (ALLOCATED(ParamData%FY)) THEN + DEALLOCATE(ParamData%FY) +ENDIF +IF (ALLOCATED(ParamData%PhiM)) THEN + DEALLOCATE(ParamData%PhiM) +ENDIF +IF (ALLOCATED(ParamData%C2_61)) THEN + DEALLOCATE(ParamData%C2_61) +ENDIF +IF (ALLOCATED(ParamData%C2_62)) THEN + DEALLOCATE(ParamData%C2_62) +ENDIF +IF (ALLOCATED(ParamData%PhiRb_TI)) THEN + DEALLOCATE(ParamData%PhiRb_TI) +ENDIF +IF (ALLOCATED(ParamData%D2_63)) THEN + DEALLOCATE(ParamData%D2_63) +ENDIF +IF (ALLOCATED(ParamData%D2_64)) THEN + DEALLOCATE(ParamData%D2_64) +ENDIF +IF (ALLOCATED(ParamData%F2_61)) THEN + DEALLOCATE(ParamData%F2_61) +ENDIF +IF (ALLOCATED(ParamData%MBB)) THEN + DEALLOCATE(ParamData%MBB) +ENDIF +IF (ALLOCATED(ParamData%KBB)) THEN + DEALLOCATE(ParamData%KBB) +ENDIF +IF (ALLOCATED(ParamData%MBM)) THEN + DEALLOCATE(ParamData%MBM) +ENDIF +IF (ALLOCATED(ParamData%UL_st_g)) THEN + DEALLOCATE(ParamData%UL_st_g) +ENDIF +IF (ALLOCATED(ParamData%PhiL_T)) THEN + DEALLOCATE(ParamData%PhiL_T) +ENDIF +IF (ALLOCATED(ParamData%PhiLInvOmgL2)) THEN + DEALLOCATE(ParamData%PhiLInvOmgL2) +ENDIF +IF (ALLOCATED(ParamData%KLLm1)) THEN + DEALLOCATE(ParamData%KLLm1) +ENDIF +IF (ALLOCATED(ParamData%AM2Jac)) THEN + DEALLOCATE(ParamData%AM2Jac) +ENDIF +IF (ALLOCATED(ParamData%AM2JacPiv)) THEN + DEALLOCATE(ParamData%AM2JacPiv) +ENDIF +IF (ALLOCATED(ParamData%TI)) THEN + DEALLOCATE(ParamData%TI) +ENDIF +IF (ALLOCATED(ParamData%TIreact)) THEN + DEALLOCATE(ParamData%TIreact) +ENDIF +IF (ALLOCATED(ParamData%Nodes_I)) THEN + DEALLOCATE(ParamData%Nodes_I) +ENDIF +IF (ALLOCATED(ParamData%Nodes_L)) THEN + DEALLOCATE(ParamData%Nodes_L) +ENDIF +IF (ALLOCATED(ParamData%Nodes_C)) THEN + DEALLOCATE(ParamData%Nodes_C) +ENDIF +IF (ALLOCATED(ParamData%IDI__)) THEN + DEALLOCATE(ParamData%IDI__) +ENDIF +IF (ALLOCATED(ParamData%IDI_Rb)) THEN + DEALLOCATE(ParamData%IDI_Rb) +ENDIF +IF (ALLOCATED(ParamData%IDI_F)) THEN + DEALLOCATE(ParamData%IDI_F) +ENDIF +IF (ALLOCATED(ParamData%IDL_L)) THEN + DEALLOCATE(ParamData%IDL_L) +ENDIF +IF (ALLOCATED(ParamData%IDC__)) THEN + DEALLOCATE(ParamData%IDC__) +ENDIF +IF (ALLOCATED(ParamData%IDC_Rb)) THEN + DEALLOCATE(ParamData%IDC_Rb) +ENDIF +IF (ALLOCATED(ParamData%IDC_L)) THEN + DEALLOCATE(ParamData%IDC_L) +ENDIF +IF (ALLOCATED(ParamData%IDC_F)) THEN + DEALLOCATE(ParamData%IDC_F) +ENDIF +IF (ALLOCATED(ParamData%IDR__)) THEN + DEALLOCATE(ParamData%IDR__) +ENDIF +IF (ALLOCATED(ParamData%ID__Rb)) THEN + DEALLOCATE(ParamData%ID__Rb) +ENDIF +IF (ALLOCATED(ParamData%ID__L)) THEN + DEALLOCATE(ParamData%ID__L) +ENDIF +IF (ALLOCATED(ParamData%ID__F)) THEN + DEALLOCATE(ParamData%ID__F) +ENDIF +IF (ALLOCATED(ParamData%FGL)) THEN + DEALLOCATE(ParamData%FGL) +ENDIF +IF (ALLOCATED(ParamData%MoutLst)) THEN +DO i1 = LBOUND(ParamData%MoutLst,1), UBOUND(ParamData%MoutLst,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst) +ENDIF +IF (ALLOCATED(ParamData%MoutLst2)) THEN +DO i1 = LBOUND(ParamData%MoutLst2,1), UBOUND(ParamData%MoutLst2,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst2(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst2) +ENDIF +IF (ALLOCATED(ParamData%MoutLst3)) THEN +DO i1 = LBOUND(ParamData%MoutLst3,1), UBOUND(ParamData%MoutLst3,1) + CALL SD_Destroymeshauxdatatype( ParamData%MoutLst3(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%MoutLst3) +ENDIF +IF (ALLOCATED(ParamData%OutParam)) THEN +DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) + CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(ParamData%OutParam) +ENDIF + END SUBROUTINE SD_DestroyParam + + SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_ParameterType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackParam' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Db_BufSz = Db_BufSz + 1 ! SDDeltaT + Int_BufSz = Int_BufSz + 1 ! IntMethod + Int_BufSz = Int_BufSz + 1 ! nDOF + Int_BufSz = Int_BufSz + 1 ! nDOF_red + Int_BufSz = Int_BufSz + 1 ! Nmembers + Int_BufSz = Int_BufSz + 1 ! Elems allocated yes/no + IF ( ALLOCATED(InData%Elems) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Elems upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Elems) ! Elems + END IF + Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no + IF ( ALLOCATED(InData%ElemProps) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ElemProps upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + Int_BufSz = Int_BufSz + 3 ! ElemProps: size of buffers for each call to pack subtype + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ElemProps + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ElemProps + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ElemProps + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no + IF ( ALLOCATED(InData%T_red) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%T_red) ! T_red + END IF + Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no + IF ( ALLOCATED(InData%NodesDOF) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOF: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no + IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no + IF ( ALLOCATED(InData%ElemsDOF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF + END IF + Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no + IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes + END IF + Int_BufSz = Int_BufSz + 1 ! nDOFM + Int_BufSz = Int_BufSz + 1 ! SttcSolve + Int_BufSz = Int_BufSz + 1 ! ExtraMoment + Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no + IF ( ALLOCATED(InData%NOmegaM2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%NOmegaM2) ! NOmegaM2 + END IF + Int_BufSz = Int_BufSz + 1 ! N2OmegaMJDamp allocated yes/no + IF ( ALLOCATED(InData%N2OmegaMJDamp) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! N2OmegaMJDamp upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%N2OmegaMJDamp) ! N2OmegaMJDamp + END IF + Int_BufSz = Int_BufSz + 1 ! MMB allocated yes/no + IF ( ALLOCATED(InData%MMB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MMB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MMB) ! MMB + END IF + Int_BufSz = Int_BufSz + 1 ! FX allocated yes/no + IF ( ALLOCATED(InData%FX) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FX upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FX) ! FX + END IF + Int_BufSz = Int_BufSz + 1 ! C1_11 allocated yes/no + IF ( ALLOCATED(InData%C1_11) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C1_11 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C1_11) ! C1_11 + END IF + Int_BufSz = Int_BufSz + 1 ! C1_12 allocated yes/no + IF ( ALLOCATED(InData%C1_12) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C1_12 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C1_12) ! C1_12 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_13 allocated yes/no + IF ( ALLOCATED(InData%D1_13) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_14 allocated yes/no + IF ( ALLOCATED(InData%D1_14) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 + END IF + Int_BufSz = Int_BufSz + 1 ! FY allocated yes/no + IF ( ALLOCATED(InData%FY) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FY upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FY) ! FY + END IF + Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no + IF ( ALLOCATED(InData%PhiM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiM) ! PhiM + END IF + Int_BufSz = Int_BufSz + 1 ! C2_61 allocated yes/no + IF ( ALLOCATED(InData%C2_61) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C2_61 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C2_61) ! C2_61 + END IF + Int_BufSz = Int_BufSz + 1 ! C2_62 allocated yes/no + IF ( ALLOCATED(InData%C2_62) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! C2_62 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%C2_62) ! C2_62 + END IF + Int_BufSz = Int_BufSz + 1 ! PhiRb_TI allocated yes/no + IF ( ALLOCATED(InData%PhiRb_TI) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiRb_TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiRb_TI) ! PhiRb_TI + END IF + Int_BufSz = Int_BufSz + 1 ! D2_63 allocated yes/no + IF ( ALLOCATED(InData%D2_63) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D2_63 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D2_63) ! D2_63 + END IF + Int_BufSz = Int_BufSz + 1 ! D2_64 allocated yes/no + IF ( ALLOCATED(InData%D2_64) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D2_64 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D2_64) ! D2_64 + END IF + Int_BufSz = Int_BufSz + 1 ! F2_61 allocated yes/no + IF ( ALLOCATED(InData%F2_61) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F2_61 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F2_61) ! F2_61 + END IF + Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no + IF ( ALLOCATED(InData%MBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB + END IF + Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no + IF ( ALLOCATED(InData%KBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB + END IF + Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no + IF ( ALLOCATED(InData%MBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM + END IF + Int_BufSz = Int_BufSz + 1 ! UL_st_g allocated yes/no + IF ( ALLOCATED(InData%UL_st_g) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! UL_st_g upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%UL_st_g) ! UL_st_g + END IF + Int_BufSz = Int_BufSz + 1 ! PhiL_T allocated yes/no + IF ( ALLOCATED(InData%PhiL_T) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiL_T upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiL_T) ! PhiL_T + END IF + Int_BufSz = Int_BufSz + 1 ! PhiLInvOmgL2 allocated yes/no + IF ( ALLOCATED(InData%PhiLInvOmgL2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiLInvOmgL2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PhiLInvOmgL2) ! PhiLInvOmgL2 + END IF + Int_BufSz = Int_BufSz + 1 ! KLLm1 allocated yes/no + IF ( ALLOCATED(InData%KLLm1) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KLLm1 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KLLm1) ! KLLm1 + END IF + Int_BufSz = Int_BufSz + 1 ! AM2Jac allocated yes/no + IF ( ALLOCATED(InData%AM2Jac) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AM2Jac upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AM2Jac) ! AM2Jac + END IF + Int_BufSz = Int_BufSz + 1 ! AM2JacPiv allocated yes/no + IF ( ALLOCATED(InData%AM2JacPiv) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AM2JacPiv upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%AM2JacPiv) ! AM2JacPiv + END IF + Int_BufSz = Int_BufSz + 1 ! TI allocated yes/no + IF ( ALLOCATED(InData%TI) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TI upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI + END IF + Int_BufSz = Int_BufSz + 1 ! TIreact allocated yes/no + IF ( ALLOCATED(InData%TIreact) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! TIreact upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%TIreact) ! TIreact + END IF + Int_BufSz = Int_BufSz + 1 ! nNodes + Int_BufSz = Int_BufSz + 1 ! nNodes_I + Int_BufSz = Int_BufSz + 1 ! nNodes_L + Int_BufSz = Int_BufSz + 1 ! nNodes_C + Int_BufSz = Int_BufSz + 1 ! Nodes_I allocated yes/no + IF ( ALLOCATED(InData%Nodes_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_I upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_I) ! Nodes_I + END IF + Int_BufSz = Int_BufSz + 1 ! Nodes_L allocated yes/no + IF ( ALLOCATED(InData%Nodes_L) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_L) ! Nodes_L + END IF + Int_BufSz = Int_BufSz + 1 ! Nodes_C allocated yes/no + IF ( ALLOCATED(InData%Nodes_C) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Nodes_C upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_C) ! Nodes_C + END IF + Int_BufSz = Int_BufSz + 1 ! nDOFI__ + Int_BufSz = Int_BufSz + 1 ! nDOFI_Rb + Int_BufSz = Int_BufSz + 1 ! nDOFI_F + Int_BufSz = Int_BufSz + 1 ! nDOFL_L + Int_BufSz = Int_BufSz + 1 ! nDOFC__ + Int_BufSz = Int_BufSz + 1 ! nDOFC_Rb + Int_BufSz = Int_BufSz + 1 ! nDOFC_L + Int_BufSz = Int_BufSz + 1 ! nDOFC_F + Int_BufSz = Int_BufSz + 1 ! nDOFR__ + Int_BufSz = Int_BufSz + 1 ! nDOF__Rb + Int_BufSz = Int_BufSz + 1 ! nDOF__L + Int_BufSz = Int_BufSz + 1 ! nDOF__F + Int_BufSz = Int_BufSz + 1 ! IDI__ allocated yes/no + IF ( ALLOCATED(InData%IDI__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI__) ! IDI__ + END IF + Int_BufSz = Int_BufSz + 1 ! IDI_Rb allocated yes/no + IF ( ALLOCATED(InData%IDI_Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI_Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI_Rb) ! IDI_Rb + END IF + Int_BufSz = Int_BufSz + 1 ! IDI_F allocated yes/no + IF ( ALLOCATED(InData%IDI_F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDI_F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDI_F) ! IDI_F + END IF + Int_BufSz = Int_BufSz + 1 ! IDL_L allocated yes/no + IF ( ALLOCATED(InData%IDL_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDL_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDL_L) ! IDL_L + END IF + Int_BufSz = Int_BufSz + 1 ! IDC__ allocated yes/no + IF ( ALLOCATED(InData%IDC__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC__) ! IDC__ + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_Rb allocated yes/no + IF ( ALLOCATED(InData%IDC_Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_Rb) ! IDC_Rb + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_L allocated yes/no + IF ( ALLOCATED(InData%IDC_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_L) ! IDC_L + END IF + Int_BufSz = Int_BufSz + 1 ! IDC_F allocated yes/no + IF ( ALLOCATED(InData%IDC_F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDC_F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDC_F) ! IDC_F + END IF + Int_BufSz = Int_BufSz + 1 ! IDR__ allocated yes/no + IF ( ALLOCATED(InData%IDR__) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IDR__ upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IDR__) ! IDR__ + END IF + Int_BufSz = Int_BufSz + 1 ! ID__Rb allocated yes/no + IF ( ALLOCATED(InData%ID__Rb) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__Rb upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__Rb) ! ID__Rb + END IF + Int_BufSz = Int_BufSz + 1 ! ID__L allocated yes/no + IF ( ALLOCATED(InData%ID__L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__L upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__L) ! ID__L + END IF + Int_BufSz = Int_BufSz + 1 ! ID__F allocated yes/no + IF ( ALLOCATED(InData%ID__F) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ID__F upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ID__F) ! ID__F + END IF + Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no + IF ( ALLOCATED(InData%FGL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL + END IF + Int_BufSz = Int_BufSz + 1 ! NMOutputs + Int_BufSz = Int_BufSz + 1 ! NumOuts + Int_BufSz = Int_BufSz + 1 ! OutSwtch + Int_BufSz = Int_BufSz + 1 ! UnJckF + Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim + Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt + Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt + Int_BufSz = Int_BufSz + 1 ! MoutLst allocated yes/no + IF ( ALLOCATED(InData%MoutLst) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MoutLst2 allocated yes/no + IF ( ALLOCATED(InData%MoutLst2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst2 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst2: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst2 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst2 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst2 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! MoutLst3 allocated yes/no + IF ( ALLOCATED(InData%MoutLst3) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MoutLst3 upper/lower bounds for each dimension + DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) + Int_BufSz = Int_BufSz + 3 ! MoutLst3: size of buffers for each call to pack subtype + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst3 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! MoutLst3 + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! MoutLst3 + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! MoutLst3 + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no + IF ( ALLOCATED(InData%OutParam) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension + DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) + Int_BufSz = Int_BufSz + 3 ! OutParam: size of buffers for each call to pack subtype + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! OutParam + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! OutParam + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! OutParam + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 1 ! OutAll + Int_BufSz = Int_BufSz + 1 ! OutReact + Int_BufSz = Int_BufSz + 1 ! OutAllInt + Int_BufSz = Int_BufSz + 1 ! OutAllDims + Int_BufSz = Int_BufSz + 1 ! OutDec + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%SDDeltaT + Db_Xferred = Db_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF_red + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Nmembers + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Elems) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Elems)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Elems))-1 ) = PACK(InData%Elems,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Elems) + END IF + IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) + CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%T_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%T_red) + END IF + IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOF,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) + END IF + IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%SttcSolve + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%ExtraMoment , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NOmegaM2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NOmegaM2,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%NOmegaM2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%NOmegaM2))-1 ) = PACK(InData%NOmegaM2,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%NOmegaM2) + END IF + IF ( .NOT. ALLOCATED(InData%N2OmegaMJDamp) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%N2OmegaMJDamp,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%N2OmegaMJDamp,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%N2OmegaMJDamp)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%N2OmegaMJDamp))-1 ) = PACK(InData%N2OmegaMJDamp,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%N2OmegaMJDamp) + END IF + IF ( .NOT. ALLOCATED(InData%MMB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MMB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MMB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MMB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MMB))-1 ) = PACK(InData%MMB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MMB) + END IF + IF ( .NOT. ALLOCATED(InData%FX) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FX,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FX,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FX))-1 ) = PACK(InData%FX,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FX) + END IF + IF ( .NOT. ALLOCATED(InData%C1_11) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_11,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_11,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%C1_11)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C1_11))-1 ) = PACK(InData%C1_11,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%C1_11) + END IF + IF ( .NOT. ALLOCATED(InData%C1_12) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_12,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_12,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%C1_12)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C1_12))-1 ) = PACK(InData%C1_12,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%C1_12) + END IF + IF ( .NOT. ALLOCATED(InData%D1_13) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D1_13)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_13))-1 ) = PACK(InData%D1_13,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D1_13) + END IF + IF ( .NOT. ALLOCATED(InData%D1_14) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D1_14)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_14))-1 ) = PACK(InData%D1_14,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D1_14) + END IF + IF ( .NOT. ALLOCATED(InData%FY) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FY,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FY,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FY)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FY))-1 ) = PACK(InData%FY,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FY) + END IF + IF ( .NOT. ALLOCATED(InData%PhiM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiM))-1 ) = PACK(InData%PhiM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiM) + END IF + IF ( .NOT. ALLOCATED(InData%C2_61) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_61,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_61,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%C2_61)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C2_61))-1 ) = PACK(InData%C2_61,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%C2_61) + END IF + IF ( .NOT. ALLOCATED(InData%C2_62) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_62,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_62,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%C2_62)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C2_62))-1 ) = PACK(InData%C2_62,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%C2_62) + END IF + IF ( .NOT. ALLOCATED(InData%PhiRb_TI) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiRb_TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiRb_TI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiRb_TI)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiRb_TI))-1 ) = PACK(InData%PhiRb_TI,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiRb_TI) + END IF + IF ( .NOT. ALLOCATED(InData%D2_63) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_63,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_63,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D2_63)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D2_63))-1 ) = PACK(InData%D2_63,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D2_63) + END IF + IF ( .NOT. ALLOCATED(InData%D2_64) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_64,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_64,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%D2_64)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D2_64))-1 ) = PACK(InData%D2_64,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%D2_64) + END IF + IF ( .NOT. ALLOCATED(InData%F2_61) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F2_61,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F2_61,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%F2_61)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F2_61))-1 ) = PACK(InData%F2_61,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%F2_61) + END IF + IF ( .NOT. ALLOCATED(InData%MBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MBB) + END IF + IF ( .NOT. ALLOCATED(InData%KBB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%KBB) + END IF + IF ( .NOT. ALLOCATED(InData%MBM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%MBM) + END IF + IF ( .NOT. ALLOCATED(InData%UL_st_g) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_st_g,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_st_g,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%UL_st_g)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_st_g))-1 ) = PACK(InData%UL_st_g,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%UL_st_g) + END IF + IF ( .NOT. ALLOCATED(InData%PhiL_T) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL_T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL_T,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiL_T)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiL_T))-1 ) = PACK(InData%PhiL_T,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiL_T) + END IF + IF ( .NOT. ALLOCATED(InData%PhiLInvOmgL2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiLInvOmgL2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiLInvOmgL2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%PhiLInvOmgL2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiLInvOmgL2))-1 ) = PACK(InData%PhiLInvOmgL2,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%PhiLInvOmgL2) + END IF + IF ( .NOT. ALLOCATED(InData%KLLm1) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%KLLm1)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KLLm1))-1 ) = PACK(InData%KLLm1,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%KLLm1) + END IF + IF ( .NOT. ALLOCATED(InData%AM2Jac) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2Jac,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2Jac,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AM2Jac)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM2Jac))-1 ) = PACK(InData%AM2Jac,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%AM2Jac) + END IF + IF ( .NOT. ALLOCATED(InData%AM2JacPiv) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2JacPiv,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2JacPiv,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%AM2JacPiv)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%AM2JacPiv))-1 ) = PACK(InData%AM2JacPiv,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%AM2JacPiv) + END IF + IF ( .NOT. ALLOCATED(InData%TI) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TI,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%TI)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TI))-1 ) = PACK(InData%TI,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%TI) + END IF + IF ( .NOT. ALLOCATED(InData%TIreact) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TIreact,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%TIreact,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%TIreact)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TIreact))-1 ) = PACK(InData%TIreact,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%TIreact) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_C + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Nodes_I) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Nodes_I)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_I))-1 ) = PACK(InData%Nodes_I,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_I) + END IF + IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) + END IF + IF ( .NOT. ALLOCATED(InData%Nodes_C) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Nodes_C)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_C))-1 ) = PACK(InData%Nodes_C,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Nodes_C) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__L + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__F + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%IDI__) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI__,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDI__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI__))-1 ) = PACK(InData%IDI__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI__) + END IF + IF ( .NOT. ALLOCATED(InData%IDI_Rb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_Rb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDI_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_Rb))-1 ) = PACK(InData%IDI_Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI_Rb) + END IF + IF ( .NOT. ALLOCATED(InData%IDI_F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDI_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_F))-1 ) = PACK(InData%IDI_F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDI_F) + END IF + IF ( .NOT. ALLOCATED(InData%IDL_L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDL_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL_L,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDL_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDL_L))-1 ) = PACK(InData%IDL_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDL_L) + END IF + IF ( .NOT. ALLOCATED(InData%IDC__) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC__,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC__))-1 ) = PACK(InData%IDC__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC__) + END IF + IF ( .NOT. ALLOCATED(InData%IDC_Rb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_Rb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_Rb))-1 ) = PACK(InData%IDC_Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_Rb) + END IF + IF ( .NOT. ALLOCATED(InData%IDC_L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_L,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_L))-1 ) = PACK(InData%IDC_L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_L) + END IF + IF ( .NOT. ALLOCATED(InData%IDC_F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDC_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_F))-1 ) = PACK(InData%IDC_F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDC_F) + END IF + IF ( .NOT. ALLOCATED(InData%IDR__) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR__,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR__,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IDR__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR__))-1 ) = PACK(InData%IDR__,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%IDR__) + END IF + IF ( .NOT. ALLOCATED(InData%ID__Rb) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__Rb,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__Rb,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__Rb))-1 ) = PACK(InData%ID__Rb,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__Rb) + END IF + IF ( .NOT. ALLOCATED(InData%ID__L) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__L,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__L))-1 ) = PACK(InData%ID__L,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__L) + END IF + IF ( .NOT. ALLOCATED(InData%ID__F) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__F,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__F,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%ID__F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__F))-1 ) = PACK(InData%ID__F,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%ID__F) + END IF + IF ( .NOT. ALLOCATED(InData%FGL) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FGL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FGL) + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMOutputs + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%UnJckF + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( .NOT. ALLOCATED(InData%MoutLst) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MoutLst2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MoutLst3) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst3,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst3,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) + CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst3 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutAll , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutReact , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllInt + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllDims + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutDec + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackParam + + SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_ParameterType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackParam' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%SDDeltaT = DbKiBuf( Db_Xferred ) + Db_Xferred = Db_Xferred + 1 + OutData%IntMethod = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF_red = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%Nmembers = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Elems)) DEALLOCATE(OutData%Elems) + ALLOCATE(OutData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Elems)>0) OutData%Elems = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Elems))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Elems) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) + ALLOCATE(OutData%ElemProps(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackelemproptype( Re_Buf, Db_Buf, Int_Buf, OutData%ElemProps(i1), ErrStat2, ErrMsg2 ) ! ElemProps + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%T_red)) DEALLOCATE(OutData%T_red) + ALLOCATE(OutData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%T_red) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesDOF)) DEALLOCATE(OutData%NodesDOF) + ALLOCATE(OutData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodesDOF,1), UBOUND(OutData%NodesDOF,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOF(i1), ErrStat2, ErrMsg2 ) ! NodesDOF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) + ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElemsDOF)) DEALLOCATE(OutData%ElemsDOF) + ALLOCATE(OutData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) + ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) + DEALLOCATE(mask2) + END IF + OutData%nDOFM = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%SttcSolve = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%ExtraMoment = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NOmegaM2)) DEALLOCATE(OutData%NOmegaM2) + ALLOCATE(OutData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%NOmegaM2)>0) OutData%NOmegaM2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%NOmegaM2))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%NOmegaM2) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! N2OmegaMJDamp not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%N2OmegaMJDamp)) DEALLOCATE(OutData%N2OmegaMJDamp) + ALLOCATE(OutData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%N2OmegaMJDamp)>0) OutData%N2OmegaMJDamp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%N2OmegaMJDamp))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%N2OmegaMJDamp) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MMB)) DEALLOCATE(OutData%MMB) + ALLOCATE(OutData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MMB)>0) OutData%MMB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MMB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MMB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FX not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FX)) DEALLOCATE(OutData%FX) + ALLOCATE(OutData%FX(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FX.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FX)>0) OutData%FX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FX))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FX) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%C1_11)) DEALLOCATE(OutData%C1_11) + ALLOCATE(OutData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_11.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%C1_11)>0) OutData%C1_11 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C1_11))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%C1_11) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_12 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%C1_12)) DEALLOCATE(OutData%C1_12) + ALLOCATE(OutData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_12.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%C1_12)>0) OutData%C1_12 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C1_12))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%C1_12) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_13)) DEALLOCATE(OutData%D1_13) + ALLOCATE(OutData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_13.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D1_13)>0) OutData%D1_13 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_13))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D1_13) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_14 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_14)) DEALLOCATE(OutData%D1_14) + ALLOCATE(OutData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_14.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D1_14)>0) OutData%D1_14 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_14))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D1_14) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FY not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FY)) DEALLOCATE(OutData%FY) + ALLOCATE(OutData%FY(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FY.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FY)>0) OutData%FY = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FY))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FY) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiM)) DEALLOCATE(OutData%PhiM) + ALLOCATE(OutData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiM)>0) OutData%PhiM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_61 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%C2_61)) DEALLOCATE(OutData%C2_61) + ALLOCATE(OutData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%C2_61)>0) OutData%C2_61 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C2_61))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%C2_61) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_62 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%C2_62)) DEALLOCATE(OutData%C2_62) + ALLOCATE(OutData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_62.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%C2_62)>0) OutData%C2_62 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C2_62))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%C2_62) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiRb_TI not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiRb_TI)) DEALLOCATE(OutData%PhiRb_TI) + ALLOCATE(OutData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiRb_TI)>0) OutData%PhiRb_TI = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiRb_TI))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiRb_TI) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_63 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D2_63)) DEALLOCATE(OutData%D2_63) + ALLOCATE(OutData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_63.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D2_63)>0) OutData%D2_63 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D2_63))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D2_63) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_64 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D2_64)) DEALLOCATE(OutData%D2_64) + ALLOCATE(OutData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_64.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%D2_64)>0) OutData%D2_64 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D2_64))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%D2_64) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F2_61 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F2_61)) DEALLOCATE(OutData%F2_61) + ALLOCATE(OutData%F2_61(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F2_61.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%F2_61)>0) OutData%F2_61 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F2_61))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%F2_61) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) + ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MBB)>0) OutData%MBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) + ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%KBB)>0) OutData%KBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%KBB) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) + ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%MBM)>0) OutData%MBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%MBM) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_st_g not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%UL_st_g)) DEALLOCATE(OutData%UL_st_g) + ALLOCATE(OutData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_st_g.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%UL_st_g)>0) OutData%UL_st_g = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_st_g))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%UL_st_g) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiL_T)) DEALLOCATE(OutData%PhiL_T) + ALLOCATE(OutData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiL_T)>0) OutData%PhiL_T = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiL_T))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiL_T) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiLInvOmgL2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PhiLInvOmgL2)) DEALLOCATE(OutData%PhiLInvOmgL2) + ALLOCATE(OutData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%PhiLInvOmgL2)>0) OutData%PhiLInvOmgL2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiLInvOmgL2))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%PhiLInvOmgL2) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KLLm1 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%KLLm1)) DEALLOCATE(OutData%KLLm1) + ALLOCATE(OutData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KLLm1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%KLLm1)>0) OutData%KLLm1 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KLLm1))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%KLLm1) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AM2Jac)) DEALLOCATE(OutData%AM2Jac) + ALLOCATE(OutData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2Jac.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%AM2Jac)>0) OutData%AM2Jac = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM2Jac))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%AM2Jac) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2JacPiv not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AM2JacPiv)) DEALLOCATE(OutData%AM2JacPiv) + ALLOCATE(OutData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%AM2JacPiv)>0) OutData%AM2JacPiv = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%AM2JacPiv))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%AM2JacPiv) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%TI)) DEALLOCATE(OutData%TI) + ALLOCATE(OutData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%TI)>0) OutData%TI = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TI))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%TI) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TIreact not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%TIreact)) DEALLOCATE(OutData%TIreact) + ALLOCATE(OutData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TIreact.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%TIreact)>0) OutData%TIreact = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TIreact))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%TIreact) + DEALLOCATE(mask2) + END IF + OutData%nNodes = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_I = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_C = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes_I)) DEALLOCATE(OutData%Nodes_I) + ALLOCATE(OutData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Nodes_I)>0) OutData%Nodes_I = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_I))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_I) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes_L)) DEALLOCATE(OutData%Nodes_L) + ALLOCATE(OutData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Nodes_L)>0) OutData%Nodes_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_L))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_C not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes_C)) DEALLOCATE(OutData%Nodes_C) + ALLOCATE(OutData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_C.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Nodes_C)>0) OutData%Nodes_C = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_C))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_C) + DEALLOCATE(mask2) + END IF + OutData%nDOFI__ = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_Rb = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_F = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFL_L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC__ = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_Rb = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_F = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFR__ = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__Rb = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__L = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__F = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI__ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI__)) DEALLOCATE(OutData%IDI__) + ALLOCATE(OutData%IDI__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI__)>0) OutData%IDI__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI__) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_Rb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI_Rb)) DEALLOCATE(OutData%IDI_Rb) + ALLOCATE(OutData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI_Rb)>0) OutData%IDI_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI_Rb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_F not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDI_F)) DEALLOCATE(OutData%IDI_F) + ALLOCATE(OutData%IDI_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDI_F)>0) OutData%IDI_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDI_F) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDL_L)) DEALLOCATE(OutData%IDL_L) + ALLOCATE(OutData%IDL_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDL_L)>0) OutData%IDL_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL_L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDL_L) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC__ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC__)) DEALLOCATE(OutData%IDC__) + ALLOCATE(OutData%IDC__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC__)>0) OutData%IDC__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC__) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_Rb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC_Rb)) DEALLOCATE(OutData%IDC_Rb) + ALLOCATE(OutData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC_Rb)>0) OutData%IDC_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_Rb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC_L)) DEALLOCATE(OutData%IDC_L) + ALLOCATE(OutData%IDC_L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC_L)>0) OutData%IDC_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_L) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_F not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDC_F)) DEALLOCATE(OutData%IDC_F) + ALLOCATE(OutData%IDC_F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDC_F)>0) OutData%IDC_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDC_F) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR__ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IDR__)) DEALLOCATE(OutData%IDR__) + ALLOCATE(OutData%IDR__(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR__.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IDR__)>0) OutData%IDR__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR__))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%IDR__) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__Rb not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ID__Rb)) DEALLOCATE(OutData%ID__Rb) + ALLOCATE(OutData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__Rb.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%ID__Rb)>0) OutData%ID__Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__Rb))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__Rb) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__L not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ID__L)) DEALLOCATE(OutData%ID__L) + ALLOCATE(OutData%ID__L(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__L.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%ID__L)>0) OutData%ID__L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__L))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__L) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__F not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ID__F)) DEALLOCATE(OutData%ID__F) + ALLOCATE(OutData%ID__F(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__F.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%ID__F)>0) OutData%ID__F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__F))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%ID__F) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FGL)) DEALLOCATE(OutData%FGL) + ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FGL)>0) OutData%FGL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FGL))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FGL) + DEALLOCATE(mask1) + END IF + OutData%NMOutputs = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%UnJckF = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MoutLst)) DEALLOCATE(OutData%MoutLst) + ALLOCATE(OutData%MoutLst(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst,1), UBOUND(OutData%MoutLst,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst(i1), ErrStat2, ErrMsg2 ) ! MoutLst + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MoutLst2)) DEALLOCATE(OutData%MoutLst2) + ALLOCATE(OutData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst2,1), UBOUND(OutData%MoutLst2,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst2(i1), ErrStat2, ErrMsg2 ) ! MoutLst2 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst3 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MoutLst3)) DEALLOCATE(OutData%MoutLst3) + ALLOCATE(OutData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst3.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MoutLst3,1), UBOUND(OutData%MoutLst3,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst3(i1), ErrStat2, ErrMsg2 ) ! MoutLst3 + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%OutParam)) DEALLOCATE(OutData%OutParam) + ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + OutData%OutAll = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + OutData%OutReact = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllInt = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllDims = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%OutDec = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_UnPackParam + + SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: SrcInputData + TYPE(SD_InputType), INTENT(INOUT) :: DstInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcInputData%TPMesh, DstInputData%TPMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcInputData%LMesh, DstInputData%LMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE SD_CopyInput + + SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) + TYPE(SD_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( InputData%TPMesh, ErrStat, ErrMsg ) + CALL MeshDestroy( InputData%LMesh, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInput + + SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_InputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! TPMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TPMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TPMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TPMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! LMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! LMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! LMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! LMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + CALL MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE SD_PackInput + + SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_InputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TPMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE SD_UnPackInput + + SUBROUTINE SD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_OutputType), INTENT(INOUT) :: SrcOutputData + TYPE(SD_OutputType), INTENT(INOUT) :: DstOutputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshCopy( SrcOutputData%Y1Mesh, DstOutputData%Y1Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL MeshCopy( SrcOutputData%Y2Mesh, DstOutputData%Y2Mesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN + i1_l = LBOUND(SrcOutputData%WriteOutput,1) + i1_u = UBOUND(SrcOutputData%WriteOutput,1) + IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN + ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%WriteOutput = SrcOutputData%WriteOutput +ENDIF + END SUBROUTINE SD_CopyOutput + + SUBROUTINE SD_DestroyOutput( OutputData, ErrStat, ErrMsg ) + TYPE(SD_OutputType), INTENT(INOUT) :: OutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOutput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + CALL MeshDestroy( OutputData%Y1Mesh, ErrStat, ErrMsg ) + CALL MeshDestroy( OutputData%Y2Mesh, ErrStat, ErrMsg ) +IF (ALLOCATED(OutputData%WriteOutput)) THEN + DEALLOCATE(OutputData%WriteOutput) +ENDIF + END SUBROUTINE SD_DestroyOutput + + SUBROUTINE SD_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_OutputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackOutput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Y1Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y1Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Y1Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Y1Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Y1Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Y2Mesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Y2Mesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Y2Mesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Y2Mesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no + IF ( ALLOCATED(InData%WriteOutput) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + CALL MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y1Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) + END IF + END SUBROUTINE SD_PackOutput + + SUBROUTINE SD_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_OutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + LOGICAL :: mask0 + LOGICAL, ALLOCATABLE :: mask1(:) + LOGICAL, ALLOCATABLE :: mask2(:,:) + LOGICAL, ALLOCATABLE :: mask3(:,:,:) + LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) + LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackOutput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y1Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y2Mesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) + ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) + DEALLOCATE(mask1) + END IF + END SUBROUTINE SD_UnPackOutput + + + SUBROUTINE SD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(u)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(u) - 1 + IF ( order .eq. 0 ) THEN + CALL SD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SD_Input_ExtrapInterp + + + SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 + TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + CALL MeshExtrapInterp1(u1%TPMesh, u2%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(u1%LMesh, u2%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE SD_Input_ExtrapInterp1 + + + SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 + TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 + TYPE(SD_InputType), INTENT(INOUT) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + CALL MeshExtrapInterp2(u1%TPMesh, u2%TPMesh, u3%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(u1%LMesh, u2%LMesh, u3%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + END SUBROUTINE SD_Input_ExtrapInterp2 + + + SUBROUTINE SD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y +! +! expressions below based on either +! +! f(t) = a +! f(t) = a + b * t, or +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 + REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + if ( size(t) .ne. size(y)) then + CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) + RETURN + endif + order = SIZE(y) - 1 + IF ( order .eq. 0 ) THEN + CALL SD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 1 ) THEN + CALL SD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE IF ( order .eq. 2 ) THEN + CALL SD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + ELSE + CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) + RETURN + ENDIF + END SUBROUTINE SD_Output_ExtrapInterp + + + SUBROUTINE SD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 + TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp1' + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + CALL MeshExtrapInterp1(y1%Y1Mesh, y2%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp1(y1%Y2Mesh, y2%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) + ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) + b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) + y_out%WriteOutput = y1%WriteOutput + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated + END SUBROUTINE SD_Output_ExtrapInterp1 + + + SUBROUTINE SD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 + TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 + TYPE(SD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation + REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp2' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" + ! we'll subtract a constant from the times to resolve some + ! numerical issues when t gets large (and to simplify the equations) + t = tin - tin(1) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + CALL MeshExtrapInterp2(y1%Y1Mesh, y2%Y1Mesh, y3%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + CALL MeshExtrapInterp2(y1%Y2Mesh, y2%Y2Mesh, y3%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) + ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) + b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*y1%WriteOutput + t(3)*y2%WriteOutput - t(2)*y3%WriteOutput ) / (t(2)*t(3)*(t(2) - t(3))) + y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated + END SUBROUTINE SD_Output_ExtrapInterp2 + +END MODULE SubDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/subdyn/src_soildyn/Yaml.f90 b/modules/subdyn/src_soildyn/Yaml.f90 new file mode 100644 index 000000000..ec3043c23 --- /dev/null +++ b/modules/subdyn/src_soildyn/Yaml.f90 @@ -0,0 +1,609 @@ +!.................................................................................................................................. +! LICENSING +! Copyright (C) 2013-2016 National Renewable Energy Laboratory +! +! This file is part of SubDyn. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** +module YAML + use NWTC_Library + + implicit none + + integer(IntKi), parameter :: INDENT_SPACES = 2 + + !> Write 1D or 2D array to file + interface yaml_write_array + module procedure yaml_write_array1I ! Single dimension array (Ary) of IntKi + module procedure yaml_write_array1R4 ! Single dimension array (Ary) of SiKi + module procedure yaml_write_array2R4 ! Two dimension array of SiKi + module procedure yaml_write_array1R8 ! Single dimension array (Ary) of R8Ki + module procedure yaml_write_array2R8 ! Two dimension array of R8Ki + module procedure yaml_write_array2I ! Two dimension array of IntKi + module procedure yaml_write_array1R16 ! Single dimension array (Ary) of QuKi + module procedure yaml_write_array2R16 ! Two dimension array of QuKi + end interface + + !> Write variable to file + interface yaml_write_var + module procedure yaml_write_varC ! Character + module procedure yaml_write_varI ! IntKi + module procedure yaml_write_varR4 ! SiKi + module procedure yaml_write_varR8 ! R8Ki + module procedure yaml_write_varR16 ! QuKi + end interface + private + + public :: yaml_write_var + public :: yaml_write_array + +contains + +! -------------------------------------------------------------------------------- +! --- Write variable +! -------------------------------------------------------------------------------- +!> Write simple key/variable to yaml file +subroutine yaml_write_varC(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + character(len=*), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varC + +subroutine yaml_write_varI(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + integer(IntKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varI + +subroutine yaml_write_varR4(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(SiKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR4 + +subroutine yaml_write_varR8(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(R8Ki), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR8 + +subroutine yaml_write_varR16(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Variable name + real(QuKi), intent(in ) :: val !< Value + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' + write(fid, Fmt, iostat=ErrStat) key, val, comment + else + Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' + write(fid, Fmt, iostat=ErrStat) key, val + endif + if (ErrStat /= 0) then + ErrMsg='Error writting variable '//trim(key)//' to YAML file' + return + endif +end subroutine yaml_write_varR16 + +! -------------------------------------------------------------------------------- +! --- Write array +! -------------------------------------------------------------------------------- +!> Write 1D or 2D array to file +subroutine yaml_write_array1I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + integer(IntKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1I + +subroutine yaml_write_array1R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(SiKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R4 + +subroutine yaml_write_array1R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(R8Ki), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R8 + +subroutine yaml_write_array1R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(QuKi), dimension(:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + integer :: nc ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nc = size(A,1) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nc==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + write(fid, Fmt, iostat=ErrStat) A(:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + endif +end subroutine yaml_write_array1R16 + +subroutine yaml_write_array2I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, label) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + integer(IntKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + logical, optional, intent(in ) :: label !< If present, add a index label at end of line + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + if (present(label)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"] # ",I0)' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif + do i=1,nr + if (present(label)) then + write(fid, Fmt, iostat=ErrStat) A(i,:), i + else + write(fid, Fmt, iostat=ErrStat) A(i,:) + endif + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2I + +subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(SiKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' + else + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif + endif + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R4 + +subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(R8Ki), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + if (present(level)) then + Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + else + Fmt = '' + endif + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' + else + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif + endif + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R8 + +subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) + integer(IntKi), intent(in ) :: fid !< File Unit + character(len=*), intent(in ) :: key !< Array name + real(QuKi), dimension(:,:), intent(in ) :: A !< Array + character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers + integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred + character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none + integer(IntKi), optional, intent(in ) :: level !< indentation level + character(len=*), optional, intent(in ) :: comment !< + character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line + integer :: nr, nc, i ! size (rows and columns) of A + integer :: nSpaces ! number of indentation spaces + character(256) :: Fmt + ErrStat = ErrID_None + ErrMsg = "" + nr = size(A,1) + nc = size(A,2) + + Fmt = '' + if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' + if (present(comment)) then + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) + + else + write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc + end if + + if (present(level)) then + Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' + else + Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' + endif + if (nr==0) then + write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) + else + if (nc==0) then + Fmt = '('//trim(Fmt)//'"- []")' + else + if (present(AllFmt)) then + Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' + else + Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' + endif + endif + do i=1,nr + write(fid, Fmt, iostat=ErrStat) A(i,:) + if (ErrStat /= 0) then + ErrMsg='Error writting array '//trim(key)//' to YAML file' + return + end if + end do + endif +end subroutine yaml_write_array2R16 + + +end module YAML diff --git a/modules/subdyn/src_soildyn/qsort_c_module.f90 b/modules/subdyn/src_soildyn/qsort_c_module.f90 new file mode 100644 index 000000000..553b25544 --- /dev/null +++ b/modules/subdyn/src_soildyn/qsort_c_module.f90 @@ -0,0 +1,61 @@ +!********************************************************************************************************************************** +module qsort_c_module +!This routine ASSUMES A is (m,2) dimensioned array +implicit none +public :: QsortC +private :: Partition + +contains + +recursive subroutine QsortC(A) + integer, intent(in out), dimension(:,:) :: A + integer :: iq + + if(size(A,1) > 1) then + call Partition(A, iq) + call QsortC(A(:iq-1, :)) + call QsortC(A(iq:, :)) + endif +end subroutine QsortC + +subroutine Partition(A, marker) + integer, intent(in out), dimension(:,:) :: A + integer, intent(out) :: marker + integer :: i, j, k + integer :: temp + integer :: x ! pivot point + x = A(1, 1) + i= 0 + j= size(A,1) + 1 + + + do + j = j-1 + do + if (A(j,1) <= x) exit + j = j-1 + end do + i = i+1 + do + if (A(i,1) >= x) exit + i = i+1 + end do + if (i < j) then + ! exchange A(i) and A(j) + do k=1,size(A,2) + temp = A(i,k) + A(i,k) = A(j,k) + A(j,k) = temp + end do !k + elseif (i == j) then + marker = i+1 + return + else + marker = i + return + endif + end do + +end subroutine Partition + +end module qsort_c_module \ No newline at end of file From a78c267ed6839e2054eec7919f38ec65abdeb8da Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jul 2020 16:58:03 -0600 Subject: [PATCH 239/377] FlexSub: allocation fix --- docs/source/user/api_change.rst | 2 +- modules/subdyn/src/SD_FEM.f90 | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index a17515d64..7856ab809 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -13,7 +13,7 @@ OpenFAST v2.3.0 to OpenFAST v2.4.0 ---------------------------------- Many changes were applied to SubDyn input file format. You may consult the following example: -:download:`(SubDyn's Input File) < subdyn/examples/OC4_Jacket_SD_Input.dat>`: +:download:`(SubDyn's Input File) <./subdyn/examples/OC4_Jacket_SD_Input.dat>`: and the online SubDyn documentation. ============================================= ==== =============== ======================================================================================================================================================================================================== diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index b86614e7c..fe7685bab 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1281,6 +1281,7 @@ SUBROUTINE CleanUp_BuildTMatrix() if (allocated(Tc) ) deallocate(Tc) if (allocated(IDOFOld)) deallocate(IDOFOld) if (allocated(INodesID)) deallocate(INodesID) + if (allocated(RA_DOFtilde)) deallocate(RA_DOFtilde) END SUBROUTINE CleanUp_BuildTMatrix !> Returns number of DOF after constraint reduction (via the matrix T) @@ -1803,6 +1804,8 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) enddo Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) + D_Add endif + if(allocated(K_Add)) deallocate(K_Add) + if(allocated(D_Add)) deallocate(D_Add) endif enddo END SUBROUTINE InsertJointStiffDamp From 56c93bf2b9399eca67d49fd892083950044c79e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jul 2020 17:11:48 -0600 Subject: [PATCH 240/377] FlexSub: renamed tilde to red, optimization when reduction not needed --- docs/source/user/api_change.rst | 24 ++--- modules/subdyn/src/SD_FEM.f90 | 112 +++++++++++++-------- modules/subdyn/src/SubDyn.f90 | 63 +++++++----- modules/subdyn/src/SubDyn_Registry.txt | 5 +- modules/subdyn/src/SubDyn_Types.f90 | 131 +++++++++++++------------ 5 files changed, 195 insertions(+), 140 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index 7856ab809..49e75deba 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -27,14 +27,14 @@ SubDyn 16 RayleighDamp 0.001, 0.003 SubDyn 17 GuyanDampSize 6 GuyanDampSize - Guyan damping matrix size (square, 6x6) [only if GuyanDampMod=2] SubDyn 18 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 SubDyn -23 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 -SubDyn - CablesSection -------------------------- CABLE PROPERTIES ------------------------------------- -SubDyn - CablesSection 0 NCablePropSets - Number of cable cable properties -SubDyn - CablesSection PropSetID EA MatDens T0 -SubDyn - CablesSection (-) (N) (kg/m) (N) -SubDyn - RigidSection ---------------------- RIGID LINK PROPERTIES ------------------------------------ -SubDyn - RigidSection 0 NRigidPropSets - Number of rigid link properties -SubDyn - RigidSection PropSetID MatDens -SubDyn - RigidSection (-) (kg/m) +SubDyn na CablesSection -------------------------- CABLE PROPERTIES ------------------------------------- +SubDyn na CablesSection 0 NCablePropSets - Number of cable cable properties +SubDyn na CablesSection PropSetID EA MatDens T0 +SubDyn na CablesSection (-) (N) (kg/m) (N) +SubDyn na RigidSection ---------------------- RIGID LINK PROPERTIES ------------------------------------ +SubDyn na RigidSection 0 NRigidPropSets - Number of rigid link properties +SubDyn na RigidSection PropSetID MatDens +SubDyn na RigidSection (-) (kg/m) ============================================= ==== =============== ======================================================================================================================================================================================================== @@ -45,10 +45,10 @@ Module Line Flag Name Example Val ============================================= ==== =============== ======================================================================================================================================================================================================== SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) -SubDyn - Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID -SubDyn - Members (-) (-) (-) (-) (-) (-) (-) -SubDyn - ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ -SubDyn - ConcentratedM (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) +SubDyn na Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID +SubDyn na Members (-) (-) (-) (-) (-) (-) (-) +SubDyn na ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ +SubDyn na ConcentratedM (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) ============================================= ==== =============== ======================================================================================================================================================================================================== diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index fe7685bab..ba8c0aedb 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -252,9 +252,9 @@ SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) T_ref(:,:)=0 DO I = 1, nDOF iDOF = DOF(I) ! DOF index in constrained system - iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) + iNode = p%DOFred2Nodes(iDOF,1) ! First column is node + nDOFPerNode = p%DOFred2Nodes(iDOF,2) ! Second column is number of DOF per node + iiDOF = p%DOFred2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) if ((iiDOF<1) .or. (iiDOF>6)) then ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal @@ -1160,7 +1160,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) integer(IntKi) :: nc !< Number of DOF after constraints applied integer(IntKi) :: nj real(ReKi) :: phat(3) !< Directional vector of the joint - type(IList), dimension(:), allocatable :: RA_DOFtilde ! DOF indices for each rigid assembly, in reduced system + type(IList), dimension(:), allocatable :: RA_DOFred ! DOF indices for each rigid assembly, in reduced system INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None @@ -1169,10 +1169,12 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) ! --- Misc inits nullify(IDOFNew) I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - allocate(p%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system - allocate(RA_DOFtilde(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system + allocate(p%NodesDOFred(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system + allocate(RA_DOFred(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system p%nDOF_red = nDOF_ConstraintReduced() + p%reduced = reductionNeeded() ! True if reduction needed, allow for optimization if not needed + if (DEV_VERSION) then print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF endif @@ -1207,13 +1209,13 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) if ( ia <= 0) then ! This rigid assembly has already been processed ! OLD: The DOF list is taken from the stored RA DOF list - ! call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) + ! call init_list(p%NodesDOFred(iNode), RA_DOFred(aID)%List, ErrStat2, ErrMsg2) ! NEW: this node has no DOFs - call init_list(p%NodesDOFtilde(iNode), 0, 0, ErrStat2, ErrMsg2) + call init_list(p%NodesDOFred(iNode), 0, 0, ErrStat2, ErrMsg2) if (DEV_VERSION) then print*,'The RA',aID,', has already been processed!' print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) - print*,'N',iNode,'It',RA_DOFtilde(aID)%List + print*,'N',iNode,'It',RA_DOFred(aID)%List endif cycle ! We pass to the next joint else @@ -1225,15 +1227,15 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) IDOFOld( (I-1)*6+1 : I*6 ) = p%NodesDOF(INodesID(I))%List(1:6) enddo - ! Storing DOF list for this RA (Note: same as NodesDOFtilde below) + ! Storing DOF list for this RA (Note: same as NodesDOFred below) nc=size(Tc,2) - call init_list(RA_DOFtilde(aID), (/ (iprev + i, i=1,nc) /), ErrStat2, ErrMsg2); + call init_list(RA_DOFred(aID), (/ (iprev + i, i=1,nc) /), ErrStat2, ErrMsg2); endif else ! --- Regular cantilever joint ! TODO/NOTE: We could apply fixed constraint/BC here, returning Tc as a 6xn matrix with n<6 - ! Extreme case would be Tc: 6*0, in which case NodesDOFtilde would be empty ([]) + ! Extreme case would be Tc: 6*0, in which case NodesDOFred would be empty ([]) allocate(Tc(1:6,1:6)) allocate(IDOFOld(1:6)) Tc=I6 @@ -1247,9 +1249,9 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return endif nc=size(Tc,2) - call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) - p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) - IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations + call init_list(p%NodesDOFred(iNode), nc, 0, ErrStat2, ErrMsg2) + p%NodesDOFred(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) + IDOFNew => p%NodesDOFred(iNode)%List(1:nc) ! alias to shorten notations !print*,'N',iNode,'I ',IDOFOld !print*,'N',iNode,'It',IDOFNew Tred(IDOFOld, IDOFNew) = Tc @@ -1281,7 +1283,7 @@ SUBROUTINE CleanUp_BuildTMatrix() if (allocated(Tc) ) deallocate(Tc) if (allocated(IDOFOld)) deallocate(IDOFOld) if (allocated(INodesID)) deallocate(INodesID) - if (allocated(RA_DOFtilde)) deallocate(RA_DOFtilde) + if (allocated(RA_DOFred)) deallocate(RA_DOFred) END SUBROUTINE CleanUp_BuildTMatrix !> Returns number of DOF after constraint reduction (via the matrix T) @@ -1326,6 +1328,30 @@ INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() endif end do END FUNCTION nDOF_ConstraintReduced + + !> return true if reduction needed (i.e. special joints, special elements) + logical FUNCTION reductionNeeded() + integer(IntKi) :: i + integer(IntKi) :: myType + reductionNeeded=.false. + ! Rigid or cable links + do i =1,size(p%Elems,1) + myType = p%Elems(i, iMType) + if (any((/idMemberCable, idMemberRigid/)==myType)) then + reductionNeeded=.true. + return + endif + enddo + ! Special joints + do i = 1, p%nNodes + myType = Init%Nodes(i,iJointType) + if (any((/idJointPin, idJointUniversal, idJointBall/)==myType)) then + reductionNeeded=.true. + return + endif + enddo + end FUNCTION reductionNeeded + END SUBROUTINE BuildTMatrix !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector @@ -1353,36 +1379,38 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return ! --- DOF elimination for system matrices and RHS vector - ! Temporary backup of M and K of full system - call move_alloc(Init%M, MM) - call move_alloc(Init%K, KK) - call move_alloc(Init%FG, FF) - ! Reallocating nDOF = p%nDOF_red + if (p%reduced) then + ! Temporary backup of M and K of full system + call move_alloc(Init%M, MM) + call move_alloc(Init%K, KK) + call move_alloc(Init%FG, FF) + ! Reallocating + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + ! Elimination + Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) + Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) + Init%FG = matmul(transpose(p%T_red), FF) + + ! --- Triggers for storage of DOF indices, replacing with indices in constrained system + CALL ReInitBCs(Init, p) + CALL ReInitIntFc(Init, p) + endif CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix - CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - ! Elimination - Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) - Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) - Init%FG = matmul(transpose(p%T_red), FF) Init%D = 0 !< Used for additional stiffness - ! --- Triggers for storage of DOF indices, replacing with indices in constrained system - CALL ReInitBCs(Init, p) - CALL ReInitIntFc(Init, p) - ! --- Creating a convenient Map from DOF to Nodes - call AllocAry(p%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; - p%DOFtilde2Nodes=-999 + call AllocAry(p%DOFred2Nodes, p%nDOF_red, 3, 'DOFred2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; + p%DOFred2Nodes=-999 do iNode=1,p%nNodes - nDOFPerNode = len(p%NodesDOFtilde(iNode)) + nDOFPerNode = len(p%NodesDOFred(iNode)) do iiDOF = 1, nDOFPerNode - iDOF = p%NodesDOFtilde(iNode)%List(iiDOF) - p%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index - p%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node - p%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node + iDOF = p%NodesDOFred(iNode)%List(iiDOF) + p%DOFred2Nodes(iDOF,1) = iNode ! First column is Node index + p%DOFred2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node + p%DOFred2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node enddo enddo @@ -1412,7 +1440,7 @@ SUBROUTINE ReInitBCs(Init, p) DO I = 1, p%nNodes_C iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 ! TODO NOTE here assumptions that 6 DOF are present - Init%BCs( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) + Init%BCs( (I-1)*6+J, 1) = p%NodesDOFred(iNode)%List(J) ! DOF number (constrained) ENDDO ENDDO END SUBROUTINE ReInitBCs @@ -1425,7 +1453,7 @@ SUBROUTINE ReInitIntFc(Init, p) DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) + Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFred(iNode)%List(J) ! DOF number (unconstrained) ENDDO ENDDO END SUBROUTINE ReInitIntFc @@ -1782,7 +1810,7 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) else if ( JType == idJointUniversal ) then; iStart=5; nSpace=1; else if ( JType == idJointPin ) then; iStart=6; nSpace=0; endif - Ifreerot=>p%NodesDOFtilde(iNode)%List(iStart:) + Ifreerot=>p%NodesDOFred(iNode)%List(iStart:) nFreeRot = size(Ifreerot) ! Creating matrices of 0, and -K and nK on diagonals allocate(K_Add(1:nFreeRot,1:nFreeRot)); diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 752da1e1a..df69db3ff 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -195,6 +195,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + if (p%ExtraMoment) call WrScr(' Extra moment will be included in Y1') ! -------------------------------------------------------------------------------- ! --- Manipulation of Init and parameters @@ -448,9 +449,15 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_red_dotdot(p%IDC_Rb)= 0 ! TODO m%U_red_dotdot(p%ID__F) = 0 - m%U_full = matmul(p%T_red, m%U_red) - m%U_full_dot = matmul(p%T_red, m%U_red_dot) - m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) + if (p%reduced) then + m%U_full = matmul(p%T_red, m%U_red) + m%U_full_dot = matmul(p%T_red, m%U_red_dot) + m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) + else + m%U_full = m%U_red + m%U_full_dot = m%U_red_dot + m%U_full_dotdot = m%U_red_dotdot + endif ! --- Place displacement/velocity/acceleration into Y2 output mesh DO iSDNode = 1,p%nNodes @@ -1802,8 +1809,8 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 - ! --- Remove SSI from Mass and stiffness matrix (NOTE: use NodesDOFtilde, reduced matrix) - CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.True.); + ! --- Remove SSI from Mass and stiffness matrix (NOTE: use NodesDOFred, reduced matrix) + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFred, Init, p, ErrStat2, ErrMsg2, Substract=.True.); ! --- Perform Guyan reduction to get MBB nR = p%nDOFR__ ! Using interface + reaction nodes @@ -1828,7 +1835,7 @@ SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) if(allocated(OmegaL)) deallocate(OmegaL) ! --- Insert SSI from Mass and stiffness matrix again - CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return + CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFred, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return contains logical function Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1861,6 +1868,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' + real(ReKi) :: dt_max, freq_max + character(ErrMsgLen) :: Info ErrStat = ErrID_None ErrMsg = '' @@ -2010,6 +2019,13 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2); if(Failed()) return END IF + freq_max =maxval(OmegaL(1:p%nDOFM))/TwoPi + dt_max = 1/(20*freq_max) + if (p%SDDeltaT>dt_max) then + print*,'Warning: time step appears too large compared to max SubDyn frequency.' + endif + write(Info,'(3x,A,F8.5,A,F8.5,A,F8.5)') 'SubDyn recommended dt:',dt_max, ' - Current dt:', p%SDDeltaT,' - Max frequency:', freq_max + call WrScr(Info) ELSE ! no retained modes, so ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables @@ -2020,7 +2036,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! FY (with 0 retained modes) p%FY = - MATMUL( TI_transpose, FGB ) - END IF CONTAINS @@ -2172,7 +2187,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) p%nDOFI_Rb=0 ! Leader p%nDOFI_F =0 ! Fixed do iiNode= 1,p%nNodes_I - p%nDOFI__ = p%nDOFI__ + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) + p%nDOFI__ = p%nDOFI__ + len(p%NodesDOFred( p%Nodes_I(iiNode,1) )) p%nDOFI_Rb= p%nDOFI_Rb+ count(p%Nodes_I(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs p%nDOFI_F = p%nDOFI_F + count(p%Nodes_I(iiNode, 2:7)==idBC_Fixed) ! assumes 6 DOFs enddo @@ -2186,7 +2201,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) p%nDOFC_F =0 ! Fixed p%nDOFC_L =0 ! Internal do iiNode= 1,p%nNodes_C - p%nDOFC__ = p%nDOFC__ + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) + p%nDOFC__ = p%nDOFC__ + len(p%NodesDOFred( p%Nodes_C(iiNode,1) )) p%nDOFC_Rb= p%nDOFC_Rb+ count(p%Nodes_C(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs p%nDOFC_F = p%nDOFC_F + count(p%Nodes_C(iiNode, 2:7)==idBC_Fixed ) ! assumes 6 DOFs p%nDOFC_L = p%nDOFC_L + count(p%Nodes_C(iiNode, 2:7)==idBC_Internal) ! assumes 6 DOFs @@ -2200,7 +2215,7 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) ! DOFs of internal nodes p%nDOFL_L=0 do iiNode= 1,p%nNodes_L - p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) + p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFred( p%Nodes_L(iiNode,1) )) enddo if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then call Fatal('Error in distributing internal DOFs, total number of internal DOF('//num2lstr(p%nDOFL_L)//') does not equal total number of DOF('//num2lstr(p%nDOF_red)//') minus interface and reaction ('//num2lstr(p%nDOFR__)//')'); return @@ -2241,14 +2256,14 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) iNode = p%Nodes_I(iiNode,1) do J = 1, 6 ! DOFs: ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss c__=c__+1 - p%IDI__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDI__(c__) = p%NodesDOFred(iNode)%List(J) ! DOF number if (p%Nodes_I(iiNode, J+1)==idBC_Leader) then c_B=c_B+1 - p%IDI_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDI_Rb(c_B) = p%NodesDOFred(iNode)%List(J) ! DOF number elseif (p%Nodes_I(iiNode, J+1)==idBC_Fixed) then ! c_F=c_F+1 - p%IDI_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDI_F(c_F) = p%NodesDOFred(iNode)%List(J) ! DOF number endif enddo enddo @@ -2261,18 +2276,18 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) iNode = p%Nodes_C(iiNode,1) do J = 1, 6 ! DOFs c__=c__+1 - p%IDC__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDC__(c__) = p%NodesDOFred(iNode)%List(J) ! DOF number if (p%Nodes_C(iiNode, J+1)==idBC_Leader) then c_B=c_B+1 - p%IDC_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDC_Rb(c_B) = p%NodesDOFred(iNode)%List(J) ! DOF number elseif (p%Nodes_C(iiNode, J+1)==idBC_Fixed) then ! c_F=c_F+1 - p%IDC_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDC_F(c_F) = p%NodesDOFred(iNode)%List(J) ! DOF number elseif (p%Nodes_C(iiNode, J+1)==idBC_Internal) then ! c_L=c_L+1 - p%IDC_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDC_L(c_L) = p%NodesDOFred(iNode)%List(J) ! DOF number endif enddo enddo @@ -2290,9 +2305,9 @@ SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) c_L=0; ! Counters over L dofs do iiNode= 1,p%nNodes_L !Loop on interface nodes iNode = p%Nodes_L(iiNode,1) - do J = 1, size(p%NodesDOFtilde(iNode)%List) ! DOFs + do J = 1, size(p%NodesDOFred(iNode)%List) ! DOFs c_L=c_L+1 - p%IDL_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number + p%IDL_L(c_L) = p%NodesDOFred(iNode)%List(J) ! DOF number enddo enddo @@ -2399,8 +2414,12 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) endif endif ! --- Reduced vector of external force - m%Fext_red = matmul(transpose(p%T_red), m%Fext) - UFL= m%Fext_red(p%ID__L) + if (p%reduced) then + m%Fext_red = matmul(transpose(p%T_red), m%Fext) + UFL= m%Fext_red(p%ID__L) + else + UFL= m%Fext(p%ID__L) + endif END SUBROUTINE GetExtForceOnInternalDOF @@ -2516,7 +2535,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A)') '#Index map from DOF to nodes' WRITE(UnSum, '(A)') '# Node No., DOF/Node, NodalDOF' - call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) + call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFred2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) ! Nodes properties write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index a3bb28f0e..cfbfc4e6a 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -173,11 +173,12 @@ typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub struc typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" # --- Constraints reduction +typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" -typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" +typedef ^ ^ IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" -typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" +typedef ^ ^ IntKi DOFred2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" # --- CB reduction typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 748c85bf1..ed2004e7a 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -212,11 +212,12 @@ MODULE SubDyn_Types INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] + LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] + TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFred !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFred2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] @@ -6605,6 +6606,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF + DstParamData%reduced = SrcParamData%reduced IF (ALLOCATED(SrcParamData%T_red)) THEN i1_l = LBOUND(SrcParamData%T_red,1) i1_u = UBOUND(SrcParamData%T_red,1) @@ -6635,18 +6637,18 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF -IF (ALLOCATED(SrcParamData%NodesDOFtilde)) THEN - i1_l = LBOUND(SrcParamData%NodesDOFtilde,1) - i1_u = UBOUND(SrcParamData%NodesDOFtilde,1) - IF (.NOT. ALLOCATED(DstParamData%NodesDOFtilde)) THEN - ALLOCATE(DstParamData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%NodesDOFred)) THEN + i1_l = LBOUND(SrcParamData%NodesDOFred,1) + i1_u = UBOUND(SrcParamData%NodesDOFred,1) + IF (.NOT. ALLOCATED(DstParamData%NodesDOFred)) THEN + ALLOCATE(DstParamData%NodesDOFred(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOFred.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DO i1 = LBOUND(SrcParamData%NodesDOFtilde,1), UBOUND(SrcParamData%NodesDOFtilde,1) - CALL SD_Copyilist( SrcParamData%NodesDOFtilde(i1), DstParamData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) + DO i1 = LBOUND(SrcParamData%NodesDOFred,1), UBOUND(SrcParamData%NodesDOFred,1) + CALL SD_Copyilist( SrcParamData%NodesDOFred(i1), DstParamData%NodesDOFred(i1), CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO @@ -6665,19 +6667,19 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%ElemsDOF = SrcParamData%ElemsDOF ENDIF -IF (ALLOCATED(SrcParamData%DOFtilde2Nodes)) THEN - i1_l = LBOUND(SrcParamData%DOFtilde2Nodes,1) - i1_u = UBOUND(SrcParamData%DOFtilde2Nodes,1) - i2_l = LBOUND(SrcParamData%DOFtilde2Nodes,2) - i2_u = UBOUND(SrcParamData%DOFtilde2Nodes,2) - IF (.NOT. ALLOCATED(DstParamData%DOFtilde2Nodes)) THEN - ALLOCATE(DstParamData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%DOFred2Nodes)) THEN + i1_l = LBOUND(SrcParamData%DOFred2Nodes,1) + i1_u = UBOUND(SrcParamData%DOFred2Nodes,1) + i2_l = LBOUND(SrcParamData%DOFred2Nodes,2) + i2_u = UBOUND(SrcParamData%DOFred2Nodes,2) + IF (.NOT. ALLOCATED(DstParamData%DOFred2Nodes)) THEN + ALLOCATE(DstParamData%DOFred2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOFred2Nodes.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%DOFtilde2Nodes = SrcParamData%DOFtilde2Nodes + DstParamData%DOFred2Nodes = SrcParamData%DOFred2Nodes ENDIF DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve @@ -7421,17 +7423,17 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%NodesDOF) ENDIF -IF (ALLOCATED(ParamData%NodesDOFtilde)) THEN -DO i1 = LBOUND(ParamData%NodesDOFtilde,1), UBOUND(ParamData%NodesDOFtilde,1) - CALL SD_Destroyilist( ParamData%NodesDOFtilde(i1), ErrStat, ErrMsg ) +IF (ALLOCATED(ParamData%NodesDOFred)) THEN +DO i1 = LBOUND(ParamData%NodesDOFred,1), UBOUND(ParamData%NodesDOFred,1) + CALL SD_Destroyilist( ParamData%NodesDOFred(i1), ErrStat, ErrMsg ) ENDDO - DEALLOCATE(ParamData%NodesDOFtilde) + DEALLOCATE(ParamData%NodesDOFred) ENDIF IF (ALLOCATED(ParamData%ElemsDOF)) THEN DEALLOCATE(ParamData%ElemsDOF) ENDIF -IF (ALLOCATED(ParamData%DOFtilde2Nodes)) THEN - DEALLOCATE(ParamData%DOFtilde2Nodes) +IF (ALLOCATED(ParamData%DOFred2Nodes)) THEN + DEALLOCATE(ParamData%DOFred2Nodes) ENDIF IF (ALLOCATED(ParamData%NOmegaM2)) THEN DEALLOCATE(ParamData%NOmegaM2) @@ -7669,6 +7671,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! reduced Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no IF ( ALLOCATED(InData%T_red) ) THEN Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension @@ -7697,24 +7700,24 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no - IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde + Int_BufSz = Int_BufSz + 1 ! NodesDOFred allocated yes/no + IF ( ALLOCATED(InData%NodesDOFred) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodesDOFred upper/lower bounds for each dimension + DO i1 = LBOUND(InData%NodesDOFred,1), UBOUND(InData%NodesDOFred,1) + Int_BufSz = Int_BufSz + 3 ! NodesDOFred: size of buffers for each call to pack subtype + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFred(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFred CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde + IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFred Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde + IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFred Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde + IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFred Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -7725,10 +7728,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF END IF - Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no - IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes + Int_BufSz = Int_BufSz + 1 ! DOFred2Nodes allocated yes/no + IF ( ALLOCATED(InData%DOFred2Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! DOFred2Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DOFred2Nodes) ! DOFred2Nodes END IF Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve @@ -8182,6 +8185,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%reduced , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%T_red) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8239,18 +8244,18 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN + IF ( .NOT. ALLOCATED(InData%NodesDOFred) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFred,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFred,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde + DO i1 = LBOUND(InData%NodesDOFred,1), UBOUND(InData%NodesDOFred,1) + CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFred(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFred CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -8296,21 +8301,21 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) END IF - IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN + IF ( .NOT. ALLOCATED(InData%DOFred2Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFred2Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFred2Nodes,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFred2Nodes,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFred2Nodes,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) + IF (SIZE(InData%DOFred2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFred2Nodes))-1 ) = PACK(InData%DOFred2Nodes,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DOFred2Nodes) END IF IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM Int_Xferred = Int_Xferred + 1 @@ -9364,6 +9369,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + OutData%reduced = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9446,20 +9453,20 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFred not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) - ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%NodesDOFred)) DEALLOCATE(OutData%NodesDOFred) + ALLOCATE(OutData%NodesDOFred(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFred.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) + DO i1 = LBOUND(OutData%NodesDOFred,1), UBOUND(OutData%NodesDOFred,1) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -9493,7 +9500,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde + CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFred(i1), ErrStat2, ErrMsg2 ) ! NodesDOFred CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -9528,7 +9535,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFred2Nodes not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -9538,10 +9545,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) - ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%DOFred2Nodes)) DEALLOCATE(OutData%DOFred2Nodes) + ALLOCATE(OutData%DOFred2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFred2Nodes.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) @@ -9550,8 +9557,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) + IF (SIZE(OutData%DOFred2Nodes)>0) OutData%DOFred2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFred2Nodes))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DOFred2Nodes) DEALLOCATE(mask2) END IF OutData%nDOFM = IntKiBuf( Int_Xferred ) From 86ca3aa847d343a21ce36ac12858a8de5f274d36 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 8 Jul 2020 19:15:31 -0600 Subject: [PATCH 241/377] FlexSub: adding joint damping --- modules/subdyn/src/FEM.f90 | 104 ++++++++++++++-- modules/subdyn/src/SubDyn.f90 | 108 ++++++++++------ modules/subdyn/src/SubDyn_Registry.txt | 5 +- modules/subdyn/src/SubDyn_Types.f90 | 165 +++++++++++++++++-------- 4 files changed, 282 insertions(+), 100 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index ceb18fd0f..e0d325b24 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -232,7 +232,7 @@ end subroutine ChessBoard !! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) !! MRL = M(IDR, IDL), KRR = K(IDR, IDL) !! NOTE: generic code -SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) +SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL, CC, CRR, CLL, CRL) REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix INTEGER(IntKi), INTENT(IN ) :: nR @@ -248,6 +248,10 @@ SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) + REAL(ReKi), OPTIONAL, INTENT(IN ) :: CC(:,:) !< Stiffness matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CRR(nR, nR) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CLL(nL, nL) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CRL(nR, nL) INTEGER(IntKi) :: I, J, II, JJ ! RR: Leader/Boundary DOFs @@ -292,6 +296,32 @@ SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, enddo endif endif + if (present(CC)) then + ! RR: Leader/Boundary DOFs + DO I = 1, nR + II = IDR(I) + DO J = 1, nR + JJ = IDR(J) + CRR(I, J) = CC(II, JJ) + ENDDO + ENDDO + ! LL: Interior/follower DOFs + DO I = 1, nL + II = IDL(I) + DO J = 1, nL + JJ = IDL(J) + CLL(I, J) = CC(II, JJ) + ENDDO + ENDDO + ! RL: cross terms + DO I = 1, nR + II = IDR(I) + DO J = 1, nL + JJ = IDL(J) + CRL(I, J) = CC(II, JJ) + ENDDO + ENDDO + endif END SUBROUTINE BreakSysMtrx !------------------------------------------------------------------------------------------------------ @@ -305,7 +335,7 @@ END SUBROUTINE BreakSysMtrx !! - Possibility to get more CB modes using the input nM_Out>nM !! !! NOTE: generic code -SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM) +SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM, CC, CBB, CBM, CMM) REAL(ReKi), INTENT(IN ) :: MM(:, :) !< Mass matrix REAL(ReKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix INTEGER(IntKi), INTENT(IN ) :: nR @@ -325,6 +355,10 @@ SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL + REAL(ReKi), OPTIONAL, INTENT(IN ) :: CC(:, :) !< Damping matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBB(nR, nR) !< Guyan Damping matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBM(nR, nM) !< Coupling Damping matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CMM(nM, nM) !< Craig-Bampton Damping matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None INTEGER(IntKi) :: ErrStat2 @@ -337,6 +371,9 @@ SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, real(ReKi), allocatable :: KRR(:, :) real(ReKi), allocatable :: KLL(:, :) real(ReKi), allocatable :: KRL(:, :) + real(ReKi), allocatable :: CRR(:, :) + real(ReKi), allocatable :: CRL(:, :) + real(ReKi), allocatable :: CLL(:, :) ! --- Break system CALL AllocAry(MRR, nR, nR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry(MLL, nL, nL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -344,14 +381,17 @@ SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, CALL AllocAry(KRR, nR, nR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry(KLL, nL, nL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry(KRL, nR, nL, 'matrix KRL', ErrStat2, ErrMsg2 ); if(Failed()) return - if (present(FG).and.present(FGR).and.present(FGL)) then - call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) - else - call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL) + if (present(CC)) then + CALL AllocAry(CRR, nR, nR, 'matrix CRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(CLL, nL, nL, 'matrix CLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(CRL, nR, nL, 'matrix CRL', ErrStat2, ErrMsg2 ); if(Failed()) return endif + call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG=FG, FGR=FGR, FGL=FGL, CC=CC, CRR=CRR, CLL=CLL, CRL=CRL) ! --- CB reduction call CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& !< Inputs - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) !< Outputs + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2,& !< Outputs + CRR=CRR, CLL=CLL, CRL=CRL,& !< Optional inputs + CBB=CBB, CBM=CBM, CMM=CMM) !< Optional Outputs if(Failed()) return ! --- Reduction of force if provided @@ -378,6 +418,9 @@ subroutine CleanUp() IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) + IF(ALLOCATED(CRR) ) DEALLOCATE(CRR) + IF(ALLOCATED(CLL) ) DEALLOCATE(CLL) + IF(ALLOCATED(CRL) ) DEALLOCATE(CRL) end subroutine END SUBROUTINE CraigBamptonReduction @@ -392,13 +435,14 @@ END SUBROUTINE CraigBamptonReduction !! !! NOTE: generic code SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,& + CRR, CLL, CRL, CBB, CBM, CMM) USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf INTEGER(IntKi), INTENT( in) :: nR INTEGER(IntKi), INTENT( in) :: nL INTEGER(IntKi), INTENT( in) :: nM_Out INTEGER(IntKi), INTENT( in) :: nM - REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Paritioned matrices + REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Partitioned mass and stiffness matrices REAL(ReKi), INTENT( IN) :: MLL( nL, nL) REAL(ReKi), INTENT( IN) :: MRL( nR, nL) REAL(ReKi), INTENT( IN) :: KRR( nR, nR) @@ -410,8 +454,14 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes REAL(ReKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(ReKi), OPTIONAL, INTENT( IN) :: CRR( nR, nR) !< Partitioned damping matrices + REAL(ReKi), OPTIONAL, INTENT( IN) :: CLL( nL, nL) + REAL(ReKi), OPTIONAL, INTENT( IN) :: CRL( nR, nL) + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBB( nR, nR) !< Guyan damping matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBM( nR, nM) !< Coupling damping matrix + REAL(ReKi), OPTIONAL, INTENT( OUT) :: CMM( nM, nM) !< CB damping matrix ! LOCAL VARIABLES REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] @@ -451,9 +501,20 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) ENDDO DEALLOCATE(MU) + if (present(CRR)) then + ! CB damping CMM = PhiL^T CLL PhiL + CALL AllocAry( Temp , nM, nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return + CALL AllocAry( MU , nM, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return + MU = TRANSPOSE(PhiL(1:nL, 1:nM)) + Temp = MATMUL( MU, CLL ) + CMM = MATMUL( Temp, PhiL(1:nL, 1:nM) ) + DEALLOCATE(MU) + DEALLOCATE(Temp) + endif else PhiL = 0.0_ReKi OmegaL = 0.0_ReKi + if (present(CRR)) CMM = 0.0_ReKi end if if (nL>0) then @@ -482,11 +543,32 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR KBB = MATMUL(KRL, PhiR) KBB = KBB + KRR + + if (present(CRR)) then + ! Guyan damping CBB = CRR + (CRL*PhiR) + (CRL*PhiR)^T + PhiR^T*CLL*PhiR + PhiR_T_MLL = TRANSPOSE(PhiR) + PhiR_T_MLL = MATMUL(PhiR_T_MLL, CLL) + CBB = MATMUL(CRL, PhiR) + CBB = CRR + CBB + TRANSPOSE( CBB ) + MATMUL( PhiR_T_MLL, PhiR ) + ! Cross coupling CMB = PhiM^T*CLR + PhiM^T CLL PhiR + ! CBM = CRL*PhiM + PhiR^T CLL^T PhiM (NOTE: assuming CLL symmetric) + IF ( nM == 0) THEN + CBM = 0.0_ReKi + CMM = 0.0_ReKi + ELSE + CBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation + CBM = MATMUL( CRL, PhiL(:,1:nM) ) + CBM !This had PhiM + ENDIF + endif else PhiR(1:nL,1:nR) = 0.0_ReKi ! Empty MBM (1:nR,1:nM) = 0.0_ReKi ! Empty MBB = MRR KBB = KRR + if (present(CRR)) then + CBB=CRR + CBM=0.0_ReKi + endif endif call CleanUp() diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index df69db3ff..f167f56c6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -612,8 +612,8 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) - !dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX + !dxdt%qmdot = -p%KMMDiag*x%qm + p%CMMDiag*x%qmdot - matmul(p%CMB,m%udotdot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX END SUBROUTINE SD_CalcContStateDeriv @@ -1612,7 +1612,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array - junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D !.................................................... @@ -1704,13 +1704,16 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%CBB, nR, nR, 'CB%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%CBM, nR, nM, 'CB%CBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( CB%CMM, nM, nM, 'CB%CMM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%PhiL, nL, nM_out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& - Init%FG, FGR, FGL, FGB, FGM) + Init%FG, FGR, FGL, FGB, FGM, Init%D, CB%CBB, CB%CBM, CB%CMM) ! TODO if(Failed()) return CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1721,7 +1724,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) PhiRb=CB%PhiR ! Remove me in the future endif ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%CBB, CB%CBM, CB%CMM, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1757,11 +1760,15 @@ subroutine applyConstr(CBParams, FGB, PhiRb) !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(ReKi), ALLOCATABLE :: MBBb(:, :) REAL(ReKi), ALLOCATABLE :: MBMb(:, :) + REAL(ReKi), ALLOCATABLE :: CBBb(:, :) + REAL(ReKi), ALLOCATABLE :: CBMb(:, :) REAL(ReKi), ALLOCATABLE :: KBBb(:, :) REAL(ReKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); + CALL AllocAry( CBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix CBBb', ErrStat2, ErrMsg2 ); + CALL AllocAry( CBmb, p%nDOF__Rb, p%nDOFM, 'matrix CBmb', ErrStat2, ErrMsg2 ); CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); @@ -1773,18 +1780,24 @@ subroutine applyConstr(CBParams, FGB, PhiRb) ! TODO avoid this all together MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) + CBBb = CBparams%CBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) IF (p%nDOFM > 0) THEN MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) + CBMb = CBparams%CBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) END IF FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) deallocate(CBparams%MBB) deallocate(CBparams%KBB) deallocate(CBparams%MBM) + deallocate(CBparams%CMM) + deallocate(CBparams%CBM) !deallocate(CBparams%PhiR) call move_alloc(MBBb, CBparams%MBB) call move_alloc(KBBb, CBparams%KBB) call move_alloc(MBMb, CBparams%MBM) + call move_alloc(CBBb, CBparams%CBB) + call move_alloc(CBMb, CBparams%CBM) call move_alloc(FGBb, FGB) !call move_alloc(PhiRb, CBparams%PhiR) end subroutine applyConstr @@ -1845,13 +1858,16 @@ END SUBROUTINE SD_Guyan_RigidBodyMass !------------------------------------------------------------------------------------------------------ !> Set parameters to compute state and output equations -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, CBBb, CBMb, CMM, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan mass matrix REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) - REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) + REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan stiffness matrix + REAL(ReKi), INTENT(IN ) :: CBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan damping + REAL(ReKi), INTENT(IN ) :: CBMb( p%nDOF__Rb, p%nDOFM) ! Cross damping + REAL(ReKi), INTENT(IN ) :: CMM ( p%nDOFM , p%nDOFM) ! CB damping integer(IntKi), INTENT(IN ) :: nM_out REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) @@ -1915,35 +1931,45 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !............................... p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt + p%CBB = MATMUL( MATMUL( TI_transpose, CBBb ), p%TI) != CBBt ! 6x6 Guyan Damping matrix if (Init%GuyanDampMod == idGuyanDamp_None) then ! No Damping - p%CBB=0.0_ReKi + p%CBB = p%CBB + 0.0_ReKi elseif (Init%GuyanDampMod == idGuyanDamp_Rayleigh) then ! Rayleigh Damping - p%CBB = Init%RayleighDamp(1) * p%MBB + Init%RayleighDamp(2) * p%KBB + p%CBB = p%CBB + Init%RayleighDamp(1) * p%MBB + Init%RayleighDamp(2) * p%KBB elseif (Init%GuyanDampMod == idGuyanDamp_66) then ! User 6x6 matrix if (size(p%CBB,1)/=6) then ErrMsg='Cannot use 6x6 Guyan Damping matrix, number of interface DOFs is'//num2lstr(size(p%CBB,1)); ErrStat=ErrID_Fatal; return endif - p%CBB = Init%GuyanDampMat + p%CBB = p%CBB + Init%GuyanDampMat endif !p%D1_15=-TI_transpose !this is 6x6NIN IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 - ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt - CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') + ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt + CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return + p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt + !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, CBMb, 0.0_ReKi, p%CBM, ErrStat2, ErrMsg2); if (Failed()) return + p%CBM = 0.0_ReKi ! TODO no cross couplings p%MMB = TRANSPOSE( p%MBM ) != MMBt + p%CMB = TRANSPOSE( p%CBM ) != CMBt + p%PhiM = PhiL(:,1:p%nDOFM) - ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) - p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array - p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array + ! A_21=-Kmm (diagonal), A_22=-Cmm (approximated as diagonal) + p%KMMDiag= OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array + p%CMMDiag = 2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array + ! + DO I = 1, p%nDOFM + p%CMMDiag(I) = p%CMMDiag(I) + CMM(I,I) ! Adding CB damping from CB reduced damping matrix (joints) + ENDDO + ! B_23, B_24 !p%PhiM_T = TRANSPOSE( p%PhiM ) @@ -1953,24 +1979,23 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped - p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) - p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) + p%C1_11(:, I) = -p%MBM(:, I)*p%KMMDiag(I) + p%C1_12(:, I) = p%CBM(:,I) -p%MBM(:, I)*p%CMMDiag(I) ENDDO ! D1 Matrices ! D1_12 = CBBt - MBmt*CmBt - p%D1_12 = p%CBB !TODO TODO cross coupling term + !CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%CBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_12 = MATMUL( p%MBM, p%CMB ) + p%D1_12 = MATMUL( p%MBM, p%CMB ) + p%D1_12 = p%CBB - p%D1_12 ! D1_13 = MBBt - MBmt*MmBt !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ) ! p%D1_13 = MATMUL( p%MBM, p%MMB ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) p%D1_13 = p%MBB - p%D1_13 !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 ! FY (with retained modes) @@ -1980,17 +2005,16 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! C2_21, C2_42 ! C2_61, C2_62 DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped - p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) - p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) + p%C2_61(:, i) = -p%PhiM(:, i)*p%KMMDiag(i) + p%C2_62(:, i) = -p%PhiM(:, i)*p%CMMDiag(i) ENDDO ! D2_53, D2_63, D2_64 p%D2_63 = MATMUL( p%PhiM, p%MMB ) p%D2_63 = p%PhiRb_TI - p%D2_63 - !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) !bjj: why does this use stack space? - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ) !bjj: replaced MATMUL with this routine to avoid issues with stack size - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ); if(Failed()) return; ! F2_61 p%F2_61 = MATMUL( p%D2_64, FGL ) @@ -2005,8 +2029,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! (note the Jacobian is first stored as p%AM2InvJac) p%AM2Jac=0. DO i=1,p%nDOFM - p%AM2Jac(i+p%nDOFM,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 - p%AM2Jac(i+p%nDOFM,i+p%nDOFM)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize + p%AM2Jac(i+p%nDOFM,i ) =-p%SDdeltaT/2.*p%KMMDiag(i) !J21 + p%AM2Jac(i+p%nDOFM,i+p%nDOFM)=-p%SDdeltaT/2.*p%CMMDiag(i) !J22 -initialize END DO DO I=1,p%nDOFM @@ -2073,8 +2097,10 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) if (p%nDOFM > 0 ) THEN CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%NOmegaM2, nDOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%N2OmegaMJDamp, nDOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%KMMDiag, nDOFM, 'p%KMMDiag', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%CMMDiag, nDOFM, 'p%CMMDiag', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%CMB, nDOFM, nDOFL_TP, 'p%CMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%CBM, nDOFL_TP, nDOFM, 'p%CBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2665,7 +2691,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (Guyan DOFs)" call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) call yaml_write_array(UnSum, 'MBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'CBBt', p%CBB, 'E15.9', ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'CBBt', p%CBB, Refmt, ErrStat2, ErrMsg2, comment='(user Guyan Damping + potential joint damping from CB-reduction)') ! Set TI2, transformation matrix from R DOFs to SubDyn Origin CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -2704,6 +2730,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') + call yaml_write_array(UnSum, 'D', Init%D, ReFmt, ErrStat2, ErrMsg2, comment='Damping matrix') ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system WRITE(UnSum, '(A)') SectionDivide @@ -2713,10 +2740,17 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! --- write CB system matrices WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' - call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'MBB ',CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'CBB', CBparams%CBB, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'CBM', CBparams%CBM, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'CBMt',p%CBM, ReFmt, ErrStat2, ErrMsg2, comment='(at TP)') + call yaml_write_array(UnSum, 'CMM', CBparams%CMM, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'CMMdiag_zeta',2.0_ReKi * CBparams%OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) , ReFmt, ErrStat2, ErrMsg2, comment='(2ZetaOmegaM)') + call yaml_write_array(UnSum, 'CMMdiag_all',p%CMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(Joint+2ZetaOmegaM)') call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') + call yaml_write_array(UnSum, 'KMMdiag', p%KMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') IF (p%SttcSolve/= idSIM_None) THEN call yaml_write_array(UnSum, 'PhiL', transpose(p%PhiL_T), ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index cfbfc4e6a..6f0fafa0c 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -183,8 +183,8 @@ typedef ^ ^ IntKi DOFred2Nodes {:}{:} - - "nDOFRed x 3, typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" -typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" -typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" +typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" +typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" typedef ^ ParameterType ReKi FX {:} - - "Load components in X" typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" @@ -203,6 +203,7 @@ typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" typedef ^ ParameterType ReKi MBB {:}{:} - - "Guyan Mass Matrix after C-B reduction" typedef ^ ParameterType ReKi KBB {:}{:} - - "Guyan Stiffness Matrix after C-B reduction" typedef ^ ParameterType ReKi CBB {:}{:} - - "Guyan Damping Matrix after C-B reduction" +typedef ^ ParameterType ReKi CMB {:}{:} - - "Cross coupling Guyan-CB damping matrix" typedef ^ ParameterType ReKi CBM {:}{:} - - "Cross coupling Guyan-CB damping matrix" typedef ^ ParameterType ReKi CMM {:}{:} - - "CB damping matrix" typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index ed2004e7a..ef509888b 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -221,8 +221,8 @@ MODULE SubDyn_Types INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] @@ -241,6 +241,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Guyan Mass Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Guyan Stiffness Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< Guyan Damping Matrix after C-B reduction [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMB !< Cross coupling Guyan-CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< Cross coupling Guyan-CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] @@ -6684,29 +6685,29 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment -IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN - i1_l = LBOUND(SrcParamData%NOmegaM2,1) - i1_u = UBOUND(SrcParamData%NOmegaM2,1) - IF (.NOT. ALLOCATED(DstParamData%NOmegaM2)) THEN - ALLOCATE(DstParamData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%KMMDiag)) THEN + i1_l = LBOUND(SrcParamData%KMMDiag,1) + i1_u = UBOUND(SrcParamData%KMMDiag,1) + IF (.NOT. ALLOCATED(DstParamData%KMMDiag)) THEN + ALLOCATE(DstParamData%KMMDiag(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%NOmegaM2 = SrcParamData%NOmegaM2 + DstParamData%KMMDiag = SrcParamData%KMMDiag ENDIF -IF (ALLOCATED(SrcParamData%N2OmegaMJDamp)) THEN - i1_l = LBOUND(SrcParamData%N2OmegaMJDamp,1) - i1_u = UBOUND(SrcParamData%N2OmegaMJDamp,1) - IF (.NOT. ALLOCATED(DstParamData%N2OmegaMJDamp)) THEN - ALLOCATE(DstParamData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%CMMDiag)) THEN + i1_l = LBOUND(SrcParamData%CMMDiag,1) + i1_u = UBOUND(SrcParamData%CMMDiag,1) + IF (.NOT. ALLOCATED(DstParamData%CMMDiag)) THEN + ALLOCATE(DstParamData%CMMDiag(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%N2OmegaMJDamp = SrcParamData%N2OmegaMJDamp + DstParamData%CMMDiag = SrcParamData%CMMDiag ENDIF IF (ALLOCATED(SrcParamData%MMB)) THEN i1_l = LBOUND(SrcParamData%MMB,1) @@ -6954,6 +6955,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%CBB = SrcParamData%CBB ENDIF +IF (ALLOCATED(SrcParamData%CMB)) THEN + i1_l = LBOUND(SrcParamData%CMB,1) + i1_u = UBOUND(SrcParamData%CMB,1) + i2_l = LBOUND(SrcParamData%CMB,2) + i2_u = UBOUND(SrcParamData%CMB,2) + IF (.NOT. ALLOCATED(DstParamData%CMB)) THEN + ALLOCATE(DstParamData%CMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CMB = SrcParamData%CMB +ENDIF IF (ALLOCATED(SrcParamData%CBM)) THEN i1_l = LBOUND(SrcParamData%CBM,1) i1_u = UBOUND(SrcParamData%CBM,1) @@ -7435,11 +7450,11 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%DOFred2Nodes)) THEN DEALLOCATE(ParamData%DOFred2Nodes) ENDIF -IF (ALLOCATED(ParamData%NOmegaM2)) THEN - DEALLOCATE(ParamData%NOmegaM2) +IF (ALLOCATED(ParamData%KMMDiag)) THEN + DEALLOCATE(ParamData%KMMDiag) ENDIF -IF (ALLOCATED(ParamData%N2OmegaMJDamp)) THEN - DEALLOCATE(ParamData%N2OmegaMJDamp) +IF (ALLOCATED(ParamData%CMMDiag)) THEN + DEALLOCATE(ParamData%CMMDiag) ENDIF IF (ALLOCATED(ParamData%MMB)) THEN DEALLOCATE(ParamData%MMB) @@ -7495,6 +7510,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%CBB)) THEN DEALLOCATE(ParamData%CBB) ENDIF +IF (ALLOCATED(ParamData%CMB)) THEN + DEALLOCATE(ParamData%CMB) +ENDIF IF (ALLOCATED(ParamData%CBM)) THEN DEALLOCATE(ParamData%CBM) ENDIF @@ -7736,15 +7754,15 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment - Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no - IF ( ALLOCATED(InData%NOmegaM2) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%NOmegaM2) ! NOmegaM2 + Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no + IF ( ALLOCATED(InData%KMMDiag) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! KMMDiag upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%KMMDiag) ! KMMDiag END IF - Int_BufSz = Int_BufSz + 1 ! N2OmegaMJDamp allocated yes/no - IF ( ALLOCATED(InData%N2OmegaMJDamp) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! N2OmegaMJDamp upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%N2OmegaMJDamp) ! N2OmegaMJDamp + Int_BufSz = Int_BufSz + 1 ! CMMDiag allocated yes/no + IF ( ALLOCATED(InData%CMMDiag) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CMMDiag upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMMDiag) ! CMMDiag END IF Int_BufSz = Int_BufSz + 1 ! MMB allocated yes/no IF ( ALLOCATED(InData%MMB) ) THEN @@ -7836,6 +7854,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! CBB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%CBB) ! CBB END IF + Int_BufSz = Int_BufSz + 1 ! CMB allocated yes/no + IF ( ALLOCATED(InData%CMB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CMB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CMB) ! CMB + END IF Int_BufSz = Int_BufSz + 1 ! CBM allocated yes/no IF ( ALLOCATED(InData%CBM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! CBM upper/lower bounds for each dimension @@ -8323,31 +8346,31 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%ExtraMoment , IntKiBuf(1), 1) Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN + IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NOmegaM2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NOmegaM2,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%KMMDiag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KMMDiag,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%NOmegaM2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%NOmegaM2))-1 ) = PACK(InData%NOmegaM2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%NOmegaM2) + IF (SIZE(InData%KMMDiag)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KMMDiag))-1 ) = PACK(InData%KMMDiag,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%KMMDiag) END IF - IF ( .NOT. ALLOCATED(InData%N2OmegaMJDamp) ) THEN + IF ( .NOT. ALLOCATED(InData%CMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%N2OmegaMJDamp,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%N2OmegaMJDamp,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMMDiag,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMMDiag,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%N2OmegaMJDamp)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%N2OmegaMJDamp))-1 ) = PACK(InData%N2OmegaMJDamp,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%N2OmegaMJDamp) + IF (SIZE(InData%CMMDiag)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMMDiag))-1 ) = PACK(InData%CMMDiag,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CMMDiag) END IF IF ( .NOT. ALLOCATED(InData%MMB) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8628,6 +8651,22 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF (SIZE(InData%CBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBB))-1 ) = PACK(InData%CBB,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%CBB) END IF + IF ( .NOT. ALLOCATED(InData%CMB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CMB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMB,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CMB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMB))-1 ) = PACK(InData%CMB,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CMB) + END IF IF ( .NOT. ALLOCATED(InData%CBM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9567,17 +9606,17 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%ExtraMoment = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NOmegaM2)) DEALLOCATE(OutData%NOmegaM2) - ALLOCATE(OutData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%KMMDiag)) DEALLOCATE(OutData%KMMDiag) + ALLOCATE(OutData%KMMDiag(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9586,21 +9625,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%NOmegaM2)>0) OutData%NOmegaM2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%NOmegaM2))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%NOmegaM2) + IF (SIZE(OutData%KMMDiag)>0) OutData%KMMDiag = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KMMDiag))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%KMMDiag) DEALLOCATE(mask1) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! N2OmegaMJDamp not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%N2OmegaMJDamp)) DEALLOCATE(OutData%N2OmegaMJDamp) - ALLOCATE(OutData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%CMMDiag)) DEALLOCATE(OutData%CMMDiag) + ALLOCATE(OutData%CMMDiag(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) @@ -9609,8 +9648,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%N2OmegaMJDamp)>0) OutData%N2OmegaMJDamp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%N2OmegaMJDamp))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%N2OmegaMJDamp) + IF (SIZE(OutData%CMMDiag)>0) OutData%CMMDiag = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMMDiag))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CMMDiag) DEALLOCATE(mask1) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMB not allocated @@ -10072,6 +10111,32 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(OutData%CBB) DEALLOCATE(mask2) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMB not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CMB)) DEALLOCATE(OutData%CMB) + ALLOCATE(OutData%CMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%CMB)>0) OutData%CMB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMB))-1 ), mask2, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CMB) + DEALLOCATE(mask2) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated Int_Xferred = Int_Xferred + 1 ELSE From 78c5a1ff17debcb21111638de83e92db8726b1ad Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jul 2020 14:40:52 -0600 Subject: [PATCH 242/377] FlexSub: removing joint damping from input file, only CB damping --- modules/subdyn/src/SD_FEM.f90 | 28 +-- modules/subdyn/src/SubDyn.f90 | 87 +++------ modules/subdyn/src/SubDyn_Registry.txt | 4 - modules/subdyn/src/SubDyn_Types.f90 | 260 ------------------------- 4 files changed, 34 insertions(+), 345 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ba8c0aedb..51990d141 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -28,7 +28,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 !TODO rename me ! 6 degrees of freedom (length of u subarray [UTP]) ! values of these parameters are ordered by their place in SubDyn input file: - INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff JointDamp) + INTEGER(IntKi), PARAMETER :: JointsCol = 9 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff) INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) @@ -47,7 +47,6 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: iJointType= 5 ! Index in Joints where the joint type is stored INTEGER(IntKi), PARAMETER :: iJointDir= 6 ! Index in Joints where the joint-direction are stored INTEGER(IntKi), PARAMETER :: iJointStiff= 9 ! Index in Joints where the joint-stiffness is stored - INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored ! ID for joint types INTEGER(IntKi), PARAMETER :: idJointCantilever = 1 @@ -631,7 +630,6 @@ SUBROUTINE SetNewNode(k, x, y, z, Init) ! Properties below are for non-cantilever joints Init%Nodes(k, iJointDir:iJointDir+2) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes Init%Nodes(k, iJointStiff) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes - Init%Nodes(k, iJointDamp) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes END SUBROUTINE SetNewNode !> Set properties of element k @@ -1398,8 +1396,8 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) CALL ReInitBCs(Init, p) CALL ReInitIntFc(Init, p) endif - CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix - Init%D = 0 !< Used for additional stiffness + !CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix + !Init%D = 0 !< Used for additional damping ! --- Creating a convenient Map from DOF to Nodes call AllocAry(p%DOFred2Nodes, p%nDOF_red, 3, 'DOFred2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; @@ -1774,6 +1772,7 @@ END SUBROUTINE RigidLinkAssemblies !------------------------------------------------------------------------------------------------------ !> Add stiffness and damping to some joints +!! NOTE: damping was removed around 13/07/2020 SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) TYPE(SD_ParameterType),target,INTENT(IN ) :: p TYPE(SD_InitType), INTENT(INOUT) :: Init @@ -1784,25 +1783,20 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) integer(IntKi) :: nFreeRot ! Number of free rot DOF integer(IntKi) :: nMembers ! Number of members attached to this node integer(IntKi) :: nSpace ! Number of spaces between diagonal "bands" (0:pin, 1:univ, 2:ball) - real(ReKi) :: StifAdd, DampAdd - real(ReKi), dimension(:,:), allocatable :: K_Add, D_Add ! Stiffness and damping matrix added to global system + real(ReKi) :: StifAdd + real(ReKi), dimension(:,:), allocatable :: K_Add ! Stiffness matrix added to global system integer(IntKi), dimension(:), pointer :: Ifreerot ErrStat = ErrID_None ErrMsg = "" do iNode = 1, p%nNodes JType = int(Init%Nodes(iNode,iJointType)) StifAdd = Init%Nodes(iNode, iJointStiff) - DampAdd = Init%Nodes(iNode, iJointDamp ) if(JType == idJointCantilever ) then ! Cantilever joints should not have damping or stiffness if(StifAdd>0) then ErrMsg='InsertJointStiffDamp: Additional stiffness should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; return endif - if(DampAdd>0) then - ErrMsg='InsertJointStiffDamp: Additional damping should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; - return - endif else ! Ball/Univ/Pin joints have damping/stiffness inserted at indices of "free rotation" nMembers = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint @@ -1814,9 +1808,7 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) nFreeRot = size(Ifreerot) ! Creating matrices of 0, and -K and nK on diagonals allocate(K_Add(1:nFreeRot,1:nFreeRot)); - allocate(D_Add(1:nFreeRot,1:nFreeRot)); call ChessBoard(K_Add, -StifAdd, 0._ReKi, nSpace=nSpace, diagVal=(nMembers-1)*StifAdd) - call ChessBoard(D_Add, -DampAdd, 0._ReKi, nSpace=nSpace, diagVal=(nMembers-1)*DampAdd) ! Ball/Pin/Universal joints if(StifAdd>0) then print*,'Stiffness Add, Node:',iNode,'DOF:', Ifreerot @@ -1825,15 +1817,7 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) enddo Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + K_Add endif - if(DampAdd>0) then - print*,'Damping Add, Node:',iNode,'DOF:', Ifreerot - do i=1,nFreeRot - print*,'D Add',D_Add(i,:) - enddo - Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) + D_Add - endif if(allocated(K_Add)) deallocate(K_Add) - if(allocated(D_Add)) deallocate(D_Add) endif enddo END SUBROUTINE InsertJointStiffDamp diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f167f56c6..b1323d0e3 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -613,7 +613,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) !dxdt%qmdot = -p%KMMDiag*x%qm + p%CMMDiag*x%qmdot - matmul(p%CMB,m%udotdot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX END SUBROUTINE SD_CalcContStateDeriv @@ -641,6 +641,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) LOGICAL :: Dummy_Bool +INTEGER(IntKi) :: Dummy_Int INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ! Initialize ErrStat @@ -750,24 +751,16 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the ! last entry to fill in remaining values. !Check 1st value, we need at least one good value from user or throw error - IF ((Init%JDampings(1) < 0 ) .OR. (Init%JDampings(1) >= 100.0)) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100') - return - ELSE - DO I = 2, p%nDOFM - IF ( Init%JDampings(I) .EQ. WrongNo ) THEN - Init%Jdampings(I:p%nDOFM)=Init%JDampings(I-1) - IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) - ErrStat = ErrID_Info - ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%nDOFM))//'.' - END IF - EXIT - ELSEIF ( ( Init%JDampings(I) < 0 ) .OR.( Init%JDampings(I) >= 100.0 ) ) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100') - return - ENDIF - ENDDO - ENDIF + DO I = 2, p%nDOFM + IF ( Init%JDampings(I) .EQ. WrongNo ) THEN + Init%Jdampings(I:p%nDOFM)=Init%JDampings(I-1) + IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) + ErrStat = ErrID_Info + ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%nDOFM))//'.' + END IF + EXIT + ENDIF + ENDDO IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%nDOFM,NWTC_MaxAryLen)) END IF @@ -783,10 +776,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) !Read 1 damping value for all modes CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - IF ( ( Init%JDampings(1) < 0 ) .OR.( Init%JDampings(1) >= 100.0 ) ) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100.') - RETURN - ENDIF ENDIF IF ((p%nDOFM > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%nDOFM is undefined, but if Nmodes=0 then JDampings does not exist @@ -799,7 +788,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) if (is_numeric(Dummy_Str, DummyFloat)) then Init%GuyanDampMod=int(DummyFloat) CALL ReadAry( UnIn, SDInputFile, Init%RayleighDamp, 2, "RayleighDamp", "", ErrStat2, ErrMsg2, UnEc) - CALL ReadCom( UnIn, SDInputFile, 'Guyan damping matrix (6x6)' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + CALL ReadVar (UnIn, SDInputFile, Dummy_Int, 'GuyanDampSize', 'Guyan damping matrix size', ErrStat2, ErrMsg2, UnEc); if(Failed()) return + IF (Check(Dummy_Int/=6, 'Invalid value entered for GuyanDampSize, value should be 6 for now.')) return CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(1,:), 6, "GuyanDampMat1", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(2,:), 6, "GuyanDampMat2", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) CALL ReadAry( UnIn, SDInputFile, Init%GuyanDampMat(3,:), 6, "GuyanDampMat3", "Guyan Damping matrix ", ErrStat2, ErrMsg2, UnEc) @@ -1704,16 +1694,13 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%CBB, nR, nR, 'CB%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%CBM, nR, nM, 'CB%CBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%CMM, nM, nM, 'CB%CMM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%PhiL, nL, nM_out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& - Init%FG, FGR, FGL, FGB, FGM, Init%D, CB%CBB, CB%CBM, CB%CMM) ! TODO + Init%FG, FGR, FGL, FGB, FGM) if(Failed()) return CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1724,7 +1711,7 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) PhiRb=CB%PhiR ! Remove me in the future endif ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, CB%CBB, CB%CBM, CB%CMM, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -1760,15 +1747,11 @@ subroutine applyConstr(CBParams, FGB, PhiRb) !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(ReKi), ALLOCATABLE :: MBBb(:, :) REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: CBBb(:, :) - REAL(ReKi), ALLOCATABLE :: CBMb(:, :) REAL(ReKi), ALLOCATABLE :: KBBb(:, :) REAL(ReKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); - CALL AllocAry( CBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix CBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( CBmb, p%nDOF__Rb, p%nDOFM, 'matrix CBmb', ErrStat2, ErrMsg2 ); CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); @@ -1780,24 +1763,18 @@ subroutine applyConstr(CBParams, FGB, PhiRb) ! TODO avoid this all together MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - CBBb = CBparams%CBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) IF (p%nDOFM > 0) THEN MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) - CBMb = CBparams%CBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) END IF FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) deallocate(CBparams%MBB) deallocate(CBparams%KBB) deallocate(CBparams%MBM) - deallocate(CBparams%CMM) - deallocate(CBparams%CBM) !deallocate(CBparams%PhiR) call move_alloc(MBBb, CBparams%MBB) call move_alloc(KBBb, CBparams%KBB) call move_alloc(MBMb, CBparams%MBM) - call move_alloc(CBBb, CBparams%CBB) - call move_alloc(CBMb, CBparams%CBM) call move_alloc(FGBb, FGB) !call move_alloc(PhiRb, CBparams%PhiR) end subroutine applyConstr @@ -1858,16 +1835,13 @@ END SUBROUTINE SD_Guyan_RigidBodyMass !------------------------------------------------------------------------------------------------------ !> Set parameters to compute state and output equations -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, CBBb, CBMb, CMM, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan mass matrix REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan stiffness matrix - REAL(ReKi), INTENT(IN ) :: CBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan damping - REAL(ReKi), INTENT(IN ) :: CBMb( p%nDOF__Rb, p%nDOFM) ! Cross damping - REAL(ReKi), INTENT(IN ) :: CMM ( p%nDOFM , p%nDOFM) ! CB damping integer(IntKi), INTENT(IN ) :: nM_out REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) @@ -1931,29 +1905,29 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, CBBb, CBMb, CMM, nM_o !............................... p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt - p%CBB = MATMUL( MATMUL( TI_transpose, CBBb ), p%TI) != CBBt ! 6x6 Guyan Damping matrix if (Init%GuyanDampMod == idGuyanDamp_None) then ! No Damping - p%CBB = p%CBB + 0.0_ReKi + p%CBB = 0.0_ReKi elseif (Init%GuyanDampMod == idGuyanDamp_Rayleigh) then ! Rayleigh Damping - p%CBB = p%CBB + Init%RayleighDamp(1) * p%MBB + Init%RayleighDamp(2) * p%KBB + p%CBB = Init%RayleighDamp(1) * p%MBB + Init%RayleighDamp(2) * p%KBB elseif (Init%GuyanDampMod == idGuyanDamp_66) then ! User 6x6 matrix if (size(p%CBB,1)/=6) then ErrMsg='Cannot use 6x6 Guyan Damping matrix, number of interface DOFs is'//num2lstr(size(p%CBB,1)); ErrStat=ErrID_Fatal; return endif - p%CBB = p%CBB + Init%GuyanDampMat + print*,'GuyanDampMat',Init%GuyanDampMat + p%CBB = Init%GuyanDampMat endif !p%D1_15=-TI_transpose !this is 6x6NIN IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return - p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt + !p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, CBMb, 0.0_ReKi, p%CBM, ErrStat2, ErrMsg2); if (Failed()) return p%CBM = 0.0_ReKi ! TODO no cross couplings @@ -1965,10 +1939,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, CBBb, CBMb, CMM, nM_o ! A_21=-Kmm (diagonal), A_22=-Cmm (approximated as diagonal) p%KMMDiag= OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array p%CMMDiag = 2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array - ! - DO I = 1, p%nDOFM - p%CMMDiag(I) = p%CMMDiag(I) + CMM(I,I) ! Adding CB damping from CB reduced damping matrix (joints) - ENDDO ! B_23, B_24 @@ -2730,7 +2700,6 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') - call yaml_write_array(UnSum, 'D', Init%D, ReFmt, ErrStat2, ErrMsg2, comment='Damping matrix') ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system WRITE(UnSum, '(A)') SectionDivide @@ -2742,12 +2711,12 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' call yaml_write_array(UnSum, 'MBB ',CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'CBB', CBparams%CBB, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'CBM', CBparams%CBM, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'CBMt',p%CBM, ReFmt, ErrStat2, ErrMsg2, comment='(at TP)') - call yaml_write_array(UnSum, 'CMM', CBparams%CMM, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'CMMdiag_zeta',2.0_ReKi * CBparams%OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) , ReFmt, ErrStat2, ErrMsg2, comment='(2ZetaOmegaM)') - call yaml_write_array(UnSum, 'CMMdiag_all',p%CMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(Joint+2ZetaOmegaM)') + !call yaml_write_array(UnSum, 'CBB', CBparams%CBB, ReFmt, ErrStat2, ErrMsg2, comment='') + !call yaml_write_array(UnSum, 'CBM', CBparams%CBM, ReFmt, ErrStat2, ErrMsg2, comment='') + !call yaml_write_array(UnSum, 'CBMt',p%CBM, ReFmt, ErrStat2, ErrMsg2, comment='(at TP)') + !call yaml_write_array(UnSum, 'CMM', CBparams%CMM, ReFmt, ErrStat2, ErrMsg2, comment='') + !call yaml_write_array(UnSum, 'CMMdiag_zeta',2.0_ReKi * CBparams%OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) , ReFmt, ErrStat2, ErrMsg2, comment='(2ZetaOmegaM)') + call yaml_write_array(UnSum, 'CMMdiag',p%CMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(2 Zeta OmegaM)') call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') call yaml_write_array(UnSum, 'KMMdiag', p%KMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 6f0fafa0c..f3f440604 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -41,9 +41,6 @@ typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector co typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi CBB {:}{:} - - "FULL CBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi CBM {:}{:} - - "FULL CBM ( no constraints applied)" -typedef ^ CB_MatArrays ReKi CMM {:}{:} - - "FULL CMM ( no constraints applied)" typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" @@ -108,7 +105,6 @@ typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" -typedef ^ ^ ReKi D {:}{:} - - "System damping matrix" typedef ^ ^ ReKi F {:} - - "System force vector" N typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index ef509888b..000e61d57 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -73,9 +73,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< FULL CBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< FULL CBM ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< FULL CMM ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] @@ -143,7 +140,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D !< System damping matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] @@ -1706,48 +1702,6 @@ SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCo END IF DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%CBB)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%CBB,1) - i1_u = UBOUND(SrcCB_MatArraysData%CBB,1) - i2_l = LBOUND(SrcCB_MatArraysData%CBB,2) - i2_u = UBOUND(SrcCB_MatArraysData%CBB,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%CBB)) THEN - ALLOCATE(DstCB_MatArraysData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%CBB = SrcCB_MatArraysData%CBB -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%CBM)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%CBM,1) - i1_u = UBOUND(SrcCB_MatArraysData%CBM,1) - i2_l = LBOUND(SrcCB_MatArraysData%CBM,2) - i2_u = UBOUND(SrcCB_MatArraysData%CBM,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%CBM)) THEN - ALLOCATE(DstCB_MatArraysData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%CBM = SrcCB_MatArraysData%CBM -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%CMM)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%CMM,1) - i1_u = UBOUND(SrcCB_MatArraysData%CMM,1) - i2_l = LBOUND(SrcCB_MatArraysData%CMM,2) - i2_u = UBOUND(SrcCB_MatArraysData%CMM,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%CMM)) THEN - ALLOCATE(DstCB_MatArraysData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%CMM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%CMM = SrcCB_MatArraysData%CMM -ENDIF IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) @@ -1808,15 +1762,6 @@ SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) IF (ALLOCATED(CB_MatArraysData%KBB)) THEN DEALLOCATE(CB_MatArraysData%KBB) ENDIF -IF (ALLOCATED(CB_MatArraysData%CBB)) THEN - DEALLOCATE(CB_MatArraysData%CBB) -ENDIF -IF (ALLOCATED(CB_MatArraysData%CBM)) THEN - DEALLOCATE(CB_MatArraysData%CBM) -ENDIF -IF (ALLOCATED(CB_MatArraysData%CMM)) THEN - DEALLOCATE(CB_MatArraysData%CMM) -ENDIF IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN DEALLOCATE(CB_MatArraysData%PhiL) ENDIF @@ -1878,21 +1823,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB END IF - Int_BufSz = Int_BufSz + 1 ! CBB allocated yes/no - IF ( ALLOCATED(InData%CBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CBB) ! CBB - END IF - Int_BufSz = Int_BufSz + 1 ! CBM allocated yes/no - IF ( ALLOCATED(InData%CBM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CBM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CBM) ! CBM - END IF - Int_BufSz = Int_BufSz + 1 ! CMM allocated yes/no - IF ( ALLOCATED(InData%CMM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CMM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CMM) ! CMM - END IF Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no IF ( ALLOCATED(InData%PhiL) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension @@ -1983,54 +1913,6 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%KBB) END IF - IF ( .NOT. ALLOCATED(InData%CBB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%CBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBB))-1 ) = PACK(InData%CBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CBB) - END IF - IF ( .NOT. ALLOCATED(InData%CBM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%CBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBM))-1 ) = PACK(InData%CBM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CBM) - END IF - IF ( .NOT. ALLOCATED(InData%CMM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%CMM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMM))-1 ) = PACK(InData%CMM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CMM) - END IF IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2190,84 +2072,6 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + SIZE(OutData%KBB) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CBB)) DEALLOCATE(OutData%CBB) - ALLOCATE(OutData%CBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CBB)>0) OutData%CBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CBB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CBM)) DEALLOCATE(OutData%CBM) - ALLOCATE(OutData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CBM)>0) OutData%CBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CBM) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CMM)) DEALLOCATE(OutData%CMM) - ALLOCATE(OutData%CMM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CMM)>0) OutData%CMM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CMM) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2863,20 +2667,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%M = SrcInitTypeData%M ENDIF -IF (ALLOCATED(SrcInitTypeData%D)) THEN - i1_l = LBOUND(SrcInitTypeData%D,1) - i1_u = UBOUND(SrcInitTypeData%D,1) - i2_l = LBOUND(SrcInitTypeData%D,2) - i2_u = UBOUND(SrcInitTypeData%D,2) - IF (.NOT. ALLOCATED(DstInitTypeData%D)) THEN - ALLOCATE(DstInitTypeData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%D = SrcInitTypeData%D -ENDIF IF (ALLOCATED(SrcInitTypeData%F)) THEN i1_l = LBOUND(SrcInitTypeData%F,1) i1_u = UBOUND(SrcInitTypeData%F,1) @@ -3054,9 +2844,6 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%M)) THEN DEALLOCATE(InitTypeData%M) ENDIF -IF (ALLOCATED(InitTypeData%D)) THEN - DEALLOCATE(InitTypeData%D) -ENDIF IF (ALLOCATED(InitTypeData%F)) THEN DEALLOCATE(InitTypeData%F) ENDIF @@ -3237,11 +3024,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%M) ! M END IF - Int_BufSz = Int_BufSz + 1 ! D allocated yes/no - IF ( ALLOCATED(InData%D) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D) ! D - END IF Int_BufSz = Int_BufSz + 1 ! F allocated yes/no IF ( ALLOCATED(InData%F) ) THEN Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension @@ -3663,22 +3445,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF (SIZE(InData%M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%M) END IF - IF ( .NOT. ALLOCATED(InData%D) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D))-1 ) = PACK(InData%D,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D) - END IF IF ( .NOT. ALLOCATED(InData%F) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4411,32 +4177,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + SIZE(OutData%M) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D)) DEALLOCATE(OutData%D) - ALLOCATE(OutData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D)>0) OutData%D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D) - DEALLOCATE(mask2) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated Int_Xferred = Int_Xferred + 1 ELSE From 9cb8fe2e4123443e5990bf3cea484418a0c0f2f9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 13 Jul 2020 21:12:36 -0600 Subject: [PATCH 243/377] FlexSub: implemented linearization, mixed analytical finite diff --- modules/extptfm/src/ExtPtfm_MCKF.f90 | 2 + modules/extptfm/src/ExtPtfm_MCKF_Registry.txt | 1 + modules/extptfm/src/ExtPtfm_MCKF_Types.f90 | 57 ++ modules/openfast-library/src/FAST_Lin.f90 | 57 +- modules/openfast-library/src/FAST_Subs.f90 | 22 +- modules/subdyn/src/SD_FEM.f90 | 5 +- modules/subdyn/src/SubDyn.f90 | 592 +++++++++++++++- modules/subdyn/src/SubDyn_Output.f90 | 236 +++++++ modules/subdyn/src/SubDyn_Registry.txt | 29 +- modules/subdyn/src/SubDyn_Types.f90 | 646 ++++++++++++++++++ 10 files changed, 1608 insertions(+), 39 deletions(-) diff --git a/modules/extptfm/src/ExtPtfm_MCKF.f90 b/modules/extptfm/src/ExtPtfm_MCKF.f90 index e27fec588..41c01fb16 100644 --- a/modules/extptfm/src/ExtPtfm_MCKF.f90 +++ b/modules/extptfm/src/ExtPtfm_MCKF.f90 @@ -251,9 +251,11 @@ SUBROUTINE ExtPtfm_Init( InitInp, u, p, x, xd, z, OtherState, y, m, dt_gluecode, CALL AllocAry(InitOut%RotFrame_y, 6+p%NumOuts , 'RotFrame_y', ErrStat, ErrMsg); if(Failed()) return CALL AllocAry(InitOut%LinNames_x, 2*p%nCB , 'LinNames_x', ErrStat, ErrMsg); if(Failed()) return CALL AllocAry(InitOut%RotFrame_x, 2*p%nCB , 'RotFrame_x', ErrStat, ErrMsg); if(Failed()) return + CALL AllocAry(InitOut%DerivOrder_x, 2*p%nCB , 'DerivOrd_x', ErrStat, ErrMsg); if(Failed()) return CALL AllocAry(InitOut%LinNames_u, N_INPUTS , 'LinNames_u', ErrStat, ErrMsg); if(Failed()) return CALL AllocAry(InitOut%RotFrame_u, N_INPUTS , 'RotFrame_u', ErrStat, ErrMsg); if(Failed()) return CALL AllocAry(InitOut%IsLoad_u , N_INPUTS , 'IsLoad_u' , ErrStat, ErrMsg); if(Failed()) return + InitOut%DerivOrder_x(:)=2 ! LinNames_y do I=1,3; InitOut%LinNames_y(I) = 'Interface node '//XYZ(I)//' force, N' diff --git a/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt b/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt index df8b051a8..c75fee857 100644 --- a/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt +++ b/modules/extptfm/src/ExtPtfm_MCKF_Registry.txt @@ -54,6 +54,7 @@ typedef ^ ^ LOGICAL RotFrame_y { typedef ^ ^ LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - typedef ^ ^ LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ ^ IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - # ..... States .................................................................................................................... diff --git a/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 b/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 index 722545f71..919f0a80a 100644 --- a/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 +++ b/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 @@ -73,6 +73,7 @@ MODULE ExtPtfm_MCKF_Types LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame [-] LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] END TYPE ExtPtfm_InitOutputType ! ======================= ! ========= ExtPtfm_ContinuousStateType ======= @@ -883,6 +884,18 @@ SUBROUTINE ExtPtfm_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCod END IF END IF DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x ENDIF END SUBROUTINE ExtPtfm_CopyInitOutput @@ -922,6 +935,9 @@ SUBROUTINE ExtPtfm_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) ENDIF IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) ENDIF END SUBROUTINE ExtPtfm_DestroyInitOutput @@ -1023,6 +1039,11 @@ SUBROUTINE ExtPtfm_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1215,6 +1236,19 @@ SUBROUTINE ExtPtfm_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IF (SIZE(InData%IsLoad_u)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%IsLoad_u)-1 ) = TRANSFER(PACK( InData%IsLoad_u ,.TRUE.), IntKiBuf(1), SIZE(InData%IsLoad_u)) Int_Xferred = Int_Xferred + SIZE(InData%IsLoad_u) END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) + END IF END SUBROUTINE ExtPtfm_PackInitOutput SUBROUTINE ExtPtfm_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1517,6 +1551,29 @@ SUBROUTINE ExtPtfm_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = Int_Xferred + SIZE(OutData%IsLoad_u) DEALLOCATE(mask1) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) + DEALLOCATE(mask1) + END IF END SUBROUTINE ExtPtfm_UnPackInitOutput SUBROUTINE ExtPtfm_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 763f28e26..04f7aae38 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -108,7 +108,10 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, NumBl, ErrStat, ErrMsg) end if ! ExtPtfm is next, if activated: - if ( p_FAST%CompSub == Module_ExtPtfm ) then + if ( p_FAST%CompSub == Module_SD ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_SD + else if ( p_FAST%CompSub == Module_ExtPtfm ) then p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_ExtPtfm end if @@ -412,7 +415,11 @@ SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) end if ! ExtPtfm standard inputs: x1, x1dot x1ddot ! TODO TODO TODO CHECK - if (p_FAST%CompSub == MODULE_ExtPtfm) then + if (p_FAST%CompSub == MODULE_SD) then + do j = 1,18 ! TODO TODO TODO + y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + else if (p_FAST%CompSub == MODULE_ExtPtfm) then do j = 1,18 y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. end do @@ -825,7 +832,43 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD1 !..................... ! ExtPtfm !..................... - if ( p_FAST%CompSub == Module_ExtPtfm ) then + if ( p_FAST%CompSub == Module_SD ) then + ! get the jacobians + call SD_JacobianPInput( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & + SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, & + dYdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%B ) + if(Failed()) return; + + call SD_JacobianPContState( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & + SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2,& + dYdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%A ) + if(Failed()) return; + + ! get the operating point + call SD_GetOP(t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR),& + SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_u,& + y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_dx) + if(Failed()) return; + + ! write the module matrices: + if (p_FAST%LinOutMod) then + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) + if(Failed()) return; + + if (p_FAST%LinOutJac) then + ! Jacobians + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx') + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) + end if + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1) ) + end if + elseif ( p_FAST%CompSub == Module_ExtPtfm ) then ! get the jacobians call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & @@ -1534,7 +1577,9 @@ SUBROUTINE Glue_Jacobians( t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF (p_FAST%CompSub == Module_ExtPtfm) THEN + IF (p_FAST%CompSub == Module_SD) THEN + write(*,*)'>>> FAST_LIN: Linear_SubDyn_InputSolve_du, TODO' + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_du, TODO' ENDIF @@ -1639,7 +1684,9 @@ SUBROUTINE Glue_Jacobians( t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD14, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF (p_FAST%CompSub == Module_ExtPtfm) THEN + IF (p_FAST%CompSub == Module_SD) THEN + write(*,*)'>>> FAST_LIN: Linear_SD_InputSolve_dy, TODO' + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO' ENDIF diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 6876cca9a..4005c401d 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -865,12 +865,13 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, InitInData_SD%WtrDpth = 0.0_ReKi END IF + InitInData_SD%Linearize = p_FAST%Linearize InitInData_SD%g = InitOutData_ED%Gravity !InitInData_SD%UseInputFile = .TRUE. InitInData_SD%SDInputFile = p_FAST%SubFile InitInData_SD%RootName = p_FAST%OutFileRoot - InitInData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! bjj: not sure what this is supposed to be - InitInData_SD%SubRotateZ = 0.0 ! bjj: not sure what this is supposed to be + InitInData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to + InitInData_SD%SubRotateZ = 0.0 ! Used by driver to rotate structure around z CALL SD_Init( InitInData_SD, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR), & @@ -880,6 +881,21 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, p_FAST%ModuleInitialized(Module_SD) = .TRUE. CALL SetModuleSubstepTime(Module_SD, p_FAST, y_FAST, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + allocate( y_FAST%Lin%Modules(MODULE_SD)%Instance(1), stat=ErrStat2) + if (ErrStat2 /= 0 ) then + call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(SD).", ErrStat, ErrMsg, RoutineName ) + else + if (allocated(InitOutData_SD%LinNames_y)) call move_alloc(InitOutData_SD%LinNames_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_y) + if (allocated(InitOutData_SD%LinNames_x)) call move_alloc(InitOutData_SD%LinNames_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_x) + if (allocated(InitOutData_SD%LinNames_u)) call move_alloc(InitOutData_SD%LinNames_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_u) + if (allocated(InitOutData_SD%RotFrame_y)) call move_alloc(InitOutData_SD%RotFrame_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_y) + if (allocated(InitOutData_SD%RotFrame_x)) call move_alloc(InitOutData_SD%RotFrame_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_x) + if (allocated(InitOutData_SD%RotFrame_u)) call move_alloc(InitOutData_SD%RotFrame_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_u) + if (allocated(InitOutData_SD%IsLoad_u )) call move_alloc(InitOutData_SD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%IsLoad_u ) + if (allocated(InitOutData_SD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%NumOutputs = size(InitOutData_SD%WriteOutputHdr) + if (allocated(InitOutData_SD%DerivOrder_x)) call move_alloc(InitOutData_SD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%DerivOrder_x) + end if IF (ErrStat >= AbortErrLev) THEN CALL Cleanup() @@ -913,6 +929,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if (allocated(InitOutData_ExtPtfm%RotFrame_u)) call move_alloc(InitOutData_ExtPtfm%RotFrame_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_u) if (allocated(InitOutData_ExtPtfm%IsLoad_u )) call move_alloc(InitOutData_ExtPtfm%IsLoad_u ,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%IsLoad_u ) if (allocated(InitOutData_ExtPtfm%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%NumOutputs = size(InitOutData_ExtPtfm%WriteOutputHdr) + if (allocated(InitOutData_ExtPtfm%DerivOrder_x)) call move_alloc(InitOutData_ExtPtfm%DerivOrder_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%DerivOrder_x) end if IF (ErrStat >= AbortErrLev) THEN @@ -1753,7 +1770,6 @@ SUBROUTINE ValidateInputData(p, ErrStat, ErrMsg) ! now, make sure we haven't asked for any modules that we can't yet linearize: if (p%CompInflow == MODULE_OpFM) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the OpenFOAM coupling.',ErrStat, ErrMsg, RoutineName) if (p%CompAero == MODULE_AD14) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the AeroDyn v14 module.',ErrStat, ErrMsg, RoutineName) - if (p%CompSub == MODULE_SD) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the SubDyn module.',ErrStat, ErrMsg, RoutineName) if (p%CompMooring == MODULE_MD) call SetErrStat(ErrID_Fatal,'Linearization is not implemented MoorDyn.', ErrStat, ErrMsg, RoutineName) if (p%CompMooring == MODULE_FEAM) call SetErrStat(ErrID_Fatal,'Linearization is not implemented FEAMooring.', ErrStat, ErrMsg, RoutineName) if (p%CompIce /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for any of the ice loading modules.',ErrStat, ErrMsg, RoutineName) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 51990d141..179dce589 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -78,7 +78,10 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) - LOGICAL, PARAMETER :: DEV_VERSION = .false. + ! Implementation Flags + LOGICAL, PARAMETER :: DEV_VERSION = .false. + LOGICAL, PARAMETER :: BC_Before_CB = .true. + LOGICAL, PARAMETER :: ANALYTICAL_LIN = .true. INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b1323d0e3..f07335c69 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -45,6 +45,11 @@ Module SubDyn PUBLIC :: SD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating PUBLIC :: SD_CalcOutput ! Routine for computing outputs PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + PUBLIC :: SD_JacobianPContState ! + PUBLIC :: SD_JacobianPInput ! + PUBLIC :: SD_JacobianPDiscState ! + PUBLIC :: SD_JacobianPConstrState ! + PUBLIC :: SD_GetOP ! CONTAINS @@ -288,6 +293,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ); if(Failed()) return END IF + if (InitInput%Linearize) then + call SD_Init_Jacobian( p, u, y, m, InitOut, ErrStat2, ErrMsg2); if(Failed()) return + endif ! Tell GLUECODE the SubDyn timestep interval Interval = p%SDdeltaT @@ -606,6 +614,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! form u(4) in Eq. 10: CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) + !print*,'UFL',m%UFL !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot @@ -613,7 +622,8 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) !dxdt%qmdot = -p%KMMDiag*x%qm + p%CMMDiag*x%qmdot - matmul(p%CMB,m%udotdot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(transpose(p%PhiM), m%UFL) + p%FX + !print*,'PhiM_T UFL', matmul(transpose(p%PhiM), m%UFL) END SUBROUTINE SD_CalcContStateDeriv @@ -823,7 +833,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) deallocate(StrArray) CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ); if(Failed()) return - call LegacyWarning('Joint table contains 4 columns instead of 10. All joints will be assumed cantilever, all members regular beams.') + call LegacyWarning('Joint table contains 4 columns instead of 9. All joints will be assumed cantilever, all members regular beams.') Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 LegacyFormat=.True. ! Legacy format - Delete me in 2024 @@ -1622,6 +1632,418 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg END SUBROUTINE SD_AM2 +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +! ###### The following four routines are Jacobian routines for linearization capabilities ####### +! If the module does not implement them, set ErrStat = ErrID_Fatal in SD_Init() when InitInp%Linearize is .true. +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the inputs (u). The partial derivatives dY/du, dX/du, dXd/du, and DZ/du are returned. +SUBROUTINE SD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdu, dXdu, dXddu, dZdu) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Output (change to inout if a mesh copy is required); Output fields are not used by this routine, but type is available here so that mesh parameter information (i.e., connectivity) does not have to be recalculated for dYdu. + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdu(:,:) !< Partial derivatives of output functions (Y) wrt the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) wrt the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) wrt the inputs (u) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) wrt the inputs (u) [intent in to avoid deallocation] + ! local variables + TYPE(SD_OutputType) :: y_m, y_p + TYPE(SD_ContinuousStateType) :: x_m, x_p + TYPE(SD_InputType) :: u_perturb + REAL(R8Ki) :: delta_p, delta_m ! delta change in input (plus, minus) + INTEGER(IntKi) :: i + REAL(R8Ki) :: RotateStates(3,3) + integer(intKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'SD_JacobianPInput' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! get OP values here: + call SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2 ); if(Failed()) return + ! make a copy of the inputs to perturb + call SD_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + IF ( PRESENT( dYdu ) ) THEN + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: + if (.not. allocated(dYdu) ) then + call AllocAry(dYdu,p%Jac_ny, size(p%Jac_u_indx,1),'dYdu', ErrStat2, ErrMsg2); if(Failed()) return + end if + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call SD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + call SD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + do i=1,size(p%Jac_u_indx,1) + ! get u_op + delta_p u + call SD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_Perturb_u( p, i, 1, u_perturb, delta_p ) + ! compute y at u_op + delta_p u + call SD_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get u_op - delta_m u + call SD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_Perturb_u( p, i, -1, u_perturb, delta_m ) + ! compute y at u_op - delta_m u + call SD_CalcOutput( t, u_perturb, p, x, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get central difference: + call SD_Compute_dY( p, y_p, y_m, delta_p, dYdu(:,i) ) + end do + if(Failed()) return + END IF + IF ( PRESENT( dXdu ) ) THEN + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: + ! TODO: dXdu should be constant, in theory we dont' need to recompute it + if(ANALYTICAL_LIN) then + call StateMatrices(p, ErrStat2, ErrMsg2, BB=dXdu); if(Failed()) return ! Allocation occurs in function + else + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, p%Jac_nx * 2, size(p%Jac_u_indx,1), 'dXdu', ErrStat2, ErrMsg2); if (Failed()) return + endif + do i=1,size(p%Jac_u_indx,1) + ! get u_op + delta u + call SD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_Perturb_u( p, i, 1, u_perturb, delta_p ) + ! compute x at u_op + delta u + call SD_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get u_op - delta u + call SD_CopyInput( u, u_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_Perturb_u( p, i, -1, u_perturb, delta_m ) + ! compute x at u_op - delta u + call SD_CalcContStateDeriv( t, u_perturb, p, x, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get central difference: + ! we may have had an error allocating memory, so we'll check + if(Failed()) return + ! get central difference: + call SD_Compute_dX( p, x_p, x_m, delta_p, dXdu(:,i) ) + end do + endif ! analytical or numerical + END IF ! dXdu + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF + call CleanUp() +contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + call SD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) ! we don't need this any more + call SD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) ! we don't need this any more + call SD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call SD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call SD_DestroyInput(u_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE SD_JacobianPInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the continuous states (x). The partial derivatives dY/dx, dX/dx, dXd/dx, and dZ/dx are returned. +SUBROUTINE SD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx, dXddx, dZdx, StateRotation ) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Output (change to inout if a mesh copy is required); Output fields are not used by this routine, but type is available here so that mesh parameter information (i.e., connectivity) does not have to be recalculated for dYdx. + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdx(:,:) !< Partial derivatives of output functions wrt the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdx(:,:) !< Partial derivatives of continuous state functions (X) wrt the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddx(:,:) !< Partial derivatives of discrete state functions (Xd) wrt the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdx(:,:) !< Partial derivatives of constraint state functions (Z) wrt the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: StateRotation(:,:) !< Matrix by which the states are optionally rotated + ! local variables + TYPE(SD_OutputType) :: y_p, y_m + TYPE(SD_ContinuousStateType) :: x_p, x_m + TYPE(SD_ContinuousStateType) :: x_perturb + REAL(R8Ki) :: RotateStates(3,3) + REAL(R8Ki) :: RotateStatesTranspose(3,3) + REAL(R8Ki) :: delta ! delta change in input or state + INTEGER(IntKi) :: i, k + INTEGER(IntKi) :: idx + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_JacobianPContState' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! make a copy of the continuous states to perturb NOTE: MESH_NEWCOPY + call SD_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + IF ( PRESENT( dYdx ) ) THEN + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%Jac_ny, p%Jac_nx*2, 'dYdx', ErrStat2, ErrMsg2); if(Failed()) return + end if + ! make a copy of outputs because we will need two for the central difference computations (with orientations) + call SD_CopyOutput( y, y_p, MESH_NEWCOPY, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_CopyOutput( y, y_m, MESH_NEWCOPY, ErrStat2, ErrMsg2); if(Failed()) return + idx = 1 + do k=1,2 ! 1=disp, 2=veloc + do i=1,p%Jac_nx ! CB mode + ! get x_op + delta x + call SD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_perturb_x(p, k, i, 1, x_perturb, delta ) + ! compute y at x_op + delta x + call SD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_p, m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get x_op - delta x + call SD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_perturb_x(p, k, i, -1, x_perturb, delta ) + ! compute y at x_op - delta x + call SD_CalcOutput( t, u, p, x_perturb, xd, z, OtherState, y_m, m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get central difference: + call SD_Compute_dY( p, y_p, y_m, delta, dYdx(:,idx) ) + idx = idx+1 + end do + end do + if(Failed()) return + END IF + IF ( PRESENT( dXdx ) ) THEN + ! Calculate the partial derivative of the continuous state functions (X) with respect to the continuous states (x) here: + ! TODO: dXdx should be constant, in theory we don't need to recompute it + if(ANALYTICAL_LIN) then + call StateMatrices(p, ErrStat2, ErrMsg2, AA=dXdx); if(Failed()) return ! Allocation occurs in function + else + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, p%Jac_nx * 2, p%Jac_nx * 2, 'dXdx', ErrStat2, ErrMsg2); if(Failed()) return + end if + idx = 1 ! counter into dXdx + do k=1,2 ! 1=positions (x_perturb%q); 2=velocities (x_perturb%dqdt) + do i=1,p%Jac_nx + ! get x_op + delta x + call SD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_perturb_x(p, k, i, 1, x_perturb, delta ) + ! compute x at x_op + delta x + call SD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_p, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ! get x_op - delta x + call SD_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + call SD_perturb_x(p, k, i, -1, x_perturb, delta ) + ! compute x at x_op - delta x + call SD_CalcContStateDeriv( t, u, p, x_perturb, xd, z, OtherState, m, x_m, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if(Failed()) return + ! get central difference: + call SD_Compute_dX( p, x_p, x_m, delta, dXdx(:,idx) ) + idx = idx+1 + end do + end do + endif ! analytical or numerical + END IF + IF ( PRESENT( dXddx ) ) THEN + if (allocated(dXddx)) deallocate(dXddx) + END IF + IF ( PRESENT( dZdx ) ) THEN + if (allocated(dZdx)) deallocate(dZdx) + END IF + call CleanUp() + +contains + + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_JacobianPContState') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + call SD_DestroyOutput( y_p, ErrStat2, ErrMsg2 ) + call SD_DestroyOutput( y_m, ErrStat2, ErrMsg2 ) + call SD_DestroyContState( x_p, ErrStat2, ErrMsg2 ) + call SD_DestroyContState( x_m, ErrStat2, ErrMsg2 ) + call SD_DestroyContState(x_perturb, ErrStat2, ErrMsg2 ) + end subroutine cleanup + +END SUBROUTINE SD_JacobianPContState + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the discrete states (xd). The partial derivatives dY/dxd, dX/dxd, dXd/dxd, and DZ/dxd are returned. +SUBROUTINE SD_JacobianPDiscState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdxd, dXdxd, dXddxd, dZdxd ) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Output (change to inout if a mesh copy is required); Output fields are not used by this routine, but type is available here so that mesh parameter information (i.e., connectivity) does not have to be recalculated for dYdx. + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdxd(:,:) !< Partial derivatives of output functions (Y) wrt the discrete states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdxd(:,:) !< Partial derivatives of continuous state functions (X) wrt the discrete states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddxd(:,:)!< Partial derivatives of discrete state functions (Xd) wrt the discrete states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdxd(:,:) !< Partial derivatives of constraint state functions (Z) wrt discrete states (xd) [intent in to avoid deallocation] + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + IF ( PRESENT( dYdxd ) ) THEN + END IF + IF ( PRESENT( dXdxd ) ) THEN + END IF + IF ( PRESENT( dXddxd ) ) THEN + END IF + IF ( PRESENT( dZdxd ) ) THEN + END IF +END SUBROUTINE SD_JacobianPDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the constraint states (z). The partial derivatives dY/dz, dX/dz, dXd/dz, and DZ/dz are returned. +SUBROUTINE SD_JacobianPConstrState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdz, dXdz, dXddz, dZdz ) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SD_OutputType), INTENT(INOUT) :: y !< Output (change to inout if a mesh copy is required); Output fields are not used by this routine, but type is available here so that mesh parameter information (i.e., connectivity) does not have to be recalculated for dYdx. + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdz(:,:) !< Partial derivatives of output functions (Y) with respect to the constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdz(:,:) !< Partial derivatives of continuous state functions (X) with respect to the constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddz(:,:) !< Partial derivatives of discrete state functions (Xd) with respect to the constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdz(:,:) !< Partial derivatives of constraint state functions (Z) with respect to the constraint states (z) [intent in to avoid deallocation] + ! local variables + character(*), parameter :: RoutineName = 'SD_JacobianPConstrState' + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + IF ( PRESENT( dYdz ) ) THEN + END IF + IF ( PRESENT( dXdz ) ) THEN + if (allocated(dXdz)) deallocate(dXdz) + END IF + IF ( PRESENT( dXddz ) ) THEN + if (allocated(dXddz)) deallocate(dXddz) + END IF + IF ( PRESENT(dZdz) ) THEN + END IF +END SUBROUTINE SD_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE SD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, y_op, x_op, dx_op, xd_op, z_op ) + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(SD_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: u_op(:) !< values of linearized inputs + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: y_op(:) !< values of linearized outputs + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: x_op(:) !< values of linearized continuous states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dx_op(:) !< values of first time derivatives of linearized continuous states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: xd_op(:) !< values of linearized discrete states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: z_op(:) !< values of linearized constraint states + ! Local + INTEGER(IntKi) :: idx, i + INTEGER(IntKi) :: nu + INTEGER(IntKi) :: ny + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_GetOP' + LOGICAL :: FieldMask(FIELDMASK_SIZE) + TYPE(SD_ContinuousStateType) :: dx ! derivative of continuous states at operating point + ErrStat = ErrID_None + ErrMsg = '' + IF ( PRESENT( u_op ) ) THEN + nu = size(p%Jac_u_indx,1) + u%TPMesh%NNodes * 6 ! Jac_u_indx has 3 orientation angles, but the OP needs the full 9 elements of the DCM (thus 6 more per node) + if (.not. allocated(u_op)) then + call AllocAry(u_op, nu, 'u_op', ErrStat2, ErrMsg2); if(Failed()) return + end if + idx = 1 + FieldMask = .false. + FieldMask(MASKID_TranslationDisp) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TranslationVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TranslationAcc) = .true. + FieldMask(MASKID_RotationAcc) = .true. + call PackMotionMesh(u%TPMesh, u_op, idx, FieldMask=FieldMask) + call PackLoadMesh(u%LMesh, u_op, idx) + END IF + IF ( PRESENT( y_op ) ) THEN + ny = p%Jac_ny + y%Y2Mesh%NNodes * 6 ! Jac_ny has 3 orientation angles, but the OP needs the full 9 elements of the DCM (thus 6 more per node) + if (.not. allocated(y_op)) then + call AllocAry(y_op, ny, 'y_op', ErrStat2, ErrMsg2); if(Failed()) return + end if + idx = 1 + call PackLoadMesh(y%Y1Mesh, y_op, idx) + FieldMask = .false. + FieldMask(MASKID_TranslationDisp) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TranslationVel) = .true. + FieldMask(MASKID_RotationVel) = .true. + FieldMask(MASKID_TranslationAcc) = .true. + FieldMask(MASKID_RotationAcc) = .true. + call PackMotionMesh(y%Y2Mesh, y_op, idx, FieldMask=FieldMask) + idx = idx - 1 + do i=1,p%NumOuts + y_op(i+idx) = y%WriteOutput(i) + end do + END IF + IF ( PRESENT( x_op ) ) THEN + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%Jac_nx*2,'x_op',ErrStat2,ErrMsg2); if (Failed()) return + end if + do i=1, p%Jac_nx + x_op(i) = x%qm(i) + end do + do i=1, p%Jac_nx + x_op(i+p%nDOFM) = x%qmdot(i) + end do + END IF + IF ( PRESENT( dx_op ) ) THEN + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%Jac_nx * 2,'dx_op',ErrStat2,ErrMsg2); if(failed()) return + end if + call SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) ; if(Failed()) return + idx = 1 + do i=1, p%Jac_nx + dx_op(i) = dx%qm(i) + end do + do i=1, p%Jac_nx + dx_op(i+p%nDOFM) = dx%qmdot(i) + end do + END IF + IF ( PRESENT( xd_op ) ) THEN + ! pass + END IF + IF ( PRESENT( z_op ) ) THEN + ! pass + END IF + call CleanUp() +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + + subroutine CleanUp() + call SD_DestroyContState(dx, ErrStat2, ErrMsg2); + end subroutine +END SUBROUTINE SD_GetOP +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ !------------------------------------------------------------------------------------------------------ !> Perform Craig Bampton (CB) reduction and set parameters needed for States and Ouputs equations !! Sets the following values, as documented in the SubDyn Theory Guide: @@ -1643,7 +2065,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) INTEGER(IntKi) :: nL, nM, nM_out INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb - LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 character(*), parameter :: RoutineName = 'SD_Craig_Bampton' @@ -1668,7 +2089,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return ! Switch between BC before or after CB, KEEP ME - BC_Before_CB=.true. if(BC_Before_CB) then !print*,' > Boundary conditions will be applied before Craig-Bampton (New)' nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction @@ -1919,7 +2339,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ErrMsg='Cannot use 6x6 Guyan Damping matrix, number of interface DOFs is'//num2lstr(size(p%CBB,1)); ErrStat=ErrID_Fatal; return endif - print*,'GuyanDampMat',Init%GuyanDampMat p%CBB = Init%GuyanDampMat endif @@ -2015,9 +2434,9 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, freq_max =maxval(OmegaL(1:p%nDOFM))/TwoPi dt_max = 1/(20*freq_max) - if (p%SDDeltaT>dt_max) then - print*,'Warning: time step appears too large compared to max SubDyn frequency.' - endif + !if (p%SDDeltaT>dt_max) then + ! print*,'info: time step may be too large compared to max SubDyn frequency.' + !endif write(Info,'(3x,A,F8.5,A,F8.5,A,F8.5)') 'SubDyn recommended dt:',dt_max, ' - Current dt:', p%SDDeltaT,' - Max frequency:', freq_max call WrScr(Info) ELSE ! no retained modes, so @@ -2060,7 +2479,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%CBB, nDOFL_TP, nDOFL_TP, 'p%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2080,7 +2499,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%D1_12, nDOFL_TP, nDOFL_TP , 'p%D1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 - CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L,'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if @@ -2448,9 +2867,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega real(ReKi), dimension(:,:), allocatable :: Modes + real(R8Ki), dimension(:,:), allocatable :: AA, BB, CC, DD ! Linearization matrices real(ReKi), dimension(:) , allocatable :: Omega logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) - character(len=*),parameter :: ReFmt='E15.6' + character(len=*),parameter :: ReFmt='ES15.6E2' character(len=*),parameter :: SFmt='A15,1x' ! Need +1 for comma compared to ReFmt character(len=*),parameter :: IFmt='I7' ! @@ -2495,7 +2915,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_var(UnSum, 'nNodes_C', p%nNodes_C,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "reactions" (C)') call yaml_write_var(UnSum, 'nNodes_L', p%nNodes_L,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "internal" (L)') call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') -#ifdef SD_SUMMARY_DEBUG + if(p%OutAll) then call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') call yaml_write_var(UnSum, 'nDOFI_B ', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') @@ -2505,12 +2925,12 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') -#endif + endif call yaml_write_var(UnSum, 'nDOF__B ', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: retained (__B)') call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: internal (__L)') call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: fixed (__F)') call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total') -#ifdef SD_SUMMARY_DEBUG + if(p%OutAll) then call yaml_write_array(UnSum, 'Nodes_I', p%Nodes_I(:,1), IFmt, ErrStat2, ErrMsg2, comment='"interface" nodes"') call yaml_write_array(UnSum, 'Nodes_C', p%Nodes_C(:,1), IFmt, ErrStat2, ErrMsg2, comment='"reaction" nodes"') call yaml_write_array(UnSum, 'Nodes_L', p%Nodes_L(:,1), IFmt, ErrStat2, ErrMsg2, comment='"internal" nodes"') @@ -2523,7 +2943,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'DOF_C_F', p%IDC_F , IFmt, ErrStat2, ErrMsg2, comment='"reaction" fixed DOFs') call yaml_write_array(UnSum, 'DOF_L_L', p%IDL_L , IFmt, ErrStat2, ErrMsg2, comment='"internal" internal DOFs') call yaml_write_array(UnSum, 'DOF_R_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') -#endif + endif call yaml_write_array(UnSum, 'DOF___B', p%ID__Rb, IFmt, ErrStat2, ErrMsg2, comment='all retained DOFs') call yaml_write_array(UnSum, 'DOF___F', p%ID__F , IFmt, ErrStat2, ErrMsg2, comment='all fixed DOFs') call yaml_write_array(UnSum, 'DOF___L', p%ID__L , IFmt, ErrStat2, ErrMsg2, comment='all internal DOFs') @@ -2567,7 +2987,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' - WRITE(UnSum, '("#",I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) + WRITE(UnSum, '("#",I8, ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#No. of Reaction DOFs:',p%nDOFC__ @@ -2626,7 +3046,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) XYZ2 = Init%Joints(iNode2,2:4) CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) DirCos=TRANSPOSE(DirCos) !This is now global to local - WRITE(UnSum, '("#",I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + WRITE(UnSum, '("#",I9,9(ES15.6E2))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO !------------------------------------------------------------------------------------------------------------- @@ -2676,11 +3096,12 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' call yaml_write_array(UnSum, 'MRB', MRB, ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A,E15.6)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) - WRITE(UnSum, '(A,3(E15.6))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) + WRITE(UnSum, '(A,ES15.6E2)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) + WRITE(UnSum, '(A,3(ES15.6E2))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) deallocate(TI2) -#ifdef SD_SUMMARY_DEBUG + + if(p%OutAll) then WRITE(UnSum, '()') WRITE(UnSum, '(A)') SectionDivide @@ -2727,14 +3148,25 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) endif ! --- Reduction info WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'T_red', p%T_red, 'E9.2', ErrStat2, ErrMsg2, comment='(Constraint elimination matrix)') -#endif + call yaml_write_array(UnSum, 'T_red', p%T_red, 'ES9.2E2', ErrStat2, ErrMsg2, comment='(Constraint elimination matrix)') + + ! --- Linearization/ state matrices + call StateMatrices(p, ErrStat2, ErrMsg2, AA, BB, CC, DD); if(Failed()) return + call yaml_write_array(UnSum, 'AA', AA, 'ES10.3E2', ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'BB', BB, 'ES10.3E2', ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'CC', CC, 'ES10.3E2', ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'DD', DD, 'ES10.3E2', ErrStat2, ErrMsg2) + if(allocated(AA)) deallocate(AA) + if(allocated(BB)) deallocate(BB) + if(allocated(CC)) deallocate(CC) + if(allocated(DD)) deallocate(DD) + endif ! --- write TP TI matrix WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'TI' , p%TI , 'E9.2', ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') + call yaml_write_array(UnSum, 'TI' , p%TI , 'ES9.2E2', ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') if (allocated(p%TIReact)) then - call yaml_write_array(UnSum, 'TIReact', p%TIReact, 'E9.2', ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') + call yaml_write_array(UnSum, 'TIReact', p%TIReact, 'ES9.2E2', ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') endif call CleanUp() @@ -2752,6 +3184,118 @@ SUBROUTINE CleanUp() END SUBROUTINE CleanUp END SUBROUTINE OutSummary +SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) + type(SD_ParameterType), intent(in) :: p !< Parameters + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + real(R8Ki), dimension(:,:), allocatable, optional :: AA !< + real(R8Ki), dimension(:,:), allocatable, optional :: BB !< + real(R8Ki), dimension(:,:), allocatable, optional :: CC !< + real(R8Ki), dimension(:,:), allocatable, optional :: DD !< + integer(IntKi) :: nU, nX, nY, nCB, i, j, iNode, iDOF, iOff,jj, k, nMembers, iField + real(R8Ki), dimension(:), allocatable :: dFext_dFmeshk + real(R8Ki), dimension(:), allocatable :: dFred_dFmeshk + real(R8Ki), dimension(:), allocatable :: dFL_dFmeshk + real(R8Ki), dimension(:,:), allocatable :: PhiM_T + character(ErrMsgLen) :: ErrMsg2 + integer(IntKi) :: ErrStat2 + ErrStat = ErrID_None + ErrMsg = "" + + nCB = p%nDOFM + nX = 2*nCB + nU = 18 + 6*p%nNodes + nY=6 + + ! --- A matrix + if (present(AA)) then + if(allocated(AA)) deallocate(AA) + call AllocAry(AA, nX, nX, 'AA', ErrStat2, ErrMsg2 ); if(Failed()) return; AA(:,:) = 0.0_ReKi + do i=1,nCB + AA(i,nCB+i) = 1.0_ReKi ! Identity for 12 + enddo + do i=1,nCB + AA(nCB+i,i ) = -p%KMMDiag(i) ! 11 + AA(nCB+i,nCB+i) = -p%CMMDiag(i) ! 22 + enddo + endif + + ! --- B matrix + if (present(BB)) then + if(allocated(BB)) deallocate(BB) + call AllocAry(BB, nX, nU, 'BB', ErrStat2, ErrMsg2 ); if(Failed()) return; BB(:,:) = 0.0_ReKi + BB(nCB+1:nX, 1 :6 ) = 0.0_ReKi + BB(nCB+1:nX, 7:12 ) = -p%CMB(1:nCB,1:6) + BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) + call AllocAry(dFext_dFmeshk, p%nDOF , 'dFext', ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(dFred_dFmeshk, p%nDOF_red , 'dFred', ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(dFL_dFmeshk , p%nDOF__L , 'dFl' , ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(PhiM_T , p%nDOFM , p%nDOF__L , 'PhiMT', ErrStat2, ErrMsg2 ); if(Failed()) return + PhiM_T = transpose(p%PhiM) + iOff=18 + k=0 + do iField = 1,2 ! Forces, Moment + do iNode = 1,p%nNodes + nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + do j=1,3 + k=k+1 + ! Build Fext with unit load (see GetExtForceOnInternalDOF) + dFext_dFmeshk= 0.0_ReKi + if (iField==1) then + ! Force - All nodes have only 3 translational DOFs + dFext_dFmeshk( p%NodesDOF(iNode)%List(j) ) = 1.0_ReKi + else + ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + dFext_dFmeshk( p%NodesDOF(iNode)%List((3+j)::3)) = 1.0_ReKi/nMembers + endif + ! Reduce and keep only "internal" DOFs L + if (p%reduced) then + dFred_dFmeshk = matmul(transpose(p%T_red), dFext_dFmeshk) + dFL_dFmeshk= dFred_dFmeshk(p%ID__L) + else + dFL_dFmeshk= dFext_dFmeshk(p%ID__L) + endif + ! + BB(nCB+1:nX, iOff+k) = matmul(PhiM_T, dFL_dFmeshk) + enddo ! 1-3 + enddo ! nodes + enddo ! field + endif + + ! --- C matrix + if (present(CC)) then + if(allocated(CC)) deallocate(CC) + call AllocAry(CC, nY, nX, 'CC', ErrStat2, ErrMsg2 ); if(Failed()) return; CC(:,:) = 0.0_ReKi + !print*,'Warning: C matrix does not have all outputs, or extra moment, or static solve' + CC(1:nY,1:nCB ) = - p%C1_11 + CC(1:nY,nCB+1:nX) = - p%C1_12 + endif + + ! --- D matrix + if (present(DD)) then + !print*,'Warning: D matrix does not have all outputs, or extra moment, or static solve' + if(allocated(DD)) deallocate(DD) + call AllocAry(DD, nY, nU, 'DD', ErrStat2, ErrMsg2 ); if(Failed()) return; DD(:,:) = 0.0_ReKi + DD(1:nY,1:6 ) = - p%KBB + DD(1:nY,7:12 ) = - p%D1_12 + DD(1:nY,13:18 ) = - p%D1_13 + endif + + call CleanUp() +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'StateMatrices') + Failed = ErrStat >= AbortErrLev + if(Failed) call CleanUp() + END FUNCTION Failed + SUBROUTINE CleanUp() + if(allocated(dFext_dFmeshk)) deallocate(dFext_dFmeshk) + if(allocated(dFred_dFmeshk)) deallocate(dFred_dFmeshk) + if(allocated(dFL_dFmeshk)) deallocate(dFL_dFmeshk) + if(allocated(PhiM_T)) deallocate(PhiM_T) + END SUBROUTINE CleanUp +END SUBROUTINE StateMatrices + !------------------------------------------------------------------------------------------------------ !> Calculate length of a member as given in input file !! Joints and Members ID have not been reindexed (Elems and Nodes have) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 2c68d3b49..55b6e5c95 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -40,6 +40,11 @@ MODULE SubDyn_Output PUBLIC :: SDOut_WriteOutputUnits PUBLIC :: SDOut_WriteOutputs PUBLIC :: SDOut_Init + PUBLIC :: SD_Init_Jacobian + PUBLIC :: SD_Perturb_u + PUBLIC :: SD_Perturb_x + PUBLIC :: SD_Compute_dY + PUBLIC :: SD_Compute_dX CONTAINS @@ -801,4 +806,235 @@ SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) END SUBROUTINE SDOut_ChkOutLst !==================================================================================================== +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. +!! Do not change the order of this packing without changing subroutine ! +SUBROUTINE SD_Init_Jacobian( p, u, y, m, InitOut, ErrStat, ErrMsg) + TYPE(SD_ParameterType) , INTENT(INOUT) :: p !< parameters + TYPE(SD_InputType) , INTENT(IN ) :: u !< inputs + TYPE(SD_OutputType) , INTENT(IN ) :: y !< outputs + TYPE(SD_MiscVarType) , INTENT(INOUT) :: m !< misc var data + TYPE(SD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) + INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_Init_Jacobian' + ! local variables: + ErrStat = ErrID_None + ErrMsg = "" + + call Init_Jacobian_y(); if (Failed()) return + call Init_Jacobian_x(); if (Failed()) return + call Init_Jacobian_u(); if (Failed()) return + +contains + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init_Jacobian') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed + !> This routine initializes the Jacobian parameters and initialization outputs for the linearized outputs. + + SUBROUTINE Init_Jacobian_y() + INTEGER(IntKi) :: index_next, i + ! Number of outputs + p%Jac_ny = y%Y1Mesh%nNodes * 6 & ! 3 forces + 3 moments at each node + + y%Y2Mesh%nNodes * 18 & ! 6 displacements + 6 velocities + 6 accelerations at each node + + p%NumOuts ! WriteOutput values + ! Storage info for each output (names, rotframe) + call AllocAry(InitOut%LinNames_y, p%Jac_ny, 'LinNames_y',ErrStat2,ErrMsg2); if(ErrStat2/=ErrID_None) return + call AllocAry(InitOut%RotFrame_y, p%Jac_ny, 'RotFrame_y',ErrStat2,ErrMsg2); if(ErrStat2/=ErrID_None) return + ! Names + index_next = 1 + call PackLoadMesh_Names( y%Y1Mesh, 'Interface displacement', InitOut%LinNames_y, index_next) + call PackMotionMesh_Names(y%Y2Mesh, 'Nodes motion' , InitOut%LinNames_y, index_next) + do i=1,p%NumOuts + InitOut%LinNames_y(i+index_next-1) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) + end do + ! RotFrame + InitOut%RotFrame_y(:) = .false. + END SUBROUTINE Init_Jacobian_y + + !> This routine initializes the Jacobian parameters and initialization outputs for the linearized continuous states. + SUBROUTINE Init_Jacobian_x() + INTEGER(IntKi) :: i + p%Jac_nx = p%nDOFM ! qm + ! allocate space for the row/column names and for perturbation sizes + CALL AllocAry(InitOut%LinNames_x , 2*p%Jac_nx, 'LinNames_x' , ErrStat2, ErrMsg2); if(ErrStat/=ErrID_None) return + CALL AllocAry(InitOut%RotFrame_x , 2*p%Jac_nx, 'RotFrame_x' , ErrStat2, ErrMsg2); if(ErrStat/=ErrID_None) return + CALL AllocAry(InitOut%DerivOrder_x, 2*p%Jac_nx, 'DerivOrder_x', ErrStat2, ErrMsg2); if(ErrStat/=ErrID_None) return + ! default perturbations, p%dx: + p%dx(1) = 2.0_ReKi*D2R_D ! deflection states in rad and rad/s + p%dx(2) = 2.0_ReKi*D2R_D ! deflection states in rad and rad/s + InitOut%RotFrame_x = .true. + InitOut%DerivOrder_x = 2 + ! set linearization output names: + do i=1,p%Jac_nx + InitOut%LinNames_x(i) = 'Craig-Bampton mode '//trim(num2lstr(i))//' amplitude, -'; + end do + do i=1,p%Jac_nx + InitOut%LinNames_x(i+p%Jac_nx) = 'First time derivative of '//trim(InitOut%LinNames_x(i))//'/s' + InitOut%RotFrame_x(i+p%Jac_nx) = InitOut%RotFrame_x(i) + end do + END SUBROUTINE Init_Jacobian_x + + SUBROUTINE Init_Jacobian_u() + REAL(R8Ki) :: perturb + INTEGER(IntKi) :: i, j, idx, nu, i_meshField + ! Number of inputs + nu = u%TPMesh%nNodes * 18 & ! 3 Translation Displacements + 3 orientations + 6 velocities + 6 accelerations at each node + + u%LMesh%nNodes * 6 ! 3 forces + 3 moments at each node + ! --- Info of linearized inputs (Names, RotFrame, IsLoad) + call AllocAry(InitOut%LinNames_u, nu, 'LinNames_u', ErrStat2, ErrMsg2); if(ErrStat2/=ErrID_None) return + call AllocAry(InitOut%RotFrame_u, nu, 'RotFrame_u', ErrStat2, ErrMsg2); if(ErrStat2/=ErrID_None) return + call AllocAry(InitOut%IsLoad_u , nu, 'IsLoad_u' , ErrStat2, ErrMsg2); if(ErrStat2/=ErrID_None) return + InitOut%RotFrame_u = .false. ! every input is on a mesh, which stores values in the global (not rotating) frame + idx = 1 + call PackMotionMesh_Names(u%TPMesh, 'TPMesh', InitOut%LinNames_u, idx) ! all 6 motion fields + InitOut%IsLoad_u(1:idx-1) = .false. ! the TPMesh inputs are not loads + InitOut%IsLoad_u(idx:) = .true. ! the remaining inputs are loads + call PackLoadMesh_Names( u%LMesh, 'LMesh', InitOut%LinNames_u, idx) + + ! --- Jac_u_indx: matrix to store index to help us figure out what the ith value of the u vector really means + ! (see perturb_u ... these MUST match ) + ! column 1 indicates module's mesh and field + ! column 2 indicates the first index (x-y-z component) of the field + ! column 3 is the node + call allocAry( p%Jac_u_indx, nu, 3, 'p%Jac_u_indx', ErrStat2, ErrMsg2); if(ErrStat2/=ErrID_None) return + idx = 1 + !Module/Mesh/Field: u%TPMesh%TranslationDisp = 1; + !Module/Mesh/Field: u%TPMesh%Orientation = 2; + !Module/Mesh/Field: u%TPMesh%TranslationVel = 3; + !Module/Mesh/Field: u%TPMesh%RotationVel = 4; + !Module/Mesh/Field: u%TPMesh%TranslationAcc = 5; + !Module/Mesh/Field: u%TPMesh%RotationAcc = 6; + do i_meshField = 1,6 + do i=1,u%TPMesh%nNodes + do j=1,3 + p%Jac_u_indx(idx,1) = i_meshField + p%Jac_u_indx(idx,2) = j !component idx: j + p%Jac_u_indx(idx,3) = i !Node: i + idx = idx + 1 + end do !j + end do !i + end do + !Module/Mesh/Field: u%LMesh%Force = 7; + !Module/Mesh/Field: u%LMesh%Moment = 8; + do i_meshField = 7,8 + do i=1,u%LMesh%nNodes + do j=1,3 + p%Jac_u_indx(idx,1) = i_meshField + p%Jac_u_indx(idx,2) = j !component idx: j + p%Jac_u_indx(idx,3) = i !Node: i + idx = idx + 1 + end do !j + end do !i + end do + + ! --- Default perturbations, p%du: + call allocAry( p%du, 8, 'p%du', ErrStat2, ErrMsg2); if(ErrStat2/=ErrID_None) return ! 8 = number of unique values in p%Jac_u_indx(:,1) + perturb = 2.0_R8Ki*D2R_D + p%du( 1) = perturb ! u%TPMesh%TranslationDisp = 1; + p%du( 2) = perturb ! u%TPMesh%Orientation = 2; + p%du( 3) = perturb ! u%TPMesh%TranslationVel = 3; + p%du( 4) = perturb ! u%TPMesh%RotationVel = 4; + p%du( 5) = perturb ! u%TPMesh%TranslationAcc = 5; + p%du( 6) = perturb ! u%TPMesh%RotationAcc = 6; + p%du( 7) = perturb*5000 ! u%LMesh%Force = 7; + p%du( 8) = perturb*50000 ! u%LMesh%Moment = 8; + END SUBROUTINE Init_Jacobian_u + +END SUBROUTINE SD_Init_Jacobian +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the u array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE SD_Perturb_u( p, n, perturb_sign, u, du ) + TYPE(SD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: n !< number of array element to use + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(SD_InputType) , INTENT(INOUT) :: u !< perturbed SD inputs + REAL( R8Ki ) , INTENT( OUT) :: du !< amount that specific input was perturbed + ! local variables + INTEGER :: fieldIndx + INTEGER :: node + fieldIndx = p%Jac_u_indx(n,2) + node = p%Jac_u_indx(n,3) + du = p%du( p%Jac_u_indx(n,1) ) + ! determine which mesh we're trying to perturb and perturb the input: + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 1) !Module/Mesh/Field: u%TPMesh%TranslationDisp = 1; + u%TPMesh%TranslationDisp( fieldIndx,node) = u%TPMesh%TranslationDisp( fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%TPMesh%Orientation = 2; + CALL PerturbOrientationMatrix( u%TPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%TPMesh%TranslationVel = 3; + u%TPMesh%TranslationVel( fieldIndx,node) = u%TPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%TPMesh%RotationVel = 4; + u%TPMesh%RotationVel(fieldIndx,node) = u%TPMesh%RotationVel(fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%TPMesh%TranslationAcc = 5; + u%TPMesh%TranslationAcc( fieldIndx,node) = u%TPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%TPMesh%RotationAcc = 6; + u%TPMesh%RotationAcc(fieldIndx,node) = u%TPMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + CASE ( 7) !Module/Mesh/Field: u%LMesh%Force = 7; + u%LMesh%Force(fieldIndx,node) = u%LMesh%Force(fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%LMesh%Moment = 8; + u%LMesh%Moment(fieldIndx,node) = u%LMesh%Moment(fieldIndx,node) + du * perturb_sign + END SELECT +END SUBROUTINE SD_Perturb_u +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine beamdyn::init_jacobian is consistant with this routine! +SUBROUTINE SD_Compute_dY(p, y_p, y_m, delta, dY) + TYPE(SD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(SD_OutputType) , INTENT(IN ) :: y_p !< SD outputs at \f$ u + \Delta_p u \f$ or \f$ z + \Delta_p z \f$ (p=plus) + TYPE(SD_OutputType) , INTENT(IN ) :: y_m !< SD outputs at \f$ u - \Delta_m u \f$ or \f$ z - \Delta_m z \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dY(:) !< column of dYdu or dYdx: \f$ \frac{\partial Y}{\partial u_i} = \frac{y_p - y_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial Y}{\partial z_i} = \frac{y_p - y_m}{2 \, \Delta x}\f$ + ! local variables: + INTEGER(IntKi) :: i ! loop over outputs + INTEGER(IntKi) :: indx_first ! index indicating next value of dY to be filled + indx_first = 1 + call PackLoadMesh_dY( y_p%Y1Mesh, y_m%Y1Mesh, dY, indx_first) + call PackMotionMesh_dY(y_p%Y2Mesh, y_m%Y2Mesh, dY, indx_first) ! all 6 motion fields + do i=1,p%NumOuts + dY(i+indx_first-1) = y_p%WriteOutput(i) - y_m%WriteOutput(i) + end do + dY = dY / (2.0_R8Ki*delta) +END SUBROUTINE SD_Compute_dY +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine perturbs the nth element of the x array (and mesh/field it corresponds to) +!! Do not change this without making sure subroutine sd_init_jacobian is consistant with this routine! +SUBROUTINE SD_Perturb_x( p, fieldIndx, mode, perturb_sign, x, dx ) + TYPE(SD_ParameterType) , INTENT(IN ) :: p !< parameters + INTEGER( IntKi ) , INTENT(IN ) :: fieldIndx !< field in the state type: 1=displacements; 2=velocities + INTEGER( IntKi ) , INTENT(IN ) :: mode !< node number + INTEGER( IntKi ) , INTENT(IN ) :: perturb_sign !< +1 or -1 (value to multiply perturbation by; positive or negative difference) + TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< perturbed SD states + REAL( R8Ki ) , INTENT( OUT) :: dx !< amount that specific state was perturbed + if (fieldIndx==1) then + dx=p%dx(1) + x%qm(mode) = x%qm(mode) + dx * perturb_sign + else + dx=p%dx(2) + x%qmdot(mode) = x%qmdot(mode) + dx * perturb_sign + end if +END SUBROUTINE SD_Perturb_x +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine uses values of two output types to compute an array of differences. +!! Do not change this packing without making sure subroutine sd_init_jacobian is consistant with this routine! +SUBROUTINE SD_Compute_dX(p, x_p, x_m, delta, dX) + TYPE(SD_ParameterType) , INTENT(IN ) :: p !< parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x_p !< SD continuous states at \f$ u + \Delta_p u \f$ or \f$ x + \Delta_p x \f$ (p=plus) + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x_m !< SD continuous states at \f$ u - \Delta_m u \f$ or \f$ x - \Delta_m x \f$ (m=minus) + REAL(R8Ki) , INTENT(IN ) :: delta !< difference in inputs or states \f$ delta_p = \Delta_p u \f$ or \f$ delta_p = \Delta_p x \f$ + REAL(R8Ki) , INTENT(INOUT) :: dX(:) !< column of dXdu or dXdx: \f$ \frac{\partial X}{\partial u_i} = \frac{x_p - x_m}{2 \, \Delta u}\f$ or \f$ \frac{\partial X}{\partial x_i} = \frac{x_p - x_m}{2 \, \Delta x}\f$ + INTEGER(IntKi) :: i ! loop over modes + do i=1,p%Jac_nx + dX(i) = x_p%qm(i) - x_m%qm(i) + end do + do i=1,p%Jac_nx + dX(p%Jac_nx+i) = x_p%qmdot(i) - x_m%qmdot(i) + end do + dX = dX / (2.0_R8Ki*delta) +END SUBROUTINE SD_Compute_dX + END MODULE SubDyn_Output diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index f3f440604..20967fcd7 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -15,17 +15,27 @@ typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" ! type(IList), pointer :: next => null() # ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ -typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" -typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" -typedef ^ InitInputType ReKi g - - - "Gravity acceleration" -typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" -typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" -typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" +typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ InitInputType ReKi g - - - "Gravity acceleration" +typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" +typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - # ============================== Define Initialization outputs here: ============================================================================================================================================ typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +# Linearization +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ InitOutputType LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - # ============================== Define Internal data types here: ============================================================================================================================================ typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" @@ -261,6 +271,13 @@ typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" +# --- Linearization +typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ParameterType R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" +typedef ^ ParameterType R8Ki dx {2} - - "vector that determines size of perturbation for x (continuous states)" +typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - +typedef ^ ParameterType Integer Jac_nx - - - "half the number of continuous states in jacobian matrix" - +typedef ^ ParameterType logical RotStates - - - "Orient states in rotating frame during linearization? (flag)" - # ============================== Inputs ============================================================================================================================================ typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 000e61d57..a9d6ffdb4 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -46,6 +46,7 @@ MODULE SubDyn_Types REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] END TYPE SD_InitInputType ! ======================= ! ========= SD_InitOutputType ======= @@ -53,6 +54,14 @@ MODULE SubDyn_Types CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] END TYPE SD_InitOutputType ! ======================= ! ========= MeshAuxDataType ======= @@ -297,6 +306,12 @@ MODULE SubDyn_Types INTEGER(IntKi) :: OutAllInt !< Integer version of OutAll [-] INTEGER(IntKi) :: OutAllDims !< Integer version of OutAll [-] INTEGER(IntKi) :: OutDec !< Output Decimation for Requested Channels [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Jac_u_indx !< matrix to help fill/pack the u vector in computing the jacobian [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-] + REAL(R8Ki) , DIMENSION(1:2) :: dx !< vector that determines size of perturbation for x (continuous states) [-] + INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-] + INTEGER(IntKi) :: Jac_nx !< half the number of continuous states in jacobian matrix [-] + LOGICAL :: RotStates !< Orient states in rotating frame during linearization? (flag) [-] END TYPE SD_ParameterType ! ======================= ! ========= SD_InputType ======= @@ -523,6 +538,7 @@ SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ + DstInitInputData%Linearize = SrcInitInputData%Linearize END SUBROUTINE SD_CopyInitInput SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) @@ -577,6 +593,7 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = Re_BufSz + 1 ! WtrDpth Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Int_BufSz = Int_BufSz + 1 ! Linearize IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -620,6 +637,8 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ Re_Xferred = Re_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Linearize , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackInitInput SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -680,6 +699,8 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err DEALLOCATE(mask1) OutData%SubRotateZ = ReKiBuf( Re_Xferred ) Re_Xferred = Re_Xferred + 1 + OutData%Linearize = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_UnPackInitInput SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -724,6 +745,102 @@ SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, Er CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x +ENDIF END SUBROUTINE SD_CopyInitOutput SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) @@ -742,6 +859,30 @@ SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) DEALLOCATE(InitOutputData%WriteOutputUnt) ENDIF CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) +ENDIF +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF END SUBROUTINE SD_DestroyInitOutput SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -807,6 +948,46 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -896,6 +1077,122 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%RotFrame_y)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_y)-1 ) = TRANSFER(PACK( InData%RotFrame_y ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_y)) + Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_y) + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%RotFrame_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_x)-1 ) = TRANSFER(PACK( InData%RotFrame_x ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_x)) + Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_x) + END IF + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%RotFrame_u)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_u)-1 ) = TRANSFER(PACK( InData%RotFrame_u ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_u)) + Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_u) + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%IsLoad_u)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%IsLoad_u)-1 ) = TRANSFER(PACK( InData%IsLoad_u ,.TRUE.), IntKiBuf(1), SIZE(InData%IsLoad_u)) + Int_Xferred = Int_Xferred + SIZE(InData%IsLoad_u) + END IF + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) + END IF END SUBROUTINE SD_PackInitOutput SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1025,6 +1322,202 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO !i1 + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%RotFrame_y)>0) OutData%RotFrame_y = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_y))-1 ), OutData%RotFrame_y), mask1,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_y) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%RotFrame_x)>0) OutData%RotFrame_x = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_x))-1 ), OutData%RotFrame_x), mask1,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_x) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%RotFrame_u)>0) OutData%RotFrame_u = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_u))-1 ), OutData%RotFrame_u), mask1,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%IsLoad_u)>0) OutData%IsLoad_u = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IsLoad_u))-1 ), OutData%IsLoad_u), mask1,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(OutData%IsLoad_u) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) + DEALLOCATE(mask1) + END IF END SUBROUTINE SD_UnPackInitOutput SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -7149,6 +7642,36 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%OutAllInt = SrcParamData%OutAllInt DstParamData%OutAllDims = SrcParamData%OutAllDims DstParamData%OutDec = SrcParamData%OutDec +IF (ALLOCATED(SrcParamData%Jac_u_indx)) THEN + i1_l = LBOUND(SrcParamData%Jac_u_indx,1) + i1_u = UBOUND(SrcParamData%Jac_u_indx,1) + i2_l = LBOUND(SrcParamData%Jac_u_indx,2) + i2_u = UBOUND(SrcParamData%Jac_u_indx,2) + IF (.NOT. ALLOCATED(DstParamData%Jac_u_indx)) THEN + ALLOCATE(DstParamData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Jac_u_indx = SrcParamData%Jac_u_indx +ENDIF +IF (ALLOCATED(SrcParamData%du)) THEN + i1_l = LBOUND(SrcParamData%du,1) + i1_u = UBOUND(SrcParamData%du,1) + IF (.NOT. ALLOCATED(DstParamData%du)) THEN + ALLOCATE(DstParamData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%du = SrcParamData%du +ENDIF + DstParamData%dx = SrcParamData%dx + DstParamData%Jac_ny = SrcParamData%Jac_ny + DstParamData%Jac_nx = SrcParamData%Jac_nx + DstParamData%RotStates = SrcParamData%RotStates END SUBROUTINE SD_CopyParam SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) @@ -7357,6 +7880,12 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%OutParam) +ENDIF +IF (ALLOCATED(ParamData%Jac_u_indx)) THEN + DEALLOCATE(ParamData%Jac_u_indx) +ENDIF +IF (ALLOCATED(ParamData%du)) THEN + DEALLOCATE(ParamData%du) ENDIF END SUBROUTINE SD_DestroyParam @@ -7854,6 +8383,20 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! OutAllInt Int_BufSz = Int_BufSz + 1 ! OutAllDims Int_BufSz = Int_BufSz + 1 ! OutDec + Int_BufSz = Int_BufSz + 1 ! Jac_u_indx allocated yes/no + IF ( ALLOCATED(InData%Jac_u_indx) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Jac_u_indx upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Jac_u_indx) ! Jac_u_indx + END IF + Int_BufSz = Int_BufSz + 1 ! du allocated yes/no + IF ( ALLOCATED(InData%du) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! du upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%du) ! du + END IF + Db_BufSz = Db_BufSz + SIZE(InData%dx) ! dx + Int_BufSz = Int_BufSz + 1 ! Jac_ny + Int_BufSz = Int_BufSz + 1 ! Jac_nx + Int_BufSz = Int_BufSz + 1 ! RotStates IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -9020,6 +9563,43 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutDec Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Jac_u_indx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%Jac_u_indx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Jac_u_indx))-1 ) = PACK(InData%Jac_u_indx,.TRUE.) + Int_Xferred = Int_Xferred + SIZE(InData%Jac_u_indx) + END IF + IF ( .NOT. ALLOCATED(InData%du) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%du,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%du)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%du))-1 ) = PACK(InData%du,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%du) + END IF + DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%dx))-1 ) = PACK(InData%dx,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%dx) + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Jac_nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%RotStates , IntKiBuf(1), 1) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackParam SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -10820,6 +11400,72 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%OutDec = IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Jac_u_indx)) DEALLOCATE(OutData%Jac_u_indx) + ALLOCATE(OutData%Jac_u_indx(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask2 = .TRUE. + IF (SIZE(OutData%Jac_u_indx)>0) OutData%Jac_u_indx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Jac_u_indx))-1 ), mask2, 0_IntKi ) + Int_Xferred = Int_Xferred + SIZE(OutData%Jac_u_indx) + DEALLOCATE(mask2) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%du)) DEALLOCATE(OutData%du) + ALLOCATE(OutData%du(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%du)>0) OutData%du = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%du))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%du) + DEALLOCATE(mask1) + END IF + i1_l = LBOUND(OutData%dx,1) + i1_u = UBOUND(OutData%dx,1) + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + OutData%dx = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%dx))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%dx) + DEALLOCATE(mask1) + OutData%Jac_ny = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%Jac_nx = IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + OutData%RotStates = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_UnPackParam SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) From c8cfc6d69194b864e4e0a5c6341fdd69ad29bf1f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 14 Jul 2020 17:40:45 -0600 Subject: [PATCH 244/377] FlexSub: doc: update to remove Joint damping --- docs/source/user/api_change.rst | 4 +- .../subdyn/examples/OC4_Jacket_SD_Input.dat | 136 +++++++++--------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index 49e75deba..836b3221c 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -43,8 +43,8 @@ Changed in OpenFAST v2.4.0 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Module Line Flag Name Example Value ============================================= ==== =============== ======================================================================================================================================================================================================== -SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp -SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) +SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff +SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) SubDyn na Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID SubDyn na Members (-) (-) (-) (-) (-) (-) (-) SubDyn na ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index 9e13f79d9..ad619999d 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -14,7 +14,7 @@ True CBMod - [T/F] If True perform C-B reduction, else full FE 1 JDampings - Damping Ratios for each retained mode (% of critical) If Nmodes>0, list Nmodes structural damping ratios for each retained mode (% of critical), or a single damping ratio to be applied to all retained modes. (last entered value will be used for all remaining modes). 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} 0.000, 0.000 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] - 6 GuyanDampMat - Guyan damping matrix (6x6) [only if GuyanDampMod=2] + 6 GuyanDampSize - Guyan damping matrix (6x6) [only if GuyanDampMod=2] 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 @@ -23,72 +23,72 @@ True CBMod - [T/F] If True perform C-B reduction, else full FE 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 ---- STRUCTURE JOINTS: joints connect structure members (~Hydrodyn Input File)--- 64 NJoints - Number of joints (-) -JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff JointDamp - (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) (Nm/rad.s) - 1 6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 - 2 6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 - 3 5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 - 4 5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 - 5 5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 - 6 -6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 - 7 -6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 - 8 -5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 - 9 -5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 - 10 -5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 - 11 -6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 - 12 -6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 - 13 -5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 - 14 -5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 - 15 -5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 - 16 6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 0.0 - 17 6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 0.0 - 18 5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 0.0 - 19 5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 0.0 - 20 5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 0.0 - 21 4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 - 22 4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 - 23 4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 - 24 4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 - 25 -4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 - 26 -4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 - 27 -4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 - 28 -4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 - 29 -4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 - 30 -4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 - 31 -4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 - 32 -4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 - 33 4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 0.0 - 34 4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 0.0 - 35 4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 0.0 - 36 4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 0.0 - 37 5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 - 38 -5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 - 39 0.00000 5.62000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 - 40 0.00000 -5.62000 -33.37300 1 0.0 0.0 0.0 0.0 0.0 - 41 5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 0.0 - 42 -5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 0.0 - 43 0.00000 5.06400 -16.37100 1 0.0 0.0 0.0 0.0 0.0 - 44 0.00000 -5.06400 -16.37100 1 0.0 0.0 0.0 0.0 0.0 - 45 4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 0.0 - 46 -4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 0.0 - 47 0.00000 4.59200 -1.95800 1 0.0 0.0 0.0 0.0 0.0 - 48 0.00000 -4.59200 -1.95800 1 0.0 0.0 0.0 0.0 0.0 - 49 4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 0.0 - 50 -4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 0.0 - 51 0.00000 4.19300 10.26200 1 0.0 0.0 0.0 0.0 0.0 - 52 0.00000 -4.19300 10.26200 1 0.0 0.0 0.0 0.0 0.0 - 53 4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 - 54 -4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 - 55 4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 - 56 -4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 0.0 - 57 6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 - 58 6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 - 59 -6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 - 60 -6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 0.0 - 61 6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 - 62 6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 - 63 -6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 - 64 -6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 0.0 +JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff + (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) + 1 6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 + 2 6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 + 3 5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 + 4 5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 + 5 5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 + 6 -6.00000 6.00000 -45.50000 1 0.0 0.0 0.0 0.0 + 7 -6.00000 6.00000 -45.00000 1 0.0 0.0 0.0 0.0 + 8 -5.96700 5.96700 -44.00100 1 0.0 0.0 0.0 0.0 + 9 -5.93900 5.93900 -43.12700 1 0.0 0.0 0.0 0.0 + 10 -5.33300 5.33300 -24.61400 1 0.0 0.0 0.0 0.0 + 11 -6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 + 12 -6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 + 13 -5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 + 14 -5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 + 15 -5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 + 16 6.00000 -6.00000 -45.50000 1 0.0 0.0 0.0 0.0 + 17 6.00000 -6.00000 -45.00000 1 0.0 0.0 0.0 0.0 + 18 5.96700 -5.96700 -44.00100 1 0.0 0.0 0.0 0.0 + 19 5.93900 -5.93900 -43.12700 1 0.0 0.0 0.0 0.0 + 20 5.33300 -5.33300 -24.61400 1 0.0 0.0 0.0 0.0 + 21 4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 + 22 4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 + 23 4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 + 24 4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 + 25 -4.82000 4.82000 -8.92200 1 0.0 0.0 0.0 0.0 + 26 -4.38500 4.38500 4.37800 1 0.0 0.0 0.0 0.0 + 27 -4.01600 4.01600 15.65100 1 0.0 0.0 0.0 0.0 + 28 -4.00000 4.00000 16.15000 1 0.0 0.0 0.0 0.0 + 29 -4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 + 30 -4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 + 31 -4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 + 32 -4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 + 33 4.82000 -4.82000 -8.92200 1 0.0 0.0 0.0 0.0 + 34 4.38500 -4.38500 4.37800 1 0.0 0.0 0.0 0.0 + 35 4.01600 -4.01600 15.65100 1 0.0 0.0 0.0 0.0 + 36 4.00000 -4.00000 16.15000 1 0.0 0.0 0.0 0.0 + 37 5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 + 38 -5.62000 0.00000 -33.37300 1 0.0 0.0 0.0 0.0 + 39 0.00000 5.62000 -33.37300 1 0.0 0.0 0.0 0.0 + 40 0.00000 -5.62000 -33.37300 1 0.0 0.0 0.0 0.0 + 41 5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 + 42 -5.06400 0.00000 -16.37100 1 0.0 0.0 0.0 0.0 + 43 0.00000 5.06400 -16.37100 1 0.0 0.0 0.0 0.0 + 44 0.00000 -5.06400 -16.37100 1 0.0 0.0 0.0 0.0 + 45 4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 + 46 -4.59200 0.00000 -1.95800 1 0.0 0.0 0.0 0.0 + 47 0.00000 4.59200 -1.95800 1 0.0 0.0 0.0 0.0 + 48 0.00000 -4.59200 -1.95800 1 0.0 0.0 0.0 0.0 + 49 4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 + 50 -4.19300 0.00000 10.26200 1 0.0 0.0 0.0 0.0 + 51 0.00000 4.19300 10.26200 1 0.0 0.0 0.0 0.0 + 52 0.00000 -4.19300 10.26200 1 0.0 0.0 0.0 0.0 + 53 4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 + 54 -4.00000 4.00000 20.15000 1 0.0 0.0 0.0 0.0 + 55 4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 + 56 -4.00000 -4.00000 20.15000 1 0.0 0.0 0.0 0.0 + 57 6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 + 58 6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 + 59 -6.00000 -6.00000 -49.50000 1 0.0 0.0 0.0 0.0 + 60 -6.00000 6.00000 -49.50000 1 0.0 0.0 0.0 0.0 + 61 6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 + 62 6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 + 63 -6.00000 -6.00000 -50.00100 1 0.0 0.0 0.0 0.0 + 64 -6.00000 6.00000 -50.00100 1 0.0 0.0 0.0 0.0 ------------------- BASE REACTION JOINTS: 1/0 for Locked/Free DOF @ each Reaction Node --------------------- 4 NReact - Number of Joints with reaction forces; be sure to remove all rigid motion DOFs of the structure (else det([K])=[0]) RJointID RctTDXss RctTDYss RctTDZss RctRDXss RctRDYss RctRDZss SSIfile [Global Coordinate System] @@ -257,7 +257,7 @@ CMJointID JMass JMXX JMYY JMZZ ---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. IT can also … False OutCOSM - Output cosine matrices with the selected output member forces (flag) -False OutAll - [T/F] Output all members' end forces +False OutAll - [T/F] Output all members' end forces and additional summary file info 1 OutSwtch - [1/2/3] Output requested channels to: 1=.SD.out 2=.out (generated by FAST) 3=both files. True TabDelim - Generate a tab-delimited output in the .SD.out file 1 OutDec - Decimation of output in the .SD.out file From 61c5684c9e04fe015f8bba6905a6e19334d91d84 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 14 Jul 2020 18:15:16 -0600 Subject: [PATCH 245/377] FlexSub: adjusting perturb_u, and small fixes --- modules/subdyn/src/SubDyn.f90 | 112 ++++++++++++++------------- modules/subdyn/src/SubDyn_Output.f90 | 15 +++- 2 files changed, 70 insertions(+), 57 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f07335c69..087415d5d 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -294,7 +294,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO END IF if (InitInput%Linearize) then - call SD_Init_Jacobian( p, u, y, m, InitOut, ErrStat2, ErrMsg2); if(Failed()) return + call SD_Init_Jacobian(Init, p, u, y, m, InitOut, ErrStat2, ErrMsg2); if(Failed()) return endif ! Tell GLUECODE the SubDyn timestep interval @@ -614,7 +614,6 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! form u(4) in Eq. 10: CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) - !print*,'UFL',m%UFL !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot @@ -622,8 +621,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) !dxdt%qmdot = -p%KMMDiag*x%qm + p%CMMDiag*x%qmdot - matmul(p%CMB,m%udotdot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(transpose(p%PhiM), m%UFL) + p%FX - !print*,'PhiM_T UFL', matmul(transpose(p%PhiM), m%UFL) + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) + p%FX END SUBROUTINE SD_CalcContStateDeriv @@ -1137,11 +1135,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) subroutine LegacyWarning(Message) character(len=*), intent(in) :: Message - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - print*,'Warning: the SubDyn input file is not at the latest format!' - print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' - print*,'> Issue: '//trim(Message) - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + call WrScr('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + call WrScr('Warning: the SubDyn input file is not at the latest format!' ) + call WrScr(' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html') + call WrScr('> Issue: '//trim(Message)) + call WrScr('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') end subroutine LegacyWarning LOGICAL FUNCTION Check(Condition, ErrMsg_in) @@ -3211,55 +3209,59 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) if (present(AA)) then if(allocated(AA)) deallocate(AA) call AllocAry(AA, nX, nX, 'AA', ErrStat2, ErrMsg2 ); if(Failed()) return; AA(:,:) = 0.0_ReKi - do i=1,nCB - AA(i,nCB+i) = 1.0_ReKi ! Identity for 12 - enddo - do i=1,nCB - AA(nCB+i,i ) = -p%KMMDiag(i) ! 11 - AA(nCB+i,nCB+i) = -p%CMMDiag(i) ! 22 - enddo + if (nCB>0) then + do i=1,nCB + AA(i,nCB+i) = 1.0_ReKi ! Identity for 12 + enddo + do i=1,nCB + AA(nCB+i,i ) = -p%KMMDiag(i) ! 11 + AA(nCB+i,nCB+i) = -p%CMMDiag(i) ! 22 + enddo + endif endif ! --- B matrix if (present(BB)) then if(allocated(BB)) deallocate(BB) call AllocAry(BB, nX, nU, 'BB', ErrStat2, ErrMsg2 ); if(Failed()) return; BB(:,:) = 0.0_ReKi - BB(nCB+1:nX, 1 :6 ) = 0.0_ReKi - BB(nCB+1:nX, 7:12 ) = -p%CMB(1:nCB,1:6) - BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) - call AllocAry(dFext_dFmeshk, p%nDOF , 'dFext', ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry(dFred_dFmeshk, p%nDOF_red , 'dFred', ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry(dFL_dFmeshk , p%nDOF__L , 'dFl' , ErrStat2, ErrMsg2 ); if(Failed()) return - call AllocAry(PhiM_T , p%nDOFM , p%nDOF__L , 'PhiMT', ErrStat2, ErrMsg2 ); if(Failed()) return - PhiM_T = transpose(p%PhiM) - iOff=18 - k=0 - do iField = 1,2 ! Forces, Moment - do iNode = 1,p%nNodes - nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList - do j=1,3 - k=k+1 - ! Build Fext with unit load (see GetExtForceOnInternalDOF) - dFext_dFmeshk= 0.0_ReKi - if (iField==1) then - ! Force - All nodes have only 3 translational DOFs - dFext_dFmeshk( p%NodesDOF(iNode)%List(j) ) = 1.0_ReKi - else - ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs - dFext_dFmeshk( p%NodesDOF(iNode)%List((3+j)::3)) = 1.0_ReKi/nMembers - endif - ! Reduce and keep only "internal" DOFs L - if (p%reduced) then - dFred_dFmeshk = matmul(transpose(p%T_red), dFext_dFmeshk) - dFL_dFmeshk= dFred_dFmeshk(p%ID__L) - else - dFL_dFmeshk= dFext_dFmeshk(p%ID__L) - endif - ! - BB(nCB+1:nX, iOff+k) = matmul(PhiM_T, dFL_dFmeshk) - enddo ! 1-3 - enddo ! nodes - enddo ! field + if(nCB>0) then + BB(nCB+1:nX, 1 :6 ) = 0.0_ReKi + BB(nCB+1:nX, 7:12 ) = -p%CMB(1:nCB,1:6) + BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) + call AllocAry(dFext_dFmeshk, p%nDOF , 'dFext', ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(dFred_dFmeshk, p%nDOF_red , 'dFred', ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(dFL_dFmeshk , p%nDOF__L , 'dFl' , ErrStat2, ErrMsg2 ); if(Failed()) return + call AllocAry(PhiM_T , p%nDOFM , p%nDOF__L , 'PhiMT', ErrStat2, ErrMsg2 ); if(Failed()) return + PhiM_T = transpose(p%PhiM) + iOff=18 + k=0 + do iField = 1,2 ! Forces, Moment + do iNode = 1,p%nNodes + nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + do j=1,3 + k=k+1 + ! Build Fext with unit load (see GetExtForceOnInternalDOF) + dFext_dFmeshk= 0.0_ReKi + if (iField==1) then + ! Force - All nodes have only 3 translational DOFs + dFext_dFmeshk( p%NodesDOF(iNode)%List(j) ) = 1.0_ReKi + else + ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + dFext_dFmeshk( p%NodesDOF(iNode)%List((3+j)::3)) = 1.0_ReKi/nMembers + endif + ! Reduce and keep only "internal" DOFs L + if (p%reduced) then + dFred_dFmeshk = matmul(transpose(p%T_red), dFext_dFmeshk) + dFL_dFmeshk= dFred_dFmeshk(p%ID__L) + else + dFL_dFmeshk= dFext_dFmeshk(p%ID__L) + endif + ! + BB(nCB+1:nX, iOff+k) = matmul(PhiM_T, dFL_dFmeshk) + enddo ! 1-3 + enddo ! nodes + enddo ! field + endif endif ! --- C matrix @@ -3267,8 +3269,10 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) if(allocated(CC)) deallocate(CC) call AllocAry(CC, nY, nX, 'CC', ErrStat2, ErrMsg2 ); if(Failed()) return; CC(:,:) = 0.0_ReKi !print*,'Warning: C matrix does not have all outputs, or extra moment, or static solve' - CC(1:nY,1:nCB ) = - p%C1_11 - CC(1:nY,nCB+1:nX) = - p%C1_12 + if (nCB>0) then + CC(1:nY,1:nCB ) = - p%C1_11 + CC(1:nY,nCB+1:nX) = - p%C1_12 + endif endif ! --- D matrix diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 55b6e5c95..8826fdd0c 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -809,7 +809,8 @@ END SUBROUTINE SDOut_ChkOutLst !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ !> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. !! Do not change the order of this packing without changing subroutine ! -SUBROUTINE SD_Init_Jacobian( p, u, y, m, InitOut, ErrStat, ErrMsg) +SUBROUTINE SD_Init_Jacobian(Init, p, u, y, m, InitOut, ErrStat, ErrMsg) + TYPE(SD_InitType) , INTENT(IN ) :: Init !< Init TYPE(SD_ParameterType) , INTENT(INOUT) :: p !< parameters TYPE(SD_InputType) , INTENT(IN ) :: u !< inputs TYPE(SD_OutputType) , INTENT(IN ) :: y !< outputs @@ -820,10 +821,18 @@ SUBROUTINE SD_Init_Jacobian( p, u, y, m, InitOut, ErrStat, ErrMsg) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_Init_Jacobian' + real(ReKi) :: dx, dy, dz, maxDim ! local variables: ErrStat = ErrID_None ErrMsg = "" + ! --- System dimension + dx = maxval(Init%Nodes(:,2))- minval(Init%Nodes(:,2)) + dy = maxval(Init%Nodes(:,3))- minval(Init%Nodes(:,3)) + dz = maxval(Init%Nodes(:,4))- minval(Init%Nodes(:,4)) + maxDim = max(dx, dy, dz) + print*,'dx,dy,dz', dx, dy, dz, maxDim + ! --- System dimension call Init_Jacobian_y(); if (Failed()) return call Init_Jacobian_x(); if (Failed()) return call Init_Jacobian_u(); if (Failed()) return @@ -940,8 +949,8 @@ SUBROUTINE Init_Jacobian_u() p%du( 4) = perturb ! u%TPMesh%RotationVel = 4; p%du( 5) = perturb ! u%TPMesh%TranslationAcc = 5; p%du( 6) = perturb ! u%TPMesh%RotationAcc = 6; - p%du( 7) = perturb*5000 ! u%LMesh%Force = 7; - p%du( 8) = perturb*50000 ! u%LMesh%Moment = 8; + p%du( 7) = 170*maxDim**2 ! u%LMesh%Force = 7; + p%du( 8) = 14*maxDim**3 ! u%LMesh%Moment = 8; END SUBROUTINE Init_Jacobian_u END SUBROUTINE SD_Init_Jacobian From c6f0c33eac707761926b4b4c1cde9b305f18e8ee Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 20 Jul 2020 14:45:36 -0600 Subject: [PATCH 246/377] FlexSub: fix output bug when nDiv>1 and cable or rigid links --- modules/subdyn/src/SD_FEM.f90 | 50 ++++++++++++++++++++-------- modules/subdyn/src/SubDyn.f90 | 12 ++++--- modules/subdyn/src/SubDyn_Output.f90 | 13 ++++---- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 179dce589..3fca9d628 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -414,6 +414,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 LOGICAL :: found, CreateNewProp + INTEGER(IntKi) :: nMemberCable, nMemberRigid, nMemberBeam !< Number of memebers per type INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -427,22 +428,29 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.'); return ENDIF - ! Total number of element - Init%NElem = p%NMembers*Init%NDiv ! Note: This is a max since cable and rigid cannot be subdivided + ! --- Total number of element + nMemberBeam = count(Init%Members(:,iMType) == idMemberBeam) + nMemberCable = count(Init%Members(:,iMType) == idMemberCable) + nMemberRigid = count(Init%Members(:,iMType) == idMemberRigid) + Init%NElem = nMemberBeam*Init%NDiv + nMemberCable + nMemberRigid ! NOTE: only Beams are divided + IF ( (nMemberBeam+nMemberRigid+nMemberCable) /= size(Init%Members,1)) then + CALL Fatal(' Member list contains an element which is not a beam, a cable or a rigid link'); return + ENDIF + ! Total number of nodes - Depends on division and number of nodes per element - p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! Note: Same as above. Can be improved by counting R&C + p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*nMemberBeam ! check the number of interior modes IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))); return ENDIF + ! TODO replace this with an integer list! CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays ! NOTE: need NNode and NElem - CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return + CALL SD_ReIndex_CreateNodesAndElems(Init, p, ErrStat2, ErrMsg2); if(Failed()) return Init%MemberNodes = 0 @@ -534,7 +542,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! node connect to Node1 knode = knode + 1 Init%MemberNodes(I, 2) = knode - CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) ! Set Init%Nodes(knode,:) + CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init); if (ErrStat>ErrID_None) return; IF ( CreateNewProp ) THEN ! create a new property set @@ -542,11 +550,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) kprop = kprop + 1 CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p); if (ErrStat>ErrID_None) return; nprop = kprop ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p); if (ErrStat>ErrID_None) return; nprop = Prop1 ENDIF @@ -563,22 +571,26 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) kprop = kprop + 1 CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p); if (ErrStat>ErrID_None) return; nprop = kprop ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p); if (ErrStat>ErrID_None) return; ENDIF ENDDO ! the element connect to Node2 kelem = kelem + 1 - CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) + CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p); if (ErrStat>ErrID_None) return; ENDDO ! loop over all members ! Init%NPropB = kprop - Init%NElem = kelem ! TODO since not all members might have been divided - p%nNodes = knode ! TODO since not all members might have been divided + if(knode/=size(Init%Nodes,1)) then + call Fatal('Implementation error. Number of nodes wrongly estimated.');return + endif + if(kelem/=size(p%Elems,1)) then + call Fatal('Implementation error. Number of elements wrongly estimated.');return + endif ENDIF ! if NDiv is greater than 1 @@ -625,6 +637,10 @@ SUBROUTINE SetNewNode(k, x, y, z, Init) TYPE(SD_InitType), INTENT(INOUT) :: Init INTEGER, INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: x, y, z + if (k>size(Init%Nodes,1)) then + call Fatal('Implementation Error. Attempt to add more node than space allocated.'); + return + endif Init%Nodes(k, 1) = k Init%Nodes(k, 2) = x Init%Nodes(k, 3) = y @@ -644,6 +660,10 @@ SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) INTEGER, INTENT(IN ) :: p1 INTEGER, INTENT(IN ) :: p2 TYPE(SD_ParameterType), INTENT(INOUT) :: p + if (k>size(p%Elems,1)) then + call Fatal('Implementation Error. Attempt to add more element than space allocated.'); + return + endif p%Elems(k, 1) = k p%Elems(k, 2) = n1 p%Elems(k, 3) = n2 @@ -657,6 +677,10 @@ SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) INTEGER , INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: E, G, rho, d, t REAL(ReKi), INTENT(INOUT):: TempProps(:, :) + if (k>size(TempProps,1)) then + call Fatal('Implementation Error. Attempt to add more properties than space allocated.'); + return + endif TempProps(k, 1) = k TempProps(k, 2) = E TempProps(k, 3) = G diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 087415d5d..22ec4bbfa 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -3003,7 +3003,9 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of concentrated masses (NCMass):',Init%NCMass WRITE(UnSum, '(A10,10(A15))') '#JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' - WRITE(UnSum, '("#",F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) + do i=1,Init%NCMass + WRITE(UnSum, '("#",F10.0, 10(E15.6))') (Init%Cmass(i, j), j = 1, CMassCol) + enddo WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#Number of members',p%NMembers @@ -3150,10 +3152,10 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! --- Linearization/ state matrices call StateMatrices(p, ErrStat2, ErrMsg2, AA, BB, CC, DD); if(Failed()) return - call yaml_write_array(UnSum, 'AA', AA, 'ES10.3E2', ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'BB', BB, 'ES10.3E2', ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'CC', CC, 'ES10.3E2', ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'DD', DD, 'ES10.3E2', ErrStat2, ErrMsg2) + call yaml_write_array(UnSum, 'AA', AA, 'ES10.3E2', ErrStat2, ErrMsg2, comment='(State matrix dXdx)') + call yaml_write_array(UnSum, 'BB', BB, 'ES10.3E2', ErrStat2, ErrMsg2, comment='(State matrix dXdu)') + call yaml_write_array(UnSum, 'CC', CC, 'ES10.3E2', ErrStat2, ErrMsg2, comment='(State matrix dYdx)') + call yaml_write_array(UnSum, 'DD', DD, 'ES10.3E2', ErrStat2, ErrMsg2, comment='(State matrix dYdu)') if(allocated(AA)) deallocate(AA) if(allocated(BB)) deallocate(BB) if(allocated(CC)) deallocate(CC) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 8826fdd0c..bb915e235 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -68,7 +68,7 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) INTEGER(IntKi) :: iElem ! Index of element in Element List INTEGER(IntKi) :: iNode ! Index of node in Node list INTEGER(IntKi) :: iiElem ! Loop counter on element index - INTEGER(IntKi) :: nElemPerNode ! Number of elements connecting to a node + INTEGER(IntKi) :: nElemPerNode, nNodesPerElem ! Number of elements connecting to a node, Number of nodes per elem type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities real(ReKi), allocatable :: T_TIreact(:,:) ! Transpose of TIreact, temporary ErrStat = 0 @@ -137,20 +137,21 @@ SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) DO iMember=1,p%NMembers pLst => p%MOutLst2(iMember) ! Alias - CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return + pLst%MemberID = Init%Members(iMember,1) + nNodesPerElem = count(Init%MemberNodes(iMember,:) >0 ) + CALL AllocAry(pLst%NodeIDs, nNodesPerElem, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - pLst%MemberID = Init%Members(iMember,1) - pLst%NodeIDs = Init%MemberNodes(iMember,1:Init%Ndiv+1) ! We are storing the actual node numbers in the member + pLst%NodeIDs(1:nNodesPerElem) = Init%MemberNodes(iMember,1:nNodesPerElem) ! We are storing the actual node numbers in the member !ElmIDs could contain the same element twice if Ndiv=1 pLst%ElmIDs=0 !Initialize to 0 - DO J=1,Init%Ndiv+1,Init%Ndiv ! loop on first and last node of member + DO J=1,nNodesPerElem,nNodesPerElem-1 ! loop on first and last node of member iNode = pLst%NodeIDs(J) ! Index of requested node in node list nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the 1st or last node of the member - K2= J/(Init%Ndiv+1)+1 ! 1 (first node) or 2 (last node) depending on J + K2= J/(nNodesPerElem)+1 ! 1 (first node) or 2 (last node) depending on J DO iiElem=1, nElemPerNode iElem = Init%NodesConnE(iNode,iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN From 6242fa5caf2a513d459df394d6135f919c17d11b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 20 Jul 2020 16:04:40 -0600 Subject: [PATCH 247/377] FlexSub: fix of summary file --- modules/subdyn/src/SubDyn.f90 | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 22ec4bbfa..ea5aaba8c 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2952,8 +2952,8 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFred2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) ! Nodes properties - write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' - call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),(F15.0,","),5(E15.6,",")') !, comment='',label=.true.) + write(UnSum, '("#",4x,1(A9),8('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]' + call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),(F15.0,","),4(E15.6,",")') !, comment='',label=.true.) ! Element properties CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -3024,10 +3024,20 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, .TRUE.) - WRITE(UnSum, '("#",I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propIDs(1),propIDs(2),& mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) - else - WRITE(UnSum, '(A)') '#TODO, member mass for non-beam elements' + else if (mType==idMemberCable) then + iProp(1) = FINDLOCI(Init%PropSetsC(:,1), propIDs(1)) + mMass= Init%PropSetsC(iProp(1),3) * mLength ! rho [kg/m] * L + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,2(I6),A)') Init%Members(i,1:3),propIDs(1),propIDs(2),& + mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, 2), ' # Cable' + else if (mType==idMemberRigid) then + iProp(1) = FINDLOCI(Init%PropSetsR(:,1), propIDs(1)) + mMass= Init%PropSetsR(iProp(1),2) * mLength ! rho [kg/m] * L + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,2(I6),A)') Init%Members(i,1:3),propIDs(1),propIDs(2),& + mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, 2), ' # Rigid link' + else + WRITE(UnSum, '(A)') '#TODO, member unknown' endif ELSE RETURN From 880550c692849c9476426154434023ae745bbbac Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 21 Jul 2020 20:52:20 -0600 Subject: [PATCH 248/377] FlexSub: explicit float types for Ke and Me --- modules/subdyn/src/FEM.f90 | 95 +++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index e0d325b24..92e2ba0b6 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -953,26 +953,26 @@ SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) Ax = kappa*A Ay = kappa*A - K(1:12,1:12) = 0 + K(1:12,1:12) = 0.0_ReKi IF (Shear) THEN - Kx = 12.0*E*Iyy / (G*Ax*L*L) - Ky = 12.0*E*Ixx / (G*Ay*L*L) + Kx = 12.0_ReKi*E*Iyy / (G*Ax*L*L) + Ky = 12.0_ReKi*E*Ixx / (G*Ay*L*L) ELSE - Kx = 0.0 - Ky = 0.0 + Kx = 0.0_ReKi + Ky = 0.0_ReKi ENDIF K( 9, 9) = E*A/L - K( 7, 7) = 12.0*E*Iyy/( L*L*L*(1.0 + Kx) ) - K( 8, 8) = 12.0*E*Ixx/( L*L*L*(1.0 + Ky) ) + K( 7, 7) = 12.0_ReKi*E*Iyy/( L*L*L*(1.0_ReKi + Kx) ) + K( 8, 8) = 12.0_ReKi*E*Ixx/( L*L*L*(1.0_ReKi + Ky) ) K(12, 12) = G*Jzz/L - K(10, 10) = (4.0 + Ky)*E*Ixx / ( L*(1.0+Ky) ) - K(11, 11) = (4.0 + Kx)*E*Iyy / ( L*(1.0+Kx) ) - K( 2, 4) = -6.*E*Ixx / ( L*L*(1.0+Ky) ) - K( 1, 5) = 6.*E*Iyy / ( L*L*(1.0+Kx) ) - K( 4, 10) = (2.0-Ky)*E*Ixx / ( L*(1.0+Ky) ) - K( 5, 11) = (2.0-Kx)*E*Iyy / ( L*(1.0+Kx) ) + K(10, 10) = (4.0_ReKi + Ky)*E*Ixx / ( L*(1.0_ReKi+Ky) ) + K(11, 11) = (4.0_ReKi + Kx)*E*Iyy / ( L*(1.0_ReKi+Kx) ) + K( 2, 4) = -6._ReKi*E*Ixx / ( L*L*(1.0_ReKi+Ky) ) + K( 1, 5) = 6._ReKi*E*Iyy / ( L*L*(1.0_ReKi+Kx) ) + K( 4, 10) = (2.0_ReKi-Ky)*E*Ixx / ( L*(1.0_ReKi+Ky) ) + K( 5, 11) = (2.0_ReKi-Kx)*E*Iyy / ( L*(1.0_ReKi+Kx) ) K( 3, 3) = K(9,9) K( 1, 1) = K(7,7) @@ -1005,7 +1005,7 @@ SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) K(8,4) = -K(4,2) K(4,8) = -K(4,2) - DC = 0 + DC = 0.0_ReKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1031,9 +1031,9 @@ SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) EAL0 = E*A/L0 EE = EAL0* Eps0/(1+Eps0) - K(1:12,1:12)=0 + K(1:12,1:12)=0.0_ReKi - ! Note: only translatoinal DOF involved (1-3, 7-9) + ! Note: only translational DOF involved (1-3, 7-9) K(1,1)= EE K(2,2)= EE K(3,3)= EAL0 @@ -1050,7 +1050,8 @@ SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) K(8,8)= EE K(9,9)= EAL0 - DC = 0 + + DC = 0.0_ReKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1073,28 +1074,28 @@ SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) ry = rho*Iyy; po = rho*Jzz*L; - M(1:12,1:12) = 0 + M(1:12,1:12) = 0.0_ReKi - M( 9, 9) = t/3.0 - M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) - M( 8, 8) = 13.0*t/35.0 + 6.0*rx/(5.0*L) - M(12, 12) = po/3.0 - M(10, 10) = t*L*L/105.0 + 2.0*L*rx/15.0 - M(11, 11) = t*L*L/105.0 + 2.0*L*ry/15.0 - M( 2, 4) = -11.0*t*L/210.0 - rx/10.0 - M( 1, 5) = 11.0*t*L/210.0 + ry/10.0 - M( 3, 9) = t/6.0 - M( 5, 7) = 13.*t*L/420. - ry/10. - M( 4, 8) = -13.*t*L/420. + rx/10. - M( 6, 12) = po/6. - M( 2, 10) = 13.*t*L/420. - rx/10. - M( 1, 11) = -13.*t*L/420. + ry/10. - M( 8, 10) = 11.*t*L/210. + rx/10. - M( 7, 11) = -11.*t*L/210. - ry/10. - M( 1, 7) = 9.*t/70. - 6.*ry/(5.*L) - M( 2, 8) = 9.*t/70. - 6.*rx/(5.*L) - M( 4, 10) = -L*L*t/140. - rx*L/30. - M( 5, 11) = -L*L*t/140. - ry*L/30. + M( 9, 9) = t/3.0_ReKi + M( 7, 7) = 13.0_ReKi*t/35.0_ReKi + 6.0_ReKi*ry/(5.0_ReKi*L) + M( 8, 8) = 13.0_ReKi*t/35.0_ReKi + 6.0_ReKi*rx/(5.0_ReKi*L) + M(12, 12) = po/3.0_ReKi + M(10, 10) = t*L*L/105.0_ReKi + 2.0_ReKi*L*rx/15.0_ReKi + M(11, 11) = t*L*L/105.0_ReKi + 2.0_ReKi*L*ry/15.0_ReKi + M( 2, 4) = -11.0_ReKi*t*L/210.0_ReKi - rx/10.0_ReKi + M( 1, 5) = 11.0_ReKi*t*L/210.0_ReKi + ry/10.0_ReKi + M( 3, 9) = t/6.0_ReKi + M( 5, 7) = 13._ReKi*t*L/420._ReKi - ry/10._ReKi + M( 4, 8) = -13._ReKi*t*L/420._ReKi + rx/10._ReKi + M( 6, 12) = po/6._ReKi + M( 2, 10) = 13._ReKi*t*L/420._ReKi - rx/10._ReKi + M( 1, 11) = -13._ReKi*t*L/420._ReKi + ry/10._ReKi + M( 8, 10) = 11._ReKi*t*L/210._ReKi + rx/10._ReKi + M( 7, 11) = -11._ReKi*t*L/210._ReKi - ry/10._ReKi + M( 1, 7) = 9._ReKi*t/70._ReKi - 6._ReKi*ry/(5._ReKi*L) + M( 2, 8) = 9._ReKi*t/70._ReKi - 6._ReKi*rx/(5._ReKi*L) + M( 4, 10) = -L*L*t/140._ReKi - rx*L/30._ReKi + M( 5, 11) = -L*L*t/140._ReKi - ry*L/30._ReKi M( 3, 3) = M( 9, 9) M( 1, 1) = M( 7, 7) @@ -1117,7 +1118,7 @@ SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) M(10, 4) = M( 4, 10) M(11, 5) = M( 5, 11) - DC = 0 + DC = 0.0_ReKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1138,7 +1139,7 @@ SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) t = rho*A*L; - M(1:12,1:12) = 0 + M(1:12,1:12) = 0.0_ReKi M( 1, 1) = 13._ReKi/35._ReKi * t M( 2, 2) = 13._ReKi/35._ReKi * t @@ -1156,7 +1157,7 @@ SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) M( 8, 2) = 9._ReKi/70._ReKi * t M( 9, 3) = t/6.0_ReKi - DC = 0 + DC = 0.0_ReKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1179,19 +1180,19 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) REAL(ReKi) :: TempCoeff REAL(ReKi) :: w ! weight per unit length - F = 0 ! initialize whole array to zero, then set the non-zero portions + F = 0.0_ReKi ! initialize whole array to zero, then set the non-zero portions w = rho*A*g ! weight per unit length ! lumped forces on both nodes (z component only): - F(3) = -0.5*L*w + F(3) = -0.5_ReKi*L*w F(9) = F(3) ! lumped moments on node 1 (x and y components only): ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice - F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12. !bjj: DirCos(2,3) = Dy/L - F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12. !bjj: DirCos(1,3) = Dx/L + F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12._ReKi !bjj: DirCos(2,3) = Dy/L + F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12._ReKi !bjj: DirCos(1,3) = Dx/L ! lumped moments on node 2: (note the opposite sign of node 1 moment) F(10) = -F(4) @@ -1208,11 +1209,11 @@ SUBROUTINE ElemF_Cable(T0, DirCos, F) ! Local variables REAL(ReKi) :: DC(12, 12) - F(1:12) = 0 ! init + F(1:12) = 0.0_ReKi ! init F(3) = +T0 F(9) = -T0 - DC = 0 + DC = 0.0_ReKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos From 3ca97417208684693947b2a80ecd06376853c565 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 23 Jul 2020 11:07:21 -0600 Subject: [PATCH 249/377] Add linearization related code for NBodyMod --- modules/hydrodyn/src/HydroDyn.f90 | 652 ++++--- modules/hydrodyn/src/HydroDyn.txt | 3 + modules/hydrodyn/src/HydroDyn_Types.f90 | 21 + modules/hydrodyn/src/Morison_Types.f90 | 2247 ++++++++++++++--------- 4 files changed, 1844 insertions(+), 1079 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index a42bd69c0..02a3d78d6 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1429,19 +1429,31 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I IF ( InitLocal%PotMod == 1 .AND. InitLocal%WAMIT%RdtnMod == 1) THEN - ! Write the header for this section - WRITE( InitLocal%UnSum, '(//)' ) - WRITE( InitLocal%UnSum, '(A)' ) 'Radiation memory effect kernel' - WRITE( InitLocal%UnSum, '(//)' ) - WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' n ' , ' t ', ' K11 ', ' K12 ', ' K13 ', ' K14 ', ' K15 ', ' K16 ', ' K22 ', ' K23 ', ' K24 ', ' K25 ', ' K26 ', ' K33 ', ' K34 ', ' K35 ', 'K36 ', ' K44 ', ' K45 ', ' K46 ', ' K55 ', ' K56 ', ' K66 ' - WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' (-) ' , ' (s) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)' + ! Write the header for this section: Note: When NBodyMod = 1 the kernel is now 6*NBody by 6*Nbody in size, + ! and we have NBody 6 by 6 kernels for NBodyMod=2 or 3 + if (p%NBodyMod == 1) then + !TODO: Implement NBodyMod=1 kernel printout + else + do j = 1,p%nWAMITObj + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(A)' ) 'Radiation memory effect kernel' + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' n ' , ' t ', ' K11 ', ' K12 ', ' K13 ', ' K14 ', ' K15 ', ' K16 ', ' K22 ', ' K23 ', ' K24 ', ' K25 ', ' K26 ', ' K33 ', ' K34 ', ' K35 ', 'K36 ', ' K44 ', ' K45 ', ' K46 ', ' K55 ', ' K56 ', ' K66 ' + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10,21(2X,A16))' ) ' (-) ' , ' (s) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kg/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', ' (kgm/s^2) ', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)', '(kgm^2/s^2)' ! Write the data - DO I = 0,p%WAMIT(1)%Conv_Rdtn%NStepRdtn-1 - - WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%WAMIT(1)%Conv_Rdtn%RdtnDT, p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,1), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,2), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,1,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,2), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,2,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,3), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,3,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,4), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,4,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,5,5), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,5,6), p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(I,6,6) - - END DO + DO I = 0,p%WAMIT(j)%Conv_Rdtn%NStepRdtn-1 + WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5,21(2X,ES16.5))' ) I, I*p%WAMIT(j)%Conv_Rdtn%RdtnDT, & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,1), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,2), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,3), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,4), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,5), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,1,6), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,2,2), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,2,3), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,2,4), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,2,5), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,2,6), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,3,3), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,3,4), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,3,5), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,3,6), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,4,4), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,4,5), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,4,6), & + p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,5,5), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,5,6), p%WAMIT(j)%Conv_Rdtn%RdtnKrnl(I,6,6) + END DO + end do + end if END IF END IF @@ -2409,7 +2421,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM TYPE(HydroDyn_ContinuousStateType) :: x_m TYPE(HydroDyn_InputType) :: u_perturb REAL(R8Ki) :: delta ! delta change in input or state - INTEGER(IntKi) :: i, j, NN, offsetI, offsetJ + INTEGER(IntKi) :: i, j, k, startingI, startingJ, bOffset, offsetI, offsetJ, n_du_plus1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -2421,8 +2433,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM ErrStat = ErrID_None ErrMsg = '' - ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid - NN = p%WAMIT(1)%SS_Rdtn%numStates + p%WAMIT(1)%SS_Exctn%numStates + n_du_plus1 = size(p%Jac_u_indx,1)+1 ! make a copy of the inputs to perturb call HydroDyn_CopyInput( u, u_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2440,7 +2451,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM ! allocate dYdu if necessary if (.not. allocated(dYdu)) then - call AllocAry(dYdu, p%Jac_ny, size(p%Jac_u_indx,1)+1, 'dYdu', ErrStat2, ErrMsg2) + call AllocAry(dYdu, p%Jac_ny, n_du_plus1, 'dYdu', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) then call cleanup() @@ -2486,7 +2497,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM end do ! p%WaveElev0 column - dYdu(:,size(p%Jac_u_indx,1)+1) = 0 + dYdu(:,n_du_plus1) = 0 if (ErrStat>=AbortErrLev) then @@ -2502,11 +2513,14 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM IF ( PRESENT( dXdu ) ) THEN + ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: ! allocate dXdu if necessary if (.not. allocated(dXdu)) then - call AllocAry(dXdu, NN, size(p%Jac_u_indx,1)+1, 'dXdu', ErrStat2, ErrMsg2) + call AllocAry(dXdu, p%totalStates, n_du_plus1, 'dXdu', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) then call cleanup() @@ -2517,21 +2531,103 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM offsetI = 0 dXdu = 0.0_R8Ki - - do i = 1,p%WAMIT(1)%SS_Exctn%numStates - dXdu(offsetI+i,size(p%Jac_u_indx,1)+1) = p%WAMIT(1)%SS_Exctn%B(i) + do j = 1,p%nWAMITObj + do i = 1,p%WAMIT(j)%SS_Exctn%numStates + dXdu(offsetI+i,n_du_plus1) = p%WAMIT(j)%SS_Exctn%B(i) ! B is numStates by 1 + end do + offsetI = offsetI + p%WAMIT(j)%SS_Exctn%numStates end do + startingI = p%totalStates - p%totalRdtnStates + startingJ = n_du_plus1 - 1 - 18 - 4*3*p%NBody ! subtract 1 for WaveElev0, then 6*3 for PRPMesh and then 4*3*NBody to place us at the beginning of the velocity inputs + ! B is numStates by 6*NBody where NBody =1 if NBodyMod=2 or 3, but could be >1 for NBodyMod=1 + if ( p%NBodyMod == 1 ) then + ! Example for NBodyMod=1 and NBody = 2, + ! dXdu(:,startingIndx + 1) = p%WAMIT(1)%SS_Rdtn%B(:,1) + ! dXdu(:,startingIndx + 2) = p%WAMIT(1)%SS_Rdtn%B(:,2) + ! dXdu(:,startingIndx + 3) = p%WAMIT(1)%SS_Rdtn%B(:,3) + ! dXdu(:,startingIndx + 4) = p%WAMIT(1)%SS_Rdtn%B(:,7) + ! dXdu(:,startingIndx + 5) = p%WAMIT(1)%SS_Rdtn%B(:,8) + ! dXdu(:,startingIndx + 6) = p%WAMIT(1)%SS_Rdtn%B(:,9) + ! dXdu(:,startingIndx + 7) = p%WAMIT(1)%SS_Rdtn%B(:,4) ! start of rotationalVel + ! dXdu(:,startingIndx + 8) = p%WAMIT(1)%SS_Rdtn%B(:,5) + ! dXdu(:,startingIndx + 9) = p%WAMIT(1)%SS_Rdtn%B(:,6) + ! dXdu(:,startingIndx +10) = p%WAMIT(1)%SS_Rdtn%B(:,10) + ! dXdu(:,startingIndx +11) = p%WAMIT(1)%SS_Rdtn%B(:,11) + ! dXdu(:,startingIndx +12) = p%WAMIT(1)%SS_Rdtn%B(:,12) - offsetI = NN - p%WAMIT(1)%SS_Rdtn%numStates - offsetJ = size(p%Jac_u_indx,1)+1 - 13 - do j = 1, 6 do i = 1,p%WAMIT(1)%SS_Rdtn%numStates - dXdu(offsetI+i,offsetJ+j) = p%WAMIT(1)%SS_Rdtn%B(i,j) + k=0 + ! First set all translationalVel components + do j = 1, p%WAMIT(1)%NBody + bOffset = (j-1)*6 + dXdu(startingI+i,startingJ+k+1) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+1) + dXdu(startingI+i,startingJ+k+2) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+2) + dXdu(startingI+i,startingJ+k+3) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+3) + k = k + 3 + end do + ! Now set all rotationalVel components + do j = 1, p%WAMIT(1)%NBody + bOffset = (j-1)*6 + dXdu(startingI+i,startingJ+k+1) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+4) + dXdu(startingI+i,startingJ+k+2) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+5) + dXdu(startingI+i,startingJ+k+3) = p%WAMIT(1)%SS_Rdtn%B(i,bOffset+6) + k = k + 3 + end do + end do + else + ! Example NBodyMod=2or3 and NBody = 2, + ! dXdu(:,startingIndx + 1) = p%WAMIT(1)%SS_Rdtn%B(:,1) + ! dXdu(:,startingIndx + 2) = p%WAMIT(1)%SS_Rdtn%B(:,2) + ! dXdu(:,startingIndx + 3) = p%WAMIT(1)%SS_Rdtn%B(:,3) + ! dXdu(:,startingIndx + 4) = p%WAMIT(2)%SS_Rdtn%B(:,1) + ! dXdu(:,startingIndx + 5) = p%WAMIT(2)%SS_Rdtn%B(:,2) + ! dXdu(:,startingIndx + 6) = p%WAMIT(2)%SS_Rdtn%B(:,3) + ! dXdu(:,startingIndx + 7) = p%WAMIT(1)%SS_Rdtn%B(:,4) ! start of rotationalVel + ! dXdu(:,startingIndx + 8) = p%WAMIT(1)%SS_Rdtn%B(:,5) + ! dXdu(:,startingIndx + 9) = p%WAMIT(1)%SS_Rdtn%B(:,6) + ! dXdu(:,startingIndx +10) = p%WAMIT(2)%SS_Rdtn%B(:,4) + ! dXdu(:,startingIndx +11) = p%WAMIT(2)%SS_Rdtn%B(:,5) + ! dXdu(:,startingIndx +12) = p%WAMIT(2)%SS_Rdtn%B(:,6) + + + k=0 + offsetI=0 + ! First set all translationalVel components + do j = 1, p%nWAMITObj + do i = 1,p%WAMIT(j)%SS_Rdtn%numStates + dXdu(startingI+offsetI+i,startingJ+k+1) = p%WAMIT(j)%SS_Rdtn%B(i,1) + dXdu(startingI+offsetI+i,startingJ+k+2) = p%WAMIT(j)%SS_Rdtn%B(i,2) + dXdu(startingI+offsetI+i,startingJ+k+3) = p%WAMIT(j)%SS_Rdtn%B(i,3) + end do + k = k + 3 + offsetI = offsetI + p%WAMIT(j)%SS_Rdtn%numStates + end do + ! Now set all rotationalVel components + offsetI=0 + do j = 1, p%nWAMITObj + do i = 1,p%WAMIT(j)%SS_Rdtn%numStates + dXdu(startingI+offsetI+i,startingJ+k+1) = p%WAMIT(1)%SS_Rdtn%B(i,4) + dXdu(startingI+offsetI+i,startingJ+k+2) = p%WAMIT(1)%SS_Rdtn%B(i,5) + dXdu(startingI+offsetI+i,startingJ+k+3) = p%WAMIT(1)%SS_Rdtn%B(i,6) + end do + k = k + 3 + offsetI = offsetI + p%WAMIT(j)%SS_Rdtn%numStates end do + end if + + do k = 1,p%nWAMITObj + ! TODO + + do j = 1, 6*p%WAMIT(k)%NBody + do i = 1,p%WAMIT(k)%SS_Rdtn%numStates + dXdu(offsetI+i,offsetJ+j) = p%WAMIT(k)%SS_Rdtn%B(i,j) ! B is numStates by 6*NBody where NBody =1 if NBodyMod=2 or 3, but could be >1 for NBodyMod=1 + end do + end do + offsetI = offsetI + p%WAMIT(k)%SS_Rdtn%numStates + offsetJ = offsetJ + p%WAMIT(k)%SS_Rdtn%numStates end do - END IF @@ -2594,7 +2690,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, TYPE(HydroDyn_ContinuousStateType) :: x_m TYPE(HydroDyn_ContinuousStateType) :: x_perturb REAL(R8Ki) :: delta ! delta change in input or state - INTEGER(IntKi) :: i, j, NN + INTEGER(IntKi) :: i, j, k, sOffset INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -2608,7 +2704,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: - NN = p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates + ! make a copy of the continuous states to perturb call HydroDyn_CopyContState( x, x_perturb, MESH_NEWCOPY, ErrStat2, ErrMsg2) @@ -2623,7 +2719,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ! allocate dYdx if necessary if (.not. allocated(dYdx)) then - call AllocAry(dYdx, p%Jac_ny, NN, 'dYdx', ErrStat2, ErrMsg2) + call AllocAry(dYdx, p%Jac_ny, p%totalStates, 'dYdx', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) then call cleanup() @@ -2642,7 +2738,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, end if - do i=1,NN + do i=1,p%totalStates ! get x_op + delta x call HydroDyn_CopyContState( x, x_perturb, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) @@ -2684,7 +2780,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ! allocate dXdu if necessary if (.not. allocated(dXdx)) then - call AllocAry(dXdx, NN, NN, 'dXdx', ErrStat2, ErrMsg2) + call AllocAry(dXdx, p%totalStates, p%totalStates, 'dXdx', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat>=AbortErrLev) then call cleanup() @@ -2694,18 +2790,26 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, dXdx = 0.0_R8Ki ! Analytical Jacobians from State-space models - if ( p%WAMIT(1)%SS_Exctn%numStates > 0 ) then - do j=1,p%WAMIT(1)%SS_Exctn%numStates - do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all active (enabled) DOFs - dXdx(i, j) = p%WAMIT(1)%SS_Exctn%A(i,j) + if ( p%totalExctnStates > 0 ) then + sOffset = 0 + do k=1,p%nWAMITObj + do j=1,p%WAMIT(k)%SS_Exctn%numStates + do i=1,p%WAMIT(k)%SS_Exctn%numStates ! Loop through all active (enabled) DOFs + dXdx(i+sOffset, j+sOffset) = p%WAMIT(k)%SS_Exctn%A(i,j) + end do end do + sOffset = sOffset + p%WAMIT(k)%SS_Exctn%numStates end do end if - if ( p%WAMIT(1)%SS_Rdtn%numStates > 0 ) then - do j=1,p%WAMIT(1)%SS_Rdtn%numStates - do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all active (enabled) DOFs - dXdx(i+p%WAMIT(1)%SS_Exctn%numStates, j+p%WAMIT(1)%SS_Exctn%numStates) = p%WAMIT(1)%SS_Rdtn%A(i,j) + if ( p%totalRdtnStates > 0 ) then + sOffset = 0 + do k=1,p%nWAMITObj + do j=1,p%WAMIT(k)%SS_Rdtn%numStates + do i=1,p%WAMIT(k)%SS_Rdtn%numStates ! Loop through all active (enabled) DOFs + dXdx(i+p%totalExctnStates+sOffset, j+p%totalExctnStates+sOffset) = p%WAMIT(k)%SS_Rdtn%A(i,j) + end do end do + sOffset = sOffset + p%WAMIT(k)%SS_Rdtn%numStates end do end if @@ -2904,12 +3008,12 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) ! determine how many outputs there are in the Jacobians p%Jac_ny = 0 if ( y%Morison%Mesh%Committed ) then - p%Jac_ny = p%Jac_ny + y%Morison%Mesh%NNodes * 6 ! 3 Force, Moment, at each node on the distributed loads mesh + p%Jac_ny = p%Jac_ny + y%Morison%Mesh%NNodes * 6 ! 3 Force, Moment, at each node on the morison mesh end if - - p%Jac_ny = p%Jac_ny + y%WAMITMesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point -!TODO: With NBody WAMIT rework need to see if removing this causes issues - ! p%Jac_ny = p%Jac_ny + y%AllHdroOrigin%NNodes * 6 ! 3 Force, Moment, of all HD loads integrated to the origin (0,0,0) + if ( y%WAMITMesh%Committed ) then + p%Jac_ny = p%Jac_ny + y%WAMITMesh%NNodes * 6 ! 3 Force, Moment, at the WAMIT reference Point(s) + end if + p%Jac_ny = p%Jac_ny + p%NumTotalOuts ! WriteOutput values @@ -2930,13 +3034,10 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) call PackLoadMesh_Names(y%Morison%Mesh, 'MorisonLoads', InitOut%LinNames_y, index_next) end if - - index_last = index_next - call PackLoadMesh_Names(y%WAMITMesh, 'PlatformRefPtLoads', InitOut%LinNames_y, index_next) - -!TODO: With NBody WAMIT rework need to see if removing this causes issues - ! index_last = index_next - ! call PackLoadMesh_Names(y%AllHdroOrigin, 'AllHdroOrigin', InitOut%LinNames_y, index_next) + if ( y%WAMITMesh%Committed ) then + index_last = index_next + call PackLoadMesh_Names(y%WAMITMesh, 'WAMITLoads', InitOut%LinNames_y, index_next) + end if index_last = index_next @@ -2963,54 +3064,67 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) CHARACTER(*), PARAMETER :: RoutineName = 'HD_Init_Jacobian_x' ! local variables: - INTEGER(IntKi) :: i, j, k, NN, spdof, indx + INTEGER(IntKi) :: i, j, k, l, spdof, indx CHARACTER(10) :: modLabels(2), dofLabels(6) ErrStat = ErrID_None ErrMsg = "" indx = 1 - NN = p%WAMIT(1)%SS_Rdtn%numStates + p%WAMIT(1)%SS_Exctn%numStates - if ( NN == 0 ) return + + ! Need to determine how many wamit body objects there are + p%totalExctnStates = 0 + p%totalRdtnStates = 0 + do j = 1, p%nWAMITObj + p%totalExctnStates = p%totalExctnStates + p%WAMIT(j)%SS_Exctn%numStates + p%totalRdtnStates = p%totalRdtnStates + p%WAMIT(j)%SS_Rdtn%numStates + end do + p%totalStates = p%totalExctnStates + p%totalRdtnStates + if ( p%totalStates == 0 ) return ! allocate space for the row/column names and for perturbation sizes - call allocAry(p%dx, NN, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - call AllocAry(InitOut%LinNames_x, NN, 'LinNames_x', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(InitOut%DerivOrder_x, NN, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call allocAry(p%dx, p%totalStates, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(InitOut%LinNames_x, p%totalStates, 'LinNames_x' , ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry(InitOut%DerivOrder_x, p%totalStates, 'DerivOrder_x', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! All Hydrodyn continuous states are max order = 1 if ( allocated(InitOut%DerivOrder_x) ) InitOut%DerivOrder_x = 1 ! set perturbation sizes: p%dx - - do i = 1, p%WAMIT(1)%SS_Exctn%numStates - p%dx(i) = 20000.0_R8Ki * D2R_D + k = 1 + do j = 1, p%nWAMITObj + do i = 1, p%WAMIT(j)%SS_Exctn%numStates + p%dx(k) = 20000.0_R8Ki * D2R_D + k=k+1 + end do end do - - do i = 1, p%WAMIT(1)%SS_Rdtn%numStates - p%dx(i+p%WAMIT(1)%SS_Exctn%numStates) = 2.0_R8Ki * D2R_D + do j = 1, p%nWAMITObj + do i = 1, p%WAMIT(j)%SS_Rdtn%numStates + p%dx(k) = 2.0_R8Ki * D2R_D + k=k+1 + end do end do modLabels = (/'Exctn ','Rdtn '/) dofLabels = (/'PtfmSg ','PtfmSw ','PtfmHv ','PtfmR ','PtfmP ','PtfmY '/) - - ! set linearization state names: + !TODO: If NBodyMod=1, do not use the 'B' + number prefix do k = 1, 2 ! 1 = Excitation, 2 = Radiation - - - do j = 1, 6 + do l=1,p%nWAMITObj - if (k == 1) then - spdof = p%WAMIT(1)%SS_Exctn%spdof(j) - else - spdof = p%WAMIT(1)%SS_Rdtn%spdof(j) - end if + ! set linearization state names: + do j = 1, 6 + + if (k == 1) then + spdof = p%WAMIT(l)%SS_Exctn%spdof(j) + else + spdof = p%WAMIT(l)%SS_Rdtn%spdof(j) + end if - do i = 1,spdof - InitOut%LinNames_x(indx) = trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) - indx = indx + 1 + do i = 1,spdof + InitOut%LinNames_x(indx) = 'B'//trim(num2lstr(l))//trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) + indx = indx + 1 + end do end do end do end do - END SUBROUTINE HD_Init_Jacobian_x !---------------------------------------------------------------------------------------------------------------------------------- !> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. @@ -3051,10 +3165,13 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) ! determine how many inputs there are in the Jacobians nu = 0; if ( u%Morison%Mesh%Committed ) then - nu = nu + u%Morison%Mesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + nu = u%Morison%Mesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + end if + if ( u%WAMITMesh%Committed ) then + nu = nu + u%WAMITMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node end if - nu = nu + u%WAMITMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node + nu = nu + u%PRPMesh%NNodes * 18 ! 3 TranslationDisp, Orientation, TranslationVel, RotationVel, TranslationAcc, and RotationAcc at each node ! DO NOT Add the extended input WaveElev0 when computing the size of p%Jac_u_indx @@ -3078,6 +3195,7 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) index = 1 meshFieldCount = 0 + if ( u%Morison%Mesh%Committed ) then !Module/Mesh/Field: u%Morison%Mesh%TranslationDisp = 1; !Module/Mesh/Field: u%Morison%Mesh%Orientation = 2; @@ -3086,34 +3204,28 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) !Module/Mesh/Field: u%Morison%Mesh%TranslationAcc = 5; !Module/Mesh/Field: u%Morison%Mesh%RotationAcc = 6; - do i_meshField = 1,6 - do i=1,u%Morison%Mesh%NNodes - do j=1,3 - p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%Morison%Mesh%{TranslationDisp/Orientation/TranslationVel/RotationVel/TranslationAcc/RotationAcc} = m - p%Jac_u_indx(index,2) = j !index: j - p%Jac_u_indx(index,3) = i !Node: i - index = index + 1 - end do !j - end do !i + do i_meshField = 1,6 + do i=1,u%Morison%Mesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = i_meshField !Module/Mesh/Field: u%Morison%Mesh%{TranslationDisp/Orientation/TranslationVel/RotationVel/TranslationAcc/RotationAcc} = m + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i - end do !i_meshField - meshFieldCount = 6 - !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationDisp = 7; - !Module/Mesh/Field: u%Morison%LumpedMesh%Orientation = 8; - !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationVel = 9; - !Module/Mesh/Field: u%Morison%LumpedMesh%RotationVel = 10; - !Module/Mesh/Field: u%Morison%LumpedMesh%TranslationAcc = 11; - !Module/Mesh/Field: u%Morison%LumpedMesh%RotationAcc = 12; + end do !i_meshField + meshFieldCount = 6 end if - !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 or 1; - !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 or 2; - !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 or 3; - !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 or 4; - !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 or 5; - !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 or 6; - + if ( u%WAMITMesh%Committed ) then + !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 7 or 1; + !Module/Mesh/Field: u%WAMITMesh%Orientation = 8 or 2; + !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 9 or 3; + !Module/Mesh/Field: u%WAMITMesh%RotationVel = 10 or 4; + !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 11 or 5; + !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 12 or 6; do i_meshField = 1,6 do i=1,u%WAMITMesh%NNodes do j=1,3 @@ -3123,22 +3235,36 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) index = index + 1 end do !j end do !i - end do !i_meshField - + end do !i_meshField + meshFieldCount = meshFieldCount + 6 + end if + + !Module/Mesh/Field: u%PRPMesh%TranslationDisp = 13 or 7 or 1; + !Module/Mesh/Field: u%PRPMesh%Orientation = 14 or 8 or 2; + !Module/Mesh/Field: u%PRPMesh%TranslationVel = 15 or 9 or 3; + !Module/Mesh/Field: u%PRPMesh%RotationVel = 16 or 10 or 4; + !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 17 or 11 or 5; + !Module/Mesh/Field: u%PRPMesh%RotationAcc = 18 or 12 or 6; + do i_meshField = 1,6 + do i=1,u%PRPMesh%NNodes + do j=1,3 + p%Jac_u_indx(index,1) = meshFieldCount + i_meshField + p%Jac_u_indx(index,2) = j !index: j + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !j + end do !i + end do !i_meshField + meshFieldCount = meshFieldCount + 6 !................ ! input perturbations, du: !................ - if ( u%Morison%Mesh%Committed ) then - call AllocAry(p%du, 12, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - else - call AllocAry(p%du, 6, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - - end if + + call AllocAry(p%du, meshFieldCount, 'p%du', ErrStat2, ErrMsg2) ! number of unique values in p%Jac_u_indx(:,1) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + perturb_t = 0.02_ReKi*D2R * max(p%WtrDpth,1.0_ReKi) ! translation input scaling ! LIN-TODO What about MSL offset? perturb = 2*D2R ! rotational input scaling @@ -3154,16 +3280,22 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) index = 6 end if - - p%du(index + 1) = perturb_t ! u%WAMITMesh%TranslationDisp - p%du(index + 2) = perturb ! u%WAMITMesh%Orientation - p%du(index + 3) = perturb_t ! u%WAMITMesh%TranslationVel - p%du(index + 4) = perturb ! u%WAMITMesh%RotationVel - p%du(index + 5) = perturb_t ! u%WAMITMesh%TranslationAcc - p%du(index + 6) = perturb ! u%WAMITMesh%RotationAcc - index = index + 6 - + if ( u%WAMITMesh%Committed ) then + p%du(index + 1) = perturb_t ! u%WAMITMesh%TranslationDisp + p%du(index + 2) = perturb ! u%WAMITMesh%Orientation + p%du(index + 3) = perturb_t ! u%WAMITMesh%TranslationVel + p%du(index + 4) = perturb ! u%WAMITMesh%RotationVel + p%du(index + 5) = perturb_t ! u%WAMITMesh%TranslationAcc + p%du(index + 6) = perturb ! u%WAMITMesh%RotationAcc + index = index + 6 + end if + p%du(index + 1) = perturb_t ! u%PRPMesh%TranslationDisp + p%du(index + 2) = perturb ! u%PRPMesh%Orientation + p%du(index + 3) = perturb_t ! u%PRPMesh%TranslationVel + p%du(index + 4) = perturb ! u%PRPMesh%RotationVel + p%du(index + 5) = perturb_t ! u%PRPMesh%TranslationAcc + p%du(index + 6) = perturb ! u%PRPMesh%RotationAcc !................ ! names of the columns, InitOut%LinNames_u: @@ -3190,6 +3322,17 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) end if + if ( u%WAMITMesh%Committed ) then + FieldMask = .false. + FieldMask(MASKID_TRANSLATIONDISP) = .true. + FieldMask(MASKID_Orientation) = .true. + FieldMask(MASKID_TRANSLATIONVel) = .true. + FieldMask(MASKID_ROTATIONVel) = .true. + FieldMask(MASKID_TRANSLATIONACC) = .true. + FieldMask(MASKID_ROTATIONACC) = .true. + call PackMotionMesh_Names(u%WAMITMesh, 'WAMIT', InitOut%LinNames_u, index, FieldMask=FieldMask) + end if + FieldMask = .false. FieldMask(MASKID_TRANSLATIONDISP) = .true. FieldMask(MASKID_Orientation) = .true. @@ -3197,8 +3340,8 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) FieldMask(MASKID_ROTATIONVel) = .true. FieldMask(MASKID_TRANSLATIONACC) = .true. FieldMask(MASKID_ROTATIONACC) = .true. - call PackMotionMesh_Names(u%WAMITMesh, 'Platform-RefPt', InitOut%LinNames_u, index, FieldMask=FieldMask) - + call PackMotionMesh_Names(u%PRPMesh, 'Platform-RefPt', InitOut%LinNames_u, index, FieldMask=FieldMask) + InitOut%LinNames_u(index) = 'Extended input: wave elevation at platform ref point, m' END SUBROUTINE HD_Init_Jacobian @@ -3216,19 +3359,18 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) ! local variables integer :: fieldIndx - integer :: node + integer :: node, index - + index = 0 fieldIndx = p%Jac_u_indx(n,2) node = p%Jac_u_indx(n,3) - + !TODO: One last review of mesh names in below logic GJH du = p%du( p%Jac_u_indx(n,1) ) ! determine which mesh we're trying to perturb and perturb the input: ! If we do not have Morison meshes, then the following select cases will vary if ( u%Morison%Mesh%Committed ) then - SELECT CASE( p%Jac_u_indx(n,1) ) CASE ( 1) !Module/Mesh/Field: u%Morison%Mesh%TranslationDisp = 1 u%Morison%Mesh%TranslationDisp (fieldIndx,node) = u%Morison%Mesh%TranslationDisp (fieldIndx,node) + du * perturb_sign @@ -3242,40 +3384,97 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) u%Morison%Mesh%TranslationAcc( fieldIndx,node) = u%Morison%Mesh%TranslationAcc( fieldIndx,node) + du * perturb_sign CASE ( 6) !Module/Mesh/Field: u%Morison%Mesh%RotationAcc = 6 u%Morison%Mesh%RotationAcc(fieldIndx,node) = u%Morison%Mesh%RotationAcc(fieldIndx,node) + du * perturb_sign - - CASE ( 7) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 - u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE ( 8) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 - CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE ( 9) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 - u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (10) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 - u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (11) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 - u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (12) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 - u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign - - + end select + if ( u%WAMITMesh%Committed ) then + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 7) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 7 + u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%WAMITMesh%Orientation = 8 + CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 9) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 9 + u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 10 + u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (11) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 11 + u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (12) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 12 + u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign END SELECT - else + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE (13) !Module/Mesh/Field: u%PRPMesh%TranslationDisp = 13 + u%PRPMesh%TranslationDisp (fieldIndx,node) = u%PRPMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE (14) !Module/Mesh/Field: u%PRPMesh%Orientation = 14 + CALL PerturbOrientationMatrix( u%PRPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE (15) !Module/Mesh/Field: u%PRPMesh%TranslationVel = 15 + u%PRPMesh%TranslationVel( fieldIndx,node) = u%PRPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (16) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + u%PRPMesh%RotationVel (fieldIndx,node) = u%PRPMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (17) !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 17 + u%PRPMesh%TranslationAcc( fieldIndx,node) = u%PRPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (18) !Module/Mesh/Field: u%PRPMesh%RotationAcc = 18 + u%PRPMesh%RotationAcc(fieldIndx,node) = u%PRPMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + END SELECT + else + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 7) !Module/Mesh/Field: u%PRPMesh%TranslationDisp = 7 + u%PRPMesh%TranslationDisp (fieldIndx,node) = u%PRPMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%PRPMesh%Orientation = 8 + CALL PerturbOrientationMatrix( u%PRPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 9) !Module/Mesh/Field: u%PRPMesh%TranslationVel = 9 + u%PRPMesh%TranslationVel( fieldIndx,node) = u%PRPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%PRPMesh%RotationVel = 10 + u%PRPMesh%RotationVel (fieldIndx,node) = u%PRPMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (11) !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 11 + u%PRPMesh%TranslationAcc( fieldIndx,node) = u%PRPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (12) !Module/Mesh/Field: u%PRPMesh%RotationAcc = 12 + u%PRPMesh%RotationAcc(fieldIndx,node) = u%PRPMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + END SELECT + end if + else if ( u%WAMITMesh%Committed ) then SELECT CASE( p%Jac_u_indx(n,1) ) - CASE (1) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 13 + CASE (1) !Module/Mesh/Field: u%WAMITMesh%TranslationDisp = 1 u%WAMITMesh%TranslationDisp (fieldIndx,node) = u%WAMITMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign - CASE (2) !Module/Mesh/Field: u%WAMITMesh%Orientation = 14 + CASE (2) !Module/Mesh/Field: u%WAMITMesh%Orientation = 2 CALL PerturbOrientationMatrix( u%WAMITMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) - CASE (3) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 15 + CASE (3) !Module/Mesh/Field: u%WAMITMesh%TranslationVel = 3 u%WAMITMesh%TranslationVel( fieldIndx,node) = u%WAMITMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (4) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + CASE (4) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 4 u%WAMITMesh%RotationVel (fieldIndx,node) = u%WAMITMesh%RotationVel (fieldIndx,node) + du * perturb_sign - CASE (5) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 17 + CASE (5) !Module/Mesh/Field: u%WAMITMesh%TranslationAcc = 5 u%WAMITMesh%TranslationAcc( fieldIndx,node) = u%WAMITMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign - CASE (6) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 18 + CASE (6) !Module/Mesh/Field: u%WAMITMesh%RotationAcc = 6 u%WAMITMesh%RotationAcc(fieldIndx,node) = u%WAMITMesh%RotationAcc(fieldIndx,node) + du * perturb_sign - - END SELECT + END SELECT + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 7) !Module/Mesh/Field: u%PRPMesh%TranslationDisp = 7 + u%PRPMesh%TranslationDisp (fieldIndx,node) = u%PRPMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 8) !Module/Mesh/Field: u%PRPMesh%Orientation = 8 + CALL PerturbOrientationMatrix( u%PRPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 9) !Module/Mesh/Field: u%PRPMesh%TranslationVel = 9 + u%PRPMesh%TranslationVel( fieldIndx,node) = u%PRPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE (10) !Module/Mesh/Field: u%PRPMesh%RotationVel = 10 + u%PRPMesh%RotationVel (fieldIndx,node) = u%PRPMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE (11) !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 11 + u%PRPMesh%TranslationAcc( fieldIndx,node) = u%PRPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE (12) !Module/Mesh/Field: u%PRPMesh%RotationAcc = 12 + u%PRPMesh%RotationAcc(fieldIndx,node) = u%PRPMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + END SELECT + else + SELECT CASE( p%Jac_u_indx(n,1) ) + CASE ( 1) !Module/Mesh/Field: u%PRPMesh%TranslationDisp = 1 + u%PRPMesh%TranslationDisp (fieldIndx,node) = u%PRPMesh%TranslationDisp (fieldIndx,node) + du * perturb_sign + CASE ( 2) !Module/Mesh/Field: u%PRPMesh%Orientation = 2 + CALL PerturbOrientationMatrix( u%PRPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) + CASE ( 3) !Module/Mesh/Field: u%PRPMesh%TranslationVel = 3 + u%PRPMesh%TranslationVel( fieldIndx,node) = u%PRPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign + CASE ( 4) !Module/Mesh/Field: u%PRPMesh%RotationVel = 4 + u%PRPMesh%RotationVel (fieldIndx,node) = u%PRPMesh%RotationVel (fieldIndx,node) + du * perturb_sign + CASE ( 5) !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 5 + u%PRPMesh%TranslationAcc( fieldIndx,node) = u%PRPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign + CASE ( 6) !Module/Mesh/Field: u%PRPMesh%RotationAcc = 6 + u%PRPMesh%RotationAcc(fieldIndx,node) = u%PRPMesh%RotationAcc(fieldIndx,node) + du * perturb_sign + END SELECT end if - END SUBROUTINE HD_Perturb_u !---------------------------------------------------------------------------------------------------------------------------------- @@ -3291,17 +3490,34 @@ SUBROUTINE HD_Perturb_x( p, n, perturb_sign, x, dx ) ! local variables - integer(intKi) :: indx + integer(intKi) :: i, indx, offset1, offset2, n2 + !TODO: Note: All excitation states for all bodies are stored 1st, then all radiation states dx = p%dx(n) + offset1 = 1 + if ( n <= p%totalExctnStates ) then + + ! Find body index for exctn states - if (n > p%WAMIT(1)%SS_Exctn%numStates) then - indx = n - p%WAMIT(1)%SS_Exctn%numStates - x%WAMIT(1)%SS_Rdtn%x( indx ) = x%WAMIT(1)%SS_Rdtn%x( indx ) + dx * perturb_sign else - indx = n - x%WAMIT(1)%SS_Exctn%x( indx ) = x%WAMIT(1)%SS_Exctn%x( indx ) + dx * perturb_sign + ! Find body index for rdtn states end if + + do i=1,p%nWAMITObj + offset2 = offset1 + p%WAMIT(i)%SS_Exctn%numStates + p%WAMIT(i)%SS_Rdtn%numStates + if ( n >= offset1 .and. n < offset2) then + n2 = n - offset1 + if ( n2 > p%WAMIT(i)%SS_Exctn%numStates) then + indx = n2 - p%WAMIT(i)%SS_Exctn%numStates + x%WAMIT(i)%SS_Rdtn%x( indx ) = x%WAMIT(i)%SS_Rdtn%x( indx ) + dx * perturb_sign + else + indx = n2 + x%WAMIT(i)%SS_Exctn%x( indx ) = x%WAMIT(i)%SS_Exctn%x( indx ) + dx * perturb_sign + end if + else + offset1 = offset2 + end if + end do END SUBROUTINE HD_Perturb_x @@ -3329,10 +3545,9 @@ SUBROUTINE Compute_dY(p, y_p, y_m, delta, dY) if ( y_p%Morison%Mesh%Committed ) then call PackLoadMesh_dY(y_p%Morison%Mesh, y_m%Morison%Mesh, dY, indx_first) end if - - call PackLoadMesh_dY(y_p%WAMITMesh, y_m%WAMITMesh, dY, indx_first) -!TODO: With NBody WAMIT rework need to see if removing this causes issues - !call PackLoadMesh_dY(y_p%AllHdroOrigin, y_m%AllHdroOrigin, dY, indx_first) + if ( y_p%WAMITMesh%Committed ) then + call PackLoadMesh_dY(y_p%WAMITMesh, y_m%WAMITMesh, dY, indx_first) + end if do k=1,p%NumTotalOuts dY(k+indx_first-1) = y_p%WriteOutput(k) - y_m%WriteOutput(k) @@ -3368,7 +3583,7 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, - INTEGER(IntKi) :: i, k, index, nu + INTEGER(IntKi) :: i, j, k, index, nu INTEGER(IntKi) :: ny INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -3391,13 +3606,14 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, ! our operating point includes DCM (orientation) matrices, not just small angles like the perturbation matrices do if ( u%Morison%Mesh%Committed ) then - nu = nu + u%Morison%Mesh%NNodes * 6 & ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node - + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node - nu = nu + 1 ! Extended input - else - nu = nu + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node - nu = nu + 1 ! Extended input + nu = nu + u%Morison%Mesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node end if + if ( u%WAMITMesh%Committed ) then + nu = nu + u%WAMITMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + end if + + nu = nu + u%PRPMesh%NNodes * 6 ! p%Jac_u_indx has 3 for Orientation, but we need 9 at each node + nu = nu + 1 ! Extended input call AllocAry(u_op, nu,'u_op',ErrStat2,ErrMsg2) ! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -3418,8 +3634,12 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, call PackMotionMesh(u%Morison%Mesh, u_op, index, FieldMask=Mask) end if - call PackMotionMesh(u%WAMITMesh, u_op, index, FieldMask=Mask) - + if ( u%WAMITMesh%Committed ) then + call PackMotionMesh(u%WAMITMesh, u_op, index, FieldMask=Mask) + end if + + call PackMotionMesh(u%PRPMesh, u_op, index, FieldMask=Mask) + ! extended input: u_op(index) = 0.0_R8Ki !u%WaveElev0 @@ -3439,10 +3659,9 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, if ( y%Morison%Mesh%Committed ) then call PackLoadMesh(y%Morison%Mesh, y_op, index) end if - - call PackLoadMesh(y%WAMITMesh, y_op, index) -!TODO: With NBody WAMIT rework need to see if removing this causes issues -! call PackLoadMesh(y%AllHdroOrigin, y_op, index) + if ( y%WAMITMesh%Committed ) then + call PackLoadMesh(y%WAMITMesh, y_op, index) + end if index = index - 1 do i=1,p%NumTotalOuts @@ -3453,47 +3672,58 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, !.................................. IF ( PRESENT( x_op ) ) THEN - - if (.not. allocated(x_op)) then - call AllocAry(x_op, p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates,'x_op',ErrStat2,ErrMsg2) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat>=AbortErrLev) return + if ( y%WAMITMesh%Committed ) then + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%totalStates,'x_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return + end if + index = 1 + do j=1, p%nWAMITObj + do i=1,p%WAMIT(j)%SS_Exctn%numStates ! Loop through all DOFs + x_op(index) = x%WAMIT(j)%SS_Exctn%x(i) + index = index + 1 + end do + end do + do j=1, p%nWAMITObj + do i=1,p%WAMIT(j)%SS_Rdtn%numStates ! Loop through all DOFs + x_op(index) = x%WAMIT(j)%SS_Rdtn%x(i) + index = index + 1 + end do + end do end if - - do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all DOFs - x_op(i) = x%WAMIT(1)%SS_Exctn%x(i) - end do - do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all DOFs - x_op(i+p%WAMIT(1)%SS_Exctn%numStates) = x%WAMIT(1)%SS_Rdtn%x(i) - end do - END IF !.................................. IF ( PRESENT( dx_op ) ) THEN - - if (.not. allocated(dx_op)) then - call AllocAry(dx_op, p%WAMIT(1)%SS_Exctn%numStates+p%WAMIT(1)%SS_Rdtn%numStates,'dx_op',ErrStat2,ErrMsg2) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat>=AbortErrLev) return - end if - - call HydroDyn_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat>=AbortErrLev) then - call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) - return + if ( y%WAMITMesh%Committed ) then + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%totalStates,'dx_op',ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) return end if - - do i=1,p%WAMIT(1)%SS_Exctn%numStates ! Loop through all DOFs - dx_op(i) = dx%WAMIT(1)%SS_Exctn%x(i) - end do - do i=1,p%WAMIT(1)%SS_Rdtn%numStates ! Loop through all DOFs - dx_op(i+p%WAMIT(1)%SS_Exctn%numStates) = dx%WAMIT(1)%SS_Rdtn%x(i) - end do - call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) - + call HydroDyn_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dx, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat>=AbortErrLev) then + call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) + return + end if + index = 1 + do j=1, p%nWAMITObj + do i=1,p%WAMIT(j)%SS_Exctn%numStates ! Loop through all DOFs + dx_op(index) = dx%WAMIT(j)%SS_Exctn%x(i) + index = index + 1 + end do + end do + do j=1, p%nWAMITObj + do i=1,p%WAMIT(j)%SS_Rdtn%numStates ! Loop through all DOFs + dx_op(index) = dx%WAMIT(j)%SS_Rdtn%x(i) + index = index + 1 + end do + end do + call HydroDyn_DestroyContState( dx, ErrStat2, ErrMsg2) + end if END IF !.................................. diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index f9abb2da0..b8a4de128 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -169,6 +169,9 @@ typedef ^ ^ Morison_Par typedef ^ ^ INTEGER PotMod - - - "1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model" - typedef ^ ^ INTEGER NBody - - - "[>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]" - typedef ^ ^ INTEGER NBodyMod - - - "Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]" - +typedef ^ ^ INTEGER totalStates - - - "Number of excitation and radiation states for all WAMIT bodies" - +typedef ^ ^ INTEGER totalExctnStates - - - "Number of excitation states for all WAMIT bodies" - +typedef ^ ^ INTEGER totalRdtnStates - - - "Number of radiation states for all WAMIT bodies" - typedef ^ ^ SiKi WaveTime {:} - - "Array of time samples, (sec)" - typedef ^ ^ INTEGER NStepWave - - - "Number of data points in the wave kinematics arrays" - typedef ^ ^ INTEGER NWaveElev - - - "Number of wave elevation outputs" - diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index 0782dca33..7dc58021b 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -185,6 +185,9 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: PotMod !< 1 if using WAMIT model, 0 if no potential flow model, or 2 if FIT model [-] INTEGER(IntKi) :: NBody !< [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] [-] INTEGER(IntKi) :: NBodyMod !< Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] [-] + INTEGER(IntKi) :: totalStates !< Number of excitation and radiation states for all WAMIT bodies [-] + INTEGER(IntKi) :: totalExctnStates !< Number of excitation states for all WAMIT bodies [-] + INTEGER(IntKi) :: totalRdtnStates !< Number of radiation states for all WAMIT bodies [-] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Array of time samples, (sec) [-] INTEGER(IntKi) :: NStepWave !< Number of data points in the wave kinematics arrays [-] INTEGER(IntKi) :: NWaveElev !< Number of wave elevation outputs [-] @@ -7197,6 +7200,9 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er DstParamData%PotMod = SrcParamData%PotMod DstParamData%NBody = SrcParamData%NBody DstParamData%NBodyMod = SrcParamData%NBodyMod + DstParamData%totalStates = SrcParamData%totalStates + DstParamData%totalExctnStates = SrcParamData%totalExctnStates + DstParamData%totalRdtnStates = SrcParamData%totalRdtnStates IF (ALLOCATED(SrcParamData%WaveTime)) THEN i1_l = LBOUND(SrcParamData%WaveTime,1) i1_u = UBOUND(SrcParamData%WaveTime,1) @@ -7568,6 +7574,9 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Int_BufSz = Int_BufSz + 1 ! PotMod Int_BufSz = Int_BufSz + 1 ! NBody Int_BufSz = Int_BufSz + 1 ! NBodyMod + Int_BufSz = Int_BufSz + 1 ! totalStates + Int_BufSz = Int_BufSz + 1 ! totalExctnStates + Int_BufSz = Int_BufSz + 1 ! totalRdtnStates Int_BufSz = Int_BufSz + 1 ! WaveTime allocated yes/no IF ( ALLOCATED(InData%WaveTime) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WaveTime upper/lower bounds for each dimension @@ -7836,6 +7845,12 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NBodyMod Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%totalStates + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%totalExctnStates + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%totalRdtnStates + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WaveTime) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8364,6 +8379,12 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E Int_Xferred = Int_Xferred + 1 OutData%NBodyMod = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%totalStates = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%totalExctnStates = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%totalRdtnStates = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveTime not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index afd977d40..dd5fc4259 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -192,6 +192,21 @@ MODULE Morison_Types LOGICAL :: PropPot !< Is this element/member modeled with potential flow theory T/F [-] END TYPE Morison_MemberType ! ======================= +! ========= Morison_MemberLoads ======= + TYPE, PUBLIC :: Morison_MemberLoads + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D !< Member-based (side-effects) Nodal viscous drag loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I !< Member-based (side-effects) Nodal inertial loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A !< Member-based (side-effects) Nodal added mass loads at time t [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B !< Member-based (side-effects) Nodal buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF !< Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_If !< Member-based (side-effects) Nodal flooded ballast inertia loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_WMG !< Member-based (side-effects) Nodal marine growth weight loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG !< Member-based (side-effects) Nodal marine growth inertia loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FV !< Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FA !< Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] + END TYPE Morison_MemberLoads +! ======================= ! ========= Morison_CoefMembers ======= TYPE, PUBLIC :: Morison_CoefMembers INTEGER(IntKi) :: MemberID !< User-specified integer id for the Member-based coefs [-] @@ -234,9 +249,11 @@ MODULE Morison_Types INTEGER(IntKi) :: NOutLoc !< The number of requested output locations [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NodeLocs !< Normalized locations along user-specified member for the outputs [-] INTEGER(IntKi) :: MemberIDIndx !< Index for member in the master list [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Marker1 !< Index of node in DistribMesh for the start of the member [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Marker2 !< Index of node in DistribMesh for the end of the member [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: s !< Linear interpolation factor between Marker1 and Marker2 for the output location [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: MeshIndx1 !< Index of node in Mesh for the start of the member element [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: MeshIndx2 !< Index of node in Mesh for the end of the member element [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: MemberIndx1 !< Index of Member nodes for the start of the member element [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: MemberIndx2 !< Index of Member nodes for the end of the member element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: s !< Linear interpolation factor between node1 and node2 for the output location [-] END TYPE Morison_MOutput ! ======================= ! ========= Morison_JOutput ======= @@ -331,20 +348,12 @@ MODULE Morison_Types ! ======================= ! ========= Morison_MiscVarType ======= TYPE, PUBLIC :: Morison_MiscVarType - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D !< Member-based (side-effects) Nodal viscous drag loads at time t [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I !< Member-based (side-effects) Nodal inertial loads at time t [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A !< Member-based (side-effects) Nodal added mass loads at time t [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B !< Member-based (side-effects) Nodal buoyancy loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF !< Member-based (side-effects) Nodal flooded ballast weight/buoyancy loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_If !< Member-based (side-effects) Nodal flooded ballast inertia loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_WMG !< Member-based (side-effects) Nodal marine growth weight loads [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG !< Member-based (side-effects) Nodal marine growth inertia loads [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FV !< Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FA !< Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FDynP !< Fluid dynamic pressure at line element node at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: vrel !< velocity of structural node relative to the water [m/s^2] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-] + TYPE(Morison_MemberLoads) , DIMENSION(:), ALLOCATABLE :: memberLoads !< Array (NMembers long) of member-based side-effects load contributions [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_B_End !< [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_D_End !< Lumped viscous drag loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I_End !< Lumped intertia loads at time t, which may not correspond to the WaveTime array of times [-] @@ -4018,63 +4027,227 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_UnPackMemberType - SUBROUTINE Morison_CopyCoefMembers( SrcCoefMembersData, DstCoefMembersData, CtrlCode, ErrStat, ErrMsg ) - TYPE(Morison_CoefMembers), INTENT(IN) :: SrcCoefMembersData - TYPE(Morison_CoefMembers), INTENT(INOUT) :: DstCoefMembersData + SUBROUTINE Morison_CopyMemberLoads( SrcMemberLoadsData, DstMemberLoadsData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_MemberLoads), INTENT(IN) :: SrcMemberLoadsData + TYPE(Morison_MemberLoads), INTENT(INOUT) :: DstMemberLoadsData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyCoefMembers' + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyMemberLoads' ! ErrStat = ErrID_None ErrMsg = "" - DstCoefMembersData%MemberID = SrcCoefMembersData%MemberID - DstCoefMembersData%MemberCd1 = SrcCoefMembersData%MemberCd1 - DstCoefMembersData%MemberCd2 = SrcCoefMembersData%MemberCd2 - DstCoefMembersData%MemberCdMG1 = SrcCoefMembersData%MemberCdMG1 - DstCoefMembersData%MemberCdMG2 = SrcCoefMembersData%MemberCdMG2 - DstCoefMembersData%MemberCa1 = SrcCoefMembersData%MemberCa1 - DstCoefMembersData%MemberCa2 = SrcCoefMembersData%MemberCa2 - DstCoefMembersData%MemberCaMG1 = SrcCoefMembersData%MemberCaMG1 - DstCoefMembersData%MemberCaMG2 = SrcCoefMembersData%MemberCaMG2 - DstCoefMembersData%MemberCp1 = SrcCoefMembersData%MemberCp1 - DstCoefMembersData%MemberCp2 = SrcCoefMembersData%MemberCp2 - DstCoefMembersData%MemberCpMG1 = SrcCoefMembersData%MemberCpMG1 - DstCoefMembersData%MemberCpMG2 = SrcCoefMembersData%MemberCpMG2 - DstCoefMembersData%MemberAxCd1 = SrcCoefMembersData%MemberAxCd1 - DstCoefMembersData%MemberAxCd2 = SrcCoefMembersData%MemberAxCd2 - DstCoefMembersData%MemberAxCdMG1 = SrcCoefMembersData%MemberAxCdMG1 - DstCoefMembersData%MemberAxCdMG2 = SrcCoefMembersData%MemberAxCdMG2 - DstCoefMembersData%MemberAxCa1 = SrcCoefMembersData%MemberAxCa1 - DstCoefMembersData%MemberAxCa2 = SrcCoefMembersData%MemberAxCa2 - DstCoefMembersData%MemberAxCaMG1 = SrcCoefMembersData%MemberAxCaMG1 - DstCoefMembersData%MemberAxCaMG2 = SrcCoefMembersData%MemberAxCaMG2 - DstCoefMembersData%MemberAxCp1 = SrcCoefMembersData%MemberAxCp1 - DstCoefMembersData%MemberAxCp2 = SrcCoefMembersData%MemberAxCp2 - DstCoefMembersData%MemberAxCpMG1 = SrcCoefMembersData%MemberAxCpMG1 - DstCoefMembersData%MemberAxCpMG2 = SrcCoefMembersData%MemberAxCpMG2 - END SUBROUTINE Morison_CopyCoefMembers +IF (ALLOCATED(SrcMemberLoadsData%F_D)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_D,1) + i1_u = UBOUND(SrcMemberLoadsData%F_D,1) + i2_l = LBOUND(SrcMemberLoadsData%F_D,2) + i2_u = UBOUND(SrcMemberLoadsData%F_D,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_D)) THEN + ALLOCATE(DstMemberLoadsData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_D = SrcMemberLoadsData%F_D +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_I)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_I,1) + i1_u = UBOUND(SrcMemberLoadsData%F_I,1) + i2_l = LBOUND(SrcMemberLoadsData%F_I,2) + i2_u = UBOUND(SrcMemberLoadsData%F_I,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_I)) THEN + ALLOCATE(DstMemberLoadsData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_I = SrcMemberLoadsData%F_I +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_A)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_A,1) + i1_u = UBOUND(SrcMemberLoadsData%F_A,1) + i2_l = LBOUND(SrcMemberLoadsData%F_A,2) + i2_u = UBOUND(SrcMemberLoadsData%F_A,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_A)) THEN + ALLOCATE(DstMemberLoadsData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_A = SrcMemberLoadsData%F_A +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_B)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_B,1) + i1_u = UBOUND(SrcMemberLoadsData%F_B,1) + i2_l = LBOUND(SrcMemberLoadsData%F_B,2) + i2_u = UBOUND(SrcMemberLoadsData%F_B,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_B)) THEN + ALLOCATE(DstMemberLoadsData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_B = SrcMemberLoadsData%F_B +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_BF)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_BF,1) + i1_u = UBOUND(SrcMemberLoadsData%F_BF,1) + i2_l = LBOUND(SrcMemberLoadsData%F_BF,2) + i2_u = UBOUND(SrcMemberLoadsData%F_BF,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_BF)) THEN + ALLOCATE(DstMemberLoadsData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_BF = SrcMemberLoadsData%F_BF +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_If)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_If,1) + i1_u = UBOUND(SrcMemberLoadsData%F_If,1) + i2_l = LBOUND(SrcMemberLoadsData%F_If,2) + i2_u = UBOUND(SrcMemberLoadsData%F_If,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_If)) THEN + ALLOCATE(DstMemberLoadsData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_If.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_If = SrcMemberLoadsData%F_If +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_WMG)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_WMG,1) + i1_u = UBOUND(SrcMemberLoadsData%F_WMG,1) + i2_l = LBOUND(SrcMemberLoadsData%F_WMG,2) + i2_u = UBOUND(SrcMemberLoadsData%F_WMG,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_WMG)) THEN + ALLOCATE(DstMemberLoadsData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_WMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_WMG = SrcMemberLoadsData%F_WMG +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_IMG)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_IMG,1) + i1_u = UBOUND(SrcMemberLoadsData%F_IMG,1) + i2_l = LBOUND(SrcMemberLoadsData%F_IMG,2) + i2_u = UBOUND(SrcMemberLoadsData%F_IMG,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_IMG)) THEN + ALLOCATE(DstMemberLoadsData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_IMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_IMG = SrcMemberLoadsData%F_IMG +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%FV)) THEN + i1_l = LBOUND(SrcMemberLoadsData%FV,1) + i1_u = UBOUND(SrcMemberLoadsData%FV,1) + i2_l = LBOUND(SrcMemberLoadsData%FV,2) + i2_u = UBOUND(SrcMemberLoadsData%FV,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%FV)) THEN + ALLOCATE(DstMemberLoadsData%FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%FV = SrcMemberLoadsData%FV +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%FA)) THEN + i1_l = LBOUND(SrcMemberLoadsData%FA,1) + i1_u = UBOUND(SrcMemberLoadsData%FA,1) + i2_l = LBOUND(SrcMemberLoadsData%FA,2) + i2_u = UBOUND(SrcMemberLoadsData%FA,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%FA)) THEN + ALLOCATE(DstMemberLoadsData%FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%FA = SrcMemberLoadsData%FA +ENDIF +IF (ALLOCATED(SrcMemberLoadsData%F_DP)) THEN + i1_l = LBOUND(SrcMemberLoadsData%F_DP,1) + i1_u = UBOUND(SrcMemberLoadsData%F_DP,1) + i2_l = LBOUND(SrcMemberLoadsData%F_DP,2) + i2_u = UBOUND(SrcMemberLoadsData%F_DP,2) + IF (.NOT. ALLOCATED(DstMemberLoadsData%F_DP)) THEN + ALLOCATE(DstMemberLoadsData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMemberLoadsData%F_DP = SrcMemberLoadsData%F_DP +ENDIF + END SUBROUTINE Morison_CopyMemberLoads - SUBROUTINE Morison_DestroyCoefMembers( CoefMembersData, ErrStat, ErrMsg ) - TYPE(Morison_CoefMembers), INTENT(INOUT) :: CoefMembersData + SUBROUTINE Morison_DestroyMemberLoads( MemberLoadsData, ErrStat, ErrMsg ) + TYPE(Morison_MemberLoads), INTENT(INOUT) :: MemberLoadsData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyCoefMembers' + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyMemberLoads' INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 ! ErrStat = ErrID_None ErrMsg = "" - END SUBROUTINE Morison_DestroyCoefMembers +IF (ALLOCATED(MemberLoadsData%F_D)) THEN + DEALLOCATE(MemberLoadsData%F_D) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_I)) THEN + DEALLOCATE(MemberLoadsData%F_I) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_A)) THEN + DEALLOCATE(MemberLoadsData%F_A) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_B)) THEN + DEALLOCATE(MemberLoadsData%F_B) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_BF)) THEN + DEALLOCATE(MemberLoadsData%F_BF) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_If)) THEN + DEALLOCATE(MemberLoadsData%F_If) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_WMG)) THEN + DEALLOCATE(MemberLoadsData%F_WMG) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_IMG)) THEN + DEALLOCATE(MemberLoadsData%F_IMG) +ENDIF +IF (ALLOCATED(MemberLoadsData%FV)) THEN + DEALLOCATE(MemberLoadsData%FV) +ENDIF +IF (ALLOCATED(MemberLoadsData%FA)) THEN + DEALLOCATE(MemberLoadsData%FA) +ENDIF +IF (ALLOCATED(MemberLoadsData%F_DP)) THEN + DEALLOCATE(MemberLoadsData%F_DP) +ENDIF + END SUBROUTINE Morison_DestroyMemberLoads - SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE Morison_PackMemberLoads( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(Morison_CoefMembers), INTENT(IN) :: InData + TYPE(Morison_MemberLoads), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -4089,7 +4262,7 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_PackCoefMembers' + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_PackMemberLoads' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -4105,31 +4278,61 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! MemberID - Re_BufSz = Re_BufSz + 1 ! MemberCd1 - Re_BufSz = Re_BufSz + 1 ! MemberCd2 - Re_BufSz = Re_BufSz + 1 ! MemberCdMG1 - Re_BufSz = Re_BufSz + 1 ! MemberCdMG2 - Re_BufSz = Re_BufSz + 1 ! MemberCa1 - Re_BufSz = Re_BufSz + 1 ! MemberCa2 - Re_BufSz = Re_BufSz + 1 ! MemberCaMG1 - Re_BufSz = Re_BufSz + 1 ! MemberCaMG2 - Re_BufSz = Re_BufSz + 1 ! MemberCp1 - Re_BufSz = Re_BufSz + 1 ! MemberCp2 - Re_BufSz = Re_BufSz + 1 ! MemberCpMG1 - Re_BufSz = Re_BufSz + 1 ! MemberCpMG2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCd1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCd2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCa1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCa2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCp1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCp2 - Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG1 - Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG2 + Int_BufSz = Int_BufSz + 1 ! F_D allocated yes/no + IF ( ALLOCATED(InData%F_D) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_D upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_D) ! F_D + END IF + Int_BufSz = Int_BufSz + 1 ! F_I allocated yes/no + IF ( ALLOCATED(InData%F_I) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_I upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_I) ! F_I + END IF + Int_BufSz = Int_BufSz + 1 ! F_A allocated yes/no + IF ( ALLOCATED(InData%F_A) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_A upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_A) ! F_A + END IF + Int_BufSz = Int_BufSz + 1 ! F_B allocated yes/no + IF ( ALLOCATED(InData%F_B) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_B upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_B) ! F_B + END IF + Int_BufSz = Int_BufSz + 1 ! F_BF allocated yes/no + IF ( ALLOCATED(InData%F_BF) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_BF upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_BF) ! F_BF + END IF + Int_BufSz = Int_BufSz + 1 ! F_If allocated yes/no + IF ( ALLOCATED(InData%F_If) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_If upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_If) ! F_If + END IF + Int_BufSz = Int_BufSz + 1 ! F_WMG allocated yes/no + IF ( ALLOCATED(InData%F_WMG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_WMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_WMG) ! F_WMG + END IF + Int_BufSz = Int_BufSz + 1 ! F_IMG allocated yes/no + IF ( ALLOCATED(InData%F_IMG) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_IMG upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_IMG) ! F_IMG + END IF + Int_BufSz = Int_BufSz + 1 ! FV allocated yes/no + IF ( ALLOCATED(InData%FV) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FV) ! FV + END IF + Int_BufSz = Int_BufSz + 1 ! FA allocated yes/no + IF ( ALLOCATED(InData%FA) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! FA upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FA) ! FA + END IF + Int_BufSz = Int_BufSz + 1 ! F_DP allocated yes/no + IF ( ALLOCATED(InData%F_DP) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! F_DP upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -4157,56 +4360,700 @@ SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%MemberID + IF ( .NOT. ALLOCATED(InData%F_D) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCd1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCd2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCdMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCdMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCa1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCa2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberCpMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCd1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCd2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCdMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCdMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCa1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCa2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCaMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCaMG2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCp1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCp2 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCpMG1 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MemberAxCpMG2 - Re_Xferred = Re_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_D,2), UBOUND(InData%F_D,2) + DO i1 = LBOUND(InData%F_D,1), UBOUND(InData%F_D,1) + ReKiBuf(Re_Xferred) = InData%F_D(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_I) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_I,2), UBOUND(InData%F_I,2) + DO i1 = LBOUND(InData%F_I,1), UBOUND(InData%F_I,1) + ReKiBuf(Re_Xferred) = InData%F_I(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_A) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_A,2), UBOUND(InData%F_A,2) + DO i1 = LBOUND(InData%F_A,1), UBOUND(InData%F_A,1) + ReKiBuf(Re_Xferred) = InData%F_A(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_B) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_B,2), UBOUND(InData%F_B,2) + DO i1 = LBOUND(InData%F_B,1), UBOUND(InData%F_B,1) + ReKiBuf(Re_Xferred) = InData%F_B(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_BF) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_BF,2), UBOUND(InData%F_BF,2) + DO i1 = LBOUND(InData%F_BF,1), UBOUND(InData%F_BF,1) + ReKiBuf(Re_Xferred) = InData%F_BF(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_If) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_If,2), UBOUND(InData%F_If,2) + DO i1 = LBOUND(InData%F_If,1), UBOUND(InData%F_If,1) + ReKiBuf(Re_Xferred) = InData%F_If(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_WMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_WMG,2), UBOUND(InData%F_WMG,2) + DO i1 = LBOUND(InData%F_WMG,1), UBOUND(InData%F_WMG,1) + ReKiBuf(Re_Xferred) = InData%F_WMG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_IMG) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_IMG,2), UBOUND(InData%F_IMG,2) + DO i1 = LBOUND(InData%F_IMG,1), UBOUND(InData%F_IMG,1) + ReKiBuf(Re_Xferred) = InData%F_IMG(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FV) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FV,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FV,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FV,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FV,2), UBOUND(InData%FV,2) + DO i1 = LBOUND(InData%FV,1), UBOUND(InData%FV,1) + ReKiBuf(Re_Xferred) = InData%FV(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%FA) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FA,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FA,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FA,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FA,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%FA,2), UBOUND(InData%FA,2) + DO i1 = LBOUND(InData%FA,1), UBOUND(InData%FA,1) + ReKiBuf(Re_Xferred) = InData%FA(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%F_DP) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%F_DP,2), UBOUND(InData%F_DP,2) + DO i1 = LBOUND(InData%F_DP,1), UBOUND(InData%F_DP,1) + ReKiBuf(Re_Xferred) = InData%F_DP(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE Morison_PackMemberLoads + + SUBROUTINE Morison_UnPackMemberLoads( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Morison_MemberLoads), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMemberLoads' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_D not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_D)) DEALLOCATE(OutData%F_D) + ALLOCATE(OutData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_D,2), UBOUND(OutData%F_D,2) + DO i1 = LBOUND(OutData%F_D,1), UBOUND(OutData%F_D,1) + OutData%F_D(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_I)) DEALLOCATE(OutData%F_I) + ALLOCATE(OutData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_I,2), UBOUND(OutData%F_I,2) + DO i1 = LBOUND(OutData%F_I,1), UBOUND(OutData%F_I,1) + OutData%F_I(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_A not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_A)) DEALLOCATE(OutData%F_A) + ALLOCATE(OutData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_A,2), UBOUND(OutData%F_A,2) + DO i1 = LBOUND(OutData%F_A,1), UBOUND(OutData%F_A,1) + OutData%F_A(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_B)) DEALLOCATE(OutData%F_B) + ALLOCATE(OutData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_B,2), UBOUND(OutData%F_B,2) + DO i1 = LBOUND(OutData%F_B,1), UBOUND(OutData%F_B,1) + OutData%F_B(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_BF not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_BF)) DEALLOCATE(OutData%F_BF) + ALLOCATE(OutData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_BF,2), UBOUND(OutData%F_BF,2) + DO i1 = LBOUND(OutData%F_BF,1), UBOUND(OutData%F_BF,1) + OutData%F_BF(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_If not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_If)) DEALLOCATE(OutData%F_If) + ALLOCATE(OutData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_If.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_If,2), UBOUND(OutData%F_If,2) + DO i1 = LBOUND(OutData%F_If,1), UBOUND(OutData%F_If,1) + OutData%F_If(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_WMG)) DEALLOCATE(OutData%F_WMG) + ALLOCATE(OutData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_WMG,2), UBOUND(OutData%F_WMG,2) + DO i1 = LBOUND(OutData%F_WMG,1), UBOUND(OutData%F_WMG,1) + OutData%F_WMG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_IMG not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_IMG)) DEALLOCATE(OutData%F_IMG) + ALLOCATE(OutData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_IMG,2), UBOUND(OutData%F_IMG,2) + DO i1 = LBOUND(OutData%F_IMG,1), UBOUND(OutData%F_IMG,1) + OutData%F_IMG(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FV not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FV)) DEALLOCATE(OutData%FV) + ALLOCATE(OutData%FV(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FV,2), UBOUND(OutData%FV,2) + DO i1 = LBOUND(OutData%FV,1), UBOUND(OutData%FV,1) + OutData%FV(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FA not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FA)) DEALLOCATE(OutData%FA) + ALLOCATE(OutData%FA(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FA.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%FA,2), UBOUND(OutData%FA,2) + DO i1 = LBOUND(OutData%FA,1), UBOUND(OutData%FA,1) + OutData%FA(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%F_DP)) DEALLOCATE(OutData%F_DP) + ALLOCATE(OutData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%F_DP,2), UBOUND(OutData%F_DP,2) + DO i1 = LBOUND(OutData%F_DP,1), UBOUND(OutData%F_DP,1) + OutData%F_DP(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE Morison_UnPackMemberLoads + + SUBROUTINE Morison_CopyCoefMembers( SrcCoefMembersData, DstCoefMembersData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Morison_CoefMembers), INTENT(IN) :: SrcCoefMembersData + TYPE(Morison_CoefMembers), INTENT(INOUT) :: DstCoefMembersData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_CopyCoefMembers' +! + ErrStat = ErrID_None + ErrMsg = "" + DstCoefMembersData%MemberID = SrcCoefMembersData%MemberID + DstCoefMembersData%MemberCd1 = SrcCoefMembersData%MemberCd1 + DstCoefMembersData%MemberCd2 = SrcCoefMembersData%MemberCd2 + DstCoefMembersData%MemberCdMG1 = SrcCoefMembersData%MemberCdMG1 + DstCoefMembersData%MemberCdMG2 = SrcCoefMembersData%MemberCdMG2 + DstCoefMembersData%MemberCa1 = SrcCoefMembersData%MemberCa1 + DstCoefMembersData%MemberCa2 = SrcCoefMembersData%MemberCa2 + DstCoefMembersData%MemberCaMG1 = SrcCoefMembersData%MemberCaMG1 + DstCoefMembersData%MemberCaMG2 = SrcCoefMembersData%MemberCaMG2 + DstCoefMembersData%MemberCp1 = SrcCoefMembersData%MemberCp1 + DstCoefMembersData%MemberCp2 = SrcCoefMembersData%MemberCp2 + DstCoefMembersData%MemberCpMG1 = SrcCoefMembersData%MemberCpMG1 + DstCoefMembersData%MemberCpMG2 = SrcCoefMembersData%MemberCpMG2 + DstCoefMembersData%MemberAxCd1 = SrcCoefMembersData%MemberAxCd1 + DstCoefMembersData%MemberAxCd2 = SrcCoefMembersData%MemberAxCd2 + DstCoefMembersData%MemberAxCdMG1 = SrcCoefMembersData%MemberAxCdMG1 + DstCoefMembersData%MemberAxCdMG2 = SrcCoefMembersData%MemberAxCdMG2 + DstCoefMembersData%MemberAxCa1 = SrcCoefMembersData%MemberAxCa1 + DstCoefMembersData%MemberAxCa2 = SrcCoefMembersData%MemberAxCa2 + DstCoefMembersData%MemberAxCaMG1 = SrcCoefMembersData%MemberAxCaMG1 + DstCoefMembersData%MemberAxCaMG2 = SrcCoefMembersData%MemberAxCaMG2 + DstCoefMembersData%MemberAxCp1 = SrcCoefMembersData%MemberAxCp1 + DstCoefMembersData%MemberAxCp2 = SrcCoefMembersData%MemberAxCp2 + DstCoefMembersData%MemberAxCpMG1 = SrcCoefMembersData%MemberAxCpMG1 + DstCoefMembersData%MemberAxCpMG2 = SrcCoefMembersData%MemberAxCpMG2 + END SUBROUTINE Morison_CopyCoefMembers + + SUBROUTINE Morison_DestroyCoefMembers( CoefMembersData, ErrStat, ErrMsg ) + TYPE(Morison_CoefMembers), INTENT(INOUT) :: CoefMembersData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_DestroyCoefMembers' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" + END SUBROUTINE Morison_DestroyCoefMembers + + SUBROUTINE Morison_PackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Morison_CoefMembers), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_PackCoefMembers' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! MemberID + Re_BufSz = Re_BufSz + 1 ! MemberCd1 + Re_BufSz = Re_BufSz + 1 ! MemberCd2 + Re_BufSz = Re_BufSz + 1 ! MemberCdMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCdMG2 + Re_BufSz = Re_BufSz + 1 ! MemberCa1 + Re_BufSz = Re_BufSz + 1 ! MemberCa2 + Re_BufSz = Re_BufSz + 1 ! MemberCaMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCaMG2 + Re_BufSz = Re_BufSz + 1 ! MemberCp1 + Re_BufSz = Re_BufSz + 1 ! MemberCp2 + Re_BufSz = Re_BufSz + 1 ! MemberCpMG1 + Re_BufSz = Re_BufSz + 1 ! MemberCpMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCd1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCd2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCdMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCa1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCa2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCaMG2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCp1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCp2 + Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG1 + Re_BufSz = Re_BufSz + 1 ! MemberAxCpMG2 + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%MemberID + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCdMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCa1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCa2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberCpMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCd1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCd2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCdMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCdMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCa1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCa2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCaMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCaMG2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCp1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCp2 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCpMG1 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MemberAxCpMG2 + Re_Xferred = Re_Xferred + 1 END SUBROUTINE Morison_PackCoefMembers SUBROUTINE Morison_UnPackCoefMembers( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -4454,29 +5301,53 @@ SUBROUTINE Morison_CopyMOutput( SrcMOutputData, DstMOutputData, CtrlCode, ErrSta DstMOutputData%NodeLocs = SrcMOutputData%NodeLocs ENDIF DstMOutputData%MemberIDIndx = SrcMOutputData%MemberIDIndx -IF (ALLOCATED(SrcMOutputData%Marker1)) THEN - i1_l = LBOUND(SrcMOutputData%Marker1,1) - i1_u = UBOUND(SrcMOutputData%Marker1,1) - IF (.NOT. ALLOCATED(DstMOutputData%Marker1)) THEN - ALLOCATE(DstMOutputData%Marker1(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMOutputData%MeshIndx1)) THEN + i1_l = LBOUND(SrcMOutputData%MeshIndx1,1) + i1_u = UBOUND(SrcMOutputData%MeshIndx1,1) + IF (.NOT. ALLOCATED(DstMOutputData%MeshIndx1)) THEN + ALLOCATE(DstMOutputData%MeshIndx1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%MeshIndx1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%MeshIndx1 = SrcMOutputData%MeshIndx1 +ENDIF +IF (ALLOCATED(SrcMOutputData%MeshIndx2)) THEN + i1_l = LBOUND(SrcMOutputData%MeshIndx2,1) + i1_u = UBOUND(SrcMOutputData%MeshIndx2,1) + IF (.NOT. ALLOCATED(DstMOutputData%MeshIndx2)) THEN + ALLOCATE(DstMOutputData%MeshIndx2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%MeshIndx2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMOutputData%MeshIndx2 = SrcMOutputData%MeshIndx2 +ENDIF +IF (ALLOCATED(SrcMOutputData%MemberIndx1)) THEN + i1_l = LBOUND(SrcMOutputData%MemberIndx1,1) + i1_u = UBOUND(SrcMOutputData%MemberIndx1,1) + IF (.NOT. ALLOCATED(DstMOutputData%MemberIndx1)) THEN + ALLOCATE(DstMOutputData%MemberIndx1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%Marker1.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%MemberIndx1.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMOutputData%Marker1 = SrcMOutputData%Marker1 + DstMOutputData%MemberIndx1 = SrcMOutputData%MemberIndx1 ENDIF -IF (ALLOCATED(SrcMOutputData%Marker2)) THEN - i1_l = LBOUND(SrcMOutputData%Marker2,1) - i1_u = UBOUND(SrcMOutputData%Marker2,1) - IF (.NOT. ALLOCATED(DstMOutputData%Marker2)) THEN - ALLOCATE(DstMOutputData%Marker2(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMOutputData%MemberIndx2)) THEN + i1_l = LBOUND(SrcMOutputData%MemberIndx2,1) + i1_u = UBOUND(SrcMOutputData%MemberIndx2,1) + IF (.NOT. ALLOCATED(DstMOutputData%MemberIndx2)) THEN + ALLOCATE(DstMOutputData%MemberIndx2(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%Marker2.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMOutputData%MemberIndx2.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMOutputData%Marker2 = SrcMOutputData%Marker2 + DstMOutputData%MemberIndx2 = SrcMOutputData%MemberIndx2 ENDIF IF (ALLOCATED(SrcMOutputData%s)) THEN i1_l = LBOUND(SrcMOutputData%s,1) @@ -4504,11 +5375,17 @@ SUBROUTINE Morison_DestroyMOutput( MOutputData, ErrStat, ErrMsg ) IF (ALLOCATED(MOutputData%NodeLocs)) THEN DEALLOCATE(MOutputData%NodeLocs) ENDIF -IF (ALLOCATED(MOutputData%Marker1)) THEN - DEALLOCATE(MOutputData%Marker1) +IF (ALLOCATED(MOutputData%MeshIndx1)) THEN + DEALLOCATE(MOutputData%MeshIndx1) +ENDIF +IF (ALLOCATED(MOutputData%MeshIndx2)) THEN + DEALLOCATE(MOutputData%MeshIndx2) ENDIF -IF (ALLOCATED(MOutputData%Marker2)) THEN - DEALLOCATE(MOutputData%Marker2) +IF (ALLOCATED(MOutputData%MemberIndx1)) THEN + DEALLOCATE(MOutputData%MemberIndx1) +ENDIF +IF (ALLOCATED(MOutputData%MemberIndx2)) THEN + DEALLOCATE(MOutputData%MemberIndx2) ENDIF IF (ALLOCATED(MOutputData%s)) THEN DEALLOCATE(MOutputData%s) @@ -4558,15 +5435,25 @@ SUBROUTINE Morison_PackMOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = Re_BufSz + SIZE(InData%NodeLocs) ! NodeLocs END IF Int_BufSz = Int_BufSz + 1 ! MemberIDIndx - Int_BufSz = Int_BufSz + 1 ! Marker1 allocated yes/no - IF ( ALLOCATED(InData%Marker1) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Marker1 upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Marker1) ! Marker1 - END IF - Int_BufSz = Int_BufSz + 1 ! Marker2 allocated yes/no - IF ( ALLOCATED(InData%Marker2) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Marker2 upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Marker2) ! Marker2 + Int_BufSz = Int_BufSz + 1 ! MeshIndx1 allocated yes/no + IF ( ALLOCATED(InData%MeshIndx1) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MeshIndx1 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MeshIndx1) ! MeshIndx1 + END IF + Int_BufSz = Int_BufSz + 1 ! MeshIndx2 allocated yes/no + IF ( ALLOCATED(InData%MeshIndx2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MeshIndx2 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MeshIndx2) ! MeshIndx2 + END IF + Int_BufSz = Int_BufSz + 1 ! MemberIndx1 allocated yes/no + IF ( ALLOCATED(InData%MemberIndx1) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MemberIndx1 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MemberIndx1) ! MemberIndx1 + END IF + Int_BufSz = Int_BufSz + 1 ! MemberIndx2 allocated yes/no + IF ( ALLOCATED(InData%MemberIndx2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! MemberIndx2 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%MemberIndx2) ! MemberIndx2 END IF Int_BufSz = Int_BufSz + 1 ! s allocated yes/no IF ( ALLOCATED(InData%s) ) THEN @@ -4621,33 +5508,63 @@ SUBROUTINE Morison_PackMOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err END IF IntKiBuf(Int_Xferred) = InData%MemberIDIndx Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Marker1) ) THEN + IF ( .NOT. ALLOCATED(InData%MeshIndx1) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MeshIndx1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeshIndx1,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MeshIndx1,1), UBOUND(InData%MeshIndx1,1) + IntKiBuf(Int_Xferred) = InData%MeshIndx1(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MeshIndx2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MeshIndx2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MeshIndx2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%MeshIndx2,1), UBOUND(InData%MeshIndx2,1) + IntKiBuf(Int_Xferred) = InData%MeshIndx2(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%MemberIndx1) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Marker1,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Marker1,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberIndx1,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberIndx1,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Marker1,1), UBOUND(InData%Marker1,1) - IntKiBuf(Int_Xferred) = InData%Marker1(i1) + DO i1 = LBOUND(InData%MemberIndx1,1), UBOUND(InData%MemberIndx1,1) + IntKiBuf(Int_Xferred) = InData%MemberIndx1(i1) Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%Marker2) ) THEN + IF ( .NOT. ALLOCATED(InData%MemberIndx2) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Marker2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Marker2,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberIndx2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberIndx2,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%Marker2,1), UBOUND(InData%Marker2,1) - IntKiBuf(Int_Xferred) = InData%Marker2(i1) + DO i1 = LBOUND(InData%MemberIndx2,1), UBOUND(InData%MemberIndx2,1) + IntKiBuf(Int_Xferred) = InData%MemberIndx2(i1) Int_Xferred = Int_Xferred + 1 END DO END IF @@ -4719,39 +5636,75 @@ SUBROUTINE Morison_UnPackMOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END IF OutData%MemberIDIndx = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Marker1 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MeshIndx1 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MeshIndx1)) DEALLOCATE(OutData%MeshIndx1) + ALLOCATE(OutData%MeshIndx1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MeshIndx1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MeshIndx1,1), UBOUND(OutData%MeshIndx1,1) + OutData%MeshIndx1(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MeshIndx2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MeshIndx2)) DEALLOCATE(OutData%MeshIndx2) + ALLOCATE(OutData%MeshIndx2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MeshIndx2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%MeshIndx2,1), UBOUND(OutData%MeshIndx2,1) + OutData%MeshIndx2(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberIndx1 not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Marker1)) DEALLOCATE(OutData%Marker1) - ALLOCATE(OutData%Marker1(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%MemberIndx1)) DEALLOCATE(OutData%MemberIndx1) + ALLOCATE(OutData%MemberIndx1(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Marker1.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MemberIndx1.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%Marker1,1), UBOUND(OutData%Marker1,1) - OutData%Marker1(i1) = IntKiBuf(Int_Xferred) + DO i1 = LBOUND(OutData%MemberIndx1,1), UBOUND(OutData%MemberIndx1,1) + OutData%MemberIndx1(i1) = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Marker2 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberIndx2 not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Marker2)) DEALLOCATE(OutData%Marker2) - ALLOCATE(OutData%Marker2(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%MemberIndx2)) DEALLOCATE(OutData%MemberIndx2) + ALLOCATE(OutData%MemberIndx2(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Marker2.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MemberIndx2.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%Marker2,1), UBOUND(OutData%Marker2,1) - OutData%Marker2(i1) = IntKiBuf(Int_Xferred) + DO i1 = LBOUND(OutData%MemberIndx2,1), UBOUND(OutData%MemberIndx2,1) + OutData%MemberIndx2(i1) = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END DO END IF @@ -7971,118 +8924,6 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcMiscData%F_D)) THEN - i1_l = LBOUND(SrcMiscData%F_D,1) - i1_u = UBOUND(SrcMiscData%F_D,1) - i2_l = LBOUND(SrcMiscData%F_D,2) - i2_u = UBOUND(SrcMiscData%F_D,2) - IF (.NOT. ALLOCATED(DstMiscData%F_D)) THEN - ALLOCATE(DstMiscData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_D = SrcMiscData%F_D -ENDIF -IF (ALLOCATED(SrcMiscData%F_I)) THEN - i1_l = LBOUND(SrcMiscData%F_I,1) - i1_u = UBOUND(SrcMiscData%F_I,1) - i2_l = LBOUND(SrcMiscData%F_I,2) - i2_u = UBOUND(SrcMiscData%F_I,2) - IF (.NOT. ALLOCATED(DstMiscData%F_I)) THEN - ALLOCATE(DstMiscData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_I = SrcMiscData%F_I -ENDIF -IF (ALLOCATED(SrcMiscData%F_A)) THEN - i1_l = LBOUND(SrcMiscData%F_A,1) - i1_u = UBOUND(SrcMiscData%F_A,1) - i2_l = LBOUND(SrcMiscData%F_A,2) - i2_u = UBOUND(SrcMiscData%F_A,2) - IF (.NOT. ALLOCATED(DstMiscData%F_A)) THEN - ALLOCATE(DstMiscData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_A.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_A = SrcMiscData%F_A -ENDIF -IF (ALLOCATED(SrcMiscData%F_B)) THEN - i1_l = LBOUND(SrcMiscData%F_B,1) - i1_u = UBOUND(SrcMiscData%F_B,1) - i2_l = LBOUND(SrcMiscData%F_B,2) - i2_u = UBOUND(SrcMiscData%F_B,2) - IF (.NOT. ALLOCATED(DstMiscData%F_B)) THEN - ALLOCATE(DstMiscData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_B.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_B = SrcMiscData%F_B -ENDIF -IF (ALLOCATED(SrcMiscData%F_BF)) THEN - i1_l = LBOUND(SrcMiscData%F_BF,1) - i1_u = UBOUND(SrcMiscData%F_BF,1) - i2_l = LBOUND(SrcMiscData%F_BF,2) - i2_u = UBOUND(SrcMiscData%F_BF,2) - IF (.NOT. ALLOCATED(DstMiscData%F_BF)) THEN - ALLOCATE(DstMiscData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_BF = SrcMiscData%F_BF -ENDIF -IF (ALLOCATED(SrcMiscData%F_If)) THEN - i1_l = LBOUND(SrcMiscData%F_If,1) - i1_u = UBOUND(SrcMiscData%F_If,1) - i2_l = LBOUND(SrcMiscData%F_If,2) - i2_u = UBOUND(SrcMiscData%F_If,2) - IF (.NOT. ALLOCATED(DstMiscData%F_If)) THEN - ALLOCATE(DstMiscData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_If.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_If = SrcMiscData%F_If -ENDIF -IF (ALLOCATED(SrcMiscData%F_WMG)) THEN - i1_l = LBOUND(SrcMiscData%F_WMG,1) - i1_u = UBOUND(SrcMiscData%F_WMG,1) - i2_l = LBOUND(SrcMiscData%F_WMG,2) - i2_u = UBOUND(SrcMiscData%F_WMG,2) - IF (.NOT. ALLOCATED(DstMiscData%F_WMG)) THEN - ALLOCATE(DstMiscData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_WMG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_WMG = SrcMiscData%F_WMG -ENDIF -IF (ALLOCATED(SrcMiscData%F_IMG)) THEN - i1_l = LBOUND(SrcMiscData%F_IMG,1) - i1_u = UBOUND(SrcMiscData%F_IMG,1) - i2_l = LBOUND(SrcMiscData%F_IMG,2) - i2_u = UBOUND(SrcMiscData%F_IMG,2) - IF (.NOT. ALLOCATED(DstMiscData%F_IMG)) THEN - ALLOCATE(DstMiscData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_IMG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_IMG = SrcMiscData%F_IMG -ENDIF IF (ALLOCATED(SrcMiscData%FV)) THEN i1_l = LBOUND(SrcMiscData%FV,1) i1_u = UBOUND(SrcMiscData%FV,1) @@ -8123,20 +8964,6 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg END IF DstMiscData%FDynP = SrcMiscData%FDynP ENDIF -IF (ALLOCATED(SrcMiscData%F_DP)) THEN - i1_l = LBOUND(SrcMiscData%F_DP,1) - i1_u = UBOUND(SrcMiscData%F_DP,1) - i2_l = LBOUND(SrcMiscData%F_DP,2) - i2_u = UBOUND(SrcMiscData%F_DP,2) - IF (.NOT. ALLOCATED(DstMiscData%F_DP)) THEN - ALLOCATE(DstMiscData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_DP.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%F_DP = SrcMiscData%F_DP -ENDIF IF (ALLOCATED(SrcMiscData%vrel)) THEN i1_l = LBOUND(SrcMiscData%vrel,1) i1_u = UBOUND(SrcMiscData%vrel,1) @@ -8161,7 +8988,23 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg RETURN END IF END IF - DstMiscData%nodeInWater = SrcMiscData%nodeInWater + DstMiscData%nodeInWater = SrcMiscData%nodeInWater +ENDIF +IF (ALLOCATED(SrcMiscData%memberLoads)) THEN + i1_l = LBOUND(SrcMiscData%memberLoads,1) + i1_u = UBOUND(SrcMiscData%memberLoads,1) + IF (.NOT. ALLOCATED(DstMiscData%memberLoads)) THEN + ALLOCATE(DstMiscData%memberLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%memberLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcMiscData%memberLoads,1), UBOUND(SrcMiscData%memberLoads,1) + CALL Morison_Copymemberloads( SrcMiscData%memberLoads(i1), DstMiscData%memberLoads(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO ENDIF IF (ALLOCATED(SrcMiscData%F_B_End)) THEN i1_l = LBOUND(SrcMiscData%F_B_End,1) @@ -8259,30 +9102,6 @@ SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(MiscData%F_D)) THEN - DEALLOCATE(MiscData%F_D) -ENDIF -IF (ALLOCATED(MiscData%F_I)) THEN - DEALLOCATE(MiscData%F_I) -ENDIF -IF (ALLOCATED(MiscData%F_A)) THEN - DEALLOCATE(MiscData%F_A) -ENDIF -IF (ALLOCATED(MiscData%F_B)) THEN - DEALLOCATE(MiscData%F_B) -ENDIF -IF (ALLOCATED(MiscData%F_BF)) THEN - DEALLOCATE(MiscData%F_BF) -ENDIF -IF (ALLOCATED(MiscData%F_If)) THEN - DEALLOCATE(MiscData%F_If) -ENDIF -IF (ALLOCATED(MiscData%F_WMG)) THEN - DEALLOCATE(MiscData%F_WMG) -ENDIF -IF (ALLOCATED(MiscData%F_IMG)) THEN - DEALLOCATE(MiscData%F_IMG) -ENDIF IF (ALLOCATED(MiscData%FV)) THEN DEALLOCATE(MiscData%FV) ENDIF @@ -8292,15 +9111,18 @@ SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%FDynP)) THEN DEALLOCATE(MiscData%FDynP) ENDIF -IF (ALLOCATED(MiscData%F_DP)) THEN - DEALLOCATE(MiscData%F_DP) -ENDIF IF (ALLOCATED(MiscData%vrel)) THEN DEALLOCATE(MiscData%vrel) ENDIF IF (ALLOCATED(MiscData%nodeInWater)) THEN DEALLOCATE(MiscData%nodeInWater) ENDIF +IF (ALLOCATED(MiscData%memberLoads)) THEN +DO i1 = LBOUND(MiscData%memberLoads,1), UBOUND(MiscData%memberLoads,1) + CALL Morison_Destroymemberloads( MiscData%memberLoads(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(MiscData%memberLoads) +ENDIF IF (ALLOCATED(MiscData%F_B_End)) THEN DEALLOCATE(MiscData%F_B_End) ENDIF @@ -8356,46 +9178,6 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! F_D allocated yes/no - IF ( ALLOCATED(InData%F_D) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_D upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_D) ! F_D - END IF - Int_BufSz = Int_BufSz + 1 ! F_I allocated yes/no - IF ( ALLOCATED(InData%F_I) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_I upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_I) ! F_I - END IF - Int_BufSz = Int_BufSz + 1 ! F_A allocated yes/no - IF ( ALLOCATED(InData%F_A) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_A upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_A) ! F_A - END IF - Int_BufSz = Int_BufSz + 1 ! F_B allocated yes/no - IF ( ALLOCATED(InData%F_B) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_B) ! F_B - END IF - Int_BufSz = Int_BufSz + 1 ! F_BF allocated yes/no - IF ( ALLOCATED(InData%F_BF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_BF upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_BF) ! F_BF - END IF - Int_BufSz = Int_BufSz + 1 ! F_If allocated yes/no - IF ( ALLOCATED(InData%F_If) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_If upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_If) ! F_If - END IF - Int_BufSz = Int_BufSz + 1 ! F_WMG allocated yes/no - IF ( ALLOCATED(InData%F_WMG) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_WMG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_WMG) ! F_WMG - END IF - Int_BufSz = Int_BufSz + 1 ! F_IMG allocated yes/no - IF ( ALLOCATED(InData%F_IMG) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_IMG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_IMG) ! F_IMG - END IF Int_BufSz = Int_BufSz + 1 ! FV allocated yes/no IF ( ALLOCATED(InData%FV) ) THEN Int_BufSz = Int_BufSz + 2*2 ! FV upper/lower bounds for each dimension @@ -8411,11 +9193,6 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*1 ! FDynP upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%FDynP) ! FDynP END IF - Int_BufSz = Int_BufSz + 1 ! F_DP allocated yes/no - IF ( ALLOCATED(InData%F_DP) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! F_DP upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F_DP) ! F_DP - END IF Int_BufSz = Int_BufSz + 1 ! vrel allocated yes/no IF ( ALLOCATED(InData%vrel) ) THEN Int_BufSz = Int_BufSz + 2*2 ! vrel upper/lower bounds for each dimension @@ -8426,6 +9203,30 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*1 ! nodeInWater upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater END IF + Int_BufSz = Int_BufSz + 1 ! memberLoads allocated yes/no + IF ( ALLOCATED(InData%memberLoads) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! memberLoads upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + DO i1 = LBOUND(InData%memberLoads,1), UBOUND(InData%memberLoads,1) + Int_BufSz = Int_BufSz + 3 ! memberLoads: size of buffers for each call to pack subtype + CALL Morison_Packmemberloads( Re_Buf, Db_Buf, Int_Buf, InData%memberLoads(i1), ErrStat2, ErrMsg2, .TRUE. ) ! memberLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! memberLoads + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! memberLoads + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! memberLoads + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF Int_BufSz = Int_BufSz + 1 ! F_B_End allocated yes/no IF ( ALLOCATED(InData%F_B_End) ) THEN Int_BufSz = Int_BufSz + 2*2 ! F_B_End upper/lower bounds for each dimension @@ -8462,188 +9263,28 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%F_D) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_D,2), UBOUND(InData%F_D,2) - DO i1 = LBOUND(InData%F_D,1), UBOUND(InData%F_D,1) - ReKiBuf(Re_Xferred) = InData%F_D(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_I) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_I,2), UBOUND(InData%F_I,2) - DO i1 = LBOUND(InData%F_I,1), UBOUND(InData%F_I,1) - ReKiBuf(Re_Xferred) = InData%F_I(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_A) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_A,2), UBOUND(InData%F_A,2) - DO i1 = LBOUND(InData%F_A,1), UBOUND(InData%F_A,1) - ReKiBuf(Re_Xferred) = InData%F_A(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_B) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_B,2), UBOUND(InData%F_B,2) - DO i1 = LBOUND(InData%F_B,1), UBOUND(InData%F_B,1) - ReKiBuf(Re_Xferred) = InData%F_B(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_BF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_BF,2), UBOUND(InData%F_BF,2) - DO i1 = LBOUND(InData%F_BF,1), UBOUND(InData%F_BF,1) - ReKiBuf(Re_Xferred) = InData%F_BF(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_If) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_If,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_If,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_If,2), UBOUND(InData%F_If,2) - DO i1 = LBOUND(InData%F_If,1), UBOUND(InData%F_If,1) - ReKiBuf(Re_Xferred) = InData%F_If(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_WMG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_WMG,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_WMG,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_WMG,2), UBOUND(InData%F_WMG,2) - DO i1 = LBOUND(InData%F_WMG,1), UBOUND(InData%F_WMG,1) - ReKiBuf(Re_Xferred) = InData%F_WMG(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_IMG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_IMG,2), UBOUND(InData%F_IMG,2) - DO i1 = LBOUND(InData%F_IMG,1), UBOUND(InData%F_IMG,1) - ReKiBuf(Re_Xferred) = InData%F_IMG(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( .NOT. ALLOCATED(InData%FV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8699,26 +9340,6 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%F_DP) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_DP,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_DP,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_DP,2), UBOUND(InData%F_DP,2) - DO i1 = LBOUND(InData%F_DP,1), UBOUND(InData%F_DP,1) - ReKiBuf(Re_Xferred) = InData%F_DP(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( .NOT. ALLOCATED(InData%vrel) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8754,342 +9375,199 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_B_End,2), UBOUND(InData%F_B_End,2) - DO i1 = LBOUND(InData%F_B_End,1), UBOUND(InData%F_B_End,1) - ReKiBuf(Re_Xferred) = InData%F_B_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_D_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_D_End,2), UBOUND(InData%F_D_End,2) - DO i1 = LBOUND(InData%F_D_End,1), UBOUND(InData%F_D_End,1) - ReKiBuf(Re_Xferred) = InData%F_D_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_I_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_I_End,2), UBOUND(InData%F_I_End,2) - DO i1 = LBOUND(InData%F_I_End,1), UBOUND(InData%F_I_End,1) - ReKiBuf(Re_Xferred) = InData%F_I_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_IMG_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_IMG_End,2), UBOUND(InData%F_IMG_End,2) - DO i1 = LBOUND(InData%F_IMG_End,1), UBOUND(InData%F_IMG_End,1) - ReKiBuf(Re_Xferred) = InData%F_IMG_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_A_End) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%F_A_End,2), UBOUND(InData%F_A_End,2) - DO i1 = LBOUND(InData%F_A_End,1), UBOUND(InData%F_A_End,1) - ReKiBuf(Re_Xferred) = InData%F_A_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%F_BF_End) ) THEN + IF ( .NOT. ALLOCATED(InData%memberLoads) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%memberLoads,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%memberLoads,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%F_BF_End,2), UBOUND(InData%F_BF_End,2) - DO i1 = LBOUND(InData%F_BF_End,1), UBOUND(InData%F_BF_End,1) - ReKiBuf(Re_Xferred) = InData%F_BF_End(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IntKiBuf(Int_Xferred) = InData%LastIndWave - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE Morison_PackMisc + DO i1 = LBOUND(InData%memberLoads,1), UBOUND(InData%memberLoads,1) + CALL Morison_Packmemberloads( Re_Buf, Db_Buf, Int_Buf, InData%memberLoads(i1), ErrStat2, ErrMsg2, OnlySize ) ! memberLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN - SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Morison_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_D not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_D)) DEALLOCATE(OutData%F_D) - ALLOCATE(OutData%F_D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_D,2), UBOUND(OutData%F_D,2) - DO i1 = LBOUND(OutData%F_D,1), UBOUND(OutData%F_D,1) - OutData%F_D(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_I not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_I)) DEALLOCATE(OutData%F_I) - ALLOCATE(OutData%F_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_I,2), UBOUND(OutData%F_I,2) - DO i1 = LBOUND(OutData%F_I,1), UBOUND(OutData%F_I,1) - OutData%F_I(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_A not allocated + IF ( .NOT. ALLOCATED(InData%F_B_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_B_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_B_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_A)) DEALLOCATE(OutData%F_A) - ALLOCATE(OutData%F_A(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_A.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_A,2), UBOUND(OutData%F_A,2) - DO i1 = LBOUND(OutData%F_A,1), UBOUND(OutData%F_A,1) - OutData%F_A(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_B_End,2), UBOUND(InData%F_B_End,2) + DO i1 = LBOUND(InData%F_B_End,1), UBOUND(InData%F_B_End,1) + ReKiBuf(Re_Xferred) = InData%F_B_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B not allocated + IF ( .NOT. ALLOCATED(InData%F_D_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_D_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_D_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_B)) DEALLOCATE(OutData%F_B) - ALLOCATE(OutData%F_B(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_B.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_B,2), UBOUND(OutData%F_B,2) - DO i1 = LBOUND(OutData%F_B,1), UBOUND(OutData%F_B,1) - OutData%F_B(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_D_End,2), UBOUND(InData%F_D_End,2) + DO i1 = LBOUND(InData%F_D_End,1), UBOUND(InData%F_D_End,1) + ReKiBuf(Re_Xferred) = InData%F_D_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_BF not allocated + IF ( .NOT. ALLOCATED(InData%F_I_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_I_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_I_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_BF)) DEALLOCATE(OutData%F_BF) - ALLOCATE(OutData%F_BF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_BF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_BF,2), UBOUND(OutData%F_BF,2) - DO i1 = LBOUND(OutData%F_BF,1), UBOUND(OutData%F_BF,1) - OutData%F_BF(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_I_End,2), UBOUND(InData%F_I_End,2) + DO i1 = LBOUND(InData%F_I_End,1), UBOUND(InData%F_I_End,1) + ReKiBuf(Re_Xferred) = InData%F_I_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_If not allocated + IF ( .NOT. ALLOCATED(InData%F_IMG_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_IMG_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_IMG_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_If)) DEALLOCATE(OutData%F_If) - ALLOCATE(OutData%F_If(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_If.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_If,2), UBOUND(OutData%F_If,2) - DO i1 = LBOUND(OutData%F_If,1), UBOUND(OutData%F_If,1) - OutData%F_If(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_IMG_End,2), UBOUND(InData%F_IMG_End,2) + DO i1 = LBOUND(InData%F_IMG_End,1), UBOUND(InData%F_IMG_End,1) + ReKiBuf(Re_Xferred) = InData%F_IMG_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_WMG not allocated + IF ( .NOT. ALLOCATED(InData%F_A_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_A_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_A_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_WMG)) DEALLOCATE(OutData%F_WMG) - ALLOCATE(OutData%F_WMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_WMG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_WMG,2), UBOUND(OutData%F_WMG,2) - DO i1 = LBOUND(OutData%F_WMG,1), UBOUND(OutData%F_WMG,1) - OutData%F_WMG(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_A_End,2), UBOUND(InData%F_A_End,2) + DO i1 = LBOUND(InData%F_A_End,1), UBOUND(InData%F_A_End,1) + ReKiBuf(Re_Xferred) = InData%F_A_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_IMG not allocated + IF ( .NOT. ALLOCATED(InData%F_BF_End) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_BF_End,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_BF_End,2) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_IMG)) DEALLOCATE(OutData%F_IMG) - ALLOCATE(OutData%F_IMG(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_IMG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_IMG,2), UBOUND(OutData%F_IMG,2) - DO i1 = LBOUND(OutData%F_IMG,1), UBOUND(OutData%F_IMG,1) - OutData%F_IMG(i1,i2) = ReKiBuf(Re_Xferred) + + DO i2 = LBOUND(InData%F_BF_End,2), UBOUND(InData%F_BF_End,2) + DO i1 = LBOUND(InData%F_BF_End,1), UBOUND(InData%F_BF_End,1) + ReKiBuf(Re_Xferred) = InData%F_BF_End(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO END IF + IntKiBuf(Int_Xferred) = InData%LastIndWave + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE Morison_PackMisc + + SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Morison_MiscVarType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'Morison_UnPackMisc' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FV not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9154,29 +9632,6 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_DP not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F_DP)) DEALLOCATE(OutData%F_DP) - ALLOCATE(OutData%F_DP(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_DP.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%F_DP,2), UBOUND(OutData%F_DP,2) - DO i1 = LBOUND(OutData%F_DP,1), UBOUND(OutData%F_DP,1) - OutData%F_DP(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! vrel not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9218,6 +9673,62 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Int_Xferred = Int_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! memberLoads not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%memberLoads)) DEALLOCATE(OutData%memberLoads) + ALLOCATE(OutData%memberLoads(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%memberLoads.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%memberLoads,1), UBOUND(OutData%memberLoads,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL Morison_Unpackmemberloads( Re_Buf, Db_Buf, Int_Buf, OutData%memberLoads(i1), ErrStat2, ErrMsg2 ) ! memberLoads + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_B_End not allocated Int_Xferred = Int_Xferred + 1 ELSE From 5d9449f779256721a161f8a744ddb6cdc0f81b13 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 23 Jul 2020 11:10:50 -0600 Subject: [PATCH 250/377] Linearization fixes and draft code Fixed indexing for HD meshes, added some initial SD-related linearization code --- modules/openfast-library/src/FAST_Lin.f90 | 62 ++++++++++++++++++-- modules/openfast-library/src/FAST_Solver.f90 | 18 +++--- modules/openfast-library/src/FAST_Subs.f90 | 2 +- modules/openfast-library/src/FAST_Types.f90 | 2 +- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 8054fb073..2d40b3b5c 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -109,8 +109,11 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_MAP end if - ! ExtPtfm is next, if activated: - if ( p_FAST%CompSub == Module_ExtPtfm ) then + ! SD or ExtPtfm is next, if activated: + if ( p_FAST%CompSub == Module_SD ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_SD + else if ( p_FAST%CompSub == Module_ExtPtfm ) then p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_ExtPtfm end if @@ -493,13 +496,17 @@ SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%SizeLin(LIN_INPUT_COL)) = .true. end if + if (p_FAST%CompSub == MODULE_SD) then + do j = 1,18 ! TODO TODO TODO + y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + else if (p_FAST%CompSub == MODULE_ExtPtfm) then !bjj: removed because I'm not sure these should be included in the "standard" inputs !!!! ExtPtfm standard inputs: x1, x1dot x1ddot ! TODO TODO TODO CHECK - !!!if (p_FAST%CompSub == MODULE_ExtPtfm) then !!! do j = 1,18 !!! y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. !!! end do - !!!end if + end if elseif(p_FAST%LinInputs == LIN_ALL) then do i = 1,p_FAST%Lin_NumMods @@ -1036,10 +1043,51 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, end if ! if ( p_FAST%LinOutMod ) end if ! if ( p_FAST%CompMooring == Module_MAP ) + + !..................... + ! SubDyn + !..................... + if ( p_FAST%CompSub == Module_SD ) then + ! get the jacobians + call SD_JacobianPInput( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & + SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, & + dYdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%B ) + if(Failed()) return; + + call SD_JacobianPContState( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & + SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2,& + dYdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%A ) + if(Failed()) return; + + ! get the operating point + call SD_GetOP(t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR),& + SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_u,& + y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_dx) + if(Failed()) return; + + ! write the module matrices: + if (p_FAST%LinOutMod) then + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) + if(Failed()) return; + + if (p_FAST%LinOutJac) then + ! Jacobians + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx') + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y) + call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) + end if + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1) ) + end if + !..................... ! ExtPtfm !..................... - if ( p_FAST%CompSub == Module_ExtPtfm ) then + elseif ( p_FAST%CompSub == Module_ExtPtfm ) then ! get the jacobians call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & @@ -1652,7 +1700,9 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF (p_FAST%CompSub == Module_ExtPtfm) THEN + IF (p_FAST%CompSub == Module_SD) THEN + write(*,*)'>>> FAST_LIN: Linear_SD_InputSolve_dy, TODO' + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN CALL WrScr('>>> FAST_LIN: Linear_ExtPtfm_InputSolve_du, TODO') ENDIF diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 32c2964a5..37b5bdb78 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -3057,7 +3057,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP + SD_LMesh%NNodes *6 ! SD inputs: 6 loads per node (size of SD input from HD) END IF - p_FAST%SizeJac_Opt1(4) = HD_M_Mesh%NNodes *6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + p_FAST%SizeJac_Opt1(4) = HD_M_Mesh%NNodes *6 & ! HD inputs: 6 accelerations per node (on each Morison mesh) + HD_WAMIT_Mesh%NNodes*6 ! HD inputs: 6 accelerations per node (on the WAMIT mesh) IF ( p_FAST%CompElast == Module_BD .and. BD_Solve_Option1) THEN @@ -3231,7 +3231,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP !(Mesh) do i=1,HD_WAMIT_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 13 !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 13 + MeshMapData%Jac_u_indx(index,1) = 11 !Module/Mesh/Field: u_HD%WAMITMesh%TranslationAcc = 11 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3240,7 +3240,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,HD_WAMIT_Mesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 14 !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 14 + MeshMapData%Jac_u_indx(index,1) = 12 !Module/Mesh/Field: u_HD%WAMITMesh%RotationAcc = 12 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3257,7 +3257,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,u_BD(k)%RootMotion%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 13 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%TranslationAcc = 15 (k=1), 17 (k=2), 19 (k=3) + MeshMapData%Jac_u_indx(index,1) = 11 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%TranslationAcc = 13 (k=1), 15 (k=2), 17 (k=3) MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3266,7 +3266,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,u_BD(k)%RootMotion%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 14 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%RotationAcc = 16 (k=1), 18 (k=2), 20 (k=3) + MeshMapData%Jac_u_indx(index,1) = 12 + 2*k !Module/Mesh/Field: u_BD(k)%RootMotion%RotationAcc = 14 (k=1), 16 (k=2), 18 (k=3) MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3284,7 +3284,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP ! Orca_PtfmMesh do i=1,Orca_PtfmMesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 21 !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 21 + MeshMapData%Jac_u_indx(index,1) = 19 !Module/Mesh/Field: u_Orca%PtfmMesh%TranslationAcc = 19 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3293,7 +3293,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,Orca_PtfmMesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 22 !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 22 + MeshMapData%Jac_u_indx(index,1) = 20 !Module/Mesh/Field: u_Orca%PtfmMesh%RotationAcc = 20 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3307,7 +3307,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP ! ExtPtfm_PtfmMesh do i=1,ExtPtfm_PtfmMesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 23 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 23 + MeshMapData%Jac_u_indx(index,1) = 21 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%TranslationAcc = 21 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -3316,7 +3316,7 @@ SUBROUTINE Init_FullOpt1_Jacobian( p_FAST, MeshMapData, ED_PlatformPtMesh, SD_TP do i=1,ExtPtfm_PtfmMesh%NNodes do j=1,3 - MeshMapData%Jac_u_indx(index,1) = 24 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 24 + MeshMapData%Jac_u_indx(index,1) = 22 !Module/Mesh/Field: u_ExtPtfm%PtfmMesh%RotationAcc = 22 MeshMapData%Jac_u_indx(index,2) = j !index: j MeshMapData%Jac_u_indx(index,3) = i !Node: i index = index + 1 diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 48c2fb3ef..20c05c8c1 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -1678,7 +1678,7 @@ SUBROUTINE ValidateInputData(p, m_FAST, ErrStat, ErrMsg) if (p%CompInflow == MODULE_OpFM) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the OpenFOAM coupling.',ErrStat, ErrMsg, RoutineName) if (p%CompAero == MODULE_AD14) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the AeroDyn v14 module.',ErrStat, ErrMsg, RoutineName) !if (p%CompSub == MODULE_SD) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the SubDyn module.',ErrStat, ErrMsg, RoutineName) - if (p%CompSub /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the any of the substructure modules.',ErrStat, ErrMsg, RoutineName) + if (p%CompSub /= MODULE_None .and. p%CompMooring /= MODULE_SD ) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the ExtPtfm_MCKF substructure module.',ErrStat, ErrMsg, RoutineName) if (p%CompMooring /= MODULE_None .and. p%CompMooring /= MODULE_MAP) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the FEAMooring or MoorDyn mooring modules.',ErrStat, ErrMsg, RoutineName) if (p%CompIce /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for any of the ice loading modules.',ErrStat, ErrMsg, RoutineName) diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index 527b8e09b..25f0904f7 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -40698,7 +40698,7 @@ SUBROUTINE FAST_UnPackExternInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS END SUBROUTINE FAST_UnPackExternInputType SUBROUTINE FAST_CopyInitData( SrcInitDataData, DstInitDataData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FAST_InitData), INTENT(INOUT) :: SrcInitDataData + TYPE(FAST_InitData), INTENT(IN) :: SrcInitDataData TYPE(FAST_InitData), INTENT(INOUT) :: DstInitDataData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat From e7517d183aa3c0a507c00db0be05d38f3382b20b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 27 Jul 2020 14:32:37 -0600 Subject: [PATCH 251/377] FlexSub: removed files added by mistake --- modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src_soildyn/FEM.f90 | 1215 -- modules/subdyn/src_soildyn/IntegerList.f90 | 459 - modules/subdyn/src_soildyn/SD_FEM.f90 | 1897 --- modules/subdyn/src_soildyn/SubDyn.f90 | 2885 ---- modules/subdyn/src_soildyn/SubDyn_Driver.f90 | 342 - modules/subdyn/src_soildyn/SubDyn_Output.f90 | 804 -- .../src_soildyn/SubDyn_Output_Params.f90 | 3723 ----- .../subdyn/src_soildyn/SubDyn_Registry.txt | 269 - modules/subdyn/src_soildyn/SubDyn_Tests.f90 | 440 - modules/subdyn/src_soildyn/SubDyn_Types.f90 | 11876 ---------------- modules/subdyn/src_soildyn/Yaml.f90 | 609 - modules/subdyn/src_soildyn/qsort_c_module.f90 | 61 - 13 files changed, 1 insertion(+), 24581 deletions(-) delete mode 100644 modules/subdyn/src_soildyn/FEM.f90 delete mode 100644 modules/subdyn/src_soildyn/IntegerList.f90 delete mode 100644 modules/subdyn/src_soildyn/SD_FEM.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Driver.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Output.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Registry.txt delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Tests.f90 delete mode 100644 modules/subdyn/src_soildyn/SubDyn_Types.f90 delete mode 100644 modules/subdyn/src_soildyn/Yaml.f90 delete mode 100644 modules/subdyn/src_soildyn/qsort_c_module.f90 diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 3fca9d628..282443dc5 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -35,7 +35,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) - INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) + INTEGER(IntKi), PARAMETER :: PropSetsCCol = 5 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0, CtrlChannel) INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) INTEGER(IntKi), PARAMETER :: CMassCol = 11 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ, Optional:JMXY,JMXZ,JMYZ,CGX,CGY,CGZ) diff --git a/modules/subdyn/src_soildyn/FEM.f90 b/modules/subdyn/src_soildyn/FEM.f90 deleted file mode 100644 index d96fac91e..000000000 --- a/modules/subdyn/src_soildyn/FEM.f90 +++ /dev/null @@ -1,1215 +0,0 @@ -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -!********************************************************************************************************************************** -!> Standalone tools for beam-based finite element method (FEM) -!! No dependency with SubDyn types and representation -MODULE FEM - USE NWTC_Library - IMPLICIT NONE - - INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors - -CONTAINS -!------------------------------------------------------------------------------------------------------ -!> Return eigenvalues, Omega, and eigenvectors -SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) - USE NWTC_LAPACK, only: LAPACK_ggev - USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT - INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K - REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix - REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix - LOGICAL, INTENT(IN ) :: bCheckSingularity !< If True, check for singularities - REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors - REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! LOCALS - REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables - INTEGER :: i - INTEGER :: LWORK !variables for the eigensolver - INTEGER, ALLOCATABLE :: KEY(:) - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = '' - - ! allocate working arrays and return arrays for the eigensolver - LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine - !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out - CALL AllocAry( Work, LWORK, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAR, N, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAI, N, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( BETA, N, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( VL, N, N, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( KEY, N, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return - - ! --- Eigenvalue analysis - ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. - ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 - ! bjj: This comes from the LAPACK documentation: - ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. - ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less - ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). - ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted - CALL LAPACK_ggev('N','V',N ,K, M, ALPHAR, ALPHAI, BETA, VL, EigVect, WORK, LWORK, ErrStat2, ErrMsg2) - if(Failed()) return - - ! --- Determinign and sorting eigen frequencies - DO I=1,N !Initialize the key and calculate Omega - KEY(I)=I - IF ( AlphaR(I)<0.0_LAKi ) THEN - !print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif - !ELSE IF ( .not.EqualRealNos(AlphaI(I),0.0_LAKi )) THEN - ! print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) - ! ErrStat2=ErrID_Fatal - ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' - ! if(Failed()) return - ELSE IF ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) THEN - Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif - ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_ReKi) ) THEN - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' - if(Failed()) return - endif - ELSE - Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) - END IF - ENDDO - ! Sorting - CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return - - ! --- Sorting eigen vectors - ! KEEP ME: scaling of the eigenvectors using generalized mass =identity criterion - ! ALLOCATE(normcoeff(N,N), STAT = ErrStat ) - ! result1 = matmul(M,EigVect) - ! result2 = matmul(transpose(EigVect),result1) - ! normcoeff=sqrt(result2) !This should be a diagonal matrix which contains the normalization factors - ! normcoeff=sqrt(matmul(transpose(EigVect),matmul(M,EigVect))) !This should be a diagonal matrix which contains the normalization factors - VL=EigVect !temporary storage for sorting EigVect - DO I=1,N - !EigVect(:,I)=VL(:,KEY(I))/normcoeff(KEY(I),KEY(I)) !reordered and normalized - EigVect(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one - ENDDO - !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! - CALL CleanupEigen() - RETURN - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolve') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUpEigen() - END FUNCTION Failed - - SUBROUTINE CleanupEigen() - IF (ALLOCATED(Work) ) DEALLOCATE(Work) - IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) - IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) - IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) - IF (ALLOCATED(VL) ) DEALLOCATE(VL) - IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) - END SUBROUTINE CleanupEigen - -END SUBROUTINE EigenSolve - -!> Compute the determinant of a real matrix using an LU factorization -FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) - use NWTC_LAPACK, only: LAPACK_GETRF - REAL(LaKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - real(LaKi) :: det !< May easily overflow - integer(IntKi) :: i - integer :: n - integer, allocatable :: ipiv(:) - real(LaKi), allocatable :: PLU(:,:) - real(LaKi) :: ScaleVal - - n = size(A(1,:)) - allocate(PLU(n,n)) - allocate(ipiv(n)) - ScaleVal= 1.0_LaKi - PLU = A/ScaleVal - ! general matrix factorization: Factor matrix into A=PLU. - call LAPACK_GETRF( n, n, PLU, ipiv, ErrStat, ErrMsg ) !call dgetrf(n, n, PLU, n, ipiv, info) - if (ErrStat==ErrID_Fatal) then - print*,'Error in getrf' - det = 0 - deallocate(PLU) - deallocate(ipiv) - return - endif - ! PLU now contains the LU of the factorization A = PLU - ! As L has unit diagonal entries, the determinant can be computed - ! from the product of U's diagonal entries. Additional sign changes - ! stemming from the permutations P have to be taken into account as well. - det = 1.0_LaKi - do i = 1,n - if(ipiv(i) /= i) then ! additional sign change - det = -det*PLU(i,i) - else - det = det*PLU(i,i) - endif - end do - deallocate(PLU) - deallocate(ipiv) - IF ( EqualRealNos(real(det, ReKi), 0.0_ReKi) ) THEN - print*,'Det is zero' - return - else - det = det*(ScaleVal**n) - endif -END FUNCTION Determinant -!------------------------------------------------------------------------------------------------------ -!> Partition matrices and vectors into Boundary (R) and internal (L) nodes -!! M = [ MRR, MRL ] -!! [ sym, MLL ] -!! MRR = M(IDR, IDR), KRR = M(IDR, IDR), FR = F(IDR) -!! MLL = M(IDL, IDL), KRR = K(IDL, IDL), FL = F(IDL) -!! MRL = M(IDR, IDL), KRR = K(IDR, IDL) -!! NOTE: generic code -SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) - REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix - REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix - INTEGER(IntKi), INTENT(IN ) :: nR - INTEGER(IntKi), INTENT(IN ) :: nL - INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs - INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs - REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) - REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) - REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) - INTEGER(IntKi) :: I, J, II, JJ - - ! RR: Leader/Boundary DOFs - DO I = 1, nR - II = IDR(I) - DO J = 1, nR - JJ = IDR(J) - MRR(I, J) = MM(II, JJ) - KRR(I, J) = KK(II, JJ) - ENDDO - ENDDO - ! LL: Interior/follower DOFs - DO I = 1, nL - II = IDL(I) - DO J = 1, nL - JJ = IDL(J) - MLL(I, J) = MM(II, JJ) - KLL(I, J) = KK(II, JJ) - ENDDO - ENDDO - ! RL: cross terms - DO I = 1, nR - II = IDR(I) - DO J = 1, nL - JJ = IDL(J) - MRL(I, J) = MM(II, JJ) - KRL(I, J) = KK(II, JJ) - ENDDO - ENDDO - ! Forces - if (present(FG)) then - if (present(FGR)) then - do I = 1, nR - II = IDR(I) - FGR(I) = FG(II) - enddo - endif - if (present(FGL)) then - do I = 1, nL - II = IDL(I) - FGL(I) = FG(II) - enddo - endif - endif -END SUBROUTINE BreakSysMtrx - -!------------------------------------------------------------------------------------------------------ -!> Performs Craig-Bampton reduction of M and K matrices and optional Force vector -!! TODO: (Damping optional) -!! Convention is: -!! "R": leader DOF -> "B": reduced leader DOF -!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) -!! NOTE: -!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned -!! - Possibility to get more CB modes using the input nM_Out>nM -!! -!! NOTE: generic code -SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM) - REAL(ReKi), INTENT(IN ) :: MM(:, :) !< Mass matrix - REAL(ReKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix - INTEGER(IntKi), INTENT(IN ) :: nR - INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs - INTEGER(IntKi), INTENT(IN ) :: nL - INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs - INTEGER(IntKi), INTENT(IN ) :: nM !< Number of CB modes - INTEGER(IntKi), INTENT(IN ) :: nM_Out !< Number of modes returned for PhiL & OmegaL - REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) !< Reduced Guyan Mass Matrix - REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) !< Reduced Guyan Stiffness matrix - REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) !< Cross term - REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes - REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_out) !< Craig-Bampton modes - REAL(ReKi), INTENT( OUT) :: OmegaL(nM_out) !< Eigenvalues - REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector (typically a constant force, like gravity) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) !< Force vector partitioned for R DOFs (TODO remove me) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' - ! Partitioned variables - real(ReKi), allocatable :: MRR(:, :) - real(ReKi), allocatable :: MLL(:, :) - real(ReKi), allocatable :: MRL(:, :) - real(ReKi), allocatable :: KRR(:, :) - real(ReKi), allocatable :: KLL(:, :) - real(ReKi), allocatable :: KRL(:, :) - ! --- Break system - CALL AllocAry(MRR, nR, nR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(MLL, nL, nL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(MRL, nR, nL, 'matrix MRL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(KRR, nR, nR, 'matrix KRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(KLL, nL, nL, 'matrix KLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry(KRL, nR, nL, 'matrix KRL', ErrStat2, ErrMsg2 ); if(Failed()) return - if (present(FG).and.present(FGR).and.present(FGL)) then - call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL) - else - call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL) - endif - ! --- CB reduction - call CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& !< Inputs - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) !< Outputs - if(Failed()) return - - ! --- Reduction of force if provided - if (present(FG).and.present(FGR).and.present(FGL)) then - if (present(FGM)) then - FGB = FGR + matmul( transpose(PhiR), FGL) - endif - if (present(FGB)) then - FGM = matmul( FGL, PhiL(:,1:nM) ) != matmul( transpose(PhiM), FGL ) because FGL is 1-D - endif - endif - call CleanUp() - -contains - logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - end function Failed - subroutine CleanUp() - IF(ALLOCATED(MRR) ) DEALLOCATE(MRR) - IF(ALLOCATED(MLL) ) DEALLOCATE(MLL) - IF(ALLOCATED(MRL) ) DEALLOCATE(MRL) - IF(ALLOCATED(KRR) ) DEALLOCATE(KRR) - IF(ALLOCATED(KLL) ) DEALLOCATE(KLL) - IF(ALLOCATED(KRL) ) DEALLOCATE(KRL) - end subroutine -END SUBROUTINE CraigBamptonReduction - -!------------------------------------------------------------------------------------------------------ -!> Performs Craig-Bampton reduction based on partitioned matrices M and K -!! Convention is: -!! "R": leader DOF -> "B": reduced leader DOF -!! "L": interior DOF -> "M": reduced interior DOF (CB-modes) -!! NOTE: -!! - M_MM = Identity and K_MM = Omega*2 hence these matrices are not returned -!! - Possibility to get more CB modes using the input nM_Out>nM (e.g. for static improvement) -!! -!! NOTE: generic code -SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg) - USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf - INTEGER(IntKi), INTENT( in) :: nR - INTEGER(IntKi), INTENT( in) :: nL - INTEGER(IntKi), INTENT( in) :: nM_Out - INTEGER(IntKi), INTENT( in) :: nM - REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Paritioned matrices - REAL(ReKi), INTENT( IN) :: MLL( nL, nL) - REAL(ReKi), INTENT( IN) :: MRL( nR, nL) - REAL(ReKi), INTENT( IN) :: KRR( nR, nR) - REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) - REAL(ReKi), INTENT( IN) :: KRL( nR, nL) - REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) - REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) - REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) - REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes - REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes - REAL(ReKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! LOCAL VARIABLES - REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(nR,nL) = transpose of PhiR * MLL (temporary storage) - INTEGER :: I !counter - INTEGER :: ipiv(nL) ! length min(m,n) (See LAPACK documentation) - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' - ErrStat = ErrID_None - ErrMsg = '' - - if (nM_out>nL) then - ErrMsg2='Cannot request more modes than internal degrees of Freedom'; ErrStat2=ErrID_Fatal; - if(Failed()) return; - endif - if (nM_out 0 ) then - ! bCheckSingularity = True - CALL EigenSolveWrap(KLL, MLL, nL, nM_out, .True., PhiL(:,1:nM_out), OmegaL(1:nM_out), ErrStat2, ErrMsg2); if(Failed()) return - ! --- Normalize PhiL - ! bjj: break up this equation to avoid as many temporary variables on the stack - ! MU = MATMUL ( MATMUL( TRANSPOSE(PhiL), MLL ), PhiL ) - CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return - CALL AllocAry( MU , nM_out, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return - MU = TRANSPOSE(PhiL) - Temp = MATMUL( MU, MLL ) - MU(1:nM_Out,1:nM_Out) = MATMUL( Temp, PhiL ) - DEALLOCATE(Temp) - ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) - DO I = 1, nM_out - PhiL(:,I) = PhiL(:,I) / SQRT( MU(I, I) ) - ENDDO - DEALLOCATE(MU) - else - PhiL = 0.0_ReKi - OmegaL = 0.0_ReKi - end if - - if (nL>0) then - ! --- Compute Guyan Modes (PhiR) - ! factor KLL to compute PhiR: KLL*PhiR=-TRANSPOSE(KRL) - ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** - CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return - - PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) - CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return - - ! --- Set MBB, MBM, and KBB from Eq. 4: - CALL AllocAry( PhiR_T_MLL, nR, nL, 'PhiR_T_MLL', ErrStat2, ErrMsg2); if(Failed()) return - - PhiR_T_MLL = TRANSPOSE(PhiR) - PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) - MBB = MATMUL(MRL, PhiR) - MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) - - IF ( nM == 0) THEN - MBM = 0.0_ReKi - ELSE - MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation - MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM - ENDIF - - KBB = MATMUL(KRL, PhiR) - KBB = KBB + KRR - else - PhiR(1:nL,1:nR) = 0.0_ReKi ! Empty - MBM (1:nR,1:nM) = 0.0_ReKi ! Empty - MBB = MRR - KBB = KRR - endif - - call CleanUp() -CONTAINS - - logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CraigBamptonReduction_FromPartition') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - end function Failed - - subroutine CleanUp() - if (allocated(Mu )) DEALLOCATE(Mu ) - if (allocated(Temp )) DEALLOCATE(Temp ) - if (allocated(PhiR_T_MLL)) DEALLOCATE(PhiR_T_MLL) - end subroutine -END SUBROUTINE CraigBamptonReduction_FromPartition - -!------------------------------------------------------------------------------------------------------ -!> Wrapper function for eigen value analyses, for two cases: -!! Case1: K and M are taken "as is", this is used for the "LL" part of the matrix -!! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system -SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) - INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system - REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix - REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix - INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues - LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present - REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors - REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) - - ! LOCALS - REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) - REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) - REAL(ReKi) :: Om2 - INTEGER(IntKi) :: N, i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = '' - - ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi - if (present(bDOF)) then - ! Remove unwanted DOFs - call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return - else - N=size(K,1) - CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - K_LaKi = real( K, LaKi ) - M_LaKi = real( M, LaKi ) - endif - N=size(K_LaKi,1) - - ! Note: NOmega must be <= N, which is the length of Omega2, Phi! - if ( NOmega > nDOF ) then - CALL SetErrStat(ErrID_Fatal,"NOmega must be less than or equal to N",ErrStat,ErrMsg,'EigenSolveWrap') - CALL CleanupEigen() - return - end if - - - ! --- Eigenvalue analysis - CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; - - ! --- Setting up Phi, and type conversion - do i = 1, NOmega - if (abs(Omega2_LaKi(i))>huge(1.0_ReKi)) then - Om2 = huge(1.0_ReKi) * sign(1.0_LaKi, Omega2_LaKi(i)) - else - Om2 = real(Omega2_LaKi(i), ReKi) - endif - if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics - Omega(i)=0.0_ReKi - elseif (Om2>0) then - Omega(i)=sqrt(Om2) ! was getting floating invalid - else - print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 - Omega(i)= 0.0_ReKi - endif - enddo - if (present(bDOF)) then - ! Insert 0s where bDOF was false - CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return - else - EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors - endif - CALL CleanupEigen() - return -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'EigenSolveWrap') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUpEigen() - END FUNCTION Failed - - SUBROUTINE CleanupEigen() - IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) - IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) - IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) - IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) - END SUBROUTINE CleanupEigen - -END SUBROUTINE EigenSolveWrap -!------------------------------------------------------------------------------------------------------ -!> Remove degrees of freedom from a matrix (lines and rows) -SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) - REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix - logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER :: I, J ! counters into full matrix - INTEGER :: Ir, Jr ! counters into reduced matrix - INTEGER :: nr ! number of reduced DOF - ErrStat = ErrID_None - ErrMsg = '' - - nr= count(bDOF) - CALL AllocAry(Ared, nr, nr, 'Ared', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return - - ! Remove rows and columns from A when bDOF is - Jr=0 - do J = 1, size(A,1) - if (bDOF(J)) then - Jr=Jr+1 - Ir=0 - do I = 1, size(A,1) - if (bDOF(I)) then - Ir=Ir+1 - Ared(Ir, Jr) = REAL( A(I, J), LAKi ) - end if - end do - endif - end do -END SUBROUTINE RemoveDOF - -!> Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) -SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) - REAL(LAKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix - logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(ReKi), INTENT(IN ) :: DefaultVal ! Default value to fill the - REAL(ReKi) , INTENT(INOUT) :: A(:,:) ! Full matrix - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - INTEGER :: I ! counter into full matrix - INTEGER :: Ir ! counter into reduced matrix - INTEGER :: n ! number of DOF (fullsystem) - ErrStat = ErrID_None - ErrMsg = '' - n= size(bDOF) - IF ( size(Ared,1) > n) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'InsertDOFrows: Number of reduced rows needs to be lower than full system rows' - RETURN - END IF - IF ( size(Ared,2) /= size(A,2) ) THEN - ErrStat = ErrID_Fatal - ErrMsg = 'InsertDOFrows: Inconsistent number of columns between A and Ared' - RETURN - END IF - !CALL AllocAry(A, n, size(Ared,2), 'A', ErrStat, ErrMsg ); if (ErrStat >= AbortErrLev) return - - ! Use rows from Ared when bDOF is true, use default value otherwise - ir=0 ! initialize - do i=1,n - if (bDOF(i)) then - ir =ir +1 - A(i,:)=real( Ared(ir,:), ReKi ) - else - A(i,:)=DefaultVal - endif - enddo -END SUBROUTINE InsertDOFrows -!------------------------------------------------------------------------------------------------------ -!> Returns index of val in Array (val is an integer!) -! NOTE: in the future use intrinsinc function findloc -FUNCTION FINDLOCI_ReKi(Array, Val) result(i) - real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == NINT(Array(i)) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 -END FUNCTION -!> Returns index of val in Array (val is an integer!) -! NOTE: in the future use intrinsinc function findloc -FUNCTION FINDLOCI_IntKi(Array, Val) result(i) - integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == Array(i) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 -END FUNCTION -!------------------------------------------------------------------------------------------------------ -SUBROUTINE RigidTransformationLine(dx,dy,dz,iLine,Line) - real(ReKi), INTENT(IN) :: dx,dy,dz - integer(IntKi) , INTENT(IN) :: iLine - Real(ReKi), dimension(6), INTENT(OUT) :: Line - SELECT CASE (iLine) - CASE (1); Line = (/1.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, dz, -dy/) - CASE (2); Line = (/0.0_ReKi, 1.0_ReKi, 0.0_ReKi, -dz, 0.0_ReKi, dx/) - CASE (3); Line = (/0.0_ReKi, 0.0_ReKi, 1.0_ReKi, dy, -dx, 0.0_ReKi/) - CASE (4); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi, 0.0_ReKi/) - CASE (5); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi, 0.0_ReKi/) - CASE (6); Line = (/0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 0.0_ReKi, 1.0_ReKi/) - CASE DEFAULT - Line=-99999999_ReKi - print*,'Error in RigidTransformationLine' - STOP -! ErrStat = ErrID_Fatal -! ErrMsg = 'Error calculating transformation matrix TI ' -! return - END SELECT -END SUBROUTINE -!------------------------------------------------------------------------------------------------------ -!> Rigid transformation matrix between DOFs of node j and k where node j is the leader node. -SUBROUTINE GetRigidTransformation(Pj, Pk, TRigid, ErrStat, ErrMsg) - REAL(ReKi), INTENT(IN ) :: Pj(3) ! (x,y,z) positions of leader node - REAL(ReKi), INTENT(IN ) :: Pk(3) ! (x,y,z) positions of follower node - REAL(ReKi), INTENT( OUT) :: TRigid(6,6) ! Transformation matrix such that xk = T.xj - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local - !REAL(ReKi) :: L ! length of element - !REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrix - !REAL(ReKi) :: R0(3,3) - integer(IntKi) :: I - ErrStat = ErrID_None - ErrMsg = "" - - ! --- Formulation using Delta of Global coordinates - Trigid=0; do I = 1,6; Trigid(I,I) = 1; enddo - Trigid ( 1, 5 ) = (Pk(3) - Pj(3)) - Trigid ( 1, 6 ) = -(Pk(2) - Pj(2)) - Trigid ( 2, 4 ) = -(Pk(3) - Pj(3)) - Trigid ( 2, 6 ) = (Pk(1) - Pj(1)) - Trigid ( 3, 4 ) = (Pk(2) - Pj(2)) - Trigid ( 3, 5 ) = -(Pk(1) - Pj(1)) - - ! --- Formulation bty transforming the "local" matrix into a global one - !call GetDirCos(Pj, Pk, R0, L, ErrStat, ErrMsg) - !TRigid = 0 ; do I = 1,6; TRigid(I,I) = 1; enddo - !TRigid (1, 5) = L - !TRigid (2, 4) = -L - !TRigid(1:3,4:6) = matmul( R0 , matmul(TRigid(1:3,4:6), transpose(R0)) ) - - ! --- Formulation using L and Rotation matrix - !TRigid = 0; do I = 1,6; TRigid(I,I) = 1; enddo - !TRigid ( 1, 5 ) = L*R0(3,3) - !TRigid ( 1, 6 ) = -L*R0(2,3) - !TRigid ( 2, 4 ) = -L*R0(3,3) - !TRigid ( 2, 6 ) = L*R0(1,3) - !TRigid ( 3, 4 ) = L*R0(2,3) - !TRigid ( 3, 5 ) = -L*R0(1,3) -END SUBROUTINE GetRigidTransformation -!------------------------------------------------------------------------------------------------------ -!> Computes directional cosine matrix DirCos -!! Transforms from element to global coordinates: xg = DC.xe, Kg = DC.Ke.DC^t -!! Assumes that the element main direction is along ze. -!! -!! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix -!! in the FAST framework. -SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) - REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element - REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix - REAL(ReKi) , INTENT( OUT) :: L ! length of element - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: Dx, Dy, Dz, Dxy ! distances between nodes - ErrMsg = "" - ErrStat = ErrID_None - - Dx=P2(1)-P1(1) - Dy=P2(2)-P1(2) - Dz=P2(3)-P1(3) - Dxy = sqrt( Dx**2 + Dy**2 ) - L = sqrt( Dx**2 + Dy**2 + Dz**2) - - IF ( EqualRealNos(L, 0.0_ReKi) ) THEN - ErrMsg = ' Same starting and ending location in the element.' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - IF ( EqualRealNos(Dxy, 0.0_ReKi) ) THEN - DirCos=0.0_ReKi ! whole matrix set to 0 - IF ( Dz < 0) THEN !x is kept along global x - DirCos(1, 1) = 1.0_ReKi - DirCos(2, 2) = -1.0_ReKi - DirCos(3, 3) = -1.0_ReKi - ELSE - DirCos(1, 1) = 1.0_ReKi - DirCos(2, 2) = 1.0_ReKi - DirCos(3, 3) = 1.0_ReKi - ENDIF - ELSE - DirCos(1, 1) = Dy/Dxy - DirCos(1, 2) = +Dx*Dz/(L*Dxy) - DirCos(1, 3) = Dx/L - - DirCos(2, 1) = -Dx/Dxy - DirCos(2, 2) = +Dz*Dy/(L*Dxy) - DirCos(2, 3) = Dy/L - - DirCos(3, 1) = 0.0_ReKi - DirCos(3, 2) = -Dxy/L - DirCos(3, 3) = +Dz/L - ENDIF - -END SUBROUTINE GetDirCos -!------------------------------------------------------------------------------------------------------ -!> Returns two vectors orthonormal to the input vector -SUBROUTINE GetOrthVectors(e1, e2, e3, ErrStat, ErrMsg) - real(ReKi) , intent(in ) :: e1(3) !< - real(ReKi) , intent( out) :: e2(3) !< - real(ReKi) , intent( out) :: e3(3) !< - integer(IntKi), intent( out) :: ErrStat ! error status of the operation - character(*), intent( out) :: ErrMsg ! error message if errstat /= errid_none - real(ReKi) :: min_norm - real(ReKi) :: e2_norm - real(ReKi) :: e1b(3) - ErrMsg = "" - ErrStat = ErrID_None - - min_norm = min( abs(e1(1)), abs(e1(2)), abs(e1(3)) ) - ! Finding a good candidate for orthogonality - if (min_norm == abs(e1(1))) then; e2 = (/ 0._ReKi, -e1(3), e1(2) /) - else if (min_norm == abs(e1(2))) then; e2 = (/ e1(3) , 0._ReKi, -e1(1) /) - else if (min_norm == abs(e1(3))) then; e2 = (/-e1(2) , e1(1), 0._ReKi /) - endif - ! Normalizing - e2_norm=sqrt(e2(1)**2 + e2(2)**2 + e2(3)**2) - if (abs(e2_norm)<1e-8) then - ErrStat=ErrID_Fatal - ErrMsg='Failed to determine orthogonal vector' - e2=-99999._ReKi - e3=-99999._ReKi - return - endif - e2 = e2/e2_norm - e1b= e1/sqrt(e1(1)**2 + e1(2)**2 + e1(3)**2) - ! Third - e3 = cross_product(e1b,e2) -END SUBROUTINE GetOrthVectors -!------------------------------------------------------------------------------------------------------ -!> Element stiffness matrix for classical beam elements -!! shear is true -- non-tapered Timoshenko beam -!! shear is false -- non-tapered Euler-Bernoulli beam -SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - LOGICAL , INTENT( IN) :: Shear - REAL(ReKi), INTENT(OUT) :: K(12, 12) - ! Local variables - REAL(ReKi) :: Ax, Ay, Kx, Ky - REAL(ReKi) :: DC(12, 12) - - Ax = kappa*A - Ay = kappa*A - - K(1:12,1:12) = 0 - - IF (Shear) THEN - Kx = 12.0*E*Iyy / (G*Ax*L*L) - Ky = 12.0*E*Ixx / (G*Ay*L*L) - ELSE - Kx = 0.0 - Ky = 0.0 - ENDIF - - K( 9, 9) = E*A/L - K( 7, 7) = 12.0*E*Iyy/( L*L*L*(1.0 + Kx) ) - K( 8, 8) = 12.0*E*Ixx/( L*L*L*(1.0 + Ky) ) - K(12, 12) = G*Jzz/L - K(10, 10) = (4.0 + Ky)*E*Ixx / ( L*(1.0+Ky) ) - K(11, 11) = (4.0 + Kx)*E*Iyy / ( L*(1.0+Kx) ) - K( 2, 4) = -6.*E*Ixx / ( L*L*(1.0+Ky) ) - K( 1, 5) = 6.*E*Iyy / ( L*L*(1.0+Kx) ) - K( 4, 10) = (2.0-Ky)*E*Ixx / ( L*(1.0+Ky) ) - K( 5, 11) = (2.0-Kx)*E*Iyy / ( L*(1.0+Kx) ) - - K( 3, 3) = K(9,9) - K( 1, 1) = K(7,7) - K( 2, 2) = K(8,8) - K( 6, 6) = K(12,12) - K( 4, 4) = K(10,10) - K(5,5) = K(11,11) - K(4,2) = K(2,4) - K(5,1) = K(1,5) - K(10,4) = K(4,10) - K(11,5) = K(5,11) - K(12,6)= -K(6,6) - K(10,2)= K(4,2) - K(11,1)= K(5,1) - K(9,3) = -K(3,3) - K(7,1) = -K(1,1) - K(8,2) = -K(2,2) - K(6, 12) = -K(6,6) - K(2, 10) = K(4,2) - K(1, 11) = K(5,1) - K(3, 9) = -K(3,3) - K(1, 7) = -K(1,1) - K(2, 8) = -K(2,2) - K(11,7) = -K(5,1) - K(10,8) = -K(4,2) - K(7,11) = -K(5,1) - K(8,10) = -K(4,2) - K(7,5) = -K(5,1) - K(5,7) = -K(5,1) - K(8,4) = -K(4,2) - K(4,8) = -K(4,2) - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed - -END SUBROUTINE ElemK_Beam -!------------------------------------------------------------------------------------------------------ -!> Element stiffness matrix for pretension cable -!! Element coordinate system: z along the cable! -SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) - REAL(ReKi), INTENT( IN) :: A, L, E - REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: K(12, 12) - ! Local variables - REAL(ReKi) :: L0, Eps0, EAL0, EE - REAL(ReKi) :: DC(12, 12) - - Eps0 = T0/(E*A) - L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 - EAL0 = E*A/L0 - EE = EAL0* Eps0/(1+Eps0) - - K(1:12,1:12)=0 - - ! Note: only translatoinal DOF involved (1-3, 7-9) - K(1,1)= EE - K(2,2)= EE - K(3,3)= EAL0 - - K(1,7)= -EE - K(2,8)= -EE - K(3,9)= -EAL0 - - K(7,1)= -EE - K(8,2)= -EE - K(9,3)= -EAL0 - - K(7,7)= EE - K(8,8)= EE - K(9,9)= EAL0 - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - K = MATMUL( MATMUL(DC, K), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed -END SUBROUTINE ElemK_Cable -!------------------------------------------------------------------------------------------------------ -!> Element mass matrix for classical beam elements -SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) - REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: M(12, 12) - - REAL(ReKi) :: t, rx, ry, po - REAL(ReKi) :: DC(12, 12) - - t = rho*A*L; - rx = rho*Ixx; - ry = rho*Iyy; - po = rho*Jzz*L; - - M(1:12,1:12) = 0 - - M( 9, 9) = t/3.0 - M( 7, 7) = 13.0*t/35.0 + 6.0*ry/(5.0*L) - M( 8, 8) = 13.0*t/35.0 + 6.0*rx/(5.0*L) - M(12, 12) = po/3.0 - M(10, 10) = t*L*L/105.0 + 2.0*L*rx/15.0 - M(11, 11) = t*L*L/105.0 + 2.0*L*ry/15.0 - M( 2, 4) = -11.0*t*L/210.0 - rx/10.0 - M( 1, 5) = 11.0*t*L/210.0 + ry/10.0 - M( 3, 9) = t/6.0 - M( 5, 7) = 13.*t*L/420. - ry/10. - M( 4, 8) = -13.*t*L/420. + rx/10. - M( 6, 12) = po/6. - M( 2, 10) = 13.*t*L/420. - rx/10. - M( 1, 11) = -13.*t*L/420. + ry/10. - M( 8, 10) = 11.*t*L/210. + rx/10. - M( 7, 11) = -11.*t*L/210. - ry/10. - M( 1, 7) = 9.*t/70. - 6.*ry/(5.*L) - M( 2, 8) = 9.*t/70. - 6.*rx/(5.*L) - M( 4, 10) = -L*L*t/140. - rx*L/30. - M( 5, 11) = -L*L*t/140. - ry*L/30. - - M( 3, 3) = M( 9, 9) - M( 1, 1) = M( 7, 7) - M( 2, 2) = M( 8, 8) - M( 6, 6) = M(12, 12) - M( 4, 4) = M(10, 10) - M( 5, 5) = M(11, 11) - M( 4, 2) = M( 2, 4) - M( 5, 1) = M( 1, 5) - M( 9, 3) = M( 3, 9) - M( 7, 5) = M( 5, 7) - M( 8, 4) = M( 4, 8) - M(12, 6) = M( 6, 12) - M(10, 2) = M( 2, 10) - M(11, 1) = M( 1, 11) - M(10, 8) = M( 8, 10) - M(11, 7) = M( 7, 11) - M( 7, 1) = M( 1, 7) - M( 8, 2) = M( 2, 8) - M(10, 4) = M( 4, 10) - M(11, 5) = M( 5, 11) - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO change me if direction cosine is transposed - -END SUBROUTINE ElemM_Beam -!------------------------------------------------------------------------------------------------------ -!> Element stiffness matrix for pretension cable -SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) - REAL(ReKi), INTENT( IN) :: A, L, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: M(12, 12) - ! Local variables - REAL(ReKi) :: DC(12, 12) - REAL(ReKi) :: t - - t = rho*A*L; - - M(1:12,1:12) = 0 - - M( 1, 1) = 13._ReKi/35._ReKi * t - M( 2, 2) = 13._ReKi/35._ReKi * t - M( 3, 3) = t/3.0_ReKi - - M( 7, 7) = 13._ReKi/35._ReKi * t - M( 8, 8) = 13._ReKi/35._ReKi * t - M( 9, 9) = t/3.0_ReKi - - M( 1, 7) = 9._ReKi/70._ReKi * t - M( 2, 8) = 9._ReKi/70._ReKi * t - M( 3, 9) = t/6.0_ReKi - - M( 7, 1) = 9._ReKi/70._ReKi * t - M( 8, 2) = 9._ReKi/70._ReKi * t - M( 9, 3) = t/6.0_ReKi - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - M = MATMUL( MATMUL(DC, M), TRANSPOSE(DC) ) ! TODO: change me if DirCos convention is transposed -END SUBROUTINE ElemM_Cable -!------------------------------------------------------------------------------------------------------ -!> calculates the lumped forces and moments due to gravity on a given element: -!! the element has two nodes, with the loads for both elements stored in array F. Indexing of F is: -!! Fx_n1=1,Fy_n1=2,Fz_n1=3,Mx_n1= 4,My_n1= 5,Mz_n1= 6, -!! Fx_n2=7,Fy_n2=8,Fz_n2=9,Mx_n2=10,My_n2=11,Mz_n2=12 -SUBROUTINE ElemG(A, L, rho, DirCos, F, g) - REAL(ReKi), INTENT( IN ) :: A !< area - REAL(ReKi), INTENT( IN ) :: L !< element length - REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1 ; 7-12 are loads for node 2. - REAL(ReKi) :: TempCoeff - REAL(ReKi) :: w ! weight per unit length - - F = 0 ! initialize whole array to zero, then set the non-zero portions - w = rho*A*g ! weight per unit length - - ! lumped forces on both nodes (z component only): - F(3) = -0.5*L*w - F(9) = F(3) - - ! lumped moments on node 1 (x and y components only): - ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary - ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. - TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice - F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12. !bjj: DirCos(2,3) = Dy/L - F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12. !bjj: DirCos(1,3) = Dx/L - - ! lumped moments on node 2: (note the opposite sign of node 1 moment) - F(10) = -F(4) - F(11) = -F(5) - !F(12) is 0 for g along z alone - -END SUBROUTINE ElemG -!------------------------------------------------------------------------------------------------------ -!> -SUBROUTINE ElemF_Cable(T0, DirCos, F) - REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. - ! Local variables - REAL(ReKi) :: DC(12, 12) - - F(1:12) = 0 ! init - F(3) = +T0 - F(9) = -T0 - - DC = 0 - DC( 1: 3, 1: 3) = DirCos - DC( 4: 6, 4: 6) = DirCos - DC( 7: 9, 7: 9) = DirCos - DC(10:12, 10:12) = DirCos - - F = MATMUL(DC, F)! TODO: change me if DirCos convention is transposed - -END SUBROUTINE ElemF_Cable -!------------------------------------------------------------------------------------------------------ -!> Calculates the lumped gravity forces at the nodes given the element geometry -!! It assumes a linear variation of the dimensions from node 1 to node 2, thus the area may be quadratically varying if crat<>1 -!! bjj: note this routine is a work in progress, intended for future version of SubDyn. Compare with ElemG. -SUBROUTINE LumpForces(Area1,Area2,crat,L,rho, g, DirCos, F) - REAL(ReKi), INTENT( IN ) :: Area1,Area2,crat !< X-sectional areas at node 1 and node 2, t2/t1 thickness ratio - REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( IN ) :: L !< Length of element - REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT( OUT) :: F(12) !< Lumped forces - !LOCALS - REAL(ReKi) :: TempCoeff,a0,a1,a2 !coefficients of the gravity quadratically distributed force - - !Calculate quadratic polynomial coefficients - a0 = a1 - print*,'Error: the function lumpforces is not ready to use' - STOP - - !Calculate quadratic polynomial coefficients - a0 = -99999 ! TODO: this is wrong - a2 = ( (Area1+A2) - (Area1*crat+Area2/crat) )/L**2. ! *x**2 - a1 = (Area2-Area1)/L -a2*L ! *x - - !Now calculate the Lumped Forces - F = 0 - F(3) = -(a0*L/2. +a1*L**2/6. +a2*L**3/12. )*rho*g !Forces along z (must be negative on earth) - F(9) = -(a0*L/2. +a1*L**2/3. +a2*L**3/4. )*rho*g !Forces along z (must be negative on earth) - - !Now calculate the Lumped Moments - !HERE TO BE COMPLETED FOR THE BELOW - TempCoeff = 1.0/12.0*g*L*L*rho*Area2 !RRD : I am changing this to >0 sign 6/10/13 - - !F(4) = TempCoeff*( DirCos(1, 3)*DirCos(2, 1) - DirCos(1, 1)*DirCos(2, 3) ) !These do not work if convnetion on z2>z1, x2>x1, y2>y1 are not followed as I have discovered 7/23 - !F(5) = TempCoeff*( DirCos(1, 3)*DirCos(2, 2) - DirCos(1, 2)*DirCos(2, 3) ) - - !RRD attempt at new dircos which keeps x in the X-Y plane - F(4) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(1,1) !bjj: compare with ElemG() and verify this lumping is consistent - F(5) = -TempCoeff * SQRT(1-DirCos(3,3)**2) * DirCos(2,1) !bjj: compare with ElemG() and verify this lumping is consistent - !RRD ends - F(10) = -F(4) - F(11) = -F(5) - !F(12) is 0 for g along z alone -END SUBROUTINE LumpForces - -!------------------------------------------------------------------------------------------------------ -!> -!! Method 1: pinv_A = A \ eye(m) (matlab) -!! call _GELSS to solve A.X=B -!! pinv(A) = B(1:n,1:m) -!! Method 2: [U,S,V] = svd(A); pinv_A = ( V / S ) * U'; (matlab) -! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' -SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) - use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM - real(LaKi), dimension(:,:), intent(in) :: A - real(LaKi), dimension(:,:), allocatable :: Ainv - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! < Error message if ErrStat / = ErrID_None - ! - real(LaKi), dimension(:), allocatable :: S - real(LaKi), dimension(:,:), allocatable :: U - real(LaKi), dimension(:,:), allocatable :: Vt - real(LaKi), dimension(:), allocatable :: WORK - real(LaKi), dimension(:,:), allocatable :: Acopy - integer :: i, j ! Loop indices - integer :: M !< The number of rows of the input matrix A - integer :: N !< The number of columns of the input matrix A - integer :: K !< - integer :: L !< - integer :: LWORK !< - integer :: INFO - real(ReKi) :: tol - M = size(A,1) - N = size(A,2) - K = min(M,N) - L = max(M,N) - LWORK = MAX(1,3*K +L,5*K) - allocate(S(K)); S = 0; - !! LWORK >= MAX(1,3*MIN(M,N) + MAX(M,N),5*MIN(M,N)) for the other paths - allocate(Work(LWORK)); Work=0 - allocate(U (M,K) ); U=0; - allocate(Vt(K,N) ); Vt=0; - allocate(Ainv(N,M)); Ainv=0; - allocate(Acopy(M,N)); Acopy=A; - - ! --- Compute the SVD of A - ! [U,S,V] = svd(A) - !call DGESVD ('S', 'S', M, N, A, M, S, U, M , Vt , K, WORK, LWORK, INFO) - call LAPACK_DGESVD('S', 'S', M, N, Acopy, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) - - !--- Compute PINV = V**T * SIGMA * U**T in two steps - ! SIGMA = S^(-1)=1/S(j), S is diagonal - do j = 1, K - U(:,j) = U(:,j)/S(j) - end do - ! Compute Ainv = 1.0*V^t * U^t + 0.0*Ainv V*(inv(S))*U' - !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) - call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) - ! --- Compute rank - !tol=maxval(shape(A))*epsilon(maxval(S)) - !rank=0 - !do i=1,K - ! if(S(i) .gt. tol)then - ! rank=rank+1 - ! end if - !end do - !print*,'Rank',rank - ! Ainv=transpose(matmul(matmul(U(:,1:r),S_inv(1:r,1:r)),Vt(1:r,:))) - END SUBROUTINE PseudoInverse - -END MODULE FEM diff --git a/modules/subdyn/src_soildyn/IntegerList.f90 b/modules/subdyn/src_soildyn/IntegerList.f90 deleted file mode 100644 index 299622368..000000000 --- a/modules/subdyn/src_soildyn/IntegerList.f90 +++ /dev/null @@ -1,459 +0,0 @@ -!> Module providing suport for an integer list stored as an array and not a chained list -!! Used since registry does not support pointer with recursive types. -module IntegerList - use SubDyn_Types, only: IList - use NWTC_Library, only: IntKi, ReKi, AllocAry, ErrID_None, ErrID_Fatal, num2lstr - - implicit none - - public :: IList - - public :: init_list - public :: destroy_list - public :: len - public :: append - public :: pop - public :: get - public :: find - public :: sort - public :: reverse - interface pop - module procedure pop_last - module procedure pop_item - end interface - interface init_list - module procedure init_list_n_def - module procedure init_list_vect - end interface - interface find - module procedure find_list - module procedure find_intarray - end interface - interface unique - module procedure unique_list - module procedure unique_intarray - module procedure unique_intarray_in_place - end interface -contains - - !> Concatenate lists: I3=[I1,I2] - subroutine concatenate_lists(I1,I2,I3, ErrStat, ErrMsg) - integer(intki), intent(in) :: i1(:), i2(:) - integer(intki), intent(out) :: i3(:) - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat=ErrID_None - ErrMsg='' - I3(1:size(I1)) = I1 - I3(size(I1)+1:size(I1)+size(I2)) = I2 - endsubroutine - subroutine concatenate_3lists(I1,I2,I3,I4, ErrStat, ErrMsg) - integer(intki), intent(in) :: i1(:), i2(:), i3(:) - integer(intki), intent(out) :: i4(:) - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat=ErrID_None - ErrMsg='' - I4( 1:size(I1) ) = I1 - I4(size(I1) +1:size(I1)+size(I2) ) = I2 - I4(size(I1)+size(I2)+1:size(I1)+size(I2)+size(I3)) = I3 - endsubroutine - - !> Set difference: I3=I1-I2 (assumes I1 is biggger than I2), elements of I1 not in I2 - subroutine lists_difference(I1, I2, I3, ErrStat, ErrMsg) - integer(IntKi), intent(in) :: I1(:), I2(:) - integer(IntKi), intent(out) :: I3(:) - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - integer(IntKi) :: I - logical, dimension(:), allocatable :: bUnique - ErrStat = ErrID_None - ErrMsg = "" - allocate(bUnique(1:size(I1))) - ! Then, remove DOFs on the boundaries: - DO i = 1, size(I1) !Boundary DOFs (Interface + Constraints) - if (find(I2,I1(i))>0) then - bUnique(I) = .false. - else - bUnique(I) = .true. - endif - ENDDO - if (count(bUnique) /= size(I3)) then - ErrStat=ErrID_Fatal; ErrMsg='Storage for list difference is of wrong size'; return - endif - I3 = pack(I1, bUnique) - deallocate(bUnique) - endsubroutine - - !> Initialize an integer list - subroutine init_list_n_def(L,n,default_val,ErrStat,ErrMsg) - type(IList), intent(inout) :: L !< List - integer(IntKi), intent(in) :: n !< number of initial values - integer(IntKi), intent(in) :: default_val !< default values - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - call AllocAry(L%List, n, 'L%List', ErrStat, ErrMsg) - if (ErrStat/=ErrID_None) return - L%List(1:n) = default_val - end subroutine init_list_n_def - - subroutine init_list_vect(L,vect,ErrStat,ErrMsg) - type(IList), intent(inout) :: L !< List - integer(IntKi), dimension(:), intent(in) :: vect !< number of initial values - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - call AllocAry(L%List, size(vect), 'L%List', ErrStat, ErrMsg) - if (ErrStat/=ErrID_None) return - L%List = vect - end subroutine init_list_vect - - !> Deallocate list - subroutine destroy_list(L,ErrStat,ErrMsg) - type(IList), intent(inout) :: L !< List - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - if (allocated(L%List)) deallocate(L%List) - end subroutine destroy_list - - !> Returns list length - integer function len(L) - type(IList), intent(in) :: L - if (allocated(L%List)) then - len=size(L%List) - else - len=0 - endif - end function len - - !> Append element to list - subroutine append(L,e, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent(in) :: e - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - if (allocated(L%List)) then - call resize_array(L%List,len(L)+1,e) - else - call init_list(L, 1, e, ErrStat, ErrMsg) - endif - end subroutine append - - !> Get element i from list - integer function get(L,i, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent(in) :: i - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - if ((i<=0).or.(i>len(L))) then - ErrStat=ErrID_Fatal - ErrMsg="Index out of bound "//trim(num2lstr(i))//", list length is "//trim(num2lstr(len(L))) - get=-9999 - else - ErrStat = ErrID_None - ErrMsg = "" - get = L%List(i) ! No error handling, throws "index array out of bound", like a regular array - endif - end function get - - !> Pop last element of the list and reduce list size by 1 - integer function pop_last(L,ErrStat,ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - integer(IntKi) :: n - ErrStat = ErrID_None - ErrMsg = "" - n=len(L) - pop_last = get(L, n, ErrStat, ErrMsg) ! index array out of bound will be thrown - call resize_array(L%List,n-1,0) - end function pop_last - - !> Pop element i from the list and reduce the size of the list by 1 - integer function pop_item(L,i,ErrStat,ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent(in) :: i - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - integer(IntKi) :: n - ErrStat = ErrID_None - ErrMsg = "" - n=len(L) - pop_item = get(L, i, ErrStat, ErrMsg) ! index array out of bound will be thrown - L%List(i:n-1)=L%List(i+1:n) - call resize_array(L%List,n-1,0) - end function pop_item - - !> Sort list - subroutine sort(L, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - if (allocated(L%List)) then - call sort_in_place(L%List) - else - ErrStat=ErrID_Fatal - ErrMsg="Cannot sort a list not allocated" - endif - end subroutine sort - - !> Reverse list - subroutine reverse(L, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - integer(IntKi) :: i - integer(IntKi) :: n - ErrStat = ErrID_None - ErrMsg = "" - n=len(L) - do i =1,int(n/2) - call swap(i, n-i+1) - enddo - contains - subroutine swap(i,j) - integer(IntKi), intent(in) :: i,j - integer(IntKi) :: tmp - tmp=L%List(i) - L%List(i) = L%List(j) - L%List(j) = tmp - end subroutine - end subroutine reverse - - - !> Returns index of element e in L, returns 0 if not found - !! NOTE: list but be sorted to call this function - integer(IntKi) function find_list(L, e, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent(in ) :: e - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - if (len(L)>0) then - find_list = binary_search(L%List, e) ! Binary search returns index for inequality List(i)<=e - if (find_list>0) then - if (L%List(find_list)/=e) then - find_list=-1 - endif - endif - else - find_list=-1 - endif - end function find_list - - !> Unique, in place - subroutine unique_list(L, ErrStat, ErrMsg) - type(IList), intent(inout) :: L - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat / = ErrID_None - ErrStat = ErrID_None - ErrMsg = "" - if (len(L)>0) then - call unique_intarray_in_place(L%List) - endif - end subroutine - - !> Print - subroutine print_list(L, varname, u_opt) - type(IList), intent(in) :: L - character(len=*),intent(in) :: varname - integer(IntKi), intent(in),optional :: u_opt - ! - character(len=*),parameter :: IFMT='I7.0' !< - integer(IntKi) :: u - integer(IntKi) :: n - character(len=20) :: fmt - ! Optional args - if (present(u_opt)) then - u=u_opt - else - u=6 - endif - n=len(L) - if (n>0) then - write(fmt,*) n - write(u,"(A,A,"// adjustl(fmt)//IFMT//",A)") varname,"=[",L%List,"];" - else - write(u,'(A,A)') varname,'=[];' - endif - end subroutine print_list - - ! -------------------------------------------------------------------------------- - ! --- Generic helper functions (should be part of NWTC library) - ! -------------------------------------------------------------------------------- - !> Sort integer array in place - pure subroutine sort_in_place(a) - integer(IntKi), intent(inout), dimension(:) :: a - integer(IntKi) :: temp - integer(IntKi) :: i, j - do i = 2, size(a) - j = i - 1 - temp = a(i) - do while (j>=1 .and. a(j)>temp) - a(j+1) = a(j) - j = j - 1 - if (j<1) then - exit - endif - end do - a(j+1) = temp - end do - end subroutine sort_in_place - - !> Performs binary search and return the largest index such that x(i) <= x0 - !! allows equlity - Integer(IntKi) function binary_search(x, x0) result(i_inf) - ! Arguments declarations - integer(IntKi), dimension(:),intent(in) :: x !< x *sorted* vector - integer(IntKi), intent(in) :: x0 !< - ! Variable declarations - integer(IntKi) :: i_sup !< - integer(IntKi) :: mid !< - i_inf=1 - i_sup=size(x) - ! Safety test - if (x0=x(i_sup)) then - i_inf=i_sup - return - end if - ! We loop until we narrow down to one index - do while (i_inf+1 Returns index of val in Array (val is an integer!) - ! NOTE: in the future use intrinsinc function findloc - function find_intarray(Array, Val) result(i) - integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in - integer(IntKi), intent(in) :: val !< Val - integer(IntKi) :: i !< Index of joint in joint table - logical :: found - i = 1 - do while ( i <= size(Array) ) - if ( Val == Array(i) ) THEN - return ! Exit when found - else - i = i + 1 - endif - enddo - i=-1 - end function - - !> return in res the unique values of v - subroutine unique_intarray(v,res) - ! Arguments - integer(IntKi),dimension(:),intent(in) :: v - integer(IntKi),dimension(:),allocatable::res - ! - integer(IntKi),dimension(:),pointer::tmp - integer :: k !< number of unique elements - integer :: i, j - if (allocated(res)) deallocate(res) - allocate(tmp(1:size(v))) - k = 1 - tmp(1) = v(1) - outer: do i=2,size(v) - do j=1,k - if (tmp(j) == v(i)) then - ! Found a match so start looking again - cycle outer - end if - end do - ! No match found so add it to the output - k = k + 1 - tmp(k) = v(i) - end do outer - allocate(res(1:k)) - res(1:k)=tmp(1:k) - deallocate(tmp) - end subroutine - - subroutine unique_intarray_in_place(v) - integer(IntKi),dimension(:),allocatable :: v - integer(IntKi),dimension(:),allocatable::res - integer :: k !< number of unique elements - integer :: i, j - allocate(res(1:size(v))) - k = 1 - res(1) = v(1) - outer: do i=2,size(v) - do j=1,k - if (res(j) == v(i)) then - ! Found a match so start looking again - cycle outer - end if - end do - ! No match found so add it to the output - k = k + 1 - res(k) = v(i) - end do outer - deallocate(v) - allocate(v(1:k)) - v(1:k)=res(1:k) - deallocate(res) - end subroutine - - !> Resize integer array of dimension 1 - subroutine resize_array(array,nNewSize,default_val) - integer(IntKi),dimension(:),allocatable,intent(inout) :: array - integer(IntKi) , intent(in) :: nNewSize - integer(IntKi), intent(in) :: default_val - ! Local variables - integer(IntKi),dimension(:),allocatable :: tmp !< backup of input - integer(IntKi) :: nDimTmp - integer(IntKi) :: AllocateStatus - ! To save memory, if nNewSize is below second dim, we take the min - nDimTmp= min(size(array,1),nNewSize) - ! Making of copy of the input - allocate(tmp(1:nDimTmp), STAT = AllocateStatus) - if (AllocateStatus /= 0) STOP "*** Not enough memory ***" - tmp(1:nDimTmp)=array(1:nDimTmp) - ! Reallocating the array - deallocate(array) - allocate(array(1:nNewSize), STAT = AllocateStatus) - if (AllocateStatus /= 0) STOP "*** Not enough memory ***" - ! We copy the original data into it - array(1:nDimTmp)=tmp(1:nDimTmp) - if(nDimTmp+1<=nNewSize) array(nDimTmp+1:nNewSize)=default_val - end subroutine - - !> Append two integer arrays of dimension 1 - subroutine append_arrays(array1,n1,array2,n2) - integer(IntKi), dimension(:), allocatable :: array1 - integer(IntKi), dimension(:) :: array2 - integer(IntKi), intent(inout) :: n1 !< SIDE EFFECTS - integer(IntKi), intent(in) :: n2 - ! Local variables - integer :: nNew - nNew=n1+n2 - ! --- Making enough space if needed - if(nNew>size(array1,1)) then - call resize_array(array1,nNew,0) - endif - ! --- Appending - array1((n1+1):(n1+n2))=array2(1:n2) - ! updating n1 - n1=n1+n2; - end subroutine - -end module IntegerList diff --git a/modules/subdyn/src_soildyn/SD_FEM.f90 b/modules/subdyn/src_soildyn/SD_FEM.f90 deleted file mode 100644 index e931274c9..000000000 --- a/modules/subdyn/src_soildyn/SD_FEM.f90 +++ /dev/null @@ -1,1897 +0,0 @@ -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -!********************************************************************************************************************************** -MODULE SD_FEM - USE NWTC_Library - USE SubDyn_Types - USE FEM - IMPLICIT NONE - - - INTEGER(IntKi), PARAMETER :: MaxMemJnt = 10 ! Maximum number of members at one joint - INTEGER(IntKi), PARAMETER :: MaxOutChs = 2000 ! Max number of Output Channels to be read in - INTEGER(IntKi), PARAMETER :: nDOFL_TP = 6 ! 6 degrees of freedom (length of u subarray [UTP]) - - ! values of these parameters are ordered by their place in SubDyn input file: - INTEGER(IntKi), PARAMETER :: JointsCol = 10 ! Number of columns in Joints (JointID, JointXss, JointYss, JointZss, JointType, JointDirX JointDirY JointDirZ JointStiff JointDamp) - INTEGER(IntKi), PARAMETER :: InterfCol = 7 ! Number of columns in interf matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) - INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) - INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) - INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) - INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs - INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) - INTEGER(IntKi), PARAMETER :: PropSetsCCol = 4 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) - INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) - INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) - INTEGER(IntKi), PARAMETER :: CMassCol = 11 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ, Optional:JMXY,JMXZ,JMYZ,CGX,CGY,CGZ) - ! Indices in Members table - INTEGER(IntKi), PARAMETER :: iMType= 6 ! Index in Members table where the type is stored - INTEGER(IntKi), PARAMETER :: iMProp= 4 ! Index in Members table where the PropSet1 and 2 are stored - - ! Indices in Joints table - INTEGER(IntKi), PARAMETER :: iJointType= 5 ! Index in Joints where the joint type is stored - INTEGER(IntKi), PARAMETER :: iJointDir= 6 ! Index in Joints where the joint-direction are stored - INTEGER(IntKi), PARAMETER :: iJointStiff= 9 ! Index in Joints where the joint-stiffness is stored - INTEGER(IntKi), PARAMETER :: iJointDamp= 10 ! Index in Joints where the joint-damping is stored - - ! ID for joint types - INTEGER(IntKi), PARAMETER :: idJointCantilever = 1 - INTEGER(IntKi), PARAMETER :: idJointUniversal = 2 - INTEGER(IntKi), PARAMETER :: idJointPin = 3 - INTEGER(IntKi), PARAMETER :: idJointBall = 4 - - ! ID for member types - INTEGER(IntKi), PARAMETER :: idMemberBeam = 1 - INTEGER(IntKi), PARAMETER :: idMemberCable = 2 - INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 - - ! Types of Boundary Conditions - INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 - INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 - INTEGER(IntKi), PARAMETER :: idBC_Leader = 13 ! TODO, and maybe "BC" not appropriate here - - ! Types of Static Improvement Methods - INTEGER(IntKi), PARAMETER :: idSIM_None = 0 - INTEGER(IntKi), PARAMETER :: idSIM_Full = 1 - INTEGER(IntKi), PARAMETER :: idSIM_GravOnly = 2 - INTEGER(IntKi) :: idSIM_Valid(3) = (/idSIM_None, idSIM_Full, idSIM_GravOnly /) - - INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) - - LOGICAL, PARAMETER :: DEV_VERSION = .false. - - INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic - MODULE PROCEDURE FINDLOCI_ReKi - MODULE PROCEDURE FINDLOCI_IntKi - END INTERFACE - - -CONTAINS -!------------------------------------------------------------------------------------------------------ -! --- Helper functions -!------------------------------------------------------------------------------------------------------ -!> Maps nodes to elements -!! allocate NodesConnE and NodesConnN -SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT( INOUT ) :: Init - TYPE(SD_ParameterType), INTENT( IN ) :: p - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements - INTEGER(IntKi) :: I,J,K !counter - - ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) - CALL AllocAry(Init%NodesConnE, p%nNodes, MaxMemJnt+1,'NodesConnE', ErrStat, ErrMsg); if (ErrStat/=0) return; - CALL AllocAry(Init%NodesConnN, p%nNodes, MaxMemJnt+2,'NodesConnN', ErrStat, ErrMsg); if (ErrStat/=0) return; - Init%NodesConnE = 0 - Init%NodesConnN = -99999 ! Not Used - - ! find the node connectivity, nodes/elements that connect to a common node - DO I = 1, p%nNodes - !Init%NodesConnN(I, 1) = NINT( Init%Nodes(I, 1) ) !This should not be needed, could remove the extra 1st column like for the other array - k = 0 - DO J = 1, Init%NElem !This should be vectorized - IF ( ( NINT(Init%Nodes(I, 1))==p%Elems(J, 2)) .OR. (NINT(Init%Nodes(I, 1))==p%Elems(J, 3) ) ) THEN !If i-th nodeID matches 1st node or 2nd of j-th element - k = k + 1 - if (k > MaxMemJnt+1) then - CALL SetErrStat(ErrID_Fatal, 'Maximum number of members reached on node'//trim(Num2LStr(NINT(Init%Nodes(I,1)))), ErrStat, ErrMsg, 'NodeCon'); - endif - Init%NodesConnE(I, k + 1) = p%Elems(J, 1) - ENDIF - ENDDO - Init%NodesConnE(I, 1) = k !Store how many elements connect i-th node in 2nd column - ENDDO - -END SUBROUTINE NodeCon - -!---------------------------------------------------------------------------- -!> Check if two elements are connected -!! returns true if they are, and return which node (1 or 2) of each element is involved -LOGICAL FUNCTION ElementsConnected(p, ie1, ie2, iWhichNode_e1, iWhichNode_e2) - TYPE(SD_ParameterType), INTENT(IN) :: p - INTEGER(IntKi), INTENT(IN) :: ie1, ie2 ! Indices of elements - INTEGER(IntKi), INTENT(OUT) :: iWhichNode_e1, iWhichNode_e2 ! 1 or 2 if node 1 or node 2 - if ((p%Elems(ie1, 2) == p%Elems(ie2, 2))) then ! node 1 connected to node 1 - iWhichNode_e1=1 - iWhichNode_e2=1 - ElementsConnected=.True. - else if((p%Elems(ie1, 2) == p%Elems(ie2, 3))) then ! node 1 connected to node 2 - iWhichNode_e1=1 - iWhichNode_e2=2 - ElementsConnected=.True. - else if((p%Elems(ie1, 3) == p%Elems(ie2, 2))) then ! node 2 connected to node 1 - iWhichNode_e1=2 - iWhichNode_e2=1 - ElementsConnected=.True. - else if((p%Elems(ie1, 3) == p%Elems(ie2, 3))) then ! node 2 connected to node 2 - iWhichNode_e1=2 - iWhichNode_e2=2 - ElementsConnected=.True. - else - ElementsConnected=.False. - iWhichNode_e1=-1 - iWhichNode_e2=-1 - endif -END FUNCTION ElementsConnected - -!> Loop through a list of elements and returns a list of unique joints -TYPE(IList) FUNCTION NodesList(p, Elements) - use IntegerList, only: init_list, append, find, sort - use IntegerList, only: print_list - TYPE(SD_ParameterType), INTENT(IN) :: p - integer(IntKi), dimension(:), INTENT(IN) :: Elements - integer(IntKi) :: ie, ei, j1, j2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - call init_list(NodesList, 0, 0, ErrStat2, ErrMsg2) - do ie = 1, size(Elements) - ei = Elements(ie) ! Element index - j1 = p%Elems(ei,2) ! Joint 1 - j2 = p%Elems(ei,3) ! Joint 2 - ! Append joints indices if not in list already - if (find(NodesList, j1, ErrStat2, ErrMsg2)<=0) call append(NodesList, j1, ErrStat2, ErrMsg2) - if (find(NodesList, j2, ErrStat2, ErrMsg2)<=0) call append(NodesList, j2, ErrStat2, ErrMsg2) - ! Sorting required by find function - call sort(NodesList, ErrStat2, ErrMsg2) - enddo - if (DEV_VERSION) then - call print_list(NodesList, 'Joint list') - endif -END FUNCTION NodesList -!------------------------------------------------------------------------------------------------------ -!> Returns list of rigid link elements (Er) -TYPE(IList) FUNCTION RigidLinkElements(Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, append - use IntegerList, only: print_list - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - integer(IntKi) :: ie !< Index on elements - ErrStat = ErrID_None - ErrMsg = "" - ! --- Establish a list of rigid link elements - call init_list(RigidLinkElements, 0, 0, ErrStat, ErrMsg); - - do ie = 1, Init%NElem - if (p%ElemProps(ie)%eType == idMemberRigid) then - call append(RigidLinkElements, ie, ErrStat, ErrMsg); - endif - end do - if (DEV_VERSION) then - call print_list(RigidLinkElements,'Rigid element list') - endif -END FUNCTION RigidLinkElements - -!------------------------------------------------------------------------------------------------------ -!> Returns true if one of the element connected to the node is a rigid link -LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p, ei) - integer(IntKi), intent(in) :: iJoint - type(SD_InitType), intent(in) :: Init - type(SD_ParameterType), intent(in) :: p - integer(IntKi), intent( out) :: ei !< Element index that connects do iJoint rigidly - ! Local variables - integer(IntKi) :: ie !< Loop index on elements - integer(IntKi) :: m ! Number of elements connected to a joint - - NodeHasRigidElem = .False. ! default return value - ! Loop through elements connected to node J - do ie = 1, Init%NodesConnE(iJoint, 1) - ei = Init%NodesConnE(iJoint, ie+1) - if (p%ElemProps(ei)%eType == idMemberRigid) then - NodeHasRigidElem = .True. - return ! we exit as soon as one rigid member is found - endif - enddo - ei=-1 -END FUNCTION NodeHasRigidElem -!------------------------------------------------------------------------------------------------------ -!> Returns a rigid body transformation matrix from nDOF to 6 reference DOF: T_ref (6 x nDOF), such that Uref = T_ref.U_subset -!! Typically called to get: -!! - the transformation from the interface points to the TP point -!! - the transformation from the bottom nodes to SubDyn origin (0,0,) -SUBROUTINE RigidTrnsf(Init, p, RefPoint, DOF, nDOF, T_ref, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(IN ) :: p - REAL(ReKi), INTENT(IN ) :: RefPoint(3) ! Coordinate of the reference point - INTEGER(IntKi), INTENT(IN ) :: nDOF ! Number of DOFS - INTEGER(IntKi), INTENT(IN ) :: DOF(nDOF) ! DOF indices that are used to create the transformation matrix - REAL(ReKi), INTENT( OUT) :: T_ref(nDOF,6) ! matrix that relates the subset of DOFs to the reference point - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER :: I, iDOF, iiDOF, iNode, nDOFPerNode - REAL(ReKi) :: dx, dy, dz - REAL(ReKi), dimension(6) :: Line - ErrStat = ErrID_None - ErrMsg = "" - T_ref(:,:)=0 - DO I = 1, nDOF - iDOF = DOF(I) ! DOF index in constrained system - iNode = p%DOFtilde2Nodes(iDOF,1) ! First column is node - nDOFPerNode = p%DOFtilde2Nodes(iDOF,2) ! Second column is number of DOF per node - iiDOF = p%DOFtilde2Nodes(iDOF,3) ! Third column is dof index for this joint (1-6 for cantilever) - - if ((iiDOF<1) .or. (iiDOF>6)) then - ErrMsg = 'RigidTrnsf, node DOF number is not valid. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' iiDOF:'//trim(Num2LStr(iiDOF)); ErrStat = ErrID_Fatal - return - endif - if (nDOFPerNode/=6) then - ErrMsg = 'RigidTrnsf, node doesnt have 6 DOFs. DOF:'//trim(Num2LStr(iDOF))//' Node:'//trim(Num2LStr(iNode))//' nDOF:'//trim(Num2LStr(nDOFPerNode)); ErrStat = ErrID_Fatal - return - endif - - dx = Init%Nodes(iNode, 2) - RefPoint(1) - dy = Init%Nodes(iNode, 3) - RefPoint(2) - dz = Init%Nodes(iNode, 4) - RefPoint(3) - - CALL RigidTransformationLine(dx,dy,dz,iiDOF,Line) !returns Line - T_ref(I, 1:6) = Line - ENDDO -END SUBROUTINE RigidTrnsf - -!------------------------------------------------------------------------------------------------------ -! --- Main routines, more or less listed in order in which they are called -!------------------------------------------------------------------------------------------------------ -!> -! - Removes the notion of "ID" and use Index instead -! - Creates Nodes (use indices instead of ID), similar to Joints array -! - Creates Elems (use indices instead of ID) similar to Members array -! - Updates Reacts (use indices instead of ID) -! - Updates Interf (use indices instead of ID) -SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) ::Init - TYPE(SD_ParameterType), INTENT(INOUT) ::p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable - INTEGER :: I, n, iMem, iNode, JointID - INTEGER(IntKi) :: mType !< Member Type - CHARACTER(1255) :: sType !< String for element type - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! TODO See if Elems is actually used elsewhere - - CALL AllocAry(p%Elems, Init%NElem, MembersCol, 'p%Elems', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%Nodes, p%nNodes, JointsCol, 'Init%Nodes', ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Initialize Nodes - Init%Nodes = -999999 ! Init to unphysical values - do I = 1,Init%NJoints - Init%Nodes(I, 1) = I ! JointID replaced by index I - Init%Nodes(I, 2:JointsCol) = Init%Joints(I, 2:JointsCol) ! All the rest is copied - enddo - - ! --- Re-Initialize Reactions, pointing to index instead of JointID - do I = 1, p%nNodes_C - JointID=p%Nodes_C(I,1) - p%Nodes_C(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) ! Replace JointID with Index - if (p%Nodes_C(I,1)<=0) then - CALL Fatal('Reaction joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - ! --- Re-Initialize interface joints, pointing to index instead of JointID - do I = 1, p%nNodes_I - JointID=p%Nodes_I(I,1) - p%Nodes_I(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (p%Nodes_I(I,1)<=0) then - CALL Fatal('Interface joint table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - ! Change numbering in concentrated mass matrix - do I = 1, Init%NCMass - JointID = Init%CMass(I,1) - Init%CMass(I,1) = FINDLOCI(Init%Joints(:,1), JointID ) - if (Init%CMass(I,1)<=0) then - CALL Fatal('Concentrated mass table: line '//TRIM(Num2LStr(I))//' refers to JointID '//trim(Num2LStr(JointID))//' which is not in the joint list!') - return - endif - enddo - - - ! --- Initialize Elems, starting with each member as an element (we'll take NDiv into account later) - p%Elems = 0 - ! --- Replacing "MemberID" "JointID", and "PropSetID" by simple index in this tables - DO iMem = 1, p%NMembers - ! Column 1 : member index (instead of MemberID) - p%Elems(iMem, 1) = iMem - mType = Init%Members(iMem, iMType) ! - ! Column 2-3: Joint index (instead of JointIDs) - p%Elems(iMem, 1) = iMem ! NOTE: element/member number (not MemberID) - do iNode=2,3 - p%Elems(iMem,iNode) = FINDLOCI(Init%Joints(:,1), Init%Members(iMem, iNode) ) - if (p%Elems(iMem,iNode)<=0) then - CALL Fatal(' MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//' has JointID'//TRIM(Num2LStr(iNode-1))//' = '// TRIM(Num2LStr(Init%Members(iMem, iNode)))//' which is not in the joint list!') - return - endif - enddo - ! Column 4-5: PropIndex 1-2 (instead of PropSetID1&2) - ! NOTE: this index has different meaning depending on the member type ! - DO n=iMProp,iMProp+1 - - if (mType==idMemberBeam) then - sType='Member x-section property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) - else if (mType==idMemberCable) then - sType='Cable property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) - else if (mType==idMemberRigid) then - sType='Rigid property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) - else - ! Should not happen - print*,'Element type unknown',mType - STOP - end if - - if (p%Elems(iMem,n)<=0) then - CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') - endif - END DO !n, loop through property ids - ! Column 6: member type - p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! - END DO !iMem, loop through members - - ! TODO in theory, we shouldn't need these anymore - ! deallocate(Init%Members) - ! deallocate(Init%Joints) -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - SUBROUTINE Fatal(ErrMsg_in) - CHARACTER(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_ReIndex_CreateNodesAndElems'); - END SUBROUTINE Fatal -END SUBROUTINE SD_ReIndex_CreateNodesAndElems - -!---------------------------------------------------------------------------- -SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) ::Init - TYPE(SD_ParameterType), INTENT(INOUT) ::p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variable - INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 - INTEGER :: NNE ! number of nodes per element - INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempProps(:, :) - INTEGER, ALLOCATABLE :: TempMembers(:, :) - INTEGER :: knode, kelem, kprop, nprop - REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 - LOGICAL :: found, CreateNewProp - INTEGER(IntKi) :: eType !< Element Type - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! number of nodes per element - IF( ( Init%FEMMod >= 0 ) .and. (Init%FEMMod <= 3) ) THEN - NNE = 2 - ELSE - CALL Fatal('FEMMod '//TRIM(Num2LStr(Init%FEMMod))//' not implemented.'); return - ENDIF - - ! Total number of element - Init%NElem = p%NMembers*Init%NDiv ! Note: This is a max since cable and rigid cannot be subdivided - ! Total number of nodes - Depends on division and number of nodes per element - p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*p%NMembers - p%nNodes = p%nNodes + (NNE - 2)*Init%NElem ! Note: Same as above. Can be improved by counting R&C - - ! check the number of interior modes - IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN - CALL Fatal(' NModes must be less than or equal to '//TRIM(Num2LStr( 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ))); return - ENDIF - - CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different - - ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays - ! NOTE: need NNode and NElem - CALL SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat2, ErrMsg2); if(Failed()) return - - - Init%MemberNodes = 0 - ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) - if (Init%NDiv==1) then - ! NDiv = 1 - Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) - Init%NPropB = Init%NPropSetsB - - else if (Init%NDiv > 1) then - - ! Discretize structure according to NDiv - ! - Elems is fully reinitialized, connectivity needs to be done again using SetNewElem - ! - Nodes are not reinitialized, but appended to NNodes - ! - - ! Initialize Temp arrays that will contain user inputs + input from the subdivided members - ! We don't know how many properties will be needed, so allocated to size MaxNProp - MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) - CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempProps, MaxNProp, PropSetsBCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return - TempProps = -9999. - TempMembers = p%Elems(1:p%NMembers,:) - TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB - p%Elems(:,:) = -9999. ! Reinitialized. Elements will be ordered by member subdivisions (see setNewElem) - - kelem = 0 - knode = Init%NJoints - kprop = Init%NPropSetsB - DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information - ! Member data - Node1 = TempMembers(I, 2) - Node2 = TempMembers(I, 3) - Prop1 = TempMembers(I, iMProp ) - Prop2 = TempMembers(I, iMProp+1) - eType = TempMembers(I, iMType ) - - IF ( Node1==Node2 ) THEN - CALL Fatal(' Same starting and ending node in the member.') - RETURN - ENDIF - - if (eType/=idMemberBeam) then - ! --- Cables and rigid links are not subdivided - ! No need to create new properties or new nodes - Init%MemberNodes(I, 1) = Node1 - Init%MemberNodes(I, 2) = Node2 - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p) - cycle - endif - - ! --- Subdivision of beams - Init%MemberNodes(I, 1) = Node1 - Init%MemberNodes(I, Init%NDiv+1) = Node2 - - IF ( ( .not. EqualRealNos(TempProps(Prop1, 2),TempProps(Prop2, 2) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 3),TempProps(Prop2, 3) ) ) & - .OR. ( .not. EqualRealNos(TempProps(Prop1, 4),TempProps(Prop2, 4) ) ) ) THEN - - CALL Fatal(' Material E,G and rho in a member must be the same') - RETURN - ENDIF - - x1 = Init%Nodes(Node1, 2) - y1 = Init%Nodes(Node1, 3) - z1 = Init%Nodes(Node1, 4) - - x2 = Init%Nodes(Node2, 2) - y2 = Init%Nodes(Node2, 3) - z2 = Init%Nodes(Node2, 4) - - dx = ( x2 - x1 )/Init%NDiv - dy = ( y2 - y1 )/Init%NDiv - dz = ( z2 - z1 )/Init%NDiv - - d1 = TempProps(Prop1, 5) - t1 = TempProps(Prop1, 6) - - d2 = TempProps(Prop2, 5) - t2 = TempProps(Prop2, 6) - - dd = ( d2 - d1 )/Init%NDiv - dt = ( t2 - t1 )/Init%NDiv - - ! If both dd and dt are 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node - CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) - - ! node connect to Node1 - knode = knode + 1 - Init%MemberNodes(I, 2) = knode - CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init) ! Set Init%Nodes(knode,:) - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p) - nprop = Prop1 - ENDIF - - ! interior nodes - DO J = 2, (Init%NDiv-1) - knode = knode + 1 - Init%MemberNodes(I, J+1) = knode - - CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) ! Set Init%Nodes(knode,:) - - IF ( CreateNewProp ) THEN - ! create a new property set - ! k, E, G, rho, d, t, Init - kprop = kprop + 1 - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p) - nprop = kprop - ELSE - kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p) - ENDIF - ENDDO - - ! the element connect to Node2 - kelem = kelem + 1 - CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p) - ENDDO ! loop over all members - ! - Init%NPropB = kprop - Init%NElem = kelem ! TODO since not all members might have been divided - p%nNodes = knode ! TODO since not all members might have been divided - - ENDIF ! if NDiv is greater than 1 - - ! set the props in Init - CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return - - if (Init%NDiv==1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) - else if (Init%NDiv>1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempProps(1:Init%NPropB, 1:PropSetsBCol) - endif - - ! --- Cables and rigid link properties (these cannot be subdivided, so direct copy of inputs) - Init%NPropC = Init%NPropSetsC - Init%NPropR = Init%NPropSetsR - CALL AllocAry(Init%PropsC, Init%NPropC, PropSetsCCol, 'Init%PropsCable', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%PropsR, Init%NPropR, PropSetsRCol, 'Init%PropsRigid', ErrStat2, ErrMsg2); if(Failed()) return - Init%PropsC(1:Init%NPropC, 1:PropSetsCCol) = Init%PropSetsC(1:Init%NPropC, 1:PropSetsCCol) - Init%PropsR(1:Init%NPropR, 1:PropSetsRCol) = Init%PropSetsR(1:Init%NPropR, 1:PropSetsRCol) - - CALL CleanUp_Discrt() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Discrt') - Failed = ErrStat >= AbortErrLev - if (Failed) CALL CleanUp_Discrt() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - CHARACTER(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Discrt'); - CALL CleanUp_Discrt() - END SUBROUTINE Fatal - - SUBROUTINE CleanUp_Discrt() - ! deallocate temp matrices - IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) - IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) - END SUBROUTINE CleanUp_Discrt - - !> Set properties of node k - SUBROUTINE SetNewNode(k, x, y, z, Init) - TYPE(SD_InitType), INTENT(INOUT) :: Init - INTEGER, INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: x, y, z - Init%Nodes(k, 1) = k - Init%Nodes(k, 2) = x - Init%Nodes(k, 3) = y - Init%Nodes(k, 4) = z - Init%Nodes(k, iJointType) = idJointCantilever ! Note: all added nodes are Cantilever - ! Properties below are for non-cantilever joints - Init%Nodes(k, iJointDir:iJointDir+2) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes - Init%Nodes(k, iJointStiff) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes - Init%Nodes(k, iJointDamp) = 0.0_ReKi ! NOTE: irrelevant for cantilever nodes - END SUBROUTINE SetNewNode - - !> Set properties of element k - SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p) - INTEGER, INTENT(IN ) :: k - INTEGER, INTENT(IN ) :: n1 - INTEGER, INTENT(IN ) :: n2 - INTEGER, INTENT(IN ) :: eType - INTEGER, INTENT(IN ) :: p1 - INTEGER, INTENT(IN ) :: p2 - TYPE(SD_ParameterType), INTENT(INOUT) :: p - p%Elems(k, 1) = k - p%Elems(k, 2) = n1 - p%Elems(k, 3) = n2 - p%Elems(k, iMProp ) = p1 - p%Elems(k, iMProp+1) = p2 - p%Elems(k, iMType) = eType - END SUBROUTINE SetNewElem - - !> Set material properties of element k, NOTE: this is only for a beam - SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) - INTEGER , INTENT(IN) :: k - REAL(ReKi), INTENT(IN) :: E, G, rho, d, t - REAL(ReKi), INTENT(INOUT):: TempProps(:, :) - TempProps(k, 1) = k - TempProps(k, 2) = E - TempProps(k, 3) = G - TempProps(k, 4) = rho - TempProps(k, 5) = d - TempProps(k, 6) = t - END SUBROUTINE SetNewProp - -END SUBROUTINE SD_Discrt - -!------------------------------------------------------------------------------------------------------ -!> Set Element properties p%ElemProps, different properties are set depening on element type.. -SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(IN ) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I, J, K, iTmp - INTEGER :: N1, N2 ! starting node and ending node in the element - INTEGER :: P1, P2 ! property set numbers for starting and ending nodes - REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section - REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices - REAL(ReKi) :: L ! length of the element - REAL(ReKi) :: T0 ! pretension force in cable [N] - REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer - LOGICAL :: shear - INTEGER(IntKi) :: eType !< Member type - REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrMsg = "" - ErrStat = ErrID_None - - ALLOCATE( p%ElemProps(Init%NElem), STAT=ErrStat2); ErrMsg2='Error allocating p%ElemProps' - if(Failed()) return - - ! Loop over all elements and set ElementProperties - do I = 1, Init%NElem - N1 = p%Elems(I, 2) - N2 = p%Elems(I, 3) - - P1 = p%Elems(I, iMProp ) - P2 = p%Elems(I, iMProp+1) - eType = p%Elems(I, iMType) - - ! --- Properties common to all element types: L, DirCos (and Area and rho) - Point1 = Init%Nodes(N1,2:4) - Point2 = Init%Nodes(N2,2:4) - CALL GetDirCos(Point1, Point2, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos - p%ElemProps(i)%eType = eType - p%ElemProps(i)%Length = L - p%ElemProps(i)%DirCos = DirCos - - ! Init to excessive values to detect any issue - p%ElemProps(i)%Ixx = -9.99e+36 - p%ElemProps(i)%Iyy = -9.99e+36 - p%ElemProps(i)%Jzz = -9.99e+36 - p%ElemProps(i)%Kappa = -9.99e+36 - p%ElemProps(i)%YoungE = -9.99e+36 - p%ElemProps(i)%ShearG = -9.99e+36 - p%ElemProps(i)%Area = -9.99e+36 - p%ElemProps(i)%Rho = -9.99e+36 - p%ElemProps(i)%T0 = -9.99e+36 - - ! --- Properties that are specific to some elements - if (eType==idMemberBeam) then - E = Init%PropsB(P1, 2) - G = Init%PropsB(P1, 3) - rho = Init%PropsB(P1, 4) - D1 = Init%PropsB(P1, 5) - t1 = Init%PropsB(P1, 6) - D2 = Init%PropsB(P2, 5) - t2 = Init%PropsB(P2, 6) - r1 = 0.25*(D1 + D2) - t = 0.5*(t1+t2) - if ( EqualRealNos(t, 0.0_ReKi) ) then - r2 = 0 - else - r2 = r1 - t - endif - A = Pi_D*(r1*r1-r2*r2) - Ixx = 0.25*Pi_D*(r1**4-r2**4) - Iyy = Ixx - Jzz = 2.0*Ixx - - if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli - Shear = .false. - kappa = 0 - elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko - Shear = .true. - ! kappa = 0.53 - ! equation 13 (Steinboeck et al) in SubDyn Theory Manual - nu = E / (2.0_ReKi*G) - 1.0_ReKi - D_outer = 2.0_ReKi * r1 ! average (outer) diameter - D_inner = D_outer - 2*t ! remove 2x thickness to get inner diameter - ratioSq = ( D_inner / D_outer)**2 - kappa = ( 6.0 * (1.0 + nu) **2 * (1.0 + ratioSq)**2 ) & - / ( ( 1.0 + ratioSq )**2 * ( 7.0 + 14.0*nu + 8.0*nu**2 ) + 4.0 * ratioSq * ( 5.0 + 10.0*nu + 4.0 *nu**2 ) ) - endif - ! Storing Beam specific properties - p%ElemProps(i)%Ixx = Ixx - p%ElemProps(i)%Iyy = Iyy - p%ElemProps(i)%Jzz = Jzz - p%ElemProps(i)%Shear = Shear - p%ElemProps(i)%kappa = kappa - p%ElemProps(i)%YoungE = E - p%ElemProps(i)%ShearG = G - p%ElemProps(i)%Area = A - p%ElemProps(i)%Rho = rho - - else if (eType==idMemberCable) then - if (DEV_VERSION) then - print*,'Member',I,'is a cable' - endif - p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 - p%ElemProps(i)%YoungE = Init%PropsC(P1, 2)/1 ! Young's modulus, E=EA/A [N/m^2] - p%ElemProps(i)%Rho = Init%PropsC(P1, 3) ! Material density [kg/m3] - p%ElemProps(i)%T0 = Init%PropsC(P1, 4) ! Pretension force [N] - - else if (eType==idMemberRigid) then - if (DEV_VERSION) then - print*,'Member',I,'is a rigid link' - endif - p%ElemProps(i)%Area = 1 ! Arbitrary set to 1 - p%ElemProps(i)%Rho = Init%PropsR(P1, 2) - - else - ! Should not happen - print*,'Element type unknown',eType - STOP - end if - enddo ! I end loop over elements -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed -END SUBROUTINE SetElementProperties - - -!> Distribute global DOF indices corresponding to Nodes, Elements, BCs, Reactions -!! For Cantilever Joint -> Condensation into 3 translational and 3 rotational DOFs -!! For other joint type -> Condensation of the 3 translational DOF -!! -> Keeping 3 rotational DOF for each memeber connected to the joint -SUBROUTINE DistributeDOF(Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, len - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer(IntKi) :: iNode, k - integer(IntKi) :: iPrev ! Cumulative counter over the global DOF - integer(IntKi) :: iElem ! - integer(IntKi) :: idElem - integer(IntKi) :: nRot ! Number of rotational DOFs (multiple of 3) to be used at the joint - integer(IntKi) :: iOff ! Offset, 0 or 6, depending if node 1 or node 2 - integer(IntKi), dimension(6) :: DOFNode_Old - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - ErrMsg = "" - ErrStat = ErrID_None - - allocate(p%NodesDOF(1:p%nNodes), stat=ErrStat2) - ErrMsg2="Error allocating NodesDOF" - if(Failed()) return - - call AllocAry(p%ElemsDOF, 12, Init%NElem, 'ElemsDOF', ErrStat2, ErrMsg2); if(Failed()) return; - p%ElemsDOF=-9999 - - iPrev =0 - do iNode = 1, p%nNodes - ! --- Distribute to joints iPrev + 1:6, or, iPrev + 1:(3+3m) - if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then - nRot=3 - else - nRot= 3*Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint - endif - call init_list(p%NodesDOF(iNode), 3+nRot, iPrev, ErrStat2, ErrMsg2) - p%NodesDOF(iNode)%List(1:(3+nRot)) = (/ ((iElem+iPrev), iElem=1,3+nRot) /) - - ! --- Distribute to members - do iElem = 1, Init%NodesConnE(iNode,1) ! members connected to joint iJ - idElem = Init%NodesConnE(iNode,iElem+1) - if (iNode == p%Elems(idElem, 2)) then ! Current joint is Elem node 1 - iOff = 0 - else ! Current joint is Elem node 2 - iOff = 6 - endif - p%ElemsDOF(iOff+1:iOff+3, idElem) = p%NodesDOF(iNode)%List(1:3) - if (int(Init%Nodes(iNode,iJointType)) == idJointCantilever ) then - p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(4:6) - else - p%ElemsDOF(iOff+4:iOff+6, idElem) = p%NodesDOF(iNode)%List(3*iElem+1:3*iElem+3) - endif - enddo ! iElem, loop on members connect to joint - iPrev = iPrev + len(p%NodesDOF(iNode)) - enddo ! iNode, loop on joints - - ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%BCs, 6*p%nNodes_C, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return - CALL InitBCs(Init, p) - - ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%IntFc, 6*p%nNodes_I,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return - CALL InitIntFc(Init, p) - - ! --- Safety check - if (any(p%ElemsDOF<0)) then - ErrStat=ErrID_Fatal - ErrMsg ="Implementation error in Distribute DOF, some member DOF were not allocated" - endif - - ! --- Safety check (backward compatibility, only valid if all joints are Cantilever) - if (p%nNodes == count( Init%Nodes(:, iJointType) == idJointCantilever)) then - do idElem = 1, Init%NElem - iNode = p%Elems(idElem, 2) - DOFNode_Old= (/ ((iNode*6-5+k), k=0,5) /) - if ( any( (p%ElemsDOF(1:6, idElem) /= DOFNode_Old)) ) then - ErrStat=ErrID_Fatal - ErrMsg ="Implementation error in Distribute DOF, DOF indices have changed for iElem="//trim(Num2LStr(idElem)) - return - endif - enddo - else - ! Safety check does not apply if some joints are non-cantilever - endif - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetElementProperties') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - - !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have - !! NOTE: need p%Nodes_C to have an updated first column that uses indices and not JointIDs - !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" - SUBROUTINE InitBCs(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(INOUT) :: p - INTEGER(IntKi) :: I, J, iNode - Init%BCs = -9999 - DO I = 1, p%nNodes_C - iNode = p%Nodes_C(I,1) ! Node index - DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) - Init%BCs( (I-1)*6+J, 2) = idBC_Fixed - p%Nodes_C(I, J+1) = idBC_Fixed - else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF - Init%BCs( (I-1)*6+J, 2) = idBC_Internal - p%Nodes_C(I, J+1) = idBC_Internal - else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF - Init%BCs( (I-1)*6+J, 2) = idBC_Leader - p%Nodes_C(I, J+1) = idBC_Leader - print*,'BC 2 not allowed for now, node',iNode - STOP - else - print*,'Wrong boundary condition input for reaction node',iNode - STOP - endif - ENDDO - ENDDO - END SUBROUTINE InitBCs - - !> Sets a list of DOF indices and the value these DOF should have - !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs - !! TODO remove me and merge me with CraigBampton - SUBROUTINE InitIntFc(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(INOUT) :: p - INTEGER(IntKi) :: I, J, iNode - Init%IntFc = -9999 - DO I = 1, p%nNodes_I - iNode = p%Nodes_I(I,1) ! Node index - DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - - if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF - Init%IntFc((I-1)*6+J, 2) = idBC_Leader - p%Nodes_I(I,J+1) = idBC_Leader - elseif (p%Nodes_I(I,J+1)==1) then ! User input 0=Fixed DOF - Init%IntFc( (I-1)*6+J, 2) = idBC_Fixed - p%Nodes_I(I,J+1) = idBC_Fixed - print*,'Fixed boundary condition not yet supported for interface nodes, node:',iNode - STOP - else - print*,'Wrong boundary condition input for interface node',iNode - STOP - endif - ENDDO - ENDDO - END SUBROUTINE InitIntFc - -END SUBROUTINE DistributeDOF - -!------------------------------------------------------------------------------------------------------ -!> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I, J, K - INTEGER :: iGlob - REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector - REAL(ReKi) :: FCe(12) ! Pretension force from cable element - REAL(ReKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - INTEGER(IntKi) :: iNode !< Node index - integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system - integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system - real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node - real(ReKi) :: m, x, y, z, Jxx, Jyy, Jzz, Jxy, Jxz, Jyz - INTEGER :: jGlob, kGlob - ErrMsg = "" - ErrStat = ErrID_None - - ! total unconstrained degrees of freedom of the system - p%nDOF = nDOF_Unconstrained() - if (DEV_VERSION) then - print*,'nDOF_unconstrained:',p%nDOF, ' (if all Cantilever, it would be: ',6*p%nNodes,')' - endif - - CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - Init%K = 0.0_ReKi - Init%M = 0.0_ReKi - Init%FG = 0.0_ReKi - - ! loop over all elements, compute element matrices and assemble into global matrices - DO i = 1, Init%NElem - ! --- Element Me,Ke,Fg, Fce - CALL ElemM(p%ElemProps(i), Me) - CALL ElemK(p%ElemProps(i), Ke) - CALL ElemF(p%ElemProps(i), Init%g, FGe, FCe) - - ! --- Assembly in global unconstrained system - IDOF = p%ElemsDOF(1:12, i) - Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces - Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) - Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) - ENDDO - - ! Add concentrated mass to mass matrix - DO I = 1, Init%nCMass - iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added - ! Safety check (otherwise we might have more than 6 DOF) - if (Init%Nodes(iNode,iJointType) /= idJointCantilever) then - ErrMsg2='Concentrated mass is only for cantilever joints. Problematic node: '//trim(Num2LStr(iNode)); ErrStat2=ErrID_Fatal; - if(Failed()) return - endif - ! Mass matrix of a rigid body - M66 = 0.0_ReKi - m = Init%CMass(I,2) - Jxx = Init%CMass(I,3 ); Jxy = Init%CMass(I,6 ); x = Init%CMass(I,9 ); - Jyy = Init%CMass(I,4 ); Jxz = Init%CMass(I,7 ); y = Init%CMass(I,10); - Jzz = Init%CMass(I,5 ); Jyz = Init%CMass(I,8 ); z = Init%CMass(I,11); - M66(1 , :)=(/ m , 0._ReKi , 0._ReKi , 0._ReKi , z*m , -y*m /) - M66(2 , :)=(/ 0._ReKi , m , 0._ReKi , -z*m , 0._ReKi , x*m /) - M66(3 , :)=(/ 0._ReKi , 0._ReKi , m , y*m , -x*m , 0._ReKi /) - M66(4 , :)=(/ 0._ReKi , -z*m , y*m , Jxx + m*(y**2+z**2) , Jxy - m*x*y , Jxz - m*x*z /) - M66(5 , :)=(/ z*m , 0._ReKi , -x*m , Jxy - m*x*y , Jyy + m*(x**2+z**2) , Jyz - m*y*z /) - M66(6 , :)=(/ -y*m , x*m , 0._ReKi , Jxz - m*x*z , Jyz - m*y*z , Jzz + m*(x**2+y**2) /) - ! Adding - DO J = 1, 6 - jGlob = p%NodesDOF(iNode)%List(J) - DO K = 1, 6 - kGlob = p%NodesDOF(iNode)%List(K) - Init%M(jGlob, kGlob) = Init%M(jGlob, kGlob) + M66(J,K) - ENDDO - ENDDO - ENDDO ! Loop on concentrated mass - - ! Add concentrated mass induced gravity force - DO I = 1, Init%nCMass - iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added - iGlob = p%NodesDOF(iNode)%List(3) ! uz - Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g - ENDDO - - CALL CleanUp_AssembleKM() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AssembleKM') - Failed = ErrStat >= AbortErrLev - if (Failed) call Cleanup_AssembleKM() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'AssembleKM'); - CALL CleanUp_AssembleKM() - END SUBROUTINE Fatal - - SUBROUTINE CleanUp_AssembleKM() - !pass - END SUBROUTINE CleanUp_AssembleKM - - INTEGER(IntKi) FUNCTION nDOF_Unconstrained() - integer(IntKi) :: i - integer(IntKi) :: m - nDOF_Unconstrained=0 - do i = 1,p%nNodes - if (int(Init%Nodes(i,iJointType)) == idJointCantilever ) then - nDOF_Unconstrained = nDOF_Unconstrained + 6 - else - m = Init%NodesConnE(i,1) ! Col1: number of elements connected to this joint - nDOF_Unconstrained = nDOF_Unconstrained + 3 + 3*m - endif - end do - END FUNCTION - -END SUBROUTINE AssembleKM - -!> Add soil stiffness and mass to global system matrices -!! Soil stiffness can come from two sources: -!! - "SSI" matrices (specified at reaction nodes) -!! - "Soil" matrices (specified at Initalization) -SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) - real(ReKi), dimension(:,:), intent(inout) :: M - real(ReKi), dimension(:,:), intent(inout) :: K - type(IList),dimension(:), intent(in ) :: NodesDOF !< Map from Node Index to DOF lists - type(SD_InitType), intent(inout) :: Init !< TODO set it to in only - type(SD_ParameterType), intent(in ) :: p - integer(IntKi), intent( out) :: ErrStat ! Error status of the operation - character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None - logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding - integer :: I, J, iiNode, nDOF - integer :: iDOF, jDOF, iNode !< DOF and node indices - real(ReKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil - real(ReKi) :: Dist - ErrMsg = "" - ErrStat = ErrID_None - ! --- SSI matrices - ! TODO consider doing the 21 -> 6x6 conversion while reading - ! 6x6 matrix goes to one node of one element only - do iiNode = 1, p%nNodes_C ! loop on constrained nodes - iNode = p%Nodes_C(iiNode,1) - nDOF=size(NodesDOF(iNode)%List) - if (nDOF/=6) then - ErrMsg='SSI soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; - ErrStat=ErrID_Fatal; return - endif - call Array21_to_6by6(Init%SSIK(:,iiNode), K_soil) - call Array21_to_6by6(Init%SSIM(:,iiNode), M_soil) - if (present(Substract)) then - if (Substract) then - K_soil = - K_soil - M_soil = - M_soil - endif - endif - do I = 1, 6 - iDOF = NodesDOF(iNode)%List(I) ! DOF index - do J = 1, 6 - jDOF = NodesDOF(iNode)%List(J) ! DOF index - K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) - M(iDOF, jDOF) = M(iDOF, jDOF) + M_soil(I,J) - enddo - enddo - enddo - ! --- "Soil" matrices - if (allocated(Init%Soil_K)) then - do iiNode = 1,size(Init%Soil_Points,2) - ! --- Find closest node - call FindClosestNodes(Init%Soil_Points(1:3,iiNode), Init%Nodes, iNode, Dist); - if (Dist>0.1_ReKi) then - ErrMsg='Closest SubDyn Node is node '//Num2LStr(iNode)//', which is more than 0.1m away from soildyn point '//num2lstr(iiNode); - ErrStat=ErrID_Fatal; return - endif - Init%Soil_Nodes(iiNode) = iNode - ! --- Insert/remove from matrices - nDOF=size(NodesDOF(iNode)%List) - if (nDOF/=6) then - ErrMsg='Soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; - ErrStat=ErrID_Fatal; return - endif - K_soil = Init%Soil_K(1:6,1:6,iiNode) - if (present(Substract)) then - if (Substract) then - K_soil = - K_soil - endif - endif - do I = 1, 6 - iDOF = NodesDOF(iNode)%List(I) ! DOF index - do J = 1, 6 - jDOF = NodesDOF(iNode)%List(J) ! DOF index - K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) - enddo - enddo - if (.not.present(Substract)) then - CALL WrScr(' Soil stiffness inserted at SubDyn node '//trim(Num2LStr(iNode))) - endif - enddo - endif -contains - !> Convert a flatten array of 21 values into a symmetric 6x6 matrix - SUBROUTINE Array21_to_6by6(A21, M66) - use NWTC_LAPACK, only: LAPACK_TPTTR - real(ReKi), dimension(21) , intent(in) :: A21 - real(ReKi), dimension(6,6), intent(out) :: M66 - integer :: j - M66 = 0.0_ReKi - ! Reconstruct from sparse elements - CALL LAPACK_TPTTR('U',6,A21,M66,6, ErrStat, ErrMsg) - ! Ensuring symmetry - do j=1,6 - M66(j,j) = M66(j,j)/2 - enddo - M66=M66+TRANSPOSE(M66) - END SUBROUTINE Array21_to_6by6 -END SUBROUTINE InsertSoilMatrices - -!------------------------------------------------------------------------------------------------------ -!> Find closest node index to a point, returns distance as well -SUBROUTINE FindClosestNodes(Point, Nodes, iNode, Dist) - real(ReKi), dimension(3), intent(IN ) :: Point !< Point coordinates - real(ReKi), dimension(:,:), intent(IN ) :: Nodes !< List of nodes, Positions are in columns 2-4... - integer(IntKi), intent( OUT) :: iNode !< Index of closest node - real(ReKi), intent( OUT) :: Dist !< Distance from Point to node iNode - integer(IntKi) :: I - real(ReKi) :: min_dist, loc_dist - ! - min_dist=999999._ReKi - iNode=-1 - do i = 1, size(Nodes,1) - loc_dist = sqrt((Point(1) - Nodes(i,2))**2 + (Point(2) - Nodes(i,3))**2+ (Point(3) - Nodes(i,4))**2) - if (loc_dist Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF -SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) - use IntegerList, only: init_list, find, pop, destroy_list, len - use IntegerList, only: print_list - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType),target,INTENT(INOUT) :: p - type(IList), dimension(:), INTENT(IN ) :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination - ! Local - real(ReKi), dimension(:,:), allocatable :: Tc - integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - integer(IntKi), dimension(:), allocatable :: IDOFOld !< - integer(IntKi), dimension(:), pointer :: IDOFNew !< - real(ReKi), dimension(6,6) :: I6 !< Identity matrix of size 6 - integer(IntKi) :: iPrev - type(IList) :: IRA !< list of rigid assembly indices to process - integer(IntKi) :: aID, ia ! assembly ID, and index in IRA - integer(IntKi) :: iNode - integer(IntKi) :: er !< Index of one rigid element belong to a rigid assembly - integer(IntKi) :: JType - integer(IntKi) :: I - integer(IntKi) :: nc !< Number of DOF after constraints applied - integer(IntKi) :: nj - real(ReKi) :: phat(3) !< Directional vector of the joint - type(IList), dimension(:), allocatable :: RA_DOFtilde ! DOF indices for each rigid assembly, in reduced system - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! --- Misc inits - nullify(IDOFNew) - I6(1:6,1:6)=0; do i = 1,6 ; I6(i,i)=1_ReKi; enddo ! I6 = eye(6) - allocate(p%NodesDOFtilde(1:p%nNodes), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each joint, in reduced system - allocate(RA_DOFtilde(1:size(RA)), stat=ErrStat2); if(Failed()) return; ! Indices of DOF for each rigid assmbly, in reduced system - - p%nDOF_red = nDOF_ConstraintReduced() - if (DEV_VERSION) then - print*,'nDOF constraint elim', p%nDOF_red , '/' , p%nDOF - endif - CALL AllocAry( Tred, p%nDOF, p%nDOF_red, 'p%T_red', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - Tred=0 - call init_list(IRA, size(RA), 0, ErrStat2, ErrMsg2); if(Failed()) return; - IRA%List(1:size(RA)) = (/(ia , ia = 1,size(RA))/) - if (DEV_VERSION) then - call print_list(IRA, 'List of RA indices') - endif - - ! --- For each node: - ! - create list of indices I in the assembled vector of DOF - ! - create list of indices Itilde in the reduced vector of DOF - ! - increment iPrev by the number of DOF of Itilde - iPrev =0 - do iNode = 1, p%nNodes - if (allocated(Tc)) deallocate(Tc) - if (allocated(IDOFOld)) deallocate(IDOFOld) - JType = int(Init%Nodes(iNode,iJointType)) - if(JType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p, er)) then - ! --- Joint involved in a rigid link assembly - aID = RAm1(er) - if (aID<0) then - call Fatal('No rigid assembly attributed to node'//trim(Num2LStr(iNode))//'. RAm1 wrong'); return - endif - ia = find(IRA, aID, ErrStat2, ErrMsg2); if(Failed()) return - if (DEV_VERSION) then - print*,'Node',iNode, 'is involved in RA:', aID, '. Index in list of RA to process', ia - endif - if ( ia <= 0) then - ! This rigid assembly has already been processed - ! OLD: The DOF list is taken from the stored RA DOF list - ! call init_list(p%NodesDOFtilde(iNode), RA_DOFtilde(aID)%List, ErrStat2, ErrMsg2) - ! NEW: this node has no DOFs - call init_list(p%NodesDOFtilde(iNode), 0, 0, ErrStat2, ErrMsg2) - if (DEV_VERSION) then - print*,'The RA',aID,', has already been processed!' - print*,'N',iNode,'I ',p%NodesDOF(iNode)%List(1:6) - print*,'N',iNode,'It',RA_DOFtilde(aID)%List - endif - cycle ! We pass to the next joint - else - call RAElimination( RA(aID)%List, Tc, INodesID, Init, p, ErrStat2, ErrMsg2); if(Failed()) return; - aID = pop(IRA, ia, ErrStat2, ErrMsg2) ! this assembly has been processed - nj = size(INodesID) - allocate(IDOFOld(1:6*nj)) - do I=1, nj - IDOFOld( (I-1)*6+1 : I*6 ) = p%NodesDOF(INodesID(I))%List(1:6) - enddo - - ! Storing DOF list for this RA (Note: same as NodesDOFtilde below) - nc=size(Tc,2) - call init_list(RA_DOFtilde(aID), (/ (iprev + i, i=1,nc) /), ErrStat2, ErrMsg2); - - endif - else - ! --- Regular cantilever joint - ! TODO/NOTE: We could apply fixed constraint/BC here, returning Tc as a 6xn matrix with n<6 - ! Extreme case would be Tc: 6*0, in which case NodesDOFtilde would be empty ([]) - allocate(Tc(1:6,1:6)) - allocate(IDOFOld(1:6)) - Tc=I6 - IDOFOld = p%NodesDOF(iNode)%List(1:6) - endif - else - ! --- Ball/Pin/Universal joint - allocate(IDOFOld(1:len(p%NodesDOF(iNode)))) - IDOFOld(:) = p%NodesDOF(iNode)%List(:) - phat = Init%Nodes(iNode, iJointDir:iJointDir+2) - call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return - endif - nc=size(Tc,2) - call init_list(p%NodesDOFtilde(iNode), nc, 0, ErrStat2, ErrMsg2) - p%NodesDOFtilde(iNode)%List(1:nc) = (/ (iprev + i, i=1,nc) /) - IDOFNew => p%NodesDOFtilde(iNode)%List(1:nc) ! alias to shorten notations - !print*,'N',iNode,'I ',IDOFOld - !print*,'N',iNode,'It',IDOFNew - Tred(IDOFOld, IDOFNew) = Tc - iPrev = iPrev + nc - enddo - ! --- Safety checks - if (len(IRA)>0) then - call Fatal('Not all rigid assemblies were processed'); return - endif - if (iPrev /= p%nDOF_red) then - call Fatal('Inconsistency in number of reduced DOF'); return - endif - call CleanUp_BuildTMatrix() -contains - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'BuildTMatrix') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp_BuildTMatrix() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - CHARACTER(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'BuildTMatrix'); - END SUBROUTINE Fatal - - SUBROUTINE CleanUp_BuildTMatrix() - nullify(IDOFNew) - call destroy_list(IRA, ErrStat2, ErrMsg2) - if (allocated(Tc) ) deallocate(Tc) - if (allocated(IDOFOld)) deallocate(IDOFOld) - if (allocated(INodesID)) deallocate(INodesID) - END SUBROUTINE CleanUp_BuildTMatrix - - !> Returns number of DOF after constraint reduction (via the matrix T) - INTEGER(IntKi) FUNCTION nDOF_ConstraintReduced() - integer(IntKi) :: iNode - integer(IntKi) :: ia ! Index on rigid link assembly - integer(IntKi) :: m ! Number of elements connected to a joint - integer(IntKi) :: NodeType - nDOF_ConstraintReduced = 0 - - ! Rigid assemblies contribution - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6*size(RA) - - ! Contribution from all the other joints - do iNode = 1, p%nNodes - m = Init%NodesConnE(iNode,1) ! Col1: number of elements connected to this joint - NodeType = Init%Nodes(iNode,iJointType) - - if (NodeType == idJointPin ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 5 + 1*m - print*,'Node',iNode, 'is a pin joint, number of members involved: ', m - - elseif(NodeType == idJointUniversal ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 4 + 2*m - print*,'Node',iNode, 'is an universal joint, number of members involved: ', m - - elseif(NodeType == idJointBall ) then - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 3 + 3*m - print*,'Node',iNode, 'is a ball joint, number of members involved: ', m - - elseif(NodeType == idJointCantilever ) then - if ( NodeHasRigidElem(iNode, Init, p, er)) then - ! This joint is involved in a rigid link assembly, we skip it (accounted for above) - print*,'Node',iNode, 'is involved in a Rigid assembly' - else - ! That's a regular Cantilever joint - nDOF_ConstraintReduced = nDOF_ConstraintReduced + 6 - !print*,'Node',iNode, 'is a regular cantilever' - endif - else - ErrMsg='Wrong joint type'; ErrStat=ErrID_Fatal - endif - end do - END FUNCTION nDOF_ConstraintReduced -END SUBROUTINE BuildTMatrix -!------------------------------------------------------------------------------------------------------ -!> Assemble stiffness and mass matrix, and gravity force vector -SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) - use IntegerList, only: len - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType),target,INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ! Varaibles for rigid assembly - type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - real(ReKi), dimension(:,:), allocatable :: MM, KK - real(ReKi), dimension(:), allocatable :: FF - integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF - ErrStat = ErrID_None - ErrMsg = "" - - ! Setup list of rigid link assemblies (RA) and the inverse function RA^{-1} - call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - - call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return - - ! --- DOF elimination for system matrices and RHS vector - ! Temporary backup of M and K of full system - call move_alloc(Init%M, MM) - call move_alloc(Init%K, KK) - call move_alloc(Init%FG, FF) - ! Reallocating - nDOF = p%nDOF_red - CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix - CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - ! Elimination - Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) - Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) - Init%FG = matmul(transpose(p%T_red), FF) - Init%D = 0 !< Used for additional stiffness - - ! --- Triggers for storage of DOF indices, replacing with indices in constrained system - CALL ReInitBCs(Init, p) - CALL ReInitIntFc(Init, p) - - ! --- Creating a convenient Map from DOF to Nodes - call AllocAry(p%DOFtilde2Nodes, p%nDOF_red, 3, 'DOFtilde2Nodes', ErrStat2, ErrMsg2); if(Failed()) return; - p%DOFtilde2Nodes=-999 - do iNode=1,p%nNodes - nDOFPerNode = len(p%NodesDOFtilde(iNode)) - do iiDOF = 1, nDOFPerNode - iDOF = p%NodesDOFtilde(iNode)%List(iiDOF) - p%DOFtilde2Nodes(iDOF,1) = iNode ! First column is Node index - p%DOFtilde2Nodes(iDOF,2) = nDOFPerNode ! Second column is number of DOF per node - p%DOFtilde2Nodes(iDOF,3) = iiDOF ! Third column is number of DOF per node - enddo - enddo - - call CleanUp_DirectElimination() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'DirectElimination') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp_DirectElimination() - END FUNCTION Failed - SUBROUTINE CleanUp_DirectElimination() - ! Cleaning up memory - if (allocated(MM )) deallocate(MM ) - if (allocated(KK )) deallocate(KK ) - if (allocated(FF )) deallocate(FF ) - if (allocated(RA )) deallocate(RA ) - if (allocated(RAm1)) deallocate(RAm1) - if (allocated(RA )) deallocate(RA ) - END SUBROUTINE CleanUp_DirectElimination - - !> Reset DOF indices after elimination, does not change the BC - SUBROUTINE ReInitBCs(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_C - iNode = p%Nodes_C(I,1) ! Node index - DO J = 1, 6 ! TODO NOTE here assumptions that 6 DOF are present - Init%BCs( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (constrained) - ENDDO - ENDDO - END SUBROUTINE ReInitBCs - - !> Reset DOF indices after elimination - SUBROUTINE ReInitIntFc(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_I - iNode = p%Nodes_I(I,1) ! Node index - DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFtilde(iNode)%List(J) ! DOF number (unconstrained) - ENDDO - ENDDO - END SUBROUTINE ReInitIntFc -END SUBROUTINE DirectElimination - -!------------------------------------------------------------------------------------------------------ -!> Returns constraint matrix Tc for a rigid assembly (RA) formed by a set of elements. -!! x_c = Tc.x_c_tilde -!! where x_c are all the DOF of the rigid assembly, and x_c_tilde are the 6 reduced DOF (leader DOF) -SUBROUTINE RAElimination(Elements, Tc, INodesID, Init, p, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get, unique, find - integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements - real(ReKi), dimension(:,:), allocatable :: Tc - integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements - TYPE(SD_InitType), INTENT(IN ) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Local variables - type(IList) :: LNodesID !< List of nodes id involved in element - type(IList) :: LNodesInterf !< List of nodes id involved in interface - integer(IntKi) :: NodeID !< NodeID - integer(IntKi) :: iTmp !< Temporary index - integer(IntKi) :: iNodeID !< Loop index on node ID list - integer(IntKi) :: iiMainNode !< Index of main node selected for rigid assembly within INodesID list - integer(IntKi) :: iMainNode !< Main node index - integer(IntKi) :: nNodes !< Number of Nodes involved in RA - integer(IntKi) :: iFound !< Loop index on node ID list - integer(IntKi) :: i !< Loop index - real(ReKi) :: TRigid(6,6) ! Transformation matrix such that xi = T.x1 - real(ReKi) :: P1(3), Pi(3) ! Nodal points - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - - ! --- List of nodes stored first in LINodes than moved to INodes - LNodesID = NodesList(p, Elements) - if (DEV_VERSION) then - print*,'Nodes involved in assembly (bfr1) ',LNodesID%List - endif - call unique(LNodesID, ErrStat2, ErrMsg2); - if (DEV_VERSION) then - print*,'Nodes involved in assembly (bfr2) ',LNodesID%List - endif - - !--- Look for potential interface node - call init_list(LNodesInterf, 0, 0, ErrStat2, ErrMsg2); - do iNodeID = 1, len(LNodesID) - NodeID = LNodesID%List(iNodeID) - iFound = FINDLOCI( p%Nodes_I(:,1), NodeID) - if (iFound>0) then - call append(LNodesInterf, NodeID, ErrStat2, ErrMsg2) - ! This node is an interface node - print*,'Node',NodeID, 'is an interface node, selecting it for the rigid assembly' - endif - enddo - - ! --- Decide which node will be the main node of the rigid assembly - if (len(LNodesInterf)==0) then - iiMainNode = 1 ! By default we select the first node - else if (len(LNodesInterf)==1) then - ! Finding the index of the interface node - iMainNode = pop(LNodesInterf, ErrStat2, ErrMsg2) - iiMainNode = find(LNodesID, iMainNode, ErrStat2, ErrMsg2); - else - ErrStat=ErrID_Fatal - ErrMsg='Cannot have several interface nodes linked within a same rigid assembly' - return - endif - call destroy_list(LNodesInterf, ErrStat2, ErrMsg2) - - ! --- Extracting index array from list - if (allocated(INodesID)) deallocate(INodesID) - call move_alloc(LNodesID%List, INodesID) - call destroy_list(LNodesID, ErrStat2, ErrMsg2) - - ! --- Order list of joints with main node first (swapping iMainNode with INodes(1)) - iTmp = INodesID(1) - INodesID(1) = INodesID(iiMainNode) - INodesID(iiMainNode) = iTmp - if (DEV_VERSION) then - print*,'Nodes involved in assembly (after)',INodesID - endif - - ! --- Building Transformation matrix - nNodes =size(INodesID) - allocate(Tc(6*nNodes,6)) - Tc(:,:)=0 - ! I6 for first node - do i = 1,6 ; Tc(i,i)=1_ReKi; enddo ! I6 = eye(6) - ! Rigid transformation matrix for the other nodes - P1 = Init%Nodes(INodesID(1), 2:4) ! reference node coordinates - do i = 2, nNodes - Pi = Init%Nodes(INodesID(i), 2:4) ! follower node coordinates - call GetRigidTransformation(P1, Pi, TRigid, ErrStat2, ErrMsg2) - Tc( ((i-1)*6)+1:6*i, 1:6) = TRigid(1:6,1:6) - enddo -END SUBROUTINE RAElimination -!------------------------------------------------------------------------------------------------------ -!> Returns constraint matrix Tc for a joint involving several Elements -!! x_c = Tc.x_c_tilde -!! where -! x_c are all the DOF of the joint (3 translation + 3*m, m the number of elements) -! x_c_tilde are the nc reduced DOF -SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get - integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements involved at a joint - integer(IntKi), INTENT(IN ) :: JType !< Joint type - real(ReKi), INTENT(IN ) :: phat(3) !< Directional vector of the joint - TYPE(SD_InitType), INTENT(IN ) :: Init - TYPE(SD_ParameterType), INTENT(IN ) :: p - real(ReKi), dimension(:,:), allocatable :: Tc !< Transformation matrix from eliminated to full - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Local variables - !type(IList) :: I !< List of indices for Nodes involved in interface - integer(IntKi) :: i, j, ie, ne !< Loop index - integer(IntKi) :: nDOFr !< Number of reduced DOF - integer(IntKi) :: nDOFt !< Number of total DOF *nreduced) - real(ReKi) :: e1(3), e2(3), e3(3) ! forming orthonormal basis with phat - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - real(LaKi), dimension(:,:), allocatable :: Tc_rot !< Part of Tc just for rotational DOF - real(LaKi), dimension(:,:), allocatable :: Tc_rot_m1 !< Inverse of Tc_rot - real(ReKi) :: ColMean - ErrStat = ErrID_None - ErrMsg = "" - - ne = Elements(1) ! TODO TODO - nDOFt = 3 + 3*ne - - ! The elements already share the same translational DOF - - if (JType == idJointPin ) then - nDOFr = 5 + 1*ne - allocate(Tc (nDOFt, nDOFr)); - allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); - Tc(:,:)=0 - Tc_rot_m1(:,:)=0 - - ! Normalizing - e3= phat/sqrt(phat(1)**2 + phat(2)**2 + phat(3)**2) - call GetOrthVectors(e3, e1, e2, ErrStat2, ErrMsg2); - ! Forming Tcm1, inverse of Tc - do ie=1,ne - Tc_rot_m1(1 , (ie-1)*3+1:ie*3 ) = e1(1:3)/ne - Tc_rot_m1(2 , (ie-1)*3+1:ie*3 ) = e2(1:3)/ne - Tc_rot_m1(ie+2, (ie-1)*3+1:ie*3 ) = e3(1:3) - enddo - ! Pseudo inverse: - call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) - ! --- Forming Tc - do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF - Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) - deallocate(Tc_rot) - deallocate(Tc_rot_m1) - - elseif(JType == idJointUniversal ) then - if (ne/=2) then - ErrMsg='JointElimination: universal joints should only connect two elements.'; ErrStat=ErrID_Fatal - return - endif - nDOFr = 4 + 2*ne - allocate(Tc(nDOFt, nDOFr)); - allocate(Tc_rot_m1(nDOFr-3, nDOFt-3)); - Tc(:,:)=0 - Tc_rot_m1(:,:)=0 ! Important init - ! Forming the inverse of Tc_rot - Tc_rot_m1(1,1:3) = p%ElemProps(Elements(1))%DirCos(:,3)/2._ReKi - Tc_rot_m1(1,4:6) = p%ElemProps(Elements(2))%DirCos(:,3)/2._ReKi - Tc_rot_m1(2,1:3) = p%ElemProps(Elements(1))%DirCos(:,1) - Tc_rot_m1(3,1:3) = p%ElemProps(Elements(1))%DirCos(:,2) - Tc_rot_m1(4,4:6) = p%ElemProps(Elements(2))%DirCos(:,1) - Tc_rot_m1(5,4:6) = p%ElemProps(Elements(2))%DirCos(:,2) - ! Pseudo inverse - call PseudoInverse(Tc_rot_m1, Tc_rot, ErrStat2, ErrMsg2) - ! --- Forming Tc - do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF - Tc(4:nDOFt,4:nDOFr)=Tc_rot(1:nDOFt-3, 1:nDOFr-3) - deallocate(Tc_rot) - deallocate(Tc_rot_m1) - - elseif(JType == idJointBall ) then - nDOFr = 3 + 3*ne - allocate(Tc(nDOFt, nDOFr)); - Tc(:,:)=0 - do i = 1,3 ; Tc(i,i)=1_ReKi; enddo ! I3 for translational DOF - do i = 3,nDOFr; Tc(i,i)=1_ReKi; enddo ! Identity for other DOF as well - - else - ErrMsg='JointElimination: Wrong joint type'; ErrStat=ErrID_Fatal - endif - !do i=1,nDOFt - ! print*,'Tc',Tc(i,:) - !enddo - ! --- Safety check - do j =1, size(Tc,2) - ColMean=0; do i=1,size(Tc,1) ; ColMean = ColMean + abs(Tc(i,j)); enddo - ColMean = ColMean/size(Tc,1) - if (ColMean<1e-6) then - ErrMsg='JointElimination: a reduced degree of freedom has a singular mapping.'; ErrStat=ErrID_Fatal - return - endif - enddo - -END SUBROUTINE JointElimination - -!------------------------------------------------------------------------------------------------------ -!> Setup a list of rigid link assemblies (RA) -!! RA(a) = [e1,..,en] : list of elements that form the rigid assembly of index "a" -SUBROUTINE RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat, ErrMsg) - use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get - TYPE(SD_InitType), INTENT(INOUT) :: Init - TYPE(SD_ParameterType), INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly - integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - ! Local variables - type(IList) :: Er !< List of rigid elements - type(IList) :: Ea !< List of elements in a rigid assembly - integer(IntKi) :: nRA !< Number of rigid assemblies - integer(IntKi) :: ie !< Index on elements - integer(IntKi) :: ia !< Index on assemblies - integer(IntKi) :: e0 !< Index of an element - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - allocate(RAm1(1:Init%NElem)) - RAm1(1:Init%NElem) = -1 - - ! --- Establish a list of rigid link elements - Er = RigidLinkElements(Init, p, ErrStat2, ErrMsg2) - nRA=0 - do while (len(Er)>0) - nRA=nRA+1 - ! Creating List Ea of elements of a given assembly - call init_list(Ea, 0, 0, ErrStat2, ErrMsg2); - e0 = pop(Er, ErrStat2, ErrMsg2); - call append(Ea, e0, ErrStat2, ErrMsg2); - call AddNeighbors(e0, Er, Ea) - if (DEV_VERSION) then - call print_list(Ea,'Rigid assembly (loop 1)') - endif - do ie = 1, len(Ea) - e0 = get(Ea, ie, ErrStat2, ErrMsg2) - RAm1(e0) = nRA ! Index of rigid assembly that this element belongs to - enddo - call destroy_list(Ea, ErrStat2, ErrMsg2) - enddo - call destroy_list(Er, ErrStat2, ErrMsg2) - - ! --- Creating RA, array of lists of assembly elements. - ! Note: exactly the same as all the Ea created above, but we didn't know the total number of RA - allocate(RA(1:nRA)) - do ia = 1, nRA - call init_list(RA(ia), 0, 0, ErrStat2, ErrMsg2) - enddo - do ie = 1, Init%NElem - ia = RAm1(ie) ! Index of the assembly the element belongs to: RA^{-1}(ie) = ia - if (ia>0) then - call append(RA(ia), ie, ErrStat2, ErrMsg2) - endif - enddo - if (DEV_VERSION) then - do ia = 1, nRA - call print_list(RA(ia),'Rigid assembly (loop 2)') - enddo - endif -CONTAINS - !> The neighbor-elements of element e0 (that are found within the list Er) are added to the list Ea - RECURSIVE SUBROUTINE AddNeighbors(e0, Er, Ea) - integer(IntKi), intent(in) :: e0 !< Index of an element - type(IList), intent(inout) :: Er !< List of rigid elements - type(IList), intent(inout) :: Ea !< List of elements in a rigid assembly - type(IList) :: En !< List of neighbors of e0 - integer (IntKi) :: ik - integer (IntKi) :: ek, ek2 - integer (IntKi) :: iWhichNode_e0, iWhichNode_ek - call init_list(En, 0, 0, ErrStat2, ErrMsg2) - ! Loop through all elements, setup list of e0-neighbors, add them to Ea, remove them from Er - ik=0 - do while (ik< len(Er)) - ik=ik+1 - ek = Er%List(ik) - if (ElementsConnected(p, e0, ek, iWhichNode_e0, iWhichNode_ek)) then - if (DEV_VERSION) then - print*,'Element ',ek,'is connected to element',e0,'via its node',iWhichNode_ek - endif - ! Remove element from Er (a rigid element can belong to only one assembly) - ek2 = pop(Er, ik, ErrStat2, ErrMsg2) ! same as ek before - ik=ik-1 - if (ek/=ek2) then - print*,'Problem in popping',ek,ek2 - STOP - endif - call append(En, ek, ErrStat2, ErrMsg2) - call append(Ea, ek, ErrStat2, ErrMsg2) - endif - enddo - ! Loop through neighbors and recursively add neighbors of neighbors - do ik = 1, len(En) - ek = En%List(ik) - call AddNeighbors(ek, Er, Ea) - enddo - call destroy_list(En, ErrStat2, ErrMsg2) - END SUBROUTINE AddNeighbors - -END SUBROUTINE RigidLinkAssemblies - - -!------------------------------------------------------------------------------------------------------ -!> Add stiffness and damping to some joints -SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) - TYPE(SD_ParameterType),target,INTENT(IN ) :: p - TYPE(SD_InitType), INTENT(INOUT) :: Init - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - integer(IntKi) :: iNode, JType, iStart - real(ReKi) :: StifAdd, DampAdd - integer(IntKi), dimension(:), pointer :: Ifreerot - ErrStat = ErrID_None - ErrMsg = "" - do iNode = 1, p%nNodes - JType = int(Init%Nodes(iNode,iJointType)) - StifAdd = Init%Nodes(iNode, iJointStiff) - DampAdd = Init%Nodes(iNode, iJointDamp ) - if(JType == idJointCantilever ) then - ! Cantilever joints should not have damping or stiffness - if(StifAdd>0) then - ErrMsg='InsertJointStiffDamp: Additional stiffness should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; - return - endif - if(DampAdd>0) then - ErrMsg='InsertJointStiffDamp: Additional damping should be 0 for cantilever joints. Index of problematic node: '//trim(Num2LStr(iNode)); ErrStat=ErrID_Fatal; - return - endif - else - ! Ball/Univ/Pin joints have damping/stiffness inserted at indices of "free rotation" - if ( JType == idJointBall ) then; iStart=4; - else if ( JType == idJointUniversal ) then; iStart=5; - else if ( JType == idJointPin ) then; iStart=6; - endif - Ifreerot=>p%NodesDOFtilde(iNode)%List(iStart:) - ! Ball/Pin/Universal joints - if(StifAdd>0) then - print*,'StiffAdd, Node',iNode,StifAdd, Ifreerot - Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + StifAdd - endif - if(DampAdd>0) then - print*,'DampAdd, Node',iNode,DampAdd, Ifreerot - Init%D(Ifreerot,Ifreerot) = Init%D(Ifreerot,Ifreerot) +DampAdd - endif - endif - enddo -END SUBROUTINE InsertJointStiffDamp - -SUBROUTINE ElemM(ep, Me) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Me(12, 12) - REAL(ReKi) :: L0, Eps0 - if (ep%eType==idMemberBeam) then - !Calculate Ke, Me to be used for output - CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) - - else if (ep%eType==idMemberCable) then - Eps0 = ep%T0/(ep%YoungE*ep%Area) - L0 = ep%Length/(1+Eps0) ! "rest length" for which pretension would be 0 - CALL ElemM_Cable(ep%Area, L0, ep%rho, ep%DirCos, Me) - - else if (ep%eType==idMemberRigid) then - if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then - Me=0.0_ReKi - else - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) - !CALL ElemM_(A, L, rho, DirCos, Me) - endif - endif -END SUBROUTINE ElemM - -SUBROUTINE ElemK(ep, Ke) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Ke(12, 12) - - if (ep%eType==idMemberBeam) then - CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) - - else if (ep%eType==idMemberCable) then - CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) - - else if (ep%eType==idMemberRigid) then - Ke = 0.0_ReKi - endif -END SUBROUTINE ElemK - -SUBROUTINE ElemF(ep, gravity, Fg, Fo) - TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity - REAL(ReKi), INTENT(OUT) :: Fg(12) - REAL(ReKi), INTENT(OUT) :: Fo(12) - if (ep%eType==idMemberBeam) then - Fo(1:12)=0 - else if (ep%eType==idMemberCable) then - CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) - else if (ep%eType==idMemberRigid) then - Fo(1:12)=0 - endif - CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) -END SUBROUTINE ElemF - -END MODULE SD_FEM diff --git a/modules/subdyn/src_soildyn/SubDyn.f90 b/modules/subdyn/src_soildyn/SubDyn.f90 deleted file mode 100644 index 75ae62056..000000000 --- a/modules/subdyn/src_soildyn/SubDyn.f90 +++ /dev/null @@ -1,2885 +0,0 @@ -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -!> SubDyn is a time-domain structural-dynamics module for multi-member fixed-bottom substructures. -!! SubDyn relies on two main engineering schematizations: (1) a linear frame finite-element beam model (LFEB), and -!! (2) a dynamics system reduction via Craig-Bampton's (C-B) method, together with a Static-Improvement method, greatly reducing -!! the number of modes needed to obtain an accurate solution. -Module SubDyn - - USE NWTC_Library - USE SubDyn_Types - USE SubDyn_Output - USE SubDyn_Tests - USE SD_FEM - - IMPLICIT NONE - - PRIVATE - - !............................ - ! NOTE: for debugging, add preprocessor definition SD_SUMMARY_DEBUG - ! this will add additional matrices to the SubDyn summary file. - !............................ - TYPE(ProgDesc), PARAMETER :: SD_ProgDesc = ProgDesc( 'SubDyn', '', '' ) - - ! ..... Public Subroutines ................................................................................................... - PUBLIC :: SD_Init ! Initialization routine - PUBLIC :: SD_End ! Ending routine (includes clean up) - PUBLIC :: SD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating - PUBLIC :: SD_CalcOutput ! Routine for computing outputs - PUBLIC :: SD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states - -CONTAINS - -SUBROUTINE CreateTPMeshes( TP_RefPoint, inputMesh, outputMesh, ErrStat, ErrMsg ) - REAL(ReKi), INTENT( IN ) :: TP_RefPoint(3) - TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%TPMesh - TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y1Mesh - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! NOTE: The initialization of the fields for these meshes is to be handled by FAST/Driver - CALL MeshCreate( BlankMesh = inputMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = 1 & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. ) - ! Create the node and mesh element, note: assumes identiy matrix as reference orientation - CALL MeshPositionNode (inputMesh, 1, TP_RefPoint, ErrStat, ErrMsg); IF(ErrStat>=AbortErrLev) return - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, 1) - CALL MeshCommit( inputMesh, ErrStat, ErrMsg); if(ErrStat >= AbortErrLev) return - - ! Create the Transition Piece reference point output mesh as a sibling copy of the input mesh - CALL MeshCopy ( SrcMesh = inputMesh & - ,DestMesh = outputMesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. ) -END SUBROUTINE CreateTPMeshes -!--------------------------------------------------------------------------- -!> Create output (Y2, for motion) and input (u, for forces)meshes, based on SubDyn nodes -!! Ordering of nodes is the same as SubDyn (used to be : I L C) -SUBROUTINE CreateInputOutputMeshes( NNode, Nodes, inputMesh, outputMesh, ErrStat, ErrMsg ) - INTEGER(IntKi), INTENT( IN ) :: NNode !total number of nodes in the structure, used to size the array Nodes, i.e. its rows - REAL(ReKi), INTENT( IN ) :: Nodes(NNode, JointsCol) - TYPE(MeshType), INTENT( INOUT ) :: inputMesh ! u%LMesh - TYPE(MeshType), INTENT( INOUT ) :: outputMesh ! y%Y2Mesh - INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - REAL(ReKi), dimension(3) :: Point - INTEGER :: I, iOffset, iNode ! generic counter variable - INTEGER :: nodeIndx - - CALL MeshCreate( BlankMesh = inputMesh & - ,IOS = COMPONENT_INPUT & - ,Nnodes = size(Nodes,1) & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,Force = .TRUE. & - ,Moment = .TRUE. ) - - DO I = 1,size(Nodes,1) - Point = Nodes(I, 2:4) - CALL MeshPositionNode(inputMesh, I, Point, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - CALL MeshConstructElement(inputMesh, ELEMENT_POINT, ErrStat, ErrMsg, I) - ENDDO - CALL MeshCommit ( inputMesh, ErrStat, ErrMsg); IF(ErrStat/=ErrID_None) RETURN - - ! Create the Interior Points output mesh as a sibling copy of the input mesh - CALL MeshCopy ( SrcMesh = inputMesh & - ,DestMesh = outputMesh & - ,CtrlCode = MESH_SIBLING & - ,IOS = COMPONENT_OUTPUT & - ,ErrStat = ErrStat & - ,ErrMess = ErrMsg & - ,TranslationDisp = .TRUE. & - ,Orientation = .TRUE. & - ,TranslationVel = .TRUE. & - ,RotationVel = .TRUE. & - ,TranslationAcc = .TRUE. & - ,RotationAcc = .TRUE. ) - - ! Set the Orientation (rotational) field for the nodes based on assumed 0 (rotational) deflections - !Identity should mean no rotation, which is our first guess at the output -RRD - CALL Eye( outputMesh%Orientation, ErrStat, ErrMsg ) - -END SUBROUTINE CreateInputOutputMeshes -!--------------------------------------------------------------------------- -!> This routine is called at the start of the simulation to perform initialization steps. -!! The parameters are set here and not changed during the simulation. -!! The initial states and initial guess for the input are defined. -SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(IN ) :: InitInput !< Input data for initialization routine - TYPE(SD_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined - TYPE(SD_ParameterType), INTENT( OUT) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states - TYPE(SD_DiscreteStateType), INTENT( OUT) :: xd !< Initial discrete states - TYPE(SD_ConstraintStateType), INTENT( OUT) :: z !< Initial guess of the constraint states - TYPE(SD_OtherStateType), INTENT( OUT) :: OtherState !< Initial other states - TYPE(SD_OutputType), INTENT( OUT) :: y !< Initial system outputs (outputs are not calculated; - !! only the output mesh is initialized) - REAL(DbKi), INTENT(INOUT) :: Interval !< Coupling interval in seconds: the rate that - !! (1) Mod1_UpdateStates() is called in loose coupling & - !! (2) Mod1_UpdateDiscState() is called in tight coupling. - !! Input is the suggested time from the glue code; - !! Output is the actual coupling interval that will be used - !! by the glue code. - TYPE(SD_MiscVarType), INTENT( OUT) :: m !< Initial misc/optimization variables - TYPE(SD_InitOutputType), INTENT( OUT) :: InitOut !< Output for initialization routine - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_InitType) :: Init - TYPE(CB_MatArrays) :: CBparams ! CB parameters to be stored and written to summary file - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - - ! Initialize variables - ErrStat = ErrID_None - ErrMsg = "" - - - ! Initialize the NWTC Subroutine Library - CALL NWTC_Init( ) - - ! Display the module information - CALL DispNVD( SD_ProgDesc ) - InitOut%Ver = SD_ProgDesc - - ! --- Test TODO remove me in the future - if (DEV_VERSION) then - CALL SD_Tests(ErrStat2, ErrMsg2); if(Failed()) return - endif - - ! transfer glue-code information to data structure for SubDyn initialization: - Init%g = InitInput%g - Init%TP_RefPoint = InitInput%TP_RefPoint - Init%SubRotateZ = InitInput%SubRotateZ - if ((allocated(InitInput%SoilStiffness)) .and. (InitInput%SoilMesh%Initialized)) then - ! Soil Mesh and Stiffness - ! SoilMesh has N points. Correspond in order to the SoilStiffness matrices passed in - ! %RefOrientation is the identity matrix (3,3,N) - ! %Position is the reference position (3,N) - ! Maybe some logic to make sure these points correspond roughly to nodes -- though this may not be true for a long pile into the soil with multiple connection points - ! Note: F = -kx whre k is the relevant 6x6 matrix from SoilStiffness - call AllocAry(Init%Soil_K, 6,6, size(InitInput%SoilStiffness,3), 'Soil_K', ErrStat2, ErrMsg2); - call AllocAry(Init%Soil_Points, 3, InitInput%SoilMesh%NNodes, 'Soil_Points', ErrStat2, ErrMsg2); - call AllocAry(Init%Soil_Nodes, InitInput%SoilMesh%NNodes, 'Soil_Nodes' , ErrStat2, ErrMsg2); - Init%Soil_K = InitInput%SoilStiffness ! SoilStiffness is dimensioned (6,6,N) - Init%Soil_Points = InitInput%SoilMesh%Position ! SoilStiffness is dimensioned (6,6,N) - Init%Soil_Nodes = -1 ! Will be determined in InsertSoilMatrices, Nodes not known yet - if (size(Init%Soil_K,3) /= size(Init%Soil_Points,2)) then - ErrStat2=ErrID_Fatal; ErrMsg2='Number of soil points inconsistent with number of soil stiffness matrix' - endif - if (Failed()) return - endif - - !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. - IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) - - ! Establish the GLUECODE requested/suggested time step. This may be overridden by SubDyn based on the SDdeltaT parameter of the SubDyn input file. - Init%DT = Interval - IF ( LEN_TRIM(Init%RootName) == 0 ) THEN - CALL GetRoot( InitInput%SDInputFile, Init%RootName ) - ELSE - Init%RootName = TRIM(InitInput%RootName)//'.SD' - END IF - - ! Parse the SubDyn inputs - CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! -------------------------------------------------------------------------------- - ! --- Manipulation of Init and parameters - ! -------------------------------------------------------------------------------- - ! Discretize the structure according to the division size - ! sets p%nNodes, Init%NElm - CALL SD_Discrt(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! Set element properties (p%ElemProps) - CALL SetElementProperties(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - !Store mapping between nodes and elements - CALL NodeCon(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Allocate DOF indices to joints and members - call DistributeDOF(Init, p ,ErrStat2, ErrMsg2); if(Failed()) return; - - ! Assemble Stiffness and mass matrix - CALL AssembleKM(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! Insert soil stiffness and mass matrix (NOTE: using NodesDOF, unreduced matrix) - CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOF, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Elimination of constraints (reset M, K, D, to lower size, and BCs IntFc ) - CALL DirectElimination(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Additional Damping and stiffness at pin/ball/universal joints - CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return - - - ! -------------------------------------------------------------------------------- - ! --- CB, Misc - ! -------------------------------------------------------------------------------- - ! --- Partitioning - ! Nodes into (I,C,L,R): I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior - ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior - call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return - - ! --- Craig-Bampton reduction (sets many parameters) - CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Initial system states - IF ( p%nDOFM > 0 ) THEN - CALL AllocAry(x%qm, p%nDOFM, 'x%qm', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(x%qmdot, p%nDOFM, 'x%qmdot', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry(m%qmdotdot, p%nDOFM, 'm%qmdotdot', ErrStat2, ErrMsg2 ); if(Failed()) return - x%qm = 0.0_ReKi - x%qmdot = 0.0_ReKi - m%qmdotdot= 0.0_ReKi - END IF - - xd%DummyDiscState = 0.0_ReKi - z%DummyConstrState = 0.0_ReKi - - ! Allocate OtherState%xdot if using multi-step method; initialize n - IF ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) THEN - !bjj: note that the way SD_UpdateStates is implemented, "n" doesn't need to be initialized here - Allocate( OtherState%xdot(4), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat ( ErrID_Fatal, 'Error allocating OtherState%xdot', ErrStat, ErrMsg, 'SD_Init' ) - CALL CleanUp() - RETURN - END IF - ENDIF - - ! Allocate miscellaneous variables, used only to avoid temporary copies of variables allocated/deallocated and sometimes recomputed each time - CALL AllocMiscVars(p, m, ErrStat2, ErrMsg2); if(Failed()) return - - ! -------------------------------------------------------------------------------- - ! --- Initialize Inputs and Outputs - ! -------------------------------------------------------------------------------- - ! Create the input and output meshes associated with Transition Piece reference point - CALL CreateTPMeshes( InitInput%TP_RefPoint, u%TPMesh, y%Y1Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - - ! Construct the input mesh (u%LMesh, force on nodes) and output mesh (y%Y2Mesh, displacements) - CALL CreateInputOutputMeshes( p%nNodes, Init%Nodes, u%LMesh, y%Y2Mesh, ErrStat2, ErrMsg2 ); if(Failed()) return - - ! --- Write the summary file - IF ( Init%SSSum ) THEN - ! note p%KBB/MBB are KBBt/MBBt - ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init, p, InitInput, CBparams, ErrStat2, ErrMsg2); if(Failed()) return - ENDIF - - ! Initialize the outputs & Store mapping between nodes and elements - CALL SDOUT_Init( Init, y, p, m, InitOut, InitInput%WtrDpth, ErrStat2, ErrMsg2 ); if(Failed()) return - - ! Determine if we need to perform output file handling - IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - CALL SDOUT_OpenOutput( SD_ProgDesc, Init%RootName, p, InitOut, ErrStat2, ErrMsg2 ); if(Failed()) return - END IF - - - ! Tell GLUECODE the SubDyn timestep interval - Interval = p%SDdeltaT - CALL CleanUp() - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Init') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - END FUNCTION Failed - - SUBROUTINE CleanUp() - CALL SD_DestroyInitType(Init, ErrStat2, ErrMsg2) - CALL SD_DestroyCB_MatArrays( CBparams, ErrStat2, ErrMsg2 ) ! local variables - END SUBROUTINE CleanUp - -END SUBROUTINE SD_Init - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete and other states. -!! Continuous, discrete, constraint, and other states are updated for t + Interval. -SUBROUTINE SD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval - TYPE(SD_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at Times - REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; - !! Output: Continuous states at t + Interval - TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; - !! Output: Discrete states at t + Interval - TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; - !! Output: Constraint states at t + Interval - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Input: Other states at t; - !! Output: Other states at t + Interval - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Initialize variables - ErrStat = ErrID_None ! no error has occurred - ErrMsg = "" - - IF ( p%nDOFM == 0) RETURN ! no retained modes = no states - - IF (p%IntMethod .eq. 1) THEN - CALL SD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSEIF (p%IntMethod .eq. 2) THEN - CALL SD_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSEIF (p%IntMethod .eq. 3) THEN - CALL SD_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - ELSE - CALL SD_AM2( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - END IF - -END SUBROUTINE SD_UpdateStates - - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Routine for computing outputs, used in both loose and tight coupling. -SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t - TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t - TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t - TYPE(SD_OutputType), INTENT(INOUT) :: y !< Outputs computed at t (Input only so that mesh con- - !! nectivity information does not have to be recalculated) - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - !locals - INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays - INTEGER(IntKi) :: I,J ! Counters - INTEGER(IntKi) :: iSDNode, iY2Node - REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) - REAL(ReKi) :: rotations(3) - REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method - REAL(ReKi) :: Y1(6) - REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement - INTEGER(IntKi), pointer :: DOFList(:) - INTEGER(IntKi) :: startDOF - REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) - REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) - TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - ! Compute the small rotation angles given the input direction cosine matrix - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return - - ! Inputs at the transition piece: - m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) - m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) - m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - - ! Inputs on interior nodes: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) - - !________________________________________ - ! Set motion outputs on y%Y2mesh - !________________________________________ - ! Y2 = C2*x + D2*u + F2 (Eq. 17) - m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] - m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] - m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] - - IF ( p%nDOFM > 0) THEN - m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? - + p%F2_61 ! + F2(6) ] - ELSE ! There are no states when p%nDOFM=0 (i.e., no retained modes: p%nDOFM=0), so we omit those portions of the equations - m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] - END IF - - !STATIC IMPROVEMENT METHOD ( modify UL ) - if (p%SttcSolve/=idSIM_None) then - if (p%SttcSolve==idSIM_Full) then - FLt = MATMUL(p%PhiL_T , m%UFL + p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - ! TODO New - !ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) - elseif (p%SttcSolve==idSIM_GravOnly) then - FLt = MATMUL(p%PhiL_T , p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - ! TODO New - !ULS = p%UL_st_g - else - STOP ! Should never happen - endif - m%UL = m%UL + ULS - if ( p%nDOFM > 0) then - UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) - ! TODO new - ! <<< - m%UL = m%UL - UL0M - end if - endif - ! --- Build original DOF vectors (DOF before the CB reduction) - m%U_red (p%IDI__) = m%UR_bar - m%U_red (p%ID__L) = m%UL - m%U_red (p%IDC_Rb)= 0 ! TODO - m%U_red (p%ID__F) = 0 - m%U_red_dot (p%IDI__) = m%UR_bar_dot - m%U_red_dot (p%ID__L) = m%UL_dot - m%U_red_dot (p%IDC_Rb)= 0 ! TODO - m%U_red_dot (p%ID__F) = 0 - m%U_red_dotdot(p%IDI__) = m%UR_bar_dotdot - m%U_red_dotdot(p%ID__L) = m%UL_dotdot - m%U_red_dotdot(p%IDC_Rb)= 0 ! TODO - m%U_red_dotdot(p%ID__F) = 0 - - m%U_full = matmul(p%T_red, m%U_red) - m%U_full_dot = matmul(p%T_red, m%U_red_dot) - m%U_full_dotdot = matmul(p%T_red, m%U_red_dotdot) - - ! --- Place displacement/velocity/acceleration into Y2 output mesh - DO iSDNode = 1,p%nNodes - iY2Node = iSDNode - DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations - ! TODO TODO which orientation to give for joints with more than 6 dofs? - ! Construct the direction cosine matrix given the output angles - CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - y%Y2mesh%Orientation (:,:,iY2Node) = DCM - y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) - y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) - y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) - y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) - y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) - enddo - !________________________________________ - ! Set loads outputs on y%Y1Mesh - !________________________________________ - ! --------------------------------------------------------------------------------- - !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above - ! --------------------------------------------------------------------------------- - ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] - !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES - !Aggregate the forces and moments at the interface nodes to the reference point - !TODO: where are these HydroTP, HydroForces documented? - DO I = 1, p%nNodes_I - iSDNode = p%Nodes_I(I,1) - iY2Node = iSDNode - startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes - !Take care of Hydrodynamic Forces that will go into INterface Forces later - HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) - ENDDO - - !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below - ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D - IF ( p%nDOFM > 0) THEN - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) - + matmul(p%KBB, m%u_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) - ELSE ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%MBB, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) - END IF - ! Computing extra moments due to lever arm introduced by interface displacement - ! Y1(:3) = -f_TP - ! MExtra = -u_TP x f_TP - ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs - if (p%ExtraMoment) then - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment - endif - - ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces - y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) - - !________________________________________ - ! CALCULATE OUTPUT TO BE WRITTEN TO FILE - !________________________________________ - ! OutSwtch determines whether or not to actually output results via the WriteOutput array - ! 0 = No one needs the SubDyn outputs provided via the WriteOutput array. - ! 1 = SubDyn will generate an output file of its own. - ! 2 = the caller will handle the outputs, but SubDyn needs to provide them. - ! 3 = Both 1 and 2 - IF ( p%OutSwtch > 0 ) THEN - ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file - !find xdot at t - IF ( p%nDOFM > 0 ) THEN - ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() - CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return - !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear - m%qmdotdot=dxdt%qmdot - ! Destroy dxdt because it is not necessary for the rest of the subroutine - CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2); if(Failed()) return - END IF - - ! Write the previous output data into the output file - IF ( ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) .AND. ( t > m%LastOutTime ) ) THEN - IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN - m%Decimat=1 !reset counter - CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat2, ErrMsg2 ); if(Failed()) return - ELSE - m%Decimat=m%Decimat+1 - ENDIF - END IF - - ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations - CALL SDOut_MapOutputs(t, u, p, x, y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return - - ! Put the output data in the WriteOutput array - DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims - y%WriteOutput(I) = p%OutParam(I)%SignM * AllOuts( p%OutParam(I)%Indx ) - IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - m%SDWrOutput(I) = y%WriteOutput(I) - END IF - END DO - m%LastOutTime = t - ENDIF - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - END FUNCTION Failed - - SUBROUTINE CleanUp - CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2) - END SUBROUTINE CleanUp - -END SUBROUTINE SD_CalcOutput - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Tight coupling routine for computing derivatives of continuous states -!! note that this also sets m%UFL and m%udotdot_TP -SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(IN) :: x !< Continuous states at t -WHY IS THIS INOUT and not JUST IN? RRD, changed to IN on2/19/14 check with Greg - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t - TYPE(SD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - TYPE(SD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - ! INTENT(OUT) automatically deallocates the arrays on entry, we have to allocate them here - CALL AllocAry(dxdt%qm, p%nDOFM, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) - CALL AllocAry(dxdt%qmdot, p%nDOFM, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) - IF ( ErrStat >= AbortErrLev ) RETURN - - IF ( p%nDOFM == 0 ) RETURN - - ! form u(3) in Eq. 10: - m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) - - ! form u(4) in Eq. 10: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) - - !Equation 12: X=A*x + B*u + Fx (Eq 12) - dxdt%qm= x%qmdot - - ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D - != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) - !dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM ) + p%FX - -END SUBROUTINE SD_CalcContStateDeriv - -!----------------------------------------------------------------------------------------------------------------------- -SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) - CHARACTER(*), INTENT(IN) :: SDInputFile - TYPE(SD_InitType) , INTENT(INOUT) :: Init - TYPE(SD_ParameterType) , INTENT(INOUT) :: p - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None -! local variable for input and output -CHARACTER(1024) :: PriPath ! The path to the primary input file -CHARACTER(1024) :: Line, Dummy_Str ! String to temporarially hold value of read line -INTEGER :: Sttus -CHARACTER(64), ALLOCATABLE :: StrArray(:) ! Array of strings, for better control of table inputs -LOGICAL :: Echo -LOGICAL :: LegacyFormat -LOGICAL :: bNumeric -INTEGER(IntKi) :: UnIn -INTEGER(IntKi) :: nColumns, nColValid, nColNumeric -INTEGER(IntKi) :: IOS -INTEGER(IntKi) :: UnEc !Echo file ID -REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings -INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf -REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat -INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) -LOGICAL :: Dummy_Bool -INTEGER(IntKi) :: ErrStat2 -CHARACTER(ErrMsgLen) :: ErrMsg2 -! Initialize ErrStat -ErrStat = ErrID_None -ErrMsg = "" - -UnEc = -1 -Echo = .FALSE. - -CALL GetNewUnit( UnIn ) - -CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) - -IF ( ErrStat2 /= ErrID_None ) THEN - Call Fatal('Could not open SubDyn input file') - return -END IF - -CALL GetPath( SDInputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. - - -!-------------------------- HEADER --------------------------------------------- -CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ); if(Failed()) return -CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ); if(Failed()) return - -!-------------------------- SIMULATION CONTROL PARAMETERS ---------------------- -CALL ReadCom( UnIn, SDInputFile, ' SIMULATION CONTROL PARAMETERS ', ErrStat2, ErrMsg2 ); if(Failed()) return -CALL ReadVar(UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2); if(Failed()) return - -IF ( Echo ) THEN - CALL OpenEcho ( UnEc, TRIM(Init%RootName)//'.ech' ,ErrStat2, ErrMsg2) - IF ( ErrStat2 /= 0 ) THEN - CALL Fatal("Could not open SubDyn echo file") - return - END IF - REWIND(UnIn) - !bjj: note we don't need to do error checking here; it was already checked (this is just a repeat of above) - CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 1', ErrStat2, ErrMsg2 ) - CALL ReadCom( UnIn, SDInputFile, 'SubDyn input file header line 2', ErrStat2, ErrMsg2 ) - CALL ReadCom( UnIn, SDInputFile, 'SIMULATION CONTROL PARAMETERS' , ErrStat2, ErrMsg2, UnEc ) - CALL ReadVar( UnIn, SDInputFile, Echo, 'Echo', 'Echo Input File Logic Variable',ErrStat2, ErrMsg2, UnEc ) -ENDIF - -! Read time step ("default" means use the glue-code default) -CALL ReadVar( UnIn, SDInputFile, Line, 'SDdeltaT', 'Subdyn Time Step',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - -CALL Conv2UC( Line ) ! Convert Line to upper case. -IF ( TRIM(Line) == 'DEFAULT' ) THEN ! .TRUE. when one wants to use the default value timestep provided by the glue code. - p%SDdeltaT=Init%DT -ELSE ! The input must have been specified numerically. - READ (Line,*,IOSTAT=IOS) p%SDdeltaT - CALL CheckIOS ( IOS, SDInputFile, 'SDdeltaT', NumType, ErrStat2,ErrMsg2 ); if(Failed()) return - - IF ( ( p%SDdeltaT <= 0 ) ) THEN - call Fatal('SDdeltaT must be greater than or equal to 0.') - return - END IF -END IF - -CALL ReadVar ( UnIn, SDInputFile, p%IntMethod, 'IntMethod', 'Integration Method',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'SttcSolve', 'Solve dynamics about static equilibrium point', ErrStat2, ErrMsg2, UnEc); if(Failed()) return -p%SttcSolve = idSIM_None -if (is_numeric(Dummy_Str, DummyFloat)) then - p%SttcSolve = int(DummyFloat) -else if (is_logical(Dummy_Str, Dummy_Bool)) then - if (Dummy_Bool) p%SttcSolve = idSIM_Full -else - call Fatal('SttcSolve should be an integer or a logical, received: '//trim(Dummy_Str)) - return -endif -IF (Check(.not.(any(idSIM_Valid==p%SttcSolve)), 'Invalid value entered for SttcSolve')) return - -! ExtraMoment - For legacy, allowing this line to be a comment -CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'ExtraMoment', 'Add extra lever arm contribution to interface loads', ErrStat2, ErrMsg2, UnEc); if(Failed()) return -if (is_logical(Dummy_Str, Dummy_Bool)) then ! the parameter was present - p%ExtraMoment=Dummy_Bool - ! We still need to read the comment on the next line - CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -else ! we have a actually read a comment line, we do nothing. - p%ExtraMoment=.False. ! For Legacy, ExtraMoment is False -endif - -!-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- -CALL ReadIVar ( UnIn, SDInputFile, Init%FEMMod, 'FEMMod', 'FEM analysis mode' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ! 0= Euler-Bernoulli(E-B); 1=Tapered E-B; 2= Timoshenko; 3= tapered Timoshenko -CALL ReadIVar ( UnIn, SDInputFile, Init%NDiv , 'NDiv' , 'Number of divisions per member',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadLVar ( UnIn, SDInputFile, Init%CBMod , 'CBMod' , 'C-B mod flag' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - -IF (Check( (p%IntMethod < 1) .OR.(p%IntMethod > 4) , 'IntMethod must be 1 through 4.')) return -IF (Check( (Init%FEMMod < 0 ) .OR. ( Init%FEMMod > 4 ) , 'FEMMod must be 0, 1, 2, or 3.')) return -IF (Check( Init%NDiv < 1 , 'NDiv must be a positive integer')) return -IF (Check( Init%FEMMod==2 , 'FEMMod = 2 (tapered Euler-Bernoulli) not implemented')) return -IF (Check( Init%FEMMod==4 , 'FEMMod = 4 (tapered Timoshenko) not implemented')) return - -IF (Init%CBMod) THEN - ! Nmodes - Number of interal modes to retain. - CALL ReadIVar ( UnIn, SDInputFile, p%nDOFM, 'Nmodes', 'Number of internal modes',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - - IF (Check( p%nDOFM < 0 , 'Nmodes must be a non-negative integer.')) return - - if ( p%nDOFM > 0 ) THEN - ! Damping ratios for retained modes - CALL AllocAry(Init%JDampings, p%nDOFM, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return - Init%JDampings=WrongNo !Initialize - - CALL ReadAry( UnIn, SDInputFile, Init%JDampings, p%nDOFM, 'JDamping', 'Damping ratio of the internal modes', ErrStat2, ErrMsg2, UnEc ); - ! note that we don't check the ErrStat2 here; if the user entered fewer than Nmodes values, we will use the - ! last entry to fill in remaining values. - !Check 1st value, we need at least one good value from user or throw error - IF ((Init%JDampings(1) < 0 ) .OR. (Init%JDampings(1) >= 100.0)) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100') - return - ELSE - DO I = 2, p%nDOFM - IF ( Init%JDampings(I) .EQ. WrongNo ) THEN - Init%Jdampings(I:p%nDOFM)=Init%JDampings(I-1) - IF (i /= 2) THEN ! display an informational message if we're repeating the last value (unless we only entered one value) - ErrStat = ErrID_Info - ErrMsg = 'Using damping ratio '//trim(num2lstr(Init%JDampings(I-1)))//' for modes '//trim(num2lstr(I))//' - '//trim(num2lstr(p%nDOFM))//'.' - END IF - EXIT - ELSEIF ( ( Init%JDampings(I) < 0 ) .OR.( Init%JDampings(I) >= 100.0 ) ) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100') - return - ENDIF - ENDDO - ENDIF - IF (ErrStat2 /= ErrID_None .AND. Echo) THEN ! ReadAry had an error because it couldn't read the entire array so it didn't write this to the echo file; we assume the last-read values are used for remaining JDampings - WRITE( UnEc, Ec_ReAryFrmt ) 'JDamping', 'Damping ratio of the internal modes', Init%Jdampings(1:MIN(p%nDOFM,NWTC_MaxAryLen)) - END IF - ELSE - CALL ReadCom( UnIn, SDInputFile, 'JDamping', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - END IF - -ELSE !CBMOD=FALSE : all modes are retained, not sure how many they are yet - !note at this stage I do not know nDOFL yet; Nmodes will be updated later for the FULL FEM CASE. - p%nDOFM = -1 - !Ignore next line - CALL ReadCom( UnIn, SDInputFile, 'Nmodes', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - !Read 1 damping value for all modes - CALL AllocAry(Init%JDampings, 1, 'JDamping', ErrStat2, ErrMsg2) ; if(Failed()) return - CALL ReadVar ( UnIn, SDInputFile, Init%JDampings(1), 'JDampings', 'Damping ratio',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - IF ( ( Init%JDampings(1) < 0 ) .OR.( Init%JDampings(1) >= 100.0 ) ) THEN - CALL Fatal('Damping ratio should be larger than 0 and less than 100.') - RETURN - ENDIF -ENDIF - -IF ((p%nDOFM > 0) .OR. (.NOT.(Init%CBMod))) THEN !This if should not be at all, dampings should be divided by 100 regardless, also if CBmod=false p%nDOFM is undefined, but if Nmodes=0 then JDampings does not exist - Init%JDampings = Init%JDampings/100.0_ReKi !now the 20 is .20 as it should in all cases for 1 or Nmodes JDampings -END IF - -!--------------------- STRUCTURE JOINTS: joints connect structure members ------------------------------- -CALL ReadCom ( UnIn, SDInputFile, 'STRUCTURE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NJoints, 'NJoints', 'Number of joints',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Joint Coordinates Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%Joints, Init%NJoints, JointsCol, 'Joints', ErrStat2, ErrMsg2 ); if(Failed()) return -IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return -! --- Reading first line to detect file format -READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of joints array'; if (Failed()) return -! --- Reading first line to detect file format based on number of columns -nColumns=JointsCol -CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return -CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ) -if (ErrStat2/=0) then - ! We try with 4 columns (legacy format) - nColumns = 4 - deallocate(StrArray) - CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return - CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Joints', 'First line of joints array', ErrStat2, ErrMsg2 ); if(Failed()) return - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - print*,'Warning: Legacy joints table format detected in SubDyn input file!' - print*,' Some feature might be missing and only partial legacy support is provided.' - print*,' All joints are assumed cantilever, all members regular beams.' - print*,' Visit: https://openfast.readthedocs.io/en/dev/source/user/api_change.html' - print*,' Look at the SubDyn API changes to adapt your input files.' - print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - Init%Joints(:,iJointType) = idJointCantilever ! All joints assumed cantilever - Init%Joints(:,iJointType+1:JointsCol) = 0.0 ! remaining columns set to 0 - LegacyFormat=.True. ! Legacy format - Delete me in 2024 -else - ! New format - LegacyFormat=.False. -endif -! Extract fields from first line -DO I = 1, nColumns - bNumeric = is_numeric(StrArray(I), Init%Joints(1,I)) ! Convert from string to float - if (.not.bNumeric) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non numeric character found in Joints line. Problematic line: "'//trim(Line)//'"') - return - endif -ENDDO -deallocate(StrArray) -! Read remaining lines -DO I = 2, Init%NJoints - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, nColumns, 'Joints', 'Joint number and coordinates', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - Init%Joints(I,1:nColumns) = Dummy_ReAry(1:nColumns) -ENDDO -IF (Check( Init%NJoints < 2, 'NJoints must be greater than 1')) return - -!---------- GO AHEAD and ROTATE STRUCTURE IF DESIRED TO SIMULATE WINDS FROM OTHER DIRECTIONS ------------- -CALL SubRotate(Init%Joints,Init%NJoints,Init%SubRotateZ) - -!------------------- BASE REACTION JOINTS: T/F for Locked/Free DOF @ each Reaction Node --------------------- -! The joints should be all clamped for now -CALL ReadCom ( UnIn, SDInputFile, 'BASE REACTION JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_C, 'NReact', 'Number of joints with reaction forces',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints headers ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Base reaction joints units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - -CALL AllocAry(p%Nodes_C, p%nNodes_C, ReactCol , 'Reacts', ErrStat2, ErrMsg2 ); if(Failed()) return -p%Nodes_C(:,:) = 1 ! Important: By default all DOFs are contrained -p%Nodes_C(:,1) = -1 ! First column is node, initalize to wrong value for safety - -call AllocAry(Init%SSIfile, p%nNodes_C, 'SSIFile', ErrStat2, ErrMsg2); if(Failed()) return -call AllocAry(Init%SSIK, 21, p%nNodes_C, 'SSIK', ErrStat2, ErrMsg2); if(Failed()) return -call AllocAry(Init%SSIM, 21, p%nNodes_C, 'SSIM', ErrStat2, ErrMsg2); if(Failed()) return -Init%SSIfile(:) = '' -Init%SSIK = 0.0_ReKi ! Important init TODO: read these matrices on the fly in SD_FEM maybe? -Init%SSIM = 0.0_ReKi ! Important init -! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile -DO I = 1, p%nNodes_C - READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading reaction line'; if (Failed()) return - call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); - if (nColValid==1 .and. nColNumeric==1) then - ! Temporary allowing this - print*,'Warning: SubDyn reaction line has only 1 column. Please use 7 or 8 values' - else if (nColNumeric==7 .and.(nColValid==7.or.nColValid==8)) then - ! This is fine. - else - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') - return - endif -ENDDO -IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return - - -! Reading SSI matrices if present -DO I = 1, p%nNodes_C - if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then - Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) - CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(:,I),Init%SSIM(:,I), ErrStat, ErrMsg, UnEc ); if(Failed()) return - endif -enddo - - - -!------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- -! Joints with reaction forces, joint number and locked/free dof -CALL ReadCom ( UnIn, SDInputFile, 'INTERFACE JOINTS' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, p%nNodes_I, 'NInterf', 'Number of joints fixed to TP',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Interface joints headers',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Interface joints units ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - -CALL AllocAry(p%Nodes_I, p%nNodes_I, InterfCol, 'Interf', ErrStat2, ErrMsg2); if(Failed()) return -p%Nodes_I(:,:) = 1 ! Important: By default all DOFs are contrained -p%Nodes_I(:,1) = -1 ! First column is node, initalize to wrong value for safety -! Reading interface lines one by one, allowing for 1 or 7 columns (cannot use ReadIAry) -DO I = 1, p%nNodes_I - READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='Error reading interface line'; if (Failed()) return - call ReadIAryFromStr(Line, p%Nodes_I(I,:), 7, nColValid, nColNumeric); - if ((nColValid/=nColNumeric).or.((nColNumeric/=1).and.(nColNumeric/=7)) ) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 1 or 7 numerical values. Problematic line: "'//trim(Line)//'"') - return - endif - if (any(p%Nodes_I(I,:)<=0)) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": For now, all DOF must be activated for interface lines. Problematic line: "'//trim(Line)//'"') - return - endif -ENDDO -IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN - -!----------------------------------- MEMBERS -------------------------------------- -! One day we will need to take care of COSMIDs for non-circular members -CALL ReadCom ( UnIn, SDInputFile, 'Members ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) -Init%Members(:,:) = 0.0_ReKi -if (LegacyFormat) then - nColumns = 5 - Init%Members(:,iMType) = idMemberBeam ! Important, in legacy all members are beams -else - nColumns = MembersCol -endif -DO I = 1, p%NMembers - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members line '//Num2LStr(I), 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) -ENDDO -IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return - -!------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ -CALL ReadCom ( UnIn, SDInputFile, ' Member X-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsB, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%PropSetsB, Init%NPropSetsB, PropSetsBCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return -DO I = 1, Init%NPropSetsB - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return - Init%PropSetsB(I,:) = Dummy_ReAry(1:PropSetsBCol) -ENDDO -IF (Check( Init%NPropSetsB < 1 , 'NPropSets must be >0')) return - -!------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ -CALL ReadCom ( UnIn, SDInputFile, 'Member X-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsX, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%PropSetsX, Init%NPropSetsX, PropSetsXCol, 'XPropSets', ErrStat2, ErrMsg2); if(Failed()) return -DO I = 1, Init%NPropSetsX - CALL ReadAry( UnIn, SDInputFile, Init%PropSetsX(I,:), PropSetsXCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -ENDDO -IF (Check( Init%NPropSetsX < 0, 'NXPropSets must be >=0')) return - -if (.not. LegacyFormat) then - !-------------------------- CABLE PROPERTIES ------------------------------------- - CALL ReadCom ( UnIn, SDInputFile, 'Cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsC, 'NPropSetsC', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return - DO I = 1, Init%NPropSetsC - CALL ReadAry( UnIn, SDInputFile, Init%PropSetsC(I,:), PropSetsCCol, 'PropSetsC', 'PropSetsC ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - ENDDO - IF (Check( Init%NPropSetsC < 0, 'NPropSetsCable must be >=0')) return - !----------------------- RIGID LINK PROPERTIES ------------------------------------ - CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsR, 'NPropSetsR', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return - DO I = 1, Init%NPropSetsR - CALL ReadAry( UnIn, SDInputFile, Init%PropSetsR(I,:), PropSetsRCol, 'RigidPropSets', 'RigidPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - ENDDO - IF (Check( Init%NPropSetsR < 0, 'NPropSetsRigid must be >=0')) return -else - Init%NPropSetsC=0 - Init%NPropSetsR=0 - CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Init%PropSetsR, Init%NPropSetsR, PropSetsRCol, 'RigidPropSets', ErrStat2, ErrMsg2); if(Failed()) return -endif - -!---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------ -CALL ReadCom ( UnIn, SDInputFile, 'Member direction cosine matrices ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NCOSMs, 'NCOSMs', 'Number of unique direction cosine matrices',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Cosine Matrices Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%COSMs, Init%NCOSMs, COSMsCol, 'COSMs', ErrStat2, ErrMsg2); if(Failed()) return -DO I = 1, Init%NCOSMs - CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -ENDDO -IF (Check( Init%NCOSMs < 0 ,'NCOSMs must be >=0')) return - -!------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- -CALL ReadCom ( UnIn, SDInputFile, 'Additional concentrated masses at joints ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%nCMass, 'nCMass', 'Number of joints that have concentrated masses',ErrStat2, ErrMsg2, UnEc); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, 'Concentrated Mass Units' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%CMass, Init%nCMass, CMassCol, 'CMass', ErrStat2, ErrMsg2); if(Failed()) return -Init%CMass = 0.0 ! Important init since we allow user to only provide diagonal terms -DO I = 1, Init%nCMass - ! CALL ReadAry( UnIn, SDInputFile, Init%CMass(I,:), CMassCol, 'CMass', 'Joint number and mass values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading concentrated mass line'; if (Failed()) return - call ReadFAryFromStr(Line, Init%CMass(I,:), CMassCol, nColValid, nColNumeric); - if ((nColValid/=nColNumeric).or.((nColNumeric/=5).and.(nColNumeric/=11)) ) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Interface line must consist of 5 or 11 numerical values. Problematic line: "'//trim(Line)//'"') - return - endif - if (Init%CMass(I,1)<=0) then ! Further checks in JointIDs are done in SD_FEM - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Invalid concentrated mass JointID. Problematic line: "'//trim(Line)//'"') - return - endif -ENDDO -IF (Check( Init%nCMass < 0 , 'NCMass must be >=0')) return - -!---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ -CALL ReadCom (UnIn, SDInputFile, 'OUTPUT' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. -CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -!Store an integer version of it -p%OutAllInt= 1 -IF ( .NOT. p%OutAll ) p%OutAllInt= 0 -CALL ReadIVar(UnIn, SDInputFile, p%OutSwtch, 'OutSwtch', 'Output to which file variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -IF (Check( ( p%OutSwtch < 1 ) .OR. ( p%OutSwtch > 3) ,'OutSwtch must be >0 and <4')) return - -Swtch: SELECT CASE (p%OutSwtch) - CASE (1, 3) Swtch - !p%OutJckF = TRIM(Init%RootName)//'.out' - CASE (2) Swtch - !pass to glue code - CASE DEFAULT Swtch - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": OutSwtch must be >0 and <4') - return - END SELECT Swtch - -! TabDelim - Output format for tabular data. -CALL ReadLVar ( UnIn, SDInputFile, Init%TabDelim, 'TabDelim', 'Use Tab Delimitation for numerical outputs',ErrStat2, ErrMsg2, UnEc); if(Failed()) return -IF ( Init%TabDelim ) THEN - p%Delim = TAB -ELSE - p%Delim = ' ' -END IF - -CALL ReadIVar( UnIn, SDInputFile, p%OutDec , 'OutDec' , 'Output Decimation' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return -CALL ReadVar ( UnIn, SDInputFile, p%OutFmt , 'OutFmt' , 'Format for numerical outputs' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return -CALL ReadVar ( UnIn, SDInputFile, p%OutSFmt , 'OutSFmt' , 'Format for output column headers' , ErrStat2 , ErrMsg2 , UnEc ); if(Failed()) return -CALL ReadCom ( UnIn, SDInputFile, ' Member Output List SECTION ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar( UnIn, SDInputFile, p%NMOutputs, 'NMOutputs', 'Number of Members whose output must go into OutJckF and/or FAST .out',ErrStat2, ErrMsg2, UnEc ) -if (Failed()) return -IF (Check ( (p%NMOutputs < 0) .OR. (p%NMOutputs > p%NMembers) .OR. (p%NMOutputs > 9), 'NMOutputs must be >=0 and <= minimim(NMembers,9)')) return - -CALL ReadCom( UnIn, SDInputFile, ' Output Member Headers',ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return -CALL ReadCom( UnIn, SDInputFile, ' Output Member Units' ,ErrStat2, ErrMsg2, UnEc) ; if(Failed()) return - -IF ( p%NMOutputs > 0 ) THEN - ! Allocate memory for filled group arrays - ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = ErrStat2 ) !this list contains different arrays for each of its elements - IF ( ErrStat2 /= ErrID_None ) THEN - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//': Error allocating MOutLst arrays') - RETURN - END IF - - DO I = 1,p%NMOutputs - READ(UnIn,'(A)',IOSTAT=ErrStat2) Line !read into a line - IF (ErrStat2 == 0) THEN - READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt - IF ( ErrStat2 /= 0 .OR. p%MOutLst(I)%NOutCnt < 1 .OR. p%MOutLst(I)%NOutCnt > 9 .OR. p%MOutLst(I)%NOutCnt > Init%Ndiv+1) THEN - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": NOutCnt must be >= 1 and <= minimim(Ndiv+1,9)') - RETURN - END IF - CALL AllocAry( p%MOutLst(I)%NodeCnt, p%MOutLst(I)%NOutCnt, 'NodeCnt', ErrStat2, ErrMsg2); if(Failed()) return - - READ(Line,*,IOSTAT=ErrStat2) p%MOutLst(I)%MemberID, p%MOutLst(I)%NOutCnt, p%MOutLst(I)%NodeCnt - IF ( Check( ErrStat2 /= 0 , 'Failed to read member output list properties.')) return - - ! Check if MemberID is in the member list and the NodeCnt is a valid number - flg = 0 - DO J = 1, p%NMembers - IF(p%MOutLst(I)%MemberID .EQ. Init%Members(j, 1)) THEN - flg = flg + 1 ! flg could be greater than 1, when there are more than 9 internal nodes of a member. - IF( (p%MOutLst(I)%NOutCnt < 10) .and. ((p%MOutLst(I)%NOutCnt > 0)) ) THEN - DO K = 1,p%MOutLst(I)%NOutCnt - ! node number should be less than NDiv + 1 - IF( (p%MOutLst(I)%NodeCnt(k) > (Init%NDiv+1)) .or. (p%MOutLst(I)%NodeCnt(k) < 1) ) THEN - CALL Fatal(' NodeCnt should be less than NDIV+1 and greater than 0. ') - RETURN - ENDIF - ENDDO - ELSE - CALL Fatal(' NOutCnt should be less than 10 and greater than 0. ') - RETURN - ENDIF - ENDIF - ENDDO - IF (Check (flg .EQ. 0 , ' MemberID is not in the Members list. ')) return - - IF ( Echo ) THEN - WRITE( UnEc, '(A)' ) TRIM(Line) - END IF - END IF - END DO -END IF - -! OutList - list of requested parameters to output to a file -CALL ReadCom( UnIn, SDInputFile, 'SSOutList',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return - -ALLOCATE(Init%SSOutList(MaxOutChs), STAT=ErrStat2) -If (Check( ErrStat2 /= ErrID_None ,'Error allocating SSOutList arrays')) return -CALL ReadOutputList ( UnIn, SDInputFile, Init%SSOutList, p%NumOuts, 'SSOutList', 'List of outputs requested', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL CleanUp() - -CONTAINS - - LOGICAL FUNCTION Check(Condition, ErrMsg_in) - logical, intent(in) :: Condition - character(len=*), intent(in) :: ErrMsg_in - Check=Condition - if (Check) call Fatal(' Error in file '//TRIM(SDInputFile)//': '//trim(ErrMsg_in)) - END FUNCTION Check - - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_Input') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - END FUNCTION Failed - - SUBROUTINE Fatal(ErrMsg_in) - character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'SD_Input'); - CALL CleanUp() - END SUBROUTINE Fatal - - SUBROUTINE CleanUp() - CLOSE( UnIn ) - if(allocated(StrArray)) deallocate(StrArray) - IF (Echo) CLOSE( UnEc ) - END SUBROUTINE -END SUBROUTINE SD_Input - -!> Extract integers from a string (space delimited substrings) -!! If StrArrayOut is present, non numeric strings are also returned -!! Example Str="1 2 not_a_int 3" -> IntArray = (/1,2,3/) StrArrayOut=(/"not_a_int"/) -!! No need for error handling, the caller will check how many valid inputs were on the line -!! TODO, place me in NWTC LIb -SUBROUTINE ReadIAryFromStr(Str, IntArray, nColMax, nColValid, nColNumeric, StrArrayOut) - character(len=*), intent(in) :: Str !< - integer(IntKi), dimension(:), intent(inout) :: IntArray !< NOTE: inout, to allow for init values - integer(IntKi), intent(in) :: nColMax - integer(IntKi), intent(out) :: nColValid, nColNumeric !< - character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric - character(255), allocatable :: StrArray(:) ! Array of strings extracted from line - real(ReKi) :: DummyFloat - integer(IntKi) :: J, nColStr - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - nColValid = 0 ; - nColNumeric = 0 ; - nColStr = 0 ; - ! --- First extract the different sub strings - CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); - if (ErrStat2/=ErrID_None) then - return ! User should notice that there is 0 valid columns - endif - StrArray(:)=''; - CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! - ! --- Then look for numerical values - do J = 1, nColMax - if (len(trim(StrArray(J)))>0) then - nColValid=nColValid+1 - if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! - nColNumeric=nColNumeric+1 - if (nColNumeric<=size(IntArray)) then - IntArray(nColNumeric) = int(DummyFloat) - endif - else - nColStr = nColStr+1 - if (present(StrArrayOut)) then - if (nColStr <=size(StrArrayOut) )then - StrArrayOut(nColStr) = StrArray(J) - endif - endif - endif - endif - enddo - if(allocated(StrArray)) deallocate(StrArray) -END SUBROUTINE ReadIAryFromStr - -!> See ReadIAryFromStr, same but for floats -SUBROUTINE ReadFAryFromStr(Str, FloatArray, nColMax, nColValid, nColNumeric, StrArrayOut) - character(len=*), intent(in) :: Str !< - real(ReKi), dimension(:), intent(inout) :: FloatArray !< NOTE: inout, to allow for init values - integer(IntKi), intent(in) :: nColMax - integer(IntKi), intent(out) :: nColValid, nColNumeric !< - character(len=*), dimension(:), intent(out), optional :: StrArrayOut(:) !< Array of strings that are non numeric - character(255), allocatable :: StrArray(:) ! Array of strings extracted from line - real(ReKi) :: DummyFloat - integer(IntKi) :: J, nColStr - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - nColValid = 0 ; - nColNumeric = 0 ; - nColStr = 0 ; - ! --- First extract the different sub strings - CALL AllocAry(StrArray, nColMax, 'StrArray', ErrStat2, ErrMsg2); - if (ErrStat2/=ErrID_None) then - return ! User should notice that there is 0 valid columns - endif - StrArray(:)=''; - CALL ReadCAryFromStr(Str, StrArray, nColMax, 'StrArray', 'StrArray', ErrStat2, ErrMsg2)! NOTE:No Error handling! - ! --- Then look for numerical values - do J = 1, nColMax - if (len(trim(StrArray(J)))>0) then - nColValid=nColValid+1 - if (is_numeric(StrArray(J), DummyFloat) ) then !< TODO we should check for int here! - nColNumeric=nColNumeric+1 - if (nColNumeric<=size(FloatArray)) then - FloatArray(nColNumeric) = DummyFloat - endif - else - nColStr = nColStr+1 - if (present(StrArrayOut)) then - if (nColStr <=size(StrArrayOut) )then - StrArrayOut(nColStr) = StrArray(J) - endif - endif - endif - endif - enddo - if(allocated(StrArray)) deallocate(StrArray) -END SUBROUTINE ReadFAryFromStr - - - - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Rotate the joint coordinates with respect to global z -SUBROUTINE SubRotate(Joints,NJoints,SubRotZ) - REAL(ReKi), INTENT(IN) :: SubRotZ ! Rotational angle in degrees - INTEGER(IntKi), INTENT(IN) :: NJOINTS ! Row size of Joints - REAL(ReKi), DIMENSION(NJOINTS,3), INTENT(INOUT) :: JOINTS ! Rotational angle in degrees (Njoints,4) - !locals - REAL(ReKi) :: rot !angle in rad - REAL(ReKi), DIMENSION(2,2) :: ROTM !rotational matrix (cos matrix with -theta) - - rot=pi*SubRotz/180. - ROTM=transpose(reshape([ COS(rot), -SIN(rot) , & - SIN(rot) , COS(rot)], [2,2] )) - Joints(:,2:3)= transpose(matmul(ROTM,transpose(Joints(:,2:3)))) - -END SUBROUTINE SubRotate - -!---------------------------------------------------------------------------------------------------------------------------------- -!> This routine is called at the end of the simulation. -SUBROUTINE SD_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) - TYPE(SD_InputType), INTENT(INOUT) :: u !< System inputs - TYPE(SD_ParameterType), INTENT(INOUT) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states - TYPE(SD_DiscreteStateType), INTENT(INOUT) :: xd !< Discrete states - TYPE(SD_ConstraintStateType), INTENT(INOUT) :: z !< Constraint states - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states - TYPE(SD_OutputType), INTENT(INOUT) :: y !< System outputs - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - ! Determine if we need to close the output file - IF ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) THEN - IF ((m%Decimat .EQ. p%OutDec) .OR. (m%Decimat .EQ. 0)) THEN - ! Write out the last stored set of outputs before closing - CALL SDOut_WriteOutputs( p%UnJckF, m%LastOutTime, m%SDWrOutput, p, ErrStat, ErrMsg ) - ENDIF - CALL SDOut_CloseOutput( p, ErrStat, ErrMsg ) - END IF - - ! Destroy data - CALL SD_DestroyInput( u, ErrStat, ErrMsg ) - CALL SD_DestroyParam( p, ErrStat, ErrMsg ) - CALL SD_DestroyContState( x, ErrStat, ErrMsg ) - CALL SD_DestroyDiscState( xd, ErrStat, ErrMsg ) - CALL SD_DestroyConstrState( z, ErrStat, ErrMsg ) - CALL SD_DestroyOtherState( OtherState, ErrStat, ErrMsg ) - CALL SD_DestroyMisc( m, ErrStat, ErrMsg ) - CALL SD_DestroyOutput( y, ErrStat, ErrMsg ) - -END SUBROUTINE SD_End - -!---------------------------------------------------------------------------------------------------------------------------------- -!> This subroutine implements the fourth-order Adams-Bashforth Method (RK4) for numerically integrating ordinary differential -!! equations: -!! -!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). -!! -!! x(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) -!! -!! See, e.g., -!! - http://en.wikipedia.org/wiki/Linear_multistep_method -!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. -SUBROUTINE SD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - INTEGER(IntKi), INTENT(IN ) :: n !< time step number - TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t - REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_ContinuousStateType) :: xdot ! Continuous state derivs at t - TYPE(SD_InputType) :: u_interp - - ErrStat = ErrID_None - ErrMsg = "" - - ! need xdot at t - CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t, ErrStat, ErrMsg) - CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) ! initializes xdot - CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! we don't need this local copy anymore - - if (n <= 2) then - OtherState%n = n - !OtherState%xdot ( 3 - n ) = xdot - CALL SD_CopyContState( xdot, OtherState%xdot ( 3 - n ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - CALL SD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - else - if (OtherState%n < n) then - OtherState%n = n - CALL SD_CopyContState( OtherState%xdot ( 3 ), OtherState%xdot ( 4 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( OtherState%xdot ( 2 ), OtherState%xdot ( 3 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( OtherState%xdot ( 1 ), OtherState%xdot ( 2 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - !OtherState%xdot(4) = OtherState%xdot(3) - !OtherState%xdot(3) = OtherState%xdot(2) - !OtherState%xdot(2) = OtherState%xdot(1) - elseif (OtherState%n > n) then - ErrStat = ErrID_Fatal - ErrMsg = ' Backing up in time is not supported with a multistep method ' - RETURN - endif - CALL SD_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, ErrStat, ErrMsg ) - !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date - x%qm = x%qm + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qm - 59.*OtherState%xdot(2)%qm + 37.*OtherState%xdot(3)%qm & - - 9. * OtherState%xdot(4)%qm ) - x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 55.*OtherState%xdot(1)%qmdot - 59.*OtherState%xdot(2)%qmdot & - + 37.*OtherState%xdot(3)%qmdot - 9.*OtherState%xdot(4)%qmdot ) - endif - CALL SD_DestroyContState(xdot, ErrStat, ErrMsg) - CALL SD_DestroyInput(u_interp, ErrStat, ErrMsg) -END SUBROUTINE SD_AB4 - -!---------------------------------------------------------------------------------------------------------------------------------- -!> This subroutine implements the fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating ordinary -!! differential equations: -!! -!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). -!! -!! Adams-Bashforth Predictor: -!! x^p(t+dt) = x(t) + (dt / 24.) * ( 55.*f(t,x) - 59.*f(t-dt,x) + 37.*f(t-2.*dt,x) - 9.*f(t-3.*dt,x) ) -!! -!! Adams-Moulton Corrector: -!! x(t+dt) = x(t) + (dt / 24.) * ( 9.*f(t+dt,x^p) + 19.*f(t,x) - 5.*f(t-dt,x) + 1.*f(t-2.*dt,x) ) -!! -!! See, e.g., -!! - http://en.wikipedia.org/wiki/Linear_multistep_method -!! - K. E. Atkinson, "An Introduction to Numerical Analysis", 1989, John Wiley & Sons, Inc, Second Edition. -SUBROUTINE SD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - INTEGER(IntKi), INTENT(IN ) :: n !< time step number - TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t - REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_InputType) :: u_interp ! Continuous states at t - TYPE(SD_ContinuousStateType) :: x_pred ! Continuous states at t - TYPE(SD_ContinuousStateType) :: xdot_pred ! Continuous states at t - - ErrStat = ErrID_None - ErrMsg = "" - - CALL SD_CopyContState(x, x_pred, MESH_NEWCOPY, ErrStat, ErrMsg) !initialize x_pred - CALL SD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, ErrStat, ErrMsg ) - - if (n > 2) then - CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) - - CALL SD_CalcContStateDeriv(t + p%SDDeltaT, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, ErrStat, ErrMsg ) ! initializes xdot_pred - CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg) ! local copy no longer needed - - x%qm = x%qm + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qm + 19. * OtherState%xdot(1)%qm - 5. * OtherState%xdot(2)%qm & - + 1. * OtherState%xdot(3)%qm ) - - x%qmdot = x%qmdot + (p%SDDeltaT / 24.) * ( 9. * xdot_pred%qmdot + 19. * OtherState%xdot(1)%qmdot - 5. * OtherState%xdot(2)%qmdot & - + 1. * OtherState%xdot(3)%qmdot ) - CALL SD_DestroyContState( xdot_pred, ErrStat, ErrMsg) ! local copy no longer needed - else - x%qm = x_pred%qm - x%qmdot = x_pred%qmdot - endif - - CALL SD_DestroyContState( x_pred, ErrStat, ErrMsg) ! local copy no longer needed - -END SUBROUTINE SD_ABM4 - -!---------------------------------------------------------------------------------------------------------------------------------- -!> This subroutine implements the fourth-order Runge-Kutta Method (RK4) for numerically integrating ordinary differential equations: -!! -!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). -!! Define constants k1, k2, k3, and k4 as -!! k1 = dt * f(t , x_t ) -!! k2 = dt * f(t + dt/2 , x_t + k1/2 ) -!! k3 = dt * f(t + dt/2 , x_t + k2/2 ), and -!! k4 = dt * f(t + dt , x_t + k3 ). -!! Then the continuous states at t = t + dt are -!! x_(t+dt) = x_t + k1/6 + k2/3 + k3/3 + k4/6 + O(dt^5) -!! -!! For details, see: -!! Press, W. H.; Flannery, B. P.; Teukolsky, S. A.; and Vetterling, W. T. "Runge-Kutta Method" and "Adaptive Step Size Control for -!! Runge-Kutta." sections 16.1 and 16.2 in Numerical Recipes in FORTRAN: The Art of Scientific Computing, 2nd ed. Cambridge, England: -!! Cambridge University Press, pp. 704-716, 1992. -SUBROUTINE SD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - INTEGER(IntKi), INTENT(IN ) :: n !< time step number - TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t - REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_ContinuousStateType) :: xdot ! time derivatives of continuous states - TYPE(SD_ContinuousStateType) :: k1 ! RK4 constant; see above - TYPE(SD_ContinuousStateType) :: k2 ! RK4 constant; see above - TYPE(SD_ContinuousStateType) :: k3 ! RK4 constant; see above - TYPE(SD_ContinuousStateType) :: k4 ! RK4 constant; see above - TYPE(SD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x - TYPE(SD_InputType) :: u_interp ! interpolated value of inputs - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - ! Initialize interim vars - !bjj: the state type contains allocatable arrays, so we must first allocate space: - CALL SD_CopyContState( x, k1, MESH_NEWCOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( x, k2, MESH_NEWCOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( x, k3, MESH_NEWCOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( x, k4, MESH_NEWCOPY, ErrStat, ErrMsg ) - CALL SD_CopyContState( x, x_tmp, MESH_NEWCOPY, ErrStat, ErrMsg ) - - ! interpolate u to find u_interp = u(t) - CALL SD_CopyInput(u(1), u_interp, MESH_NEWCOPY, ErrStat, ErrMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... - CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat, ErrMsg ) - - ! find xdot at t - CALL SD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) !initializes xdot - k1%qm = p%SDDeltaT * xdot%qm - k1%qmdot = p%SDDeltaT * xdot%qmdot - x_tmp%qm = x%qm + 0.5 * k1%qm - x_tmp%qmdot = x%qmdot + 0.5 * k1%qmdot - ! interpolate u to find u_interp = u(t + dt/2) - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5*p%SDDeltaT, ErrStat, ErrMsg) - - ! find xdot at t + dt/2 - CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - k2%qm = p%SDDeltaT * xdot%qm - k2%qmdot = p%SDDeltaT * xdot%qmdot - x_tmp%qm = x%qm + 0.5 * k2%qm - x_tmp%qmdot = x%qmdot + 0.5 * k2%qmdot - - ! find xdot at t + dt/2 - CALL SD_CalcContStateDeriv( t + 0.5*p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - k3%qm = p%SDDeltaT * xdot%qm - k3%qmdot = p%SDDeltaT * xdot%qmdot - x_tmp%qm = x%qm + k3%qm - x_tmp%qmdot = x%qmdot + k3%qmdot - ! interpolate u to find u_interp = u(t + dt) - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t + p%SDDeltaT, ErrStat, ErrMsg) - - ! find xdot at t + dt - CALL SD_CalcContStateDeriv( t + p%SDDeltaT, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, ErrStat, ErrMsg ) - k4%qm = p%SDDeltaT * xdot%qm - k4%qmdot = p%SDDeltaT * xdot%qmdot - x%qm = x%qm + ( k1%qm + 2. * k2%qm + 2. * k3%qm + k4%qm ) / 6. - x%qmdot = x%qmdot + ( k1%qmdot + 2. * k2%qmdot + 2. * k3%qmdot + k4%qmdot ) / 6. - - CALL CleanUp() - -CONTAINS - - SUBROUTINE CleanUp() - INTEGER(IntKi) :: ErrStat3 ! The error identifier (ErrStat) - CHARACTER(ErrMsgLen) :: ErrMsg3 ! The error message (ErrMsg) - CALL SD_DestroyContState( xdot, ErrStat3, ErrMsg3 ) - CALL SD_DestroyContState( k1, ErrStat3, ErrMsg3 ) - CALL SD_DestroyContState( k2, ErrStat3, ErrMsg3 ) - CALL SD_DestroyContState( k3, ErrStat3, ErrMsg3 ) - CALL SD_DestroyContState( k4, ErrStat3, ErrMsg3 ) - CALL SD_DestroyContState( x_tmp, ErrStat3, ErrMsg3 ) - CALL SD_DestroyInput( u_interp, ErrStat3, ErrMsg3 ) - END SUBROUTINE CleanUp - -END SUBROUTINE SD_RK4 - -!---------------------------------------------------------------------------------------------------------------------------------- -!> This subroutine implements the 2nd-order Adams-Moulton Implicit Method (AM2,Trapezoidal rule) for numerically integrating ordinary differential equations: -!! -!! Let f(t, x) = xdot denote the time (t) derivative of the continuous states (x). -!! Define constants k1, k2, k3, and k4 as -!! k1 = f(t , x_t ) -!! k2 = f(t + dt , x_t+dt ) -!! Then the continuous states at t = t + dt are -!! x_(t+dt) =x_n+1 = x_t + deltat/2*(k1 + k2) + O(dt^3) -!! Now this can be re-written as: 0=Z(x_n+1) = x_n - x_n+1 +dt/2 *(f_n + f_n+1) = 0 -!! f_n= A*x_n + B*u_n + Fx from Eq. 1.12 of the manual -!! So to solve this linear system, I can just use x(k)=x(k-1) -J^-1 * Z(x(k-1)) (this is a simple root solver of the linear equation) -!! with J=dZ/dx_n+1 = -I +dt/2*A -!! -!! Thus x_n+1 = x_n - J^-1 *dt/2 * (2*A*x_n + B *(u_n + u_n+1) +2*Fx) -!! or J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) -SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - USE NWTC_LAPACK, only: LAPACK_getrs - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - INTEGER(IntKi), INTENT(IN ) :: n !< time step number - TYPE(SD_InputType), INTENT(INOUT) :: u(:) !< Inputs at t - REAL(DbKi), INTENT(IN ) :: utimes(:) !< times of input - TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: x !< Continuous states at t on input at t + dt on output - TYPE(SD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t - TYPE(SD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t (possibly a guess) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherState !< Other states at t on input at t + dt on output - TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - TYPE(SD_InputType) :: u_interp ! interpolated value of inputs - REAL(ReKi) :: junk2(2*p%nDOFM) !temporary states (qm and qmdot only) - REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP - REAL(ReKi) :: UFL2(p%nDOF__L) ! temporary copy of UFL - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = "" - - ! Initialize interim vars - CALL SD_CopyInput( u(1), u_interp, MESH_NEWCOPY, ErrStat2,ErrMsg2);CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - - !Start by getting u_n and u_n+1 - ! interpolate u to find u_interp = u(t) = u_n - CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL ) - - ! extrapolate u to find u_interp = u(t + dt)=u_n+1 - CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2 ) - - ! calculate (u_n + u_n+1)/2 - udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) - UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) - - ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array - junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (p%NOmegaM2*x%qm + p%N2OmegaMJDamp*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array - ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D - - !.................................................... - ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) - ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - !.................................................... - CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - !IF ( ErrStat >= AbortErrLev ) RETURN - - ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: - x%qm = x%qm - junk2( 1: p%nDOFM) - x%qmdot = x%qmdot - junk2(p%nDOFM+1:2*p%nDOFM) - - ! clean up temporary variable(s) - CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) - -END SUBROUTINE SD_AM2 - -!------------------------------------------------------------------------------------------------------ -!> Perform Craig Bampton (CB) reduction and set parameters needed for States and Ouputs equations -!! Sets the following values, as documented in the SubDyn Theory Guide: -!! CB%OmegaL (omega) and CB%PhiL from Eq. 2 -!! p%PhiL_T and p%PhiLInvOmgL2 for static improvement -!! CB%PhiR from Eq. 3 -!! CB%MBB, CB%MBM, and CB%KBB from Eq. 4. -SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType),INTENT(INOUT),target::p ! Parameters - TYPE(CB_MatArrays), INTENT(INOUT) :: CB ! CB parameters that will be passed out for summary file use - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(ReKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) - REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file - REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array - INTEGER(IntKi) :: i - INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) - INTEGER(IntKi) :: nL, nM, nM_out - INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb - LOGICAL :: BC_Before_CB ! If true, apply fixed BC to the system before doing CB reduction, for temporary bacward compatibility - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - character(*), parameter :: RoutineName = 'SD_Craig_Bampton' - ErrStat = ErrID_None - ErrMsg = "" - - IF(Init%CBMod) THEN ! C-B reduction - ! check number of internal modes - IF(p%nDOFM > p%nDOFL_L) THEN - CALL Fatal('Number of internal modes is larger than number of internal DOFs.') - return - ENDIF - ELSE ! full FEM - p%nDOFM = p%nDOFL_L - !Jdampings need to be reallocated here because nDOFL not known during Init - !So assign value to one temporary variable - JDamping1=Init%Jdampings(1) - DEALLOCATE(Init%JDampings) - CALL AllocAry( Init%JDampings, p%nDOFL_L, 'Init%JDampings', ErrStat2, ErrMsg2 ) ; if(Failed()) return - Init%JDampings = JDamping1 ! set default values for all modes - ENDIF - - CALL AllocParameters(p, p%nDOFM, ErrStat2, ErrMsg2); ; if (Failed()) return - ! Switch between BC before or after CB, KEEP ME - BC_Before_CB=.true. - if(BC_Before_CB) then - !print*,' > Boundary conditions will be applied before Craig-Bampton (New)' - nR = p%nDOF__Rb ! we remove the Fixed BC before performing the CB-reduction - IDR => p%ID__Rb - else - !print*,' > Craig-Bampton will be applied before boundary conditions (Legacy)' - nR = p%nDOFR__ ! Old way, applying CB on full unconstrained system - IDR => p%IDR__ - endif - - IF (p%SttcSolve/=idSIM_None) THEN ! STATIC TREATMENT IMPROVEMENT - nM_out=p%nDOF__L ! Selecting all CB modes for outputs to the function below - ELSE - nM_out=p%nDOFM ! Selecting only the requrested number of CB modes - ENDIF - nL = p%nDOF__L - nM = p%nDOFM - - CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') - CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGR, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGB, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%PhiL, nL, nM_out,'CB%PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - - CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& - Init%FG, FGR, FGL, FGB, FGM) - if(Failed()) return - - CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if(.not.BC_Before_CB) then - ! We apply the BC now, removing unwanted DOFs - call applyConstr(CB, FGB, PhiRb) ! Reduces size of CB%MBB, CB%KBB, CB%MBM, FGB, NOTE: "L" unaffected - else - PhiRb=CB%PhiR ! Remove me in the future - endif - ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') - - CALL CleanUpCB() - -contains - - SUBROUTINE Fatal(ErrMsg_in) - character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'Craig_Bampton'); - CALL CleanUpCB() - END SUBROUTINE Fatal - - logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'Craig_Bampton') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUpCB() - end function Failed - - subroutine CleanUpCB() - IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) - IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) - IF(ALLOCATED(FGM) ) DEALLOCATE(FGM) - IF(ALLOCATED(FGB) ) DEALLOCATE(FGB) - IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) - end subroutine CleanUpCB - - !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system - !! NOTE: PhiL and OmegaL are not modified - subroutine applyConstr(CBParams, FGB, PhiRb) - TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) - !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: MBBb(:, :) - REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: FGBb(:) - ! "b" stands for "bar" - CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); - CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); - !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); - !................................ - ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to - ! MBBb, MBMb, KBBb, PHiRb, FGBb - ! (throw out rows/columns of first matrices to create second matrices) - !................................ - ! TODO avoid this all together - MBBb = CBparams%MBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - KBBb = CBparams%KBB(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - IF (p%nDOFM > 0) THEN - MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) - END IF - FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) - PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) - deallocate(CBparams%MBB) - deallocate(CBparams%KBB) - deallocate(CBparams%MBM) - !deallocate(CBparams%PhiR) - call move_alloc(MBBb, CBparams%MBB) - call move_alloc(KBBb, CBparams%KBB) - call move_alloc(MBMb, CBparams%MBM) - call move_alloc(FGBb, FGB) - !call move_alloc(PhiRb, CBparams%PhiR) - end subroutine applyConstr - -END SUBROUTINE SD_Craig_Bampton - -!> Extract rigid body mass without SSI -!! NOTE: performs a Guyan reduction -SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) - type(SD_InitType), intent(inout) :: Init ! NOTE: Mass and Stiffness are modified but then set back to original - type(SD_ParameterType), intent(in ) :: p ! Parameters - real(ReKi), allocatable, intent(out) :: MBB(:,:) !< MBB - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< error message if errstat /= errid_none - integer(IntKi) :: nM, nR, nL, nM_out - real(ReKi), allocatable :: MBM(:, :) - real(ReKi), allocatable :: KBB(:, :) - real(ReKi), allocatable :: PhiL(:, :) - real(ReKi), allocatable :: PhiR(:, :) - real(ReKi), allocatable :: OmegaL(:) - character(*), parameter :: RoutineName = 'SD_Guyan_RigidBodyMass' - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - - ! --- Remove SSI from Mass and stiffness matrix (NOTE: use NodesDOFtilde, reduced matrix) - CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.True.); - - ! --- Perform Guyan reduction to get MBB - nR = p%nDOFR__ ! Using interface + reaction nodes - nL = p%nDOF__L - nM = 0 ! No CB modes (Guyan) - nM_out = 0 - if(allocated(MBB)) deallocate(MBB) - CALL AllocAry( MBB, nR, nR, 'MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( MBM, nR, nM, 'MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( KBB, nR, nR, 'KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( PhiL, nL, nL, 'PhiL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( PhiR, nL, nR, 'PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( OmegaL, nL, 'OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - - CALL CraigBamptonReduction(Init%M, Init%K, p%IDR__, nR, p%ID__L, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2) - if(Failed()) return - - if(allocated(KBB) ) deallocate(KBB) - if(allocated(MBM) ) deallocate(MBM) - if(allocated(PhiR) ) deallocate(PhiR) - if(allocated(PhiL) ) deallocate(PhiL) - if(allocated(OmegaL)) deallocate(OmegaL) - - ! --- Insert SSI from Mass and stiffness matrix again - CALL InsertSoilMatrices(Init%M, Init%K, p%NodesDOFtilde, Init, p, ErrStat2, ErrMsg2, Substract=.False.); if(Failed()) return -contains - logical function Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - Failed = ErrStat >= AbortErrLev - end function Failed -END SUBROUTINE SD_Guyan_RigidBodyMass - -!------------------------------------------------------------------------------------------------------ -!> Set parameters to compute state and output equations -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) - use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf - TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) - REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) - integer(IntKi), INTENT(IN ) :: nM_out - REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) - REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: OmegaL(nM_out) - REAL(ReKi), INTENT(IN ) :: FGB(p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) - REAL(ReKi), INTENT(IN ) :: FGM(p%nDOFM) - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI__) !bjj: added this so we don't have to take the transpose 5+ times - INTEGER(IntKi) :: I - integer(IntKi) :: n ! size of jacobian in AM2 calculation - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SetParameters' - ErrStat = ErrID_None - ErrMsg = '' - - if (p%nDOFI__/=p%nDOF__Rb) then - ! Limitation due to the TI matrix, on the input U_R to the module for now - ErrMsg2='For now number of leader DOF has to be the same a Rb DOF' - ErrStat2=ErrID_Fatal - if(Failed()) return - endif - - ! Set TI, transformation matrix from interface DOFs to TP ref point (Note: TI allocated in AllocParameters) - CALL RigidTrnsf(Init, p, Init%TP_RefPoint, p%IDI__, p%nDOFI__, p%TI, ErrStat2, ErrMsg2); if(Failed()) return - TI_transpose = TRANSPOSE(p%TI) - - ! Store Static Improvement Method constants - if (p%SttcSolve /= idSIM_None) then - if (p%SttcSolve == idSIM_Full) then - CALL WrScr(' Using static improvement method for gravity and ext. loads') - else - CALL WrScr(' Using static improvement method for gravity only') - endif - ! Allocations - CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%KLLm1 , p%nDOF__L, p%nDOF__L, 'p%KLLm1', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%UL_st_g, p%nDOF__L, 'p%UL_st_g', ErrStat2, ErrMsg2 ); if(Failed())return - ! TODO PhiL_T and PhiLInvOmgL2 may not be needed if KLLm1 is stored. - p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement - do I = 1, nM_out - p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) - enddo - p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t - p%FGL = FGL - p%UL_st_g = MATMUL(p%KLLm1, FGL) - endif - - ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) - p%PhiRb_TI = MATMUL(PhiRb, p%TI) - - !............................... - ! equation 46-47 (used to be 9): - !............................... - p%MBB = MATMUL( MATMUL( TI_transpose, MBBb ), p%TI) != MBBt - p%KBB = MATMUL( MATMUL( TI_transpose, KBBb ), p%TI) != KBBt - - !p%D1_15=-TI_transpose !this is 6x6NIN - IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 - ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt - CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2) != MBMt - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//'p%MBM') - - p%MMB = TRANSPOSE( p%MBM ) != MMBt - p%PhiM = PhiL(:,1:p%nDOFM) - - ! A_21, A_22 (these are diagonal matrices. bjj: I am storing them as arrays instead of full matrices) - p%NOmegaM2 = -1.0_ReKi * OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array - p%N2OmegaMJDamp = -2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array - - ! B_23, B_24 - !p%PhiM_T = TRANSPOSE( p%PhiM ) - - ! FX = matmul( transpose(PhiM), FGL ) (output of CraigBamptonReduction) - p%FX = FGM - - ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) - DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped - p%C1_11(:, I) = p%MBM(:, I)*p%NOmegaM2(I) - p%C1_12(:, I) = p%MBM(:, I)*p%N2OmegaMJDamp(I) - ENDDO - - ! D1_13, D1_14 (with retained modes) - !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ) ! p%D1_13 = MATMUL( p%MBM, p%MMB ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - p%D1_13 = p%MBB - p%D1_13 - - !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ) ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - - ! FY (with retained modes) - p%FY = MATMUL( p%MBM, p%FX ) & - - MATMUL( TI_transpose, FGB ) - - ! C2_21, C2_42 - ! C2_61, C2_62 - DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped - p%C2_61(:, i) = p%PhiM(:, i)*p%NOmegaM2(i) - p%C2_62(:, i) = p%PhiM(:, i)*p%N2OmegaMJDamp(i) - ENDDO - - ! D2_53, D2_63, D2_64 - p%D2_63 = MATMUL( p%PhiM, p%MMB ) - p%D2_63 = p%PhiRb_TI - p%D2_63 - - !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) !bjj: why does this use stack space? - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ) !bjj: replaced MATMUL with this routine to avoid issues with stack size - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - ! F2_61 - p%F2_61 = MATMUL( p%D2_64, FGL ) - - !Now calculate a Jacobian used when AM2 is called and store in parameters - IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%nDOFM > 0) - n=2*p%nDOFM - CALL AllocAry( p%AM2Jac, n, n, 'p%AM2InvJac', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL AllocAry( p%AM2JacPiv, n, 'p%AM2JacPiv', ErrStat2, ErrMsg2 ); if(Failed()) return - - ! First we calculate the Jacobian: - ! (note the Jacobian is first stored as p%AM2InvJac) - p%AM2Jac=0. - DO i=1,p%nDOFM - p%AM2Jac(i+p%nDOFM,i )=p%SDdeltaT/2.*p%NOmegaM2(i) !J21 - p%AM2Jac(i+p%nDOFM,i+p%nDOFM)=p%SDdeltaT/2.*p%N2OmegaMJDamp(i) !J22 -initialize - END DO - - DO I=1,p%nDOFM - p%AM2Jac(I,I)=-1. !J11 - p%AM2Jac(I,p%nDOFM+I)=p%SDdeltaT/2. !J12 - p%AM2Jac(p%nDOFM+I,p%nDOFM+I)=p%AM2Jac(p%nDOFM+I,p%nDOFM+I)-1 !J22 complete - ENDDO - ! Now need to factor it: - !I think it could be improved and made more efficient if we can say the matrix is positive definite - CALL LAPACK_getrf( n, n, p%AM2Jac, p%AM2JacPiv, ErrStat2, ErrMsg2); if(Failed()) return - END IF - - ELSE ! no retained modes, so - ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case - ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables - ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable - ! p%D1_13 = p%MBB in this case so we simplify the equations in the code, omitting storage of this variable - - ! D1_14 (with 0 retained modes) - p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - - ! FY (with 0 retained modes) - p%FY = - MATMUL( TI_transpose, FGB ) - - END IF - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SetParameters') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - -END SUBROUTINE SetParameters - -!------------------------------------------------------------------------------------------------------ -!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. -SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) - TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - INTEGER(IntKi), INTENT( in) :: nDOFM - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ! initialize error handling: - ErrStat = ErrID_None - ErrMsg = "" - - ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - - CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L, 'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - -if (p%nDOFM > 0 ) THEN - CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%NOmegaM2, nDOFM, 'p%NOmegaM2', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%N2OmegaMJDamp, nDOFM, 'p%N2OmegaMJDamp', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP, 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 - CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 - CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L, 'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 - CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 -end if - -END SUBROUTINE AllocParameters - -!------------------------------------------------------------------------------------------------------ -!> Allocate parameter arrays, based on the dimensions already set in the parameter data type. -SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) - TYPE(SD_MiscVarType), INTENT(INOUT) :: Misc ! Miscellaneous values, used to avoid local copies and/or multiple allocation/deallocation of same variables each call - TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - ! initialize error handling: - ErrStat = ErrID_None - ErrMsg = "" - - ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( Misc%UFL, p%nDOF__L, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UR_bar, p%nDOFI__, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb - CALL AllocAry( Misc%UR_bar_dot, p%nDOFI__, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb - CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI__, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb - CALL AllocAry( Misc%UL, p%nDOF__L, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dot, p%nDOF__L, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%UL_dotdot, p%nDOF__L, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - - CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - -END SUBROUTINE AllocMiscVars - -!------------------------------------------------------------------------------------------------------ -!> Partition DOFs and Nodes into sets: -!! Nodes are partitioned into the I,C,L (and R) sets, Nodes_I, Nodes_C, Nodes_L, with: -!! I="Interface" nodes -!! C="Reaction" nodes -!! L=Interior nodes -!! R=I+C -!! DOFs indices are partitioned into B, F, L -!! B=Leader DOFs (Rbar in SubDyn documentation) -!! F=Fixed DOFS -!! L=Interior DOFs -!! Subpartitions of both categories use the convention: "NodePartition_DOFPartition" -!! e.g. C_F : "reaction" nodes DOFs that are fixed -!! C_L : "reaction" nodes DOFs that will be counted as internal -!! I_B : "interface" nodes DOFs that are leader DOFs -SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) - use qsort_c_module, only: QsortC - use IntegerList, only: len, concatenate_lists, lists_difference, concatenate_3lists, sort_in_place - type(SD_Inittype), intent( in) :: Init !< Input data for initialization routine - type(SD_MiscVartype), intent( in) :: m !< Misc - type(SD_Parametertype), intent(inout) :: p !< Parameters - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! local variables - integer(IntKi) :: I, J, c_B, c_F, c_L, c__ ! counters - integer(IntKi) :: iNode, iiNode - integer(IntKi) :: nNodes_R - integer(IntKi), allocatable :: IDAll(:) - integer(IntKi), allocatable :: INodesAll(:) - integer(IntKi), allocatable :: Nodes_R(:) - integer(IntKi) :: ErrStat2 ! < Error status of the operation - character(ErrMsgLen) :: ErrMsg2 - ErrStat = ErrID_None - ErrMsg = "" - ! --- Count nodes per types - p%nNodes_I = p%nNodes_I ! Number of interface nodes - nNodes_R = p%nNodes_I+p%nNodes_C ! I+C nodes - p%nNodes_L = p%nNodes - nNodes_R ! Number of Interior nodes - ! NOTE: some of the interior nodes may have no DOF if they are involved in a rigid assembly.. - - CALL AllocAry( p%Nodes_L, p%nNodes_L, 1, 'p%Nodes_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( Nodes_R , nNodes_R , 'Nodes_R' , ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - - ! -------------------------------------------------------------------------------- - ! --- Partition Nodes: Nodes_L = IAll - NodesR - ! -------------------------------------------------------------------------------- - allocate(INodesAll(1:p%nNodes)); - do iNode=1,p%nNodes - INodesAll(iNode)=iNode - enddo - ! Nodes_R = [Nodes_C Nodes_I] - call concatenate_lists(p%Nodes_C(:,1), p%Nodes_I(:,1), Nodes_R, ErrStat2, ErrMsg2); if(Failed()) return - ! Nodes_L = IAll - Nodes_R - call lists_difference(INodesAll, Nodes_R, p%Nodes_L(:,1), ErrStat2, ErrMsg2); if(Failed()) return - - ! -------------------------------------------------------------------------------- - ! --- Count DOFs - NOTE: we count node by node - ! -------------------------------------------------------------------------------- - ! DOFs of interface nodes - p%nDOFI__ =0 ! Total - p%nDOFI_Rb=0 ! Leader - p%nDOFI_F =0 ! Fixed - do iiNode= 1,p%nNodes_I - p%nDOFI__ = p%nDOFI__ + len(p%NodesDOFtilde( p%Nodes_I(iiNode,1) )) - p%nDOFI_Rb= p%nDOFI_Rb+ count(p%Nodes_I(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs - p%nDOFI_F = p%nDOFI_F + count(p%Nodes_I(iiNode, 2:7)==idBC_Fixed) ! assumes 6 DOFs - enddo - if (p%nDOFI__/=p%nDOFI_Rb+p%nDOFI_F) then - call Fatal('Error in distributing interface DOFs, total number of interface DOF('//num2lstr(p%nDOFI__)//') does not equal sum of: leader ('//num2lstr(p%nDOFI_Rb)//'), fixed ('//num2lstr(p%nDOFI_F)//')'); return - endif - - ! DOFs of reaction nodes - p%nDOFC__ =0 ! Total - p%nDOFC_Rb=0 ! Leader - p%nDOFC_F =0 ! Fixed - p%nDOFC_L =0 ! Internal - do iiNode= 1,p%nNodes_C - p%nDOFC__ = p%nDOFC__ + len(p%NodesDOFtilde( p%Nodes_C(iiNode,1) )) - p%nDOFC_Rb= p%nDOFC_Rb+ count(p%Nodes_C(iiNode, 2:7)==idBC_Leader) ! assumes 6 DOFs - p%nDOFC_F = p%nDOFC_F + count(p%Nodes_C(iiNode, 2:7)==idBC_Fixed ) ! assumes 6 DOFs - p%nDOFC_L = p%nDOFC_L + count(p%Nodes_C(iiNode, 2:7)==idBC_Internal) ! assumes 6 DOFs - enddo - if (p%nDOFC__/=p%nDOFC_Rb+p%nDOFC_F+p%nDOFC_L) then - call Fatal('Error in distributing reaction DOFs, total number of reaction DOF('//num2lstr(p%nDOFC__)//') does not equal sum of: leader ('//num2lstr(p%nDOFC_Rb)//'), fixed ('//num2lstr(p%nDOFC_F)//'), internal ('//num2lstr(p%nDOFC_L)//')'); return - endif - ! DOFs of reaction + interface nodes - p%nDOFR__ = p%nDOFI__ + p%nDOFC__ ! Total number, used to be called "nDOFR" - - ! DOFs of internal nodes - p%nDOFL_L=0 - do iiNode= 1,p%nNodes_L - p%nDOFL_L = p%nDOFL_L + len(p%NodesDOFtilde( p%Nodes_L(iiNode,1) )) - enddo - if (p%nDOFL_L/=p%nDOF_red-p%nDOFR__) then - call Fatal('Error in distributing internal DOFs, total number of internal DOF('//num2lstr(p%nDOFL_L)//') does not equal total number of DOF('//num2lstr(p%nDOF_red)//') minus interface and reaction ('//num2lstr(p%nDOFR__)//')'); return - endif - - ! Total number of DOFs in each category: - p%nDOF__Rb = p%nDOFC_Rb + p%nDOFI_Rb ! OK, generic - p%nDOF__F = p%nDOFC_F + p%nDOFI_F ! OK, generic - p%nDOF__L = p%nDOFC_L + p%nDOFL_L ! OK, generic - - ! --- Safety checks ! TODO: these checks are temporary! - if (p%nDOFI_Rb /= p%nNodes_I*6) then - call Fatal('Wrong number of DOF for interface nodes, likely some interface nodes are special joints or are fixed'); return - endif - - ! Set the index arrays - CALL AllocAry( p%IDI__, p%nDOFI__, 'p%IDI__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDI_Rb,p%nDOFI_Rb, 'p%IDI_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDI_F, p%nDOFI_F, 'p%IDI_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDC__, p%nDOFC__, 'p%IDC__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDC_Rb,p%nDOFC_Rb, 'p%IDC_Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDC_F, p%nDOFC_F, 'p%IDC_F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDC_L, p%nDOFC_L, 'p%IDC_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDL_L, p%nDOFL_L, 'p%IDL_L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%IDR__, p%nDOFR__, 'p%IDR__', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%ID__Rb,p%nDOF__Rb, 'p%ID__Rb',ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%ID__F, p%nDOF__F, 'p%ID__F', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - CALL AllocAry( p%ID__L, p%nDOF__L, 'p%ID__L', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') ! TODO TODO - if(Failed()) return - - ! -------------------------------------------------------------------------------- - ! --- Distibutes the I, L, C nodal DOFs into B, F, L sub-categories - ! -------------------------------------------------------------------------------- - - ! Distribute the interface DOFs into R,F - c__=0; c_B=0; c_F=0 ! Counters over R and F dofs - do iiNode= 1,p%nNodes_I !Loop on interface nodes - iNode = p%Nodes_I(iiNode,1) - do J = 1, 6 ! DOFs: ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - c__=c__+1 - p%IDI__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - if (p%Nodes_I(iiNode, J+1)==idBC_Leader) then - c_B=c_B+1 - p%IDI_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - - elseif (p%Nodes_I(iiNode, J+1)==idBC_Fixed) then ! - c_F=c_F+1 - p%IDI_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - endif - enddo - enddo - ! Indices IDI__ = [IDI_B, IDI_F], interface - !call concatenate_lists(p%IDI_Rb, p%IDI_F, p%IDI__, ErrStat2, ErrMsg2); if(Failed()) return - - ! Distribute the reaction DOFs into R,F,L - c__=0; c_B=0; c_F=0; c_L=0; ! Counters over R, F, L dofs - do iiNode= 1,p%nNodes_C !Loop on interface nodes - iNode = p%Nodes_C(iiNode,1) - do J = 1, 6 ! DOFs - c__=c__+1 - p%IDC__(c__) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - if (p%Nodes_C(iiNode, J+1)==idBC_Leader) then - c_B=c_B+1 - p%IDC_Rb(c_B) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - - elseif (p%Nodes_C(iiNode, J+1)==idBC_Fixed) then ! - c_F=c_F+1 - p%IDC_F(c_F) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - - elseif (p%Nodes_C(iiNode, J+1)==idBC_Internal) then ! - c_L=c_L+1 - p%IDC_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - endif - enddo - enddo - ! Indices IDC__ = [IDC_B, IDC_F, IDC_L], interface - !call concatenate_3lists(p%IDC_Rb, p%IDC_F, p%IDC_L, p%IDC__, ErrStat2, ErrMsg2); if(Failed()) return - !call sort_in_place(p%IDC__) - - - ! Indices IDR__ = [IDI__, IDC__], interface - !call concatenate_lists(p%IDI__, p%IDC__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return - ! TODO, NOTE: Backward compatibility [IDC, IDI] - call concatenate_lists(p%IDC__, p%IDI__, p%IDR__, ErrStat2, ErrMsg2); if(Failed()) return - - ! Distribute the internal DOFs - c_L=0; ! Counters over L dofs - do iiNode= 1,p%nNodes_L !Loop on interface nodes - iNode = p%Nodes_L(iiNode,1) - do J = 1, size(p%NodesDOFtilde(iNode)%List) ! DOFs - c_L=c_L+1 - p%IDL_L(c_L) = p%NodesDOFtilde(iNode)%List(J) ! DOF number - enddo - enddo - - ! -------------------------------------------------------------------------------- - ! --- Total indices per partition B, F, L - ! -------------------------------------------------------------------------------- - ! Indices ID__Rb = [IDC_B, IDI_B], retained/leader DOFs - call concatenate_lists(p%IDC_Rb, p%IDI_Rb, p%ID__Rb, ErrStat2, ErrMsg2); if(Failed()) return - ! Indices ID__F = [IDC_F, IDI_F], fixed DOFs - call concatenate_lists(p%IDC_F, p%IDI_F, p%ID__F, ErrStat2, ErrMsg2); if(Failed()) return - ! Indices ID__L = [IDL_L, IDC_L], internal DOFs - call concatenate_lists(p%IDL_L, p%IDC_L, p%ID__L, ErrStat2, ErrMsg2); if(Failed()) return - - ! --- Check that partition is complete - if (any(p%ID__Rb<=0)) then - call Fatal('R - Partioning incorrect.'); return - elseif (any(p%ID__F<=0)) then - call Fatal('F - Partioning incorrect.'); return - elseif (any(p%ID__L<=0)) then - call Fatal('L - Partioning incorrect.'); return - endif - allocate(IDAll(1:p%nDOF_red)) - call concatenate_3lists(p%ID__Rb, p%ID__L, p%ID__F, IDAll, ErrStat2, ErrMsg2); if(Failed()) return - call sort_in_place(IDAll) - do I = 1, p%nDOF_red - if (IDAll(I)/=I) then - call Fatal('DOF '//trim(Num2LStr(I))//' missing, problem in R, L F partitioning'); return - endif - enddo - - if(DEV_VERSION) then - write(*,'(A,I0)')'Number of DOFs: "interface" (I__): ',p%nDOFI__ - write(*,'(A,I0)')'Number of DOFs: "interface" retained (I_B): ',p%nDOFI_Rb - write(*,'(A,I0)')'Number of DOFs: "interface" fixed (I_F): ',p%nDOFI_F - write(*,'(A,I0)')'Number of DOFs: "reactions" (C__): ',p%nDOFC__ - write(*,'(A,I0)')'Number of DOFs: "reactions" retained (C_B): ',p%nDOFC_Rb - write(*,'(A,I0)')'Number of DOFs: "reactions" internal (C_L): ',p%nDOFC_L - write(*,'(A,I0)')'Number of DOFs: "reactions" fixed (C_F): ',p%nDOFC_F - write(*,'(A,I0)')'Number of DOFs: "intf+react" (__R): ',p%nDOFR__ - write(*,'(A,I0)')'Number of DOFs: "internal" internal (L_L): ',p%nDOFL_L - write(*,'(A,I0)')'Number of DOFs: retained (__B): ',p%nDOF__Rb - write(*,'(A,I0)')'Number of DOFs: internal (__L): ',p%nDOF__L - write(*,'(A,I0)')'Number of DOFs: fixed (__F): ',p%nDOF__F - write(*,'(A,I0)')'Number of DOFs: total : ',p%nDOF_red - write(*,'(A,I0)')'Number of Nodes: "interface" (I): ',p%nNodes_I - write(*,'(A,I0)')'Number of Nodes: "reactions" (C): ',p%nNodes_C - write(*,'(A,I0)')'Number of Nodes: "internal" (L): ',p%nNodes_L - write(*,'(A,I0)')'Number of Nodes: total (I+C+L): ',p%nNodes - endif - - call CleanUp() - -contains - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'PartitionDOFNodes') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - END FUNCTION Failed - SUBROUTINE Fatal(ErrMsg_in) - character(len=*), intent(in) :: ErrMsg_in - CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'PartitionDOFNodes'); - CALL CleanUp() - END SUBROUTINE Fatal - SUBROUTINE CleanUp() - if(allocated(INodesAll)) deallocate(INodesAll) - if(allocated(IDAll)) deallocate(IDAll) - if(allocated(Nodes_R)) deallocate(Nodes_R) - END SUBROUTINE CleanUp - -END SUBROUTINE PartitionDOFNodes - -!------------------------------------------------------------------------------------------------------ -!> Construct force vector on internal DOF (L) from the values on the input mesh -!! First, the full vector of external forces is built on the non-reduced DOF -!! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) - type(SD_InputType), intent(in ) :: u ! Inputs - type(SD_ParameterType), intent(in ) :: p ! Parameters - type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%nDOF__L) - integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes - integer :: nMembers - real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! TODO to save time, perform Tred multiplication only if Tred is not identity - - ! --- Build vector of external force - m%Fext= myNaN - DO iMeshNode = 1,p%nNodes - iSDNode = iMeshNode - nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList - ! Force - All nodes have only 3 translational DOFs - m%Fext( p%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) - ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs - m%Fext( p%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers - m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers - m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers - enddo - - ! TODO: remove test below in the future - if (DEV_VERSION) then - if (any(m%Fext == myNaN)) then - print*,'Error in setting up Fext' - STOP - endif - endif - ! --- Reduced vector of external force - m%Fext_red = matmul(transpose(p%T_red), m%Fext) - UFL= m%Fext_red(p%ID__L) - -END SUBROUTINE GetExtForceOnInternalDOF - -!------------------------------------------------------------------------------------------------------ -!> Output the summary file -SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) - use Yaml - TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file - TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file - TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine - TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use - INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !LOCALS - INTEGER(IntKi) :: UnSum ! unit number for this summary file - INTEGER(IntKi) :: ErrStat2 ! Temporary storage for local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary storage for local errors - CHARACTER(1024) :: SummaryName ! name of the SubDyn summary file - INTEGER(IntKi) :: i, j, k, propIDs(2), Iprop(2) !counter and temporary holders - INTEGER(IntKi) :: iNode1, iNode2 ! Node indices - INTEGER(IntKi) :: mType ! Member Type - Real(ReKi) :: mMass, mLength ! Member mass and length - REAL(ReKi) :: MRB(6,6) ! REDUCED SYSTEM Kmatrix, equivalent mass matrix - REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix - REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length - CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' - real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix - real(ReKi) :: Ke(12,12), Me(12, 12), FCe(12), FGe(12) ! element stiffness and mass matrices gravity force vector - real(ReKi), dimension(:,:), allocatable :: DummyArray ! - ! Variables for Eigenvalue analysis - integer(IntKi) :: nOmega - real(ReKi), dimension(:,:), allocatable :: Modes - real(ReKi), dimension(:) , allocatable :: Omega - logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) - character(len=*),parameter :: ReFmt='E15.6' - character(len=*),parameter :: SFmt='A15,1x' ! Need +1 for comma compared to ReFmt - character(len=*),parameter :: IFmt='I7' - ! - ErrStat = ErrID_None - ErrMsg = "" - - ! --- Eigen values of full system (for summary file output only) - ! We call the EigenSolver here only so that we get a print-out the eigenvalues from the full system (minus Reaction DOF) - ! M and K are reduced matrices, but Boundary conditions are not applied - ! We set bDOF, which is true if not a fixed Boundary conditions - ! NOTE: we don't check for singularities/rigig body modes here - CALL WrScr(' Calculating Full System Modes (for summary file output)') - CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return - bDOF(:) = .true. - bDOF(p%ID__F) = .false. - nOmega = count(bDOF) - CALL AllocAry(Omega, nOmega, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(Modes, p%nDOF_red, nOmega, 'Modes', ErrStat2, ErrMsg2); if(Failed()) return - call EigenSolveWrap(Init%K, Init%M, p%nDOF_red, nOmega, .False., Modes, Omega, ErrStat2, ErrMsg2, bDOF); if(Failed()) return - IF (ALLOCATED(bDOF) ) DEALLOCATE(bDOF) - - !------------------------------------------------------------------------------------------------------------- - ! open txt file - !------------------------------------------------------------------------------------------------------------- - SummaryName = TRIM(Init%RootName)//'.sum.yaml' - UnSum = -1 ! we haven't opened the summary file, yet. - - CALL SDOut_OpenSum( UnSum, SummaryName, SD_ProgDesc, ErrStat2, ErrMsg2 ); if(Failed()) return - !------------------------------------------------------------------------------------------------------------- - ! write discretized data to a txt file - !------------------------------------------------------------------------------------------------------------- -!bjj: for debugging, i recommend using the p% versions of all these variables whenever possible in this summary file: -! (it helps in debugging) - WRITE(UnSum, '(A)') '#Unless specified, units are consistent with Input units, [SI] system is advised.' - WRITE(UnSum, '(A)') SectionDivide - write(UnSum,'(A,3(E15.6))')'#TP reference point:',InitInput%TP_RefPoint(1:3) - - ! --- Internal FEM representation - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '# Internal FEM representation' - call yaml_write_var(UnSum, 'nNodes_I', p%nNodes_I,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "interface" (I)') - call yaml_write_var(UnSum, 'nNodes_C', p%nNodes_C,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "reactions" (C)') - call yaml_write_var(UnSum, 'nNodes_L', p%nNodes_L,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: "internal" (L)') - call yaml_write_var(UnSum, 'nNodes ', p%nNodes ,IFmt, ErrStat2, ErrMsg2, comment='Number of Nodes: total (I+C+L)') -#ifdef SD_SUMMARY_DEBUG - call yaml_write_var(UnSum, 'nDOFI__ ', p%nDOFI__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" (I__)') - call yaml_write_var(UnSum, 'nDOFI_B ', p%nDOFI_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" retained (I_B)') - call yaml_write_var(UnSum, 'nDOFI_F ', p%nDOFI_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "interface" fixed (I_F)') - call yaml_write_var(UnSum, 'nDOFC__ ', p%nDOFC__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" (C__)') - call yaml_write_var(UnSum, 'nDOFC_B ', p%nDOFC_Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" retained (C_B)') - call yaml_write_var(UnSum, 'nDOFC_L ', p%nDOFC_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" internal (C_L)') - call yaml_write_var(UnSum, 'nDOFC_F ', p%nDOFC_F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "reactions" fixed (C_F)') - call yaml_write_var(UnSum, 'nDOFR__ ', p%nDOFR__ ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "intf+react" (__R)') - call yaml_write_var(UnSum, 'nDOFL_L ', p%nDOFL_L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: "internal" internal (L_L)') -#endif - call yaml_write_var(UnSum, 'nDOF__B ', p%nDOF__Rb,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: retained (__B)') - call yaml_write_var(UnSum, 'nDOF__L ', p%nDOF__L ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: internal (__L)') - call yaml_write_var(UnSum, 'nDOF__F ', p%nDOF__F ,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: fixed (__F)') - call yaml_write_var(UnSum, 'nDOF_red', p%nDOF_red,IFmt, ErrStat2, ErrMsg2, comment='Number of DOFs: total') -#ifdef SD_SUMMARY_DEBUG - call yaml_write_array(UnSum, 'Nodes_I', p%Nodes_I(:,1), IFmt, ErrStat2, ErrMsg2, comment='"interface" nodes"') - call yaml_write_array(UnSum, 'Nodes_C', p%Nodes_C(:,1), IFmt, ErrStat2, ErrMsg2, comment='"reaction" nodes"') - call yaml_write_array(UnSum, 'Nodes_L', p%Nodes_L(:,1), IFmt, ErrStat2, ErrMsg2, comment='"internal" nodes"') - call yaml_write_array(UnSum, 'DOF_I__', p%IDI__ , IFmt, ErrStat2, ErrMsg2, comment='"interface" DOFs"') - call yaml_write_array(UnSum, 'DOF_I_B', p%IDI_Rb, IFmt, ErrStat2, ErrMsg2, comment='"interface" retained DOFs') - call yaml_write_array(UnSum, 'DOF_I_F', p%IDI_F , IFmt, ErrStat2, ErrMsg2, comment='"interface" fixed DOFs') - call yaml_write_array(UnSum, 'DOF_C__', p%IDC__ , IFmt, ErrStat2, ErrMsg2, comment='"reaction" DOFs"') - call yaml_write_array(UnSum, 'DOF_C_B', p%IDC_Rb, IFmt, ErrStat2, ErrMsg2, comment='"reaction" retained DOFs') - call yaml_write_array(UnSum, 'DOF_C_L', p%IDC_L , IFmt, ErrStat2, ErrMsg2, comment='"reaction" internal DOFs') - call yaml_write_array(UnSum, 'DOF_C_F', p%IDC_F , IFmt, ErrStat2, ErrMsg2, comment='"reaction" fixed DOFs') - call yaml_write_array(UnSum, 'DOF_L_L', p%IDL_L , IFmt, ErrStat2, ErrMsg2, comment='"internal" internal DOFs') - call yaml_write_array(UnSum, 'DOF_R_', p%IDR__ , IFmt, ErrStat2, ErrMsg2, comment='"interface&reaction" DOFs') -#endif - call yaml_write_array(UnSum, 'DOF___B', p%ID__Rb, IFmt, ErrStat2, ErrMsg2, comment='all retained DOFs') - call yaml_write_array(UnSum, 'DOF___F', p%ID__F , IFmt, ErrStat2, ErrMsg2, comment='all fixed DOFs') - call yaml_write_array(UnSum, 'DOF___L', p%ID__L , IFmt, ErrStat2, ErrMsg2, comment='all internal DOFs') - - WRITE(UnSum, '()') - WRITE(UnSum, '(A)') '#Index map from DOF to nodes' - WRITE(UnSum, '(A)') '# Node No., DOF/Node, NodalDOF' - call yaml_write_array(UnSum, 'DOF2Nodes', p%DOFtilde2Nodes , IFmt, ErrStat2, ErrMsg2, comment='(nDOFRed x 3, for each constrained DOF, col1: node index, col2: number of DOF, col3: DOF starting from 1)',label=.true.) - - ! Nodes properties - write(UnSum, '("#",4x,1(A9),9('//trim(SFmt)//'))') 'Node_[#]', 'X_[m]','Y_[m]','Z_[m]', 'JType_[-]', 'JDirX_[-]','JDirY_[-]','JDirZ_[-]','JStff_[Nm/rad]','JDmp_[Nm/rad.s]' - call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),F15.0,5(E15.6,",")') !, comment='',label=.true.) - - ! Element properties - CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return - do i=1,size(p%ElemProps) - DummyArray(i,1) = p%Elems(i,1) ! Should be == i - DummyArray(i,2) = p%Elems(i,2) ! Node 1 - DummyArray(i,3) = p%Elems(i,3) ! Node 2 - DummyArray(i,4) = p%Elems(i,4) ! Prop 1 - DummyArray(i,5) = p%Elems(i,5) ! Prop 2 - DummyArray(i,6) = p%ElemProps(i)%eType ! Type - DummyArray(i,7) = p%ElemProps(i)%Length !Length - DummyArray(i,8) = p%ElemProps(i)%Area ! Area m^2 - DummyArray(i,9) = p%ElemProps(i)%Rho ! density kg/m^3 - DummyArray(i,10) = p%ElemProps(i)%YoungE ! Young modulus - DummyArray(i,11) = p%ElemProps(i)%ShearG ! G - DummyArray(i,12) = p%ElemProps(i)%Kappa ! Shear coefficient - DummyArray(i,13) = p%ElemProps(i)%Ixx ! Moment of inertia - DummyArray(i,14) = p%ElemProps(i)%Iyy ! Moment of inertia - DummyArray(i,15) = p%ElemProps(i)%Jzz ! Moment of inertia - DummyArray(i,16) = p%ElemProps(i)%T0 ! Pretension [N] - enddo - write(UnSum, '("#",4x,6(A9),10('//trim(SFmt)//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' - call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),7(E15.6,",")') !, comment='',label=.true.) - deallocate(DummyArray) - - if (allocated(Init%Soil_K)) then - call yaml_write_array(UnSum, 'Soil_Nodes', Init%Soil_Nodes, IFmt, ErrStat2, ErrMsg2, comment='') - CALL AllocAry( DummyArray, 3, size(Init%Soil_Points,2), 'SoilP', ErrStat2, ErrMsg2 ); if(Failed()) return - do i=1,size(Init%Soil_K,3) - DummyArray(1:3,I) = Init%Nodes(Init%Soil_Nodes(I), 2:4) - call yaml_write_array(UnSum, 'Soil_K'//Num2LStr(I), Init%Soil_K(:,:,I), ReFmt, ErrStat2, ErrMsg2, comment='') - enddo - call yaml_write_array(UnSum, 'Soil_Points_SoilDyn', Init%Soil_Points, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'Soil_Points_SubDyn', DummyArray, ReFmt, ErrStat2, ErrMsg2, comment='') - deallocate(DummyArray) - endif - - ! --- User inputs (less interesting, repeat of input file) - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#User inputs' - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB - WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' - WRITE(UnSum, '("#",I8, E15.6,E15.6,E15.6,E15.6,E15.6 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#No. of Reaction DOFs:',p%nDOFC__ - WRITE(UnSum, '(A, A6)') '#React. DOF_ID', 'BC' - do i = 1, size(p%IDC_F ); WRITE(UnSum, '("#",I10, A10)') p%IDC_F(i) , ' Fixed' ; enddo - do i = 1, size(p%IDC_L ); WRITE(UnSum, '("#",I10, A10)') p%IDC_L(i) , ' Free' ; enddo - do i = 1, size(p%IDC_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDC_Rb(i), ' Leader'; enddo - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#No. of Interface DOFs:',p%nDOFI__ - WRITE(UnSum, '(A,A6)') '#Interf. DOF_ID', 'BC' - do i = 1, size(p%IDI_F ); WRITE(UnSum, '("#",I10, A10)') p%IDI_F(i) , ' Fixed' ; enddo - do i = 1, size(p%IDI_Rb); WRITE(UnSum, '("#",I10, A10)') p%IDI_Rb(i), ' Leader'; enddo - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of concentrated masses (NCMass):',Init%NCMass - WRITE(UnSum, '(A10,10(A15))') '#JointCMass', 'Mass', 'JXX', 'JYY', 'JZZ', 'JXY', 'JXZ', 'JYZ', 'MCGX', 'MCGY', 'MCGZ' - WRITE(UnSum, '("#",F10.0, 10(E15.6))') ((Init%Cmass(i, j), j = 1, CMassCol), i = 1, Init%NCMass) - - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of members',p%NMembers - WRITE(UnSum, '(A,I6)') '#Number of nodes per member:', Init%Ndiv+1 - WRITE(UnSum, '(A9,A10,A10,A10,A10,A15,A15,A16)') '#Member ID', 'Joint1_ID', 'Joint2_ID','Prop_I','Prop_J', 'Mass','Length', 'Node IDs...' - DO i=1,p%NMembers - !Calculate member mass here; this should really be done somewhere else, yet it is not used anywhere else - !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS - propIDs=Init%Members(i,iMProp:iMProp+1) - mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length - IF (ErrStat .EQ. ErrID_None) THEN - mType = Init%Members(I, iMType) ! - if (mType==idMemberBeam) then - iProp(1) = FINDLOCI(Init%PropSetsB(:,1), propIDs(1)) - iProp(2) = FINDLOCI(Init%PropSetsB(:,1), propIDs(2)) - mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & - Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, .TRUE.) - - WRITE(UnSum, '("#",I9,I10,I10,I10,I10,E15.6,E15.6, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propids(1),propids(2),& - mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) - else - WRITE(UnSum, '(A)') '#TODO, member mass for non-beam elements' - endif - ELSE - RETURN - ENDIF - ENDDO - !------------------------------------------------------------------------------------------------------------- - ! write Cosine matrix for all members to a txt file - !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') '#Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers - WRITE(UnSum, '(A9,9(A15))') '#Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' - DO i=1,p%NMembers - iNode1 = FINDLOCI(Init%Joints(:,1), Init%Members(i,2)) ! index of joint 1 of member i - iNode2 = FINDLOCI(Init%Joints(:,1), Init%Members(i,3)) ! index of joint 2 of member i - XYZ1 = Init%Joints(iNode1,2:4) - XYZ2 = Init%Joints(iNode2,2:4) - CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) - DirCos=TRANSPOSE(DirCos) !This is now global to local - WRITE(UnSum, '("#",I9,9(E15.6))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) - ENDDO - - !------------------------------------------------------------------------------------------------------------- - ! write Eigenvalues of full SYstem and CB reduced System - !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') "#Eigenfrequencies for full system (no constraint) [Hz]" - call yaml_write_array(UnSum, 'Full_frequencies', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A, I6)') "#CB frequencies [Hz]" - call yaml_write_array(UnSum, 'CB_frequencies', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) - - !------------------------------------------------------------------------------------------------------------- - ! write Eigenvectors of full System - !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& - ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega - call yaml_write_array(UnSum, 'Full_Modes', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) - - !------------------------------------------------------------------------------------------------------------- - ! write CB system matrices - !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' - call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2, comment='(CB modes)') - call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2, comment='(Guyan modes)') - - !------------------------------------------------------------------------------------------------------------- - ! write CB system KBBt and MBBt matrices, eq stiffness matrices of the entire substructure at the TP ref point - !------------------------------------------------------------------------------------------------------------- - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') "#SubDyn's Structure Equivalent Stiffness and Mass Matrices at the TP reference point (KBBt and MBBt)" - call yaml_write_array(UnSum, 'KBBt', p%KBB, ReFmt, ErrStat2, ErrMsg2) - call yaml_write_array(UnSum, 'MBBt', p%MBB, ReFmt, ErrStat2, ErrMsg2) - - ! Set TI2, transformation matrix from R DOFs to SubDyn Origin - CALL AllocAry( TI2, p%nDOFR__ , 6, 'TI2', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL RigidTrnsf(Init, p, (/0._ReKi, 0._ReKi, 0._ReKi/), p%IDR__, p%nDOFR__, TI2, ErrStat2, ErrMsg2); if(Failed()) return - ! Compute Rigid body mass matrix (without Soil, and using both Interface and Reactions nodes as leader DOF) - if (p%nDOFR__/=p%nDOF__Rb) then - call SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat2, ErrMsg2); if(Failed()) return - MRB=matmul(TRANSPOSE(TI2),matmul(MBB,TI2)) !Equivalent mass matrix of the rigid body - else - MRB=matmul(TRANSPOSE(TI2),matmul(CBparams%MBB,TI2)) !Equivalent mass matrix of the rigid body - endif - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Rigid Body Equivalent Mass Matrix w.r.t. (0,0,0).' - call yaml_write_array(UnSum, 'MRB', MRB, ReFmt, ErrStat2, ErrMsg2) - WRITE(UnSum, '(A,E15.6)') "#SubDyn's Total Mass (structural and non-structural)=", MRB(1,1) - WRITE(UnSum, '(A,3(E15.6))') "#SubDyn's Total Mass CM coordinates (Xcm,Ycm,Zcm) =", (/-MRB(3,5),-MRB(1,6), MRB(1,5)/) /MRB(1,1) - deallocate(TI2) - -#ifdef SD_SUMMARY_DEBUG - - WRITE(UnSum, '()') - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#**** Additional Debugging Information ****' - - ! --- Element Me,Ke,Fg, Fce - CALL ElemM(p%ElemProps(1), Me) - CALL ElemK(p%ElemProps(1), Ke) - CALL ElemF(p%ElemProps(1), Init%g, FGe, FCe) - call yaml_write_array(UnSum, 'Ke',Ke, ReFmt, ErrStat2, ErrMsg2, comment='First element stiffness matrix') - call yaml_write_array(UnSum, 'Me',Me, ReFmt, ErrStat2, ErrMsg2, comment='First element mass matrix') - call yaml_write_array(UnSum, 'FGe',FGe, ReFmt, ErrStat2, ErrMsg2, comment='First element gravity vector') - call yaml_write_array(UnSum, 'FCe',FCe, ReFmt, ErrStat2, ErrMsg2, comment='First element cable pretension') - - ! --- Write assembed K M to a txt file - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') '#FULL FEM K and M matrices. TOTAL FEM TDOFs:', p%nDOF - call yaml_write_array(UnSum, 'K', Init%K, ReFmt, ErrStat2, ErrMsg2, comment='Stiffness matrix') - call yaml_write_array(UnSum, 'M', Init%M, ReFmt, ErrStat2, ErrMsg2, comment='Mass matrix') - - ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' - call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') - - ! --- write CB system matrices - WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Additional CB Matrices (MBB,MBM,KBB) (constraint applied)' - call yaml_write_array(UnSum, 'MBB', CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'KBB', CBparams%KBB, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'KMM', CBparams%OmegaL**2, ReFmt, ErrStat2, ErrMsg2, comment='(diagonal components, OmegaL^2)') - IF (p%SttcSolve/= idSIM_None) THEN - call yaml_write_array(UnSum, 'PhiL', transpose(p%PhiL_T), ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'PhiLOm2-1', p%PhiLInvOmgL2, ReFmt, ErrStat2, ErrMsg2, comment='') - call yaml_write_array(UnSum, 'KLL^-1' , p%KLLm1 , ReFmt, ErrStat2, ErrMsg2, comment='') - endif - ! --- Reduction info - WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'T_red', p%T_red, 'E9.2', ErrStat2, ErrMsg2, comment='(Constraint elimination matrix)') -#endif - - ! --- write TP TI matrix - WRITE(UnSum, '(A)') SectionDivide - call yaml_write_array(UnSum, 'TI' , p%TI , 'E9.2', ErrStat2, ErrMsg2, comment='(TP refpoint Transformation Matrix TI)') - if (allocated(p%TIReact)) then - call yaml_write_array(UnSum, 'TIReact', p%TIReact, 'E9.2', ErrStat2, ErrMsg2, comment='(Transformation Matrix TIreact to (0,0,-WtrDepth))') - endif - - call CleanUp() - -contains - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'OutSummary') - Failed = ErrStat >= AbortErrLev - if (Failed) call CleanUp() - END FUNCTION Failed - SUBROUTINE CleanUp() - if(allocated(Omega)) deallocate(Omega) - if(allocated(Modes)) deallocate(Modes) - CALL SDOut_CloseSum( UnSum, ErrStat2, ErrMsg2 ) - END SUBROUTINE CleanUp -END SUBROUTINE OutSummary - -!------------------------------------------------------------------------------------------------------ -!> Calculate length of a member as given in input file -!! Joints and Members ID have not been reindexed (Elems and Nodes have) -FUNCTION MemberLength(MemberID,Init,ErrStat,ErrMsg) - TYPE(SD_InitType), INTENT(IN) :: Init !< Input data for initialization routine, this structure contains many variables needed for summary file - INTEGER(IntKi), INTENT(IN) :: MemberID !< Member ID # - REAL(ReKi) :: MemberLength !< Member Length - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - !Locals - REAL(Reki) :: xyz1(3),xyz2(3) ! Coordinates of joints in GLOBAL REF SYS - integer(IntKi) :: iMember !< Member index in Init%Members list - INTEGER(IntKi) :: Joint1,Joint2 ! JointID - CHARACTER(*), PARAMETER :: RoutineName = 'MemberLength' - ErrStat = ErrID_None - ErrMsg = '' - MemberLength=0.0 - - !Find the MemberID in the list - iMember = FINDLOCI(Init%Members(:,1), MemberID) - if (iMember<=0) then - call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' not found in member list!', ErrStat,ErrMsg,RoutineName); - return - endif - ! Find joints ID for this member - Joint1 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,2)) - Joint2 = FINDLOCI(Init%Joints(:,1), Init%Members(iMember,3)) - xyz1= Init%Joints(Joint1,2:4) - xyz2= Init%Joints(Joint2,2:4) - MemberLength=SQRT( SUM((xyz2-xyz1)**2.) ) - if ( EqualRealNos(MemberLength, 0.0_ReKi) ) then - call SetErrStat(ErrID_Fatal,' Member with ID '//trim(Num2LStr(MemberID))//' has zero length!', ErrStat,ErrMsg,RoutineName); - return - endif -END FUNCTION MemberLength - -!------------------------------------------------------------------------------------------------------ -!> Calculate member mass, given properties at the ends, keep units consistent -!! For now it works only for circular pipes or for a linearly varying area -FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,ctube) - REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member - LOGICAL, INTENT(IN) :: ctube ! =TRUE for circular pipes, false elseshape - REAL(ReKi) :: BeamMass !mass - REAL(ReKi) :: a0,a1,a2,b0,b1,dd,dt !temporary coefficients - !Density allowed to vary linearly only - b0=rho1 - b1=(rho2-rho1)/L - !Here we will need to figure out what element it is for now circular pipes - IF (ctube) THEN !circular tube - a0=pi * (D1*t1-t1**2.) - dt=t2-t1 !thickness variation - dd=D2-D1 !OD variation - a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L - a2=pi * ( dd*dt-dt**2.)/L**2. - ELSE !linearly varying area - a0=D1 !This is an area - a1=(D2-D1)/L !Delta area - a2=0. - ENDIF - BeamMass= b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz -END FUNCTION BeamMass - -!------------------------------------------------------------------------------------------------------ -!> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR -SUBROUTINE SymMatDebug(M,MAT) - INTEGER(IntKi), INTENT(IN) :: M ! Number of rows and columns - REAL(ReKi),INTENT(IN) :: MAT(M ,M) !matrix to be checked - !LOCALS - REAL(ReKi) :: Error,MaxErr !element by element relative difference in (Transpose(MAT)-MAT)/MAT - INTEGER(IntKi) :: i, j, imax,jmax !counter and temporary holders - - MaxErr=0. - imax=0 - jmax=0 - DO j=1,M - DO i=1,M - Error=MAT(i,j)-MAT(j,i) - IF (MAT(i,j).NE.0) THEN - Error=ABS(Error)/MAT(i,j) - ENDIF - IF (Error > MaxErr) THEN - imax=i - jmax=j - MaxErr=Error - ENDIF - ENDDO - ENDDO - - !-------------------------------------- - ! write discretized data to a txt file - WRITE(*, '(A,e15.6)') 'Matrix Symmetry Check: Largest (abs) relative error is:', MaxErr - WRITE(*, '(A,I4,I4)') 'Matrix Symmetry Check: (I,J)=', imax,jmax - -END SUBROUTINE SymMatDebug - -FUNCTION is_numeric(string, x) - IMPLICIT NONE - CHARACTER(len=*), INTENT(IN) :: string - REAL(ReKi), INTENT(OUT) :: x - LOGICAL :: is_numeric - INTEGER :: e,n - CHARACTER(len=12) :: fmt - x = 0.0_ReKi - n=LEN_TRIM(string) - WRITE(fmt,'("(F",I0,".0)")') n - READ(string,fmt,IOSTAT=e) x - is_numeric = e == 0 -END FUNCTION is_numeric -FUNCTION is_logical(string, b) - IMPLICIT NONE - CHARACTER(len=*), INTENT(IN) :: string - Logical, INTENT(OUT) :: b - LOGICAL :: is_logical - INTEGER :: e,n - b = .false. - n=LEN_TRIM(string) - READ(string,*,IOSTAT=e) b - is_logical = e == 0 -END FUNCTION is_logical - -!> Parses a file for Kxx,Kxy,..Kxthtx,..Kxtz, Kytx, Kyty,..Kztz -SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) - USE NWTC_IO - INTEGER, INTENT(IN) :: JointID !< ID of th ejoint for which we are reading SSI - INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc - INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error - CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message - INTEGER :: CurLine !< The current line to be parsed in the FileInfo structure. - REAL(ReKi), INTENT(INOUT) , dimension(21) :: SSIK, SSIM !< Matrices being filled by reading the file. - CHARACTER(*), INTENT(IN) :: Filename !< Name of the input file. - ! Local declarations: - CHARACTER(5), DIMENSION(21) :: Knames=(/'Kxx ','Kxy ','Kyy ','Kxz ','Kyz ', 'Kzz ','Kxtx ','Kytx ','Kztx ','Ktxtx', & - 'Kxty ','Kyty ','Kzty ','Ktxty','Ktyty', & - 'Kxtz ','Kytz ','Kztz ','Ktxtz','Ktytz','Ktztz'/) ! Dictionary of names by column for an Upper Triangular Matrix - CHARACTER(5), DIMENSION(21) :: Mnames=(/'Mxx ','Mxy ','Myy ','Mxz ','Myz ', 'Mzz ','Mxtx ','Mytx ','Mztx ','Mtxtx', & - 'Mxty ','Myty ','Mzty ','Mtxty','Mtyty', & - 'Mxtz ','Mytz ','Mztz ','Mtxtz','Mtytz','Mtztz'/) - TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. - INTEGER :: IOS ! I/O status returned from the read statement. - INTEGER(IntKi) :: i, j, imax !counters - CHARACTER(ErrMsgLen) :: ErrMsg2 - INTEGER(IntKi) :: ErrStat2 ! Error status; if present, program does not abort on error - CHARACTER(*), PARAMETER :: RoutineName = 'ReadSSIfile' - - SSIK=0.0_ReKi - SSIM=0.0_ReKi - - CALL ProcessComFile ( Filename, FileInfo, ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); IF (ErrStat >= AbortErrLev) RETURN - CurLine = 1 - imax=21 - DO i=1, imax !This will search also for already hit up names, but that's ok, it should be pretty fast - DO j=1,FileInfo%NumLines - CurLine=j - CALL ParseVarWDefault ( FileInfo, CurLine, Knames(i), SSIK(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) - CALL ParseVarWDefault ( FileInfo, CurLine, Mnames(i), SSIM(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) - ENDDO - ENDDO - IF ( PRESENT(UnEc) ) THEN - IF ( UnEc .GT. 0 ) THEN - WRITE (UnEc,'(1X,A20," = ",I11)') 'JOINT ID',JointID - DO i=1,21 - WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIK(i), Knames(i) - WRITE (UnEc,'(1X,ES11.4e2," = ",A20)') SSIM(i), Mnames(i) - ENDDO - ENDIF - END IF - RETURN -END SUBROUTINE ReadSSIfile - - -end module SubDyn diff --git a/modules/subdyn/src_soildyn/SubDyn_Driver.f90 b/modules/subdyn/src_soildyn/SubDyn_Driver.f90 deleted file mode 100644 index 372928e4b..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Driver.f90 +++ /dev/null @@ -1,342 +0,0 @@ -!********************************************************************************************************************************** -! SubDyn_DriverCode: This code tests the SubDyn modules -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -PROGRAM TestSubDyn - - USE NWTC_Library - USE SubDyn - USE SubDyn_Types - USE SubDyn_Output - USE VersionInfo - - IMPLICIT NONE - - INTEGER(IntKi), PARAMETER :: NumInp = 1 ! Number of inputs sent to SD_UpdateStates - - - TYPE SD_Drvr_InitInput - LOGICAL :: Echo - REAL(ReKi) :: Gravity - CHARACTER(1024) :: SDInputFile - REAL(ReKi) :: WtrDpth - CHARACTER(1024) :: OutRootName - INTEGER :: NSteps - REAL(DbKi) :: TimeInterval - REAL(ReKi) :: TP_RefPoint(3) - REAL(ReKi) :: SubRotateZ - INTEGER :: InputsMod - CHARACTER(1024) :: InputsFile - REAL(ReKi) :: uTPInSteady(6) - REAL(ReKi) :: uDotTPInSteady(6) - REAL(ReKi) :: uDotDotTPInSteady(6) - END TYPE SD_Drvr_InitInput - - - ! Program variables - - REAL(DbKi) :: Time ! Variable for storing time, in seconds - REAL(DbKi) :: TimeInterval ! Interval between time steps, in seconds - REAL(DbKi) :: InputTime(NumInp) ! Variable for storing time associated with inputs, in seconds - - TYPE(SD_InitInputType) :: InitInData ! Input data for initialization - TYPE(SD_InitOutputType) :: InitOutData ! Output data from initialization - - TYPE(SD_ContinuousStateType) :: x ! Continuous states - TYPE(SD_DiscreteStateType) :: xd ! Discrete states - TYPE(SD_ConstraintStateType) :: z ! Constraint states - TYPE(SD_OtherStateType) :: OtherState ! Other states - TYPE(SD_MiscVarType) :: m ! Misc/optimization variables - - TYPE(SD_ParameterType) :: p ! Parameters - TYPE(SD_InputType) :: u(NumInp) ! System inputs - TYPE(SD_OutputType) :: y ! System outputs - - - INTEGER(IntKi) :: n ! Loop counter (for time step) - INTEGER(IntKi) :: ErrStat, ErrStat1, ErrStat2, ErrStat3 ! Status of error message - CHARACTER(1024) :: ErrMsg, ErrMsg1, ErrMsg2, ErrMsg3 ! Error message if ErrStat /= ErrID_None - - - CHARACTER(1024) :: drvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. - TYPE(SD_Drvr_InitInput) :: drvrInitInp ! Initialization data for the driver program - INTEGER :: UnIn ! Unit number for the input file - INTEGER :: UnEcho ! The local unit number for this module's echo file - INTEGER(IntKi) :: UnSD_Out ! Output file identifier - REAL(ReKi), ALLOCATABLE :: SDin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for SubDyn inputs - INTEGER(IntKi) :: J ! Generic loop counter - REAL(ReKi) :: dcm (3,3) ! The resulting transformation matrix from X to x, (-). - CHARACTER(10) :: AngleMsg ! For debugging, a string version of the largest rotation input - - ! Other/Misc variables - REAL(DbKi) :: TiLstPrn ! The time of the last print - REAL(DbKi) :: TMax - REAL(DbKi) :: OutTime ! Used to determine if output should be generated at this simulation time - REAL(ReKi) :: PrevClockTime ! Clock time at start of simulation in seconds - REAL(ReKi) :: UsrTime1 ! User CPU time for simulation initialization - INTEGER :: StrtTime (8) ! Start time of simulation - CHARACTER(200) :: git_commit ! String containing the current git commit hash - TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'SubDyn Driver', '', '' ) ! The version number of this program. - !............................................................................................................................... - ! Routines called in initialization - !............................................................................................................................... - ErrMsg = "" - ErrStat = ErrID_None - UnEcho=-1 - UnIn =-1 - - ! Get the current time - CALL DATE_AND_TIME ( Values=StrtTime ) ! Let's time the whole simulation - CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) - PrevClockTime = TimeValues2Seconds( StrtTime ) ! We'll use this time for the SimStats routine - TiLstPrn = 0.0_DbKi ! The first value of ZTime, used to write simulation stats to screen (s) - - ! Initialize the NWTC Subroutine Library - CALL NWTC_Init( ) - - ! Display the copyright notice - CALL DispCopyrightLicense( version%Name ) - ! Obtain OpenFAST git commit hash - git_commit = QueryGitVersion() - ! Tell our users what they're running - CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) - - ! Set the abort error level to a fatal error - AbortErrLev = ErrID_Fatal - - IF ( command_argument_count() /= 1 ) then - CALL print_help() - STOP - endif - - ! Parse the driver input file and run the simulation based on that file - IF ( command_argument_count() == 1 ) THEN - CALL get_command_argument(1, drvrFilename) - - CALL ReadDriverInputFile( drvrFilename, drvrInitInp); - InitInData%g = drvrInitInp%Gravity - InitInData%SDInputFile = drvrInitInp%SDInputFile - InitInData%RootName = drvrInitInp%OutRootName - InitInData%TP_RefPoint = drvrInitInp%TP_RefPoint - InitInData%SubRotateZ = drvrInitInp%SubRotateZ - TimeInterval = drvrInitInp%TimeInterval - InitInData%WtrDpth = drvrInitInp%WtrDpth - END IF - - TMax = TimeInterval * drvrInitInp%NSteps - - ! Initialize the module - CALL SD_Init( InitInData, u(1), p, x, xd, z, OtherState, y, m, TimeInterval, InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() - - CALL AllocAry(SDin, drvrInitInp%NSteps, 13, 'SDinput array', ErrStat2, ErrMsg2); call AbortIfFailed() - SDin(:,:)=0.0_ReKi - - ! Read Input time series data from a file - IF ( drvrInitInp%InputsMod == 2 ) THEN - ! Open the inputs data file - CALL GetNewUnit( UnIn ) - CALL OpenFInpFile ( UnIn, drvrInitInp%InputsFile, ErrStat2, ErrMsg2); Call AbortIfFailed() - DO n = 1,drvrInitInp%NSteps - READ (UnIn,*,IOSTAT=ErrStat2) (SDin (n,J), J=1,13) - ErrMsg2 = ' Error reading line '//trim(Num2LStr(n))//' of file: '//trim(drvrInitInp%InputsFile) - call AbortIfFailed() - END DO - CLOSE ( UnIn ) - else - ! We fill an array with constant values - do n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 - SDin(n+1,1) = n*TimeInterval - SDin(n+1,2:7 ) = drvrInitInp%uTPInSteady(1:6) ! Displacements - SDin(n+1,8:13) = drvrInitInp%uDotTPInSteady(1:6) ! Velocities - !SDin(n+1,14:19) = drvrInitInp%uDotDotTPInSteady(1:6) ! Accelerations - enddo - end if - - ! Destroy initialization data - CALL SD_DestroyInitInput( InitInData, ErrStat2, ErrMsg2 ); call AbortIfFailed() - CALL SD_DestroyInitOutput( InitOutData, ErrStat2, ErrMsg2 ); call AbortIfFailed() - - !............................................................................................................................... - ! Routines called in loose coupling -- the glue code may implement this in various ways - !............................................................................................................................... - ! Force the displacement of the interface node in the global Z direction to be the sag of the column under it's own weight - ! u(1)%UFL(3) =-12.958 !this is for testbeam3 - call WrScr('') - DO n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 - - Time = n*TimeInterval - InputTime(1) = Time - - ! Set module inputs u (likely from the outputs of another module or a set of test conditions) here: - IF ( u(1)%TPMesh%Initialized ) THEN - ! For now, set all hydrodynamic load inputs to 0.0 - u(1)%LMesh%Force (:,:) = 0.0 - u(1)%LMesh%Moment (:,:) = 0.0 - - ! Input displacements, velocities and potentially accelerations - u(1)%TPMesh%TranslationDisp(:,1) = SDin(n+1,2:4) - CALL SmllRotTrans( 'InputRotation', REAL(SDin(n+1,5),reki), REAL(SDin(n+1,6),reki), REAL(SDin(n+1,7),reki), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%TPMesh%Orientation(:,:,1) = dcm - u(1)%TPMesh%TranslationVel(:,1) = SDin(n+1,8:10) - u(1)%TPMesh%RotationVel(:,1) = SDin(n+1,11:13) - - IF ( drvrInitInp%InputsMod == 2 ) THEN - ! User time series have no acceleration for now.. - u(1)%TPMesh%TranslationAcc(:,1) = 0.0_ReKi - u(1)%TPMesh%RotationAcc(:,1) = 0.0_ReKi - ELSE ! constant inputs - u(1)%TPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(1:3) - u(1)%TPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotTPInSteady(4:6) - END IF - END IF - - ! Calculate outputs at n - CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2); call AbortIfFailed() - ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 - CALL SD_UpdateStates( Time, n, u, InputTime, p, x, xd, z, OtherState, m, ErrStat2, ErrMsg2); call AbortIfFailed() - ! Display simulation status every SttsTime-seconds: - IF ( Time - TiLstPrn >= 1 ) THEN - CALL SimStatus( TiLstPrn, PrevClockTime, Time, TMax ) - ENDIF - - END DO ! Loop on n, time steps - - ! Routine to terminate program execution - CALL SD_End( u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2) - IF ( ErrStat /= ErrID_None ) THEN - CALL WrScr( ErrMsg ) - END IF - - ! Write simulation times and stop - CALL RunTimes( StrtTime, UsrTime1, StrtTime, UsrTime1, Time ) - -CONTAINS - SUBROUTINE AbortIfFailed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SubDyn_Driver') - IF ( ErrStat /= ErrID_None ) THEN - CALL WrScr( ErrMsg ) - END IF - if (ErrStat >= AbortErrLev) then - call CleanUp() - STOP - endif - END SUBROUTINE AbortIfFailed - - SUBROUTINE CleanUp() - if(UnEcho>0) CLOSE(UnEcho) - if(UnEcho>0) CLOSE( UnIn) - if(allocated(SDin)) deallocate(SDin) - END SUBROUTINE CleanUp - - !------------------------------------------------------------------------------------------------------------------------------- - SUBROUTINE ReadDriverInputFile( inputFile, InitInp) - CHARACTER(*), INTENT( IN ) :: inputFile - TYPE(SD_Drvr_InitInput), INTENT( OUT ) :: InitInp - ! Local variables - INTEGER :: I ! generic integer for counting - INTEGER :: J ! generic integer for counting - CHARACTER( 2) :: strI ! string version of the loop counter - - CHARACTER(1024) :: EchoFile ! Name of SubDyn echo file - CHARACTER(1024) :: Line ! String to temporarially hold value of read line - CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name - CHARACTER(1024) :: TmpFmt ! Temporary storage for format statement - CHARACTER(1024) :: FileName ! Name of SubDyn input file - CHARACTER(1024) :: FilePath ! Path Name of SubDyn input file - - UnEcho=-1 - UnIn =-1 - - FileName = TRIM(inputFile) - - CALL GetNewUnit( UnIn ) - CALL OpenFInpFile( UnIn, FileName, ErrStat2, ErrMsg2); - call AbortIfFailed() - - CALL WrScr( 'Opening SubDyn Driver input file: '//FileName ) - - ! Read until "echo" - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2); call AbortIfFailed() - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2); call AbortIfFailed() - CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', ErrStat2, ErrMsg2); call AbortIfFailed() - ! If we echo, we rewind - IF ( InitInp%Echo ) THEN - EchoFile = TRIM(FileName)//'.echo' - CALL GetNewUnit( UnEcho ) - CALL OpenEcho ( UnEcho, EchoFile, ErrStat, ErrMsg ); call AbortIfFailed() - REWIND(UnIn) - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 1', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadCom( UnIn, FileName, 'SubDyn Driver input file header line 2', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - END IF - !---------------------- ENVIRONMENTAL CONDITIONS ------------------------------------------------- - CALL ReadCom( UnIn, FileName, 'Environmental conditions header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%Gravity, 'Gravity', 'Gravity', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%WtrDpth, 'WtrDpth', 'WtrDpth', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - !---------------------- SubDyn ------------------------------------------------------------------- - CALL ReadCom( UnIn, FileName, 'SubDyn header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%SDInputFile, 'HDInputFile', 'SubDyn input filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%OutRootName, 'OutRootName', 'SubDyn output root filename', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%NSteps , 'NSteps', 'Number of time steps in the SubDyn simulation', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%TimeInterval, 'TimeInterval', 'Time interval for any SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadAry( UnIn, FileName, InitInp%TP_RefPoint, 3, 'TP reference point', 'TP reference point', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%SubRotateZ, 'SubRotateZ', 'Rotation angle in degrees about Z axis.', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - !---------------------- INPUTS ------------------------------------------------------------------- - CALL ReadCom( UnIn, FileName, 'INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%InputsMod , 'InputsMod', 'Model for the inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - CALL ReadVar( UnIn, FileName, InitInp%InputsFile, 'InputsFile', 'Filename for the SubDyn inputs', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - !---------------------- STEADY INPUTS (for InputsMod = 1) ---------------------------------------- - CALL ReadCom( UnIn, FileName, 'STEADY STATE INPUTS header', ErrStat2, ErrMsg2, UnEcho); call AbortIfFailed() - IF ( InitInp%InputsMod == 1 ) THEN - CALL ReadAry ( UnIn, FileName, InitInp%uTPInSteady , 6, 'uInSteady', 'Steady-state TP displacements and rotations.', ErrStat2, ErrMsg2, UnEcho) - CALL ReadAry ( UnIn, FileName, InitInp%uDotTPInSteady , 6, 'uDotTPInSteady', 'Steady-state TP translational and rotational velocities.', ErrStat2, ErrMsg2, UnEcho) - CALL ReadAry ( UnIn, FileName, InitInp%uDotDotTPInSteady, 6, 'uDotDotTPInSteady', 'Steady-state TP translational and rotational accelerations.', ErrStat2, ErrMsg2, UnEcho) - ELSE - InitInp%uTPInSteady = 0.0 - InitInp%uDotTPInSteady = 0.0 - InitInp%uDotDotTPInSteady = 0.0 - END IF - if(UnEcho>0) CLOSE( UnEcho ) - if(UnIn>0) CLOSE( UnIn ) - - ! Perform input checks and triggers - CALL GetPath( FileName, FilePath ) - IF ( PathIsRelative( InitInp%SDInputFile ) ) then - InitInp%SDInputFile = TRIM(FilePath)//TRIM(InitInp%SDInputFile) - END IF - IF ( PathIsRelative( InitInp%OutRootName ) ) then - InitInp%OutRootName = TRIM(FilePath)//TRIM(InitInp%OutRootName) - endif - IF ( PathIsRelative( InitInp%InputsFile ) ) then - InitInp%InputsFile = TRIM(FilePath)//TRIM(InitInp%InputsFile) - endif - - END SUBROUTINE ReadDriverInputFile - - subroutine print_help() - print '(a)', 'usage: ' - print '(a)', '' - print '(a)', 'SubDynDriver.exe driverfilename' - print '(a)', '' - print '(a)', 'Where driverfilename is the name of the SubDyn driver input file.' - print '(a)', '' - end subroutine print_help -!---------------------------------------------------------------------------------------------------------------------------------- -END PROGRAM TestSubDyn diff --git a/modules/subdyn/src_soildyn/SubDyn_Output.f90 b/modules/subdyn/src_soildyn/SubDyn_Output.f90 deleted file mode 100644 index 2c68d3b49..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Output.f90 +++ /dev/null @@ -1,804 +0,0 @@ -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -MODULE SubDyn_Output - USE NWTC_Library - USE SubDyn_Types - USE SD_FEM - USE SubDyn_Output_Params, only: MNfmKe, MNfmMe, MNTDss, MNRDe, MNTRAe, IntfSS, IntfTRss, IntfTRAss, ReactSS - USE SubDyn_Output_Params, only: ParamIndxAry, ParamUnitsAry, ValidParamAry, SSqm01, SSqmd01, SSqmdd01 - - IMPLICIT NONE - - ! The maximum number of output channels which can be output by the code. - INTEGER(IntKi),PUBLIC, PARAMETER :: MaxOutPts = 2265 - - PRIVATE - ! ..... Public Subroutines ................................................................................................... - PUBLIC :: SDOut_CloseSum - PUBLIC :: SDOut_OpenSum - PUBLIC :: SDOut_MapOutputs - PUBLIC :: SDOut_OpenOutput - PUBLIC :: SDOut_CloseOutput - PUBLIC :: SDOut_WriteOutputNames - PUBLIC :: SDOut_WriteOutputUnits - PUBLIC :: SDOut_WriteOutputs - PUBLIC :: SDOut_Init - -CONTAINS - - -!> This subroutine initializes the output module, checking if the output parameter list (OutList) -! contains valid names, and opening the output file if there are any requested outputs -SUBROUTINE SDOut_Init( Init, y, p, misc, InitOut, WtrDpth, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT( INOUT ) :: Init ! data needed to initialize the output module - TYPE(SD_OutputType), INTENT( INOUT ) :: y ! SubDyn module's output data - TYPE(SD_ParameterType), target, INTENT( INOUT ) :: p ! SubDyn module paramters - TYPE(SD_MiscVarType), INTENT( INOUT ) :: misc ! SubDyn misc/optimization variables - TYPE(SD_InitOutputType ), INTENT( INOUT ) :: InitOut ! SubDyn module initialization output data - REAL(ReKi), INTENT( IN ) :: WtrDpth ! water depth from initialization routine - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER(IntKi) :: ErrStat2 ! Error status of the operation - CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat /= ErrID_None - INTEGER(IntKi) :: I,J,K2 !Counters - INTEGER(IntKi) :: iMember ! Member index (not member ID) - INTEGER(IntKi) :: iElem ! Index of element in Element List - INTEGER(IntKi) :: iNode ! Index of node in Node list - INTEGER(IntKi) :: iiElem ! Loop counter on element index - INTEGER(IntKi) :: nElemPerNode ! Number of elements connecting to a node - type(MeshAuxDataType), pointer :: pLst !< Alias to shorten notation and highlight code similarities - real(ReKi), allocatable :: T_TIreact(:,:) ! Transpose of TIreact, temporary - ErrStat = 0 - ErrMsg="" - - p%OutAllDims=12*p%NMembers*2 !size of AllOut Member Joint forces - - ! Check that the variables in OutList are valid - CALL SDOut_ChkOutLst( Init%SSOutList, p, ErrStat2, ErrMsg2 ); if(Failed()) return - - ! --- Allocation (size 0 if not outputs) - !IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested - ! Allocate SDWrOuput which is used to store a time step's worth of output channels, prior to writing to a file. - CALL AllocAry(misc%SDWrOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'SDWrOutupt' , ErrStat2, ErrMsg2) ; if(Failed()) return - ! Allocate WriteOuput - CALL AllocAry(y%WriteOutput , p%NumOuts + p%OutAllInt*p%OutAllDims, 'WriteOutput', ErrStat2, ErrMsg2); if(Failed()) return - ! Header, and Units, copy of data already available in the OutParam data structure ! TODO TODO TODO remove copy - CALL AllocAry(InitOut%WriteOutputHdr, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputHdr', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(InitOut%WriteOutputUnt, p%NumOuts + p%OutAllint*p%OutAllDims, 'WriteOutputUnt', ErrStat2, ErrMsg2); if(Failed()) return - misc%SDWrOutput = 0.0_ReKi - misc%LastOutTime = 0.0_DbKi - misc%Decimat = 0 - y%WriteOutput = 0 - DO I = 1,p%NumOuts+p%OutAllint*p%OutAllDims - InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) - InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) - END DO - - !_________________________________ OUTPUT FOR REQUESTED MEMBERS _______________________________ - DO I=1,p%NMOutputs - pLst => p%MOutLst(I) ! Alias to shorten notations - CALL AllocAry(pLst%NodeIDs, pLst%NoutCnt , 'MOutLst(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmIDs, pLst%NoutCnt, 2, 'MOutLst(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, pLst%NoutCnt, 2, 'MOutLst(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12, pLst%NoutCnt, 2, 'MOutLst(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - - ! NOTE: len(MemberNodes) >2 if nDiv>1 - iMember = FINDLOCI(Init%Members(:,1), pLst%MemberID) ! Reindexing from MemberID to 1:nMembers - pLst%NodeIDs(1:pLst%NoutCnt)=Init%MemberNodes(iMember, pLst%NodeCnt) ! We are storing the actual node numbers corresponding to what the user ordinal number is requesting - pLst%ElmIDs=0 !Initialize to 0 - pLst%ElmNds=0 !Initialize to 0 - - DO J=1,pLst%NoutCnt ! loop on requested nodes for that member - iNode = pLst%NodeIDs(J) ! Index of requested node in node list - nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the j-th node - ! Finding 1 or max 2 elements that belong to the member and connect to the node - K2=0 ! Counter so that max 2 elements are included: NOTE: I belive more than 2 should be an error - DO iiElem = 1, nElemPerNode - iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number - IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN - IF (K2 == 2) EXIT ! we found both elements already, error... - K2=K2+1 - call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=J, iStore=K2, NodeID2=iNode) - END IF - ENDDO ! iiElem, nElemPerNode - ENDDO !J, Noutcnt - ENDDO !I, NMOutputs - - !_________________________________ OUTPUT FOR ALL MEMBERS __________________________________ - IF (p%OutAll) THEN !I need to store all member end forces and moments - - ! MOutLst2: nodal output info by members, for all members, First and Last Node - ALLOCATE ( p%MOutLst2(p%NMembers), STAT = ErrStat2 ); ErrMsg2 = 'Error allocating p%MOutLst2 array in SDOut_Init'; if(Failed()) return - - DO iMember=1,p%NMembers - pLst => p%MOutLst2(iMember) ! Alias - CALL AllocAry(pLst%NodeIDs, Init%Ndiv+1, 'MOutLst2(I)%NodeIDs', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmIDs, 2, 1, 'MOutLst2(I)%ElmIDs' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, 2, 1, 'MOutLst2(I)%ElmNds' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12, 2, 1, 'MOutLst2(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12, 2, 1, 'MOutLst2(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12, 2, 1, 'MOutLst2(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - pLst%MemberID = Init%Members(iMember,1) - pLst%NodeIDs = Init%MemberNodes(iMember,1:Init%Ndiv+1) ! We are storing the actual node numbers in the member - !ElmIDs could contain the same element twice if Ndiv=1 - pLst%ElmIDs=0 !Initialize to 0 - DO J=1,Init%Ndiv+1,Init%Ndiv ! loop on first and last node of member - iNode = pLst%NodeIDs(J) ! Index of requested node in node list - nElemPerNode = Init%NodesConnE(iNode, 1) ! Number of elements connecting to the 1st or last node of the member - K2= J/(Init%Ndiv+1)+1 ! 1 (first node) or 2 (last node) depending on J - DO iiElem=1, nElemPerNode - iElem = Init%NodesConnE(iNode,iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node - IF (ThisElementIsAlongMember(iElem, iNode, iMember)) THEN - call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=K2, iStore=1, NodeID2=iNode) - EXIT !We found the element for that node, exit loop on elements - ENDIF - ENDDO - ENDDO ! Loop on divisions - ENDDO ! Loop on members - ENDIF ! OutAll - !_____________________________________REACTIONS_____________________________________________ - ! --- Check if reaction requested by user - p%OutReact = .FALSE. - DO I=1,p%NumOuts - if ( ANY( p%OutParam(I)%Indx == ReactSS) ) THEN ! bjj: removed check of first 5 characters being "React" because (1) cases matter and (2) we can also ask for "-React*" or "mREACT" - p%OutReact =.TRUE. - EXIT - ENDIF - ENDDO - IF (p%OutReact) THEN !I need to store all constrained forces and moments; WE do not allow more than one member to be connected at a constrained joint for the time being - ! MOutLst3: nodal output info by members, for the members involved in reaction - ALLOCATE(p%MOutLst3(p%nNodes_C), STAT = ErrStat2); ErrMsg2 = 'Error allocating p%MOutLst3 array in SDOut_Init'; if(Failed()) return - - DO I=1,p%nNodes_C !For all constrained node - pLst => p%MOutLst3(I) - iNode = p%Nodes_C(I,1) ! Note: Nodes_C has been reindexed - nElemPerNode = Init%NodesConnE(iNode,1) ! Number of elements connecting to the joint - CALL AllocAry(pLst%ElmIDs, 1, nElemPerNode, ' p%MOutLst3(I)%ElmIds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%ElmNds, 1, nElemPerNode, ' p%MOutLst3(I)%ElmNds', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Me, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Me' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Ke, 12, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Ke' , ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(pLst%Fg, 12 , 1, nElemPerNode, ' p%MOutLst3(I)%Fg' , ErrStat2, ErrMsg2); if(Failed()) return - DO iiElem = 1, nElemPerNode - iElem = Init%NodesConnE(iNode, iiElem+1) ! iiElem-th Element Number in the set of elements attached to the selected node - call ConfigOutputNode_MKF_ID(pLst, iElem, iiNode=1, iStore=iiElem, NodeID2=iNode) - ENDDO - ENDDO - ! Compute p%TIreact, rigid transf. matrix from reaction DOFs to base structure point (0,0,-WD) - CALL AllocAry(p%TIreact, 6, p%nDOFC__, 'TIReact ', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(T_TIreact, p%nDOFC__, 6, 'TIReact_T', ErrStat2, ErrMsg2); if(Failed()) return - call RigidTrnsf(Init, p, (/0.0_Reki, 0.0_ReKi, -WtrDpth /), p%IDC__, p%nDOFC__, T_TIreact, ErrStat2, ErrMsg2); if(Failed()) return - p%TIreact=transpose(T_TIreact) - deallocate(T_TIreact) - ENDIF - RETURN - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SDOut_Init') - Failed = ErrStat >= AbortErrLev - END FUNCTION Failed - - !> Returns true if an element is connected to node iNode, and along member iMember - LOGICAL FUNCTION ThisElementIsAlongMember(iElem, iNode, iMember) - integer(IntKi), intent(in) :: iElem !< Element index - integer(IntKi), intent(in) :: iNode !< Node index - integer(IntKi), intent(in) :: iMember !< Member index - integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) - integer(IntKi) :: iOtherNode ! Other node than iNode for element iElem - ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the element - ! Check that the other node belongs to the member - IF (ElemNodes(1) == iNode) then - iOtherNode=ElemNodes(2) - else if (ElemNodes(2) == iNode) then - iOtherNode=ElemNodes(1) - else - ThisElementIsAlongMember=.false. ! Not along member since nodes don't match - return - endif - ! Being along the member means the second node of the element is in the node list of the member - ThisElementIsAlongMember= ANY(Init%MemberNodes(iMember,:) == iOtherNode) - END FUNCTION - - !> Set different "data" for a given output node, and possibly store more than one "data" per node: - !! The "data" is: - !! - Mass, stiffness matrices and constant element force (gravity and cable) - !! - A flag whether the node is the 1st or second node of an element - !! The "data" is stored at the index (iiNode,iStore): - !! - iiNode: node index within the list of nodes that are to be used for output for this member - !! - iStore: index over the number of "data" stored per node. E.g. Member1 and 2 connecting to a node - SUBROUTINE ConfigOutputNode_MKF_ID(pLst, iElem, iiNode, iStore, NodeID2) - type(MeshAuxDataType), intent(inout) :: pLst !< Info for one member output - integer(IntKi) , intent(in) :: iElem !< Element index to which the node belong - integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) - integer(IntKi) , intent(in) :: iStore !< Storage index, used several informations are stored per node - integer(IntKi) , intent(in) :: NodeID2 !< If ElemNode(2) == NodeID2, then it's the second node - integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) - REAL(ReKi) :: FCe(12) ! Pretension force from cable element - pLst%ElmIDs(iiNode,iStore) = iElem ! This array has for each joint requested the elements' ID to get results for - ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the k-th element - if (ElemNodes(2) == NodeID2) then - pLst%ElmNds(iiNode,iStore) = 2 ! store whether first or second node of element - else - pLst%ElmNds(iiNode,iStore) = 1 ! store whether first or second node of element - endif - ! --- Element Me, Ke, Fg, Fce - CALL ElemM(p%ElemProps(iElem), pLst%Me(:,:,iiNode,iStore)) - CALL ElemK(p%ElemProps(iElem), pLst%Ke(:,:,iiNode,iStore)) - CALL ElemF(p%ElemProps(iElem), Init%g, pLst%Fg(:,iiNode,iStore), FCe) - pLst%Fg(:,iiNode,iStore) = pLst%Fg(:,iiNode,iStore) + FCe(1:12) ! Adding cable element force - END SUBROUTINE ConfigOutputNode_MKF_ID - - -END SUBROUTINE SDOut_Init -!------------------------------------------------------------------------------------------------------ -!> Writes the data stored in the y variable to the correct indexed postions in WriteOutput -!! This is called by SD_CalcOutput() at each time step. -!! This routine does fill Allouts -!! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling -!! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) -SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) - real(DbKi), intent( in ) :: CurrentTime ! Current simulation time in seconds - type(SD_InputType), intent( in ) :: u ! SubDyn module's input data - type(SD_ContinuousStateType), intent( in ) :: x ! SubDyn module's states data - type(SD_OutputType), intent( inout ) :: y ! SubDyn module's output data - type(SD_ParameterType), target,intent( in ) :: p ! SubDyn module's parameter data - type(SD_MiscVarType), intent( inout ) :: m ! Misc/optimization variables - real(ReKi), intent( out ) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) ! Array of output data for all possible outputs - integer(IntKi), intent( out ) :: ErrStat ! Error status of the operation - character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - !locals - integer(IntKi) :: iMemberOutput, iiNode, iSDNode, iMeshNode, I, J, L, L2 ! Counters - integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM - real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments - real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments - real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) - real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions - integer(IntKi) :: sgn !+1/-1 for node force calculations - type(MeshAuxDataType), pointer :: pLst !< Info for a given member-output (Alias to shorten notation) - integer(IntKi), pointer :: DOFList(:) !< List of DOF indices for a given Nodes (Alias to shorten notation) - ErrStat = ErrID_None - ErrMsg = "" - - AllOuts = 0.0_ReKi ! initialize for those outputs that aren't valid (and thus aren't set in this routine) - - ! -------------------------------------------------------------------------------- - ! --- Requested member-outputs (Node kinematics and loads) - ! -------------------------------------------------------------------------------- - ! p%MOutLst has the mapping for the member, node, elements per node, to be used - ! MXNYZZZ will need to connects to p%MOutLst(X)%ElmIDs(Y,1:2) if it is a force or accel; else to u%UFL(p%MOutLst(X)%NodeIDs(Y)) - if (p%NumOuts > 0) then !bjj: some of these fields aren't allocated when NumOuts==0 - ! Loop over member-outputs requested - DO iMemberOutput=1,p%NMOutputs - pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output - DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member - ! --- Forces (potentially averaged on 2 elements) - call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) - FM_elm2=sgn*FM_elm - FK_elm2=sgn*FK_elm - IF (pLst%ElmIDs(iiNode,2) .NE. 0) THEN ! Second element exist - ! NOTE: forces are computed in the coordinate system of the first element for averaging - call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above - FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average - FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average - ENDIF - ! Static (elastic) component of reaction forces and moments at MαNβ along local member coordinate system - ! "MαNβFKxe, MαNβFKye, MαNβFKze, MαNβMKxe, MαNβMKye, MαNβMKze" - AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref - ! Dynamic (inertial) component of reaction forces and moments at MαNβ along local member coordinate system - ! "MαNβFMxe, MαNβFMye, MαNβFMze, MαNβMMxe, MαNβMMye, MαNβMMze" - AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref - - ! --- Displacements and acceleration - DOFList => p%NodesDOF(pLst%NodeIDs(iiNode))%List - ! Displacement- Translational -no need for averaging since it is a node translation - In global reference SS - ! "MαNβTDxss, MαNβTDyss, MαNβTDzss" - AllOuts(MNTDss (:,iiNode,iMemberOutput)) = m%U_full(DOFList(1:3)) - ! Displacement- Rotational - need direction cosine matrix to tranform rotations - In Local reference Element Ref Sys - ! "MαNβRDxss, MαNβRDye, MαNβRDze" - AllOuts(MNRDe (:,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full(DOFList(4:6))) !local ref - ! Accelerations- I need to get the direction cosine matrix to tranform displacement and rotations - ! "MαNβTAxe, MαNβTAye, MαNβTAze" - ! "MαNβRAxe, MαNβRAye, MαNβRAze" - AllOuts(MNTRAe (1:3,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(1:3))) ! translational accel local ref - AllOuts(MNTRAe (4:6,iiNode,iMemberOutput)) = matmul(DIRCOS,m%U_full_dotdot(DOFList(4:6))) ! rotational accel local ref - ENDDO ! iiNode, Loop on requested nodes for that member - ENDDO ! iMemberOutput, Loop on member outputs - END IF - - ! -------------------------------------------------------------------------------- - ! --- All nodal loads from stiffness and mass matrix - ! -------------------------------------------------------------------------------- - ! "MaaaJbFKxe, MaaaJbMKxe MaaaJbFMxe, MaaaJbMMxe for member aaa and node b." - IF (p%OutAll) THEN - DO iMemberOutput=1,p%NMembers !Cycle on all members - pLst=>p%MOutLst2(iMemberOutput) - DO iiNode=1,2 !Iterate on requested nodes for that member (first and last) - call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) - ! Store in All Outs - L = MaxOutPts+(iMemberOutput-1)*24+(iiNode-1)*12+1 - L2 = L+11 - AllOuts( L:L2 ) =sgn* (/FK_elm,FM_elm/) - ENDDO !iiNode, nodes 1 and 2 - ENDDO ! iMemberOutput, Loop on members - ENDIF - - ! -------------------------------------------------------------------------------- - ! --- Interface kinematics and loads (TP/platform reference point) - ! -------------------------------------------------------------------------------- - ! Total interface reaction forces and moments in SS coordinate system - ! "IntfFXss, IntfFYss, IntfFZss, IntfMXss, IntfMYss, IntfMZss," - AllOuts(IntfSS(1:nDOFL_TP))= - (/y%Y1Mesh%Force (:,1), y%Y1Mesh%Moment(:,1)/) !-y%Y1 !Note this is the force that the TP applies to the Jacket, opposite to what the GLue Code needs thus "-" sign - ! Interface translations and rotations in SS coordinate system - ! "IntfTDXss, IntfTDYss, IntfTDZss, IntfRDXss, IntfRDYss IntfRDZss" - AllOuts(IntfTRss(1:nDOFL_TP))=m%u_TP - ! Interface Translational and rotational accelerations in SS coordinate system - ! "IntfTAXss, IntfTAYss, IntfTAZss, IntfRAXss, IntfRAYss IntfRAZss" - AllOuts(IntfTRAss(1:nDOFL_TP))= m%udotdot_TP - - ! -------------------------------------------------------------------------------- - ! --- Modal parameters "SSqmXX, SSqmdotXX, SSqmddXX" amplitude, speed and acceleration - ! -------------------------------------------------------------------------------- - maxOutModes = min(p%nDOFM,99) ! We only have space for the first 99 values - IF ( maxOutModes > 0 ) THEN - !BJJ: TODO: is there a check to see if we requested these channels but didn't request the modes? (i.e., retain 2 modes but asked for 75th mode?) - AllOuts(SSqm01 :SSqm01 +maxOutModes-1) = x%qm (1:maxOutModes) - AllOuts(SSqmd01 :SSqmd01 +maxOutModes-1) = x%qmdot (1:maxOutModes) - AllOuts(SSqmdd01:SSqmdd01+maxOutModes-1) = m%qmdotdot(1:maxOutModes) - END IF - - ! --------------------------------------------------------------------------------} - ! --- Base reaction loads - ! --------------------------------------------------------------------------------{ - ! Total base reaction forces and moments at the (0.,0.,-WtrDpth) location in SS coordinate system - ! "ReactFXss, ReactFYss, ReactFZss, ReactMXss, ReactMYss, ReactMZss" - IF (p%OutReact) THEN - ALLOCATE ( ReactNs(6*p%nNodes_C), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for ReactNs array.' - ErrStat = ErrID_Fatal - RETURN - END IF - ReactNs = 0.0_ReKi !Initialize - DO I=1,p%nNodes_C !Do for each constrained node, they are ordered as given in the input file and so as in the order of y2mesh - FK_elm2=0._ReKi !Initialize for cumulative force - FM_elm2=0._ReKi !Initialize - pLst => p%MOutLst3(I) - !Find the joint forces - DO J=1,SIZE(pLst%ElmIDs(1,:)) !for all the elements connected (normally 1) - iiNode = 1 - call ElementForce(pLst, iiNode, J, FM_elm, FK_elm, sgn, DIRCOS, .false.) - !transform back to global, need to do 3 at a time since cosine matrix is 3x3 - DO L=1,2 - FM_elm2((L-1)*3+1:L*3) = FM_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FM_elm((L-1)*3+1:L*3)) !sum forces at joint in GLOBAL REF - FK_elm2((L-1)*3+1:L*3) = FK_elm2((L-1)*3+1:L*3) + matmul(transpose(DIRCOS),FK_elm((L-1)*3+1:L*3)) !signs may be wrong, we will fix that later; - ! I believe this is all fixed in terms of signs now ,RRD 5/20/13 - ENDDO - ENDDO - ! FK_elm2 ! + FM_elm2 !removed the inertial component 12/13 !Not sure why I need an intermediate step here, but the sum would not work otherwise - ! NEED TO ADD HYDRODYNAMIC FORCES AT THE RESTRAINT NODES - iSDNode = p%Nodes_C(I,1) - iMeshNode = iSDNode ! input and Y2 mesh nodes are the same as subdyn - Fext = (/ u%LMesh%Force(:,iMeshNode), u%LMesh%Moment(:,iMeshNode) /) - ReactNs((I-1)*6+1:6*I) = FK_elm2 - Fext !Accumulate reactions from all nodes in GLOBAL COORDINATES - ENDDO - ! Store into AllOuts - AllOuts( ReactSS(1:nDOFL_TP) ) = matmul(p%TIreact,ReactNs) - ENDIF - if (allocated(ReactNs)) deallocate(ReactNs) -contains - - subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInputDirCos) - type(MeshAuxDataType), intent(in) :: pLst !< Info for one member output - integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) - integer(IntKi) , intent(in) :: JJ !< TODO: interpretation: index over other member connected to the current member (for averaging) - real(ReKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) - real(ReKi), dimension (6), intent(out) :: FM_elm, FK_elm !output static and dynamic forces and moments - integer(IntKi), intent(out) :: sgn !+1/-1 for node force calculations - logical, intent(in) :: bUseInputDirCos !< If True, use DIRCOS from input, otherwise, use element DirCos - ! Local - integer(IntKi) :: iElem !< Element index/number - integer(IntKi) :: FirstOrSecond !< 1 or 2 if first node or second node - integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) - real(ReKi) , dimension(12) :: X_e, Xdd_e ! Displacement and acceleration for an element - integer(IntKi), dimension(2), parameter :: NodeNumber_To_Sign = (/-1, +1/) - - iElem = pLst%ElmIDs(iiNode,JJ) ! element number - FirstOrSecond = pLst%ElmNds(iiNode,JJ) ! first or second node of the element to be considered - sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node - ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element iElem - X_e(1:6) = m%U_full (p%NodesDOF(ElemNodes(1))%List(1:6)) - X_e(7:12) = m%U_full (p%NodesDOF(ElemNodes(2))%List(1:6)) - Xdd_e(1:6) = m%U_full_dotdot(p%NodesDOF(ElemNodes(1))%List(1:6)) - Xdd_e(7:12) = m%U_full_dotdot(p%NodesDOF(ElemNodes(2))%List(1:6)) - if (.not. bUseInputDirCos) then - DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local - endif - CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,JJ),pLst%Ke(:,:,iiNode,JJ), Xdd_e, X_e, pLst%Fg(:,iiNode,JJ), FirstOrSecond, FM_elm, FK_elm) - end subroutine ElementForce - - !==================================================================================================== - !> Calculates static and dynamic forces for a given element, using K and M of the element, and - !output quantities Udotdot and Y2 containing the - !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked - !---------------------------------------------------------------------------------------------------- - SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) - Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) - Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces - Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest - REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments - !Locals - INTEGER(IntKi) :: L !counter - REAL(DbKi), DIMENSION(12) :: FM_glb, FF_glb, FM_elm, FF_elm ! temporary storage - - FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE - FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE - FF_glb = FF_glb - Fg ! GLOBAL REFERENCE - DO L=1,4 ! Transforming coordinates 3 at a time - FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) - FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) - ENDDO - FM_nod = FM_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) ! k2=1, 1:6, k2=2 7:12 - FK_nod = FF_elm(6*(FirstOrSecond-1)+1:FirstOrSecond*6) - - END SUBROUTINE CALC_NODE_FORCES -END SUBROUTINE SDOut_MapOutputs - - -!==================================================================================================== -SUBROUTINE SDOut_CloseSum( UnSum, ErrStat, ErrMsg ) - INTEGER, INTENT( IN ) :: UnSum ! the unit number for the SubDyn summary file - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: Stat ! status from I/) operation - ErrStat = ErrID_None - ErrMsg = "" - ! Write any closing information in the summary file - IF ( UnSum > 0 ) THEN - WRITE (UnSum,'(/,A/)', IOSTAT=Stat) '#This summary file was closed on '//CurDate()//' at '//CurTime()//'.' - IF (Stat /= 0) THEN - ErrStat = ErrID_FATAL - ErrMsg = ' Problem writing to summary file.' - END IF - ! Close the file - CLOSE( UnSum, IOSTAT=Stat ) - IF (Stat /= 0) THEN - ErrStat = ErrID_FATAL - ErrMsg = TRIM(ErrMsg)//' Problem closing summary file.' - END IF - IF ( ErrStat /= ErrID_None ) ErrMsg = 'SDOut_CloseSum'//TRIM(ErrMsg) - END IF -END SUBROUTINE SDOut_CloseSum - -!==================================================================================================== -SUBROUTINE SDOut_OpenSum( UnSum, SummaryName, SD_Prog, ErrStat, ErrMsg ) - INTEGER, INTENT( OUT ) :: UnSum ! the unit number for the SubDyn summary file - CHARACTER(*), INTENT( IN ) :: SummaryName ! the name of the SubDyn summary file - TYPE(ProgDesc), INTENT( IN ) :: SD_Prog ! the name/version/date of the program - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer :: ErrStat2 - ErrStat = ErrID_None - ErrMsg = "" - - CALL GetNewUnit( UnSum ) - CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = 'Failed to open SubDyn summary file: '//TRIM(ErrMsg) - RETURN - END IF - - ! Write the summary file header - WRITE (UnSum,'(/,A/)', IOSTAT=ErrStat2) '#This summary file was generated by '//TRIM( SD_Prog%Name )//& - ' '//TRIM( SD_Prog%Ver )//' on '//CurDate()//' at '//CurTime()//'.' -END SUBROUTINE SDOut_OpenSum - -!==================================================================================================== -SUBROUTINE SDOut_OpenOutput( ProgVer, OutRootName, p, InitOut, ErrStat, ErrMsg ) -! This subroutine initialized the output module, checking if the output parameter list (OutList) -! contains valid names, and opening the output file if there are any requested outputs -!---------------------------------------------------------------------------------------------------- - ! Passed variables - TYPE(ProgDesc), INTENT( IN ) :: ProgVer - CHARACTER(*), INTENT( IN ) :: OutRootName ! Root name for the output file - TYPE(SD_ParameterType), INTENT( INOUT ) :: p - TYPE(SD_InitOutPutType ), INTENT( IN ) :: InitOut ! - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I ! Generic loop counter - CHARACTER(1024) :: OutFileName ! The name of the output file including the full path. - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: ErrStat2 - ErrStat = ErrID_None - ErrMsg = "" - ! Open the output file, if necessary, and write the header - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file - ! Open the file for output - OutFileName = TRIM(OutRootName)//'.out' - CALL GetNewUnit( p%UnJckF ) - - CALL OpenFOutFile ( p%UnJckF, OutFileName, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = ' Error opening SubDyn-level output file: '//TRIM(ErrMsg) - RETURN - END IF - - ! Write the output file header - WRITE (p%UnJckF,'(/,A/)', IOSTAT=ErrStat2) 'These predictions were generated by '//TRIM(GETNVD(ProgVer))//& - ' on '//CurDate()//' at '//CurTime()//'.' - - WRITE(p%UnJckF, '(//)') ! add 3 lines to make file format consistant with FAST v8 (headers on line 7; units on line 8) [this allows easier post-processing] - - ! Write the names of the output parameters: - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 'Time' ), ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - - ! Write the units of the output parameters: - WRITE(p%UnJckF,Frmt, IOSTAT=ErrStat2) TRIM( 's'), ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - END IF ! there are any requested outputs -END SUBROUTINE SDOut_OpenOutput - -!==================================================================================================== - - -!==================================================================================================== -SUBROUTINE SDOut_CloseOutput ( p, ErrStat, ErrMsg ) -! This function cleans up after running the SubDyn output module. It closes the output file, -! releases memory, and resets the number of outputs requested to 0. -!---------------------------------------------------------------------------------------------------- - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! data for this instance of the floating platform module - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - LOGICAL :: Err - - ErrStat = 0 - ErrMsg = "" - Err = .FALSE. - - ! Close our output file - CLOSE( p%UnJckF, IOSTAT = ErrStat ) - IF ( ErrStat /= 0 ) Err = .TRUE. - - ! Make sure ErrStat is non-zero if an error occurred - IF ( Err ) ErrStat = ErrID_Fatal - RETURN - -END SUBROUTINE SDOut_CloseOutput -!==================================================================================================== - -SUBROUTINE SDOut_WriteOutputNames( UnJckF, p, ErrStat, ErrMsg ) - - INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file - TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Name ), ( p%Delim, TRIM( p%OutParam(I)%Name ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - -END SUBROUTINE SDOut_WriteOutputNames - -!==================================================================================================== - -SUBROUTINE SDOut_WriteOutputUnits( UnJckF, p, ErrStat, ErrMsg ) - INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file - TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - CHARACTER(200) :: Frmt ! a string to hold a format statement - INTEGER :: I ! Generic loop counter - ErrStat = ErrID_None - ErrMsg = "" - - Frmt = '(A8,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutSFmt )//'))' - - WRITE(UnJckF,Frmt) TRIM( p%OutParam(0)%Units ), ( p%Delim, TRIM( p%OutParam(I)%Units ), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - -END SUBROUTINE SDOut_WriteOutputUnits - -!==================================================================================================== -SUBROUTINE SDOut_WriteOutputs( UnJckF, Time, SDWrOutput, p, ErrStat, ErrMsg ) -! This subroutine writes the data stored in WriteOutputs (and indexed in OutParam) to the file -! opened in SDOut_Init() -!---------------------------------------------------------------------------------------------------- - INTEGER, INTENT( IN ) :: UnJckF ! file unit for the output file - REAL(DbKi), INTENT( IN ) :: Time ! Time for this output - REAL(ReKi), INTENT( IN ) :: SDWrOutput(:) ! SubDyn module's output data - TYPE(SD_ParameterType), INTENT( IN ) :: p ! SubDyn module's parameter data - INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables - INTEGER :: I ! Generic loop counter - CHARACTER(200) :: Frmt ! a string to hold a format statement - ErrStat = ErrID_None - ErrMsg = "" - - ! Initialize ErrStat and determine if it makes any sense to write output - IF ( .NOT. ALLOCATED( p%OutParam ) .OR. UnJckF < 0 ) THEN - ErrStat = ErrID_Fatal - ErrMsg = ' To write outputs for SubDyn there must be a valid file ID and OutParam must be allocated.' - RETURN - ELSE - ErrStat = ErrID_None - END IF - - ! Write the output parameters to the file - Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts+p%OutAllInt*p%OutAllDims))//'(:,A,'//TRIM( p%OutFmt )//'))' - - WRITE(UnJckF,Frmt) Time, ( p%Delim, SDWrOutput(I), I=1,p%NumOuts+p%OutAllInt*p%OutAllDims ) - -END SUBROUTINE SDOut_WriteOutputs - -!==================================================================================================== - - -!==================================================================================================== -SUBROUTINE SDOut_ChkOutLst( OutList, p, ErrStat, ErrMsg ) -! This routine checks the names of inputted output channels, checks to see if any of them are ill- -! conditioned (returning an error if so), and assigns the OutputDataType settings (i.e, the index, -! name, and units of the output channels). -! NOTE OutParam is populated here -!---------------------------------------------------------------------------------------------------- - TYPE(SD_ParameterType), INTENT( INOUT ) :: p ! SubDyn module parameter data - CHARACTER(ChanLen), INTENT( IN ) :: OutList (:) ! An array holding the names of the requested output channels. - INTEGER, INTENT( OUT ) :: ErrStat ! a non-zero value indicates an error occurred - CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! Local variables. - INTEGER :: I,J,K ! Generic loop-counting index. - INTEGER :: INDX ! Index for valid arrays - CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I). - !CHARACTER(28), PARAMETER :: OutPFmt = "( I4, 3X,A 10,1 X, A10 )" ! Output format parameter output list. - CHARACTER(ChanLen), DIMENSION(24) :: ToTUnits,ToTNames,ToTNames0 - LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration - LOGICAL :: CheckOutListAgain - ErrStat = ErrID_None - ErrMsg = "" - - InvalidOutput = .FALSE. - - ! mark invalid output channels: - DO k=p%nDOFM+1,99 - InvalidOutput(SSqm01 +k-1) = .true. - InvalidOutput(SSqmd01 +k-1) = .true. - InvalidOutput(SSqmdd01+k-1) = .true. - END DO - - DO I=1,9 - !I know el # and whether it is 1st node or second node - if (I <= p%NMOutputs) then - INDX=p%MOutLst(I)%NOutCnt+1 - else - INDX = 1 - end if - - DO J=INDX,9 !Iterate on requested nodes for that member - !Forces and moments - InvalidOutput(MNfmKe (:,J,I)) = .true. !static forces and moments (6) Local Ref - InvalidOutput(MNfmMe (:,J,I)) = .true. !dynamic forces and moments (6) Local Ref - !Displacement - InvalidOutput(MNTDss (:,J,I)) = .true. !Translational - InvalidOutput(MNRDe (:,J,I)) = .true. !Rotational - !Accelerations - InvalidOutput(MNTRAe (:,J,I)) = .true. !translational accel local ref - END DO - END DO - - !------------------------------------------------------------------------------------------------- - ! ALLOCATE the OutParam array - !------------------------------------------------------------------------------------------------- - ALLOCATE ( p%OutParam(1:p%NumOuts+p%OutAllInt*p%OutAllDims) , STAT=ErrStat ) - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error allocating memory for the OutParam array.' - ErrStat = ErrID_Fatal - RETURN - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set index, name, and units for the output channels - ! If a selected output channel is not available in this module, set error flag and return. - !------------------------------------------------------------------------------------------------- - !!!p%OutParam(0)%Name = 'Time' ! OutData(0) is the time channel by default. - !!!p%OutParam(0)%Units = '(sec)' ! - !!!p%OutParam(0)%Indx = Time - !!!p%OutParam(0)%SignM = 1 - - DO I = 1,p%NumOuts - - p%OutParam(I)%Name = OutList(I) - OutListTmp = OutList(I) - - - ! Reverse the sign (+/-) of the output channel if the user prefixed the - ! channel name with a '-', '_', 'm', or 'M' character indicating "minus". - - CheckOutListAgain = .FALSE. - - IF ( INDEX( '-_', OutListTmp(1:1) ) > 0 ) THEN - p%OutParam(I)%SignM = -1 ! ex, '-TipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - ELSE IF ( INDEX( 'mM', OutListTmp(1:1) ) > 0 ) THEN ! We'll assume this is a variable name for now, (if not, we will check later if OutListTmp(2:) is also a variable name) - CheckOutListAgain = .TRUE. - p%OutParam(I)%SignM = 1 - ELSE - p%OutParam(I)%SignM = 1 - END IF - - CALL Conv2UC( OutListTmp ) ! Convert OutListTmp to upper case - - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - - IF ( CheckOutListAgain .AND. Indx < 1 ) THEN ! Let's assume that "M" really meant "minus" and then test again - p%OutParam(I)%SignM = -1 ! ex, 'MTipDxc1' causes the sign of TipDxc1 to be switched. - OutListTmp = OutListTmp(2:) - - Indx = IndexCharAry( OutListTmp(1:9), ValidParamAry ) - END IF - - IF ( Indx > 0 ) THEN - p%OutParam(I)%Indx = ParamIndxAry(Indx) - IF ( InvalidOutput( ParamIndxAry(Indx) ) ) THEN - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%SignM = 0 - ELSE - p%OutParam(I)%Units = ParamUnitsAry(Indx) - END IF - ELSE - ErrMsg = p%OutParam(I)%Name//' is not an available output channel.' - ErrStat = ErrID_Fatal - p%OutParam(I)%Units = 'INVALID' - p%OutParam(I)%Indx = 0 - p%OutParam(I)%SignM = 0 ! this will print all zeros - END IF - - END DO - - IF (p%OutAll) THEN !Finish populating the OutParam with all the joint forces and moments - ToTNames0=RESHAPE(SPREAD( (/"FKxe", "FKye", "FKze", "MKxe", "MKye", "MKze", "FMxe", "FMye", "FMze", "MMxe", "MMye", "MMze"/), 2, 2), (/24/) ) - ToTUnits=RESHAPE(SPREAD( (/"(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)", "(N) ","(N) ","(N) ", "(N*m)","(N*m)","(N*m)"/), 2, 2), (/24/) ) - DO I=1,p%NMembers - DO K=1,2 - DO J=1,12 - TotNames(J+(K-1)*12)=TRIM("M"//Int2Lstr(I))//TRIM("J"//Int2Lstr(K))//TRIM(TotNames0(J)) - ENDDO - ENDDO - p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Name = ToTNames - p%OutParam(p%NumOuts+(I-1)*12*2+1:p%NumOuts+I*12*2)%Units = ToTUnits - ENDDO - p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%SignM = 1 - p%OutParam(p%NumOuts+1:p%NumOuts+p%OutAllDims)%Indx= MaxOutPts+(/(J, J=1, p%OutAllDims)/) - ENDIF - -END SUBROUTINE SDOut_ChkOutLst -!==================================================================================================== -END MODULE SubDyn_Output diff --git a/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 b/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 deleted file mode 100644 index 4844a51f1..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Output_Params.f90 +++ /dev/null @@ -1,3723 +0,0 @@ -module SubDyn_Output_Params - use NWTC_Library - - ! Indices for computing output channels: - ! NOTES: - ! (1) These parameters are in the order stored in "OutListParameters.xlsx" - ! (2) Array AllOuts() must be dimensioned to the value of the largest output parameter - IMPLICIT NONE - - PUBLIC - - ! Time: - INTEGER, PARAMETER :: Time = 0 - - ! Member Forces: - - INTEGER(IntKi), PARAMETER :: M1N1FKxe = 1 - INTEGER(IntKi), PARAMETER :: M1N2FKxe = 2 - INTEGER(IntKi), PARAMETER :: M1N3FKxe = 3 - INTEGER(IntKi), PARAMETER :: M1N4FKxe = 4 - INTEGER(IntKi), PARAMETER :: M1N5FKxe = 5 - INTEGER(IntKi), PARAMETER :: M1N6FKxe = 6 - INTEGER(IntKi), PARAMETER :: M1N7FKxe = 7 - INTEGER(IntKi), PARAMETER :: M1N8FKxe = 8 - INTEGER(IntKi), PARAMETER :: M1N9FKxe = 9 - INTEGER(IntKi), PARAMETER :: M2N1FKxe = 10 - INTEGER(IntKi), PARAMETER :: M2N2FKxe = 11 - INTEGER(IntKi), PARAMETER :: M2N3FKxe = 12 - INTEGER(IntKi), PARAMETER :: M2N4FKxe = 13 - INTEGER(IntKi), PARAMETER :: M2N5FKxe = 14 - INTEGER(IntKi), PARAMETER :: M2N6FKxe = 15 - INTEGER(IntKi), PARAMETER :: M2N7FKxe = 16 - INTEGER(IntKi), PARAMETER :: M2N8FKxe = 17 - INTEGER(IntKi), PARAMETER :: M2N9FKxe = 18 - INTEGER(IntKi), PARAMETER :: M3N1FKxe = 19 - INTEGER(IntKi), PARAMETER :: M3N2FKxe = 20 - INTEGER(IntKi), PARAMETER :: M3N3FKxe = 21 - INTEGER(IntKi), PARAMETER :: M3N4FKxe = 22 - INTEGER(IntKi), PARAMETER :: M3N5FKxe = 23 - INTEGER(IntKi), PARAMETER :: M3N6FKxe = 24 - INTEGER(IntKi), PARAMETER :: M3N7FKxe = 25 - INTEGER(IntKi), PARAMETER :: M3N8FKxe = 26 - INTEGER(IntKi), PARAMETER :: M3N9FKxe = 27 - INTEGER(IntKi), PARAMETER :: M4N1FKxe = 28 - INTEGER(IntKi), PARAMETER :: M4N2FKxe = 29 - INTEGER(IntKi), PARAMETER :: M4N3FKxe = 30 - INTEGER(IntKi), PARAMETER :: M4N4FKxe = 31 - INTEGER(IntKi), PARAMETER :: M4N5FKxe = 32 - INTEGER(IntKi), PARAMETER :: M4N6FKxe = 33 - INTEGER(IntKi), PARAMETER :: M4N7FKxe = 34 - INTEGER(IntKi), PARAMETER :: M4N8FKxe = 35 - INTEGER(IntKi), PARAMETER :: M4N9FKxe = 36 - INTEGER(IntKi), PARAMETER :: M5N1FKxe = 37 - INTEGER(IntKi), PARAMETER :: M5N2FKxe = 38 - INTEGER(IntKi), PARAMETER :: M5N3FKxe = 39 - INTEGER(IntKi), PARAMETER :: M5N4FKxe = 40 - INTEGER(IntKi), PARAMETER :: M5N5FKxe = 41 - INTEGER(IntKi), PARAMETER :: M5N6FKxe = 42 - INTEGER(IntKi), PARAMETER :: M5N7FKxe = 43 - INTEGER(IntKi), PARAMETER :: M5N8FKxe = 44 - INTEGER(IntKi), PARAMETER :: M5N9FKxe = 45 - INTEGER(IntKi), PARAMETER :: M6N1FKxe = 46 - INTEGER(IntKi), PARAMETER :: M6N2FKxe = 47 - INTEGER(IntKi), PARAMETER :: M6N3FKxe = 48 - INTEGER(IntKi), PARAMETER :: M6N4FKxe = 49 - INTEGER(IntKi), PARAMETER :: M6N5FKxe = 50 - INTEGER(IntKi), PARAMETER :: M6N6FKxe = 51 - INTEGER(IntKi), PARAMETER :: M6N7FKxe = 52 - INTEGER(IntKi), PARAMETER :: M6N8FKxe = 53 - INTEGER(IntKi), PARAMETER :: M6N9FKxe = 54 - INTEGER(IntKi), PARAMETER :: M7N1FKxe = 55 - INTEGER(IntKi), PARAMETER :: M7N2FKxe = 56 - INTEGER(IntKi), PARAMETER :: M7N3FKxe = 57 - INTEGER(IntKi), PARAMETER :: M7N4FKxe = 58 - INTEGER(IntKi), PARAMETER :: M7N5FKxe = 59 - INTEGER(IntKi), PARAMETER :: M7N6FKxe = 60 - INTEGER(IntKi), PARAMETER :: M7N7FKxe = 61 - INTEGER(IntKi), PARAMETER :: M7N8FKxe = 62 - INTEGER(IntKi), PARAMETER :: M7N9FKxe = 63 - INTEGER(IntKi), PARAMETER :: M8N1FKxe = 64 - INTEGER(IntKi), PARAMETER :: M8N2FKxe = 65 - INTEGER(IntKi), PARAMETER :: M8N3FKxe = 66 - INTEGER(IntKi), PARAMETER :: M8N4FKxe = 67 - INTEGER(IntKi), PARAMETER :: M8N5FKxe = 68 - INTEGER(IntKi), PARAMETER :: M8N6FKxe = 69 - INTEGER(IntKi), PARAMETER :: M8N7FKxe = 70 - INTEGER(IntKi), PARAMETER :: M8N8FKxe = 71 - INTEGER(IntKi), PARAMETER :: M8N9FKxe = 72 - INTEGER(IntKi), PARAMETER :: M9N1FKxe = 73 - INTEGER(IntKi), PARAMETER :: M9N2FKxe = 74 - INTEGER(IntKi), PARAMETER :: M9N3FKxe = 75 - INTEGER(IntKi), PARAMETER :: M9N4FKxe = 76 - INTEGER(IntKi), PARAMETER :: M9N5FKxe = 77 - INTEGER(IntKi), PARAMETER :: M9N6FKxe = 78 - INTEGER(IntKi), PARAMETER :: M9N7FKxe = 79 - INTEGER(IntKi), PARAMETER :: M9N8FKxe = 80 - INTEGER(IntKi), PARAMETER :: M9N9FKxe = 81 - INTEGER(IntKi), PARAMETER :: M1N1FKye = 82 - INTEGER(IntKi), PARAMETER :: M1N2FKye = 83 - INTEGER(IntKi), PARAMETER :: M1N3FKye = 84 - INTEGER(IntKi), PARAMETER :: M1N4FKye = 85 - INTEGER(IntKi), PARAMETER :: M1N5FKye = 86 - INTEGER(IntKi), PARAMETER :: M1N6FKye = 87 - INTEGER(IntKi), PARAMETER :: M1N7FKye = 88 - INTEGER(IntKi), PARAMETER :: M1N8FKye = 89 - INTEGER(IntKi), PARAMETER :: M1N9FKye = 90 - INTEGER(IntKi), PARAMETER :: M2N1FKye = 91 - INTEGER(IntKi), PARAMETER :: M2N2FKye = 92 - INTEGER(IntKi), PARAMETER :: M2N3FKye = 93 - INTEGER(IntKi), PARAMETER :: M2N4FKye = 94 - INTEGER(IntKi), PARAMETER :: M2N5FKye = 95 - INTEGER(IntKi), PARAMETER :: M2N6FKye = 96 - INTEGER(IntKi), PARAMETER :: M2N7FKye = 97 - INTEGER(IntKi), PARAMETER :: M2N8FKye = 98 - INTEGER(IntKi), PARAMETER :: M2N9FKye = 99 - INTEGER(IntKi), PARAMETER :: M3N1FKye = 100 - INTEGER(IntKi), PARAMETER :: M3N2FKye = 101 - INTEGER(IntKi), PARAMETER :: M3N3FKye = 102 - INTEGER(IntKi), PARAMETER :: M3N4FKye = 103 - INTEGER(IntKi), PARAMETER :: M3N5FKye = 104 - INTEGER(IntKi), PARAMETER :: M3N6FKye = 105 - INTEGER(IntKi), PARAMETER :: M3N7FKye = 106 - INTEGER(IntKi), PARAMETER :: M3N8FKye = 107 - INTEGER(IntKi), PARAMETER :: M3N9FKye = 108 - INTEGER(IntKi), PARAMETER :: M4N1FKye = 109 - INTEGER(IntKi), PARAMETER :: M4N2FKye = 110 - INTEGER(IntKi), PARAMETER :: M4N3FKye = 111 - INTEGER(IntKi), PARAMETER :: M4N4FKye = 112 - INTEGER(IntKi), PARAMETER :: M4N5FKye = 113 - INTEGER(IntKi), PARAMETER :: M4N6FKye = 114 - INTEGER(IntKi), PARAMETER :: M4N7FKye = 115 - INTEGER(IntKi), PARAMETER :: M4N8FKye = 116 - INTEGER(IntKi), PARAMETER :: M4N9FKye = 117 - INTEGER(IntKi), PARAMETER :: M5N1FKye = 118 - INTEGER(IntKi), PARAMETER :: M5N2FKye = 119 - INTEGER(IntKi), PARAMETER :: M5N3FKye = 120 - INTEGER(IntKi), PARAMETER :: M5N4FKye = 121 - INTEGER(IntKi), PARAMETER :: M5N5FKye = 122 - INTEGER(IntKi), PARAMETER :: M5N6FKye = 123 - INTEGER(IntKi), PARAMETER :: M5N7FKye = 124 - INTEGER(IntKi), PARAMETER :: M5N8FKye = 125 - INTEGER(IntKi), PARAMETER :: M5N9FKye = 126 - INTEGER(IntKi), PARAMETER :: M6N1FKye = 127 - INTEGER(IntKi), PARAMETER :: M6N2FKye = 128 - INTEGER(IntKi), PARAMETER :: M6N3FKye = 129 - INTEGER(IntKi), PARAMETER :: M6N4FKye = 130 - INTEGER(IntKi), PARAMETER :: M6N5FKye = 131 - INTEGER(IntKi), PARAMETER :: M6N6FKye = 132 - INTEGER(IntKi), PARAMETER :: M6N7FKye = 133 - INTEGER(IntKi), PARAMETER :: M6N8FKye = 134 - INTEGER(IntKi), PARAMETER :: M6N9FKye = 135 - INTEGER(IntKi), PARAMETER :: M7N1FKye = 136 - INTEGER(IntKi), PARAMETER :: M7N2FKye = 137 - INTEGER(IntKi), PARAMETER :: M7N3FKye = 138 - INTEGER(IntKi), PARAMETER :: M7N4FKye = 139 - INTEGER(IntKi), PARAMETER :: M7N5FKye = 140 - INTEGER(IntKi), PARAMETER :: M7N6FKye = 141 - INTEGER(IntKi), PARAMETER :: M7N7FKye = 142 - INTEGER(IntKi), PARAMETER :: M7N8FKye = 143 - INTEGER(IntKi), PARAMETER :: M7N9FKye = 144 - INTEGER(IntKi), PARAMETER :: M8N1FKye = 145 - INTEGER(IntKi), PARAMETER :: M8N2FKye = 146 - INTEGER(IntKi), PARAMETER :: M8N3FKye = 147 - INTEGER(IntKi), PARAMETER :: M8N4FKye = 148 - INTEGER(IntKi), PARAMETER :: M8N5FKye = 149 - INTEGER(IntKi), PARAMETER :: M8N6FKye = 150 - INTEGER(IntKi), PARAMETER :: M8N7FKye = 151 - INTEGER(IntKi), PARAMETER :: M8N8FKye = 152 - INTEGER(IntKi), PARAMETER :: M8N9FKye = 153 - INTEGER(IntKi), PARAMETER :: M9N1FKye = 154 - INTEGER(IntKi), PARAMETER :: M9N2FKye = 155 - INTEGER(IntKi), PARAMETER :: M9N3FKye = 156 - INTEGER(IntKi), PARAMETER :: M9N4FKye = 157 - INTEGER(IntKi), PARAMETER :: M9N5FKye = 158 - INTEGER(IntKi), PARAMETER :: M9N6FKye = 159 - INTEGER(IntKi), PARAMETER :: M9N7FKye = 160 - INTEGER(IntKi), PARAMETER :: M9N8FKye = 161 - INTEGER(IntKi), PARAMETER :: M9N9FKye = 162 - INTEGER(IntKi), PARAMETER :: M1N1FKze = 163 - INTEGER(IntKi), PARAMETER :: M1N2FKze = 164 - INTEGER(IntKi), PARAMETER :: M1N3FKze = 165 - INTEGER(IntKi), PARAMETER :: M1N4FKze = 166 - INTEGER(IntKi), PARAMETER :: M1N5FKze = 167 - INTEGER(IntKi), PARAMETER :: M1N6FKze = 168 - INTEGER(IntKi), PARAMETER :: M1N7FKze = 169 - INTEGER(IntKi), PARAMETER :: M1N8FKze = 170 - INTEGER(IntKi), PARAMETER :: M1N9FKze = 171 - INTEGER(IntKi), PARAMETER :: M2N1FKze = 172 - INTEGER(IntKi), PARAMETER :: M2N2FKze = 173 - INTEGER(IntKi), PARAMETER :: M2N3FKze = 174 - INTEGER(IntKi), PARAMETER :: M2N4FKze = 175 - INTEGER(IntKi), PARAMETER :: M2N5FKze = 176 - INTEGER(IntKi), PARAMETER :: M2N6FKze = 177 - INTEGER(IntKi), PARAMETER :: M2N7FKze = 178 - INTEGER(IntKi), PARAMETER :: M2N8FKze = 179 - INTEGER(IntKi), PARAMETER :: M2N9FKze = 180 - INTEGER(IntKi), PARAMETER :: M3N1FKze = 181 - INTEGER(IntKi), PARAMETER :: M3N2FKze = 182 - INTEGER(IntKi), PARAMETER :: M3N3FKze = 183 - INTEGER(IntKi), PARAMETER :: M3N4FKze = 184 - INTEGER(IntKi), PARAMETER :: M3N5FKze = 185 - INTEGER(IntKi), PARAMETER :: M3N6FKze = 186 - INTEGER(IntKi), PARAMETER :: M3N7FKze = 187 - INTEGER(IntKi), PARAMETER :: M3N8FKze = 188 - INTEGER(IntKi), PARAMETER :: M3N9FKze = 189 - INTEGER(IntKi), PARAMETER :: M4N1FKze = 190 - INTEGER(IntKi), PARAMETER :: M4N2FKze = 191 - INTEGER(IntKi), PARAMETER :: M4N3FKze = 192 - INTEGER(IntKi), PARAMETER :: M4N4FKze = 193 - INTEGER(IntKi), PARAMETER :: M4N5FKze = 194 - INTEGER(IntKi), PARAMETER :: M4N6FKze = 195 - INTEGER(IntKi), PARAMETER :: M4N7FKze = 196 - INTEGER(IntKi), PARAMETER :: M4N8FKze = 197 - INTEGER(IntKi), PARAMETER :: M4N9FKze = 198 - INTEGER(IntKi), PARAMETER :: M5N1FKze = 199 - INTEGER(IntKi), PARAMETER :: M5N2FKze = 200 - INTEGER(IntKi), PARAMETER :: M5N3FKze = 201 - INTEGER(IntKi), PARAMETER :: M5N4FKze = 202 - INTEGER(IntKi), PARAMETER :: M5N5FKze = 203 - INTEGER(IntKi), PARAMETER :: M5N6FKze = 204 - INTEGER(IntKi), PARAMETER :: M5N7FKze = 205 - INTEGER(IntKi), PARAMETER :: M5N8FKze = 206 - INTEGER(IntKi), PARAMETER :: M5N9FKze = 207 - INTEGER(IntKi), PARAMETER :: M6N1FKze = 208 - INTEGER(IntKi), PARAMETER :: M6N2FKze = 209 - INTEGER(IntKi), PARAMETER :: M6N3FKze = 210 - INTEGER(IntKi), PARAMETER :: M6N4FKze = 211 - INTEGER(IntKi), PARAMETER :: M6N5FKze = 212 - INTEGER(IntKi), PARAMETER :: M6N6FKze = 213 - INTEGER(IntKi), PARAMETER :: M6N7FKze = 214 - INTEGER(IntKi), PARAMETER :: M6N8FKze = 215 - INTEGER(IntKi), PARAMETER :: M6N9FKze = 216 - INTEGER(IntKi), PARAMETER :: M7N1FKze = 217 - INTEGER(IntKi), PARAMETER :: M7N2FKze = 218 - INTEGER(IntKi), PARAMETER :: M7N3FKze = 219 - INTEGER(IntKi), PARAMETER :: M7N4FKze = 220 - INTEGER(IntKi), PARAMETER :: M7N5FKze = 221 - INTEGER(IntKi), PARAMETER :: M7N6FKze = 222 - INTEGER(IntKi), PARAMETER :: M7N7FKze = 223 - INTEGER(IntKi), PARAMETER :: M7N8FKze = 224 - INTEGER(IntKi), PARAMETER :: M7N9FKze = 225 - INTEGER(IntKi), PARAMETER :: M8N1FKze = 226 - INTEGER(IntKi), PARAMETER :: M8N2FKze = 227 - INTEGER(IntKi), PARAMETER :: M8N3FKze = 228 - INTEGER(IntKi), PARAMETER :: M8N4FKze = 229 - INTEGER(IntKi), PARAMETER :: M8N5FKze = 230 - INTEGER(IntKi), PARAMETER :: M8N6FKze = 231 - INTEGER(IntKi), PARAMETER :: M8N7FKze = 232 - INTEGER(IntKi), PARAMETER :: M8N8FKze = 233 - INTEGER(IntKi), PARAMETER :: M8N9FKze = 234 - INTEGER(IntKi), PARAMETER :: M9N1FKze = 235 - INTEGER(IntKi), PARAMETER :: M9N2FKze = 236 - INTEGER(IntKi), PARAMETER :: M9N3FKze = 237 - INTEGER(IntKi), PARAMETER :: M9N4FKze = 238 - INTEGER(IntKi), PARAMETER :: M9N5FKze = 239 - INTEGER(IntKi), PARAMETER :: M9N6FKze = 240 - INTEGER(IntKi), PARAMETER :: M9N7FKze = 241 - INTEGER(IntKi), PARAMETER :: M9N8FKze = 242 - INTEGER(IntKi), PARAMETER :: M9N9FKze = 243 - INTEGER(IntKi), PARAMETER :: M1N1FMxe = 244 - INTEGER(IntKi), PARAMETER :: M1N2FMxe = 245 - INTEGER(IntKi), PARAMETER :: M1N3FMxe = 246 - INTEGER(IntKi), PARAMETER :: M1N4FMxe = 247 - INTEGER(IntKi), PARAMETER :: M1N5FMxe = 248 - INTEGER(IntKi), PARAMETER :: M1N6FMxe = 249 - INTEGER(IntKi), PARAMETER :: M1N7FMxe = 250 - INTEGER(IntKi), PARAMETER :: M1N8FMxe = 251 - INTEGER(IntKi), PARAMETER :: M1N9FMxe = 252 - INTEGER(IntKi), PARAMETER :: M2N1FMxe = 253 - INTEGER(IntKi), PARAMETER :: M2N2FMxe = 254 - INTEGER(IntKi), PARAMETER :: M2N3FMxe = 255 - INTEGER(IntKi), PARAMETER :: M2N4FMxe = 256 - INTEGER(IntKi), PARAMETER :: M2N5FMxe = 257 - INTEGER(IntKi), PARAMETER :: M2N6FMxe = 258 - INTEGER(IntKi), PARAMETER :: M2N7FMxe = 259 - INTEGER(IntKi), PARAMETER :: M2N8FMxe = 260 - INTEGER(IntKi), PARAMETER :: M2N9FMxe = 261 - INTEGER(IntKi), PARAMETER :: M3N1FMxe = 262 - INTEGER(IntKi), PARAMETER :: M3N2FMxe = 263 - INTEGER(IntKi), PARAMETER :: M3N3FMxe = 264 - INTEGER(IntKi), PARAMETER :: M3N4FMxe = 265 - INTEGER(IntKi), PARAMETER :: M3N5FMxe = 266 - INTEGER(IntKi), PARAMETER :: M3N6FMxe = 267 - INTEGER(IntKi), PARAMETER :: M3N7FMxe = 268 - INTEGER(IntKi), PARAMETER :: M3N8FMxe = 269 - INTEGER(IntKi), PARAMETER :: M3N9FMxe = 270 - INTEGER(IntKi), PARAMETER :: M4N1FMxe = 271 - INTEGER(IntKi), PARAMETER :: M4N2FMxe = 272 - INTEGER(IntKi), PARAMETER :: M4N3FMxe = 273 - INTEGER(IntKi), PARAMETER :: M4N4FMxe = 274 - INTEGER(IntKi), PARAMETER :: M4N5FMxe = 275 - INTEGER(IntKi), PARAMETER :: M4N6FMxe = 276 - INTEGER(IntKi), PARAMETER :: M4N7FMxe = 277 - INTEGER(IntKi), PARAMETER :: M4N8FMxe = 278 - INTEGER(IntKi), PARAMETER :: M4N9FMxe = 279 - INTEGER(IntKi), PARAMETER :: M5N1FMxe = 280 - INTEGER(IntKi), PARAMETER :: M5N2FMxe = 281 - INTEGER(IntKi), PARAMETER :: M5N3FMxe = 282 - INTEGER(IntKi), PARAMETER :: M5N4FMxe = 283 - INTEGER(IntKi), PARAMETER :: M5N5FMxe = 284 - INTEGER(IntKi), PARAMETER :: M5N6FMxe = 285 - INTEGER(IntKi), PARAMETER :: M5N7FMxe = 286 - INTEGER(IntKi), PARAMETER :: M5N8FMxe = 287 - INTEGER(IntKi), PARAMETER :: M5N9FMxe = 288 - INTEGER(IntKi), PARAMETER :: M6N1FMxe = 289 - INTEGER(IntKi), PARAMETER :: M6N2FMxe = 290 - INTEGER(IntKi), PARAMETER :: M6N3FMxe = 291 - INTEGER(IntKi), PARAMETER :: M6N4FMxe = 292 - INTEGER(IntKi), PARAMETER :: M6N5FMxe = 293 - INTEGER(IntKi), PARAMETER :: M6N6FMxe = 294 - INTEGER(IntKi), PARAMETER :: M6N7FMxe = 295 - INTEGER(IntKi), PARAMETER :: M6N8FMxe = 296 - INTEGER(IntKi), PARAMETER :: M6N9FMxe = 297 - INTEGER(IntKi), PARAMETER :: M7N1FMxe = 298 - INTEGER(IntKi), PARAMETER :: M7N2FMxe = 299 - INTEGER(IntKi), PARAMETER :: M7N3FMxe = 300 - INTEGER(IntKi), PARAMETER :: M7N4FMxe = 301 - INTEGER(IntKi), PARAMETER :: M7N5FMxe = 302 - INTEGER(IntKi), PARAMETER :: M7N6FMxe = 303 - INTEGER(IntKi), PARAMETER :: M7N7FMxe = 304 - INTEGER(IntKi), PARAMETER :: M7N8FMxe = 305 - INTEGER(IntKi), PARAMETER :: M7N9FMxe = 306 - INTEGER(IntKi), PARAMETER :: M8N1FMxe = 307 - INTEGER(IntKi), PARAMETER :: M8N2FMxe = 308 - INTEGER(IntKi), PARAMETER :: M8N3FMxe = 309 - INTEGER(IntKi), PARAMETER :: M8N4FMxe = 310 - INTEGER(IntKi), PARAMETER :: M8N5FMxe = 311 - INTEGER(IntKi), PARAMETER :: M8N6FMxe = 312 - INTEGER(IntKi), PARAMETER :: M8N7FMxe = 313 - INTEGER(IntKi), PARAMETER :: M8N8FMxe = 314 - INTEGER(IntKi), PARAMETER :: M8N9FMxe = 315 - INTEGER(IntKi), PARAMETER :: M9N1FMxe = 316 - INTEGER(IntKi), PARAMETER :: M9N2FMxe = 317 - INTEGER(IntKi), PARAMETER :: M9N3FMxe = 318 - INTEGER(IntKi), PARAMETER :: M9N4FMxe = 319 - INTEGER(IntKi), PARAMETER :: M9N5FMxe = 320 - INTEGER(IntKi), PARAMETER :: M9N6FMxe = 321 - INTEGER(IntKi), PARAMETER :: M9N7FMxe = 322 - INTEGER(IntKi), PARAMETER :: M9N8FMxe = 323 - INTEGER(IntKi), PARAMETER :: M9N9FMxe = 324 - INTEGER(IntKi), PARAMETER :: M1N1FMye = 325 - INTEGER(IntKi), PARAMETER :: M1N2FMye = 326 - INTEGER(IntKi), PARAMETER :: M1N3FMye = 327 - INTEGER(IntKi), PARAMETER :: M1N4FMye = 328 - INTEGER(IntKi), PARAMETER :: M1N5FMye = 329 - INTEGER(IntKi), PARAMETER :: M1N6FMye = 330 - INTEGER(IntKi), PARAMETER :: M1N7FMye = 331 - INTEGER(IntKi), PARAMETER :: M1N8FMye = 332 - INTEGER(IntKi), PARAMETER :: M1N9FMye = 333 - INTEGER(IntKi), PARAMETER :: M2N1FMye = 334 - INTEGER(IntKi), PARAMETER :: M2N2FMye = 335 - INTEGER(IntKi), PARAMETER :: M2N3FMye = 336 - INTEGER(IntKi), PARAMETER :: M2N4FMye = 337 - INTEGER(IntKi), PARAMETER :: M2N5FMye = 338 - INTEGER(IntKi), PARAMETER :: M2N6FMye = 339 - INTEGER(IntKi), PARAMETER :: M2N7FMye = 340 - INTEGER(IntKi), PARAMETER :: M2N8FMye = 341 - INTEGER(IntKi), PARAMETER :: M2N9FMye = 342 - INTEGER(IntKi), PARAMETER :: M3N1FMye = 343 - INTEGER(IntKi), PARAMETER :: M3N2FMye = 344 - INTEGER(IntKi), PARAMETER :: M3N3FMye = 345 - INTEGER(IntKi), PARAMETER :: M3N4FMye = 346 - INTEGER(IntKi), PARAMETER :: M3N5FMye = 347 - INTEGER(IntKi), PARAMETER :: M3N6FMye = 348 - INTEGER(IntKi), PARAMETER :: M3N7FMye = 349 - INTEGER(IntKi), PARAMETER :: M3N8FMye = 350 - INTEGER(IntKi), PARAMETER :: M3N9FMye = 351 - INTEGER(IntKi), PARAMETER :: M4N1FMye = 352 - INTEGER(IntKi), PARAMETER :: M4N2FMye = 353 - INTEGER(IntKi), PARAMETER :: M4N3FMye = 354 - INTEGER(IntKi), PARAMETER :: M4N4FMye = 355 - INTEGER(IntKi), PARAMETER :: M4N5FMye = 356 - INTEGER(IntKi), PARAMETER :: M4N6FMye = 357 - INTEGER(IntKi), PARAMETER :: M4N7FMye = 358 - INTEGER(IntKi), PARAMETER :: M4N8FMye = 359 - INTEGER(IntKi), PARAMETER :: M4N9FMye = 360 - INTEGER(IntKi), PARAMETER :: M5N1FMye = 361 - INTEGER(IntKi), PARAMETER :: M5N2FMye = 362 - INTEGER(IntKi), PARAMETER :: M5N3FMye = 363 - INTEGER(IntKi), PARAMETER :: M5N4FMye = 364 - INTEGER(IntKi), PARAMETER :: M5N5FMye = 365 - INTEGER(IntKi), PARAMETER :: M5N6FMye = 366 - INTEGER(IntKi), PARAMETER :: M5N7FMye = 367 - INTEGER(IntKi), PARAMETER :: M5N8FMye = 368 - INTEGER(IntKi), PARAMETER :: M5N9FMye = 369 - INTEGER(IntKi), PARAMETER :: M6N1FMye = 370 - INTEGER(IntKi), PARAMETER :: M6N2FMye = 371 - INTEGER(IntKi), PARAMETER :: M6N3FMye = 372 - INTEGER(IntKi), PARAMETER :: M6N4FMye = 373 - INTEGER(IntKi), PARAMETER :: M6N5FMye = 374 - INTEGER(IntKi), PARAMETER :: M6N6FMye = 375 - INTEGER(IntKi), PARAMETER :: M6N7FMye = 376 - INTEGER(IntKi), PARAMETER :: M6N8FMye = 377 - INTEGER(IntKi), PARAMETER :: M6N9FMye = 378 - INTEGER(IntKi), PARAMETER :: M7N1FMye = 379 - INTEGER(IntKi), PARAMETER :: M7N2FMye = 380 - INTEGER(IntKi), PARAMETER :: M7N3FMye = 381 - INTEGER(IntKi), PARAMETER :: M7N4FMye = 382 - INTEGER(IntKi), PARAMETER :: M7N5FMye = 383 - INTEGER(IntKi), PARAMETER :: M7N6FMye = 384 - INTEGER(IntKi), PARAMETER :: M7N7FMye = 385 - INTEGER(IntKi), PARAMETER :: M7N8FMye = 386 - INTEGER(IntKi), PARAMETER :: M7N9FMye = 387 - INTEGER(IntKi), PARAMETER :: M8N1FMye = 388 - INTEGER(IntKi), PARAMETER :: M8N2FMye = 389 - INTEGER(IntKi), PARAMETER :: M8N3FMye = 390 - INTEGER(IntKi), PARAMETER :: M8N4FMye = 391 - INTEGER(IntKi), PARAMETER :: M8N5FMye = 392 - INTEGER(IntKi), PARAMETER :: M8N6FMye = 393 - INTEGER(IntKi), PARAMETER :: M8N7FMye = 394 - INTEGER(IntKi), PARAMETER :: M8N8FMye = 395 - INTEGER(IntKi), PARAMETER :: M8N9FMye = 396 - INTEGER(IntKi), PARAMETER :: M9N1FMye = 397 - INTEGER(IntKi), PARAMETER :: M9N2FMye = 398 - INTEGER(IntKi), PARAMETER :: M9N3FMye = 399 - INTEGER(IntKi), PARAMETER :: M9N4FMye = 400 - INTEGER(IntKi), PARAMETER :: M9N5FMye = 401 - INTEGER(IntKi), PARAMETER :: M9N6FMye = 402 - INTEGER(IntKi), PARAMETER :: M9N7FMye = 403 - INTEGER(IntKi), PARAMETER :: M9N8FMye = 404 - INTEGER(IntKi), PARAMETER :: M9N9FMye = 405 - INTEGER(IntKi), PARAMETER :: M1N1FMze = 406 - INTEGER(IntKi), PARAMETER :: M1N2FMze = 407 - INTEGER(IntKi), PARAMETER :: M1N3FMze = 408 - INTEGER(IntKi), PARAMETER :: M1N4FMze = 409 - INTEGER(IntKi), PARAMETER :: M1N5FMze = 410 - INTEGER(IntKi), PARAMETER :: M1N6FMze = 411 - INTEGER(IntKi), PARAMETER :: M1N7FMze = 412 - INTEGER(IntKi), PARAMETER :: M1N8FMze = 413 - INTEGER(IntKi), PARAMETER :: M1N9FMze = 414 - INTEGER(IntKi), PARAMETER :: M2N1FMze = 415 - INTEGER(IntKi), PARAMETER :: M2N2FMze = 416 - INTEGER(IntKi), PARAMETER :: M2N3FMze = 417 - INTEGER(IntKi), PARAMETER :: M2N4FMze = 418 - INTEGER(IntKi), PARAMETER :: M2N5FMze = 419 - INTEGER(IntKi), PARAMETER :: M2N6FMze = 420 - INTEGER(IntKi), PARAMETER :: M2N7FMze = 421 - INTEGER(IntKi), PARAMETER :: M2N8FMze = 422 - INTEGER(IntKi), PARAMETER :: M2N9FMze = 423 - INTEGER(IntKi), PARAMETER :: M3N1FMze = 424 - INTEGER(IntKi), PARAMETER :: M3N2FMze = 425 - INTEGER(IntKi), PARAMETER :: M3N3FMze = 426 - INTEGER(IntKi), PARAMETER :: M3N4FMze = 427 - INTEGER(IntKi), PARAMETER :: M3N5FMze = 428 - INTEGER(IntKi), PARAMETER :: M3N6FMze = 429 - INTEGER(IntKi), PARAMETER :: M3N7FMze = 430 - INTEGER(IntKi), PARAMETER :: M3N8FMze = 431 - INTEGER(IntKi), PARAMETER :: M3N9FMze = 432 - INTEGER(IntKi), PARAMETER :: M4N1FMze = 433 - INTEGER(IntKi), PARAMETER :: M4N2FMze = 434 - INTEGER(IntKi), PARAMETER :: M4N3FMze = 435 - INTEGER(IntKi), PARAMETER :: M4N4FMze = 436 - INTEGER(IntKi), PARAMETER :: M4N5FMze = 437 - INTEGER(IntKi), PARAMETER :: M4N6FMze = 438 - INTEGER(IntKi), PARAMETER :: M4N7FMze = 439 - INTEGER(IntKi), PARAMETER :: M4N8FMze = 440 - INTEGER(IntKi), PARAMETER :: M4N9FMze = 441 - INTEGER(IntKi), PARAMETER :: M5N1FMze = 442 - INTEGER(IntKi), PARAMETER :: M5N2FMze = 443 - INTEGER(IntKi), PARAMETER :: M5N3FMze = 444 - INTEGER(IntKi), PARAMETER :: M5N4FMze = 445 - INTEGER(IntKi), PARAMETER :: M5N5FMze = 446 - INTEGER(IntKi), PARAMETER :: M5N6FMze = 447 - INTEGER(IntKi), PARAMETER :: M5N7FMze = 448 - INTEGER(IntKi), PARAMETER :: M5N8FMze = 449 - INTEGER(IntKi), PARAMETER :: M5N9FMze = 450 - INTEGER(IntKi), PARAMETER :: M6N1FMze = 451 - INTEGER(IntKi), PARAMETER :: M6N2FMze = 452 - INTEGER(IntKi), PARAMETER :: M6N3FMze = 453 - INTEGER(IntKi), PARAMETER :: M6N4FMze = 454 - INTEGER(IntKi), PARAMETER :: M6N5FMze = 455 - INTEGER(IntKi), PARAMETER :: M6N6FMze = 456 - INTEGER(IntKi), PARAMETER :: M6N7FMze = 457 - INTEGER(IntKi), PARAMETER :: M6N8FMze = 458 - INTEGER(IntKi), PARAMETER :: M6N9FMze = 459 - INTEGER(IntKi), PARAMETER :: M7N1FMze = 460 - INTEGER(IntKi), PARAMETER :: M7N2FMze = 461 - INTEGER(IntKi), PARAMETER :: M7N3FMze = 462 - INTEGER(IntKi), PARAMETER :: M7N4FMze = 463 - INTEGER(IntKi), PARAMETER :: M7N5FMze = 464 - INTEGER(IntKi), PARAMETER :: M7N6FMze = 465 - INTEGER(IntKi), PARAMETER :: M7N7FMze = 466 - INTEGER(IntKi), PARAMETER :: M7N8FMze = 467 - INTEGER(IntKi), PARAMETER :: M7N9FMze = 468 - INTEGER(IntKi), PARAMETER :: M8N1FMze = 469 - INTEGER(IntKi), PARAMETER :: M8N2FMze = 470 - INTEGER(IntKi), PARAMETER :: M8N3FMze = 471 - INTEGER(IntKi), PARAMETER :: M8N4FMze = 472 - INTEGER(IntKi), PARAMETER :: M8N5FMze = 473 - INTEGER(IntKi), PARAMETER :: M8N6FMze = 474 - INTEGER(IntKi), PARAMETER :: M8N7FMze = 475 - INTEGER(IntKi), PARAMETER :: M8N8FMze = 476 - INTEGER(IntKi), PARAMETER :: M8N9FMze = 477 - INTEGER(IntKi), PARAMETER :: M9N1FMze = 478 - INTEGER(IntKi), PARAMETER :: M9N2FMze = 479 - INTEGER(IntKi), PARAMETER :: M9N3FMze = 480 - INTEGER(IntKi), PARAMETER :: M9N4FMze = 481 - INTEGER(IntKi), PARAMETER :: M9N5FMze = 482 - INTEGER(IntKi), PARAMETER :: M9N6FMze = 483 - INTEGER(IntKi), PARAMETER :: M9N7FMze = 484 - INTEGER(IntKi), PARAMETER :: M9N8FMze = 485 - INTEGER(IntKi), PARAMETER :: M9N9FMze = 486 - INTEGER(IntKi), PARAMETER :: M1N1MKxe = 487 - INTEGER(IntKi), PARAMETER :: M1N2MKxe = 488 - INTEGER(IntKi), PARAMETER :: M1N3MKxe = 489 - INTEGER(IntKi), PARAMETER :: M1N4MKxe = 490 - INTEGER(IntKi), PARAMETER :: M1N5MKxe = 491 - INTEGER(IntKi), PARAMETER :: M1N6MKxe = 492 - INTEGER(IntKi), PARAMETER :: M1N7MKxe = 493 - INTEGER(IntKi), PARAMETER :: M1N8MKxe = 494 - INTEGER(IntKi), PARAMETER :: M1N9MKxe = 495 - INTEGER(IntKi), PARAMETER :: M2N1MKxe = 496 - INTEGER(IntKi), PARAMETER :: M2N2MKxe = 497 - INTEGER(IntKi), PARAMETER :: M2N3MKxe = 498 - INTEGER(IntKi), PARAMETER :: M2N4MKxe = 499 - INTEGER(IntKi), PARAMETER :: M2N5MKxe = 500 - INTEGER(IntKi), PARAMETER :: M2N6MKxe = 501 - INTEGER(IntKi), PARAMETER :: M2N7MKxe = 502 - INTEGER(IntKi), PARAMETER :: M2N8MKxe = 503 - INTEGER(IntKi), PARAMETER :: M2N9MKxe = 504 - INTEGER(IntKi), PARAMETER :: M3N1MKxe = 505 - INTEGER(IntKi), PARAMETER :: M3N2MKxe = 506 - INTEGER(IntKi), PARAMETER :: M3N3MKxe = 507 - INTEGER(IntKi), PARAMETER :: M3N4MKxe = 508 - INTEGER(IntKi), PARAMETER :: M3N5MKxe = 509 - INTEGER(IntKi), PARAMETER :: M3N6MKxe = 510 - INTEGER(IntKi), PARAMETER :: M3N7MKxe = 511 - INTEGER(IntKi), PARAMETER :: M3N8MKxe = 512 - INTEGER(IntKi), PARAMETER :: M3N9MKxe = 513 - INTEGER(IntKi), PARAMETER :: M4N1MKxe = 514 - INTEGER(IntKi), PARAMETER :: M4N2MKxe = 515 - INTEGER(IntKi), PARAMETER :: M4N3MKxe = 516 - INTEGER(IntKi), PARAMETER :: M4N4MKxe = 517 - INTEGER(IntKi), PARAMETER :: M4N5MKxe = 518 - INTEGER(IntKi), PARAMETER :: M4N6MKxe = 519 - INTEGER(IntKi), PARAMETER :: M4N7MKxe = 520 - INTEGER(IntKi), PARAMETER :: M4N8MKxe = 521 - INTEGER(IntKi), PARAMETER :: M4N9MKxe = 522 - INTEGER(IntKi), PARAMETER :: M5N1MKxe = 523 - INTEGER(IntKi), PARAMETER :: M5N2MKxe = 524 - INTEGER(IntKi), PARAMETER :: M5N3MKxe = 525 - INTEGER(IntKi), PARAMETER :: M5N4MKxe = 526 - INTEGER(IntKi), PARAMETER :: M5N5MKxe = 527 - INTEGER(IntKi), PARAMETER :: M5N6MKxe = 528 - INTEGER(IntKi), PARAMETER :: M5N7MKxe = 529 - INTEGER(IntKi), PARAMETER :: M5N8MKxe = 530 - INTEGER(IntKi), PARAMETER :: M5N9MKxe = 531 - INTEGER(IntKi), PARAMETER :: M6N1MKxe = 532 - INTEGER(IntKi), PARAMETER :: M6N2MKxe = 533 - INTEGER(IntKi), PARAMETER :: M6N3MKxe = 534 - INTEGER(IntKi), PARAMETER :: M6N4MKxe = 535 - INTEGER(IntKi), PARAMETER :: M6N5MKxe = 536 - INTEGER(IntKi), PARAMETER :: M6N6MKxe = 537 - INTEGER(IntKi), PARAMETER :: M6N7MKxe = 538 - INTEGER(IntKi), PARAMETER :: M6N8MKxe = 539 - INTEGER(IntKi), PARAMETER :: M6N9MKxe = 540 - INTEGER(IntKi), PARAMETER :: M7N1MKxe = 541 - INTEGER(IntKi), PARAMETER :: M7N2MKxe = 542 - INTEGER(IntKi), PARAMETER :: M7N3MKxe = 543 - INTEGER(IntKi), PARAMETER :: M7N4MKxe = 544 - INTEGER(IntKi), PARAMETER :: M7N5MKxe = 545 - INTEGER(IntKi), PARAMETER :: M7N6MKxe = 546 - INTEGER(IntKi), PARAMETER :: M7N7MKxe = 547 - INTEGER(IntKi), PARAMETER :: M7N8MKxe = 548 - INTEGER(IntKi), PARAMETER :: M7N9MKxe = 549 - INTEGER(IntKi), PARAMETER :: M8N1MKxe = 550 - INTEGER(IntKi), PARAMETER :: M8N2MKxe = 551 - INTEGER(IntKi), PARAMETER :: M8N3MKxe = 552 - INTEGER(IntKi), PARAMETER :: M8N4MKxe = 553 - INTEGER(IntKi), PARAMETER :: M8N5MKxe = 554 - INTEGER(IntKi), PARAMETER :: M8N6MKxe = 555 - INTEGER(IntKi), PARAMETER :: M8N7MKxe = 556 - INTEGER(IntKi), PARAMETER :: M8N8MKxe = 557 - INTEGER(IntKi), PARAMETER :: M8N9MKxe = 558 - INTEGER(IntKi), PARAMETER :: M9N1MKxe = 559 - INTEGER(IntKi), PARAMETER :: M9N2MKxe = 560 - INTEGER(IntKi), PARAMETER :: M9N3MKxe = 561 - INTEGER(IntKi), PARAMETER :: M9N4MKxe = 562 - INTEGER(IntKi), PARAMETER :: M9N5MKxe = 563 - INTEGER(IntKi), PARAMETER :: M9N6MKxe = 564 - INTEGER(IntKi), PARAMETER :: M9N7MKxe = 565 - INTEGER(IntKi), PARAMETER :: M9N8MKxe = 566 - INTEGER(IntKi), PARAMETER :: M9N9MKxe = 567 - INTEGER(IntKi), PARAMETER :: M1N1MKye = 568 - INTEGER(IntKi), PARAMETER :: M1N2MKye = 569 - INTEGER(IntKi), PARAMETER :: M1N3MKye = 570 - INTEGER(IntKi), PARAMETER :: M1N4MKye = 571 - INTEGER(IntKi), PARAMETER :: M1N5MKye = 572 - INTEGER(IntKi), PARAMETER :: M1N6MKye = 573 - INTEGER(IntKi), PARAMETER :: M1N7MKye = 574 - INTEGER(IntKi), PARAMETER :: M1N8MKye = 575 - INTEGER(IntKi), PARAMETER :: M1N9MKye = 576 - INTEGER(IntKi), PARAMETER :: M2N1MKye = 577 - INTEGER(IntKi), PARAMETER :: M2N2MKye = 578 - INTEGER(IntKi), PARAMETER :: M2N3MKye = 579 - INTEGER(IntKi), PARAMETER :: M2N4MKye = 580 - INTEGER(IntKi), PARAMETER :: M2N5MKye = 581 - INTEGER(IntKi), PARAMETER :: M2N6MKye = 582 - INTEGER(IntKi), PARAMETER :: M2N7MKye = 583 - INTEGER(IntKi), PARAMETER :: M2N8MKye = 584 - INTEGER(IntKi), PARAMETER :: M2N9MKye = 585 - INTEGER(IntKi), PARAMETER :: M3N1MKye = 586 - INTEGER(IntKi), PARAMETER :: M3N2MKye = 587 - INTEGER(IntKi), PARAMETER :: M3N3MKye = 588 - INTEGER(IntKi), PARAMETER :: M3N4MKye = 589 - INTEGER(IntKi), PARAMETER :: M3N5MKye = 590 - INTEGER(IntKi), PARAMETER :: M3N6MKye = 591 - INTEGER(IntKi), PARAMETER :: M3N7MKye = 592 - INTEGER(IntKi), PARAMETER :: M3N8MKye = 593 - INTEGER(IntKi), PARAMETER :: M3N9MKye = 594 - INTEGER(IntKi), PARAMETER :: M4N1MKye = 595 - INTEGER(IntKi), PARAMETER :: M4N2MKye = 596 - INTEGER(IntKi), PARAMETER :: M4N3MKye = 597 - INTEGER(IntKi), PARAMETER :: M4N4MKye = 598 - INTEGER(IntKi), PARAMETER :: M4N5MKye = 599 - INTEGER(IntKi), PARAMETER :: M4N6MKye = 600 - INTEGER(IntKi), PARAMETER :: M4N7MKye = 601 - INTEGER(IntKi), PARAMETER :: M4N8MKye = 602 - INTEGER(IntKi), PARAMETER :: M4N9MKye = 603 - INTEGER(IntKi), PARAMETER :: M5N1MKye = 604 - INTEGER(IntKi), PARAMETER :: M5N2MKye = 605 - INTEGER(IntKi), PARAMETER :: M5N3MKye = 606 - INTEGER(IntKi), PARAMETER :: M5N4MKye = 607 - INTEGER(IntKi), PARAMETER :: M5N5MKye = 608 - INTEGER(IntKi), PARAMETER :: M5N6MKye = 609 - INTEGER(IntKi), PARAMETER :: M5N7MKye = 610 - INTEGER(IntKi), PARAMETER :: M5N8MKye = 611 - INTEGER(IntKi), PARAMETER :: M5N9MKye = 612 - INTEGER(IntKi), PARAMETER :: M6N1MKye = 613 - INTEGER(IntKi), PARAMETER :: M6N2MKye = 614 - INTEGER(IntKi), PARAMETER :: M6N3MKye = 615 - INTEGER(IntKi), PARAMETER :: M6N4MKye = 616 - INTEGER(IntKi), PARAMETER :: M6N5MKye = 617 - INTEGER(IntKi), PARAMETER :: M6N6MKye = 618 - INTEGER(IntKi), PARAMETER :: M6N7MKye = 619 - INTEGER(IntKi), PARAMETER :: M6N8MKye = 620 - INTEGER(IntKi), PARAMETER :: M6N9MKye = 621 - INTEGER(IntKi), PARAMETER :: M7N1MKye = 622 - INTEGER(IntKi), PARAMETER :: M7N2MKye = 623 - INTEGER(IntKi), PARAMETER :: M7N3MKye = 624 - INTEGER(IntKi), PARAMETER :: M7N4MKye = 625 - INTEGER(IntKi), PARAMETER :: M7N5MKye = 626 - INTEGER(IntKi), PARAMETER :: M7N6MKye = 627 - INTEGER(IntKi), PARAMETER :: M7N7MKye = 628 - INTEGER(IntKi), PARAMETER :: M7N8MKye = 629 - INTEGER(IntKi), PARAMETER :: M7N9MKye = 630 - INTEGER(IntKi), PARAMETER :: M8N1MKye = 631 - INTEGER(IntKi), PARAMETER :: M8N2MKye = 632 - INTEGER(IntKi), PARAMETER :: M8N3MKye = 633 - INTEGER(IntKi), PARAMETER :: M8N4MKye = 634 - INTEGER(IntKi), PARAMETER :: M8N5MKye = 635 - INTEGER(IntKi), PARAMETER :: M8N6MKye = 636 - INTEGER(IntKi), PARAMETER :: M8N7MKye = 637 - INTEGER(IntKi), PARAMETER :: M8N8MKye = 638 - INTEGER(IntKi), PARAMETER :: M8N9MKye = 639 - INTEGER(IntKi), PARAMETER :: M9N1MKye = 640 - INTEGER(IntKi), PARAMETER :: M9N2MKye = 641 - INTEGER(IntKi), PARAMETER :: M9N3MKye = 642 - INTEGER(IntKi), PARAMETER :: M9N4MKye = 643 - INTEGER(IntKi), PARAMETER :: M9N5MKye = 644 - INTEGER(IntKi), PARAMETER :: M9N6MKye = 645 - INTEGER(IntKi), PARAMETER :: M9N7MKye = 646 - INTEGER(IntKi), PARAMETER :: M9N8MKye = 647 - INTEGER(IntKi), PARAMETER :: M9N9MKye = 648 - INTEGER(IntKi), PARAMETER :: M1N1MKze = 649 - INTEGER(IntKi), PARAMETER :: M1N2MKze = 650 - INTEGER(IntKi), PARAMETER :: M1N3MKze = 651 - INTEGER(IntKi), PARAMETER :: M1N4MKze = 652 - INTEGER(IntKi), PARAMETER :: M1N5MKze = 653 - INTEGER(IntKi), PARAMETER :: M1N6MKze = 654 - INTEGER(IntKi), PARAMETER :: M1N7MKze = 655 - INTEGER(IntKi), PARAMETER :: M1N8MKze = 656 - INTEGER(IntKi), PARAMETER :: M1N9MKze = 657 - INTEGER(IntKi), PARAMETER :: M2N1MKze = 658 - INTEGER(IntKi), PARAMETER :: M2N2MKze = 659 - INTEGER(IntKi), PARAMETER :: M2N3MKze = 660 - INTEGER(IntKi), PARAMETER :: M2N4MKze = 661 - INTEGER(IntKi), PARAMETER :: M2N5MKze = 662 - INTEGER(IntKi), PARAMETER :: M2N6MKze = 663 - INTEGER(IntKi), PARAMETER :: M2N7MKze = 664 - INTEGER(IntKi), PARAMETER :: M2N8MKze = 665 - INTEGER(IntKi), PARAMETER :: M2N9MKze = 666 - INTEGER(IntKi), PARAMETER :: M3N1MKze = 667 - INTEGER(IntKi), PARAMETER :: M3N2MKze = 668 - INTEGER(IntKi), PARAMETER :: M3N3MKze = 669 - INTEGER(IntKi), PARAMETER :: M3N4MKze = 670 - INTEGER(IntKi), PARAMETER :: M3N5MKze = 671 - INTEGER(IntKi), PARAMETER :: M3N6MKze = 672 - INTEGER(IntKi), PARAMETER :: M3N7MKze = 673 - INTEGER(IntKi), PARAMETER :: M3N8MKze = 674 - INTEGER(IntKi), PARAMETER :: M3N9MKze = 675 - INTEGER(IntKi), PARAMETER :: M4N1MKze = 676 - INTEGER(IntKi), PARAMETER :: M4N2MKze = 677 - INTEGER(IntKi), PARAMETER :: M4N3MKze = 678 - INTEGER(IntKi), PARAMETER :: M4N4MKze = 679 - INTEGER(IntKi), PARAMETER :: M4N5MKze = 680 - INTEGER(IntKi), PARAMETER :: M4N6MKze = 681 - INTEGER(IntKi), PARAMETER :: M4N7MKze = 682 - INTEGER(IntKi), PARAMETER :: M4N8MKze = 683 - INTEGER(IntKi), PARAMETER :: M4N9MKze = 684 - INTEGER(IntKi), PARAMETER :: M5N1MKze = 685 - INTEGER(IntKi), PARAMETER :: M5N2MKze = 686 - INTEGER(IntKi), PARAMETER :: M5N3MKze = 687 - INTEGER(IntKi), PARAMETER :: M5N4MKze = 688 - INTEGER(IntKi), PARAMETER :: M5N5MKze = 689 - INTEGER(IntKi), PARAMETER :: M5N6MKze = 690 - INTEGER(IntKi), PARAMETER :: M5N7MKze = 691 - INTEGER(IntKi), PARAMETER :: M5N8MKze = 692 - INTEGER(IntKi), PARAMETER :: M5N9MKze = 693 - INTEGER(IntKi), PARAMETER :: M6N1MKze = 694 - INTEGER(IntKi), PARAMETER :: M6N2MKze = 695 - INTEGER(IntKi), PARAMETER :: M6N3MKze = 696 - INTEGER(IntKi), PARAMETER :: M6N4MKze = 697 - INTEGER(IntKi), PARAMETER :: M6N5MKze = 698 - INTEGER(IntKi), PARAMETER :: M6N6MKze = 699 - INTEGER(IntKi), PARAMETER :: M6N7MKze = 700 - INTEGER(IntKi), PARAMETER :: M6N8MKze = 701 - INTEGER(IntKi), PARAMETER :: M6N9MKze = 702 - INTEGER(IntKi), PARAMETER :: M7N1MKze = 703 - INTEGER(IntKi), PARAMETER :: M7N2MKze = 704 - INTEGER(IntKi), PARAMETER :: M7N3MKze = 705 - INTEGER(IntKi), PARAMETER :: M7N4MKze = 706 - INTEGER(IntKi), PARAMETER :: M7N5MKze = 707 - INTEGER(IntKi), PARAMETER :: M7N6MKze = 708 - INTEGER(IntKi), PARAMETER :: M7N7MKze = 709 - INTEGER(IntKi), PARAMETER :: M7N8MKze = 710 - INTEGER(IntKi), PARAMETER :: M7N9MKze = 711 - INTEGER(IntKi), PARAMETER :: M8N1MKze = 712 - INTEGER(IntKi), PARAMETER :: M8N2MKze = 713 - INTEGER(IntKi), PARAMETER :: M8N3MKze = 714 - INTEGER(IntKi), PARAMETER :: M8N4MKze = 715 - INTEGER(IntKi), PARAMETER :: M8N5MKze = 716 - INTEGER(IntKi), PARAMETER :: M8N6MKze = 717 - INTEGER(IntKi), PARAMETER :: M8N7MKze = 718 - INTEGER(IntKi), PARAMETER :: M8N8MKze = 719 - INTEGER(IntKi), PARAMETER :: M8N9MKze = 720 - INTEGER(IntKi), PARAMETER :: M9N1MKze = 721 - INTEGER(IntKi), PARAMETER :: M9N2MKze = 722 - INTEGER(IntKi), PARAMETER :: M9N3MKze = 723 - INTEGER(IntKi), PARAMETER :: M9N4MKze = 724 - INTEGER(IntKi), PARAMETER :: M9N5MKze = 725 - INTEGER(IntKi), PARAMETER :: M9N6MKze = 726 - INTEGER(IntKi), PARAMETER :: M9N7MKze = 727 - INTEGER(IntKi), PARAMETER :: M9N8MKze = 728 - INTEGER(IntKi), PARAMETER :: M9N9MKze = 729 - INTEGER(IntKi), PARAMETER :: M1N1MMxe = 730 - INTEGER(IntKi), PARAMETER :: M1N2MMxe = 731 - INTEGER(IntKi), PARAMETER :: M1N3MMxe = 732 - INTEGER(IntKi), PARAMETER :: M1N4MMxe = 733 - INTEGER(IntKi), PARAMETER :: M1N5MMxe = 734 - INTEGER(IntKi), PARAMETER :: M1N6MMxe = 735 - INTEGER(IntKi), PARAMETER :: M1N7MMxe = 736 - INTEGER(IntKi), PARAMETER :: M1N8MMxe = 737 - INTEGER(IntKi), PARAMETER :: M1N9MMxe = 738 - INTEGER(IntKi), PARAMETER :: M2N1MMxe = 739 - INTEGER(IntKi), PARAMETER :: M2N2MMxe = 740 - INTEGER(IntKi), PARAMETER :: M2N3MMxe = 741 - INTEGER(IntKi), PARAMETER :: M2N4MMxe = 742 - INTEGER(IntKi), PARAMETER :: M2N5MMxe = 743 - INTEGER(IntKi), PARAMETER :: M2N6MMxe = 744 - INTEGER(IntKi), PARAMETER :: M2N7MMxe = 745 - INTEGER(IntKi), PARAMETER :: M2N8MMxe = 746 - INTEGER(IntKi), PARAMETER :: M2N9MMxe = 747 - INTEGER(IntKi), PARAMETER :: M3N1MMxe = 748 - INTEGER(IntKi), PARAMETER :: M3N2MMxe = 749 - INTEGER(IntKi), PARAMETER :: M3N3MMxe = 750 - INTEGER(IntKi), PARAMETER :: M3N4MMxe = 751 - INTEGER(IntKi), PARAMETER :: M3N5MMxe = 752 - INTEGER(IntKi), PARAMETER :: M3N6MMxe = 753 - INTEGER(IntKi), PARAMETER :: M3N7MMxe = 754 - INTEGER(IntKi), PARAMETER :: M3N8MMxe = 755 - INTEGER(IntKi), PARAMETER :: M3N9MMxe = 756 - INTEGER(IntKi), PARAMETER :: M4N1MMxe = 757 - INTEGER(IntKi), PARAMETER :: M4N2MMxe = 758 - INTEGER(IntKi), PARAMETER :: M4N3MMxe = 759 - INTEGER(IntKi), PARAMETER :: M4N4MMxe = 760 - INTEGER(IntKi), PARAMETER :: M4N5MMxe = 761 - INTEGER(IntKi), PARAMETER :: M4N6MMxe = 762 - INTEGER(IntKi), PARAMETER :: M4N7MMxe = 763 - INTEGER(IntKi), PARAMETER :: M4N8MMxe = 764 - INTEGER(IntKi), PARAMETER :: M4N9MMxe = 765 - INTEGER(IntKi), PARAMETER :: M5N1MMxe = 766 - INTEGER(IntKi), PARAMETER :: M5N2MMxe = 767 - INTEGER(IntKi), PARAMETER :: M5N3MMxe = 768 - INTEGER(IntKi), PARAMETER :: M5N4MMxe = 769 - INTEGER(IntKi), PARAMETER :: M5N5MMxe = 770 - INTEGER(IntKi), PARAMETER :: M5N6MMxe = 771 - INTEGER(IntKi), PARAMETER :: M5N7MMxe = 772 - INTEGER(IntKi), PARAMETER :: M5N8MMxe = 773 - INTEGER(IntKi), PARAMETER :: M5N9MMxe = 774 - INTEGER(IntKi), PARAMETER :: M6N1MMxe = 775 - INTEGER(IntKi), PARAMETER :: M6N2MMxe = 776 - INTEGER(IntKi), PARAMETER :: M6N3MMxe = 777 - INTEGER(IntKi), PARAMETER :: M6N4MMxe = 778 - INTEGER(IntKi), PARAMETER :: M6N5MMxe = 779 - INTEGER(IntKi), PARAMETER :: M6N6MMxe = 780 - INTEGER(IntKi), PARAMETER :: M6N7MMxe = 781 - INTEGER(IntKi), PARAMETER :: M6N8MMxe = 782 - INTEGER(IntKi), PARAMETER :: M6N9MMxe = 783 - INTEGER(IntKi), PARAMETER :: M7N1MMxe = 784 - INTEGER(IntKi), PARAMETER :: M7N2MMxe = 785 - INTEGER(IntKi), PARAMETER :: M7N3MMxe = 786 - INTEGER(IntKi), PARAMETER :: M7N4MMxe = 787 - INTEGER(IntKi), PARAMETER :: M7N5MMxe = 788 - INTEGER(IntKi), PARAMETER :: M7N6MMxe = 789 - INTEGER(IntKi), PARAMETER :: M7N7MMxe = 790 - INTEGER(IntKi), PARAMETER :: M7N8MMxe = 791 - INTEGER(IntKi), PARAMETER :: M7N9MMxe = 792 - INTEGER(IntKi), PARAMETER :: M8N1MMxe = 793 - INTEGER(IntKi), PARAMETER :: M8N2MMxe = 794 - INTEGER(IntKi), PARAMETER :: M8N3MMxe = 795 - INTEGER(IntKi), PARAMETER :: M8N4MMxe = 796 - INTEGER(IntKi), PARAMETER :: M8N5MMxe = 797 - INTEGER(IntKi), PARAMETER :: M8N6MMxe = 798 - INTEGER(IntKi), PARAMETER :: M8N7MMxe = 799 - INTEGER(IntKi), PARAMETER :: M8N8MMxe = 800 - INTEGER(IntKi), PARAMETER :: M8N9MMxe = 801 - INTEGER(IntKi), PARAMETER :: M9N1MMxe = 802 - INTEGER(IntKi), PARAMETER :: M9N2MMxe = 803 - INTEGER(IntKi), PARAMETER :: M9N3MMxe = 804 - INTEGER(IntKi), PARAMETER :: M9N4MMxe = 805 - INTEGER(IntKi), PARAMETER :: M9N5MMxe = 806 - INTEGER(IntKi), PARAMETER :: M9N6MMxe = 807 - INTEGER(IntKi), PARAMETER :: M9N7MMxe = 808 - INTEGER(IntKi), PARAMETER :: M9N8MMxe = 809 - INTEGER(IntKi), PARAMETER :: M9N9MMxe = 810 - INTEGER(IntKi), PARAMETER :: M1N1MMye = 811 - INTEGER(IntKi), PARAMETER :: M1N2MMye = 812 - INTEGER(IntKi), PARAMETER :: M1N3MMye = 813 - INTEGER(IntKi), PARAMETER :: M1N4MMye = 814 - INTEGER(IntKi), PARAMETER :: M1N5MMye = 815 - INTEGER(IntKi), PARAMETER :: M1N6MMye = 816 - INTEGER(IntKi), PARAMETER :: M1N7MMye = 817 - INTEGER(IntKi), PARAMETER :: M1N8MMye = 818 - INTEGER(IntKi), PARAMETER :: M1N9MMye = 819 - INTEGER(IntKi), PARAMETER :: M2N1MMye = 820 - INTEGER(IntKi), PARAMETER :: M2N2MMye = 821 - INTEGER(IntKi), PARAMETER :: M2N3MMye = 822 - INTEGER(IntKi), PARAMETER :: M2N4MMye = 823 - INTEGER(IntKi), PARAMETER :: M2N5MMye = 824 - INTEGER(IntKi), PARAMETER :: M2N6MMye = 825 - INTEGER(IntKi), PARAMETER :: M2N7MMye = 826 - INTEGER(IntKi), PARAMETER :: M2N8MMye = 827 - INTEGER(IntKi), PARAMETER :: M2N9MMye = 828 - INTEGER(IntKi), PARAMETER :: M3N1MMye = 829 - INTEGER(IntKi), PARAMETER :: M3N2MMye = 830 - INTEGER(IntKi), PARAMETER :: M3N3MMye = 831 - INTEGER(IntKi), PARAMETER :: M3N4MMye = 832 - INTEGER(IntKi), PARAMETER :: M3N5MMye = 833 - INTEGER(IntKi), PARAMETER :: M3N6MMye = 834 - INTEGER(IntKi), PARAMETER :: M3N7MMye = 835 - INTEGER(IntKi), PARAMETER :: M3N8MMye = 836 - INTEGER(IntKi), PARAMETER :: M3N9MMye = 837 - INTEGER(IntKi), PARAMETER :: M4N1MMye = 838 - INTEGER(IntKi), PARAMETER :: M4N2MMye = 839 - INTEGER(IntKi), PARAMETER :: M4N3MMye = 840 - INTEGER(IntKi), PARAMETER :: M4N4MMye = 841 - INTEGER(IntKi), PARAMETER :: M4N5MMye = 842 - INTEGER(IntKi), PARAMETER :: M4N6MMye = 843 - INTEGER(IntKi), PARAMETER :: M4N7MMye = 844 - INTEGER(IntKi), PARAMETER :: M4N8MMye = 845 - INTEGER(IntKi), PARAMETER :: M4N9MMye = 846 - INTEGER(IntKi), PARAMETER :: M5N1MMye = 847 - INTEGER(IntKi), PARAMETER :: M5N2MMye = 848 - INTEGER(IntKi), PARAMETER :: M5N3MMye = 849 - INTEGER(IntKi), PARAMETER :: M5N4MMye = 850 - INTEGER(IntKi), PARAMETER :: M5N5MMye = 851 - INTEGER(IntKi), PARAMETER :: M5N6MMye = 852 - INTEGER(IntKi), PARAMETER :: M5N7MMye = 853 - INTEGER(IntKi), PARAMETER :: M5N8MMye = 854 - INTEGER(IntKi), PARAMETER :: M5N9MMye = 855 - INTEGER(IntKi), PARAMETER :: M6N1MMye = 856 - INTEGER(IntKi), PARAMETER :: M6N2MMye = 857 - INTEGER(IntKi), PARAMETER :: M6N3MMye = 858 - INTEGER(IntKi), PARAMETER :: M6N4MMye = 859 - INTEGER(IntKi), PARAMETER :: M6N5MMye = 860 - INTEGER(IntKi), PARAMETER :: M6N6MMye = 861 - INTEGER(IntKi), PARAMETER :: M6N7MMye = 862 - INTEGER(IntKi), PARAMETER :: M6N8MMye = 863 - INTEGER(IntKi), PARAMETER :: M6N9MMye = 864 - INTEGER(IntKi), PARAMETER :: M7N1MMye = 865 - INTEGER(IntKi), PARAMETER :: M7N2MMye = 866 - INTEGER(IntKi), PARAMETER :: M7N3MMye = 867 - INTEGER(IntKi), PARAMETER :: M7N4MMye = 868 - INTEGER(IntKi), PARAMETER :: M7N5MMye = 869 - INTEGER(IntKi), PARAMETER :: M7N6MMye = 870 - INTEGER(IntKi), PARAMETER :: M7N7MMye = 871 - INTEGER(IntKi), PARAMETER :: M7N8MMye = 872 - INTEGER(IntKi), PARAMETER :: M7N9MMye = 873 - INTEGER(IntKi), PARAMETER :: M8N1MMye = 874 - INTEGER(IntKi), PARAMETER :: M8N2MMye = 875 - INTEGER(IntKi), PARAMETER :: M8N3MMye = 876 - INTEGER(IntKi), PARAMETER :: M8N4MMye = 877 - INTEGER(IntKi), PARAMETER :: M8N5MMye = 878 - INTEGER(IntKi), PARAMETER :: M8N6MMye = 879 - INTEGER(IntKi), PARAMETER :: M8N7MMye = 880 - INTEGER(IntKi), PARAMETER :: M8N8MMye = 881 - INTEGER(IntKi), PARAMETER :: M8N9MMye = 882 - INTEGER(IntKi), PARAMETER :: M9N1MMye = 883 - INTEGER(IntKi), PARAMETER :: M9N2MMye = 884 - INTEGER(IntKi), PARAMETER :: M9N3MMye = 885 - INTEGER(IntKi), PARAMETER :: M9N4MMye = 886 - INTEGER(IntKi), PARAMETER :: M9N5MMye = 887 - INTEGER(IntKi), PARAMETER :: M9N6MMye = 888 - INTEGER(IntKi), PARAMETER :: M9N7MMye = 889 - INTEGER(IntKi), PARAMETER :: M9N8MMye = 890 - INTEGER(IntKi), PARAMETER :: M9N9MMye = 891 - INTEGER(IntKi), PARAMETER :: M1N1MMze = 892 - INTEGER(IntKi), PARAMETER :: M1N2MMze = 893 - INTEGER(IntKi), PARAMETER :: M1N3MMze = 894 - INTEGER(IntKi), PARAMETER :: M1N4MMze = 895 - INTEGER(IntKi), PARAMETER :: M1N5MMze = 896 - INTEGER(IntKi), PARAMETER :: M1N6MMze = 897 - INTEGER(IntKi), PARAMETER :: M1N7MMze = 898 - INTEGER(IntKi), PARAMETER :: M1N8MMze = 899 - INTEGER(IntKi), PARAMETER :: M1N9MMze = 900 - INTEGER(IntKi), PARAMETER :: M2N1MMze = 901 - INTEGER(IntKi), PARAMETER :: M2N2MMze = 902 - INTEGER(IntKi), PARAMETER :: M2N3MMze = 903 - INTEGER(IntKi), PARAMETER :: M2N4MMze = 904 - INTEGER(IntKi), PARAMETER :: M2N5MMze = 905 - INTEGER(IntKi), PARAMETER :: M2N6MMze = 906 - INTEGER(IntKi), PARAMETER :: M2N7MMze = 907 - INTEGER(IntKi), PARAMETER :: M2N8MMze = 908 - INTEGER(IntKi), PARAMETER :: M2N9MMze = 909 - INTEGER(IntKi), PARAMETER :: M3N1MMze = 910 - INTEGER(IntKi), PARAMETER :: M3N2MMze = 911 - INTEGER(IntKi), PARAMETER :: M3N3MMze = 912 - INTEGER(IntKi), PARAMETER :: M3N4MMze = 913 - INTEGER(IntKi), PARAMETER :: M3N5MMze = 914 - INTEGER(IntKi), PARAMETER :: M3N6MMze = 915 - INTEGER(IntKi), PARAMETER :: M3N7MMze = 916 - INTEGER(IntKi), PARAMETER :: M3N8MMze = 917 - INTEGER(IntKi), PARAMETER :: M3N9MMze = 918 - INTEGER(IntKi), PARAMETER :: M4N1MMze = 919 - INTEGER(IntKi), PARAMETER :: M4N2MMze = 920 - INTEGER(IntKi), PARAMETER :: M4N3MMze = 921 - INTEGER(IntKi), PARAMETER :: M4N4MMze = 922 - INTEGER(IntKi), PARAMETER :: M4N5MMze = 923 - INTEGER(IntKi), PARAMETER :: M4N6MMze = 924 - INTEGER(IntKi), PARAMETER :: M4N7MMze = 925 - INTEGER(IntKi), PARAMETER :: M4N8MMze = 926 - INTEGER(IntKi), PARAMETER :: M4N9MMze = 927 - INTEGER(IntKi), PARAMETER :: M5N1MMze = 928 - INTEGER(IntKi), PARAMETER :: M5N2MMze = 929 - INTEGER(IntKi), PARAMETER :: M5N3MMze = 930 - INTEGER(IntKi), PARAMETER :: M5N4MMze = 931 - INTEGER(IntKi), PARAMETER :: M5N5MMze = 932 - INTEGER(IntKi), PARAMETER :: M5N6MMze = 933 - INTEGER(IntKi), PARAMETER :: M5N7MMze = 934 - INTEGER(IntKi), PARAMETER :: M5N8MMze = 935 - INTEGER(IntKi), PARAMETER :: M5N9MMze = 936 - INTEGER(IntKi), PARAMETER :: M6N1MMze = 937 - INTEGER(IntKi), PARAMETER :: M6N2MMze = 938 - INTEGER(IntKi), PARAMETER :: M6N3MMze = 939 - INTEGER(IntKi), PARAMETER :: M6N4MMze = 940 - INTEGER(IntKi), PARAMETER :: M6N5MMze = 941 - INTEGER(IntKi), PARAMETER :: M6N6MMze = 942 - INTEGER(IntKi), PARAMETER :: M6N7MMze = 943 - INTEGER(IntKi), PARAMETER :: M6N8MMze = 944 - INTEGER(IntKi), PARAMETER :: M6N9MMze = 945 - INTEGER(IntKi), PARAMETER :: M7N1MMze = 946 - INTEGER(IntKi), PARAMETER :: M7N2MMze = 947 - INTEGER(IntKi), PARAMETER :: M7N3MMze = 948 - INTEGER(IntKi), PARAMETER :: M7N4MMze = 949 - INTEGER(IntKi), PARAMETER :: M7N5MMze = 950 - INTEGER(IntKi), PARAMETER :: M7N6MMze = 951 - INTEGER(IntKi), PARAMETER :: M7N7MMze = 952 - INTEGER(IntKi), PARAMETER :: M7N8MMze = 953 - INTEGER(IntKi), PARAMETER :: M7N9MMze = 954 - INTEGER(IntKi), PARAMETER :: M8N1MMze = 955 - INTEGER(IntKi), PARAMETER :: M8N2MMze = 956 - INTEGER(IntKi), PARAMETER :: M8N3MMze = 957 - INTEGER(IntKi), PARAMETER :: M8N4MMze = 958 - INTEGER(IntKi), PARAMETER :: M8N5MMze = 959 - INTEGER(IntKi), PARAMETER :: M8N6MMze = 960 - INTEGER(IntKi), PARAMETER :: M8N7MMze = 961 - INTEGER(IntKi), PARAMETER :: M8N8MMze = 962 - INTEGER(IntKi), PARAMETER :: M8N9MMze = 963 - INTEGER(IntKi), PARAMETER :: M9N1MMze = 964 - INTEGER(IntKi), PARAMETER :: M9N2MMze = 965 - INTEGER(IntKi), PARAMETER :: M9N3MMze = 966 - INTEGER(IntKi), PARAMETER :: M9N4MMze = 967 - INTEGER(IntKi), PARAMETER :: M9N5MMze = 968 - INTEGER(IntKi), PARAMETER :: M9N6MMze = 969 - INTEGER(IntKi), PARAMETER :: M9N7MMze = 970 - INTEGER(IntKi), PARAMETER :: M9N8MMze = 971 - INTEGER(IntKi), PARAMETER :: M9N9MMze = 972 - - - ! Displacements: - - INTEGER(IntKi), PARAMETER :: M1N1TDxss = 973 - INTEGER(IntKi), PARAMETER :: M1N2TDxss = 974 - INTEGER(IntKi), PARAMETER :: M1N3TDxss = 975 - INTEGER(IntKi), PARAMETER :: M1N4TDxss = 976 - INTEGER(IntKi), PARAMETER :: M1N5TDxss = 977 - INTEGER(IntKi), PARAMETER :: M1N6TDxss = 978 - INTEGER(IntKi), PARAMETER :: M1N7TDxss = 979 - INTEGER(IntKi), PARAMETER :: M1N8TDxss = 980 - INTEGER(IntKi), PARAMETER :: M1N9TDxss = 981 - INTEGER(IntKi), PARAMETER :: M2N1TDxss = 982 - INTEGER(IntKi), PARAMETER :: M2N2TDxss = 983 - INTEGER(IntKi), PARAMETER :: M2N3TDxss = 984 - INTEGER(IntKi), PARAMETER :: M2N4TDxss = 985 - INTEGER(IntKi), PARAMETER :: M2N5TDxss = 986 - INTEGER(IntKi), PARAMETER :: M2N6TDxss = 987 - INTEGER(IntKi), PARAMETER :: M2N7TDxss = 988 - INTEGER(IntKi), PARAMETER :: M2N8TDxss = 989 - INTEGER(IntKi), PARAMETER :: M2N9TDxss = 990 - INTEGER(IntKi), PARAMETER :: M3N1TDxss = 991 - INTEGER(IntKi), PARAMETER :: M3N2TDxss = 992 - INTEGER(IntKi), PARAMETER :: M3N3TDxss = 993 - INTEGER(IntKi), PARAMETER :: M3N4TDxss = 994 - INTEGER(IntKi), PARAMETER :: M3N5TDxss = 995 - INTEGER(IntKi), PARAMETER :: M3N6TDxss = 996 - INTEGER(IntKi), PARAMETER :: M3N7TDxss = 997 - INTEGER(IntKi), PARAMETER :: M3N8TDxss = 998 - INTEGER(IntKi), PARAMETER :: M3N9TDxss = 999 - INTEGER(IntKi), PARAMETER :: M4N1TDxss = 1000 - INTEGER(IntKi), PARAMETER :: M4N2TDxss = 1001 - INTEGER(IntKi), PARAMETER :: M4N3TDxss = 1002 - INTEGER(IntKi), PARAMETER :: M4N4TDxss = 1003 - INTEGER(IntKi), PARAMETER :: M4N5TDxss = 1004 - INTEGER(IntKi), PARAMETER :: M4N6TDxss = 1005 - INTEGER(IntKi), PARAMETER :: M4N7TDxss = 1006 - INTEGER(IntKi), PARAMETER :: M4N8TDxss = 1007 - INTEGER(IntKi), PARAMETER :: M4N9TDxss = 1008 - INTEGER(IntKi), PARAMETER :: M5N1TDxss = 1009 - INTEGER(IntKi), PARAMETER :: M5N2TDxss = 1010 - INTEGER(IntKi), PARAMETER :: M5N3TDxss = 1011 - INTEGER(IntKi), PARAMETER :: M5N4TDxss = 1012 - INTEGER(IntKi), PARAMETER :: M5N5TDxss = 1013 - INTEGER(IntKi), PARAMETER :: M5N6TDxss = 1014 - INTEGER(IntKi), PARAMETER :: M5N7TDxss = 1015 - INTEGER(IntKi), PARAMETER :: M5N8TDxss = 1016 - INTEGER(IntKi), PARAMETER :: M5N9TDxss = 1017 - INTEGER(IntKi), PARAMETER :: M6N1TDxss = 1018 - INTEGER(IntKi), PARAMETER :: M6N2TDxss = 1019 - INTEGER(IntKi), PARAMETER :: M6N3TDxss = 1020 - INTEGER(IntKi), PARAMETER :: M6N4TDxss = 1021 - INTEGER(IntKi), PARAMETER :: M6N5TDxss = 1022 - INTEGER(IntKi), PARAMETER :: M6N6TDxss = 1023 - INTEGER(IntKi), PARAMETER :: M6N7TDxss = 1024 - INTEGER(IntKi), PARAMETER :: M6N8TDxss = 1025 - INTEGER(IntKi), PARAMETER :: M6N9TDxss = 1026 - INTEGER(IntKi), PARAMETER :: M7N1TDxss = 1027 - INTEGER(IntKi), PARAMETER :: M7N2TDxss = 1028 - INTEGER(IntKi), PARAMETER :: M7N3TDxss = 1029 - INTEGER(IntKi), PARAMETER :: M7N4TDxss = 1030 - INTEGER(IntKi), PARAMETER :: M7N5TDxss = 1031 - INTEGER(IntKi), PARAMETER :: M7N6TDxss = 1032 - INTEGER(IntKi), PARAMETER :: M7N7TDxss = 1033 - INTEGER(IntKi), PARAMETER :: M7N8TDxss = 1034 - INTEGER(IntKi), PARAMETER :: M7N9TDxss = 1035 - INTEGER(IntKi), PARAMETER :: M8N1TDxss = 1036 - INTEGER(IntKi), PARAMETER :: M8N2TDxss = 1037 - INTEGER(IntKi), PARAMETER :: M8N3TDxss = 1038 - INTEGER(IntKi), PARAMETER :: M8N4TDxss = 1039 - INTEGER(IntKi), PARAMETER :: M8N5TDxss = 1040 - INTEGER(IntKi), PARAMETER :: M8N6TDxss = 1041 - INTEGER(IntKi), PARAMETER :: M8N7TDxss = 1042 - INTEGER(IntKi), PARAMETER :: M8N8TDxss = 1043 - INTEGER(IntKi), PARAMETER :: M8N9TDxss = 1044 - INTEGER(IntKi), PARAMETER :: M9N1TDxss = 1045 - INTEGER(IntKi), PARAMETER :: M9N2TDxss = 1046 - INTEGER(IntKi), PARAMETER :: M9N3TDxss = 1047 - INTEGER(IntKi), PARAMETER :: M9N4TDxss = 1048 - INTEGER(IntKi), PARAMETER :: M9N5TDxss = 1049 - INTEGER(IntKi), PARAMETER :: M9N6TDxss = 1050 - INTEGER(IntKi), PARAMETER :: M9N7TDxss = 1051 - INTEGER(IntKi), PARAMETER :: M9N8TDxss = 1052 - INTEGER(IntKi), PARAMETER :: M9N9TDxss = 1053 - INTEGER(IntKi), PARAMETER :: M1N1TDyss = 1054 - INTEGER(IntKi), PARAMETER :: M1N2TDyss = 1055 - INTEGER(IntKi), PARAMETER :: M1N3TDyss = 1056 - INTEGER(IntKi), PARAMETER :: M1N4TDyss = 1057 - INTEGER(IntKi), PARAMETER :: M1N5TDyss = 1058 - INTEGER(IntKi), PARAMETER :: M1N6TDyss = 1059 - INTEGER(IntKi), PARAMETER :: M1N7TDyss = 1060 - INTEGER(IntKi), PARAMETER :: M1N8TDyss = 1061 - INTEGER(IntKi), PARAMETER :: M1N9TDyss = 1062 - INTEGER(IntKi), PARAMETER :: M2N1TDyss = 1063 - INTEGER(IntKi), PARAMETER :: M2N2TDyss = 1064 - INTEGER(IntKi), PARAMETER :: M2N3TDyss = 1065 - INTEGER(IntKi), PARAMETER :: M2N4TDyss = 1066 - INTEGER(IntKi), PARAMETER :: M2N5TDyss = 1067 - INTEGER(IntKi), PARAMETER :: M2N6TDyss = 1068 - INTEGER(IntKi), PARAMETER :: M2N7TDyss = 1069 - INTEGER(IntKi), PARAMETER :: M2N8TDyss = 1070 - INTEGER(IntKi), PARAMETER :: M2N9TDyss = 1071 - INTEGER(IntKi), PARAMETER :: M3N1TDyss = 1072 - INTEGER(IntKi), PARAMETER :: M3N2TDyss = 1073 - INTEGER(IntKi), PARAMETER :: M3N3TDyss = 1074 - INTEGER(IntKi), PARAMETER :: M3N4TDyss = 1075 - INTEGER(IntKi), PARAMETER :: M3N5TDyss = 1076 - INTEGER(IntKi), PARAMETER :: M3N6TDyss = 1077 - INTEGER(IntKi), PARAMETER :: M3N7TDyss = 1078 - INTEGER(IntKi), PARAMETER :: M3N8TDyss = 1079 - INTEGER(IntKi), PARAMETER :: M3N9TDyss = 1080 - INTEGER(IntKi), PARAMETER :: M4N1TDyss = 1081 - INTEGER(IntKi), PARAMETER :: M4N2TDyss = 1082 - INTEGER(IntKi), PARAMETER :: M4N3TDyss = 1083 - INTEGER(IntKi), PARAMETER :: M4N4TDyss = 1084 - INTEGER(IntKi), PARAMETER :: M4N5TDyss = 1085 - INTEGER(IntKi), PARAMETER :: M4N6TDyss = 1086 - INTEGER(IntKi), PARAMETER :: M4N7TDyss = 1087 - INTEGER(IntKi), PARAMETER :: M4N8TDyss = 1088 - INTEGER(IntKi), PARAMETER :: M4N9TDyss = 1089 - INTEGER(IntKi), PARAMETER :: M5N1TDyss = 1090 - INTEGER(IntKi), PARAMETER :: M5N2TDyss = 1091 - INTEGER(IntKi), PARAMETER :: M5N3TDyss = 1092 - INTEGER(IntKi), PARAMETER :: M5N4TDyss = 1093 - INTEGER(IntKi), PARAMETER :: M5N5TDyss = 1094 - INTEGER(IntKi), PARAMETER :: M5N6TDyss = 1095 - INTEGER(IntKi), PARAMETER :: M5N7TDyss = 1096 - INTEGER(IntKi), PARAMETER :: M5N8TDyss = 1097 - INTEGER(IntKi), PARAMETER :: M5N9TDyss = 1098 - INTEGER(IntKi), PARAMETER :: M6N1TDyss = 1099 - INTEGER(IntKi), PARAMETER :: M6N2TDyss = 1100 - INTEGER(IntKi), PARAMETER :: M6N3TDyss = 1101 - INTEGER(IntKi), PARAMETER :: M6N4TDyss = 1102 - INTEGER(IntKi), PARAMETER :: M6N5TDyss = 1103 - INTEGER(IntKi), PARAMETER :: M6N6TDyss = 1104 - INTEGER(IntKi), PARAMETER :: M6N7TDyss = 1105 - INTEGER(IntKi), PARAMETER :: M6N8TDyss = 1106 - INTEGER(IntKi), PARAMETER :: M6N9TDyss = 1107 - INTEGER(IntKi), PARAMETER :: M7N1TDyss = 1108 - INTEGER(IntKi), PARAMETER :: M7N2TDyss = 1109 - INTEGER(IntKi), PARAMETER :: M7N3TDyss = 1110 - INTEGER(IntKi), PARAMETER :: M7N4TDyss = 1111 - INTEGER(IntKi), PARAMETER :: M7N5TDyss = 1112 - INTEGER(IntKi), PARAMETER :: M7N6TDyss = 1113 - INTEGER(IntKi), PARAMETER :: M7N7TDyss = 1114 - INTEGER(IntKi), PARAMETER :: M7N8TDyss = 1115 - INTEGER(IntKi), PARAMETER :: M7N9TDyss = 1116 - INTEGER(IntKi), PARAMETER :: M8N1TDyss = 1117 - INTEGER(IntKi), PARAMETER :: M8N2TDyss = 1118 - INTEGER(IntKi), PARAMETER :: M8N3TDyss = 1119 - INTEGER(IntKi), PARAMETER :: M8N4TDyss = 1120 - INTEGER(IntKi), PARAMETER :: M8N5TDyss = 1121 - INTEGER(IntKi), PARAMETER :: M8N6TDyss = 1122 - INTEGER(IntKi), PARAMETER :: M8N7TDyss = 1123 - INTEGER(IntKi), PARAMETER :: M8N8TDyss = 1124 - INTEGER(IntKi), PARAMETER :: M8N9TDyss = 1125 - INTEGER(IntKi), PARAMETER :: M9N1TDyss = 1126 - INTEGER(IntKi), PARAMETER :: M9N2TDyss = 1127 - INTEGER(IntKi), PARAMETER :: M9N3TDyss = 1128 - INTEGER(IntKi), PARAMETER :: M9N4TDyss = 1129 - INTEGER(IntKi), PARAMETER :: M9N5TDyss = 1130 - INTEGER(IntKi), PARAMETER :: M9N6TDyss = 1131 - INTEGER(IntKi), PARAMETER :: M9N7TDyss = 1132 - INTEGER(IntKi), PARAMETER :: M9N8TDyss = 1133 - INTEGER(IntKi), PARAMETER :: M9N9TDyss = 1134 - INTEGER(IntKi), PARAMETER :: M1N1TDzss = 1135 - INTEGER(IntKi), PARAMETER :: M1N2TDzss = 1136 - INTEGER(IntKi), PARAMETER :: M1N3TDzss = 1137 - INTEGER(IntKi), PARAMETER :: M1N4TDzss = 1138 - INTEGER(IntKi), PARAMETER :: M1N5TDzss = 1139 - INTEGER(IntKi), PARAMETER :: M1N6TDzss = 1140 - INTEGER(IntKi), PARAMETER :: M1N7TDzss = 1141 - INTEGER(IntKi), PARAMETER :: M1N8TDzss = 1142 - INTEGER(IntKi), PARAMETER :: M1N9TDzss = 1143 - INTEGER(IntKi), PARAMETER :: M2N1TDzss = 1144 - INTEGER(IntKi), PARAMETER :: M2N2TDzss = 1145 - INTEGER(IntKi), PARAMETER :: M2N3TDzss = 1146 - INTEGER(IntKi), PARAMETER :: M2N4TDzss = 1147 - INTEGER(IntKi), PARAMETER :: M2N5TDzss = 1148 - INTEGER(IntKi), PARAMETER :: M2N6TDzss = 1149 - INTEGER(IntKi), PARAMETER :: M2N7TDzss = 1150 - INTEGER(IntKi), PARAMETER :: M2N8TDzss = 1151 - INTEGER(IntKi), PARAMETER :: M2N9TDzss = 1152 - INTEGER(IntKi), PARAMETER :: M3N1TDzss = 1153 - INTEGER(IntKi), PARAMETER :: M3N2TDzss = 1154 - INTEGER(IntKi), PARAMETER :: M3N3TDzss = 1155 - INTEGER(IntKi), PARAMETER :: M3N4TDzss = 1156 - INTEGER(IntKi), PARAMETER :: M3N5TDzss = 1157 - INTEGER(IntKi), PARAMETER :: M3N6TDzss = 1158 - INTEGER(IntKi), PARAMETER :: M3N7TDzss = 1159 - INTEGER(IntKi), PARAMETER :: M3N8TDzss = 1160 - INTEGER(IntKi), PARAMETER :: M3N9TDzss = 1161 - INTEGER(IntKi), PARAMETER :: M4N1TDzss = 1162 - INTEGER(IntKi), PARAMETER :: M4N2TDzss = 1163 - INTEGER(IntKi), PARAMETER :: M4N3TDzss = 1164 - INTEGER(IntKi), PARAMETER :: M4N4TDzss = 1165 - INTEGER(IntKi), PARAMETER :: M4N5TDzss = 1166 - INTEGER(IntKi), PARAMETER :: M4N6TDzss = 1167 - INTEGER(IntKi), PARAMETER :: M4N7TDzss = 1168 - INTEGER(IntKi), PARAMETER :: M4N8TDzss = 1169 - INTEGER(IntKi), PARAMETER :: M4N9TDzss = 1170 - INTEGER(IntKi), PARAMETER :: M5N1TDzss = 1171 - INTEGER(IntKi), PARAMETER :: M5N2TDzss = 1172 - INTEGER(IntKi), PARAMETER :: M5N3TDzss = 1173 - INTEGER(IntKi), PARAMETER :: M5N4TDzss = 1174 - INTEGER(IntKi), PARAMETER :: M5N5TDzss = 1175 - INTEGER(IntKi), PARAMETER :: M5N6TDzss = 1176 - INTEGER(IntKi), PARAMETER :: M5N7TDzss = 1177 - INTEGER(IntKi), PARAMETER :: M5N8TDzss = 1178 - INTEGER(IntKi), PARAMETER :: M5N9TDzss = 1179 - INTEGER(IntKi), PARAMETER :: M6N1TDzss = 1180 - INTEGER(IntKi), PARAMETER :: M6N2TDzss = 1181 - INTEGER(IntKi), PARAMETER :: M6N3TDzss = 1182 - INTEGER(IntKi), PARAMETER :: M6N4TDzss = 1183 - INTEGER(IntKi), PARAMETER :: M6N5TDzss = 1184 - INTEGER(IntKi), PARAMETER :: M6N6TDzss = 1185 - INTEGER(IntKi), PARAMETER :: M6N7TDzss = 1186 - INTEGER(IntKi), PARAMETER :: M6N8TDzss = 1187 - INTEGER(IntKi), PARAMETER :: M6N9TDzss = 1188 - INTEGER(IntKi), PARAMETER :: M7N1TDzss = 1189 - INTEGER(IntKi), PARAMETER :: M7N2TDzss = 1190 - INTEGER(IntKi), PARAMETER :: M7N3TDzss = 1191 - INTEGER(IntKi), PARAMETER :: M7N4TDzss = 1192 - INTEGER(IntKi), PARAMETER :: M7N5TDzss = 1193 - INTEGER(IntKi), PARAMETER :: M7N6TDzss = 1194 - INTEGER(IntKi), PARAMETER :: M7N7TDzss = 1195 - INTEGER(IntKi), PARAMETER :: M7N8TDzss = 1196 - INTEGER(IntKi), PARAMETER :: M7N9TDzss = 1197 - INTEGER(IntKi), PARAMETER :: M8N1TDzss = 1198 - INTEGER(IntKi), PARAMETER :: M8N2TDzss = 1199 - INTEGER(IntKi), PARAMETER :: M8N3TDzss = 1200 - INTEGER(IntKi), PARAMETER :: M8N4TDzss = 1201 - INTEGER(IntKi), PARAMETER :: M8N5TDzss = 1202 - INTEGER(IntKi), PARAMETER :: M8N6TDzss = 1203 - INTEGER(IntKi), PARAMETER :: M8N7TDzss = 1204 - INTEGER(IntKi), PARAMETER :: M8N8TDzss = 1205 - INTEGER(IntKi), PARAMETER :: M8N9TDzss = 1206 - INTEGER(IntKi), PARAMETER :: M9N1TDzss = 1207 - INTEGER(IntKi), PARAMETER :: M9N2TDzss = 1208 - INTEGER(IntKi), PARAMETER :: M9N3TDzss = 1209 - INTEGER(IntKi), PARAMETER :: M9N4TDzss = 1210 - INTEGER(IntKi), PARAMETER :: M9N5TDzss = 1211 - INTEGER(IntKi), PARAMETER :: M9N6TDzss = 1212 - INTEGER(IntKi), PARAMETER :: M9N7TDzss = 1213 - INTEGER(IntKi), PARAMETER :: M9N8TDzss = 1214 - INTEGER(IntKi), PARAMETER :: M9N9TDzss = 1215 - INTEGER(IntKi), PARAMETER :: M1N1RDxe = 1216 - INTEGER(IntKi), PARAMETER :: M1N2RDxe = 1217 - INTEGER(IntKi), PARAMETER :: M1N3RDxe = 1218 - INTEGER(IntKi), PARAMETER :: M1N4RDxe = 1219 - INTEGER(IntKi), PARAMETER :: M1N5RDxe = 1220 - INTEGER(IntKi), PARAMETER :: M1N6RDxe = 1221 - INTEGER(IntKi), PARAMETER :: M1N7RDxe = 1222 - INTEGER(IntKi), PARAMETER :: M1N8RDxe = 1223 - INTEGER(IntKi), PARAMETER :: M1N9RDxe = 1224 - INTEGER(IntKi), PARAMETER :: M2N1RDxe = 1225 - INTEGER(IntKi), PARAMETER :: M2N2RDxe = 1226 - INTEGER(IntKi), PARAMETER :: M2N3RDxe = 1227 - INTEGER(IntKi), PARAMETER :: M2N4RDxe = 1228 - INTEGER(IntKi), PARAMETER :: M2N5RDxe = 1229 - INTEGER(IntKi), PARAMETER :: M2N6RDxe = 1230 - INTEGER(IntKi), PARAMETER :: M2N7RDxe = 1231 - INTEGER(IntKi), PARAMETER :: M2N8RDxe = 1232 - INTEGER(IntKi), PARAMETER :: M2N9RDxe = 1233 - INTEGER(IntKi), PARAMETER :: M3N1RDxe = 1234 - INTEGER(IntKi), PARAMETER :: M3N2RDxe = 1235 - INTEGER(IntKi), PARAMETER :: M3N3RDxe = 1236 - INTEGER(IntKi), PARAMETER :: M3N4RDxe = 1237 - INTEGER(IntKi), PARAMETER :: M3N5RDxe = 1238 - INTEGER(IntKi), PARAMETER :: M3N6RDxe = 1239 - INTEGER(IntKi), PARAMETER :: M3N7RDxe = 1240 - INTEGER(IntKi), PARAMETER :: M3N8RDxe = 1241 - INTEGER(IntKi), PARAMETER :: M3N9RDxe = 1242 - INTEGER(IntKi), PARAMETER :: M4N1RDxe = 1243 - INTEGER(IntKi), PARAMETER :: M4N2RDxe = 1244 - INTEGER(IntKi), PARAMETER :: M4N3RDxe = 1245 - INTEGER(IntKi), PARAMETER :: M4N4RDxe = 1246 - INTEGER(IntKi), PARAMETER :: M4N5RDxe = 1247 - INTEGER(IntKi), PARAMETER :: M4N6RDxe = 1248 - INTEGER(IntKi), PARAMETER :: M4N7RDxe = 1249 - INTEGER(IntKi), PARAMETER :: M4N8RDxe = 1250 - INTEGER(IntKi), PARAMETER :: M4N9RDxe = 1251 - INTEGER(IntKi), PARAMETER :: M5N1RDxe = 1252 - INTEGER(IntKi), PARAMETER :: M5N2RDxe = 1253 - INTEGER(IntKi), PARAMETER :: M5N3RDxe = 1254 - INTEGER(IntKi), PARAMETER :: M5N4RDxe = 1255 - INTEGER(IntKi), PARAMETER :: M5N5RDxe = 1256 - INTEGER(IntKi), PARAMETER :: M5N6RDxe = 1257 - INTEGER(IntKi), PARAMETER :: M5N7RDxe = 1258 - INTEGER(IntKi), PARAMETER :: M5N8RDxe = 1259 - INTEGER(IntKi), PARAMETER :: M5N9RDxe = 1260 - INTEGER(IntKi), PARAMETER :: M6N1RDxe = 1261 - INTEGER(IntKi), PARAMETER :: M6N2RDxe = 1262 - INTEGER(IntKi), PARAMETER :: M6N3RDxe = 1263 - INTEGER(IntKi), PARAMETER :: M6N4RDxe = 1264 - INTEGER(IntKi), PARAMETER :: M6N5RDxe = 1265 - INTEGER(IntKi), PARAMETER :: M6N6RDxe = 1266 - INTEGER(IntKi), PARAMETER :: M6N7RDxe = 1267 - INTEGER(IntKi), PARAMETER :: M6N8RDxe = 1268 - INTEGER(IntKi), PARAMETER :: M6N9RDxe = 1269 - INTEGER(IntKi), PARAMETER :: M7N1RDxe = 1270 - INTEGER(IntKi), PARAMETER :: M7N2RDxe = 1271 - INTEGER(IntKi), PARAMETER :: M7N3RDxe = 1272 - INTEGER(IntKi), PARAMETER :: M7N4RDxe = 1273 - INTEGER(IntKi), PARAMETER :: M7N5RDxe = 1274 - INTEGER(IntKi), PARAMETER :: M7N6RDxe = 1275 - INTEGER(IntKi), PARAMETER :: M7N7RDxe = 1276 - INTEGER(IntKi), PARAMETER :: M7N8RDxe = 1277 - INTEGER(IntKi), PARAMETER :: M7N9RDxe = 1278 - INTEGER(IntKi), PARAMETER :: M8N1RDxe = 1279 - INTEGER(IntKi), PARAMETER :: M8N2RDxe = 1280 - INTEGER(IntKi), PARAMETER :: M8N3RDxe = 1281 - INTEGER(IntKi), PARAMETER :: M8N4RDxe = 1282 - INTEGER(IntKi), PARAMETER :: M8N5RDxe = 1283 - INTEGER(IntKi), PARAMETER :: M8N6RDxe = 1284 - INTEGER(IntKi), PARAMETER :: M8N7RDxe = 1285 - INTEGER(IntKi), PARAMETER :: M8N8RDxe = 1286 - INTEGER(IntKi), PARAMETER :: M8N9RDxe = 1287 - INTEGER(IntKi), PARAMETER :: M9N1RDxe = 1288 - INTEGER(IntKi), PARAMETER :: M9N2RDxe = 1289 - INTEGER(IntKi), PARAMETER :: M9N3RDxe = 1290 - INTEGER(IntKi), PARAMETER :: M9N4RDxe = 1291 - INTEGER(IntKi), PARAMETER :: M9N5RDxe = 1292 - INTEGER(IntKi), PARAMETER :: M9N6RDxe = 1293 - INTEGER(IntKi), PARAMETER :: M9N7RDxe = 1294 - INTEGER(IntKi), PARAMETER :: M9N8RDxe = 1295 - INTEGER(IntKi), PARAMETER :: M9N9RDxe = 1296 - INTEGER(IntKi), PARAMETER :: M1N1RDye = 1297 - INTEGER(IntKi), PARAMETER :: M1N2RDye = 1298 - INTEGER(IntKi), PARAMETER :: M1N3RDye = 1299 - INTEGER(IntKi), PARAMETER :: M1N4RDye = 1300 - INTEGER(IntKi), PARAMETER :: M1N5RDye = 1301 - INTEGER(IntKi), PARAMETER :: M1N6RDye = 1302 - INTEGER(IntKi), PARAMETER :: M1N7RDye = 1303 - INTEGER(IntKi), PARAMETER :: M1N8RDye = 1304 - INTEGER(IntKi), PARAMETER :: M1N9RDye = 1305 - INTEGER(IntKi), PARAMETER :: M2N1RDye = 1306 - INTEGER(IntKi), PARAMETER :: M2N2RDye = 1307 - INTEGER(IntKi), PARAMETER :: M2N3RDye = 1308 - INTEGER(IntKi), PARAMETER :: M2N4RDye = 1309 - INTEGER(IntKi), PARAMETER :: M2N5RDye = 1310 - INTEGER(IntKi), PARAMETER :: M2N6RDye = 1311 - INTEGER(IntKi), PARAMETER :: M2N7RDye = 1312 - INTEGER(IntKi), PARAMETER :: M2N8RDye = 1313 - INTEGER(IntKi), PARAMETER :: M2N9RDye = 1314 - INTEGER(IntKi), PARAMETER :: M3N1RDye = 1315 - INTEGER(IntKi), PARAMETER :: M3N2RDye = 1316 - INTEGER(IntKi), PARAMETER :: M3N3RDye = 1317 - INTEGER(IntKi), PARAMETER :: M3N4RDye = 1318 - INTEGER(IntKi), PARAMETER :: M3N5RDye = 1319 - INTEGER(IntKi), PARAMETER :: M3N6RDye = 1320 - INTEGER(IntKi), PARAMETER :: M3N7RDye = 1321 - INTEGER(IntKi), PARAMETER :: M3N8RDye = 1322 - INTEGER(IntKi), PARAMETER :: M3N9RDye = 1323 - INTEGER(IntKi), PARAMETER :: M4N1RDye = 1324 - INTEGER(IntKi), PARAMETER :: M4N2RDye = 1325 - INTEGER(IntKi), PARAMETER :: M4N3RDye = 1326 - INTEGER(IntKi), PARAMETER :: M4N4RDye = 1327 - INTEGER(IntKi), PARAMETER :: M4N5RDye = 1328 - INTEGER(IntKi), PARAMETER :: M4N6RDye = 1329 - INTEGER(IntKi), PARAMETER :: M4N7RDye = 1330 - INTEGER(IntKi), PARAMETER :: M4N8RDye = 1331 - INTEGER(IntKi), PARAMETER :: M4N9RDye = 1332 - INTEGER(IntKi), PARAMETER :: M5N1RDye = 1333 - INTEGER(IntKi), PARAMETER :: M5N2RDye = 1334 - INTEGER(IntKi), PARAMETER :: M5N3RDye = 1335 - INTEGER(IntKi), PARAMETER :: M5N4RDye = 1336 - INTEGER(IntKi), PARAMETER :: M5N5RDye = 1337 - INTEGER(IntKi), PARAMETER :: M5N6RDye = 1338 - INTEGER(IntKi), PARAMETER :: M5N7RDye = 1339 - INTEGER(IntKi), PARAMETER :: M5N8RDye = 1340 - INTEGER(IntKi), PARAMETER :: M5N9RDye = 1341 - INTEGER(IntKi), PARAMETER :: M6N1RDye = 1342 - INTEGER(IntKi), PARAMETER :: M6N2RDye = 1343 - INTEGER(IntKi), PARAMETER :: M6N3RDye = 1344 - INTEGER(IntKi), PARAMETER :: M6N4RDye = 1345 - INTEGER(IntKi), PARAMETER :: M6N5RDye = 1346 - INTEGER(IntKi), PARAMETER :: M6N6RDye = 1347 - INTEGER(IntKi), PARAMETER :: M6N7RDye = 1348 - INTEGER(IntKi), PARAMETER :: M6N8RDye = 1349 - INTEGER(IntKi), PARAMETER :: M6N9RDye = 1350 - INTEGER(IntKi), PARAMETER :: M7N1RDye = 1351 - INTEGER(IntKi), PARAMETER :: M7N2RDye = 1352 - INTEGER(IntKi), PARAMETER :: M7N3RDye = 1353 - INTEGER(IntKi), PARAMETER :: M7N4RDye = 1354 - INTEGER(IntKi), PARAMETER :: M7N5RDye = 1355 - INTEGER(IntKi), PARAMETER :: M7N6RDye = 1356 - INTEGER(IntKi), PARAMETER :: M7N7RDye = 1357 - INTEGER(IntKi), PARAMETER :: M7N8RDye = 1358 - INTEGER(IntKi), PARAMETER :: M7N9RDye = 1359 - INTEGER(IntKi), PARAMETER :: M8N1RDye = 1360 - INTEGER(IntKi), PARAMETER :: M8N2RDye = 1361 - INTEGER(IntKi), PARAMETER :: M8N3RDye = 1362 - INTEGER(IntKi), PARAMETER :: M8N4RDye = 1363 - INTEGER(IntKi), PARAMETER :: M8N5RDye = 1364 - INTEGER(IntKi), PARAMETER :: M8N6RDye = 1365 - INTEGER(IntKi), PARAMETER :: M8N7RDye = 1366 - INTEGER(IntKi), PARAMETER :: M8N8RDye = 1367 - INTEGER(IntKi), PARAMETER :: M8N9RDye = 1368 - INTEGER(IntKi), PARAMETER :: M9N1RDye = 1369 - INTEGER(IntKi), PARAMETER :: M9N2RDye = 1370 - INTEGER(IntKi), PARAMETER :: M9N3RDye = 1371 - INTEGER(IntKi), PARAMETER :: M9N4RDye = 1372 - INTEGER(IntKi), PARAMETER :: M9N5RDye = 1373 - INTEGER(IntKi), PARAMETER :: M9N6RDye = 1374 - INTEGER(IntKi), PARAMETER :: M9N7RDye = 1375 - INTEGER(IntKi), PARAMETER :: M9N8RDye = 1376 - INTEGER(IntKi), PARAMETER :: M9N9RDye = 1377 - INTEGER(IntKi), PARAMETER :: M1N1RDze = 1378 - INTEGER(IntKi), PARAMETER :: M1N2RDze = 1379 - INTEGER(IntKi), PARAMETER :: M1N3RDze = 1380 - INTEGER(IntKi), PARAMETER :: M1N4RDze = 1381 - INTEGER(IntKi), PARAMETER :: M1N5RDze = 1382 - INTEGER(IntKi), PARAMETER :: M1N6RDze = 1383 - INTEGER(IntKi), PARAMETER :: M1N7RDze = 1384 - INTEGER(IntKi), PARAMETER :: M1N8RDze = 1385 - INTEGER(IntKi), PARAMETER :: M1N9RDze = 1386 - INTEGER(IntKi), PARAMETER :: M2N1RDze = 1387 - INTEGER(IntKi), PARAMETER :: M2N2RDze = 1388 - INTEGER(IntKi), PARAMETER :: M2N3RDze = 1389 - INTEGER(IntKi), PARAMETER :: M2N4RDze = 1390 - INTEGER(IntKi), PARAMETER :: M2N5RDze = 1391 - INTEGER(IntKi), PARAMETER :: M2N6RDze = 1392 - INTEGER(IntKi), PARAMETER :: M2N7RDze = 1393 - INTEGER(IntKi), PARAMETER :: M2N8RDze = 1394 - INTEGER(IntKi), PARAMETER :: M2N9RDze = 1395 - INTEGER(IntKi), PARAMETER :: M3N1RDze = 1396 - INTEGER(IntKi), PARAMETER :: M3N2RDze = 1397 - INTEGER(IntKi), PARAMETER :: M3N3RDze = 1398 - INTEGER(IntKi), PARAMETER :: M3N4RDze = 1399 - INTEGER(IntKi), PARAMETER :: M3N5RDze = 1400 - INTEGER(IntKi), PARAMETER :: M3N6RDze = 1401 - INTEGER(IntKi), PARAMETER :: M3N7RDze = 1402 - INTEGER(IntKi), PARAMETER :: M3N8RDze = 1403 - INTEGER(IntKi), PARAMETER :: M3N9RDze = 1404 - INTEGER(IntKi), PARAMETER :: M4N1RDze = 1405 - INTEGER(IntKi), PARAMETER :: M4N2RDze = 1406 - INTEGER(IntKi), PARAMETER :: M4N3RDze = 1407 - INTEGER(IntKi), PARAMETER :: M4N4RDze = 1408 - INTEGER(IntKi), PARAMETER :: M4N5RDze = 1409 - INTEGER(IntKi), PARAMETER :: M4N6RDze = 1410 - INTEGER(IntKi), PARAMETER :: M4N7RDze = 1411 - INTEGER(IntKi), PARAMETER :: M4N8RDze = 1412 - INTEGER(IntKi), PARAMETER :: M4N9RDze = 1413 - INTEGER(IntKi), PARAMETER :: M5N1RDze = 1414 - INTEGER(IntKi), PARAMETER :: M5N2RDze = 1415 - INTEGER(IntKi), PARAMETER :: M5N3RDze = 1416 - INTEGER(IntKi), PARAMETER :: M5N4RDze = 1417 - INTEGER(IntKi), PARAMETER :: M5N5RDze = 1418 - INTEGER(IntKi), PARAMETER :: M5N6RDze = 1419 - INTEGER(IntKi), PARAMETER :: M5N7RDze = 1420 - INTEGER(IntKi), PARAMETER :: M5N8RDze = 1421 - INTEGER(IntKi), PARAMETER :: M5N9RDze = 1422 - INTEGER(IntKi), PARAMETER :: M6N1RDze = 1423 - INTEGER(IntKi), PARAMETER :: M6N2RDze = 1424 - INTEGER(IntKi), PARAMETER :: M6N3RDze = 1425 - INTEGER(IntKi), PARAMETER :: M6N4RDze = 1426 - INTEGER(IntKi), PARAMETER :: M6N5RDze = 1427 - INTEGER(IntKi), PARAMETER :: M6N6RDze = 1428 - INTEGER(IntKi), PARAMETER :: M6N7RDze = 1429 - INTEGER(IntKi), PARAMETER :: M6N8RDze = 1430 - INTEGER(IntKi), PARAMETER :: M6N9RDze = 1431 - INTEGER(IntKi), PARAMETER :: M7N1RDze = 1432 - INTEGER(IntKi), PARAMETER :: M7N2RDze = 1433 - INTEGER(IntKi), PARAMETER :: M7N3RDze = 1434 - INTEGER(IntKi), PARAMETER :: M7N4RDze = 1435 - INTEGER(IntKi), PARAMETER :: M7N5RDze = 1436 - INTEGER(IntKi), PARAMETER :: M7N6RDze = 1437 - INTEGER(IntKi), PARAMETER :: M7N7RDze = 1438 - INTEGER(IntKi), PARAMETER :: M7N8RDze = 1439 - INTEGER(IntKi), PARAMETER :: M7N9RDze = 1440 - INTEGER(IntKi), PARAMETER :: M8N1RDze = 1441 - INTEGER(IntKi), PARAMETER :: M8N2RDze = 1442 - INTEGER(IntKi), PARAMETER :: M8N3RDze = 1443 - INTEGER(IntKi), PARAMETER :: M8N4RDze = 1444 - INTEGER(IntKi), PARAMETER :: M8N5RDze = 1445 - INTEGER(IntKi), PARAMETER :: M8N6RDze = 1446 - INTEGER(IntKi), PARAMETER :: M8N7RDze = 1447 - INTEGER(IntKi), PARAMETER :: M8N8RDze = 1448 - INTEGER(IntKi), PARAMETER :: M8N9RDze = 1449 - INTEGER(IntKi), PARAMETER :: M9N1RDze = 1450 - INTEGER(IntKi), PARAMETER :: M9N2RDze = 1451 - INTEGER(IntKi), PARAMETER :: M9N3RDze = 1452 - INTEGER(IntKi), PARAMETER :: M9N4RDze = 1453 - INTEGER(IntKi), PARAMETER :: M9N5RDze = 1454 - INTEGER(IntKi), PARAMETER :: M9N6RDze = 1455 - INTEGER(IntKi), PARAMETER :: M9N7RDze = 1456 - INTEGER(IntKi), PARAMETER :: M9N8RDze = 1457 - INTEGER(IntKi), PARAMETER :: M9N9RDze = 1458 - - - ! Accelerations: - - INTEGER(IntKi), PARAMETER :: M1N1TAxe = 1459 - INTEGER(IntKi), PARAMETER :: M1N2TAxe = 1460 - INTEGER(IntKi), PARAMETER :: M1N3TAxe = 1461 - INTEGER(IntKi), PARAMETER :: M1N4TAxe = 1462 - INTEGER(IntKi), PARAMETER :: M1N5TAxe = 1463 - INTEGER(IntKi), PARAMETER :: M1N6TAxe = 1464 - INTEGER(IntKi), PARAMETER :: M1N7TAxe = 1465 - INTEGER(IntKi), PARAMETER :: M1N8TAxe = 1466 - INTEGER(IntKi), PARAMETER :: M1N9TAxe = 1467 - INTEGER(IntKi), PARAMETER :: M2N1TAxe = 1468 - INTEGER(IntKi), PARAMETER :: M2N2TAxe = 1469 - INTEGER(IntKi), PARAMETER :: M2N3TAxe = 1470 - INTEGER(IntKi), PARAMETER :: M2N4TAxe = 1471 - INTEGER(IntKi), PARAMETER :: M2N5TAxe = 1472 - INTEGER(IntKi), PARAMETER :: M2N6TAxe = 1473 - INTEGER(IntKi), PARAMETER :: M2N7TAxe = 1474 - INTEGER(IntKi), PARAMETER :: M2N8TAxe = 1475 - INTEGER(IntKi), PARAMETER :: M2N9TAxe = 1476 - INTEGER(IntKi), PARAMETER :: M3N1TAxe = 1477 - INTEGER(IntKi), PARAMETER :: M3N2TAxe = 1478 - INTEGER(IntKi), PARAMETER :: M3N3TAxe = 1479 - INTEGER(IntKi), PARAMETER :: M3N4TAxe = 1480 - INTEGER(IntKi), PARAMETER :: M3N5TAxe = 1481 - INTEGER(IntKi), PARAMETER :: M3N6TAxe = 1482 - INTEGER(IntKi), PARAMETER :: M3N7TAxe = 1483 - INTEGER(IntKi), PARAMETER :: M3N8TAxe = 1484 - INTEGER(IntKi), PARAMETER :: M3N9TAxe = 1485 - INTEGER(IntKi), PARAMETER :: M4N1TAxe = 1486 - INTEGER(IntKi), PARAMETER :: M4N2TAxe = 1487 - INTEGER(IntKi), PARAMETER :: M4N3TAxe = 1488 - INTEGER(IntKi), PARAMETER :: M4N4TAxe = 1489 - INTEGER(IntKi), PARAMETER :: M4N5TAxe = 1490 - INTEGER(IntKi), PARAMETER :: M4N6TAxe = 1491 - INTEGER(IntKi), PARAMETER :: M4N7TAxe = 1492 - INTEGER(IntKi), PARAMETER :: M4N8TAxe = 1493 - INTEGER(IntKi), PARAMETER :: M4N9TAxe = 1494 - INTEGER(IntKi), PARAMETER :: M5N1TAxe = 1495 - INTEGER(IntKi), PARAMETER :: M5N2TAxe = 1496 - INTEGER(IntKi), PARAMETER :: M5N3TAxe = 1497 - INTEGER(IntKi), PARAMETER :: M5N4TAxe = 1498 - INTEGER(IntKi), PARAMETER :: M5N5TAxe = 1499 - INTEGER(IntKi), PARAMETER :: M5N6TAxe = 1500 - INTEGER(IntKi), PARAMETER :: M5N7TAxe = 1501 - INTEGER(IntKi), PARAMETER :: M5N8TAxe = 1502 - INTEGER(IntKi), PARAMETER :: M5N9TAxe = 1503 - INTEGER(IntKi), PARAMETER :: M6N1TAxe = 1504 - INTEGER(IntKi), PARAMETER :: M6N2TAxe = 1505 - INTEGER(IntKi), PARAMETER :: M6N3TAxe = 1506 - INTEGER(IntKi), PARAMETER :: M6N4TAxe = 1507 - INTEGER(IntKi), PARAMETER :: M6N5TAxe = 1508 - INTEGER(IntKi), PARAMETER :: M6N6TAxe = 1509 - INTEGER(IntKi), PARAMETER :: M6N7TAxe = 1510 - INTEGER(IntKi), PARAMETER :: M6N8TAxe = 1511 - INTEGER(IntKi), PARAMETER :: M6N9TAxe = 1512 - INTEGER(IntKi), PARAMETER :: M7N1TAxe = 1513 - INTEGER(IntKi), PARAMETER :: M7N2TAxe = 1514 - INTEGER(IntKi), PARAMETER :: M7N3TAxe = 1515 - INTEGER(IntKi), PARAMETER :: M7N4TAxe = 1516 - INTEGER(IntKi), PARAMETER :: M7N5TAxe = 1517 - INTEGER(IntKi), PARAMETER :: M7N6TAxe = 1518 - INTEGER(IntKi), PARAMETER :: M7N7TAxe = 1519 - INTEGER(IntKi), PARAMETER :: M7N8TAxe = 1520 - INTEGER(IntKi), PARAMETER :: M7N9TAxe = 1521 - INTEGER(IntKi), PARAMETER :: M8N1TAxe = 1522 - INTEGER(IntKi), PARAMETER :: M8N2TAxe = 1523 - INTEGER(IntKi), PARAMETER :: M8N3TAxe = 1524 - INTEGER(IntKi), PARAMETER :: M8N4TAxe = 1525 - INTEGER(IntKi), PARAMETER :: M8N5TAxe = 1526 - INTEGER(IntKi), PARAMETER :: M8N6TAxe = 1527 - INTEGER(IntKi), PARAMETER :: M8N7TAxe = 1528 - INTEGER(IntKi), PARAMETER :: M8N8TAxe = 1529 - INTEGER(IntKi), PARAMETER :: M8N9TAxe = 1530 - INTEGER(IntKi), PARAMETER :: M9N1TAxe = 1531 - INTEGER(IntKi), PARAMETER :: M9N2TAxe = 1532 - INTEGER(IntKi), PARAMETER :: M9N3TAxe = 1533 - INTEGER(IntKi), PARAMETER :: M9N4TAxe = 1534 - INTEGER(IntKi), PARAMETER :: M9N5TAxe = 1535 - INTEGER(IntKi), PARAMETER :: M9N6TAxe = 1536 - INTEGER(IntKi), PARAMETER :: M9N7TAxe = 1537 - INTEGER(IntKi), PARAMETER :: M9N8TAxe = 1538 - INTEGER(IntKi), PARAMETER :: M9N9TAxe = 1539 - INTEGER(IntKi), PARAMETER :: M1N1TAye = 1540 - INTEGER(IntKi), PARAMETER :: M1N2TAye = 1541 - INTEGER(IntKi), PARAMETER :: M1N3TAye = 1542 - INTEGER(IntKi), PARAMETER :: M1N4TAye = 1543 - INTEGER(IntKi), PARAMETER :: M1N5TAye = 1544 - INTEGER(IntKi), PARAMETER :: M1N6TAye = 1545 - INTEGER(IntKi), PARAMETER :: M1N7TAye = 1546 - INTEGER(IntKi), PARAMETER :: M1N8TAye = 1547 - INTEGER(IntKi), PARAMETER :: M1N9TAye = 1548 - INTEGER(IntKi), PARAMETER :: M2N1TAye = 1549 - INTEGER(IntKi), PARAMETER :: M2N2TAye = 1550 - INTEGER(IntKi), PARAMETER :: M2N3TAye = 1551 - INTEGER(IntKi), PARAMETER :: M2N4TAye = 1552 - INTEGER(IntKi), PARAMETER :: M2N5TAye = 1553 - INTEGER(IntKi), PARAMETER :: M2N6TAye = 1554 - INTEGER(IntKi), PARAMETER :: M2N7TAye = 1555 - INTEGER(IntKi), PARAMETER :: M2N8TAye = 1556 - INTEGER(IntKi), PARAMETER :: M2N9TAye = 1557 - INTEGER(IntKi), PARAMETER :: M3N1TAye = 1558 - INTEGER(IntKi), PARAMETER :: M3N2TAye = 1559 - INTEGER(IntKi), PARAMETER :: M3N3TAye = 1560 - INTEGER(IntKi), PARAMETER :: M3N4TAye = 1561 - INTEGER(IntKi), PARAMETER :: M3N5TAye = 1562 - INTEGER(IntKi), PARAMETER :: M3N6TAye = 1563 - INTEGER(IntKi), PARAMETER :: M3N7TAye = 1564 - INTEGER(IntKi), PARAMETER :: M3N8TAye = 1565 - INTEGER(IntKi), PARAMETER :: M3N9TAye = 1566 - INTEGER(IntKi), PARAMETER :: M4N1TAye = 1567 - INTEGER(IntKi), PARAMETER :: M4N2TAye = 1568 - INTEGER(IntKi), PARAMETER :: M4N3TAye = 1569 - INTEGER(IntKi), PARAMETER :: M4N4TAye = 1570 - INTEGER(IntKi), PARAMETER :: M4N5TAye = 1571 - INTEGER(IntKi), PARAMETER :: M4N6TAye = 1572 - INTEGER(IntKi), PARAMETER :: M4N7TAye = 1573 - INTEGER(IntKi), PARAMETER :: M4N8TAye = 1574 - INTEGER(IntKi), PARAMETER :: M4N9TAye = 1575 - INTEGER(IntKi), PARAMETER :: M5N1TAye = 1576 - INTEGER(IntKi), PARAMETER :: M5N2TAye = 1577 - INTEGER(IntKi), PARAMETER :: M5N3TAye = 1578 - INTEGER(IntKi), PARAMETER :: M5N4TAye = 1579 - INTEGER(IntKi), PARAMETER :: M5N5TAye = 1580 - INTEGER(IntKi), PARAMETER :: M5N6TAye = 1581 - INTEGER(IntKi), PARAMETER :: M5N7TAye = 1582 - INTEGER(IntKi), PARAMETER :: M5N8TAye = 1583 - INTEGER(IntKi), PARAMETER :: M5N9TAye = 1584 - INTEGER(IntKi), PARAMETER :: M6N1TAye = 1585 - INTEGER(IntKi), PARAMETER :: M6N2TAye = 1586 - INTEGER(IntKi), PARAMETER :: M6N3TAye = 1587 - INTEGER(IntKi), PARAMETER :: M6N4TAye = 1588 - INTEGER(IntKi), PARAMETER :: M6N5TAye = 1589 - INTEGER(IntKi), PARAMETER :: M6N6TAye = 1590 - INTEGER(IntKi), PARAMETER :: M6N7TAye = 1591 - INTEGER(IntKi), PARAMETER :: M6N8TAye = 1592 - INTEGER(IntKi), PARAMETER :: M6N9TAye = 1593 - INTEGER(IntKi), PARAMETER :: M7N1TAye = 1594 - INTEGER(IntKi), PARAMETER :: M7N2TAye = 1595 - INTEGER(IntKi), PARAMETER :: M7N3TAye = 1596 - INTEGER(IntKi), PARAMETER :: M7N4TAye = 1597 - INTEGER(IntKi), PARAMETER :: M7N5TAye = 1598 - INTEGER(IntKi), PARAMETER :: M7N6TAye = 1599 - INTEGER(IntKi), PARAMETER :: M7N7TAye = 1600 - INTEGER(IntKi), PARAMETER :: M7N8TAye = 1601 - INTEGER(IntKi), PARAMETER :: M7N9TAye = 1602 - INTEGER(IntKi), PARAMETER :: M8N1TAye = 1603 - INTEGER(IntKi), PARAMETER :: M8N2TAye = 1604 - INTEGER(IntKi), PARAMETER :: M8N3TAye = 1605 - INTEGER(IntKi), PARAMETER :: M8N4TAye = 1606 - INTEGER(IntKi), PARAMETER :: M8N5TAye = 1607 - INTEGER(IntKi), PARAMETER :: M8N6TAye = 1608 - INTEGER(IntKi), PARAMETER :: M8N7TAye = 1609 - INTEGER(IntKi), PARAMETER :: M8N8TAye = 1610 - INTEGER(IntKi), PARAMETER :: M8N9TAye = 1611 - INTEGER(IntKi), PARAMETER :: M9N1TAye = 1612 - INTEGER(IntKi), PARAMETER :: M9N2TAye = 1613 - INTEGER(IntKi), PARAMETER :: M9N3TAye = 1614 - INTEGER(IntKi), PARAMETER :: M9N4TAye = 1615 - INTEGER(IntKi), PARAMETER :: M9N5TAye = 1616 - INTEGER(IntKi), PARAMETER :: M9N6TAye = 1617 - INTEGER(IntKi), PARAMETER :: M9N7TAye = 1618 - INTEGER(IntKi), PARAMETER :: M9N8TAye = 1619 - INTEGER(IntKi), PARAMETER :: M9N9TAye = 1620 - INTEGER(IntKi), PARAMETER :: M1N1TAze = 1621 - INTEGER(IntKi), PARAMETER :: M1N2TAze = 1622 - INTEGER(IntKi), PARAMETER :: M1N3TAze = 1623 - INTEGER(IntKi), PARAMETER :: M1N4TAze = 1624 - INTEGER(IntKi), PARAMETER :: M1N5TAze = 1625 - INTEGER(IntKi), PARAMETER :: M1N6TAze = 1626 - INTEGER(IntKi), PARAMETER :: M1N7TAze = 1627 - INTEGER(IntKi), PARAMETER :: M1N8TAze = 1628 - INTEGER(IntKi), PARAMETER :: M1N9TAze = 1629 - INTEGER(IntKi), PARAMETER :: M2N1TAze = 1630 - INTEGER(IntKi), PARAMETER :: M2N2TAze = 1631 - INTEGER(IntKi), PARAMETER :: M2N3TAze = 1632 - INTEGER(IntKi), PARAMETER :: M2N4TAze = 1633 - INTEGER(IntKi), PARAMETER :: M2N5TAze = 1634 - INTEGER(IntKi), PARAMETER :: M2N6TAze = 1635 - INTEGER(IntKi), PARAMETER :: M2N7TAze = 1636 - INTEGER(IntKi), PARAMETER :: M2N8TAze = 1637 - INTEGER(IntKi), PARAMETER :: M2N9TAze = 1638 - INTEGER(IntKi), PARAMETER :: M3N1TAze = 1639 - INTEGER(IntKi), PARAMETER :: M3N2TAze = 1640 - INTEGER(IntKi), PARAMETER :: M3N3TAze = 1641 - INTEGER(IntKi), PARAMETER :: M3N4TAze = 1642 - INTEGER(IntKi), PARAMETER :: M3N5TAze = 1643 - INTEGER(IntKi), PARAMETER :: M3N6TAze = 1644 - INTEGER(IntKi), PARAMETER :: M3N7TAze = 1645 - INTEGER(IntKi), PARAMETER :: M3N8TAze = 1646 - INTEGER(IntKi), PARAMETER :: M3N9TAze = 1647 - INTEGER(IntKi), PARAMETER :: M4N1TAze = 1648 - INTEGER(IntKi), PARAMETER :: M4N2TAze = 1649 - INTEGER(IntKi), PARAMETER :: M4N3TAze = 1650 - INTEGER(IntKi), PARAMETER :: M4N4TAze = 1651 - INTEGER(IntKi), PARAMETER :: M4N5TAze = 1652 - INTEGER(IntKi), PARAMETER :: M4N6TAze = 1653 - INTEGER(IntKi), PARAMETER :: M4N7TAze = 1654 - INTEGER(IntKi), PARAMETER :: M4N8TAze = 1655 - INTEGER(IntKi), PARAMETER :: M4N9TAze = 1656 - INTEGER(IntKi), PARAMETER :: M5N1TAze = 1657 - INTEGER(IntKi), PARAMETER :: M5N2TAze = 1658 - INTEGER(IntKi), PARAMETER :: M5N3TAze = 1659 - INTEGER(IntKi), PARAMETER :: M5N4TAze = 1660 - INTEGER(IntKi), PARAMETER :: M5N5TAze = 1661 - INTEGER(IntKi), PARAMETER :: M5N6TAze = 1662 - INTEGER(IntKi), PARAMETER :: M5N7TAze = 1663 - INTEGER(IntKi), PARAMETER :: M5N8TAze = 1664 - INTEGER(IntKi), PARAMETER :: M5N9TAze = 1665 - INTEGER(IntKi), PARAMETER :: M6N1TAze = 1666 - INTEGER(IntKi), PARAMETER :: M6N2TAze = 1667 - INTEGER(IntKi), PARAMETER :: M6N3TAze = 1668 - INTEGER(IntKi), PARAMETER :: M6N4TAze = 1669 - INTEGER(IntKi), PARAMETER :: M6N5TAze = 1670 - INTEGER(IntKi), PARAMETER :: M6N6TAze = 1671 - INTEGER(IntKi), PARAMETER :: M6N7TAze = 1672 - INTEGER(IntKi), PARAMETER :: M6N8TAze = 1673 - INTEGER(IntKi), PARAMETER :: M6N9TAze = 1674 - INTEGER(IntKi), PARAMETER :: M7N1TAze = 1675 - INTEGER(IntKi), PARAMETER :: M7N2TAze = 1676 - INTEGER(IntKi), PARAMETER :: M7N3TAze = 1677 - INTEGER(IntKi), PARAMETER :: M7N4TAze = 1678 - INTEGER(IntKi), PARAMETER :: M7N5TAze = 1679 - INTEGER(IntKi), PARAMETER :: M7N6TAze = 1680 - INTEGER(IntKi), PARAMETER :: M7N7TAze = 1681 - INTEGER(IntKi), PARAMETER :: M7N8TAze = 1682 - INTEGER(IntKi), PARAMETER :: M7N9TAze = 1683 - INTEGER(IntKi), PARAMETER :: M8N1TAze = 1684 - INTEGER(IntKi), PARAMETER :: M8N2TAze = 1685 - INTEGER(IntKi), PARAMETER :: M8N3TAze = 1686 - INTEGER(IntKi), PARAMETER :: M8N4TAze = 1687 - INTEGER(IntKi), PARAMETER :: M8N5TAze = 1688 - INTEGER(IntKi), PARAMETER :: M8N6TAze = 1689 - INTEGER(IntKi), PARAMETER :: M8N7TAze = 1690 - INTEGER(IntKi), PARAMETER :: M8N8TAze = 1691 - INTEGER(IntKi), PARAMETER :: M8N9TAze = 1692 - INTEGER(IntKi), PARAMETER :: M9N1TAze = 1693 - INTEGER(IntKi), PARAMETER :: M9N2TAze = 1694 - INTEGER(IntKi), PARAMETER :: M9N3TAze = 1695 - INTEGER(IntKi), PARAMETER :: M9N4TAze = 1696 - INTEGER(IntKi), PARAMETER :: M9N5TAze = 1697 - INTEGER(IntKi), PARAMETER :: M9N6TAze = 1698 - INTEGER(IntKi), PARAMETER :: M9N7TAze = 1699 - INTEGER(IntKi), PARAMETER :: M9N8TAze = 1700 - INTEGER(IntKi), PARAMETER :: M9N9TAze = 1701 - INTEGER(IntKi), PARAMETER :: M1N1RAxe = 1702 - INTEGER(IntKi), PARAMETER :: M1N2RAxe = 1703 - INTEGER(IntKi), PARAMETER :: M1N3RAxe = 1704 - INTEGER(IntKi), PARAMETER :: M1N4RAxe = 1705 - INTEGER(IntKi), PARAMETER :: M1N5RAxe = 1706 - INTEGER(IntKi), PARAMETER :: M1N6RAxe = 1707 - INTEGER(IntKi), PARAMETER :: M1N7RAxe = 1708 - INTEGER(IntKi), PARAMETER :: M1N8RAxe = 1709 - INTEGER(IntKi), PARAMETER :: M1N9RAxe = 1710 - INTEGER(IntKi), PARAMETER :: M2N1RAxe = 1711 - INTEGER(IntKi), PARAMETER :: M2N2RAxe = 1712 - INTEGER(IntKi), PARAMETER :: M2N3RAxe = 1713 - INTEGER(IntKi), PARAMETER :: M2N4RAxe = 1714 - INTEGER(IntKi), PARAMETER :: M2N5RAxe = 1715 - INTEGER(IntKi), PARAMETER :: M2N6RAxe = 1716 - INTEGER(IntKi), PARAMETER :: M2N7RAxe = 1717 - INTEGER(IntKi), PARAMETER :: M2N8RAxe = 1718 - INTEGER(IntKi), PARAMETER :: M2N9RAxe = 1719 - INTEGER(IntKi), PARAMETER :: M3N1RAxe = 1720 - INTEGER(IntKi), PARAMETER :: M3N2RAxe = 1721 - INTEGER(IntKi), PARAMETER :: M3N3RAxe = 1722 - INTEGER(IntKi), PARAMETER :: M3N4RAxe = 1723 - INTEGER(IntKi), PARAMETER :: M3N5RAxe = 1724 - INTEGER(IntKi), PARAMETER :: M3N6RAxe = 1725 - INTEGER(IntKi), PARAMETER :: M3N7RAxe = 1726 - INTEGER(IntKi), PARAMETER :: M3N8RAxe = 1727 - INTEGER(IntKi), PARAMETER :: M3N9RAxe = 1728 - INTEGER(IntKi), PARAMETER :: M4N1RAxe = 1729 - INTEGER(IntKi), PARAMETER :: M4N2RAxe = 1730 - INTEGER(IntKi), PARAMETER :: M4N3RAxe = 1731 - INTEGER(IntKi), PARAMETER :: M4N4RAxe = 1732 - INTEGER(IntKi), PARAMETER :: M4N5RAxe = 1733 - INTEGER(IntKi), PARAMETER :: M4N6RAxe = 1734 - INTEGER(IntKi), PARAMETER :: M4N7RAxe = 1735 - INTEGER(IntKi), PARAMETER :: M4N8RAxe = 1736 - INTEGER(IntKi), PARAMETER :: M4N9RAxe = 1737 - INTEGER(IntKi), PARAMETER :: M5N1RAxe = 1738 - INTEGER(IntKi), PARAMETER :: M5N2RAxe = 1739 - INTEGER(IntKi), PARAMETER :: M5N3RAxe = 1740 - INTEGER(IntKi), PARAMETER :: M5N4RAxe = 1741 - INTEGER(IntKi), PARAMETER :: M5N5RAxe = 1742 - INTEGER(IntKi), PARAMETER :: M5N6RAxe = 1743 - INTEGER(IntKi), PARAMETER :: M5N7RAxe = 1744 - INTEGER(IntKi), PARAMETER :: M5N8RAxe = 1745 - INTEGER(IntKi), PARAMETER :: M5N9RAxe = 1746 - INTEGER(IntKi), PARAMETER :: M6N1RAxe = 1747 - INTEGER(IntKi), PARAMETER :: M6N2RAxe = 1748 - INTEGER(IntKi), PARAMETER :: M6N3RAxe = 1749 - INTEGER(IntKi), PARAMETER :: M6N4RAxe = 1750 - INTEGER(IntKi), PARAMETER :: M6N5RAxe = 1751 - INTEGER(IntKi), PARAMETER :: M6N6RAxe = 1752 - INTEGER(IntKi), PARAMETER :: M6N7RAxe = 1753 - INTEGER(IntKi), PARAMETER :: M6N8RAxe = 1754 - INTEGER(IntKi), PARAMETER :: M6N9RAxe = 1755 - INTEGER(IntKi), PARAMETER :: M7N1RAxe = 1756 - INTEGER(IntKi), PARAMETER :: M7N2RAxe = 1757 - INTEGER(IntKi), PARAMETER :: M7N3RAxe = 1758 - INTEGER(IntKi), PARAMETER :: M7N4RAxe = 1759 - INTEGER(IntKi), PARAMETER :: M7N5RAxe = 1760 - INTEGER(IntKi), PARAMETER :: M7N6RAxe = 1761 - INTEGER(IntKi), PARAMETER :: M7N7RAxe = 1762 - INTEGER(IntKi), PARAMETER :: M7N8RAxe = 1763 - INTEGER(IntKi), PARAMETER :: M7N9RAxe = 1764 - INTEGER(IntKi), PARAMETER :: M8N1RAxe = 1765 - INTEGER(IntKi), PARAMETER :: M8N2RAxe = 1766 - INTEGER(IntKi), PARAMETER :: M8N3RAxe = 1767 - INTEGER(IntKi), PARAMETER :: M8N4RAxe = 1768 - INTEGER(IntKi), PARAMETER :: M8N5RAxe = 1769 - INTEGER(IntKi), PARAMETER :: M8N6RAxe = 1770 - INTEGER(IntKi), PARAMETER :: M8N7RAxe = 1771 - INTEGER(IntKi), PARAMETER :: M8N8RAxe = 1772 - INTEGER(IntKi), PARAMETER :: M8N9RAxe = 1773 - INTEGER(IntKi), PARAMETER :: M9N1RAxe = 1774 - INTEGER(IntKi), PARAMETER :: M9N2RAxe = 1775 - INTEGER(IntKi), PARAMETER :: M9N3RAxe = 1776 - INTEGER(IntKi), PARAMETER :: M9N4RAxe = 1777 - INTEGER(IntKi), PARAMETER :: M9N5RAxe = 1778 - INTEGER(IntKi), PARAMETER :: M9N6RAxe = 1779 - INTEGER(IntKi), PARAMETER :: M9N7RAxe = 1780 - INTEGER(IntKi), PARAMETER :: M9N8RAxe = 1781 - INTEGER(IntKi), PARAMETER :: M9N9RAxe = 1782 - INTEGER(IntKi), PARAMETER :: M1N1RAye = 1783 - INTEGER(IntKi), PARAMETER :: M1N2RAye = 1784 - INTEGER(IntKi), PARAMETER :: M1N3RAye = 1785 - INTEGER(IntKi), PARAMETER :: M1N4RAye = 1786 - INTEGER(IntKi), PARAMETER :: M1N5RAye = 1787 - INTEGER(IntKi), PARAMETER :: M1N6RAye = 1788 - INTEGER(IntKi), PARAMETER :: M1N7RAye = 1789 - INTEGER(IntKi), PARAMETER :: M1N8RAye = 1790 - INTEGER(IntKi), PARAMETER :: M1N9RAye = 1791 - INTEGER(IntKi), PARAMETER :: M2N1RAye = 1792 - INTEGER(IntKi), PARAMETER :: M2N2RAye = 1793 - INTEGER(IntKi), PARAMETER :: M2N3RAye = 1794 - INTEGER(IntKi), PARAMETER :: M2N4RAye = 1795 - INTEGER(IntKi), PARAMETER :: M2N5RAye = 1796 - INTEGER(IntKi), PARAMETER :: M2N6RAye = 1797 - INTEGER(IntKi), PARAMETER :: M2N7RAye = 1798 - INTEGER(IntKi), PARAMETER :: M2N8RAye = 1799 - INTEGER(IntKi), PARAMETER :: M2N9RAye = 1800 - INTEGER(IntKi), PARAMETER :: M3N1RAye = 1801 - INTEGER(IntKi), PARAMETER :: M3N2RAye = 1802 - INTEGER(IntKi), PARAMETER :: M3N3RAye = 1803 - INTEGER(IntKi), PARAMETER :: M3N4RAye = 1804 - INTEGER(IntKi), PARAMETER :: M3N5RAye = 1805 - INTEGER(IntKi), PARAMETER :: M3N6RAye = 1806 - INTEGER(IntKi), PARAMETER :: M3N7RAye = 1807 - INTEGER(IntKi), PARAMETER :: M3N8RAye = 1808 - INTEGER(IntKi), PARAMETER :: M3N9RAye = 1809 - INTEGER(IntKi), PARAMETER :: M4N1RAye = 1810 - INTEGER(IntKi), PARAMETER :: M4N2RAye = 1811 - INTEGER(IntKi), PARAMETER :: M4N3RAye = 1812 - INTEGER(IntKi), PARAMETER :: M4N4RAye = 1813 - INTEGER(IntKi), PARAMETER :: M4N5RAye = 1814 - INTEGER(IntKi), PARAMETER :: M4N6RAye = 1815 - INTEGER(IntKi), PARAMETER :: M4N7RAye = 1816 - INTEGER(IntKi), PARAMETER :: M4N8RAye = 1817 - INTEGER(IntKi), PARAMETER :: M4N9RAye = 1818 - INTEGER(IntKi), PARAMETER :: M5N1RAye = 1819 - INTEGER(IntKi), PARAMETER :: M5N2RAye = 1820 - INTEGER(IntKi), PARAMETER :: M5N3RAye = 1821 - INTEGER(IntKi), PARAMETER :: M5N4RAye = 1822 - INTEGER(IntKi), PARAMETER :: M5N5RAye = 1823 - INTEGER(IntKi), PARAMETER :: M5N6RAye = 1824 - INTEGER(IntKi), PARAMETER :: M5N7RAye = 1825 - INTEGER(IntKi), PARAMETER :: M5N8RAye = 1826 - INTEGER(IntKi), PARAMETER :: M5N9RAye = 1827 - INTEGER(IntKi), PARAMETER :: M6N1RAye = 1828 - INTEGER(IntKi), PARAMETER :: M6N2RAye = 1829 - INTEGER(IntKi), PARAMETER :: M6N3RAye = 1830 - INTEGER(IntKi), PARAMETER :: M6N4RAye = 1831 - INTEGER(IntKi), PARAMETER :: M6N5RAye = 1832 - INTEGER(IntKi), PARAMETER :: M6N6RAye = 1833 - INTEGER(IntKi), PARAMETER :: M6N7RAye = 1834 - INTEGER(IntKi), PARAMETER :: M6N8RAye = 1835 - INTEGER(IntKi), PARAMETER :: M6N9RAye = 1836 - INTEGER(IntKi), PARAMETER :: M7N1RAye = 1837 - INTEGER(IntKi), PARAMETER :: M7N2RAye = 1838 - INTEGER(IntKi), PARAMETER :: M7N3RAye = 1839 - INTEGER(IntKi), PARAMETER :: M7N4RAye = 1840 - INTEGER(IntKi), PARAMETER :: M7N5RAye = 1841 - INTEGER(IntKi), PARAMETER :: M7N6RAye = 1842 - INTEGER(IntKi), PARAMETER :: M7N7RAye = 1843 - INTEGER(IntKi), PARAMETER :: M7N8RAye = 1844 - INTEGER(IntKi), PARAMETER :: M7N9RAye = 1845 - INTEGER(IntKi), PARAMETER :: M8N1RAye = 1846 - INTEGER(IntKi), PARAMETER :: M8N2RAye = 1847 - INTEGER(IntKi), PARAMETER :: M8N3RAye = 1848 - INTEGER(IntKi), PARAMETER :: M8N4RAye = 1849 - INTEGER(IntKi), PARAMETER :: M8N5RAye = 1850 - INTEGER(IntKi), PARAMETER :: M8N6RAye = 1851 - INTEGER(IntKi), PARAMETER :: M8N7RAye = 1852 - INTEGER(IntKi), PARAMETER :: M8N8RAye = 1853 - INTEGER(IntKi), PARAMETER :: M8N9RAye = 1854 - INTEGER(IntKi), PARAMETER :: M9N1RAye = 1855 - INTEGER(IntKi), PARAMETER :: M9N2RAye = 1856 - INTEGER(IntKi), PARAMETER :: M9N3RAye = 1857 - INTEGER(IntKi), PARAMETER :: M9N4RAye = 1858 - INTEGER(IntKi), PARAMETER :: M9N5RAye = 1859 - INTEGER(IntKi), PARAMETER :: M9N6RAye = 1860 - INTEGER(IntKi), PARAMETER :: M9N7RAye = 1861 - INTEGER(IntKi), PARAMETER :: M9N8RAye = 1862 - INTEGER(IntKi), PARAMETER :: M9N9RAye = 1863 - INTEGER(IntKi), PARAMETER :: M1N1RAze = 1864 - INTEGER(IntKi), PARAMETER :: M1N2RAze = 1865 - INTEGER(IntKi), PARAMETER :: M1N3RAze = 1866 - INTEGER(IntKi), PARAMETER :: M1N4RAze = 1867 - INTEGER(IntKi), PARAMETER :: M1N5RAze = 1868 - INTEGER(IntKi), PARAMETER :: M1N6RAze = 1869 - INTEGER(IntKi), PARAMETER :: M1N7RAze = 1870 - INTEGER(IntKi), PARAMETER :: M1N8RAze = 1871 - INTEGER(IntKi), PARAMETER :: M1N9RAze = 1872 - INTEGER(IntKi), PARAMETER :: M2N1RAze = 1873 - INTEGER(IntKi), PARAMETER :: M2N2RAze = 1874 - INTEGER(IntKi), PARAMETER :: M2N3RAze = 1875 - INTEGER(IntKi), PARAMETER :: M2N4RAze = 1876 - INTEGER(IntKi), PARAMETER :: M2N5RAze = 1877 - INTEGER(IntKi), PARAMETER :: M2N6RAze = 1878 - INTEGER(IntKi), PARAMETER :: M2N7RAze = 1879 - INTEGER(IntKi), PARAMETER :: M2N8RAze = 1880 - INTEGER(IntKi), PARAMETER :: M2N9RAze = 1881 - INTEGER(IntKi), PARAMETER :: M3N1RAze = 1882 - INTEGER(IntKi), PARAMETER :: M3N2RAze = 1883 - INTEGER(IntKi), PARAMETER :: M3N3RAze = 1884 - INTEGER(IntKi), PARAMETER :: M3N4RAze = 1885 - INTEGER(IntKi), PARAMETER :: M3N5RAze = 1886 - INTEGER(IntKi), PARAMETER :: M3N6RAze = 1887 - INTEGER(IntKi), PARAMETER :: M3N7RAze = 1888 - INTEGER(IntKi), PARAMETER :: M3N8RAze = 1889 - INTEGER(IntKi), PARAMETER :: M3N9RAze = 1890 - INTEGER(IntKi), PARAMETER :: M4N1RAze = 1891 - INTEGER(IntKi), PARAMETER :: M4N2RAze = 1892 - INTEGER(IntKi), PARAMETER :: M4N3RAze = 1893 - INTEGER(IntKi), PARAMETER :: M4N4RAze = 1894 - INTEGER(IntKi), PARAMETER :: M4N5RAze = 1895 - INTEGER(IntKi), PARAMETER :: M4N6RAze = 1896 - INTEGER(IntKi), PARAMETER :: M4N7RAze = 1897 - INTEGER(IntKi), PARAMETER :: M4N8RAze = 1898 - INTEGER(IntKi), PARAMETER :: M4N9RAze = 1899 - INTEGER(IntKi), PARAMETER :: M5N1RAze = 1900 - INTEGER(IntKi), PARAMETER :: M5N2RAze = 1901 - INTEGER(IntKi), PARAMETER :: M5N3RAze = 1902 - INTEGER(IntKi), PARAMETER :: M5N4RAze = 1903 - INTEGER(IntKi), PARAMETER :: M5N5RAze = 1904 - INTEGER(IntKi), PARAMETER :: M5N6RAze = 1905 - INTEGER(IntKi), PARAMETER :: M5N7RAze = 1906 - INTEGER(IntKi), PARAMETER :: M5N8RAze = 1907 - INTEGER(IntKi), PARAMETER :: M5N9RAze = 1908 - INTEGER(IntKi), PARAMETER :: M6N1RAze = 1909 - INTEGER(IntKi), PARAMETER :: M6N2RAze = 1910 - INTEGER(IntKi), PARAMETER :: M6N3RAze = 1911 - INTEGER(IntKi), PARAMETER :: M6N4RAze = 1912 - INTEGER(IntKi), PARAMETER :: M6N5RAze = 1913 - INTEGER(IntKi), PARAMETER :: M6N6RAze = 1914 - INTEGER(IntKi), PARAMETER :: M6N7RAze = 1915 - INTEGER(IntKi), PARAMETER :: M6N8RAze = 1916 - INTEGER(IntKi), PARAMETER :: M6N9RAze = 1917 - INTEGER(IntKi), PARAMETER :: M7N1RAze = 1918 - INTEGER(IntKi), PARAMETER :: M7N2RAze = 1919 - INTEGER(IntKi), PARAMETER :: M7N3RAze = 1920 - INTEGER(IntKi), PARAMETER :: M7N4RAze = 1921 - INTEGER(IntKi), PARAMETER :: M7N5RAze = 1922 - INTEGER(IntKi), PARAMETER :: M7N6RAze = 1923 - INTEGER(IntKi), PARAMETER :: M7N7RAze = 1924 - INTEGER(IntKi), PARAMETER :: M7N8RAze = 1925 - INTEGER(IntKi), PARAMETER :: M7N9RAze = 1926 - INTEGER(IntKi), PARAMETER :: M8N1RAze = 1927 - INTEGER(IntKi), PARAMETER :: M8N2RAze = 1928 - INTEGER(IntKi), PARAMETER :: M8N3RAze = 1929 - INTEGER(IntKi), PARAMETER :: M8N4RAze = 1930 - INTEGER(IntKi), PARAMETER :: M8N5RAze = 1931 - INTEGER(IntKi), PARAMETER :: M8N6RAze = 1932 - INTEGER(IntKi), PARAMETER :: M8N7RAze = 1933 - INTEGER(IntKi), PARAMETER :: M8N8RAze = 1934 - INTEGER(IntKi), PARAMETER :: M8N9RAze = 1935 - INTEGER(IntKi), PARAMETER :: M9N1RAze = 1936 - INTEGER(IntKi), PARAMETER :: M9N2RAze = 1937 - INTEGER(IntKi), PARAMETER :: M9N3RAze = 1938 - INTEGER(IntKi), PARAMETER :: M9N4RAze = 1939 - INTEGER(IntKi), PARAMETER :: M9N5RAze = 1940 - INTEGER(IntKi), PARAMETER :: M9N6RAze = 1941 - INTEGER(IntKi), PARAMETER :: M9N7RAze = 1942 - INTEGER(IntKi), PARAMETER :: M9N8RAze = 1943 - INTEGER(IntKi), PARAMETER :: M9N9RAze = 1944 - - - ! Reactions: - - INTEGER(IntKi), PARAMETER :: ReactFXss = 1945 - INTEGER(IntKi), PARAMETER :: ReactFYss = 1946 - INTEGER(IntKi), PARAMETER :: ReactFZss = 1947 - INTEGER(IntKi), PARAMETER :: ReactMXss = 1948 - INTEGER(IntKi), PARAMETER :: ReactMYss = 1949 - INTEGER(IntKi), PARAMETER :: ReactMZss = 1950 - INTEGER(IntKi), PARAMETER :: IntfFXss = 1951 - INTEGER(IntKi), PARAMETER :: IntfFYss = 1952 - INTEGER(IntKi), PARAMETER :: IntfFZss = 1953 - INTEGER(IntKi), PARAMETER :: IntfMXss = 1954 - INTEGER(IntKi), PARAMETER :: IntfMYss = 1955 - INTEGER(IntKi), PARAMETER :: IntfMZss = 1956 - - - ! Interface Deflections: - - INTEGER(IntKi), PARAMETER :: IntfTDXss = 1957 - INTEGER(IntKi), PARAMETER :: IntfTDYss = 1958 - INTEGER(IntKi), PARAMETER :: IntfTDZss = 1959 - INTEGER(IntKi), PARAMETER :: IntfRDXss = 1960 - INTEGER(IntKi), PARAMETER :: IntfRDYss = 1961 - INTEGER(IntKi), PARAMETER :: IntfRDZss = 1962 - - - ! Interface Accelerations: - - INTEGER(IntKi), PARAMETER :: IntfTAXss = 1963 - INTEGER(IntKi), PARAMETER :: IntfTAYss = 1964 - INTEGER(IntKi), PARAMETER :: IntfTAZss = 1965 - INTEGER(IntKi), PARAMETER :: IntfRAXss = 1966 - INTEGER(IntKi), PARAMETER :: IntfRAYss = 1967 - INTEGER(IntKi), PARAMETER :: IntfRAZss = 1968 - - - ! Modal Parameters: - - INTEGER(IntKi), PARAMETER :: SSqm01 = 1969 - INTEGER(IntKi), PARAMETER :: SSqm02 = 1970 - INTEGER(IntKi), PARAMETER :: SSqm03 = 1971 - INTEGER(IntKi), PARAMETER :: SSqm04 = 1972 - INTEGER(IntKi), PARAMETER :: SSqm05 = 1973 - INTEGER(IntKi), PARAMETER :: SSqm06 = 1974 - INTEGER(IntKi), PARAMETER :: SSqm07 = 1975 - INTEGER(IntKi), PARAMETER :: SSqm08 = 1976 - INTEGER(IntKi), PARAMETER :: SSqm09 = 1977 - INTEGER(IntKi), PARAMETER :: SSqm10 = 1978 - INTEGER(IntKi), PARAMETER :: SSqm11 = 1979 - INTEGER(IntKi), PARAMETER :: SSqm12 = 1980 - INTEGER(IntKi), PARAMETER :: SSqm13 = 1981 - INTEGER(IntKi), PARAMETER :: SSqm14 = 1982 - INTEGER(IntKi), PARAMETER :: SSqm15 = 1983 - INTEGER(IntKi), PARAMETER :: SSqm16 = 1984 - INTEGER(IntKi), PARAMETER :: SSqm17 = 1985 - INTEGER(IntKi), PARAMETER :: SSqm18 = 1986 - INTEGER(IntKi), PARAMETER :: SSqm19 = 1987 - INTEGER(IntKi), PARAMETER :: SSqm20 = 1988 - INTEGER(IntKi), PARAMETER :: SSqm21 = 1989 - INTEGER(IntKi), PARAMETER :: SSqm22 = 1990 - INTEGER(IntKi), PARAMETER :: SSqm23 = 1991 - INTEGER(IntKi), PARAMETER :: SSqm24 = 1992 - INTEGER(IntKi), PARAMETER :: SSqm25 = 1993 - INTEGER(IntKi), PARAMETER :: SSqm26 = 1994 - INTEGER(IntKi), PARAMETER :: SSqm27 = 1995 - INTEGER(IntKi), PARAMETER :: SSqm28 = 1996 - INTEGER(IntKi), PARAMETER :: SSqm29 = 1997 - INTEGER(IntKi), PARAMETER :: SSqm30 = 1998 - INTEGER(IntKi), PARAMETER :: SSqm31 = 1999 - INTEGER(IntKi), PARAMETER :: SSqm32 = 2000 - INTEGER(IntKi), PARAMETER :: SSqm33 = 2001 - INTEGER(IntKi), PARAMETER :: SSqm34 = 2002 - INTEGER(IntKi), PARAMETER :: SSqm35 = 2003 - INTEGER(IntKi), PARAMETER :: SSqm36 = 2004 - INTEGER(IntKi), PARAMETER :: SSqm37 = 2005 - INTEGER(IntKi), PARAMETER :: SSqm38 = 2006 - INTEGER(IntKi), PARAMETER :: SSqm39 = 2007 - INTEGER(IntKi), PARAMETER :: SSqm40 = 2008 - INTEGER(IntKi), PARAMETER :: SSqm41 = 2009 - INTEGER(IntKi), PARAMETER :: SSqm42 = 2010 - INTEGER(IntKi), PARAMETER :: SSqm43 = 2011 - INTEGER(IntKi), PARAMETER :: SSqm44 = 2012 - INTEGER(IntKi), PARAMETER :: SSqm45 = 2013 - INTEGER(IntKi), PARAMETER :: SSqm46 = 2014 - INTEGER(IntKi), PARAMETER :: SSqm47 = 2015 - INTEGER(IntKi), PARAMETER :: SSqm48 = 2016 - INTEGER(IntKi), PARAMETER :: SSqm49 = 2017 - INTEGER(IntKi), PARAMETER :: SSqm50 = 2018 - INTEGER(IntKi), PARAMETER :: SSqm51 = 2019 - INTEGER(IntKi), PARAMETER :: SSqm52 = 2020 - INTEGER(IntKi), PARAMETER :: SSqm53 = 2021 - INTEGER(IntKi), PARAMETER :: SSqm54 = 2022 - INTEGER(IntKi), PARAMETER :: SSqm55 = 2023 - INTEGER(IntKi), PARAMETER :: SSqm56 = 2024 - INTEGER(IntKi), PARAMETER :: SSqm57 = 2025 - INTEGER(IntKi), PARAMETER :: SSqm58 = 2026 - INTEGER(IntKi), PARAMETER :: SSqm59 = 2027 - INTEGER(IntKi), PARAMETER :: SSqm60 = 2028 - INTEGER(IntKi), PARAMETER :: SSqm61 = 2029 - INTEGER(IntKi), PARAMETER :: SSqm62 = 2030 - INTEGER(IntKi), PARAMETER :: SSqm63 = 2031 - INTEGER(IntKi), PARAMETER :: SSqm64 = 2032 - INTEGER(IntKi), PARAMETER :: SSqm65 = 2033 - INTEGER(IntKi), PARAMETER :: SSqm66 = 2034 - INTEGER(IntKi), PARAMETER :: SSqm67 = 2035 - INTEGER(IntKi), PARAMETER :: SSqm68 = 2036 - INTEGER(IntKi), PARAMETER :: SSqm69 = 2037 - INTEGER(IntKi), PARAMETER :: SSqm70 = 2038 - INTEGER(IntKi), PARAMETER :: SSqm71 = 2039 - INTEGER(IntKi), PARAMETER :: SSqm72 = 2040 - INTEGER(IntKi), PARAMETER :: SSqm73 = 2041 - INTEGER(IntKi), PARAMETER :: SSqm74 = 2042 - INTEGER(IntKi), PARAMETER :: SSqm75 = 2043 - INTEGER(IntKi), PARAMETER :: SSqm76 = 2044 - INTEGER(IntKi), PARAMETER :: SSqm77 = 2045 - INTEGER(IntKi), PARAMETER :: SSqm78 = 2046 - INTEGER(IntKi), PARAMETER :: SSqm79 = 2047 - INTEGER(IntKi), PARAMETER :: SSqm80 = 2048 - INTEGER(IntKi), PARAMETER :: SSqm81 = 2049 - INTEGER(IntKi), PARAMETER :: SSqm82 = 2050 - INTEGER(IntKi), PARAMETER :: SSqm83 = 2051 - INTEGER(IntKi), PARAMETER :: SSqm84 = 2052 - INTEGER(IntKi), PARAMETER :: SSqm85 = 2053 - INTEGER(IntKi), PARAMETER :: SSqm86 = 2054 - INTEGER(IntKi), PARAMETER :: SSqm87 = 2055 - INTEGER(IntKi), PARAMETER :: SSqm88 = 2056 - INTEGER(IntKi), PARAMETER :: SSqm89 = 2057 - INTEGER(IntKi), PARAMETER :: SSqm90 = 2058 - INTEGER(IntKi), PARAMETER :: SSqm91 = 2059 - INTEGER(IntKi), PARAMETER :: SSqm92 = 2060 - INTEGER(IntKi), PARAMETER :: SSqm93 = 2061 - INTEGER(IntKi), PARAMETER :: SSqm94 = 2062 - INTEGER(IntKi), PARAMETER :: SSqm95 = 2063 - INTEGER(IntKi), PARAMETER :: SSqm96 = 2064 - INTEGER(IntKi), PARAMETER :: SSqm97 = 2065 - INTEGER(IntKi), PARAMETER :: SSqm98 = 2066 - INTEGER(IntKi), PARAMETER :: SSqm99 = 2067 - INTEGER(IntKi), PARAMETER :: SSqmd01 = 2068 - INTEGER(IntKi), PARAMETER :: SSqmd02 = 2069 - INTEGER(IntKi), PARAMETER :: SSqmd03 = 2070 - INTEGER(IntKi), PARAMETER :: SSqmd04 = 2071 - INTEGER(IntKi), PARAMETER :: SSqmd05 = 2072 - INTEGER(IntKi), PARAMETER :: SSqmd06 = 2073 - INTEGER(IntKi), PARAMETER :: SSqmd07 = 2074 - INTEGER(IntKi), PARAMETER :: SSqmd08 = 2075 - INTEGER(IntKi), PARAMETER :: SSqmd09 = 2076 - INTEGER(IntKi), PARAMETER :: SSqmd10 = 2077 - INTEGER(IntKi), PARAMETER :: SSqmd11 = 2078 - INTEGER(IntKi), PARAMETER :: SSqmd12 = 2079 - INTEGER(IntKi), PARAMETER :: SSqmd13 = 2080 - INTEGER(IntKi), PARAMETER :: SSqmd14 = 2081 - INTEGER(IntKi), PARAMETER :: SSqmd15 = 2082 - INTEGER(IntKi), PARAMETER :: SSqmd16 = 2083 - INTEGER(IntKi), PARAMETER :: SSqmd17 = 2084 - INTEGER(IntKi), PARAMETER :: SSqmd18 = 2085 - INTEGER(IntKi), PARAMETER :: SSqmd19 = 2086 - INTEGER(IntKi), PARAMETER :: SSqmd20 = 2087 - INTEGER(IntKi), PARAMETER :: SSqmd21 = 2088 - INTEGER(IntKi), PARAMETER :: SSqmd22 = 2089 - INTEGER(IntKi), PARAMETER :: SSqmd23 = 2090 - INTEGER(IntKi), PARAMETER :: SSqmd24 = 2091 - INTEGER(IntKi), PARAMETER :: SSqmd25 = 2092 - INTEGER(IntKi), PARAMETER :: SSqmd26 = 2093 - INTEGER(IntKi), PARAMETER :: SSqmd27 = 2094 - INTEGER(IntKi), PARAMETER :: SSqmd28 = 2095 - INTEGER(IntKi), PARAMETER :: SSqmd29 = 2096 - INTEGER(IntKi), PARAMETER :: SSqmd30 = 2097 - INTEGER(IntKi), PARAMETER :: SSqmd31 = 2098 - INTEGER(IntKi), PARAMETER :: SSqmd32 = 2099 - INTEGER(IntKi), PARAMETER :: SSqmd33 = 2100 - INTEGER(IntKi), PARAMETER :: SSqmd34 = 2101 - INTEGER(IntKi), PARAMETER :: SSqmd35 = 2102 - INTEGER(IntKi), PARAMETER :: SSqmd36 = 2103 - INTEGER(IntKi), PARAMETER :: SSqmd37 = 2104 - INTEGER(IntKi), PARAMETER :: SSqmd38 = 2105 - INTEGER(IntKi), PARAMETER :: SSqmd39 = 2106 - INTEGER(IntKi), PARAMETER :: SSqmd40 = 2107 - INTEGER(IntKi), PARAMETER :: SSqmd41 = 2108 - INTEGER(IntKi), PARAMETER :: SSqmd42 = 2109 - INTEGER(IntKi), PARAMETER :: SSqmd43 = 2110 - INTEGER(IntKi), PARAMETER :: SSqmd44 = 2111 - INTEGER(IntKi), PARAMETER :: SSqmd45 = 2112 - INTEGER(IntKi), PARAMETER :: SSqmd46 = 2113 - INTEGER(IntKi), PARAMETER :: SSqmd47 = 2114 - INTEGER(IntKi), PARAMETER :: SSqmd48 = 2115 - INTEGER(IntKi), PARAMETER :: SSqmd49 = 2116 - INTEGER(IntKi), PARAMETER :: SSqmd50 = 2117 - INTEGER(IntKi), PARAMETER :: SSqmd51 = 2118 - INTEGER(IntKi), PARAMETER :: SSqmd52 = 2119 - INTEGER(IntKi), PARAMETER :: SSqmd53 = 2120 - INTEGER(IntKi), PARAMETER :: SSqmd54 = 2121 - INTEGER(IntKi), PARAMETER :: SSqmd55 = 2122 - INTEGER(IntKi), PARAMETER :: SSqmd56 = 2123 - INTEGER(IntKi), PARAMETER :: SSqmd57 = 2124 - INTEGER(IntKi), PARAMETER :: SSqmd58 = 2125 - INTEGER(IntKi), PARAMETER :: SSqmd59 = 2126 - INTEGER(IntKi), PARAMETER :: SSqmd60 = 2127 - INTEGER(IntKi), PARAMETER :: SSqmd61 = 2128 - INTEGER(IntKi), PARAMETER :: SSqmd62 = 2129 - INTEGER(IntKi), PARAMETER :: SSqmd63 = 2130 - INTEGER(IntKi), PARAMETER :: SSqmd64 = 2131 - INTEGER(IntKi), PARAMETER :: SSqmd65 = 2132 - INTEGER(IntKi), PARAMETER :: SSqmd66 = 2133 - INTEGER(IntKi), PARAMETER :: SSqmd67 = 2134 - INTEGER(IntKi), PARAMETER :: SSqmd68 = 2135 - INTEGER(IntKi), PARAMETER :: SSqmd69 = 2136 - INTEGER(IntKi), PARAMETER :: SSqmd70 = 2137 - INTEGER(IntKi), PARAMETER :: SSqmd71 = 2138 - INTEGER(IntKi), PARAMETER :: SSqmd72 = 2139 - INTEGER(IntKi), PARAMETER :: SSqmd73 = 2140 - INTEGER(IntKi), PARAMETER :: SSqmd74 = 2141 - INTEGER(IntKi), PARAMETER :: SSqmd75 = 2142 - INTEGER(IntKi), PARAMETER :: SSqmd76 = 2143 - INTEGER(IntKi), PARAMETER :: SSqmd77 = 2144 - INTEGER(IntKi), PARAMETER :: SSqmd78 = 2145 - INTEGER(IntKi), PARAMETER :: SSqmd79 = 2146 - INTEGER(IntKi), PARAMETER :: SSqmd80 = 2147 - INTEGER(IntKi), PARAMETER :: SSqmd81 = 2148 - INTEGER(IntKi), PARAMETER :: SSqmd82 = 2149 - INTEGER(IntKi), PARAMETER :: SSqmd83 = 2150 - INTEGER(IntKi), PARAMETER :: SSqmd84 = 2151 - INTEGER(IntKi), PARAMETER :: SSqmd85 = 2152 - INTEGER(IntKi), PARAMETER :: SSqmd86 = 2153 - INTEGER(IntKi), PARAMETER :: SSqmd87 = 2154 - INTEGER(IntKi), PARAMETER :: SSqmd88 = 2155 - INTEGER(IntKi), PARAMETER :: SSqmd89 = 2156 - INTEGER(IntKi), PARAMETER :: SSqmd90 = 2157 - INTEGER(IntKi), PARAMETER :: SSqmd91 = 2158 - INTEGER(IntKi), PARAMETER :: SSqmd92 = 2159 - INTEGER(IntKi), PARAMETER :: SSqmd93 = 2160 - INTEGER(IntKi), PARAMETER :: SSqmd94 = 2161 - INTEGER(IntKi), PARAMETER :: SSqmd95 = 2162 - INTEGER(IntKi), PARAMETER :: SSqmd96 = 2163 - INTEGER(IntKi), PARAMETER :: SSqmd97 = 2164 - INTEGER(IntKi), PARAMETER :: SSqmd98 = 2165 - INTEGER(IntKi), PARAMETER :: SSqmd99 = 2166 - INTEGER(IntKi), PARAMETER :: SSqmdd01 = 2167 - INTEGER(IntKi), PARAMETER :: SSqmdd02 = 2168 - INTEGER(IntKi), PARAMETER :: SSqmdd03 = 2169 - INTEGER(IntKi), PARAMETER :: SSqmdd04 = 2170 - INTEGER(IntKi), PARAMETER :: SSqmdd05 = 2171 - INTEGER(IntKi), PARAMETER :: SSqmdd06 = 2172 - INTEGER(IntKi), PARAMETER :: SSqmdd07 = 2173 - INTEGER(IntKi), PARAMETER :: SSqmdd08 = 2174 - INTEGER(IntKi), PARAMETER :: SSqmdd09 = 2175 - INTEGER(IntKi), PARAMETER :: SSqmdd10 = 2176 - INTEGER(IntKi), PARAMETER :: SSqmdd11 = 2177 - INTEGER(IntKi), PARAMETER :: SSqmdd12 = 2178 - INTEGER(IntKi), PARAMETER :: SSqmdd13 = 2179 - INTEGER(IntKi), PARAMETER :: SSqmdd14 = 2180 - INTEGER(IntKi), PARAMETER :: SSqmdd15 = 2181 - INTEGER(IntKi), PARAMETER :: SSqmdd16 = 2182 - INTEGER(IntKi), PARAMETER :: SSqmdd17 = 2183 - INTEGER(IntKi), PARAMETER :: SSqmdd18 = 2184 - INTEGER(IntKi), PARAMETER :: SSqmdd19 = 2185 - INTEGER(IntKi), PARAMETER :: SSqmdd20 = 2186 - INTEGER(IntKi), PARAMETER :: SSqmdd21 = 2187 - INTEGER(IntKi), PARAMETER :: SSqmdd22 = 2188 - INTEGER(IntKi), PARAMETER :: SSqmdd23 = 2189 - INTEGER(IntKi), PARAMETER :: SSqmdd24 = 2190 - INTEGER(IntKi), PARAMETER :: SSqmdd25 = 2191 - INTEGER(IntKi), PARAMETER :: SSqmdd26 = 2192 - INTEGER(IntKi), PARAMETER :: SSqmdd27 = 2193 - INTEGER(IntKi), PARAMETER :: SSqmdd28 = 2194 - INTEGER(IntKi), PARAMETER :: SSqmdd29 = 2195 - INTEGER(IntKi), PARAMETER :: SSqmdd30 = 2196 - INTEGER(IntKi), PARAMETER :: SSqmdd31 = 2197 - INTEGER(IntKi), PARAMETER :: SSqmdd32 = 2198 - INTEGER(IntKi), PARAMETER :: SSqmdd33 = 2199 - INTEGER(IntKi), PARAMETER :: SSqmdd34 = 2200 - INTEGER(IntKi), PARAMETER :: SSqmdd35 = 2201 - INTEGER(IntKi), PARAMETER :: SSqmdd36 = 2202 - INTEGER(IntKi), PARAMETER :: SSqmdd37 = 2203 - INTEGER(IntKi), PARAMETER :: SSqmdd38 = 2204 - INTEGER(IntKi), PARAMETER :: SSqmdd39 = 2205 - INTEGER(IntKi), PARAMETER :: SSqmdd40 = 2206 - INTEGER(IntKi), PARAMETER :: SSqmdd41 = 2207 - INTEGER(IntKi), PARAMETER :: SSqmdd42 = 2208 - INTEGER(IntKi), PARAMETER :: SSqmdd43 = 2209 - INTEGER(IntKi), PARAMETER :: SSqmdd44 = 2210 - INTEGER(IntKi), PARAMETER :: SSqmdd45 = 2211 - INTEGER(IntKi), PARAMETER :: SSqmdd46 = 2212 - INTEGER(IntKi), PARAMETER :: SSqmdd47 = 2213 - INTEGER(IntKi), PARAMETER :: SSqmdd48 = 2214 - INTEGER(IntKi), PARAMETER :: SSqmdd49 = 2215 - INTEGER(IntKi), PARAMETER :: SSqmdd50 = 2216 - INTEGER(IntKi), PARAMETER :: SSqmdd51 = 2217 - INTEGER(IntKi), PARAMETER :: SSqmdd52 = 2218 - INTEGER(IntKi), PARAMETER :: SSqmdd53 = 2219 - INTEGER(IntKi), PARAMETER :: SSqmdd54 = 2220 - INTEGER(IntKi), PARAMETER :: SSqmdd55 = 2221 - INTEGER(IntKi), PARAMETER :: SSqmdd56 = 2222 - INTEGER(IntKi), PARAMETER :: SSqmdd57 = 2223 - INTEGER(IntKi), PARAMETER :: SSqmdd58 = 2224 - INTEGER(IntKi), PARAMETER :: SSqmdd59 = 2225 - INTEGER(IntKi), PARAMETER :: SSqmdd60 = 2226 - INTEGER(IntKi), PARAMETER :: SSqmdd61 = 2227 - INTEGER(IntKi), PARAMETER :: SSqmdd62 = 2228 - INTEGER(IntKi), PARAMETER :: SSqmdd63 = 2229 - INTEGER(IntKi), PARAMETER :: SSqmdd64 = 2230 - INTEGER(IntKi), PARAMETER :: SSqmdd65 = 2231 - INTEGER(IntKi), PARAMETER :: SSqmdd66 = 2232 - INTEGER(IntKi), PARAMETER :: SSqmdd67 = 2233 - INTEGER(IntKi), PARAMETER :: SSqmdd68 = 2234 - INTEGER(IntKi), PARAMETER :: SSqmdd69 = 2235 - INTEGER(IntKi), PARAMETER :: SSqmdd70 = 2236 - INTEGER(IntKi), PARAMETER :: SSqmdd71 = 2237 - INTEGER(IntKi), PARAMETER :: SSqmdd72 = 2238 - INTEGER(IntKi), PARAMETER :: SSqmdd73 = 2239 - INTEGER(IntKi), PARAMETER :: SSqmdd74 = 2240 - INTEGER(IntKi), PARAMETER :: SSqmdd75 = 2241 - INTEGER(IntKi), PARAMETER :: SSqmdd76 = 2242 - INTEGER(IntKi), PARAMETER :: SSqmdd77 = 2243 - INTEGER(IntKi), PARAMETER :: SSqmdd78 = 2244 - INTEGER(IntKi), PARAMETER :: SSqmdd79 = 2245 - INTEGER(IntKi), PARAMETER :: SSqmdd80 = 2246 - INTEGER(IntKi), PARAMETER :: SSqmdd81 = 2247 - INTEGER(IntKi), PARAMETER :: SSqmdd82 = 2248 - INTEGER(IntKi), PARAMETER :: SSqmdd83 = 2249 - INTEGER(IntKi), PARAMETER :: SSqmdd84 = 2250 - INTEGER(IntKi), PARAMETER :: SSqmdd85 = 2251 - INTEGER(IntKi), PARAMETER :: SSqmdd86 = 2252 - INTEGER(IntKi), PARAMETER :: SSqmdd87 = 2253 - INTEGER(IntKi), PARAMETER :: SSqmdd88 = 2254 - INTEGER(IntKi), PARAMETER :: SSqmdd89 = 2255 - INTEGER(IntKi), PARAMETER :: SSqmdd90 = 2256 - INTEGER(IntKi), PARAMETER :: SSqmdd91 = 2257 - INTEGER(IntKi), PARAMETER :: SSqmdd92 = 2258 - INTEGER(IntKi), PARAMETER :: SSqmdd93 = 2259 - INTEGER(IntKi), PARAMETER :: SSqmdd94 = 2260 - INTEGER(IntKi), PARAMETER :: SSqmdd95 = 2261 - INTEGER(IntKi), PARAMETER :: SSqmdd96 = 2262 - INTEGER(IntKi), PARAMETER :: SSqmdd97 = 2263 - INTEGER(IntKi), PARAMETER :: SSqmdd98 = 2264 - INTEGER(IntKi), PARAMETER :: SSqmdd99 = 2265 - - - ! The maximum number of output channels which can be output by the code. - !INTEGER(IntKi), PARAMETER :: MaxOutPts = 2265 - -!End of code generated by Matlab script - - INTEGER, PARAMETER :: MNfmKe(6,9,9) = reshape((/ M1N1FKxe,M1N1FKye,M1N1FKze,M1N1MKxe,M1N1MKye,M1N1MKze, & - M1N2FKxe,M1N2FKye,M1N2FKze,M1N2MKxe,M1N2MKye,M1N2MKze, & - M1N3FKxe,M1N3FKye,M1N3FKze,M1N3MKxe,M1N3MKye,M1N3MKze, & - M1N4FKxe,M1N4FKye,M1N4FKze,M1N4MKxe,M1N4MKye,M1N4MKze, & - M1N5FKxe,M1N5FKye,M1N5FKze,M1N5MKxe,M1N5MKye,M1N5MKze, & - M1N6FKxe,M1N6FKye,M1N6FKze,M1N6MKxe,M1N6MKye,M1N6MKze, & - M1N7FKxe,M1N7FKye,M1N7FKze,M1N7MKxe,M1N7MKye,M1N7MKze, & - M1N8FKxe,M1N8FKye,M1N8FKze,M1N8MKxe,M1N8MKye,M1N8MKze, & - M1N9FKxe,M1N9FKye,M1N9FKze,M1N9MKxe,M1N9MKye,M1N9MKze, & - M2N1FKxe,M2N1FKye,M2N1FKze,M2N1MKxe,M2N1MKye,M2N1MKze, & - M2N2FKxe,M2N2FKye,M2N2FKze,M2N2MKxe,M2N2MKye,M2N2MKze, & - M2N3FKxe,M2N3FKye,M2N3FKze,M2N3MKxe,M2N3MKye,M2N3MKze, & - M2N4FKxe,M2N4FKye,M2N4FKze,M2N4MKxe,M2N4MKye,M2N4MKze, & - M2N5FKxe,M2N5FKye,M2N5FKze,M2N5MKxe,M2N5MKye,M2N5MKze, & - M2N6FKxe,M2N6FKye,M2N6FKze,M2N6MKxe,M2N6MKye,M2N6MKze, & - M2N7FKxe,M2N7FKye,M2N7FKze,M2N7MKxe,M2N7MKye,M2N7MKze, & - M2N8FKxe,M2N8FKye,M2N8FKze,M2N8MKxe,M2N8MKye,M2N8MKze, & - M2N9FKxe,M2N9FKye,M2N9FKze,M2N9MKxe,M2N9MKye,M2N9MKze, & - M3N1FKxe,M3N1FKye,M3N1FKze,M3N1MKxe,M3N1MKye,M3N1MKze, & - M3N2FKxe,M3N2FKye,M3N2FKze,M3N2MKxe,M3N2MKye,M3N2MKze, & - M3N3FKxe,M3N3FKye,M3N3FKze,M3N3MKxe,M3N3MKye,M3N3MKze, & - M3N4FKxe,M3N4FKye,M3N4FKze,M3N4MKxe,M3N4MKye,M3N4MKze, & - M3N5FKxe,M3N5FKye,M3N5FKze,M3N5MKxe,M3N5MKye,M3N5MKze, & - M3N6FKxe,M3N6FKye,M3N6FKze,M3N6MKxe,M3N6MKye,M3N6MKze, & - M3N7FKxe,M3N7FKye,M3N7FKze,M3N7MKxe,M3N7MKye,M3N7MKze, & - M3N8FKxe,M3N8FKye,M3N8FKze,M3N8MKxe,M3N8MKye,M3N8MKze, & - M3N9FKxe,M3N9FKye,M3N9FKze,M3N9MKxe,M3N9MKye,M3N9MKze, & - M4N1FKxe,M4N1FKye,M4N1FKze,M4N1MKxe,M4N1MKye,M4N1MKze, & - M4N2FKxe,M4N2FKye,M4N2FKze,M4N2MKxe,M4N2MKye,M4N2MKze, & - M4N3FKxe,M4N3FKye,M4N3FKze,M4N3MKxe,M4N3MKye,M4N3MKze, & - M4N4FKxe,M4N4FKye,M4N4FKze,M4N4MKxe,M4N4MKye,M4N4MKze, & - M4N5FKxe,M4N5FKye,M4N5FKze,M4N5MKxe,M4N5MKye,M4N5MKze, & - M4N6FKxe,M4N6FKye,M4N6FKze,M4N6MKxe,M4N6MKye,M4N6MKze, & - M4N7FKxe,M4N7FKye,M4N7FKze,M4N7MKxe,M4N7MKye,M4N7MKze, & - M4N8FKxe,M4N8FKye,M4N8FKze,M4N8MKxe,M4N8MKye,M4N8MKze, & - M4N9FKxe,M4N9FKye,M4N9FKze,M4N9MKxe,M4N9MKye,M4N9MKze, & - M5N1FKxe,M5N1FKye,M5N1FKze,M5N1MKxe,M5N1MKye,M5N1MKze, & - M5N2FKxe,M5N2FKye,M5N2FKze,M5N2MKxe,M5N2MKye,M5N2MKze, & - M5N3FKxe,M5N3FKye,M5N3FKze,M5N3MKxe,M5N3MKye,M5N3MKze, & - M5N4FKxe,M5N4FKye,M5N4FKze,M5N4MKxe,M5N4MKye,M5N4MKze, & - M5N5FKxe,M5N5FKye,M5N5FKze,M5N5MKxe,M5N5MKye,M5N5MKze, & - M5N6FKxe,M5N6FKye,M5N6FKze,M5N6MKxe,M5N6MKye,M5N6MKze, & - M5N7FKxe,M5N7FKye,M5N7FKze,M5N7MKxe,M5N7MKye,M5N7MKze, & - M5N8FKxe,M5N8FKye,M5N8FKze,M5N8MKxe,M5N8MKye,M5N8MKze, & - M5N9FKxe,M5N9FKye,M5N9FKze,M5N9MKxe,M5N9MKye,M5N9MKze, & - M6N1FKxe,M6N1FKye,M6N1FKze,M6N1MKxe,M6N1MKye,M6N1MKze, & - M6N2FKxe,M6N2FKye,M6N2FKze,M6N2MKxe,M6N2MKye,M6N2MKze, & - M6N3FKxe,M6N3FKye,M6N3FKze,M6N3MKxe,M6N3MKye,M6N3MKze, & - M6N4FKxe,M6N4FKye,M6N4FKze,M6N4MKxe,M6N4MKye,M6N4MKze, & - M6N5FKxe,M6N5FKye,M6N5FKze,M6N5MKxe,M6N5MKye,M6N5MKze, & - M6N6FKxe,M6N6FKye,M6N6FKze,M6N6MKxe,M6N6MKye,M6N6MKze, & - M6N7FKxe,M6N7FKye,M6N7FKze,M6N7MKxe,M6N7MKye,M6N7MKze, & - M6N8FKxe,M6N8FKye,M6N8FKze,M6N8MKxe,M6N8MKye,M6N8MKze, & - M6N9FKxe,M6N9FKye,M6N9FKze,M6N9MKxe,M6N9MKye,M6N9MKze, & - M7N1FKxe,M7N1FKye,M7N1FKze,M7N1MKxe,M7N1MKye,M7N1MKze, & - M7N2FKxe,M7N2FKye,M7N2FKze,M7N2MKxe,M7N2MKye,M7N2MKze, & - M7N3FKxe,M7N3FKye,M7N3FKze,M7N3MKxe,M7N3MKye,M7N3MKze, & - M7N4FKxe,M7N4FKye,M7N4FKze,M7N4MKxe,M7N4MKye,M7N4MKze, & - M7N5FKxe,M7N5FKye,M7N5FKze,M7N5MKxe,M7N5MKye,M7N5MKze, & - M7N6FKxe,M7N6FKye,M7N6FKze,M7N6MKxe,M7N6MKye,M7N6MKze, & - M7N7FKxe,M7N7FKye,M7N7FKze,M7N7MKxe,M7N7MKye,M7N7MKze, & - M7N8FKxe,M7N8FKye,M7N8FKze,M7N8MKxe,M7N8MKye,M7N8MKze, & - M7N9FKxe,M7N9FKye,M7N9FKze,M7N9MKxe,M7N9MKye,M7N9MKze, & - M8N1FKxe,M8N1FKye,M8N1FKze,M8N1MKxe,M8N1MKye,M8N1MKze, & - M8N2FKxe,M8N2FKye,M8N2FKze,M8N2MKxe,M8N2MKye,M8N2MKze, & - M8N3FKxe,M8N3FKye,M8N3FKze,M8N3MKxe,M8N3MKye,M8N3MKze, & - M8N4FKxe,M8N4FKye,M8N4FKze,M8N4MKxe,M8N4MKye,M8N4MKze, & - M8N5FKxe,M8N5FKye,M8N5FKze,M8N5MKxe,M8N5MKye,M8N5MKze, & - M8N6FKxe,M8N6FKye,M8N6FKze,M8N6MKxe,M8N6MKye,M8N6MKze, & - M8N7FKxe,M8N7FKye,M8N7FKze,M8N7MKxe,M8N7MKye,M8N7MKze, & - M8N8FKxe,M8N8FKye,M8N8FKze,M8N8MKxe,M8N8MKye,M8N8MKze, & - M8N9FKxe,M8N9FKye,M8N9FKze,M8N9MKxe,M8N9MKye,M8N9MKze, & - M9N1FKxe,M9N1FKye,M9N1FKze,M9N1MKxe,M9N1MKye,M9N1MKze, & - M9N2FKxe,M9N2FKye,M9N2FKze,M9N2MKxe,M9N2MKye,M9N2MKze, & - M9N3FKxe,M9N3FKye,M9N3FKze,M9N3MKxe,M9N3MKye,M9N3MKze, & - M9N4FKxe,M9N4FKye,M9N4FKze,M9N4MKxe,M9N4MKye,M9N4MKze, & - M9N5FKxe,M9N5FKye,M9N5FKze,M9N5MKxe,M9N5MKye,M9N5MKze, & - M9N6FKxe,M9N6FKye,M9N6FKze,M9N6MKxe,M9N6MKye,M9N6MKze, & - M9N7FKxe,M9N7FKye,M9N7FKze,M9N7MKxe,M9N7MKye,M9N7MKze, & - M9N8FKxe,M9N8FKye,M9N8FKze,M9N8MKxe,M9N8MKye,M9N8MKze, & - M9N9FKxe,M9N9FKye,M9N9FKze,M9N9MKxe,M9N9MKye,M9N9MKze /),(/6,9,9/)) - - - - INTEGER, PARAMETER :: MNfmMe(6,9,9) = reshape((/ M1N1FMxe,M1N1FMye,M1N1FMze,M1N1MMxe,M1N1MMye,M1N1MMze, & - M1N2FMxe,M1N2FMye,M1N2FMze,M1N2MMxe,M1N2MMye,M1N2MMze, & - M1N3FMxe,M1N3FMye,M1N3FMze,M1N3MMxe,M1N3MMye,M1N3MMze, & - M1N4FMxe,M1N4FMye,M1N4FMze,M1N4MMxe,M1N4MMye,M1N4MMze, & - M1N5FMxe,M1N5FMye,M1N5FMze,M1N5MMxe,M1N5MMye,M1N5MMze, & - M1N6FMxe,M1N6FMye,M1N6FMze,M1N6MMxe,M1N6MMye,M1N6MMze, & - M1N7FMxe,M1N7FMye,M1N7FMze,M1N7MMxe,M1N7MMye,M1N7MMze, & - M1N8FMxe,M1N8FMye,M1N8FMze,M1N8MMxe,M1N8MMye,M1N8MMze, & - M1N9FMxe,M1N9FMye,M1N9FMze,M1N9MMxe,M1N9MMye,M1N9MMze, & - M2N1FMxe,M2N1FMye,M2N1FMze,M2N1MMxe,M2N1MMye,M2N1MMze, & - M2N2FMxe,M2N2FMye,M2N2FMze,M2N2MMxe,M2N2MMye,M2N2MMze, & - M2N3FMxe,M2N3FMye,M2N3FMze,M2N3MMxe,M2N3MMye,M2N3MMze, & - M2N4FMxe,M2N4FMye,M2N4FMze,M2N4MMxe,M2N4MMye,M2N4MMze, & - M2N5FMxe,M2N5FMye,M2N5FMze,M2N5MMxe,M2N5MMye,M2N5MMze, & - M2N6FMxe,M2N6FMye,M2N6FMze,M2N6MMxe,M2N6MMye,M2N6MMze, & - M2N7FMxe,M2N7FMye,M2N7FMze,M2N7MMxe,M2N7MMye,M2N7MMze, & - M2N8FMxe,M2N8FMye,M2N8FMze,M2N8MMxe,M2N8MMye,M2N8MMze, & - M2N9FMxe,M2N9FMye,M2N9FMze,M2N9MMxe,M2N9MMye,M2N9MMze, & - M3N1FMxe,M3N1FMye,M3N1FMze,M3N1MMxe,M3N1MMye,M3N1MMze, & - M3N2FMxe,M3N2FMye,M3N2FMze,M3N2MMxe,M3N2MMye,M3N2MMze, & - M3N3FMxe,M3N3FMye,M3N3FMze,M3N3MMxe,M3N3MMye,M3N3MMze, & - M3N4FMxe,M3N4FMye,M3N4FMze,M3N4MMxe,M3N4MMye,M3N4MMze, & - M3N5FMxe,M3N5FMye,M3N5FMze,M3N5MMxe,M3N5MMye,M3N5MMze, & - M3N6FMxe,M3N6FMye,M3N6FMze,M3N6MMxe,M3N6MMye,M3N6MMze, & - M3N7FMxe,M3N7FMye,M3N7FMze,M3N7MMxe,M3N7MMye,M3N7MMze, & - M3N8FMxe,M3N8FMye,M3N8FMze,M3N8MMxe,M3N8MMye,M3N8MMze, & - M3N9FMxe,M3N9FMye,M3N9FMze,M3N9MMxe,M3N9MMye,M3N9MMze, & - M4N1FMxe,M4N1FMye,M4N1FMze,M4N1MMxe,M4N1MMye,M4N1MMze, & - M4N2FMxe,M4N2FMye,M4N2FMze,M4N2MMxe,M4N2MMye,M4N2MMze, & - M4N3FMxe,M4N3FMye,M4N3FMze,M4N3MMxe,M4N3MMye,M4N3MMze, & - M4N4FMxe,M4N4FMye,M4N4FMze,M4N4MMxe,M4N4MMye,M4N4MMze, & - M4N5FMxe,M4N5FMye,M4N5FMze,M4N5MMxe,M4N5MMye,M4N5MMze, & - M4N6FMxe,M4N6FMye,M4N6FMze,M4N6MMxe,M4N6MMye,M4N6MMze, & - M4N7FMxe,M4N7FMye,M4N7FMze,M4N7MMxe,M4N7MMye,M4N7MMze, & - M4N8FMxe,M4N8FMye,M4N8FMze,M4N8MMxe,M4N8MMye,M4N8MMze, & - M4N9FMxe,M4N9FMye,M4N9FMze,M4N9MMxe,M4N9MMye,M4N9MMze, & - M5N1FMxe,M5N1FMye,M5N1FMze,M5N1MMxe,M5N1MMye,M5N1MMze, & - M5N2FMxe,M5N2FMye,M5N2FMze,M5N2MMxe,M5N2MMye,M5N2MMze, & - M5N3FMxe,M5N3FMye,M5N3FMze,M5N3MMxe,M5N3MMye,M5N3MMze, & - M5N4FMxe,M5N4FMye,M5N4FMze,M5N4MMxe,M5N4MMye,M5N4MMze, & - M5N5FMxe,M5N5FMye,M5N5FMze,M5N5MMxe,M5N5MMye,M5N5MMze, & - M5N6FMxe,M5N6FMye,M5N6FMze,M5N6MMxe,M5N6MMye,M5N6MMze, & - M5N7FMxe,M5N7FMye,M5N7FMze,M5N7MMxe,M5N7MMye,M5N7MMze, & - M5N8FMxe,M5N8FMye,M5N8FMze,M5N8MMxe,M5N8MMye,M5N8MMze, & - M5N9FMxe,M5N9FMye,M5N9FMze,M5N9MMxe,M5N9MMye,M5N9MMze, & - M6N1FMxe,M6N1FMye,M6N1FMze,M6N1MMxe,M6N1MMye,M6N1MMze, & - M6N2FMxe,M6N2FMye,M6N2FMze,M6N2MMxe,M6N2MMye,M6N2MMze, & - M6N3FMxe,M6N3FMye,M6N3FMze,M6N3MMxe,M6N3MMye,M6N3MMze, & - M6N4FMxe,M6N4FMye,M6N4FMze,M6N4MMxe,M6N4MMye,M6N4MMze, & - M6N5FMxe,M6N5FMye,M6N5FMze,M6N5MMxe,M6N5MMye,M6N5MMze, & - M6N6FMxe,M6N6FMye,M6N6FMze,M6N6MMxe,M6N6MMye,M6N6MMze, & - M6N7FMxe,M6N7FMye,M6N7FMze,M6N7MMxe,M6N7MMye,M6N7MMze, & - M6N8FMxe,M6N8FMye,M6N8FMze,M6N8MMxe,M6N8MMye,M6N8MMze, & - M6N9FMxe,M6N9FMye,M6N9FMze,M6N9MMxe,M6N9MMye,M6N9MMze, & - M7N1FMxe,M7N1FMye,M7N1FMze,M7N1MMxe,M7N1MMye,M7N1MMze, & - M7N2FMxe,M7N2FMye,M7N2FMze,M7N2MMxe,M7N2MMye,M7N2MMze, & - M7N3FMxe,M7N3FMye,M7N3FMze,M7N3MMxe,M7N3MMye,M7N3MMze, & - M7N4FMxe,M7N4FMye,M7N4FMze,M7N4MMxe,M7N4MMye,M7N4MMze, & - M7N5FMxe,M7N5FMye,M7N5FMze,M7N5MMxe,M7N5MMye,M7N5MMze, & - M7N6FMxe,M7N6FMye,M7N6FMze,M7N6MMxe,M7N6MMye,M7N6MMze, & - M7N7FMxe,M7N7FMye,M7N7FMze,M7N7MMxe,M7N7MMye,M7N7MMze, & - M7N8FMxe,M7N8FMye,M7N8FMze,M7N8MMxe,M7N8MMye,M7N8MMze, & - M7N9FMxe,M7N9FMye,M7N9FMze,M7N9MMxe,M7N9MMye,M7N9MMze, & - M8N1FMxe,M8N1FMye,M8N1FMze,M8N1MMxe,M8N1MMye,M8N1MMze, & - M8N2FMxe,M8N2FMye,M8N2FMze,M8N2MMxe,M8N2MMye,M8N2MMze, & - M8N3FMxe,M8N3FMye,M8N3FMze,M8N3MMxe,M8N3MMye,M8N3MMze, & - M8N4FMxe,M8N4FMye,M8N4FMze,M8N4MMxe,M8N4MMye,M8N4MMze, & - M8N5FMxe,M8N5FMye,M8N5FMze,M8N5MMxe,M8N5MMye,M8N5MMze, & - M8N6FMxe,M8N6FMye,M8N6FMze,M8N6MMxe,M8N6MMye,M8N6MMze, & - M8N7FMxe,M8N7FMye,M8N7FMze,M8N7MMxe,M8N7MMye,M8N7MMze, & - M8N8FMxe,M8N8FMye,M8N8FMze,M8N8MMxe,M8N8MMye,M8N8MMze, & - M8N9FMxe,M8N9FMye,M8N9FMze,M8N9MMxe,M8N9MMye,M8N9MMze, & - M9N1FMxe,M9N1FMye,M9N1FMze,M9N1MMxe,M9N1MMye,M9N1MMze, & - M9N2FMxe,M9N2FMye,M9N2FMze,M9N2MMxe,M9N2MMye,M9N2MMze, & - M9N3FMxe,M9N3FMye,M9N3FMze,M9N3MMxe,M9N3MMye,M9N3MMze, & - M9N4FMxe,M9N4FMye,M9N4FMze,M9N4MMxe,M9N4MMye,M9N4MMze, & - M9N5FMxe,M9N5FMye,M9N5FMze,M9N5MMxe,M9N5MMye,M9N5MMze, & - M9N6FMxe,M9N6FMye,M9N6FMze,M9N6MMxe,M9N6MMye,M9N6MMze, & - M9N7FMxe,M9N7FMye,M9N7FMze,M9N7MMxe,M9N7MMye,M9N7MMze, & - M9N8FMxe,M9N8FMye,M9N8FMze,M9N8MMxe,M9N8MMye,M9N8MMze, & - M9N9FMxe,M9N9FMye,M9N9FMze,M9N9MMxe,M9N9MMye,M9N9MMze /),(/6,9,9/)) - - INTEGER, PARAMETER :: MNTDss(3,9,9) = reshape((/M1N1TDxss,M1N1TDyss,M1N1TDzss, & - M1N2TDxss,M1N2TDyss,M1N2TDzss, & - M1N3TDxss,M1N3TDyss,M1N3TDzss, & - M1N4TDxss,M1N4TDyss,M1N4TDzss, & - M1N5TDxss,M1N5TDyss,M1N5TDzss, & - M1N6TDxss,M1N6TDyss,M1N6TDzss, & - M1N7TDxss,M1N7TDyss,M1N7TDzss, & - M1N8TDxss,M1N8TDyss,M1N8TDzss, & - M1N9TDxss,M1N9TDyss,M1N9TDzss, & - M2N1TDxss,M2N1TDyss,M2N1TDzss, & - M2N2TDxss,M2N2TDyss,M2N2TDzss, & - M2N3TDxss,M2N3TDyss,M2N3TDzss, & - M2N4TDxss,M2N4TDyss,M2N4TDzss, & - M2N5TDxss,M2N5TDyss,M2N5TDzss, & - M2N6TDxss,M2N6TDyss,M2N6TDzss, & - M2N7TDxss,M2N7TDyss,M2N7TDzss, & - M2N8TDxss,M2N8TDyss,M2N8TDzss, & - M2N9TDxss,M2N9TDyss,M2N9TDzss, & - M3N1TDxss,M3N1TDyss,M3N1TDzss, & - M3N2TDxss,M3N2TDyss,M3N2TDzss, & - M3N3TDxss,M3N3TDyss,M3N3TDzss, & - M3N4TDxss,M3N4TDyss,M3N4TDzss, & - M3N5TDxss,M3N5TDyss,M3N5TDzss, & - M3N6TDxss,M3N6TDyss,M3N6TDzss, & - M3N7TDxss,M3N7TDyss,M3N7TDzss, & - M3N8TDxss,M3N8TDyss,M3N8TDzss, & - M3N9TDxss,M3N9TDyss,M3N9TDzss, & - M4N1TDxss,M4N1TDyss,M4N1TDzss, & - M4N2TDxss,M4N2TDyss,M4N2TDzss, & - M4N3TDxss,M4N3TDyss,M4N3TDzss, & - M4N4TDxss,M4N4TDyss,M4N4TDzss, & - M4N5TDxss,M4N5TDyss,M4N5TDzss, & - M4N6TDxss,M4N6TDyss,M4N6TDzss, & - M4N7TDxss,M4N7TDyss,M4N7TDzss, & - M4N8TDxss,M4N8TDyss,M4N8TDzss, & - M4N9TDxss,M4N9TDyss,M4N9TDzss, & - M5N1TDxss,M5N1TDyss,M5N1TDzss, & - M5N2TDxss,M5N2TDyss,M5N2TDzss, & - M5N3TDxss,M5N3TDyss,M5N3TDzss, & - M5N4TDxss,M5N4TDyss,M5N4TDzss, & - M5N5TDxss,M5N5TDyss,M5N5TDzss, & - M5N6TDxss,M5N6TDyss,M5N6TDzss, & - M5N7TDxss,M5N7TDyss,M5N7TDzss, & - M5N8TDxss,M5N8TDyss,M5N8TDzss, & - M5N9TDxss,M5N9TDyss,M5N9TDzss, & - M6N1TDxss,M6N1TDyss,M6N1TDzss, & - M6N2TDxss,M6N2TDyss,M6N2TDzss, & - M6N3TDxss,M6N3TDyss,M6N3TDzss, & - M6N4TDxss,M6N4TDyss,M6N4TDzss, & - M6N5TDxss,M6N5TDyss,M6N5TDzss, & - M6N6TDxss,M6N6TDyss,M6N6TDzss, & - M6N7TDxss,M6N7TDyss,M6N7TDzss, & - M6N8TDxss,M6N8TDyss,M6N8TDzss, & - M6N9TDxss,M6N9TDyss,M6N9TDzss, & - M7N1TDxss,M7N1TDyss,M7N1TDzss, & - M7N2TDxss,M7N2TDyss,M7N2TDzss, & - M7N3TDxss,M7N3TDyss,M7N3TDzss, & - M7N4TDxss,M7N4TDyss,M7N4TDzss, & - M7N5TDxss,M7N5TDyss,M7N5TDzss, & - M7N6TDxss,M7N6TDyss,M7N6TDzss, & - M7N7TDxss,M7N7TDyss,M7N7TDzss, & - M7N8TDxss,M7N8TDyss,M7N8TDzss, & - M7N9TDxss,M7N9TDyss,M7N9TDzss, & - M8N1TDxss,M8N1TDyss,M8N1TDzss, & - M8N2TDxss,M8N2TDyss,M8N2TDzss, & - M8N3TDxss,M8N3TDyss,M8N3TDzss, & - M8N4TDxss,M8N4TDyss,M8N4TDzss, & - M8N5TDxss,M8N5TDyss,M8N5TDzss, & - M8N6TDxss,M8N6TDyss,M8N6TDzss, & - M8N7TDxss,M8N7TDyss,M8N7TDzss, & - M8N8TDxss,M8N8TDyss,M8N8TDzss, & - M8N9TDxss,M8N9TDyss,M8N9TDzss, & - M9N1TDxss,M9N1TDyss,M9N1TDzss, & - M9N2TDxss,M9N2TDyss,M9N2TDzss, & - M9N3TDxss,M9N3TDyss,M9N3TDzss, & - M9N4TDxss,M9N4TDyss,M9N4TDzss, & - M9N5TDxss,M9N5TDyss,M9N5TDzss, & - M9N6TDxss,M9N6TDyss,M9N6TDzss, & - M9N7TDxss,M9N7TDyss,M9N7TDzss, & - M9N8TDxss,M9N8TDyss,M9N8TDzss, & - M9N9TDxss,M9N9TDyss,M9N9TDzss/), (/3,9,9/)) - -INTEGER, PARAMETER :: MNRDe (3,9,9) = reshape((/M1N1RDxe,M1N1RDye,M1N1RDze, & - M1N2RDxe,M1N2RDye,M1N2RDze, & - M1N3RDxe,M1N3RDye,M1N3RDze, & - M1N4RDxe,M1N4RDye,M1N4RDze, & - M1N5RDxe,M1N5RDye,M1N5RDze, & - M1N6RDxe,M1N6RDye,M1N6RDze, & - M1N7RDxe,M1N7RDye,M1N7RDze, & - M1N8RDxe,M1N8RDye,M1N8RDze, & - M1N9RDxe,M1N9RDye,M1N9RDze, & - M2N1RDxe,M2N1RDye,M2N1RDze, & - M2N2RDxe,M2N2RDye,M2N2RDze, & - M2N3RDxe,M2N3RDye,M2N3RDze, & - M2N4RDxe,M2N4RDye,M2N4RDze, & - M2N5RDxe,M2N5RDye,M2N5RDze, & - M2N6RDxe,M2N6RDye,M2N6RDze, & - M2N7RDxe,M2N7RDye,M2N7RDze, & - M2N8RDxe,M2N8RDye,M2N8RDze, & - M2N9RDxe,M2N9RDye,M2N9RDze, & - M3N1RDxe,M3N1RDye,M3N1RDze, & - M3N2RDxe,M3N2RDye,M3N2RDze, & - M3N3RDxe,M3N3RDye,M3N3RDze, & - M3N4RDxe,M3N4RDye,M3N4RDze, & - M3N5RDxe,M3N5RDye,M3N5RDze, & - M3N6RDxe,M3N6RDye,M3N6RDze, & - M3N7RDxe,M3N7RDye,M3N7RDze, & - M3N8RDxe,M3N8RDye,M3N8RDze, & - M3N9RDxe,M3N9RDye,M3N9RDze, & - M4N1RDxe,M4N1RDye,M4N1RDze, & - M4N2RDxe,M4N2RDye,M4N2RDze, & - M4N3RDxe,M4N3RDye,M4N3RDze, & - M4N4RDxe,M4N4RDye,M4N4RDze, & - M4N5RDxe,M4N5RDye,M4N5RDze, & - M4N6RDxe,M4N6RDye,M4N6RDze, & - M4N7RDxe,M4N7RDye,M4N7RDze, & - M4N8RDxe,M4N8RDye,M4N8RDze, & - M4N9RDxe,M4N9RDye,M4N9RDze, & - M5N1RDxe,M5N1RDye,M5N1RDze, & - M5N2RDxe,M5N2RDye,M5N2RDze, & - M5N3RDxe,M5N3RDye,M5N3RDze, & - M5N4RDxe,M5N4RDye,M5N4RDze, & - M5N5RDxe,M5N5RDye,M5N5RDze, & - M5N6RDxe,M5N6RDye,M5N6RDze, & - M5N7RDxe,M5N7RDye,M5N7RDze, & - M5N8RDxe,M5N8RDye,M5N8RDze, & - M5N9RDxe,M5N9RDye,M5N9RDze, & - M6N1RDxe,M6N1RDye,M6N1RDze, & - M6N2RDxe,M6N2RDye,M6N2RDze, & - M6N3RDxe,M6N3RDye,M6N3RDze, & - M6N4RDxe,M6N4RDye,M6N4RDze, & - M6N5RDxe,M6N5RDye,M6N5RDze, & - M6N6RDxe,M6N6RDye,M6N6RDze, & - M6N7RDxe,M6N7RDye,M6N7RDze, & - M6N8RDxe,M6N8RDye,M6N8RDze, & - M6N9RDxe,M6N9RDye,M6N9RDze, & - M7N1RDxe,M7N1RDye,M7N1RDze, & - M7N2RDxe,M7N2RDye,M7N2RDze, & - M7N3RDxe,M7N3RDye,M7N3RDze, & - M7N4RDxe,M7N4RDye,M7N4RDze, & - M7N5RDxe,M7N5RDye,M7N5RDze, & - M7N6RDxe,M7N6RDye,M7N6RDze, & - M7N7RDxe,M7N7RDye,M7N7RDze, & - M7N8RDxe,M7N8RDye,M7N8RDze, & - M7N9RDxe,M7N9RDye,M7N9RDze, & - M8N1RDxe,M8N1RDye,M8N1RDze, & - M8N2RDxe,M8N2RDye,M8N2RDze, & - M8N3RDxe,M8N3RDye,M8N3RDze, & - M8N4RDxe,M8N4RDye,M8N4RDze, & - M8N5RDxe,M8N5RDye,M8N5RDze, & - M8N6RDxe,M8N6RDye,M8N6RDze, & - M8N7RDxe,M8N7RDye,M8N7RDze, & - M8N8RDxe,M8N8RDye,M8N8RDze, & - M8N9RDxe,M8N9RDye,M8N9RDze, & - M9N1RDxe,M9N1RDye,M9N1RDze, & - M9N2RDxe,M9N2RDye,M9N2RDze, & - M9N3RDxe,M9N3RDye,M9N3RDze, & - M9N4RDxe,M9N4RDye,M9N4RDze, & - M9N5RDxe,M9N5RDye,M9N5RDze, & - M9N6RDxe,M9N6RDye,M9N6RDze, & - M9N7RDxe,M9N7RDye,M9N7RDze, & - M9N8RDxe,M9N8RDye,M9N8RDze, & - M9N9RDxe,M9N9RDye,M9N9RDze/), (/3,9,9/)) - - - INTEGER, PARAMETER :: MNTRAe(6,9,9) = reshape( (/M1N1TAxe,M1N1TAye,M1N1TAze,M1N1RAxe,M1N1RAye,M1N1RAze, & - M1N2TAxe,M1N2TAye,M1N2TAze,M1N2RAxe,M1N2RAye,M1N2RAze, & - M1N3TAxe,M1N3TAye,M1N3TAze,M1N3RAxe,M1N3RAye,M1N3RAze, & - M1N4TAxe,M1N4TAye,M1N4TAze,M1N4RAxe,M1N4RAye,M1N4RAze, & - M1N5TAxe,M1N5TAye,M1N5TAze,M1N5RAxe,M1N5RAye,M1N5RAze, & - M1N6TAxe,M1N6TAye,M1N6TAze,M1N6RAxe,M1N6RAye,M1N6RAze, & - M1N7TAxe,M1N7TAye,M1N7TAze,M1N7RAxe,M1N7RAye,M1N7RAze, & - M1N8TAxe,M1N8TAye,M1N8TAze,M1N8RAxe,M1N8RAye,M1N8RAze, & - M1N9TAxe,M1N9TAye,M1N9TAze,M1N9RAxe,M1N9RAye,M1N9RAze, & - M2N1TAxe,M2N1TAye,M2N1TAze,M2N1RAxe,M2N1RAye,M2N1RAze, & - M2N2TAxe,M2N2TAye,M2N2TAze,M2N2RAxe,M2N2RAye,M2N2RAze, & - M2N3TAxe,M2N3TAye,M2N3TAze,M2N3RAxe,M2N3RAye,M2N3RAze, & - M2N4TAxe,M2N4TAye,M2N4TAze,M2N4RAxe,M2N4RAye,M2N4RAze, & - M2N5TAxe,M2N5TAye,M2N5TAze,M2N5RAxe,M2N5RAye,M2N5RAze, & - M2N6TAxe,M2N6TAye,M2N6TAze,M2N6RAxe,M2N6RAye,M2N6RAze, & - M2N7TAxe,M2N7TAye,M2N7TAze,M2N7RAxe,M2N7RAye,M2N7RAze, & - M2N8TAxe,M2N8TAye,M2N8TAze,M2N8RAxe,M2N8RAye,M2N8RAze, & - M2N9TAxe,M2N9TAye,M2N9TAze,M2N9RAxe,M2N9RAye,M2N9RAze, & - M3N1TAxe,M3N1TAye,M3N1TAze,M3N1RAxe,M3N1RAye,M3N1RAze, & - M3N2TAxe,M3N2TAye,M3N2TAze,M3N2RAxe,M3N2RAye,M3N2RAze, & - M3N3TAxe,M3N3TAye,M3N3TAze,M3N3RAxe,M3N3RAye,M3N3RAze, & - M3N4TAxe,M3N4TAye,M3N4TAze,M3N4RAxe,M3N4RAye,M3N4RAze, & - M3N5TAxe,M3N5TAye,M3N5TAze,M3N5RAxe,M3N5RAye,M3N5RAze, & - M3N6TAxe,M3N6TAye,M3N6TAze,M3N6RAxe,M3N6RAye,M3N6RAze, & - M3N7TAxe,M3N7TAye,M3N7TAze,M3N7RAxe,M3N7RAye,M3N7RAze, & - M3N8TAxe,M3N8TAye,M3N8TAze,M3N8RAxe,M3N8RAye,M3N8RAze, & - M3N9TAxe,M3N9TAye,M3N9TAze,M3N9RAxe,M3N9RAye,M3N9RAze, & - M4N1TAxe,M4N1TAye,M4N1TAze,M4N1RAxe,M4N1RAye,M4N1RAze, & - M4N2TAxe,M4N2TAye,M4N2TAze,M4N2RAxe,M4N2RAye,M4N2RAze, & - M4N3TAxe,M4N3TAye,M4N3TAze,M4N3RAxe,M4N3RAye,M4N3RAze, & - M4N4TAxe,M4N4TAye,M4N4TAze,M4N4RAxe,M4N4RAye,M4N4RAze, & - M4N5TAxe,M4N5TAye,M4N5TAze,M4N5RAxe,M4N5RAye,M4N5RAze, & - M4N6TAxe,M4N6TAye,M4N6TAze,M4N6RAxe,M4N6RAye,M4N6RAze, & - M4N7TAxe,M4N7TAye,M4N7TAze,M4N7RAxe,M4N7RAye,M4N7RAze, & - M4N8TAxe,M4N8TAye,M4N8TAze,M4N8RAxe,M4N8RAye,M4N8RAze, & - M4N9TAxe,M4N9TAye,M4N9TAze,M4N9RAxe,M4N9RAye,M4N9RAze, & - M5N1TAxe,M5N1TAye,M5N1TAze,M5N1RAxe,M5N1RAye,M5N1RAze, & - M5N2TAxe,M5N2TAye,M5N2TAze,M5N2RAxe,M5N2RAye,M5N2RAze, & - M5N3TAxe,M5N3TAye,M5N3TAze,M5N3RAxe,M5N3RAye,M5N3RAze, & - M5N4TAxe,M5N4TAye,M5N4TAze,M5N4RAxe,M5N4RAye,M5N4RAze, & - M5N5TAxe,M5N5TAye,M5N5TAze,M5N5RAxe,M5N5RAye,M5N5RAze, & - M5N6TAxe,M5N6TAye,M5N6TAze,M5N6RAxe,M5N6RAye,M5N6RAze, & - M5N7TAxe,M5N7TAye,M5N7TAze,M5N7RAxe,M5N7RAye,M5N7RAze, & - M5N8TAxe,M5N8TAye,M5N8TAze,M5N8RAxe,M5N8RAye,M5N8RAze, & - M5N9TAxe,M5N9TAye,M5N9TAze,M5N9RAxe,M5N9RAye,M5N9RAze, & - M6N1TAxe,M6N1TAye,M6N1TAze,M6N1RAxe,M6N1RAye,M6N1RAze, & - M6N2TAxe,M6N2TAye,M6N2TAze,M6N2RAxe,M6N2RAye,M6N2RAze, & - M6N3TAxe,M6N3TAye,M6N3TAze,M6N3RAxe,M6N3RAye,M6N3RAze, & - M6N4TAxe,M6N4TAye,M6N4TAze,M6N4RAxe,M6N4RAye,M6N4RAze, & - M6N5TAxe,M6N5TAye,M6N5TAze,M6N5RAxe,M6N5RAye,M6N5RAze, & - M6N6TAxe,M6N6TAye,M6N6TAze,M6N6RAxe,M6N6RAye,M6N6RAze, & - M6N7TAxe,M6N7TAye,M6N7TAze,M6N7RAxe,M6N7RAye,M6N7RAze, & - M6N8TAxe,M6N8TAye,M6N8TAze,M6N8RAxe,M6N8RAye,M6N8RAze, & - M6N9TAxe,M6N9TAye,M6N9TAze,M6N9RAxe,M6N9RAye,M6N9RAze, & - M7N1TAxe,M7N1TAye,M7N1TAze,M7N1RAxe,M7N1RAye,M7N1RAze, & - M7N2TAxe,M7N2TAye,M7N2TAze,M7N2RAxe,M7N2RAye,M7N2RAze, & - M7N3TAxe,M7N3TAye,M7N3TAze,M7N3RAxe,M7N3RAye,M7N3RAze, & - M7N4TAxe,M7N4TAye,M7N4TAze,M7N4RAxe,M7N4RAye,M7N4RAze, & - M7N5TAxe,M7N5TAye,M7N5TAze,M7N5RAxe,M7N5RAye,M7N5RAze, & - M7N6TAxe,M7N6TAye,M7N6TAze,M7N6RAxe,M7N6RAye,M7N6RAze, & - M7N7TAxe,M7N7TAye,M7N7TAze,M7N7RAxe,M7N7RAye,M7N7RAze, & - M7N8TAxe,M7N8TAye,M7N8TAze,M7N8RAxe,M7N8RAye,M7N8RAze, & - M7N9TAxe,M7N9TAye,M7N9TAze,M7N9RAxe,M7N9RAye,M7N9RAze, & - M8N1TAxe,M8N1TAye,M8N1TAze,M8N1RAxe,M8N1RAye,M8N1RAze, & - M8N2TAxe,M8N2TAye,M8N2TAze,M8N2RAxe,M8N2RAye,M8N2RAze, & - M8N3TAxe,M8N3TAye,M8N3TAze,M8N3RAxe,M8N3RAye,M8N3RAze, & - M8N4TAxe,M8N4TAye,M8N4TAze,M8N4RAxe,M8N4RAye,M8N4RAze, & - M8N5TAxe,M8N5TAye,M8N5TAze,M8N5RAxe,M8N5RAye,M8N5RAze, & - M8N6TAxe,M8N6TAye,M8N6TAze,M8N6RAxe,M8N6RAye,M8N6RAze, & - M8N7TAxe,M8N7TAye,M8N7TAze,M8N7RAxe,M8N7RAye,M8N7RAze, & - M8N8TAxe,M8N8TAye,M8N8TAze,M8N8RAxe,M8N8RAye,M8N8RAze, & - M8N9TAxe,M8N9TAye,M8N9TAze,M8N9RAxe,M8N9RAye,M8N9RAze, & - M9N1TAxe,M9N1TAye,M9N1TAze,M9N1RAxe,M9N1RAye,M9N1RAze, & - M9N2TAxe,M9N2TAye,M9N2TAze,M9N2RAxe,M9N2RAye,M9N2RAze, & - M9N3TAxe,M9N3TAye,M9N3TAze,M9N3RAxe,M9N3RAye,M9N3RAze, & - M9N4TAxe,M9N4TAye,M9N4TAze,M9N4RAxe,M9N4RAye,M9N4RAze, & - M9N5TAxe,M9N5TAye,M9N5TAze,M9N5RAxe,M9N5RAye,M9N5RAze, & - M9N6TAxe,M9N6TAye,M9N6TAze,M9N6RAxe,M9N6RAye,M9N6RAze, & - M9N7TAxe,M9N7TAye,M9N7TAze,M9N7RAxe,M9N7RAye,M9N7RAze, & - M9N8TAxe,M9N8TAye,M9N8TAze,M9N8RAxe,M9N8RAye,M9N8RAze, & - M9N9TAxe,M9N9TAye,M9N9TAze,M9N9RAxe,M9N9RAye,M9N9RAze/), (/6,9,9/)) - - INTEGER, PARAMETER :: ReactSS(6) = (/ReactFXss, ReactFYss, ReactFZss , & - ReactMXss, ReactMYss, ReactMZss/) - - INTEGER, PARAMETER :: IntfSS(6) = (/IntfFXss, IntfFYss, IntfFZss , & - IntfMXss, IntfMYss, IntfMZss/) - - - INTEGER, PARAMETER :: IntfTRss(6) = (/IntfTDXss, IntfTDYss, IntfTDZss , & - IntfRDXss, IntfRDYss, IntfRDZss/) - - INTEGER, PARAMETER :: IntfTRAss(6) = (/IntfTAXss, IntfTAYss, IntfTAZss , & - IntfRAXss, IntfRAYss, IntfRAZss/) - - - - - - - - CHARACTER(10), PARAMETER :: ValidParamAry(2265) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "INTFFXSS ","INTFFYSS ","INTFFZSS ","INTFMXSS ","INTFMYSS ","INTFMZSS ","INTFRAXSS", & - "INTFRAYSS","INTFRAZSS","INTFRDXSS","INTFRDYSS","INTFRDZSS","INTFTAXSS","INTFTAYSS", & - "INTFTAZSS","INTFTDXSS","INTFTDYSS","INTFTDZSS","M1N1FKXE ","M1N1FKYE ","M1N1FKZE ", & - "M1N1FMXE ","M1N1FMYE ","M1N1FMZE ","M1N1MKXE ","M1N1MKYE ","M1N1MKZE ","M1N1MMXE ", & - "M1N1MMYE ","M1N1MMZE ","M1N1RAXE ","M1N1RAYE ","M1N1RAZE ","M1N1RDXE ","M1N1RDYE ", & - "M1N1RDZE ","M1N1TAXE ","M1N1TAYE ","M1N1TAZE ","M1N1TDXSS","M1N1TDYSS","M1N1TDZSS", & - "M1N2FKXE ","M1N2FKYE ","M1N2FKZE ","M1N2FMXE ","M1N2FMYE ","M1N2FMZE ","M1N2MKXE ", & - "M1N2MKYE ","M1N2MKZE ","M1N2MMXE ","M1N2MMYE ","M1N2MMZE ","M1N2RAXE ","M1N2RAYE ", & - "M1N2RAZE ","M1N2RDXE ","M1N2RDYE ","M1N2RDZE ","M1N2TAXE ","M1N2TAYE ","M1N2TAZE ", & - "M1N2TDXSS","M1N2TDYSS","M1N2TDZSS","M1N3FKXE ","M1N3FKYE ","M1N3FKZE ","M1N3FMXE ", & - "M1N3FMYE ","M1N3FMZE ","M1N3MKXE ","M1N3MKYE ","M1N3MKZE ","M1N3MMXE ","M1N3MMYE ", & - "M1N3MMZE ","M1N3RAXE ","M1N3RAYE ","M1N3RAZE ","M1N3RDXE ","M1N3RDYE ","M1N3RDZE ", & - "M1N3TAXE ","M1N3TAYE ","M1N3TAZE ","M1N3TDXSS","M1N3TDYSS","M1N3TDZSS","M1N4FKXE ", & - "M1N4FKYE ","M1N4FKZE ","M1N4FMXE ","M1N4FMYE ","M1N4FMZE ","M1N4MKXE ","M1N4MKYE ", & - "M1N4MKZE ","M1N4MMXE ","M1N4MMYE ","M1N4MMZE ","M1N4RAXE ","M1N4RAYE ","M1N4RAZE ", & - "M1N4RDXE ","M1N4RDYE ","M1N4RDZE ","M1N4TAXE ","M1N4TAYE ","M1N4TAZE ","M1N4TDXSS", & - "M1N4TDYSS","M1N4TDZSS","M1N5FKXE ","M1N5FKYE ","M1N5FKZE ","M1N5FMXE ","M1N5FMYE ", & - "M1N5FMZE ","M1N5MKXE ","M1N5MKYE ","M1N5MKZE ","M1N5MMXE ","M1N5MMYE ","M1N5MMZE ", & - "M1N5RAXE ","M1N5RAYE ","M1N5RAZE ","M1N5RDXE ","M1N5RDYE ","M1N5RDZE ","M1N5TAXE ", & - "M1N5TAYE ","M1N5TAZE ","M1N5TDXSS","M1N5TDYSS","M1N5TDZSS","M1N6FKXE ","M1N6FKYE ", & - "M1N6FKZE ","M1N6FMXE ","M1N6FMYE ","M1N6FMZE ","M1N6MKXE ","M1N6MKYE ","M1N6MKZE ", & - "M1N6MMXE ","M1N6MMYE ","M1N6MMZE ","M1N6RAXE ","M1N6RAYE ","M1N6RAZE ","M1N6RDXE ", & - "M1N6RDYE ","M1N6RDZE ","M1N6TAXE ","M1N6TAYE ","M1N6TAZE ","M1N6TDXSS","M1N6TDYSS", & - "M1N6TDZSS","M1N7FKXE ","M1N7FKYE ","M1N7FKZE ","M1N7FMXE ","M1N7FMYE ","M1N7FMZE ", & - "M1N7MKXE ","M1N7MKYE ","M1N7MKZE ","M1N7MMXE ","M1N7MMYE ","M1N7MMZE ","M1N7RAXE ", & - "M1N7RAYE ","M1N7RAZE ","M1N7RDXE ","M1N7RDYE ","M1N7RDZE ","M1N7TAXE ","M1N7TAYE ", & - "M1N7TAZE ","M1N7TDXSS","M1N7TDYSS","M1N7TDZSS","M1N8FKXE ","M1N8FKYE ","M1N8FKZE ", & - "M1N8FMXE ","M1N8FMYE ","M1N8FMZE ","M1N8MKXE ","M1N8MKYE ","M1N8MKZE ","M1N8MMXE ", & - "M1N8MMYE ","M1N8MMZE ","M1N8RAXE ","M1N8RAYE ","M1N8RAZE ","M1N8RDXE ","M1N8RDYE ", & - "M1N8RDZE ","M1N8TAXE ","M1N8TAYE ","M1N8TAZE ","M1N8TDXSS","M1N8TDYSS","M1N8TDZSS", & - "M1N9FKXE ","M1N9FKYE ","M1N9FKZE ","M1N9FMXE ","M1N9FMYE ","M1N9FMZE ","M1N9MKXE ", & - "M1N9MKYE ","M1N9MKZE ","M1N9MMXE ","M1N9MMYE ","M1N9MMZE ","M1N9RAXE ","M1N9RAYE ", & - "M1N9RAZE ","M1N9RDXE ","M1N9RDYE ","M1N9RDZE ","M1N9TAXE ","M1N9TAYE ","M1N9TAZE ", & - "M1N9TDXSS","M1N9TDYSS","M1N9TDZSS","M2N1FKXE ","M2N1FKYE ","M2N1FKZE ","M2N1FMXE ", & - "M2N1FMYE ","M2N1FMZE ","M2N1MKXE ","M2N1MKYE ","M2N1MKZE ","M2N1MMXE ","M2N1MMYE ", & - "M2N1MMZE ","M2N1RAXE ","M2N1RAYE ","M2N1RAZE ","M2N1RDXE ","M2N1RDYE ","M2N1RDZE ", & - "M2N1TAXE ","M2N1TAYE ","M2N1TAZE ","M2N1TDXSS","M2N1TDYSS","M2N1TDZSS","M2N2FKXE ", & - "M2N2FKYE ","M2N2FKZE ","M2N2FMXE ","M2N2FMYE ","M2N2FMZE ","M2N2MKXE ","M2N2MKYE ", & - "M2N2MKZE ","M2N2MMXE ","M2N2MMYE ","M2N2MMZE ","M2N2RAXE ","M2N2RAYE ","M2N2RAZE ", & - "M2N2RDXE ","M2N2RDYE ","M2N2RDZE ","M2N2TAXE ","M2N2TAYE ","M2N2TAZE ","M2N2TDXSS", & - "M2N2TDYSS","M2N2TDZSS","M2N3FKXE ","M2N3FKYE ","M2N3FKZE ","M2N3FMXE ","M2N3FMYE ", & - "M2N3FMZE ","M2N3MKXE ","M2N3MKYE ","M2N3MKZE ","M2N3MMXE ","M2N3MMYE ","M2N3MMZE ", & - "M2N3RAXE ","M2N3RAYE ","M2N3RAZE ","M2N3RDXE ","M2N3RDYE ","M2N3RDZE ","M2N3TAXE ", & - "M2N3TAYE ","M2N3TAZE ","M2N3TDXSS","M2N3TDYSS","M2N3TDZSS","M2N4FKXE ","M2N4FKYE ", & - "M2N4FKZE ","M2N4FMXE ","M2N4FMYE ","M2N4FMZE ","M2N4MKXE ","M2N4MKYE ","M2N4MKZE ", & - "M2N4MMXE ","M2N4MMYE ","M2N4MMZE ","M2N4RAXE ","M2N4RAYE ","M2N4RAZE ","M2N4RDXE ", & - "M2N4RDYE ","M2N4RDZE ","M2N4TAXE ","M2N4TAYE ","M2N4TAZE ","M2N4TDXSS","M2N4TDYSS", & - "M2N4TDZSS","M2N5FKXE ","M2N5FKYE ","M2N5FKZE ","M2N5FMXE ","M2N5FMYE ","M2N5FMZE ", & - "M2N5MKXE ","M2N5MKYE ","M2N5MKZE ","M2N5MMXE ","M2N5MMYE ","M2N5MMZE ","M2N5RAXE ", & - "M2N5RAYE ","M2N5RAZE ","M2N5RDXE ","M2N5RDYE ","M2N5RDZE ","M2N5TAXE ","M2N5TAYE ", & - "M2N5TAZE ","M2N5TDXSS","M2N5TDYSS","M2N5TDZSS","M2N6FKXE ","M2N6FKYE ","M2N6FKZE ", & - "M2N6FMXE ","M2N6FMYE ","M2N6FMZE ","M2N6MKXE ","M2N6MKYE ","M2N6MKZE ","M2N6MMXE ", & - "M2N6MMYE ","M2N6MMZE ","M2N6RAXE ","M2N6RAYE ","M2N6RAZE ","M2N6RDXE ","M2N6RDYE ", & - "M2N6RDZE ","M2N6TAXE ","M2N6TAYE ","M2N6TAZE ","M2N6TDXSS","M2N6TDYSS","M2N6TDZSS", & - "M2N7FKXE ","M2N7FKYE ","M2N7FKZE ","M2N7FMXE ","M2N7FMYE ","M2N7FMZE ","M2N7MKXE ", & - "M2N7MKYE ","M2N7MKZE ","M2N7MMXE ","M2N7MMYE ","M2N7MMZE ","M2N7RAXE ","M2N7RAYE ", & - "M2N7RAZE ","M2N7RDXE ","M2N7RDYE ","M2N7RDZE ","M2N7TAXE ","M2N7TAYE ","M2N7TAZE ", & - "M2N7TDXSS","M2N7TDYSS","M2N7TDZSS","M2N8FKXE ","M2N8FKYE ","M2N8FKZE ","M2N8FMXE ", & - "M2N8FMYE ","M2N8FMZE ","M2N8MKXE ","M2N8MKYE ","M2N8MKZE ","M2N8MMXE ","M2N8MMYE ", & - "M2N8MMZE ","M2N8RAXE ","M2N8RAYE ","M2N8RAZE ","M2N8RDXE ","M2N8RDYE ","M2N8RDZE ", & - "M2N8TAXE ","M2N8TAYE ","M2N8TAZE ","M2N8TDXSS","M2N8TDYSS","M2N8TDZSS","M2N9FKXE ", & - "M2N9FKYE ","M2N9FKZE ","M2N9FMXE ","M2N9FMYE ","M2N9FMZE ","M2N9MKXE ","M2N9MKYE ", & - "M2N9MKZE ","M2N9MMXE ","M2N9MMYE ","M2N9MMZE ","M2N9RAXE ","M2N9RAYE ","M2N9RAZE ", & - "M2N9RDXE ","M2N9RDYE ","M2N9RDZE ","M2N9TAXE ","M2N9TAYE ","M2N9TAZE ","M2N9TDXSS", & - "M2N9TDYSS","M2N9TDZSS","M3N1FKXE ","M3N1FKYE ","M3N1FKZE ","M3N1FMXE ","M3N1FMYE ", & - "M3N1FMZE ","M3N1MKXE ","M3N1MKYE ","M3N1MKZE ","M3N1MMXE ","M3N1MMYE ","M3N1MMZE ", & - "M3N1RAXE ","M3N1RAYE ","M3N1RAZE ","M3N1RDXE ","M3N1RDYE ","M3N1RDZE ","M3N1TAXE ", & - "M3N1TAYE ","M3N1TAZE ","M3N1TDXSS","M3N1TDYSS","M3N1TDZSS","M3N2FKXE ","M3N2FKYE ", & - "M3N2FKZE ","M3N2FMXE ","M3N2FMYE ","M3N2FMZE ","M3N2MKXE ","M3N2MKYE ","M3N2MKZE ", & - "M3N2MMXE ","M3N2MMYE ","M3N2MMZE ","M3N2RAXE ","M3N2RAYE ","M3N2RAZE ","M3N2RDXE ", & - "M3N2RDYE ","M3N2RDZE ","M3N2TAXE ","M3N2TAYE ","M3N2TAZE ","M3N2TDXSS","M3N2TDYSS", & - "M3N2TDZSS","M3N3FKXE ","M3N3FKYE ","M3N3FKZE ","M3N3FMXE ","M3N3FMYE ","M3N3FMZE ", & - "M3N3MKXE ","M3N3MKYE ","M3N3MKZE ","M3N3MMXE ","M3N3MMYE ","M3N3MMZE ","M3N3RAXE ", & - "M3N3RAYE ","M3N3RAZE ","M3N3RDXE ","M3N3RDYE ","M3N3RDZE ","M3N3TAXE ","M3N3TAYE ", & - "M3N3TAZE ","M3N3TDXSS","M3N3TDYSS","M3N3TDZSS","M3N4FKXE ","M3N4FKYE ","M3N4FKZE ", & - "M3N4FMXE ","M3N4FMYE ","M3N4FMZE ","M3N4MKXE ","M3N4MKYE ","M3N4MKZE ","M3N4MMXE ", & - "M3N4MMYE ","M3N4MMZE ","M3N4RAXE ","M3N4RAYE ","M3N4RAZE ","M3N4RDXE ","M3N4RDYE ", & - "M3N4RDZE ","M3N4TAXE ","M3N4TAYE ","M3N4TAZE ","M3N4TDXSS","M3N4TDYSS","M3N4TDZSS", & - "M3N5FKXE ","M3N5FKYE ","M3N5FKZE ","M3N5FMXE ","M3N5FMYE ","M3N5FMZE ","M3N5MKXE ", & - "M3N5MKYE ","M3N5MKZE ","M3N5MMXE ","M3N5MMYE ","M3N5MMZE ","M3N5RAXE ","M3N5RAYE ", & - "M3N5RAZE ","M3N5RDXE ","M3N5RDYE ","M3N5RDZE ","M3N5TAXE ","M3N5TAYE ","M3N5TAZE ", & - "M3N5TDXSS","M3N5TDYSS","M3N5TDZSS","M3N6FKXE ","M3N6FKYE ","M3N6FKZE ","M3N6FMXE ", & - "M3N6FMYE ","M3N6FMZE ","M3N6MKXE ","M3N6MKYE ","M3N6MKZE ","M3N6MMXE ","M3N6MMYE ", & - "M3N6MMZE ","M3N6RAXE ","M3N6RAYE ","M3N6RAZE ","M3N6RDXE ","M3N6RDYE ","M3N6RDZE ", & - "M3N6TAXE ","M3N6TAYE ","M3N6TAZE ","M3N6TDXSS","M3N6TDYSS","M3N6TDZSS","M3N7FKXE ", & - "M3N7FKYE ","M3N7FKZE ","M3N7FMXE ","M3N7FMYE ","M3N7FMZE ","M3N7MKXE ","M3N7MKYE ", & - "M3N7MKZE ","M3N7MMXE ","M3N7MMYE ","M3N7MMZE ","M3N7RAXE ","M3N7RAYE ","M3N7RAZE ", & - "M3N7RDXE ","M3N7RDYE ","M3N7RDZE ","M3N7TAXE ","M3N7TAYE ","M3N7TAZE ","M3N7TDXSS", & - "M3N7TDYSS","M3N7TDZSS","M3N8FKXE ","M3N8FKYE ","M3N8FKZE ","M3N8FMXE ","M3N8FMYE ", & - "M3N8FMZE ","M3N8MKXE ","M3N8MKYE ","M3N8MKZE ","M3N8MMXE ","M3N8MMYE ","M3N8MMZE ", & - "M3N8RAXE ","M3N8RAYE ","M3N8RAZE ","M3N8RDXE ","M3N8RDYE ","M3N8RDZE ","M3N8TAXE ", & - "M3N8TAYE ","M3N8TAZE ","M3N8TDXSS","M3N8TDYSS","M3N8TDZSS","M3N9FKXE ","M3N9FKYE ", & - "M3N9FKZE ","M3N9FMXE ","M3N9FMYE ","M3N9FMZE ","M3N9MKXE ","M3N9MKYE ","M3N9MKZE ", & - "M3N9MMXE ","M3N9MMYE ","M3N9MMZE ","M3N9RAXE ","M3N9RAYE ","M3N9RAZE ","M3N9RDXE ", & - "M3N9RDYE ","M3N9RDZE ","M3N9TAXE ","M3N9TAYE ","M3N9TAZE ","M3N9TDXSS","M3N9TDYSS", & - "M3N9TDZSS","M4N1FKXE ","M4N1FKYE ","M4N1FKZE ","M4N1FMXE ","M4N1FMYE ","M4N1FMZE ", & - "M4N1MKXE ","M4N1MKYE ","M4N1MKZE ","M4N1MMXE ","M4N1MMYE ","M4N1MMZE ","M4N1RAXE ", & - "M4N1RAYE ","M4N1RAZE ","M4N1RDXE ","M4N1RDYE ","M4N1RDZE ","M4N1TAXE ","M4N1TAYE ", & - "M4N1TAZE ","M4N1TDXSS","M4N1TDYSS","M4N1TDZSS","M4N2FKXE ","M4N2FKYE ","M4N2FKZE ", & - "M4N2FMXE ","M4N2FMYE ","M4N2FMZE ","M4N2MKXE ","M4N2MKYE ","M4N2MKZE ","M4N2MMXE ", & - "M4N2MMYE ","M4N2MMZE ","M4N2RAXE ","M4N2RAYE ","M4N2RAZE ","M4N2RDXE ","M4N2RDYE ", & - "M4N2RDZE ","M4N2TAXE ","M4N2TAYE ","M4N2TAZE ","M4N2TDXSS","M4N2TDYSS","M4N2TDZSS", & - "M4N3FKXE ","M4N3FKYE ","M4N3FKZE ","M4N3FMXE ","M4N3FMYE ","M4N3FMZE ","M4N3MKXE ", & - "M4N3MKYE ","M4N3MKZE ","M4N3MMXE ","M4N3MMYE ","M4N3MMZE ","M4N3RAXE ","M4N3RAYE ", & - "M4N3RAZE ","M4N3RDXE ","M4N3RDYE ","M4N3RDZE ","M4N3TAXE ","M4N3TAYE ","M4N3TAZE ", & - "M4N3TDXSS","M4N3TDYSS","M4N3TDZSS","M4N4FKXE ","M4N4FKYE ","M4N4FKZE ","M4N4FMXE ", & - "M4N4FMYE ","M4N4FMZE ","M4N4MKXE ","M4N4MKYE ","M4N4MKZE ","M4N4MMXE ","M4N4MMYE ", & - "M4N4MMZE ","M4N4RAXE ","M4N4RAYE ","M4N4RAZE ","M4N4RDXE ","M4N4RDYE ","M4N4RDZE ", & - "M4N4TAXE ","M4N4TAYE ","M4N4TAZE ","M4N4TDXSS","M4N4TDYSS","M4N4TDZSS","M4N5FKXE ", & - "M4N5FKYE ","M4N5FKZE ","M4N5FMXE ","M4N5FMYE ","M4N5FMZE ","M4N5MKXE ","M4N5MKYE ", & - "M4N5MKZE ","M4N5MMXE ","M4N5MMYE ","M4N5MMZE ","M4N5RAXE ","M4N5RAYE ","M4N5RAZE ", & - "M4N5RDXE ","M4N5RDYE ","M4N5RDZE ","M4N5TAXE ","M4N5TAYE ","M4N5TAZE ","M4N5TDXSS", & - "M4N5TDYSS","M4N5TDZSS","M4N6FKXE ","M4N6FKYE ","M4N6FKZE ","M4N6FMXE ","M4N6FMYE ", & - "M4N6FMZE ","M4N6MKXE ","M4N6MKYE ","M4N6MKZE ","M4N6MMXE ","M4N6MMYE ","M4N6MMZE ", & - "M4N6RAXE ","M4N6RAYE ","M4N6RAZE ","M4N6RDXE ","M4N6RDYE ","M4N6RDZE ","M4N6TAXE ", & - "M4N6TAYE ","M4N6TAZE ","M4N6TDXSS","M4N6TDYSS","M4N6TDZSS","M4N7FKXE ","M4N7FKYE ", & - "M4N7FKZE ","M4N7FMXE ","M4N7FMYE ","M4N7FMZE ","M4N7MKXE ","M4N7MKYE ","M4N7MKZE ", & - "M4N7MMXE ","M4N7MMYE ","M4N7MMZE ","M4N7RAXE ","M4N7RAYE ","M4N7RAZE ","M4N7RDXE ", & - "M4N7RDYE ","M4N7RDZE ","M4N7TAXE ","M4N7TAYE ","M4N7TAZE ","M4N7TDXSS","M4N7TDYSS", & - "M4N7TDZSS","M4N8FKXE ","M4N8FKYE ","M4N8FKZE ","M4N8FMXE ","M4N8FMYE ","M4N8FMZE ", & - "M4N8MKXE ","M4N8MKYE ","M4N8MKZE ","M4N8MMXE ","M4N8MMYE ","M4N8MMZE ","M4N8RAXE ", & - "M4N8RAYE ","M4N8RAZE ","M4N8RDXE ","M4N8RDYE ","M4N8RDZE ","M4N8TAXE ","M4N8TAYE ", & - "M4N8TAZE ","M4N8TDXSS","M4N8TDYSS","M4N8TDZSS","M4N9FKXE ","M4N9FKYE ","M4N9FKZE ", & - "M4N9FMXE ","M4N9FMYE ","M4N9FMZE ","M4N9MKXE ","M4N9MKYE ","M4N9MKZE ","M4N9MMXE ", & - "M4N9MMYE ","M4N9MMZE ","M4N9RAXE ","M4N9RAYE ","M4N9RAZE ","M4N9RDXE ","M4N9RDYE ", & - "M4N9RDZE ","M4N9TAXE ","M4N9TAYE ","M4N9TAZE ","M4N9TDXSS","M4N9TDYSS","M4N9TDZSS", & - "M5N1FKXE ","M5N1FKYE ","M5N1FKZE ","M5N1FMXE ","M5N1FMYE ","M5N1FMZE ","M5N1MKXE ", & - "M5N1MKYE ","M5N1MKZE ","M5N1MMXE ","M5N1MMYE ","M5N1MMZE ","M5N1RAXE ","M5N1RAYE ", & - "M5N1RAZE ","M5N1RDXE ","M5N1RDYE ","M5N1RDZE ","M5N1TAXE ","M5N1TAYE ","M5N1TAZE ", & - "M5N1TDXSS","M5N1TDYSS","M5N1TDZSS","M5N2FKXE ","M5N2FKYE ","M5N2FKZE ","M5N2FMXE ", & - "M5N2FMYE ","M5N2FMZE ","M5N2MKXE ","M5N2MKYE ","M5N2MKZE ","M5N2MMXE ","M5N2MMYE ", & - "M5N2MMZE ","M5N2RAXE ","M5N2RAYE ","M5N2RAZE ","M5N2RDXE ","M5N2RDYE ","M5N2RDZE ", & - "M5N2TAXE ","M5N2TAYE ","M5N2TAZE ","M5N2TDXSS","M5N2TDYSS","M5N2TDZSS","M5N3FKXE ", & - "M5N3FKYE ","M5N3FKZE ","M5N3FMXE ","M5N3FMYE ","M5N3FMZE ","M5N3MKXE ","M5N3MKYE ", & - "M5N3MKZE ","M5N3MMXE ","M5N3MMYE ","M5N3MMZE ","M5N3RAXE ","M5N3RAYE ","M5N3RAZE ", & - "M5N3RDXE ","M5N3RDYE ","M5N3RDZE ","M5N3TAXE ","M5N3TAYE ","M5N3TAZE ","M5N3TDXSS", & - "M5N3TDYSS","M5N3TDZSS","M5N4FKXE ","M5N4FKYE ","M5N4FKZE ","M5N4FMXE ","M5N4FMYE ", & - "M5N4FMZE ","M5N4MKXE ","M5N4MKYE ","M5N4MKZE ","M5N4MMXE ","M5N4MMYE ","M5N4MMZE ", & - "M5N4RAXE ","M5N4RAYE ","M5N4RAZE ","M5N4RDXE ","M5N4RDYE ","M5N4RDZE ","M5N4TAXE ", & - "M5N4TAYE ","M5N4TAZE ","M5N4TDXSS","M5N4TDYSS","M5N4TDZSS","M5N5FKXE ","M5N5FKYE ", & - "M5N5FKZE ","M5N5FMXE ","M5N5FMYE ","M5N5FMZE ","M5N5MKXE ","M5N5MKYE ","M5N5MKZE ", & - "M5N5MMXE ","M5N5MMYE ","M5N5MMZE ","M5N5RAXE ","M5N5RAYE ","M5N5RAZE ","M5N5RDXE ", & - "M5N5RDYE ","M5N5RDZE ","M5N5TAXE ","M5N5TAYE ","M5N5TAZE ","M5N5TDXSS","M5N5TDYSS", & - "M5N5TDZSS","M5N6FKXE ","M5N6FKYE ","M5N6FKZE ","M5N6FMXE ","M5N6FMYE ","M5N6FMZE ", & - "M5N6MKXE ","M5N6MKYE ","M5N6MKZE ","M5N6MMXE ","M5N6MMYE ","M5N6MMZE ","M5N6RAXE ", & - "M5N6RAYE ","M5N6RAZE ","M5N6RDXE ","M5N6RDYE ","M5N6RDZE ","M5N6TAXE ","M5N6TAYE ", & - "M5N6TAZE ","M5N6TDXSS","M5N6TDYSS","M5N6TDZSS","M5N7FKXE ","M5N7FKYE ","M5N7FKZE ", & - "M5N7FMXE ","M5N7FMYE ","M5N7FMZE ","M5N7MKXE ","M5N7MKYE ","M5N7MKZE ","M5N7MMXE ", & - "M5N7MMYE ","M5N7MMZE ","M5N7RAXE ","M5N7RAYE ","M5N7RAZE ","M5N7RDXE ","M5N7RDYE ", & - "M5N7RDZE ","M5N7TAXE ","M5N7TAYE ","M5N7TAZE ","M5N7TDXSS","M5N7TDYSS","M5N7TDZSS", & - "M5N8FKXE ","M5N8FKYE ","M5N8FKZE ","M5N8FMXE ","M5N8FMYE ","M5N8FMZE ","M5N8MKXE ", & - "M5N8MKYE ","M5N8MKZE ","M5N8MMXE ","M5N8MMYE ","M5N8MMZE ","M5N8RAXE ","M5N8RAYE ", & - "M5N8RAZE ","M5N8RDXE ","M5N8RDYE ","M5N8RDZE ","M5N8TAXE ","M5N8TAYE ","M5N8TAZE ", & - "M5N8TDXSS","M5N8TDYSS","M5N8TDZSS","M5N9FKXE ","M5N9FKYE ","M5N9FKZE ","M5N9FMXE ", & - "M5N9FMYE ","M5N9FMZE ","M5N9MKXE ","M5N9MKYE ","M5N9MKZE ","M5N9MMXE ","M5N9MMYE ", & - "M5N9MMZE ","M5N9RAXE ","M5N9RAYE ","M5N9RAZE ","M5N9RDXE ","M5N9RDYE ","M5N9RDZE ", & - "M5N9TAXE ","M5N9TAYE ","M5N9TAZE ","M5N9TDXSS","M5N9TDYSS","M5N9TDZSS","M6N1FKXE ", & - "M6N1FKYE ","M6N1FKZE ","M6N1FMXE ","M6N1FMYE ","M6N1FMZE ","M6N1MKXE ","M6N1MKYE ", & - "M6N1MKZE ","M6N1MMXE ","M6N1MMYE ","M6N1MMZE ","M6N1RAXE ","M6N1RAYE ","M6N1RAZE ", & - "M6N1RDXE ","M6N1RDYE ","M6N1RDZE ","M6N1TAXE ","M6N1TAYE ","M6N1TAZE ","M6N1TDXSS", & - "M6N1TDYSS","M6N1TDZSS","M6N2FKXE ","M6N2FKYE ","M6N2FKZE ","M6N2FMXE ","M6N2FMYE ", & - "M6N2FMZE ","M6N2MKXE ","M6N2MKYE ","M6N2MKZE ","M6N2MMXE ","M6N2MMYE ","M6N2MMZE ", & - "M6N2RAXE ","M6N2RAYE ","M6N2RAZE ","M6N2RDXE ","M6N2RDYE ","M6N2RDZE ","M6N2TAXE ", & - "M6N2TAYE ","M6N2TAZE ","M6N2TDXSS","M6N2TDYSS","M6N2TDZSS","M6N3FKXE ","M6N3FKYE ", & - "M6N3FKZE ","M6N3FMXE ","M6N3FMYE ","M6N3FMZE ","M6N3MKXE ","M6N3MKYE ","M6N3MKZE ", & - "M6N3MMXE ","M6N3MMYE ","M6N3MMZE ","M6N3RAXE ","M6N3RAYE ","M6N3RAZE ","M6N3RDXE ", & - "M6N3RDYE ","M6N3RDZE ","M6N3TAXE ","M6N3TAYE ","M6N3TAZE ","M6N3TDXSS","M6N3TDYSS", & - "M6N3TDZSS","M6N4FKXE ","M6N4FKYE ","M6N4FKZE ","M6N4FMXE ","M6N4FMYE ","M6N4FMZE ", & - "M6N4MKXE ","M6N4MKYE ","M6N4MKZE ","M6N4MMXE ","M6N4MMYE ","M6N4MMZE ","M6N4RAXE ", & - "M6N4RAYE ","M6N4RAZE ","M6N4RDXE ","M6N4RDYE ","M6N4RDZE ","M6N4TAXE ","M6N4TAYE ", & - "M6N4TAZE ","M6N4TDXSS","M6N4TDYSS","M6N4TDZSS","M6N5FKXE ","M6N5FKYE ","M6N5FKZE ", & - "M6N5FMXE ","M6N5FMYE ","M6N5FMZE ","M6N5MKXE ","M6N5MKYE ","M6N5MKZE ","M6N5MMXE ", & - "M6N5MMYE ","M6N5MMZE ","M6N5RAXE ","M6N5RAYE ","M6N5RAZE ","M6N5RDXE ","M6N5RDYE ", & - "M6N5RDZE ","M6N5TAXE ","M6N5TAYE ","M6N5TAZE ","M6N5TDXSS","M6N5TDYSS","M6N5TDZSS", & - "M6N6FKXE ","M6N6FKYE ","M6N6FKZE ","M6N6FMXE ","M6N6FMYE ","M6N6FMZE ","M6N6MKXE ", & - "M6N6MKYE ","M6N6MKZE ","M6N6MMXE ","M6N6MMYE ","M6N6MMZE ","M6N6RAXE ","M6N6RAYE ", & - "M6N6RAZE ","M6N6RDXE ","M6N6RDYE ","M6N6RDZE ","M6N6TAXE ","M6N6TAYE ","M6N6TAZE ", & - "M6N6TDXSS","M6N6TDYSS","M6N6TDZSS","M6N7FKXE ","M6N7FKYE ","M6N7FKZE ","M6N7FMXE ", & - "M6N7FMYE ","M6N7FMZE ","M6N7MKXE ","M6N7MKYE ","M6N7MKZE ","M6N7MMXE ","M6N7MMYE ", & - "M6N7MMZE ","M6N7RAXE ","M6N7RAYE ","M6N7RAZE ","M6N7RDXE ","M6N7RDYE ","M6N7RDZE ", & - "M6N7TAXE ","M6N7TAYE ","M6N7TAZE ","M6N7TDXSS","M6N7TDYSS","M6N7TDZSS","M6N8FKXE ", & - "M6N8FKYE ","M6N8FKZE ","M6N8FMXE ","M6N8FMYE ","M6N8FMZE ","M6N8MKXE ","M6N8MKYE ", & - "M6N8MKZE ","M6N8MMXE ","M6N8MMYE ","M6N8MMZE ","M6N8RAXE ","M6N8RAYE ","M6N8RAZE ", & - "M6N8RDXE ","M6N8RDYE ","M6N8RDZE ","M6N8TAXE ","M6N8TAYE ","M6N8TAZE ","M6N8TDXSS", & - "M6N8TDYSS","M6N8TDZSS","M6N9FKXE ","M6N9FKYE ","M6N9FKZE ","M6N9FMXE ","M6N9FMYE ", & - "M6N9FMZE ","M6N9MKXE ","M6N9MKYE ","M6N9MKZE ","M6N9MMXE ","M6N9MMYE ","M6N9MMZE ", & - "M6N9RAXE ","M6N9RAYE ","M6N9RAZE ","M6N9RDXE ","M6N9RDYE ","M6N9RDZE ","M6N9TAXE ", & - "M6N9TAYE ","M6N9TAZE ","M6N9TDXSS","M6N9TDYSS","M6N9TDZSS","M7N1FKXE ","M7N1FKYE ", & - "M7N1FKZE ","M7N1FMXE ","M7N1FMYE ","M7N1FMZE ","M7N1MKXE ","M7N1MKYE ","M7N1MKZE ", & - "M7N1MMXE ","M7N1MMYE ","M7N1MMZE ","M7N1RAXE ","M7N1RAYE ","M7N1RAZE ","M7N1RDXE ", & - "M7N1RDYE ","M7N1RDZE ","M7N1TAXE ","M7N1TAYE ","M7N1TAZE ","M7N1TDXSS","M7N1TDYSS", & - "M7N1TDZSS","M7N2FKXE ","M7N2FKYE ","M7N2FKZE ","M7N2FMXE ","M7N2FMYE ","M7N2FMZE ", & - "M7N2MKXE ","M7N2MKYE ","M7N2MKZE ","M7N2MMXE ","M7N2MMYE ","M7N2MMZE ","M7N2RAXE ", & - "M7N2RAYE ","M7N2RAZE ","M7N2RDXE ","M7N2RDYE ","M7N2RDZE ","M7N2TAXE ","M7N2TAYE ", & - "M7N2TAZE ","M7N2TDXSS","M7N2TDYSS","M7N2TDZSS","M7N3FKXE ","M7N3FKYE ","M7N3FKZE ", & - "M7N3FMXE ","M7N3FMYE ","M7N3FMZE ","M7N3MKXE ","M7N3MKYE ","M7N3MKZE ","M7N3MMXE ", & - "M7N3MMYE ","M7N3MMZE ","M7N3RAXE ","M7N3RAYE ","M7N3RAZE ","M7N3RDXE ","M7N3RDYE ", & - "M7N3RDZE ","M7N3TAXE ","M7N3TAYE ","M7N3TAZE ","M7N3TDXSS","M7N3TDYSS","M7N3TDZSS", & - "M7N4FKXE ","M7N4FKYE ","M7N4FKZE ","M7N4FMXE ","M7N4FMYE ","M7N4FMZE ","M7N4MKXE ", & - "M7N4MKYE ","M7N4MKZE ","M7N4MMXE ","M7N4MMYE ","M7N4MMZE ","M7N4RAXE ","M7N4RAYE ", & - "M7N4RAZE ","M7N4RDXE ","M7N4RDYE ","M7N4RDZE ","M7N4TAXE ","M7N4TAYE ","M7N4TAZE ", & - "M7N4TDXSS","M7N4TDYSS","M7N4TDZSS","M7N5FKXE ","M7N5FKYE ","M7N5FKZE ","M7N5FMXE ", & - "M7N5FMYE ","M7N5FMZE ","M7N5MKXE ","M7N5MKYE ","M7N5MKZE ","M7N5MMXE ","M7N5MMYE ", & - "M7N5MMZE ","M7N5RAXE ","M7N5RAYE ","M7N5RAZE ","M7N5RDXE ","M7N5RDYE ","M7N5RDZE ", & - "M7N5TAXE ","M7N5TAYE ","M7N5TAZE ","M7N5TDXSS","M7N5TDYSS","M7N5TDZSS","M7N6FKXE ", & - "M7N6FKYE ","M7N6FKZE ","M7N6FMXE ","M7N6FMYE ","M7N6FMZE ","M7N6MKXE ","M7N6MKYE ", & - "M7N6MKZE ","M7N6MMXE ","M7N6MMYE ","M7N6MMZE ","M7N6RAXE ","M7N6RAYE ","M7N6RAZE ", & - "M7N6RDXE ","M7N6RDYE ","M7N6RDZE ","M7N6TAXE ","M7N6TAYE ","M7N6TAZE ","M7N6TDXSS", & - "M7N6TDYSS","M7N6TDZSS","M7N7FKXE ","M7N7FKYE ","M7N7FKZE ","M7N7FMXE ","M7N7FMYE ", & - "M7N7FMZE ","M7N7MKXE ","M7N7MKYE ","M7N7MKZE ","M7N7MMXE ","M7N7MMYE ","M7N7MMZE ", & - "M7N7RAXE ","M7N7RAYE ","M7N7RAZE ","M7N7RDXE ","M7N7RDYE ","M7N7RDZE ","M7N7TAXE ", & - "M7N7TAYE ","M7N7TAZE ","M7N7TDXSS","M7N7TDYSS","M7N7TDZSS","M7N8FKXE ","M7N8FKYE ", & - "M7N8FKZE ","M7N8FMXE ","M7N8FMYE ","M7N8FMZE ","M7N8MKXE ","M7N8MKYE ","M7N8MKZE ", & - "M7N8MMXE ","M7N8MMYE ","M7N8MMZE ","M7N8RAXE ","M7N8RAYE ","M7N8RAZE ","M7N8RDXE ", & - "M7N8RDYE ","M7N8RDZE ","M7N8TAXE ","M7N8TAYE ","M7N8TAZE ","M7N8TDXSS","M7N8TDYSS", & - "M7N8TDZSS","M7N9FKXE ","M7N9FKYE ","M7N9FKZE ","M7N9FMXE ","M7N9FMYE ","M7N9FMZE ", & - "M7N9MKXE ","M7N9MKYE ","M7N9MKZE ","M7N9MMXE ","M7N9MMYE ","M7N9MMZE ","M7N9RAXE ", & - "M7N9RAYE ","M7N9RAZE ","M7N9RDXE ","M7N9RDYE ","M7N9RDZE ","M7N9TAXE ","M7N9TAYE ", & - "M7N9TAZE ","M7N9TDXSS","M7N9TDYSS","M7N9TDZSS","M8N1FKXE ","M8N1FKYE ","M8N1FKZE ", & - "M8N1FMXE ","M8N1FMYE ","M8N1FMZE ","M8N1MKXE ","M8N1MKYE ","M8N1MKZE ","M8N1MMXE ", & - "M8N1MMYE ","M8N1MMZE ","M8N1RAXE ","M8N1RAYE ","M8N1RAZE ","M8N1RDXE ","M8N1RDYE ", & - "M8N1RDZE ","M8N1TAXE ","M8N1TAYE ","M8N1TAZE ","M8N1TDXSS","M8N1TDYSS","M8N1TDZSS", & - "M8N2FKXE ","M8N2FKYE ","M8N2FKZE ","M8N2FMXE ","M8N2FMYE ","M8N2FMZE ","M8N2MKXE ", & - "M8N2MKYE ","M8N2MKZE ","M8N2MMXE ","M8N2MMYE ","M8N2MMZE ","M8N2RAXE ","M8N2RAYE ", & - "M8N2RAZE ","M8N2RDXE ","M8N2RDYE ","M8N2RDZE ","M8N2TAXE ","M8N2TAYE ","M8N2TAZE ", & - "M8N2TDXSS","M8N2TDYSS","M8N2TDZSS","M8N3FKXE ","M8N3FKYE ","M8N3FKZE ","M8N3FMXE ", & - "M8N3FMYE ","M8N3FMZE ","M8N3MKXE ","M8N3MKYE ","M8N3MKZE ","M8N3MMXE ","M8N3MMYE ", & - "M8N3MMZE ","M8N3RAXE ","M8N3RAYE ","M8N3RAZE ","M8N3RDXE ","M8N3RDYE ","M8N3RDZE ", & - "M8N3TAXE ","M8N3TAYE ","M8N3TAZE ","M8N3TDXSS","M8N3TDYSS","M8N3TDZSS","M8N4FKXE ", & - "M8N4FKYE ","M8N4FKZE ","M8N4FMXE ","M8N4FMYE ","M8N4FMZE ","M8N4MKXE ","M8N4MKYE ", & - "M8N4MKZE ","M8N4MMXE ","M8N4MMYE ","M8N4MMZE ","M8N4RAXE ","M8N4RAYE ","M8N4RAZE ", & - "M8N4RDXE ","M8N4RDYE ","M8N4RDZE ","M8N4TAXE ","M8N4TAYE ","M8N4TAZE ","M8N4TDXSS", & - "M8N4TDYSS","M8N4TDZSS","M8N5FKXE ","M8N5FKYE ","M8N5FKZE ","M8N5FMXE ","M8N5FMYE ", & - "M8N5FMZE ","M8N5MKXE ","M8N5MKYE ","M8N5MKZE ","M8N5MMXE ","M8N5MMYE ","M8N5MMZE ", & - "M8N5RAXE ","M8N5RAYE ","M8N5RAZE ","M8N5RDXE ","M8N5RDYE ","M8N5RDZE ","M8N5TAXE ", & - "M8N5TAYE ","M8N5TAZE ","M8N5TDXSS","M8N5TDYSS","M8N5TDZSS","M8N6FKXE ","M8N6FKYE ", & - "M8N6FKZE ","M8N6FMXE ","M8N6FMYE ","M8N6FMZE ","M8N6MKXE ","M8N6MKYE ","M8N6MKZE ", & - "M8N6MMXE ","M8N6MMYE ","M8N6MMZE ","M8N6RAXE ","M8N6RAYE ","M8N6RAZE ","M8N6RDXE ", & - "M8N6RDYE ","M8N6RDZE ","M8N6TAXE ","M8N6TAYE ","M8N6TAZE ","M8N6TDXSS","M8N6TDYSS", & - "M8N6TDZSS","M8N7FKXE ","M8N7FKYE ","M8N7FKZE ","M8N7FMXE ","M8N7FMYE ","M8N7FMZE ", & - "M8N7MKXE ","M8N7MKYE ","M8N7MKZE ","M8N7MMXE ","M8N7MMYE ","M8N7MMZE ","M8N7RAXE ", & - "M8N7RAYE ","M8N7RAZE ","M8N7RDXE ","M8N7RDYE ","M8N7RDZE ","M8N7TAXE ","M8N7TAYE ", & - "M8N7TAZE ","M8N7TDXSS","M8N7TDYSS","M8N7TDZSS","M8N8FKXE ","M8N8FKYE ","M8N8FKZE ", & - "M8N8FMXE ","M8N8FMYE ","M8N8FMZE ","M8N8MKXE ","M8N8MKYE ","M8N8MKZE ","M8N8MMXE ", & - "M8N8MMYE ","M8N8MMZE ","M8N8RAXE ","M8N8RAYE ","M8N8RAZE ","M8N8RDXE ","M8N8RDYE ", & - "M8N8RDZE ","M8N8TAXE ","M8N8TAYE ","M8N8TAZE ","M8N8TDXSS","M8N8TDYSS","M8N8TDZSS", & - "M8N9FKXE ","M8N9FKYE ","M8N9FKZE ","M8N9FMXE ","M8N9FMYE ","M8N9FMZE ","M8N9MKXE ", & - "M8N9MKYE ","M8N9MKZE ","M8N9MMXE ","M8N9MMYE ","M8N9MMZE ","M8N9RAXE ","M8N9RAYE ", & - "M8N9RAZE ","M8N9RDXE ","M8N9RDYE ","M8N9RDZE ","M8N9TAXE ","M8N9TAYE ","M8N9TAZE ", & - "M8N9TDXSS","M8N9TDYSS","M8N9TDZSS","M9N1FKXE ","M9N1FKYE ","M9N1FKZE ","M9N1FMXE ", & - "M9N1FMYE ","M9N1FMZE ","M9N1MKXE ","M9N1MKYE ","M9N1MKZE ","M9N1MMXE ","M9N1MMYE ", & - "M9N1MMZE ","M9N1RAXE ","M9N1RAYE ","M9N1RAZE ","M9N1RDXE ","M9N1RDYE ","M9N1RDZE ", & - "M9N1TAXE ","M9N1TAYE ","M9N1TAZE ","M9N1TDXSS","M9N1TDYSS","M9N1TDZSS","M9N2FKXE ", & - "M9N2FKYE ","M9N2FKZE ","M9N2FMXE ","M9N2FMYE ","M9N2FMZE ","M9N2MKXE ","M9N2MKYE ", & - "M9N2MKZE ","M9N2MMXE ","M9N2MMYE ","M9N2MMZE ","M9N2RAXE ","M9N2RAYE ","M9N2RAZE ", & - "M9N2RDXE ","M9N2RDYE ","M9N2RDZE ","M9N2TAXE ","M9N2TAYE ","M9N2TAZE ","M9N2TDXSS", & - "M9N2TDYSS","M9N2TDZSS","M9N3FKXE ","M9N3FKYE ","M9N3FKZE ","M9N3FMXE ","M9N3FMYE ", & - "M9N3FMZE ","M9N3MKXE ","M9N3MKYE ","M9N3MKZE ","M9N3MMXE ","M9N3MMYE ","M9N3MMZE ", & - "M9N3RAXE ","M9N3RAYE ","M9N3RAZE ","M9N3RDXE ","M9N3RDYE ","M9N3RDZE ","M9N3TAXE ", & - "M9N3TAYE ","M9N3TAZE ","M9N3TDXSS","M9N3TDYSS","M9N3TDZSS","M9N4FKXE ","M9N4FKYE ", & - "M9N4FKZE ","M9N4FMXE ","M9N4FMYE ","M9N4FMZE ","M9N4MKXE ","M9N4MKYE ","M9N4MKZE ", & - "M9N4MMXE ","M9N4MMYE ","M9N4MMZE ","M9N4RAXE ","M9N4RAYE ","M9N4RAZE ","M9N4RDXE ", & - "M9N4RDYE ","M9N4RDZE ","M9N4TAXE ","M9N4TAYE ","M9N4TAZE ","M9N4TDXSS","M9N4TDYSS", & - "M9N4TDZSS","M9N5FKXE ","M9N5FKYE ","M9N5FKZE ","M9N5FMXE ","M9N5FMYE ","M9N5FMZE ", & - "M9N5MKXE ","M9N5MKYE ","M9N5MKZE ","M9N5MMXE ","M9N5MMYE ","M9N5MMZE ","M9N5RAXE ", & - "M9N5RAYE ","M9N5RAZE ","M9N5RDXE ","M9N5RDYE ","M9N5RDZE ","M9N5TAXE ","M9N5TAYE ", & - "M9N5TAZE ","M9N5TDXSS","M9N5TDYSS","M9N5TDZSS","M9N6FKXE ","M9N6FKYE ","M9N6FKZE ", & - "M9N6FMXE ","M9N6FMYE ","M9N6FMZE ","M9N6MKXE ","M9N6MKYE ","M9N6MKZE ","M9N6MMXE ", & - "M9N6MMYE ","M9N6MMZE ","M9N6RAXE ","M9N6RAYE ","M9N6RAZE ","M9N6RDXE ","M9N6RDYE ", & - "M9N6RDZE ","M9N6TAXE ","M9N6TAYE ","M9N6TAZE ","M9N6TDXSS","M9N6TDYSS","M9N6TDZSS", & - "M9N7FKXE ","M9N7FKYE ","M9N7FKZE ","M9N7FMXE ","M9N7FMYE ","M9N7FMZE ","M9N7MKXE ", & - "M9N7MKYE ","M9N7MKZE ","M9N7MMXE ","M9N7MMYE ","M9N7MMZE ","M9N7RAXE ","M9N7RAYE ", & - "M9N7RAZE ","M9N7RDXE ","M9N7RDYE ","M9N7RDZE ","M9N7TAXE ","M9N7TAYE ","M9N7TAZE ", & - "M9N7TDXSS","M9N7TDYSS","M9N7TDZSS","M9N8FKXE ","M9N8FKYE ","M9N8FKZE ","M9N8FMXE ", & - "M9N8FMYE ","M9N8FMZE ","M9N8MKXE ","M9N8MKYE ","M9N8MKZE ","M9N8MMXE ","M9N8MMYE ", & - "M9N8MMZE ","M9N8RAXE ","M9N8RAYE ","M9N8RAZE ","M9N8RDXE ","M9N8RDYE ","M9N8RDZE ", & - "M9N8TAXE ","M9N8TAYE ","M9N8TAZE ","M9N8TDXSS","M9N8TDYSS","M9N8TDZSS","M9N9FKXE ", & - "M9N9FKYE ","M9N9FKZE ","M9N9FMXE ","M9N9FMYE ","M9N9FMZE ","M9N9MKXE ","M9N9MKYE ", & - "M9N9MKZE ","M9N9MMXE ","M9N9MMYE ","M9N9MMZE ","M9N9RAXE ","M9N9RAYE ","M9N9RAZE ", & - "M9N9RDXE ","M9N9RDYE ","M9N9RDZE ","M9N9TAXE ","M9N9TAYE ","M9N9TAZE ","M9N9TDXSS", & - "M9N9TDYSS","M9N9TDZSS","REACTFXSS","REACTFYSS","REACTFZSS","REACTMXSS","REACTMYSS", & - "REACTMZSS","SSQM01 ","SSQM02 ","SSQM03 ","SSQM04 ","SSQM05 ","SSQM06 ", & - "SSQM07 ","SSQM08 ","SSQM09 ","SSQM10 ","SSQM11 ","SSQM12 ","SSQM13 ", & - "SSQM14 ","SSQM15 ","SSQM16 ","SSQM17 ","SSQM18 ","SSQM19 ","SSQM20 ", & - "SSQM21 ","SSQM22 ","SSQM23 ","SSQM24 ","SSQM25 ","SSQM26 ","SSQM27 ", & - "SSQM28 ","SSQM29 ","SSQM30 ","SSQM31 ","SSQM32 ","SSQM33 ","SSQM34 ", & - "SSQM35 ","SSQM36 ","SSQM37 ","SSQM38 ","SSQM39 ","SSQM40 ","SSQM41 ", & - "SSQM42 ","SSQM43 ","SSQM44 ","SSQM45 ","SSQM46 ","SSQM47 ","SSQM48 ", & - "SSQM49 ","SSQM50 ","SSQM51 ","SSQM52 ","SSQM53 ","SSQM54 ","SSQM55 ", & - "SSQM56 ","SSQM57 ","SSQM58 ","SSQM59 ","SSQM60 ","SSQM61 ","SSQM62 ", & - "SSQM63 ","SSQM64 ","SSQM65 ","SSQM66 ","SSQM67 ","SSQM68 ","SSQM69 ", & - "SSQM70 ","SSQM71 ","SSQM72 ","SSQM73 ","SSQM74 ","SSQM75 ","SSQM76 ", & - "SSQM77 ","SSQM78 ","SSQM79 ","SSQM80 ","SSQM81 ","SSQM82 ","SSQM83 ", & - "SSQM84 ","SSQM85 ","SSQM86 ","SSQM87 ","SSQM88 ","SSQM89 ","SSQM90 ", & - "SSQM91 ","SSQM92 ","SSQM93 ","SSQM94 ","SSQM95 ","SSQM96 ","SSQM97 ", & - "SSQM98 ","SSQM99 ","SSQMD01 ","SSQMD02 ","SSQMD03 ","SSQMD04 ","SSQMD05 ", & - "SSQMD06 ","SSQMD07 ","SSQMD08 ","SSQMD09 ","SSQMD10 ","SSQMD11 ","SSQMD12 ", & - "SSQMD13 ","SSQMD14 ","SSQMD15 ","SSQMD16 ","SSQMD17 ","SSQMD18 ","SSQMD19 ", & - "SSQMD20 ","SSQMD21 ","SSQMD22 ","SSQMD23 ","SSQMD24 ","SSQMD25 ","SSQMD26 ", & - "SSQMD27 ","SSQMD28 ","SSQMD29 ","SSQMD30 ","SSQMD31 ","SSQMD32 ","SSQMD33 ", & - "SSQMD34 ","SSQMD35 ","SSQMD36 ","SSQMD37 ","SSQMD38 ","SSQMD39 ","SSQMD40 ", & - "SSQMD41 ","SSQMD42 ","SSQMD43 ","SSQMD44 ","SSQMD45 ","SSQMD46 ","SSQMD47 ", & - "SSQMD48 ","SSQMD49 ","SSQMD50 ","SSQMD51 ","SSQMD52 ","SSQMD53 ","SSQMD54 ", & - "SSQMD55 ","SSQMD56 ","SSQMD57 ","SSQMD58 ","SSQMD59 ","SSQMD60 ","SSQMD61 ", & - "SSQMD62 ","SSQMD63 ","SSQMD64 ","SSQMD65 ","SSQMD66 ","SSQMD67 ","SSQMD68 ", & - "SSQMD69 ","SSQMD70 ","SSQMD71 ","SSQMD72 ","SSQMD73 ","SSQMD74 ","SSQMD75 ", & - "SSQMD76 ","SSQMD77 ","SSQMD78 ","SSQMD79 ","SSQMD80 ","SSQMD81 ","SSQMD82 ", & - "SSQMD83 ","SSQMD84 ","SSQMD85 ","SSQMD86 ","SSQMD87 ","SSQMD88 ","SSQMD89 ", & - "SSQMD90 ","SSQMD91 ","SSQMD92 ","SSQMD93 ","SSQMD94 ","SSQMD95 ","SSQMD96 ", & - "SSQMD97 ","SSQMD98 ","SSQMD99 ","SSQMDD01 ","SSQMDD02 ","SSQMDD03 ","SSQMDD04 ", & - "SSQMDD05 ","SSQMDD06 ","SSQMDD07 ","SSQMDD08 ","SSQMDD09 ","SSQMDD10 ","SSQMDD11 ", & - "SSQMDD12 ","SSQMDD13 ","SSQMDD14 ","SSQMDD15 ","SSQMDD16 ","SSQMDD17 ","SSQMDD18 ", & - "SSQMDD19 ","SSQMDD20 ","SSQMDD21 ","SSQMDD22 ","SSQMDD23 ","SSQMDD24 ","SSQMDD25 ", & - "SSQMDD26 ","SSQMDD27 ","SSQMDD28 ","SSQMDD29 ","SSQMDD30 ","SSQMDD31 ","SSQMDD32 ", & - "SSQMDD33 ","SSQMDD34 ","SSQMDD35 ","SSQMDD36 ","SSQMDD37 ","SSQMDD38 ","SSQMDD39 ", & - "SSQMDD40 ","SSQMDD41 ","SSQMDD42 ","SSQMDD43 ","SSQMDD44 ","SSQMDD45 ","SSQMDD46 ", & - "SSQMDD47 ","SSQMDD48 ","SSQMDD49 ","SSQMDD50 ","SSQMDD51 ","SSQMDD52 ","SSQMDD53 ", & - "SSQMDD54 ","SSQMDD55 ","SSQMDD56 ","SSQMDD57 ","SSQMDD58 ","SSQMDD59 ","SSQMDD60 ", & - "SSQMDD61 ","SSQMDD62 ","SSQMDD63 ","SSQMDD64 ","SSQMDD65 ","SSQMDD66 ","SSQMDD67 ", & - "SSQMDD68 ","SSQMDD69 ","SSQMDD70 ","SSQMDD71 ","SSQMDD72 ","SSQMDD73 ","SSQMDD74 ", & - "SSQMDD75 ","SSQMDD76 ","SSQMDD77 ","SSQMDD78 ","SSQMDD79 ","SSQMDD80 ","SSQMDD81 ", & - "SSQMDD82 ","SSQMDD83 ","SSQMDD84 ","SSQMDD85 ","SSQMDD86 ","SSQMDD87 ","SSQMDD88 ", & - "SSQMDD89 ","SSQMDD90 ","SSQMDD91 ","SSQMDD92 ","SSQMDD93 ","SSQMDD94 ","SSQMDD95 ", & - "SSQMDD96 ","SSQMDD97 ","SSQMDD98 ","SSQMDD99 "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(2265) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - IntfFXss , IntfFYss , IntfFZss , IntfMXss , IntfMYss , IntfMZss , IntfRAXss , & - IntfRAYss , IntfRAZss , IntfRDXss , IntfRDYss , IntfRDZss , IntfTAXss , IntfTAYss , & - IntfTAZss , IntfTDXss , IntfTDYss , IntfTDZss , M1N1FKxe , M1N1FKye , M1N1FKze , & - M1N1FMxe , M1N1FMye , M1N1FMze , M1N1MKxe , M1N1MKye , M1N1MKze , M1N1MMxe , & - M1N1MMye , M1N1MMze , M1N1RAxe , M1N1RAye , M1N1RAze , M1N1RDxe , M1N1RDye , & - M1N1RDze , M1N1TAxe , M1N1TAye , M1N1TAze , M1N1TDxss , M1N1TDyss , M1N1TDzss , & - M1N2FKxe , M1N2FKye , M1N2FKze , M1N2FMxe , M1N2FMye , M1N2FMze , M1N2MKxe , & - M1N2MKye , M1N2MKze , M1N2MMxe , M1N2MMye , M1N2MMze , M1N2RAxe , M1N2RAye , & - M1N2RAze , M1N2RDxe , M1N2RDye , M1N2RDze , M1N2TAxe , M1N2TAye , M1N2TAze , & - M1N2TDxss , M1N2TDyss , M1N2TDzss , M1N3FKxe , M1N3FKye , M1N3FKze , M1N3FMxe , & - M1N3FMye , M1N3FMze , M1N3MKxe , M1N3MKye , M1N3MKze , M1N3MMxe , M1N3MMye , & - M1N3MMze , M1N3RAxe , M1N3RAye , M1N3RAze , M1N3RDxe , M1N3RDye , M1N3RDze , & - M1N3TAxe , M1N3TAye , M1N3TAze , M1N3TDxss , M1N3TDyss , M1N3TDzss , M1N4FKxe , & - M1N4FKye , M1N4FKze , M1N4FMxe , M1N4FMye , M1N4FMze , M1N4MKxe , M1N4MKye , & - M1N4MKze , M1N4MMxe , M1N4MMye , M1N4MMze , M1N4RAxe , M1N4RAye , M1N4RAze , & - M1N4RDxe , M1N4RDye , M1N4RDze , M1N4TAxe , M1N4TAye , M1N4TAze , M1N4TDxss , & - M1N4TDyss , M1N4TDzss , M1N5FKxe , M1N5FKye , M1N5FKze , M1N5FMxe , M1N5FMye , & - M1N5FMze , M1N5MKxe , M1N5MKye , M1N5MKze , M1N5MMxe , M1N5MMye , M1N5MMze , & - M1N5RAxe , M1N5RAye , M1N5RAze , M1N5RDxe , M1N5RDye , M1N5RDze , M1N5TAxe , & - M1N5TAye , M1N5TAze , M1N5TDxss , M1N5TDyss , M1N5TDzss , M1N6FKxe , M1N6FKye , & - M1N6FKze , M1N6FMxe , M1N6FMye , M1N6FMze , M1N6MKxe , M1N6MKye , M1N6MKze , & - M1N6MMxe , M1N6MMye , M1N6MMze , M1N6RAxe , M1N6RAye , M1N6RAze , M1N6RDxe , & - M1N6RDye , M1N6RDze , M1N6TAxe , M1N6TAye , M1N6TAze , M1N6TDxss , M1N6TDyss , & - M1N6TDzss , M1N7FKxe , M1N7FKye , M1N7FKze , M1N7FMxe , M1N7FMye , M1N7FMze , & - M1N7MKxe , M1N7MKye , M1N7MKze , M1N7MMxe , M1N7MMye , M1N7MMze , M1N7RAxe , & - M1N7RAye , M1N7RAze , M1N7RDxe , M1N7RDye , M1N7RDze , M1N7TAxe , M1N7TAye , & - M1N7TAze , M1N7TDxss , M1N7TDyss , M1N7TDzss , M1N8FKxe , M1N8FKye , M1N8FKze , & - M1N8FMxe , M1N8FMye , M1N8FMze , M1N8MKxe , M1N8MKye , M1N8MKze , M1N8MMxe , & - M1N8MMye , M1N8MMze , M1N8RAxe , M1N8RAye , M1N8RAze , M1N8RDxe , M1N8RDye , & - M1N8RDze , M1N8TAxe , M1N8TAye , M1N8TAze , M1N8TDxss , M1N8TDyss , M1N8TDzss , & - M1N9FKxe , M1N9FKye , M1N9FKze , M1N9FMxe , M1N9FMye , M1N9FMze , M1N9MKxe , & - M1N9MKye , M1N9MKze , M1N9MMxe , M1N9MMye , M1N9MMze , M1N9RAxe , M1N9RAye , & - M1N9RAze , M1N9RDxe , M1N9RDye , M1N9RDze , M1N9TAxe , M1N9TAye , M1N9TAze , & - M1N9TDxss , M1N9TDyss , M1N9TDzss , M2N1FKxe , M2N1FKye , M2N1FKze , M2N1FMxe , & - M2N1FMye , M2N1FMze , M2N1MKxe , M2N1MKye , M2N1MKze , M2N1MMxe , M2N1MMye , & - M2N1MMze , M2N1RAxe , M2N1RAye , M2N1RAze , M2N1RDxe , M2N1RDye , M2N1RDze , & - M2N1TAxe , M2N1TAye , M2N1TAze , M2N1TDxss , M2N1TDyss , M2N1TDzss , M2N2FKxe , & - M2N2FKye , M2N2FKze , M2N2FMxe , M2N2FMye , M2N2FMze , M2N2MKxe , M2N2MKye , & - M2N2MKze , M2N2MMxe , M2N2MMye , M2N2MMze , M2N2RAxe , M2N2RAye , M2N2RAze , & - M2N2RDxe , M2N2RDye , M2N2RDze , M2N2TAxe , M2N2TAye , M2N2TAze , M2N2TDxss , & - M2N2TDyss , M2N2TDzss , M2N3FKxe , M2N3FKye , M2N3FKze , M2N3FMxe , M2N3FMye , & - M2N3FMze , M2N3MKxe , M2N3MKye , M2N3MKze , M2N3MMxe , M2N3MMye , M2N3MMze , & - M2N3RAxe , M2N3RAye , M2N3RAze , M2N3RDxe , M2N3RDye , M2N3RDze , M2N3TAxe , & - M2N3TAye , M2N3TAze , M2N3TDxss , M2N3TDyss , M2N3TDzss , M2N4FKxe , M2N4FKye , & - M2N4FKze , M2N4FMxe , M2N4FMye , M2N4FMze , M2N4MKxe , M2N4MKye , M2N4MKze , & - M2N4MMxe , M2N4MMye , M2N4MMze , M2N4RAxe , M2N4RAye , M2N4RAze , M2N4RDxe , & - M2N4RDye , M2N4RDze , M2N4TAxe , M2N4TAye , M2N4TAze , M2N4TDxss , M2N4TDyss , & - M2N4TDzss , M2N5FKxe , M2N5FKye , M2N5FKze , M2N5FMxe , M2N5FMye , M2N5FMze , & - M2N5MKxe , M2N5MKye , M2N5MKze , M2N5MMxe , M2N5MMye , M2N5MMze , M2N5RAxe , & - M2N5RAye , M2N5RAze , M2N5RDxe , M2N5RDye , M2N5RDze , M2N5TAxe , M2N5TAye , & - M2N5TAze , M2N5TDxss , M2N5TDyss , M2N5TDzss , M2N6FKxe , M2N6FKye , M2N6FKze , & - M2N6FMxe , M2N6FMye , M2N6FMze , M2N6MKxe , M2N6MKye , M2N6MKze , M2N6MMxe , & - M2N6MMye , M2N6MMze , M2N6RAxe , M2N6RAye , M2N6RAze , M2N6RDxe , M2N6RDye , & - M2N6RDze , M2N6TAxe , M2N6TAye , M2N6TAze , M2N6TDxss , M2N6TDyss , M2N6TDzss , & - M2N7FKxe , M2N7FKye , M2N7FKze , M2N7FMxe , M2N7FMye , M2N7FMze , M2N7MKxe , & - M2N7MKye , M2N7MKze , M2N7MMxe , M2N7MMye , M2N7MMze , M2N7RAxe , M2N7RAye , & - M2N7RAze , M2N7RDxe , M2N7RDye , M2N7RDze , M2N7TAxe , M2N7TAye , M2N7TAze , & - M2N7TDxss , M2N7TDyss , M2N7TDzss , M2N8FKxe , M2N8FKye , M2N8FKze , M2N8FMxe , & - M2N8FMye , M2N8FMze , M2N8MKxe , M2N8MKye , M2N8MKze , M2N8MMxe , M2N8MMye , & - M2N8MMze , M2N8RAxe , M2N8RAye , M2N8RAze , M2N8RDxe , M2N8RDye , M2N8RDze , & - M2N8TAxe , M2N8TAye , M2N8TAze , M2N8TDxss , M2N8TDyss , M2N8TDzss , M2N9FKxe , & - M2N9FKye , M2N9FKze , M2N9FMxe , M2N9FMye , M2N9FMze , M2N9MKxe , M2N9MKye , & - M2N9MKze , M2N9MMxe , M2N9MMye , M2N9MMze , M2N9RAxe , M2N9RAye , M2N9RAze , & - M2N9RDxe , M2N9RDye , M2N9RDze , M2N9TAxe , M2N9TAye , M2N9TAze , M2N9TDxss , & - M2N9TDyss , M2N9TDzss , M3N1FKxe , M3N1FKye , M3N1FKze , M3N1FMxe , M3N1FMye , & - M3N1FMze , M3N1MKxe , M3N1MKye , M3N1MKze , M3N1MMxe , M3N1MMye , M3N1MMze , & - M3N1RAxe , M3N1RAye , M3N1RAze , M3N1RDxe , M3N1RDye , M3N1RDze , M3N1TAxe , & - M3N1TAye , M3N1TAze , M3N1TDxss , M3N1TDyss , M3N1TDzss , M3N2FKxe , M3N2FKye , & - M3N2FKze , M3N2FMxe , M3N2FMye , M3N2FMze , M3N2MKxe , M3N2MKye , M3N2MKze , & - M3N2MMxe , M3N2MMye , M3N2MMze , M3N2RAxe , M3N2RAye , M3N2RAze , M3N2RDxe , & - M3N2RDye , M3N2RDze , M3N2TAxe , M3N2TAye , M3N2TAze , M3N2TDxss , M3N2TDyss , & - M3N2TDzss , M3N3FKxe , M3N3FKye , M3N3FKze , M3N3FMxe , M3N3FMye , M3N3FMze , & - M3N3MKxe , M3N3MKye , M3N3MKze , M3N3MMxe , M3N3MMye , M3N3MMze , M3N3RAxe , & - M3N3RAye , M3N3RAze , M3N3RDxe , M3N3RDye , M3N3RDze , M3N3TAxe , M3N3TAye , & - M3N3TAze , M3N3TDxss , M3N3TDyss , M3N3TDzss , M3N4FKxe , M3N4FKye , M3N4FKze , & - M3N4FMxe , M3N4FMye , M3N4FMze , M3N4MKxe , M3N4MKye , M3N4MKze , M3N4MMxe , & - M3N4MMye , M3N4MMze , M3N4RAxe , M3N4RAye , M3N4RAze , M3N4RDxe , M3N4RDye , & - M3N4RDze , M3N4TAxe , M3N4TAye , M3N4TAze , M3N4TDxss , M3N4TDyss , M3N4TDzss , & - M3N5FKxe , M3N5FKye , M3N5FKze , M3N5FMxe , M3N5FMye , M3N5FMze , M3N5MKxe , & - M3N5MKye , M3N5MKze , M3N5MMxe , M3N5MMye , M3N5MMze , M3N5RAxe , M3N5RAye , & - M3N5RAze , M3N5RDxe , M3N5RDye , M3N5RDze , M3N5TAxe , M3N5TAye , M3N5TAze , & - M3N5TDxss , M3N5TDyss , M3N5TDzss , M3N6FKxe , M3N6FKye , M3N6FKze , M3N6FMxe , & - M3N6FMye , M3N6FMze , M3N6MKxe , M3N6MKye , M3N6MKze , M3N6MMxe , M3N6MMye , & - M3N6MMze , M3N6RAxe , M3N6RAye , M3N6RAze , M3N6RDxe , M3N6RDye , M3N6RDze , & - M3N6TAxe , M3N6TAye , M3N6TAze , M3N6TDxss , M3N6TDyss , M3N6TDzss , M3N7FKxe , & - M3N7FKye , M3N7FKze , M3N7FMxe , M3N7FMye , M3N7FMze , M3N7MKxe , M3N7MKye , & - M3N7MKze , M3N7MMxe , M3N7MMye , M3N7MMze , M3N7RAxe , M3N7RAye , M3N7RAze , & - M3N7RDxe , M3N7RDye , M3N7RDze , M3N7TAxe , M3N7TAye , M3N7TAze , M3N7TDxss , & - M3N7TDyss , M3N7TDzss , M3N8FKxe , M3N8FKye , M3N8FKze , M3N8FMxe , M3N8FMye , & - M3N8FMze , M3N8MKxe , M3N8MKye , M3N8MKze , M3N8MMxe , M3N8MMye , M3N8MMze , & - M3N8RAxe , M3N8RAye , M3N8RAze , M3N8RDxe , M3N8RDye , M3N8RDze , M3N8TAxe , & - M3N8TAye , M3N8TAze , M3N8TDxss , M3N8TDyss , M3N8TDzss , M3N9FKxe , M3N9FKye , & - M3N9FKze , M3N9FMxe , M3N9FMye , M3N9FMze , M3N9MKxe , M3N9MKye , M3N9MKze , & - M3N9MMxe , M3N9MMye , M3N9MMze , M3N9RAxe , M3N9RAye , M3N9RAze , M3N9RDxe , & - M3N9RDye , M3N9RDze , M3N9TAxe , M3N9TAye , M3N9TAze , M3N9TDxss , M3N9TDyss , & - M3N9TDzss , M4N1FKxe , M4N1FKye , M4N1FKze , M4N1FMxe , M4N1FMye , M4N1FMze , & - M4N1MKxe , M4N1MKye , M4N1MKze , M4N1MMxe , M4N1MMye , M4N1MMze , M4N1RAxe , & - M4N1RAye , M4N1RAze , M4N1RDxe , M4N1RDye , M4N1RDze , M4N1TAxe , M4N1TAye , & - M4N1TAze , M4N1TDxss , M4N1TDyss , M4N1TDzss , M4N2FKxe , M4N2FKye , M4N2FKze , & - M4N2FMxe , M4N2FMye , M4N2FMze , M4N2MKxe , M4N2MKye , M4N2MKze , M4N2MMxe , & - M4N2MMye , M4N2MMze , M4N2RAxe , M4N2RAye , M4N2RAze , M4N2RDxe , M4N2RDye , & - M4N2RDze , M4N2TAxe , M4N2TAye , M4N2TAze , M4N2TDxss , M4N2TDyss , M4N2TDzss , & - M4N3FKxe , M4N3FKye , M4N3FKze , M4N3FMxe , M4N3FMye , M4N3FMze , M4N3MKxe , & - M4N3MKye , M4N3MKze , M4N3MMxe , M4N3MMye , M4N3MMze , M4N3RAxe , M4N3RAye , & - M4N3RAze , M4N3RDxe , M4N3RDye , M4N3RDze , M4N3TAxe , M4N3TAye , M4N3TAze , & - M4N3TDxss , M4N3TDyss , M4N3TDzss , M4N4FKxe , M4N4FKye , M4N4FKze , M4N4FMxe , & - M4N4FMye , M4N4FMze , M4N4MKxe , M4N4MKye , M4N4MKze , M4N4MMxe , M4N4MMye , & - M4N4MMze , M4N4RAxe , M4N4RAye , M4N4RAze , M4N4RDxe , M4N4RDye , M4N4RDze , & - M4N4TAxe , M4N4TAye , M4N4TAze , M4N4TDxss , M4N4TDyss , M4N4TDzss , M4N5FKxe , & - M4N5FKye , M4N5FKze , M4N5FMxe , M4N5FMye , M4N5FMze , M4N5MKxe , M4N5MKye , & - M4N5MKze , M4N5MMxe , M4N5MMye , M4N5MMze , M4N5RAxe , M4N5RAye , M4N5RAze , & - M4N5RDxe , M4N5RDye , M4N5RDze , M4N5TAxe , M4N5TAye , M4N5TAze , M4N5TDxss , & - M4N5TDyss , M4N5TDzss , M4N6FKxe , M4N6FKye , M4N6FKze , M4N6FMxe , M4N6FMye , & - M4N6FMze , M4N6MKxe , M4N6MKye , M4N6MKze , M4N6MMxe , M4N6MMye , M4N6MMze , & - M4N6RAxe , M4N6RAye , M4N6RAze , M4N6RDxe , M4N6RDye , M4N6RDze , M4N6TAxe , & - M4N6TAye , M4N6TAze , M4N6TDxss , M4N6TDyss , M4N6TDzss , M4N7FKxe , M4N7FKye , & - M4N7FKze , M4N7FMxe , M4N7FMye , M4N7FMze , M4N7MKxe , M4N7MKye , M4N7MKze , & - M4N7MMxe , M4N7MMye , M4N7MMze , M4N7RAxe , M4N7RAye , M4N7RAze , M4N7RDxe , & - M4N7RDye , M4N7RDze , M4N7TAxe , M4N7TAye , M4N7TAze , M4N7TDxss , M4N7TDyss , & - M4N7TDzss , M4N8FKxe , M4N8FKye , M4N8FKze , M4N8FMxe , M4N8FMye , M4N8FMze , & - M4N8MKxe , M4N8MKye , M4N8MKze , M4N8MMxe , M4N8MMye , M4N8MMze , M4N8RAxe , & - M4N8RAye , M4N8RAze , M4N8RDxe , M4N8RDye , M4N8RDze , M4N8TAxe , M4N8TAye , & - M4N8TAze , M4N8TDxss , M4N8TDyss , M4N8TDzss , M4N9FKxe , M4N9FKye , M4N9FKze , & - M4N9FMxe , M4N9FMye , M4N9FMze , M4N9MKxe , M4N9MKye , M4N9MKze , M4N9MMxe , & - M4N9MMye , M4N9MMze , M4N9RAxe , M4N9RAye , M4N9RAze , M4N9RDxe , M4N9RDye , & - M4N9RDze , M4N9TAxe , M4N9TAye , M4N9TAze , M4N9TDxss , M4N9TDyss , M4N9TDzss , & - M5N1FKxe , M5N1FKye , M5N1FKze , M5N1FMxe , M5N1FMye , M5N1FMze , M5N1MKxe , & - M5N1MKye , M5N1MKze , M5N1MMxe , M5N1MMye , M5N1MMze , M5N1RAxe , M5N1RAye , & - M5N1RAze , M5N1RDxe , M5N1RDye , M5N1RDze , M5N1TAxe , M5N1TAye , M5N1TAze , & - M5N1TDxss , M5N1TDyss , M5N1TDzss , M5N2FKxe , M5N2FKye , M5N2FKze , M5N2FMxe , & - M5N2FMye , M5N2FMze , M5N2MKxe , M5N2MKye , M5N2MKze , M5N2MMxe , M5N2MMye , & - M5N2MMze , M5N2RAxe , M5N2RAye , M5N2RAze , M5N2RDxe , M5N2RDye , M5N2RDze , & - M5N2TAxe , M5N2TAye , M5N2TAze , M5N2TDxss , M5N2TDyss , M5N2TDzss , M5N3FKxe , & - M5N3FKye , M5N3FKze , M5N3FMxe , M5N3FMye , M5N3FMze , M5N3MKxe , M5N3MKye , & - M5N3MKze , M5N3MMxe , M5N3MMye , M5N3MMze , M5N3RAxe , M5N3RAye , M5N3RAze , & - M5N3RDxe , M5N3RDye , M5N3RDze , M5N3TAxe , M5N3TAye , M5N3TAze , M5N3TDxss , & - M5N3TDyss , M5N3TDzss , M5N4FKxe , M5N4FKye , M5N4FKze , M5N4FMxe , M5N4FMye , & - M5N4FMze , M5N4MKxe , M5N4MKye , M5N4MKze , M5N4MMxe , M5N4MMye , M5N4MMze , & - M5N4RAxe , M5N4RAye , M5N4RAze , M5N4RDxe , M5N4RDye , M5N4RDze , M5N4TAxe , & - M5N4TAye , M5N4TAze , M5N4TDxss , M5N4TDyss , M5N4TDzss , M5N5FKxe , M5N5FKye , & - M5N5FKze , M5N5FMxe , M5N5FMye , M5N5FMze , M5N5MKxe , M5N5MKye , M5N5MKze , & - M5N5MMxe , M5N5MMye , M5N5MMze , M5N5RAxe , M5N5RAye , M5N5RAze , M5N5RDxe , & - M5N5RDye , M5N5RDze , M5N5TAxe , M5N5TAye , M5N5TAze , M5N5TDxss , M5N5TDyss , & - M5N5TDzss , M5N6FKxe , M5N6FKye , M5N6FKze , M5N6FMxe , M5N6FMye , M5N6FMze , & - M5N6MKxe , M5N6MKye , M5N6MKze , M5N6MMxe , M5N6MMye , M5N6MMze , M5N6RAxe , & - M5N6RAye , M5N6RAze , M5N6RDxe , M5N6RDye , M5N6RDze , M5N6TAxe , M5N6TAye , & - M5N6TAze , M5N6TDxss , M5N6TDyss , M5N6TDzss , M5N7FKxe , M5N7FKye , M5N7FKze , & - M5N7FMxe , M5N7FMye , M5N7FMze , M5N7MKxe , M5N7MKye , M5N7MKze , M5N7MMxe , & - M5N7MMye , M5N7MMze , M5N7RAxe , M5N7RAye , M5N7RAze , M5N7RDxe , M5N7RDye , & - M5N7RDze , M5N7TAxe , M5N7TAye , M5N7TAze , M5N7TDxss , M5N7TDyss , M5N7TDzss , & - M5N8FKxe , M5N8FKye , M5N8FKze , M5N8FMxe , M5N8FMye , M5N8FMze , M5N8MKxe , & - M5N8MKye , M5N8MKze , M5N8MMxe , M5N8MMye , M5N8MMze , M5N8RAxe , M5N8RAye , & - M5N8RAze , M5N8RDxe , M5N8RDye , M5N8RDze , M5N8TAxe , M5N8TAye , M5N8TAze , & - M5N8TDxss , M5N8TDyss , M5N8TDzss , M5N9FKxe , M5N9FKye , M5N9FKze , M5N9FMxe , & - M5N9FMye , M5N9FMze , M5N9MKxe , M5N9MKye , M5N9MKze , M5N9MMxe , M5N9MMye , & - M5N9MMze , M5N9RAxe , M5N9RAye , M5N9RAze , M5N9RDxe , M5N9RDye , M5N9RDze , & - M5N9TAxe , M5N9TAye , M5N9TAze , M5N9TDxss , M5N9TDyss , M5N9TDzss , M6N1FKxe , & - M6N1FKye , M6N1FKze , M6N1FMxe , M6N1FMye , M6N1FMze , M6N1MKxe , M6N1MKye , & - M6N1MKze , M6N1MMxe , M6N1MMye , M6N1MMze , M6N1RAxe , M6N1RAye , M6N1RAze , & - M6N1RDxe , M6N1RDye , M6N1RDze , M6N1TAxe , M6N1TAye , M6N1TAze , M6N1TDxss , & - M6N1TDyss , M6N1TDzss , M6N2FKxe , M6N2FKye , M6N2FKze , M6N2FMxe , M6N2FMye , & - M6N2FMze , M6N2MKxe , M6N2MKye , M6N2MKze , M6N2MMxe , M6N2MMye , M6N2MMze , & - M6N2RAxe , M6N2RAye , M6N2RAze , M6N2RDxe , M6N2RDye , M6N2RDze , M6N2TAxe , & - M6N2TAye , M6N2TAze , M6N2TDxss , M6N2TDyss , M6N2TDzss , M6N3FKxe , M6N3FKye , & - M6N3FKze , M6N3FMxe , M6N3FMye , M6N3FMze , M6N3MKxe , M6N3MKye , M6N3MKze , & - M6N3MMxe , M6N3MMye , M6N3MMze , M6N3RAxe , M6N3RAye , M6N3RAze , M6N3RDxe , & - M6N3RDye , M6N3RDze , M6N3TAxe , M6N3TAye , M6N3TAze , M6N3TDxss , M6N3TDyss , & - M6N3TDzss , M6N4FKxe , M6N4FKye , M6N4FKze , M6N4FMxe , M6N4FMye , M6N4FMze , & - M6N4MKxe , M6N4MKye , M6N4MKze , M6N4MMxe , M6N4MMye , M6N4MMze , M6N4RAxe , & - M6N4RAye , M6N4RAze , M6N4RDxe , M6N4RDye , M6N4RDze , M6N4TAxe , M6N4TAye , & - M6N4TAze , M6N4TDxss , M6N4TDyss , M6N4TDzss , M6N5FKxe , M6N5FKye , M6N5FKze , & - M6N5FMxe , M6N5FMye , M6N5FMze , M6N5MKxe , M6N5MKye , M6N5MKze , M6N5MMxe , & - M6N5MMye , M6N5MMze , M6N5RAxe , M6N5RAye , M6N5RAze , M6N5RDxe , M6N5RDye , & - M6N5RDze , M6N5TAxe , M6N5TAye , M6N5TAze , M6N5TDxss , M6N5TDyss , M6N5TDzss , & - M6N6FKxe , M6N6FKye , M6N6FKze , M6N6FMxe , M6N6FMye , M6N6FMze , M6N6MKxe , & - M6N6MKye , M6N6MKze , M6N6MMxe , M6N6MMye , M6N6MMze , M6N6RAxe , M6N6RAye , & - M6N6RAze , M6N6RDxe , M6N6RDye , M6N6RDze , M6N6TAxe , M6N6TAye , M6N6TAze , & - M6N6TDxss , M6N6TDyss , M6N6TDzss , M6N7FKxe , M6N7FKye , M6N7FKze , M6N7FMxe , & - M6N7FMye , M6N7FMze , M6N7MKxe , M6N7MKye , M6N7MKze , M6N7MMxe , M6N7MMye , & - M6N7MMze , M6N7RAxe , M6N7RAye , M6N7RAze , M6N7RDxe , M6N7RDye , M6N7RDze , & - M6N7TAxe , M6N7TAye , M6N7TAze , M6N7TDxss , M6N7TDyss , M6N7TDzss , M6N8FKxe , & - M6N8FKye , M6N8FKze , M6N8FMxe , M6N8FMye , M6N8FMze , M6N8MKxe , M6N8MKye , & - M6N8MKze , M6N8MMxe , M6N8MMye , M6N8MMze , M6N8RAxe , M6N8RAye , M6N8RAze , & - M6N8RDxe , M6N8RDye , M6N8RDze , M6N8TAxe , M6N8TAye , M6N8TAze , M6N8TDxss , & - M6N8TDyss , M6N8TDzss , M6N9FKxe , M6N9FKye , M6N9FKze , M6N9FMxe , M6N9FMye , & - M6N9FMze , M6N9MKxe , M6N9MKye , M6N9MKze , M6N9MMxe , M6N9MMye , M6N9MMze , & - M6N9RAxe , M6N9RAye , M6N9RAze , M6N9RDxe , M6N9RDye , M6N9RDze , M6N9TAxe , & - M6N9TAye , M6N9TAze , M6N9TDxss , M6N9TDyss , M6N9TDzss , M7N1FKxe , M7N1FKye , & - M7N1FKze , M7N1FMxe , M7N1FMye , M7N1FMze , M7N1MKxe , M7N1MKye , M7N1MKze , & - M7N1MMxe , M7N1MMye , M7N1MMze , M7N1RAxe , M7N1RAye , M7N1RAze , M7N1RDxe , & - M7N1RDye , M7N1RDze , M7N1TAxe , M7N1TAye , M7N1TAze , M7N1TDxss , M7N1TDyss , & - M7N1TDzss , M7N2FKxe , M7N2FKye , M7N2FKze , M7N2FMxe , M7N2FMye , M7N2FMze , & - M7N2MKxe , M7N2MKye , M7N2MKze , M7N2MMxe , M7N2MMye , M7N2MMze , M7N2RAxe , & - M7N2RAye , M7N2RAze , M7N2RDxe , M7N2RDye , M7N2RDze , M7N2TAxe , M7N2TAye , & - M7N2TAze , M7N2TDxss , M7N2TDyss , M7N2TDzss , M7N3FKxe , M7N3FKye , M7N3FKze , & - M7N3FMxe , M7N3FMye , M7N3FMze , M7N3MKxe , M7N3MKye , M7N3MKze , M7N3MMxe , & - M7N3MMye , M7N3MMze , M7N3RAxe , M7N3RAye , M7N3RAze , M7N3RDxe , M7N3RDye , & - M7N3RDze , M7N3TAxe , M7N3TAye , M7N3TAze , M7N3TDxss , M7N3TDyss , M7N3TDzss , & - M7N4FKxe , M7N4FKye , M7N4FKze , M7N4FMxe , M7N4FMye , M7N4FMze , M7N4MKxe , & - M7N4MKye , M7N4MKze , M7N4MMxe , M7N4MMye , M7N4MMze , M7N4RAxe , M7N4RAye , & - M7N4RAze , M7N4RDxe , M7N4RDye , M7N4RDze , M7N4TAxe , M7N4TAye , M7N4TAze , & - M7N4TDxss , M7N4TDyss , M7N4TDzss , M7N5FKxe , M7N5FKye , M7N5FKze , M7N5FMxe , & - M7N5FMye , M7N5FMze , M7N5MKxe , M7N5MKye , M7N5MKze , M7N5MMxe , M7N5MMye , & - M7N5MMze , M7N5RAxe , M7N5RAye , M7N5RAze , M7N5RDxe , M7N5RDye , M7N5RDze , & - M7N5TAxe , M7N5TAye , M7N5TAze , M7N5TDxss , M7N5TDyss , M7N5TDzss , M7N6FKxe , & - M7N6FKye , M7N6FKze , M7N6FMxe , M7N6FMye , M7N6FMze , M7N6MKxe , M7N6MKye , & - M7N6MKze , M7N6MMxe , M7N6MMye , M7N6MMze , M7N6RAxe , M7N6RAye , M7N6RAze , & - M7N6RDxe , M7N6RDye , M7N6RDze , M7N6TAxe , M7N6TAye , M7N6TAze , M7N6TDxss , & - M7N6TDyss , M7N6TDzss , M7N7FKxe , M7N7FKye , M7N7FKze , M7N7FMxe , M7N7FMye , & - M7N7FMze , M7N7MKxe , M7N7MKye , M7N7MKze , M7N7MMxe , M7N7MMye , M7N7MMze , & - M7N7RAxe , M7N7RAye , M7N7RAze , M7N7RDxe , M7N7RDye , M7N7RDze , M7N7TAxe , & - M7N7TAye , M7N7TAze , M7N7TDxss , M7N7TDyss , M7N7TDzss , M7N8FKxe , M7N8FKye , & - M7N8FKze , M7N8FMxe , M7N8FMye , M7N8FMze , M7N8MKxe , M7N8MKye , M7N8MKze , & - M7N8MMxe , M7N8MMye , M7N8MMze , M7N8RAxe , M7N8RAye , M7N8RAze , M7N8RDxe , & - M7N8RDye , M7N8RDze , M7N8TAxe , M7N8TAye , M7N8TAze , M7N8TDxss , M7N8TDyss , & - M7N8TDzss , M7N9FKxe , M7N9FKye , M7N9FKze , M7N9FMxe , M7N9FMye , M7N9FMze , & - M7N9MKxe , M7N9MKye , M7N9MKze , M7N9MMxe , M7N9MMye , M7N9MMze , M7N9RAxe , & - M7N9RAye , M7N9RAze , M7N9RDxe , M7N9RDye , M7N9RDze , M7N9TAxe , M7N9TAye , & - M7N9TAze , M7N9TDxss , M7N9TDyss , M7N9TDzss , M8N1FKxe , M8N1FKye , M8N1FKze , & - M8N1FMxe , M8N1FMye , M8N1FMze , M8N1MKxe , M8N1MKye , M8N1MKze , M8N1MMxe , & - M8N1MMye , M8N1MMze , M8N1RAxe , M8N1RAye , M8N1RAze , M8N1RDxe , M8N1RDye , & - M8N1RDze , M8N1TAxe , M8N1TAye , M8N1TAze , M8N1TDxss , M8N1TDyss , M8N1TDzss , & - M8N2FKxe , M8N2FKye , M8N2FKze , M8N2FMxe , M8N2FMye , M8N2FMze , M8N2MKxe , & - M8N2MKye , M8N2MKze , M8N2MMxe , M8N2MMye , M8N2MMze , M8N2RAxe , M8N2RAye , & - M8N2RAze , M8N2RDxe , M8N2RDye , M8N2RDze , M8N2TAxe , M8N2TAye , M8N2TAze , & - M8N2TDxss , M8N2TDyss , M8N2TDzss , M8N3FKxe , M8N3FKye , M8N3FKze , M8N3FMxe , & - M8N3FMye , M8N3FMze , M8N3MKxe , M8N3MKye , M8N3MKze , M8N3MMxe , M8N3MMye , & - M8N3MMze , M8N3RAxe , M8N3RAye , M8N3RAze , M8N3RDxe , M8N3RDye , M8N3RDze , & - M8N3TAxe , M8N3TAye , M8N3TAze , M8N3TDxss , M8N3TDyss , M8N3TDzss , M8N4FKxe , & - M8N4FKye , M8N4FKze , M8N4FMxe , M8N4FMye , M8N4FMze , M8N4MKxe , M8N4MKye , & - M8N4MKze , M8N4MMxe , M8N4MMye , M8N4MMze , M8N4RAxe , M8N4RAye , M8N4RAze , & - M8N4RDxe , M8N4RDye , M8N4RDze , M8N4TAxe , M8N4TAye , M8N4TAze , M8N4TDxss , & - M8N4TDyss , M8N4TDzss , M8N5FKxe , M8N5FKye , M8N5FKze , M8N5FMxe , M8N5FMye , & - M8N5FMze , M8N5MKxe , M8N5MKye , M8N5MKze , M8N5MMxe , M8N5MMye , M8N5MMze , & - M8N5RAxe , M8N5RAye , M8N5RAze , M8N5RDxe , M8N5RDye , M8N5RDze , M8N5TAxe , & - M8N5TAye , M8N5TAze , M8N5TDxss , M8N5TDyss , M8N5TDzss , M8N6FKxe , M8N6FKye , & - M8N6FKze , M8N6FMxe , M8N6FMye , M8N6FMze , M8N6MKxe , M8N6MKye , M8N6MKze , & - M8N6MMxe , M8N6MMye , M8N6MMze , M8N6RAxe , M8N6RAye , M8N6RAze , M8N6RDxe , & - M8N6RDye , M8N6RDze , M8N6TAxe , M8N6TAye , M8N6TAze , M8N6TDxss , M8N6TDyss , & - M8N6TDzss , M8N7FKxe , M8N7FKye , M8N7FKze , M8N7FMxe , M8N7FMye , M8N7FMze , & - M8N7MKxe , M8N7MKye , M8N7MKze , M8N7MMxe , M8N7MMye , M8N7MMze , M8N7RAxe , & - M8N7RAye , M8N7RAze , M8N7RDxe , M8N7RDye , M8N7RDze , M8N7TAxe , M8N7TAye , & - M8N7TAze , M8N7TDxss , M8N7TDyss , M8N7TDzss , M8N8FKxe , M8N8FKye , M8N8FKze , & - M8N8FMxe , M8N8FMye , M8N8FMze , M8N8MKxe , M8N8MKye , M8N8MKze , M8N8MMxe , & - M8N8MMye , M8N8MMze , M8N8RAxe , M8N8RAye , M8N8RAze , M8N8RDxe , M8N8RDye , & - M8N8RDze , M8N8TAxe , M8N8TAye , M8N8TAze , M8N8TDxss , M8N8TDyss , M8N8TDzss , & - M8N9FKxe , M8N9FKye , M8N9FKze , M8N9FMxe , M8N9FMye , M8N9FMze , M8N9MKxe , & - M8N9MKye , M8N9MKze , M8N9MMxe , M8N9MMye , M8N9MMze , M8N9RAxe , M8N9RAye , & - M8N9RAze , M8N9RDxe , M8N9RDye , M8N9RDze , M8N9TAxe , M8N9TAye , M8N9TAze , & - M8N9TDxss , M8N9TDyss , M8N9TDzss , M9N1FKxe , M9N1FKye , M9N1FKze , M9N1FMxe , & - M9N1FMye , M9N1FMze , M9N1MKxe , M9N1MKye , M9N1MKze , M9N1MMxe , M9N1MMye , & - M9N1MMze , M9N1RAxe , M9N1RAye , M9N1RAze , M9N1RDxe , M9N1RDye , M9N1RDze , & - M9N1TAxe , M9N1TAye , M9N1TAze , M9N1TDxss , M9N1TDyss , M9N1TDzss , M9N2FKxe , & - M9N2FKye , M9N2FKze , M9N2FMxe , M9N2FMye , M9N2FMze , M9N2MKxe , M9N2MKye , & - M9N2MKze , M9N2MMxe , M9N2MMye , M9N2MMze , M9N2RAxe , M9N2RAye , M9N2RAze , & - M9N2RDxe , M9N2RDye , M9N2RDze , M9N2TAxe , M9N2TAye , M9N2TAze , M9N2TDxss , & - M9N2TDyss , M9N2TDzss , M9N3FKxe , M9N3FKye , M9N3FKze , M9N3FMxe , M9N3FMye , & - M9N3FMze , M9N3MKxe , M9N3MKye , M9N3MKze , M9N3MMxe , M9N3MMye , M9N3MMze , & - M9N3RAxe , M9N3RAye , M9N3RAze , M9N3RDxe , M9N3RDye , M9N3RDze , M9N3TAxe , & - M9N3TAye , M9N3TAze , M9N3TDxss , M9N3TDyss , M9N3TDzss , M9N4FKxe , M9N4FKye , & - M9N4FKze , M9N4FMxe , M9N4FMye , M9N4FMze , M9N4MKxe , M9N4MKye , M9N4MKze , & - M9N4MMxe , M9N4MMye , M9N4MMze , M9N4RAxe , M9N4RAye , M9N4RAze , M9N4RDxe , & - M9N4RDye , M9N4RDze , M9N4TAxe , M9N4TAye , M9N4TAze , M9N4TDxss , M9N4TDyss , & - M9N4TDzss , M9N5FKxe , M9N5FKye , M9N5FKze , M9N5FMxe , M9N5FMye , M9N5FMze , & - M9N5MKxe , M9N5MKye , M9N5MKze , M9N5MMxe , M9N5MMye , M9N5MMze , M9N5RAxe , & - M9N5RAye , M9N5RAze , M9N5RDxe , M9N5RDye , M9N5RDze , M9N5TAxe , M9N5TAye , & - M9N5TAze , M9N5TDxss , M9N5TDyss , M9N5TDzss , M9N6FKxe , M9N6FKye , M9N6FKze , & - M9N6FMxe , M9N6FMye , M9N6FMze , M9N6MKxe , M9N6MKye , M9N6MKze , M9N6MMxe , & - M9N6MMye , M9N6MMze , M9N6RAxe , M9N6RAye , M9N6RAze , M9N6RDxe , M9N6RDye , & - M9N6RDze , M9N6TAxe , M9N6TAye , M9N6TAze , M9N6TDxss , M9N6TDyss , M9N6TDzss , & - M9N7FKxe , M9N7FKye , M9N7FKze , M9N7FMxe , M9N7FMye , M9N7FMze , M9N7MKxe , & - M9N7MKye , M9N7MKze , M9N7MMxe , M9N7MMye , M9N7MMze , M9N7RAxe , M9N7RAye , & - M9N7RAze , M9N7RDxe , M9N7RDye , M9N7RDze , M9N7TAxe , M9N7TAye , M9N7TAze , & - M9N7TDxss , M9N7TDyss , M9N7TDzss , M9N8FKxe , M9N8FKye , M9N8FKze , M9N8FMxe , & - M9N8FMye , M9N8FMze , M9N8MKxe , M9N8MKye , M9N8MKze , M9N8MMxe , M9N8MMye , & - M9N8MMze , M9N8RAxe , M9N8RAye , M9N8RAze , M9N8RDxe , M9N8RDye , M9N8RDze , & - M9N8TAxe , M9N8TAye , M9N8TAze , M9N8TDxss , M9N8TDyss , M9N8TDzss , M9N9FKxe , & - M9N9FKye , M9N9FKze , M9N9FMxe , M9N9FMye , M9N9FMze , M9N9MKxe , M9N9MKye , & - M9N9MKze , M9N9MMxe , M9N9MMye , M9N9MMze , M9N9RAxe , M9N9RAye , M9N9RAze , & - M9N9RDxe , M9N9RDye , M9N9RDze , M9N9TAxe , M9N9TAye , M9N9TAze , M9N9TDxss , & - M9N9TDyss , M9N9TDzss , ReactFXss , ReactFYss , ReactFZss , ReactMXss , ReactMYss , & - ReactMZss , SSqm01 , SSqm02 , SSqm03 , SSqm04 , SSqm05 , SSqm06 , & - SSqm07 , SSqm08 , SSqm09 , SSqm10 , SSqm11 , SSqm12 , SSqm13 , & - SSqm14 , SSqm15 , SSqm16 , SSqm17 , SSqm18 , SSqm19 , SSqm20 , & - SSqm21 , SSqm22 , SSqm23 , SSqm24 , SSqm25 , SSqm26 , SSqm27 , & - SSqm28 , SSqm29 , SSqm30 , SSqm31 , SSqm32 , SSqm33 , SSqm34 , & - SSqm35 , SSqm36 , SSqm37 , SSqm38 , SSqm39 , SSqm40 , SSqm41 , & - SSqm42 , SSqm43 , SSqm44 , SSqm45 , SSqm46 , SSqm47 , SSqm48 , & - SSqm49 , SSqm50 , SSqm51 , SSqm52 , SSqm53 , SSqm54 , SSqm55 , & - SSqm56 , SSqm57 , SSqm58 , SSqm59 , SSqm60 , SSqm61 , SSqm62 , & - SSqm63 , SSqm64 , SSqm65 , SSqm66 , SSqm67 , SSqm68 , SSqm69 , & - SSqm70 , SSqm71 , SSqm72 , SSqm73 , SSqm74 , SSqm75 , SSqm76 , & - SSqm77 , SSqm78 , SSqm79 , SSqm80 , SSqm81 , SSqm82 , SSqm83 , & - SSqm84 , SSqm85 , SSqm86 , SSqm87 , SSqm88 , SSqm89 , SSqm90 , & - SSqm91 , SSqm92 , SSqm93 , SSqm94 , SSqm95 , SSqm96 , SSqm97 , & - SSqm98 , SSqm99 , SSqmd01 , SSqmd02 , SSqmd03 , SSqmd04 , SSqmd05 , & - SSqmd06 , SSqmd07 , SSqmd08 , SSqmd09 , SSqmd10 , SSqmd11 , SSqmd12 , & - SSqmd13 , SSqmd14 , SSqmd15 , SSqmd16 , SSqmd17 , SSqmd18 , SSqmd19 , & - SSqmd20 , SSqmd21 , SSqmd22 , SSqmd23 , SSqmd24 , SSqmd25 , SSqmd26 , & - SSqmd27 , SSqmd28 , SSqmd29 , SSqmd30 , SSqmd31 , SSqmd32 , SSqmd33 , & - SSqmd34 , SSqmd35 , SSqmd36 , SSqmd37 , SSqmd38 , SSqmd39 , SSqmd40 , & - SSqmd41 , SSqmd42 , SSqmd43 , SSqmd44 , SSqmd45 , SSqmd46 , SSqmd47 , & - SSqmd48 , SSqmd49 , SSqmd50 , SSqmd51 , SSqmd52 , SSqmd53 , SSqmd54 , & - SSqmd55 , SSqmd56 , SSqmd57 , SSqmd58 , SSqmd59 , SSqmd60 , SSqmd61 , & - SSqmd62 , SSqmd63 , SSqmd64 , SSqmd65 , SSqmd66 , SSqmd67 , SSqmd68 , & - SSqmd69 , SSqmd70 , SSqmd71 , SSqmd72 , SSqmd73 , SSqmd74 , SSqmd75 , & - SSqmd76 , SSqmd77 , SSqmd78 , SSqmd79 , SSqmd80 , SSqmd81 , SSqmd82 , & - SSqmd83 , SSqmd84 , SSqmd85 , SSqmd86 , SSqmd87 , SSqmd88 , SSqmd89 , & - SSqmd90 , SSqmd91 , SSqmd92 , SSqmd93 , SSqmd94 , SSqmd95 , SSqmd96 , & - SSqmd97 , SSqmd98 , SSqmd99 , SSqmdd01 , SSqmdd02 , SSqmdd03 , SSqmdd04 , & - SSqmdd05 , SSqmdd06 , SSqmdd07 , SSqmdd08 , SSqmdd09 , SSqmdd10 , SSqmdd11 , & - SSqmdd12 , SSqmdd13 , SSqmdd14 , SSqmdd15 , SSqmdd16 , SSqmdd17 , SSqmdd18 , & - SSqmdd19 , SSqmdd20 , SSqmdd21 , SSqmdd22 , SSqmdd23 , SSqmdd24 , SSqmdd25 , & - SSqmdd26 , SSqmdd27 , SSqmdd28 , SSqmdd29 , SSqmdd30 , SSqmdd31 , SSqmdd32 , & - SSqmdd33 , SSqmdd34 , SSqmdd35 , SSqmdd36 , SSqmdd37 , SSqmdd38 , SSqmdd39 , & - SSqmdd40 , SSqmdd41 , SSqmdd42 , SSqmdd43 , SSqmdd44 , SSqmdd45 , SSqmdd46 , & - SSqmdd47 , SSqmdd48 , SSqmdd49 , SSqmdd50 , SSqmdd51 , SSqmdd52 , SSqmdd53 , & - SSqmdd54 , SSqmdd55 , SSqmdd56 , SSqmdd57 , SSqmdd58 , SSqmdd59 , SSqmdd60 , & - SSqmdd61 , SSqmdd62 , SSqmdd63 , SSqmdd64 , SSqmdd65 , SSqmdd66 , SSqmdd67 , & - SSqmdd68 , SSqmdd69 , SSqmdd70 , SSqmdd71 , SSqmdd72 , SSqmdd73 , SSqmdd74 , & - SSqmdd75 , SSqmdd76 , SSqmdd77 , SSqmdd78 , SSqmdd79 , SSqmdd80 , SSqmdd81 , & - SSqmdd82 , SSqmdd83 , SSqmdd84 , SSqmdd85 , SSqmdd86 , SSqmdd87 , SSqmdd88 , & - SSqmdd89 , SSqmdd90 , SSqmdd91 , SSqmdd92 , SSqmdd93 , SSqmdd94 , SSqmdd95 , & - SSqmdd96 , SSqmdd97 , SSqmdd98 , SSqmdd99 /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(2265) = (/ & ! This lists the units corresponding to the allowed parameters - "(N) ","(N) ","(N) ","(Nm) ","(Nm) ","(Nm) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ", & - "(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ", & - "(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ", & - "(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ", & - "(rad/s^2) ","(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(N) ","(N) ","(N) ","(N) ", & - "(N) ","(N) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ","(N*m) ", & - "(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ","(rad) ","(rad) ","(rad) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(N) ", & - "(N) ","(N) ","(N) ","(N) ","(N) ","(N*m) ","(N*m) ", & - "(N*m) ","(N*m) ","(N*m) ","(N*m) ","(rad/s^2) ","(rad/s^2) ","(rad/s^2) ", & - "(rad) ","(rad) ","(rad) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ", & - "(m) ","(m) ","(N) ","(N) ","(N) ","(Nm) ","(Nm) ", & - "(Nm) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(--) ","(--) ","(--) ","(--) ","(--) ", & - "(--) ","(--) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ","(1/s) ", & - "(1/s) ","(1/s) ","(1/s) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) ", & - "(1/s^2) ","(1/s^2) ","(1/s^2) ","(1/s^2) "/) - - -!End of code generated by Matlab script -end module SubDyn_Output_Params diff --git a/modules/subdyn/src_soildyn/SubDyn_Registry.txt b/modules/subdyn/src_soildyn/SubDyn_Registry.txt deleted file mode 100644 index adca6cee0..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Registry.txt +++ /dev/null @@ -1,269 +0,0 @@ -##################### Registry for SubDyn ################## -# -# -# Use ^ as a shortcut for the value in the same column from the previous line. -################################################################################################################################### -# ...... Include files (definitions from NWTC Library) ............................................................................ -include Registry_NWTC_Library.txt - -# -# Keyword ModuleName/ModName Derived data type Field type Variable name Dimemsion of the variable Initial value not used Description Units - -typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" - -! integer, dimension(:), pointer :: data => null() -! type(IList), pointer :: next => null() - -# ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ -typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" -typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" -typedef ^ InitInputType ReKi g - - - "Gravity acceleration" -typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" -typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" -typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" -typedef ^ InitInputType ReKi SoilStiffness ::: - - "Soil stiffness matrices from SoilDyn" '(N/m, N-m/rad)' -typedef ^ InitInputType MeshType SoilMesh - - - "Mesh for soil stiffness locations" - - -# ============================== Define Initialization outputs here: ============================================================================================================================================ -typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - -typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - -typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - - -# ============================== Define Internal data types here: ============================================================================================================================================ -typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" -typedef ^ MeshAuxDataType INTEGER NOutCnt - - - "Number of Nodes for the output member" -typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the output member" -typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" -typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" -typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" -typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" -# CB_MatArrays: Matrices and arrays for CB summary -typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" -typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" -typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" -typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" -# -typedef ^ ElemPropType IntKi eType - - - "Element Type" -typedef ^ ^ ReKi Length - - - "Length of an element" -typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" -typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" -typedef ^ ^ ReKi Kappa - - - "Shear coefficient" -typedef ^ ^ ReKi YoungE - - - "Young's modulus" -typedef ^ ^ ReKi ShearG - - - "Shear modulus" N/m^2 -# Properties common to all element types: -typedef ^ ^ ReKi Area - - - "Area of an element" m^2 -typedef ^ ^ ReKi Rho - - - "Density" kg/m^3 -typedef ^ ^ ReKi T0 - - - "Pretension " N -typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" -# ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ -#--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- -typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" -typedef ^ ^ ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" -typedef ^ ^ ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" -typedef ^ ^ ReKi g - - - "Gravity acceleration" -typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds -typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" -typedef ^ ^ INTEGER NPropSetsX - - - "Number of extended property sets" -typedef ^ ^ INTEGER NPropSetsB - - - "Number of property sets for beams" -typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" -typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" -typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" -typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" -typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" -typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" -typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" -typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" -typedef ^ ^ ReKi PropSetsB {:}{:} - - "Property sets number and values" -typedef ^ ^ ReKi PropSetsC {:}{:} - - "Property ID and values for cables" -typedef ^ ^ ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" -typedef ^ ^ ReKi PropSetsX {:}{:} - - "Extended property sets" -typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" -typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" -typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" -typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" -typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" -typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" -typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" -typedef ^ ^ ReKi SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" -typedef ^ ^ ReKi SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" -typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" -typedef ^ ^ ReKi Soil_K {:}{:}{:} - - "Soil stiffness (at passed at Init, not in input file) 6x6xn" -typedef ^ ^ ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added" -typedef ^ ^ Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added" -#-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -typedef ^ ^ INTEGER NElem - - - "Total number of elements" -typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" -typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" -typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" -typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" -typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" -typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" -typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" -typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" -typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" -typedef ^ ^ ReKi D {:}{:} - - "System damping matrix" -typedef ^ ^ ReKi F {:} - - "System force vector" N -typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N -typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" -typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" -typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" -typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" -typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" -typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" -typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" - -# ============================== States ============================================================================================================================================ -# Define continuous (differentiable) states here: -typedef ^ ContinuousStateType ReKi qm {:} - - "Virtual states, Nmod elements" -typedef ^ ContinuousStateType ReKi qmdot {:} - - "Derivative of states, Nmod elements" -# Define discrete (nondifferentiable) states here: -typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" -# Define constraint states here: -typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - -# Define any other states, including integer or logical states here: -typedef SubDyn/SD OtherStateType SD_ContinuousStateType xdot {:} - - "previous state derivs for m-step time integrator" -typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated last" - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi qmdotdot {:} - - "2nd Derivative of states, used only for output-file purposes" -typedef ^ ^ ReKi u_TP 6 - - -typedef ^ ^ ReKi udot_TP 6 - - -typedef ^ ^ ReKi udotdot_TP 6 - - -typedef ^ ^ ReKi UFL {:} - - -typedef ^ ^ ReKi UR_bar {:} - - -typedef ^ ^ ReKi UR_bar_dot {:} - - -typedef ^ ^ ReKi UR_bar_dotdot {:} - - -typedef ^ ^ ReKi UL {:} - - -typedef ^ ^ ReKi UL_dot {:} - - -typedef ^ ^ ReKi UL_dotdot {:} - - -typedef ^ ^ ReKi U_full {:} - - -typedef ^ ^ ReKi U_full_dot {:} - - -typedef ^ ^ ReKi U_full_dotdot {:} - - -typedef ^ ^ ReKi U_red {:} - - -typedef ^ ^ ReKi U_red_dot {:} - - -typedef ^ ^ ReKi U_red_dotdot {:} - - -### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### -typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" -typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" -typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" -typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" -typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" - - - -# ============================== Parameters ============================================================================================================================================ -# --- Algo -typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds -typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" -# --- FEM -typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" -typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" -typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" -typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" -typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" -# --- Constraints reduction -typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" -typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" -typedef ^ ^ IList NodesDOFtilde {:} - - "DOF indices of each nodes in constrained assembled system " "-" -typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" -typedef ^ ^ IntKi DOFtilde2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" -# --- CB reduction -typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" -typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" -typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" -typedef ^ ParameterType ReKi NOmegaM2 {:} - - "Coefficient of x in X (negative omegaM squared)" -typedef ^ ParameterType ReKi N2OmegaMJDamp {:} - - "Coefficient of x in X (negative 2 omegaM * JDamping)" -typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" -typedef ^ ParameterType ReKi FX {:} - - "Load components in X" -typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of u in Y1" -typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of u in Y1" -typedef ^ ParameterType ReKi FY {:} - - "Load Components in Y1" -typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" -typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R bar * TI)" -typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" -typedef ^ ParameterType ReKi MBB {:}{:} - - "Matrix after C-B reduction" -typedef ^ ParameterType ReKi KBB {:}{:} - - "Matrix after C-B reduction" -typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" -typedef ^ ParameterType ReKi UL_st_g {:} - - "Motion of internal DOFs due to static gravitational force, for static improvement" -typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" -typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" -typedef ^ ParameterType ReKi KLLm1 {:}{:} - - "KLL^{-1}, inverse of matrix KLL, for static solve only" -typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" -typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" -typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" -typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" -# --- Partitioning I L C Y, R=[C I] -typedef ^ ParameterType IntKi nNodes - - - "Total number of nodes" -typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" -typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" -typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" -typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" -typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" -typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" -typedef ^ ParameterType IntKi nDOFI__ - - - "Size of IDI__" -typedef ^ ParameterType IntKi nDOFI_Rb - - - "Size of IDI_Rb" -typedef ^ ParameterType IntKi nDOFI_F - - - "Size of IDI_F" -typedef ^ ParameterType IntKi nDOFL_L - - - "Size of IDL_L" -typedef ^ ParameterType IntKi nDOFC__ - - - "Size of IDC__" -typedef ^ ParameterType IntKi nDOFC_Rb - - - "Size of IDC_Rb" -typedef ^ ParameterType IntKi nDOFC_L - - - "Size of IDC_L" -typedef ^ ParameterType IntKi nDOFC_F - - - "Size of IDC_F" -typedef ^ ParameterType IntKi nDOFR__ - - - "Size of IDR__" -typedef ^ ParameterType IntKi nDOF__Rb - - - "Size of ID__Rb" -typedef ^ ParameterType IntKi nDOF__L - - - "Size of ID__L" -typedef ^ ParameterType IntKi nDOF__F - - - "Size of ID__F" -typedef ^ ParameterType IntKi IDI__ {:} - - "Index of all Interface DOFs" -typedef ^ ParameterType IntKi IDI_Rb {:} - - "Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs" -typedef ^ ParameterType IntKi IDI_F {:} - - "Index array of the interface (nodes connect to TP) dofs that are fixed DOF" -typedef ^ ParameterType IntKi IDL_L {:} - - "Index array of the internal dofs coming from internal nodes" -typedef ^ ParameterType IntKi IDC__ {:} - - "Index of all bottom DOF" -typedef ^ ParameterType IntKi IDC_Rb {:} - - "Index array of the contraint dofs that are retained/master/follower DOF" -typedef ^ ParameterType IntKi IDC_L {:} - - "Index array of the contraint dofs that are follower/internal DOF" -typedef ^ ParameterType IntKi IDC_F {:} - - "Index array of the contraint dofs that are fixd DOF" -typedef ^ ParameterType IntKi IDR__ {:} - - "Index array of the interface and restraint dofs" -typedef ^ ParameterType IntKi ID__Rb {:} - - "Index array of all the retained/leader/master dofs (from any nodes of the structure)" -typedef ^ ParameterType IntKi ID__L {:} - - "Index array of all the follower/internal dofs (from any nodes of the structure)" -typedef ^ ParameterType IntKi ID__F {:} - - "Index array of the DOF that are fixed (from any nodes of the structure)" -typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" -# --- Outputs -typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" -typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" -typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" -typedef ^ ParameterType IntKi UnJckF - - - "Unit of SD ouput file" -typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" -typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format for Output" -typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" -typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" -typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" -typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" -typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" -typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" -typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" -typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" -typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" -typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" - -# ============================== Inputs ============================================================================================================================================ -typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" -typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" - -# ============================== Outputs ============================================================================================================================================ -typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" -typedef ^ OutputType MeshType Y2Mesh - - - "Interior+Interface nodes outputs on a point mesh" -typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file" diff --git a/modules/subdyn/src_soildyn/SubDyn_Tests.f90 b/modules/subdyn/src_soildyn/SubDyn_Tests.f90 deleted file mode 100644 index b80f476e3..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Tests.f90 +++ /dev/null @@ -1,440 +0,0 @@ -module SubDyn_Tests - use NWTC_Library - use SubDyn_Types - use SD_FEM - use IntegerList - - implicit none - - public :: SD_Tests - private - - character(len=255),save :: testname - interface test_equal; module procedure & - test_equal_i1, & - test_equal_i0 - end interface - interface test_almost_equal; module procedure & - test_almost_equal_0, & - test_almost_equal_1, & - test_almost_equal_2 - end interface -contains - - ! -------------------------------------------------------------------------------- - ! --- Helper functions (should be part of NWTC library) - ! -------------------------------------------------------------------------------- - subroutine test_success(info,bPrint_in) - character(len=*), intent(in) :: info - logical, intent(in), optional :: bPrint_in - if(present(bPrint_in)) then - if(bPrint_in) then - write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) - endif - else - write(*,'(A)')'[ OK ] '//trim(testname)//': '//trim(Info) - endif - end subroutine - - subroutine test_fail(info,bPrint_in,bStop_in) - character(len=*), intent(in) :: info - logical, intent(in), optional :: bPrint_in - logical, intent(in), optional :: bStop_in - if(present(bPrint_in)) then - if(bPrint_in) then - write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) - endif - else - write(*,'(A)')'[FAIL] '//trim(testname)//': '//trim(Info) - endif - if(present(bStop_in)) then - if(bStop_in) then - STOP - endif - else - STOP - endif - end subroutine - - subroutine test_equal_i0(Var,iTry,iRef) - ! Arguments - character(len=*), intent(in) :: Var - integer, intent(in) :: iTry !< - integer, intent(in) :: iRef !< - ! Variables - character(len=255) :: InfoAbs - if(iRef/=iTry) then - write(InfoAbs,'(A,I0,A,I0)') trim(Var),iRef,'/',iTry - call test_fail(InfoAbs) - STOP - else - write(InfoAbs,'(A,A,I0)') trim(Var),' ok ',iRef - call test_success(InfoAbs) - endif - end subroutine - - subroutine test_equal_i1(Var,VecTry,VecRef,bTest,bPrintOnly,bPassed) - ! Arguments - character(len=*), intent(in) :: Var - integer, dimension(:), intent(in) :: VecTry !< - integer, dimension(:), intent(in) :: VecRef !< - logical, intent(in) :: bTest - logical, intent(in) :: bPrintOnly - logical, intent(out),optional :: bPassed - ! Variables - character(len=255) :: InfoAbs - integer :: i,cpt - ! - cpt=0 - do i=1,size(VecRef) - if(VecRef(i)/=VecTry(i)) then - cpt=cpt+1 - endif - enddo - if(cpt>0) then - write(InfoAbs,'(A,I0)') trim(Var)//' Elements different: ',cpt - if(present(bPassed)) then - bPassed=.false. - endif - else - write(InfoAbs,'(A)') trim(Var)//' reproduced to identity' - if(present(bPassed)) then - bPassed=.true. - endif - endif - if(bPrintOnly) then - print'(A)',trim(InfoAbs) - endif - if(bTest) then - if(cpt>0) then - call test_fail(InfoAbs) - STOP - else - call test_success(InfoAbs) - endif - endif - end subroutine - - subroutine test_almost_equal_0(Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) - ! Arguments - character(len=*), intent(in) :: Var - real(ReKi), intent(in) :: Ref !< - real(ReKi), intent(in) :: Try !< - real(ReKi), intent(in) :: MINNORM - logical, intent(in) :: bStop - logical, intent(in) :: bPrint - logical, intent(out),optional :: bPassed - ! Variables - character(len=255) :: InfoAbs - real(ReKi) :: delta - integer :: cpt - ! - cpt=0 - delta=abs(Ref-Try) - if(delta>MINNORM) then - write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta,' - Failed:',cpt - call test_fail(InfoAbs,bPrint,bStop) - else - write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta - call test_success(InfoAbs,bPrint) - endif - if(present(bPassed)) then - bPassed=delta>MINNORM - endif - end subroutine - subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) - ! Arguments - character(len=*), intent(in) :: Var - real(ReKi), dimension(:), intent(in) :: VecRef !< - real(ReKi), dimension(:), intent(in) :: VecTry !< - real(ReKi), intent(in) :: MINNORM - logical, intent(in) :: bStop - logical, intent(in) :: bPrint - logical, intent(out),optional :: bPassed - ! Variables - character(len=255) :: InfoAbs - integer :: i,cpt - real(ReKi) :: delta - real(ReKi) :: delta_cum - ! - cpt=0 - delta_cum=0.0_ReKi - do i=1,size(VecRef,1) - delta=abs(VecRef(i)-VecTry(i)) - delta_cum=delta_cum+delta - if(delta>MINNORM) then - cpt=cpt+1 - endif - enddo - delta_cum=delta_cum/size(VecRef) - - if(cpt>0) then - write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum,' - Failed:',cpt - call test_fail(InfoAbs,bPrint,bStop) - else - write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum - call test_success(InfoAbs,bPrint) - endif - if(present(bPassed)) then - bPassed=(cpt==0) - endif - end subroutine - subroutine test_almost_equal_2(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) - ! Arguments - character(len=*), intent(in) :: Var - real(ReKi), dimension(:,:), intent(in) :: VecRef !< - real(ReKi), dimension(:,:), intent(in) :: VecTry !< - real(ReKi), intent(in) :: MINNORM - logical, intent(in) :: bStop - logical, intent(in) :: bPrint - logical, intent(out),optional :: bPassed - ! Variables - real(ReKi), dimension(:),allocatable :: VecRef2 !< - real(ReKi), dimension(:),allocatable :: VecTry2 !< - integer :: p, i,j,n1,n2,nCPs - ! - n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 - allocate ( VecRef2 (n1*n2) ) ; allocate ( VecTry2 (n1*n2) ) - p=0 - do j=1,n2; do i=1,n1 - p=p+1 - VecRef2(p)=VecRef(i,j) - VecTry2(p)=VecTry(i,j) - enddo; enddo; - call test_almost_equal(Var,VecRef2,VecTry2,MINNORM,bStop,bPrint,bPassed) - end subroutine - - - - ! --------------------------------------------------------------------------------} - ! --- Specific SubDyn tests - ! --------------------------------------------------------------------------------{ - subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg, Init, p) - TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters - INTEGER(IntKi) :: DOFTP, DOFM - REAL(ReKi) :: MBBt(DOFTP, DOFTP) - REAL(ReKi) :: MBmt(DOFTP, DOFM) - REAL(ReKi) :: KBBt(DOFTP, DOFTP) - REAL(ReKi) :: OmegaM(DOFM) - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: DOFT, NM, i - REAL(ReKi), Allocatable :: OmegaCB(:), PhiCB(:, :) - REAL(ReKi), Allocatable :: K(:, :) - REAL(ReKi), Allocatable :: M(:, :) - Character(1024) :: rootname - ErrStat = ErrID_None - ErrMsg = '' - print*,'This test is not a unit test' - - DOFT = DOFTP + DOFM - NM = DOFT - 3 - Allocate( OmegaCB(NM), K(DOFT, DOFT), M(DOFT, DOFT), PhiCB(DOFT, NM) ) - K = 0.0 - M = 0.0 - OmegaCB = 0.0 - PhiCB = 0.0 - - M(1:DOFTP, 1:DOFTP) = MBBt - M(1:DOFTP, (DOFTP+1):DOFT ) = MBMt - M((DOFTP+1):DOFT, 1:DOFTP ) = transpose(mbmt) - - DO i = 1, DOFM - K(DOFTP+i, DOFTP+i) = OmegaM(i)*OmegaM(i) - M(DOFTP+i, DOFTP+i) = 1.0 - ENDDO - - K(1:DOFTP, 1:DOFTP) = KBBt - - ! temporary rootname - rootname = './test_assemble_C-B_out' - - ! NOTE: Eigensolve is in SubDyn - !CALL EigenSolve(K, M, DOFT, NM,.False.,Init,p, PhiCB, OmegaCB, ErrStat, ErrMsg) - IF ( ErrStat /= 0 ) RETURN - end subroutine Test_CB_Results - - !> Transformation matrices tests - subroutine Test_Transformations(ErrStat,ErrMsg) - integer(IntKi) , intent(out) :: ErrStat - character(ErrMsgLen), intent(out) :: ErrMsg - - real(ReKi), dimension(3) :: P1, P2, e1, e2, e3 - real(ReKi), dimension(3,3) :: DirCos, A, R0, Ref - real(ReKi), dimension(6,6) :: T, Tref - real(ReKi) :: L - integer(IntKi) :: I - testname='Transf' - - ! --- DirCos - P1=(/0,0,0/) - P2=(/2,0,0/) - call GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) - Ref = reshape( (/0_ReKi,-1_ReKi,0_ReKi, 0_ReKi, 0_ReKi, -1_ReKi, 1_ReKi, 0_ReKi, 0_ReKi/) , (/3,3/)) - call test_almost_equal('DirCos',Ref,DirCos,1e-8_ReKi,.true.,.true.) - - ! --- Rigid Transo - P1=(/1,2,-1/) - P2=(/2,5,5/) - call GetRigidTransformation(P1, P2, T, ErrStat, ErrMsg) - Tref = 0; do I=1,6; Tref(I,I) =1_ReKi; enddo - Tref(1,5) = 6._ReKi; Tref(1,6) =-3._ReKi; - Tref(2,4) =-6._ReKi; Tref(2,6) = 1._ReKi; - Tref(3,4) = 3._ReKi; Tref(3,5) =-1._ReKi; - call test_almost_equal('TRigid',Tref,T,1e-8_ReKi,.true.,.true.) - - - ! --- Orthogonal vectors - e1 = (/10,0,0/) - call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi,-1._ReKi/),1e-8_ReKi,.true.,.true.) - call test_almost_equal('orth',e3,(/0._ReKi,1._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) - e1 = (/0,10,0/) - call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('orth',e2,(/0._ReKi,0._ReKi, 1._ReKi/),1e-8_ReKi,.true.,.true.) - call test_almost_equal('orth',e3,(/1._ReKi,0._ReKi, 0._ReKi/),1e-8_ReKi,.true.,.true.) - e1 = (/1,2,4/) - call GetOrthVectors(e1,e2,e3,ErrStat, ErrMsg) - call test_almost_equal('dot', 0._ReKi, dot_product(e1,e2), 1e-8_ReKi, .true., .true.) - call test_almost_equal('dot', 0._ReKi, dot_product(e1,e3), 1e-8_ReKi, .true., .true.) - end subroutine Test_Transformations - - - !> Linear algebra tests - subroutine Test_Linalg(ErrStat,ErrMsg) - integer(IntKi) , intent(out) :: ErrStat - character(ErrMsgLen), intent(out) :: ErrMsg - real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref - real(DbKi) :: det - integer(IntKi) :: I, J - testname='Linalg' - - ! --- Determinant of a singular matrix - ! Commented since might lead to floating invalid - !allocate(A(3,3)); - !A(1,1) = 0 ; A(1,2) = 0 ; A(1,3) = 1 ; - !A(2,1) = 0 ; A(2,2) = 0 ; A(2,3) = -1 ; - !A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; - !det = Determinant(A,ErrStat, ErrMsg) - !call test_almost_equal('Det of singular 3x3 matrix', real(det,ReKi), 0.0_ReKi, 1e-8_ReKi, .true. , .true.) - !deallocate(A ) - - ! --- Inverse and determinant of a 3x3 matrix - allocate(A(3,3)); allocate(Aref(3,3)) - A(1,1) = 7 ; A(1,2) = 2 ; A(1,3) = 1 ; - A(2,1) = 0 ; A(2,2) = 3 ; A(2,3) = -1 ; - A(3,1) =-3 ; A(3,2) = 4 ; A(3,3) = -2 ; - Aref(1,1) =-2 ; Aref(1,2) = 8 ; Aref(1,3) = -5 ; - Aref(2,1) = 3 ; Aref(2,2) =-11; Aref(2,3) = 7 ; - Aref(3,1) = 9 ; Aref(3,2) =-34; Aref(3,3) = 21; - call PseudoInverse(A, Ainv, ErrStat, ErrMsg) - ! Determinant test - det = Determinant(A,ErrStat, ErrMsg) - call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) - det = Determinant(Ainv,ErrStat, ErrMsg) - call test_almost_equal('Det of 3x3 matrix', real(det,ReKi), 1.0_ReKi, 1e-8_ReKi, .true. , .true.) - ! Inverse test - call test_almost_equal('Inverse of 3x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-8_ReKi, .true., .true.) - deallocate(A ) - deallocate(Ainv) - deallocate(Aref) - - ! --- Inverse of a 3x6 matrix - allocate(A(3,6)) - allocate(Aref(6,3)) - A(1,:) = (/ 0, 1, 2, 0, 1, 2 /) - A(2,:) = (/ -1, 1, 2, -0, 0, 0 /) - A(3,:) = (/ -0, 0, 0, -1, 1, 2 /) - Aref(:,:) = transpose(reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /))) - call PseudoInverse(A, Ainv, ErrStat, ErrMsg) - call test_almost_equal('Inverse of 3x6 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) - deallocate(A ) - deallocate(Ainv) - deallocate(Aref) - - ! --- Inverse of a 6x3 matrix - allocate(A(6,3)) - allocate(Aref(3,6)) - A(:,1) = (/ 0, 1, 2, 0, 1, 2 /) - A(:,2) = (/ -1, 1, 2, -0, 0, 0 /) - A(:,3) = (/ -0, 0, 0, -1, 1, 2 /) - Aref(:,:) = reshape( (/ 0.500000, -0.583333, -0.416667, 0.100000, 0.083333, -0.083333 , 0.200000, 0.166667, -0.166667 , 0.500000, -0.416667, -0.583333 , 0.100000, -0.083333, 0.083333 , 0.200000, -0.166667, 0.166667 /), (/ 3, 6 /)) - call PseudoInverse(A, Ainv, ErrStat, ErrMsg) - call test_almost_equal('Inverse of 6x3 matrix', real(Aref,ReKi), real(Ainv,ReKi), 1e-6_ReKi, .true., .true.) - end subroutine Test_Linalg - - !> Series of tests for integer lists - subroutine Test_lists(ErrStat,ErrMsg) - integer(IntKi) , intent(out) :: ErrStat - character(ErrMsgLen), intent(out) :: ErrMsg - type(IList) :: L1 - type(IList) :: L2 - integer(IntKi) :: e - ErrStat = ErrID_None - ErrMsg = "" - testname='Lists' - - call init_list(L1, 0, 0 ,ErrStat, ErrMsg) - call init_list(L2, 10, 12,ErrStat, ErrMsg) - - ! test len - call test_equal('length',0 ,len(L1)) - call test_equal('length',10,len(L2)) - - ! test append - call append(L1, 5, ErrStat, ErrMsg) - call append(L1, 3, ErrStat, ErrMsg) - call append(L1, 1, ErrStat, ErrMsg) - call test_equal('appnd',L1%List, (/5,3,1/) , .true. , .false.) - - ! test get - call test_equal('get ',get(L1,2, ErrStat, ErrMsg), 3) - e = get(L1,0, ErrStat, ErrMsg) - call test_equal('get <0 ', ErrStat, ErrID_Fatal) - e = get(L1,7, ErrStat, ErrMsg) - call test_equal('get >n ', ErrStat, ErrID_Fatal) - - ! test sort - call sort(L1, ErrStat, ErrMsg) - call test_equal('sort ',L1%List, (/1,3,5/) , .true. , .false.) - - ! test reverse - call reverse(L1, ErrStat, ErrMsg) - call test_equal('rev ',L1%List, (/5,3,1/) , .true. , .false.) - - ! test pop - e = pop(L1, ErrStat, ErrMsg) - call test_equal('pop ',e , 1) - e = pop(L1, ErrStat, ErrMsg) - call test_equal('pop ',e , 3) - e = pop(L1, ErrStat, ErrMsg) - call test_equal('pop ',e , 5) - call destroy_list(L1, ErrStat, ErrMsg) - - ! test unique - call init_list(L1,(/5,3,2,3,8/),ErrStat, ErrMsg) - call unique(L1, ErrStat, ErrMsg) - call test_equal('uniq ',L1%List, (/5,3,2,8/) , .true. , .false.) - - call destroy_list(L1, ErrStat, ErrMsg) - call destroy_list(L2, ErrStat, ErrMsg) - end subroutine Test_lists - - subroutine SD_Tests(ErrStat,ErrMsg) - integer(IntKi) , intent(out) :: ErrStat !< Error status of the operation - character(ErrMsgLen), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - call Test_lists(ErrStat2, ErrMsg2) - call Test_Transformations(ErrStat2, ErrMsg2) - call Test_Linalg(ErrStat2, ErrMsg2) - end subroutine SD_Tests - - -end module SubDyn_Tests diff --git a/modules/subdyn/src_soildyn/SubDyn_Types.f90 b/modules/subdyn/src_soildyn/SubDyn_Types.f90 deleted file mode 100644 index 16bb630f3..000000000 --- a/modules/subdyn/src_soildyn/SubDyn_Types.f90 +++ /dev/null @@ -1,11876 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'SubDyn_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! SubDyn_Types -!................................................................................................................................. -! This file is part of SubDyn. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in SubDyn. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE SubDyn_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE NWTC_Library -IMPLICIT NONE -! ========= IList ======= - TYPE, PUBLIC :: IList - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: List !< List of integers [-] - END TYPE IList -! ======================= -! ========= SD_InitInputType ======= - TYPE, PUBLIC :: SD_InitInputType - CHARACTER(1024) :: SDInputFile !< Name of the input file [-] - CHARACTER(1024) :: RootName !< SubDyn rootname [-] - REAL(ReKi) :: g !< Gravity acceleration [-] - REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] - REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] - REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SoilStiffness !< Soil stiffness matrices from SoilDyn ['(N/m,] - TYPE(MeshType) :: SoilMesh !< Mesh for soil stiffness locations [-] - END TYPE SD_InitInputType -! ======================= -! ========= SD_InitOutputType ======= - TYPE, PUBLIC :: SD_InitOutputType - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] - TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] - END TYPE SD_InitOutputType -! ======================= -! ========= MeshAuxDataType ======= - TYPE, PUBLIC :: MeshAuxDataType - INTEGER(IntKi) :: MemberID !< Member ID for Output [-] - INTEGER(IntKi) :: NOutCnt !< Number of Nodes for the output member [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeCnt !< Node ordinal numbers for the output member [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIDs !< Node IDs associated with ordinal numbers for the output member [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmIDs !< Element IDs connected to each NodeIDs; max 10 elements [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmNds !< Flag to indicate 1st or 2nd node of element for each ElmIDs [-] - REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] - END TYPE MeshAuxDataType -! ======================= -! ========= CB_MatArrays ======= - TYPE, PUBLIC :: CB_MatArrays - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] - END TYPE CB_MatArrays -! ======================= -! ========= ElemPropType ======= - TYPE, PUBLIC :: ElemPropType - INTEGER(IntKi) :: eType !< Element Type [-] - REAL(ReKi) :: Length !< Length of an element [-] - REAL(ReKi) :: Ixx !< Moment of inertia of an element [-] - REAL(ReKi) :: Iyy !< Moment of inertia of an element [-] - REAL(ReKi) :: Jzz !< Moment of inertia of an element [-] - LOGICAL :: Shear !< Use timoshenko (true) E-B (false) [-] - REAL(ReKi) :: Kappa !< Shear coefficient [-] - REAL(ReKi) :: YoungE !< Young's modulus [-] - REAL(ReKi) :: ShearG !< Shear modulus [N/m^2] - REAL(ReKi) :: Area !< Area of an element [m^2] - REAL(ReKi) :: Rho !< Density [kg/m^3] - REAL(ReKi) :: T0 !< Pretension [N] - REAL(ReKi) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] - END TYPE ElemPropType -! ======================= -! ========= SD_InitType ======= - TYPE, PUBLIC :: SD_InitType - CHARACTER(1024) :: RootName !< SubDyn rootname [-] - REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] - REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] - REAL(ReKi) :: g !< Gravity acceleration [-] - REAL(DbKi) :: DT !< Time step from Glue Code [seconds] - INTEGER(IntKi) :: NJoints !< Number of joints of the sub structure [-] - INTEGER(IntKi) :: NPropSetsX !< Number of extended property sets [-] - INTEGER(IntKi) :: NPropSetsB !< Number of property sets for beams [-] - INTEGER(IntKi) :: NPropSetsC !< Number of property sets for cables [-] - INTEGER(IntKi) :: NPropSetsR !< Number of property sets for rigid links [-] - INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] - INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] - INTEGER(IntKi) :: FEMMod !< FEM switch: element model in the FEM [-] - INTEGER(IntKi) :: NDiv !< Number of divisions for each member [-] - LOGICAL :: CBMod !< Perform C-B flag [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsB !< Property sets number and values [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsC !< Property ID and values for cables [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsR !< Property ID and values for rigid link [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsX !< Extended property sets [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: COSMs !< Independent direction cosine matrices [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMass !< Concentrated mass information [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: JDampings !< Damping coefficients for internal modes [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] - LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] - LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] - CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Soil_K !< Soil stiffness (at passed at Init, not in input file) 6x6xn [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] - INTEGER(IntKi) :: NElem !< Total number of elements [-] - INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] - INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] - INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D !< System damping matrix [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and list of nodes making up a member (>2 if subdivided) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] - LOGICAL :: SSSum !< SubDyn Summary File Flag [-] - END TYPE SD_InitType -! ======================= -! ========= SD_ContinuousStateType ======= - TYPE, PUBLIC :: SD_ContinuousStateType - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qm !< Virtual states, Nmod elements [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdot !< Derivative of states, Nmod elements [-] - END TYPE SD_ContinuousStateType -! ======================= -! ========= SD_DiscreteStateType ======= - TYPE, PUBLIC :: SD_DiscreteStateType - REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] - END TYPE SD_DiscreteStateType -! ======================= -! ========= SD_ConstraintStateType ======= - TYPE, PUBLIC :: SD_ConstraintStateType - REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] - END TYPE SD_ConstraintStateType -! ======================= -! ========= SD_OtherStateType ======= - TYPE, PUBLIC :: SD_OtherStateType - TYPE(SD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< previous state derivs for m-step time integrator [-] - INTEGER(IntKi) :: n !< tracks time step for which OtherState was updated last [-] - END TYPE SD_OtherStateType -! ======================= -! ========= SD_MiscVarType ======= - TYPE, PUBLIC :: SD_MiscVarType - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdotdot !< 2nd Derivative of states, used only for output-file purposes [-] - REAL(ReKi) , DIMENSION(1:6) :: u_TP - REAL(ReKi) , DIMENSION(1:6) :: udot_TP - REAL(ReKi) , DIMENSION(1:6) :: udotdot_TP - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UFL - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] - REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] - INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads on unconstrained DOFs [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext_red !< External loads on constrained DOFs, Fext_red= T^t Fext [-] - END TYPE SD_MiscVarType -! ======================= -! ========= SD_ParameterType ======= - TYPE, PUBLIC :: SD_ParameterType - REAL(DbKi) :: SDDeltaT !< Time step (for integration of continuous states) [seconds] - INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] - INTEGER(IntKi) :: nDOF !< Total degree of freedom [-] - INTEGER(IntKi) :: nDOF_red !< Total degree of freedom after constraint reduction [-] - INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] - TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] - TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFtilde !< DOF indices of each nodes in constrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFtilde2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] - INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] - INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] - LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: NOmegaM2 !< Coefficient of x in X (negative omegaM squared) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: N2OmegaMJDamp !< Coefficient of x in X (negative 2 omegaM * JDamping) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of u in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of u in Y1 [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Load Components in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiRb_TI !< Coefficient of u in Y2 (Phi_R bar * TI) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_63 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_64 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F2_61 !< Load Component in Y2 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_st_g !< Motion of internal DOFs due to static gravitational force, for static improvement [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KLLm1 !< KLL^{-1}, inverse of matrix KLL, for static solve only [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AM2Jac !< Jacobian (factored) for Adams-Boulton 2nd order Integration [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AM2JacPiv !< Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TI !< Matrix to calculate TP reference point reaction at top of structure [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TIreact !< Matrix to calculate single point reaction at base of structure [-] - INTEGER(IntKi) :: nNodes !< Total number of nodes [-] - INTEGER(IntKi) :: nNodes_I !< Number of Interface nodes [-] - INTEGER(IntKi) :: nNodes_L !< Number of Internal nodes [-] - INTEGER(IntKi) :: nNodes_C !< Number of joints with reactions [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_I !< Interface degree of freedoms [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_L !< Internal nodes (not interface nor reaction) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes_C !< React degree of freedoms [-] - INTEGER(IntKi) :: nDOFI__ !< Size of IDI__ [-] - INTEGER(IntKi) :: nDOFI_Rb !< Size of IDI_Rb [-] - INTEGER(IntKi) :: nDOFI_F !< Size of IDI_F [-] - INTEGER(IntKi) :: nDOFL_L !< Size of IDL_L [-] - INTEGER(IntKi) :: nDOFC__ !< Size of IDC__ [-] - INTEGER(IntKi) :: nDOFC_Rb !< Size of IDC_Rb [-] - INTEGER(IntKi) :: nDOFC_L !< Size of IDC_L [-] - INTEGER(IntKi) :: nDOFC_F !< Size of IDC_F [-] - INTEGER(IntKi) :: nDOFR__ !< Size of IDR__ [-] - INTEGER(IntKi) :: nDOF__Rb !< Size of ID__Rb [-] - INTEGER(IntKi) :: nDOF__L !< Size of ID__L [-] - INTEGER(IntKi) :: nDOF__F !< Size of ID__F [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI__ !< Index of all Interface DOFs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_Rb !< Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDI_F !< Index array of the interface (nodes connect to TP) dofs that are fixed DOF [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDL_L !< Index array of the internal dofs coming from internal nodes [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC__ !< Index of all bottom DOF [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_Rb !< Index array of the contraint dofs that are retained/master/follower DOF [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_L !< Index array of the contraint dofs that are follower/internal DOF [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDC_F !< Index array of the contraint dofs that are fixd DOF [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: IDR__ !< Index array of the interface and restraint dofs [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__Rb !< Index array of all the retained/leader/master dofs (from any nodes of the structure) [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__L !< Index array of all the follower/internal dofs (from any nodes of the structure) [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__F !< Index array of the DOF that are fixed (from any nodes of the structure) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] - INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] - INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] - INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] - INTEGER(IntKi) :: UnJckF !< Unit of SD ouput file [-] - CHARACTER(1) :: Delim !< Column delimiter for output text files [-] - CHARACTER(20) :: OutFmt !< Format for Output [-] - CHARACTER(20) :: OutSFmt !< Format for Output Headers [-] - TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst !< List of user requested members and nodes [-] - TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst2 !< List of all member joint nodes and elements for output [-] - TYPE(MeshAuxDataType) , DIMENSION(:), ALLOCATABLE :: MoutLst3 !< List of all member joint nodes and elements for output [-] - TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< An array holding names, units, and indices of all of the selected output channels. logical [-] - LOGICAL :: OutAll !< Flag to output or not all joint forces [-] - LOGICAL :: OutReact !< Flag to check whether reactions are requested [-] - INTEGER(IntKi) :: OutAllInt !< Integer version of OutAll [-] - INTEGER(IntKi) :: OutAllDims !< Integer version of OutAll [-] - INTEGER(IntKi) :: OutDec !< Output Decimation for Requested Channels [-] - END TYPE SD_ParameterType -! ======================= -! ========= SD_InputType ======= - TYPE, PUBLIC :: SD_InputType - TYPE(MeshType) :: TPMesh !< Transition piece inputs on a point mesh [-] - TYPE(MeshType) :: LMesh !< Point mesh for interior node inputs [-] - END TYPE SD_InputType -! ======================= -! ========= SD_OutputType ======= - TYPE, PUBLIC :: SD_OutputType - TYPE(MeshType) :: Y1Mesh !< Transition piece outputs on a point mesh [-] - TYPE(MeshType) :: Y2Mesh !< Interior+Interface nodes outputs on a point mesh [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Data to be written to an output file [-] - END TYPE SD_OutputType -! ======================= -CONTAINS - SUBROUTINE SD_CopyIList( SrcIListData, DstIListData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IList), INTENT(IN) :: SrcIListData - TYPE(IList), INTENT(INOUT) :: DstIListData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyIList' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcIListData%List)) THEN - i1_l = LBOUND(SrcIListData%List,1) - i1_u = UBOUND(SrcIListData%List,1) - IF (.NOT. ALLOCATED(DstIListData%List)) THEN - ALLOCATE(DstIListData%List(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstIListData%List.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstIListData%List = SrcIListData%List -ENDIF - END SUBROUTINE SD_CopyIList - - SUBROUTINE SD_DestroyIList( IListData, ErrStat, ErrMsg ) - TYPE(IList), INTENT(INOUT) :: IListData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyIList' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(IListData%List)) THEN - DEALLOCATE(IListData%List) -ENDIF - END SUBROUTINE SD_DestroyIList - - SUBROUTINE SD_PackIList( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IList), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackIList' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! List allocated yes/no - IF ( ALLOCATED(InData%List) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! List upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%List) ! List - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%List) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%List,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%List,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%List)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%List))-1 ) = PACK(InData%List,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%List) - END IF - END SUBROUTINE SD_PackIList - - SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IList), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackIList' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! List not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%List)) DEALLOCATE(OutData%List) - ALLOCATE(OutData%List(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%List.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%List)>0) OutData%List = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%List))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%List) - DEALLOCATE(mask1) - END IF - END SUBROUTINE SD_UnPackIList - - SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(INOUT) :: SrcInitInputData - TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%SDInputFile = SrcInitInputData%SDInputFile - DstInitInputData%RootName = SrcInitInputData%RootName - DstInitInputData%g = SrcInitInputData%g - DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth - DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint - DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ -IF (ALLOCATED(SrcInitInputData%SoilStiffness)) THEN - i1_l = LBOUND(SrcInitInputData%SoilStiffness,1) - i1_u = UBOUND(SrcInitInputData%SoilStiffness,1) - i2_l = LBOUND(SrcInitInputData%SoilStiffness,2) - i2_u = UBOUND(SrcInitInputData%SoilStiffness,2) - i3_l = LBOUND(SrcInitInputData%SoilStiffness,3) - i3_u = UBOUND(SrcInitInputData%SoilStiffness,3) - IF (.NOT. ALLOCATED(DstInitInputData%SoilStiffness)) THEN - ALLOCATE(DstInitInputData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitInputData%SoilStiffness = SrcInitInputData%SoilStiffness -ENDIF - CALL MeshCopy( SrcInitInputData%SoilMesh, DstInitInputData%SoilMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE SD_CopyInitInput - - SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitInput' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(InitInputData%SoilStiffness)) THEN - DEALLOCATE(InitInputData%SoilStiffness) -ENDIF - CALL MeshDestroy( InitInputData%SoilMesh, ErrStat, ErrMsg ) - END SUBROUTINE SD_DestroyInitInput - - SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%SDInputFile) ! SDInputFile - Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName - Re_BufSz = Re_BufSz + 1 ! g - Re_BufSz = Re_BufSz + 1 ! WtrDpth - Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint - Re_BufSz = Re_BufSz + 1 ! SubRotateZ - Int_BufSz = Int_BufSz + 1 ! SoilStiffness allocated yes/no - IF ( ALLOCATED(InData%SoilStiffness) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! SoilStiffness upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SoilStiffness) ! SoilStiffness - END IF - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! SoilMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! SoilMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! SoilMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! SoilMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%SDInputFile) - IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%RootName) - IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ - Re_Xferred = Re_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%SoilStiffness) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%SoilStiffness)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SoilStiffness))-1 ) = PACK(InData%SoilStiffness,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SoilStiffness) - END IF - CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE SD_PackInitInput - - SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%SDInputFile) - OutData%SDInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%RootName) - OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%g = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%WtrDpth = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%TP_RefPoint,1) - i1_u = UBOUND(OutData%TP_RefPoint,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) - DEALLOCATE(mask1) - OutData%SubRotateZ = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SoilStiffness not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SoilStiffness)) DEALLOCATE(OutData%SoilStiffness) - ALLOCATE(OutData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%SoilStiffness)>0) OutData%SoilStiffness = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SoilStiffness))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SoilStiffness) - DEALLOCATE(mask3) - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE SD_UnPackInitInput - - SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(SD_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN - ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr -ENDIF -IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN - ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt -ENDIF - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE SD_CopyInitOutput - - SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) - TYPE(SD_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitOutput' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN - DEALLOCATE(InitOutputData%WriteOutputHdr) -ENDIF -IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN - DEALLOCATE(InitOutputData%WriteOutputUnt) -ENDIF - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) - END SUBROUTINE SD_DestroyInitOutput - - SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no - IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr - END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no - IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt - END IF - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE SD_PackInitOutput - - SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE SD_UnPackInitOutput - - SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(MeshAuxDataType), INTENT(IN) :: SrcMeshAuxDataTypeData - TYPE(MeshAuxDataType), INTENT(INOUT) :: DstMeshAuxDataTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMeshAuxDataType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMeshAuxDataTypeData%MemberID = SrcMeshAuxDataTypeData%MemberID - DstMeshAuxDataTypeData%NOutCnt = SrcMeshAuxDataTypeData%NOutCnt -IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeCnt)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeCnt)) THEN - ALLOCATE(DstMeshAuxDataTypeData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeCnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%NodeCnt = SrcMeshAuxDataTypeData%NodeCnt -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeIDs)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeIDs)) THEN - ALLOCATE(DstMeshAuxDataTypeData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%NodeIDs = SrcMeshAuxDataTypeData%NodeIDs -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmIDs)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmIDs)) THEN - ALLOCATE(DstMeshAuxDataTypeData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%ElmIDs = SrcMeshAuxDataTypeData%ElmIDs -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmNds)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,2) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmNds)) THEN - ALLOCATE(DstMeshAuxDataTypeData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmNds.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Me,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Me,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Me,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Me,3) - i4_l = LBOUND(SrcMeshAuxDataTypeData%Me,4) - i4_u = UBOUND(SrcMeshAuxDataTypeData%Me,4) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Me)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Me.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Me = SrcMeshAuxDataTypeData%Me -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Ke)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Ke,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Ke,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Ke,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Ke,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Ke,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Ke,3) - i4_l = LBOUND(SrcMeshAuxDataTypeData%Ke,4) - i4_u = UBOUND(SrcMeshAuxDataTypeData%Ke,4) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Ke)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Ke.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Ke = SrcMeshAuxDataTypeData%Ke -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Fg)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Fg,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Fg,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Fg,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Fg,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Fg,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Fg,3) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Fg)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Fg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg -ENDIF - END SUBROUTINE SD_CopyMeshAuxDataType - - SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) - TYPE(MeshAuxDataType), INTENT(INOUT) :: MeshAuxDataTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMeshAuxDataType' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(MeshAuxDataTypeData%NodeCnt)) THEN - DEALLOCATE(MeshAuxDataTypeData%NodeCnt) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%NodeIDs)) THEN - DEALLOCATE(MeshAuxDataTypeData%NodeIDs) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%ElmIDs)) THEN - DEALLOCATE(MeshAuxDataTypeData%ElmIDs) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%ElmNds)) THEN - DEALLOCATE(MeshAuxDataTypeData%ElmNds) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Me)) THEN - DEALLOCATE(MeshAuxDataTypeData%Me) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Ke)) THEN - DEALLOCATE(MeshAuxDataTypeData%Ke) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Fg)) THEN - DEALLOCATE(MeshAuxDataTypeData%Fg) -ENDIF - END SUBROUTINE SD_DestroyMeshAuxDataType - - SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(MeshAuxDataType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMeshAuxDataType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! MemberID - Int_BufSz = Int_BufSz + 1 ! NOutCnt - Int_BufSz = Int_BufSz + 1 ! NodeCnt allocated yes/no - IF ( ALLOCATED(InData%NodeCnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodeCnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodeCnt) ! NodeCnt - END IF - Int_BufSz = Int_BufSz + 1 ! NodeIDs allocated yes/no - IF ( ALLOCATED(InData%NodeIDs) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodeIDs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodeIDs) ! NodeIDs - END IF - Int_BufSz = Int_BufSz + 1 ! ElmIDs allocated yes/no - IF ( ALLOCATED(InData%ElmIDs) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElmIDs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElmIDs) ! ElmIDs - END IF - Int_BufSz = Int_BufSz + 1 ! ElmNds allocated yes/no - IF ( ALLOCATED(InData%ElmNds) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds - END IF - Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no - IF ( ALLOCATED(InData%Me) ) THEN - Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Me) ! Me - END IF - Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no - IF ( ALLOCATED(InData%Ke) ) THEN - Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Ke) ! Ke - END IF - Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no - IF ( ALLOCATED(InData%Fg) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Fg) ! Fg - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%MemberID - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NOutCnt - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%NodeCnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeCnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeCnt,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%NodeCnt)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeCnt))-1 ) = PACK(InData%NodeCnt,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%NodeCnt) - END IF - IF ( .NOT. ALLOCATED(InData%NodeIDs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIDs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIDs,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%NodeIDs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodeIDs))-1 ) = PACK(InData%NodeIDs,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%NodeIDs) - END IF - IF ( .NOT. ALLOCATED(InData%ElmIDs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ElmIDs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmIDs))-1 ) = PACK(InData%ElmIDs,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElmIDs) - END IF - IF ( .NOT. ALLOCATED(InData%ElmNds) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ElmNds)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElmNds))-1 ) = PACK(InData%ElmNds,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElmNds) - END IF - IF ( .NOT. ALLOCATED(InData%Me) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Me)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Me))-1 ) = PACK(InData%Me,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Me) - END IF - IF ( .NOT. ALLOCATED(InData%Ke) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Ke)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ke))-1 ) = PACK(InData%Ke,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Ke) - END IF - IF ( .NOT. ALLOCATED(InData%Fg) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Fg)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fg))-1 ) = PACK(InData%Fg,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fg) - END IF - END SUBROUTINE SD_PackMeshAuxDataType - - SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(MeshAuxDataType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMeshAuxDataType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%MemberID = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NOutCnt = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeCnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodeCnt)) DEALLOCATE(OutData%NodeCnt) - ALLOCATE(OutData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeCnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%NodeCnt)>0) OutData%NodeCnt = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeCnt))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%NodeCnt) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIDs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodeIDs)) DEALLOCATE(OutData%NodeIDs) - ALLOCATE(OutData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%NodeIDs)>0) OutData%NodeIDs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodeIDs))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%NodeIDs) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmIDs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElmIDs)) DEALLOCATE(OutData%ElmIDs) - ALLOCATE(OutData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElmIDs)>0) OutData%ElmIDs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmIDs))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElmIDs) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmNds not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElmNds)) DEALLOCATE(OutData%ElmNds) - ALLOCATE(OutData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmNds.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElmNds)>0) OutData%ElmNds = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElmNds))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElmNds) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Me)) DEALLOCATE(OutData%Me) - ALLOCATE(OutData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Me.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask4(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask4.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask4 = .TRUE. - IF (SIZE(OutData%Me)>0) OutData%Me = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Me))-1 ), mask4, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Me) - DEALLOCATE(mask4) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Ke)) DEALLOCATE(OutData%Ke) - ALLOCATE(OutData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ke.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask4(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask4.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask4 = .TRUE. - IF (SIZE(OutData%Ke)>0) OutData%Ke = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ke))-1 ), mask4, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Ke) - DEALLOCATE(mask4) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Fg)) DEALLOCATE(OutData%Fg) - ALLOCATE(OutData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%Fg)>0) OutData%Fg = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fg))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fg) - DEALLOCATE(mask3) - END IF - END SUBROUTINE SD_UnPackMeshAuxDataType - - SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) - TYPE(CB_MatArrays), INTENT(IN) :: SrcCB_MatArraysData - TYPE(CB_MatArrays), INTENT(INOUT) :: DstCB_MatArraysData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyCB_MatArrays' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) - i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) - i2_l = LBOUND(SrcCB_MatArraysData%MBB,2) - i2_u = UBOUND(SrcCB_MatArraysData%MBB,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBB)) THEN - ALLOCATE(DstCB_MatArraysData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%MBB = SrcCB_MatArraysData%MBB -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%MBM)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%MBM,1) - i1_u = UBOUND(SrcCB_MatArraysData%MBM,1) - i2_l = LBOUND(SrcCB_MatArraysData%MBM,2) - i2_u = UBOUND(SrcCB_MatArraysData%MBM,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBM)) THEN - ALLOCATE(DstCB_MatArraysData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%MBM = SrcCB_MatArraysData%MBM -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%KBB)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%KBB,1) - i1_u = UBOUND(SrcCB_MatArraysData%KBB,1) - i2_l = LBOUND(SrcCB_MatArraysData%KBB,2) - i2_u = UBOUND(SrcCB_MatArraysData%KBB,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%KBB)) THEN - ALLOCATE(DstCB_MatArraysData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%KBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) - i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) - i2_l = LBOUND(SrcCB_MatArraysData%PhiL,2) - i2_u = UBOUND(SrcCB_MatArraysData%PhiL,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiL)) THEN - ALLOCATE(DstCB_MatArraysData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%PhiL = SrcCB_MatArraysData%PhiL -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%PhiR)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%PhiR,1) - i1_u = UBOUND(SrcCB_MatArraysData%PhiR,1) - i2_l = LBOUND(SrcCB_MatArraysData%PhiR,2) - i2_u = UBOUND(SrcCB_MatArraysData%PhiR,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiR)) THEN - ALLOCATE(DstCB_MatArraysData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%PhiR = SrcCB_MatArraysData%PhiR -ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%OmegaL)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%OmegaL,1) - i1_u = UBOUND(SrcCB_MatArraysData%OmegaL,1) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%OmegaL)) THEN - ALLOCATE(DstCB_MatArraysData%OmegaL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%OmegaL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstCB_MatArraysData%OmegaL = SrcCB_MatArraysData%OmegaL -ENDIF - END SUBROUTINE SD_CopyCB_MatArrays - - SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) - TYPE(CB_MatArrays), INTENT(INOUT) :: CB_MatArraysData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyCB_MatArrays' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(CB_MatArraysData%MBB)) THEN - DEALLOCATE(CB_MatArraysData%MBB) -ENDIF -IF (ALLOCATED(CB_MatArraysData%MBM)) THEN - DEALLOCATE(CB_MatArraysData%MBM) -ENDIF -IF (ALLOCATED(CB_MatArraysData%KBB)) THEN - DEALLOCATE(CB_MatArraysData%KBB) -ENDIF -IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN - DEALLOCATE(CB_MatArraysData%PhiL) -ENDIF -IF (ALLOCATED(CB_MatArraysData%PhiR)) THEN - DEALLOCATE(CB_MatArraysData%PhiR) -ENDIF -IF (ALLOCATED(CB_MatArraysData%OmegaL)) THEN - DEALLOCATE(CB_MatArraysData%OmegaL) -ENDIF - END SUBROUTINE SD_DestroyCB_MatArrays - - SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(CB_MatArrays), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackCB_MatArrays' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no - IF ( ALLOCATED(InData%MBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB - END IF - Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no - IF ( ALLOCATED(InData%MBM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM - END IF - Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no - IF ( ALLOCATED(InData%KBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB - END IF - Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no - IF ( ALLOCATED(InData%PhiL) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiL) ! PhiL - END IF - Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no - IF ( ALLOCATED(InData%PhiR) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiR) ! PhiR - END IF - Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no - IF ( ALLOCATED(InData%OmegaL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%OmegaL) ! OmegaL - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%MBB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBB) - END IF - IF ( .NOT. ALLOCATED(InData%MBM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBM) - END IF - IF ( .NOT. ALLOCATED(InData%KBB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KBB) - END IF - IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiL))-1 ) = PACK(InData%PhiL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiL) - END IF - IF ( .NOT. ALLOCATED(InData%PhiR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiR))-1 ) = PACK(InData%PhiR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiR) - END IF - IF ( .NOT. ALLOCATED(InData%OmegaL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OmegaL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%OmegaL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%OmegaL))-1 ) = PACK(InData%OmegaL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%OmegaL) - END IF - END SUBROUTINE SD_PackCB_MatArrays - - SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(CB_MatArrays), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackCB_MatArrays' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) - ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MBB)>0) OutData%MBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) - ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MBM)>0) OutData%MBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBM) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) - ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%KBB)>0) OutData%KBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KBB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiL)) DEALLOCATE(OutData%PhiL) - ALLOCATE(OutData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiL)>0) OutData%PhiL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiL))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiL) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiR)) DEALLOCATE(OutData%PhiR) - ALLOCATE(OutData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiR)>0) OutData%PhiR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiR) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%OmegaL)) DEALLOCATE(OutData%OmegaL) - ALLOCATE(OutData%OmegaL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OmegaL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%OmegaL)>0) OutData%OmegaL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%OmegaL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%OmegaL) - DEALLOCATE(mask1) - END IF - END SUBROUTINE SD_UnPackCB_MatArrays - - SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData - TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyElemPropType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstElemPropTypeData%eType = SrcElemPropTypeData%eType - DstElemPropTypeData%Length = SrcElemPropTypeData%Length - DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx - DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy - DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz - DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear - DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa - DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE - DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG - DstElemPropTypeData%Area = SrcElemPropTypeData%Area - DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho - DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 - DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos - END SUBROUTINE SD_CopyElemPropType - - SUBROUTINE SD_DestroyElemPropType( ElemPropTypeData, ErrStat, ErrMsg ) - TYPE(ElemPropType), INTENT(INOUT) :: ElemPropTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyElemPropType' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - END SUBROUTINE SD_DestroyElemPropType - - SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ElemPropType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackElemPropType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! eType - Re_BufSz = Re_BufSz + 1 ! Length - Re_BufSz = Re_BufSz + 1 ! Ixx - Re_BufSz = Re_BufSz + 1 ! Iyy - Re_BufSz = Re_BufSz + 1 ! Jzz - Int_BufSz = Int_BufSz + 1 ! Shear - Re_BufSz = Re_BufSz + 1 ! Kappa - Re_BufSz = Re_BufSz + 1 ! YoungE - Re_BufSz = Re_BufSz + 1 ! ShearG - Re_BufSz = Re_BufSz + 1 ! Area - Re_BufSz = Re_BufSz + 1 ! Rho - Re_BufSz = Re_BufSz + 1 ! T0 - Re_BufSz = Re_BufSz + SIZE(InData%DirCos) ! DirCos - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%eType - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Length - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ixx - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Iyy - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Jzz - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Shear , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Kappa - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%YoungE - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%ShearG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Area - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Rho - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%T0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DirCos) - END SUBROUTINE SD_PackElemPropType - - SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ElemPropType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackElemPropType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%eType = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Length = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Ixx = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Iyy = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Jzz = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Shear = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%Kappa = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%YoungE = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%ShearG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Area = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Rho = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%T0 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%DirCos,1) - i1_u = UBOUND(OutData%DirCos,1) - i2_l = LBOUND(OutData%DirCos,2) - i2_u = UBOUND(OutData%DirCos,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%DirCos = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DirCos))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%DirCos) - DEALLOCATE(mask2) - END SUBROUTINE SD_UnPackElemPropType - - SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT(IN) :: SrcInitTypeData - TYPE(SD_InitType), INTENT(INOUT) :: DstInitTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitTypeData%RootName = SrcInitTypeData%RootName - DstInitTypeData%TP_RefPoint = SrcInitTypeData%TP_RefPoint - DstInitTypeData%SubRotateZ = SrcInitTypeData%SubRotateZ - DstInitTypeData%g = SrcInitTypeData%g - DstInitTypeData%DT = SrcInitTypeData%DT - DstInitTypeData%NJoints = SrcInitTypeData%NJoints - DstInitTypeData%NPropSetsX = SrcInitTypeData%NPropSetsX - DstInitTypeData%NPropSetsB = SrcInitTypeData%NPropSetsB - DstInitTypeData%NPropSetsC = SrcInitTypeData%NPropSetsC - DstInitTypeData%NPropSetsR = SrcInitTypeData%NPropSetsR - DstInitTypeData%NCMass = SrcInitTypeData%NCMass - DstInitTypeData%NCOSMs = SrcInitTypeData%NCOSMs - DstInitTypeData%FEMMod = SrcInitTypeData%FEMMod - DstInitTypeData%NDiv = SrcInitTypeData%NDiv - DstInitTypeData%CBMod = SrcInitTypeData%CBMod -IF (ALLOCATED(SrcInitTypeData%Joints)) THEN - i1_l = LBOUND(SrcInitTypeData%Joints,1) - i1_u = UBOUND(SrcInitTypeData%Joints,1) - i2_l = LBOUND(SrcInitTypeData%Joints,2) - i2_u = UBOUND(SrcInitTypeData%Joints,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Joints)) THEN - ALLOCATE(DstInitTypeData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Joints.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Joints = SrcInitTypeData%Joints -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropSetsB)) THEN - i1_l = LBOUND(SrcInitTypeData%PropSetsB,1) - i1_u = UBOUND(SrcInitTypeData%PropSetsB,1) - i2_l = LBOUND(SrcInitTypeData%PropSetsB,2) - i2_u = UBOUND(SrcInitTypeData%PropSetsB,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsB)) THEN - ALLOCATE(DstInitTypeData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropSetsB = SrcInitTypeData%PropSetsB -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropSetsC)) THEN - i1_l = LBOUND(SrcInitTypeData%PropSetsC,1) - i1_u = UBOUND(SrcInitTypeData%PropSetsC,1) - i2_l = LBOUND(SrcInitTypeData%PropSetsC,2) - i2_u = UBOUND(SrcInitTypeData%PropSetsC,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsC)) THEN - ALLOCATE(DstInitTypeData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsC.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropSetsC = SrcInitTypeData%PropSetsC -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropSetsR)) THEN - i1_l = LBOUND(SrcInitTypeData%PropSetsR,1) - i1_u = UBOUND(SrcInitTypeData%PropSetsR,1) - i2_l = LBOUND(SrcInitTypeData%PropSetsR,2) - i2_u = UBOUND(SrcInitTypeData%PropSetsR,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsR)) THEN - ALLOCATE(DstInitTypeData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropSetsR = SrcInitTypeData%PropSetsR -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropSetsX)) THEN - i1_l = LBOUND(SrcInitTypeData%PropSetsX,1) - i1_u = UBOUND(SrcInitTypeData%PropSetsX,1) - i2_l = LBOUND(SrcInitTypeData%PropSetsX,2) - i2_u = UBOUND(SrcInitTypeData%PropSetsX,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropSetsX)) THEN - ALLOCATE(DstInitTypeData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropSetsX = SrcInitTypeData%PropSetsX -ENDIF -IF (ALLOCATED(SrcInitTypeData%COSMs)) THEN - i1_l = LBOUND(SrcInitTypeData%COSMs,1) - i1_u = UBOUND(SrcInitTypeData%COSMs,1) - i2_l = LBOUND(SrcInitTypeData%COSMs,2) - i2_u = UBOUND(SrcInitTypeData%COSMs,2) - IF (.NOT. ALLOCATED(DstInitTypeData%COSMs)) THEN - ALLOCATE(DstInitTypeData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%COSMs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%COSMs = SrcInitTypeData%COSMs -ENDIF -IF (ALLOCATED(SrcInitTypeData%CMass)) THEN - i1_l = LBOUND(SrcInitTypeData%CMass,1) - i1_u = UBOUND(SrcInitTypeData%CMass,1) - i2_l = LBOUND(SrcInitTypeData%CMass,2) - i2_u = UBOUND(SrcInitTypeData%CMass,2) - IF (.NOT. ALLOCATED(DstInitTypeData%CMass)) THEN - ALLOCATE(DstInitTypeData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%CMass.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%CMass = SrcInitTypeData%CMass -ENDIF -IF (ALLOCATED(SrcInitTypeData%JDampings)) THEN - i1_l = LBOUND(SrcInitTypeData%JDampings,1) - i1_u = UBOUND(SrcInitTypeData%JDampings,1) - IF (.NOT. ALLOCATED(DstInitTypeData%JDampings)) THEN - ALLOCATE(DstInitTypeData%JDampings(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%JDampings.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%JDampings = SrcInitTypeData%JDampings -ENDIF -IF (ALLOCATED(SrcInitTypeData%Members)) THEN - i1_l = LBOUND(SrcInitTypeData%Members,1) - i1_u = UBOUND(SrcInitTypeData%Members,1) - i2_l = LBOUND(SrcInitTypeData%Members,2) - i2_u = UBOUND(SrcInitTypeData%Members,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Members)) THEN - ALLOCATE(DstInitTypeData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Members.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Members = SrcInitTypeData%Members -ENDIF -IF (ALLOCATED(SrcInitTypeData%SSOutList)) THEN - i1_l = LBOUND(SrcInitTypeData%SSOutList,1) - i1_u = UBOUND(SrcInitTypeData%SSOutList,1) - IF (.NOT. ALLOCATED(DstInitTypeData%SSOutList)) THEN - ALLOCATE(DstInitTypeData%SSOutList(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSOutList.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%SSOutList = SrcInitTypeData%SSOutList -ENDIF - DstInitTypeData%OutCOSM = SrcInitTypeData%OutCOSM - DstInitTypeData%TabDelim = SrcInitTypeData%TabDelim -IF (ALLOCATED(SrcInitTypeData%SSIK)) THEN - i1_l = LBOUND(SrcInitTypeData%SSIK,1) - i1_u = UBOUND(SrcInitTypeData%SSIK,1) - i2_l = LBOUND(SrcInitTypeData%SSIK,2) - i2_u = UBOUND(SrcInitTypeData%SSIK,2) - IF (.NOT. ALLOCATED(DstInitTypeData%SSIK)) THEN - ALLOCATE(DstInitTypeData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIK.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%SSIK = SrcInitTypeData%SSIK -ENDIF -IF (ALLOCATED(SrcInitTypeData%SSIM)) THEN - i1_l = LBOUND(SrcInitTypeData%SSIM,1) - i1_u = UBOUND(SrcInitTypeData%SSIM,1) - i2_l = LBOUND(SrcInitTypeData%SSIM,2) - i2_u = UBOUND(SrcInitTypeData%SSIM,2) - IF (.NOT. ALLOCATED(DstInitTypeData%SSIM)) THEN - ALLOCATE(DstInitTypeData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%SSIM = SrcInitTypeData%SSIM -ENDIF -IF (ALLOCATED(SrcInitTypeData%SSIfile)) THEN - i1_l = LBOUND(SrcInitTypeData%SSIfile,1) - i1_u = UBOUND(SrcInitTypeData%SSIfile,1) - IF (.NOT. ALLOCATED(DstInitTypeData%SSIfile)) THEN - ALLOCATE(DstInitTypeData%SSIfile(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%SSIfile.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%SSIfile = SrcInitTypeData%SSIfile -ENDIF -IF (ALLOCATED(SrcInitTypeData%Soil_K)) THEN - i1_l = LBOUND(SrcInitTypeData%Soil_K,1) - i1_u = UBOUND(SrcInitTypeData%Soil_K,1) - i2_l = LBOUND(SrcInitTypeData%Soil_K,2) - i2_u = UBOUND(SrcInitTypeData%Soil_K,2) - i3_l = LBOUND(SrcInitTypeData%Soil_K,3) - i3_u = UBOUND(SrcInitTypeData%Soil_K,3) - IF (.NOT. ALLOCATED(DstInitTypeData%Soil_K)) THEN - ALLOCATE(DstInitTypeData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_K.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Soil_K = SrcInitTypeData%Soil_K -ENDIF -IF (ALLOCATED(SrcInitTypeData%Soil_Points)) THEN - i1_l = LBOUND(SrcInitTypeData%Soil_Points,1) - i1_u = UBOUND(SrcInitTypeData%Soil_Points,1) - i2_l = LBOUND(SrcInitTypeData%Soil_Points,2) - i2_u = UBOUND(SrcInitTypeData%Soil_Points,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Points)) THEN - ALLOCATE(DstInitTypeData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Points.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Soil_Points = SrcInitTypeData%Soil_Points -ENDIF -IF (ALLOCATED(SrcInitTypeData%Soil_Nodes)) THEN - i1_l = LBOUND(SrcInitTypeData%Soil_Nodes,1) - i1_u = UBOUND(SrcInitTypeData%Soil_Nodes,1) - IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Nodes)) THEN - ALLOCATE(DstInitTypeData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Soil_Nodes = SrcInitTypeData%Soil_Nodes -ENDIF - DstInitTypeData%NElem = SrcInitTypeData%NElem - DstInitTypeData%NPropB = SrcInitTypeData%NPropB - DstInitTypeData%NPropC = SrcInitTypeData%NPropC - DstInitTypeData%NPropR = SrcInitTypeData%NPropR -IF (ALLOCATED(SrcInitTypeData%Nodes)) THEN - i1_l = LBOUND(SrcInitTypeData%Nodes,1) - i1_u = UBOUND(SrcInitTypeData%Nodes,1) - i2_l = LBOUND(SrcInitTypeData%Nodes,2) - i2_u = UBOUND(SrcInitTypeData%Nodes,2) - IF (.NOT. ALLOCATED(DstInitTypeData%Nodes)) THEN - ALLOCATE(DstInitTypeData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%Nodes = SrcInitTypeData%Nodes -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropsB)) THEN - i1_l = LBOUND(SrcInitTypeData%PropsB,1) - i1_u = UBOUND(SrcInitTypeData%PropsB,1) - i2_l = LBOUND(SrcInitTypeData%PropsB,2) - i2_u = UBOUND(SrcInitTypeData%PropsB,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropsB)) THEN - ALLOCATE(DstInitTypeData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropsB = SrcInitTypeData%PropsB -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropsC)) THEN - i1_l = LBOUND(SrcInitTypeData%PropsC,1) - i1_u = UBOUND(SrcInitTypeData%PropsC,1) - i2_l = LBOUND(SrcInitTypeData%PropsC,2) - i2_u = UBOUND(SrcInitTypeData%PropsC,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropsC)) THEN - ALLOCATE(DstInitTypeData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsC.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropsC = SrcInitTypeData%PropsC -ENDIF -IF (ALLOCATED(SrcInitTypeData%PropsR)) THEN - i1_l = LBOUND(SrcInitTypeData%PropsR,1) - i1_u = UBOUND(SrcInitTypeData%PropsR,1) - i2_l = LBOUND(SrcInitTypeData%PropsR,2) - i2_u = UBOUND(SrcInitTypeData%PropsR,2) - IF (.NOT. ALLOCATED(DstInitTypeData%PropsR)) THEN - ALLOCATE(DstInitTypeData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%PropsR = SrcInitTypeData%PropsR -ENDIF -IF (ALLOCATED(SrcInitTypeData%K)) THEN - i1_l = LBOUND(SrcInitTypeData%K,1) - i1_u = UBOUND(SrcInitTypeData%K,1) - i2_l = LBOUND(SrcInitTypeData%K,2) - i2_u = UBOUND(SrcInitTypeData%K,2) - IF (.NOT. ALLOCATED(DstInitTypeData%K)) THEN - ALLOCATE(DstInitTypeData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%K.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%K = SrcInitTypeData%K -ENDIF -IF (ALLOCATED(SrcInitTypeData%M)) THEN - i1_l = LBOUND(SrcInitTypeData%M,1) - i1_u = UBOUND(SrcInitTypeData%M,1) - i2_l = LBOUND(SrcInitTypeData%M,2) - i2_u = UBOUND(SrcInitTypeData%M,2) - IF (.NOT. ALLOCATED(DstInitTypeData%M)) THEN - ALLOCATE(DstInitTypeData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%M = SrcInitTypeData%M -ENDIF -IF (ALLOCATED(SrcInitTypeData%D)) THEN - i1_l = LBOUND(SrcInitTypeData%D,1) - i1_u = UBOUND(SrcInitTypeData%D,1) - i2_l = LBOUND(SrcInitTypeData%D,2) - i2_u = UBOUND(SrcInitTypeData%D,2) - IF (.NOT. ALLOCATED(DstInitTypeData%D)) THEN - ALLOCATE(DstInitTypeData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%D = SrcInitTypeData%D -ENDIF -IF (ALLOCATED(SrcInitTypeData%F)) THEN - i1_l = LBOUND(SrcInitTypeData%F,1) - i1_u = UBOUND(SrcInitTypeData%F,1) - IF (.NOT. ALLOCATED(DstInitTypeData%F)) THEN - ALLOCATE(DstInitTypeData%F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%F = SrcInitTypeData%F -ENDIF -IF (ALLOCATED(SrcInitTypeData%FG)) THEN - i1_l = LBOUND(SrcInitTypeData%FG,1) - i1_u = UBOUND(SrcInitTypeData%FG,1) - IF (.NOT. ALLOCATED(DstInitTypeData%FG)) THEN - ALLOCATE(DstInitTypeData%FG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%FG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%FG = SrcInitTypeData%FG -ENDIF -IF (ALLOCATED(SrcInitTypeData%ElemProps)) THEN - i1_l = LBOUND(SrcInitTypeData%ElemProps,1) - i1_u = UBOUND(SrcInitTypeData%ElemProps,1) - i2_l = LBOUND(SrcInitTypeData%ElemProps,2) - i2_u = UBOUND(SrcInitTypeData%ElemProps,2) - IF (.NOT. ALLOCATED(DstInitTypeData%ElemProps)) THEN - ALLOCATE(DstInitTypeData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%ElemProps = SrcInitTypeData%ElemProps -ENDIF -IF (ALLOCATED(SrcInitTypeData%BCs)) THEN - i1_l = LBOUND(SrcInitTypeData%BCs,1) - i1_u = UBOUND(SrcInitTypeData%BCs,1) - i2_l = LBOUND(SrcInitTypeData%BCs,2) - i2_u = UBOUND(SrcInitTypeData%BCs,2) - IF (.NOT. ALLOCATED(DstInitTypeData%BCs)) THEN - ALLOCATE(DstInitTypeData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%BCs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%BCs = SrcInitTypeData%BCs -ENDIF -IF (ALLOCATED(SrcInitTypeData%IntFc)) THEN - i1_l = LBOUND(SrcInitTypeData%IntFc,1) - i1_u = UBOUND(SrcInitTypeData%IntFc,1) - i2_l = LBOUND(SrcInitTypeData%IntFc,2) - i2_u = UBOUND(SrcInitTypeData%IntFc,2) - IF (.NOT. ALLOCATED(DstInitTypeData%IntFc)) THEN - ALLOCATE(DstInitTypeData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%IntFc.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%IntFc = SrcInitTypeData%IntFc -ENDIF -IF (ALLOCATED(SrcInitTypeData%MemberNodes)) THEN - i1_l = LBOUND(SrcInitTypeData%MemberNodes,1) - i1_u = UBOUND(SrcInitTypeData%MemberNodes,1) - i2_l = LBOUND(SrcInitTypeData%MemberNodes,2) - i2_u = UBOUND(SrcInitTypeData%MemberNodes,2) - IF (.NOT. ALLOCATED(DstInitTypeData%MemberNodes)) THEN - ALLOCATE(DstInitTypeData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%MemberNodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%MemberNodes = SrcInitTypeData%MemberNodes -ENDIF -IF (ALLOCATED(SrcInitTypeData%NodesConnN)) THEN - i1_l = LBOUND(SrcInitTypeData%NodesConnN,1) - i1_u = UBOUND(SrcInitTypeData%NodesConnN,1) - i2_l = LBOUND(SrcInitTypeData%NodesConnN,2) - i2_u = UBOUND(SrcInitTypeData%NodesConnN,2) - IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnN)) THEN - ALLOCATE(DstInitTypeData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnN.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%NodesConnN = SrcInitTypeData%NodesConnN -ENDIF -IF (ALLOCATED(SrcInitTypeData%NodesConnE)) THEN - i1_l = LBOUND(SrcInitTypeData%NodesConnE,1) - i1_u = UBOUND(SrcInitTypeData%NodesConnE,1) - i2_l = LBOUND(SrcInitTypeData%NodesConnE,2) - i2_u = UBOUND(SrcInitTypeData%NodesConnE,2) - IF (.NOT. ALLOCATED(DstInitTypeData%NodesConnE)) THEN - ALLOCATE(DstInitTypeData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%NodesConnE.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%NodesConnE = SrcInitTypeData%NodesConnE -ENDIF - DstInitTypeData%SSSum = SrcInitTypeData%SSSum - END SUBROUTINE SD_CopyInitType - - SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) - TYPE(SD_InitType), INTENT(INOUT) :: InitTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitType' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(InitTypeData%Joints)) THEN - DEALLOCATE(InitTypeData%Joints) -ENDIF -IF (ALLOCATED(InitTypeData%PropSetsB)) THEN - DEALLOCATE(InitTypeData%PropSetsB) -ENDIF -IF (ALLOCATED(InitTypeData%PropSetsC)) THEN - DEALLOCATE(InitTypeData%PropSetsC) -ENDIF -IF (ALLOCATED(InitTypeData%PropSetsR)) THEN - DEALLOCATE(InitTypeData%PropSetsR) -ENDIF -IF (ALLOCATED(InitTypeData%PropSetsX)) THEN - DEALLOCATE(InitTypeData%PropSetsX) -ENDIF -IF (ALLOCATED(InitTypeData%COSMs)) THEN - DEALLOCATE(InitTypeData%COSMs) -ENDIF -IF (ALLOCATED(InitTypeData%CMass)) THEN - DEALLOCATE(InitTypeData%CMass) -ENDIF -IF (ALLOCATED(InitTypeData%JDampings)) THEN - DEALLOCATE(InitTypeData%JDampings) -ENDIF -IF (ALLOCATED(InitTypeData%Members)) THEN - DEALLOCATE(InitTypeData%Members) -ENDIF -IF (ALLOCATED(InitTypeData%SSOutList)) THEN - DEALLOCATE(InitTypeData%SSOutList) -ENDIF -IF (ALLOCATED(InitTypeData%SSIK)) THEN - DEALLOCATE(InitTypeData%SSIK) -ENDIF -IF (ALLOCATED(InitTypeData%SSIM)) THEN - DEALLOCATE(InitTypeData%SSIM) -ENDIF -IF (ALLOCATED(InitTypeData%SSIfile)) THEN - DEALLOCATE(InitTypeData%SSIfile) -ENDIF -IF (ALLOCATED(InitTypeData%Soil_K)) THEN - DEALLOCATE(InitTypeData%Soil_K) -ENDIF -IF (ALLOCATED(InitTypeData%Soil_Points)) THEN - DEALLOCATE(InitTypeData%Soil_Points) -ENDIF -IF (ALLOCATED(InitTypeData%Soil_Nodes)) THEN - DEALLOCATE(InitTypeData%Soil_Nodes) -ENDIF -IF (ALLOCATED(InitTypeData%Nodes)) THEN - DEALLOCATE(InitTypeData%Nodes) -ENDIF -IF (ALLOCATED(InitTypeData%PropsB)) THEN - DEALLOCATE(InitTypeData%PropsB) -ENDIF -IF (ALLOCATED(InitTypeData%PropsC)) THEN - DEALLOCATE(InitTypeData%PropsC) -ENDIF -IF (ALLOCATED(InitTypeData%PropsR)) THEN - DEALLOCATE(InitTypeData%PropsR) -ENDIF -IF (ALLOCATED(InitTypeData%K)) THEN - DEALLOCATE(InitTypeData%K) -ENDIF -IF (ALLOCATED(InitTypeData%M)) THEN - DEALLOCATE(InitTypeData%M) -ENDIF -IF (ALLOCATED(InitTypeData%D)) THEN - DEALLOCATE(InitTypeData%D) -ENDIF -IF (ALLOCATED(InitTypeData%F)) THEN - DEALLOCATE(InitTypeData%F) -ENDIF -IF (ALLOCATED(InitTypeData%FG)) THEN - DEALLOCATE(InitTypeData%FG) -ENDIF -IF (ALLOCATED(InitTypeData%ElemProps)) THEN - DEALLOCATE(InitTypeData%ElemProps) -ENDIF -IF (ALLOCATED(InitTypeData%BCs)) THEN - DEALLOCATE(InitTypeData%BCs) -ENDIF -IF (ALLOCATED(InitTypeData%IntFc)) THEN - DEALLOCATE(InitTypeData%IntFc) -ENDIF -IF (ALLOCATED(InitTypeData%MemberNodes)) THEN - DEALLOCATE(InitTypeData%MemberNodes) -ENDIF -IF (ALLOCATED(InitTypeData%NodesConnN)) THEN - DEALLOCATE(InitTypeData%NodesConnN) -ENDIF -IF (ALLOCATED(InitTypeData%NodesConnE)) THEN - DEALLOCATE(InitTypeData%NodesConnE) -ENDIF - END SUBROUTINE SD_DestroyInitType - - SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InitType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName - Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint - Re_BufSz = Re_BufSz + 1 ! SubRotateZ - Re_BufSz = Re_BufSz + 1 ! g - Db_BufSz = Db_BufSz + 1 ! DT - Int_BufSz = Int_BufSz + 1 ! NJoints - Int_BufSz = Int_BufSz + 1 ! NPropSetsX - Int_BufSz = Int_BufSz + 1 ! NPropSetsB - Int_BufSz = Int_BufSz + 1 ! NPropSetsC - Int_BufSz = Int_BufSz + 1 ! NPropSetsR - Int_BufSz = Int_BufSz + 1 ! NCMass - Int_BufSz = Int_BufSz + 1 ! NCOSMs - Int_BufSz = Int_BufSz + 1 ! FEMMod - Int_BufSz = Int_BufSz + 1 ! NDiv - Int_BufSz = Int_BufSz + 1 ! CBMod - Int_BufSz = Int_BufSz + 1 ! Joints allocated yes/no - IF ( ALLOCATED(InData%Joints) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Joints upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Joints) ! Joints - END IF - Int_BufSz = Int_BufSz + 1 ! PropSetsB allocated yes/no - IF ( ALLOCATED(InData%PropSetsB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropSetsB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropSetsB) ! PropSetsB - END IF - Int_BufSz = Int_BufSz + 1 ! PropSetsC allocated yes/no - IF ( ALLOCATED(InData%PropSetsC) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropSetsC upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropSetsC) ! PropSetsC - END IF - Int_BufSz = Int_BufSz + 1 ! PropSetsR allocated yes/no - IF ( ALLOCATED(InData%PropSetsR) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropSetsR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropSetsR) ! PropSetsR - END IF - Int_BufSz = Int_BufSz + 1 ! PropSetsX allocated yes/no - IF ( ALLOCATED(InData%PropSetsX) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropSetsX upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropSetsX) ! PropSetsX - END IF - Int_BufSz = Int_BufSz + 1 ! COSMs allocated yes/no - IF ( ALLOCATED(InData%COSMs) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! COSMs upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%COSMs) ! COSMs - END IF - Int_BufSz = Int_BufSz + 1 ! CMass allocated yes/no - IF ( ALLOCATED(InData%CMass) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CMass upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CMass) ! CMass - END IF - Int_BufSz = Int_BufSz + 1 ! JDampings allocated yes/no - IF ( ALLOCATED(InData%JDampings) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! JDampings upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%JDampings) ! JDampings - END IF - Int_BufSz = Int_BufSz + 1 ! Members allocated yes/no - IF ( ALLOCATED(InData%Members) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Members upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Members) ! Members - END IF - Int_BufSz = Int_BufSz + 1 ! SSOutList allocated yes/no - IF ( ALLOCATED(InData%SSOutList) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! SSOutList upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%SSOutList)*LEN(InData%SSOutList) ! SSOutList - END IF - Int_BufSz = Int_BufSz + 1 ! OutCOSM - Int_BufSz = Int_BufSz + 1 ! TabDelim - Int_BufSz = Int_BufSz + 1 ! SSIK allocated yes/no - IF ( ALLOCATED(InData%SSIK) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! SSIK upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SSIK) ! SSIK - END IF - Int_BufSz = Int_BufSz + 1 ! SSIM allocated yes/no - IF ( ALLOCATED(InData%SSIM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! SSIM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SSIM) ! SSIM - END IF - Int_BufSz = Int_BufSz + 1 ! SSIfile allocated yes/no - IF ( ALLOCATED(InData%SSIfile) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! SSIfile upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%SSIfile)*LEN(InData%SSIfile) ! SSIfile - END IF - Int_BufSz = Int_BufSz + 1 ! Soil_K allocated yes/no - IF ( ALLOCATED(InData%Soil_K) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! Soil_K upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Soil_K) ! Soil_K - END IF - Int_BufSz = Int_BufSz + 1 ! Soil_Points allocated yes/no - IF ( ALLOCATED(InData%Soil_Points) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Soil_Points upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Soil_Points) ! Soil_Points - END IF - Int_BufSz = Int_BufSz + 1 ! Soil_Nodes allocated yes/no - IF ( ALLOCATED(InData%Soil_Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Soil_Nodes upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Soil_Nodes) ! Soil_Nodes - END IF - Int_BufSz = Int_BufSz + 1 ! NElem - Int_BufSz = Int_BufSz + 1 ! NPropB - Int_BufSz = Int_BufSz + 1 ! NPropC - Int_BufSz = Int_BufSz + 1 ! NPropR - Int_BufSz = Int_BufSz + 1 ! Nodes allocated yes/no - IF ( ALLOCATED(InData%Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Nodes upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Nodes) ! Nodes - END IF - Int_BufSz = Int_BufSz + 1 ! PropsB allocated yes/no - IF ( ALLOCATED(InData%PropsB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropsB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropsB) ! PropsB - END IF - Int_BufSz = Int_BufSz + 1 ! PropsC allocated yes/no - IF ( ALLOCATED(InData%PropsC) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropsC upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropsC) ! PropsC - END IF - Int_BufSz = Int_BufSz + 1 ! PropsR allocated yes/no - IF ( ALLOCATED(InData%PropsR) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PropsR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PropsR) ! PropsR - END IF - Int_BufSz = Int_BufSz + 1 ! K allocated yes/no - IF ( ALLOCATED(InData%K) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! K upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%K) ! K - END IF - Int_BufSz = Int_BufSz + 1 ! M allocated yes/no - IF ( ALLOCATED(InData%M) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%M) ! M - END IF - Int_BufSz = Int_BufSz + 1 ! D allocated yes/no - IF ( ALLOCATED(InData%D) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D) ! D - END IF - Int_BufSz = Int_BufSz + 1 ! F allocated yes/no - IF ( ALLOCATED(InData%F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F) ! F - END IF - Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no - IF ( ALLOCATED(InData%FG) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FG) ! FG - END IF - Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no - IF ( ALLOCATED(InData%ElemProps) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElemProps upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%ElemProps) ! ElemProps - END IF - Int_BufSz = Int_BufSz + 1 ! BCs allocated yes/no - IF ( ALLOCATED(InData%BCs) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! BCs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%BCs) ! BCs - END IF - Int_BufSz = Int_BufSz + 1 ! IntFc allocated yes/no - IF ( ALLOCATED(InData%IntFc) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! IntFc upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IntFc) ! IntFc - END IF - Int_BufSz = Int_BufSz + 1 ! MemberNodes allocated yes/no - IF ( ALLOCATED(InData%MemberNodes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MemberNodes upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%MemberNodes) ! MemberNodes - END IF - Int_BufSz = Int_BufSz + 1 ! NodesConnN allocated yes/no - IF ( ALLOCATED(InData%NodesConnN) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! NodesConnN upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodesConnN) ! NodesConnN - END IF - Int_BufSz = Int_BufSz + 1 ! NodesConnE allocated yes/no - IF ( ALLOCATED(InData%NodesConnE) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! NodesConnE upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodesConnE) ! NodesConnE - END IF - Int_BufSz = Int_BufSz + 1 ! SSSum - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%RootName) - IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g - Re_Xferred = Re_Xferred + 1 - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsX - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsB - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsC - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsR - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCMass - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCOSMs - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%FEMMod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NDiv - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%CBMod , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Joints) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Joints,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Joints,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Joints,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Joints)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Joints))-1 ) = PACK(InData%Joints,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Joints) - END IF - IF ( .NOT. ALLOCATED(InData%PropSetsB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropSetsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsB))-1 ) = PACK(InData%PropSetsB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsB) - END IF - IF ( .NOT. ALLOCATED(InData%PropSetsC) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsC,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropSetsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsC))-1 ) = PACK(InData%PropSetsC,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsC) - END IF - IF ( .NOT. ALLOCATED(InData%PropSetsR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsR,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropSetsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsR))-1 ) = PACK(InData%PropSetsR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsR) - END IF - IF ( .NOT. ALLOCATED(InData%PropSetsX) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropSetsX,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropSetsX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsX))-1 ) = PACK(InData%PropSetsX,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsX) - END IF - IF ( .NOT. ALLOCATED(InData%COSMs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%COSMs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%COSMs,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%COSMs,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%COSMs)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%COSMs))-1 ) = PACK(InData%COSMs,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%COSMs) - END IF - IF ( .NOT. ALLOCATED(InData%CMass) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMass,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMass,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMass,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%CMass)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMass))-1 ) = PACK(InData%CMass,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CMass) - END IF - IF ( .NOT. ALLOCATED(InData%JDampings) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%JDampings,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%JDampings,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%JDampings)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%JDampings))-1 ) = PACK(InData%JDampings,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%JDampings) - END IF - IF ( .NOT. ALLOCATED(InData%Members) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Members,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Members,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Members)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Members))-1 ) = PACK(InData%Members,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Members) - END IF - IF ( .NOT. ALLOCATED(InData%SSOutList) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSOutList,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSOutList,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%SSOutList,1), UBOUND(InData%SSOutList,1) - DO I = 1, LEN(InData%SSOutList) - IntKiBuf(Int_Xferred) = ICHAR(InData%SSOutList(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutCOSM , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%SSIK) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIK,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%SSIK)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIK) - END IF - IF ( .NOT. ALLOCATED(InData%SSIM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%SSIM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIM) - END IF - IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SSIfile,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIfile,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%SSIfile,1), UBOUND(InData%SSIfile,1) - DO I = 1, LEN(InData%SSIfile) - IntKiBuf(Int_Xferred) = ICHAR(InData%SSIfile(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - END IF - IF ( .NOT. ALLOCATED(InData%Soil_K) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,3) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Soil_K)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Soil_K))-1 ) = PACK(InData%Soil_K,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Soil_K) - END IF - IF ( .NOT. ALLOCATED(InData%Soil_Points) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Soil_Points)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Soil_Points))-1 ) = PACK(InData%Soil_Points,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Soil_Points) - END IF - IF ( .NOT. ALLOCATED(InData%Soil_Nodes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Nodes,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Soil_Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Soil_Nodes))-1 ) = PACK(InData%Soil_Nodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Soil_Nodes) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropC - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropR - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Nodes)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Nodes))-1 ) = PACK(InData%Nodes,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Nodes) - END IF - IF ( .NOT. ALLOCATED(InData%PropsB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsB))-1 ) = PACK(InData%PropsB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsB) - END IF - IF ( .NOT. ALLOCATED(InData%PropsC) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsC,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsC))-1 ) = PACK(InData%PropsC,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsC) - END IF - IF ( .NOT. ALLOCATED(InData%PropsR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PropsR,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PropsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsR))-1 ) = PACK(InData%PropsR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsR) - END IF - IF ( .NOT. ALLOCATED(InData%K) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%K,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%K,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%K)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%K))-1 ) = PACK(InData%K,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%K) - END IF - IF ( .NOT. ALLOCATED(InData%M) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%M,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%M,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%M) - END IF - IF ( .NOT. ALLOCATED(InData%D) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D))-1 ) = PACK(InData%D,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D) - END IF - IF ( .NOT. ALLOCATED(InData%F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F))-1 ) = PACK(InData%F,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F) - END IF - IF ( .NOT. ALLOCATED(InData%FG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%FG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FG))-1 ) = PACK(InData%FG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FG) - END IF - IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ElemProps)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%ElemProps))-1 ) = PACK(InData%ElemProps,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%ElemProps) - END IF - IF ( .NOT. ALLOCATED(InData%BCs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%BCs)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%BCs))-1 ) = PACK(InData%BCs,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%BCs) - END IF - IF ( .NOT. ALLOCATED(InData%IntFc) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IntFc)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IntFc))-1 ) = PACK(InData%IntFc,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IntFc) - END IF - IF ( .NOT. ALLOCATED(InData%MemberNodes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberNodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MemberNodes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MemberNodes,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MemberNodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%MemberNodes))-1 ) = PACK(InData%MemberNodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%MemberNodes) - END IF - IF ( .NOT. ALLOCATED(InData%NodesConnN) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnN,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnN,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnN,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%NodesConnN)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodesConnN))-1 ) = PACK(InData%NodesConnN,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%NodesConnN) - END IF - IF ( .NOT. ALLOCATED(InData%NodesConnE) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnE,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesConnE,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesConnE,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%NodesConnE)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%NodesConnE))-1 ) = PACK(InData%NodesConnE,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%NodesConnE) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%SSSum , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_PackInitType - - SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InitType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%RootName) - OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - i1_l = LBOUND(OutData%TP_RefPoint,1) - i1_u = UBOUND(OutData%TP_RefPoint,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) - DEALLOCATE(mask1) - OutData%SubRotateZ = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%g = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%DT = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%NJoints = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsX = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsB = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsC = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsR = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NCMass = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NCOSMs = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%FEMMod = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NDiv = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%CBMod = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Joints not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Joints)) DEALLOCATE(OutData%Joints) - ALLOCATE(OutData%Joints(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Joints.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Joints)>0) OutData%Joints = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Joints))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Joints) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropSetsB)) DEALLOCATE(OutData%PropSetsB) - ALLOCATE(OutData%PropSetsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsB)>0) OutData%PropSetsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsC not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropSetsC)) DEALLOCATE(OutData%PropSetsC) - ALLOCATE(OutData%PropSetsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsC.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsC)>0) OutData%PropSetsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsC))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsC) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropSetsR)) DEALLOCATE(OutData%PropSetsR) - ALLOCATE(OutData%PropSetsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsR)>0) OutData%PropSetsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsR) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsX not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropSetsX)) DEALLOCATE(OutData%PropSetsX) - ALLOCATE(OutData%PropSetsX(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsX)>0) OutData%PropSetsX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsX))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsX) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%COSMs)) DEALLOCATE(OutData%COSMs) - ALLOCATE(OutData%COSMs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%COSMs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%COSMs)>0) OutData%COSMs = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%COSMs))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%COSMs) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMass not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CMass)) DEALLOCATE(OutData%CMass) - ALLOCATE(OutData%CMass(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMass.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CMass)>0) OutData%CMass = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMass))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CMass) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! JDampings not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%JDampings)) DEALLOCATE(OutData%JDampings) - ALLOCATE(OutData%JDampings(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%JDampings.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%JDampings)>0) OutData%JDampings = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%JDampings))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%JDampings) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Members)) DEALLOCATE(OutData%Members) - ALLOCATE(OutData%Members(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Members.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Members)>0) OutData%Members = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Members))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Members) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSOutList not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SSOutList)) DEALLOCATE(OutData%SSOutList) - ALLOCATE(OutData%SSOutList(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSOutList.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%SSOutList,1), UBOUND(OutData%SSOutList,1) - DO I = 1, LEN(OutData%SSOutList) - OutData%SSOutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - OutData%OutCOSM = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIK not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SSIK)) DEALLOCATE(OutData%SSIK) - ALLOCATE(OutData%SSIK(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIK.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%SSIK)>0) OutData%SSIK = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIK) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SSIM)) DEALLOCATE(OutData%SSIM) - ALLOCATE(OutData%SSIM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%SSIM)>0) OutData%SSIM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIM) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SSIfile)) DEALLOCATE(OutData%SSIfile) - ALLOCATE(OutData%SSIfile(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIfile.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%SSIfile,1), UBOUND(OutData%SSIfile,1) - DO I = 1, LEN(OutData%SSIfile) - OutData%SSIfile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO !i1 - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_K not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Soil_K)) DEALLOCATE(OutData%Soil_K) - ALLOCATE(OutData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_K.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask3(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask3 = .TRUE. - IF (SIZE(OutData%Soil_K)>0) OutData%Soil_K = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Soil_K))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Soil_K) - DEALLOCATE(mask3) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Points not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Soil_Points)) DEALLOCATE(OutData%Soil_Points) - ALLOCATE(OutData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Points.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Soil_Points)>0) OutData%Soil_Points = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Soil_Points))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Soil_Points) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Nodes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Soil_Nodes)) DEALLOCATE(OutData%Soil_Nodes) - ALLOCATE(OutData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Soil_Nodes)>0) OutData%Soil_Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Soil_Nodes))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Soil_Nodes) - DEALLOCATE(mask1) - END IF - OutData%NElem = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropB = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropC = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropR = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes)) DEALLOCATE(OutData%Nodes) - ALLOCATE(OutData%Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes)>0) OutData%Nodes = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Nodes))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Nodes) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropsB)) DEALLOCATE(OutData%PropsB) - ALLOCATE(OutData%PropsB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsB)>0) OutData%PropsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsC not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropsC)) DEALLOCATE(OutData%PropsC) - ALLOCATE(OutData%PropsC(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsC.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsC)>0) OutData%PropsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsC))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsC) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PropsR)) DEALLOCATE(OutData%PropsR) - ALLOCATE(OutData%PropsR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsR)>0) OutData%PropsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsR) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%K)) DEALLOCATE(OutData%K) - ALLOCATE(OutData%K(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%K)>0) OutData%K = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%K))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%K) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%M)) DEALLOCATE(OutData%M) - ALLOCATE(OutData%M(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%M.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%M)>0) OutData%M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%M))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%M) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D)) DEALLOCATE(OutData%D) - ALLOCATE(OutData%D(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D)>0) OutData%D = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F)) DEALLOCATE(OutData%F) - ALLOCATE(OutData%F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%F)>0) OutData%F = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FG)) DEALLOCATE(OutData%FG) - ALLOCATE(OutData%FG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FG)>0) OutData%FG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FG))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FG) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) - ALLOCATE(OutData%ElemProps(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElemProps)>0) OutData%ElemProps = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%ElemProps))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%ElemProps) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BCs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%BCs)) DEALLOCATE(OutData%BCs) - ALLOCATE(OutData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BCs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%BCs)>0) OutData%BCs = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%BCs))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%BCs) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IntFc not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IntFc)) DEALLOCATE(OutData%IntFc) - ALLOCATE(OutData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IntFc.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%IntFc)>0) OutData%IntFc = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IntFc))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IntFc) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberNodes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MemberNodes)) DEALLOCATE(OutData%MemberNodes) - ALLOCATE(OutData%MemberNodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MemberNodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MemberNodes)>0) OutData%MemberNodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%MemberNodes))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%MemberNodes) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnN not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesConnN)) DEALLOCATE(OutData%NodesConnN) - ALLOCATE(OutData%NodesConnN(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnN.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%NodesConnN)>0) OutData%NodesConnN = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodesConnN))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%NodesConnN) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesConnE not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesConnE)) DEALLOCATE(OutData%NodesConnE) - ALLOCATE(OutData%NodesConnE(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesConnE.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%NodesConnE)>0) OutData%NodesConnE = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%NodesConnE))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%NodesConnE) - DEALLOCATE(mask2) - END IF - OutData%SSSum = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_UnPackInitType - - SUBROUTINE SD_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_ContinuousStateType), INTENT(IN) :: SrcContStateData - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: DstContStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyContState' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcContStateData%qm)) THEN - i1_l = LBOUND(SrcContStateData%qm,1) - i1_u = UBOUND(SrcContStateData%qm,1) - IF (.NOT. ALLOCATED(DstContStateData%qm)) THEN - ALLOCATE(DstContStateData%qm(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qm.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstContStateData%qm = SrcContStateData%qm -ENDIF -IF (ALLOCATED(SrcContStateData%qmdot)) THEN - i1_l = LBOUND(SrcContStateData%qmdot,1) - i1_u = UBOUND(SrcContStateData%qmdot,1) - IF (.NOT. ALLOCATED(DstContStateData%qmdot)) THEN - ALLOCATE(DstContStateData%qmdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%qmdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstContStateData%qmdot = SrcContStateData%qmdot -ENDIF - END SUBROUTINE SD_CopyContState - - SUBROUTINE SD_DestroyContState( ContStateData, ErrStat, ErrMsg ) - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: ContStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyContState' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(ContStateData%qm)) THEN - DEALLOCATE(ContStateData%qm) -ENDIF -IF (ALLOCATED(ContStateData%qmdot)) THEN - DEALLOCATE(ContStateData%qmdot) -ENDIF - END SUBROUTINE SD_DestroyContState - - SUBROUTINE SD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_ContinuousStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackContState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! qm allocated yes/no - IF ( ALLOCATED(InData%qm) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! qm upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%qm) ! qm - END IF - Int_BufSz = Int_BufSz + 1 ! qmdot allocated yes/no - IF ( ALLOCATED(InData%qmdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! qmdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%qmdot) ! qmdot - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%qm) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%qm,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qm,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%qm)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qm))-1 ) = PACK(InData%qm,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%qm) - END IF - IF ( .NOT. ALLOCATED(InData%qmdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%qmdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%qmdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qmdot))-1 ) = PACK(InData%qmdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%qmdot) - END IF - END SUBROUTINE SD_PackContState - - SUBROUTINE SD_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_ContinuousStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackContState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qm not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%qm)) DEALLOCATE(OutData%qm) - ALLOCATE(OutData%qm(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qm.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%qm)>0) OutData%qm = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qm))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%qm) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%qmdot)) DEALLOCATE(OutData%qmdot) - ALLOCATE(OutData%qmdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%qmdot)>0) OutData%qmdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qmdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%qmdot) - DEALLOCATE(mask1) - END IF - END SUBROUTINE SD_UnPackContState - - SUBROUTINE SD_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_DiscreteStateType), INTENT(IN) :: SrcDiscStateData - TYPE(SD_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyDiscState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState - END SUBROUTINE SD_CopyDiscState - - SUBROUTINE SD_DestroyDiscState( DiscStateData, ErrStat, ErrMsg ) - TYPE(SD_DiscreteStateType), INTENT(INOUT) :: DiscStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyDiscState' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - END SUBROUTINE SD_DestroyDiscState - - SUBROUTINE SD_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_DiscreteStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackDiscState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyDiscState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DummyDiscState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE SD_PackDiscState - - SUBROUTINE SD_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_DiscreteStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackDiscState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyDiscState = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE SD_UnPackDiscState - - SUBROUTINE SD_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_ConstraintStateType), INTENT(IN) :: SrcConstrStateData - TYPE(SD_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyConstrState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState - END SUBROUTINE SD_CopyConstrState - - SUBROUTINE SD_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg ) - TYPE(SD_ConstraintStateType), INTENT(INOUT) :: ConstrStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyConstrState' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - END SUBROUTINE SD_DestroyConstrState - - SUBROUTINE SD_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_ConstraintStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackConstrState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyConstrState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%DummyConstrState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE SD_PackConstrState - - SUBROUTINE SD_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_ConstraintStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackConstrState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyConstrState = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE SD_UnPackConstrState - - SUBROUTINE SD_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_OtherStateType), INTENT(IN) :: SrcOtherStateData - TYPE(SD_OtherStateType), INTENT(INOUT) :: DstOtherStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyOtherState' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcOtherStateData%xdot)) THEN - i1_l = LBOUND(SrcOtherStateData%xdot,1) - i1_u = UBOUND(SrcOtherStateData%xdot,1) - IF (.NOT. ALLOCATED(DstOtherStateData%xdot)) THEN - ALLOCATE(DstOtherStateData%xdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcOtherStateData%xdot,1), UBOUND(SrcOtherStateData%xdot,1) - CALL SD_CopyContState( SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF - DstOtherStateData%n = SrcOtherStateData%n - END SUBROUTINE SD_CopyOtherState - - SUBROUTINE SD_DestroyOtherState( OtherStateData, ErrStat, ErrMsg ) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OtherStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOtherState' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(OtherStateData%xdot)) THEN -DO i1 = LBOUND(OtherStateData%xdot,1), UBOUND(OtherStateData%xdot,1) - CALL SD_DestroyContState( OtherStateData%xdot(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(OtherStateData%xdot) -ENDIF - END SUBROUTINE SD_DestroyOtherState - - SUBROUTINE SD_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_OtherStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackOtherState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! xdot allocated yes/no - IF ( ALLOCATED(InData%xdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! xdot upper/lower bounds for each dimension - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) - Int_BufSz = Int_BufSz + 3 ! xdot: size of buffers for each call to pack subtype - CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, .TRUE. ) ! xdot - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! xdot - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! xdot - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! xdot - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! n - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%xdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%xdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%xdot,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%xdot,1), UBOUND(InData%xdot,1) - CALL SD_PackContState( Re_Buf, Db_Buf, Int_Buf, InData%xdot(i1), ErrStat2, ErrMsg2, OnlySize ) ! xdot - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%n - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_PackOtherState - - SUBROUTINE SD_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_OtherStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackOtherState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! xdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%xdot)) DEALLOCATE(OutData%xdot) - ALLOCATE(OutData%xdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%xdot,1), UBOUND(OutData%xdot,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_UnpackContState( Re_Buf, Db_Buf, Int_Buf, OutData%xdot(i1), ErrStat2, ErrMsg2 ) ! xdot - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - OutData%n = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_UnPackOtherState - - SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(SD_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcMiscData%qmdotdot)) THEN - i1_l = LBOUND(SrcMiscData%qmdotdot,1) - i1_u = UBOUND(SrcMiscData%qmdotdot,1) - IF (.NOT. ALLOCATED(DstMiscData%qmdotdot)) THEN - ALLOCATE(DstMiscData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%qmdotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%qmdotdot = SrcMiscData%qmdotdot -ENDIF - DstMiscData%u_TP = SrcMiscData%u_TP - DstMiscData%udot_TP = SrcMiscData%udot_TP - DstMiscData%udotdot_TP = SrcMiscData%udotdot_TP -IF (ALLOCATED(SrcMiscData%UFL)) THEN - i1_l = LBOUND(SrcMiscData%UFL,1) - i1_u = UBOUND(SrcMiscData%UFL,1) - IF (.NOT. ALLOCATED(DstMiscData%UFL)) THEN - ALLOCATE(DstMiscData%UFL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UFL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UFL = SrcMiscData%UFL -ENDIF -IF (ALLOCATED(SrcMiscData%UR_bar)) THEN - i1_l = LBOUND(SrcMiscData%UR_bar,1) - i1_u = UBOUND(SrcMiscData%UR_bar,1) - IF (.NOT. ALLOCATED(DstMiscData%UR_bar)) THEN - ALLOCATE(DstMiscData%UR_bar(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UR_bar = SrcMiscData%UR_bar -ENDIF -IF (ALLOCATED(SrcMiscData%UR_bar_dot)) THEN - i1_l = LBOUND(SrcMiscData%UR_bar_dot,1) - i1_u = UBOUND(SrcMiscData%UR_bar_dot,1) - IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dot)) THEN - ALLOCATE(DstMiscData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UR_bar_dot = SrcMiscData%UR_bar_dot -ENDIF -IF (ALLOCATED(SrcMiscData%UR_bar_dotdot)) THEN - i1_l = LBOUND(SrcMiscData%UR_bar_dotdot,1) - i1_u = UBOUND(SrcMiscData%UR_bar_dotdot,1) - IF (.NOT. ALLOCATED(DstMiscData%UR_bar_dotdot)) THEN - ALLOCATE(DstMiscData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UR_bar_dotdot = SrcMiscData%UR_bar_dotdot -ENDIF -IF (ALLOCATED(SrcMiscData%UL)) THEN - i1_l = LBOUND(SrcMiscData%UL,1) - i1_u = UBOUND(SrcMiscData%UL,1) - IF (.NOT. ALLOCATED(DstMiscData%UL)) THEN - ALLOCATE(DstMiscData%UL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UL = SrcMiscData%UL -ENDIF -IF (ALLOCATED(SrcMiscData%UL_dot)) THEN - i1_l = LBOUND(SrcMiscData%UL_dot,1) - i1_u = UBOUND(SrcMiscData%UL_dot,1) - IF (.NOT. ALLOCATED(DstMiscData%UL_dot)) THEN - ALLOCATE(DstMiscData%UL_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UL_dot = SrcMiscData%UL_dot -ENDIF -IF (ALLOCATED(SrcMiscData%UL_dotdot)) THEN - i1_l = LBOUND(SrcMiscData%UL_dotdot,1) - i1_u = UBOUND(SrcMiscData%UL_dotdot,1) - IF (.NOT. ALLOCATED(DstMiscData%UL_dotdot)) THEN - ALLOCATE(DstMiscData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%UL_dotdot = SrcMiscData%UL_dotdot -ENDIF -IF (ALLOCATED(SrcMiscData%U_full)) THEN - i1_l = LBOUND(SrcMiscData%U_full,1) - i1_u = UBOUND(SrcMiscData%U_full,1) - IF (.NOT. ALLOCATED(DstMiscData%U_full)) THEN - ALLOCATE(DstMiscData%U_full(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_full = SrcMiscData%U_full -ENDIF -IF (ALLOCATED(SrcMiscData%U_full_dot)) THEN - i1_l = LBOUND(SrcMiscData%U_full_dot,1) - i1_u = UBOUND(SrcMiscData%U_full_dot,1) - IF (.NOT. ALLOCATED(DstMiscData%U_full_dot)) THEN - ALLOCATE(DstMiscData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_full_dot = SrcMiscData%U_full_dot -ENDIF -IF (ALLOCATED(SrcMiscData%U_full_dotdot)) THEN - i1_l = LBOUND(SrcMiscData%U_full_dotdot,1) - i1_u = UBOUND(SrcMiscData%U_full_dotdot,1) - IF (.NOT. ALLOCATED(DstMiscData%U_full_dotdot)) THEN - ALLOCATE(DstMiscData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_full_dotdot = SrcMiscData%U_full_dotdot -ENDIF -IF (ALLOCATED(SrcMiscData%U_red)) THEN - i1_l = LBOUND(SrcMiscData%U_red,1) - i1_u = UBOUND(SrcMiscData%U_red,1) - IF (.NOT. ALLOCATED(DstMiscData%U_red)) THEN - ALLOCATE(DstMiscData%U_red(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_red = SrcMiscData%U_red -ENDIF -IF (ALLOCATED(SrcMiscData%U_red_dot)) THEN - i1_l = LBOUND(SrcMiscData%U_red_dot,1) - i1_u = UBOUND(SrcMiscData%U_red_dot,1) - IF (.NOT. ALLOCATED(DstMiscData%U_red_dot)) THEN - ALLOCATE(DstMiscData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_red_dot = SrcMiscData%U_red_dot -ENDIF -IF (ALLOCATED(SrcMiscData%U_red_dotdot)) THEN - i1_l = LBOUND(SrcMiscData%U_red_dotdot,1) - i1_u = UBOUND(SrcMiscData%U_red_dotdot,1) - IF (.NOT. ALLOCATED(DstMiscData%U_red_dotdot)) THEN - ALLOCATE(DstMiscData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot -ENDIF -IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN - i1_l = LBOUND(SrcMiscData%SDWrOutput,1) - i1_u = UBOUND(SrcMiscData%SDWrOutput,1) - IF (.NOT. ALLOCATED(DstMiscData%SDWrOutput)) THEN - ALLOCATE(DstMiscData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%SDWrOutput = SrcMiscData%SDWrOutput -ENDIF - DstMiscData%LastOutTime = SrcMiscData%LastOutTime - DstMiscData%Decimat = SrcMiscData%Decimat -IF (ALLOCATED(SrcMiscData%Fext)) THEN - i1_l = LBOUND(SrcMiscData%Fext,1) - i1_u = UBOUND(SrcMiscData%Fext,1) - IF (.NOT. ALLOCATED(DstMiscData%Fext)) THEN - ALLOCATE(DstMiscData%Fext(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%Fext = SrcMiscData%Fext -ENDIF -IF (ALLOCATED(SrcMiscData%Fext_red)) THEN - i1_l = LBOUND(SrcMiscData%Fext_red,1) - i1_u = UBOUND(SrcMiscData%Fext_red,1) - IF (.NOT. ALLOCATED(DstMiscData%Fext_red)) THEN - ALLOCATE(DstMiscData%Fext_red(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%Fext_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%Fext_red = SrcMiscData%Fext_red -ENDIF - END SUBROUTINE SD_CopyMisc - - SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) - TYPE(SD_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMisc' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(MiscData%qmdotdot)) THEN - DEALLOCATE(MiscData%qmdotdot) -ENDIF -IF (ALLOCATED(MiscData%UFL)) THEN - DEALLOCATE(MiscData%UFL) -ENDIF -IF (ALLOCATED(MiscData%UR_bar)) THEN - DEALLOCATE(MiscData%UR_bar) -ENDIF -IF (ALLOCATED(MiscData%UR_bar_dot)) THEN - DEALLOCATE(MiscData%UR_bar_dot) -ENDIF -IF (ALLOCATED(MiscData%UR_bar_dotdot)) THEN - DEALLOCATE(MiscData%UR_bar_dotdot) -ENDIF -IF (ALLOCATED(MiscData%UL)) THEN - DEALLOCATE(MiscData%UL) -ENDIF -IF (ALLOCATED(MiscData%UL_dot)) THEN - DEALLOCATE(MiscData%UL_dot) -ENDIF -IF (ALLOCATED(MiscData%UL_dotdot)) THEN - DEALLOCATE(MiscData%UL_dotdot) -ENDIF -IF (ALLOCATED(MiscData%U_full)) THEN - DEALLOCATE(MiscData%U_full) -ENDIF -IF (ALLOCATED(MiscData%U_full_dot)) THEN - DEALLOCATE(MiscData%U_full_dot) -ENDIF -IF (ALLOCATED(MiscData%U_full_dotdot)) THEN - DEALLOCATE(MiscData%U_full_dotdot) -ENDIF -IF (ALLOCATED(MiscData%U_red)) THEN - DEALLOCATE(MiscData%U_red) -ENDIF -IF (ALLOCATED(MiscData%U_red_dot)) THEN - DEALLOCATE(MiscData%U_red_dot) -ENDIF -IF (ALLOCATED(MiscData%U_red_dotdot)) THEN - DEALLOCATE(MiscData%U_red_dotdot) -ENDIF -IF (ALLOCATED(MiscData%SDWrOutput)) THEN - DEALLOCATE(MiscData%SDWrOutput) -ENDIF -IF (ALLOCATED(MiscData%Fext)) THEN - DEALLOCATE(MiscData%Fext) -ENDIF -IF (ALLOCATED(MiscData%Fext_red)) THEN - DEALLOCATE(MiscData%Fext_red) -ENDIF - END SUBROUTINE SD_DestroyMisc - - SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! qmdotdot allocated yes/no - IF ( ALLOCATED(InData%qmdotdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! qmdotdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%qmdotdot) ! qmdotdot - END IF - Re_BufSz = Re_BufSz + SIZE(InData%u_TP) ! u_TP - Re_BufSz = Re_BufSz + SIZE(InData%udot_TP) ! udot_TP - Re_BufSz = Re_BufSz + SIZE(InData%udotdot_TP) ! udotdot_TP - Int_BufSz = Int_BufSz + 1 ! UFL allocated yes/no - IF ( ALLOCATED(InData%UFL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UFL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UFL) ! UFL - END IF - Int_BufSz = Int_BufSz + 1 ! UR_bar allocated yes/no - IF ( ALLOCATED(InData%UR_bar) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UR_bar upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UR_bar) ! UR_bar - END IF - Int_BufSz = Int_BufSz + 1 ! UR_bar_dot allocated yes/no - IF ( ALLOCATED(InData%UR_bar_dot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dot) ! UR_bar_dot - END IF - Int_BufSz = Int_BufSz + 1 ! UR_bar_dotdot allocated yes/no - IF ( ALLOCATED(InData%UR_bar_dotdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UR_bar_dotdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UR_bar_dotdot) ! UR_bar_dotdot - END IF - Int_BufSz = Int_BufSz + 1 ! UL allocated yes/no - IF ( ALLOCATED(InData%UL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UL) ! UL - END IF - Int_BufSz = Int_BufSz + 1 ! UL_dot allocated yes/no - IF ( ALLOCATED(InData%UL_dot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UL_dot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UL_dot) ! UL_dot - END IF - Int_BufSz = Int_BufSz + 1 ! UL_dotdot allocated yes/no - IF ( ALLOCATED(InData%UL_dotdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UL_dotdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UL_dotdot) ! UL_dotdot - END IF - Int_BufSz = Int_BufSz + 1 ! U_full allocated yes/no - IF ( ALLOCATED(InData%U_full) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_full upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_full) ! U_full - END IF - Int_BufSz = Int_BufSz + 1 ! U_full_dot allocated yes/no - IF ( ALLOCATED(InData%U_full_dot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_full_dot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_full_dot) ! U_full_dot - END IF - Int_BufSz = Int_BufSz + 1 ! U_full_dotdot allocated yes/no - IF ( ALLOCATED(InData%U_full_dotdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_full_dotdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_full_dotdot) ! U_full_dotdot - END IF - Int_BufSz = Int_BufSz + 1 ! U_red allocated yes/no - IF ( ALLOCATED(InData%U_red) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_red upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_red) ! U_red - END IF - Int_BufSz = Int_BufSz + 1 ! U_red_dot allocated yes/no - IF ( ALLOCATED(InData%U_red_dot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_red_dot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_red_dot) ! U_red_dot - END IF - Int_BufSz = Int_BufSz + 1 ! U_red_dotdot allocated yes/no - IF ( ALLOCATED(InData%U_red_dotdot) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot - END IF - Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no - IF ( ALLOCATED(InData%SDWrOutput) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! SDWrOutput upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SDWrOutput) ! SDWrOutput - END IF - Db_BufSz = Db_BufSz + 1 ! LastOutTime - Int_BufSz = Int_BufSz + 1 ! Decimat - Int_BufSz = Int_BufSz + 1 ! Fext allocated yes/no - IF ( ALLOCATED(InData%Fext) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Fext upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Fext) ! Fext - END IF - Int_BufSz = Int_BufSz + 1 ! Fext_red allocated yes/no - IF ( ALLOCATED(InData%Fext_red) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Fext_red upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Fext_red) ! Fext_red - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%qmdotdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%qmdotdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%qmdotdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%qmdotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%qmdotdot))-1 ) = PACK(InData%qmdotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%qmdotdot) - END IF - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%u_TP))-1 ) = PACK(InData%u_TP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%u_TP) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%udot_TP))-1 ) = PACK(InData%udot_TP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%udot_TP) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%udotdot_TP))-1 ) = PACK(InData%udotdot_TP,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%udotdot_TP) - IF ( .NOT. ALLOCATED(InData%UFL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UFL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UFL,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UFL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UFL))-1 ) = PACK(InData%UFL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UFL) - END IF - IF ( .NOT. ALLOCATED(InData%UR_bar) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UR_bar)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar))-1 ) = PACK(InData%UR_bar,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UR_bar) - END IF - IF ( .NOT. ALLOCATED(InData%UR_bar_dot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar_dot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UR_bar_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar_dot))-1 ) = PACK(InData%UR_bar_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UR_bar_dot) - END IF - IF ( .NOT. ALLOCATED(InData%UR_bar_dotdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UR_bar_dotdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UR_bar_dotdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UR_bar_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UR_bar_dotdot))-1 ) = PACK(InData%UR_bar_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UR_bar_dotdot) - END IF - IF ( .NOT. ALLOCATED(InData%UL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL))-1 ) = PACK(InData%UL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UL) - END IF - IF ( .NOT. ALLOCATED(InData%UL_dot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_dot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UL_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_dot))-1 ) = PACK(InData%UL_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UL_dot) - END IF - IF ( .NOT. ALLOCATED(InData%UL_dotdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_dotdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_dotdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UL_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_dotdot))-1 ) = PACK(InData%UL_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UL_dotdot) - END IF - IF ( .NOT. ALLOCATED(InData%U_full) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_full)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full))-1 ) = PACK(InData%U_full,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full) - END IF - IF ( .NOT. ALLOCATED(InData%U_full_dot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_full_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dot))-1 ) = PACK(InData%U_full_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full_dot) - END IF - IF ( .NOT. ALLOCATED(InData%U_full_dotdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_dotdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dotdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_full_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dotdot))-1 ) = PACK(InData%U_full_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full_dotdot) - END IF - IF ( .NOT. ALLOCATED(InData%U_red) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red))-1 ) = PACK(InData%U_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red) - END IF - IF ( .NOT. ALLOCATED(InData%U_red_dot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_red_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dot))-1 ) = PACK(InData%U_red_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red_dot) - END IF - IF ( .NOT. ALLOCATED(InData%U_red_dotdot) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_dotdot,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dotdot,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%U_red_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dotdot))-1 ) = PACK(InData%U_red_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red_dotdot) - END IF - IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SDWrOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SDWrOutput,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%SDWrOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SDWrOutput))-1 ) = PACK(InData%SDWrOutput,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SDWrOutput) - END IF - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%LastOutTime - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Fext) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext) - END IF - IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fext_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) - END IF - END SUBROUTINE SD_PackMisc - - SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%qmdotdot)) DEALLOCATE(OutData%qmdotdot) - ALLOCATE(OutData%qmdotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%qmdotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%qmdotdot)>0) OutData%qmdotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%qmdotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%qmdotdot) - DEALLOCATE(mask1) - END IF - i1_l = LBOUND(OutData%u_TP,1) - i1_u = UBOUND(OutData%u_TP,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%u_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%u_TP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%u_TP) - DEALLOCATE(mask1) - i1_l = LBOUND(OutData%udot_TP,1) - i1_u = UBOUND(OutData%udot_TP,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%udot_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%udot_TP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%udot_TP) - DEALLOCATE(mask1) - i1_l = LBOUND(OutData%udotdot_TP,1) - i1_u = UBOUND(OutData%udotdot_TP,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%udotdot_TP = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%udotdot_TP))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%udotdot_TP) - DEALLOCATE(mask1) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UFL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UFL)) DEALLOCATE(OutData%UFL) - ALLOCATE(OutData%UFL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UFL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UFL)>0) OutData%UFL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UFL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UFL) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UR_bar)) DEALLOCATE(OutData%UR_bar) - ALLOCATE(OutData%UR_bar(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UR_bar)>0) OutData%UR_bar = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UR_bar_dot)) DEALLOCATE(OutData%UR_bar_dot) - ALLOCATE(OutData%UR_bar_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UR_bar_dot)>0) OutData%UR_bar_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar_dot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UR_bar_dotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UR_bar_dotdot)) DEALLOCATE(OutData%UR_bar_dotdot) - ALLOCATE(OutData%UR_bar_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UR_bar_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UR_bar_dotdot)>0) OutData%UR_bar_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UR_bar_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UR_bar_dotdot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UL)) DEALLOCATE(OutData%UL) - ALLOCATE(OutData%UL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UL)>0) OutData%UL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UL) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UL_dot)) DEALLOCATE(OutData%UL_dot) - ALLOCATE(OutData%UL_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UL_dot)>0) OutData%UL_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UL_dot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_dotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UL_dotdot)) DEALLOCATE(OutData%UL_dotdot) - ALLOCATE(OutData%UL_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UL_dotdot)>0) OutData%UL_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UL_dotdot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_full)) DEALLOCATE(OutData%U_full) - ALLOCATE(OutData%U_full(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full)>0) OutData%U_full = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_full_dot)) DEALLOCATE(OutData%U_full_dot) - ALLOCATE(OutData%U_full_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full_dot)>0) OutData%U_full_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_full_dotdot)) DEALLOCATE(OutData%U_full_dotdot) - ALLOCATE(OutData%U_full_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full_dotdot)>0) OutData%U_full_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dotdot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_red)) DEALLOCATE(OutData%U_red) - ALLOCATE(OutData%U_red(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red)>0) OutData%U_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_red_dot)) DEALLOCATE(OutData%U_red_dot) - ALLOCATE(OutData%U_red_dot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red_dot)>0) OutData%U_red_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dotdot not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_red_dotdot)) DEALLOCATE(OutData%U_red_dotdot) - ALLOCATE(OutData%U_red_dotdot(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red_dotdot)>0) OutData%U_red_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dotdot) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SDWrOutput)) DEALLOCATE(OutData%SDWrOutput) - ALLOCATE(OutData%SDWrOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SDWrOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%SDWrOutput)>0) OutData%SDWrOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SDWrOutput))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SDWrOutput) - DEALLOCATE(mask1) - END IF - OutData%LastOutTime = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%Decimat = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Fext)) DEALLOCATE(OutData%Fext) - ALLOCATE(OutData%Fext(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Fext)>0) OutData%Fext = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fext) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext_red not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Fext_red)) DEALLOCATE(OutData%Fext_red) - ALLOCATE(OutData%Fext_red(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Fext_red)>0) OutData%Fext_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext_red))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fext_red) - DEALLOCATE(mask1) - END IF - END SUBROUTINE SD_UnPackMisc - - SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_ParameterType), INTENT(IN) :: SrcParamData - TYPE(SD_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - DstParamData%SDDeltaT = SrcParamData%SDDeltaT - DstParamData%IntMethod = SrcParamData%IntMethod - DstParamData%nDOF = SrcParamData%nDOF - DstParamData%nDOF_red = SrcParamData%nDOF_red - DstParamData%Nmembers = SrcParamData%Nmembers -IF (ALLOCATED(SrcParamData%Elems)) THEN - i1_l = LBOUND(SrcParamData%Elems,1) - i1_u = UBOUND(SrcParamData%Elems,1) - i2_l = LBOUND(SrcParamData%Elems,2) - i2_u = UBOUND(SrcParamData%Elems,2) - IF (.NOT. ALLOCATED(DstParamData%Elems)) THEN - ALLOCATE(DstParamData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Elems.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Elems = SrcParamData%Elems -ENDIF -IF (ALLOCATED(SrcParamData%ElemProps)) THEN - i1_l = LBOUND(SrcParamData%ElemProps,1) - i1_u = UBOUND(SrcParamData%ElemProps,1) - IF (.NOT. ALLOCATED(DstParamData%ElemProps)) THEN - ALLOCATE(DstParamData%ElemProps(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%ElemProps,1), UBOUND(SrcParamData%ElemProps,1) - CALL SD_Copyelemproptype( SrcParamData%ElemProps(i1), DstParamData%ElemProps(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%T_red)) THEN - i1_l = LBOUND(SrcParamData%T_red,1) - i1_u = UBOUND(SrcParamData%T_red,1) - i2_l = LBOUND(SrcParamData%T_red,2) - i2_u = UBOUND(SrcParamData%T_red,2) - IF (.NOT. ALLOCATED(DstParamData%T_red)) THEN - ALLOCATE(DstParamData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%T_red = SrcParamData%T_red -ENDIF -IF (ALLOCATED(SrcParamData%NodesDOF)) THEN - i1_l = LBOUND(SrcParamData%NodesDOF,1) - i1_u = UBOUND(SrcParamData%NodesDOF,1) - IF (.NOT. ALLOCATED(DstParamData%NodesDOF)) THEN - ALLOCATE(DstParamData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%NodesDOF,1), UBOUND(SrcParamData%NodesDOF,1) - CALL SD_Copyilist( SrcParamData%NodesDOF(i1), DstParamData%NodesDOF(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%NodesDOFtilde)) THEN - i1_l = LBOUND(SrcParamData%NodesDOFtilde,1) - i1_u = UBOUND(SrcParamData%NodesDOFtilde,1) - IF (.NOT. ALLOCATED(DstParamData%NodesDOFtilde)) THEN - ALLOCATE(DstParamData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%NodesDOFtilde,1), UBOUND(SrcParamData%NodesDOFtilde,1) - CALL SD_Copyilist( SrcParamData%NodesDOFtilde(i1), DstParamData%NodesDOFtilde(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%ElemsDOF)) THEN - i1_l = LBOUND(SrcParamData%ElemsDOF,1) - i1_u = UBOUND(SrcParamData%ElemsDOF,1) - i2_l = LBOUND(SrcParamData%ElemsDOF,2) - i2_u = UBOUND(SrcParamData%ElemsDOF,2) - IF (.NOT. ALLOCATED(DstParamData%ElemsDOF)) THEN - ALLOCATE(DstParamData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%ElemsDOF = SrcParamData%ElemsDOF -ENDIF -IF (ALLOCATED(SrcParamData%DOFtilde2Nodes)) THEN - i1_l = LBOUND(SrcParamData%DOFtilde2Nodes,1) - i1_u = UBOUND(SrcParamData%DOFtilde2Nodes,1) - i2_l = LBOUND(SrcParamData%DOFtilde2Nodes,2) - i2_u = UBOUND(SrcParamData%DOFtilde2Nodes,2) - IF (.NOT. ALLOCATED(DstParamData%DOFtilde2Nodes)) THEN - ALLOCATE(DstParamData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%DOFtilde2Nodes = SrcParamData%DOFtilde2Nodes -ENDIF - DstParamData%nDOFM = SrcParamData%nDOFM - DstParamData%SttcSolve = SrcParamData%SttcSolve - DstParamData%ExtraMoment = SrcParamData%ExtraMoment -IF (ALLOCATED(SrcParamData%NOmegaM2)) THEN - i1_l = LBOUND(SrcParamData%NOmegaM2,1) - i1_u = UBOUND(SrcParamData%NOmegaM2,1) - IF (.NOT. ALLOCATED(DstParamData%NOmegaM2)) THEN - ALLOCATE(DstParamData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%NOmegaM2 = SrcParamData%NOmegaM2 -ENDIF -IF (ALLOCATED(SrcParamData%N2OmegaMJDamp)) THEN - i1_l = LBOUND(SrcParamData%N2OmegaMJDamp,1) - i1_u = UBOUND(SrcParamData%N2OmegaMJDamp,1) - IF (.NOT. ALLOCATED(DstParamData%N2OmegaMJDamp)) THEN - ALLOCATE(DstParamData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%N2OmegaMJDamp = SrcParamData%N2OmegaMJDamp -ENDIF -IF (ALLOCATED(SrcParamData%MMB)) THEN - i1_l = LBOUND(SrcParamData%MMB,1) - i1_u = UBOUND(SrcParamData%MMB,1) - i2_l = LBOUND(SrcParamData%MMB,2) - i2_u = UBOUND(SrcParamData%MMB,2) - IF (.NOT. ALLOCATED(DstParamData%MMB)) THEN - ALLOCATE(DstParamData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MMB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%MMB = SrcParamData%MMB -ENDIF -IF (ALLOCATED(SrcParamData%FX)) THEN - i1_l = LBOUND(SrcParamData%FX,1) - i1_u = UBOUND(SrcParamData%FX,1) - IF (.NOT. ALLOCATED(DstParamData%FX)) THEN - ALLOCATE(DstParamData%FX(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FX = SrcParamData%FX -ENDIF -IF (ALLOCATED(SrcParamData%C1_11)) THEN - i1_l = LBOUND(SrcParamData%C1_11,1) - i1_u = UBOUND(SrcParamData%C1_11,1) - i2_l = LBOUND(SrcParamData%C1_11,2) - i2_u = UBOUND(SrcParamData%C1_11,2) - IF (.NOT. ALLOCATED(DstParamData%C1_11)) THEN - ALLOCATE(DstParamData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_11.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%C1_11 = SrcParamData%C1_11 -ENDIF -IF (ALLOCATED(SrcParamData%C1_12)) THEN - i1_l = LBOUND(SrcParamData%C1_12,1) - i1_u = UBOUND(SrcParamData%C1_12,1) - i2_l = LBOUND(SrcParamData%C1_12,2) - i2_u = UBOUND(SrcParamData%C1_12,2) - IF (.NOT. ALLOCATED(DstParamData%C1_12)) THEN - ALLOCATE(DstParamData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C1_12.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%C1_12 = SrcParamData%C1_12 -ENDIF -IF (ALLOCATED(SrcParamData%D1_13)) THEN - i1_l = LBOUND(SrcParamData%D1_13,1) - i1_u = UBOUND(SrcParamData%D1_13,1) - i2_l = LBOUND(SrcParamData%D1_13,2) - i2_u = UBOUND(SrcParamData%D1_13,2) - IF (.NOT. ALLOCATED(DstParamData%D1_13)) THEN - ALLOCATE(DstParamData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_13.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D1_13 = SrcParamData%D1_13 -ENDIF -IF (ALLOCATED(SrcParamData%D1_14)) THEN - i1_l = LBOUND(SrcParamData%D1_14,1) - i1_u = UBOUND(SrcParamData%D1_14,1) - i2_l = LBOUND(SrcParamData%D1_14,2) - i2_u = UBOUND(SrcParamData%D1_14,2) - IF (.NOT. ALLOCATED(DstParamData%D1_14)) THEN - ALLOCATE(DstParamData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_14.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D1_14 = SrcParamData%D1_14 -ENDIF -IF (ALLOCATED(SrcParamData%FY)) THEN - i1_l = LBOUND(SrcParamData%FY,1) - i1_u = UBOUND(SrcParamData%FY,1) - IF (.NOT. ALLOCATED(DstParamData%FY)) THEN - ALLOCATE(DstParamData%FY(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FY.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FY = SrcParamData%FY -ENDIF -IF (ALLOCATED(SrcParamData%PhiM)) THEN - i1_l = LBOUND(SrcParamData%PhiM,1) - i1_u = UBOUND(SrcParamData%PhiM,1) - i2_l = LBOUND(SrcParamData%PhiM,2) - i2_u = UBOUND(SrcParamData%PhiM,2) - IF (.NOT. ALLOCATED(DstParamData%PhiM)) THEN - ALLOCATE(DstParamData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%PhiM = SrcParamData%PhiM -ENDIF -IF (ALLOCATED(SrcParamData%C2_61)) THEN - i1_l = LBOUND(SrcParamData%C2_61,1) - i1_u = UBOUND(SrcParamData%C2_61,1) - i2_l = LBOUND(SrcParamData%C2_61,2) - i2_u = UBOUND(SrcParamData%C2_61,2) - IF (.NOT. ALLOCATED(DstParamData%C2_61)) THEN - ALLOCATE(DstParamData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%C2_61 = SrcParamData%C2_61 -ENDIF -IF (ALLOCATED(SrcParamData%C2_62)) THEN - i1_l = LBOUND(SrcParamData%C2_62,1) - i1_u = UBOUND(SrcParamData%C2_62,1) - i2_l = LBOUND(SrcParamData%C2_62,2) - i2_u = UBOUND(SrcParamData%C2_62,2) - IF (.NOT. ALLOCATED(DstParamData%C2_62)) THEN - ALLOCATE(DstParamData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%C2_62.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%C2_62 = SrcParamData%C2_62 -ENDIF -IF (ALLOCATED(SrcParamData%PhiRb_TI)) THEN - i1_l = LBOUND(SrcParamData%PhiRb_TI,1) - i1_u = UBOUND(SrcParamData%PhiRb_TI,1) - i2_l = LBOUND(SrcParamData%PhiRb_TI,2) - i2_u = UBOUND(SrcParamData%PhiRb_TI,2) - IF (.NOT. ALLOCATED(DstParamData%PhiRb_TI)) THEN - ALLOCATE(DstParamData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%PhiRb_TI = SrcParamData%PhiRb_TI -ENDIF -IF (ALLOCATED(SrcParamData%D2_63)) THEN - i1_l = LBOUND(SrcParamData%D2_63,1) - i1_u = UBOUND(SrcParamData%D2_63,1) - i2_l = LBOUND(SrcParamData%D2_63,2) - i2_u = UBOUND(SrcParamData%D2_63,2) - IF (.NOT. ALLOCATED(DstParamData%D2_63)) THEN - ALLOCATE(DstParamData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_63.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D2_63 = SrcParamData%D2_63 -ENDIF -IF (ALLOCATED(SrcParamData%D2_64)) THEN - i1_l = LBOUND(SrcParamData%D2_64,1) - i1_u = UBOUND(SrcParamData%D2_64,1) - i2_l = LBOUND(SrcParamData%D2_64,2) - i2_u = UBOUND(SrcParamData%D2_64,2) - IF (.NOT. ALLOCATED(DstParamData%D2_64)) THEN - ALLOCATE(DstParamData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D2_64.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D2_64 = SrcParamData%D2_64 -ENDIF -IF (ALLOCATED(SrcParamData%F2_61)) THEN - i1_l = LBOUND(SrcParamData%F2_61,1) - i1_u = UBOUND(SrcParamData%F2_61,1) - IF (.NOT. ALLOCATED(DstParamData%F2_61)) THEN - ALLOCATE(DstParamData%F2_61(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%F2_61 = SrcParamData%F2_61 -ENDIF -IF (ALLOCATED(SrcParamData%MBB)) THEN - i1_l = LBOUND(SrcParamData%MBB,1) - i1_u = UBOUND(SrcParamData%MBB,1) - i2_l = LBOUND(SrcParamData%MBB,2) - i2_u = UBOUND(SrcParamData%MBB,2) - IF (.NOT. ALLOCATED(DstParamData%MBB)) THEN - ALLOCATE(DstParamData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%MBB = SrcParamData%MBB -ENDIF -IF (ALLOCATED(SrcParamData%KBB)) THEN - i1_l = LBOUND(SrcParamData%KBB,1) - i1_u = UBOUND(SrcParamData%KBB,1) - i2_l = LBOUND(SrcParamData%KBB,2) - i2_u = UBOUND(SrcParamData%KBB,2) - IF (.NOT. ALLOCATED(DstParamData%KBB)) THEN - ALLOCATE(DstParamData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%KBB = SrcParamData%KBB -ENDIF -IF (ALLOCATED(SrcParamData%MBM)) THEN - i1_l = LBOUND(SrcParamData%MBM,1) - i1_u = UBOUND(SrcParamData%MBM,1) - i2_l = LBOUND(SrcParamData%MBM,2) - i2_u = UBOUND(SrcParamData%MBM,2) - IF (.NOT. ALLOCATED(DstParamData%MBM)) THEN - ALLOCATE(DstParamData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%MBM = SrcParamData%MBM -ENDIF -IF (ALLOCATED(SrcParamData%UL_st_g)) THEN - i1_l = LBOUND(SrcParamData%UL_st_g,1) - i1_u = UBOUND(SrcParamData%UL_st_g,1) - IF (.NOT. ALLOCATED(DstParamData%UL_st_g)) THEN - ALLOCATE(DstParamData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%UL_st_g.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%UL_st_g = SrcParamData%UL_st_g -ENDIF -IF (ALLOCATED(SrcParamData%PhiL_T)) THEN - i1_l = LBOUND(SrcParamData%PhiL_T,1) - i1_u = UBOUND(SrcParamData%PhiL_T,1) - i2_l = LBOUND(SrcParamData%PhiL_T,2) - i2_u = UBOUND(SrcParamData%PhiL_T,2) - IF (.NOT. ALLOCATED(DstParamData%PhiL_T)) THEN - ALLOCATE(DstParamData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiL_T.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%PhiL_T = SrcParamData%PhiL_T -ENDIF -IF (ALLOCATED(SrcParamData%PhiLInvOmgL2)) THEN - i1_l = LBOUND(SrcParamData%PhiLInvOmgL2,1) - i1_u = UBOUND(SrcParamData%PhiLInvOmgL2,1) - i2_l = LBOUND(SrcParamData%PhiLInvOmgL2,2) - i2_u = UBOUND(SrcParamData%PhiLInvOmgL2,2) - IF (.NOT. ALLOCATED(DstParamData%PhiLInvOmgL2)) THEN - ALLOCATE(DstParamData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%PhiLInvOmgL2 = SrcParamData%PhiLInvOmgL2 -ENDIF -IF (ALLOCATED(SrcParamData%KLLm1)) THEN - i1_l = LBOUND(SrcParamData%KLLm1,1) - i1_u = UBOUND(SrcParamData%KLLm1,1) - i2_l = LBOUND(SrcParamData%KLLm1,2) - i2_u = UBOUND(SrcParamData%KLLm1,2) - IF (.NOT. ALLOCATED(DstParamData%KLLm1)) THEN - ALLOCATE(DstParamData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KLLm1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%KLLm1 = SrcParamData%KLLm1 -ENDIF -IF (ALLOCATED(SrcParamData%AM2Jac)) THEN - i1_l = LBOUND(SrcParamData%AM2Jac,1) - i1_u = UBOUND(SrcParamData%AM2Jac,1) - i2_l = LBOUND(SrcParamData%AM2Jac,2) - i2_u = UBOUND(SrcParamData%AM2Jac,2) - IF (.NOT. ALLOCATED(DstParamData%AM2Jac)) THEN - ALLOCATE(DstParamData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2Jac.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%AM2Jac = SrcParamData%AM2Jac -ENDIF -IF (ALLOCATED(SrcParamData%AM2JacPiv)) THEN - i1_l = LBOUND(SrcParamData%AM2JacPiv,1) - i1_u = UBOUND(SrcParamData%AM2JacPiv,1) - IF (.NOT. ALLOCATED(DstParamData%AM2JacPiv)) THEN - ALLOCATE(DstParamData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%AM2JacPiv = SrcParamData%AM2JacPiv -ENDIF -IF (ALLOCATED(SrcParamData%TI)) THEN - i1_l = LBOUND(SrcParamData%TI,1) - i1_u = UBOUND(SrcParamData%TI,1) - i2_l = LBOUND(SrcParamData%TI,2) - i2_u = UBOUND(SrcParamData%TI,2) - IF (.NOT. ALLOCATED(DstParamData%TI)) THEN - ALLOCATE(DstParamData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TI.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%TI = SrcParamData%TI -ENDIF -IF (ALLOCATED(SrcParamData%TIreact)) THEN - i1_l = LBOUND(SrcParamData%TIreact,1) - i1_u = UBOUND(SrcParamData%TIreact,1) - i2_l = LBOUND(SrcParamData%TIreact,2) - i2_u = UBOUND(SrcParamData%TIreact,2) - IF (.NOT. ALLOCATED(DstParamData%TIreact)) THEN - ALLOCATE(DstParamData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TIreact.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%TIreact = SrcParamData%TIreact -ENDIF - DstParamData%nNodes = SrcParamData%nNodes - DstParamData%nNodes_I = SrcParamData%nNodes_I - DstParamData%nNodes_L = SrcParamData%nNodes_L - DstParamData%nNodes_C = SrcParamData%nNodes_C -IF (ALLOCATED(SrcParamData%Nodes_I)) THEN - i1_l = LBOUND(SrcParamData%Nodes_I,1) - i1_u = UBOUND(SrcParamData%Nodes_I,1) - i2_l = LBOUND(SrcParamData%Nodes_I,2) - i2_u = UBOUND(SrcParamData%Nodes_I,2) - IF (.NOT. ALLOCATED(DstParamData%Nodes_I)) THEN - ALLOCATE(DstParamData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Nodes_I = SrcParamData%Nodes_I -ENDIF -IF (ALLOCATED(SrcParamData%Nodes_L)) THEN - i1_l = LBOUND(SrcParamData%Nodes_L,1) - i1_u = UBOUND(SrcParamData%Nodes_L,1) - i2_l = LBOUND(SrcParamData%Nodes_L,2) - i2_u = UBOUND(SrcParamData%Nodes_L,2) - IF (.NOT. ALLOCATED(DstParamData%Nodes_L)) THEN - ALLOCATE(DstParamData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Nodes_L = SrcParamData%Nodes_L -ENDIF -IF (ALLOCATED(SrcParamData%Nodes_C)) THEN - i1_l = LBOUND(SrcParamData%Nodes_C,1) - i1_u = UBOUND(SrcParamData%Nodes_C,1) - i2_l = LBOUND(SrcParamData%Nodes_C,2) - i2_u = UBOUND(SrcParamData%Nodes_C,2) - IF (.NOT. ALLOCATED(DstParamData%Nodes_C)) THEN - ALLOCATE(DstParamData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_C.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Nodes_C = SrcParamData%Nodes_C -ENDIF - DstParamData%nDOFI__ = SrcParamData%nDOFI__ - DstParamData%nDOFI_Rb = SrcParamData%nDOFI_Rb - DstParamData%nDOFI_F = SrcParamData%nDOFI_F - DstParamData%nDOFL_L = SrcParamData%nDOFL_L - DstParamData%nDOFC__ = SrcParamData%nDOFC__ - DstParamData%nDOFC_Rb = SrcParamData%nDOFC_Rb - DstParamData%nDOFC_L = SrcParamData%nDOFC_L - DstParamData%nDOFC_F = SrcParamData%nDOFC_F - DstParamData%nDOFR__ = SrcParamData%nDOFR__ - DstParamData%nDOF__Rb = SrcParamData%nDOF__Rb - DstParamData%nDOF__L = SrcParamData%nDOF__L - DstParamData%nDOF__F = SrcParamData%nDOF__F -IF (ALLOCATED(SrcParamData%IDI__)) THEN - i1_l = LBOUND(SrcParamData%IDI__,1) - i1_u = UBOUND(SrcParamData%IDI__,1) - IF (.NOT. ALLOCATED(DstParamData%IDI__)) THEN - ALLOCATE(DstParamData%IDI__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDI__ = SrcParamData%IDI__ -ENDIF -IF (ALLOCATED(SrcParamData%IDI_Rb)) THEN - i1_l = LBOUND(SrcParamData%IDI_Rb,1) - i1_u = UBOUND(SrcParamData%IDI_Rb,1) - IF (.NOT. ALLOCATED(DstParamData%IDI_Rb)) THEN - ALLOCATE(DstParamData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDI_Rb = SrcParamData%IDI_Rb -ENDIF -IF (ALLOCATED(SrcParamData%IDI_F)) THEN - i1_l = LBOUND(SrcParamData%IDI_F,1) - i1_u = UBOUND(SrcParamData%IDI_F,1) - IF (.NOT. ALLOCATED(DstParamData%IDI_F)) THEN - ALLOCATE(DstParamData%IDI_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDI_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDI_F = SrcParamData%IDI_F -ENDIF -IF (ALLOCATED(SrcParamData%IDL_L)) THEN - i1_l = LBOUND(SrcParamData%IDL_L,1) - i1_u = UBOUND(SrcParamData%IDL_L,1) - IF (.NOT. ALLOCATED(DstParamData%IDL_L)) THEN - ALLOCATE(DstParamData%IDL_L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDL_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDL_L = SrcParamData%IDL_L -ENDIF -IF (ALLOCATED(SrcParamData%IDC__)) THEN - i1_l = LBOUND(SrcParamData%IDC__,1) - i1_u = UBOUND(SrcParamData%IDC__,1) - IF (.NOT. ALLOCATED(DstParamData%IDC__)) THEN - ALLOCATE(DstParamData%IDC__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDC__ = SrcParamData%IDC__ -ENDIF -IF (ALLOCATED(SrcParamData%IDC_Rb)) THEN - i1_l = LBOUND(SrcParamData%IDC_Rb,1) - i1_u = UBOUND(SrcParamData%IDC_Rb,1) - IF (.NOT. ALLOCATED(DstParamData%IDC_Rb)) THEN - ALLOCATE(DstParamData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDC_Rb = SrcParamData%IDC_Rb -ENDIF -IF (ALLOCATED(SrcParamData%IDC_L)) THEN - i1_l = LBOUND(SrcParamData%IDC_L,1) - i1_u = UBOUND(SrcParamData%IDC_L,1) - IF (.NOT. ALLOCATED(DstParamData%IDC_L)) THEN - ALLOCATE(DstParamData%IDC_L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDC_L = SrcParamData%IDC_L -ENDIF -IF (ALLOCATED(SrcParamData%IDC_F)) THEN - i1_l = LBOUND(SrcParamData%IDC_F,1) - i1_u = UBOUND(SrcParamData%IDC_F,1) - IF (.NOT. ALLOCATED(DstParamData%IDC_F)) THEN - ALLOCATE(DstParamData%IDC_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDC_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDC_F = SrcParamData%IDC_F -ENDIF -IF (ALLOCATED(SrcParamData%IDR__)) THEN - i1_l = LBOUND(SrcParamData%IDR__,1) - i1_u = UBOUND(SrcParamData%IDR__,1) - IF (.NOT. ALLOCATED(DstParamData%IDR__)) THEN - ALLOCATE(DstParamData%IDR__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%IDR__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%IDR__ = SrcParamData%IDR__ -ENDIF -IF (ALLOCATED(SrcParamData%ID__Rb)) THEN - i1_l = LBOUND(SrcParamData%ID__Rb,1) - i1_u = UBOUND(SrcParamData%ID__Rb,1) - IF (.NOT. ALLOCATED(DstParamData%ID__Rb)) THEN - ALLOCATE(DstParamData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%ID__Rb = SrcParamData%ID__Rb -ENDIF -IF (ALLOCATED(SrcParamData%ID__L)) THEN - i1_l = LBOUND(SrcParamData%ID__L,1) - i1_u = UBOUND(SrcParamData%ID__L,1) - IF (.NOT. ALLOCATED(DstParamData%ID__L)) THEN - ALLOCATE(DstParamData%ID__L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%ID__L = SrcParamData%ID__L -ENDIF -IF (ALLOCATED(SrcParamData%ID__F)) THEN - i1_l = LBOUND(SrcParamData%ID__F,1) - i1_u = UBOUND(SrcParamData%ID__F,1) - IF (.NOT. ALLOCATED(DstParamData%ID__F)) THEN - ALLOCATE(DstParamData%ID__F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ID__F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%ID__F = SrcParamData%ID__F -ENDIF -IF (ALLOCATED(SrcParamData%FGL)) THEN - i1_l = LBOUND(SrcParamData%FGL,1) - i1_u = UBOUND(SrcParamData%FGL,1) - IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN - ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FGL = SrcParamData%FGL -ENDIF - DstParamData%NMOutputs = SrcParamData%NMOutputs - DstParamData%NumOuts = SrcParamData%NumOuts - DstParamData%OutSwtch = SrcParamData%OutSwtch - DstParamData%UnJckF = SrcParamData%UnJckF - DstParamData%Delim = SrcParamData%Delim - DstParamData%OutFmt = SrcParamData%OutFmt - DstParamData%OutSFmt = SrcParamData%OutSFmt -IF (ALLOCATED(SrcParamData%MoutLst)) THEN - i1_l = LBOUND(SrcParamData%MoutLst,1) - i1_u = UBOUND(SrcParamData%MoutLst,1) - IF (.NOT. ALLOCATED(DstParamData%MoutLst)) THEN - ALLOCATE(DstParamData%MoutLst(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%MoutLst,1), UBOUND(SrcParamData%MoutLst,1) - CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst(i1), DstParamData%MoutLst(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%MoutLst2)) THEN - i1_l = LBOUND(SrcParamData%MoutLst2,1) - i1_u = UBOUND(SrcParamData%MoutLst2,1) - IF (.NOT. ALLOCATED(DstParamData%MoutLst2)) THEN - ALLOCATE(DstParamData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%MoutLst2,1), UBOUND(SrcParamData%MoutLst2,1) - CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst2(i1), DstParamData%MoutLst2(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%MoutLst3)) THEN - i1_l = LBOUND(SrcParamData%MoutLst3,1) - i1_u = UBOUND(SrcParamData%MoutLst3,1) - IF (.NOT. ALLOCATED(DstParamData%MoutLst3)) THEN - ALLOCATE(DstParamData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MoutLst3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%MoutLst3,1), UBOUND(SrcParamData%MoutLst3,1) - CALL SD_Copymeshauxdatatype( SrcParamData%MoutLst3(i1), DstParamData%MoutLst3(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF -IF (ALLOCATED(SrcParamData%OutParam)) THEN - i1_l = LBOUND(SrcParamData%OutParam,1) - i1_u = UBOUND(SrcParamData%OutParam,1) - IF (.NOT. ALLOCATED(DstParamData%OutParam)) THEN - ALLOCATE(DstParamData%OutParam(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DO i1 = LBOUND(SrcParamData%OutParam,1), UBOUND(SrcParamData%OutParam,1) - CALL NWTC_Library_Copyoutparmtype( SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - ENDDO -ENDIF - DstParamData%OutAll = SrcParamData%OutAll - DstParamData%OutReact = SrcParamData%OutReact - DstParamData%OutAllInt = SrcParamData%OutAllInt - DstParamData%OutAllDims = SrcParamData%OutAllDims - DstParamData%OutDec = SrcParamData%OutDec - END SUBROUTINE SD_CopyParam - - SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) - TYPE(SD_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyParam' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(ParamData%Elems)) THEN - DEALLOCATE(ParamData%Elems) -ENDIF -IF (ALLOCATED(ParamData%ElemProps)) THEN -DO i1 = LBOUND(ParamData%ElemProps,1), UBOUND(ParamData%ElemProps,1) - CALL SD_Destroyelemproptype( ParamData%ElemProps(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%ElemProps) -ENDIF -IF (ALLOCATED(ParamData%T_red)) THEN - DEALLOCATE(ParamData%T_red) -ENDIF -IF (ALLOCATED(ParamData%NodesDOF)) THEN -DO i1 = LBOUND(ParamData%NodesDOF,1), UBOUND(ParamData%NodesDOF,1) - CALL SD_Destroyilist( ParamData%NodesDOF(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%NodesDOF) -ENDIF -IF (ALLOCATED(ParamData%NodesDOFtilde)) THEN -DO i1 = LBOUND(ParamData%NodesDOFtilde,1), UBOUND(ParamData%NodesDOFtilde,1) - CALL SD_Destroyilist( ParamData%NodesDOFtilde(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%NodesDOFtilde) -ENDIF -IF (ALLOCATED(ParamData%ElemsDOF)) THEN - DEALLOCATE(ParamData%ElemsDOF) -ENDIF -IF (ALLOCATED(ParamData%DOFtilde2Nodes)) THEN - DEALLOCATE(ParamData%DOFtilde2Nodes) -ENDIF -IF (ALLOCATED(ParamData%NOmegaM2)) THEN - DEALLOCATE(ParamData%NOmegaM2) -ENDIF -IF (ALLOCATED(ParamData%N2OmegaMJDamp)) THEN - DEALLOCATE(ParamData%N2OmegaMJDamp) -ENDIF -IF (ALLOCATED(ParamData%MMB)) THEN - DEALLOCATE(ParamData%MMB) -ENDIF -IF (ALLOCATED(ParamData%FX)) THEN - DEALLOCATE(ParamData%FX) -ENDIF -IF (ALLOCATED(ParamData%C1_11)) THEN - DEALLOCATE(ParamData%C1_11) -ENDIF -IF (ALLOCATED(ParamData%C1_12)) THEN - DEALLOCATE(ParamData%C1_12) -ENDIF -IF (ALLOCATED(ParamData%D1_13)) THEN - DEALLOCATE(ParamData%D1_13) -ENDIF -IF (ALLOCATED(ParamData%D1_14)) THEN - DEALLOCATE(ParamData%D1_14) -ENDIF -IF (ALLOCATED(ParamData%FY)) THEN - DEALLOCATE(ParamData%FY) -ENDIF -IF (ALLOCATED(ParamData%PhiM)) THEN - DEALLOCATE(ParamData%PhiM) -ENDIF -IF (ALLOCATED(ParamData%C2_61)) THEN - DEALLOCATE(ParamData%C2_61) -ENDIF -IF (ALLOCATED(ParamData%C2_62)) THEN - DEALLOCATE(ParamData%C2_62) -ENDIF -IF (ALLOCATED(ParamData%PhiRb_TI)) THEN - DEALLOCATE(ParamData%PhiRb_TI) -ENDIF -IF (ALLOCATED(ParamData%D2_63)) THEN - DEALLOCATE(ParamData%D2_63) -ENDIF -IF (ALLOCATED(ParamData%D2_64)) THEN - DEALLOCATE(ParamData%D2_64) -ENDIF -IF (ALLOCATED(ParamData%F2_61)) THEN - DEALLOCATE(ParamData%F2_61) -ENDIF -IF (ALLOCATED(ParamData%MBB)) THEN - DEALLOCATE(ParamData%MBB) -ENDIF -IF (ALLOCATED(ParamData%KBB)) THEN - DEALLOCATE(ParamData%KBB) -ENDIF -IF (ALLOCATED(ParamData%MBM)) THEN - DEALLOCATE(ParamData%MBM) -ENDIF -IF (ALLOCATED(ParamData%UL_st_g)) THEN - DEALLOCATE(ParamData%UL_st_g) -ENDIF -IF (ALLOCATED(ParamData%PhiL_T)) THEN - DEALLOCATE(ParamData%PhiL_T) -ENDIF -IF (ALLOCATED(ParamData%PhiLInvOmgL2)) THEN - DEALLOCATE(ParamData%PhiLInvOmgL2) -ENDIF -IF (ALLOCATED(ParamData%KLLm1)) THEN - DEALLOCATE(ParamData%KLLm1) -ENDIF -IF (ALLOCATED(ParamData%AM2Jac)) THEN - DEALLOCATE(ParamData%AM2Jac) -ENDIF -IF (ALLOCATED(ParamData%AM2JacPiv)) THEN - DEALLOCATE(ParamData%AM2JacPiv) -ENDIF -IF (ALLOCATED(ParamData%TI)) THEN - DEALLOCATE(ParamData%TI) -ENDIF -IF (ALLOCATED(ParamData%TIreact)) THEN - DEALLOCATE(ParamData%TIreact) -ENDIF -IF (ALLOCATED(ParamData%Nodes_I)) THEN - DEALLOCATE(ParamData%Nodes_I) -ENDIF -IF (ALLOCATED(ParamData%Nodes_L)) THEN - DEALLOCATE(ParamData%Nodes_L) -ENDIF -IF (ALLOCATED(ParamData%Nodes_C)) THEN - DEALLOCATE(ParamData%Nodes_C) -ENDIF -IF (ALLOCATED(ParamData%IDI__)) THEN - DEALLOCATE(ParamData%IDI__) -ENDIF -IF (ALLOCATED(ParamData%IDI_Rb)) THEN - DEALLOCATE(ParamData%IDI_Rb) -ENDIF -IF (ALLOCATED(ParamData%IDI_F)) THEN - DEALLOCATE(ParamData%IDI_F) -ENDIF -IF (ALLOCATED(ParamData%IDL_L)) THEN - DEALLOCATE(ParamData%IDL_L) -ENDIF -IF (ALLOCATED(ParamData%IDC__)) THEN - DEALLOCATE(ParamData%IDC__) -ENDIF -IF (ALLOCATED(ParamData%IDC_Rb)) THEN - DEALLOCATE(ParamData%IDC_Rb) -ENDIF -IF (ALLOCATED(ParamData%IDC_L)) THEN - DEALLOCATE(ParamData%IDC_L) -ENDIF -IF (ALLOCATED(ParamData%IDC_F)) THEN - DEALLOCATE(ParamData%IDC_F) -ENDIF -IF (ALLOCATED(ParamData%IDR__)) THEN - DEALLOCATE(ParamData%IDR__) -ENDIF -IF (ALLOCATED(ParamData%ID__Rb)) THEN - DEALLOCATE(ParamData%ID__Rb) -ENDIF -IF (ALLOCATED(ParamData%ID__L)) THEN - DEALLOCATE(ParamData%ID__L) -ENDIF -IF (ALLOCATED(ParamData%ID__F)) THEN - DEALLOCATE(ParamData%ID__F) -ENDIF -IF (ALLOCATED(ParamData%FGL)) THEN - DEALLOCATE(ParamData%FGL) -ENDIF -IF (ALLOCATED(ParamData%MoutLst)) THEN -DO i1 = LBOUND(ParamData%MoutLst,1), UBOUND(ParamData%MoutLst,1) - CALL SD_Destroymeshauxdatatype( ParamData%MoutLst(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%MoutLst) -ENDIF -IF (ALLOCATED(ParamData%MoutLst2)) THEN -DO i1 = LBOUND(ParamData%MoutLst2,1), UBOUND(ParamData%MoutLst2,1) - CALL SD_Destroymeshauxdatatype( ParamData%MoutLst2(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%MoutLst2) -ENDIF -IF (ALLOCATED(ParamData%MoutLst3)) THEN -DO i1 = LBOUND(ParamData%MoutLst3,1), UBOUND(ParamData%MoutLst3,1) - CALL SD_Destroymeshauxdatatype( ParamData%MoutLst3(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%MoutLst3) -ENDIF -IF (ALLOCATED(ParamData%OutParam)) THEN -DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) - CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat, ErrMsg ) -ENDDO - DEALLOCATE(ParamData%OutParam) -ENDIF - END SUBROUTINE SD_DestroyParam - - SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Db_BufSz = Db_BufSz + 1 ! SDDeltaT - Int_BufSz = Int_BufSz + 1 ! IntMethod - Int_BufSz = Int_BufSz + 1 ! nDOF - Int_BufSz = Int_BufSz + 1 ! nDOF_red - Int_BufSz = Int_BufSz + 1 ! Nmembers - Int_BufSz = Int_BufSz + 1 ! Elems allocated yes/no - IF ( ALLOCATED(InData%Elems) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Elems upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Elems) ! Elems - END IF - Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no - IF ( ALLOCATED(InData%ElemProps) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! ElemProps upper/lower bounds for each dimension - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) - Int_BufSz = Int_BufSz + 3 ! ElemProps: size of buffers for each call to pack subtype - CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, .TRUE. ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! ElemProps - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! ElemProps - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! ElemProps - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no - IF ( ALLOCATED(InData%T_red) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%T_red) ! T_red - END IF - Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no - IF ( ALLOCATED(InData%NodesDOF) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension - DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) - Int_BufSz = Int_BufSz + 3 ! NodesDOF: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! NodesDOF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! NodesDOF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! NodesDOF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! NodesDOFtilde allocated yes/no - IF ( ALLOCATED(InData%NodesDOFtilde) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodesDOFtilde upper/lower bounds for each dimension - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - Int_BufSz = Int_BufSz + 3 ! NodesDOFtilde: size of buffers for each call to pack subtype - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, .TRUE. ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! NodesDOFtilde - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! NodesDOFtilde - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! NodesDOFtilde - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! ElemsDOF allocated yes/no - IF ( ALLOCATED(InData%ElemsDOF) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElemsDOF upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElemsDOF) ! ElemsDOF - END IF - Int_BufSz = Int_BufSz + 1 ! DOFtilde2Nodes allocated yes/no - IF ( ALLOCATED(InData%DOFtilde2Nodes) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! DOFtilde2Nodes upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%DOFtilde2Nodes) ! DOFtilde2Nodes - END IF - Int_BufSz = Int_BufSz + 1 ! nDOFM - Int_BufSz = Int_BufSz + 1 ! SttcSolve - Int_BufSz = Int_BufSz + 1 ! ExtraMoment - Int_BufSz = Int_BufSz + 1 ! NOmegaM2 allocated yes/no - IF ( ALLOCATED(InData%NOmegaM2) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NOmegaM2 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%NOmegaM2) ! NOmegaM2 - END IF - Int_BufSz = Int_BufSz + 1 ! N2OmegaMJDamp allocated yes/no - IF ( ALLOCATED(InData%N2OmegaMJDamp) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! N2OmegaMJDamp upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%N2OmegaMJDamp) ! N2OmegaMJDamp - END IF - Int_BufSz = Int_BufSz + 1 ! MMB allocated yes/no - IF ( ALLOCATED(InData%MMB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MMB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MMB) ! MMB - END IF - Int_BufSz = Int_BufSz + 1 ! FX allocated yes/no - IF ( ALLOCATED(InData%FX) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FX upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FX) ! FX - END IF - Int_BufSz = Int_BufSz + 1 ! C1_11 allocated yes/no - IF ( ALLOCATED(InData%C1_11) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! C1_11 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%C1_11) ! C1_11 - END IF - Int_BufSz = Int_BufSz + 1 ! C1_12 allocated yes/no - IF ( ALLOCATED(InData%C1_12) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! C1_12 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%C1_12) ! C1_12 - END IF - Int_BufSz = Int_BufSz + 1 ! D1_13 allocated yes/no - IF ( ALLOCATED(InData%D1_13) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 - END IF - Int_BufSz = Int_BufSz + 1 ! D1_14 allocated yes/no - IF ( ALLOCATED(InData%D1_14) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 - END IF - Int_BufSz = Int_BufSz + 1 ! FY allocated yes/no - IF ( ALLOCATED(InData%FY) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FY upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FY) ! FY - END IF - Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no - IF ( ALLOCATED(InData%PhiM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiM) ! PhiM - END IF - Int_BufSz = Int_BufSz + 1 ! C2_61 allocated yes/no - IF ( ALLOCATED(InData%C2_61) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! C2_61 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%C2_61) ! C2_61 - END IF - Int_BufSz = Int_BufSz + 1 ! C2_62 allocated yes/no - IF ( ALLOCATED(InData%C2_62) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! C2_62 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%C2_62) ! C2_62 - END IF - Int_BufSz = Int_BufSz + 1 ! PhiRb_TI allocated yes/no - IF ( ALLOCATED(InData%PhiRb_TI) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiRb_TI upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiRb_TI) ! PhiRb_TI - END IF - Int_BufSz = Int_BufSz + 1 ! D2_63 allocated yes/no - IF ( ALLOCATED(InData%D2_63) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D2_63 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D2_63) ! D2_63 - END IF - Int_BufSz = Int_BufSz + 1 ! D2_64 allocated yes/no - IF ( ALLOCATED(InData%D2_64) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D2_64 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D2_64) ! D2_64 - END IF - Int_BufSz = Int_BufSz + 1 ! F2_61 allocated yes/no - IF ( ALLOCATED(InData%F2_61) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! F2_61 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F2_61) ! F2_61 - END IF - Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no - IF ( ALLOCATED(InData%MBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB - END IF - Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no - IF ( ALLOCATED(InData%KBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB - END IF - Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no - IF ( ALLOCATED(InData%MBM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM - END IF - Int_BufSz = Int_BufSz + 1 ! UL_st_g allocated yes/no - IF ( ALLOCATED(InData%UL_st_g) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UL_st_g upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UL_st_g) ! UL_st_g - END IF - Int_BufSz = Int_BufSz + 1 ! PhiL_T allocated yes/no - IF ( ALLOCATED(InData%PhiL_T) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiL_T upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiL_T) ! PhiL_T - END IF - Int_BufSz = Int_BufSz + 1 ! PhiLInvOmgL2 allocated yes/no - IF ( ALLOCATED(InData%PhiLInvOmgL2) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiLInvOmgL2 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiLInvOmgL2) ! PhiLInvOmgL2 - END IF - Int_BufSz = Int_BufSz + 1 ! KLLm1 allocated yes/no - IF ( ALLOCATED(InData%KLLm1) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! KLLm1 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%KLLm1) ! KLLm1 - END IF - Int_BufSz = Int_BufSz + 1 ! AM2Jac allocated yes/no - IF ( ALLOCATED(InData%AM2Jac) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! AM2Jac upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%AM2Jac) ! AM2Jac - END IF - Int_BufSz = Int_BufSz + 1 ! AM2JacPiv allocated yes/no - IF ( ALLOCATED(InData%AM2JacPiv) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! AM2JacPiv upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%AM2JacPiv) ! AM2JacPiv - END IF - Int_BufSz = Int_BufSz + 1 ! TI allocated yes/no - IF ( ALLOCATED(InData%TI) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! TI upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI - END IF - Int_BufSz = Int_BufSz + 1 ! TIreact allocated yes/no - IF ( ALLOCATED(InData%TIreact) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! TIreact upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%TIreact) ! TIreact - END IF - Int_BufSz = Int_BufSz + 1 ! nNodes - Int_BufSz = Int_BufSz + 1 ! nNodes_I - Int_BufSz = Int_BufSz + 1 ! nNodes_L - Int_BufSz = Int_BufSz + 1 ! nNodes_C - Int_BufSz = Int_BufSz + 1 ! Nodes_I allocated yes/no - IF ( ALLOCATED(InData%Nodes_I) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Nodes_I upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Nodes_I) ! Nodes_I - END IF - Int_BufSz = Int_BufSz + 1 ! Nodes_L allocated yes/no - IF ( ALLOCATED(InData%Nodes_L) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Nodes_L upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Nodes_L) ! Nodes_L - END IF - Int_BufSz = Int_BufSz + 1 ! Nodes_C allocated yes/no - IF ( ALLOCATED(InData%Nodes_C) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Nodes_C upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Nodes_C) ! Nodes_C - END IF - Int_BufSz = Int_BufSz + 1 ! nDOFI__ - Int_BufSz = Int_BufSz + 1 ! nDOFI_Rb - Int_BufSz = Int_BufSz + 1 ! nDOFI_F - Int_BufSz = Int_BufSz + 1 ! nDOFL_L - Int_BufSz = Int_BufSz + 1 ! nDOFC__ - Int_BufSz = Int_BufSz + 1 ! nDOFC_Rb - Int_BufSz = Int_BufSz + 1 ! nDOFC_L - Int_BufSz = Int_BufSz + 1 ! nDOFC_F - Int_BufSz = Int_BufSz + 1 ! nDOFR__ - Int_BufSz = Int_BufSz + 1 ! nDOF__Rb - Int_BufSz = Int_BufSz + 1 ! nDOF__L - Int_BufSz = Int_BufSz + 1 ! nDOF__F - Int_BufSz = Int_BufSz + 1 ! IDI__ allocated yes/no - IF ( ALLOCATED(InData%IDI__) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDI__ upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDI__) ! IDI__ - END IF - Int_BufSz = Int_BufSz + 1 ! IDI_Rb allocated yes/no - IF ( ALLOCATED(InData%IDI_Rb) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDI_Rb upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDI_Rb) ! IDI_Rb - END IF - Int_BufSz = Int_BufSz + 1 ! IDI_F allocated yes/no - IF ( ALLOCATED(InData%IDI_F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDI_F upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDI_F) ! IDI_F - END IF - Int_BufSz = Int_BufSz + 1 ! IDL_L allocated yes/no - IF ( ALLOCATED(InData%IDL_L) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDL_L upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDL_L) ! IDL_L - END IF - Int_BufSz = Int_BufSz + 1 ! IDC__ allocated yes/no - IF ( ALLOCATED(InData%IDC__) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDC__ upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDC__) ! IDC__ - END IF - Int_BufSz = Int_BufSz + 1 ! IDC_Rb allocated yes/no - IF ( ALLOCATED(InData%IDC_Rb) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDC_Rb upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDC_Rb) ! IDC_Rb - END IF - Int_BufSz = Int_BufSz + 1 ! IDC_L allocated yes/no - IF ( ALLOCATED(InData%IDC_L) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDC_L upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDC_L) ! IDC_L - END IF - Int_BufSz = Int_BufSz + 1 ! IDC_F allocated yes/no - IF ( ALLOCATED(InData%IDC_F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDC_F upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDC_F) ! IDC_F - END IF - Int_BufSz = Int_BufSz + 1 ! IDR__ allocated yes/no - IF ( ALLOCATED(InData%IDR__) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IDR__ upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IDR__) ! IDR__ - END IF - Int_BufSz = Int_BufSz + 1 ! ID__Rb allocated yes/no - IF ( ALLOCATED(InData%ID__Rb) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! ID__Rb upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ID__Rb) ! ID__Rb - END IF - Int_BufSz = Int_BufSz + 1 ! ID__L allocated yes/no - IF ( ALLOCATED(InData%ID__L) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! ID__L upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ID__L) ! ID__L - END IF - Int_BufSz = Int_BufSz + 1 ! ID__F allocated yes/no - IF ( ALLOCATED(InData%ID__F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! ID__F upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ID__F) ! ID__F - END IF - Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no - IF ( ALLOCATED(InData%FGL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL - END IF - Int_BufSz = Int_BufSz + 1 ! NMOutputs - Int_BufSz = Int_BufSz + 1 ! NumOuts - Int_BufSz = Int_BufSz + 1 ! OutSwtch - Int_BufSz = Int_BufSz + 1 ! UnJckF - Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim - Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt - Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt - Int_BufSz = Int_BufSz + 1 ! MoutLst allocated yes/no - IF ( ALLOCATED(InData%MoutLst) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! MoutLst upper/lower bounds for each dimension - DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) - Int_BufSz = Int_BufSz + 3 ! MoutLst: size of buffers for each call to pack subtype - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! MoutLst - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! MoutLst - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! MoutLst - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! MoutLst2 allocated yes/no - IF ( ALLOCATED(InData%MoutLst2) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! MoutLst2 upper/lower bounds for each dimension - DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) - Int_BufSz = Int_BufSz + 3 ! MoutLst2: size of buffers for each call to pack subtype - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst2 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! MoutLst2 - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! MoutLst2 - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! MoutLst2 - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! MoutLst3 allocated yes/no - IF ( ALLOCATED(InData%MoutLst3) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! MoutLst3 upper/lower bounds for each dimension - DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) - Int_BufSz = Int_BufSz + 3 ! MoutLst3: size of buffers for each call to pack subtype - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, .TRUE. ) ! MoutLst3 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! MoutLst3 - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! MoutLst3 - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! MoutLst3 - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no - IF ( ALLOCATED(InData%OutParam) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension - DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) - Int_BufSz = Int_BufSz + 3 ! OutParam: size of buffers for each call to pack subtype - CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutParam - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! OutParam - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! OutParam - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! OutParam - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - END DO - END IF - Int_BufSz = Int_BufSz + 1 ! OutAll - Int_BufSz = Int_BufSz + 1 ! OutReact - Int_BufSz = Int_BufSz + 1 ! OutAllInt - Int_BufSz = Int_BufSz + 1 ! OutAllDims - Int_BufSz = Int_BufSz + 1 ! OutDec - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%SDDeltaT - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%IntMethod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF_red - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Nmembers - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Elems) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Elems,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Elems)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Elems))-1 ) = PACK(InData%Elems,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Elems) - END IF - IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemProps,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemProps,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%ElemProps,1), UBOUND(InData%ElemProps,1) - CALL SD_Packelemproptype( Re_Buf, Db_Buf, Int_Buf, InData%ElemProps(i1), ErrStat2, ErrMsg2, OnlySize ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%T_red) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%T_red) - END IF - IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOF,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%NodesDOF,1), UBOUND(InData%NodesDOF,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOF(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%NodesDOFtilde) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodesDOFtilde,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodesDOFtilde,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%NodesDOFtilde,1), UBOUND(InData%NodesDOFtilde,1) - CALL SD_Packilist( Re_Buf, Db_Buf, Int_Buf, InData%NodesDOFtilde(i1), ErrStat2, ErrMsg2, OnlySize ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%ElemsDOF) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElemsDOF,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) - END IF - IF ( .NOT. ALLOCATED(InData%DOFtilde2Nodes) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DOFtilde2Nodes,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFtilde2Nodes,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DOFtilde2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFtilde2Nodes))-1 ) = PACK(InData%DOFtilde2Nodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DOFtilde2Nodes) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%SttcSolve - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%ExtraMoment , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%NOmegaM2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NOmegaM2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NOmegaM2,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%NOmegaM2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%NOmegaM2))-1 ) = PACK(InData%NOmegaM2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%NOmegaM2) - END IF - IF ( .NOT. ALLOCATED(InData%N2OmegaMJDamp) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%N2OmegaMJDamp,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%N2OmegaMJDamp,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%N2OmegaMJDamp)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%N2OmegaMJDamp))-1 ) = PACK(InData%N2OmegaMJDamp,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%N2OmegaMJDamp) - END IF - IF ( .NOT. ALLOCATED(InData%MMB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MMB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MMB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MMB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MMB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MMB))-1 ) = PACK(InData%MMB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MMB) - END IF - IF ( .NOT. ALLOCATED(InData%FX) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FX,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FX,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%FX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FX))-1 ) = PACK(InData%FX,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FX) - END IF - IF ( .NOT. ALLOCATED(InData%C1_11) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_11,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_11,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_11,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%C1_11)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C1_11))-1 ) = PACK(InData%C1_11,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%C1_11) - END IF - IF ( .NOT. ALLOCATED(InData%C1_12) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_12,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C1_12,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C1_12,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%C1_12)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C1_12))-1 ) = PACK(InData%C1_12,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%C1_12) - END IF - IF ( .NOT. ALLOCATED(InData%D1_13) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D1_13)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_13))-1 ) = PACK(InData%D1_13,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D1_13) - END IF - IF ( .NOT. ALLOCATED(InData%D1_14) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D1_14)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_14))-1 ) = PACK(InData%D1_14,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D1_14) - END IF - IF ( .NOT. ALLOCATED(InData%FY) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FY,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FY,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%FY)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FY))-1 ) = PACK(InData%FY,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FY) - END IF - IF ( .NOT. ALLOCATED(InData%PhiM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiM))-1 ) = PACK(InData%PhiM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiM) - END IF - IF ( .NOT. ALLOCATED(InData%C2_61) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_61,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_61,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_61,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%C2_61)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C2_61))-1 ) = PACK(InData%C2_61,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%C2_61) - END IF - IF ( .NOT. ALLOCATED(InData%C2_62) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_62,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%C2_62,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%C2_62,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%C2_62)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%C2_62))-1 ) = PACK(InData%C2_62,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%C2_62) - END IF - IF ( .NOT. ALLOCATED(InData%PhiRb_TI) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiRb_TI,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiRb_TI,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiRb_TI,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiRb_TI)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiRb_TI))-1 ) = PACK(InData%PhiRb_TI,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiRb_TI) - END IF - IF ( .NOT. ALLOCATED(InData%D2_63) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_63,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_63,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_63,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D2_63)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D2_63))-1 ) = PACK(InData%D2_63,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D2_63) - END IF - IF ( .NOT. ALLOCATED(InData%D2_64) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_64,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D2_64,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D2_64,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%D2_64)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D2_64))-1 ) = PACK(InData%D2_64,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D2_64) - END IF - IF ( .NOT. ALLOCATED(InData%F2_61) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F2_61,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F2_61,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F2_61)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F2_61))-1 ) = PACK(InData%F2_61,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F2_61) - END IF - IF ( .NOT. ALLOCATED(InData%MBB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBB) - END IF - IF ( .NOT. ALLOCATED(InData%KBB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KBB) - END IF - IF ( .NOT. ALLOCATED(InData%MBM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBM) - END IF - IF ( .NOT. ALLOCATED(InData%UL_st_g) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_st_g,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_st_g,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%UL_st_g)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_st_g))-1 ) = PACK(InData%UL_st_g,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UL_st_g) - END IF - IF ( .NOT. ALLOCATED(InData%PhiL_T) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL_T,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL_T,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL_T,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiL_T)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiL_T))-1 ) = PACK(InData%PhiL_T,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiL_T) - END IF - IF ( .NOT. ALLOCATED(InData%PhiLInvOmgL2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiLInvOmgL2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiLInvOmgL2,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiLInvOmgL2,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%PhiLInvOmgL2)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiLInvOmgL2))-1 ) = PACK(InData%PhiLInvOmgL2,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiLInvOmgL2) - END IF - IF ( .NOT. ALLOCATED(InData%KLLm1) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KLLm1,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%KLLm1)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KLLm1))-1 ) = PACK(InData%KLLm1,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KLLm1) - END IF - IF ( .NOT. ALLOCATED(InData%AM2Jac) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2Jac,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2Jac,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2Jac,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%AM2Jac)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%AM2Jac))-1 ) = PACK(InData%AM2Jac,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%AM2Jac) - END IF - IF ( .NOT. ALLOCATED(InData%AM2JacPiv) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%AM2JacPiv,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AM2JacPiv,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%AM2JacPiv)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%AM2JacPiv))-1 ) = PACK(InData%AM2JacPiv,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%AM2JacPiv) - END IF - IF ( .NOT. ALLOCATED(InData%TI) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TI,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TI,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TI,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%TI)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TI))-1 ) = PACK(InData%TI,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TI) - END IF - IF ( .NOT. ALLOCATED(InData%TIreact) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TIreact,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TIreact,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TIreact,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%TIreact)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TIreact))-1 ) = PACK(InData%TIreact,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TIreact) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_C - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%Nodes_I) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Nodes_I)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_I))-1 ) = PACK(InData%Nodes_I,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_I) - END IF - IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_L,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) - END IF - IF ( .NOT. ALLOCATED(InData%Nodes_C) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_C,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,2) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%Nodes_C)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_C))-1 ) = PACK(InData%Nodes_C,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_C) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_F - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_F - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__F - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%IDI__) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI__,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI__,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDI__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI__))-1 ) = PACK(InData%IDI__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI__) - END IF - IF ( .NOT. ALLOCATED(InData%IDI_Rb) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_Rb,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_Rb,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDI_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_Rb))-1 ) = PACK(InData%IDI_Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI_Rb) - END IF - IF ( .NOT. ALLOCATED(InData%IDI_F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDI_F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDI_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_F))-1 ) = PACK(InData%IDI_F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI_F) - END IF - IF ( .NOT. ALLOCATED(InData%IDL_L) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDL_L,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL_L,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDL_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDL_L))-1 ) = PACK(InData%IDL_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDL_L) - END IF - IF ( .NOT. ALLOCATED(InData%IDC__) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC__,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC__,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDC__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC__))-1 ) = PACK(InData%IDC__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC__) - END IF - IF ( .NOT. ALLOCATED(InData%IDC_Rb) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_Rb,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_Rb,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDC_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_Rb))-1 ) = PACK(InData%IDC_Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_Rb) - END IF - IF ( .NOT. ALLOCATED(InData%IDC_L) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_L,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_L,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDC_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_L))-1 ) = PACK(InData%IDC_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_L) - END IF - IF ( .NOT. ALLOCATED(InData%IDC_F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDC_F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDC_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_F))-1 ) = PACK(InData%IDC_F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_F) - END IF - IF ( .NOT. ALLOCATED(InData%IDR__) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IDR__,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR__,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%IDR__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR__))-1 ) = PACK(InData%IDR__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDR__) - END IF - IF ( .NOT. ALLOCATED(InData%ID__Rb) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__Rb,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__Rb,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ID__Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__Rb))-1 ) = PACK(InData%ID__Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__Rb) - END IF - IF ( .NOT. ALLOCATED(InData%ID__L) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__L,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__L,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ID__L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__L))-1 ) = PACK(InData%ID__L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__L) - END IF - IF ( .NOT. ALLOCATED(InData%ID__F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ID__F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%ID__F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__F))-1 ) = PACK(InData%ID__F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__F) - END IF - IF ( .NOT. ALLOCATED(InData%FGL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FGL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FGL) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMOutputs - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutSwtch - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%UnJckF - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%Delim) - IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%OutFmt) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%OutSFmt) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IF ( .NOT. ALLOCATED(InData%MoutLst) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%MoutLst,1), UBOUND(InData%MoutLst,1) - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%MoutLst2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst2,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%MoutLst2,1), UBOUND(InData%MoutLst2,1) - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst2(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst2 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%MoutLst3) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MoutLst3,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MoutLst3,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%MoutLst3,1), UBOUND(InData%MoutLst3,1) - CALL SD_Packmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, InData%MoutLst3(i1), ErrStat2, ErrMsg2, OnlySize ) ! MoutLst3 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParam,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParam,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) - CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! OutParam - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutAll , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutReact , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllInt - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllDims - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutDec - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_PackParam - - SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%SDDeltaT = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%IntMethod = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF_red = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Nmembers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Elems)) DEALLOCATE(OutData%Elems) - ALLOCATE(OutData%Elems(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Elems)>0) OutData%Elems = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Elems))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Elems) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElemProps)) DEALLOCATE(OutData%ElemProps) - ALLOCATE(OutData%ElemProps(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemProps.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%ElemProps,1), UBOUND(OutData%ElemProps,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackelemproptype( Re_Buf, Db_Buf, Int_Buf, OutData%ElemProps(i1), ErrStat2, ErrMsg2 ) ! ElemProps - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%T_red)) DEALLOCATE(OutData%T_red) - ALLOCATE(OutData%T_red(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%T_red) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesDOF)) DEALLOCATE(OutData%NodesDOF) - ALLOCATE(OutData%NodesDOF(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%NodesDOF,1), UBOUND(OutData%NodesDOF,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOF(i1), ErrStat2, ErrMsg2 ) ! NodesDOF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOFtilde not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodesDOFtilde)) DEALLOCATE(OutData%NodesDOFtilde) - ALLOCATE(OutData%NodesDOFtilde(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodesDOFtilde.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%NodesDOFtilde,1), UBOUND(OutData%NodesDOFtilde,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackilist( Re_Buf, Db_Buf, Int_Buf, OutData%NodesDOFtilde(i1), ErrStat2, ErrMsg2 ) ! NodesDOFtilde - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemsDOF not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElemsDOF)) DEALLOCATE(OutData%ElemsDOF) - ALLOCATE(OutData%ElemsDOF(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFtilde2Nodes not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DOFtilde2Nodes)) DEALLOCATE(OutData%DOFtilde2Nodes) - ALLOCATE(OutData%DOFtilde2Nodes(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFtilde2Nodes.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%DOFtilde2Nodes)>0) OutData%DOFtilde2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFtilde2Nodes))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DOFtilde2Nodes) - DEALLOCATE(mask2) - END IF - OutData%nDOFM = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%SttcSolve = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%ExtraMoment = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NOmegaM2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NOmegaM2)) DEALLOCATE(OutData%NOmegaM2) - ALLOCATE(OutData%NOmegaM2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NOmegaM2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%NOmegaM2)>0) OutData%NOmegaM2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%NOmegaM2))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%NOmegaM2) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! N2OmegaMJDamp not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%N2OmegaMJDamp)) DEALLOCATE(OutData%N2OmegaMJDamp) - ALLOCATE(OutData%N2OmegaMJDamp(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%N2OmegaMJDamp.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%N2OmegaMJDamp)>0) OutData%N2OmegaMJDamp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%N2OmegaMJDamp))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%N2OmegaMJDamp) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MMB)) DEALLOCATE(OutData%MMB) - ALLOCATE(OutData%MMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MMB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MMB)>0) OutData%MMB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MMB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MMB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FX not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FX)) DEALLOCATE(OutData%FX) - ALLOCATE(OutData%FX(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FX)>0) OutData%FX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FX))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FX) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C1_11)) DEALLOCATE(OutData%C1_11) - ALLOCATE(OutData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_11.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%C1_11)>0) OutData%C1_11 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C1_11))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%C1_11) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_12 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C1_12)) DEALLOCATE(OutData%C1_12) - ALLOCATE(OutData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_12.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%C1_12)>0) OutData%C1_12 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C1_12))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%C1_12) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_13)) DEALLOCATE(OutData%D1_13) - ALLOCATE(OutData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_13.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D1_13)>0) OutData%D1_13 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_13))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D1_13) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_14 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_14)) DEALLOCATE(OutData%D1_14) - ALLOCATE(OutData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_14.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D1_14)>0) OutData%D1_14 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_14))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D1_14) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FY not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FY)) DEALLOCATE(OutData%FY) - ALLOCATE(OutData%FY(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FY.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FY)>0) OutData%FY = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FY))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FY) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiM)) DEALLOCATE(OutData%PhiM) - ALLOCATE(OutData%PhiM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiM)>0) OutData%PhiM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiM) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_61 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C2_61)) DEALLOCATE(OutData%C2_61) - ALLOCATE(OutData%C2_61(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%C2_61)>0) OutData%C2_61 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C2_61))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%C2_61) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C2_62 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C2_62)) DEALLOCATE(OutData%C2_62) - ALLOCATE(OutData%C2_62(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C2_62.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%C2_62)>0) OutData%C2_62 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%C2_62))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%C2_62) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiRb_TI not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiRb_TI)) DEALLOCATE(OutData%PhiRb_TI) - ALLOCATE(OutData%PhiRb_TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiRb_TI.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiRb_TI)>0) OutData%PhiRb_TI = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiRb_TI))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiRb_TI) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_63 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D2_63)) DEALLOCATE(OutData%D2_63) - ALLOCATE(OutData%D2_63(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_63.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D2_63)>0) OutData%D2_63 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D2_63))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D2_63) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D2_64 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D2_64)) DEALLOCATE(OutData%D2_64) - ALLOCATE(OutData%D2_64(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D2_64.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D2_64)>0) OutData%D2_64 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D2_64))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D2_64) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F2_61 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F2_61)) DEALLOCATE(OutData%F2_61) - ALLOCATE(OutData%F2_61(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%F2_61)>0) OutData%F2_61 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F2_61))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F2_61) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) - ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MBB)>0) OutData%MBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) - ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%KBB)>0) OutData%KBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KBB) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) - ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%MBM)>0) OutData%MBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBM) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_st_g not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UL_st_g)) DEALLOCATE(OutData%UL_st_g) - ALLOCATE(OutData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_st_g.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UL_st_g)>0) OutData%UL_st_g = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_st_g))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UL_st_g) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiL_T)) DEALLOCATE(OutData%PhiL_T) - ALLOCATE(OutData%PhiL_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL_T.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiL_T)>0) OutData%PhiL_T = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiL_T))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiL_T) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiLInvOmgL2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiLInvOmgL2)) DEALLOCATE(OutData%PhiLInvOmgL2) - ALLOCATE(OutData%PhiLInvOmgL2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiLInvOmgL2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PhiLInvOmgL2)>0) OutData%PhiLInvOmgL2 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiLInvOmgL2))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiLInvOmgL2) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KLLm1 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%KLLm1)) DEALLOCATE(OutData%KLLm1) - ALLOCATE(OutData%KLLm1(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KLLm1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%KLLm1)>0) OutData%KLLm1 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KLLm1))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KLLm1) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%AM2Jac)) DEALLOCATE(OutData%AM2Jac) - ALLOCATE(OutData%AM2Jac(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2Jac.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%AM2Jac)>0) OutData%AM2Jac = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%AM2Jac))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%AM2Jac) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2JacPiv not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%AM2JacPiv)) DEALLOCATE(OutData%AM2JacPiv) - ALLOCATE(OutData%AM2JacPiv(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AM2JacPiv.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%AM2JacPiv)>0) OutData%AM2JacPiv = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%AM2JacPiv))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%AM2JacPiv) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TI not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%TI)) DEALLOCATE(OutData%TI) - ALLOCATE(OutData%TI(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TI.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%TI)>0) OutData%TI = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TI))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TI) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TIreact not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%TIreact)) DEALLOCATE(OutData%TIreact) - ALLOCATE(OutData%TIreact(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TIreact.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%TIreact)>0) OutData%TIreact = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TIreact))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TIreact) - DEALLOCATE(mask2) - END IF - OutData%nNodes = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_I = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_C = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes_I)) DEALLOCATE(OutData%Nodes_I) - ALLOCATE(OutData%Nodes_I(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_I)>0) OutData%Nodes_I = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_I))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_I) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes_L)) DEALLOCATE(OutData%Nodes_L) - ALLOCATE(OutData%Nodes_L(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_L)>0) OutData%Nodes_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_L))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) - DEALLOCATE(mask2) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_C not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes_C)) DEALLOCATE(OutData%Nodes_C) - ALLOCATE(OutData%Nodes_C(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_C.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_C)>0) OutData%Nodes_C = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_C))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_C) - DEALLOCATE(mask2) - END IF - OutData%nDOFI__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFI_Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFI_F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFL_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFR__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI__ not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDI__)) DEALLOCATE(OutData%IDI__) - ALLOCATE(OutData%IDI__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI__)>0) OutData%IDI__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI__) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_Rb not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDI_Rb)) DEALLOCATE(OutData%IDI_Rb) - ALLOCATE(OutData%IDI_Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI_Rb)>0) OutData%IDI_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI_Rb) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDI_F)) DEALLOCATE(OutData%IDI_F) - ALLOCATE(OutData%IDI_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI_F)>0) OutData%IDI_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI_F) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL_L not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDL_L)) DEALLOCATE(OutData%IDL_L) - ALLOCATE(OutData%IDL_L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDL_L)>0) OutData%IDL_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL_L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDL_L) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC__ not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC__)) DEALLOCATE(OutData%IDC__) - ALLOCATE(OutData%IDC__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC__)>0) OutData%IDC__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC__) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_Rb not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC_Rb)) DEALLOCATE(OutData%IDC_Rb) - ALLOCATE(OutData%IDC_Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_Rb)>0) OutData%IDC_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_Rb) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_L not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC_L)) DEALLOCATE(OutData%IDC_L) - ALLOCATE(OutData%IDC_L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_L)>0) OutData%IDC_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_L) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDC_F)) DEALLOCATE(OutData%IDC_F) - ALLOCATE(OutData%IDC_F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_F)>0) OutData%IDC_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_F) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR__ not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IDR__)) DEALLOCATE(OutData%IDR__) - ALLOCATE(OutData%IDR__(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR__.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDR__)>0) OutData%IDR__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDR__) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__Rb not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ID__Rb)) DEALLOCATE(OutData%ID__Rb) - ALLOCATE(OutData%ID__Rb(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__Rb.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__Rb)>0) OutData%ID__Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__Rb) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__L not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ID__L)) DEALLOCATE(OutData%ID__L) - ALLOCATE(OutData%ID__L(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__L.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__L)>0) OutData%ID__L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__L) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ID__F)) DEALLOCATE(OutData%ID__F) - ALLOCATE(OutData%ID__F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__F)>0) OutData%ID__F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__F) - DEALLOCATE(mask1) - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FGL)) DEALLOCATE(OutData%FGL) - ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FGL)>0) OutData%FGL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FGL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FGL) - DEALLOCATE(mask1) - END IF - OutData%NMOutputs = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NumOuts = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutSwtch = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%UnJckF = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%Delim) - OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%OutFmt) - OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%OutSFmt) - OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MoutLst)) DEALLOCATE(OutData%MoutLst) - ALLOCATE(OutData%MoutLst(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%MoutLst,1), UBOUND(OutData%MoutLst,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst(i1), ErrStat2, ErrMsg2 ) ! MoutLst - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MoutLst2)) DEALLOCATE(OutData%MoutLst2) - ALLOCATE(OutData%MoutLst2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%MoutLst2,1), UBOUND(OutData%MoutLst2,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst2(i1), ErrStat2, ErrMsg2 ) ! MoutLst2 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst3 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MoutLst3)) DEALLOCATE(OutData%MoutLst3) - ALLOCATE(OutData%MoutLst3(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MoutLst3.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%MoutLst3,1), UBOUND(OutData%MoutLst3,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL SD_Unpackmeshauxdatatype( Re_Buf, Db_Buf, Int_Buf, OutData%MoutLst3(i1), ErrStat2, ErrMsg2 ) ! MoutLst3 - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%OutParam)) DEALLOCATE(OutData%OutParam) - ALLOCATE(OutData%OutParam(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%OutParam,1), UBOUND(OutData%OutParam,1) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackoutparmtype( Re_Buf, Db_Buf, Int_Buf, OutData%OutParam(i1), ErrStat2, ErrMsg2 ) ! OutParam - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END DO - END IF - OutData%OutAll = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%OutReact = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%OutAllInt = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutAllDims = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutDec = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_UnPackParam - - SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InputType), INTENT(INOUT) :: SrcInputData - TYPE(SD_InputType), INTENT(INOUT) :: DstInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL MeshCopy( SrcInputData%TPMesh, DstInputData%TPMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcInputData%LMesh, DstInputData%LMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE SD_CopyInput - - SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) - TYPE(SD_InputType), INTENT(INOUT) :: InputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInput' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - CALL MeshDestroy( InputData%TPMesh, ErrStat, ErrMsg ) - CALL MeshDestroy( InputData%LMesh, ErrStat, ErrMsg ) - END SUBROUTINE SD_DestroyInput - - SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! TPMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! TPMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! TPMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! TPMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! TPMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! LMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! LMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! LMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! LMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! LMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL MeshPack( InData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! TPMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! LMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE SD_PackInput - - SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%TPMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! TPMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%LMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! LMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE SD_UnPackInput - - SUBROUTINE SD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_OutputType), INTENT(INOUT) :: SrcOutputData - TYPE(SD_OutputType), INTENT(INOUT) :: DstOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL MeshCopy( SrcOutputData%Y1Mesh, DstOutputData%Y1Mesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL MeshCopy( SrcOutputData%Y2Mesh, DstOutputData%Y2Mesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN - i1_l = LBOUND(SrcOutputData%WriteOutput,1) - i1_u = UBOUND(SrcOutputData%WriteOutput,1) - IF (.NOT. ALLOCATED(DstOutputData%WriteOutput)) THEN - ALLOCATE(DstOutputData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstOutputData%WriteOutput = SrcOutputData%WriteOutput -ENDIF - END SUBROUTINE SD_CopyOutput - - SUBROUTINE SD_DestroyOutput( OutputData, ErrStat, ErrMsg ) - TYPE(SD_OutputType), INTENT(INOUT) :: OutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyOutput' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - CALL MeshDestroy( OutputData%Y1Mesh, ErrStat, ErrMsg ) - CALL MeshDestroy( OutputData%Y2Mesh, ErrStat, ErrMsg ) -IF (ALLOCATED(OutputData%WriteOutput)) THEN - DEALLOCATE(OutputData%WriteOutput) -ENDIF - END SUBROUTINE SD_DestroyOutput - - SUBROUTINE SD_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_OutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Y1Mesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y1Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Y1Mesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Y1Mesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Y1Mesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Y2Mesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! Y2Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Y2Mesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Y2Mesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Y2Mesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no - IF ( ALLOCATED(InData%WriteOutput) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL MeshPack( InData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y1Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL MeshPack( InData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! Y2Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutput,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutput,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%WriteOutput)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%WriteOutput))-1 ) = PACK(InData%WriteOutput,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%WriteOutput) - END IF - END SUBROUTINE SD_PackOutput - - SUBROUTINE SD_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_OutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%Y1Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y1Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%Y2Mesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! Y2Mesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutput)) DEALLOCATE(OutData%WriteOutput) - ALLOCATE(OutData%WriteOutput(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutput.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%WriteOutput)>0) OutData%WriteOutput = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%WriteOutput))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%WriteOutput) - DEALLOCATE(mask1) - END IF - END SUBROUTINE SD_UnPackOutput - - - SUBROUTINE SD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time -! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u -! -! expressions below based on either -! -! f(t) = a -! f(t) = a + b * t, or -! f(t) = a + b * t + c * t**2 -! -! where a, b and c are determined as the solution to -! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) -! -!.................................................................................................................................. - - TYPE(SD_InputType), INTENT(INOUT) :: u(:) ! Input at t1 > t2 > t3 - REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Inputs - TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out - REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: order ! order of polynomial fit (max 2) - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp' - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - if ( size(t) .ne. size(u)) then - CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(u)',ErrStat,ErrMsg,RoutineName) - RETURN - endif - order = SIZE(u) - 1 - IF ( order .eq. 0 ) THEN - CALL SD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE IF ( order .eq. 1 ) THEN - CALL SD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE IF ( order .eq. 2 ) THEN - CALL SD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE - CALL SetErrStat(ErrID_Fatal,'size(u) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - END SUBROUTINE SD_Input_ExtrapInterp - - - SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time -! values of u (which has values associated with times in t). Order of the interpolation is 1. -! -! f(t) = a + b * t, or -! -! where a and b are determined as the solution to -! f(t1) = u1, f(t2) = u2 -! -!.................................................................................................................................. - - TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 - TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 - REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs - TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out - REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(DbKi) :: t(2) ! Times associated with the Inputs - REAL(DbKi) :: t_out ! Time to which to be extrap/interpd - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp1' - REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation - REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - ! we'll subtract a constant from the times to resolve some - ! numerical issues when t gets large (and to simplify the equations) - t = tin - tin(1) - t_out = tin_out - tin(1) - - IF ( EqualRealNos( t(1), t(2) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - CALL MeshExtrapInterp1(u1%TPMesh, u2%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp1(u1%LMesh, u2%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - END SUBROUTINE SD_Input_ExtrapInterp1 - - - SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time -! values of u (which has values associated with times in t). Order of the interpolation is 2. -! -! expressions below based on either -! -! f(t) = a + b * t + c * t**2 -! -! where a, b and c are determined as the solution to -! f(t1) = u1, f(t2) = u2, f(t3) = u3 -! -!.................................................................................................................................. - - TYPE(SD_InputType), INTENT(INOUT) :: u1 ! Input at t1 > t2 > t3 - TYPE(SD_InputType), INTENT(INOUT) :: u2 ! Input at t2 > t3 - TYPE(SD_InputType), INTENT(INOUT) :: u3 ! Input at t3 - REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs - TYPE(SD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out - REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(DbKi) :: t(3) ! Times associated with the Inputs - REAL(DbKi) :: t_out ! Time to which to be extrap/interpd - INTEGER(IntKi) :: order ! order of polynomial fit (max 2) - REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation - REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp2' - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - ! we'll subtract a constant from the times to resolve some - ! numerical issues when t gets large (and to simplify the equations) - t = tin - tin(1) - t_out = tin_out - tin(1) - - IF ( EqualRealNos( t(1), t(2) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - CALL MeshExtrapInterp2(u1%TPMesh, u2%TPMesh, u3%TPMesh, tin, u_out%TPMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp2(u1%LMesh, u2%LMesh, u3%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - END SUBROUTINE SD_Input_ExtrapInterp2 - - - SUBROUTINE SD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time -! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y -! -! expressions below based on either -! -! f(t) = a -! f(t) = a + b * t, or -! f(t) = a + b * t + c * t**2 -! -! where a, b and c are determined as the solution to -! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) -! -!.................................................................................................................................. - - TYPE(SD_OutputType), INTENT(INOUT) :: y(:) ! Output at t1 > t2 > t3 - REAL(DbKi), INTENT(IN ) :: t(:) ! Times associated with the Outputs - TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out - REAL(DbKi), INTENT(IN ) :: t_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - INTEGER(IntKi) :: order ! order of polynomial fit (max 2) - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp' - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - if ( size(t) .ne. size(y)) then - CALL SetErrStat(ErrID_Fatal,'size(t) must equal size(y)',ErrStat,ErrMsg,RoutineName) - RETURN - endif - order = SIZE(y) - 1 - IF ( order .eq. 0 ) THEN - CALL SD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE IF ( order .eq. 1 ) THEN - CALL SD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE IF ( order .eq. 2 ) THEN - CALL SD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - ELSE - CALL SetErrStat(ErrID_Fatal,'size(y) must be less than 4 (order must be less than 3).',ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - END SUBROUTINE SD_Output_ExtrapInterp - - - SUBROUTINE SD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time -! values of y (which has values associated with times in t). Order of the interpolation is 1. -! -! f(t) = a + b * t, or -! -! where a and b are determined as the solution to -! f(t1) = y1, f(t2) = y2 -! -!.................................................................................................................................. - - TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 - TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 - REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs - TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out - REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(DbKi) :: t(2) ! Times associated with the Outputs - REAL(DbKi) :: t_out ! Time to which to be extrap/interpd - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp1' - REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation - REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - ! we'll subtract a constant from the times to resolve some - ! numerical issues when t gets large (and to simplify the equations) - t = tin - tin(1) - t_out = tin_out - tin(1) - - IF ( EqualRealNos( t(1), t(2) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - CALL MeshExtrapInterp1(y1%Y1Mesh, y2%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp1(y1%Y2Mesh, y2%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = -(y1%WriteOutput - y2%WriteOutput)/t(2) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated - END SUBROUTINE SD_Output_ExtrapInterp1 - - - SUBROUTINE SD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) -! -! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time -! values of y (which has values associated with times in t). Order of the interpolation is 2. -! -! expressions below based on either -! -! f(t) = a + b * t + c * t**2 -! -! where a, b and c are determined as the solution to -! f(t1) = y1, f(t2) = y2, f(t3) = y3 -! -!.................................................................................................................................. - - TYPE(SD_OutputType), INTENT(INOUT) :: y1 ! Output at t1 > t2 > t3 - TYPE(SD_OutputType), INTENT(INOUT) :: y2 ! Output at t2 > t3 - TYPE(SD_OutputType), INTENT(INOUT) :: y3 ! Output at t3 - REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs - TYPE(SD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out - REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - ! local variables - REAL(DbKi) :: t(3) ! Times associated with the Outputs - REAL(DbKi) :: t_out ! Time to which to be extrap/interpd - INTEGER(IntKi) :: order ! order of polynomial fit (max 2) - REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation - REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation - REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation - INTEGER(IntKi) :: ErrStat2 ! local errors - CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors - CHARACTER(*), PARAMETER :: RoutineName = 'SD_Output_ExtrapInterp2' - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - ! we'll subtract a constant from the times to resolve some - ! numerical issues when t gets large (and to simplify the equations) - t = tin - tin(1) - t_out = tin_out - tin(1) - - IF ( EqualRealNos( t(1), t(2) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN - CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - CALL MeshExtrapInterp2(y1%Y1Mesh, y2%Y1Mesh, y3%Y1Mesh, tin, y_out%Y1Mesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - CALL MeshExtrapInterp2(y1%Y2Mesh, y2%Y2Mesh, y3%Y2Mesh, tin, y_out%Y2Mesh, tin_out, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN - ALLOCATE(b1(SIZE(y_out%WriteOutput,1))) - ALLOCATE(c1(SIZE(y_out%WriteOutput,1))) - b1 = (t(3)**2*(y1%WriteOutput - y2%WriteOutput) + t(2)**2*(-y1%WriteOutput + y3%WriteOutput))/(t(2)*t(3)*(t(2) - t(3))) - c1 = ( (t(2)-t(3))*y1%WriteOutput + t(3)*y2%WriteOutput - t(2)*y3%WriteOutput ) / (t(2)*t(3)*(t(2) - t(3))) - y_out%WriteOutput = y1%WriteOutput + b1 * t_out + c1 * t_out**2 - DEALLOCATE(b1) - DEALLOCATE(c1) -END IF ! check if allocated - END SUBROUTINE SD_Output_ExtrapInterp2 - -END MODULE SubDyn_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/subdyn/src_soildyn/Yaml.f90 b/modules/subdyn/src_soildyn/Yaml.f90 deleted file mode 100644 index ec3043c23..000000000 --- a/modules/subdyn/src_soildyn/Yaml.f90 +++ /dev/null @@ -1,609 +0,0 @@ -!.................................................................................................................................. -! LICENSING -! Copyright (C) 2013-2016 National Renewable Energy Laboratory -! -! This file is part of SubDyn. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -module YAML - use NWTC_Library - - implicit none - - integer(IntKi), parameter :: INDENT_SPACES = 2 - - !> Write 1D or 2D array to file - interface yaml_write_array - module procedure yaml_write_array1I ! Single dimension array (Ary) of IntKi - module procedure yaml_write_array1R4 ! Single dimension array (Ary) of SiKi - module procedure yaml_write_array2R4 ! Two dimension array of SiKi - module procedure yaml_write_array1R8 ! Single dimension array (Ary) of R8Ki - module procedure yaml_write_array2R8 ! Two dimension array of R8Ki - module procedure yaml_write_array2I ! Two dimension array of IntKi - module procedure yaml_write_array1R16 ! Single dimension array (Ary) of QuKi - module procedure yaml_write_array2R16 ! Two dimension array of QuKi - end interface - - !> Write variable to file - interface yaml_write_var - module procedure yaml_write_varC ! Character - module procedure yaml_write_varI ! IntKi - module procedure yaml_write_varR4 ! SiKi - module procedure yaml_write_varR8 ! R8Ki - module procedure yaml_write_varR16 ! QuKi - end interface - private - - public :: yaml_write_var - public :: yaml_write_array - -contains - -! -------------------------------------------------------------------------------- -! --- Write variable -! -------------------------------------------------------------------------------- -!> Write simple key/variable to yaml file -subroutine yaml_write_varC(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Variable name - character(len=*), intent(in ) :: val !< Value - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' - write(fid, Fmt, iostat=ErrStat) key, val, comment - else - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' - write(fid, Fmt, iostat=ErrStat) key, val - endif - if (ErrStat /= 0) then - ErrMsg='Error writting variable '//trim(key)//' to YAML file' - return - endif -end subroutine yaml_write_varC - -subroutine yaml_write_varI(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Variable name - integer(IntKi), intent(in ) :: val !< Value - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' - write(fid, Fmt, iostat=ErrStat) key, val, comment - else - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' - write(fid, Fmt, iostat=ErrStat) key, val - endif - if (ErrStat /= 0) then - ErrMsg='Error writting variable '//trim(key)//' to YAML file' - return - endif -end subroutine yaml_write_varI - -subroutine yaml_write_varR4(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Variable name - real(SiKi), intent(in ) :: val !< Value - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' - write(fid, Fmt, iostat=ErrStat) key, val, comment - else - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' - write(fid, Fmt, iostat=ErrStat) key, val - endif - if (ErrStat /= 0) then - ErrMsg='Error writting variable '//trim(key)//' to YAML file' - return - endif -end subroutine yaml_write_varR4 - -subroutine yaml_write_varR8(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Variable name - real(R8Ki), intent(in ) :: val !< Value - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' - write(fid, Fmt, iostat=ErrStat) key, val, comment - else - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' - write(fid, Fmt, iostat=ErrStat) key, val - endif - if (ErrStat /= 0) then - ErrMsg='Error writting variable '//trim(key)//' to YAML file' - return - endif -end subroutine yaml_write_varR8 - -subroutine yaml_write_varR16(fid, key, val, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Variable name - real(QuKi), intent(in ) :: val !< Value - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//', " # ",A)' - write(fid, Fmt, iostat=ErrStat) key, val, comment - else - Fmt = '('//trim(Fmt)//'A,": ",'//trim(VarFmt)//')' - write(fid, Fmt, iostat=ErrStat) key, val - endif - if (ErrStat /= 0) then - ErrMsg='Error writting variable '//trim(key)//' to YAML file' - return - endif -end subroutine yaml_write_varR16 - -! -------------------------------------------------------------------------------- -! --- Write array -! -------------------------------------------------------------------------------- -!> Write 1D or 2D array to file -subroutine yaml_write_array1I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - integer(IntKi), dimension(:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nc ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nc = size(A,1) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nc==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - write(fid, Fmt, iostat=ErrStat) A(:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - endif -end subroutine yaml_write_array1I - -subroutine yaml_write_array1R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(SiKi), dimension(:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nc ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nc = size(A,1) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nc==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - write(fid, Fmt, iostat=ErrStat) A(:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - endif -end subroutine yaml_write_array1R4 - -subroutine yaml_write_array1R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(R8Ki), dimension(:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nc ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nc = size(A,1) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key), 1, nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nc==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - write(fid, Fmt, iostat=ErrStat) A(:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - endif -end subroutine yaml_write_array1R8 - -subroutine yaml_write_array1R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(QuKi), dimension(:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - integer :: nc ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nc = size(A,1) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), 1, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),1,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nc==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - write(fid, Fmt, iostat=ErrStat) A(:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - endif -end subroutine yaml_write_array1R16 - -subroutine yaml_write_array2I(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, label) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - integer(IntKi), dimension(:,:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - logical, optional, intent(in ) :: label !< If present, add a index label at end of line - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - if (present(label)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"] # ",I0)' - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - endif - do i=1,nr - if (present(label)) then - write(fid, Fmt, iostat=ErrStat) A(i,:), i - else - write(fid, Fmt, iostat=ErrStat) A(i,:) - endif - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2I - -subroutine yaml_write_array2R4(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(SiKi), dimension(:,:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - if (nc==0) then - Fmt = '('//trim(Fmt)//'"- []")' - else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - endif - endif - do i=1,nr - write(fid, Fmt, iostat=ErrStat) A(i,:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2R4 - -subroutine yaml_write_array2R8(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(R8Ki), dimension(:,:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - if (present(level)) then - Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - else - Fmt = '' - endif - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - if (nc==0) then - Fmt = '('//trim(Fmt)//'"- []")' - else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - endif - endif - do i=1,nr - write(fid, Fmt, iostat=ErrStat) A(i,:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2R8 - -subroutine yaml_write_array2R16(fid, key, A, VarFmt, ErrStat, ErrMsg, level, comment, AllFmt) - integer(IntKi), intent(in ) :: fid !< File Unit - character(len=*), intent(in ) :: key !< Array name - real(QuKi), dimension(:,:), intent(in ) :: A !< Array - character(len=*), intent(in ) :: VarFmt !< Format for printing real numbers - integer, intent( out) :: ErrStat !< A non-zero value indicates an error occurred - character(len=*), intent( out) :: ErrMsg !< Error message if errstat /= errid_none - integer(IntKi), optional, intent(in ) :: level !< indentation level - character(len=*), optional, intent(in ) :: comment !< - character(len=*), optional, intent(in ) :: AllFmt !< Format for printing a line - integer :: nr, nc, i ! size (rows and columns) of A - integer :: nSpaces ! number of indentation spaces - character(256) :: Fmt - ErrStat = ErrID_None - ErrMsg = "" - nr = size(A,1) - nc = size(A,2) - - Fmt = '' - if (present(level)) Fmt = trim(Num2LStr(level*INDENT_SPACES))//'X,' - if (present(comment)) then - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0,1X,A)', iostat=ErrStat ) trim(key), nr, nc, trim(comment) - - else - write(fid, '('//trim(Fmt)//'A,": # ",I0," x ",I0)' , iostat=ErrStat ) trim(key),nr,nc - end if - - if (present(level)) then - Fmt = trim(Num2LStr((level+1)*INDENT_SPACES))//'X,' - else - Fmt = trim(Num2LStr(INDENT_SPACES))//'X,' - endif - if (nr==0) then - write(fid, '('//trim(Fmt)//'"- [ ]")', iostat=ErrStat) - else - if (nc==0) then - Fmt = '('//trim(Fmt)//'"- []")' - else - if (present(AllFmt)) then - Fmt = '('//trim(Fmt)//'"- [",'//trim(AllFmt)//'"]")' - else - Fmt = '('//trim(Fmt)//'"- [",'//trim(Num2LStr(nc))//'('//VarFmt//',","),"]")' - endif - endif - do i=1,nr - write(fid, Fmt, iostat=ErrStat) A(i,:) - if (ErrStat /= 0) then - ErrMsg='Error writting array '//trim(key)//' to YAML file' - return - end if - end do - endif -end subroutine yaml_write_array2R16 - - -end module YAML diff --git a/modules/subdyn/src_soildyn/qsort_c_module.f90 b/modules/subdyn/src_soildyn/qsort_c_module.f90 deleted file mode 100644 index 553b25544..000000000 --- a/modules/subdyn/src_soildyn/qsort_c_module.f90 +++ /dev/null @@ -1,61 +0,0 @@ -!********************************************************************************************************************************** -module qsort_c_module -!This routine ASSUMES A is (m,2) dimensioned array -implicit none -public :: QsortC -private :: Partition - -contains - -recursive subroutine QsortC(A) - integer, intent(in out), dimension(:,:) :: A - integer :: iq - - if(size(A,1) > 1) then - call Partition(A, iq) - call QsortC(A(:iq-1, :)) - call QsortC(A(iq:, :)) - endif -end subroutine QsortC - -subroutine Partition(A, marker) - integer, intent(in out), dimension(:,:) :: A - integer, intent(out) :: marker - integer :: i, j, k - integer :: temp - integer :: x ! pivot point - x = A(1, 1) - i= 0 - j= size(A,1) + 1 - - - do - j = j-1 - do - if (A(j,1) <= x) exit - j = j-1 - end do - i = i+1 - do - if (A(i,1) >= x) exit - i = i+1 - end do - if (i < j) then - ! exchange A(i) and A(j) - do k=1,size(A,2) - temp = A(i,k) - A(i,k) = A(j,k) - A(j,k) = temp - end do !k - elseif (i == j) then - marker = i+1 - return - else - marker = i - return - endif - end do - -end subroutine Partition - -end module qsort_c_module \ No newline at end of file From 569591a9e93b5222fbd04058fb56f8de1510c554 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 3 Aug 2020 15:18:10 -0600 Subject: [PATCH 252/377] Fixed missing % separators --- modules/openfast-library/src/FAST_Subs.f90 | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index d1e870fc1..36d1ce38d 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -837,13 +837,13 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, Init%InData_SD%WtrDpth = 0.0_ReKi END IF - InitInData_SD%Linearize = p_FAST%Linearize - InitInData_SD%g = InitOutData_ED%Gravity - !InitInData_SD%UseInputFile = .TRUE. - InitInData_SD%SDInputFile = p_FAST%SubFile - InitInData_SD%RootName = p_FAST%OutFileRoot - InitInData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to - InitInData_SD%SubRotateZ = 0.0 ! Used by driver to rotate structure around z + Init%InData_SD%Linearize = p_FAST%Linearize + Init%InData_SD%g = Init%OutData_ED%Gravity + !Ini%tInData_SD%UseInputFile = .TRUE. + Init%InData_SD%SDInputFile = p_FAST%SubFile + Init%InData_SD%RootName = p_FAST%OutFileRoot + Init%InData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to + Init%InData_SD%SubRotateZ = 0.0 ! Used by driver to rotate structure around z CALL SD_Init( Init%InData_SD, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR), & @@ -858,15 +858,15 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if (ErrStat2 /= 0 ) then call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(SD).", ErrStat, ErrMsg, RoutineName ) else - if (allocated(InitOutData_SD%LinNames_y)) call move_alloc(InitOutData_SD%LinNames_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_y) - if (allocated(InitOutData_SD%LinNames_x)) call move_alloc(InitOutData_SD%LinNames_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_x) - if (allocated(InitOutData_SD%LinNames_u)) call move_alloc(InitOutData_SD%LinNames_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_u) - if (allocated(InitOutData_SD%RotFrame_y)) call move_alloc(InitOutData_SD%RotFrame_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_y) - if (allocated(InitOutData_SD%RotFrame_x)) call move_alloc(InitOutData_SD%RotFrame_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_x) - if (allocated(InitOutData_SD%RotFrame_u)) call move_alloc(InitOutData_SD%RotFrame_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_u) - if (allocated(InitOutData_SD%IsLoad_u )) call move_alloc(InitOutData_SD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%IsLoad_u ) - if (allocated(InitOutData_SD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%NumOutputs = size(InitOutData_SD%WriteOutputHdr) - if (allocated(InitOutData_SD%DerivOrder_x)) call move_alloc(InitOutData_SD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%DerivOrder_x) + if (allocated(Init%OutData_SD%LinNames_y)) call move_alloc(Init%OutData_SD%LinNames_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_y) + if (allocated(Init%OutData_SD%LinNames_x)) call move_alloc(Init%OutData_SD%LinNames_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_x) + if (allocated(Init%OutData_SD%LinNames_u)) call move_alloc(Init%OutData_SD%LinNames_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%Names_u) + if (allocated(Init%OutData_SD%RotFrame_y)) call move_alloc(Init%OutData_SD%RotFrame_y,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_y) + if (allocated(Init%OutData_SD%RotFrame_x)) call move_alloc(Init%OutData_SD%RotFrame_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_x) + if (allocated(Init%OutData_SD%RotFrame_u)) call move_alloc(Init%OutData_SD%RotFrame_u,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%RotFrame_u) + if (allocated(Init%OutData_SD%IsLoad_u )) call move_alloc(Init%OutData_SD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%IsLoad_u ) + if (allocated(Init%OutData_SD%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%NumOutputs = size(Init%OutData_SD%WriteOutputHdr) + if (allocated(Init%OutData_SD%DerivOrder_x)) call move_alloc(Init%OutData_SD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%DerivOrder_x) end if IF (ErrStat >= AbortErrLev) THEN @@ -893,15 +893,15 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if (ErrStat2 /= 0 ) then call SetErrStat(ErrID_Fatal, "Error allocating Lin%Modules(ExtPtfm).", ErrStat, ErrMsg, RoutineName ) else - if (allocated(InitOutData_ExtPtfm%LinNames_y)) call move_alloc(InitOutData_ExtPtfm%LinNames_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_y) - if (allocated(InitOutData_ExtPtfm%LinNames_x)) call move_alloc(InitOutData_ExtPtfm%LinNames_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_x) - if (allocated(InitOutData_ExtPtfm%LinNames_u)) call move_alloc(InitOutData_ExtPtfm%LinNames_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_u) - if (allocated(InitOutData_ExtPtfm%RotFrame_y)) call move_alloc(InitOutData_ExtPtfm%RotFrame_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_y) - if (allocated(InitOutData_ExtPtfm%RotFrame_x)) call move_alloc(InitOutData_ExtPtfm%RotFrame_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_x) - if (allocated(InitOutData_ExtPtfm%RotFrame_u)) call move_alloc(InitOutData_ExtPtfm%RotFrame_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_u) - if (allocated(InitOutData_ExtPtfm%IsLoad_u )) call move_alloc(InitOutData_ExtPtfm%IsLoad_u ,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%IsLoad_u ) - if (allocated(InitOutData_ExtPtfm%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%NumOutputs = size(InitOutData_ExtPtfm%WriteOutputHdr) - if (allocated(InitOutData_ExtPtfm%DerivOrder_x)) call move_alloc(InitOutData_ExtPtfm%DerivOrder_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%DerivOrder_x) + if (allocated(Init%OutData_ExtPtfm%LinNames_y)) call move_alloc(Init%OutData_ExtPtfm%LinNames_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_y) + if (allocated(Init%OutData_ExtPtfm%LinNames_x)) call move_alloc(Init%OutData_ExtPtfm%LinNames_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_x) + if (allocated(Init%OutData_ExtPtfm%LinNames_u)) call move_alloc(Init%OutData_ExtPtfm%LinNames_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%Names_u) + if (allocated(Init%OutData_ExtPtfm%RotFrame_y)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_y,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_y) + if (allocated(Init%OutData_ExtPtfm%RotFrame_x)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_x) + if (allocated(Init%OutData_ExtPtfm%RotFrame_u)) call move_alloc(Init%OutData_ExtPtfm%RotFrame_u,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%RotFrame_u) + if (allocated(Init%OutData_ExtPtfm%IsLoad_u )) call move_alloc(Init%OutData_ExtPtfm%IsLoad_u ,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%IsLoad_u ) + if (allocated(Init%OutData_ExtPtfm%WriteOutputHdr)) y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%NumOutputs = size(Init%OutData_ExtPtfm%WriteOutputHdr) + if (allocated(Init%OutData_ExtPtfm%DerivOrder_x)) call move_alloc(Init%OutData_ExtPtfm%DerivOrder_x,y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%DerivOrder_x) end if IF (ErrStat >= AbortErrLev) THEN From 0b84d39e83c9af9e40fd69d9cb4d0f9891b9021a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 3 Aug 2020 15:19:26 -0600 Subject: [PATCH 253/377] Update Glue-code linearization for Subdyn and new module connections --- modules/openfast-library/src/FAST_Lin.f90 | 829 +++++++++++++++++----- 1 file changed, 658 insertions(+), 171 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index a3e4d75ff..5c8f6dae8 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -1751,17 +1751,20 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, end if ! we're using the InflowWind module !............ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{BD}} \end{bmatrix} = \f$ and ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{AD}} \end{bmatrix} = \f$ and - ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{BD}} \end{bmatrix} = \f$ (dUdu block row 3=ED) + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{HD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{SD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial u^{MAP}} \end{bmatrix} = \f$ (dUdu block row 3=ED) !............ ! we need to do this for CompElast=ED and CompElast=BD - call Linear_ED_InputSolve_du( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call Linear_ED_InputSolve_du( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, SD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) !............ - ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{AD}} \end{bmatrix} = \f$ and - ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} \end{bmatrix} = \f$ (dUdu block row 4=BD) + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{BD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial u^{AD}} \end{bmatrix} = \f$ (dUdu block row 4=BD) !............ IF (p_FAST%CompElast == Module_BD) THEN call Linear_BD_InputSolve_du( p_FAST, y_FAST, ED%y, AD%y, AD%Input(1), BD, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) @@ -1776,21 +1779,29 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF (p_FAST%CompSub == Module_SD) THEN - write(*,*)'>>> FAST_LIN: Linear_SD_InputSolve_dy, TODO' - ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN - CALL WrScr('>>> FAST_LIN: Linear_ExtPtfm_InputSolve_du, TODO') - ENDIF + !............ ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial u^{HD}} \end{bmatrix} = \f$ (dUdu block row 6=HD) !............ IF (p_FAST%CompHydro == MODULE_HD) THEN - call Linear_HD_InputSolve_du( p_FAST, y_FAST, HD%Input(1), ED%y, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call Linear_HD_InputSolve_du( p_FAST, y_FAST, HD%Input(1), ED%y, SD%y, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - ! LIN-TODO: Update the doc lines below to include HD and MAP + !............ + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial u^{HD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial u^{SD}} \end{bmatrix} = \f$ and + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial u^{MAP}} \end{bmatrix} = \f$ (dUdu block row 7=SD) + !............ + IF (p_FAST%CompSub == MODULE_SD) THEN + call Linear_SD_InputSolve_du( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN + CALL WrScr('>>> FAST_LIN: Linear_ExtPtfm_InputSolve_du, TODO') + ENDIF + + ! LIN-TODO: Update the doc lines below to include HD, SD, and MAP !..................................... ! dUdy !> \f$ \frac{\partial U_\Lambda}{\partial y} = @@ -1832,10 +1843,13 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{SrvD}} \end{bmatrix} = \f$ ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{ED}} \end{bmatrix} = \f$ ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{BD}} \end{bmatrix} = \f$ - ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{AD}} \end{bmatrix} = \f$ (dUdy block row 3=ED) + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{AD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{HD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{SD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{ED}}{\partial y^{MAP}} \end{bmatrix} = \f$ (dUdy block row 3=ED) !............ - call Linear_ED_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, MAPp, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call Linear_ED_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, HD, SD, MAPp, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) !............ @@ -1864,26 +1878,39 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, end if -! LIN-TODO: Implement HD-related solve + !............ - ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial y^{ED}} \end{bmatrix} = \f$ (dUdy block row 6=HD) + ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{HD}}{\partial y^{SD}} \end{bmatrix} = \f$ (dUdy block row 6=HD) !............ if (p_FAST%CompHydro == MODULE_HD) then - call Linear_HD_InputSolve_dy( p_FAST, y_FAST, HD%Input(1), ED%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call Linear_HD_InputSolve_dy( p_FAST, y_FAST, HD%Input(1), ED%y, SD%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if -! LIN-TODO: Implement Map-related solve !............ - ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{ED}} \end{bmatrix} = \f$ (dUdy block row 7=MAP) + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial y^{HD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial y^{SD}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{SD}}{\partial y^{MAP}} \end{bmatrix} = \f$ (dUdy block row 7=AD) + !............ + if (p_FAST%CompHydro == MODULE_HD) then + call Linear_HD_InputSolve_dy( p_FAST, y_FAST, HD%Input(1), ED%y, SD%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + end if + + !............ + ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{ED}} \end{bmatrix} = \f$ + ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{SD}} \end{bmatrix} = \f$ (dUdy block row 8=MAP) !............ if (p_FAST%CompMooring == MODULE_MAP) then - call Linear_MAP_InputSolve_dy( p_FAST, y_FAST, MAPp%Input(1), ED%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) + call Linear_MAP_InputSolve_dy( p_FAST, y_FAST, MAPp%Input(1), ED%y, SD%y, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if IF (p_FAST%CompSub == Module_SD) THEN - write(*,*)'>>> FAST_LIN: Linear_SD_InputSolve_dy, TODO' + call Linear_SD_InputSolve_dy( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO' ENDIF @@ -1951,7 +1978,7 @@ SUBROUTINE Linear_IfW_InputSolve_du_AD( p_FAST, y_FAST, u_AD, dUdu ) END SUBROUTINE Linear_IfW_InputSolve_du_AD !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{ED}/du^{BD} and dU^{ED}/du^{AD} blocks (ED row) of dUdu. (i.e., how do changes in the AD and BD inputs affect the ED inputs?) -SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) +SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, SD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) !LIN-TODO: Augment this interface for HD and MAP TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) @@ -1961,6 +1988,7 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linerization) TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SD data at t TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(ED)/du^(AD) block @@ -1972,8 +2000,9 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, INTEGER(IntKi) :: BD_Start ! starting index of dUdu (column) where BD root motion inputs are located INTEGER(IntKi) :: AD_Start_Bl ! starting index of dUdu (column) where AD blade motion inputs are located INTEGER(IntKi) :: ED_Start_mt ! starting index of dUdu (row) where ED blade/tower or hub moment inputs are located - INTEGER(IntKi) :: HD_Start - INTEGER(IntKi) :: MAP_Start + INTEGER(IntKi) :: HD_Start ! starting index of dUdu (column) where HD motion inputs are located + INTEGER(IntKi) :: SD_Start ! starting index of dUdu (column) where SD TP motion inputs are located + INTEGER(IntKi) :: MAP_Start ! starting index of dUdu (column) where MAP fairlead motion inputs are located INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None @@ -2057,23 +2086,56 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, END IF - !.......... - ! dU^{ED}/du^{HD} - !.......... + ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & + + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) - if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} - + if ( p_FAST%CompSub == Module_SD ) then + !.......... + ! dU^{ED}/du^{SD} + !.......... + ! Transfer SD load outputs to ED PlatformPtMesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + SD_Start = Indx_u_SD_TPMesh_Start(SD%Input(1), y_FAST) + + call Linearize_Point_to_Point( SD%y%Y1Mesh, u_ED%PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, SD%Input(1)%TPMesh, y_ED%PlatformPtMesh) !SD%Input(1)%TPMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! SD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%SD_TP_2_ED_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%SD_TP_2_ED_P%dM%m_us, ED_Start_mt, SD_Start ) + end if + + else if ( p_FAST%CompSub == Module_None ) then + !.......... + ! dU^{ED}/du^{HD} + !.......... + + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn} + ! we're just going to assume u_ED%PlatformPtMesh is committed + if ( HD%y%Morison%Mesh%Committed ) then ! meshes for floating + + ! Transfer HD load outputs to ED PlatformPtMesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + HD_Start = Indx_u_HD_Morison_Start(HD%Input(1), y_FAST) + + call Linearize_Point_to_Point( HD%y%Morison%Mesh, u_ED%PlatformPtMesh, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Morison%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Morison and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%HD_M_P_2_ED_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%HD_M_P_2_ED_P%dM%m_us, ED_Start_mt, HD_Start ) + end if + + end if if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating - ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & - + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) ! Transfer HD load outputs to ED PlatformPtMesh input: ! we're mapping loads, so we also need the sibling meshes' displacements: - HD_Start = Indx_u_HD_PlatformRef_Start(HD%Input(1), y_FAST) + HD_Start = Indx_u_HD_WAMIT_Start(HD%Input(1), y_FAST) - call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%WAMITMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) ! HD is source in the mapping, so we want M_{uSm} @@ -2082,36 +2144,268 @@ SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, end if end if - end if + end if - !.......... - ! dU^{ED}/du^{MAP} - !.......... - ! LIN-TODO: Implement - if ( p_FAST%CompMooring == Module_MAP ) then + !.......... + ! dU^{ED}/du^{MAP} + !.......... + + if ( p_FAST%CompMooring == Module_MAP ) then - ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & - + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) + ED_Start_mt = Indx_u_ED_Platform_Start(u_ED, y_FAST) & + + u_ED%PlatformPtMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) - ! Transfer MAP loads to ED PlatformPtmesh input: - ! we're mapping loads, so we also need the sibling meshes' displacements: + ! Transfer MAP loads to ED PlatformPtmesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: - MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) - ! NOTE: Assumes at least one MAP Fairlead point + ! NOTE: Assumes at least one MAP Fairlead point - CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - ! HD is source in the mapping, so we want M_{uSm} - if (allocated(MeshMapData%Mooring_P_2_ED_P%dM%m_us )) then - call SetBlockMatrix( dUdu, MeshMapData%Mooring_P_2_ED_P%dM%m_us, ED_Start_mt, MAP_Start ) + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%Mooring_P_2_ED_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%Mooring_P_2_ED_P%dM%m_us, ED_Start_mt, MAP_Start ) + end if + end if + + end if +END SUBROUTINE Linear_ED_InputSolve_du + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{SD}/du^{HD} and dU^{SD}/du^{SD} and dU^{SD}/du^{MAP} blocks (SD row) of dUdu. (i.e., how do changes in the HD and SD inputs affect the SD inputs?) +SUBROUTINE Linear_SD_InputSolve_du( p_FAST, y_FAST, u_SD, y_SD, y_ED, HD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) +!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) + TYPE(SD_InputType), INTENT(INOUT) :: u_SD !< SD Inputs at t + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SubDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^(SD)/du^(AD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: HD_Start + INTEGER(IntKi) :: MAP_Start + INTEGER(IntKi) :: SD_Start, SD_Start_td, SD_Start_tr + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_SD_InputSolve_du' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( p_FAST%CompSub == Module_SD ) THEN ! see routine U_ED_SD_HD_BD_Orca_Residual() in SolveOption1 + + !.......... + ! dU^{SD}/du^{SD} + !.......... + + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! SD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + + SD_Start_td = y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + SD_Start_tr = SD_Start_td + u_SD%TPMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_SD_TP%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_SD_TP%dM%tv_ud, SD_Start_tr, SD_Start_td ) + end if + + ! translational acceleration: + SD_Start_tr = SD_Start_tr + u_SD%TPMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%ED_P_2_SD_TP%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_SD_TP%dM%ta_ud, SD_Start_tr, SD_Start_td ) + end if + + + !.......... + ! dU^{SD}/du^{HD} + !.......... + + ! we're just going to assume u_SD%LMesh is committed + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) & + + u_SD%LMesh%NNodes * 3 ! 3 forces at each node (we're going to start at the moments) + + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + + + ! Transfer HD load outputs to SD LMesh input: + if ( HD%y%Morison%Mesh%Committed ) then ! meshes for floating + + ! dU^{SD}/du^{HD} + + ! we're mapping loads, so we also need the sibling meshes' displacements: + HD_Start = Indx_u_HD_Morison_Start(HD%Input(1), y_FAST) + + call Linearize_Point_to_Point( HD%y%Morison%Mesh, u_SD%LMesh, MeshMapData%HD_M_P_2_SD_P, ErrStat2, ErrMsg2, HD%Input(1)%Morison%Mesh, y_SD%Y2Mesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%HD_M_P_2_SD_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%HD_M_P_2_SD_P%dM%m_us, SD_Start, HD_Start ) + end if + + + + + end if + if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating + + ! Transfer HD load outputs to ED PlatformPtMesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + HD_Start = Indx_u_HD_WAMIT_Start(HD%Input(1), y_FAST) + + call Linearize_Point_to_Point( HD%y%WAMITMesh, u_SD%LMesh, MeshMapData%HD_W_P_2_SD_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_SD%Y2Mesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + call SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! HD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%HD_W_P_2_SD_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%HD_W_P_2_SD_P%dM%m_us, SD_Start, HD_Start ) + end if + + + end if end if + + !.......... + ! dU^{SD}/du^{MAP} + !.......... + + if ( p_FAST%CompMooring == Module_MAP ) then + + ! Transfer MAP loads to ED PlatformPtmesh input: + ! we're mapping loads, so we also need the sibling meshes' displacements: + + MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) -END SUBROUTINE Linear_ED_InputSolve_du + ! NOTE: Assumes at least one MAP Fairlead point + + CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_SD%LMesh, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_SD%Y2Mesh) !MAPp%Input(1)%ptFairleadLoad and y_SD%Y2Mesh contain the displaced positions for load calculations + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + + ! SD is source in the mapping, so we want M_{uSm} + if (allocated(MeshMapData%Mooring_P_2_SD_P%dM%m_us )) then + call SetBlockMatrix( dUdu, MeshMapData%Mooring_P_2_SD_P%dM%m_us, SD_Start, MAP_Start ) + end if + + end if + END IF +END SUBROUTINE Linear_SD_InputSolve_du +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine forms the dU^{SD}/du^{HD} and dU^{SD}/du^{SD} blocks (SD row) of dUdu. (i.e., how do changes in the HD and SD inputs affect the SD inputs?) +SUBROUTINE Linear_SD_InputSolve_dy( p_FAST, y_FAST, u_SD, y_SD, y_ED, HD, MAPp, MeshMapData, dUdy, ErrStat, ErrMsg ) +!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) + TYPE(SD_InputType), INTENT(INOUT) :: u_SD !< SD Inputs at t + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SubDyn outputs (need translation displacement on meshes for loads mapping) + TYPE(ED_OutputType), INTENT(IN ) :: y_ED !< ElastoDyn outputs + TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t + TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules + REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^(SD)/dy^(SD) block + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message + + ! local variables + INTEGER(IntKi) :: SD_Start, SD_Out_Start, HD_Start, HD_Out_Start, ED_Out_Start, MAP_Out_Start + INTEGER(IntKi) :: MAP_Start + INTEGER(IntKi) :: ErrStat2 ! temporary Error status of the operation + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName = 'Linear_SD_InputSolve_du' + + + ! Initialize error status + + ErrStat = ErrID_None + ErrMsg = "" + if ( p_FAST%CompSub /= Module_SD ) return !LIN-TODO: Verify that it is ok to simply return. What is dUdy in that case + + !.......... + ! dU^{SD}/dy^{ED} + !.......... + + !!! ! This linearization was done in forming dUdu (see Linear_SD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, ErrStat2, ErrMsg2 ) + + SD_Start = Indx_u_SD_TPMesh_Start(u_SD, y_FAST) ! start of u_SD%MTPMesh%TranslationDisp field + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_SD%TPMesh, MeshMapData%ED_P_2_SD_TP, SD_Start, ED_Out_Start, dUdy, .false.) + + !.......... + ! dU^{SD}/dy^{HD} + !.......... + ! HD + ! parts of dU^{SD}/dy^{HD} and dU^{SD}/dy^{SD}: + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-SubDyn + SD_Out_Start = Indx_y_SD_Y2Mesh_Start(y_SD, y_FAST) ! start of y_SD%Y2Mesh%TranslationDisp field + ! we're just going to assume u_SD%LMesh is committed + if ( HD%y%Morison%Mesh%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! call Linearize_Point_to_Point( HD%y%Morison, u_ED%PlatformPtMesh, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Morison, y_ED%PlatformPtMesh) !HD%Input(1)%Morison and y_ED%PlatformPtMesh contain the displaced positions for load calculations + HD_Out_Start = Indx_y_HD_Morison_Start(HD%y, y_FAST) + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) ! start of u_SD%LMesh%Force field + call Assemble_dUdy_Loads(HD%y%Morison%Mesh, u_SD%LMesh, MeshMapData%HD_M_P_2_SD_P, SD_Start, HD_Out_Start, dUdy) + + ! SD translation displacement-to-SD moment transfer (dU^{SD}/dy^{SD}): + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) + u_SD%LMesh%NNodes*3 ! start of u_SD%LMesh%Moment field (skip the SD forces) + call SetBlockMatrix( dUdy, MeshMapData%HD_M_P_2_SD_P%dM%m_uD, SD_Start, SD_Out_Start ) +! maybe this should be SumBlockMatrix with future changes to linearized modules??? + end if + if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%WAMITMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + HD_Out_Start = Indx_y_HD_WAMIT_Start(HD%y, y_FAST) + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) ! start of u_SD%LMesh%Force field + call Assemble_dUdy_Loads(HD%y%WAMITMesh, u_SD%LMesh, MeshMapData%HD_W_P_2_SD_P, SD_Start, HD_Out_Start, dUdy) + + ! SD translation displacement-to-SD moment transfer (dU^{SD}/dy^{SD}): + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) + u_SD%LMesh%NNodes*3 ! start of u_SD%LMesh%Moment field (skip the SD forces) + call SumBlockMatrix( dUdy, MeshMapData%HD_W_P_2_SD_P%dM%m_uD, SD_Start, SD_Out_Start ) +! maybe this should be SumBlockMatrix with future changes to linearized modules??? + end if + end if + + !.......... + ! dU^{SD}/dy^{MAP} + !.......... + if ( p_FAST%CompMooring == Module_MAP ) then + if ( MAPp%y%ptFairleadLoad%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_SD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_SD%LMesh, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_SD%Y2Mesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%Y2Mesh contain the displaced positions for load calculations + MAP_Out_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) ! start of u_SD%LMesh%TranslationDisp field + call Assemble_dUdy_Loads(MAPp%y%ptFairLeadLoad, u_SD%LMesh, MeshMapData%Mooring_P_2_SD_P, SD_Start, MAP_Out_Start, dUdy) + + ! SD translation displacement-to-SD moment transfer (dU^{SD}/dy^{SD}): + SD_Start = Indx_u_SD_LMesh_Start(u_SD, y_FAST) + u_SD%LMesh%NNodes*3 ! start of u_ED%LMesh%Moment field (skip the SD forces) + SD_Out_Start = Indx_y_SD_Y2Mesh_Start(y_SD, y_FAST) ! start of y_SD%Y2Mesh%TranslationDisp field + call SumBlockMatrix( dUdy, MeshMapData%Mooring_P_2_SD_P%dM%m_uD, SD_Start, SD_Out_Start ) + end if + end if +END SUBROUTINE Linear_SD_InputSolve_dy + !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{BD}/du^{BD} and dU^{BD}/du^{AD} blocks (BD row) of dUdu. (i.e., how do changes in the AD and BD inputs @@ -2356,7 +2650,7 @@ END SUBROUTINE Linear_SrvD_InputSolve_dy !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{ED}/dy^{SrvD}, dU^{ED}/dy^{ED}, dU^{ED}/dy^{BD}, dU^{ED}/dy^{AD}, dU^{ED}/dy^{HD}, and dU^{ED}/dy^{MAP} !! blocks of dUdy. (i.e., how do changes in the SrvD, ED, BD, AD, HD, and MAP outputs effect the ED inputs?) -SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, MAPp, MeshMapData, dUdy, ErrStat, ErrMsg ) +SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, SD, MAPp, MeshMapData, dUdy, ErrStat, ErrMsg ) TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) @@ -2366,6 +2660,7 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, TYPE(AD_InputType), INTENT(INOUT) :: u_AD !< AD inputs (for AD-ED load linerization) TYPE(BeamDyn_Data), INTENT(INOUT) :: BD !< BD data at t TYPE(HydroDyn_Data), INTENT(INOUT) :: HD !< HD data at t + TYPE(SubDyn_Data), INTENT(INOUT) :: SD !< SD data at t TYPE(MAP_Data), INTENT(INOUT) :: MAPp !< MAP data at t TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules @@ -2382,6 +2677,7 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, INTEGER(IntKi) :: ED_Start ! starting index of dUdy (row) where ED input fields are located INTEGER(IntKi) :: ED_Out_Start ! starting index of dUdy (column) where ED output fields are located INTEGER(IntKi) :: HD_Out_Start + INTEGER(IntKi) :: SD_Out_Start INTEGER(IntKi) :: MAP_Out_Start CHARACTER(*), PARAMETER :: RoutineName = 'Linear_ED_InputSolve_dy' @@ -2483,49 +2779,75 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, END IF - ! HD - ! parts of dU^{ED}/dy^{HD} and dU^{ED}/dy^{ED}: - if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + if ( p_FAST%CompSub == Module_None ) then + ! HD + ! parts of dU^{ED}/dy^{HD} and dU^{ED}/dy^{ED}: + if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + ! we're just going to assume u_ED%PlatformPtMesh is committed + if ( HD%y%Morison%Mesh%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! call Linearize_Point_to_Point( HD%y%Morison, u_ED%PlatformPtMesh, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Morison, y_ED%PlatformPtMesh) !HD%Input(1)%Morison and y_ED%PlatformPtMesh contain the displaced positions for load calculations + HD_Out_Start = Indx_y_HD_Morison_Start(HD%y, y_FAST) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%Force field + call Assemble_dUdy_Loads(HD%y%Morison%Mesh, u_ED%PlatformPtMesh, MeshMapData%HD_M_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) + call SumBlockMatrix( dUdy, MeshMapData%HD_M_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) + + end if + if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%WAMITMesh, y_ED%PlatformPtMesh) !HD%Input(1)%WAMITMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + HD_Out_Start = Indx_y_HD_WAMIT_Start(HD%y, y_FAST) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%Force field + call Assemble_dUdy_Loads(HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) + call SumBlockMatrix( dUdy, MeshMapData%HD_W_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) + + end if + - ! we're just going to assume u_ED%PlatformPtMesh is committed - - if ( HD%y%WAMITMesh%Committed ) then ! meshes for floating + end if + + ! MAP + ! parts of dU^{ED}/dy^{MAP} and dU^{ED}/dy^{ED}: + if ( p_FAST%CompMooring == Module_MAP ) then + if ( MAPp%y%ptFairleadLoad%Committed ) then ! meshes for floating !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices !!! ! while forming dUdy, too. - ! call Linearize_Point_to_Point( HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ErrStat2, ErrMsg2, HD%Input(1)%Mesh, y_ED%PlatformPtMesh) !HD%Input(1)%Mesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations - HD_Out_Start = Indx_y_HD_AllHdro_Start(HD%y, y_FAST) - ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%Moment field - call Assemble_dUdy_Loads(HD%y%WAMITMesh, u_ED%PlatformPtMesh, MeshMapData%HD_W_P_2_ED_P, ED_Start, HD_Out_Start, dUdy) - - ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ! CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations + MAP_Out_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Loads(MAPp%y%ptFairLeadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ED_Start, MAP_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call SetBlockMatrix( dUdy, MeshMapData%HD_W_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) -! maybe this should be SumBlockMatrix with future changes to linearized modules??? + call SumBlockMatrix( dUdy, MeshMapData%Mooring_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) end if - - - end if - - ! MAP - ! parts of dU^{ED}/dy^{MAP} and dU^{ED}/dy^{ED}: - if ( p_FAST%CompMooring == Module_MAP ) then - if ( MAPp%y%ptFairleadLoad%Committed ) then ! meshes for floating - !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices - !!! ! while forming dUdy, too. - ! CALL Linearize_Point_to_Point( MAPp%y%ptFairleadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ErrStat2, ErrMsg2, MAPp%Input(1)%PtFairDisplacement, y_ED%PlatformPtMesh) !MAPp%Input(1)%ptFairleadLoad and y_ED%PlatformPtMesh contain the displaced positions for load calculations - MAP_Out_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) - ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Loads(MAPp%y%ptFairLeadLoad, u_ED%PlatformPtMesh, MeshMapData%Mooring_P_2_ED_P, ED_Start, MAP_Out_Start, dUdy) - - ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): - ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call SumBlockMatrix( dUdy, MeshMapData%Mooring_P_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) - end if + end if + else if ( p_FAST%CompSub == Module_SD ) then + ! SubDyn + ! parts of dU^{ED}/dy^{SD} and dU^{ED}/dy^{ED}: !TODO: Does this actually include terms for dU^{ED}/dy^{ED}??? + !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + ! CALL Linearize_Point_to_Point( SD%y%Y1Mesh, u_ED%PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, SD%Input(1)%TPMesh, y_ED%PlatformPtMesh) !SD%Input(1)%TPMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations + SD_Out_Start = y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) ! start of u_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Loads(SD%y%Y1Mesh, u_ED%PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ED_Start, SD_Out_Start, dUdy) + + ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}): + ED_Start = Indx_u_ED_Platform_Start(u_ED, y_FAST) + u_ED%PlatformPtMesh%NNodes*3 ! start of u_ED%PlatformPtMesh%Moment field (skip the ED forces) + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call SetBlockMatrix( dUdy, MeshMapData%SD_TP_2_ED_P%dM%m_uD, ED_Start, ED_Out_Start ) end if - END SUBROUTINE Linear_ED_InputSolve_dy !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{BD}/dy^{ED}, dU^{BD}/dy^{BD}, and dU^{BD}/dy^{AD} blocks of dUdy. (i.e., how do @@ -2818,13 +3140,14 @@ END SUBROUTINE Linear_AD_InputSolve_NoIfW_dy !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{HD}/du^{HD} blocks of dUdu. -SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUdu, ErrStat, ErrMsg ) +SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapData, dUdu, ErrStat, ErrMsg ) ! Passed variables TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< The inputs to HydroDyn - TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the ElastoDyn structural dynamics module + TYPE(SD_OutputType), INTENT(IN) :: y_SD !< The outputs from the SubDyn structural dynamics module TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules REAL(R8Ki), INTENT(INOUT) :: dUdu(:,:) !< Jacobian matrix of which we are computing the dU^{HD}/du^{HD} block @@ -2845,6 +3168,7 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine ! We need to make six calls to SetBlockMatrix for the different output to input mappings + ! LIN-TODO: Are this row and col still valid GJH 7/31/2020 ! 1) Row 3, Col 1 ! 2) Row 5, Col 1 ! 3) Row 9, Col 7 @@ -2857,62 +3181,144 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd ! Set the inputs from ElastoDyn: !------------------------------------------------------------------------------------------------- - !.......... + !.......... ! dU^{HD}/du^{HD} ! note that the 1s on the diagonal have already been set, so we will fill in the off diagonal terms. !.......... if ( p_FAST%CompHydro == Module_HD ) then ! HydroDyn-{ElastoDyn or SubDyn} - + !=================================================== - ! y_ED%PlatformPtMesh and u_HD%Morison%Mesh - !=================================================== -!TODO-LIN: Check for new Morison GJH 4/23/20 NOw could depend on SD, right? GJH 5/11/2020 + ! y_ED%PlatformPtMesh and u_HD%PRPMesh ! this is always done with ED, even if using SD + !=================================================== - ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): - - call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): + if ( u_HD%PRPMesh%Committed ) then + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} - HD_Start_td = y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) - HD_Start_tr = HD_Start_td + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + HD_Start_td = Indx_u_HD_PRP_Start(u_HD, y_FAST) + HD_Start_tr = HD_Start_td + u_HD%PRPMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field ! translational velocity: - if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%tv_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + if (allocated(MeshMapData%ED_P_2_HD_PRP_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_PRP_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) end if ! translational acceleration: - HD_Start_tr = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) - if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + HD_Start_tr = HD_Start_tr + u_HD%PRPMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%ED_P_2_HD_PRP_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_PRP_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + end if + + if ( p_FAST%CompSub == Module_None ) then + + !=================================================== + ! y_ED%PlatformPtMesh and u_HD%Morison%Mesh + !=================================================== + + ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): + if ( u_HD%Morison%Mesh%Committed ) then + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + + HD_Start_td = Indx_u_HD_Morison_Start(u_HD, y_FAST) + HD_Start_tr = HD_Start_td + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + !LIN-TODO: Handle case where Morison is not allocated + HD_Start_tr = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if end if - !=================================================== ! y_ED%PlatformPtMesh and u_HD%WAMITMesh - !=================================================== -!TODO-LIN: Check for new Morison+WAMIT GJH 4/23/20 -! Should this potentially be between SD and HD for some cases? - call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + !=================================================== + if ( u_HD%WAMITMesh%Committed ) then - HD_Start_td = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 field ( TranslationalAcc and RotationAcc) - HD_Start_tr = HD_Start_td + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field - ! translational velocity: - if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%tv_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) - end if + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + HD_Start_td = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) + HD_Start_tr = HD_Start_td + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + ! translational velocity: + if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if - ! translational acceleration: - HD_Start_tr = HD_Start_tr + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) - if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%ta_uD )) then - call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + if (allocated(MeshMapData%ED_P_2_HD_W_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + end if + + + else if ( p_FAST%CompSub == Module_SD ) then + + + !=================================================== + ! y_SD%Y2Mesh and u_HD%Morison%Mesh + !=================================================== + if ( u_HD%Morison%Mesh%Committed ) then + ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): + + call Linearize_Point_to_Point( y_SD%Y2Mesh, u_HD%Morison%Mesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} + + HD_Start_td = Indx_u_HD_Morison_Start(u_HD, y_FAST) + HD_Start_tr = HD_Start_td + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + + ! translational velocity: + if (allocated(MeshMapData%SD_P_2_HD_M_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%SD_P_2_HD_M_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + if (allocated(MeshMapData%SD_P_2_HD_M_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%SD_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if end if + + !=================================================== + ! y_SD%Y2Mesh and u_HD%WAMITMesh + !=================================================== + if ( u_HD%WAMITMesh%Committed ) then + call Linearize_Point_to_Point( y_SD%Y2Mesh, u_HD%WAMITMesh, MeshMapData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + HD_Start_td = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) + HD_Start_tr = HD_Start_td + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field + ! translational velocity: + if (allocated(MeshMapData%SD_P_2_HD_W_P%dM%tv_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%SD_P_2_HD_W_P%dM%tv_ud, HD_Start_tr, HD_Start_td ) + end if + + ! translational acceleration: + HD_Start_tr = HD_Start_tr + u_HD%WAMITMesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) + + if (allocated(MeshMapData%SD_P_2_HD_W_P%dM%ta_uD )) then + call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_W_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) + end if + end if + + end if + end if @@ -2920,13 +3326,14 @@ END SUBROUTINE Linear_HD_InputSolve_du !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{HD}/dy^{ED} block of dUdy. (i.e., how do changes in the ED outputs affect !! the HD inputs?) -SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) +SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapData, dUdy, ErrStat, ErrMsg ) ! Passed variables TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_InputType), INTENT(INOUT) :: u_HD !< The inputs to HydroDyn - TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the ElastoDyn structural dynamics module + TYPE(SD_OutputType), INTENT(IN) :: y_SD !< The outputs from the SubDyn structural dynamics module TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{HD}/dy^{ED} block @@ -2937,55 +3344,89 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, MeshMapData, dUd INTEGER(IntKi) :: HD_Start ! starting index of dUdy (column) where particular HD fields are located INTEGER(IntKi) :: ED_Out_Start! starting index of dUdy (row) where particular ED fields are located + INTEGER(IntKi) :: SD_Out_Start! starting index of dUdy (row) where particular SD fields are located CHARACTER(*), PARAMETER :: RoutineName = 'Linear_HD_InputSolve_dy' ErrStat = ErrID_None ErrMsg = "" - - !................................... - ! Morison Mesh - !................................... - IF (u_HD%Morison%Mesh%Committed) THEN + if ( p_FAST%CompSub == Module_None ) then + ! dU^{HD}/dy^{ED} + !................................... + ! Morison Mesh + !................................... + IF (u_HD%Morison%Mesh%Committed) THEN - !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices - !!! ! while forming dUdy, too. - !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy, .false.) - END IF + HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy, .false.) + END IF - !................................... - ! Lumped Platform Reference Pt Mesh - !................................... - IF (u_HD%WAMITMesh%Committed) THEN + !................................... + ! Lumped Platform Reference Pt Mesh + !................................... + IF (u_HD%WAMITMesh%Committed) THEN - !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices - !!! ! while forming dUdy, too. - !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) - HD_Start = Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field + HD_Start = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy, .false.) - END IF + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy, .false.) + END IF + + else if ( p_FAST%CompSub == Module_SD ) then + ! dU^{HD}/dy^{SD} + SD_Out_Start = Indx_y_SD_Y2Mesh_Start(y_SD, y_FAST) ! start of y_SD%Y2Mesh%TranslationDisp field + !................................... + ! Morison Mesh + !................................... + IF (u_HD%Morison%Mesh%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Line2( y_SD%Y2Mesh, u_HD%Morison%Mesh, MeshMapData%SD_P_2_HD_M_P, ErrStat2, ErrMsg2 ) + + HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field + call Assemble_dUdy_Motions(y_SD%Y2Mesh, u_HD%Morison%Mesh, MeshMapData%SD_P_2_HD_M_P, HD_Start, SD_Out_Start, dUdy, .false.) + END IF + !................................... + ! Lumped Platform Reference Pt Mesh + !................................... + IF (u_HD%WAMITMesh%Committed) THEN + + !!! ! This linearization was done in forming dUdu (see Linear_HD_InputSolve_du()), so we don't need to re-calculate these matrices + !!! ! while forming dUdy, too. + !!!call Linearize_Point_to_Point( y_SD%Y2Mesh, u_HD%Mesh, MeshMapData%SD_P_2_HD_W_P, ErrStat2, ErrMsg2 ) + + HD_Start = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field + call Assemble_dUdy_Motions(y_SD%Y2Mesh, u_HD%WAMITMesh, MeshMapData%SD_P_2_HD_W_P, HD_Start, SD_Out_Start, dUdy, .false.) + END IF + + end if + END SUBROUTINE Linear_HD_InputSolve_dy !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{MAP}/dy^{ED} block of dUdy. (i.e., how do changes in the ED outputs affect !! the MAP inputs?) -SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) +SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, y_SD, MeshMapData, dUdy, ErrStat, ErrMsg ) ! Passed variables TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(MAP_InputType), INTENT(INOUT) :: u_MAP !< The inputs to MAP - TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module + TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the ElastoDyn structural dynamics module + TYPE(SD_OutputType), INTENT(IN) :: y_SD !< The outputs from the SubDyn structural dynamics module TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{MAP}/dy^{ED} block @@ -2996,6 +3437,7 @@ SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, d INTEGER(IntKi) :: MAP_Start ! starting index of dUdy (column) where particular MAP fields are located INTEGER(IntKi) :: ED_Out_Start! starting index of dUdy (row) where particular ED fields are located + INTEGER(IntKi) :: SD_Out_Start! starting index of dUdy (row) where particular SD fields are located INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'Linear_MAP_InputSolve_dy' @@ -3003,22 +3445,28 @@ SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, d ErrStat = ErrID_None ErrMsg = "" - - - !................................... - ! FairLead Mesh - !................................... - IF (u_MAP%PtFairDisplacement%Committed) THEN + IF (u_MAP%PtFairDisplacement%Committed) THEN + !................................... + ! FairLead Mesh + !................................... + MAP_Start = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field - - call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, MAP_Start, ED_Out_Start, dUdy, OnlyTranslationDisp=.true.) + if ( p_FAST%CompSub == Module_SD ) THEN + ! dU^{MAP}/dy^{SD} + SD_Out_Start = Indx_y_SD_Y2Mesh_Start(y_SD, y_FAST) ! start of y_SD%Y2Mesh%TranslationDisp field + call Linearize_Point_to_Point( y_SD%Y2Mesh, u_MAP%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + call Assemble_dUdy_Motions(y_SD%Y2Mesh , u_MAP%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, MAP_Start, SD_Out_Start, dUdy, OnlyTranslationDisp=.true.) + + else if ( p_FAST%CompSub == Module_None ) THEN + ! dU^{MAP}/dy^{ED} + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, MAP_Start, ED_Out_Start, dUdy, OnlyTranslationDisp=.true.) + end if END IF - END SUBROUTINE Linear_MAP_InputSolve_dy ! LIN-TODO: Clean up if not used. @@ -3962,6 +4410,29 @@ FUNCTION Indx_u_AD_BladeInflow_Start(u_AD, y_FAST) RESULT(AD_Start) END FUNCTION Indx_u_AD_BladeInflow_Start !---------------------------------------------------------------------------------------------------------------------------------- + +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_SD%TPMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_SD_TPMesh_Start(u_SD, y_FAST) RESULT(SD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(SD_InputType), INTENT(IN ) :: u_SD !< SD Inputs at t + + INTEGER :: SD_Start !< starting index of this mesh in SubDyn inputs + + SD_Start = y_FAST%Lin%Modules(Module_SD)%Instance(1)%LinStartIndx(LIN_INPUT_COL) + +END FUNCTION Indx_u_SD_TPMesh_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_SD%TPMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_SD_LMesh_Start(u_SD, y_FAST) RESULT(SD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(SD_InputType), INTENT(IN ) :: u_SD !< SD Inputs at t + + INTEGER :: SD_Start !< starting index of this mesh in SubDyn inputs + + SD_Start = Indx_u_SD_TPMesh_Start(u_SD, y_FAST) + u_SD%TPMesh%NNodes**18 ! 6 fields with 3 components + +END FUNCTION Indx_u_SD_LMesh_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the u_HD%Morison%Mesh mesh in the FAST linearization inputs. FUNCTION Indx_u_HD_Morison_Start(u_HD, y_FAST) RESULT(HD_Start) @@ -3975,7 +4446,7 @@ FUNCTION Indx_u_HD_Morison_Start(u_HD, y_FAST) RESULT(HD_Start) END FUNCTION Indx_u_HD_Morison_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the u_HD%WAMITMesh mesh in the FAST linearization inputs. -FUNCTION Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) RESULT(HD_Start) +FUNCTION Indx_u_HD_WAMIT_Start(u_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t @@ -3984,7 +4455,19 @@ FUNCTION Indx_u_HD_PlatformRef_Start(u_HD, y_FAST) RESULT(HD_Start) HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) if (u_HD%Morison%Mesh%committed) HD_Start = HD_Start + u_HD%Morison%Mesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components - END FUNCTION Indx_u_HD_PlatformRef_Start +END FUNCTION Indx_u_HD_WAMIT_Start +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the u_HD%PRPMesh mesh in the FAST linearization inputs. +FUNCTION Indx_u_HD_PRP_Start(u_HD, y_FAST) RESULT(HD_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(HydroDyn_InputType), INTENT(IN ) :: u_HD !< HD Inputs at t + + INTEGER :: HD_Start !< starting index of this mesh in HydroDyn inputs + + HD_Start = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) + if (u_HD%WAMITMesh%committed) HD_Start = HD_Start + u_HD%WAMITMesh%NNodes * 18 ! 6 fields (MASKID_TRANSLATIONDISP,MASKID_Orientation,MASKID_TRANSLATIONVel,MASKID_ROTATIONVel,MASKID_TRANSLATIONAcc,MASKID_ROTATIONAcc) with 3 components + + END FUNCTION Indx_u_HD_PRP_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the y_HD%Morison%DistribMesh mesh in the FAST linearization outputs. FUNCTION Indx_y_HD_Morison_Start(y_HD, y_FAST) RESULT(HD_Start) @@ -3998,7 +4481,7 @@ FUNCTION Indx_y_HD_Morison_Start(y_HD, y_FAST) RESULT(HD_Start) END FUNCTION Indx_y_HD_Morison_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This routine returns the starting index for the y_HD%Mesh mesh in the FAST linearization outputs. -FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) +FUNCTION Indx_y_HD_WAMIT_Start(y_HD, y_FAST) RESULT(HD_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t @@ -4009,22 +4492,26 @@ FUNCTION Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) RESULT(HD_Start) HD_Start = Indx_y_HD_Morison_Start(y_HD, y_FAST) if (y_HD%Morison%Mesh%committed) HD_Start = HD_Start + y_HD%Morison%Mesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components - END FUNCTION Indx_y_HD_PlatformRef_Start + END FUNCTION Indx_y_HD_WAMIT_Start !---------------------------------------------------------------------------------------------------------------------------------- -!> This routine returns the starting index for the y_HD%WAMITMesh mesh in the FAST linearization outputs. -FUNCTION Indx_y_HD_AllHdro_Start(y_HD, y_FAST) RESULT(HD_Start) +!> This routine returns the starting index for the y_SD%Y1Mesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_SD_Y1Mesh_Start(y_SD, y_FAST) RESULT(SD_Out_Start) TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) - TYPE(HydroDyn_OutputType), INTENT(IN ) :: y_HD !< HD Outputs at t + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SD outputs at t - INTEGER :: HD_Start - - !< starting index of this mesh in HydroDyn Outputs + INTEGER :: SD_Out_Start !< starting index of this mesh in ElastoDyn outputs - HD_Start = Indx_y_HD_PlatformRef_Start(y_HD, y_FAST) - if (y_HD%WAMITMesh%committed) HD_Start = HD_Start + y_HD%WAMITMesh%NNodes * 6 ! 2 fields (MASKID_FORCE,MASKID_MOMENT) with 3 components + SD_Out_Start = y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%LinStartIndx(LIN_OUTPUT_COL) +END FUNCTION Indx_y_SD_Y1Mesh_Start!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine returns the starting index for the y_SD%Y2Mesh mesh in the FAST linearization outputs. +FUNCTION Indx_y_SD_Y2Mesh_Start(y_SD, y_FAST) RESULT(SD_Out_Start) + TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) + TYPE(SD_OutputType), INTENT(IN ) :: y_SD !< SD outputs at t -END FUNCTION Indx_y_HD_AllHdro_Start + INTEGER :: SD_Out_Start !< starting index of this mesh in ElastoDyn outputs + SD_Out_Start = Indx_y_SD_Y1Mesh_Start(y_SD, y_FAST) + y_SD%Y1Mesh%NNodes * 6 ! 3 forces + 3 moments at each node! skip all of the Y1Mesh data and get to the beginning of +END FUNCTION Indx_y_SD_Y2Mesh_Start !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine allocates the arrays that store the operating point at each linearization time for later producing VTK @@ -4616,7 +5103,7 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, end if END IF - + !LIN-TODO: Do we need this for SD and Map? GJH !!!! SubDyn: copy final predictions to actual states !!!IF ( p_FAST%CompSub == Module_SD ) THEN !!!ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN From 17a4c2efe46cdfa1fd514bb1bfc3e031b2fd649d Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 3 Aug 2020 15:19:53 -0600 Subject: [PATCH 254/377] AD UserProp linearization --- modules/aerodyn/src/AeroDyn.f90 | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 6e1948298..ab3ed906c 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -3366,7 +3366,15 @@ SUBROUTINE AD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, index = index + 1 end do end do + + do k=1,p%NumBlades + do j = 1, size(u%UserProp,1) ! Number of nodes for a blade + u_op(index) = u%UserProp(j,k) + index = index + 1 + end do + end do + END IF IF ( PRESENT( y_op ) ) THEN @@ -3585,7 +3593,8 @@ SUBROUTINE Init_Jacobian( InputFileData, p, u, y, m, InitOut, ErrStat, ErrMsg) nu = u%TowerMotion%NNodes * 9 & ! 3 Translation Displacements + 3 orientations + 3 Translation velocities at each node + u%hubMotion%NNodes * 9 & ! 3 Translation Displacements + 3 orientations + 3 Rotation velocities at each node + size( u%InflowOnBlade) & - + size( u%InflowOnTower) + + size( u%InflowOnTower) & + + size( u%UserProp) do i=1,p%NumBlades nu = nu + u%BladeMotion(i)%NNodes * 9 & ! 3 Translation Displacements + 3 orientations + 3 Translation velocities at each node @@ -3705,7 +3714,16 @@ SUBROUTINE Init_Jacobian( InputFileData, p, u, y, m, InitOut, ErrStat, ErrMsg) end do !j end do !i + !Module/Mesh/Field: u%UserProp(:,:) = 23,24,25; + do k=1,size(u%UserProp,2) ! p%NumBlades + do i=1,size(u%UserProp,1) ! numNodes + p%Jac_u_indx(index,1) = 22 + k + p%Jac_u_indx(index,2) = 1 !component index: this is a scalar, so 1, but is never used + p%Jac_u_indx(index,3) = i !Node: i + index = index + 1 + end do !i + end do !k !...................................... ! default perturbations, p%du: !...................................... @@ -3742,8 +3760,9 @@ SUBROUTINE Init_Jacobian( InputFileData, p, u, y, m, InitOut, ErrStat, ErrMsg) p%du(18 + k) = perturb_b(k) ! u%InflowOnBlade(:,:,k) = 18 + k end do p%du(22) = perturb_t ! u%InflowOnTower(:,:) = 22 - - + do k=1,p%NumBlades + p%du(22+k) = perturb ! u%UserProp(:,:) = 23,24,25 + end do !..................... ! get names of linearized inputs !..................... @@ -3895,7 +3914,12 @@ SUBROUTINE Perturb_u( p, n, perturb_sign, u, du ) CASE (22) !Module/Mesh/Field: u%InflowOnTower(:,:) = 22; u%InflowOnTower(fieldIndx,node) = u%InflowOnTower(fieldIndx,node) + du * perturb_sign - + CASE (23) !Module/Mesh/Field: u%UserProp(:,1) = 23; + u%UserProp(node,1) = u%UserProp(node,1) + du * perturb_sign + CASE (24) !Module/Mesh/Field: u%UserProp(:,2) = 23; + u%UserProp(node,2) = u%UserProp(node,2) + du * perturb_sign + CASE (25) !Module/Mesh/Field: u%UserProp(:,3) = 23; + u%UserProp(node,3) = u%UserProp(node,3) + du * perturb_sign END SELECT END SUBROUTINE Perturb_u From 156af49ffb3c89526dcac0abf36331265fb6c7a0 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 5 Aug 2020 09:37:41 -0600 Subject: [PATCH 255/377] Needed to update continuous states to R8Ki to match linearization code --- modules/subdyn/src/SubDyn_Registry.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 20967fcd7..540726a3f 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -127,8 +127,8 @@ typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" # ============================== States ============================================================================================================================================ # Define continuous (differentiable) states here: -typedef ^ ContinuousStateType ReKi qm {:} - - "Virtual states, Nmod elements" -typedef ^ ContinuousStateType ReKi qmdot {:} - - "Derivative of states, Nmod elements" +typedef ^ ContinuousStateType R8Ki qm {:} - - "Virtual states, Nmod elements" +typedef ^ ContinuousStateType R8Ki qmdot {:} - - "Derivative of states, Nmod elements" # Define discrete (nondifferentiable) states here: typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" # Define constraint states here: From fd0d4172bd205f00ea23aca1141f4dfbbf4403b9 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 5 Aug 2020 09:40:51 -0600 Subject: [PATCH 256/377] Updated linearization for AD UserProp and other Lin fixes --- modules/aerodyn/src/AeroDyn.f90 | 3 +- modules/openfast-library/src/FAST_Lin.f90 | 369 ++++++++---------- .../openfast-library/src/FAST_Registry.txt | 2 + modules/openfast-library/src/FAST_Subs.f90 | 4 +- 4 files changed, 167 insertions(+), 211 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index ab3ed906c..665ae7f13 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -871,7 +871,8 @@ subroutine SetParameters( InitInp, InputFileData, p, ErrStat, ErrMsg ) end if - ! p%numBlades = InitInp%numBlades ! this was set earlier because it was necessary + ! NOTE: In the following we use InputFileData%BladeProps(1)%NumBlNds as the number of aero nodes on EACH blade, + ! but if AD changes this, then it must be handled in the Glue-code linearization code, too (and elsewhere?) ! p%NumBlNds = InputFileData%BladeProps(1)%NumBlNds if (p%TwrPotent == TwrPotent_none .and. .not. p%TwrShadow .and. .not. p%TwrAero) then p%NumTwrNds = 0 diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 5c8f6dae8..ca1673b9b 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -30,14 +30,15 @@ MODULE FAST_Linear !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ !---------------------------------------------------------------------------------------------------------------------------------- !> Routine that initializes some variables for linearization. -SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) +SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, NumBlNodes, ErrStat, ErrMsg) TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST !< Miscellaneous variables TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data TYPE(ElastoDyn_Data), INTENT(IN ) :: ED !< ElastoDyn data - INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED input array) + INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED,AD input array) + INTEGER(IntKi), INTENT(IN ) :: NumBlNodes !< Number of blade nodes (for index into AD input array) INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -103,12 +104,7 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_HD end if - ! MAP is next, if activated: - if ( p_FAST%CompMooring == Module_MAP ) then - p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 - p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_MAP - end if - + ! SD or ExtPtfm is next, if activated: if ( p_FAST%CompSub == Module_SD ) then p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 @@ -117,6 +113,13 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_ExtPtfm end if + + ! MAP is next, if activated: + if ( p_FAST%CompMooring == Module_MAP ) then + p_FAST%Lin_NumMods = p_FAST%Lin_NumMods + 1 + p_FAST%Lin_ModOrder( p_FAST%Lin_NumMods ) = Module_MAP + end if + !..................... ! determine total number of inputs/outputs/contStates: @@ -156,7 +159,7 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, ErrStat, ErrMsg) ! ................................... ! determine which of the module inputs/outputs are written to file ! ................................... - call Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat2, ErrMsg2) + call Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, NumBlNodes, ErrStat2, ErrMsg2) call SetErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ! ................................... @@ -422,11 +425,12 @@ SUBROUTINE Init_Lin_IfW( p_FAST, y_FAST, u_AD ) END SUBROUTINE Init_Lin_IfW !---------------------------------------------------------------------------------------------------------------------------------- !> Routine that initializes some use_u and use_y, which determine which, if any, inputs and outputs are output in the linearization file. -SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) +SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, NumBlNodes, ErrStat, ErrMsg) TYPE(FAST_ParameterType), INTENT(INOUT) :: p_FAST !< Parameters for the glue code TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code - INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED input array) + INTEGER(IntKi), INTENT(IN ) :: NumBl !< Number of blades (for index into ED,AD input array) + INTEGER(IntKi), INTENT(IN ) :: NumBlNodes !< Number of blades nodes (for index into AD input array) INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -479,6 +483,12 @@ SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) end do end do + ! AD standard inputs: UserProp(NumBlNodes,NumBl) + ! LIN-TODO Add these Userprop values + do j=1,NumBl*NumBlNodes + y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + ! ED standard inputs: BlPitchCom, YawMom, GenTrq, extended input (collective pitch) do j=1,NumBl+3 y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. @@ -496,17 +506,7 @@ SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, ErrStat, ErrMsg) y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%SizeLin(LIN_INPUT_COL)) = .true. end if - if (p_FAST%CompSub == MODULE_SD) then - do j = 1,18 ! TODO TODO TODO - y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_SD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. - end do - else if (p_FAST%CompSub == MODULE_ExtPtfm) then - !bjj: removed because I'm not sure these should be included in the "standard" inputs - !!!! ExtPtfm standard inputs: x1, x1dot x1ddot ! TODO TODO TODO CHECK - !!! do j = 1,18 - !!! y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ExtPtfm)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. - !!! end do - end if + ! SD has no standard inputs elseif(p_FAST%LinInputs == LIN_ALL) then do i = 1,p_FAST%Lin_NumMods @@ -942,33 +942,96 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, #endif end if + + !..................... - ! ExtPtfm + ! HydroDyn + !..................... + if ( p_FAST%CompHydro == Module_HD ) then + ! get the jacobians + call HD_JacobianPInput( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%B ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + call HD_JacobianPContState( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, dYdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%A ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + + ! get the operating point + call HD_GetOP( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & + HD%y, HD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_u, y_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_y, & + x_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_dx ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + + + ! write the module matrices: + if (p_FAST%LinOutMod) then + + OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_HD)) + call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >=AbortErrLev) then + call cleanup() + return + end if + + if (p_FAST%LinOutJac) then + ! Jacobians + !dXdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx' ) + + !dXdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) + + ! dYdx: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y ) + + !dYdu: + call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y, & + UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) + + end if + + ! finish writing the file + call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1) ) + + end if + end if + + !LIN-TODO: Review SubDyn!!!! !..................... + ! SubDyn / ExtPtfm + !..................... + if ( p_FAST%CompSub == Module_SD ) then ! get the jacobians call SD_JacobianPInput( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, & dYdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%B ) - if(Failed()) return; + !if(Failed()) return; call SD_JacobianPContState( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2,& dYdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%A ) - if(Failed()) return; + !if(Failed()) return; ! get the operating point call SD_GetOP(t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR),& SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_u,& y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y, & x_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_dx) - if(Failed()) return; + !if(Failed()) return; ! write the module matrices: if (p_FAST%LinOutMod) then OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SD)) call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - if(Failed()) return; + !if(Failed()) return; if (p_FAST%LinOutJac) then ! Jacobians @@ -986,25 +1049,25 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & dYdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B ) - if(Failed()) return; + !if(Failed()) return; call ExtPtfm_JacobianPContState( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2,& dYdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A ) - if(Failed()) return; + !if(Failed()) return; ! get the operating point call ExtPtfm_GetOP(t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR),& ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_u,& y_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_y, & x_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_dx) - if(Failed()) return; + !if(Failed()) return; ! write the module matrices: if (p_FAST%LinOutMod) then OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_ExtPtfm)) call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - if(Failed()) return; + !if(Failed()) return; if (p_FAST%LinOutJac) then ! Jacobians @@ -1017,64 +1080,9 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, ! finish writing the file call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1) ) end if - end if ! ExtPtfm + end if ! SubDyn/ExtPtfm - !..................... - ! HydroDyn - !..................... - if ( p_FAST%CompHydro == Module_HD ) then - ! get the jacobians - call HD_JacobianPInput( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & - HD%y, HD%m, ErrStat2, ErrMsg2, dYdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_HD)%Instance(1)%B ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - call HD_JacobianPContState( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & - HD%y, HD%m, ErrStat2, ErrMsg2, dYdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_HD)%Instance(1)%A ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! get the operating point - call HD_GetOP( t_global, HD%Input(1), HD%p, HD%x(STATE_CURR), HD%xd(STATE_CURR), HD%z(STATE_CURR), HD%OtherSt(STATE_CURR), & - HD%y, HD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_u, y_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_y, & - x_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_HD)%Instance(1)%op_dx ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat >=AbortErrLev) then - call cleanup() - return - end if - - ! write the module matrices: - if (p_FAST%LinOutMod) then - - OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_HD)) - call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat >=AbortErrLev) then - call cleanup() - return - end if - - if (p_FAST%LinOutJac) then - ! Jacobians - !dXdx: - call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx' ) - - !dXdu: - call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) - - ! dYdx: - call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y ) - - !dYdu: - call WrPartialMatrix( y_FAST%Lin%Modules(Module_HD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_y, & - UseCol=y_FAST%Lin%Modules(Module_HD)%Instance(1)%use_u ) - - end if - - ! finish writing the file - call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_HD)%Instance(1) ) - - end if ! LIN-TODO: Check if this is really where we want to terminate the if block - end if !..................... ! MAP !..................... @@ -1084,8 +1092,9 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, MAPp%OtherSt, MAPp%y, ErrStat2, ErrMsg2, y_FAST%Lin%Modules(Module_MAP)%Instance(1)%D ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ! et the operating point + ! get the operating point !LIN-TODO: template uses OtherSt(STATE_CURR), but the FAST MAP DATA has OtherSt as a scalar + ! email bonnie for a discussion on this. call MAP_GetOP( t_global, MAPp%Input(1), MAPp%p, MAPp%x(STATE_CURR), MAPp%xd(STATE_CURR), MAPp%z(STATE_CURR), & MAPp%OtherSt, MAPp%y, ErrStat2, ErrMsg2, & y_FAST%Lin%Modules(Module_MAP)%Instance(1)%op_u, y_FAST%Lin%Modules(Module_MAP)%Instance(1)%op_y ) @@ -1713,7 +1722,7 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, !! 0 & 0 & 0 & 0 & \frac{\partial U_\Lambda^{AD}}{\partial u^{AD}} \\ !! \end{bmatrix} \f$ !..................................... -! LIN-TODO: Add doc strings for new modules: HD & MAP +! LIN-TODO: Add doc strings for new modules: HD & MAP & SD if (.not. allocated(dUdu)) then call AllocAry(dUdu, y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), y_FAST%Lin%Glue%SizeLin(LIN_INPUT_COL), 'dUdu', ErrStat2, ErrMsg2) @@ -1899,6 +1908,14 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if + !LIN-TODO: Add doc strings and look at above doc string + IF (p_FAST%CompSub == Module_SD) THEN + call Linear_SD_InputSolve_dy( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN + write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO' + ENDIF + !............ ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{ED}} \end{bmatrix} = \f$ ! \f$ \frac{\partial U_\Lambda^{MAP}}{\partial y^{SD}} \end{bmatrix} = \f$ (dUdy block row 8=MAP) @@ -1908,12 +1925,7 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if - IF (p_FAST%CompSub == Module_SD) THEN - call Linear_SD_InputSolve_dy( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN - write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO' - ENDIF + END SUBROUTINE Glue_Jacobians !---------------------------------------------------------------------------------------------------------------------------------- @@ -1979,7 +1991,7 @@ END SUBROUTINE Linear_IfW_InputSolve_du_AD !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{ED}/du^{BD} and dU^{ED}/du^{AD} blocks (ED row) of dUdu. (i.e., how do changes in the AD and BD inputs affect the ED inputs?) SUBROUTINE Linear_ED_InputSolve_du( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, HD, SD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) -!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) TYPE(ED_InputType), INTENT(INOUT) :: u_ED !< ED Inputs at t @@ -2178,7 +2190,7 @@ END SUBROUTINE Linear_ED_InputSolve_du !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{SD}/du^{HD} and dU^{SD}/du^{SD} and dU^{SD}/du^{MAP} blocks (SD row) of dUdu. (i.e., how do changes in the HD and SD inputs affect the SD inputs?) SUBROUTINE Linear_SD_InputSolve_du( p_FAST, y_FAST, u_SD, y_SD, y_ED, HD, MAPp, MeshMapData, dUdu, ErrStat, ErrMsg ) -!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) TYPE(SD_InputType), INTENT(INOUT) :: u_SD !< SD Inputs at t @@ -2310,7 +2322,7 @@ END SUBROUTINE Linear_SD_InputSolve_du !---------------------------------------------------------------------------------------------------------------------------------- !> This routine forms the dU^{SD}/du^{HD} and dU^{SD}/du^{SD} blocks (SD row) of dUdu. (i.e., how do changes in the HD and SD inputs affect the SD inputs?) SUBROUTINE Linear_SD_InputSolve_dy( p_FAST, y_FAST, u_SD, y_SD, y_ED, HD, MAPp, MeshMapData, dUdy, ErrStat, ErrMsg ) -!LIN-TODO: Augment this interface for HD and MAP + TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Glue-code simulation parameters TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< Glue-code output parameters (for linearization) TYPE(SD_InputType), INTENT(INOUT) :: u_SD !< SD Inputs at t @@ -2336,7 +2348,7 @@ SUBROUTINE Linear_SD_InputSolve_dy( p_FAST, y_FAST, u_SD, y_SD, y_ED, HD, MAPp, ErrStat = ErrID_None ErrMsg = "" - if ( p_FAST%CompSub /= Module_SD ) return !LIN-TODO: Verify that it is ok to simply return. What is dUdy in that case + if ( p_FAST%CompSub /= Module_SD ) return !.......... ! dU^{SD}/dy^{ED} @@ -2835,7 +2847,7 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, end if else if ( p_FAST%CompSub == Module_SD ) then ! SubDyn - ! parts of dU^{ED}/dy^{SD} and dU^{ED}/dy^{ED}: !TODO: Does this actually include terms for dU^{ED}/dy^{ED}??? + ! parts of dU^{ED}/dy^{SD} and dU^{ED}/dy^{ED}: !!! ! This linearization was done in forming dUdu (see Linear_ED_InputSolve_du()), so we don't need to re-calculate these matrices !!! ! while forming dUdy, too. ! CALL Linearize_Point_to_Point( SD%y%Y1Mesh, u_ED%PlatformPtMesh, MeshMapData%SD_TP_2_ED_P, ErrStat2, ErrMsg2, SD%Input(1)%TPMesh, y_ED%PlatformPtMesh) !SD%Input(1)%TPMesh and y_ED%PlatformPtMesh contain the displaced positions for load calculations @@ -3236,7 +3248,6 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapDat end if ! translational acceleration: - !LIN-TODO: Handle case where Morison is not allocated HD_Start_tr = HD_Start_tr + u_HD%Morison%Mesh%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) if (allocated(MeshMapData%ED_P_2_HD_M_P%dM%ta_uD )) then call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_HD_M_P%dM%ta_ud, HD_Start_tr, HD_Start_td ) @@ -3467,84 +3478,7 @@ SUBROUTINE Linear_MAP_InputSolve_dy( p_FAST, y_FAST, u_MAP, y_ED, y_SD, MeshMapD end if END IF -END SUBROUTINE Linear_MAP_InputSolve_dy - -! LIN-TODO: Clean up if not used. -!!---------------------------------------------------------------------------------------------------------------------------------- -!!> This routine forms the dU^{MAP}/dy^{ED} blocks of dUdu. -!SUBROUTINE Linear_MAP_InputSolve_du( p_FAST, y_FAST, u_MAP, y_ED, MeshMapData, dUdy, ErrStat, ErrMsg ) -! -! ! Passed variables -! TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< FAST parameter data -! TYPE(FAST_OutputFileType), INTENT(IN ) :: y_FAST !< FAST output file data (for linearization) -! TYPE(HD_InputType), INTENT(INOUT) :: u_MAP !< The inputs to HydroDyn - -! TYPE(ED_OutputType), INTENT(IN) :: y_ED !< The outputs from the structural dynamics module -! TYPE(FAST_ModuleMapType), INTENT(INOUT) :: MeshMapData !< Data for mapping between modules -! REAL(R8Ki), INTENT(INOUT) :: dUdy(:,:) !< Jacobian matrix of which we are computing the dU^{MAP}/dy^{ED} block -! -! INTEGER(IntKi) :: ErrStat !< Error status of the operation -! CHARACTER(*) :: ErrMsg !< Error message if ErrStat /= ErrID_None -! -! ! Local variables: -! -! INTEGER(IntKi) :: MAP_Start ! starting index of dUdy (column) where particular MAP fields are located -! INTEGER(IntKi) :: ED_Start ! starting index of dUdy (row) where particular ED fields are located -! INTEGER(IntKi) :: ErrStat2 -! CHARACTER(ErrMsgLen) :: ErrMsg2 -! CHARACTER(*), PARAMETER :: RoutineName = 'Linear_MAP_InputSolve_dy' -! -! -! ErrStat = ErrID_None -! ErrMsg = "" -! -! ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine -! ! We need to make six calls to SetBlockMatrix for the different output to input mappings -! ! 1) Row 3, Col 1 -! ! 2) Row 4, Col 1 -! -! -! ! look at how the translational displacement gets transfered to the translational velocity and translational acceleration: -! !------------------------------------------------------------------------------------------------- -! ! Set the inputs from ElastoDyn: -! !------------------------------------------------------------------------------------------------- -! -! !.......... -! ! dU^{MAP}/dy^{ED} -! ! note that the 1s on the diagonal have already been set, so we will fill in the off diagonal terms. -! !.......... -! -! if ( p_FAST%CompMooring == Module_MAP ) then ! MAP- ElastoDyn -! -! !=================================================== -! ! y_ED%PlatformPtMesh and u_MAP%Morison%Mesh -! !=================================================== -! -! ! Transfer ED motions to HD motion input (HD inputs depend on previously calculated HD inputs from ED): -! -! call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_MAP%Morison%DistribMesh, MeshMapData%ED_P_2_MAP_M_L, ErrStat2, ErrMsg2 ) -! call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) -! -! ! HD is destination in the mapping, so we want M_{tv_uD} and M_{ta_uD} -! -! HD_Start_td = y_FAST%Lin%Modules(MODULE_MAP)%Instance(1)%LinStartIndx(LIN_INPUT_COL) -! HD_Start_tr = HD_Start_td + u_MAP%Morison%DistribMesh%%NNodes * 6 ! skip 2 fields (TranslationDisp and Orientation) with 3 components before translational velocity field -! -! ! translational velocity: -! if (allocated(MeshMapData%ED_P_2_MAP_M_L%dM%tv_uD )) then -! call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_MAP_M_L%dM%tv_ud, HD_Start_tr, HD_Start_td ) -! end if -! -! ! translational acceleration: -! HD_Start_tr = HD_Start_tr + u_MAP%Morison%DistribMesh%%NNodes * 6 ! skip 2 fields ( TranslationVel and RotationVel) -! if (allocated(MeshMapData%ED_P_2_MAP_M_L%dM%ta_uD )) then -! call SetBlockMatrix( dUdu, MeshMapData%ED_P_2_MAP_M_L%dM%ta_ud, HD_Start_tr, HD_Start_td ) -! end if -! -! end if -! -! -!END SUBROUTINE Linear_MAP_InputSolve_du +END SUBROUTINE Linear_MAP_InputSolve_dy !---------------------------------------------------------------------------------------------------------------------------------- @@ -3727,7 +3661,7 @@ SUBROUTINE Glue_StateMatrices( p_FAST, y_FAST, dUdu, dUdy, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" - + !LIN-TODO: Update doc string comments below for HD, MAP, SD !..................................... ! allocate the glue-code state matrices; after this call they will contain the state matrices from the @@ -5103,27 +5037,20 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, end if END IF - !LIN-TODO: Do we need this for SD and Map? GJH + !LIN-TODO: we need this for SD GJH !!!! SubDyn: copy final predictions to actual states !!!IF ( p_FAST%CompSub == Module_SD ) THEN + ! SubDyn: + ThisModule = Module_SD + if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then + nStates = size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)/2 + + call GetStateAry(p_FAST, iMode, t, SD%x( STATE_CURR)%qm, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) + call GetStateAry(p_FAST, iMode, t, SD%x( STATE_CURR)%qmdot, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) + end if + !!!ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN - !!!END IF - !!! - !!! - !!!! MAP/MoorDyn/FEAM: copy op to actual states and inputs - !!!IF (p_FAST%CompMooring == Module_MAP) THEN - !!!ELSEIF (p_FAST%CompMooring == Module_MD) THEN - !!!ELSEIF (p_FAST%CompMooring == Module_FEAM) THEN - !!!!ELSEIF (p_FAST%CompMooring == Module_Orca) THEN - !!!END IF - !!! - !!! ! IceFloe/IceDyn: copy op to actual states and inputs - !!!IF ( p_FAST%CompIce == Module_IceF ) THEN - !!!ELSEIF ( p_FAST%CompIce == Module_IceD ) THEN - !!! DO k=1,p_FAST%numIceLegs - !!! END DO !!!END IF - END SUBROUTINE PerturbOP !---------------------------------------------------------------------------------------------------------------------------------- @@ -5665,12 +5592,23 @@ SUBROUTINE FAST_InitSteadyOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, H end if END IF ! HydroDyn - !! SubDyn/ExtPtfm_MCKF - !IF ( p_FAST%CompSub == Module_SD ) THEN - !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN - !END IF ! SubDyn/ExtPtfm_MCKF + IF ( p_FAST%CompSub == Module_SD ) THEN + allocate( SD%Output( p_FAST%LinInterpOrder+1 ), STAT = ErrStat2 ) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, "Error allocating SD%Output.", ErrStat, ErrMsg, RoutineName ) + else + do j = 1, p_FAST%LinInterpOrder + 1 + call SD_CopyOutput(SD%y, SD%Output(j), MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end do + + call SD_CopyOutput(SD%y, SD%y_interp, MESH_NEWCOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + end if + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + END IF ! SubDyn/ExtPtfm_MCKF ! Mooring (MAP , FEAM , MoorDyn) @@ -5842,11 +5780,17 @@ SUBROUTINE FAST_SaveOutputs( psi, p_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, END IF ! HydroDyn - !! SubDyn/ExtPtfm_MCKF - !IF ( p_FAST%CompSub == Module_SD ) THEN - !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN - !END IF ! SubDyn/ExtPtfm_MCKF + IF ( p_FAST%CompSub == Module_SD ) THEN + DO j = p_FAST%LinInterpOrder, 1, -1 + CALL SD_CopyOutput (SD%Output(j), SD%Output(j+1), MESH_UPDATECOPY, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + END DO + + CALL SD_CopyOutput (SD%y, SD%Output(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + END IF ! SubDyn/ExtPtfm_MCKF ! Mooring (MAP , FEAM , MoorDyn) @@ -5999,11 +5943,18 @@ SUBROUTINE FAST_DiffInterpOutputs( psi_target, p_FAST, y_FAST, m_FAST, ED, BD, S call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) END IF ! HydroDyn - + !! SubDyn/ExtPtfm_MCKF - !IF ( p_FAST%CompSub == Module_SD ) THEN - !ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN - !END IF ! SubDyn/ExtPtfm_MCKF + IF ( p_FAST%CompSub == Module_SD ) THEN + + CALL SD_Output_ExtrapInterp (SD%Output, m_FAST%Lin%Psi, SD%y_interp, psi_target, ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName ) + + call SD_GetOP( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), & + SD%y_interp, SD%m, ErrStat2, ErrMsg2, y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + END IF ! SubDyn/ExtPtfm_MCKF ! Mooring (MAP , FEAM , MoorDyn) diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index cfaf1a4d9..563d6b8ee 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -463,6 +463,8 @@ typedef ^ ^ SD_InputType u - - - "System inputs" typedef ^ ^ SD_OutputType y - - - "System outputs" typedef ^ ^ SD_MiscVarType m - - - "Misc/optimization variables" typedef ^ ^ SD_InputType Input {:} - - "Array of inputs associated with InputTimes" +typedef ^ ^ SD_OutputType Output {:} - - "Array of outputs associated with CalcSteady Azimuths" +typedef ^ ^ SD_OutputType y_interp - - - "interpolated system outputs for CalcSteady" typedef ^ ^ DbKi InputTimes {:} - - "Array of times associated with Input Array" # ..... ExtPtfm data ....................................................................................................... diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 36d1ce38d..8b84da615 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -1208,7 +1208,9 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, ! Initialize for linearization: ! ------------------------------------------------------------------------- if ( p_FAST%Linearize ) then - call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, ErrStat2, ErrMsg2) + ! NOTE: In the following call, we use Init%OutData_AD%BladeProps(1)%NumBlNds as the number of aero nodes on EACH blade, which + ! is consistent with the current AD implementation, but if AD changes this, then it must be handled here, too! + call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, Init%OutData_AD%BladeProps(1)%NumBlNds, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat >= AbortErrLev) then From 2599998eb30fa398df97bd771a4c9c2e1f2f8151 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 5 Aug 2020 09:41:11 -0600 Subject: [PATCH 257/377] Updating Types files --- modules/beamdyn/src/BeamDyn_Types.f90 | 36 - modules/elastodyn/src/ElastoDyn_Types.f90 | 36 - modules/extptfm/src/ExtPtfm_MCKF_Types.f90 | 19 +- modules/openfast-library/src/FAST_Types.f90 | 233 +++ modules/subdyn/src/SubDyn_Types.f90 | 2017 +++++++++---------- 5 files changed, 1191 insertions(+), 1150 deletions(-) diff --git a/modules/beamdyn/src/BeamDyn_Types.f90 b/modules/beamdyn/src/BeamDyn_Types.f90 index 2e81c8c38..378cf4010 100644 --- a/modules/beamdyn/src/BeamDyn_Types.f90 +++ b/modules/beamdyn/src/BeamDyn_Types.f90 @@ -1155,19 +1155,6 @@ SUBROUTINE BD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) - END IF END SUBROUTINE BD_PackInitOutput SUBROUTINE BD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1453,29 +1440,6 @@ SUBROUTINE BD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) - ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) - DEALLOCATE(mask1) - END IF END SUBROUTINE BD_UnPackInitOutput SUBROUTINE BD_CopyBladeInputData( SrcBladeInputDataData, DstBladeInputDataData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/elastodyn/src/ElastoDyn_Types.f90 b/modules/elastodyn/src/ElastoDyn_Types.f90 index f24bcef0b..35338dc22 100644 --- a/modules/elastodyn/src/ElastoDyn_Types.f90 +++ b/modules/elastodyn/src/ElastoDyn_Types.f90 @@ -1666,19 +1666,6 @@ SUBROUTINE ED_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) - END IF IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2016,29 +2003,6 @@ SUBROUTINE ED_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) - ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 b/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 index 0e3d68dbf..aac3e92fb 100644 --- a/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 +++ b/modules/extptfm/src/ExtPtfm_MCKF_Types.f90 @@ -1226,8 +1226,10 @@ SUBROUTINE ExtPtfm_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE ExtPtfm_PackInitOutput @@ -1483,15 +1485,10 @@ SUBROUTINE ExtPtfm_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE ExtPtfm_UnPackInitOutput diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index 25f0904f7..b106d029e 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -503,6 +503,8 @@ MODULE FAST_Types TYPE(SD_OutputType) :: y !< System outputs [-] TYPE(SD_MiscVarType) :: m !< Misc/optimization variables [-] TYPE(SD_InputType) , DIMENSION(:), ALLOCATABLE :: Input !< Array of inputs associated with InputTimes [-] + TYPE(SD_OutputType) , DIMENSION(:), ALLOCATABLE :: Output !< Array of outputs associated with CalcSteady Azimuths [-] + TYPE(SD_OutputType) :: y_interp !< interpolated system outputs for CalcSteady [-] REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: InputTimes !< Array of times associated with Input Array [-] END TYPE SubDyn_Data ! ======================= @@ -26535,6 +26537,25 @@ SUBROUTINE FAST_CopySubDyn_Data( SrcSubDyn_DataData, DstSubDyn_DataData, CtrlCod IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF +IF (ALLOCATED(SrcSubDyn_DataData%Output)) THEN + i1_l = LBOUND(SrcSubDyn_DataData%Output,1) + i1_u = UBOUND(SrcSubDyn_DataData%Output,1) + IF (.NOT. ALLOCATED(DstSubDyn_DataData%Output)) THEN + ALLOCATE(DstSubDyn_DataData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstSubDyn_DataData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DO i1 = LBOUND(SrcSubDyn_DataData%Output,1), UBOUND(SrcSubDyn_DataData%Output,1) + CALL SD_CopyOutput( SrcSubDyn_DataData%Output(i1), DstSubDyn_DataData%Output(i1), CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + ENDDO +ENDIF + CALL SD_CopyOutput( SrcSubDyn_DataData%y_interp, DstSubDyn_DataData%y_interp, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcSubDyn_DataData%InputTimes)) THEN i1_l = LBOUND(SrcSubDyn_DataData%InputTimes,1) i1_u = UBOUND(SrcSubDyn_DataData%InputTimes,1) @@ -26580,6 +26601,13 @@ SUBROUTINE FAST_DestroySubDyn_Data( SubDyn_DataData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(SubDyn_DataData%Input) ENDIF +IF (ALLOCATED(SubDyn_DataData%Output)) THEN +DO i1 = LBOUND(SubDyn_DataData%Output,1), UBOUND(SubDyn_DataData%Output,1) + CALL SD_DestroyOutput( SubDyn_DataData%Output(i1), ErrStat, ErrMsg ) +ENDDO + DEALLOCATE(SubDyn_DataData%Output) +ENDIF + CALL SD_DestroyOutput( SubDyn_DataData%y_interp, ErrStat, ErrMsg ) IF (ALLOCATED(SubDyn_DataData%InputTimes)) THEN DEALLOCATE(SubDyn_DataData%InputTimes) ENDIF @@ -26788,6 +26816,46 @@ SUBROUTINE FAST_PackSubDyn_Data( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END IF END DO END IF + Int_BufSz = Int_BufSz + 1 ! Output allocated yes/no + IF ( ALLOCATED(InData%Output) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Output upper/lower bounds for each dimension + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + Int_BufSz = Int_BufSz + 3 ! Output: size of buffers for each call to pack subtype + CALL SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, .TRUE. ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Output + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Output + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Output + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + END DO + END IF + Int_BufSz = Int_BufSz + 3 ! y_interp: size of buffers for each call to pack subtype + CALL SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, .TRUE. ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! y_interp + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! y_interp + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! y_interp + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 1 ! InputTimes allocated yes/no IF ( ALLOCATED(InData%InputTimes) ) THEN Int_BufSz = Int_BufSz + 2*1 ! InputTimes upper/lower bounds for each dimension @@ -27093,6 +27161,75 @@ SUBROUTINE FAST_PackSubDyn_Data( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er ENDIF END DO END IF + IF ( .NOT. ALLOCATED(InData%Output) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Output,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Output,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Output,1), UBOUND(InData%Output,1) + CALL SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%Output(i1), ErrStat2, ErrMsg2, OnlySize ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END DO + END IF + CALL SD_PackOutput( Re_Buf, Db_Buf, Int_Buf, InData%y_interp, ErrStat2, ErrMsg2, OnlySize ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF IF ( .NOT. ALLOCATED(InData%InputTimes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -27529,6 +27666,102 @@ SUBROUTINE FAST_UnPackSubDyn_Data( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Output not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Output)) DEALLOCATE(OutData%Output) + ALLOCATE(OutData%Output(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Output.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Output,1), UBOUND(OutData%Output,1) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%Output(i1), ErrStat2, ErrMsg2 ) ! Output + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END DO + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL SD_UnpackOutput( Re_Buf, Db_Buf, Int_Buf, OutData%y_interp, ErrStat2, ErrMsg2 ) ! y_interp + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! InputTimes not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 2d74ad9cd..7808ba684 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -162,8 +162,8 @@ MODULE SubDyn_Types ! ======================= ! ========= SD_ContinuousStateType ======= TYPE, PUBLIC :: SD_ContinuousStateType - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qm !< Virtual states, Nmod elements [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qmdot !< Derivative of states, Nmod elements [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: qm !< Virtual states, Nmod elements [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: qmdot !< Derivative of states, Nmod elements [-] END TYPE SD_ContinuousStateType ! ======================= ! ========= SD_DiscreteStateType ======= @@ -451,8 +451,10 @@ SUBROUTINE SD_PackIList( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%List,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%List)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%List))-1 ) = PACK(InData%List,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%List) + DO i1 = LBOUND(InData%List,1), UBOUND(InData%List,1) + IntKiBuf(Int_Xferred) = InData%List(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE SD_PackIList @@ -469,12 +471,6 @@ SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i - LOGICAL :: mask0 - LOGICAL, ALLOCATABLE :: mask1(:) - LOGICAL, ALLOCATABLE :: mask2(:,:) - LOGICAL, ALLOCATABLE :: mask3(:,:,:) - LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) - LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 @@ -505,15 +501,10 @@ SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%List.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%List)>0) OutData%List = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%List))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%List) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%List,1), UBOUND(OutData%List,1) + OutData%List(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE SD_UnPackIList @@ -621,24 +612,26 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 - DO I = 1, LEN(InData%SDInputFile) - IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%RootName) - IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%WtrDpth - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Linearize , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%SDInputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) + ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackInitInput SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -682,19 +675,14 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = Re_Xferred + 1 i1_l = LBOUND(OutData%TP_RefPoint,1) i1_u = UBOUND(OutData%TP_RefPoint,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) - DEALLOCATE(mask1) - OutData%SubRotateZ = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Linearize = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) + OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%SubRotateZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_UnPackInitInput SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -1081,12 +1069,12 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) DO I = 1, LEN(InData%LinNames_y) IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 + END DO END IF IF ( .NOT. ALLOCATED(InData%LinNames_x) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1098,12 +1086,12 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) DO I = 1, LEN(InData%LinNames_x) IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 + END DO END IF IF ( .NOT. ALLOCATED(InData%LinNames_u) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1115,12 +1103,12 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) DO I = 1, LEN(InData%LinNames_u) IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 + END DO END IF IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1132,8 +1120,10 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%RotFrame_y)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_y)-1 ) = TRANSFER(PACK( InData%RotFrame_y ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_y)) - Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_y) + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1145,8 +1135,10 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%RotFrame_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_x)-1 ) = TRANSFER(PACK( InData%RotFrame_x ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_x)) - Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_x) + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1158,8 +1150,10 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%RotFrame_u)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%RotFrame_u)-1 ) = TRANSFER(PACK( InData%RotFrame_u ,.TRUE.), IntKiBuf(1), SIZE(InData%RotFrame_u)) - Int_Xferred = Int_Xferred + SIZE(InData%RotFrame_u) + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1171,8 +1165,10 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IsLoad_u)>0) IntKiBuf ( Int_Xferred:Int_Xferred+SIZE(InData%IsLoad_u)-1 ) = TRANSFER(PACK( InData%IsLoad_u ,.TRUE.), IntKiBuf(1), SIZE(InData%IsLoad_u)) - Int_Xferred = Int_Xferred + SIZE(InData%IsLoad_u) + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1184,8 +1180,10 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%DerivOrder_x)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DerivOrder_x))-1 ) = PACK(InData%DerivOrder_x,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DerivOrder_x) + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE SD_PackInitOutput @@ -1309,19 +1307,12 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) DO I = 1, LEN(OutData%LinNames_y) OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 - DEALLOCATE(mask1) + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x not allocated Int_Xferred = Int_Xferred + 1 @@ -1336,19 +1327,12 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) DO I = 1, LEN(OutData%LinNames_x) OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 - DEALLOCATE(mask1) + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u not allocated Int_Xferred = Int_Xferred + 1 @@ -1363,19 +1347,12 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) DO I = 1, LEN(OutData%LinNames_u) OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 - DEALLOCATE(mask1) + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y not allocated Int_Xferred = Int_Xferred + 1 @@ -1390,15 +1367,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%RotFrame_y)>0) OutData%RotFrame_y = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_y))-1 ), OutData%RotFrame_y), mask1,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_y) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x not allocated Int_Xferred = Int_Xferred + 1 @@ -1413,15 +1385,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%RotFrame_x)>0) OutData%RotFrame_x = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_x))-1 ), OutData%RotFrame_x), mask1,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_x) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u not allocated Int_Xferred = Int_Xferred + 1 @@ -1436,15 +1403,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%RotFrame_u)>0) OutData%RotFrame_u = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%RotFrame_u))-1 ), OutData%RotFrame_u), mask1,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(OutData%RotFrame_u) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u not allocated Int_Xferred = Int_Xferred + 1 @@ -1459,15 +1421,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IsLoad_u)>0) OutData%IsLoad_u = UNPACK( TRANSFER( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IsLoad_u))-1 ), OutData%IsLoad_u), mask1,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(OutData%IsLoad_u) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated Int_Xferred = Int_Xferred + 1 @@ -1482,15 +1439,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%DerivOrder_x)>0) OutData%DerivOrder_x = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DerivOrder_x))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DerivOrder_x) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF END SUBROUTINE SD_UnPackInitOutput @@ -2742,32 +2694,36 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%eType - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Length - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Ixx - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Iyy - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Jzz - Re_Xferred = Re_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%Shear , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Kappa - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%YoungE - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%ShearG - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Area - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%Rho - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%T0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DirCos) + IntKiBuf(Int_Xferred) = InData%eType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Length + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ixx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Iyy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Jzz + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Shear, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kappa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YoungE + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShearG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Area + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rho + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T0 + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%DirCos,2), UBOUND(InData%DirCos,2) + DO i1 = LBOUND(InData%DirCos,1), UBOUND(InData%DirCos,1) + ReKiBuf(Re_Xferred) = InData%DirCos(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END SUBROUTINE SD_PackElemPropType SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2798,30 +2754,30 @@ SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%eType = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Length = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Ixx = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Iyy = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Jzz = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Shear = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%Kappa = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%YoungE = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%ShearG = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Area = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%Rho = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%T0 = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 + OutData%eType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Length = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ixx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Iyy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Jzz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Shear = TRANSFER(IntKiBuf(Int_Xferred), OutData%Shear) + Int_Xferred = Int_Xferred + 1 + OutData%Kappa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YoungE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShearG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Area = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rho = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 i1_l = LBOUND(OutData%DirCos,1) i1_u = UBOUND(OutData%DirCos,1) i2_l = LBOUND(OutData%DirCos,2) @@ -3559,38 +3515,40 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Db_Xferred = 1 Int_Xferred = 1 - DO I = 1, LEN(InData%RootName) - IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%TP_RefPoint))-1 ) = PACK(InData%TP_RefPoint,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%TP_RefPoint) - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%SubRotateZ - Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%g - Re_Xferred = Re_Xferred + 1 - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%DT - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NJoints - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsX - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsB - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsC - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropSetsR - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCMass - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NCOSMs - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%FEMMod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NDiv - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%CBMod , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) + ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NJoints + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropSetsX + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropSetsB + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropSetsC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropSetsR + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NCMass + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NCOSMs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%FEMMod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NDiv + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CBMod, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Joints) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3624,8 +3582,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropSetsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsB))-1 ) = PACK(InData%PropSetsB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsB) + DO i2 = LBOUND(InData%PropSetsB,2), UBOUND(InData%PropSetsB,2) + DO i1 = LBOUND(InData%PropSetsB,1), UBOUND(InData%PropSetsB,1) + ReKiBuf(Re_Xferred) = InData%PropSetsB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%PropSetsC) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3640,8 +3602,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsC,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropSetsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsC))-1 ) = PACK(InData%PropSetsC,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsC) + DO i2 = LBOUND(InData%PropSetsC,2), UBOUND(InData%PropSetsC,2) + DO i1 = LBOUND(InData%PropSetsC,1), UBOUND(InData%PropSetsC,1) + ReKiBuf(Re_Xferred) = InData%PropSetsC(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%PropSetsR) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3656,8 +3622,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsR,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropSetsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsR))-1 ) = PACK(InData%PropSetsR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsR) + DO i2 = LBOUND(InData%PropSetsR,2), UBOUND(InData%PropSetsR,2) + DO i1 = LBOUND(InData%PropSetsR,1), UBOUND(InData%PropSetsR,1) + ReKiBuf(Re_Xferred) = InData%PropSetsR(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%PropSetsX) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3672,8 +3642,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropSetsX,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropSetsX)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropSetsX))-1 ) = PACK(InData%PropSetsX,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropSetsX) + DO i2 = LBOUND(InData%PropSetsX,2), UBOUND(InData%PropSetsX,2) + DO i1 = LBOUND(InData%PropSetsX,1), UBOUND(InData%PropSetsX,1) + ReKiBuf(Re_Xferred) = InData%PropSetsX(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%COSMs) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3730,12 +3704,18 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Re_Xferred = Re_Xferred + 1 END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%GuyanDampMod - Int_Xferred = Int_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%RayleighDamp))-1 ) = PACK(InData%RayleighDamp,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%RayleighDamp) - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%GuyanDampMat))-1 ) = PACK(InData%GuyanDampMat,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%GuyanDampMat) + IntKiBuf(Int_Xferred) = InData%GuyanDampMod + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RayleighDamp,1), UBOUND(InData%RayleighDamp,1) + ReKiBuf(Re_Xferred) = InData%RayleighDamp(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i2 = LBOUND(InData%GuyanDampMat,2), UBOUND(InData%GuyanDampMat,2) + DO i1 = LBOUND(InData%GuyanDampMat,1), UBOUND(InData%GuyanDampMat,1) + ReKiBuf(Re_Xferred) = InData%GuyanDampMat(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO IF ( .NOT. ALLOCATED(InData%Members) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3773,10 +3753,10 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END DO ! I END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutCOSM , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%TabDelim , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutCOSM, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TabDelim, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%SSIK) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3790,8 +3770,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%SSIK)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIK) + DO i2 = LBOUND(InData%SSIK,2), UBOUND(InData%SSIK,2) + DO i1 = LBOUND(InData%SSIK,1), UBOUND(InData%SSIK,1) + ReKiBuf(Re_Xferred) = InData%SSIK(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%SSIM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3806,8 +3790,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%SSIM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIM) + DO i2 = LBOUND(InData%SSIM,2), UBOUND(InData%SSIM,2) + DO i1 = LBOUND(InData%SSIM,1), UBOUND(InData%SSIM,1) + ReKiBuf(Re_Xferred) = InData%SSIM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3819,21 +3807,21 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIfile,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%SSIfile,1), UBOUND(InData%SSIfile,1) + DO i1 = LBOUND(InData%SSIfile,1), UBOUND(InData%SSIfile,1) DO I = 1, LEN(InData%SSIfile) IntKiBuf(Int_Xferred) = ICHAR(InData%SSIfile(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NElem - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropB - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropC - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NPropR - Int_Xferred = Int_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NElem + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropB + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropC + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NPropR + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -3867,8 +3855,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropsB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsB))-1 ) = PACK(InData%PropsB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsB) + DO i2 = LBOUND(InData%PropsB,2), UBOUND(InData%PropsB,2) + DO i1 = LBOUND(InData%PropsB,1), UBOUND(InData%PropsB,1) + ReKiBuf(Re_Xferred) = InData%PropsB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%PropsC) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3883,8 +3875,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsC,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropsC)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsC))-1 ) = PACK(InData%PropsC,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsC) + DO i2 = LBOUND(InData%PropsC,2), UBOUND(InData%PropsC,2) + DO i1 = LBOUND(InData%PropsC,1), UBOUND(InData%PropsC,1) + ReKiBuf(Re_Xferred) = InData%PropsC(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%PropsR) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3899,8 +3895,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PropsR,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PropsR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PropsR))-1 ) = PACK(InData%PropsR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PropsR) + DO i2 = LBOUND(InData%PropsR,2), UBOUND(InData%PropsR,2) + DO i1 = LBOUND(InData%PropsR,1), UBOUND(InData%PropsR,1) + ReKiBuf(Re_Xferred) = InData%PropsR(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%K) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -4130,41 +4130,36 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM END DO ! I i1_l = LBOUND(OutData%TP_RefPoint,1) i1_u = UBOUND(OutData%TP_RefPoint,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%TP_RefPoint = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%TP_RefPoint))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%TP_RefPoint) - DEALLOCATE(mask1) - OutData%SubRotateZ = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%g = ReKiBuf( Re_Xferred ) - Re_Xferred = Re_Xferred + 1 - OutData%DT = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%NJoints = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsX = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsB = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsC = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropSetsR = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NCMass = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NCOSMs = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%FEMMod = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NDiv = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%CBMod = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) + OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%SubRotateZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NJoints = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsX = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsB = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropSetsR = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NCMass = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NCOSMs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FEMMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NDiv = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%CBMod = TRANSFER(IntKiBuf(Int_Xferred), OutData%CBMod) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Joints not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4204,15 +4199,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsB)>0) OutData%PropSetsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsB) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropSetsB,2), UBOUND(OutData%PropSetsB,2) + DO i1 = LBOUND(OutData%PropSetsB,1), UBOUND(OutData%PropSetsB,1) + OutData%PropSetsB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsC not allocated Int_Xferred = Int_Xferred + 1 @@ -4230,15 +4222,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsC.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsC)>0) OutData%PropSetsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsC))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsC) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropSetsC,2), UBOUND(OutData%PropSetsC,2) + DO i1 = LBOUND(OutData%PropSetsC,1), UBOUND(OutData%PropSetsC,1) + OutData%PropSetsC(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsR not allocated Int_Xferred = Int_Xferred + 1 @@ -4256,15 +4245,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsR.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsR)>0) OutData%PropSetsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsR) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropSetsR,2), UBOUND(OutData%PropSetsR,2) + DO i1 = LBOUND(OutData%PropSetsR,1), UBOUND(OutData%PropSetsR,1) + OutData%PropSetsR(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropSetsX not allocated Int_Xferred = Int_Xferred + 1 @@ -4282,15 +4268,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropSetsX.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropSetsX)>0) OutData%PropSetsX = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropSetsX))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropSetsX) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropSetsX,2), UBOUND(OutData%PropSetsX,2) + DO i1 = LBOUND(OutData%PropSetsX,1), UBOUND(OutData%PropSetsX,1) + OutData%PropSetsX(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! COSMs not allocated Int_Xferred = Int_Xferred + 1 @@ -4356,32 +4339,24 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Re_Xferred = Re_Xferred + 1 END DO END IF - OutData%GuyanDampMod = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%GuyanDampMod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%RayleighDamp,1) i1_u = UBOUND(OutData%RayleighDamp,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%RayleighDamp = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%RayleighDamp))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%RayleighDamp) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%RayleighDamp,1), UBOUND(OutData%RayleighDamp,1) + OutData%RayleighDamp(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO i1_l = LBOUND(OutData%GuyanDampMat,1) i1_u = UBOUND(OutData%GuyanDampMat,1) i2_l = LBOUND(OutData%GuyanDampMat,2) i2_u = UBOUND(OutData%GuyanDampMat,2) - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - OutData%GuyanDampMat = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%GuyanDampMat))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%GuyanDampMat) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%GuyanDampMat,2), UBOUND(OutData%GuyanDampMat,2) + DO i1 = LBOUND(OutData%GuyanDampMat,1), UBOUND(OutData%GuyanDampMat,1) + OutData%GuyanDampMat(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Members not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4418,24 +4393,17 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSOutList.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%SSOutList,1), UBOUND(OutData%SSOutList,1) + DO i1 = LBOUND(OutData%SSOutList,1), UBOUND(OutData%SSOutList,1) DO I = 1, LEN(OutData%SSOutList) OutData%SSOutList(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I - END DO !i1 - DEALLOCATE(mask1) + END DO END IF - OutData%OutCOSM = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%TabDelim = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + OutData%OutCOSM = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutCOSM) + Int_Xferred = Int_Xferred + 1 + OutData%TabDelim = TRANSFER(IntKiBuf(Int_Xferred), OutData%TabDelim) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIK not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4452,15 +4420,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIK.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%SSIK)>0) OutData%SSIK = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIK) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%SSIK,2), UBOUND(OutData%SSIK,2) + DO i1 = LBOUND(OutData%SSIK,1), UBOUND(OutData%SSIK,1) + OutData%SSIK(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIM not allocated Int_Xferred = Int_Xferred + 1 @@ -4478,15 +4443,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIM.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%SSIM)>0) OutData%SSIM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIM) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%SSIM,2), UBOUND(OutData%SSIM,2) + DO i1 = LBOUND(OutData%SSIM,1), UBOUND(OutData%SSIM,1) + OutData%SSIM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated Int_Xferred = Int_Xferred + 1 @@ -4501,27 +4463,21 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SSIfile.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - DO i1 = LBOUND(OutData%SSIfile,1), UBOUND(OutData%SSIfile,1) + DO i1 = LBOUND(OutData%SSIfile,1), UBOUND(OutData%SSIfile,1) DO I = 1, LEN(OutData%SSIfile) OutData%SSIfile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 + Int_Xferred = Int_Xferred + 1 END DO ! I END DO END IF - OutData%NElem = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropB = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropC = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NPropR = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%NElem = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropB = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropC = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NPropR = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4561,15 +4517,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsB)>0) OutData%PropsB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsB) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropsB,2), UBOUND(OutData%PropsB,2) + DO i1 = LBOUND(OutData%PropsB,1), UBOUND(OutData%PropsB,1) + OutData%PropsB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsC not allocated Int_Xferred = Int_Xferred + 1 @@ -4587,16 +4540,13 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsC.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsC)>0) OutData%PropsC = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsC))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsC) - DEALLOCATE(mask2) - END IF + DO i2 = LBOUND(OutData%PropsC,2), UBOUND(OutData%PropsC,2) + DO i1 = LBOUND(OutData%PropsC,1), UBOUND(OutData%PropsC,1) + OutData%PropsC(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PropsR not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4613,15 +4563,12 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PropsR.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%PropsR)>0) OutData%PropsR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PropsR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PropsR) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%PropsR,2), UBOUND(OutData%PropsR,2) + DO i1 = LBOUND(OutData%PropsR,1), UBOUND(OutData%PropsR,1) + OutData%PropsR(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K not allocated Int_Xferred = Int_Xferred + 1 @@ -4943,12 +4890,12 @@ SUBROUTINE SD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 1 ! qm allocated yes/no IF ( ALLOCATED(InData%qm) ) THEN Int_BufSz = Int_BufSz + 2*1 ! qm upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%qm) ! qm + Db_BufSz = Db_BufSz + SIZE(InData%qm) ! qm END IF Int_BufSz = Int_BufSz + 1 ! qmdot allocated yes/no IF ( ALLOCATED(InData%qmdot) ) THEN Int_BufSz = Int_BufSz + 2*1 ! qmdot upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%qmdot) ! qmdot + Db_BufSz = Db_BufSz + SIZE(InData%qmdot) ! qmdot END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -4988,8 +4935,8 @@ SUBROUTINE SD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%qm,1), UBOUND(InData%qm,1) - ReKiBuf(Re_Xferred) = InData%qm(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%qm(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%qmdot) ) THEN @@ -5003,8 +4950,8 @@ SUBROUTINE SD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%qmdot,1), UBOUND(InData%qmdot,1) - ReKiBuf(Re_Xferred) = InData%qmdot(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%qmdot(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF END SUBROUTINE SD_PackContState @@ -5050,8 +4997,8 @@ SUBROUTINE SD_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF DO i1 = LBOUND(OutData%qm,1), UBOUND(OutData%qm,1) - OutData%qm(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%qm(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! qmdot not allocated @@ -5068,8 +5015,8 @@ SUBROUTINE SD_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF DO i1 = LBOUND(OutData%qmdot,1), UBOUND(OutData%qmdot,1) - OutData%qmdot(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%qmdot(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 END DO END IF END SUBROUTINE SD_UnPackContState @@ -6176,8 +6123,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_full)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full))-1 ) = PACK(InData%U_full,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full) + DO i1 = LBOUND(InData%U_full,1), UBOUND(InData%U_full,1) + ReKiBuf(Re_Xferred) = InData%U_full(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%U_full_dot) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6189,8 +6138,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dot,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_full_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dot))-1 ) = PACK(InData%U_full_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full_dot) + DO i1 = LBOUND(InData%U_full_dot,1), UBOUND(InData%U_full_dot,1) + ReKiBuf(Re_Xferred) = InData%U_full_dot(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%U_full_dotdot) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6202,8 +6153,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_dotdot,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_full_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_full_dotdot))-1 ) = PACK(InData%U_full_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_full_dotdot) + DO i1 = LBOUND(InData%U_full_dotdot,1), UBOUND(InData%U_full_dotdot,1) + ReKiBuf(Re_Xferred) = InData%U_full_dotdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%U_red) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6215,8 +6168,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red))-1 ) = PACK(InData%U_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red) + DO i1 = LBOUND(InData%U_red,1), UBOUND(InData%U_red,1) + ReKiBuf(Re_Xferred) = InData%U_red(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%U_red_dot) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6228,8 +6183,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dot,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_red_dot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dot))-1 ) = PACK(InData%U_red_dot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red_dot) + DO i1 = LBOUND(InData%U_red_dot,1), UBOUND(InData%U_red_dot,1) + ReKiBuf(Re_Xferred) = InData%U_red_dot(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%U_red_dotdot) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6241,8 +6198,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_dotdot,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%U_red_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dotdot))-1 ) = PACK(InData%U_red_dotdot,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%U_red_dotdot) + DO i1 = LBOUND(InData%U_red_dotdot,1), UBOUND(InData%U_red_dotdot,1) + ReKiBuf(Re_Xferred) = InData%U_red_dotdot(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6259,10 +6218,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%LastOutTime - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Decimat - Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%LastOutTime + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Decimat + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Fext) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6273,8 +6232,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Fext)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext))-1 ) = PACK(InData%Fext,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext) + DO i1 = LBOUND(InData%Fext,1), UBOUND(InData%Fext,1) + ReKiBuf(Re_Xferred) = InData%Fext(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%Fext_red) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -6286,8 +6247,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fext_red,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Fext_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fext_red))-1 ) = PACK(InData%Fext_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fext_red) + DO i1 = LBOUND(InData%Fext_red,1), UBOUND(InData%Fext_red,1) + ReKiBuf(Re_Xferred) = InData%Fext_red(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF END SUBROUTINE SD_PackMisc @@ -6493,15 +6456,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full)>0) OutData%U_full = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_full,1), UBOUND(OutData%U_full,1) + OutData%U_full(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dot not allocated Int_Xferred = Int_Xferred + 1 @@ -6516,15 +6474,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dot.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full_dot)>0) OutData%U_full_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dot) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_full_dot,1), UBOUND(OutData%U_full_dot,1) + OutData%U_full_dot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_dotdot not allocated Int_Xferred = Int_Xferred + 1 @@ -6539,15 +6492,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_dotdot.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_full_dotdot)>0) OutData%U_full_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_full_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_full_dotdot) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_full_dotdot,1), UBOUND(OutData%U_full_dotdot,1) + OutData%U_full_dotdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red not allocated Int_Xferred = Int_Xferred + 1 @@ -6562,15 +6510,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red)>0) OutData%U_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_red,1), UBOUND(OutData%U_red,1) + OutData%U_red(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dot not allocated Int_Xferred = Int_Xferred + 1 @@ -6585,15 +6528,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dot.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red_dot)>0) OutData%U_red_dot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dot) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_red_dot,1), UBOUND(OutData%U_red_dot,1) + OutData%U_red_dot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_dotdot not allocated Int_Xferred = Int_Xferred + 1 @@ -6608,15 +6546,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_dotdot.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%U_red_dotdot)>0) OutData%U_red_dotdot = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%U_red_dotdot))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dotdot) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%U_red_dotdot,1), UBOUND(OutData%U_red_dotdot,1) + OutData%U_red_dotdot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput not allocated Int_Xferred = Int_Xferred + 1 @@ -6636,10 +6569,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF - OutData%LastOutTime = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%Decimat = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%LastOutTime = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Decimat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6653,15 +6586,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Fext)>0) OutData%Fext = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fext) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%Fext,1), UBOUND(OutData%Fext,1) + OutData%Fext(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fext_red not allocated Int_Xferred = Int_Xferred + 1 @@ -6676,15 +6604,10 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fext_red.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%Fext_red)>0) OutData%Fext_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fext_red))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fext_red) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%Fext_red,1), UBOUND(OutData%Fext_red,1) + OutData%Fext_red(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF END SUBROUTINE SD_UnPackMisc @@ -8323,16 +8246,16 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Db_Xferred = 1 Int_Xferred = 1 - DbKiBuf ( Db_Xferred:Db_Xferred+(1)-1 ) = InData%SDDeltaT - Db_Xferred = Db_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%IntMethod - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF_red - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Nmembers - Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%SDDeltaT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%IntMethod + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOF + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOF_red + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Nmembers + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Elems) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8346,8 +8269,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Elems,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Elems)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Elems))-1 ) = PACK(InData%Elems,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Elems) + DO i2 = LBOUND(InData%Elems,2), UBOUND(InData%Elems,2) + DO i1 = LBOUND(InData%Elems,1), UBOUND(InData%Elems,1) + IntKiBuf(Int_Xferred) = InData%Elems(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8390,8 +8317,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%reduced , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%reduced, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%T_red) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8405,8 +8332,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%T_red) + DO i2 = LBOUND(InData%T_red,2), UBOUND(InData%T_red,2) + DO i1 = LBOUND(InData%T_red,1), UBOUND(InData%T_red,1) + ReKiBuf(Re_Xferred) = InData%T_red(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8503,8 +8434,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElemsDOF,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%ElemsDOF)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ElemsDOF))-1 ) = PACK(InData%ElemsDOF,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ElemsDOF) + DO i2 = LBOUND(InData%ElemsDOF,2), UBOUND(InData%ElemsDOF,2) + DO i1 = LBOUND(InData%ElemsDOF,1), UBOUND(InData%ElemsDOF,1) + IntKiBuf(Int_Xferred) = InData%ElemsDOF(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%DOFred2Nodes) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8519,15 +8454,19 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DOFred2Nodes,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%DOFred2Nodes)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%DOFred2Nodes))-1 ) = PACK(InData%DOFred2Nodes,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%DOFred2Nodes) + DO i2 = LBOUND(InData%DOFred2Nodes,2), UBOUND(InData%DOFred2Nodes,2) + DO i1 = LBOUND(InData%DOFred2Nodes,1), UBOUND(InData%DOFred2Nodes,1) + IntKiBuf(Int_Xferred) = InData%DOFred2Nodes(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFM - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%SttcSolve - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%ExtraMoment , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFM + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SttcSolve + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ExtraMoment, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8538,8 +8477,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KMMDiag,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%KMMDiag)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KMMDiag))-1 ) = PACK(InData%KMMDiag,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KMMDiag) + DO i1 = LBOUND(InData%KMMDiag,1), UBOUND(InData%KMMDiag,1) + ReKiBuf(Re_Xferred) = InData%KMMDiag(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%CMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8551,8 +8492,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMMDiag,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CMMDiag)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMMDiag))-1 ) = PACK(InData%CMMDiag,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CMMDiag) + DO i1 = LBOUND(InData%CMMDiag,1), UBOUND(InData%CMMDiag,1) + ReKiBuf(Re_Xferred) = InData%CMMDiag(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%MMB) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8642,8 +8585,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_12,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%D1_12)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%D1_12))-1 ) = PACK(InData%D1_12,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%D1_12) + DO i2 = LBOUND(InData%D1_12,2), UBOUND(InData%D1_12,2) + DO i1 = LBOUND(InData%D1_12,1), UBOUND(InData%D1_12,1) + ReKiBuf(Re_Xferred) = InData%D1_12(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%D1_13) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8888,8 +8835,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBB))-1 ) = PACK(InData%CBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CBB) + DO i2 = LBOUND(InData%CBB,2), UBOUND(InData%CBB,2) + DO i1 = LBOUND(InData%CBB,1), UBOUND(InData%CBB,1) + ReKiBuf(Re_Xferred) = InData%CBB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%CMB) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8904,8 +8855,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CMB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMB))-1 ) = PACK(InData%CMB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CMB) + DO i2 = LBOUND(InData%CMB,2), UBOUND(InData%CMB,2) + DO i1 = LBOUND(InData%CMB,1), UBOUND(InData%CMB,1) + ReKiBuf(Re_Xferred) = InData%CMB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%CBM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8920,8 +8875,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CBM))-1 ) = PACK(InData%CBM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CBM) + DO i2 = LBOUND(InData%CBM,2), UBOUND(InData%CBM,2) + DO i1 = LBOUND(InData%CBM,1), UBOUND(InData%CBM,1) + ReKiBuf(Re_Xferred) = InData%CBM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%CMM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8936,8 +8895,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMM,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%CMM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CMM))-1 ) = PACK(InData%CMM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%CMM) + DO i2 = LBOUND(InData%CMM,2), UBOUND(InData%CMM,2) + DO i1 = LBOUND(InData%CMM,1), UBOUND(InData%CMM,1) + ReKiBuf(Re_Xferred) = InData%CMM(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%MBM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -8969,8 +8932,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_st_g,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%UL_st_g)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%UL_st_g))-1 ) = PACK(InData%UL_st_g,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%UL_st_g) + DO i1 = LBOUND(InData%UL_st_g,1), UBOUND(InData%UL_st_g,1) + ReKiBuf(Re_Xferred) = InData%UL_st_g(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%PhiL_T) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9025,8 +8990,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KLLm1,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%KLLm1)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KLLm1))-1 ) = PACK(InData%KLLm1,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KLLm1) + DO i2 = LBOUND(InData%KLLm1,2), UBOUND(InData%KLLm1,2) + DO i1 = LBOUND(InData%KLLm1,1), UBOUND(InData%KLLm1,1) + ReKiBuf(Re_Xferred) = InData%KLLm1(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%AM2Jac) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9103,14 +9072,14 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_I - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nNodes_C - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodes + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodes_I + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodes_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nNodes_C + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Nodes_I) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9124,8 +9093,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Nodes_I)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_I))-1 ) = PACK(InData%Nodes_I,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_I) + DO i2 = LBOUND(InData%Nodes_I,2), UBOUND(InData%Nodes_I,2) + DO i1 = LBOUND(InData%Nodes_I,1), UBOUND(InData%Nodes_I,1) + IntKiBuf(Int_Xferred) = InData%Nodes_I(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%Nodes_L) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9140,8 +9113,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_L,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Nodes_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_L))-1 ) = PACK(InData%Nodes_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_L) + DO i2 = LBOUND(InData%Nodes_L,2), UBOUND(InData%Nodes_L,2) + DO i1 = LBOUND(InData%Nodes_L,1), UBOUND(InData%Nodes_L,1) + IntKiBuf(Int_Xferred) = InData%Nodes_L(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%Nodes_C) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9156,33 +9133,37 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_C,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Nodes_C)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Nodes_C))-1 ) = PACK(InData%Nodes_C,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Nodes_C) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFI_F - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFL_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFC_F - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOFR__ - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__Rb - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__L - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%nDOF__F - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%Nodes_C,2), UBOUND(InData%Nodes_C,2) + DO i1 = LBOUND(InData%Nodes_C,1), UBOUND(InData%Nodes_C,1) + IntKiBuf(Int_Xferred) = InData%Nodes_C(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IntKiBuf(Int_Xferred) = InData%nDOFI__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFI_Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFI_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFL_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFC__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFC_Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFC_L + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFC_F + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOFR__ + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOF__Rb + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOF__L + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nDOF__F + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%IDI__) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9193,8 +9174,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI__,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDI__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI__))-1 ) = PACK(InData%IDI__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI__) + DO i1 = LBOUND(InData%IDI__,1), UBOUND(InData%IDI__,1) + IntKiBuf(Int_Xferred) = InData%IDI__(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDI_Rb) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9206,8 +9189,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_Rb,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDI_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_Rb))-1 ) = PACK(InData%IDI_Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI_Rb) + DO i1 = LBOUND(InData%IDI_Rb,1), UBOUND(InData%IDI_Rb,1) + IntKiBuf(Int_Xferred) = InData%IDI_Rb(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDI_F) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9219,8 +9204,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDI_F,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDI_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDI_F))-1 ) = PACK(InData%IDI_F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDI_F) + DO i1 = LBOUND(InData%IDI_F,1), UBOUND(InData%IDI_F,1) + IntKiBuf(Int_Xferred) = InData%IDI_F(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDL_L) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9232,8 +9219,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDL_L,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDL_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDL_L))-1 ) = PACK(InData%IDL_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDL_L) + DO i1 = LBOUND(InData%IDL_L,1), UBOUND(InData%IDL_L,1) + IntKiBuf(Int_Xferred) = InData%IDL_L(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDC__) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9245,8 +9234,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC__,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDC__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC__))-1 ) = PACK(InData%IDC__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC__) + DO i1 = LBOUND(InData%IDC__,1), UBOUND(InData%IDC__,1) + IntKiBuf(Int_Xferred) = InData%IDC__(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDC_Rb) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9258,8 +9249,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_Rb,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDC_Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_Rb))-1 ) = PACK(InData%IDC_Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_Rb) + DO i1 = LBOUND(InData%IDC_Rb,1), UBOUND(InData%IDC_Rb,1) + IntKiBuf(Int_Xferred) = InData%IDC_Rb(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDC_L) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9271,8 +9264,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_L,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDC_L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_L))-1 ) = PACK(InData%IDC_L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_L) + DO i1 = LBOUND(InData%IDC_L,1), UBOUND(InData%IDC_L,1) + IntKiBuf(Int_Xferred) = InData%IDC_L(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDC_F) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9284,8 +9279,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDC_F,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDC_F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDC_F))-1 ) = PACK(InData%IDC_F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDC_F) + DO i1 = LBOUND(InData%IDC_F,1), UBOUND(InData%IDC_F,1) + IntKiBuf(Int_Xferred) = InData%IDC_F(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%IDR__) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9297,8 +9294,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IDR__,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%IDR__)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%IDR__))-1 ) = PACK(InData%IDR__,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%IDR__) + DO i1 = LBOUND(InData%IDR__,1), UBOUND(InData%IDR__,1) + IntKiBuf(Int_Xferred) = InData%IDR__(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%ID__Rb) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9310,8 +9309,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__Rb,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%ID__Rb)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__Rb))-1 ) = PACK(InData%ID__Rb,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__Rb) + DO i1 = LBOUND(InData%ID__Rb,1), UBOUND(InData%ID__Rb,1) + IntKiBuf(Int_Xferred) = InData%ID__Rb(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%ID__L) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9323,8 +9324,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__L,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%ID__L)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__L))-1 ) = PACK(InData%ID__L,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__L) + DO i1 = LBOUND(InData%ID__L,1), UBOUND(InData%ID__L,1) + IntKiBuf(Int_Xferred) = InData%ID__L(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%ID__F) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9336,8 +9339,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ID__F,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%ID__F)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%ID__F))-1 ) = PACK(InData%ID__F,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%ID__F) + DO i1 = LBOUND(InData%ID__F,1), UBOUND(InData%ID__F,1) + IntKiBuf(Int_Xferred) = InData%ID__F(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( .NOT. ALLOCATED(InData%FGL) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9349,29 +9354,31 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%FGL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FGL))-1 ) = PACK(InData%FGL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FGL) - END IF - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NMOutputs - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%NumOuts - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutSwtch - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%UnJckF - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(InData%Delim) - IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%OutFmt) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%OutSFmt) - IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i1 = LBOUND(InData%FGL,1), UBOUND(InData%FGL,1) + ReKiBuf(Re_Xferred) = InData%FGL(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IntKiBuf(Int_Xferred) = InData%NMOutputs + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutSwtch + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%UnJckF + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(InData%Delim) + IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%OutSFmt) + IntKiBuf(Int_Xferred) = ICHAR(InData%OutSFmt(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I IF ( .NOT. ALLOCATED(InData%MoutLst) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9536,16 +9543,16 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutAll , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%OutReact , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllInt - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutAllDims - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%OutDec - Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutAll, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutReact, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutAllInt + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutAllDims + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%OutDec + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Jac_u_indx) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9559,8 +9566,12 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Jac_u_indx,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Jac_u_indx)>0) IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(InData%Jac_u_indx))-1 ) = PACK(InData%Jac_u_indx,.TRUE.) - Int_Xferred = Int_Xferred + SIZE(InData%Jac_u_indx) + DO i2 = LBOUND(InData%Jac_u_indx,2), UBOUND(InData%Jac_u_indx,2) + DO i1 = LBOUND(InData%Jac_u_indx,1), UBOUND(InData%Jac_u_indx,1) + IntKiBuf(Int_Xferred) = InData%Jac_u_indx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( .NOT. ALLOCATED(InData%du) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9572,17 +9583,21 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%du,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%du)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%du))-1 ) = PACK(InData%du,.TRUE.) - Db_Xferred = Db_Xferred + SIZE(InData%du) + DO i1 = LBOUND(InData%du,1), UBOUND(InData%du,1) + DbKiBuf(Db_Xferred) = InData%du(i1) + Db_Xferred = Db_Xferred + 1 + END DO END IF - DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%dx))-1 ) = PACK(InData%dx,.TRUE.) - Db_Xferred = Db_Xferred + SIZE(InData%dx) - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Jac_ny - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+(1)-1 ) = InData%Jac_nx - Int_Xferred = Int_Xferred + 1 - IntKiBuf ( Int_Xferred:Int_Xferred+1-1 ) = TRANSFER( InData%RotStates , IntKiBuf(1), 1) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%dx,1), UBOUND(InData%dx,1) + DbKiBuf(Db_Xferred) = InData%dx(i1) + Db_Xferred = Db_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%Jac_ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%Jac_nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotStates, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackParam SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -9613,16 +9628,16 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%SDDeltaT = DbKiBuf( Db_Xferred ) - Db_Xferred = Db_Xferred + 1 - OutData%IntMethod = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF_red = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Nmembers = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%SDDeltaT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%IntMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF_red = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Nmembers = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Elems not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9639,15 +9654,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Elems.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Elems)>0) OutData%Elems = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Elems))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Elems) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%Elems,2), UBOUND(OutData%Elems,2) + DO i1 = LBOUND(OutData%Elems,1), UBOUND(OutData%Elems,1) + OutData%Elems(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated Int_Xferred = Int_Xferred + 1 @@ -9705,8 +9717,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%reduced = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + OutData%reduced = TRANSFER(IntKiBuf(Int_Xferred), OutData%reduced) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9723,15 +9735,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_red.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%T_red) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%T_red,2), UBOUND(OutData%T_red,2) + DO i1 = LBOUND(OutData%T_red,1), UBOUND(OutData%T_red,1) + OutData%T_red(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated Int_Xferred = Int_Xferred + 1 @@ -9861,15 +9870,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElemsDOF.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%ElemsDOF)>0) OutData%ElemsDOF = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ElemsDOF))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ElemsDOF) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%ElemsDOF,2), UBOUND(OutData%ElemsDOF,2) + DO i1 = LBOUND(OutData%ElemsDOF,1), UBOUND(OutData%ElemsDOF,1) + OutData%ElemsDOF(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DOFred2Nodes not allocated Int_Xferred = Int_Xferred + 1 @@ -9887,22 +9893,19 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DOFred2Nodes.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%DOFred2Nodes)>0) OutData%DOFred2Nodes = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%DOFred2Nodes))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%DOFred2Nodes) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%DOFred2Nodes,2), UBOUND(OutData%DOFred2Nodes,2) + DO i1 = LBOUND(OutData%DOFred2Nodes,1), UBOUND(OutData%DOFred2Nodes,1) + OutData%DOFred2Nodes(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF - OutData%nDOFM = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%SttcSolve = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%ExtraMoment = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + OutData%nDOFM = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SttcSolve = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ExtraMoment = TRANSFER(IntKiBuf(Int_Xferred), OutData%ExtraMoment) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -9916,15 +9919,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%KMMDiag)>0) OutData%KMMDiag = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KMMDiag))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KMMDiag) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%KMMDiag,1), UBOUND(OutData%KMMDiag,1) + OutData%KMMDiag(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMMDiag not allocated Int_Xferred = Int_Xferred + 1 @@ -9939,15 +9937,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMMDiag.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%CMMDiag)>0) OutData%CMMDiag = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMMDiag))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CMMDiag) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%CMMDiag,1), UBOUND(OutData%CMMDiag,1) + OutData%CMMDiag(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MMB not allocated Int_Xferred = Int_Xferred + 1 @@ -10052,15 +10045,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_12.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%D1_12)>0) OutData%D1_12 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%D1_12))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%D1_12) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%D1_12,2), UBOUND(OutData%D1_12,2) + DO i1 = LBOUND(OutData%D1_12,1), UBOUND(OutData%D1_12,1) + OutData%D1_12(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 not allocated Int_Xferred = Int_Xferred + 1 @@ -10344,15 +10334,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CBB)>0) OutData%CBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CBB) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%CBB,2), UBOUND(OutData%CBB,2) + DO i1 = LBOUND(OutData%CBB,1), UBOUND(OutData%CBB,1) + OutData%CBB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMB not allocated Int_Xferred = Int_Xferred + 1 @@ -10370,15 +10357,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CMB)>0) OutData%CMB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CMB) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%CMB,2), UBOUND(OutData%CMB,2) + DO i1 = LBOUND(OutData%CMB,1), UBOUND(OutData%CMB,1) + OutData%CMB(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated Int_Xferred = Int_Xferred + 1 @@ -10396,15 +10380,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBM.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CBM)>0) OutData%CBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CBM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CBM) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%CBM,2), UBOUND(OutData%CBM,2) + DO i1 = LBOUND(OutData%CBM,1), UBOUND(OutData%CBM,1) + OutData%CBM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM not allocated Int_Xferred = Int_Xferred + 1 @@ -10422,15 +10403,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMM.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%CMM)>0) OutData%CMM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CMM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%CMM) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%CMM,2), UBOUND(OutData%CMM,2) + DO i1 = LBOUND(OutData%CMM,1), UBOUND(OutData%CMM,1) + OutData%CMM(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated Int_Xferred = Int_Xferred + 1 @@ -10468,15 +10446,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_st_g.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%UL_st_g)>0) OutData%UL_st_g = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%UL_st_g))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%UL_st_g) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%UL_st_g,1), UBOUND(OutData%UL_st_g,1) + OutData%UL_st_g(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T not allocated Int_Xferred = Int_Xferred + 1 @@ -10540,15 +10513,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KLLm1.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%KLLm1)>0) OutData%KLLm1 = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KLLm1))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KLLm1) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%KLLm1,2), UBOUND(OutData%KLLm1,2) + DO i1 = LBOUND(OutData%KLLm1,1), UBOUND(OutData%KLLm1,1) + OutData%KLLm1(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AM2Jac not allocated Int_Xferred = Int_Xferred + 1 @@ -10637,14 +10607,14 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - OutData%nNodes = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_I = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nNodes_C = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%nNodes = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_I = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_L = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nNodes_C = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10661,15 +10631,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_I)>0) OutData%Nodes_I = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_I))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_I) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%Nodes_I,2), UBOUND(OutData%Nodes_I,2) + DO i1 = LBOUND(OutData%Nodes_I,1), UBOUND(OutData%Nodes_I,1) + OutData%Nodes_I(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_L not allocated Int_Xferred = Int_Xferred + 1 @@ -10687,15 +10654,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_L)>0) OutData%Nodes_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_L))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_L) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%Nodes_L,2), UBOUND(OutData%Nodes_L,2) + DO i1 = LBOUND(OutData%Nodes_L,1), UBOUND(OutData%Nodes_L,1) + OutData%Nodes_L(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_C not allocated Int_Xferred = Int_Xferred + 1 @@ -10713,40 +10677,37 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_C.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Nodes_C)>0) OutData%Nodes_C = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Nodes_C))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Nodes_C) - DEALLOCATE(mask2) - END IF - OutData%nDOFI__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFI_Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFI_F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFL_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFC_F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOFR__ = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__Rb = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__L = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%nDOF__F = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(OutData%Nodes_C,2), UBOUND(OutData%Nodes_C,2) + DO i1 = LBOUND(OutData%Nodes_C,1), UBOUND(OutData%Nodes_C,1) + OutData%Nodes_C(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + OutData%nDOFI__ = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_Rb = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFI_F = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFL_L = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC__ = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_Rb = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_L = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFC_F = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOFR__ = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__Rb = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__L = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nDOF__F = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI__ not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10760,15 +10721,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI__.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI__)>0) OutData%IDI__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI__) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDI__,1), UBOUND(OutData%IDI__,1) + OutData%IDI__(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_Rb not allocated Int_Xferred = Int_Xferred + 1 @@ -10783,15 +10739,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_Rb.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI_Rb)>0) OutData%IDI_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI_Rb) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDI_Rb,1), UBOUND(OutData%IDI_Rb,1) + OutData%IDI_Rb(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDI_F not allocated Int_Xferred = Int_Xferred + 1 @@ -10806,15 +10757,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDI_F.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDI_F)>0) OutData%IDI_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDI_F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDI_F) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDI_F,1), UBOUND(OutData%IDI_F,1) + OutData%IDI_F(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDL_L not allocated Int_Xferred = Int_Xferred + 1 @@ -10829,15 +10775,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDL_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDL_L)>0) OutData%IDL_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDL_L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDL_L) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDL_L,1), UBOUND(OutData%IDL_L,1) + OutData%IDL_L(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC__ not allocated Int_Xferred = Int_Xferred + 1 @@ -10852,15 +10793,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC__.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC__)>0) OutData%IDC__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC__) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDC__,1), UBOUND(OutData%IDC__,1) + OutData%IDC__(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_Rb not allocated Int_Xferred = Int_Xferred + 1 @@ -10875,15 +10811,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_Rb.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_Rb)>0) OutData%IDC_Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_Rb) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDC_Rb,1), UBOUND(OutData%IDC_Rb,1) + OutData%IDC_Rb(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_L not allocated Int_Xferred = Int_Xferred + 1 @@ -10898,15 +10829,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_L)>0) OutData%IDC_L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_L) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDC_L,1), UBOUND(OutData%IDC_L,1) + OutData%IDC_L(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDC_F not allocated Int_Xferred = Int_Xferred + 1 @@ -10921,15 +10847,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDC_F.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDC_F)>0) OutData%IDC_F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDC_F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDC_F) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDC_F,1), UBOUND(OutData%IDC_F,1) + OutData%IDC_F(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IDR__ not allocated Int_Xferred = Int_Xferred + 1 @@ -10944,15 +10865,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IDR__.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%IDR__)>0) OutData%IDR__ = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%IDR__))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%IDR__) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%IDR__,1), UBOUND(OutData%IDR__,1) + OutData%IDR__(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__Rb not allocated Int_Xferred = Int_Xferred + 1 @@ -10967,15 +10883,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__Rb.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__Rb)>0) OutData%ID__Rb = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__Rb))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__Rb) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%ID__Rb,1), UBOUND(OutData%ID__Rb,1) + OutData%ID__Rb(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__L not allocated Int_Xferred = Int_Xferred + 1 @@ -10990,15 +10901,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__L.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__L)>0) OutData%ID__L = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__L))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__L) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%ID__L,1), UBOUND(OutData%ID__L,1) + OutData%ID__L(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ID__F not allocated Int_Xferred = Int_Xferred + 1 @@ -11013,15 +10919,10 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ID__F.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%ID__F)>0) OutData%ID__F = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%ID__F))-1 ), mask1, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%ID__F) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%ID__F,1), UBOUND(OutData%ID__F,1) + OutData%ID__F(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated Int_Xferred = Int_Xferred + 1 @@ -11036,36 +10937,31 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%FGL)>0) OutData%FGL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FGL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FGL) - DEALLOCATE(mask1) - END IF - OutData%NMOutputs = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%NumOuts = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutSwtch = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%UnJckF = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - DO I = 1, LEN(OutData%Delim) - OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%OutFmt) - OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%OutSFmt) - OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i1 = LBOUND(OutData%FGL,1), UBOUND(OutData%FGL,1) + OutData%FGL(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + OutData%NMOutputs = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NumOuts = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutSwtch = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%UnJckF = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + DO I = 1, LEN(OutData%Delim) + OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutFmt) + OutData%OutFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%OutSFmt) + OutData%OutSFmt(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MoutLst not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -11290,16 +11186,16 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - OutData%OutAll = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%OutReact = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 - OutData%OutAllInt = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutAllDims = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%OutDec = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 + OutData%OutAll = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutAll) + Int_Xferred = Int_Xferred + 1 + OutData%OutReact = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutReact) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllInt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutAllDims = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%OutDec = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Jac_u_indx not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -11316,15 +11212,12 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Jac_u_indx.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask2 = .TRUE. - IF (SIZE(OutData%Jac_u_indx)>0) OutData%Jac_u_indx = UNPACK( IntKiBuf ( Int_Xferred:Int_Xferred+(SIZE(OutData%Jac_u_indx))-1 ), mask2, 0_IntKi ) - Int_Xferred = Int_Xferred + SIZE(OutData%Jac_u_indx) - DEALLOCATE(mask2) + DO i2 = LBOUND(OutData%Jac_u_indx,2), UBOUND(OutData%Jac_u_indx,2) + DO i1 = LBOUND(OutData%Jac_u_indx,1), UBOUND(OutData%Jac_u_indx,1) + OutData%Jac_u_indx(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! du not allocated Int_Xferred = Int_Xferred + 1 @@ -11339,33 +11232,23 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%du.', ErrStat, ErrMsg,RoutineName) RETURN END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%du)>0) OutData%du = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%du))-1 ), mask1, 0.0_DbKi ), R8Ki) - Db_Xferred = Db_Xferred + SIZE(OutData%du) - DEALLOCATE(mask1) + DO i1 = LBOUND(OutData%du,1), UBOUND(OutData%du,1) + OutData%du(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END IF i1_l = LBOUND(OutData%dx,1) i1_u = UBOUND(OutData%dx,1) - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - OutData%dx = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%dx))-1 ), mask1, 0.0_DbKi ), R8Ki) - Db_Xferred = Db_Xferred + SIZE(OutData%dx) - DEALLOCATE(mask1) - OutData%Jac_ny = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%Jac_nx = IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - OutData%RotStates = TRANSFER( IntKiBuf( Int_Xferred ), mask0 ) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(OutData%dx,1), UBOUND(OutData%dx,1) + OutData%dx(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + OutData%Jac_ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Jac_nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RotStates = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotStates) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_UnPackParam SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) From 932b6f3419b880fd0b8e8974988f89d82d46e146 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 7 Aug 2020 13:03:31 -0600 Subject: [PATCH 258/377] FlexSub: starting controllable cables --- modules/subdyn/src/SD_FEM.f90 | 83 ++++++++++- modules/subdyn/src/SubDyn.f90 | 23 ++- modules/subdyn/src/SubDyn_Registry.txt | 9 +- modules/subdyn/src/SubDyn_Types.f90 | 196 ++++++++++++++++++++++++- 4 files changed, 303 insertions(+), 8 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 282443dc5..cc2433552 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -35,7 +35,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) - INTEGER(IntKi), PARAMETER :: PropSetsCCol = 5 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0, CtrlChannel) + INTEGER(IntKi), PARAMETER :: PropSetsCCol = 5 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: COSMsCol = 10 ! Number of columns in (cosine matrices) COSMs (COSMID,COSM11,COSM12,COSM13,COSM21,COSM22,COSM23,COSM31,COSM32,COSM33) INTEGER(IntKi), PARAMETER :: CMassCol = 11 ! Number of columns in Concentrated Mass (CMJointID,JMass,JMXX,JMYY,JMZZ, Optional:JMXY,JMXZ,JMYZ,CGX,CGY,CGZ) @@ -1100,6 +1100,87 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM +!> Init for control Cable force +!! The change of cable forces due to the control is linear, so we just store a "unit" force vector +!! We will just scale this vector at each time step based on the control input (Tcontrol): +!! Fcontrol = (Tcontrol-T0) * Funit +SUBROUTINE ControlCableForceInit(Init, p, m, ErrStat, ErrMsg) + TYPE(SD_InitType), INTENT(INOUT) :: Init !< Remove me, kept just in case for now + TYPE(SD_ParameterType), INTENT(IN ) :: p + TYPE(SD_MiscVarType), INTENT(INOUT) :: m + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K + INTEGER :: iGlob + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + INTEGER(IntKi) :: iNode !< Node index + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system + real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node + ErrMsg = "" + ErrStat = ErrID_None + + ! Allocating necessary arrays + CALL AllocAry( m%FC_red , p%nDOF_red, 'm%FC0_red', ErrStat2, ErrMsg2); if(Failed()) return; ! Constant cable force + CALL AllocAry( m%FC_red_unit , p%nDOF_red, 'm%FC_red' , ErrStat2, ErrMsg2); if(Failed()) return; ! Control cable force + m%FC_red = 0.0_ReKi + m%FC_red_unit = 0.0_ReKi + + ! Setting up unit force vector + call ControlCableForce_Unit(p, m%FC_red_unit, ErrStat2, ErrMsg2); if(Failed()) return; + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableForceInit') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed +END SUBROUTINE ControlCableForceInit + +!> Init for control Cable force +!! TODO TODO Expensive implementation for now +SUBROUTINE ControlCableForce_Unit(p, FC_red, ErrStat, ErrMsg) + TYPE(SD_ParameterType), INTENT(IN ) :: p + real(ReKi), DIMENSION(:), INTENT(INOUT) :: FC_red + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + INTEGER :: I, J, K, iGlob + real(ReKi), DIMENSION(:), allocatable :: FC + REAL(ReKi) :: FCe(12) ! Pretension force from cable element + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + ErrMsg = "" + ErrStat = ErrID_None + CALL AllocAry(FC ,p%nDOF , 'FC' , ErrStat2, ErrMsg2); if(Failed()) return; ! Control cable force + + ! loop over all elements, compute element matrices and assemble into global matrices + DO i = 1, size(p%ElemProps) ! TODO loop on cable only + if (p%ElemProps(i)%eType==idMemberCable) then + CALL ElemF_Cable(1.0_ReKi, p%ElemProps(i)%DirCos, FCe) !< NOTE: using unitary load T0=1.0_ReKi + ! --- Assembly in global unconstrained system + IDOF = p%ElemsDOF(1:12, i) + FC( IDOF ) = FC( IDOF ) + FCe(1:12) ! Note: gravity and pretension cable forces + endif + ENDDO + ! Transforming the vector into reduced, direct elimination system: + FC_red = matmul(transpose(p%T_red), FC) + if(allocated(FC)) deallocate(FC) + +CONTAINS + LOGICAL FUNCTION Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableForce') + Failed = ErrStat >= AbortErrLev + END FUNCTION Failed +END SUBROUTINE ControlCableForce_Unit + + + + + !> Add soil stiffness and mass to global system matrices SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) real(ReKi), dimension(:,:), intent(inout) :: M diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ea5aaba8c..471c5b191 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -230,6 +230,13 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! --- Additional Damping and stiffness at pin/ball/universal joints CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return + ! --- Prepare for control cable load, RHS + if (any(Init%PropsC(:,5)>0)) then + print*,'Need to assemble Cable Force' + CALL ControlCableForceInit(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return + print*,'Controlable cables, feature not ready.' + STOP + endif ! -------------------------------------------------------------------------------- ! --- CB, Misc @@ -976,11 +983,21 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsC, 'NPropSetsC', 'Number of cable properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Cable properties Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + IF (Check( Init%NPropSetsC < 0, 'NPropSetsCable must be >=0')) return CALL AllocAry(Init%PropSetsC, Init%NPropSetsC, PropSetsCCol, 'PropSetsC', ErrStat2, ErrMsg2); if(Failed()) return DO I = 1, Init%NPropSetsC - CALL ReadAry( UnIn, SDInputFile, Init%PropSetsC(I,:), PropSetsCCol, 'PropSetsC', 'PropSetsC ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + !CALL ReadAry( UnIn, SDInputFile, Init%PropSetsC(I,:), PropSetsCCol, 'PropSetsC', 'PropSetsC ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading cable property line'; if (Failed()) return + call ReadFAryFromStr(Line, Init%PropSetsC(I,:), PropSetsCCol, nColValid, nColNumeric); + if ((nColValid/=nColNumeric).or.((nColNumeric/=4).and.(nColNumeric/=PropSetsCCol)) ) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Cable property line must consist of 4 or 5 numerical values. Problematic line: "'//trim(Line)//'"') + return + endif + if (nColNumeric==4) then + call LegacyWarning('Using 4 values instead of 5 for cable properties. Cable will have constant properties and wont be controllable.') + Init%PropSetsC(:,5:PropSetsCCol)=0 ! No CtrlChannel + endif ENDDO - IF (Check( Init%NPropSetsC < 0, 'NPropSetsCable must be >=0')) return !----------------------- RIGID LINK PROPERTIES ------------------------------------ CALL ReadCom ( UnIn, SDInputFile, 'Rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsR, 'NPropSetsR', 'Number of rigid link properties' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -3056,7 +3073,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) XYZ2 = Init%Joints(iNode2,2:4) CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), DirCos, mLength, ErrStat, ErrMsg) DirCos=TRANSPOSE(DirCos) !This is now global to local - WRITE(UnSum, '("#",I9,9(ES15.6E2))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) + WRITE(UnSum, '("#",I9,9(ES11.3E2))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) ENDDO !------------------------------------------------------------------------------------------------------------- diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 20967fcd7..6b4d4889a 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -116,7 +116,7 @@ typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" typedef ^ ^ ReKi F {:} - - "System force vector" N -typedef ^ ^ ReKi FG {:} - - "Gravity force vector" N +typedef ^ ^ ReKi FG {:} - - "Gravity force vector (include initial Cable force T0)" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" @@ -159,6 +159,8 @@ typedef ^ ^ ReKi U_full_dotdot {:} typedef ^ ^ ReKi U_red {:} - - typedef ^ ^ ReKi U_red_dot {:} - - typedef ^ ^ ReKi U_red_dotdot {:} - - +typedef ^ ^ ReKi FC_red {:} - - "Cable Force vector (for varying cable load)" N +typedef ^ ^ ReKi FC_red_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N ### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" @@ -280,8 +282,9 @@ typedef ^ ParameterType Integer Jac_nx - - - "half the numb typedef ^ ParameterType logical RotStates - - - "Orient states in rotating frame during linearization? (flag)" - # ============================== Inputs ============================================================================================================================================ -typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" -typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" +typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" +typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" +typedef ^ InputType ReKi CableTension {:} - - "Cable tension, control input" # ============================== Outputs ============================================================================================================================================ typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a9d6ffdb4..91c712327 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -150,7 +150,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (include initial Cable force T0) [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] @@ -201,6 +201,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_red !< Cable Force vector (for varying cable load) [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_red_unit !< Cable Force vector (for varying cable load, of unit cable load) [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] @@ -318,6 +320,7 @@ MODULE SubDyn_Types TYPE, PUBLIC :: SD_InputType TYPE(MeshType) :: TPMesh !< Transition piece inputs on a point mesh [-] TYPE(MeshType) :: LMesh !< Point mesh for interior node inputs [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CableTension !< Cable tension, control input [-] END TYPE SD_InputType ! ======================= ! ========= SD_OutputType ======= @@ -5839,6 +5842,30 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot ENDIF +IF (ALLOCATED(SrcMiscData%FC_red)) THEN + i1_l = LBOUND(SrcMiscData%FC_red,1) + i1_u = UBOUND(SrcMiscData%FC_red,1) + IF (.NOT. ALLOCATED(DstMiscData%FC_red)) THEN + ALLOCATE(DstMiscData%FC_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FC_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FC_red = SrcMiscData%FC_red +ENDIF +IF (ALLOCATED(SrcMiscData%FC_red_unit)) THEN + i1_l = LBOUND(SrcMiscData%FC_red_unit,1) + i1_u = UBOUND(SrcMiscData%FC_red_unit,1) + IF (.NOT. ALLOCATED(DstMiscData%FC_red_unit)) THEN + ALLOCATE(DstMiscData%FC_red_unit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FC_red_unit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%FC_red_unit = SrcMiscData%FC_red_unit +ENDIF IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN i1_l = LBOUND(SrcMiscData%SDWrOutput,1) i1_u = UBOUND(SrcMiscData%SDWrOutput,1) @@ -5930,6 +5957,12 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%U_red_dotdot)) THEN DEALLOCATE(MiscData%U_red_dotdot) ENDIF +IF (ALLOCATED(MiscData%FC_red)) THEN + DEALLOCATE(MiscData%FC_red) +ENDIF +IF (ALLOCATED(MiscData%FC_red_unit)) THEN + DEALLOCATE(MiscData%FC_red_unit) +ENDIF IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) ENDIF @@ -6049,6 +6082,16 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot END IF + Int_BufSz = Int_BufSz + 1 ! FC_red allocated yes/no + IF ( ALLOCATED(InData%FC_red) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FC_red upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FC_red) ! FC_red + END IF + Int_BufSz = Int_BufSz + 1 ! FC_red_unit allocated yes/no + IF ( ALLOCATED(InData%FC_red_unit) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FC_red_unit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FC_red_unit) ! FC_red_unit + END IF Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no IF ( ALLOCATED(InData%SDWrOutput) ) THEN Int_BufSz = Int_BufSz + 2*1 ! SDWrOutput upper/lower bounds for each dimension @@ -6281,6 +6324,32 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz IF (SIZE(InData%U_red_dotdot)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%U_red_dotdot))-1 ) = PACK(InData%U_red_dotdot,.TRUE.) Re_Xferred = Re_Xferred + SIZE(InData%U_red_dotdot) END IF + IF ( .NOT. ALLOCATED(InData%FC_red) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FC_red,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FC_red,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FC_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FC_red))-1 ) = PACK(InData%FC_red,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FC_red) + END IF + IF ( .NOT. ALLOCATED(InData%FC_red_unit) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FC_red_unit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FC_red_unit,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%FC_red_unit)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FC_red_unit))-1 ) = PACK(InData%FC_red_unit,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%FC_red_unit) + END IF IF ( .NOT. ALLOCATED(InData%SDWrOutput) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6714,6 +6783,52 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + SIZE(OutData%U_red_dotdot) DEALLOCATE(mask1) END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_red not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FC_red)) DEALLOCATE(OutData%FC_red) + ALLOCATE(OutData%FC_red(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FC_red.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FC_red)>0) OutData%FC_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FC_red))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FC_red) + DEALLOCATE(mask1) + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_red_unit not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FC_red_unit)) DEALLOCATE(OutData%FC_red_unit) + ALLOCATE(OutData%FC_red_unit(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FC_red_unit.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%FC_red_unit)>0) OutData%FC_red_unit = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FC_red_unit))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%FC_red_unit) + DEALLOCATE(mask1) + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SDWrOutput not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -11476,6 +11591,7 @@ SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInput' @@ -11488,6 +11604,18 @@ SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) CALL MeshCopy( SrcInputData%LMesh, DstInputData%LMesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInputData%CableTension)) THEN + i1_l = LBOUND(SrcInputData%CableTension,1) + i1_u = UBOUND(SrcInputData%CableTension,1) + IF (.NOT. ALLOCATED(DstInputData%CableTension)) THEN + ALLOCATE(DstInputData%CableTension(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%CableTension.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%CableTension = SrcInputData%CableTension +ENDIF END SUBROUTINE SD_CopyInput SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) @@ -11501,6 +11629,9 @@ SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) ErrMsg = "" CALL MeshDestroy( InputData%TPMesh, ErrStat, ErrMsg ) CALL MeshDestroy( InputData%LMesh, ErrStat, ErrMsg ) +IF (ALLOCATED(InputData%CableTension)) THEN + DEALLOCATE(InputData%CableTension) +ENDIF END SUBROUTINE SD_DestroyInput SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -11573,6 +11704,11 @@ SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 1 ! CableTension allocated yes/no + IF ( ALLOCATED(InData%CableTension) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CableTension upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CableTension) ! CableTension + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -11656,6 +11792,19 @@ SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + IF ( .NOT. ALLOCATED(InData%CableTension) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CableTension,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CableTension,1) + Int_Xferred = Int_Xferred + 2 + + IF (SIZE(InData%CableTension)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%CableTension))-1 ) = PACK(InData%CableTension,.TRUE.) + Re_Xferred = Re_Xferred + SIZE(InData%CableTension) + END IF END SUBROUTINE SD_PackInput SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -11677,6 +11826,7 @@ SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg LOGICAL, ALLOCATABLE :: mask3(:,:,:) LOGICAL, ALLOCATABLE :: mask4(:,:,:,:) LOGICAL, ALLOCATABLE :: mask5(:,:,:,:,:) + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInput' @@ -11770,6 +11920,29 @@ SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CableTension not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CableTension)) DEALLOCATE(OutData%CableTension) + ALLOCATE(OutData%CableTension(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CableTension.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + mask1 = .TRUE. + IF (SIZE(OutData%CableTension)>0) OutData%CableTension = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%CableTension))-1 ), mask1, 0.0_ReKi ) + Re_Xferred = Re_Xferred + SIZE(OutData%CableTension) + DEALLOCATE(mask1) + END IF END SUBROUTINE SD_UnPackInput SUBROUTINE SD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg ) @@ -12211,6 +12384,8 @@ SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp1' REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors ! Initialize ErrStat @@ -12229,6 +12404,14 @@ SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp1(u1%LMesh, u2%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%CableTension) .AND. ALLOCATED(u1%CableTension)) THEN + ALLOCATE(b1(SIZE(u_out%CableTension,1))) + ALLOCATE(c1(SIZE(u_out%CableTension,1))) + b1 = -(u1%CableTension - u2%CableTension)/t(2) + u_out%CableTension = u1%CableTension + b1 * t_out + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SD_Input_ExtrapInterp1 @@ -12260,6 +12443,8 @@ SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrM INTEGER(IntKi) :: order ! order of polynomial fit (max 2) REAL(DbKi) :: b0 ! temporary for extrapolation/interpolation REAL(DbKi) :: c0 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: b1 ! temporary for extrapolation/interpolation + REAL(DbKi),ALLOCATABLE,DIMENSION(:) :: c1 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'SD_Input_ExtrapInterp2' @@ -12285,6 +12470,15 @@ SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrM CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp2(u1%LMesh, u2%LMesh, u3%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) +IF (ALLOCATED(u_out%CableTension) .AND. ALLOCATED(u1%CableTension)) THEN + ALLOCATE(b1(SIZE(u_out%CableTension,1))) + ALLOCATE(c1(SIZE(u_out%CableTension,1))) + b1 = (t(3)**2*(u1%CableTension - u2%CableTension) + t(2)**2*(-u1%CableTension + u3%CableTension))/(t(2)*t(3)*(t(2) - t(3))) + c1 = ( (t(2)-t(3))*u1%CableTension + t(3)*u2%CableTension - t(2)*u3%CableTension ) / (t(2)*t(3)*(t(2) - t(3))) + u_out%CableTension = u1%CableTension + b1 * t_out + c1 * t_out**2 + DEALLOCATE(b1) + DEALLOCATE(c1) +END IF ! check if allocated END SUBROUTINE SD_Input_ExtrapInterp2 From 072635f0bc3171c5c024cba1efb15bf7d53a2d0d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 7 Aug 2020 13:18:44 -0600 Subject: [PATCH 259/377] FlexSub: adding check that properties match for non-beam --- modules/subdyn/src/SD_FEM.f90 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index cc2433552..90c74281f 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -376,9 +376,16 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) print*,'Element type unknown',mType STOP end if - + ! Test that the two properties match for non-beam + if (mType/=idMemberBeam) then + if (Init%Members(iMem, iMProp)/=Init%Members(iMem, iMProp+1)) then + call Fatal('Properties should be the same at each node for non-beam members. Check member with ID: '//TRIM(Num2LStr(Init%Members(iMem,1)))) + return + endif + endif if (p%Elems(iMem,n)<=0) then CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') + return endif END DO !n, loop through property ids ! Column 6: member type @@ -494,7 +501,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF if (eType/=idMemberBeam) then - ! --- Cables and rigid links are not subdivided + ! --- Cables and rigid links are not subdivided and have same prop at nodes ! No need to create new properties or new nodes Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, 2) = Node2 From 8f9c318b2b7bdfcdd8f64a09020f6f1f26b70b40 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 11:47:25 -0600 Subject: [PATCH 260/377] FlexSub: changed logic for eigensolver --- modules/subdyn/src/FEM.f90 | 101 ++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 92e2ba0b6..dd57104aa 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -27,24 +27,24 @@ MODULE FEM CONTAINS !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors -SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) +SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix - LOGICAL, INTENT(IN ) :: bCheckSingularity !< If True, check for singularities REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! LOCALS - REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), ALPHAR(:), ALPHAI(:), BETA(:) ! eigensolver variables + REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), AlphaR(:), AlphaI(:), BETA(:) ! eigensolver variables INTEGER :: i INTEGER :: LWORK !variables for the eigensolver INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 + REAL(LaKi) :: normA ErrStat = ErrID_None ErrMsg = '' @@ -53,9 +53,9 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM LWORK=8*N + 16 !this is what the eigensolver wants >> bjj: +16 because of MKL ?ggev documenation ( "lwork >= max(1, 8n+16) for real flavors"), though LAPACK documenation says 8n is fine !bjj: there seems to be a memory problem in *GGEV, so I'm making the WORK array larger to see if I can figure it out CALL AllocAry( Work, LWORK, 'Work', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAR, N, 'ALPHAR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( ALPHAI, N, 'ALPHAI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') - CALL AllocAry( BETA, N, 'BETA', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( AlphaR, N, 'AlphaR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( AlphaI, N, 'AlphaI', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') + CALL AllocAry( Beta, N, 'Beta', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( VL, N, N, 'VL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'EigenSolve') CALL AllocAry( KEY, N, 'KEY', ErrStat2, ErrMsg2 ); if(Failed()) return @@ -63,45 +63,53 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 ! bjj: This comes from the LAPACK documentation: - ! Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. - ! Thus, the user should avoid naively computing the ratio alpha/beta. However, ALPHAR and ALPHAI will be always less + ! Note: the quotients AlphaR(j)/BETA(j) and AlphaI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. + ! Thus, the user should avoid naively computing the ratio Alpha/beta. However, AlphaR and AlphaI will be always less ! than and usually comparable with norm(A) in magnitude, and BETA always less than and usually comparable with norm(B). - ! Omega2=ALPHAR/BETA !Note this may not be correct if ALPHAI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted - CALL LAPACK_ggev('N','V',N ,K, M, ALPHAR, ALPHAI, BETA, VL, EigVect, WORK, LWORK, ErrStat2, ErrMsg2) + ! Omega2=AlphaR/BETA !Note this may not be correct if AlphaI<>0 and/or BETA=0 TO INCLUDE ERROR CHECK, also they need to be sorted + CALL LAPACK_ggev('N','V',N ,K, M, AlphaR, AlphaI, Beta, VL, EigVect, WORK, LWORK, ErrStat2, ErrMsg2) if(Failed()) return ! --- Determinign and sorting eigen frequencies + Omega2(:) =0.0_LaKi DO I=1,N !Initialize the key and calculate Omega KEY(I)=I - IF ( AlphaR(I)<0.0_LAKi ) THEN - !print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif - !ELSE IF ( .not.EqualRealNos(AlphaI(I),0.0_LAKi )) THEN - ! print*,'I', I, AlphaR(I), AlphaI(I), Beta(I), real(AlphaR(I)/Beta(I)) - ! ErrStat2=ErrID_Fatal - ! ErrMsg2= 'Complex eigenvalue found, system may be singular (may contain rigid body modes)' - ! if(Failed()) return - ELSE IF ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) THEN - Omega2(I) = HUGE(Omega2) ! bjj: should this be an error? - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Large eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return + if ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) then + ! --- Beta =0 + print*,'Large eigenvalue found, system may be ill-conditioned' + Omega2(I) = HUGE(1.0_LaKi) + elseif ( EqualRealNos(real(AlphaI(I),ReKi),0.0_ReKi) ) THEN + ! --- Real Eigenvalues + IF ( AlphaR(I)<0.0_LaKi ) THEN + if ( (AlphaR(I)/Beta(I))<1e-6_LaKi ) then + ! Tolerating very small negative eigenvalues + print*,'Negative eigenvalue found with small norm, system may be singular (may contain rigid body modes)' + Omega2(I)=0.0_LaKi + else + print*,'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + Omega2(I)=AlphaR(I)/Beta(I) + endif + else + Omega2(I) = AlphaR(I)/Beta(I) endif - ELSE IF ( EqualRealNos(real(ALPHAR(I),ReKi),0.0_ReKi) ) THEN - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Eigenvalue zero found, system is singular (may contain rigid body modes)' - if(Failed()) return + else + ! --- Complex Eigenvalues + normA = sqrt(AlphaR(I)**2 + AlphaI(I)**2) + if ( (normA/Beta(I))<1e-6_LaKi ) then + ! Tolerating very small eigenvalues with imaginary part + print*,'Complex eigenvalue found with small norm, approximating as 0' + Omega2(I) = 0.0_LaKi + elseif ( abs(AlphaR(I))>1e3_LaKi*abs(AlphaI(I)) ) then + ! Tolerating very small imaginary part compared to real part... (not pretty) + print*,'Complex eigenvalue found with small Im compare to Re' + !print*'AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) + Omega2(I) = AlphaR(I)/Beta(I) + else + print*,'Complex eigenvalue found, AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) + Omega2(I) = HUGE(1.0_LaKi) endif - ELSE - Omega2(I) = REAL( ALPHAR(I)/BETA(I), ReKi ) - END IF - ENDDO + endif + enddo ! Sorting CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return @@ -130,9 +138,9 @@ END FUNCTION Failed SUBROUTINE CleanupEigen() IF (ALLOCATED(Work) ) DEALLOCATE(Work) - IF (ALLOCATED(ALPHAR)) DEALLOCATE(ALPHAR) - IF (ALLOCATED(ALPHAI)) DEALLOCATE(ALPHAI) - IF (ALLOCATED(BETA) ) DEALLOCATE(BETA) + IF (ALLOCATED(AlphaR)) DEALLOCATE(AlphaR) + IF (ALLOCATED(AlphaI)) DEALLOCATE(AlphaI) + IF (ALLOCATED(Beta) ) DEALLOCATE(Beta) IF (ALLOCATED(VL) ) DEALLOCATE(VL) IF (ALLOCATED(KEY) ) DEALLOCATE(KEY) END SUBROUTINE CleanupEigen @@ -638,7 +646,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! --- Eigenvalue analysis CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL EigenSolve(K_LaKi, M_LaKi, N, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion do i = 1, NOmega @@ -649,11 +657,22 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega endif if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics Omega(i)=0.0_ReKi + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif elseif (Om2>0) then Omega(i)=sqrt(Om2) ! was getting floating invalid else + ! Negative eigenfrequency print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 Omega(i)= 0.0_ReKi + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif endif enddo if (present(bDOF)) then From e0ec315b4b10174d940b88304aec5dca4d2a6169 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 12:52:15 -0600 Subject: [PATCH 261/377] FlexSub: FEM and CB in double precision --- modules/subdyn/src/FEM.f90 | 484 +++++++++++++------------ modules/subdyn/src/SD_FEM.f90 | 58 +-- modules/subdyn/src/SubDyn.f90 | 77 ++-- modules/subdyn/src/SubDyn_Output.f90 | 13 +- modules/subdyn/src/SubDyn_Registry.txt | 35 +- modules/subdyn/src/SubDyn_Tests.f90 | 96 ++++- modules/subdyn/src/SubDyn_Types.f90 | 251 +++++-------- 7 files changed, 520 insertions(+), 494 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index dd57104aa..db38746da 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -22,29 +22,31 @@ MODULE FEM USE NWTC_Library IMPLICIT NONE - INTEGER, PARAMETER :: LAKi = R8Ki ! Define the kind to be used for LAPACK routines for getting eigenvalues/vectors. Apparently there is a problem with SGGEV's eigenvectors + INTEGER, PARAMETER :: FEKi = R8Ki ! Define the kind to be used for FEM CONTAINS !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors -SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) + +SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K - REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix - REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix - REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors - REAL(LaKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues + REAL(FEKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix + REAL(FEKi), INTENT(INOUT) :: M(N, N) !< Mass matrix + LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present + REAL(FEKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors + REAL(FEKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! LOCALS - REAL(LAKi), ALLOCATABLE :: WORK (:), VL(:,:), AlphaR(:), AlphaI(:), BETA(:) ! eigensolver variables + REAL(FEKi), ALLOCATABLE :: WORK (:), VL(:,:), AlphaR(:), AlphaI(:), BETA(:) ! eigensolver variables INTEGER :: i INTEGER :: LWORK !variables for the eigensolver INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - REAL(LaKi) :: normA + REAL(FEKi) :: normA ErrStat = ErrID_None ErrMsg = '' @@ -61,7 +63,7 @@ SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) ! --- Eigenvalue analysis ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. - ! DGGEV seems to work better, so I'm making these variables LAKi (which is set to R8Ki for now) - bjj 4/25/2014 + ! DGGEV seems to work better, so I'm making these variables FEKi (which is set to R8Ki for now) - bjj 4/25/2014 ! bjj: This comes from the LAPACK documentation: ! Note: the quotients AlphaR(j)/BETA(j) and AlphaI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. ! Thus, the user should avoid naively computing the ratio Alpha/beta. However, AlphaR and AlphaI will be always less @@ -71,20 +73,20 @@ SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) if(Failed()) return ! --- Determinign and sorting eigen frequencies - Omega2(:) =0.0_LaKi + Omega2(:) =0.0_FEKi DO I=1,N !Initialize the key and calculate Omega KEY(I)=I if ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) then ! --- Beta =0 print*,'Large eigenvalue found, system may be ill-conditioned' - Omega2(I) = HUGE(1.0_LaKi) + Omega2(I) = HUGE(1.0_FEKi) elseif ( EqualRealNos(real(AlphaI(I),ReKi),0.0_ReKi) ) THEN ! --- Real Eigenvalues - IF ( AlphaR(I)<0.0_LaKi ) THEN - if ( (AlphaR(I)/Beta(I))<1e-6_LaKi ) then + IF ( AlphaR(I)<0.0_FEKi ) THEN + if ( (AlphaR(I)/Beta(I))<1e-6_FEKi ) then ! Tolerating very small negative eigenvalues print*,'Negative eigenvalue found with small norm, system may be singular (may contain rigid body modes)' - Omega2(I)=0.0_LaKi + Omega2(I)=0.0_FEKi else print*,'Negative eigenvalue found, system may be singular (may contain rigid body modes)' Omega2(I)=AlphaR(I)/Beta(I) @@ -95,19 +97,29 @@ SUBROUTINE EigenSolve(K, M, N, EigVect, Omega2, ErrStat, ErrMsg ) else ! --- Complex Eigenvalues normA = sqrt(AlphaR(I)**2 + AlphaI(I)**2) - if ( (normA/Beta(I))<1e-6_LaKi ) then + if ( (normA/Beta(I))<1e-6_FEKi ) then ! Tolerating very small eigenvalues with imaginary part print*,'Complex eigenvalue found with small norm, approximating as 0' - Omega2(I) = 0.0_LaKi - elseif ( abs(AlphaR(I))>1e3_LaKi*abs(AlphaI(I)) ) then + Omega2(I) = 0.0_FEKi + elseif ( abs(AlphaR(I))>1e3_FEKi*abs(AlphaI(I)) ) then ! Tolerating very small imaginary part compared to real part... (not pretty) print*,'Complex eigenvalue found with small Im compare to Re' !print*'AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) Omega2(I) = AlphaR(I)/Beta(I) else print*,'Complex eigenvalue found, AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) - Omega2(I) = HUGE(1.0_LaKi) + Omega2(I) = HUGE(1.0_FEKi) + endif + endif + if (bCheckSingularity) then + if ( EqualRealNos(real(Omega2(I),ReKi),0.0_ReKi) ) THEN + ErrStat2=ErrID_Fatal + ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' + elseif (Omega2(I) < 0.0_FEKi) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' endif + if(Failed()) return endif enddo ! Sorting @@ -150,20 +162,20 @@ END SUBROUTINE EigenSolve !> Compute the determinant of a real matrix using an LU factorization FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) use NWTC_LAPACK, only: LAPACK_GETRF - REAL(LaKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect + REAL(FEKi), INTENT(IN ) :: A(:, :) !< Input matrix, no side effect INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - real(LaKi) :: det !< May easily overflow + real(FEKi) :: det !< May easily overflow integer(IntKi) :: i integer :: n integer, allocatable :: ipiv(:) - real(LaKi), allocatable :: PLU(:,:) - real(LaKi) :: ScaleVal + real(FEKi), allocatable :: PLU(:,:) + real(FEKi) :: ScaleVal n = size(A(1,:)) allocate(PLU(n,n)) allocate(ipiv(n)) - ScaleVal= 1.0_LaKi + ScaleVal= 1.0_FEKi PLU = A/ScaleVal ! general matrix factorization: Factor matrix into A=PLU. call LAPACK_GETRF( n, n, PLU, ipiv, ErrStat, ErrMsg ) !call dgetrf(n, n, PLU, n, ipiv, info) @@ -178,7 +190,7 @@ FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) ! As L has unit diagonal entries, the determinant can be computed ! from the product of U's diagonal entries. Additional sign changes ! stemming from the permutations P have to be taken into account as well. - det = 1.0_LaKi + det = 1.0_FEKi do i = 1,n if(ipiv(i) /= i) then ! additional sign change det = -det*PLU(i,i) @@ -241,25 +253,25 @@ end subroutine ChessBoard !! MRL = M(IDR, IDL), KRR = K(IDR, IDL) !! NOTE: generic code SUBROUTINE BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG, FGR, FGL, CC, CRR, CLL, CRL) - REAL(ReKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix - REAL(ReKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix + REAL(FEKi), INTENT(IN ) :: MM(:,:) !< Mass Matrix + REAL(FEKi), INTENT(IN ) :: KK(:,:) !< Stiffness matrix INTEGER(IntKi), INTENT(IN ) :: nR INTEGER(IntKi), INTENT(IN ) :: nL INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs - REAL(ReKi), INTENT( OUT) :: MRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: MLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: MRL(nR, nL) - REAL(ReKi), INTENT( OUT) :: KRR(nR, nR) - REAL(ReKi), INTENT( OUT) :: KLL(nL, nL) - REAL(ReKi), INTENT( OUT) :: KRL(nR, nL) - REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) - REAL(ReKi), OPTIONAL, INTENT(IN ) :: CC(:,:) !< Stiffness matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CRR(nR, nR) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CLL(nL, nL) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CRL(nR, nL) + REAL(FEKi), INTENT( OUT) :: MRR(nR, nR) + REAL(FEKi), INTENT( OUT) :: MLL(nL, nL) + REAL(FEKi), INTENT( OUT) :: MRL(nR, nL) + REAL(FEKi), INTENT( OUT) :: KRR(nR, nR) + REAL(FEKi), INTENT( OUT) :: KLL(nL, nL) + REAL(FEKi), INTENT( OUT) :: KRL(nR, nL) + REAL(FEKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGR(nR) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGL(nL) + REAL(FEKi), OPTIONAL, INTENT(IN ) :: CC(:,:) !< Stiffness matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CRR(nR, nR) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CLL(nL, nL) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CRL(nR, nL) INTEGER(IntKi) :: I, J, II, JJ ! RR: Leader/Boundary DOFs @@ -344,44 +356,44 @@ END SUBROUTINE BreakSysMtrx !! !! NOTE: generic code SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM, CC, CBB, CBM, CMM) - REAL(ReKi), INTENT(IN ) :: MM(:, :) !< Mass matrix - REAL(ReKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix + REAL(FEKi), INTENT(IN ) :: MM(:, :) !< Mass matrix + REAL(FEKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix INTEGER(IntKi), INTENT(IN ) :: nR INTEGER(IntKi), INTENT(IN ) :: IDR(nR) !< Indices of leader DOFs INTEGER(IntKi), INTENT(IN ) :: nL INTEGER(IntKi), INTENT(IN ) :: IDL(nL) !< Indices of interior DOFs INTEGER(IntKi), INTENT(IN ) :: nM !< Number of CB modes INTEGER(IntKi), INTENT(IN ) :: nM_Out !< Number of modes returned for PhiL & OmegaL - REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) !< Reduced Guyan Mass Matrix - REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) !< Reduced Guyan Stiffness matrix - REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) !< Cross term - REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes - REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_out) !< Craig-Bampton modes - REAL(ReKi), INTENT( OUT) :: OmegaL(nM_out) !< Eigenvalues - REAL(ReKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector (typically a constant force, like gravity) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGR(nR) !< Force vector partitioned for R DOFs (TODO remove me) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL - REAL(ReKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL - REAL(ReKi), OPTIONAL, INTENT(IN ) :: CC(:, :) !< Damping matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBB(nR, nR) !< Guyan Damping matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBM(nR, nM) !< Coupling Damping matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CMM(nM, nM) !< Craig-Bampton Damping matrix + REAL(FEKi), INTENT( OUT) :: MBB( nR, nR) !< Reduced Guyan Mass Matrix + REAL(FEKi), INTENT( OUT) :: KBB( nR, nR) !< Reduced Guyan Stiffness matrix + REAL(FEKi), INTENT( OUT) :: MBM( nR, nM) !< Cross term + REAL(FEKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(FEKi), INTENT( OUT) :: PhiL(nL, nM_out) !< Craig-Bampton modes + REAL(FEKi), INTENT( OUT) :: OmegaL(nM_out) !< Eigenvalues + REAL(FEKi), OPTIONAL, INTENT(IN ) :: FG(:) !< Force vector (typically a constant force, like gravity) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGR(nR) !< Force vector partitioned for R DOFs (TODO remove me) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGL(nL) !< Force vector partitioned for L DOFs (TODO somehow for Static improvment..) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGB(nR) !< Force vector in Guyan modes = FR+PhiR^t FL + REAL(FEKi), OPTIONAL, INTENT( OUT) :: FGM(nM) !< Force vector in CB modes = PhiM^t FL + REAL(FEKi), OPTIONAL, INTENT(IN ) :: CC(:, :) !< Damping matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CBB(nR, nR) !< Guyan Damping matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CBM(nR, nM) !< Coupling Damping matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CMM(nM, nM) !< Craig-Bampton Damping matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'CraigBamptonReduction_FromPartition' ! Partitioned variables - real(ReKi), allocatable :: MRR(:, :) - real(ReKi), allocatable :: MLL(:, :) - real(ReKi), allocatable :: MRL(:, :) - real(ReKi), allocatable :: KRR(:, :) - real(ReKi), allocatable :: KLL(:, :) - real(ReKi), allocatable :: KRL(:, :) - real(ReKi), allocatable :: CRR(:, :) - real(ReKi), allocatable :: CRL(:, :) - real(ReKi), allocatable :: CLL(:, :) + real(FEKi), allocatable :: MRR(:, :) + real(FEKi), allocatable :: MLL(:, :) + real(FEKi), allocatable :: MRL(:, :) + real(FEKi), allocatable :: KRR(:, :) + real(FEKi), allocatable :: KLL(:, :) + real(FEKi), allocatable :: KRL(:, :) + real(FEKi), allocatable :: CRR(:, :) + real(FEKi), allocatable :: CRL(:, :) + real(FEKi), allocatable :: CLL(:, :) ! --- Break system CALL AllocAry(MRR, nR, nR, 'matrix MRR', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry(MLL, nL, nL, 'matrix MLL', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -450,30 +462,30 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR INTEGER(IntKi), INTENT( in) :: nL INTEGER(IntKi), INTENT( in) :: nM_Out INTEGER(IntKi), INTENT( in) :: nM - REAL(ReKi), INTENT( IN) :: MRR( nR, nR) !< Partitioned mass and stiffness matrices - REAL(ReKi), INTENT( IN) :: MLL( nL, nL) - REAL(ReKi), INTENT( IN) :: MRL( nR, nL) - REAL(ReKi), INTENT( IN) :: KRR( nR, nR) - REAL(ReKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) - REAL(ReKi), INTENT( IN) :: KRL( nR, nL) - REAL(ReKi), INTENT( OUT) :: MBB( nR, nR) - REAL(ReKi), INTENT( OUT) :: MBM( nR, nM) - REAL(ReKi), INTENT( OUT) :: KBB( nR, nR) - REAL(ReKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes - REAL(ReKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes - REAL(ReKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues + REAL(FEKi), INTENT( IN) :: MRR( nR, nR) !< Partitioned mass and stiffness matrices + REAL(FEKi), INTENT( IN) :: MLL( nL, nL) + REAL(FEKi), INTENT( IN) :: MRL( nR, nL) + REAL(FEKi), INTENT( IN) :: KRR( nR, nR) + REAL(FEKi), INTENT(INOUT) :: KLL( nL, nL) ! on exit, it has been factored (otherwise not changed) + REAL(FEKi), INTENT( IN) :: KRL( nR, nL) + REAL(FEKi), INTENT( OUT) :: MBB( nR, nR) + REAL(FEKi), INTENT( OUT) :: MBM( nR, nM) + REAL(FEKi), INTENT( OUT) :: KBB( nR, nR) + REAL(FEKi), INTENT( OUT) :: PhiR(nL, nR) !< Guyan Modes + REAL(FEKi), INTENT( OUT) :: PhiL(nL, nM_Out) !< Craig-Bampton modes + REAL(FEKi), INTENT( OUT) :: OmegaL(nM_Out) !< Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - REAL(ReKi), OPTIONAL, INTENT( IN) :: CRR( nR, nR) !< Partitioned damping matrices - REAL(ReKi), OPTIONAL, INTENT( IN) :: CLL( nL, nL) - REAL(ReKi), OPTIONAL, INTENT( IN) :: CRL( nR, nL) - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBB( nR, nR) !< Guyan damping matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CBM( nR, nM) !< Coupling damping matrix - REAL(ReKi), OPTIONAL, INTENT( OUT) :: CMM( nM, nM) !< CB damping matrix + REAL(FEKi), OPTIONAL, INTENT( IN) :: CRR( nR, nR) !< Partitioned damping matrices + REAL(FEKi), OPTIONAL, INTENT( IN) :: CLL( nL, nL) + REAL(FEKi), OPTIONAL, INTENT( IN) :: CRL( nR, nL) + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CBB( nR, nR) !< Guyan damping matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CBM( nR, nM) !< Coupling damping matrix + REAL(FEKi), OPTIONAL, INTENT( OUT) :: CMM( nM, nM) !< CB damping matrix ! LOCAL VARIABLES - REAL(ReKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] - REAL(ReKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(nR,nL) = transpose of PhiR * MLL (temporary storage) + REAL(FEKi) , allocatable :: Mu(:, :) ! matrix for normalization Mu(p%nDOFL, p%nDOFL) [bjj: made allocatable to try to avoid stack issues] + REAL(FEKi) , allocatable :: Temp(:, :) ! temp matrix for intermediate steps [bjj: made allocatable to try to avoid stack issues] + REAL(FEKi) , allocatable :: PhiR_T_MLL(:,:) ! PhiR_T_MLL(nR,nL) = transpose of PhiR * MLL (temporary storage) INTEGER :: I !counter INTEGER :: ipiv(nL) ! length min(m,n) (See LAPACK documentation) INTEGER(IntKi) :: ErrStat2 @@ -520,9 +532,9 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR DEALLOCATE(Temp) endif else - PhiL = 0.0_ReKi - OmegaL = 0.0_ReKi - if (present(CRR)) CMM = 0.0_ReKi + PhiL = 0.0_FEKi + OmegaL = 0.0_FEKi + if (present(CRR)) CMM = 0.0_FEKi end if if (nL>0) then @@ -531,7 +543,7 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR ! ** note this must be done after EigenSolveWrap() because it modifies KLL ** CALL LAPACK_getrf( nL, nL, KLL, ipiv, ErrStat2, ErrMsg2); if(Failed()) return - PhiR = -1.0_ReKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) + PhiR = -1.0_FEKi * TRANSPOSE(KRL) !set "b" in Ax=b (solve KLL * PhiR = - TRANSPOSE( KRL ) for PhiR) CALL LAPACK_getrs( TRANS='N', N=nL, A=KLL, IPIV=ipiv, B=PhiR, ErrStat=ErrStat2, ErrMsg=ErrMsg2); if(Failed()) return ! --- Set MBB, MBM, and KBB from Eq. 4: @@ -543,7 +555,7 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) IF ( nM == 0) THEN - MBM = 0.0_ReKi + MBM = 0.0_FEKi ELSE MBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM @@ -561,21 +573,21 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR ! Cross coupling CMB = PhiM^T*CLR + PhiM^T CLL PhiR ! CBM = CRL*PhiM + PhiR^T CLL^T PhiM (NOTE: assuming CLL symmetric) IF ( nM == 0) THEN - CBM = 0.0_ReKi - CMM = 0.0_ReKi + CBM = 0.0_FEKi + CMM = 0.0_FEKi ELSE CBM = MATMUL( PhiR_T_MLL, PhiL(:,1:nM)) ! last half of operation CBM = MATMUL( CRL, PhiL(:,1:nM) ) + CBM !This had PhiM ENDIF endif else - PhiR(1:nL,1:nR) = 0.0_ReKi ! Empty - MBM (1:nR,1:nM) = 0.0_ReKi ! Empty + PhiR(1:nL,1:nR) = 0.0_FEKi ! Empty + MBM (1:nR,1:nM) = 0.0_FEKi ! Empty MBB = MRR KBB = KRR if (present(CRR)) then CBB=CRR - CBM=0.0_ReKi + CBM=0.0_FEKi endif endif @@ -601,39 +613,39 @@ END SUBROUTINE CraigBamptonReduction_FromPartition !! Case2: K and M contain some constraints lines, and they need to be removed from the Mass/Stiffness matrix. Used for full system SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg, bDOF ) INTEGER, INTENT(IN ) :: nDOF ! Total degrees of freedom of the incoming system - REAL(ReKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix - REAL(ReKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix + REAL(FEKi), INTENT(IN ) :: K(nDOF, nDOF) ! stiffness matrix + REAL(FEKi), INTENT(IN ) :: M(nDOF, nDOF) ! mass matrix INTEGER, INTENT(IN ) :: NOmega ! No. of requested eigenvalues LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present - REAL(ReKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors - REAL(ReKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues + REAL(FEKi), INTENT( OUT) :: EigVect(nDOF, NOmega) ! Returned Eigenvectors + REAL(FEKi), INTENT( OUT) :: Omega(NOmega) ! Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) ! LOCALS - REAL(LAKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) - REAL(LAKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega2_LaKi(:) - REAL(ReKi) :: Om2 + REAL(FEKi), ALLOCATABLE :: K_FEKi(:,:), M_FEKi(:,:) + REAL(FEKi), ALLOCATABLE :: EigVect_FEKi(:,:), Omega2_FEKi(:) + REAL(FEKi) :: Om2 INTEGER(IntKi) :: N, i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = '' - ! --- Unfortunate conversion to LaKi... TODO TODO consider storing M and K in LaKi + ! --- Unfortunate conversion to FEKi... TODO TODO consider storing M and K in FEKi if (present(bDOF)) then ! Remove unwanted DOFs - call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(M, bDOF, M_FEKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, K_FEKi, ErrStat2, ErrMsg2); if(Failed()) return else N=size(K,1) - CALL AllocAry(K_LaKi , N, N, 'K_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(M_LaKi , N, N, 'M_LaKi', ErrStat2, ErrMsg2); if(Failed()) return - K_LaKi = real( K, LaKi ) - M_LaKi = real( M, LaKi ) + CALL AllocAry(K_FEKi , N, N, 'K_FEKi', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(M_FEKi , N, N, 'M_FEKi', ErrStat2, ErrMsg2); if(Failed()) return + K_FEKi = real( K, FEKi ) + M_FEKi = real( M, FEKi ) endif - N=size(K_LaKi,1) + N=size(K_FEKi,1) ! Note: NOmega must be <= N, which is the length of Omega2, Phi! if ( NOmega > nDOF ) then @@ -644,19 +656,19 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! --- Eigenvalue analysis - CALL AllocAry(Omega2_LaKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry(EigVect_LaKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_LaKi, M_LaKi, N, EigVect_LaKi, Omega2_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL AllocAry(Omega2_FEKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry(EigVect_FEKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; + CALL EigenSolve(K_FEKi, M_FEKi, N, bCheckSingularity, EigVect_FEKi, Omega2_FEKi, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion do i = 1, NOmega - if (abs(Omega2_LaKi(i))>huge(1.0_ReKi)) then - Om2 = huge(1.0_ReKi) * sign(1.0_LaKi, Omega2_LaKi(i)) + if (abs(Omega2_FEKi(i))>huge(1.0_ReKi)) then + Om2 = huge(1.0_ReKi) * sign(1.0_FEKi, Omega2_FEKi(i)) else - Om2 = real(Omega2_LaKi(i), ReKi) + Om2 = real(Omega2_FEKi(i), FEKi) endif - if (EqualRealNos(Om2, 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics - Omega(i)=0.0_ReKi + if (EqualRealNos(Om2, 0.0_FEKi)) then ! NOTE: may be necessary for some corner numerics + Omega(i)=0.0_FEKi if (bCheckSingularity) then ErrStat2=ErrID_Fatal ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' @@ -667,7 +679,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega else ! Negative eigenfrequency print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 - Omega(i)= 0.0_ReKi + Omega(i)= 0.0_FEKi if (bCheckSingularity) then ErrStat2=ErrID_Fatal ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' @@ -677,9 +689,9 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega enddo if (present(bDOF)) then ! Insert 0s where bDOF was false - CALL InsertDOFRows(EigVect_LaKi(:,1:nOmega), bDOF, 0.0_ReKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return + CALL InsertDOFRows(EigVect_FEKi(:,1:nOmega), bDOF, 0.0_FEKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return else - EigVect=REAL( EigVect_LaKi(:,1:NOmega), ReKi ) ! eigenvectors + EigVect=REAL( EigVect_FEKi(:,1:NOmega), FEKi ) ! eigenvectors endif CALL CleanupEigen() return @@ -691,19 +703,19 @@ LOGICAL FUNCTION Failed() END FUNCTION Failed SUBROUTINE CleanupEigen() - IF (ALLOCATED(Omega2_LaKi) ) DEALLOCATE(Omega2_LaKi) - IF (ALLOCATED(EigVect_LaKi)) DEALLOCATE(EigVect_LaKi) - IF (ALLOCATED(K_LaKi) ) DEALLOCATE(K_LaKi) - IF (ALLOCATED(M_LaKi) ) DEALLOCATE(M_LaKi) + IF (ALLOCATED(Omega2_FEKi) ) DEALLOCATE(Omega2_FEKi) + IF (ALLOCATED(EigVect_FEKi)) DEALLOCATE(EigVect_FEKi) + IF (ALLOCATED(K_FEKi) ) DEALLOCATE(K_FEKi) + IF (ALLOCATED(M_FEKi) ) DEALLOCATE(M_FEKi) END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolveWrap !------------------------------------------------------------------------------------------------------ !> Remove degrees of freedom from a matrix (lines and rows) SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) - REAL(ReKi), INTENT(IN ) :: A(:, :) ! full matrix + REAL(FEKi), INTENT(IN ) :: A(:, :) ! full matrix logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(LAKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix + REAL(FEKi),ALLOCATABLE, INTENT( OUT) :: Ared(:,:) ! reduced matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals @@ -725,7 +737,7 @@ SUBROUTINE RemoveDOF(A, bDOF, Ared, ErrStat, ErrMsg ) do I = 1, size(A,1) if (bDOF(I)) then Ir=Ir+1 - Ared(Ir, Jr) = REAL( A(I, J), LAKi ) + Ared(Ir, Jr) = REAL( A(I, J), FEKi ) end if end do endif @@ -734,10 +746,10 @@ END SUBROUTINE RemoveDOF !> Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) - REAL(LAKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix + REAL(FEKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) - REAL(ReKi), INTENT(IN ) :: DefaultVal ! Default value to fill the - REAL(ReKi) , INTENT(INOUT) :: A(:,:) ! Full matrix + REAL(FEKi), INTENT(IN ) :: DefaultVal ! Default value to fill the + REAL(FEKi) , INTENT(INOUT) :: A(:,:) ! Full matrix INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None !locals @@ -764,7 +776,7 @@ SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) do i=1,n if (bDOF(i)) then ir =ir +1 - A(i,:)=real( Ared(ir,:), ReKi ) + A(i,:)=Ared(ir,:) else A(i,:)=DefaultVal endif @@ -874,13 +886,13 @@ END SUBROUTINE GetRigidTransformation !! !! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix !! in the FAST framework. -SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) +SUBROUTINE GetDirCos(P1, P2, DirCos, L_out, ErrStat, ErrMsg) REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element - REAL(ReKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix - REAL(ReKi) , INTENT( OUT) :: L ! length of element + REAL(FEKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix + REAL(ReKi) , INTENT( OUT) :: L_out ! length of element INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: Dx, Dy, Dz, Dxy ! distances between nodes + REAL(FEKi) :: Dx, Dy, Dz, Dxy,L! distances between nodes ErrMsg = "" ErrStat = ErrID_None @@ -890,18 +902,18 @@ SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) Dxy = sqrt( Dx**2 + Dy**2 ) L = sqrt( Dx**2 + Dy**2 + Dz**2) - IF ( EqualRealNos(L, 0.0_ReKi) ) THEN + IF ( EqualRealNos(L, 0.0_FEKi) ) THEN ErrMsg = ' Same starting and ending location in the element.' ErrStat = ErrID_Fatal RETURN ENDIF - IF ( EqualRealNos(Dxy, 0.0_ReKi) ) THEN - DirCos=0.0_ReKi ! whole matrix set to 0 + IF ( EqualRealNos(Dxy, 0.0_FEKi) ) THEN + DirCos=0.0_FEKi ! whole matrix set to 0 IF ( Dz < 0) THEN !x is kept along global x - DirCos(1, 1) = 1.0_ReKi - DirCos(2, 2) = -1.0_ReKi - DirCos(3, 3) = -1.0_ReKi + DirCos(1, 1) = 1.0_FEKi + DirCos(2, 2) = -1.0_FEKi + DirCos(3, 3) = -1.0_FEKi ELSE DirCos(1, 1) = 1.0_ReKi DirCos(2, 2) = 1.0_ReKi @@ -916,10 +928,11 @@ SUBROUTINE GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) DirCos(2, 2) = +Dz*Dy/(L*Dxy) DirCos(2, 3) = Dy/L - DirCos(3, 1) = 0.0_ReKi + DirCos(3, 1) = 0.0_FEKi DirCos(3, 2) = -Dxy/L DirCos(3, 3) = +Dz/L ENDIF + L_out= real(L, ReKi) END SUBROUTINE GetDirCos !------------------------------------------------------------------------------------------------------ @@ -962,36 +975,36 @@ END SUBROUTINE GetOrthVectors !! shear is false -- non-tapered Euler-Bernoulli beam SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, E, G, kappa - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t LOGICAL , INTENT( IN) :: Shear - REAL(ReKi), INTENT(OUT) :: K(12, 12) + REAL(FEKi), INTENT(OUT) :: K(12, 12) ! Local variables - REAL(ReKi) :: Ax, Ay, Kx, Ky - REAL(ReKi) :: DC(12, 12) + REAL(FEKi) :: Ax, Ay, Kx, Ky + REAL(FEKi) :: DC(12, 12) Ax = kappa*A Ay = kappa*A - K(1:12,1:12) = 0.0_ReKi + K(1:12,1:12) = 0.0_FEKi IF (Shear) THEN - Kx = 12.0_ReKi*E*Iyy / (G*Ax*L*L) - Ky = 12.0_ReKi*E*Ixx / (G*Ay*L*L) + Kx = 12.0_FEKi*E*Iyy / (G*Ax*L*L) + Ky = 12.0_FEKi*E*Ixx / (G*Ay*L*L) ELSE - Kx = 0.0_ReKi - Ky = 0.0_ReKi + Kx = 0.0_FEKi + Ky = 0.0_FEKi ENDIF K( 9, 9) = E*A/L - K( 7, 7) = 12.0_ReKi*E*Iyy/( L*L*L*(1.0_ReKi + Kx) ) - K( 8, 8) = 12.0_ReKi*E*Ixx/( L*L*L*(1.0_ReKi + Ky) ) + K( 7, 7) = 12.0_FEKi*E*Iyy/( L*L*L*(1.0_FEKi + Kx) ) + K( 8, 8) = 12.0_FEKi*E*Ixx/( L*L*L*(1.0_FEKi + Ky) ) K(12, 12) = G*Jzz/L - K(10, 10) = (4.0_ReKi + Ky)*E*Ixx / ( L*(1.0_ReKi+Ky) ) - K(11, 11) = (4.0_ReKi + Kx)*E*Iyy / ( L*(1.0_ReKi+Kx) ) - K( 2, 4) = -6._ReKi*E*Ixx / ( L*L*(1.0_ReKi+Ky) ) - K( 1, 5) = 6._ReKi*E*Iyy / ( L*L*(1.0_ReKi+Kx) ) - K( 4, 10) = (2.0_ReKi-Ky)*E*Ixx / ( L*(1.0_ReKi+Ky) ) - K( 5, 11) = (2.0_ReKi-Kx)*E*Iyy / ( L*(1.0_ReKi+Kx) ) + K(10, 10) = (4.0_FEKi + Ky)*E*Ixx / ( L*(1.0_FEKi+Ky) ) + K(11, 11) = (4.0_FEKi + Kx)*E*Iyy / ( L*(1.0_FEKi+Kx) ) + K( 2, 4) = -6._FEKi*E*Ixx / ( L*L*(1.0_FEKi+Ky) ) + K( 1, 5) = 6._FEKi*E*Iyy / ( L*L*(1.0_FEKi+Kx) ) + K( 4, 10) = (2.0_FEKi-Ky)*E*Ixx / ( L*(1.0_FEKi+Ky) ) + K( 5, 11) = (2.0_FEKi-Kx)*E*Iyy / ( L*(1.0_FEKi+Kx) ) K( 3, 3) = K(9,9) K( 1, 1) = K(7,7) @@ -1024,7 +1037,7 @@ SUBROUTINE ElemK_Beam(A, L, Ixx, Iyy, Jzz, Shear, kappa, E, G, DirCos, K) K(8,4) = -K(4,2) K(4,8) = -K(4,2) - DC = 0.0_ReKi + DC = 0.0_FEKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1039,18 +1052,18 @@ END SUBROUTINE ElemK_Beam SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) REAL(ReKi), INTENT( IN) :: A, L, E REAL(ReKi), INTENT( IN) :: T0 ! Pretension [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: K(12, 12) + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT(OUT) :: K(12, 12) ! Local variables - REAL(ReKi) :: L0, Eps0, EAL0, EE - REAL(ReKi) :: DC(12, 12) + REAL(FEKi) :: L0, Eps0, EAL0, EE + REAL(FEKi) :: DC(12, 12) Eps0 = T0/(E*A) L0 = L/(1+Eps0) ! "rest length" for which pretension would be 0 EAL0 = E*A/L0 EE = EAL0* Eps0/(1+Eps0) - K(1:12,1:12)=0.0_ReKi + K(1:12,1:12)=0.0_FEKi ! Note: only translational DOF involved (1-3, 7-9) K(1,1)= EE @@ -1070,7 +1083,7 @@ SUBROUTINE ElemK_Cable(A, L, E, T0, DirCos, K) K(9,9)= EAL0 - DC = 0.0_ReKi + DC = 0.0_FEKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1082,39 +1095,39 @@ END SUBROUTINE ElemK_Cable !> Element mass matrix for classical beam elements SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) REAL(ReKi), INTENT( IN) :: A, L, Ixx, Iyy, Jzz, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: M(12, 12) + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT(OUT) :: M(12, 12) - REAL(ReKi) :: t, rx, ry, po - REAL(ReKi) :: DC(12, 12) + REAL(FEKi) :: t, rx, ry, po + REAL(FEKi) :: DC(12, 12) t = rho*A*L; rx = rho*Ixx; ry = rho*Iyy; po = rho*Jzz*L; - M(1:12,1:12) = 0.0_ReKi + M(1:12,1:12) = 0.0_FEKi - M( 9, 9) = t/3.0_ReKi - M( 7, 7) = 13.0_ReKi*t/35.0_ReKi + 6.0_ReKi*ry/(5.0_ReKi*L) - M( 8, 8) = 13.0_ReKi*t/35.0_ReKi + 6.0_ReKi*rx/(5.0_ReKi*L) - M(12, 12) = po/3.0_ReKi - M(10, 10) = t*L*L/105.0_ReKi + 2.0_ReKi*L*rx/15.0_ReKi - M(11, 11) = t*L*L/105.0_ReKi + 2.0_ReKi*L*ry/15.0_ReKi - M( 2, 4) = -11.0_ReKi*t*L/210.0_ReKi - rx/10.0_ReKi - M( 1, 5) = 11.0_ReKi*t*L/210.0_ReKi + ry/10.0_ReKi - M( 3, 9) = t/6.0_ReKi - M( 5, 7) = 13._ReKi*t*L/420._ReKi - ry/10._ReKi - M( 4, 8) = -13._ReKi*t*L/420._ReKi + rx/10._ReKi - M( 6, 12) = po/6._ReKi - M( 2, 10) = 13._ReKi*t*L/420._ReKi - rx/10._ReKi - M( 1, 11) = -13._ReKi*t*L/420._ReKi + ry/10._ReKi - M( 8, 10) = 11._ReKi*t*L/210._ReKi + rx/10._ReKi - M( 7, 11) = -11._ReKi*t*L/210._ReKi - ry/10._ReKi - M( 1, 7) = 9._ReKi*t/70._ReKi - 6._ReKi*ry/(5._ReKi*L) - M( 2, 8) = 9._ReKi*t/70._ReKi - 6._ReKi*rx/(5._ReKi*L) - M( 4, 10) = -L*L*t/140._ReKi - rx*L/30._ReKi - M( 5, 11) = -L*L*t/140._ReKi - ry*L/30._ReKi + M( 9, 9) = t/3.0_FEKi + M( 7, 7) = 13.0_FEKi*t/35.0_FEKi + 6.0_FEKi*ry/(5.0_FEKi*L) + M( 8, 8) = 13.0_FEKi*t/35.0_FEKi + 6.0_FEKi*rx/(5.0_FEKi*L) + M(12, 12) = po/3.0_FEKi + M(10, 10) = t*L*L/105.0_FEKi + 2.0_FEKi*L*rx/15.0_FEKi + M(11, 11) = t*L*L/105.0_FEKi + 2.0_FEKi*L*ry/15.0_FEKi + M( 2, 4) = -11.0_FEKi*t*L/210.0_FEKi - rx/10.0_FEKi + M( 1, 5) = 11.0_FEKi*t*L/210.0_FEKi + ry/10.0_FEKi + M( 3, 9) = t/6.0_FEKi + M( 5, 7) = 13._FEKi*t*L/420._FEKi - ry/10._FEKi + M( 4, 8) = -13._FEKi*t*L/420._FEKi + rx/10._FEKi + M( 6, 12) = po/6._FEKi + M( 2, 10) = 13._FEKi*t*L/420._FEKi - rx/10._FEKi + M( 1, 11) = -13._FEKi*t*L/420._FEKi + ry/10._FEKi + M( 8, 10) = 11._FEKi*t*L/210._FEKi + rx/10._FEKi + M( 7, 11) = -11._FEKi*t*L/210._FEKi - ry/10._FEKi + M( 1, 7) = 9._FEKi*t/70._FEKi - 6._FEKi*ry/(5._FEKi*L) + M( 2, 8) = 9._FEKi*t/70._FEKi - 6._FEKi*rx/(5._FEKi*L) + M( 4, 10) = -L*L*t/140._FEKi - rx*L/30._FEKi + M( 5, 11) = -L*L*t/140._FEKi - ry*L/30._FEKi M( 3, 3) = M( 9, 9) M( 1, 1) = M( 7, 7) @@ -1137,7 +1150,7 @@ SUBROUTINE ElemM_Beam(A, L, Ixx, Iyy, Jzz, rho, DirCos, M) M(10, 4) = M( 4, 10) M(11, 5) = M( 5, 11) - DC = 0.0_ReKi + DC = 0.0_FEKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1149,34 +1162,35 @@ END SUBROUTINE ElemM_Beam !------------------------------------------------------------------------------------------------------ !> Element stiffness matrix for pretension cable SUBROUTINE ElemM_Cable(A, L, rho, DirCos, M) - REAL(ReKi), INTENT( IN) :: A, L, rho - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT(OUT) :: M(12, 12) + REAL(ReKi), INTENT( IN) :: A,rho + REAL(FEKi), INTENT( IN) :: L + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT(OUT) :: M(12, 12) ! Local variables - REAL(ReKi) :: DC(12, 12) - REAL(ReKi) :: t + REAL(FEKi) :: DC(12, 12) + REAL(FEKi) :: t t = rho*A*L; - M(1:12,1:12) = 0.0_ReKi + M(1:12,1:12) = 0.0_FEKi - M( 1, 1) = 13._ReKi/35._ReKi * t - M( 2, 2) = 13._ReKi/35._ReKi * t - M( 3, 3) = t/3.0_ReKi + M( 1, 1) = 13._FEKi/35._FEKi * t + M( 2, 2) = 13._FEKi/35._FEKi * t + M( 3, 3) = t/3.0_FEKi - M( 7, 7) = 13._ReKi/35._ReKi * t - M( 8, 8) = 13._ReKi/35._ReKi * t - M( 9, 9) = t/3.0_ReKi + M( 7, 7) = 13._FEKi/35._FEKi * t + M( 8, 8) = 13._FEKi/35._FEKi * t + M( 9, 9) = t/3.0_FEKi - M( 1, 7) = 9._ReKi/70._ReKi * t - M( 2, 8) = 9._ReKi/70._ReKi * t - M( 3, 9) = t/6.0_ReKi + M( 1, 7) = 9._FEKi/70._FEKi * t + M( 2, 8) = 9._FEKi/70._FEKi * t + M( 3, 9) = t/6.0_FEKi - M( 7, 1) = 9._ReKi/70._ReKi * t - M( 8, 2) = 9._ReKi/70._ReKi * t - M( 9, 3) = t/6.0_ReKi + M( 7, 1) = 9._FEKi/70._FEKi * t + M( 8, 2) = 9._FEKi/70._FEKi * t + M( 9, 3) = t/6.0_FEKi - DC = 0.0_ReKi + DC = 0.0_FEKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1193,25 +1207,25 @@ SUBROUTINE ElemG(A, L, rho, DirCos, F, g) REAL(ReKi), INTENT( IN ) :: A !< area REAL(ReKi), INTENT( IN ) :: L !< element length REAL(ReKi), INTENT( IN ) :: rho !< density - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t REAL(ReKi), INTENT( IN ) :: g !< gravity - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1 ; 7-12 are loads for node 2. - REAL(ReKi) :: TempCoeff - REAL(ReKi) :: w ! weight per unit length + REAL(FEKi), INTENT( OUT) :: F(12) !< returned loads. positions 1-6 are the loads for node 1 ; 7-12 are loads for node 2. + REAL(FEKi) :: TempCoeff + REAL(FEKi) :: w ! weight per unit length - F = 0.0_ReKi ! initialize whole array to zero, then set the non-zero portions + F = 0.0_FEKi ! initialize whole array to zero, then set the non-zero portions w = rho*A*g ! weight per unit length ! lumped forces on both nodes (z component only): - F(3) = -0.5_ReKi*L*w + F(3) = -0.5_FEKi*L*w F(9) = F(3) ! lumped moments on node 1 (x and y components only): ! bjj: note that RRD wants factor of 1/12 because of boundary conditions. Our MeshMapping routines use factor of 1/6 (assuming generic/different boundary ! conditions), so we may have some inconsistent behavior. JMJ suggests using line2 elements for SubDyn's input/output meshes to improve the situation. - TempCoeff = L*L*w/12.0_ReKi ! let's not calculate this twice - F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12._ReKi !bjj: DirCos(2,3) = Dy/L - F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12._ReKi !bjj: DirCos(1,3) = Dx/L + TempCoeff = L*L*w/12.0_FEKi ! let's not calculate this twice + F(4) = -TempCoeff * DirCos(2,3) ! = -L*w*Dy/12._FEKi !bjj: DirCos(2,3) = Dy/L + F(5) = TempCoeff * DirCos(1,3) ! = L*w*Dx/12._FEKi !bjj: DirCos(1,3) = Dx/L ! lumped moments on node 2: (note the opposite sign of node 1 moment) F(10) = -F(4) @@ -1223,16 +1237,16 @@ END SUBROUTINE ElemG !> SUBROUTINE ElemF_Cable(T0, DirCos, F) REAL(ReKi), INTENT( IN ) :: T0 !< Pretension load [N] - REAL(ReKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t - REAL(ReKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. + REAL(FEKi), INTENT( IN) :: DirCos(3,3) !< From element to global: xg = DC.xe, Kg = DC.Ke.DC^t + REAL(FEKi), INTENT( OUT) :: F(12) !< returned loads. 1-6 for node 1; 7-12 for node 2. ! Local variables - REAL(ReKi) :: DC(12, 12) + REAL(FEKi) :: DC(12, 12) - F(1:12) = 0.0_ReKi ! init + F(1:12) = 0.0_FEKi ! init F(3) = +T0 F(9) = -T0 - DC = 0.0_ReKi + DC = 0.0_FEKi DC( 1: 3, 1: 3) = DirCos DC( 4: 6, 4: 6) = DirCos DC( 7: 9, 7: 9) = DirCos @@ -1295,16 +1309,16 @@ END SUBROUTINE LumpForces ! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM - real(LaKi), dimension(:,:), intent(in) :: A - real(LaKi), dimension(:,:), allocatable :: Ainv + real(FEKi), dimension(:,:), intent(in) :: A + real(FEKi), dimension(:,:), allocatable :: Ainv INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! < Error message if ErrStat / = ErrID_None ! - real(LaKi), dimension(:), allocatable :: S - real(LaKi), dimension(:,:), allocatable :: U - real(LaKi), dimension(:,:), allocatable :: Vt - real(LaKi), dimension(:), allocatable :: WORK - real(LaKi), dimension(:,:), allocatable :: Acopy + real(FEKi), dimension(:), allocatable :: S + real(FEKi), dimension(:,:), allocatable :: U + real(FEKi), dimension(:,:), allocatable :: Vt + real(FEKi), dimension(:), allocatable :: WORK + real(FEKi), dimension(:,:), allocatable :: Acopy integer :: i, j ! Loop indices integer :: M !< The number of rows of the input matrix A integer :: N !< The number of columns of the input matrix A @@ -1338,7 +1352,7 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) end do ! Compute Ainv = 1.0*V^t * U^t + 0.0*Ainv V*(inv(S))*U' !call DGEMM( 'T', 'T', N, M, K, 1.0, V, K, U, M, 0.0, Ainv, N) - call LAPACK_GEMM( 'T', 'T', 1.0_Laki, Vt, U, 0.0_LaKi, Ainv, ErrStat, ErrMsg) + call LAPACK_GEMM( 'T', 'T', 1.0_FEKi, Vt, U, 0.0_FEKi, Ainv, ErrStat, ErrMsg) ! --- Compute rank !tol=maxval(shape(A))*epsilon(maxval(S)) !rank=0 diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 90c74281f..0885895e2 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -710,7 +710,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section - REAL(ReKi) :: DirCos(3, 3) ! direction cosine matrices + REAL(FEKi) :: DirCos(3, 3) ! direction cosine matrices REAL(ReKi) :: L ! length of the element REAL(ReKi) :: T0 ! pretension force in cable [N] REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer @@ -994,9 +994,9 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) ! Local variables INTEGER :: I, J, K INTEGER :: iGlob - REAL(ReKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector - REAL(ReKi) :: FCe(12) ! Pretension force from cable element - REAL(ReKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil + REAL(FEKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector + REAL(FEKi) :: FCe(12) ! Pretension force from cable element + REAL(FEKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 INTEGER(IntKi) :: iNode !< Node index @@ -1017,9 +1017,9 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - Init%K = 0.0_ReKi - Init%M = 0.0_ReKi - Init%FG = 0.0_ReKi + Init%K = 0.0_FEKi + Init%M = 0.0_FEKi + Init%FG = 0.0_FEKi ! loop over all elements, compute element matrices and assemble into global matrices DO i = 1, Init%NElem @@ -1155,8 +1155,8 @@ SUBROUTINE ControlCableForce_Unit(p, FC_red, ErrStat, ErrMsg) CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables INTEGER :: I, J, K, iGlob - real(ReKi), DIMENSION(:), allocatable :: FC - REAL(ReKi) :: FCe(12) ! Pretension force from cable element + real(FEKi), DIMENSION(:), allocatable :: FC + REAL(FEKi) :: FCe(12) ! Pretension force from cable element INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system @@ -1190,8 +1190,8 @@ END SUBROUTINE ControlCableForce_Unit !> Add soil stiffness and mass to global system matrices SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) - real(ReKi), dimension(:,:), intent(inout) :: M - real(ReKi), dimension(:,:), intent(inout) :: K + real(FEKi), dimension(:,:), intent(inout) :: M + real(FEKi), dimension(:,:), intent(inout) :: K type(IList),dimension(:), intent(in ) :: NodesDOF !< Map from Node Index to DOF lists type(SD_InitType), intent(in ) :: Init type(SD_ParameterType), intent(in ) :: p @@ -1200,7 +1200,7 @@ SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substrac logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding integer :: I, J, iiNode integer :: iDOF, jDOF, iNode !< DOF and node indices - real(ReKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil + real(FEKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil ErrMsg = "" ErrStat = ErrID_None ! TODO consider doing the 21 -> 6x6 conversion while reading @@ -1228,8 +1228,8 @@ SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substrac !> Convert a flatten array of 21 values into a symmetric 6x6 matrix SUBROUTINE Array21_to_6by6(A21, M66) use NWTC_LAPACK, only: LAPACK_TPTTR - real(ReKi), dimension(21) , intent(in) :: A21 - real(ReKi), dimension(6,6), intent(out) :: M66 + real(FEKi), dimension(21) , intent(in) :: A21 + real(FEKi), dimension(6,6), intent(out) :: M66 integer :: j M66 = 0.0_ReKi ! Reconstruct from sparse elements @@ -1256,7 +1256,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) integer(IntKi), dimension(:), INTENT(IN ) :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None - real(ReKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination + real(FEKi), dimension(:,:), allocatable :: Tred !< Transformation matrix for DOF elimination ! Local real(ReKi), dimension(:,:), allocatable :: Tc integer(IntKi), dimension(:), allocatable :: INodesID !< List of unique nodes involved in Elements @@ -1480,8 +1480,8 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) ! Varaibles for rigid assembly type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly - real(ReKi), dimension(:,:), allocatable :: MM, KK - real(ReKi), dimension(:), allocatable :: FF + real(FEKi), dimension(:,:), allocatable :: MM, KK + real(FEKi), dimension(:), allocatable :: FF integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF ErrStat = ErrID_None ErrMsg = "" @@ -1690,8 +1690,8 @@ SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) real(ReKi) :: e1(3), e2(3), e3(3) ! forming orthonormal basis with phat integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 - real(LaKi), dimension(:,:), allocatable :: Tc_rot !< Part of Tc just for rotational DOF - real(LaKi), dimension(:,:), allocatable :: Tc_rot_m1 !< Inverse of Tc_rot + real(FEKi), dimension(:,:), allocatable :: Tc_rot !< Part of Tc just for rotational DOF + real(FEKi), dimension(:,:), allocatable :: Tc_rot_m1 !< Inverse of Tc_rot real(ReKi) :: ColMean ErrStat = ErrID_None ErrMsg = "" @@ -1939,8 +1939,8 @@ END SUBROUTINE InsertJointStiffDamp SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Me(12, 12) - REAL(ReKi) :: L0, Eps0 + REAL(FEKi), INTENT(OUT) :: Me(12, 12) + REAL(FEKi) :: L0, Eps0 if (ep%eType==idMemberBeam) then !Calculate Ke, Me to be used for output CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) @@ -1952,9 +1952,9 @@ SUBROUTINE ElemM(ep, Me) else if (ep%eType==idMemberRigid) then if ( EqualRealNos(eP%rho, 0.0_ReKi) ) then - Me=0.0_ReKi + Me=0.0_FEKi else - CALL ElemM_Cable(ep%Area, ep%Length, ep%rho, ep%DirCos, Me) + CALL ElemM_Cable(ep%Area, real(ep%Length,FEKi), ep%rho, ep%DirCos, Me) !CALL ElemM_(A, L, rho, DirCos, Me) endif endif @@ -1962,7 +1962,7 @@ END SUBROUTINE ElemM SUBROUTINE ElemK(ep, Ke) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property - REAL(ReKi), INTENT(OUT) :: Ke(12, 12) + REAL(FEKi), INTENT(OUT) :: Ke(12, 12) if (ep%eType==idMemberBeam) then CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%kappa, eP%YoungE, eP%ShearG, eP%DirCos, Ke) @@ -1971,21 +1971,21 @@ SUBROUTINE ElemK(ep, Ke) CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) else if (ep%eType==idMemberRigid) then - Ke = 0.0_ReKi + Ke = 0.0_FEKi endif END SUBROUTINE ElemK SUBROUTINE ElemF(ep, gravity, Fg, Fo) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity - REAL(ReKi), INTENT(OUT) :: Fg(12) - REAL(ReKi), INTENT(OUT) :: Fo(12) + REAL(FEKi), INTENT(OUT) :: Fg(12) + REAL(FEKi), INTENT(OUT) :: Fo(12) if (ep%eType==idMemberBeam) then - Fo(1:12)=0 + Fo(1:12)=0.0_FEKi else if (ep%eType==idMemberCable) then CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) else if (ep%eType==idMemberRigid) then - Fo(1:12)=0 + Fo(1:12)=0.0_FEKi endif CALL ElemG( eP%Area, eP%Length, eP%rho, eP%DirCos, Fg, gravity ) END SUBROUTINE ElemF diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 471c5b191..902a10a86 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2073,8 +2073,8 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(ReKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) - REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file + REAL(FEKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) + REAL(FEKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) @@ -2177,13 +2177,13 @@ end subroutine CleanUpCB !! NOTE: PhiL and OmegaL are not modified subroutine applyConstr(CBParams, FGB, PhiRb) TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) - REAL(ReKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) + REAL(FEKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) + REAL(FEKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) - REAL(ReKi), ALLOCATABLE :: MBBb(:, :) - REAL(ReKi), ALLOCATABLE :: MBMb(:, :) - REAL(ReKi), ALLOCATABLE :: KBBb(:, :) - REAL(ReKi), ALLOCATABLE :: FGBb(:) + REAL(FEKi), ALLOCATABLE :: MBBb(:, :) + REAL(FEKi), ALLOCATABLE :: MBMb(:, :) + REAL(FEKi), ALLOCATABLE :: KBBb(:, :) + REAL(FEKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); @@ -2221,15 +2221,15 @@ END SUBROUTINE SD_Craig_Bampton SUBROUTINE SD_Guyan_RigidBodyMass(Init, p, MBB, ErrStat, ErrMsg) type(SD_InitType), intent(inout) :: Init ! NOTE: Mass and Stiffness are modified but then set back to original type(SD_ParameterType), intent(in ) :: p ! Parameters - real(ReKi), allocatable, intent(out) :: MBB(:,:) !< MBB + real(FEKi), allocatable, intent(out) :: MBB(:,:) !< MBB integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< error message if errstat /= errid_none integer(IntKi) :: nM, nR, nL, nM_out - real(ReKi), allocatable :: MBM(:, :) - real(ReKi), allocatable :: KBB(:, :) - real(ReKi), allocatable :: PhiL(:, :) - real(ReKi), allocatable :: PhiR(:, :) - real(ReKi), allocatable :: OmegaL(:) + real(FEKi), allocatable :: MBM(:, :) + real(FEKi), allocatable :: KBB(:, :) + real(FEKi), allocatable :: PhiL(:, :) + real(FEKi), allocatable :: PhiR(:, :) + real(FEKi), allocatable :: OmegaL(:) character(*), parameter :: RoutineName = 'SD_Guyan_RigidBodyMass' integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 @@ -2270,20 +2270,21 @@ END SUBROUTINE SD_Guyan_RigidBodyMass !------------------------------------------------------------------------------------------------------ !> Set parameters to compute state and output equations +!! NOTE: this function converst from FEKi to ReKi SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters - REAL(ReKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan mass matrix - REAL(ReKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) - REAL(ReKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan stiffness matrix + REAL(FEKi), INTENT(IN ) :: MBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan mass matrix + REAL(FEKi), INTENT(IN ) :: MBMb( p%nDOF__Rb, p%nDOFM) + REAL(FEKi), INTENT(IN ) :: KBBb( p%nDOF__Rb, p%nDOF__Rb) ! Guyan stiffness matrix integer(IntKi), INTENT(IN ) :: nM_out - REAL(ReKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) - REAL(ReKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: OmegaL(nM_out) - REAL(ReKi), INTENT(IN ) :: FGB(p%nDOF__Rb) - REAL(ReKi), INTENT(IN ) :: FGL(p%nDOF__L) - REAL(ReKi), INTENT(IN ) :: FGM(p%nDOFM) + REAL(FEKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) + REAL(FEKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) + REAL(FEKi), INTENT(IN ) :: OmegaL(nM_out) + REAL(FEKi), INTENT(IN ) :: FGB(p%nDOF__Rb) + REAL(FEKi), INTENT(IN ) :: FGL(p%nDOF__L) + REAL(FEKi), INTENT(IN ) :: FGM(p%nDOFM) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -2359,8 +2360,9 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !p%D1_15=-TI_transpose !this is 6x6NIN IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 - ! p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt - CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return + ! TODO cant use LAPACK due to type conversions FEKi->ReKi + p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt + !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return !p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, CBMb, 0.0_ReKi, p%CBM, ErrStat2, ErrMsg2); if (Failed()) return p%CBM = 0.0_ReKi ! TODO no cross couplings @@ -2397,8 +2399,10 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) p%D1_13 = p%MBB - p%D1_13 + ! TODO cant use LAPACK due to type conversions FEKi->ReKi !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) + p%D1_14 = MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 @@ -2873,17 +2877,18 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) INTEGER(IntKi) :: mType ! Member Type Real(ReKi) :: mMass, mLength ! Member mass and length REAL(ReKi) :: MRB(6,6) ! REDUCED SYSTEM Kmatrix, equivalent mass matrix - REAL(ReKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix - REAL(ReKi) :: XYZ1(3),XYZ2(3), DirCos(3,3) !temporary arrays, member i-th direction cosine matrix (global to local) and member length + REAL(FEKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix + REAL(ReKi) :: XYZ1(3),XYZ2(3) !temporary arrays + REAL(FEKi) :: DirCos(3,3) ! direction cosine matrix (global to local) CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix - real(ReKi) :: Ke(12,12), Me(12, 12), FCe(12), FGe(12) ! element stiffness and mass matrices gravity force vector + real(FEKi) :: Ke(12,12), Me(12, 12), FCe(12), FGe(12) ! element stiffness and mass matrices gravity force vector real(ReKi), dimension(:,:), allocatable :: DummyArray ! ! Variables for Eigenvalue analysis integer(IntKi) :: nOmega - real(ReKi), dimension(:,:), allocatable :: Modes + real(FEKi), dimension(:,:), allocatable :: Modes real(R8Ki), dimension(:,:), allocatable :: AA, BB, CC, DD ! Linearization matrices - real(ReKi), dimension(:) , allocatable :: Omega + real(FEKi), dimension(:) , allocatable :: Omega logical, allocatable :: bDOF(:) ! Mask for DOF to keep (True), or reduce (False) character(len=*),parameter :: ReFmt='ES15.6E2' character(len=*),parameter :: SFmt='A15,1x' ! Need +1 for comma compared to ReFmt @@ -3457,7 +3462,7 @@ SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status; if present, program does not abort on error CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message INTEGER :: CurLine !< The current line to be parsed in the FileInfo structure. - REAL(ReKi), INTENT(INOUT) , dimension(21) :: SSIK, SSIM !< Matrices being filled by reading the file. + REAL(FEKi), INTENT(INOUT) , dimension(21) :: SSIK, SSIM !< Matrices being filled by reading the file. CHARACTER(*), INTENT(IN) :: Filename !< Name of the input file. ! Local declarations: CHARACTER(5), DIMENSION(21) :: Knames=(/'Kxx ','Kxy ','Kyy ','Kxz ','Kyz ', 'Kzz ','Kxtx ','Kytx ','Kztx ','Ktxtx', & @@ -3473,8 +3478,8 @@ SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) INTEGER(IntKi) :: ErrStat2 ! Error status; if present, program does not abort on error CHARACTER(*), PARAMETER :: RoutineName = 'ReadSSIfile' - SSIK=0.0_ReKi - SSIM=0.0_ReKi + SSIK=0.0_FEKi + SSIM=0.0_FEKi CALL ProcessComFile ( Filename, FileInfo, ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); IF (ErrStat >= AbortErrLev) RETURN CurLine = 1 @@ -3482,8 +3487,8 @@ SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) DO i=1, imax !This will search also for already hit up names, but that's ok, it should be pretty fast DO j=1,FileInfo%NumLines CurLine=j - CALL ParseVarWDefault ( FileInfo, CurLine, Knames(i), SSIK(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) - CALL ParseVarWDefault ( FileInfo, CurLine, Mnames(i), SSIM(i), 0.0_ReKi, ErrStat2, ErrMsg2 ) + CALL ParseVarWDefault ( FileInfo, CurLine, Knames(i), SSIK(i), 0.0_FEKi, ErrStat2, ErrMsg2 ) + CALL ParseVarWDefault ( FileInfo, CurLine, Mnames(i), SSIM(i), 0.0_FEKi, ErrStat2, ErrMsg2 ) ENDDO ENDDO IF ( PRESENT(UnEc) ) THEN diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index bb915e235..3217f0988 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -239,7 +239,7 @@ SUBROUTINE ConfigOutputNode_MKF_ID(pLst, iElem, iiNode, iStore, NodeID2) integer(IntKi) , intent(in) :: iStore !< Storage index, used several informations are stored per node integer(IntKi) , intent(in) :: NodeID2 !< If ElemNode(2) == NodeID2, then it's the second node integer(IntKi), dimension(2) :: ElemNodes ! Node IDs for element under consideration (may not be consecutive numbers) - REAL(ReKi) :: FCe(12) ! Pretension force from cable element + REAL(FEKi) :: FCe(12) ! Pretension force from cable element pLst%ElmIDs(iiNode,iStore) = iElem ! This array has for each joint requested the elements' ID to get results for ElemNodes = p%Elems(iElem,2:3) ! 1st and 2nd node of the k-th element if (ElemNodes(2) == NodeID2) then @@ -277,7 +277,7 @@ SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments - real(ReKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(FEKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions integer(IntKi) :: sgn !+1/-1 for node force calculations type(MeshAuxDataType), pointer :: pLst !< Info for a given member-output (Alias to shorten notation) @@ -417,7 +417,7 @@ subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInput type(MeshAuxDataType), intent(in) :: pLst !< Info for one member output integer(IntKi) , intent(in) :: iiNode !< Index over the nodes of a given member (>2 if nDIV>1) integer(IntKi) , intent(in) :: JJ !< TODO: interpretation: index over other member connected to the current member (for averaging) - real(ReKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) + real(FEKi), dimension (3,3), intent(inout) :: DIRCOS !direction cosice matrix (global to local) (3x3) real(ReKi), dimension (6), intent(out) :: FM_elm, FK_elm !output static and dynamic forces and moments integer(IntKi), intent(out) :: sgn !+1/-1 for node force calculations logical, intent(in) :: bUseInputDirCos !< If True, use DIRCOS from input, otherwise, use element DirCos @@ -448,9 +448,10 @@ end subroutine ElementForce !and K2 indicating wheter the 1st (1) or 2nd (2) node is to be picked !---------------------------------------------------------------------------------------------------- SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FK_nod) - Real(ReKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) - Real(ReKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) - Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2, Fg !acceleration and velocities, gravity forces + Real(FEKi), DIMENSION (3,3), INTENT(IN) :: DIRCOS !direction cosice matrix (global to local) (3x3) + Real(FEKi), DIMENSION (12,12), INTENT(IN) :: Me,Ke !element M and K matrices (12x12) in GLOBAL REFERENCE (DIRCOS^T K DIRCOS) + Real(ReKi), DIMENSION (12), INTENT(IN) :: Udotdot, Y2 !acceleration and velocities, gravity forces + Real(FEKi), DIMENSION (12), INTENT(IN) :: Fg !acceleration and velocities, gravity forces Integer(IntKi), INTENT(IN) :: FirstOrSecond !1 or 2 depending on node of interest REAL(ReKi), DIMENSION (6), INTENT(OUT) :: FM_nod, FK_nod !output static and dynamic forces and moments !Locals diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 6b4d4889a..0ae625baf 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -44,16 +44,16 @@ typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" -typedef ^ MeshAuxDataType ReKi Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType ReKi Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" +typedef ^ MeshAuxDataType R8Ki Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType R8Ki Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType R8Ki Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" # CB_MatArrays: Matrices and arrays for CB summary -typedef ^ CB_MatArrays ReKi MBB {:}{:} - - "FULL MBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi MBM {:}{:} - - "FULL MBM ( no constraints applied)" -typedef ^ CB_MatArrays ReKi KBB {:}{:} - - "FULL KBB ( no constraints applied)" -typedef ^ CB_MatArrays ReKi PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" -typedef ^ CB_MatArrays ReKi PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" -typedef ^ CB_MatArrays ReKi OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" +typedef ^ CB_MatArrays R8Ki MBB {:}{:} - - "FULL MBB ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki MBM {:}{:} - - "FULL MBM ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki KBB {:}{:} - - "FULL KBB ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" +typedef ^ CB_MatArrays R8Ki PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" # typedef ^ ElemPropType IntKi eType - - - "Element Type" typedef ^ ^ ReKi Length - - - "Length of an element" @@ -68,7 +68,7 @@ typedef ^ ^ ReKi ShearG - - - "Shear modulus" N/m^2 typedef ^ ^ ReKi Area - - - "Area of an element" m^2 typedef ^ ^ ReKi Rho - - - "Density" kg/m^3 typedef ^ ^ ReKi T0 - - - "Pretension " N -typedef ^ ^ ReKi DirCos {3}{3} - - "Element direction cosine matrix" +typedef ^ ^ R8Ki DirCos {3}{3} - - "Element direction cosine matrix" # ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ #--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" @@ -83,7 +83,7 @@ typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" -typedef ^ ^ INTEGER FEMMod - - - "FEM switch: element model in the FEM" +typedef ^ ^ INTEGER FEMMod - - - "FEM switch element model in the FEM" typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" @@ -101,8 +101,8 @@ typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" -typedef ^ ^ ReKi SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" -typedef ^ ^ ReKi SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" +typedef ^ ^ R8Ki SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" +typedef ^ ^ R8Ki SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ typedef ^ ^ INTEGER NElem - - - "Total number of elements" @@ -113,10 +113,9 @@ typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" -typedef ^ ^ ReKi K {:}{:} - - "System stiffness matrix" -typedef ^ ^ ReKi M {:}{:} - - "System mass matrix" -typedef ^ ^ ReKi F {:} - - "System force vector" N -typedef ^ ^ ReKi FG {:} - - "Gravity force vector (include initial Cable force T0)" N +typedef ^ ^ R8Ki K {:}{:} - - "System stiffness matrix" +typedef ^ ^ R8Ki M {:}{:} - - "System mass matrix" +typedef ^ ^ R8Ki FG {:} - - "Gravity force vector (include initial Cable force T0)" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" @@ -182,7 +181,7 @@ typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" # --- Constraints reduction typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" -typedef ^ ^ ReKi T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 99f7396dd..baa960aa2 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -17,7 +17,9 @@ module SubDyn_Tests interface test_almost_equal; module procedure & test_almost_equal_0, & test_almost_equal_1, & - test_almost_equal_2 + test_almost_equal_1d, & + test_almost_equal_2, & + test_almost_equal_2d end interface contains @@ -145,20 +147,57 @@ subroutine test_almost_equal_0(Var,Ref,Try,MINNORM,bStop,bPrint,bPassed) subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) ! Arguments character(len=*), intent(in) :: Var - real(ReKi), dimension(:), intent(in) :: VecRef !< - real(ReKi), dimension(:), intent(in) :: VecTry !< - real(ReKi), intent(in) :: MINNORM + real(SiKi), dimension(:), intent(in) :: VecRef !< + real(SiKi), dimension(:), intent(in) :: VecTry !< + real(SiKi), intent(in) :: MINNORM logical, intent(in) :: bStop logical, intent(in) :: bPrint logical, intent(out),optional :: bPassed ! Variables character(len=255) :: InfoAbs integer :: i,cpt - real(ReKi) :: delta - real(ReKi) :: delta_cum + real(SiKi) :: delta + real(SiKi) :: delta_cum ! cpt=0 - delta_cum=0.0_ReKi + delta_cum=0.0_SiKi + do i=1,size(VecRef,1) + delta=abs(VecRef(i)-VecTry(i)) + delta_cum=delta_cum+delta + if(delta>MINNORM) then + cpt=cpt+1 + endif + enddo + delta_cum=delta_cum/size(VecRef) + + if(cpt>0) then + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2,A,I0)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum,' - Failed:',cpt + call test_fail(InfoAbs,bPrint,bStop) + else + write(InfoAbs,'(A,ES8.1E2,A,ES8.1E2)') trim(Var)//' tol: ',MINNORM,', mean: ',delta_cum + call test_success(InfoAbs,bPrint) + endif + if(present(bPassed)) then + bPassed=(cpt==0) + endif + end subroutine + subroutine test_almost_equal_1d(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(R8Ki), dimension(:), intent(in) :: VecRef !< + real(R8Ki), dimension(:), intent(in) :: VecTry !< + real(R8Ki), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + character(len=255) :: InfoAbs + integer :: i,cpt + real(R8Ki) :: delta + real(R8Ki) :: delta_cum + ! + cpt=0 + delta_cum=0.0_R8Ki do i=1,size(VecRef,1) delta=abs(VecRef(i)-VecTry(i)) delta_cum=delta_cum+delta @@ -182,15 +221,39 @@ subroutine test_almost_equal_1(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) subroutine test_almost_equal_2(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) ! Arguments character(len=*), intent(in) :: Var - real(ReKi), dimension(:,:), intent(in) :: VecRef !< - real(ReKi), dimension(:,:), intent(in) :: VecTry !< - real(ReKi), intent(in) :: MINNORM + real(SiKi), dimension(:,:), intent(in) :: VecRef !< + real(SiKi), dimension(:,:), intent(in) :: VecTry !< + real(SiKi), intent(in) :: MINNORM + logical, intent(in) :: bStop + logical, intent(in) :: bPrint + logical, intent(out),optional :: bPassed + ! Variables + real(SiKi), dimension(:),allocatable :: VecRef2 !< + real(SiKi), dimension(:),allocatable :: VecTry2 !< + integer :: p, i,j,n1,n2,nCPs + ! + n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 + allocate ( VecRef2 (n1*n2) ) ; allocate ( VecTry2 (n1*n2) ) + p=0 + do j=1,n2; do i=1,n1 + p=p+1 + VecRef2(p)=VecRef(i,j) + VecTry2(p)=VecTry(i,j) + enddo; enddo; + call test_almost_equal(Var,VecRef2,VecTry2,MINNORM,bStop,bPrint,bPassed) + end subroutine + subroutine test_almost_equal_2d(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) + ! Arguments + character(len=*), intent(in) :: Var + real(R8Ki), dimension(:,:), intent(in) :: VecRef !< + real(R8Ki), dimension(:,:), intent(in) :: VecTry !< + real(R8Ki), intent(in) :: MINNORM logical, intent(in) :: bStop logical, intent(in) :: bPrint logical, intent(out),optional :: bPassed ! Variables - real(ReKi), dimension(:),allocatable :: VecRef2 !< - real(ReKi), dimension(:),allocatable :: VecTry2 !< + real(R8Ki), dimension(:),allocatable :: VecRef2 !< + real(R8Ki), dimension(:),allocatable :: VecTry2 !< integer :: p, i,j,n1,n2,nCPs ! n1 = size(VecRef,1); n2 = size(VecRef,2); nCPs=n1*n2 @@ -262,7 +325,8 @@ subroutine Test_Transformations(ErrStat,ErrMsg) character(ErrMsgLen), intent(out) :: ErrMsg real(ReKi), dimension(3) :: P1, P2, e1, e2, e3 - real(ReKi), dimension(3,3) :: DirCos, A, R0, Ref + real(ReKi), dimension(3,3) :: A, R0 + real(FEKi), dimension(3,3) :: DirCos, Ref real(ReKi), dimension(6,6) :: T, Tref real(ReKi) :: L integer(IntKi) :: I @@ -272,8 +336,8 @@ subroutine Test_Transformations(ErrStat,ErrMsg) P1=(/0,0,0/) P2=(/2,0,0/) call GetDirCos(P1, P2, DirCos, L, ErrStat, ErrMsg) - Ref = reshape( (/0_ReKi,-1_ReKi,0_ReKi, 0_ReKi, 0_ReKi, -1_ReKi, 1_ReKi, 0_ReKi, 0_ReKi/) , (/3,3/)) - call test_almost_equal('DirCos',Ref,DirCos,1e-8_ReKi,.true.,.true.) + Ref = reshape( (/0_FEKi,-1_FEKi,0_FEKi, 0_FEKi, 0_FEKi, -1_FEKi, 1_FEKi, 0_FEKi, 0_FEKi/) , (/3,3/)) + call test_almost_equal('DirCos',Ref,DirCos,1e-8_FEKi,.true.,.true.) ! --- Rigid Transo P1=(/1,2,-1/) @@ -306,7 +370,7 @@ end subroutine Test_Transformations subroutine Test_Linalg(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg - real(LaKi), dimension(:,:), allocatable :: A, Ainv, Aref + real(FEKi), dimension(:,:), allocatable :: A, Ainv, Aref real(DbKi) :: det integer(IntKi) :: I, J testname='Linalg' diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 91c712327..a4b77955f 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -72,19 +72,19 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: NodeIDs !< Node IDs associated with ordinal numbers for the output member [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmIDs !< Element IDs connected to each NodeIDs; max 10 elements [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElmNds !< Flag to indicate 1st or 2nd node of element for each ElmIDs [-] - REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Me !< Mass matrix connected to each joint element for outAll output [-] + REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: Ke !< Mass matrix connected to each joint element for outAll output [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Fg !< Gravity load vector connected to each joint element for requested member output [-] END TYPE MeshAuxDataType ! ======================= ! ========= CB_MatArrays ======= TYPE, PUBLIC :: CB_MatArrays - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: MBB !< FULL MBB ( no constraints applied) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: MBM !< FULL MBM ( no constraints applied) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: KBB !< FULL KBB ( no constraints applied) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: PhiL !< Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM) [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: PhiR !< FULL PhiR ( no constraints applied) [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: OmegaL !< Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM) [-] END TYPE CB_MatArrays ! ======================= ! ========= ElemPropType ======= @@ -101,7 +101,7 @@ MODULE SubDyn_Types REAL(ReKi) :: Area !< Area of an element [m^2] REAL(ReKi) :: Rho !< Density [kg/m^3] REAL(ReKi) :: T0 !< Pretension [N] - REAL(ReKi) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] + REAL(R8Ki) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] END TYPE ElemPropType ! ======================= ! ========= SD_InitType ======= @@ -118,7 +118,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NPropSetsR !< Number of property sets for rigid links [-] INTEGER(IntKi) :: NCMass !< Number of joints with concentrated mass [-] INTEGER(IntKi) :: NCOSMs !< Number of independent cosine matrices [-] - INTEGER(IntKi) :: FEMMod !< FEM switch: element model in the FEM [-] + INTEGER(IntKi) :: FEMMod !< FEM switch element model in the FEM [-] INTEGER(IntKi) :: NDiv !< Number of divisions for each member [-] LOGICAL :: CBMod !< Perform C-B flag [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] @@ -136,8 +136,8 @@ MODULE SubDyn_Types CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] @@ -147,10 +147,9 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F !< System force vector [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (include initial Cable force T0) [N] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (include initial Cable force T0) [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] @@ -220,7 +219,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFred !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] @@ -1741,17 +1740,17 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no IF ( ALLOCATED(InData%Me) ) THEN Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Me) ! Me + Db_BufSz = Db_BufSz + SIZE(InData%Me) ! Me END IF Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no IF ( ALLOCATED(InData%Ke) ) THEN Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Ke) ! Ke + Db_BufSz = Db_BufSz + SIZE(InData%Ke) ! Ke END IF Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no IF ( ALLOCATED(InData%Fg) ) THEN Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Fg) ! Fg + Db_BufSz = Db_BufSz + SIZE(InData%Fg) ! Fg END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -1861,8 +1860,8 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Me)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Me))-1 ) = PACK(InData%Me,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Me) + IF (SIZE(InData%Me)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%Me))-1 ) = PACK(InData%Me,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%Me) END IF IF ( .NOT. ALLOCATED(InData%Ke) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1883,8 +1882,8 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Ke)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Ke))-1 ) = PACK(InData%Ke,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Ke) + IF (SIZE(InData%Ke)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%Ke))-1 ) = PACK(InData%Ke,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%Ke) END IF IF ( .NOT. ALLOCATED(InData%Fg) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -1902,8 +1901,8 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%Fg)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%Fg))-1 ) = PACK(InData%Fg,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%Fg) + IF (SIZE(InData%Fg)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%Fg))-1 ) = PACK(InData%Fg,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%Fg) END IF END SUBROUTINE SD_PackMeshAuxDataType @@ -2073,8 +2072,8 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta RETURN END IF mask4 = .TRUE. - IF (SIZE(OutData%Me)>0) OutData%Me = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Me))-1 ), mask4, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Me) + IF (SIZE(OutData%Me)>0) OutData%Me = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%Me))-1 ), mask4, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%Me) DEALLOCATE(mask4) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke not allocated @@ -2105,8 +2104,8 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta RETURN END IF mask4 = .TRUE. - IF (SIZE(OutData%Ke)>0) OutData%Ke = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Ke))-1 ), mask4, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Ke) + IF (SIZE(OutData%Ke)>0) OutData%Ke = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%Ke))-1 ), mask4, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%Ke) DEALLOCATE(mask4) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg not allocated @@ -2134,8 +2133,8 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta RETURN END IF mask3 = .TRUE. - IF (SIZE(OutData%Fg)>0) OutData%Fg = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%Fg))-1 ), mask3, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%Fg) + IF (SIZE(OutData%Fg)>0) OutData%Fg = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%Fg))-1 ), mask3, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%Fg) DEALLOCATE(mask3) END IF END SUBROUTINE SD_UnPackMeshAuxDataType @@ -2307,32 +2306,32 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no IF ( ALLOCATED(InData%MBB) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBB) ! MBB + Db_BufSz = Db_BufSz + SIZE(InData%MBB) ! MBB END IF Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no IF ( ALLOCATED(InData%MBM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM + Db_BufSz = Db_BufSz + SIZE(InData%MBM) ! MBM END IF Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no IF ( ALLOCATED(InData%KBB) ) THEN Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%KBB) ! KBB + Db_BufSz = Db_BufSz + SIZE(InData%KBB) ! KBB END IF Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no IF ( ALLOCATED(InData%PhiL) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiL) ! PhiL + Db_BufSz = Db_BufSz + SIZE(InData%PhiL) ! PhiL END IF Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no IF ( ALLOCATED(InData%PhiR) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PhiR) ! PhiR + Db_BufSz = Db_BufSz + SIZE(InData%PhiR) ! PhiR END IF Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no IF ( ALLOCATED(InData%OmegaL) ) THEN Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%OmegaL) ! OmegaL + Db_BufSz = Db_BufSz + SIZE(InData%OmegaL) ! OmegaL END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -2374,8 +2373,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%MBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBB) + IF (SIZE(InData%MBB)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%MBB))-1 ) = PACK(InData%MBB,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%MBB) END IF IF ( .NOT. ALLOCATED(InData%MBM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2390,8 +2389,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%MBM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%MBM) + IF (SIZE(InData%MBM)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%MBM))-1 ) = PACK(InData%MBM,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%MBM) END IF IF ( .NOT. ALLOCATED(InData%KBB) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2406,8 +2405,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%KBB)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%KBB) + IF (SIZE(InData%KBB)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%KBB))-1 ) = PACK(InData%KBB,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%KBB) END IF IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2422,8 +2421,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PhiL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiL))-1 ) = PACK(InData%PhiL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiL) + IF (SIZE(InData%PhiL)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%PhiL))-1 ) = PACK(InData%PhiL,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%PhiL) END IF IF ( .NOT. ALLOCATED(InData%PhiR) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2438,8 +2437,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%PhiR)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%PhiR))-1 ) = PACK(InData%PhiR,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%PhiR) + IF (SIZE(InData%PhiR)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%PhiR))-1 ) = PACK(InData%PhiR,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%PhiR) END IF IF ( .NOT. ALLOCATED(InData%OmegaL) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -2451,8 +2450,8 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%OmegaL)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%OmegaL))-1 ) = PACK(InData%OmegaL,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%OmegaL) + IF (SIZE(InData%OmegaL)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%OmegaL))-1 ) = PACK(InData%OmegaL,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%OmegaL) END IF END SUBROUTINE SD_PackCB_MatArrays @@ -2512,8 +2511,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%MBB)>0) OutData%MBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBB) + IF (SIZE(OutData%MBB)>0) OutData%MBB = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%MBB))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%MBB) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated @@ -2538,8 +2537,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%MBM)>0) OutData%MBM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%MBM) + IF (SIZE(OutData%MBM)>0) OutData%MBM = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%MBM))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%MBM) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated @@ -2564,8 +2563,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%KBB)>0) OutData%KBB = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%KBB) + IF (SIZE(OutData%KBB)>0) OutData%KBB = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%KBB))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%KBB) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated @@ -2590,8 +2589,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%PhiL)>0) OutData%PhiL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiL))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiL) + IF (SIZE(OutData%PhiL)>0) OutData%PhiL = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%PhiL))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%PhiL) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR not allocated @@ -2616,8 +2615,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%PhiR)>0) OutData%PhiR = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%PhiR))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%PhiR) + IF (SIZE(OutData%PhiR)>0) OutData%PhiR = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%PhiR))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%PhiR) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL not allocated @@ -2639,8 +2638,8 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%OmegaL)>0) OutData%OmegaL = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%OmegaL))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%OmegaL) + IF (SIZE(OutData%OmegaL)>0) OutData%OmegaL = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%OmegaL))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%OmegaL) DEALLOCATE(mask1) END IF END SUBROUTINE SD_UnPackCB_MatArrays @@ -2734,7 +2733,7 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = Re_BufSz + 1 ! Area Re_BufSz = Re_BufSz + 1 ! Rho Re_BufSz = Re_BufSz + 1 ! T0 - Re_BufSz = Re_BufSz + SIZE(InData%DirCos) ! DirCos + Db_BufSz = Db_BufSz + SIZE(InData%DirCos) ! DirCos IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2786,8 +2785,8 @@ SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_Xferred = Re_Xferred + 1 ReKiBuf ( Re_Xferred:Re_Xferred+(1)-1 ) = InData%T0 Re_Xferred = Re_Xferred + 1 - ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%DirCos) + DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%DirCos))-1 ) = PACK(InData%DirCos,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%DirCos) END SUBROUTINE SD_PackElemPropType SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2858,8 +2857,8 @@ SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, RETURN END IF mask2 = .TRUE. - OutData%DirCos = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%DirCos))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%DirCos) + OutData%DirCos = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%DirCos))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%DirCos) DEALLOCATE(mask2) END SUBROUTINE SD_UnPackElemPropType @@ -3163,18 +3162,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%M = SrcInitTypeData%M ENDIF -IF (ALLOCATED(SrcInitTypeData%F)) THEN - i1_l = LBOUND(SrcInitTypeData%F,1) - i1_u = UBOUND(SrcInitTypeData%F,1) - IF (.NOT. ALLOCATED(DstInitTypeData%F)) THEN - ALLOCATE(DstInitTypeData%F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%F = SrcInitTypeData%F -ENDIF IF (ALLOCATED(SrcInitTypeData%FG)) THEN i1_l = LBOUND(SrcInitTypeData%FG,1) i1_u = UBOUND(SrcInitTypeData%FG,1) @@ -3340,9 +3327,6 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%M)) THEN DEALLOCATE(InitTypeData%M) ENDIF -IF (ALLOCATED(InitTypeData%F)) THEN - DEALLOCATE(InitTypeData%F) -ENDIF IF (ALLOCATED(InitTypeData%FG)) THEN DEALLOCATE(InitTypeData%FG) ENDIF @@ -3474,12 +3458,12 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! SSIK allocated yes/no IF ( ALLOCATED(InData%SSIK) ) THEN Int_BufSz = Int_BufSz + 2*2 ! SSIK upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SSIK) ! SSIK + Db_BufSz = Db_BufSz + SIZE(InData%SSIK) ! SSIK END IF Int_BufSz = Int_BufSz + 1 ! SSIM allocated yes/no IF ( ALLOCATED(InData%SSIM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! SSIM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SSIM) ! SSIM + Db_BufSz = Db_BufSz + SIZE(InData%SSIM) ! SSIM END IF Int_BufSz = Int_BufSz + 1 ! SSIfile allocated yes/no IF ( ALLOCATED(InData%SSIfile) ) THEN @@ -3513,22 +3497,17 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 1 ! K allocated yes/no IF ( ALLOCATED(InData%K) ) THEN Int_BufSz = Int_BufSz + 2*2 ! K upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%K) ! K + Db_BufSz = Db_BufSz + SIZE(InData%K) ! K END IF Int_BufSz = Int_BufSz + 1 ! M allocated yes/no IF ( ALLOCATED(InData%M) ) THEN Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%M) ! M - END IF - Int_BufSz = Int_BufSz + 1 ! F allocated yes/no - IF ( ALLOCATED(InData%F) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + Db_BufSz = Db_BufSz + SIZE(InData%M) ! M END IF Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no IF ( ALLOCATED(InData%FG) ) THEN Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FG) ! FG + Db_BufSz = Db_BufSz + SIZE(InData%FG) ! FG END IF Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no IF ( ALLOCATED(InData%ElemProps) ) THEN @@ -3801,8 +3780,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIK,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%SSIK)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIK) + IF (SIZE(InData%SSIK)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%SSIK))-1 ) = PACK(InData%SSIK,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%SSIK) END IF IF ( .NOT. ALLOCATED(InData%SSIM) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3817,8 +3796,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SSIM,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%SSIM)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%SSIM) + IF (SIZE(InData%SSIM)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%SSIM))-1 ) = PACK(InData%SSIM,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%SSIM) END IF IF ( .NOT. ALLOCATED(InData%SSIfile) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3922,8 +3901,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%K)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%K))-1 ) = PACK(InData%K,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%K) + IF (SIZE(InData%K)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%K))-1 ) = PACK(InData%K,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%K) END IF IF ( .NOT. ALLOCATED(InData%M) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3938,21 +3917,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%M,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%M)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%M) - END IF - IF ( .NOT. ALLOCATED(InData%F) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1) - Int_Xferred = Int_Xferred + 2 - - IF (SIZE(InData%F)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%F))-1 ) = PACK(InData%F,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%F) + IF (SIZE(InData%M)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%M))-1 ) = PACK(InData%M,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%M) END IF IF ( .NOT. ALLOCATED(InData%FG) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -3964,8 +3930,8 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%FG)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%FG))-1 ) = PACK(InData%FG,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%FG) + IF (SIZE(InData%FG)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%FG))-1 ) = PACK(InData%FG,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%FG) END IF IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -4452,8 +4418,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%SSIK)>0) OutData%SSIK = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIK) + IF (SIZE(OutData%SSIK)>0) OutData%SSIK = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%SSIK))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%SSIK) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIM not allocated @@ -4478,8 +4444,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%SSIM)>0) OutData%SSIM = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%SSIM) + IF (SIZE(OutData%SSIM)>0) OutData%SSIM = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%SSIM))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%SSIM) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SSIfile not allocated @@ -4643,8 +4609,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%K)>0) OutData%K = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%K))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%K) + IF (SIZE(OutData%K)>0) OutData%K = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%K))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%K) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! M not allocated @@ -4669,33 +4635,10 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%M)>0) OutData%M = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%M))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%M) + IF (SIZE(OutData%M)>0) OutData%M = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%M))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%M) DEALLOCATE(mask2) END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F)) DEALLOCATE(OutData%F) - ALLOCATE(OutData%F(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - ALLOCATE(mask1(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating mask1.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - mask1 = .TRUE. - IF (SIZE(OutData%F)>0) OutData%F = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%F))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%F) - DEALLOCATE(mask1) - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4715,8 +4658,8 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM RETURN END IF mask1 = .TRUE. - IF (SIZE(OutData%FG)>0) OutData%FG = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%FG))-1 ), mask1, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%FG) + IF (SIZE(OutData%FG)>0) OutData%FG = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%FG))-1 ), mask1, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%FG) DEALLOCATE(mask1) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated @@ -8077,7 +8020,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no IF ( ALLOCATED(InData%T_red) ) THEN Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%T_red) ! T_red + Db_BufSz = Db_BufSz + SIZE(InData%T_red) ! T_red END IF Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no IF ( ALLOCATED(InData%NodesDOF) ) THEN @@ -8621,8 +8564,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red,2) Int_Xferred = Int_Xferred + 2 - IF (SIZE(InData%T_red)>0) ReKiBuf ( Re_Xferred:Re_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) - Re_Xferred = Re_Xferred + SIZE(InData%T_red) + IF (SIZE(InData%T_red)>0) DbKiBuf ( Db_Xferred:Db_Xferred+(SIZE(InData%T_red))-1 ) = PACK(InData%T_red,.TRUE.) + Db_Xferred = Db_Xferred + SIZE(InData%T_red) END IF IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 @@ -9867,8 +9810,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg RETURN END IF mask2 = .TRUE. - IF (SIZE(OutData%T_red)>0) OutData%T_red = UNPACK(ReKiBuf( Re_Xferred:Re_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_ReKi ) - Re_Xferred = Re_Xferred + SIZE(OutData%T_red) + IF (SIZE(OutData%T_red)>0) OutData%T_red = REAL( UNPACK(DbKiBuf( Db_Xferred:Db_Xferred+(SIZE(OutData%T_red))-1 ), mask2, 0.0_DbKi ), R8Ki) + Db_Xferred = Db_Xferred + SIZE(OutData%T_red) DEALLOCATE(mask2) END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated From bc2eacb94cb42c6697fe8679a2e5d8fcfd8ae612 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 14:11:36 -0600 Subject: [PATCH 262/377] FlexSub: eigensolver returns omega --- modules/subdyn/src/FEM.f90 | 79 +++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index db38746da..4bdcc8afb 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -28,7 +28,7 @@ MODULE FEM !------------------------------------------------------------------------------------------------------ !> Return eigenvalues, Omega, and eigenvectors -SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrMsg ) +SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K @@ -36,7 +36,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM REAL(FEKi), INTENT(INOUT) :: M(N, N) !< Mass matrix LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present REAL(FEKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors - REAL(FEKi), INTENT(INOUT) :: Omega2(N) !< Returned Eigenvalues + REAL(FEKi), INTENT(INOUT) :: Omega(N) !< Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! LOCALS @@ -46,7 +46,8 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - REAL(FEKi) :: normA + REAL(FEKi) :: normA, Om2 + REAL(FEKi) :: Omega2(N) !< Squared eigenvalues ErrStat = ErrID_None ErrMsg = '' @@ -111,16 +112,6 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM Omega2(I) = HUGE(1.0_FEKi) endif endif - if (bCheckSingularity) then - if ( EqualRealNos(real(Omega2(I),ReKi),0.0_ReKi) ) THEN - ErrStat2=ErrID_Fatal - ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' - elseif (Omega2(I) < 0.0_FEKi) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - endif - if(Failed()) return - endif enddo ! Sorting CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return @@ -138,6 +129,37 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega2, ErrStat, ErrM EigVect(:,I)=VL(:,KEY(I)) !just reordered as Huimin had a normalization outside of this one ENDDO !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! + + ! --- Return Omega (capped by huge(ReKi)) and check for singularity + Omega(:) = 0.0_FEKi + do I=1,N + ! Capping Om2 to avoid overflow + if (abs(Omega2(I))>huge(1.0_ReKi)) then + Om2 = huge(1.0_ReKi) * sign(1.0_FEKI, Omega2(i)) !< NOTE huge(ReKi) + else + Om2 = Omega2(i) + endif + if (EqualRealNos(real(Om2,ReKi), 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics + Omega(i)=0.0_FEKi + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif + elseif (Om2>0) then + Omega(i)=sqrt(Om2) + else + ! Negative eigenfrequency + print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 + Omega(i)= 0.0_FEKi + if (bCheckSingularity) then + ErrStat2=ErrID_Fatal + ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + if(Failed()) return + endif + endif + enddo + CALL CleanupEigen() RETURN @@ -626,7 +648,6 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! LOCALS REAL(FEKi), ALLOCATABLE :: K_FEKi(:,:), M_FEKi(:,:) REAL(FEKi), ALLOCATABLE :: EigVect_FEKi(:,:), Omega2_FEKi(:) - REAL(FEKi) :: Om2 INTEGER(IntKi) :: N, i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -654,39 +675,11 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega return end if - ! --- Eigenvalue analysis - CALL AllocAry(Omega2_FEKi , N, 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; CALL AllocAry(EigVect_FEKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_FEKi, M_FEKi, N, bCheckSingularity, EigVect_FEKi, Omega2_FEKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL EigenSolve(K_FEKi, M_FEKi, N, bCheckSingularity, EigVect_FEKi, Omega, ErrStat2, ErrMsg2 ); if (Failed()) return; ! --- Setting up Phi, and type conversion - do i = 1, NOmega - if (abs(Omega2_FEKi(i))>huge(1.0_ReKi)) then - Om2 = huge(1.0_ReKi) * sign(1.0_FEKi, Omega2_FEKi(i)) - else - Om2 = real(Omega2_FEKi(i), FEKi) - endif - if (EqualRealNos(Om2, 0.0_FEKi)) then ! NOTE: may be necessary for some corner numerics - Omega(i)=0.0_FEKi - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif - elseif (Om2>0) then - Omega(i)=sqrt(Om2) ! was getting floating invalid - else - ! Negative eigenfrequency - print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 - Omega(i)= 0.0_FEKi - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif - endif - enddo if (present(bDOF)) then ! Insert 0s where bDOF was false CALL InsertDOFRows(EigVect_FEKi(:,1:nOmega), bDOF, 0.0_FEKi, EigVect, ErrStat2, ErrMsg2 ); if(Failed()) return From 638b434122f5a9010b91dbb4df19a7342e0c2fd1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 15:00:44 -0600 Subject: [PATCH 263/377] FlexSub: unused variables --- modules/subdyn/src/FEM.f90 | 8 ++------ modules/subdyn/src/IntegerList.f90 | 1 - modules/subdyn/src/SD_FEM.f90 | 25 ++++++------------------- modules/subdyn/src/SubDyn.f90 | 24 ++++++++---------------- modules/subdyn/src/SubDyn_Output.f90 | 6 ++---- modules/subdyn/src/SubDyn_Tests.f90 | 8 +------- 6 files changed, 19 insertions(+), 53 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 4bdcc8afb..996a0f650 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -648,7 +648,7 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega ! LOCALS REAL(FEKi), ALLOCATABLE :: K_FEKi(:,:), M_FEKi(:,:) REAL(FEKi), ALLOCATABLE :: EigVect_FEKi(:,:), Omega2_FEKi(:) - INTEGER(IntKi) :: N, i + INTEGER(IntKi) :: N INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None @@ -782,7 +782,6 @@ FUNCTION FINDLOCI_ReKi(Array, Val) result(i) real(ReKi) , dimension(:), intent(in) :: Array !< Array to search in integer(IntKi), intent(in) :: val !< Val integer(IntKi) :: i !< Index of joint in joint table - logical :: found i = 1 do while ( i <= size(Array) ) if ( Val == NINT(Array(i)) ) THEN @@ -799,7 +798,6 @@ FUNCTION FINDLOCI_IntKi(Array, Val) result(i) integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in integer(IntKi), intent(in) :: val !< Val integer(IntKi) :: i !< Index of joint in joint table - logical :: found i = 1 do while ( i <= size(Array) ) if ( Val == Array(i) ) THEN @@ -1312,14 +1310,12 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) real(FEKi), dimension(:,:), allocatable :: Vt real(FEKi), dimension(:), allocatable :: WORK real(FEKi), dimension(:,:), allocatable :: Acopy - integer :: i, j ! Loop indices + integer :: j ! Loop indices integer :: M !< The number of rows of the input matrix A integer :: N !< The number of columns of the input matrix A integer :: K !< integer :: L !< integer :: LWORK !< - integer :: INFO - real(ReKi) :: tol M = size(A,1) N = size(A,2) K = min(M,N) diff --git a/modules/subdyn/src/IntegerList.f90 b/modules/subdyn/src/IntegerList.f90 index 299622368..a5f74112c 100644 --- a/modules/subdyn/src/IntegerList.f90 +++ b/modules/subdyn/src/IntegerList.f90 @@ -347,7 +347,6 @@ function find_intarray(Array, Val) result(i) integer(IntKi), dimension(:), intent(in) :: Array !< Array to search in integer(IntKi), intent(in) :: val !< Val integer(IntKi) :: i !< Index of joint in joint table - logical :: found i = 1 do while ( i <= size(Array) ) if ( Val == Array(i) ) THEN diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 0885895e2..40126411c 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -101,7 +101,6 @@ SUBROUTINE NodeCon(Init,p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER(IntKi) :: SortA(MaxMemJnt,1) !To sort nodes and elements INTEGER(IntKi) :: I,J,K !counter ! The row index is the number of the real node, i.e. ID, 1st col has number of elements attached to node, and 2nd col has element numbers (up to 10) @@ -218,7 +217,6 @@ LOGICAL FUNCTION NodeHasRigidElem(iJoint, Init, p, ei) integer(IntKi), intent( out) :: ei !< Element index that connects do iJoint rigidly ! Local variables integer(IntKi) :: ie !< Loop index on elements - integer(IntKi) :: m ! Number of elements connected to a joint NodeHasRigidElem = .False. ! default return value ! Loop through elements connected to node J @@ -413,14 +411,14 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variable - INTEGER :: I, J, n, Node1, Node2, Prop1, Prop2 + INTEGER :: I, J, Node1, Node2, Prop1, Prop2 INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp REAL(ReKi), ALLOCATABLE :: TempProps(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) INTEGER :: knode, kelem, kprop, nprop REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 - LOGICAL :: found, CreateNewProp + LOGICAL :: CreateNewProp INTEGER(IntKi) :: nMemberCable, nMemberRigid, nMemberBeam !< Number of memebers per type INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: ErrStat2 @@ -706,13 +704,12 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, iTmp + INTEGER :: I INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section REAL(FEKi) :: DirCos(3, 3) ! direction cosine matrices REAL(ReKi) :: L ! length of the element - REAL(ReKi) :: T0 ! pretension force in cable [N] REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, nu, ratioSq, D_inner, D_outer LOGICAL :: shear INTEGER(IntKi) :: eType !< Member type @@ -996,12 +993,10 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) INTEGER :: iGlob REAL(FEKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector REAL(FEKi) :: FCe(12) ! Pretension force from cable element - REAL(FEKi), DIMENSION(6,6):: K_soil, M_soil ! Auxiliary matrices for soil INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 INTEGER(IntKi) :: iNode !< Node index integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system - integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node real(ReKi) :: m, x, y, z, Jxx, Jyy, Jzz, Jxy, Jxz, Jyz INTEGER :: jGlob, kGlob @@ -1118,15 +1113,8 @@ SUBROUTINE ControlCableForceInit(Init, p, m, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K - INTEGER :: iGlob - REAL(ReKi) :: FCe(12) ! Pretension force from cable element INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - INTEGER(IntKi) :: iNode !< Node index - integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system - integer(IntKi), dimension(3) :: IDOF3! 3 DOF indices in global unconstrained system - real(ReKi), dimension(6,6) :: M66 ! Mass matrix of an element node ErrMsg = "" ErrStat = ErrID_None @@ -1154,7 +1142,7 @@ SUBROUTINE ControlCableForce_Unit(p, FC_red, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, iGlob + INTEGER :: I real(FEKi), DIMENSION(:), allocatable :: FC REAL(FEKi) :: FCe(12) ! Pretension force from cable element INTEGER(IntKi) :: ErrStat2 @@ -1359,7 +1347,7 @@ SUBROUTINE BuildTMatrix(Init, p, RA, RAm1, Tred, ErrStat, ErrMsg) allocate(IDOFOld(1:len(p%NodesDOF(iNode)))) IDOFOld(:) = p%NodesDOF(iNode)%List(:) phat = Init%Nodes(iNode, iJointDir:iJointDir+2) - call JointElimination(Init%NodesConnE(iNode,:), JType, phat, Init, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return + call JointElimination(Init%NodesConnE(iNode,:), JType, phat, p, Tc, ErrStat2, ErrMsg2); if(Failed()) return endif nc=size(Tc,2) call init_list(p%NodesDOFred(iNode), nc, 0, ErrStat2, ErrMsg2) @@ -1672,12 +1660,11 @@ END SUBROUTINE RAElimination !! where ! x_c are all the DOF of the joint (3 translation + 3*m, m the number of elements) ! x_c_tilde are the nc reduced DOF -SUBROUTINE JointElimination(Elements, JType, phat, Init, p, Tc, ErrStat, ErrMsg) +SUBROUTINE JointElimination(Elements, JType, phat, p, Tc, ErrStat, ErrMsg) use IntegerList, only: init_list, len, append, print_list, pop, destroy_list, get integer(IntKi), dimension(:), INTENT(IN ) :: Elements !< List of elements involved at a joint integer(IntKi), INTENT(IN ) :: JType !< Joint type real(ReKi), INTENT(IN ) :: phat(3) !< Directional vector of the joint - TYPE(SD_InitType), INTENT(IN ) :: Init TYPE(SD_ParameterType), INTENT(IN ) :: p real(ReKi), dimension(:,:), allocatable :: Tc !< Transformation matrix from eliminated to full INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 902a10a86..2c53a39c6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -99,7 +99,7 @@ SUBROUTINE CreateInputOutputMeshes( NNode, Nodes, inputMesh, outputMesh, ErrStat CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables REAL(ReKi), dimension(3) :: Point - INTEGER :: I, iOffset, iNode ! generic counter variable + INTEGER :: I ! generic counter variable INTEGER :: nodeIndx CALL MeshCreate( BlankMesh = inputMesh & @@ -301,7 +301,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO END IF if (InitInput%Linearize) then - call SD_Init_Jacobian(Init, p, u, y, m, InitOut, ErrStat2, ErrMsg2); if(Failed()) return + call SD_Init_Jacobian(Init, p, u, y, InitOut, ErrStat2, ErrMsg2); if(Failed()) return endif ! Tell GLUECODE the SubDyn timestep interval @@ -377,8 +377,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None !locals - INTEGER(IntKi) :: L1,L2 ! partial Lengths of state and input arrays - INTEGER(IntKi) :: I,J ! Counters + INTEGER(IntKi) :: I ! Counters INTEGER(IntKi) :: iSDNode, iY2Node REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) @@ -387,7 +386,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF - REAL(ReKi) :: DCM(3,3),junk(6,p%nNodes_L) + REAL(ReKi) :: DCM(3,3) REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) @@ -563,7 +562,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END IF ! Map calculated results into the AllOuts Array + perform averaging and all necessary extra calculations - CALL SDOut_MapOutputs(t, u, p, x, y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return + CALL SDOut_MapOutputs(u, p, x, y, m, AllOuts, ErrStat2, ErrMsg2); if(Failed()) return ! Put the output data in the WriteOutput array DO I = 1,p%NumOuts+p%OutAllInt*p%OutAllDims @@ -642,7 +641,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! local variable for input and output CHARACTER(1024) :: PriPath ! The path to the primary input file CHARACTER(1024) :: Line, Dummy_Str ! String to temporarially hold value of read line -INTEGER :: Sttus CHARACTER(64), ALLOCATABLE :: StrArray(:) ! Array of strings, for better control of table inputs LOGICAL :: Echo LOGICAL :: LegacyFormat @@ -652,7 +650,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) INTEGER(IntKi) :: IOS INTEGER(IntKi) :: UnEc !Echo file ID REAL(ReKi),PARAMETER :: WrongNo=-9999. ! Placeholder value for bad(old) values in JDampings -INTEGER(IntKi) :: I, J, flg, K, nColsReactInterf +INTEGER(IntKi) :: I, J, flg, K REAL(ReKi) :: Dummy_ReAry(SDMaxInpCols) , DummyFloat INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) LOGICAL :: Dummy_Bool @@ -1675,7 +1673,6 @@ SUBROUTINE SD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM TYPE(SD_InputType) :: u_perturb REAL(R8Ki) :: delta_p, delta_m ! delta change in input (plus, minus) INTEGER(IntKi) :: i - REAL(R8Ki) :: RotateStates(3,3) integer(intKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 character(*), parameter :: RoutineName = 'SD_JacobianPInput' @@ -1765,7 +1762,7 @@ END SUBROUTINE SD_JacobianPInput !---------------------------------------------------------------------------------------------------------------------------------- !> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions !! with respect to the continuous states (x). The partial derivatives dY/dx, dX/dx, dXd/dx, and dZ/dx are returned. -SUBROUTINE SD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx, dXddx, dZdx, StateRotation ) +SUBROUTINE SD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx, dXddx, dZdx) REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point TYPE(SD_InputType), INTENT(INOUT) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters @@ -1781,13 +1778,10 @@ SUBROUTINE SD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdx(:,:) !< Partial derivatives of continuous state functions (X) wrt the continuous states (x) [intent in to avoid deallocation] REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddx(:,:) !< Partial derivatives of discrete state functions (Xd) wrt the continuous states (x) [intent in to avoid deallocation] REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdx(:,:) !< Partial derivatives of constraint state functions (Z) wrt the continuous states (x) [intent in to avoid deallocation] - REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: StateRotation(:,:) !< Matrix by which the states are optionally rotated ! local variables TYPE(SD_OutputType) :: y_p, y_m TYPE(SD_ContinuousStateType) :: x_p, x_m TYPE(SD_ContinuousStateType) :: x_perturb - REAL(R8Ki) :: RotateStates(3,3) - REAL(R8Ki) :: RotateStatesTranspose(3,3) REAL(R8Ki) :: delta ! delta change in input or state INTEGER(IntKi) :: i, k INTEGER(IntKi) :: idx @@ -2076,7 +2070,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) REAL(FEKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) REAL(FEKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array - INTEGER(IntKi) :: i INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) INTEGER(IntKi) :: nL, nM, nM_out INTEGER(IntKi), pointer :: IDR(:) !< Alias to switch between IDR__ and ID__Rb @@ -3224,7 +3217,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) real(R8Ki), dimension(:,:), allocatable, optional :: BB !< real(R8Ki), dimension(:,:), allocatable, optional :: CC !< real(R8Ki), dimension(:,:), allocatable, optional :: DD !< - integer(IntKi) :: nU, nX, nY, nCB, i, j, iNode, iDOF, iOff,jj, k, nMembers, iField + integer(IntKi) :: nU, nX, nY, nCB, i, j, iNode, iOff, k, nMembers, iField real(R8Ki), dimension(:), allocatable :: dFext_dFmeshk real(R8Ki), dimension(:), allocatable :: dFred_dFmeshk real(R8Ki), dimension(:), allocatable :: dFL_dFmeshk @@ -3472,7 +3465,6 @@ SUBROUTINE ReadSSIfile ( Filename, JointID, SSIK, SSIM, ErrStat, ErrMsg, UnEc ) 'Mxty ','Myty ','Mzty ','Mtxty','Mtyty', & 'Mxtz ','Mytz ','Mztz ','Mtxtz','Mtytz','Mtztz'/) TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. - INTEGER :: IOS ! I/O status returned from the read statement. INTEGER(IntKi) :: i, j, imax !counters CHARACTER(ErrMsgLen) :: ErrMsg2 INTEGER(IntKi) :: ErrStat2 ! Error status; if present, program does not abort on error diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 3217f0988..c78ffa1f0 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -262,8 +262,7 @@ END SUBROUTINE SDOut_Init !! This routine does fill Allouts !! note that this routine assumes m%u_TP and m%udotdot_TP have been set before calling !! this routine (which is done in SD_CalcOutput() and SD CalcContStateDeriv) -SUBROUTINE SDOut_MapOutputs( CurrentTime, u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) - real(DbKi), intent( in ) :: CurrentTime ! Current simulation time in seconds +SUBROUTINE SDOut_MapOutputs(u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) type(SD_InputType), intent( in ) :: u ! SubDyn module's input data type(SD_ContinuousStateType), intent( in ) :: x ! SubDyn module's states data type(SD_OutputType), intent( inout ) :: y ! SubDyn module's output data @@ -811,12 +810,11 @@ END SUBROUTINE SDOut_ChkOutLst !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ !> This routine initializes the array that maps rows/columns of the Jacobian to specific mesh fields. !! Do not change the order of this packing without changing subroutine ! -SUBROUTINE SD_Init_Jacobian(Init, p, u, y, m, InitOut, ErrStat, ErrMsg) +SUBROUTINE SD_Init_Jacobian(Init, p, u, y, InitOut, ErrStat, ErrMsg) TYPE(SD_InitType) , INTENT(IN ) :: Init !< Init TYPE(SD_ParameterType) , INTENT(INOUT) :: p !< parameters TYPE(SD_InputType) , INTENT(IN ) :: u !< inputs TYPE(SD_OutputType) , INTENT(IN ) :: y !< outputs - TYPE(SD_MiscVarType) , INTENT(INOUT) :: m !< misc var data TYPE(SD_InitOutputType) , INTENT(INOUT) :: InitOut !< Initialization output data (for Jacobian row/column names) INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*) , INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index baa960aa2..138435f85 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -272,9 +272,7 @@ subroutine test_almost_equal_2d(Var,VecRef,VecTry,MINNORM,bStop,bPrint,bPassed) ! --------------------------------------------------------------------------------} ! --- Specific SubDyn tests ! --------------------------------------------------------------------------------{ - subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg, Init, p) - TYPE(SD_InitType), INTENT( in) :: Init ! Input data for initialization routine - TYPE(SD_ParameterType), INTENT(inout) :: p ! Parameters + subroutine Test_CB_Results(MBBt, MBMt, KBBt, OmegaM, DOFTP, DOFM, ErrStat, ErrMsg) INTEGER(IntKi) :: DOFTP, DOFM REAL(ReKi) :: MBBt(DOFTP, DOFTP) REAL(ReKi) :: MBmt(DOFTP, DOFM) @@ -325,7 +323,6 @@ subroutine Test_Transformations(ErrStat,ErrMsg) character(ErrMsgLen), intent(out) :: ErrMsg real(ReKi), dimension(3) :: P1, P2, e1, e2, e3 - real(ReKi), dimension(3,3) :: A, R0 real(FEKi), dimension(3,3) :: DirCos, Ref real(ReKi), dimension(6,6) :: T, Tref real(ReKi) :: L @@ -372,7 +369,6 @@ subroutine Test_Linalg(ErrStat,ErrMsg) character(ErrMsgLen), intent(out) :: ErrMsg real(FEKi), dimension(:,:), allocatable :: A, Ainv, Aref real(DbKi) :: det - integer(IntKi) :: I, J testname='Linalg' ! --- Determinant of a singular matrix @@ -491,8 +487,6 @@ subroutine Test_ChessBoard(ErrStat,ErrMsg) integer(IntKi) , intent(out) :: ErrStat character(ErrMsgLen), intent(out) :: ErrMsg real(ReKi), dimension(:,:), allocatable :: M, Mref - real(ReKi) :: L - integer(IntKi) :: I ErrStat = ErrID_None ErrMsg = "" testname='ChessBoard' From 8aa044d24e6e1ca6d817a5e00258d90ccfb34a09 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 18:46:56 -0600 Subject: [PATCH 264/377] FlexSub: reduced stack impact and avoiding lasrt for sorting --- modules/subdyn/CMakeLists.txt | 1 - modules/subdyn/src/FEM.f90 | 86 +++++++++++++++++---------- modules/subdyn/src/SD_FEM.f90 | 28 ++++++--- modules/subdyn/src/SubDyn.f90 | 13 ++-- modules/subdyn/src/qsort_c_module.f90 | 61 ------------------- vs-build/FASTlib/FASTlib.vfproj | 1 - vs-build/SubDyn/SubDyn.vfproj | 1 - 7 files changed, 81 insertions(+), 110 deletions(-) delete mode 100644 modules/subdyn/src/qsort_c_module.f90 diff --git a/modules/subdyn/CMakeLists.txt b/modules/subdyn/CMakeLists.txt index 8ab62a8c3..8d56cc80f 100644 --- a/modules/subdyn/CMakeLists.txt +++ b/modules/subdyn/CMakeLists.txt @@ -24,7 +24,6 @@ set(SUBDYN_SOURCES src/SD_FEM.f90 src/SubDyn_Output.f90 src/SubDyn_Output_Params.f90 - src/qsort_c_module.f90 src/SubDyn_Tests.f90 src/IntegerList.f90 src/Yaml.f90 diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 996a0f650..0d6a96ce9 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -30,7 +30,6 @@ MODULE FEM SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev - USE NWTC_ScaLAPACK, only : ScaLAPACK_LASRT INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K REAL(FEKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix REAL(FEKi), INTENT(INOUT) :: M(N, N) !< Mass matrix @@ -46,8 +45,9 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - REAL(FEKi) :: normA, Om2 + REAL(FEKi) :: normA REAL(FEKi) :: Omega2(N) !< Squared eigenvalues + REAL(FEKi), parameter :: MAX_EIGENVALUE = HUGE(1.0_ReKi) ! To avoid overflow when switching to ReKi ErrStat = ErrID_None ErrMsg = '' @@ -77,19 +77,20 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs Omega2(:) =0.0_FEKi DO I=1,N !Initialize the key and calculate Omega KEY(I)=I + Omega2(I) = AlphaR(I)/Beta(I) if ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) then ! --- Beta =0 - print*,'Large eigenvalue found, system may be ill-conditioned' - Omega2(I) = HUGE(1.0_FEKi) + call WrScr('[WARN] Large eigenvalue found, system may be ill-conditioned') + Omega2(I) = MAX_EIGENVALUE elseif ( EqualRealNos(real(AlphaI(I),ReKi),0.0_ReKi) ) THEN ! --- Real Eigenvalues IF ( AlphaR(I)<0.0_FEKi ) THEN if ( (AlphaR(I)/Beta(I))<1e-6_FEKi ) then ! Tolerating very small negative eigenvalues - print*,'Negative eigenvalue found with small norm, system may be singular (may contain rigid body modes)' + call WrScr('[INFO] Negative eigenvalue found with small norm (system may contain rigid body mode)') Omega2(I)=0.0_FEKi else - print*,'Negative eigenvalue found, system may be singular (may contain rigid body modes)' + call WrScr('[WARN] Negative eigenvalue found, system may be ill-conditioned.') Omega2(I)=AlphaR(I)/Beta(I) endif else @@ -100,21 +101,27 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs normA = sqrt(AlphaR(I)**2 + AlphaI(I)**2) if ( (normA/Beta(I))<1e-6_FEKi ) then ! Tolerating very small eigenvalues with imaginary part - print*,'Complex eigenvalue found with small norm, approximating as 0' + call WrScr('[WARN] Complex eigenvalue found with small norm, approximating as 0') Omega2(I) = 0.0_FEKi elseif ( abs(AlphaR(I))>1e3_FEKi*abs(AlphaI(I)) ) then ! Tolerating very small imaginary part compared to real part... (not pretty) - print*,'Complex eigenvalue found with small Im compare to Re' - !print*'AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) + call WrScr('[WARN] Complex eigenvalue found with small Im compare to Re') Omega2(I) = AlphaR(I)/Beta(I) else - print*,'Complex eigenvalue found, AlphaR,AlphaI,beta=',AlphaR(I), AlphaI(I), beta(I), AlphaR(I)/beta(I), AlphaI(I)/beta(I) - Omega2(I) = HUGE(1.0_FEKi) + call WrScr('[WARN] Complex eigenvalue found with large imaginary value)') + Omega2(I) = MAX_EIGENVALUE endif + call Fatal('Complex eigenvalue found, system may be ill-conditioned'); return + endif + ! Capping to avoid overflow + if (Omega2(I)> MAX_EIGENVALUE) then + Omega2(I) = MAX_EIGENVALUE endif enddo - ! Sorting - CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return + + ! Sorting. LASRT has issues for double precision 64 bit on windows + !CALL ScaLAPACK_LASRT('I',N,Omega2,KEY,ErrStat2,ErrMsg2); if(Failed()) return + CALL sort_in_place(Omega2,KEY) ! --- Sorting eigen vectors ! KEEP ME: scaling of the eigenvectors using generalized mass =identity criterion @@ -133,30 +140,18 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs ! --- Return Omega (capped by huge(ReKi)) and check for singularity Omega(:) = 0.0_FEKi do I=1,N - ! Capping Om2 to avoid overflow - if (abs(Omega2(I))>huge(1.0_ReKi)) then - Om2 = huge(1.0_ReKi) * sign(1.0_FEKI, Omega2(i)) !< NOTE huge(ReKi) - else - Om2 = Omega2(i) - endif - if (EqualRealNos(real(Om2,ReKi), 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics + if (EqualRealNos(real(Omega2(I),ReKi), 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics Omega(i)=0.0_FEKi if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Zero eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return + call Fatal('Zero eigenvalue found, system may contain rigid body mode'); return endif - elseif (Om2>0) then - Omega(i)=sqrt(Om2) + elseif (Omega2(I)>0) then + Omega(i)=sqrt(Omega2(I)) else ! Negative eigenfrequency - print*,'>>> Wrong eigenfrequency, Omega^2=',Om2 + print*,'>>> Wrong eigenfrequency, Omega^2=',Omega2(I) ! <<< This should never happen Omega(i)= 0.0_FEKi - if (bCheckSingularity) then - ErrStat2=ErrID_Fatal - ErrMsg2= 'Negative eigenvalue found, system may be singular (may contain rigid body modes)' - if(Failed()) return - endif + call Fatal('Negative eigenvalue found, system may be ill-conditioned'); return endif enddo @@ -170,6 +165,12 @@ LOGICAL FUNCTION Failed() if (Failed) call CleanUpEigen() END FUNCTION Failed + SUBROUTINE Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + CALL SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'EigenSolve'); + CALL CleanUpEigen() + END SUBROUTINE Fatal + SUBROUTINE CleanupEigen() IF (ALLOCATED(Work) ) DEALLOCATE(Work) IF (ALLOCATED(AlphaR)) DEALLOCATE(AlphaR) @@ -181,6 +182,29 @@ END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolve +pure subroutine sort_in_place(a,key) + real(FEKi), intent(inout), dimension(:) :: a + integer(IntKi), intent(inout), dimension(:) :: key + integer(IntKi) :: tempI + real(FEKi) :: temp + integer(IntKi) :: i, j + do i = 2, size(a) + j = i - 1 + temp = a(i) + tempI = key(i) + do while (j>=1 .and. a(j)>temp) + a(j+1) = a(j) + key(j+1) = key(j) + j = j - 1 + if (j<1) then + exit + endif + end do + a(j+1) = temp + key(j+1) = tempI + end do +end subroutine sort_in_place + !> Compute the determinant of a real matrix using an LU factorization FUNCTION Determinant(A, ErrStat, ErrMsg) result(det) use NWTC_LAPACK, only: LAPACK_GETRF diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 40126411c..67f6d0a39 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1470,14 +1470,16 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly real(FEKi), dimension(:,:), allocatable :: MM, KK real(FEKi), dimension(:), allocatable :: FF + real(FEKi), dimension(:,:), allocatable :: Temp, T_red_T integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF ErrStat = ErrID_None ErrMsg = "" ! Setup list of rigid link assemblies (RA) and the inverse function RA^{-1} call RigidLinkAssemblies(Init, p, RA, RAm1, ErrStat2, ErrMsg2); if(Failed()) return - call BuildTMatrix(Init, p, RA, RAm1, p%T_red, ErrStat2, ErrMsg2); if (Failed()) return + if (allocated(RAm1)) deallocate(RAm1) + if (allocated(RA )) deallocate(RA ) ! --- DOF elimination for system matrices and RHS vector nDOF = p%nDOF_red @@ -1487,13 +1489,22 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) call move_alloc(Init%K, KK) call move_alloc(Init%FG, FF) ! Reallocating - CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix - CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG ,nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix + CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix + CALL AllocAry( Init%FG, nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( Temp ,size(MM,1), nDOF, 'Temp' , ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry( T_red_T,nDOF , size(MM,1), 'T_red_T' , ErrStat2, ErrMsg2); if(Failed()) return; ! Elimination - Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) - Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) - Init%FG = matmul(transpose(p%T_red), FF) + !Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) + !Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) + T_red_T = transpose(p%T_red) + Temp = matmul(MM, p%T_red) + Init%M = matmul(T_red_T, Temp) + Temp = matmul(KK, p%T_red) + Init%K = matmul(T_red_T, Temp) + Init%FG = matmul(T_red_T, FF) + if (allocated(Temp)) deallocate(Temp) + if (allocated(T_red_T)) deallocate(T_red_T) ! --- Triggers for storage of DOF indices, replacing with indices in constrained system CALL ReInitBCs(Init, p) @@ -1530,7 +1541,8 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(FF )) deallocate(FF ) if (allocated(RA )) deallocate(RA ) if (allocated(RAm1)) deallocate(RAm1) - if (allocated(RA )) deallocate(RA ) + if (allocated(Temp)) deallocate(Temp) + if (allocated(T_red_T)) deallocate(T_red_T) END SUBROUTINE CleanUp_DirectElimination !> Reset DOF indices after elimination, does not change the BC diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 2c53a39c6..4eb2d3660 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2567,7 +2567,6 @@ END SUBROUTINE AllocMiscVars !! C_L : "reaction" nodes DOFs that will be counted as internal !! I_B : "interface" nodes DOFs that are leader DOFs SUBROUTINE PartitionDOFNodes(Init, m, p, ErrStat, ErrMsg) - use qsort_c_module, only: QsortC use IntegerList, only: len, concatenate_lists, lists_difference, concatenate_3lists, sort_in_place type(SD_Inittype), intent( in) :: Init !< Input data for initialization routine type(SD_MiscVartype), intent( in) :: m !< Misc @@ -3078,7 +3077,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write Eigenvalues of full SYstem and CB reduced System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') "#Eigenfrequencies for full system (no constraint) [Hz]" + WRITE(UnSum, '(A, I6)') "#Eigenfrequencies [Hz] for full system, with reaction constraints (+ Soil K/M + SoilDyn K0) " call yaml_write_array(UnSum, 'Full_frequencies', Omega/(TwoPi), ReFmt, ErrStat2, ErrMsg2) WRITE(UnSum, '(A, I6)') "#CB frequencies [Hz]" call yaml_write_array(UnSum, 'CB_frequencies', CBparams%OmegaL(1:p%nDOFM)/(TwoPi), ReFmt, ErrStat2, ErrMsg2) @@ -3087,15 +3086,15 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) ! write Eigenvectors of full System !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A, I6)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& - ') [m or rad]. Number of shown eigenvectors (total # of DOFs minus restrained nodes'' DOFs):'), nOmega + WRITE(UnSum, '(A)') ('#FEM Eigenvectors ('//TRIM(Num2LStr(p%nDOF_red))//' x '//TRIM(Num2LStr(nOmega))//& + ') [m or rad], full system with reaction constraints (+ Soil K/M + SoilDyn K0)') call yaml_write_array(UnSum, 'Full_Modes', Modes(:,1:nOmega), ReFmt, ErrStat2, ErrMsg2) !------------------------------------------------------------------------------------------------------------- ! write CB system matrices !------------------------------------------------------------------------------------------------------------- WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (constraint applied)' + WRITE(UnSum, '(A)') '#CB Matrices (PhiM,PhiR) (reaction constraints applied)' call yaml_write_array(UnSum, 'PhiM', CBparams%PhiL(:,1:p%nDOFM ), ReFmt, ErrStat2, ErrMsg2, comment='(CB modes)') call yaml_write_array(UnSum, 'PhiR', CBparams%PhiR, ReFmt, ErrStat2, ErrMsg2, comment='(Guyan modes)') @@ -3126,7 +3125,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) deallocate(TI2) - if(p%OutAll) then + if(p%OutAll) then ! //--- START DEBUG OUTPUTS WRITE(UnSum, '()') WRITE(UnSum, '(A)') SectionDivide @@ -3185,7 +3184,7 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) if(allocated(BB)) deallocate(BB) if(allocated(CC)) deallocate(CC) if(allocated(DD)) deallocate(DD) - endif + endif ! //--- END DEBUG OUTPUTS ! --- write TP TI matrix WRITE(UnSum, '(A)') SectionDivide diff --git a/modules/subdyn/src/qsort_c_module.f90 b/modules/subdyn/src/qsort_c_module.f90 deleted file mode 100644 index 553b25544..000000000 --- a/modules/subdyn/src/qsort_c_module.f90 +++ /dev/null @@ -1,61 +0,0 @@ -!********************************************************************************************************************************** -module qsort_c_module -!This routine ASSUMES A is (m,2) dimensioned array -implicit none -public :: QsortC -private :: Partition - -contains - -recursive subroutine QsortC(A) - integer, intent(in out), dimension(:,:) :: A - integer :: iq - - if(size(A,1) > 1) then - call Partition(A, iq) - call QsortC(A(:iq-1, :)) - call QsortC(A(iq:, :)) - endif -end subroutine QsortC - -subroutine Partition(A, marker) - integer, intent(in out), dimension(:,:) :: A - integer, intent(out) :: marker - integer :: i, j, k - integer :: temp - integer :: x ! pivot point - x = A(1, 1) - i= 0 - j= size(A,1) + 1 - - - do - j = j-1 - do - if (A(j,1) <= x) exit - j = j-1 - end do - i = i+1 - do - if (A(i,1) >= x) exit - i = i+1 - end do - if (i < j) then - ! exchange A(i) and A(j) - do k=1,size(A,2) - temp = A(i,k) - A(i,k) = A(j,k) - A(j,k) = temp - end do !k - elseif (i == j) then - marker = i+1 - return - else - marker = i - return - endif - end do - -end subroutine Partition - -end module qsort_c_module \ No newline at end of file diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index ceb338d7b..eeb5db06d 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -1723,7 +1723,6 @@ - diff --git a/vs-build/SubDyn/SubDyn.vfproj b/vs-build/SubDyn/SubDyn.vfproj index ff937857a..b8e89e3c0 100644 --- a/vs-build/SubDyn/SubDyn.vfproj +++ b/vs-build/SubDyn/SubDyn.vfproj @@ -175,7 +175,6 @@ - From 20748423ff3e3004fc74ce119eda89872948be44 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 11 Aug 2020 20:30:41 -0600 Subject: [PATCH 265/377] FlexSub: reintroducing LaKi and fix bound issue --- modules/subdyn/src/FEM.f90 | 96 +++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 0d6a96ce9..812cffd01 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -23,6 +23,7 @@ MODULE FEM IMPLICIT NONE INTEGER, PARAMETER :: FEKi = R8Ki ! Define the kind to be used for FEM + INTEGER, PARAMETER :: LaKi = R8Ki ! Define the kind to be used for LaPack CONTAINS !------------------------------------------------------------------------------------------------------ @@ -31,23 +32,23 @@ MODULE FEM SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMsg ) USE NWTC_LAPACK, only: LAPACK_ggev INTEGER , INTENT(IN ) :: N !< Number of degrees of freedom, size of M and K - REAL(FEKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix - REAL(FEKi), INTENT(INOUT) :: M(N, N) !< Mass matrix + REAL(LaKi), INTENT(INOUT) :: K(N, N) !< Stiffness matrix + REAL(LaKi), INTENT(INOUT) :: M(N, N) !< Mass matrix LOGICAL, INTENT(IN ) :: bCheckSingularity ! If True, the solver will fail if rigid modes are present - REAL(FEKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors - REAL(FEKi), INTENT(INOUT) :: Omega(N) !< Returned Eigenvalues + REAL(LaKi), INTENT(INOUT) :: EigVect(N, N) !< Returned Eigenvectors + REAL(LaKi), INTENT(INOUT) :: Omega(N) !< Returned Eigenvalues INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! LOCALS - REAL(FEKi), ALLOCATABLE :: WORK (:), VL(:,:), AlphaR(:), AlphaI(:), BETA(:) ! eigensolver variables + REAL(LaKi), ALLOCATABLE :: WORK (:), VL(:,:), AlphaR(:), AlphaI(:), BETA(:) ! eigensolver variables INTEGER :: i INTEGER :: LWORK !variables for the eigensolver INTEGER, ALLOCATABLE :: KEY(:) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - REAL(FEKi) :: normA - REAL(FEKi) :: Omega2(N) !< Squared eigenvalues - REAL(FEKi), parameter :: MAX_EIGENVALUE = HUGE(1.0_ReKi) ! To avoid overflow when switching to ReKi + REAL(LaKi) :: normA + REAL(LaKi) :: Omega2(N) !< Squared eigenvalues + REAL(LaKi), parameter :: MAX_EIGENVALUE = HUGE(1.0_ReKi) ! To avoid overflow when switching to ReKi ErrStat = ErrID_None ErrMsg = '' @@ -64,7 +65,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs ! --- Eigenvalue analysis ! note: SGGEV seems to have memory issues in certain cases. The eigenvalues seem to be okay, but the eigenvectors vary wildly with different compiling options. - ! DGGEV seems to work better, so I'm making these variables FEKi (which is set to R8Ki for now) - bjj 4/25/2014 + ! DGGEV seems to work better, so I'm making these variables LaKi (which is set to R8Ki for now) - bjj 4/25/2014 ! bjj: This comes from the LAPACK documentation: ! Note: the quotients AlphaR(j)/BETA(j) and AlphaI(j)/BETA(j) may easily over- or underflow, and BETA(j) may even be zero. ! Thus, the user should avoid naively computing the ratio Alpha/beta. However, AlphaR and AlphaI will be always less @@ -74,7 +75,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs if(Failed()) return ! --- Determinign and sorting eigen frequencies - Omega2(:) =0.0_FEKi + Omega2(:) =0.0_LaKi DO I=1,N !Initialize the key and calculate Omega KEY(I)=I Omega2(I) = AlphaR(I)/Beta(I) @@ -84,11 +85,11 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs Omega2(I) = MAX_EIGENVALUE elseif ( EqualRealNos(real(AlphaI(I),ReKi),0.0_ReKi) ) THEN ! --- Real Eigenvalues - IF ( AlphaR(I)<0.0_FEKi ) THEN - if ( (AlphaR(I)/Beta(I))<1e-6_FEKi ) then + IF ( AlphaR(I)<0.0_LaKi ) THEN + if ( (AlphaR(I)/Beta(I))<1e-6_LaKi ) then ! Tolerating very small negative eigenvalues call WrScr('[INFO] Negative eigenvalue found with small norm (system may contain rigid body mode)') - Omega2(I)=0.0_FEKi + Omega2(I)=0.0_LaKi else call WrScr('[WARN] Negative eigenvalue found, system may be ill-conditioned.') Omega2(I)=AlphaR(I)/Beta(I) @@ -99,11 +100,11 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs else ! --- Complex Eigenvalues normA = sqrt(AlphaR(I)**2 + AlphaI(I)**2) - if ( (normA/Beta(I))<1e-6_FEKi ) then + if ( (normA/Beta(I))<1e-6_LaKi ) then ! Tolerating very small eigenvalues with imaginary part call WrScr('[WARN] Complex eigenvalue found with small norm, approximating as 0') - Omega2(I) = 0.0_FEKi - elseif ( abs(AlphaR(I))>1e3_FEKi*abs(AlphaI(I)) ) then + Omega2(I) = 0.0_LaKi + elseif ( abs(AlphaR(I))>1e3_LaKi*abs(AlphaI(I)) ) then ! Tolerating very small imaginary part compared to real part... (not pretty) call WrScr('[WARN] Complex eigenvalue found with small Im compare to Re') Omega2(I) = AlphaR(I)/Beta(I) @@ -111,7 +112,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs call WrScr('[WARN] Complex eigenvalue found with large imaginary value)') Omega2(I) = MAX_EIGENVALUE endif - call Fatal('Complex eigenvalue found, system may be ill-conditioned'); return + !call Fatal('Complex eigenvalue found, system may be ill-conditioned'); return endif ! Capping to avoid overflow if (Omega2(I)> MAX_EIGENVALUE) then @@ -138,10 +139,10 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++! ! --- Return Omega (capped by huge(ReKi)) and check for singularity - Omega(:) = 0.0_FEKi + Omega(:) = 0.0_LaKi do I=1,N if (EqualRealNos(real(Omega2(I),ReKi), 0.0_ReKi)) then ! NOTE: may be necessary for some corner numerics - Omega(i)=0.0_FEKi + Omega(i)=0.0_LaKi if (bCheckSingularity) then call Fatal('Zero eigenvalue found, system may contain rigid body mode'); return endif @@ -150,7 +151,7 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs else ! Negative eigenfrequency print*,'>>> Wrong eigenfrequency, Omega^2=',Omega2(I) ! <<< This should never happen - Omega(i)= 0.0_FEKi + Omega(i)= 0.0_LaKi call Fatal('Negative eigenvalue found, system may be ill-conditioned'); return endif enddo @@ -183,10 +184,10 @@ END SUBROUTINE CleanupEigen END SUBROUTINE EigenSolve pure subroutine sort_in_place(a,key) - real(FEKi), intent(inout), dimension(:) :: a + real(LaKi), intent(inout), dimension(:) :: a integer(IntKi), intent(inout), dimension(:) :: key integer(IntKi) :: tempI - real(FEKi) :: temp + real(LaKi) :: temp integer(IntKi) :: i, j do i = 2, size(a) j = i - 1 @@ -455,11 +456,12 @@ SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, call BreakSysMtrx(MM, KK, IDR, IDL, nR, nL, MRR, MLL, MRL, KRR, KLL, KRL, FG=FG, FGR=FGR, FGL=FGL, CC=CC, CRR=CRR, CLL=CLL, CRL=CRL) ! --- CB reduction call CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& !< Inputs - MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2,& !< Outputs + MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat2, ErrMsg2, & !< Outputs CRR=CRR, CLL=CLL, CRL=CRL,& !< Optional inputs CBB=CBB, CBM=CBM, CMM=CMM) !< Optional Outputs if(Failed()) return + ! --- Reduction of force if provided if (present(FG).and.present(FGR).and.present(FGL)) then if (present(FGM)) then @@ -670,27 +672,29 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega LOGICAL, OPTIONAL, INTENT(IN ) :: bDOF(nDOF) ! Optinal Mask for DOF to keep (True), or reduce (False) ! LOCALS - REAL(FEKi), ALLOCATABLE :: K_FEKi(:,:), M_FEKi(:,:) - REAL(FEKi), ALLOCATABLE :: EigVect_FEKi(:,:), Omega2_FEKi(:) + REAL(LaKi), ALLOCATABLE :: K_LaKi(:,:), M_LaKi(:,:) + REAL(LaKi), ALLOCATABLE :: EigVect_LaKi(:,:), Omega_LaKi(:) INTEGER(IntKi) :: N INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrStat = ErrID_None ErrMsg = '' + EigVect=0.0_FeKi + Omega=0.0_FeKi ! --- Unfortunate conversion to FEKi... TODO TODO consider storing M and K in FEKi if (present(bDOF)) then ! Remove unwanted DOFs - call RemoveDOF(M, bDOF, M_FEKi, ErrStat2, ErrMsg2); if(Failed()) return - call RemoveDOF(K, bDOF, K_FEKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(M, bDOF, M_LaKi, ErrStat2, ErrMsg2); if(Failed()) return + call RemoveDOF(K, bDOF, K_LaKi, ErrStat2, ErrMsg2); if(Failed()) return else N=size(K,1) - CALL AllocAry(K_FEKi , N, N, 'K_FEKi', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(M_FEKi , N, N, 'M_FEKi', ErrStat2, ErrMsg2); if(Failed()) return - K_FEKi = real( K, FEKi ) - M_FEKi = real( M, FEKi ) + CALL AllocAry(K_LaKi , N, N, 'K_FEKi', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(M_LaKi , N, N, 'M_FEKi', ErrStat2, ErrMsg2); if(Failed()) return + K_LaKi = real( K, LaKi ) + M_LaKi = real( M, LaKi ) endif - N=size(K_FEKi,1) + N=size(K_LaKi,1) ! Note: NOmega must be <= N, which is the length of Omega2, Phi! if ( NOmega > nDOF ) then @@ -700,15 +704,19 @@ SUBROUTINE EigenSolveWrap(K, M, nDOF, NOmega, bCheckSingularity, EigVect, Omega end if ! --- Eigenvalue analysis - CALL AllocAry(EigVect_FEKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; - CALL EigenSolve(K_FEKi, M_FEKi, N, bCheckSingularity, EigVect_FEKi, Omega, ErrStat2, ErrMsg2 ); if (Failed()) return; + CALL AllocAry(EigVect_LAKi, N, N, 'EigVect', ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry(Omega_LaKi, N , 'Omega', ErrStat2, ErrMsg2); if(Failed()) return; ! <<< NOTE: Needed due to dimension of Omega + CALL EigenSolve(K_LaKi, M_LaKi, N, bCheckSingularity, EigVect_LaKi, Omega_LaKi, ErrStat2, ErrMsg2 ); if (Failed()) return; + + Omega(:) = huge(1.0_ReKi) + Omega(1:nOmega) = real(Omega_LaKi(1:nOmega), FEKi) !<<< nOmega Expand a matrix to includes rows where bDOF is False (inverse behavior as RemoveDOF) SUBROUTINE InsertDOFrows(Ared, bDOF, DefaultVal, A, ErrStat, ErrMsg ) - REAL(FEKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix + REAL(LaKi), INTENT(IN ) :: Ared(:, :) ! Reduced matrix logical, INTENT(IN ) :: bDOF(:) ! Array of logical specifying whether a DOF is to be kept(True), or removed (False) REAL(FEKi), INTENT(IN ) :: DefaultVal ! Default value to fill the REAL(FEKi) , INTENT(INOUT) :: A(:,:) ! Full matrix @@ -1323,7 +1331,7 @@ END SUBROUTINE LumpForces !! Method 2: [U,S,V] = svd(A); pinv_A = ( V / S ) * U'; (matlab) ! perform lapack GESVD and then pinv(A) = V*(inv(S))*U' SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) - use NWTC_LAPACK, only: LAPACK_DGESVD, LAPACK_GEMM + use NWTC_LAPACK, only: LAPACK_GESVD, LAPACK_GEMM real(FEKi), dimension(:,:), intent(in) :: A real(FEKi), dimension(:,:), allocatable :: Ainv INTEGER(IntKi), INTENT( OUT) :: ErrStat ! < Error status of the operation @@ -1356,7 +1364,7 @@ SUBROUTINE PseudoInverse(A, Ainv, ErrStat, ErrMsg) ! --- Compute the SVD of A ! [U,S,V] = svd(A) !call DGESVD ('S', 'S', M, N, A, M, S, U, M , Vt , K, WORK, LWORK, INFO) - call LAPACK_DGESVD('S', 'S', M, N, Acopy, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) + call LAPACK_GESVD('S', 'S', M, N, Acopy, S, U, Vt, WORK, LWORK, ErrStat, ErrMsg) !--- Compute PINV = V**T * SIGMA * U**T in two steps ! SIGMA = S^(-1)=1/S(j), S is diagonal From 1a5a8a867406d1746235186bc50b9fbbb8172f79 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 12 Aug 2020 13:15:19 -0600 Subject: [PATCH 266/377] FlexSub: update of doc due to label being case sensitive --- docs/source/user/subdyn/theory.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 612f033db..048557c1b 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -935,7 +935,7 @@ leading to the following identification: In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the transition piece :math:`F_{TP}`: -.. math:: :label: y1 +.. math:: :label: smally1 y1 = Y_1 =-F_{TP} @@ -990,7 +990,7 @@ Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: The output equation for :math:`y_1` can now be identified as: -.. math:: :label: Y1 +.. math:: :label: bigY1 -Y_1 = F_{TP} = C_1 x + D_1 \bar{u} + F_{Y1} @@ -1073,7 +1073,7 @@ Using the expression of :math:`\ddot{q}m` from Eq. :eq:`ddotqm`, the internal ac The output equation for :math:`y_2`: can then be written as: -.. math:: :label: Y2 +.. math:: :label: bigY2 Y_2 = C_2 x + D_2 u + F_{Y2} @@ -1109,7 +1109,7 @@ where \Phi_m \Phi_m^T F_{L,g} \end{bmatrix} -The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`Y2sim` is used instead. +The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`bigY2sim` is used instead. @@ -1240,7 +1240,7 @@ known values, with the inputs :math:`u(t)` coming from ElastoDyn and HydroDyn, a the states :math:`x(t)` known from the previous time-step integration. All of the parameter matrices are calculated in the SubDyn initiation module. With known :math:`u(t)` and :math:`x(t)`, :math:`{\dot{x}(t)}` can be calculated using the state equation :math:`{\dot{x}(t)=X(u,x,t)}` (see Eq. :eq:`state_eq`), and -the outputs :math:`y_1(t)` and :math:`y_2(t)` can be calculated solving Eqs. :eq:`Y1` and :eq:`Y2`. The element forces +the outputs :math:`y_1(t)` and :math:`y_2(t)` can be calculated solving Eqs. :eq:`bigY1` and :eq:`bigY2`. The element forces can also be calculated using Eq. :eq:`el_loads`. The next time-step states :math:`{x(t + \Delta t)}` are obtained by integration: @@ -1397,7 +1397,7 @@ The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R described in :numref:`SSformulation` to :numref:`TimeIntegration`. For example, states are still calculated and integrated as in Eq. :eq:`state_eq`, and the output to ElastoDyn, i.e., the reaction provided by the substructure at the TP interface, is also -calculated as it was done previously in Eqs. :eq:`y1` and :eq:`Y1`. +calculated as it was done previously in Eqs. :eq:`smally1` and :eq:`bigY1`. However, the state-space formulation is slightly modified (simply adding the contribution :math:`U_{L0}-U_{L0m}` to :math:`F_{Y2}` @@ -1421,9 +1421,9 @@ when computing the outputs to HydroDyn as: \ddot{U}_L \\ \end{bmatrix} -The array :math:`F_{Y2}` from Eq. :eq:`Y2` is now defined as follows: +The array :math:`F_{Y2}` from Eq. :eq:`bigY2` is now defined as follows: -.. math:: :label: Y2sim +.. math:: :label: bigY2sim F_{Y2} &= \begin{bmatrix} 0 \\ From a90bee8f191ee3029185f3c76c66f2c34e0504b9 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Aug 2020 14:35:03 -0600 Subject: [PATCH 267/377] Bug fixes and code clean up Handling corner case where there are no Excitation and Radiation states, but we are using linearization. Added writing of Radiation Kernel for NBodyMod=1. Altered computation of perturbed SS_Exctn or SS_Rdtn states. Removed several TODO comments --- modules/hydrodyn/src/HydroDyn.f90 | 165 ++++++++++++------- modules/hydrodyn/src/SS_Excitation.txt | 2 +- modules/hydrodyn/src/SS_Excitation_Types.f90 | 2 +- modules/hydrodyn/src/SS_Radiation.txt | 2 +- modules/hydrodyn/src/SS_Radiation_Types.f90 | 2 +- modules/hydrodyn/src/WAMIT.f90 | 2 +- 6 files changed, 112 insertions(+), 63 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 02a3d78d6..d92038f7f 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -87,7 +87,7 @@ SUBROUTINE WvStretch_Init(WaveStMod, WtrDpth, NStepWave, NNodes, & INTEGER, INTENT(IN ) :: WaveStMod REAL(SiKi), INTENT(IN ) :: WtrDpth INTEGER, INTENT(IN ) :: NStepWave - INTEGER, INTENT(IN ) :: NNodes !< TODO: WHY are there both NNodes and NWaveElev ??? GJH 2/1/2016 + INTEGER, INTENT(IN ) :: NNodes INTEGER, INTENT(IN ) :: NWaveElev REAL(SiKi), INTENT(IN ) :: WaveElev(0:,:) REAL(SiKi), INTENT(IN ) :: WaveKinzi(:) @@ -225,7 +225,7 @@ END SUBROUTINE WvStretch_Init SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut, ErrStat, ErrMsg ) !.................................................................................................................................. - TYPE(HydroDyn_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine. TODO: This does not follow the template due to the interface of HydroDyn_CopyInitInput() + TYPE(HydroDyn_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization routine. TYPE(HydroDyn_InputType), INTENT( OUT) :: u !< An initial guess for the input; input mesh must be defined TYPE(HydroDyn_ParameterType), INTENT( OUT) :: p !< Parameters TYPE(HydroDyn_ContinuousStateType), INTENT( OUT) :: x !< Initial continuous states @@ -256,7 +256,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! LOGICAL :: hasWAMITOuts ! Are there any WAMIT-related outputs ! LOGICAL :: hasMorisonOuts ! Are there any Morison-related outputs ! INTEGER :: numHydroOuts ! total number of WAMIT and Morison outputs - INTEGER :: I, J, iBody ! Generic counters + INTEGER :: I, J, k, iBody ! Generic counters REAL(SiKi) :: WaveNmbr ! Wavenumber of the current frequency component (1/meter) ! These are dummy variables to satisfy the framework, but are not used @@ -930,12 +930,10 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I InitLocal%WAMIT%WaveDirMin = Waves_InitOut%WaveDirMin InitLocal%WAMIT%WaveDirMax = Waves_InitOut%WaveDirMax InitLocal%WAMIT%WaveDOmega = Waves_InitOut%WaveDOmega - -!<==============TODO Check if this code block is needed ===================== + ! Init inputs for the SS_Excitation model (set this just in case it will be used) InitLocal%WAMIT%WaveDir = Waves_InitOut%WaveDir - CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) -!<==============TODO Check if this code block is needed ===================== + CALL MOVE_ALLOC(Waves_InitOut%WaveElev0, InitLocal%WAMIT%WaveElev0) ! Temporarily move arrays to init input for WAMIT (save some space) CALL MOVE_ALLOC(p%WaveTime, InitLocal%WAMIT%WaveTime) @@ -1432,7 +1430,50 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Write the header for this section: Note: When NBodyMod = 1 the kernel is now 6*NBody by 6*Nbody in size, ! and we have NBody 6 by 6 kernels for NBodyMod=2 or 3 if (p%NBodyMod == 1) then - !TODO: Implement NBodyMod=1 kernel printout + ! NBodyMod=1 kernel printout which is 6*NBody x 6*NBody long + WRITE( InitLocal%UnSum, '(//)' ) + WRITE( InitLocal%UnSum, '(A)' ) 'Radiation memory effect kernel' + WRITE( InitLocal%UnSum, '(//)' ) + + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10)',ADVANCE='no' ) ' n ' , ' t ' + do i = 1,6*p%NBody + do j = 1,6*p%NBody + WRITE( InitLocal%UnSum, '(2X,A16)',ADVANCE='no' ) 'K'//trim(num2lstr(i))//trim(num2lstr(j)) + end do + end do + write(InitLocal%UnSum,'()') ! end of line character + + + WRITE( InitLocal%UnSum, '(1X,A10,2X,A10)',ADVANCE='no' ) ' (-) ' , ' (s) ' + do i = 1,6*p%NBody + do j = 1,6*p%NBody + if ( mod(i-1,6)+1 < 4 ) then + if ( mod(j-1,6)+1 < 4 ) then + WRITE( InitLocal%UnSum, '(2X,A16)',ADVANCE='no' ) ' (kg/s^2) ' + else + WRITE( InitLocal%UnSum, '(2X,A16)',ADVANCE='no' ) ' (kgm/s^2) ' + end if + else + if ( mod(j-1,6)+1 < 4 ) then + WRITE( InitLocal%UnSum, '(2X,A16)',ADVANCE='no' ) ' (kgm/s^2) ' + else + WRITE( InitLocal%UnSum, '(2X,A16)',ADVANCE='no' ) '(kgm^2/s^2)' + end if + end if + end do + end do + write(InitLocal%UnSum,'()') ! end of line character + + do k= 0,p%WAMIT(1)%Conv_Rdtn%NStepRdtn-1 + WRITE( InitLocal%UnSum, '(1X,I10,2X,E12.5)',ADVANCE='no' ) K, K*p%WAMIT(1)%Conv_Rdtn%RdtnDT + do i = 1,6*p%NBody + do j = 1,6*p%NBody + WRITE( InitLocal%UnSum, '(2X,ES16.5)',ADVANCE='no' ) p%WAMIT(1)%Conv_Rdtn%RdtnKrnl(k,i,j) + end do + end do + write(InitLocal%UnSum,'()') ! end of line character + end do + else do j = 1,p%nWAMITObj WRITE( InitLocal%UnSum, '(//)' ) @@ -1842,7 +1883,6 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt ! Allocate array of WAMIT inputs - ! TODO: We should avoid allocating this at each time step if we can! !FIXME: Error handling appears to be broken here @@ -2017,7 +2057,6 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, if ( p%PotMod == 1 ) then - !TODO: Check that we have valid Mesh data? do iBody = 1, p%NBody ! Determine the rotational angles from the direction-cosine matrix rotdisp = GetSmllRotAngs ( u%WAMITMesh%Orientation(:,:,iBody), ErrStat2, ErrMsg2 ) @@ -2513,8 +2552,10 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM IF ( PRESENT( dXdu ) ) THEN - ! LIN_TODO: We need to deal with the case where either RdtnMod=0, and/or ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid - + ! For the case where either RdtnMod=0 and ExtcnMod=0 and hence %SS_Rdtn data or %SS_Exctn data is not valid then we do not have states, so simply return + ! The key here is to never allocate the dXdu and related state Jacobian arrays because then the glue-code will behave properly + + if ( p%totalStates == 0 ) return ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: @@ -2614,21 +2655,7 @@ SUBROUTINE HD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM k = k + 3 offsetI = offsetI + p%WAMIT(j)%SS_Rdtn%numStates end do - end if - - do k = 1,p%nWAMITObj - ! TODO - - do j = 1, 6*p%WAMIT(k)%NBody - do i = 1,p%WAMIT(k)%SS_Rdtn%numStates - dXdu(offsetI+i,offsetJ+j) = p%WAMIT(k)%SS_Rdtn%B(i,j) ! B is numStates by 6*NBody where NBody =1 if NBodyMod=2 or 3, but could be >1 for NBodyMod=1 - end do - end do - offsetI = offsetI + p%WAMIT(k)%SS_Rdtn%numStates - offsetJ = offsetJ + p%WAMIT(k)%SS_Rdtn%numStates - end do - - + end if END IF @@ -2702,6 +2729,7 @@ SUBROUTINE HD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrStat = ErrID_None ErrMsg = '' + if ( p%totalStates == 0 ) return ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: @@ -3021,7 +3049,8 @@ SUBROUTINE HD_Init_Jacobian_y( p, y, InitOut, ErrStat, ErrMsg) ! set linearization output names: !................. CALL AllocAry(InitOut%LinNames_y, p%Jac_ny, 'LinNames_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - ! LIN-TODO: Do we need RotFrame_y for this module? + ! We do not need RotFrame_y for this module and the glue code with handle the fact that we did not allocate the array and hence set all values to false at the glue-code level + ! Same with RotFrame_x !CALL AllocAry(InitOut%RotFrame_y, p%Jac_ny, 'RotFrame_y', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -3074,11 +3103,13 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) p%totalExctnStates = 0 p%totalRdtnStates = 0 do j = 1, p%nWAMITObj - p%totalExctnStates = p%totalExctnStates + p%WAMIT(j)%SS_Exctn%numStates - p%totalRdtnStates = p%totalRdtnStates + p%WAMIT(j)%SS_Rdtn%numStates + p%totalExctnStates = p%totalExctnStates + p%WAMIT(j)%SS_Exctn%numStates !numStates defaults to zero in the case where ExctnMod = 0 instead of 2 + p%totalRdtnStates = p%totalRdtnStates + p%WAMIT(j)%SS_Rdtn%numStates !numStates defaults to zero in the case where RdtnMod = 0 instead of 2 end do p%totalStates = p%totalExctnStates + p%totalRdtnStates - if ( p%totalStates == 0 ) return + + if ( p%totalStates == 0 ) return ! No states, so return and do not allocate the following arrays. This lets the glue-code know that the module does not have states + ! allocate space for the row/column names and for perturbation sizes call allocAry(p%dx, p%totalStates, 'p%dx', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) call AllocAry(InitOut%LinNames_x, p%totalStates, 'LinNames_x' , ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -3105,7 +3136,6 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) modLabels = (/'Exctn ','Rdtn '/) dofLabels = (/'PtfmSg ','PtfmSw ','PtfmHv ','PtfmR ','PtfmP ','PtfmY '/) - !TODO: If NBodyMod=1, do not use the 'B' + number prefix do k = 1, 2 ! 1 = Excitation, 2 = Radiation do l=1,p%nWAMITObj @@ -3118,10 +3148,18 @@ SUBROUTINE HD_Init_Jacobian_x( p, InitOut, ErrStat, ErrMsg) spdof = p%WAMIT(l)%SS_Rdtn%spdof(j) end if - do i = 1,spdof - InitOut%LinNames_x(indx) = 'B'//trim(num2lstr(l))//trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) - indx = indx + 1 - end do + if ( p%NBodyMod == 1 ) then + do i = 1,spdof + InitOut%LinNames_x(indx) = trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) + indx = indx + 1 + end do + else + do i = 1,spdof + InitOut%LinNames_x(indx) = 'B'//trim(num2lstr(l))//trim(modLabels(k))//trim(dofLabels(j))//trim(num2lstr(i)) + indx = indx + 1 + end do + end if + end do end do end do @@ -3266,7 +3304,7 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) if (ErrStat >= AbortErrLev) return - perturb_t = 0.02_ReKi*D2R * max(p%WtrDpth,1.0_ReKi) ! translation input scaling ! LIN-TODO What about MSL offset? + perturb_t = 0.02_ReKi*D2R * max(p%WtrDpth,1.0_ReKi) ! translation input scaling perturb = 2*D2R ! rotational input scaling index = 0 @@ -3301,9 +3339,9 @@ SUBROUTINE HD_Init_Jacobian( p, u, y, InitOut, ErrStat, ErrMsg) ! names of the columns, InitOut%LinNames_u: !................ call AllocAry(InitOut%LinNames_u, nu+1, 'LinNames_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - !LIN-TODO: We do not need any RotFrame info, right? + ! We do not need RotFrame_u for this module and the glue code with handle the fact that we did not allocate the array and hence set all values to false at the glue-code level !call AllocAry(InitOut%RotFrame_u, nu+1, 'RotFrame_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - ! LIN-TODO: have we implemented IsLoad_u ? + call AllocAry(InitOut%IsLoad_u, nu+1, 'IsLoad_u', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -3364,7 +3402,7 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) index = 0 fieldIndx = p%Jac_u_indx(n,2) node = p%Jac_u_indx(n,3) - !TODO: One last review of mesh names in below logic GJH + du = p%du( p%Jac_u_indx(n,1) ) ! determine which mesh we're trying to perturb and perturb the input: @@ -3407,7 +3445,7 @@ SUBROUTINE HD_Perturb_u( p, n, perturb_sign, u, du ) CALL PerturbOrientationMatrix( u%PRPMesh%Orientation(:,:,node), du * perturb_sign, fieldIndx ) CASE (15) !Module/Mesh/Field: u%PRPMesh%TranslationVel = 15 u%PRPMesh%TranslationVel( fieldIndx,node) = u%PRPMesh%TranslationVel( fieldIndx,node) + du * perturb_sign - CASE (16) !Module/Mesh/Field: u%WAMITMesh%RotationVel = 16 + CASE (16) !Module/Mesh/Field: u%PRPMesh%RotationVel = 16 u%PRPMesh%RotationVel (fieldIndx,node) = u%PRPMesh%RotationVel (fieldIndx,node) + du * perturb_sign CASE (17) !Module/Mesh/Field: u%PRPMesh%TranslationAcc = 17 u%PRPMesh%TranslationAcc( fieldIndx,node) = u%PRPMesh%TranslationAcc( fieldIndx,node) + du * perturb_sign @@ -3490,34 +3528,39 @@ SUBROUTINE HD_Perturb_x( p, n, perturb_sign, x, dx ) ! local variables - integer(intKi) :: i, indx, offset1, offset2, n2 + integer(intKi) :: i, offset1, offset2, n2 + + if ( p%totalStates == 0 ) return - !TODO: Note: All excitation states for all bodies are stored 1st, then all radiation states + !Note: All excitation states for all bodies are stored 1st, then all radiation states dx = p%dx(n) offset1 = 1 if ( n <= p%totalExctnStates ) then ! Find body index for exctn states + do i=1,p%nWAMITObj + offset2 = offset1 + p%WAMIT(i)%SS_Exctn%numStates + if ( n >= offset1 .and. n < offset2) then + n2 = n - offset1 + 1 + x%WAMIT(i)%SS_Exctn%x( n2 ) = x%WAMIT(i)%SS_Exctn%x( n2 ) + dx * perturb_sign + exit + end if + offset1 = offset2 + end do else + offset1 = p%totalExctnStates + 1 ! Find body index for rdtn states - end if - - do i=1,p%nWAMITObj - offset2 = offset1 + p%WAMIT(i)%SS_Exctn%numStates + p%WAMIT(i)%SS_Rdtn%numStates - if ( n >= offset1 .and. n < offset2) then - n2 = n - offset1 - if ( n2 > p%WAMIT(i)%SS_Exctn%numStates) then - indx = n2 - p%WAMIT(i)%SS_Exctn%numStates - x%WAMIT(i)%SS_Rdtn%x( indx ) = x%WAMIT(i)%SS_Rdtn%x( indx ) + dx * perturb_sign - else - indx = n2 - x%WAMIT(i)%SS_Exctn%x( indx ) = x%WAMIT(i)%SS_Exctn%x( indx ) + dx * perturb_sign + do i=1,p%nWAMITObj + offset2 = offset1 + p%WAMIT(i)%SS_Exctn%numStates + if ( n >= offset1 .and. n < offset2) then + n2 = n - offset1 + 1 + x%WAMIT(i)%SS_Rdtn%x( n2 ) = x%WAMIT(i)%SS_Rdtn%x( n2 ) + dx * perturb_sign + exit end if - else offset1 = offset2 - end if - end do + end do + end if END SUBROUTINE HD_Perturb_x @@ -3672,6 +3715,9 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, !.................................. IF ( PRESENT( x_op ) ) THEN + + if ( p%totalStates == 0 ) return + if ( y%WAMITMesh%Committed ) then if (.not. allocated(x_op)) then call AllocAry(x_op, p%totalStates,'x_op',ErrStat2,ErrMsg2) @@ -3696,6 +3742,9 @@ SUBROUTINE HD_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, !.................................. IF ( PRESENT( dx_op ) ) THEN + + if ( p%totalStates == 0 ) return + if ( y%WAMITMesh%Committed ) then if (.not. allocated(dx_op)) then call AllocAry(dx_op, p%totalStates,'dx_op',ErrStat2,ErrMsg2) diff --git a/modules/hydrodyn/src/SS_Excitation.txt b/modules/hydrodyn/src/SS_Excitation.txt index 72bd6e193..251d863d7 100644 --- a/modules/hydrodyn/src/SS_Excitation.txt +++ b/modules/hydrodyn/src/SS_Excitation.txt @@ -55,7 +55,7 @@ typedef ^ ^ IntKi typedef ^ ^ ReKi A {:}{:} - - "A matrix" - typedef ^ ^ ReKi B {:} - - "B matrix" - typedef ^ ^ ReKi C {:}{:} - - "C matrix" - -typedef ^ ^ INTEGER numStates - - - "Number of states" - +typedef ^ ^ INTEGER numStates - 0 - "Number of states" - typedef ^ ^ DbKi Tc - - - "Time shift" s typedef ^ ^ SiKi WaveElev0 {:} - - "Wave elevation time history at origin" m typedef ^ ^ SiKi WaveTime {:} - - "Times where wave elevation is known" s diff --git a/modules/hydrodyn/src/SS_Excitation_Types.f90 b/modules/hydrodyn/src/SS_Excitation_Types.f90 index 2ed4153ec..1dbef8c91 100644 --- a/modules/hydrodyn/src/SS_Excitation_Types.f90 +++ b/modules/hydrodyn/src/SS_Excitation_Types.f90 @@ -85,7 +85,7 @@ MODULE SS_Excitation_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: numStates !< Number of states [-] + INTEGER(IntKi) :: numStates = 0 !< Number of states [-] REAL(DbKi) :: Tc !< Time shift [s] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveElev0 !< Wave elevation time history at origin [m] REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: WaveTime !< Times where wave elevation is known [s] diff --git a/modules/hydrodyn/src/SS_Radiation.txt b/modules/hydrodyn/src/SS_Radiation.txt index eead37a5c..07e6d29ab 100644 --- a/modules/hydrodyn/src/SS_Radiation.txt +++ b/modules/hydrodyn/src/SS_Radiation.txt @@ -45,7 +45,7 @@ typedef ^ ParameterType DbKi DT typedef ^ ^ ReKi A {:}{:} - - "A matrix" - typedef ^ ^ ReKi B {:}{:} - - "B matrix" - typedef ^ ^ ReKi C {:}{:} - - "C matrix" - -typedef ^ ^ INTEGER numStates - - - "Number of states" - +typedef ^ ^ INTEGER numStates - 0 - "Number of states" - typedef ^ ^ INTEGER spdof {:} - - "States per dof" - typedef ^ ^ IntKi NBody - - - "Number of WAMIT bodies for this State Space model" - diff --git a/modules/hydrodyn/src/SS_Radiation_Types.f90 b/modules/hydrodyn/src/SS_Radiation_Types.f90 index 8822320c3..9b26c59a7 100644 --- a/modules/hydrodyn/src/SS_Radiation_Types.f90 +++ b/modules/hydrodyn/src/SS_Radiation_Types.f90 @@ -79,7 +79,7 @@ MODULE SS_Radiation_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: A !< A matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< B matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C !< C matrix [-] - INTEGER(IntKi) :: numStates !< Number of states [-] + INTEGER(IntKi) :: numStates = 0 !< Number of states [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: spdof !< States per dof [-] INTEGER(IntKi) :: NBody !< Number of WAMIT bodies for this State Space model [-] END TYPE SS_Rad_ParameterType diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 5f74a3000..04b9be358 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -1835,7 +1835,7 @@ SUBROUTINE WAMIT_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, CALL SS_Rad_CalcContStateDeriv( Time, m%SS_Rdtn_u, p%SS_Rdtn, x%SS_Rdtn, xd%SS_Rdtn, z%SS_Rdtn, OtherState%SS_Rdtn, m%SS_Rdtn, dxdt%SS_Rdtn, ErrStat, ErrMsg ) ! NOTE: The input below (0.0) will only work as part of a linearization Get_OP call! If this routine (WAMIT_CalcContStateDeriv) is called in another context, then the following - ! input needs to be implemented generically. + ! input needs to be implemented generically. As of Aug 10, 2020, this is only called for Get_OP related work. GJH CALL SS_Exc_CalcContStateDeriv( Time, 0.0_SiKi, p%SS_Exctn, x%SS_Exctn, xd%SS_Exctn, z%SS_Exctn, OtherState%SS_Exctn, m%SS_Exctn, dxdt%SS_Exctn, ErrStat, ErrMsg ) END SUBROUTINE WAMIT_CalcContStateDeriv From 08af427a81c6dd2e634acd5b05050520c0077615 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Aug 2020 14:35:28 -0600 Subject: [PATCH 268/377] Updated the ballast equation --- modules/hydrodyn/src/Morison.f90 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 52fe69676..60fb839ca 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1687,8 +1687,10 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! force and moment magnitude constants member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * member%h_fill *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)*member%dRdl_in(i) + member%Rin(i))*member%h_fill + 1/3*member%dRdl_in(i)*member%h_fill**2 ) - member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1/3 *member%dRdl_in(i)**2 *member%h_fill**2 ) - member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2/3*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) + 1.5*member%h_fill*member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*member%h_fill*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) + member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1/3 *member%dRdl_in(i)**2 *member%h_fill**2 ) + member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2/3*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) & + + 1.5*member%h_fill*member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*member%h_fill*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) & + -0.25 * member%FillDens * gravity * Pi * ( member%Rin(i) + member%h_fill*member%dRdl_in(i))**4 ! unflooded element else @@ -3102,11 +3104,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, m%F_D_End(i,j) = p%An_End(i,j)*p%DragConst_End(j)*abs(vmag)*vmag ! Note: vmag is zero if node is not in the water - !TODO: This needs to be reworked with new equations - !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) y%Mesh%Force(i,j) = y%Mesh%Force(i,j) + m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) ELSE - !m%F_B_End(I,J) = m%nodeInWater(j)*p%F_B_End(I,J) y%Mesh%Moment(i-3,j) = y%Mesh%Moment(i-3,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) END IF END DO ! I=1,6 From 5480069de9833d900cf0599c4b600edb49d1742f Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Aug 2020 14:37:01 -0600 Subject: [PATCH 269/377] Fixed bug where ED motions were set to Mooring even though SD is used Also removed TODO comments --- modules/openfast-library/src/FAST_Solver.f90 | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 37b5bdb78..7ba4e67f9 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -1095,8 +1095,8 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, END IF - IF ( p_FAST%CompMooring == Module_MAP ) THEN -!TODO: GJH Need to check for SD, if present, then SD will transfer to these Mooring modules, NOT ED! GJH 5/11/2020 + IF ( p_FAST%CompMooring == Module_MAP .and. p_FAST%CompSub /= Module_SD ) THEN +!TODO: GJH I do not have plan documentation for the External Platform connection to MAP GJH 8/11/2020 ! motions: CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MAP%PtFairDisplacement' ) @@ -2626,12 +2626,12 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, PlatformMotions => y_ED2%PlatformPtMesh + !.................. ! Set mooring line and ice inputs (which don't have acceleration fields and aren't used elsewhere in this routine, thus we're using the actual inputs (not a copy) ! Note that these values get overwritten at the completion of this routine.) !.................. -!TODO: GJH Need to determine if mooring is connected to ED or SD GJH 5/11/2020 IF ( p_FAST%CompMooring == Module_MAP ) THEN @@ -2729,10 +2729,6 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, CALL Transfer_SD_to_HD( y_SD2, MeshMapData%u_HD_W_Mesh, MeshMapData%u_HD_M_Mesh, MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) -!TODO: GJH I don't believe we need the following GJH 5/12/2020 - ! ! Map ED motion output to HD PRP inputs: - !CALL Transfer_Point_to_Point( PlatformMotions, MeshMapData%u_HD_PRP_Mesh, MeshMapData%ED_P_2_HD_PRP_P, ErrStat2, ErrMsg2 ) - ! CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) !.................. ! Get SD loads inputs (MeshMapData%u_HD_W_Mesh and MeshMapData%u_HD_M_Mesh meshes must be set first) @@ -2893,9 +2889,8 @@ SUBROUTINE U_FullOpt1_Residual( y_ED2, y_SD2, y_HD2, y_BD2, y_Orca2, y_ExtPtfm2, ! at this point, MeshMapData%u_ED_PlatformPtMesh contains the portion of loads from SD and/or HD !.................. - !TODO: GJH This is no longer added to ED if SD is present, instead these are sent to SD GJH 5/11/2020 - ! Get the loads for ED from a mooring module and add them: + ! Get the loads for ED/SD from a mooring module and add them: IF ( p_FAST%CompMooring == Module_MAP ) THEN if ( p_FAST%CompSub == Module_SD ) then CALL Transfer_Point_to_Point( y_MAP%PtFairleadLoad, MeshMapData%u_SD_LMesh_2, MeshMapData%Mooring_P_2_SD_P, ErrStat2, ErrMsg2, u_MAP%PtFairDisplacement, y_SD2%Y2Mesh ) !u_MAP and y_SD contain the displacements needed for moment calculations @@ -4133,7 +4128,6 @@ SUBROUTINE InitModuleMappings(p_FAST, ED, BD, AD14, AD, HD, SD, ExtPtfm, SrvD, M ! ElastoDyn point mesh HydroDyn Morison point mesh (ED sets inputs, but gets outputs from HD%y%WAMITMesh in floating case) IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN - !TODO: HD Changes: Need to transfer Morison Loads to PlatformLoads CALL MeshMapCreate( HD%y%Morison%Mesh, PlatformLoads, MeshMapData%HD_M_P_2_ED_P, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//':HD_M_P_2_ED_P' ) CALL MeshMapCreate( PlatformMotion, HD%Input(1)%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) @@ -4724,7 +4718,6 @@ SUBROUTINE SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, ! Set mooring line and ice inputs (which don't have acceleration fields) !.................. -!TODO: GJH Need to check whether SD or ED sends output to Mooring GJH 5/11/2020 IF ( p_FAST%CompMooring == Module_MAP ) THEN From f1df49e7befc0cb4b0273e0ff0203a93bc132b6c Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Aug 2020 14:38:23 -0600 Subject: [PATCH 270/377] Removed more TODO comments --- modules/openfast-library/src/FAST_Subs.f90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 8b84da615..a2bc71326 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -797,9 +797,6 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if (allocated(Init%OutData_HD%LinNames_y)) call move_alloc(Init%OutData_HD%LinNames_y,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_y ) if (allocated(Init%OutData_HD%LinNames_u)) call move_alloc(Init%OutData_HD%LinNames_u,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_u ) if (allocated(Init%OutData_HD%LinNames_x)) call move_alloc(Init%OutData_HD%LinNames_x, y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%Names_x ) -! LIN-TODO: Determine if we need to create this data even though we don't have rotating frames in HD - !if (allocated(Init%OutData_HD%RotFrame_y)) call move_alloc(Init%OutData_HD%RotFrame_y,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%RotFrame_y ) - !if (allocated(Init%OutData_HD%RotFrame_u)) call move_alloc(Init%OutData_HD%RotFrame_u,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%RotFrame_u ) if (allocated(Init%OutData_HD%DerivOrder_x)) call move_alloc(Init%OutData_HD%DerivOrder_x,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%DerivOrder_x) if (allocated(Init%OutData_HD%IsLoad_u )) call move_alloc(Init%OutData_HD%IsLoad_u ,y_FAST%Lin%Modules(MODULE_HD)%Instance(1)%IsLoad_u ) @@ -974,9 +971,6 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, else if (allocated(Init%OutData_MAP%LinInitOut%LinNames_y)) call move_alloc(Init%OutData_MAP%LinInitOut%LinNames_y,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%Names_y ) if (allocated(Init%OutData_MAP%LinInitOut%LinNames_u)) call move_alloc(Init%OutData_MAP%LinInitOut%LinNames_u,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%Names_u ) -! LIN-TODO: Determine if we need to create this data even though we don't have rotating frames in MAP - !if (allocated(Init%OutData_MAP%LinInitOut%RotFrame_y)) call move_alloc(Init%OutData_MAP%LinInitOut%RotFrame_y,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%RotFrame_y ) - !if (allocated(Init%OutData_MAP%LinInitOut%RotFrame_u)) call move_alloc(Init%OutData_MAP%LinInitOut%RotFrame_u,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%RotFrame_u ) if (allocated(Init%OutData_MAP%LinInitOut%IsLoad_u )) call move_alloc(Init%OutData_MAP%LinInitOut%IsLoad_u ,y_FAST%Lin%Modules(Module_MAP)%Instance(1)%IsLoad_u ) if (allocated(Init%OutData_MAP%WriteOutputHdr)) y_FAST%Lin%Modules(Module_MAP)%Instance(1)%NumOutputs = size(Init%OutData_MAP%WriteOutputHdr) From 4a4629ba3ba8c498260e9b55aba7747e2a225efb Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 12 Aug 2020 14:40:30 -0600 Subject: [PATCH 271/377] Bug fixes and code clean up Removed TODO comments Fixed bug with handling of UserProp input for AD module Removed redundant SD-related section Correct VTK state array population code for HD and SD --- modules/openfast-library/src/FAST_Lin.f90 | 160 +++++----------------- 1 file changed, 34 insertions(+), 126 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index ca1673b9b..ca139193d 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -484,11 +484,12 @@ SUBROUTINE Init_Lin_InputOutput(p_FAST, y_FAST, NumBl, NumBlNodes, ErrStat, ErrM end do ! AD standard inputs: UserProp(NumBlNodes,NumBl) - ! LIN-TODO Add these Userprop values - do j=1,NumBl*NumBlNodes - y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. - end do - + if (p_FAST%CompAero == MODULE_AD) then + do j=1,NumBl*NumBlNodes + y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_AD)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. + end do + end if + ! ED standard inputs: BlPitchCom, YawMom, GenTrq, extended input (collective pitch) do j=1,NumBl+3 y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%use_u(y_FAST%Lin%Modules(MODULE_ED)%Instance(1)%SizeLin(LIN_INPUT_COL)+1-j) = .true. @@ -1003,7 +1004,6 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, end if end if - !LIN-TODO: Review SubDyn!!!! !..................... ! SubDyn / ExtPtfm !..................... @@ -1013,25 +1013,25 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, call SD_JacobianPInput( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, & dYdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%B ) - !if(Failed()) return; + if(Failed()) return; call SD_JacobianPContState( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2,& dYdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%A ) - !if(Failed()) return; + if(Failed()) return; ! get the operating point call SD_GetOP(t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR),& SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_u,& y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y, & x_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_dx) - !if(Failed()) return; + if(Failed()) return; ! write the module matrices: if (p_FAST%LinOutMod) then OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SD)) call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - !if(Failed()) return; + if(Failed()) return; if (p_FAST%LinOutJac) then ! Jacobians @@ -1049,25 +1049,25 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & dYdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B ) - !if(Failed()) return; + if(Failed()) return; call ExtPtfm_JacobianPContState( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2,& dYdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A ) - !if(Failed()) return; + if(Failed()) return; ! get the operating point call ExtPtfm_GetOP(t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR),& ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_u,& y_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_y, & x_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_dx) - !if(Failed()) return; + if(Failed()) return; ! write the module matrices: if (p_FAST%LinOutMod) then OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_ExtPtfm)) call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - !if(Failed()) return; + if(Failed()) return; if (p_FAST%LinOutJac) then ! Jacobians @@ -1129,88 +1129,6 @@ SUBROUTINE FAST_Linearize_OP(t_global, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, end if ! if ( p_FAST%LinOutMod ) end if ! if ( p_FAST%CompMooring == Module_MAP ) - !..................... - ! SubDyn - !..................... - if ( p_FAST%CompSub == Module_SD ) then - ! get the jacobians - call SD_JacobianPInput( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & - SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, & - dYdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_SD)%Instance(1)%B ) - if(Failed()) return; - - call SD_JacobianPContState( t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), & - SD%z(STATE_CURR), SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2,& - dYdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_SD)%Instance(1)%A ) - if(Failed()) return; - - ! get the operating point - call SD_GetOP(t_global, SD%Input(1), SD%p, SD%x(STATE_CURR), SD%xd(STATE_CURR), SD%z(STATE_CURR),& - SD%OtherSt(STATE_CURR), SD%y, SD%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_u,& - y_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_y, & - x_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_SD)%Instance(1)%op_dx) - if(Failed()) return; - - ! write the module matrices: - if (p_FAST%LinOutMod) then - OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_SD)) - call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - if(Failed()) return; - - if (p_FAST%LinOutJac) then - ! Jacobians - call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx') - call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) - call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y) - call WrPartialMatrix(y_FAST%Lin%Modules(Module_SD)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_y, & - UseCol=y_FAST%Lin%Modules(Module_SD)%Instance(1)%use_u) - end if - ! finish writing the file - call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_SD)%Instance(1) ) - end if - - !..................... - ! ExtPtfm - !..................... - elseif ( p_FAST%CompSub == Module_ExtPtfm ) then - ! get the jacobians - call ExtPtfm_JacobianPInput( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & - ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, & - dYdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, dXdu=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B ) - if(Failed()) return; - - call ExtPtfm_JacobianPContState( t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), & - ExtPtfm%z(STATE_CURR), ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2,& - dYdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, dXdx=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A ) - if(Failed()) return; - - ! get the operating point - call ExtPtfm_GetOP(t_global, ExtPtfm%Input(1), ExtPtfm%p, ExtPtfm%x(STATE_CURR), ExtPtfm%xd(STATE_CURR), ExtPtfm%z(STATE_CURR),& - ExtPtfm%OtherSt(STATE_CURR), ExtPtfm%y, ExtPtfm%m, ErrStat2, ErrMsg2, u_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_u,& - y_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_y, & - x_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_x, dx_op=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%op_dx) - if(Failed()) return; - - ! write the module matrices: - if (p_FAST%LinOutMod) then - OutFileName = trim(LinRootName)//'.'//TRIM(y_FAST%Module_Abrev(Module_ExtPtfm)) - call WrLinFile_txt_Head(t_global, p_FAST, y_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1), OutFileName, Un, ErrStat2, ErrMsg2) - if(Failed()) return; - - if (p_FAST%LinOutJac) then - ! Jacobians - call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%A, Un, p_FAST%OutFmt, 'dXdx') - call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%B, Un, p_FAST%OutFmt, 'dXdu', UseCol=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_u) - call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%C, Un, p_FAST%OutFmt, 'dYdx', UseRow=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_y) - call WrPartialMatrix(y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%D, Un, p_FAST%OutFmt, 'dYdu', UseRow=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_y, & - UseCol=y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1)%use_u) - end if - ! finish writing the file - call WrLinFile_txt_End(Un, p_FAST, y_FAST%Lin%Modules(Module_ExtPtfm)%Instance(1) ) - end if - end if ! ExtPtfm - - !..................... ! Linearization of glue code Input/Output solve: !..................... @@ -2681,16 +2599,15 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, u_ED, y_ED, y_AD, u_AD, BD, CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message ! local variables - !LIN-TODO: Add comments INTEGER(IntKi) :: i ! rows/columns INTEGER(IntKi) :: K ! Loops through blades INTEGER(IntKi) :: AD_Out_Start ! starting index of dUdy (column) where particular AD fields are located INTEGER(IntKi) :: BD_Out_Start ! starting index of dUdy (column) where particular BD fields are located INTEGER(IntKi) :: ED_Start ! starting index of dUdy (row) where ED input fields are located INTEGER(IntKi) :: ED_Out_Start ! starting index of dUdy (column) where ED output fields are located - INTEGER(IntKi) :: HD_Out_Start - INTEGER(IntKi) :: SD_Out_Start - INTEGER(IntKi) :: MAP_Out_Start + INTEGER(IntKi) :: HD_Out_Start ! starting index of dUdy (column) where HD output fields are located + INTEGER(IntKi) :: SD_Out_Start ! starting index of dUdy (column) where SD output fields are located + INTEGER(IntKi) :: MAP_Out_Start ! starting index of dUdy (column) where MAP output fields are located CHARACTER(*), PARAMETER :: RoutineName = 'Linear_ED_InputSolve_dy' @@ -3178,15 +3095,6 @@ SUBROUTINE Linear_HD_InputSolve_du( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapDat ErrStat = ErrID_None ErrMsg = "" - ! note that we assume this block matrix has been initialized to the identity matrix before calling this routine - ! We need to make six calls to SetBlockMatrix for the different output to input mappings - ! LIN-TODO: Are this row and col still valid GJH 7/31/2020 - ! 1) Row 3, Col 1 - ! 2) Row 5, Col 1 - ! 3) Row 9, Col 7 - ! 4) Row 11, Col 7 - ! 5) Row 15, Col 13 - ! 6) Row 17, Col 13 ! look at how the translational displacement gets transfered to the translational velocity and translational acceleration: !------------------------------------------------------------------------------------------------- @@ -4923,7 +4831,7 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, ! local variables INTEGER(IntKi) :: k ! generic loop counters - INTEGER(IntKi) :: i ! generic loop counters + INTEGER(IntKi) :: i, iStart ! generic loop counters INTEGER(IntKi) :: iBody ! WAMIT body loop counter INTEGER(IntKi) :: j ! generic loop counters INTEGER(IntKi) :: indx ! generic loop counters @@ -4948,7 +4856,7 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x_eig_mag)) then do j=1,size(y_FAST%Lin%Modules(ThisModule)%Instance(k)%op_x) ! use this for the loop because ED may have a larger op_x_eig_mag array than op_x - + ! this is a hack because not all modules pack the continuous states in the same way: if (ThisModule == Module_ED) then if (j<= ED%p%DOFs%NActvDOF) then @@ -5015,42 +4923,42 @@ SUBROUTINE PerturbOP(t, iLinTime, iMode, p_FAST, y_FAST, ED, BD, SrvD, AD, IfW, !!!IF ( p_FAST%CompServo == Module_SrvD ) THEN !!!END IF - ! HydroDyn: copy op to actual states and inputs IF ( p_FAST%CompHydro == Module_HD ) THEN ThisModule = Module_HD if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then - ! TODO: WAMIT parameter and continuous states are now an arrays of length NBody, so we need to modify this following code to handle that - ! We will try to loop over NBody and add each to the state array + ! WAMIT parameter and continuous states are now an arrays of length NBody + ! All Excitation states are stored first and then Radiation states. + ! We will try to loop over each of the NBody(s) and add each body's states to the overall state array + iStart = 1 do iBody = 1, HD%p%NBody nStates = HD%p%WAMIT(iBody)%SS_Exctn%numStates if (nStates > 0) then - call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Exctn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Exctn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(iStart:iStart+nStates-1), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(iStart:iStart+nStates-1)) + iStart = iStart + nStates end if end do do iBody = 1, HD%p%NBody nStates = HD%p%WAMIT(iBody)%SS_Rdtn%numStates - if (nStates < size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then - call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Rdtn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) + if (nStates > 0) then + call GetStateAry(p_FAST, iMode, t, HD%x( STATE_CURR)%WAMIT(iBody)%SS_Rdtn%x, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(iStart:iStart+nStates-1), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(iStart:iStart+nStates-1)) + iStart = iStart + nStates end if end do end if END IF - - !LIN-TODO: we need this for SD GJH - !!!! SubDyn: copy final predictions to actual states - !!!IF ( p_FAST%CompSub == Module_SD ) THEN - ! SubDyn: + + + ! SubDyn: copy final predictions to actual states + IF ( p_FAST%CompSub == Module_SD ) THEN ThisModule = Module_SD if (allocated(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)) then nStates = size(y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag)/2 - call GetStateAry(p_FAST, iMode, t, SD%x( STATE_CURR)%qm, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag( :nStates), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase( :nStates)) call GetStateAry(p_FAST, iMode, t, SD%x( STATE_CURR)%qmdot, y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_mag(1+nStates: ), y_FAST%Lin%Modules(ThisModule)%Instance(1)%op_x_eig_phase(1+nStates: )) end if - - !!!ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN - !!!END IF + ELSE IF ( p_FAST%CompSub == Module_ExtPtfm ) THEN + END IF END SUBROUTINE PerturbOP !---------------------------------------------------------------------------------------------------------------------------------- From 3439a6052f4fc4bdb28f1f1b5802442fc1e775d1 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 13 Aug 2020 09:32:48 -0600 Subject: [PATCH 272/377] Big fix: corrected bad merge changes --- modules/hydrodyn/src/HydroDyn_Input.f90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 63e9170f7..120fe9163 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -267,6 +267,8 @@ SUBROUTINE HydroDynInput_GetInput( InitInp, ErrStat, ErrMsg ) CHARACTER(1024) :: Line ! String to temporarially hold value of read line CHARACTER(1024) :: FileName ! Name of HydroDyn input file CHARACTER( 35) :: Frmt ! Output format for logical parameters. (matches NWTC Subroutine Library format) + real(ReKi), ALLOCATABLE :: tmpVec1(:), tmpVec2(:) ! Temporary arrays for WAMIT data + integer(IntKi) :: startIndx, endIndx ! indices into working arrays INTEGER, ALLOCATABLE :: tmpArray(:) ! Temporary array storage of the joint output list CHARACTER(1) :: Line1 ! The first character of an input line INTEGER(IntKi) :: ErrStat2 From b64fc97cf69e309aca1ac938ca3b437377e56256 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 13 Aug 2020 11:57:01 -0600 Subject: [PATCH 273/377] FlexSub: small merge issue --- modules/openfast-library/src/FAST_Subs.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index d9b83f154..ae5ad8953 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -845,7 +845,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, !Init%InData_SD%UseInputFile = .TRUE. Init%InData_SD%SDInputFile = p_FAST%SubFile Init%InData_SD%RootName = p_FAST%OutFileRoot - Init%InData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to + Init%InData_SD%TP_RefPoint = ED%y%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to Init%InData_SD%SubRotateZ = 0.0 ! Used by driver to rotate structure around z From 121693cbfeedb03ae677115d279174a2494934d3 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 13 Aug 2020 14:08:36 -0600 Subject: [PATCH 274/377] Bug fix: changed Output(1) to y in order to use the correct data --- modules/openfast-library/src/FAST_Subs.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index f20593565..57b2fb788 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -843,7 +843,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, !Ini%tInData_SD%UseInputFile = .TRUE. Init%InData_SD%SDInputFile = p_FAST%SubFile Init%InData_SD%RootName = p_FAST%OutFileRoot - Init%InData_SD%TP_RefPoint = ED%Output(1)%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to + Init%InData_SD%TP_RefPoint = ED%y%PlatformPtMesh%Position(:,1) ! "Interface point" where loads will be transferred to Init%InData_SD%SubRotateZ = 0.0 ! Used by driver to rotate structure around z From 553cb442b5aaf817163780d870b225d169ea6940 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 13 Aug 2020 14:26:33 -0600 Subject: [PATCH 275/377] FlexSub: implemented controllable cables --- modules/subdyn/src/SD_FEM.f90 | 114 ++++++++++------- modules/subdyn/src/SubDyn.f90 | 69 +++++++--- modules/subdyn/src/SubDyn_Driver.f90 | 7 + modules/subdyn/src/SubDyn_Registry.txt | 15 ++- modules/subdyn/src/SubDyn_Types.f90 | 170 +++++++++++++------------ 5 files changed, 223 insertions(+), 152 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 67f6d0a39..2fdc1a4bc 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1102,79 +1102,95 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM -!> Init for control Cable force -!! The change of cable forces due to the control is linear, so we just store a "unit" force vector -!! We will just scale this vector at each time step based on the control input (Tcontrol): -!! Fcontrol = (Tcontrol-T0) * Funit -SUBROUTINE ControlCableForceInit(Init, p, m, ErrStat, ErrMsg) - TYPE(SD_InitType), INTENT(INOUT) :: Init !< Remove me, kept just in case for now - TYPE(SD_ParameterType), INTENT(IN ) :: p - TYPE(SD_MiscVarType), INTENT(INOUT) :: m - INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None +!> Map control cable index to control channel index +subroutine ControlCableMapping(Init, p, ErrStat, ErrMsg) + type(SD_InitType), intent(in ) :: Init !< init + type(SD_ParameterType), intent(inout) :: p !< param + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 + integer(IntKi) :: i, nCC, idCProp !< index, number of controlable cables, id of Cable Prop + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 ErrMsg = "" ErrStat = ErrID_None - - ! Allocating necessary arrays - CALL AllocAry( m%FC_red , p%nDOF_red, 'm%FC0_red', ErrStat2, ErrMsg2); if(Failed()) return; ! Constant cable force - CALL AllocAry( m%FC_red_unit , p%nDOF_red, 'm%FC_red' , ErrStat2, ErrMsg2); if(Failed()) return; ! Control cable force - m%FC_red = 0.0_ReKi - m%FC_red_unit = 0.0_ReKi - ! Setting up unit force vector - call ControlCableForce_Unit(p, m%FC_red_unit, ErrStat2, ErrMsg2); if(Failed()) return; - -CONTAINS - LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableForceInit') + ! --- Count number of Controllable cables + nCC = 0 + do i = 1, size(p%ElemProps) + if (p%ElemProps(i)%eType==idMemberCable) then + idCProp= p%Elems(i,iMProp) + if (Init%PropsC(idCProp, 5 )>0) then + !print*,'Cable Element',i,'controllable with channel',Init%PropsC(idCProp, 5 ) + nCC=nCC+1 + endif + endif + enddo + if (nCC>0) then + call WrScr('Number of controllable cables: '//trim(num2lstr(nCC))) + endif + call AllocAry( p%CtrlElem2Channel, nCC, 2, 'p%CtrlElem2Channel', ErrStat2, ErrMsg2); if(Failed()) return; ! Constant cable force + + ! --- Store mapping + nCC = 0 + do i = 1, size(p%ElemProps) + if (p%ElemProps(i)%eType==idMemberCable) then + idCProp= p%Elems(i,iMProp) + if (Init%PropsC(idCProp, 5 )>0) then + nCC=nCC+1 + p%CtrlElem2Channel(nCC, 1) = i ! Element index (in p%Elems and p%ElemProps) + p%CtrlElem2Channel(nCC, 2) = Init%PropsC(idCProp,5) ! Control channel + endif + endif + enddo +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableMapping') Failed = ErrStat >= AbortErrLev - END FUNCTION Failed -END SUBROUTINE ControlCableForceInit + end function Failed +end subroutine ControlCableMapping !> Init for control Cable force -!! TODO TODO Expensive implementation for now -SUBROUTINE ControlCableForce_Unit(p, FC_red, ErrStat, ErrMsg) - TYPE(SD_ParameterType), INTENT(IN ) :: p - real(ReKi), DIMENSION(:), INTENT(INOUT) :: FC_red +!! The change of cable forces due to the control is linear, so we just store a "unit" force vector +!! We will just scale this vector at each time step based on the control input (Tcontrol): +!! Fcontrol = (Tcontrol-T0) * Funit +!! We store it in "non-reduced" system since it will added to the external forces +SUBROUTINE ControlCableForceInit(p, m, ErrStat, ErrMsg) + TYPE(SD_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I - real(FEKi), DIMENSION(:), allocatable :: FC + INTEGER :: iCC, iElem REAL(FEKi) :: FCe(12) ! Pretension force from cable element + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system ErrMsg = "" ErrStat = ErrID_None - CALL AllocAry(FC ,p%nDOF , 'FC' , ErrStat2, ErrMsg2); if(Failed()) return; ! Control cable force + + ! Allocating necessary arrays + CALL AllocAry( m%FC_unit , p%nDOF, 'm%FC0' , ErrStat2, ErrMsg2); if(Failed()) return; ! Control cable force + m%FC_unit = 0.0_ReKi ! loop over all elements, compute element matrices and assemble into global matrices - DO i = 1, size(p%ElemProps) ! TODO loop on cable only - if (p%ElemProps(i)%eType==idMemberCable) then - CALL ElemF_Cable(1.0_ReKi, p%ElemProps(i)%DirCos, FCe) !< NOTE: using unitary load T0=1.0_ReKi - ! --- Assembly in global unconstrained system - IDOF = p%ElemsDOF(1:12, i) - FC( IDOF ) = FC( IDOF ) + FCe(1:12) ! Note: gravity and pretension cable forces - endif + DO iCC = 1, size(p%CtrlElem2Channel,1) + iElem = p%CtrlElem2Channel(iCC,1) + CALL ElemF_Cable(1.0_ReKi, p%ElemProps(iElem)%DirCos, FCe) !< NOTE: using unitary load T0=1.0_ReKi + ! --- Assembly in global unconstrained system + IDOF = p%ElemsDOF(1:12, iElem) + m%FC_unit( IDOF ) = m%FC_unit( IDOF ) + FCe(1:12) ENDDO ! Transforming the vector into reduced, direct elimination system: - FC_red = matmul(transpose(p%T_red), FC) - if(allocated(FC)) deallocate(FC) + !FC_red = matmul(transpose(p%T_red), FC) + !if(allocated(FC)) deallocate(FC) CONTAINS LOGICAL FUNCTION Failed() - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableForce') + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableForceInit') Failed = ErrStat >= AbortErrLev END FUNCTION Failed -END SUBROUTINE ControlCableForce_Unit - - - - +END SUBROUTINE ControlCableForceInit !> Add soil stiffness and mass to global system matrices SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 4eb2d3660..df1ffc91c 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -215,6 +215,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO !Store mapping between nodes and elements CALL NodeCon(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + !Store mapping between controllable elements and control channels + CALL ControlCableMapping(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + ! --- Allocate DOF indices to joints and members call DistributeDOF(Init, p ,ErrStat2, ErrMsg2); if(Failed()) return; @@ -231,10 +234,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL InsertJointStiffDamp(p, Init, ErrStat2, ErrMsg2); if(Failed()) return ! --- Prepare for control cable load, RHS - if (any(Init%PropsC(:,5)>0)) then - print*,'Need to assemble Cable Force' - CALL ControlCableForceInit(Init, p, m, ErrStat2, ErrMsg2); if(Failed()) return - print*,'Controlable cables, feature not ready.' + if (size(p%CtrlElem2Channel,1)>0) then + CALL ControlCableForceInit(p, m, ErrStat2, ErrMsg2); if(Failed()) return + print*,'Controlable cables are present, this feature is not ready at the glue code level.' STOP endif @@ -289,7 +291,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO IF ( Init%SSSum ) THEN ! note p%KBB/MBB are KBBt/MBBt ! Write a summary of the SubDyn Initialization - CALL OutSummary(Init, p, InitInput, CBparams, ErrStat2, ErrMsg2); if(Failed()) return + CALL OutSummary(Init, p, m, InitInput, CBparams, ErrStat2, ErrMsg2); if(Failed()) return ENDIF ! Initialize the outputs & Store mapping between nodes and elements @@ -404,7 +406,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) ! Inputs on interior nodes: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); if(Failed()) return !________________________________________ ! Set motion outputs on y%Y2mesh @@ -619,7 +621,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! form u(4) in Eq. 10: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); !Equation 12: X=A*x + B*u + Fx (Eq 12) dxdt%qm= x%qmdot @@ -1129,7 +1131,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ENDIF ENDIF ENDDO - IF (Check (flg .EQ. 0 , ' MemberID is not in the Members list. ')) return + IF (Check (flg .EQ. 0 , ' MemberID '//trim(Num2LStr(p%MOutLst(I)%MemberID))//' requested for output is not in the list of Members. ')) return IF ( Echo ) THEN WRITE( UnEc, '(A)' ) TRIM(Line) @@ -1612,12 +1614,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL ) + CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL, ErrStat2, ErrMsg2 ); ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2 ) + CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2, ErrStat2, ErrMsg2 ); ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2809,13 +2811,17 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL, ErrStat, ErrMsg ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%nDOF__L) + real(ReKi) , intent(out) :: UFL(p%nDOF__L) !< External force on internal nodes "L" + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes integer :: nMembers + integer :: iCC, iElem, iChannel !< Index on control cables, element, Channel + integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system real(ReKi), parameter :: myNaN = -9999998.989_ReKi ! TODO to save time, perform Tred multiplication only if Tred is not identity @@ -2839,6 +2845,23 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) STOP endif endif + + ! --- Adding controllable cable forces + if (size(p%CtrlElem2Channel,1) > 0) then + if (.not. allocated (u%CableTension)) then + call Fatal('Cable tension input not allocated but controllable cables are present'); return + endif + if (size(u%CableTension)< maxval(p%CtrlElem2Channel(:,2)) ) then + call Fatal('Cable tension input has length '//trim(num2lstr(size(u%CableTension)))//' but controllable cables need to access channel '//trim(num2lstr(maxval(p%CtrlElem2Channel(:,2))))); return + endif + do iCC = 1, size(p%CtrlElem2Channel,1) + iElem = p%CtrlElem2Channel(iCC,1) + iChannel = p%CtrlElem2Channel(iCC,2) + IDOF = p%ElemsDOF(1:12, iElem) + m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (u%CableTension(iChannel) - p%ElemProps(iElem)%T0) + enddo + endif + ! --- Reduced vector of external force if (p%reduced) then m%Fext_red = matmul(transpose(p%T_red), m%Fext) @@ -2846,15 +2869,20 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL ) else UFL= m%Fext(p%ID__L) endif - +contains + subroutine Fatal(ErrMsg_in) + character(len=*), intent(in) :: ErrMsg_in + call SetErrStat(ErrID_Fatal, ErrMsg_in, ErrStat, ErrMsg, 'GetExtForce'); + end subroutine Fatal END SUBROUTINE GetExtForceOnInternalDOF !------------------------------------------------------------------------------------------------------ !> Output the summary file -SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) +SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) use Yaml - TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine, this structure contains many variables needed for summary file - TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters,this structure contains many variables needed for summary file + TYPE(SD_InitType), INTENT(INOUT) :: Init ! Input data for initialization routine + TYPE(SD_ParameterType), INTENT(IN) :: p ! Parameters + TYPE(SD_MiscVarType) , INTENT(IN) :: m ! Misc TYPE(SD_InitInputType), INTENT(IN) :: InitInput !< Input data for initialization routine TYPE(CB_MatArrays), INTENT(IN) :: CBparams ! CB parameters that will be passed in for summary file use INTEGER(IntKi), INTENT(OUT) :: ErrStat ! Error status of the operation @@ -2989,9 +3017,16 @@ SUBROUTINE OutSummary(Init, p, InitInput, CBparams, ErrStat,ErrMsg) DummyArray(i,15) = p%ElemProps(i)%Jzz ! Moment of inertia DummyArray(i,16) = p%ElemProps(i)%T0 ! Pretension [N] enddo - write(UnSum, '("#",4x,6(A9),10('//trim(SFmt)//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' + write(UnSum, '("#",4x,6(A9),10('//SFmt//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),7(E15.6,",")') !, comment='',label=.true.) deallocate(DummyArray) + + ! --- C + if(size(p%CtrlElem2Channel,1)>0) then + write(UnSum, '("#",2x,2(A11))') 'Elem_[#] ','Channel_[#]' + call yaml_write_array(UnSum, 'CtrlElem2Channel', p%CtrlElem2Channel, IFmt, ErrStat2, ErrMsg2, comment='') + endif + ! --- User inputs (less interesting, repeat of input file) WRITE(UnSum, '(A)') SectionDivide diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index 6d334ee61..68ca309a0 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -179,6 +179,12 @@ PROGRAM TestSubDyn !............................................................................................................................... ! Force the displacement of the interface node in the global Z direction to be the sag of the column under it's own weight ! u(1)%UFL(3) =-12.958 !this is for testbeam3 + + ! TEMPORARY HACK FOR CONTROLLABLE CABLES + !allocate(u(1)%CableTension(5)) + !!u(1)%CableTension= 1.0e7_ReKi + !u(1)%CableTension= 0.0e7_ReKi + call WrScr('') DO n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 @@ -207,6 +213,7 @@ PROGRAM TestSubDyn END IF END IF + ! Calculate outputs at n CALL SD_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat2, ErrMsg2); call AbortIfFailed() ! Get state variables at next step: INPUT at step n, OUTPUT at step n + 1 diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 0ae625baf..51d7fa669 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -158,14 +158,13 @@ typedef ^ ^ ReKi U_full_dotdot {:} typedef ^ ^ ReKi U_red {:} - - typedef ^ ^ ReKi U_red_dot {:} - - typedef ^ ^ ReKi U_red_dotdot {:} - - -typedef ^ ^ ReKi FC_red {:} - - "Cable Force vector (for varying cable load)" N -typedef ^ ^ ReKi FC_red_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N +typedef ^ ^ ReKi FC_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N ### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### -typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" -typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" -typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" -typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" -typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" +typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" +typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" +typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" +typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" +typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" @@ -186,6 +185,8 @@ typedef ^ ^ IList NodesDOF {:} - - "DOF indices typedef ^ ^ IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" typedef ^ ^ IntKi DOFred2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" +# --- Control +typedef ^ ^ IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x 2, for each CtrlCable, Elem index, and Channel Index" # --- CB reduction typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 3a15a1428..0e23ce709 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -200,8 +200,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_red !< Cable Force vector (for varying cable load) [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_red_unit !< Cable Force vector (for varying cable load, of unit cable load) [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_unit !< Cable Force vector (for varying cable load, of unit cable load) [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] INTEGER(IntKi) :: Decimat !< Current output decimation counter [-] @@ -224,6 +223,7 @@ MODULE SubDyn_Types TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFred !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: DOFred2Nodes !< nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1 [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: CtrlElem2Channel !< nCtrlCable x 2, for each CtrlCable, Elem index, and Channel Index [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] @@ -5676,29 +5676,17 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot ENDIF -IF (ALLOCATED(SrcMiscData%FC_red)) THEN - i1_l = LBOUND(SrcMiscData%FC_red,1) - i1_u = UBOUND(SrcMiscData%FC_red,1) - IF (.NOT. ALLOCATED(DstMiscData%FC_red)) THEN - ALLOCATE(DstMiscData%FC_red(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%FC_unit)) THEN + i1_l = LBOUND(SrcMiscData%FC_unit,1) + i1_u = UBOUND(SrcMiscData%FC_unit,1) + IF (.NOT. ALLOCATED(DstMiscData%FC_unit)) THEN + ALLOCATE(DstMiscData%FC_unit(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FC_red.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FC_unit.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%FC_red = SrcMiscData%FC_red -ENDIF -IF (ALLOCATED(SrcMiscData%FC_red_unit)) THEN - i1_l = LBOUND(SrcMiscData%FC_red_unit,1) - i1_u = UBOUND(SrcMiscData%FC_red_unit,1) - IF (.NOT. ALLOCATED(DstMiscData%FC_red_unit)) THEN - ALLOCATE(DstMiscData%FC_red_unit(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%FC_red_unit.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%FC_red_unit = SrcMiscData%FC_red_unit + DstMiscData%FC_unit = SrcMiscData%FC_unit ENDIF IF (ALLOCATED(SrcMiscData%SDWrOutput)) THEN i1_l = LBOUND(SrcMiscData%SDWrOutput,1) @@ -5791,11 +5779,8 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%U_red_dotdot)) THEN DEALLOCATE(MiscData%U_red_dotdot) ENDIF -IF (ALLOCATED(MiscData%FC_red)) THEN - DEALLOCATE(MiscData%FC_red) -ENDIF -IF (ALLOCATED(MiscData%FC_red_unit)) THEN - DEALLOCATE(MiscData%FC_red_unit) +IF (ALLOCATED(MiscData%FC_unit)) THEN + DEALLOCATE(MiscData%FC_unit) ENDIF IF (ALLOCATED(MiscData%SDWrOutput)) THEN DEALLOCATE(MiscData%SDWrOutput) @@ -5916,15 +5901,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot END IF - Int_BufSz = Int_BufSz + 1 ! FC_red allocated yes/no - IF ( ALLOCATED(InData%FC_red) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FC_red upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FC_red) ! FC_red - END IF - Int_BufSz = Int_BufSz + 1 ! FC_red_unit allocated yes/no - IF ( ALLOCATED(InData%FC_red_unit) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FC_red_unit upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FC_red_unit) ! FC_red_unit + Int_BufSz = Int_BufSz + 1 ! FC_unit allocated yes/no + IF ( ALLOCATED(InData%FC_unit) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FC_unit upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FC_unit) ! FC_unit END IF Int_BufSz = Int_BufSz + 1 ! SDWrOutput allocated yes/no IF ( ALLOCATED(InData%SDWrOutput) ) THEN @@ -6192,33 +6172,18 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%FC_red) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FC_red,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FC_red,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%FC_red,1), UBOUND(InData%FC_red,1) - ReKiBuf(Re_Xferred) = InData%FC_red(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%FC_red_unit) ) THEN + IF ( .NOT. ALLOCATED(InData%FC_unit) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FC_red_unit,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FC_red_unit,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FC_unit,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FC_unit,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%FC_red_unit,1), UBOUND(InData%FC_red_unit,1) - ReKiBuf(Re_Xferred) = InData%FC_red_unit(i1) + DO i1 = LBOUND(InData%FC_unit,1), UBOUND(InData%FC_unit,1) + ReKiBuf(Re_Xferred) = InData%FC_unit(i1) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -6570,39 +6535,21 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_red not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FC_red)) DEALLOCATE(OutData%FC_red) - ALLOCATE(OutData%FC_red(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FC_red.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%FC_red,1), UBOUND(OutData%FC_red,1) - OutData%FC_red(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_red_unit not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_unit not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FC_red_unit)) DEALLOCATE(OutData%FC_red_unit) - ALLOCATE(OutData%FC_red_unit(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%FC_unit)) DEALLOCATE(OutData%FC_unit) + ALLOCATE(OutData%FC_unit(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FC_red_unit.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FC_unit.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%FC_red_unit,1), UBOUND(OutData%FC_red_unit,1) - OutData%FC_red_unit(i1) = ReKiBuf(Re_Xferred) + DO i1 = LBOUND(OutData%FC_unit,1), UBOUND(OutData%FC_unit,1) + OutData%FC_unit(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -6791,6 +6738,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF END IF DstParamData%DOFred2Nodes = SrcParamData%DOFred2Nodes +ENDIF +IF (ALLOCATED(SrcParamData%CtrlElem2Channel)) THEN + i1_l = LBOUND(SrcParamData%CtrlElem2Channel,1) + i1_u = UBOUND(SrcParamData%CtrlElem2Channel,1) + i2_l = LBOUND(SrcParamData%CtrlElem2Channel,2) + i2_u = UBOUND(SrcParamData%CtrlElem2Channel,2) + IF (.NOT. ALLOCATED(DstParamData%CtrlElem2Channel)) THEN + ALLOCATE(DstParamData%CtrlElem2Channel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CtrlElem2Channel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%CtrlElem2Channel = SrcParamData%CtrlElem2Channel ENDIF DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve @@ -7590,6 +7551,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%DOFred2Nodes)) THEN DEALLOCATE(ParamData%DOFred2Nodes) ENDIF +IF (ALLOCATED(ParamData%CtrlElem2Channel)) THEN + DEALLOCATE(ParamData%CtrlElem2Channel) +ENDIF IF (ALLOCATED(ParamData%KMMDiag)) THEN DEALLOCATE(ParamData%KMMDiag) ENDIF @@ -7896,6 +7860,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF ( ALLOCATED(InData%DOFred2Nodes) ) THEN Int_BufSz = Int_BufSz + 2*2 ! DOFred2Nodes upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%DOFred2Nodes) ! DOFred2Nodes + END IF + Int_BufSz = Int_BufSz + 1 ! CtrlElem2Channel allocated yes/no + IF ( ALLOCATED(InData%CtrlElem2Channel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! CtrlElem2Channel upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%CtrlElem2Channel) ! CtrlElem2Channel END IF Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve @@ -8515,6 +8484,26 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 END DO END DO + END IF + IF ( .NOT. ALLOCATED(InData%CtrlElem2Channel) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CtrlElem2Channel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CtrlElem2Channel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%CtrlElem2Channel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CtrlElem2Channel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%CtrlElem2Channel,2), UBOUND(InData%CtrlElem2Channel,2) + DO i1 = LBOUND(InData%CtrlElem2Channel,1), UBOUND(InData%CtrlElem2Channel,1) + IntKiBuf(Int_Xferred) = InData%CtrlElem2Channel(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF IntKiBuf(Int_Xferred) = InData%nDOFM Int_Xferred = Int_Xferred + 1 @@ -9954,6 +9943,29 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 END DO END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CtrlElem2Channel not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%CtrlElem2Channel)) DEALLOCATE(OutData%CtrlElem2Channel) + ALLOCATE(OutData%CtrlElem2Channel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CtrlElem2Channel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%CtrlElem2Channel,2), UBOUND(OutData%CtrlElem2Channel,2) + DO i1 = LBOUND(OutData%CtrlElem2Channel,1), UBOUND(OutData%CtrlElem2Channel,1) + OutData%CtrlElem2Channel(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO END IF OutData%nDOFM = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 From 22e07d4e184dd5dabd86d5cd8393654c41188cfd Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 13 Aug 2020 14:56:32 -0600 Subject: [PATCH 276/377] FlexSub: isolating code for interface DOF force --- modules/subdyn/src/SubDyn.f90 | 52 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index df1ffc91c..bc49c5109 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -389,7 +389,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF REAL(ReKi) :: DCM(3,3) - REAL(ReKi) :: HydroForces(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) + REAL(ReKi) :: F_I(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None @@ -405,8 +405,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - ! Inputs on interior nodes: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); if(Failed()) return + ! External force on internal and interface nodes + call GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); if(Failed()) return + call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) !________________________________________ ! Set motion outputs on y%Y2mesh @@ -497,26 +498,15 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above ! --------------------------------------------------------------------------------- ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] - !NEED TO ADD HYDRODYNAMIC FORCES AT THE Interface NODES - !Aggregate the forces and moments at the interface nodes to the reference point - !TODO: where are these HydroTP, HydroForces documented? - DO I = 1, p%nNodes_I - iSDNode = p%Nodes_I(I,1) - iY2Node = iSDNode - startDOF = (I-1)*6 + 1 ! NOTE: this works since interface is assumed to be sorted like LMesh and have 6 DOF per nodes - !Take care of Hydrodynamic Forces that will go into INterface Forces later - HydroForces(startDOF:startDOF+5) = (/u%LMesh%Force(1:3,iY2Node),u%LMesh%Moment(1:3,iY2Node)/) !(6,NNODES_I) - ENDDO - - !HydroTP = matmul(transpose(p%TI),HydroForces) ! (6,1) calculated below - ! note: matmul( HydroForces, p%TI ) = matmul( transpose(p%TI), HydroForces) because HydroForces is 1-D + !HydroTP = matmul(transpose(p%TI), F_I) ! (6,1) calculated below + ! note: matmul( F_I, p%TI ) = matmul( transpose(p%TI), F_I) because F_I is 1-D IF ( p%nDOFM > 0) THEN Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + - matmul( F_I, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) ELSE ! No retained modes, so there are no states Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( HydroForces, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + - matmul( F_I, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) END IF ! Computing extra moments due to lever arm introduced by interface displacement ! Y1(:3) = -f_TP @@ -2811,19 +2801,19 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL, ErrStat, ErrMsg ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - real(ReKi) , intent(out) :: UFL(p%nDOF__L) !< External force on internal nodes "L" + real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes integer :: nMembers + integer :: startDOF, I integer :: iCC, iElem, iChannel !< Index on control cables, element, Channel integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! TODO to save time, perform Tred multiplication only if Tred is not identity ! --- Build vector of external force m%Fext= myNaN @@ -2865,10 +2855,11 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, UFL, ErrStat, ErrMsg ) ! --- Reduced vector of external force if (p%reduced) then m%Fext_red = matmul(transpose(p%T_red), m%Fext) - UFL= m%Fext_red(p%ID__L) + F_L= m%Fext_red(p%ID__L) else - UFL= m%Fext(p%ID__L) + F_L= m%Fext(p%ID__L) endif + contains subroutine Fatal(ErrMsg_in) character(len=*), intent(in) :: ErrMsg_in @@ -2876,6 +2867,21 @@ subroutine Fatal(ErrMsg_in) end subroutine Fatal END SUBROUTINE GetExtForceOnInternalDOF +!------------------------------------------------------------------------------------------------------ +!> Construct force vector on interface DOF (I) +!! NOTE: This function should only be called after GetExtForceOnInternalDOF +SUBROUTINE GetExtForceOnInterfaceDOF( p, Fext, F_I) + type(SD_ParameterType), intent(in ) :: p ! Parameters + real(ReKi), dimension(:), intent(in ) :: Fext !< Vector of external forces on un-reduced DOF + real(ReKi) , intent(out ) :: F_I(6*p%nNodes_I) !< External force on interface DOF + integer :: iSDNode, startDOF, I + DO I = 1, p%nNodes_I + iSDNode = p%Nodes_I(I,1) + startDOF = (I-1)*6 + 1 ! NOTE: for now we have 6 DOF per interface nodes + F_I(startDOF:startDOF+5) = Fext(p%NodesDOF(iSDNode)%List(1:6)) !TODO try to use Fext_red + ENDDO +END SUBROUTINE GetExtForceOnInterfaceDOF + !------------------------------------------------------------------------------------------------------ !> Output the summary file SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) From 62dbc9758a4186a3916a981fb243d474731833c1 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 14 Aug 2020 13:00:42 -0600 Subject: [PATCH 277/377] Code merge bug fixes --- modules/aerodyn/src/AeroDyn.f90 | 20 +++++++++++--------- modules/aerodyn/src/AirfoilInfo.f90 | 6 +++--- modules/openfast-library/src/FAST_Lin.f90 | 11 +---------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 1ec981ea7..0456c19ab 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -4597,11 +4597,11 @@ SUBROUTINE Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat, ErrMsg) end do !j end do !i - !Module/Mesh/Field: u%UserProp(:,:) = 23,24,25; + !Module/Mesh/Field: u%UserProp(:,:) = 29,30,31; do k=1,size(u%UserProp,2) ! p%NumBlades do i=1,size(u%UserProp,1) ! numNodes - p%Jac_u_indx(index,1) = 22 + k + p%Jac_u_indx(index,1) = 28 + k p%Jac_u_indx(index,2) = 1 !component index: this is a scalar, so 1, but is never used p%Jac_u_indx(index,3) = i !Node: i index = index + 1 @@ -4610,7 +4610,7 @@ SUBROUTINE Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat, ErrMsg) !...................................... ! default perturbations, p%du: !...................................... - call allocAry( p%du, 28, 'p%du', ErrStat2, ErrMsg2) ! 28 = number of unique values in p%Jac_u_indx(:,1) + call allocAry( p%du, 31, 'p%du', ErrStat2, ErrMsg2) ! 31 = number of unique values in p%Jac_u_indx(:,1) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) perturb = 2*D2R @@ -4644,9 +4644,9 @@ SUBROUTINE Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat, ErrMsg) do k=1,p%NumBlades p%du(24 + k) = perturb_b(k) ! u%InflowOnBlade(:,:,k) = 24 + k end do - p%du(22) = perturb_t ! u%InflowOnTower(:,:) = 22 + p%du(28) = perturb_t ! u%InflowOnTower(:,:) = 28 do k=1,p%NumBlades - p%du(22+k) = perturb ! u%UserProp(:,:) = 23,24,25 + p%du(28+k) = perturb ! u%UserProp(:,:) = 29,30,31 end do !..................... ! get names of linearized inputs @@ -4661,7 +4661,9 @@ SUBROUTINE Init_Jacobian_u( InputFileData, p, u, InitOut, ErrStat, ErrMsg) InitOut%IsLoad_u = .false. ! None of AeroDyn's inputs are loads InitOut%RotFrame_u = .false. - + do k=0,p%NumBlades*p%NumBlNds-1 + InitOut%RotFrame_u(nu - k ) = .true. ! UserProp(:,:) + end do index = 1 FieldMask = .false. FieldMask(MASKID_TRANSLATIONDISP) = .true. @@ -4921,11 +4923,11 @@ SUBROUTINE Perturb_u( p, n, perturb_sign, u, du ) CASE (28) !Module/Mesh/Field: u%InflowOnTower(:,:) = 28; u%InflowOnTower(fieldIndx,node) = u%InflowOnTower(fieldIndx,node) + du * perturb_sign - CASE (23) !Module/Mesh/Field: u%UserProp(:,1) = 23; + CASE (29) !Module/Mesh/Field: u%UserProp(:,1) = 29; u%UserProp(node,1) = u%UserProp(node,1) + du * perturb_sign - CASE (24) !Module/Mesh/Field: u%UserProp(:,2) = 23; + CASE (30) !Module/Mesh/Field: u%UserProp(:,2) = 30; u%UserProp(node,2) = u%UserProp(node,2) + du * perturb_sign - CASE (25) !Module/Mesh/Field: u%UserProp(:,3) = 23; + CASE (31) !Module/Mesh/Field: u%UserProp(:,3) = 31; u%UserProp(node,3) = u%UserProp(node,3) + du * perturb_sign END SELECT diff --git a/modules/aerodyn/src/AirfoilInfo.f90 b/modules/aerodyn/src/AirfoilInfo.f90 index 91caba02b..709757896 100644 --- a/modules/aerodyn/src/AirfoilInfo.f90 +++ b/modules/aerodyn/src/AirfoilInfo.f90 @@ -575,9 +575,9 @@ SUBROUTINE ReadAFfile ( AFfile, NumCoefs, InCol_Alfa, InCol_Cl, InCol_Cd, InCol_ CALL ParseVar ( FileInfo, CurLine, 'C_nalpha', p%Table(iTable)%UA_BL%C_nalpha, ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'C_lalpha', p%Table(iTable)%UA_BL%C_lalpha, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! TODO: This will need to be uncommented once the f/LinearAero modifications are ready for use. GJH 8/14/2020 + ! CALL ParseVar ( FileInfo, CurLine, 'C_lalpha', p%Table(iTable)%UA_BL%C_lalpha, ErrStat2, ErrMsg2, UnEc ) + ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL ParseVarWDefault ( FileInfo, CurLine, 'T_f0', p%Table(iTable)%UA_BL%T_f0, 3.0_ReKi, ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index c02ccce4c..179bfddb1 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -1744,16 +1744,7 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, if (p_FAST%CompElast == MODULE_BD) then call Linear_BD_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - !............ - ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{ED}} \end{bmatrix} = \f$ - ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{BD}} \end{bmatrix} = \f$ - ! \f$ \frac{\partial U_\Lambda^{BD}}{\partial y^{AD}} \end{bmatrix} = \f$ (dUdy block row 4=BD) - !............ - if (p_FAST%CompElast == MODULE_BD) then - call Linear_BD_InputSolve_dy( p_FAST, y_FAST, ED%Input(1), ED%y, AD%y, AD%Input(1), BD, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - end if + end if !............ ! \f$ \frac{\partial U_\Lambda^{AD}}{\partial y^{IfW}} \end{bmatrix} = \f$ From fde64a14c591029df04a9503bfe99ae4a1c3c7c8 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 14 Aug 2020 13:01:14 -0600 Subject: [PATCH 278/377] Added SD-related work in Input Output Solve --- modules/openfast-library/src/FAST_Solver.f90 | 56 +++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index db66afc8a..6a0423af5 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -1114,28 +1114,29 @@ SUBROUTINE Transfer_ED_to_HD_SD_BD_Mooring( p_FAST, y_ED, u_HD, u_SD, u_ExtPtfm, END IF - - IF ( p_FAST%CompMooring == Module_MAP .and. p_FAST%CompSub /= Module_SD ) THEN -!TODO: GJH I do not have plan documentation for the External Platform connection to MAP GJH 8/11/2020 - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MAP%PtFairDisplacement' ) + if ( p_FAST%CompSub /= Module_SD ) then + IF ( p_FAST%CompMooring == Module_MAP ) THEN + !TODO: GJH I do not have plan documentation for the External Platform connection to MAP GJH 8/11/2020 + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MAP%PtFairDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MAP%PtFairDisplacement' ) - ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MD%PtFairleadDisplacement' ) + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_MD%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_MD%PtFairleadDisplacement' ) - ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_FEAM%PtFairleadDisplacement' ) + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_FEAM%PtFairleadDisplacement, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_FEAM%PtFairleadDisplacement' ) - ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN - ! motions: - CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_Orca%PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_Orca%PtfmMesh' ) - END IF + ELSEIF ( p_FAST%CompMooring == Module_Orca ) THEN + ! motions: + CALL Transfer_Point_to_Point( y_ED%PlatformPtMesh, u_Orca%PtfmMesh, MeshMapData%ED_P_2_Mooring_P, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat, ErrMsg,RoutineName//'u_Orca%PtfmMesh' ) + END IF + end if contains subroutine TransferEDToHD_PRP() @@ -4557,6 +4558,23 @@ SUBROUTINE CalcOutputs_And_SolveForInputs( n_t_global, this_time, this_state, ca Orca%Input(1), BD%Input(1,:), MeshMapData, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( p_FAST%CompSub == Module_SD .and. p_FAST%CompHydro == Module_HD ) THEN + CALL SD_CalcOutput( this_time, SD%Input(1), SD%p, SD%x(this_state), SD%xd(this_state), SD%z(this_state), SD%OtherSt(this_state), SD%y, SD%m, ErrStat2, ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + call Transfer_SD_to_HD( SD%y, HD%Input(1)%WAMITMesh, HD%Input(1)%Morison%Mesh, MeshMapData, ErrStat, ErrMsg ) + + IF ( p_FAST%CompMooring == Module_MAP ) THEN + CALL Transfer_Point_to_Point( SD%y%y2Mesh, MAPp%Input(1)%PtFairDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN + CALL Transfer_Point_to_Point( SD%y%y2Mesh, MD%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN + CALL Transfer_Point_to_Point( SD%y%y2Mesh, FEAM%Input(1)%PtFairleadDisplacement, MeshMapData%SD_P_2_Mooring_P, ErrStat, ErrMsg ) + CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) + END IF + END IF + !> Solve option 1 (rigorous solve on loads/accelerations) CALL SolveOption1(this_time, this_state, calcJacobian, p_FAST, ED, BD, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, IceF, IceD, MeshMapData, ErrStat2, ErrMsg2, WriteThisStep) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) From 80e7c0df508260dd8ae44946e5cd673535f1a494 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Fri, 14 Aug 2020 13:03:06 -0600 Subject: [PATCH 279/377] Updated FAST project for new files and removed files --- vs-build/FASTlib/FASTlib.vfproj | 53 ++++++--------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index 8fd2cf6b2..6ac1c7323 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -122,11 +122,11 @@ - + - + @@ -967,7 +967,6 @@ - @@ -1420,11 +1419,9 @@ - + - - @@ -1538,8 +1535,6 @@ - - @@ -1566,8 +1561,6 @@ - - @@ -1593,8 +1586,6 @@ - - @@ -1621,8 +1612,6 @@ - - @@ -1648,8 +1637,6 @@ - - @@ -1675,8 +1662,6 @@ - - @@ -1702,8 +1687,6 @@ - - @@ -1729,8 +1712,6 @@ - - @@ -1756,8 +1737,6 @@ - - @@ -1783,8 +1762,6 @@ - - @@ -1810,8 +1787,6 @@ - - @@ -1837,8 +1812,6 @@ - - @@ -1864,8 +1837,6 @@ - - @@ -1891,8 +1862,6 @@ - - @@ -1918,8 +1887,6 @@ - - @@ -1945,8 +1912,6 @@ - - @@ -1967,8 +1932,8 @@ - - + + @@ -2154,14 +2119,14 @@ + - - - + - + + From 35a152c88740faf42877c2c532df8e5d1e23c202 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 17 Aug 2020 15:00:54 -0600 Subject: [PATCH 280/377] r-test set for TCF-mods input files --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index 0d7bc558c..f7cbb88cf 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 0d7bc558c9b5cd08d5350412b0dd06e2bdaad0f3 +Subproject commit f7cbb88cf152e355d6b3ffa2176f1eb59f4fcb83 From 8cd78cc7d4ca47092d8903cd647bdf69df105529 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 17 Jun 2020 14:50:54 -0600 Subject: [PATCH 281/377] FlexSub/SlD: including soil stiffness from SoilDyn (if given) --- cmake/OpenfastFortranOptions.cmake | 4 +- modules/subdyn/src/SD_FEM.f90 | 77 ++++- modules/subdyn/src/SubDyn.f90 | 30 +- modules/subdyn/src/SubDyn_Registry.txt | 5 + modules/subdyn/src/SubDyn_Types.f90 | 375 ++++++++++++++++++++++++- 5 files changed, 483 insertions(+), 8 deletions(-) diff --git a/cmake/OpenfastFortranOptions.cmake b/cmake/OpenfastFortranOptions.cmake index 9eae6b512..ac32ec892 100644 --- a/cmake/OpenfastFortranOptions.cmake +++ b/cmake/OpenfastFortranOptions.cmake @@ -115,7 +115,7 @@ macro(set_fast_gfortran) # debug flags if(CMAKE_BUILD_TYPE MATCHES Debug) - set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fcheck=all -pedantic -fbacktrace " ) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fcheck=all,no-array-temps -pedantic -fbacktrace " ) endif() if(CYGWIN) @@ -158,7 +158,7 @@ macro(set_fast_intel_fortran_posix) # debug flags if(CMAKE_BUILD_TYPE MATCHES Debug) - set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -check all -traceback" ) + set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -check all,no-array-temps -traceback" ) endif() # OPENMP diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 2fdc1a4bc..0e8ae2055 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1193,24 +1193,34 @@ END FUNCTION Failed END SUBROUTINE ControlCableForceInit !> Add soil stiffness and mass to global system matrices +!! Soil stiffness can come from two sources: +!! - "SSI" matrices (specified at reaction nodes) +!! - "Soil" matrices (specified at Initalization) SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substract) real(FEKi), dimension(:,:), intent(inout) :: M real(FEKi), dimension(:,:), intent(inout) :: K type(IList),dimension(:), intent(in ) :: NodesDOF !< Map from Node Index to DOF lists - type(SD_InitType), intent(in ) :: Init + type(SD_InitType), intent(inout) :: Init ! TODO look for closest indices elsewhere type(SD_ParameterType), intent(in ) :: p integer(IntKi), intent( out) :: ErrStat ! Error status of the operation character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None logical, optional, intent(in ) :: SubStract ! If present, and if true, substract instead of adding - integer :: I, J, iiNode + integer :: I, J, iiNode, nDOF integer :: iDOF, jDOF, iNode !< DOF and node indices real(FEKi), dimension(6,6) :: K_soil, M_soil ! Auxiliary matrices for soil + real(ReKi) :: Dist ErrMsg = "" ErrStat = ErrID_None + ! --- SSI matrices ! TODO consider doing the 21 -> 6x6 conversion while reading ! 6x6 matrix goes to one node of one element only do iiNode = 1, p%nNodes_C ! loop on constrained nodes iNode = p%Nodes_C(iiNode,1) + nDOF=size(NodesDOF(iNode)%List) + if (nDOF/=6) then + ErrMsg='SSI soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; + ErrStat=ErrID_Fatal; return + endif call Array21_to_6by6(Init%SSIK(:,iiNode), K_soil) call Array21_to_6by6(Init%SSIM(:,iiNode), M_soil) if (present(Substract)) then @@ -1228,6 +1238,46 @@ SUBROUTINE InsertSoilMatrices(M, K, NodesDOF, Init, p, ErrStat, ErrMsg, Substrac enddo enddo enddo + ! --- "Soil" matrices + if (allocated(Init%Soil_K)) then + do iiNode = 1,size(Init%Soil_Points,2) + ! --- Find closest node + call FindClosestNodes(Init%Soil_Points(1:3,iiNode), Init%Nodes, iNode, Dist); + if (Dist>0.1_ReKi) then + ErrMsg='Closest SubDyn Node is node '//Num2LStr(iNode)//', which is more than 0.1m away from soildyn point '//num2lstr(iiNode); + ErrStat=ErrID_Fatal; return + endif + Init%Soil_Nodes(iiNode) = iNode + ! --- Insert/remove from matrices + nDOF=size(NodesDOF(iNode)%List) + if (nDOF/=6) then + ErrMsg='Soil matrix is to be inserted at SubDyn node '//Num2LStr(iNode)//', but this node has '//num2lstr(nDOF)//' DOFs'; + ErrStat=ErrID_Fatal; return + endif + K_soil = Init%Soil_K(1:6,1:6,iiNode) + if (present(Substract)) then + if (Substract) then + K_soil = - K_soil + endif + endif + do I = 1, 6 + iDOF = NodesDOF(iNode)%List(I) ! DOF index + do J = 1, 6 + jDOF = NodesDOF(iNode)%List(J) ! DOF index + K(iDOF, jDOF) = K(iDOF, jDOF) + K_soil(I,J) + enddo + enddo + if (.not.present(Substract)) then + CALL WrScr(' Soil stiffness inserted at SubDyn node '//trim(Num2LStr(iNode))) + print*,' ',K_Soil(1,1:6) + print*,' ',K_Soil(2,1:6) + print*,' ',K_Soil(3,1:6) + print*,' ',K_Soil(4,1:6) + print*,' ',K_Soil(5,1:6) + print*,' ',K_Soil(6,1:6) + endif + enddo + endif contains !> Convert a flatten array of 21 values into a symmetric 6x6 matrix SUBROUTINE Array21_to_6by6(A21, M66) @@ -1246,8 +1296,27 @@ SUBROUTINE Array21_to_6by6(A21, M66) END SUBROUTINE Array21_to_6by6 END SUBROUTINE InsertSoilMatrices - - +!------------------------------------------------------------------------------------------------------ +!> Find closest node index to a point, returns distance as well +SUBROUTINE FindClosestNodes(Point, Nodes, iNode, Dist) + real(ReKi), dimension(3), intent(IN ) :: Point !< Point coordinates + real(ReKi), dimension(:,:), intent(IN ) :: Nodes !< List of nodes, Positions are in columns 2-4... + integer(IntKi), intent( OUT) :: iNode !< Index of closest node + real(ReKi), intent( OUT) :: Dist !< Distance from Point to node iNode + integer(IntKi) :: I + real(ReKi) :: min_dist, loc_dist + ! + min_dist=999999._ReKi + iNode=-1 + do i = 1, size(Nodes,1) + loc_dist = sqrt((Point(1) - Nodes(i,2))**2 + (Point(2) - Nodes(i,3))**2+ (Point(3) - Nodes(i,4))**2) + if (loc_dist Build transformation matrix T, such that x= T.x~ where x~ is the reduced vector of DOF diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index bc49c5109..49c6f6535 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -186,6 +186,24 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO Init%g = InitInput%g Init%TP_RefPoint = InitInput%TP_RefPoint Init%SubRotateZ = InitInput%SubRotateZ + if ((allocated(InitInput%SoilStiffness)) .and. (InitInput%SoilMesh%Initialized)) then + ! Soil Mesh and Stiffness + ! SoilMesh has N points. Correspond in order to the SoilStiffness matrices passed in + ! %RefOrientation is the identity matrix (3,3,N) + ! %Position is the reference position (3,N) + ! Maybe some logic to make sure these points correspond roughly to nodes -- though this may not be true for a long pile into the soil with multiple connection points + ! Note: F = -kx whre k is the relevant 6x6 matrix from SoilStiffness + call AllocAry(Init%Soil_K, 6,6, size(InitInput%SoilStiffness,3), 'Soil_K', ErrStat2, ErrMsg2); + call AllocAry(Init%Soil_Points, 3, InitInput%SoilMesh%NNodes, 'Soil_Points', ErrStat2, ErrMsg2); + call AllocAry(Init%Soil_Nodes, InitInput%SoilMesh%NNodes, 'Soil_Nodes' , ErrStat2, ErrMsg2); + Init%Soil_K = InitInput%SoilStiffness ! SoilStiffness is dimensioned (6,6,N) + Init%Soil_Points = InitInput%SoilMesh%Position ! SoilStiffness is dimensioned (6,6,N) + Init%Soil_Nodes = -1 ! Will be determined in InsertSoilMatrices, Nodes not known yet + if (size(Init%Soil_K,3) /= size(Init%Soil_Points,2)) then + ErrStat2=ErrID_Fatal; ErrMsg2='Number of soil points inconsistent with number of soil stiffness matrix' + endif + if (Failed()) return + endif !bjj added this ugly check (mostly for checking SubDyn driver). not sure if anyone would want to play with different values of gravity so I don't return an error. IF (Init%g < 0.0_ReKi ) CALL ProgWarn( ' SubDyn calculations use gravity assuming it is input as a positive number; the input value is negative.' ) @@ -3032,7 +3050,17 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) write(UnSum, '("#",2x,2(A11))') 'Elem_[#] ','Channel_[#]' call yaml_write_array(UnSum, 'CtrlElem2Channel', p%CtrlElem2Channel, IFmt, ErrStat2, ErrMsg2, comment='') endif - + if (allocated(Init%Soil_K)) then + call yaml_write_array(UnSum, 'Soil_Nodes', Init%Soil_Nodes, IFmt, ErrStat2, ErrMsg2, comment='') + CALL AllocAry( DummyArray, 3, size(Init%Soil_Points,2), 'SoilP', ErrStat2, ErrMsg2 ); if(Failed()) return + do i=1,size(Init%Soil_K,3) + DummyArray(1:3,I) = Init%Nodes(Init%Soil_Nodes(I), 2:4) + call yaml_write_array(UnSum, 'Soil_K'//Num2LStr(I), Init%Soil_K(:,:,I), ReFmt, ErrStat2, ErrMsg2, comment='') + enddo + call yaml_write_array(UnSum, 'Soil_Points_SoilDyn', Init%Soil_Points, ReFmt, ErrStat2, ErrMsg2, comment='') + call yaml_write_array(UnSum, 'Soil_Points_SubDyn', DummyArray, ReFmt, ErrStat2, ErrMsg2, comment='') + deallocate(DummyArray) + endif ! --- User inputs (less interesting, repeat of input file) WRITE(UnSum, '(A)') SectionDivide diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 51d7fa669..50517e04d 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -21,6 +21,8 @@ typedef ^ InitInputType ReKi g - - - "Gravit typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ InitInputType ReKi SoilStiffness ::: - - "Soil stiffness matrices from SoilDyn" '(N/m, N-m/rad)' +typedef ^ InitInputType MeshType SoilMesh - - - "Mesh for soil stiffness locations" - typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - # ============================== Define Initialization outputs here: ============================================================================================================================================ @@ -104,6 +106,9 @@ typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJ typedef ^ ^ R8Ki SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" typedef ^ ^ R8Ki SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" +typedef ^ ^ ReKi Soil_K {:}{:}{:} - - "Soil stiffness (at passed at Init, not in input file) 6x6xn" +typedef ^ ^ ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added" +typedef ^ ^ Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added" #-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ typedef ^ ^ INTEGER NElem - - - "Total number of elements" typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 0e23ce709..9c4c086d1 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -46,6 +46,8 @@ MODULE SubDyn_Types REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SoilStiffness !< Soil stiffness matrices from SoilDyn ['(N/m,] + TYPE(MeshType) :: SoilMesh !< Mesh for soil stiffness locations [-] LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] END TYPE SD_InitInputType ! ======================= @@ -139,6 +141,9 @@ MODULE SubDyn_Types REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Soil_K !< Soil stiffness (at passed at Init, not in input file) 6x6xn [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] @@ -511,7 +516,7 @@ SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END SUBROUTINE SD_UnPackIList SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(SD_InitInputType), INTENT(INOUT) :: SrcInitInputData TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat @@ -519,6 +524,8 @@ SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' @@ -531,6 +538,25 @@ SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ +IF (ALLOCATED(SrcInitInputData%SoilStiffness)) THEN + i1_l = LBOUND(SrcInitInputData%SoilStiffness,1) + i1_u = UBOUND(SrcInitInputData%SoilStiffness,1) + i2_l = LBOUND(SrcInitInputData%SoilStiffness,2) + i2_u = UBOUND(SrcInitInputData%SoilStiffness,2) + i3_l = LBOUND(SrcInitInputData%SoilStiffness,3) + i3_u = UBOUND(SrcInitInputData%SoilStiffness,3) + IF (.NOT. ALLOCATED(DstInitInputData%SoilStiffness)) THEN + ALLOCATE(DstInitInputData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitInputData%SoilStiffness = SrcInitInputData%SoilStiffness +ENDIF + CALL MeshCopy( SrcInitInputData%SoilMesh, DstInitInputData%SoilMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN DstInitInputData%Linearize = SrcInitInputData%Linearize END SUBROUTINE SD_CopyInitInput @@ -543,6 +569,10 @@ SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InitInputData%SoilStiffness)) THEN + DEALLOCATE(InitInputData%SoilStiffness) +ENDIF + CALL MeshDestroy( InitInputData%SoilMesh, ErrStat, ErrMsg ) END SUBROUTINE SD_DestroyInitInput SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -586,6 +616,29 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = Re_BufSz + 1 ! WtrDpth Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Int_BufSz = Int_BufSz + 1 ! SoilStiffness allocated yes/no + IF ( ALLOCATED(InData%SoilStiffness) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SoilStiffness upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SoilStiffness) ! SoilStiffness + END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SoilMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SoilMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SoilMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SoilMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 1 ! Linearize IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -632,6 +685,59 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg END DO ReKiBuf(Re_Xferred) = InData%SubRotateZ Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SoilStiffness) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%SoilStiffness,3), UBOUND(InData%SoilStiffness,3) + DO i2 = LBOUND(InData%SoilStiffness,2), UBOUND(InData%SoilStiffness,2) + DO i1 = LBOUND(InData%SoilStiffness,1), UBOUND(InData%SoilStiffness,1) + ReKiBuf(Re_Xferred) = InData%SoilStiffness(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_PackInitInput @@ -650,6 +756,8 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' @@ -683,6 +791,74 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err END DO OutData%SubRotateZ = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SoilStiffness not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%SoilStiffness)) DEALLOCATE(OutData%SoilStiffness) + ALLOCATE(OutData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%SoilStiffness,3), UBOUND(OutData%SoilStiffness,3) + DO i2 = LBOUND(OutData%SoilStiffness,2), UBOUND(OutData%SoilStiffness,2) + DO i1 = LBOUND(OutData%SoilStiffness,1), UBOUND(OutData%SoilStiffness,1) + OutData%SoilStiffness(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) Int_Xferred = Int_Xferred + 1 END SUBROUTINE SD_UnPackInitInput @@ -2802,6 +2978,7 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitType' @@ -3003,6 +3180,48 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF END IF DstInitTypeData%SSIfile = SrcInitTypeData%SSIfile +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_K)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_K,1) + i1_u = UBOUND(SrcInitTypeData%Soil_K,1) + i2_l = LBOUND(SrcInitTypeData%Soil_K,2) + i2_u = UBOUND(SrcInitTypeData%Soil_K,2) + i3_l = LBOUND(SrcInitTypeData%Soil_K,3) + i3_u = UBOUND(SrcInitTypeData%Soil_K,3) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_K)) THEN + ALLOCATE(DstInitTypeData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_K = SrcInitTypeData%Soil_K +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_Points)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_Points,1) + i1_u = UBOUND(SrcInitTypeData%Soil_Points,1) + i2_l = LBOUND(SrcInitTypeData%Soil_Points,2) + i2_u = UBOUND(SrcInitTypeData%Soil_Points,2) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Points)) THEN + ALLOCATE(DstInitTypeData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Points.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_Points = SrcInitTypeData%Soil_Points +ENDIF +IF (ALLOCATED(SrcInitTypeData%Soil_Nodes)) THEN + i1_l = LBOUND(SrcInitTypeData%Soil_Nodes,1) + i1_u = UBOUND(SrcInitTypeData%Soil_Nodes,1) + IF (.NOT. ALLOCATED(DstInitTypeData%Soil_Nodes)) THEN + ALLOCATE(DstInitTypeData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitTypeData%Soil_Nodes = SrcInitTypeData%Soil_Nodes ENDIF DstInitTypeData%NElem = SrcInitTypeData%NElem DstInitTypeData%NPropB = SrcInitTypeData%NPropB @@ -3239,6 +3458,15 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%SSIfile)) THEN DEALLOCATE(InitTypeData%SSIfile) ENDIF +IF (ALLOCATED(InitTypeData%Soil_K)) THEN + DEALLOCATE(InitTypeData%Soil_K) +ENDIF +IF (ALLOCATED(InitTypeData%Soil_Points)) THEN + DEALLOCATE(InitTypeData%Soil_Points) +ENDIF +IF (ALLOCATED(InitTypeData%Soil_Nodes)) THEN + DEALLOCATE(InitTypeData%Soil_Nodes) +ENDIF IF (ALLOCATED(InitTypeData%Nodes)) THEN DEALLOCATE(InitTypeData%Nodes) ENDIF @@ -3399,6 +3627,21 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IF ( ALLOCATED(InData%SSIfile) ) THEN Int_BufSz = Int_BufSz + 2*1 ! SSIfile upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%SSIfile)*LEN(InData%SSIfile) ! SSIfile + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_K allocated yes/no + IF ( ALLOCATED(InData%Soil_K) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Soil_K upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Soil_K) ! Soil_K + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_Points allocated yes/no + IF ( ALLOCATED(InData%Soil_Points) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Soil_Points upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Soil_Points) ! Soil_Points + END IF + Int_BufSz = Int_BufSz + 1 ! Soil_Nodes allocated yes/no + IF ( ALLOCATED(InData%Soil_Nodes) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Soil_Nodes upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Soil_Nodes) ! Soil_Nodes END IF Int_BufSz = Int_BufSz + 1 ! NElem Int_BufSz = Int_BufSz + 1 ! NPropB @@ -3795,6 +4038,66 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 END DO ! I END DO + END IF + IF ( .NOT. ALLOCATED(InData%Soil_K) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_K,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_K,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%Soil_K,3), UBOUND(InData%Soil_K,3) + DO i2 = LBOUND(InData%Soil_K,2), UBOUND(InData%Soil_K,2) + DO i1 = LBOUND(InData%Soil_K,1), UBOUND(InData%Soil_K,1) + ReKiBuf(Re_Xferred) = InData%Soil_K(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Soil_Points) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Points,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Points,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Soil_Points,2), UBOUND(InData%Soil_Points,2) + DO i1 = LBOUND(InData%Soil_Points,1), UBOUND(InData%Soil_Points,1) + ReKiBuf(Re_Xferred) = InData%Soil_Points(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Soil_Nodes) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Soil_Nodes,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Soil_Nodes,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Soil_Nodes,1), UBOUND(InData%Soil_Nodes,1) + IntKiBuf(Int_Xferred) = InData%Soil_Nodes(i1) + Int_Xferred = Int_Xferred + 1 + END DO END IF IntKiBuf(Int_Xferred) = InData%NElem Int_Xferred = Int_Xferred + 1 @@ -4078,6 +4381,7 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitType' @@ -4436,6 +4740,75 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM Int_Xferred = Int_Xferred + 1 END DO ! I END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_K not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_K)) DEALLOCATE(OutData%Soil_K) + ALLOCATE(OutData%Soil_K(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_K.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Soil_K,3), UBOUND(OutData%Soil_K,3) + DO i2 = LBOUND(OutData%Soil_K,2), UBOUND(OutData%Soil_K,2) + DO i1 = LBOUND(OutData%Soil_K,1), UBOUND(OutData%Soil_K,1) + OutData%Soil_K(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Points not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_Points)) DEALLOCATE(OutData%Soil_Points) + ALLOCATE(OutData%Soil_Points(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Points.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Soil_Points,2), UBOUND(OutData%Soil_Points,2) + DO i1 = LBOUND(OutData%Soil_Points,1), UBOUND(OutData%Soil_Points,1) + OutData%Soil_Points(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Soil_Nodes not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Soil_Nodes)) DEALLOCATE(OutData%Soil_Nodes) + ALLOCATE(OutData%Soil_Nodes(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Soil_Nodes.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Soil_Nodes,1), UBOUND(OutData%Soil_Nodes,1) + OutData%Soil_Nodes(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO END IF OutData%NElem = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 From ddaadd3351ccabcbde5c7876f14f9889fbc427d7 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 26 Aug 2020 11:23:42 -0600 Subject: [PATCH 282/377] Fixed typo in CompSub linearization test Was checking CompMooring, but should have been checking CompSub --- modules/openfast-library/src/FAST_Subs.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 57b2fb788..83bfe853c 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -1695,7 +1695,7 @@ SUBROUTINE ValidateInputData(p, m_FAST, ErrStat, ErrMsg) if (p%CompInflow == MODULE_OpFM) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the OpenFOAM coupling.',ErrStat, ErrMsg, RoutineName) if (p%CompAero == MODULE_AD14) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the AeroDyn v14 module.',ErrStat, ErrMsg, RoutineName) !if (p%CompSub == MODULE_SD) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the SubDyn module.',ErrStat, ErrMsg, RoutineName) - if (p%CompSub /= MODULE_None .and. p%CompMooring /= MODULE_SD ) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the ExtPtfm_MCKF substructure module.',ErrStat, ErrMsg, RoutineName) + if (p%CompSub /= MODULE_None .and. p%CompSub /= MODULE_SD ) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the ExtPtfm_MCKF substructure module.',ErrStat, ErrMsg, RoutineName) if (p%CompMooring /= MODULE_None .and. p%CompMooring /= MODULE_MAP) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for the FEAMooring or MoorDyn mooring modules.',ErrStat, ErrMsg, RoutineName) if (p%CompIce /= MODULE_None) call SetErrStat(ErrID_Fatal,'Linearization is not implemented for any of the ice loading modules.',ErrStat, ErrMsg, RoutineName) From 1da862d6fbe5f48dc1e4e9fcd0837a90d328f9f1 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 31 Aug 2020 09:39:03 -0600 Subject: [PATCH 283/377] Bug Fix: fixed typo in SD Linearization: needed dUdy was using dUdu --- modules/openfast-library/src/FAST_Lin.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 179bfddb1..d494c2708 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -1785,7 +1785,7 @@ SUBROUTINE Glue_Jacobians( p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, OpFM, !LIN-TODO: Add doc strings and look at above doc string IF (p_FAST%CompSub == Module_SD) THEN - call Linear_SD_InputSolve_dy( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdu, ErrStat2, ErrMsg2 ) + call Linear_SD_InputSolve_dy( p_FAST, y_FAST, SD%Input(1), SD%y, ED%y, HD, MAPp, MeshMapData, dUdy, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) ELSE IF (p_FAST%CompSub == Module_ExtPtfm) THEN write(*,*)'>>> FAST_LIN: Linear_ExtPtfm_InputSolve_dy, TODO' From 838c9fc54ff973ffb34ad8c4dde93e0ca920b41b Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 31 Aug 2020 09:41:13 -0600 Subject: [PATCH 284/377] Added time-marching error checks and changed submerged check Now the code tests for the lowest element becoming only partially submerged during time-marching. Likewise checks are made for end-plate crossing free surface at time-marching. Also made submerged check on element to be z1<0 instead of z1<=0 --- modules/hydrodyn/src/Morison.f90 | 35 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 60fb839ca..fd0a2c76b 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2655,22 +2655,30 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! ------------------- buoyancy loads: sides: Sections 3.1 and 3.2 ------------------------ !TODO: What about elements which are buried in the seabed? This doesn't seem to be tested for - if (z1 <= 0) then ! if segment is at least partially submerged ... + if (z1 < 0) then ! if segment is at least partially submerged ... if (z1*z2 <= 0) then ! special calculation if the slice is partially submerged - + + ! Check that this is not the 1st element of the member + if ( i == 1 ) then + call SeterrStat(ErrID_Fatal, 'The lowest element of a Morison member has become partially submerged! This is not allowed. Please review your model and create a discretization such that even with displacements, the lowest element of a member does not become partially submerged.', errStat, errMsg, 'Morison_CalcOutput' ) + return + end if + h0 = -z1/cosPhi ! distances along element centerline from point 1 to the waterplane if (abs(dRdl_mg) < 0.0001) then ! untapered cylinder case Vs = Pi*r1*r1*h0 ! volume of total submerged portion - - cr = 0.25*r1*r1*tanPhi/h0 - cl = 0.5*h0 + 0.125*r1*r1*tanPhi*tanPhi/h0 - - cx = cr*cosPhi + cl*sinPhi + if ( EqualRealNos(Vs, 0.0_ReKi) ) then + cx = 0.0_ReKi ! Avoid singularity, but continue to provide the correct solution + else + cr = 0.25*r1*r1*tanPhi/h0 + cl = 0.5*h0 + 0.125*r1*r1*tanPhi*tanPhi/h0 + cx = cr*cosPhi + cl*sinPhi + end if !alpha0 = 0.5*h0/dl ! force distribution between end nodes @@ -2964,7 +2972,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, z1 = pos1(3) call GetOrientationAngles( pos1, pos2, phi1, sinPhi1, cosPhi1, tanPhi, sinBeta1, cosBeta1, k_hat1, errStat2, errMsg2 ) - if ( N == 1 ) then + if ( N == 1 ) then ! Only one element in member sinPhi2 = sinPhi1 cosPhi2 = cosPhi1 sinBeta2 = sinBeta1 @@ -2976,6 +2984,17 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, end if pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(N+1)) + u%Mesh%Position(:, mem%NodeIndx(N+1)) z2 = pos2(3) + + ! Check the member does not exhibit any of the following conditions + if (.not. mem%PropPot) then + if ( abs(z2) < abs(mem%Rmg(N+1)*sinPhi2) ) then + call SetErrStat(ErrID_Fatal, 'The upper end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(mem%MemberID)), errStat, errMsg, 'Morison_CalcOutput' ) + end if + if ( abs(z1) < abs(mem%Rmg(1)*sinPhi1) ) then + call SetErrStat(ErrID_Fatal, 'The lower end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(mem%MemberID)), errStat, errMsg, 'Morison_CalcOutput' ) + end if + end if + ! TODO: Do the equations below still work if z1 > z2 ? !TODO, should not have to test seabed crossing in time-marching loop From 4b75b1850ecc6cff7fba70e0c2157c303f5ca357 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 31 Aug 2020 09:44:00 -0600 Subject: [PATCH 285/377] Change for debugging: set Tower Freq. to NaN instead of divide by zero This change allows the code to continue without issuing a divide by zero error signal in debug mode. --- modules/elastodyn/src/ElastoDyn.f90 | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/elastodyn/src/ElastoDyn.f90 b/modules/elastodyn/src/ElastoDyn.f90 index 2e0c2814e..7b7f8d479 100644 --- a/modules/elastodyn/src/ElastoDyn.f90 +++ b/modules/elastodyn/src/ElastoDyn.f90 @@ -5255,10 +5255,18 @@ SUBROUTINE Coeff(p,InputFileData, ErrStat, ErrMsg) ! Calculate the tower natural frequencies: DO I = 1,2 ! Loop through all tower DOFs in one direction - p%FreqTFA(I,1) = Inv2Pi*SQRT( p%KTFA(I,I) /( MTFA(I,I) - p%TwrTpMass ) ) ! Natural tower I-fore-aft frequency w/o gravitational destiffening nor tower-top mass effects - p%FreqTFA(I,2) = Inv2Pi*SQRT( ( p%KTFA(I,I) + KTFAGrav(I,I) )/ MTFA(I,I) ) ! Natural tower I-fore-aft frequency w/ gravitational destiffening and tower-top mass effects - p%FreqTSS(I,1) = Inv2Pi*SQRT( p%KTSS(I,I) /( MTSS(I,I) - p%TwrTpMass ) ) ! Natural tower I-side-to-side frequency w/o gravitational destiffening nor tower-top mass effects - p%FreqTSS(I,2) = Inv2Pi*SQRT( ( p%KTSS(I,I) + KTSSGrav(I,I) )/ MTSS(I,I) ) ! Natural tower I-side-to-side frequency w/ gravitational destiffening and tower-top mass effects + if ( EqualRealNos(( MTFA(I,I) - p%TwrTpMass ), 0.0_ReKi) ) then + p%FreqTFA(I,1) = NaN ! Avoid creating a divide by zero signal, but set p%FreqTFA(I,1) = NaN + else + p%FreqTFA(I,1) = Inv2Pi*SQRT( p%KTFA(I,I)/( MTFA(I,I) - p%TwrTpMass ) ) ! Natural tower I-fore-aft frequency w/o gravitational destiffening nor tower-top mass effects + end if + if ( EqualRealNos(( MTSS(I,I) - p%TwrTpMass ), 0.0_ReKi) ) then + p%FreqTSS(I,1) = NaN ! Avoid creating a divide by zero signal, but set p%FreqTFS(I,1) = NaN + else + p%FreqTSS(I,1) = Inv2Pi*SQRT( p%KTSS(I,I)/( MTSS(I,I) - p%TwrTpMass ) ) ! Natural tower I-side-to-side frequency w/o gravitational destiffening nor tower-top mass effects + end if + p%FreqTFA(I,2) = Inv2Pi*SQRT( ( p%KTFA(I,I) + KTFAGrav(I,I) )/MTFA(I,I) ) ! Natural tower I-fore-aft frequency w/ gravitational destiffening and tower-top mass effects + p%FreqTSS(I,2) = Inv2Pi*SQRT( ( p%KTSS(I,I) + KTSSGrav(I,I) )/MTSS(I,I) ) ! Natural tower I-side-to-side frequency w/ gravitational destiffening and tower-top mass effects ENDDO ! I - All tower DOFs in one direction From 52911618f9550d1a3ecbb4a2d7da7fc8c0744e7c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 8 Sep 2020 09:28:59 -0600 Subject: [PATCH 286/377] FlexSub: documentating Extra Moment (before implementing it) --- docs/source/user/subdyn/Makefile | 21 ++- docs/source/user/subdyn/input_files.rst | 2 + docs/source/user/subdyn/theory.rst | 217 +++++++++++++++++------- 3 files changed, 176 insertions(+), 64 deletions(-) diff --git a/docs/source/user/subdyn/Makefile b/docs/source/user/subdyn/Makefile index da41c31a2..c7b2f24a4 100644 --- a/docs/source/user/subdyn/Makefile +++ b/docs/source/user/subdyn/Makefile @@ -1,6 +1,7 @@ # Makefile for Sphinx documentation # MAIN=SubDyn +INKSCAPE="C:/Program Files/Inkscape/inkscape.exe" # You can set these variables from the command line. SPHINXOPTS = @@ -12,6 +13,15 @@ PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +SVGDIR=figs +SVGOUTDIR=figs +SVGS=$(notdir $(wildcard $(SVGDIR)/*.svg)) +SVGS2PDFS=$(patsubst %,$(SVGOUTDIR)/%,$(SVGS:.svg=.pdf)) +SVGS2PNGS=$(patsubst %,$(SVGOUTDIR)/%,$(SVGS:.svg=.png)) +#INKSCAPE=inkscape + + .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest all: pdf @@ -42,7 +52,8 @@ help: clean: -rm -rf _build/* -pdf: latex pdf-compile diff +pdf: latex pdf-compile +# diff # cd _build/latex && make all-pdf pdf-compile: @@ -57,6 +68,12 @@ diff: cd _build/latex && cp $(MAIN).aux $(MAIN)-diff.aux cd _build/latex && pdflatex --interaction=nonstopmode $(MAIN)-diff.tex +# Rule to create pdf or png from svg +$(SVGOUTDIR)/%.pdf:$(SVGDIR)/%.svg + $(INKSCAPE) -A -D --file="$<" "$@" +$(SVGOUTDIR)/%.png:$(SVGDIR)/%.svg + $(INKSCAPE) -D --export-dpi 300 --file="$<" -e "$@" + html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @@ -93,7 +110,7 @@ qthelp: @echo "To view the help file:" @echo "# assistant -collectionFile _build/qthelp/sampledoc.qhc" -latex: +latex: $(SVGS2PNGS) cp -r figs _build/latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex @echo diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst index 6189b9550..a88da7bea 100644 --- a/docs/source/user/subdyn/input_files.rst +++ b/docs/source/user/subdyn/input_files.rst @@ -467,6 +467,8 @@ If SubDyn encounters an unknown/invalid channel name, it prints an error message and halts execution. Please refer to :numref:`sd_appendix_C` for a complete list of possible output parameters and their names. +.. _sd_ssi_inputfile: + SSI Input File -------------- diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 048557c1b..d734095ff 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -799,35 +799,173 @@ the state-space formulation discussed in the next section. Loads ~~~~~ -In this section we details the loads acting on the boundary (*R*), interior (*L*) and transition piece node (*TP*). External forces included in the FEM representation, such as the gravity forces, or the pretension forces are noted with the subscript *g*. -The forces at the boundary nodes can be broken down into external loads (*e*, e.g., hydrodynamic -forces, mooring forces), those transferred to and from ElastoDyn via the TP (ED), and the FEM loads: +In this section, we detail the loads acting on the boundary (*R*) and interior (*L*) nodes, and the transition piece (*TP*) node. + +External loads that are accounted for by SubDyn, such as the gravity loads or the pretension loads, are noted with the subscript *g*. +External loads acting on the substructure and coming from additional modules, constisting for instance of hydrodynamic, mooring or soil loads, are noted with the subscript *e*. +The coupling loads that ElastoDyn would transmit to SubDyn are noted with the subscript *cpl*. +In the modular implementation, SubDyn does not receive these coupling loads from ElastoDyn, but instead receives displacements of the transition piece, and outputs the corresponding loads. This will be relevant for the state-space formulation, but for the purpose of this section, the coupling loads can be thought to be coming from ElastoDyn. + +The external loads at the boundary nodes (*R*) consist of the SubDyn gravitational and cable loads (*g*), the ElastoDyn coupling loads (*cpl*), and the external loads from other modules (*e*): .. math:: :label: FR - F_R =F_{R,e} + F_{R, \text{ED}} + F_{R,g} + F_R =F_{R,e} + F_{R,g} + F_{R, \text{cpl}} -The forces at the internal nodes are the external loads from other modules (e.g. hydrodynamic), and the FEM loads (e.g. gravity): +The external loads acting on the internal nodes are similarly decomposed: .. math:: :label: FL F_L =F_{L,e} + F_{L,g} -Conversely, the TP reaction force, i.e., the force applied to the substructure -through the TP, is denoted by: +The loads at the transition piece node (*TP*) are related to the interface boundary nodes (:math:`\bar{R}`) via the transformation matrix :math:`T_I`, which assumes that the :math:`\bar{R}` and *TP* nodes are rigidly connected: .. math:: :label: FTP1 - F_{TP} = T_I^T F_{R,\textit{ED}} + F_{TP} = T_I^T \bar{F}_{R} +In particular, the coupling force exchanged between ElastoDyn and SubDyn is: + +.. math:: :label: FTP1cpl + + F_{TP,cpl} = T_I^T \bar{F}_{R,\textit{cpl}} -The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given in Eq. :eq:`tilde_partitions0` is then given by: + +The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given in Eq. :eq:`tilde_partitions0` are then decomposed as follows: .. math:: :label: FTPtilde - \tilde{F}_{TP} &= F_{TP} + T_I^T \left[ \bar{F}_{R,e}+ \bar{F}_{R,g} + \bar{\Phi}_{R}^T \left( F_{L,e} + F_{L,g} \right) \right] + \tilde{F}_{TP} &= F_{TP,cpl} + T_I^T \left[ \bar{F}_{R,e}+ \bar{F}_{R,g} + \bar{\Phi}_{R}^T \left( F_{L,e} + F_{L,g} \right) \right] + + F_m &= \Phi_m^t \left(F_{L,e} + F_{L,g}\right) + + + +.. _SD_ExtraMoment: + +Extra moment from deflection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The external loads that are applied on the substructure are computed at the location of the deflected stucture. +On the other hand, the finite element formulation expect loads to be provided relative to the undeflected position of the structure, or, if rigid body motions are present, relative to a reference undeflected position (see Figure :numref:`sd_fig_extramoment`). +Nodal forces at a displaced node can be directly applied to the reference nodal position, but the mapping introduces a moment at the reference nodal position. +The parameter **ExtraMom** in the input file is used to account for this extra nodal moment occurring due to the fact that the finite element loads are expected to be expressed at a reference position and not at the displaced position. + +The mapping of nodal forces is done as follows when the parameter **ExtraMom** is set to True. +First, a reference undeflected position of the structure is defined, with two possible configurations whether the structure is "fixed" at the sea bed, or not. The two configurations are illustrated in Figure :numref:`sd_fig_extramoment`. + +.. _sd_fig_extramoment: + +.. figure:: figs/extramoment.png + :width: 90% + + Illustration for the additional moment occurring due to the distance between the deflected position of the structure and the reference position used for the finite element representation. For simplicity, the loads are assumed to act at the Guyan position instead of the true deflected position. + +The structure is considered "fixed" at the sea bed if the 4 degrees of freedom accounting for the x-y translation and rotation are fixed for all "reaction" nodes at the sea bed, or, if all "reaction" nodes are given an additional stiffness matrix via SSI input files (see :numref:`sd_ssi_inputfile`). +Second, the external loads are assumed to be applied on the "Guyan" deflected structure, instead of the fully deflected structure. The Craig-Bampton displacements are omitted to avoid the non-linear dependency between the input loads and the Craig-Bampton states. +With this assumption, the external loads at the Guyan position are mapped to the reference position. + +The additional moment is included for all external forces, including the gravitational forces. +For a given node :math:`i \in [R,L]`, and nodal force :math:`f_i=f_{i,g} +f_{i,e}`, the following additional moment is computed: + +.. math:: + + \Delta m_i= \Delta u_i \times \left[ f_i,g + f_i,e \right] + +with the vector :math:`\Delta u_i=\{\Delta u_{ix},\Delta u_{iy},\Delta u_{iz}\}`, defined differently depending on the reference position (fixed or free) and whether the node is an internal (*L*) or boundary node (*R*): + +.. math:: :label: eqextramom + :nowrap: + + \begin{align} + \text{(fixed bottom:)}\qquad + \Delta u_{ij} = [\bar{\Phi}_{R}T_I]_{ij} U_{TP} \quad \text{for } i\in L + \ + &\text{, and, } + \quad + \Delta u_{ij} = [T_{I}]_{ij} U_{TP} \quad \text{for } i \in \bar{R} + \\ + \text{(free/floating:)}\qquad + \Delta u_{ij} = [\bar{\Phi}_{R}T_I]_{ij} U_{TP} - U_{TP} \quad \text{for } i\in L + \ + &\text{, and, } + \quad + \Delta u_{ij} = [T_{I}]_{ij} U_{TP} - U_{TP} \quad \text{for } i \in \bar{R} + \end{align} + + +where :math:`j \in [x,y,z]` and the subscript :math:`ij` in :math:`[\bar{\Phi}_R T_I]_{ij}` indicates the row corresponding to node i and translational degree of freedom j. +Boundary DOFs that are fixed have no displacements and thus no extra moment contribution. Boundary DOFs that are free are part of the internal DOF *L* in the implementation. +The gravitational and cable forces at each node (that were computed at the initialization and stored in the constant vector :math:`F_G`) are used to obtain :math:`f_{i,g}`. It is noted that the *g*-contribution to the moment , :math:`\Delta m_i`, is not a constant and needs to be computed at each time step. + +To avoid adding more notations, all the load vectors used in this document will have the additional moment implicitely included when **ExtraMom=True**. +This applies e.g.: to :math:`F_{R,e}, F_{L,e}, F_{R,g}, F_{L,g}`, where the following replacement is implied: + +.. math:: + + F_{R,e} + = \begin{Bmatrix} + \vdots\\ + f_{ix, e}\\ + f_{iy, e}\\ + f_{iz, e}\\ + m_{ix, e}\\ + m_{iy, e}\\ + m_{iz, e}\\ + \vdots\\ + \end{Bmatrix} + \quad + \longrightarrow + \quad + F_{R,e} = + \begin{Bmatrix} + \vdots\\ + f_{ix, e}\\ + f_{iy, e}\\ + f_{iz, e}\\ + m_{ix, e} + \Delta m_{ix, e}\\ + m_{iy, e} + \Delta m_{iy, e}\\ + m_{iz, e} + \Delta m_{iz, e}\\ + \vdots\\ + \end{Bmatrix} + \ + \text{(ExtraMom=True)} + + + +The dependency of the load vectors on :math:`U_{TP}` introduces some complications for the state space representation, where for instance the :math:`B` and :math:`F_X` matrices should be modified to account for the dependency in :math:`U_{TP}` in Eq. :eq:`ABFx`. +The equation remains valid even if :math:`F_{L,e}` and :math:`F_{L,g}` contains a dependency in :math:`U_{TP}`, but the matrix :math:`B` shouldn't be used for the linearization (numerical differentiation is then prefered for simplicity). +Similar considerations apply for Eq. :eq:`bigY2`. + + +The coupling load :math:`F_{{TP},cpl}` given in Eq. :eq:`bigY1` corresponds to the rection force at the TP reference position. +In the "free boundary condition" case, there is no need to correct this output load since the reference position is at the deflected position. +For the "fixed boundary condition" case, the reference position does not correspond to the deflected position, so the reaction moment needs to be transfered to the deflected position as follows: + +.. math:: + + F_{TP,cpl} + = + \begin{Bmatrix} + f_{TP,cpl} \\ + m_{TP,cpl} \\ + \end{Bmatrix} + \quad + \longrightarrow + \quad + F_{TP,cpl} = + \begin{Bmatrix} + f_{TP,cpl} \\ + m_{TP,cpl} -u_{TP} \times f_{TP,cpl} \\ + \end{Bmatrix} + \ + \text{(ExtraMom=True and Fixed BC)} + +The output equation :math:`y_1= -F_{TP,cpl}` is then modified to include this extra contribution. + + + - F_m & = \Phi_m^t \left(F_{L,e} + F_{L,g}\right) .. _SSformulation: @@ -933,11 +1071,11 @@ leading to the following identification: \end{bmatrix} -In SubDyn, the outputs to the ElastoDyn module are the reaction forces at the transition piece :math:`F_{TP}`: +In SubDyn, the outputs to the ElastoDyn module are the coupling (reaction) forces at the transition piece :math:`F_{TP,cpl}`: .. math:: :label: smally1 - y1 = Y_1 =-F_{TP} + y1 = Y_1 =-F_{TP,cpl} By examining Eq. :eq:`main4` and Eq. :eq:`FTPtilde`, the force is extracted from the first block row as: @@ -946,7 +1084,7 @@ By examining Eq. :eq:`main4` and Eq. :eq:`FTPtilde`, the force is extracted from :nowrap: \begin{align} - F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} + \tilde{M}_{Bm} \ddot{q}_m + F_{TP,cpl} =& \tilde{M}_{BB}\ddot{U}_{TP} + \tilde{M}_{Bm} \ddot{q}_m \\ &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m + \tilde{K}_{BB} U_{TP} @@ -970,11 +1108,12 @@ Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: + \tilde{K}_{BB} U_{TP} - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_{L,e} + F_{L,g}) \right) \nonumber\\ + .. math:: :label: FTP3 :nowrap: \begin{align} - F_{TP} =& + F_{TP,cpl} =& \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m +\left[\tilde{C}_{Bm}- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m \\ @@ -992,7 +1131,7 @@ The output equation for :math:`y_1` can now be identified as: .. math:: :label: bigY1 - -Y_1 = F_{TP} = C_1 x + D_1 \bar{u} + F_{Y1} + -Y_1 = F_{TP,cpl} = C_1 x + D_1 \bar{u} + F_{Y1} where @@ -1113,52 +1252,6 @@ The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq -The above neglected the influence of the lever arm introduced by the TP -displacements. The force and moments exchanged at the TP with ElastoDyn, -are written :math:`F_{TP0}=\left\{f_{TP0}, m_{TP0} \right\}^{T}`. They are related to -:math:`F_{TP}` as: - -.. math:: - - F_{TP}=\begin{Bmatrix} - f_{TP} \\ - m_{TP} \\ - \end{Bmatrix}=\begin{bmatrix} - I & 0 \\ - \left[u_{TP} \right]_{\times} & I \\ - \end{bmatrix}\begin{Bmatrix} - f_{TP0} \\ - m_{TP0} \\ - \end{Bmatrix} - -where :math:`\left[u_{TP} \right]_{\times}` is the skew symmetric -matrix representing the cross product with the vector -:math:`u_TP`. This equation is inverted as: - -.. math:: - - F_{TP0}=\begin{Bmatrix} - f_{TP0} \\ - m_{TP0} \\ - \end{Bmatrix}\begin{bmatrix} - I & 0 \\ - -\left[u_{TP} \right]_{\times}& I \\ - \end{bmatrix}\begin{Bmatrix} - f_{TP} \\ - m_{TP} \\ - \end{Bmatrix} - = F_{TP} - + - \begin{Bmatrix} - 0 \\ - -\left[u_{TP} \right]_{\times} f_{TP} \\ - \end{Bmatrix} - -The output equation is now rewritten such that :math:`y_1= -F_{TP0}`. -The input file flag **ExtraMom** is used to include the or omit the contribution from -:math:`-\left[u_{TP} \right]_{\times} f_{TP}` to the output equation. - - Member Force Calculation From dd2bc2684eb59323e228834d89b116b278b36e48 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 8 Sep 2020 12:06:36 -0600 Subject: [PATCH 287/377] FlexSub: adding figures to doc --- docs/source/user/subdyn/figs/extramoment.png | Bin 0 -> 223838 bytes docs/source/user/subdyn/figs/extramoment.svg | 624 +++++++++++++++++++ 2 files changed, 624 insertions(+) create mode 100644 docs/source/user/subdyn/figs/extramoment.png create mode 100644 docs/source/user/subdyn/figs/extramoment.svg diff --git a/docs/source/user/subdyn/figs/extramoment.png b/docs/source/user/subdyn/figs/extramoment.png new file mode 100644 index 0000000000000000000000000000000000000000..2a94789185e09cacb670d906989bae478dffb48f GIT binary patch literal 223838 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

5S-r+h3ZUL@>8tXAzLRw;xD>{fXST8@fN41x% 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≷;&KoU-`^urxR6yY_(=4v?w|=4nB0~9Nsd*% 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

UYnU)Gk7Cl(>y}j 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/figs/extramoment.svg b/docs/source/user/subdyn/figs/extramoment.svg new file mode 100644 index 000000000..97f05733d --- /dev/null +++ b/docs/source/user/subdyn/figs/extramoment.svg @@ -0,0 +1,624 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Case 1: fixed bottom Case 2: free/floating + Input position Reference position + + + + + + + + + + + + + + + + + + + + Deflected position "Guyan" position + uTP + Input position Reference position + + + + "Guyan" position + uTP + + + + + ∆ui fi + + + + ∆ui fi + Deflected position uTP + + + + "ΦRiUTP" + + + + "ΦRiUTP" + From f8c65af9c6301628e376cf31208ed40ba0690777 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 8 Sep 2020 15:28:07 -0600 Subject: [PATCH 288/377] FlexSub: implemented extra moment for all loads --- docs/source/user/subdyn/theory.rst | 2 +- modules/subdyn/src/SD_FEM.f90 | 26 ++++++ modules/subdyn/src/SubDyn.f90 | 109 ++++++++++++++++------- modules/subdyn/src/SubDyn_Output.f90 | 1 - modules/subdyn/src/SubDyn_Registry.txt | 3 + modules/subdyn/src/SubDyn_Types.f90 | 115 +++++++++++++++++++++++++ 6 files changed, 225 insertions(+), 31 deletions(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index d734095ff..47eda061f 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -861,7 +861,7 @@ First, a reference undeflected position of the structure is defined, with two po Illustration for the additional moment occurring due to the distance between the deflected position of the structure and the reference position used for the finite element representation. For simplicity, the loads are assumed to act at the Guyan position instead of the true deflected position. -The structure is considered "fixed" at the sea bed if the 4 degrees of freedom accounting for the x-y translation and rotation are fixed for all "reaction" nodes at the sea bed, or, if all "reaction" nodes are given an additional stiffness matrix via SSI input files (see :numref:`sd_ssi_inputfile`). +The structure is considered "fixed" at the sea bed if at least one reaction node satisfies one of these two conditions: the 4 degrees of freedom accounting for the x-y translation and rotation are fixed at the sea bed, or, an additional stiffness matrix is given via an SSI input file (see :numref:`sd_ssi_inputfile`). Second, the external loads are assumed to be applied on the "Guyan" deflected structure, instead of the fully deflected structure. The Craig-Bampton displacements are omitted to avoid the non-linear dependency between the input loads and the Craig-Bampton states. With this assumption, the external loads at the Guyan position are mapped to the reference position. diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 0e8ae2055..7b371a058 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1012,6 +1012,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( p%FG_full, p%nDOF, 'p%FG_full', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector Init%K = 0.0_FEKi Init%M = 0.0_FEKi Init%FG = 0.0_FEKi @@ -1029,6 +1030,8 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) ENDDO + ! Copy FG to FG_full since FG will be reduced later + p%FG_full(1:p%nDOF) = Init%FG(1:p%nDOF) ! Add concentrated mass to mass matrix DO I = 1, Init%nCMass @@ -2021,6 +2024,29 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) enddo END SUBROUTINE InsertJointStiffDamp +!> Returns true if the substructure can be considered "fixed bottom" +!! This is relevant for the ExtraMoment calculation where different reference positions +!! are used depending if translation is fixed of free. +!! As defined in the documentation: +!! The structure is considered “fixed†at the sea bed if at least one reaction node has: +!! - the 4 degrees of freedom accounting for the x-y translation and rotation are fixed +!! OR +!! - an additional stiffness matrix via an SSI input file +LOGICAL FUNCTION isFixedBottom(Init, p) result(bFixed) + TYPE(SD_InitType), INTENT(IN ) :: Init + TYPE(SD_ParameterType),INTENT(IN ) :: p + INTEGER(IntKi) :: i, nFixed + nFixed=0 + do i =1,size(p%Nodes_C,1) + if (ALL(p%Nodes_C(I,2:5)==idBC_Fixed)) then + nFixed=nFixed+1 + elseif (Init%SSIfile(I)/='') then + nFixed=nFixed+1 + endif + enddo + bFixed = nFixed >=1 +END FUNCTION isFixedBottom + SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(FEKi), INTENT(OUT) :: Me(12, 12) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 49c6f6535..39284324b 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -218,7 +218,6 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - if (p%ExtraMoment) call WrScr(' Extra moment will be included in Y1') ! -------------------------------------------------------------------------------- ! --- Manipulation of Init and parameters @@ -265,6 +264,14 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Nodes into (I,C,L,R): I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return + if (p%ExtraMoment) then + p%FixedBottom=isFixedBottom(Init,p) + if (p%FixedBottom) then + call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') + else + call WrScr(' Extra moment will be included in loads (free/floating case detected)') + endif + endif ! --- Craig-Bampton reduction (sets many parameters) CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -531,10 +538,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! MExtra = -u_TP x f_TP ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs if (p%ExtraMoment) then - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + if (p%FixedBottom) then ! if Fixed, transfer from non deflected TP to u_TP + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif endif ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces @@ -1720,9 +1729,10 @@ SUBROUTINE SD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM IF ( PRESENT( dXdu ) ) THEN ! Calculate the partial derivative of the continuous state functions (X) with respect to the inputs (u) here: ! TODO: dXdu should be constant, in theory we dont' need to recompute it - if(ANALYTICAL_LIN) then - call StateMatrices(p, ErrStat2, ErrMsg2, BB=dXdu); if(Failed()) return ! Allocation occurs in function - else + !if(ANALYTICAL_LIN) then + ! Analytical lin cannot be used anymore with extra mom + ! call StateMatrices(p, ErrStat2, ErrMsg2, BB=dXdu); if(Failed()) return ! Allocation occurs in function + !else if (.not. allocated(dXdu)) then call AllocAry(dXdu, p%Jac_nx * 2, size(p%Jac_u_indx,1), 'dXdu', ErrStat2, ErrMsg2); if (Failed()) return endif @@ -1743,7 +1753,7 @@ SUBROUTINE SD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM ! get central difference: call SD_Compute_dX( p, x_p, x_m, delta_p, dXdu(:,i) ) end do - endif ! analytical or numerical + !endif ! analytical or numerical END IF ! dXdu IF ( PRESENT( dXddu ) ) THEN if (allocated(dXddu)) deallocate(dXddu) @@ -2549,6 +2559,7 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%UL, p%nDOF__L, 'UL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dot, p%nDOF__L, 'UL_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UL_dotdot, p%nDOF__L, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%DU_full, p%nDOF, 'DU_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') @@ -2826,34 +2837,45 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - integer :: iMeshNode, iSDNode ! indices of u-mesh nodes and SD nodes + integer :: iNode ! indices of u-mesh nodes and SD nodes integer :: nMembers integer :: startDOF, I integer :: iCC, iElem, iChannel !< Index on control cables, element, Channel integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + real(ReKi) :: rotations(3) + real(ReKi) :: du(3), Moment(3), Force(3) real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! --- Build vector of external force + ! --- Compute Guyan displacement for extra moment (see CalcOutput, redundancy...) + if (p%ExtraMoment) then + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar + m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL + m%U_red(p%IDI__) = m%UR_bar + m%U_red(p%ID__L) = m%UL + m%U_red(p%IDC_Rb)= 0 ! TODO + m%U_red(p%ID__F) = 0 + if (p%reduced) then + m%DU_full = matmul(p%T_red, m%U_red) + else + m%DU_full = m%U_red + endif + if (.not.p%FixedBottom) then ! if Floating, remove u_TP translation + do iNode = 1,p%nNodes + m%DU_full(p%NodesDOF(iNode)%List(1:3)) = m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) + enddo + endif + endif + + + ! --- Build vector of external forces (Moment done below) m%Fext= myNaN - DO iMeshNode = 1,p%nNodes - iSDNode = iMeshNode - nMembers = (size(p%NodesDOF(iSDNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + DO iNode = 1,p%nNodes ! Force - All nodes have only 3 translational DOFs - m%Fext( p%NodesDOF(iSDNode)%List(1:3) ) = u%LMesh%Force (:,iMeshNode) - ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs - m%Fext( p%NodesDOF(iSDNode)%List(4::3)) = u%LMesh%Moment(1,iMeshNode)/nMembers - m%Fext( p%NodesDOF(iSDNode)%List(5::3)) = u%LMesh%Moment(2,iMeshNode)/nMembers - m%Fext( p%NodesDOF(iSDNode)%List(6::3)) = u%LMesh%Moment(3,iMeshNode)/nMembers + m%Fext( p%NodesDOF(iNode)%List(1:3) ) = u%LMesh%Force (:,iNode) enddo - ! TODO: remove test below in the future - if (DEV_VERSION) then - if (any(m%Fext == myNaN)) then - print*,'Error in setting up Fext' - STOP - endif - endif - ! --- Adding controllable cable forces if (size(p%CtrlElem2Channel,1) > 0) then if (.not. allocated (u%CableTension)) then @@ -2870,6 +2892,35 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) enddo endif + ! --- Build vector of external moment + DO iNode = 1,p%nNodes + Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh + Moment(1:3) = u%LMesh%Moment(1:3,iNode) + nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + + ! Extra moment dm = Delta u x (fe + fg) + if (p%ExtraMoment) then + Force = Force + p%FG_full(p%NodesDOF(iNode)%List(1:3)) ! Adding gravity and initial cable + du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm + Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) + Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) + Moment(3) = Moment(3) + du(1) * Force(2) - du(2) * Force(1) + endif + + ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + m%Fext( p%NodesDOF(iNode)%List(4::3)) = Moment(1)/nMembers + m%Fext( p%NodesDOF(iNode)%List(5::3)) = Moment(2)/nMembers + m%Fext( p%NodesDOF(iNode)%List(6::3)) = Moment(3)/nMembers + enddo + + ! TODO: remove test below in the future + if (DEV_VERSION) then + if (any(m%Fext == myNaN)) then + print*,'Error in setting up Fext' + STOP + endif + endif + ! --- Reduced vector of external force if (p%reduced) then m%Fext_red = matmul(transpose(p%T_red), m%Fext) @@ -2946,7 +2997,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) ! M and K are reduced matrices, but Boundary conditions are not applied ! We set bDOF, which is true if not a fixed Boundary conditions ! NOTE: we don't check for singularities/rigig body modes here - CALL WrScr(' Calculating Full System Modes (for summary file output)') + CALL WrScr(' Calculating Full System Modes for summary file (discard any [INFO] below)') CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return bDOF(:) = .true. bDOF(p%ID__F) = .false. @@ -3217,7 +3268,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Gravity force vector FG applied at each node of the full system' + WRITE(UnSum, '(A)') '#Initial gravity and cable loads applied at each node of the system (after DOF elimination with T matrix)' call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') ! --- write CB system matrices diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index c78ffa1f0..6e15e6aa5 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -830,7 +830,6 @@ SUBROUTINE SD_Init_Jacobian(Init, p, u, y, InitOut, ErrStat, ErrMsg) dy = maxval(Init%Nodes(:,3))- minval(Init%Nodes(:,3)) dz = maxval(Init%Nodes(:,4))- minval(Init%Nodes(:,4)) maxDim = max(dx, dy, dz) - print*,'dx,dy,dz', dx, dy, dz, maxDim ! --- System dimension call Init_Jacobian_y(); if (Failed()) return diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 50517e04d..b0e065337 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -157,6 +157,7 @@ typedef ^ ^ ReKi UR_bar_dotdot {:} typedef ^ ^ ReKi UL {:} - - typedef ^ ^ ReKi UL_dot {:} - - typedef ^ ^ ReKi UL_dotdot {:} - - +typedef ^ ^ ReKi DU_full {:} - - "Delta U used for extra moment" typedef ^ ^ ReKi U_full {:} - - typedef ^ ^ ReKi U_full_dot {:} - - typedef ^ ^ ReKi U_full_dotdot {:} - - @@ -183,6 +184,7 @@ typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after co typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +typedef ^ ^ R8Ki FG_full {:} - - "Gravity force vector (with initial cable force T0), not reduced" N # --- Constraints reduction typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" @@ -196,6 +198,7 @@ typedef ^ ^ IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" +typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 9c4c086d1..a80be4f66 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -199,6 +199,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DU_full !< Delta U used for extra moment [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dotdot @@ -222,6 +223,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG_full !< Gravity force vector (with initial cable force T0), not reduced [N] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] @@ -232,6 +234,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] + LOGICAL :: FixedBottom !< True if Fixed bottom [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -5977,6 +5980,18 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%UL_dotdot = SrcMiscData%UL_dotdot ENDIF +IF (ALLOCATED(SrcMiscData%DU_full)) THEN + i1_l = LBOUND(SrcMiscData%DU_full,1) + i1_u = UBOUND(SrcMiscData%DU_full,1) + IF (.NOT. ALLOCATED(DstMiscData%DU_full)) THEN + ALLOCATE(DstMiscData%DU_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%DU_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%DU_full = SrcMiscData%DU_full +ENDIF IF (ALLOCATED(SrcMiscData%U_full)) THEN i1_l = LBOUND(SrcMiscData%U_full,1) i1_u = UBOUND(SrcMiscData%U_full,1) @@ -6134,6 +6149,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%UL_dotdot)) THEN DEALLOCATE(MiscData%UL_dotdot) ENDIF +IF (ALLOCATED(MiscData%DU_full)) THEN + DEALLOCATE(MiscData%DU_full) +ENDIF IF (ALLOCATED(MiscData%U_full)) THEN DEALLOCATE(MiscData%U_full) ENDIF @@ -6244,6 +6262,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! UL_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%UL_dotdot) ! UL_dotdot END IF + Int_BufSz = Int_BufSz + 1 ! DU_full allocated yes/no + IF ( ALLOCATED(InData%DU_full) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DU_full upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DU_full) ! DU_full + END IF Int_BufSz = Int_BufSz + 1 ! U_full allocated yes/no IF ( ALLOCATED(InData%U_full) ) THEN Int_BufSz = Int_BufSz + 2*1 ! U_full upper/lower bounds for each dimension @@ -6455,6 +6478,21 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%DU_full) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DU_full,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DU_full,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DU_full,1), UBOUND(InData%DU_full,1) + ReKiBuf(Re_Xferred) = InData%DU_full(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%U_full) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6800,6 +6838,24 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DU_full not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DU_full)) DEALLOCATE(OutData%DU_full) + ALLOCATE(OutData%DU_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DU_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DU_full,1), UBOUND(OutData%DU_full,1) + OutData%DU_full(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7036,6 +7092,18 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN ENDDO +ENDIF +IF (ALLOCATED(SrcParamData%FG_full)) THEN + i1_l = LBOUND(SrcParamData%FG_full,1) + i1_u = UBOUND(SrcParamData%FG_full,1) + IF (.NOT. ALLOCATED(DstParamData%FG_full)) THEN + ALLOCATE(DstParamData%FG_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FG_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FG_full = SrcParamData%FG_full ENDIF DstParamData%reduced = SrcParamData%reduced IF (ALLOCATED(SrcParamData%T_red)) THEN @@ -7129,6 +7197,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment + DstParamData%FixedBottom = SrcParamData%FixedBottom IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) i1_u = UBOUND(SrcParamData%KMMDiag,1) @@ -7903,6 +7972,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%ElemProps) ENDIF +IF (ALLOCATED(ParamData%FG_full)) THEN + DEALLOCATE(ParamData%FG_full) +ENDIF IF (ALLOCATED(ParamData%T_red)) THEN DEALLOCATE(ParamData%T_red) ENDIF @@ -8171,6 +8243,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si DEALLOCATE(Int_Buf) END IF END DO + END IF + Int_BufSz = Int_BufSz + 1 ! FG_full allocated yes/no + IF ( ALLOCATED(InData%FG_full) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FG_full upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%FG_full) ! FG_full END IF Int_BufSz = Int_BufSz + 1 ! reduced Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no @@ -8242,6 +8319,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment + Int_BufSz = Int_BufSz + 1 ! FixedBottom Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN Int_BufSz = Int_BufSz + 2*1 ! KMMDiag upper/lower bounds for each dimension @@ -8713,6 +8791,21 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF END DO + END IF + IF ( .NOT. ALLOCATED(InData%FG_full) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FG_full,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG_full,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%FG_full,1), UBOUND(InData%FG_full,1) + DbKiBuf(Db_Xferred) = InData%FG_full(i1) + Db_Xferred = Db_Xferred + 1 + END DO END IF IntKiBuf(Int_Xferred) = TRANSFER(InData%reduced, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 @@ -8884,6 +8977,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%ExtraMoment, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedBottom, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10133,6 +10228,24 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG_full not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FG_full)) DEALLOCATE(OutData%FG_full) + ALLOCATE(OutData%FG_full(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG_full.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%FG_full,1), UBOUND(OutData%FG_full,1) + OutData%FG_full(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END IF OutData%reduced = TRANSFER(IntKiBuf(Int_Xferred), OutData%reduced) Int_Xferred = Int_Xferred + 1 @@ -10346,6 +10459,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%ExtraMoment = TRANSFER(IntKiBuf(Int_Xferred), OutData%ExtraMoment) Int_Xferred = Int_Xferred + 1 + OutData%FixedBottom = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedBottom) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE From 421e03b85c02e0c7eaf5368869702e1a2574e5e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 10 Sep 2020 10:40:51 -0600 Subject: [PATCH 289/377] FlexSub: fix rotframe for x jacobian --- modules/subdyn/src/SubDyn_Output.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 6e15e6aa5..b99b55126 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -874,7 +874,7 @@ SUBROUTINE Init_Jacobian_x() ! default perturbations, p%dx: p%dx(1) = 2.0_ReKi*D2R_D ! deflection states in rad and rad/s p%dx(2) = 2.0_ReKi*D2R_D ! deflection states in rad and rad/s - InitOut%RotFrame_x = .true. + InitOut%RotFrame_x = .false. InitOut%DerivOrder_x = 2 ! set linearization output names: do i=1,p%Jac_nx From 0b1a8c688660deec23b886e670f13a79a26c5373 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 11 Sep 2020 10:28:55 -0600 Subject: [PATCH 290/377] FlexSub: using DeltaL for cable control input, not input file --- modules/subdyn/src/SubDyn.f90 | 17 ++++--- modules/subdyn/src/SubDyn_Driver.f90 | 6 +-- modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 68 +++++++++++++------------- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 39284324b..8ca6bedc6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2842,11 +2842,12 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) integer :: startDOF, I integer :: iCC, iElem, iChannel !< Index on control cables, element, Channel integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system + real(ReKi) :: CableTension ! Controllable Cable force real(ReKi) :: rotations(3) real(ReKi) :: du(3), Moment(3), Force(3) real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! --- Compute Guyan displacement for extra moment (see CalcOutput, redundancy...) + ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) if (p%ExtraMoment) then rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) @@ -2878,17 +2879,19 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) ! --- Adding controllable cable forces if (size(p%CtrlElem2Channel,1) > 0) then - if (.not. allocated (u%CableTension)) then + if (.not. allocated (u%CableDeltaL)) then call Fatal('Cable tension input not allocated but controllable cables are present'); return endif - if (size(u%CableTension)< maxval(p%CtrlElem2Channel(:,2)) ) then - call Fatal('Cable tension input has length '//trim(num2lstr(size(u%CableTension)))//' but controllable cables need to access channel '//trim(num2lstr(maxval(p%CtrlElem2Channel(:,2))))); return + if (size(u%CableDeltaL)< maxval(p%CtrlElem2Channel(:,2)) ) then + call Fatal('Cable tension input has length '//trim(num2lstr(size(u%CableDeltaL)))//' but controllable cables need to access channel '//trim(num2lstr(maxval(p%CtrlElem2Channel(:,2))))); return endif - do iCC = 1, size(p%CtrlElem2Channel,1) + do iCC = 1, size(p%CtrlElem2Channel,1) ! Loop on controllable cables iElem = p%CtrlElem2Channel(iCC,1) iChannel = p%CtrlElem2Channel(iCC,2) IDOF = p%ElemsDOF(1:12, iElem) - m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (u%CableTension(iChannel) - p%ElemProps(iElem)%T0) + ! T(t) = EA * DeltaL(t) /(Le + Delta L(t)) + CableTension = p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) + m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) enddo endif @@ -2896,7 +2899,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) DO iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh Moment(1:3) = u%LMesh%Moment(1:3,iNode) - nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's nDOFList + nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's DOFList ! Extra moment dm = Delta u x (fe + fg) if (p%ExtraMoment) then diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index 68ca309a0..bbe48257b 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -181,9 +181,9 @@ PROGRAM TestSubDyn ! u(1)%UFL(3) =-12.958 !this is for testbeam3 ! TEMPORARY HACK FOR CONTROLLABLE CABLES - !allocate(u(1)%CableTension(5)) - !!u(1)%CableTension= 1.0e7_ReKi - !u(1)%CableTension= 0.0e7_ReKi + !allocate(u(1)%CableDeltaL(5)) + !!u(1)%CableDeltaL= 1.0e7_ReKi + !u(1)%CableDeltaL= 0.0e7_ReKi call WrScr('') DO n = 0,drvrInitInp%NSteps-1 ! Loop on time steps, starts at 0 diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index b0e065337..9fcbc585f 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -292,7 +292,7 @@ typedef ^ ParameterType logical RotStates - - - "Orient states # ============================== Inputs ============================================================================================================================================ typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" -typedef ^ InputType ReKi CableTension {:} - - "Cable tension, control input" +typedef ^ InputType ReKi CableDeltaL {:} - - "Cable tension, control input" # ============================== Outputs ============================================================================================================================================ typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a80be4f66..2a0822b27 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -327,7 +327,7 @@ MODULE SubDyn_Types TYPE, PUBLIC :: SD_InputType TYPE(MeshType) :: TPMesh !< Transition piece inputs on a point mesh [-] TYPE(MeshType) :: LMesh !< Point mesh for interior node inputs [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CableTension !< Cable tension, control input [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CableDeltaL !< Cable tension, control input [-] END TYPE SD_InputType ! ======================= ! ========= SD_OutputType ======= @@ -11827,17 +11827,17 @@ SUBROUTINE SD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) CALL MeshCopy( SrcInputData%LMesh, DstInputData%LMesh, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcInputData%CableTension)) THEN - i1_l = LBOUND(SrcInputData%CableTension,1) - i1_u = UBOUND(SrcInputData%CableTension,1) - IF (.NOT. ALLOCATED(DstInputData%CableTension)) THEN - ALLOCATE(DstInputData%CableTension(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInputData%CableDeltaL)) THEN + i1_l = LBOUND(SrcInputData%CableDeltaL,1) + i1_u = UBOUND(SrcInputData%CableDeltaL,1) + IF (.NOT. ALLOCATED(DstInputData%CableDeltaL)) THEN + ALLOCATE(DstInputData%CableDeltaL(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%CableTension.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%CableDeltaL.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInputData%CableTension = SrcInputData%CableTension + DstInputData%CableDeltaL = SrcInputData%CableDeltaL ENDIF END SUBROUTINE SD_CopyInput @@ -11852,8 +11852,8 @@ SUBROUTINE SD_DestroyInput( InputData, ErrStat, ErrMsg ) ErrMsg = "" CALL MeshDestroy( InputData%TPMesh, ErrStat, ErrMsg ) CALL MeshDestroy( InputData%LMesh, ErrStat, ErrMsg ) -IF (ALLOCATED(InputData%CableTension)) THEN - DEALLOCATE(InputData%CableTension) +IF (ALLOCATED(InputData%CableDeltaL)) THEN + DEALLOCATE(InputData%CableDeltaL) ENDIF END SUBROUTINE SD_DestroyInput @@ -11927,10 +11927,10 @@ SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! CableTension allocated yes/no - IF ( ALLOCATED(InData%CableTension) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! CableTension upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CableTension) ! CableTension + Int_BufSz = Int_BufSz + 1 ! CableDeltaL allocated yes/no + IF ( ALLOCATED(InData%CableDeltaL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! CableDeltaL upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%CableDeltaL) ! CableDeltaL END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -12015,18 +12015,18 @@ SUBROUTINE SD_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IF ( .NOT. ALLOCATED(InData%CableTension) ) THEN + IF ( .NOT. ALLOCATED(InData%CableDeltaL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CableTension,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CableTension,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%CableDeltaL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CableDeltaL,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%CableTension,1), UBOUND(InData%CableTension,1) - ReKiBuf(Re_Xferred) = InData%CableTension(i1) + DO i1 = LBOUND(InData%CableDeltaL,1), UBOUND(InData%CableDeltaL,1) + ReKiBuf(Re_Xferred) = InData%CableDeltaL(i1) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -12139,21 +12139,21 @@ SUBROUTINE SD_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CableTension not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CableDeltaL not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CableTension)) DEALLOCATE(OutData%CableTension) - ALLOCATE(OutData%CableTension(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%CableDeltaL)) DEALLOCATE(OutData%CableDeltaL) + ALLOCATE(OutData%CableDeltaL(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CableTension.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CableDeltaL.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%CableTension,1), UBOUND(OutData%CableTension,1) - OutData%CableTension(i1) = ReKiBuf(Re_Xferred) + DO i1 = LBOUND(OutData%CableDeltaL,1), UBOUND(OutData%CableDeltaL,1) + OutData%CableDeltaL(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -12611,10 +12611,10 @@ SUBROUTINE SD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp1(u1%LMesh, u2%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(u_out%CableTension) .AND. ALLOCATED(u1%CableTension)) THEN - DO i1 = LBOUND(u_out%CableTension,1),UBOUND(u_out%CableTension,1) - b = -(u1%CableTension(i1) - u2%CableTension(i1)) - u_out%CableTension(i1) = u1%CableTension(i1) + b * ScaleFactor +IF (ALLOCATED(u_out%CableDeltaL) .AND. ALLOCATED(u1%CableDeltaL)) THEN + DO i1 = LBOUND(u_out%CableDeltaL,1),UBOUND(u_out%CableDeltaL,1) + b = -(u1%CableDeltaL(i1) - u2%CableDeltaL(i1)) + u_out%CableDeltaL(i1) = u1%CableDeltaL(i1) + b * ScaleFactor END DO END IF ! check if allocated END SUBROUTINE SD_Input_ExtrapInterp1 @@ -12678,11 +12678,11 @@ SUBROUTINE SD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrM CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) CALL MeshExtrapInterp2(u1%LMesh, u2%LMesh, u3%LMesh, tin, u_out%LMesh, tin_out, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) -IF (ALLOCATED(u_out%CableTension) .AND. ALLOCATED(u1%CableTension)) THEN - DO i1 = LBOUND(u_out%CableTension,1),UBOUND(u_out%CableTension,1) - b = (t(3)**2*(u1%CableTension(i1) - u2%CableTension(i1)) + t(2)**2*(-u1%CableTension(i1) + u3%CableTension(i1)))* scaleFactor - c = ( (t(2)-t(3))*u1%CableTension(i1) + t(3)*u2%CableTension(i1) - t(2)*u3%CableTension(i1) ) * scaleFactor - u_out%CableTension(i1) = u1%CableTension(i1) + b + c * t_out +IF (ALLOCATED(u_out%CableDeltaL) .AND. ALLOCATED(u1%CableDeltaL)) THEN + DO i1 = LBOUND(u_out%CableDeltaL,1),UBOUND(u_out%CableDeltaL,1) + b = (t(3)**2*(u1%CableDeltaL(i1) - u2%CableDeltaL(i1)) + t(2)**2*(-u1%CableDeltaL(i1) + u3%CableDeltaL(i1)))* scaleFactor + c = ( (t(2)-t(3))*u1%CableDeltaL(i1) + t(3)*u2%CableDeltaL(i1) - t(2)*u3%CableDeltaL(i1) ) * scaleFactor + u_out%CableDeltaL(i1) = u1%CableDeltaL(i1) + b + c * t_out END DO END IF ! check if allocated END SUBROUTINE SD_Input_ExtrapInterp2 From affbb817ee6c38436353aeb2043e5fc9500a0b95 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 11 Sep 2020 10:37:44 -0600 Subject: [PATCH 291/377] FlexSub: removed some registry variables, added T_red_T --- modules/subdyn/src/SD_FEM.f90 | 64 ++------ modules/subdyn/src/SubDyn.f90 | 4 +- modules/subdyn/src/SubDyn_Registry.txt | 3 +- modules/subdyn/src/SubDyn_Types.f90 | 198 +++++++++---------------- 4 files changed, 79 insertions(+), 190 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 7b371a058..84cb7f3f3 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -885,11 +885,9 @@ SUBROUTINE DistributeDOF(Init, p, ErrStat, ErrMsg) enddo ! iNode, loop on joints ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%BCs, 6*p%nNodes_C, 2, 'Init%BCs', ErrStat2, ErrMsg2); if(Failed()) return CALL InitBCs(Init, p) ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL AllocAry(Init%IntFc, 6*p%nNodes_I,2, 'Init%IntFc', ErrStat2, ErrMsg2); if(Failed()) return CALL InitIntFc(Init, p) ! --- Safety check @@ -926,19 +924,14 @@ SUBROUTINE InitBCs(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(INOUT) :: p INTEGER(IntKi) :: I, J, iNode - Init%BCs = -9999 DO I = 1, p%nNodes_C iNode = p%Nodes_C(I,1) ! Node index DO J = 1, 6 - Init%BCs( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) - Init%BCs( (I-1)*6+J, 2) = idBC_Fixed p%Nodes_C(I, J+1) = idBC_Fixed else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF - Init%BCs( (I-1)*6+J, 2) = idBC_Internal p%Nodes_C(I, J+1) = idBC_Internal else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF - Init%BCs( (I-1)*6+J, 2) = idBC_Leader p%Nodes_C(I, J+1) = idBC_Leader print*,'BC 2 not allowed for now, node',iNode STOP @@ -957,17 +950,12 @@ SUBROUTINE InitIntFc(Init, p) TYPE(SD_InitType ),INTENT(INOUT) :: Init TYPE(SD_ParameterType),INTENT(INOUT) :: p INTEGER(IntKi) :: I, J, iNode - Init%IntFc = -9999 DO I = 1, p%nNodes_I iNode = p%Nodes_I(I,1) ! Node index DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = p%NodesDOF(iNode)%List(J) ! DOF number (unconstrained) - if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF - Init%IntFc((I-1)*6+J, 2) = idBC_Leader p%Nodes_I(I,J+1) = idBC_Leader elseif (p%Nodes_I(I,J+1)==1) then ! User input 0=Fixed DOF - Init%IntFc( (I-1)*6+J, 2) = idBC_Fixed p%Nodes_I(I,J+1) = idBC_Fixed print*,'Fixed boundary condition not yet supported for interface nodes, node:',iNode STOP @@ -1558,7 +1546,7 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly real(FEKi), dimension(:,:), allocatable :: MM, KK real(FEKi), dimension(:), allocatable :: FF - real(FEKi), dimension(:,:), allocatable :: Temp, T_red_T + real(FEKi), dimension(:,:), allocatable :: Temp integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF ErrStat = ErrID_None ErrMsg = "" @@ -1581,22 +1569,17 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix CALL AllocAry( Init%FG, nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector CALL AllocAry( Temp ,size(MM,1), nDOF, 'Temp' , ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry( T_red_T,nDOF , size(MM,1), 'T_red_T' , ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry( p%T_red_T,nDOF , size(MM,1), 'T_red_T' , ErrStat2, ErrMsg2); if(Failed()) return; ! Elimination !Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) !Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) - T_red_T = transpose(p%T_red) + p%T_red_T = transpose(p%T_red) Temp = matmul(MM, p%T_red) - Init%M = matmul(T_red_T, Temp) + Init%M = matmul(p%T_red_T, Temp) Temp = matmul(KK, p%T_red) - Init%K = matmul(T_red_T, Temp) - Init%FG = matmul(T_red_T, FF) + Init%K = matmul(p%T_red_T, Temp) + Init%FG = matmul(p%T_red_T, FF) if (allocated(Temp)) deallocate(Temp) - if (allocated(T_red_T)) deallocate(T_red_T) - - ! --- Triggers for storage of DOF indices, replacing with indices in constrained system - CALL ReInitBCs(Init, p) - CALL ReInitIntFc(Init, p) endif !CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix !Init%D = 0 !< Used for additional damping @@ -1630,34 +1613,7 @@ SUBROUTINE CleanUp_DirectElimination() if (allocated(RA )) deallocate(RA ) if (allocated(RAm1)) deallocate(RAm1) if (allocated(Temp)) deallocate(Temp) - if (allocated(T_red_T)) deallocate(T_red_T) END SUBROUTINE CleanUp_DirectElimination - - !> Reset DOF indices after elimination, does not change the BC - SUBROUTINE ReInitBCs(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_C - iNode = p%Nodes_C(I,1) ! Node index - DO J = 1, 6 ! TODO NOTE here assumptions that 6 DOF are present - Init%BCs( (I-1)*6+J, 1) = p%NodesDOFred(iNode)%List(J) ! DOF number (constrained) - ENDDO - ENDDO - END SUBROUTINE ReInitBCs - - !> Reset DOF indices after elimination - SUBROUTINE ReInitIntFc(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_I - iNode = p%Nodes_I(I,1) ! Node index - DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - Init%IntFc( (I-1)*6+J, 1) = p%NodesDOFred(iNode)%List(J) ! DOF number (unconstrained) - ENDDO - ENDDO - END SUBROUTINE ReInitIntFc END SUBROUTINE DirectElimination !------------------------------------------------------------------------------------------------------ @@ -2013,10 +1969,10 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) call ChessBoard(K_Add, -StifAdd, 0._ReKi, nSpace=nSpace, diagVal=(nMembers-1)*StifAdd) ! Ball/Pin/Universal joints if(StifAdd>0) then - print*,'Stiffness Add, Node:',iNode,'DOF:', Ifreerot - do i=1,nFreeRot - print*,'K Add',K_Add(i,:) - enddo + !print*,'Stiffness Add, Node:',iNode,'DOF:', Ifreerot + !do i=1,nFreeRot + ! print*,'K Add',K_Add(i,:) + !enddo Init%K(Ifreerot,Ifreerot) = Init%K(Ifreerot,Ifreerot) + K_Add endif if(allocated(K_Add)) deallocate(K_Add) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 8ca6bedc6..1c884e72f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2926,7 +2926,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) ! --- Reduced vector of external force if (p%reduced) then - m%Fext_red = matmul(transpose(p%T_red), m%Fext) + m%Fext_red = matmul(p%T_red_T, m%Fext) F_L= m%Fext_red(p%ID__L) else F_L= m%Fext(p%ID__L) @@ -3400,7 +3400,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) endif ! Reduce and keep only "internal" DOFs L if (p%reduced) then - dFred_dFmeshk = matmul(transpose(p%T_red), dFext_dFmeshk) + dFred_dFmeshk = matmul(p%T_red_T, dFext_dFmeshk) dFL_dFmeshk= dFred_dFmeshk(p%ID__L) else dFL_dFmeshk= dFext_dFmeshk(p%ID__L) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 9fcbc585f..1b1120e8e 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -122,8 +122,6 @@ typedef ^ ^ R8Ki K {:}{:} - - "System stiffness matrix" typedef ^ ^ R8Ki M {:}{:} - - "System mass matrix" typedef ^ ^ R8Ki FG {:} - - "Gravity force vector (include initial Cable force T0)" N typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" -typedef ^ ^ INTEGER BCs {:}{:} - - "Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0)" -typedef ^ ^ INTEGER IntFc {:}{:} - - "Interface constraint degree of freedoms" typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" @@ -188,6 +186,7 @@ typedef ^ ^ R8Ki FG_full {:} - - "Gravity force v # --- Constraints reduction typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ^ R8Ki T_red_T {:}{:} - - "Transpose of T_red" "-" typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" typedef ^ ^ IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 2a0822b27..72ad257e6 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -156,8 +156,6 @@ MODULE SubDyn_Types REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (include initial Cable force T0) [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: BCs !< Boundary constraint degree of freedoms. First column - DOFs(rows in the system matrices), Second column - constrained(1) or not(0) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: IntFc !< Interface constraint degree of freedoms [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and list of nodes making up a member (>2 if subdivided) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] @@ -226,6 +224,7 @@ MODULE SubDyn_Types REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG_full !< Gravity force vector (with initial cable force T0), not reduced [N] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red_T !< Transpose of T_red [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOF !< DOF indices of each nodes in unconstrained assembled system [-] TYPE(IList) , DIMENSION(:), ALLOCATABLE :: NodesDOFred !< DOF indices of each nodes in constrained assembled system [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: ElemsDOF !< 12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system [-] @@ -3340,34 +3339,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%ElemProps = SrcInitTypeData%ElemProps ENDIF -IF (ALLOCATED(SrcInitTypeData%BCs)) THEN - i1_l = LBOUND(SrcInitTypeData%BCs,1) - i1_u = UBOUND(SrcInitTypeData%BCs,1) - i2_l = LBOUND(SrcInitTypeData%BCs,2) - i2_u = UBOUND(SrcInitTypeData%BCs,2) - IF (.NOT. ALLOCATED(DstInitTypeData%BCs)) THEN - ALLOCATE(DstInitTypeData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%BCs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%BCs = SrcInitTypeData%BCs -ENDIF -IF (ALLOCATED(SrcInitTypeData%IntFc)) THEN - i1_l = LBOUND(SrcInitTypeData%IntFc,1) - i1_u = UBOUND(SrcInitTypeData%IntFc,1) - i2_l = LBOUND(SrcInitTypeData%IntFc,2) - i2_u = UBOUND(SrcInitTypeData%IntFc,2) - IF (.NOT. ALLOCATED(DstInitTypeData%IntFc)) THEN - ALLOCATE(DstInitTypeData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%IntFc.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%IntFc = SrcInitTypeData%IntFc -ENDIF IF (ALLOCATED(SrcInitTypeData%MemberNodes)) THEN i1_l = LBOUND(SrcInitTypeData%MemberNodes,1) i1_u = UBOUND(SrcInitTypeData%MemberNodes,1) @@ -3494,12 +3465,6 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%ElemProps)) THEN DEALLOCATE(InitTypeData%ElemProps) ENDIF -IF (ALLOCATED(InitTypeData%BCs)) THEN - DEALLOCATE(InitTypeData%BCs) -ENDIF -IF (ALLOCATED(InitTypeData%IntFc)) THEN - DEALLOCATE(InitTypeData%IntFc) -ENDIF IF (ALLOCATED(InitTypeData%MemberNodes)) THEN DEALLOCATE(InitTypeData%MemberNodes) ENDIF @@ -3690,16 +3655,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! ElemProps upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%ElemProps) ! ElemProps END IF - Int_BufSz = Int_BufSz + 1 ! BCs allocated yes/no - IF ( ALLOCATED(InData%BCs) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! BCs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%BCs) ! BCs - END IF - Int_BufSz = Int_BufSz + 1 ! IntFc allocated yes/no - IF ( ALLOCATED(InData%IntFc) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! IntFc upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IntFc) ! IntFc - END IF Int_BufSz = Int_BufSz + 1 ! MemberNodes allocated yes/no IF ( ALLOCATED(InData%MemberNodes) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MemberNodes upper/lower bounds for each dimension @@ -4265,46 +4220,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%BCs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%BCs,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BCs,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%BCs,2), UBOUND(InData%BCs,2) - DO i1 = LBOUND(InData%BCs,1), UBOUND(InData%BCs,1) - IntKiBuf(Int_Xferred) = InData%BCs(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%IntFc) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IntFc,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IntFc,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%IntFc,2), UBOUND(InData%IntFc,2) - DO i1 = LBOUND(InData%IntFc,1), UBOUND(InData%IntFc,1) - IntKiBuf(Int_Xferred) = InData%IntFc(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF IF ( .NOT. ALLOCATED(InData%MemberNodes) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -5000,52 +4915,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BCs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%BCs)) DEALLOCATE(OutData%BCs) - ALLOCATE(OutData%BCs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BCs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%BCs,2), UBOUND(OutData%BCs,2) - DO i1 = LBOUND(OutData%BCs,1), UBOUND(OutData%BCs,1) - OutData%BCs(i1,i2) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IntFc not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IntFc)) DEALLOCATE(OutData%IntFc) - ALLOCATE(OutData%IntFc(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IntFc.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%IntFc,2), UBOUND(OutData%IntFc,2) - DO i1 = LBOUND(OutData%IntFc,1), UBOUND(OutData%IntFc,1) - OutData%IntFc(i1,i2) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MemberNodes not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7120,6 +6989,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%T_red = SrcParamData%T_red ENDIF +IF (ALLOCATED(SrcParamData%T_red_T)) THEN + i1_l = LBOUND(SrcParamData%T_red_T,1) + i1_u = UBOUND(SrcParamData%T_red_T,1) + i2_l = LBOUND(SrcParamData%T_red_T,2) + i2_u = UBOUND(SrcParamData%T_red_T,2) + IF (.NOT. ALLOCATED(DstParamData%T_red_T)) THEN + ALLOCATE(DstParamData%T_red_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%T_red_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%T_red_T = SrcParamData%T_red_T +ENDIF IF (ALLOCATED(SrcParamData%NodesDOF)) THEN i1_l = LBOUND(SrcParamData%NodesDOF,1) i1_u = UBOUND(SrcParamData%NodesDOF,1) @@ -7978,6 +7861,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%T_red)) THEN DEALLOCATE(ParamData%T_red) ENDIF +IF (ALLOCATED(ParamData%T_red_T)) THEN + DEALLOCATE(ParamData%T_red_T) +ENDIF IF (ALLOCATED(ParamData%NodesDOF)) THEN DO i1 = LBOUND(ParamData%NodesDOF,1), UBOUND(ParamData%NodesDOF,1) CALL SD_Destroyilist( ParamData%NodesDOF(i1), ErrStat, ErrMsg ) @@ -8255,6 +8141,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! T_red upper/lower bounds for each dimension Db_BufSz = Db_BufSz + SIZE(InData%T_red) ! T_red END IF + Int_BufSz = Int_BufSz + 1 ! T_red_T allocated yes/no + IF ( ALLOCATED(InData%T_red_T) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! T_red_T upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%T_red_T) ! T_red_T + END IF Int_BufSz = Int_BufSz + 1 ! NodesDOF allocated yes/no IF ( ALLOCATED(InData%NodesDOF) ) THEN Int_BufSz = Int_BufSz + 2*1 ! NodesDOF upper/lower bounds for each dimension @@ -8829,6 +8720,26 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF + IF ( .NOT. ALLOCATED(InData%T_red_T) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red_T,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red_T,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%T_red_T,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%T_red_T,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%T_red_T,2), UBOUND(InData%T_red_T,2) + DO i1 = LBOUND(InData%T_red_T,1), UBOUND(InData%T_red_T,1) + DbKiBuf(Db_Xferred) = InData%T_red_T(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF IF ( .NOT. ALLOCATED(InData%NodesDOF) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10272,6 +10183,29 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T_red_T not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%T_red_T)) DEALLOCATE(OutData%T_red_T) + ALLOCATE(OutData%T_red_T(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%T_red_T.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%T_red_T,2), UBOUND(OutData%T_red_T,2) + DO i1 = LBOUND(OutData%T_red_T,1), UBOUND(OutData%T_red_T,1) + OutData%T_red_T(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodesDOF not allocated Int_Xferred = Int_Xferred + 1 ELSE From 91ad35d08bd895f955a624b590bd41af60599b3c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 11 Sep 2020 12:47:43 -0600 Subject: [PATCH 292/377] FlexSub: removed info for full system eigensolve:w --- modules/subdyn/src/FEM.f90 | 12 ++++++------ modules/subdyn/src/SubDyn.f90 | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 812cffd01..5d2c6706b 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -81,17 +81,17 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs Omega2(I) = AlphaR(I)/Beta(I) if ( EqualRealNos(real(Beta(I),ReKi),0.0_ReKi) ) then ! --- Beta =0 - call WrScr('[WARN] Large eigenvalue found, system may be ill-conditioned') + if (bCheckSingularity) call WrScr('[WARN] Large eigenvalue found, system may be ill-conditioned') Omega2(I) = MAX_EIGENVALUE elseif ( EqualRealNos(real(AlphaI(I),ReKi),0.0_ReKi) ) THEN ! --- Real Eigenvalues IF ( AlphaR(I)<0.0_LaKi ) THEN if ( (AlphaR(I)/Beta(I))<1e-6_LaKi ) then ! Tolerating very small negative eigenvalues - call WrScr('[INFO] Negative eigenvalue found with small norm (system may contain rigid body mode)') + if (bCheckSingularity) call WrScr('[INFO] Negative eigenvalue found with small norm (system may contain rigid body mode)') Omega2(I)=0.0_LaKi else - call WrScr('[WARN] Negative eigenvalue found, system may be ill-conditioned.') + if (bCheckSingularity) call WrScr('[WARN] Negative eigenvalue found, system may be ill-conditioned.') Omega2(I)=AlphaR(I)/Beta(I) endif else @@ -102,14 +102,14 @@ SUBROUTINE EigenSolve(K, M, N, bCheckSingularity, EigVect, Omega, ErrStat, ErrMs normA = sqrt(AlphaR(I)**2 + AlphaI(I)**2) if ( (normA/Beta(I))<1e-6_LaKi ) then ! Tolerating very small eigenvalues with imaginary part - call WrScr('[WARN] Complex eigenvalue found with small norm, approximating as 0') + if (bCheckSingularity) call WrScr('[WARN] Complex eigenvalue found with small norm, approximating as 0') Omega2(I) = 0.0_LaKi elseif ( abs(AlphaR(I))>1e3_LaKi*abs(AlphaI(I)) ) then ! Tolerating very small imaginary part compared to real part... (not pretty) - call WrScr('[WARN] Complex eigenvalue found with small Im compare to Re') + if (bCheckSingularity) call WrScr('[WARN] Complex eigenvalue found with small Im compare to Re') Omega2(I) = AlphaR(I)/Beta(I) else - call WrScr('[WARN] Complex eigenvalue found with large imaginary value)') + if (bCheckSingularity) call WrScr('[WARN] Complex eigenvalue found with large imaginary value)') Omega2(I) = MAX_EIGENVALUE endif !call Fatal('Complex eigenvalue found, system may be ill-conditioned'); return diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 1c884e72f..f332d6275 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -3000,7 +3000,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) ! M and K are reduced matrices, but Boundary conditions are not applied ! We set bDOF, which is true if not a fixed Boundary conditions ! NOTE: we don't check for singularities/rigig body modes here - CALL WrScr(' Calculating Full System Modes for summary file (discard any [INFO] below)') + CALL WrScr(' Calculating Full System Modes for summary file') CALL AllocAry(bDOF, p%nDOF_red, 'bDOF', ErrStat2, ErrMsg2); if(Failed()) return bDOF(:) = .true. bDOF(p%ID__F) = .false. From 6a92a69e0884d129ca56acf6f46624e2cd167758 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 16 Sep 2020 12:50:54 -0600 Subject: [PATCH 293/377] FlexSub: replaced matmul with Lapack, more to do --- modules/subdyn/src/SD_FEM.f90 | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 84cb7f3f3..3f6f5136b 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1533,6 +1533,7 @@ END SUBROUTINE BuildTMatrix !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) + use NWTC_LAPACK, only: LAPACK_GEMM use IntegerList, only: len TYPE(SD_InitType), INTENT(INOUT) :: Init TYPE(SD_ParameterType),target,INTENT(INOUT) :: p @@ -1547,7 +1548,7 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) real(FEKi), dimension(:,:), allocatable :: MM, KK real(FEKi), dimension(:), allocatable :: FF real(FEKi), dimension(:,:), allocatable :: Temp - integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF + integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF, i,j ErrStat = ErrID_None ErrMsg = "" @@ -1570,16 +1571,25 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%FG, nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector CALL AllocAry( Temp ,size(MM,1), nDOF, 'Temp' , ErrStat2, ErrMsg2); if(Failed()) return; CALL AllocAry( p%T_red_T,nDOF , size(MM,1), 'T_red_T' , ErrStat2, ErrMsg2); if(Failed()) return; - ! Elimination + ! --- Elimination (stack expensive) !Init%M = matmul(transpose(p%T_red), matmul(MM, p%T_red)) !Init%K = matmul(transpose(p%T_red), matmul(KK, p%T_red)) - p%T_red_T = transpose(p%T_red) - Temp = matmul(MM, p%T_red) - Init%M = matmul(p%T_red_T, Temp) - Temp = matmul(KK, p%T_red) - Init%K = matmul(p%T_red_T, Temp) - Init%FG = matmul(p%T_red_T, FF) + !p%T_red_T = transpose(p%T_red) + do i = 1, size(p%T_red,1) + do j = 1, size(p%T_red,2) + p%T_red_T(j,i) = p%T_red(i,j) + enddo + enddo + !Temp = matmul(MM, p%T_red) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, MM , p%T_red, 0.0_FeKi, Temp , ErrStat2, ErrMsg2); if(Failed()) return + !Init%M = matmul(p%T_red_T, Temp) + CALL LAPACK_gemm( 'T', 'N', 1.0_FeKi, p%T_red, Temp , 0.0_FeKi, Init%M, ErrStat2, ErrMsg2); if(Failed()) return + !Temp = matmul(KK, p%T_red) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, KK , p%T_red, 0.0_FeKi, Temp , ErrStat2, ErrMsg2); if(Failed()) return + !Init%K = matmul(p%T_red_T, Temp) + CALL LAPACK_gemm( 'T', 'N', 1.0_FeKi, p%T_red, Temp , 0.0_FeKi, Init%K, ErrStat2, ErrMsg2); if(Failed()) return if (allocated(Temp)) deallocate(Temp) + Init%FG = matmul(p%T_red_T, FF) endif !CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix !Init%D = 0 !< Used for additional damping From 99e64a3338137dff544fcc4e702fac18aab9b1e1 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 18 Sep 2020 10:58:18 -0600 Subject: [PATCH 294/377] FlexSub: more matmul replacements --- modules/subdyn/src/FEM.f90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 5d2c6706b..563c13cc4 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -505,7 +505,7 @@ END SUBROUTINE CraigBamptonReduction SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR, nL, nM, nM_Out,& MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg,& CRR, CLL, CRL, CBB, CBM, CMM) - USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf + USE NWTC_LAPACK, only: LAPACK_getrs, LAPACK_getrf, LAPACK_gemm INTEGER(IntKi), INTENT( in) :: nR INTEGER(IntKi), INTENT( in) :: nL INTEGER(IntKi), INTENT( in) :: nM_Out @@ -561,8 +561,10 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR CALL AllocAry( Temp , nL , nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return CALL AllocAry( MU , nM_out, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL) - Temp = MATMUL( MU, MLL ) - MU(1:nM_Out,1:nM_Out) = MATMUL( Temp, PhiL ) + !Temp = MATMUL( MU, MLL ) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, MU, MLL, 0.0_FeKi, Temp , ErrStat2, ErrMsg2); if(Failed()) return + !MU(1:nM_Out,1:nM_Out) = MATMUL( Temp, PhiL ) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, Temp, PhiL, 0.0_FeKi, MU , ErrStat2, ErrMsg2); if(Failed()) return DEALLOCATE(Temp) ! PhiL = MATMUL( PhiL, MU2 ) !this is the nondimensionalization (MU2 is diagonal) DO I = 1, nM_out @@ -574,8 +576,10 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR CALL AllocAry( Temp , nM, nL , 'Temp' , ErrStat2 , ErrMsg2); if(Failed()) return CALL AllocAry( MU , nM, nL , 'Mu' , ErrStat2 , ErrMsg2); if(Failed()) return MU = TRANSPOSE(PhiL(1:nL, 1:nM)) - Temp = MATMUL( MU, CLL ) - CMM = MATMUL( Temp, PhiL(1:nL, 1:nM) ) + !Temp = MATMUL( MU, CLL ) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, MU, CLL, 0.0_FeKi, Temp , ErrStat2, ErrMsg2); if(Failed()) return + ! CMM = MATMUL( Temp, PhiL(1:nL, 1:nM) ) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, Temp, PhiL, 0.0_FeKi, CMM , ErrStat2, ErrMsg2); if(Failed()) return DEALLOCATE(MU) DEALLOCATE(Temp) endif @@ -599,7 +603,9 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR PhiR_T_MLL = TRANSPOSE(PhiR) PhiR_T_MLL = MATMUL(PhiR_T_MLL, MLL) + !CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, PhiR_T_MLL, MLL, 0.0_FeKi, PhiR_T_MLL , ErrStat2, ErrMsg2); if(Failed()) return MBB = MATMUL(MRL, PhiR) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, MRL, PhiR, 0.0_FeKi, MBB , ErrStat2, ErrMsg2); if(Failed()) return MBB = MRR + MBB + TRANSPOSE( MBB ) + MATMUL( PhiR_T_MLL, PhiR ) IF ( nM == 0) THEN @@ -609,7 +615,8 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR MBM = MATMUL( MRL, PhiL(:,1:nM) ) + MBM !This had PhiM ENDIF - KBB = MATMUL(KRL, PhiR) + !KBB = MATMUL(KRL, PhiR) + CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, KRL, PhiR, 0.0_FeKi, KBB , ErrStat2, ErrMsg2); if(Failed()) return KBB = KBB + KRR if (present(CRR)) then From 697d02f4b676dc46f4722ae8dfa722f61cf38552 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 21 Sep 2020 14:09:04 -0600 Subject: [PATCH 295/377] Including updated FAST_Types.f90 --- modules/openfast-library/src/FAST_Types.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index af308fb90..d8527c7c3 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -40933,7 +40933,7 @@ SUBROUTINE FAST_UnPackExternInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS END SUBROUTINE FAST_UnPackExternInputType SUBROUTINE FAST_CopyInitData( SrcInitDataData, DstInitDataData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FAST_InitData), INTENT(IN) :: SrcInitDataData + TYPE(FAST_InitData), INTENT(INOUT) :: SrcInitDataData TYPE(FAST_InitData), INTENT(INOUT) :: DstInitDataData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat From f98db4894d9205eb722119fdf5714f79991ada6a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 23 Sep 2020 15:20:30 -0600 Subject: [PATCH 296/377] FlexSub: wrong sign in controllable cable Delta L --- modules/subdyn/src/SubDyn.f90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f332d6275..7828065f6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2342,8 +2342,10 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) enddo p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t + !CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, p%PhiLInvOmgL2, p%PhiL_T, 0.0_FeKi, p%KLLm1 , ErrStat2, ErrMsg2); if(Failed()) return p%FGL = FGL p%UL_st_g = MATMUL(p%KLLm1, FGL) + !CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, p%KLLm1, FGL, 0.0_FeKi, p%KLLm1 , ErrStat2, ErrMsg2); if(Failed()) return endif ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) @@ -2889,8 +2891,8 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) iElem = p%CtrlElem2Channel(iCC,1) iChannel = p%CtrlElem2Channel(iCC,2) IDOF = p%ElemsDOF(1:12, iElem) - ! T(t) = EA * DeltaL(t) /(Le + Delta L(t)) - CableTension = p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) + ! T(t) = EA * DeltaL(t) /(Le - Delta L(t)) + CableTension = p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length - u%CableDeltaL(iChannel)) m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) enddo endif From 4ff08882224a632df4ba0b8ad8d44a6de9d67226 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 24 Sep 2020 12:50:04 -0600 Subject: [PATCH 297/377] FlexSub: DeltaL for cable tension now negative --- modules/subdyn/src/SubDyn.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 7828065f6..c20dd7c40 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2891,8 +2891,8 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) iElem = p%CtrlElem2Channel(iCC,1) iChannel = p%CtrlElem2Channel(iCC,2) IDOF = p%ElemsDOF(1:12, iElem) - ! T(t) = EA * DeltaL(t) /(Le - Delta L(t)) - CableTension = p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length - u%CableDeltaL(iChannel)) + ! T(t) = - EA * DeltaL(t) /(Le + Delta L(t)) ! NOTE DeltaL<0 + CableTension = -p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) enddo endif From 32047db132beb68b18f16b8bdaa6f62e0667b50b Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 24 Sep 2020 13:42:17 -0600 Subject: [PATCH 298/377] FlexSub: more lapack --- modules/subdyn/src/FEM.f90 | 80 ++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index 563c13cc4..2d5972e4d 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -403,6 +403,7 @@ END SUBROUTINE BreakSysMtrx !! !! NOTE: generic code SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, KBB, PhiL, PhiR, OmegaL, ErrStat, ErrMsg, FG, FGR, FGL, FGB, FGM, CC, CBB, CBM, CMM) + use NWTC_LAPACK, only: LAPACK_GEMV REAL(FEKi), INTENT(IN ) :: MM(:, :) !< Mass matrix REAL(FEKi), INTENT(IN ) :: KK(:, :) !< Stiffness matrix INTEGER(IntKi), INTENT(IN ) :: nR @@ -461,14 +462,22 @@ SUBROUTINE CraigBamptonReduction(MM, KK, IDR, nR, IDL, nL, nM, nM_Out, MBB, MBM, CBB=CBB, CBM=CBM, CMM=CMM) !< Optional Outputs if(Failed()) return - ! --- Reduction of force if provided if (present(FG).and.present(FGR).and.present(FGL)) then - if (present(FGM)) then - FGB = FGR + matmul( transpose(PhiR), FGL) - endif if (present(FGB)) then - FGM = matmul( FGL, PhiL(:,1:nM) ) != matmul( transpose(PhiM), FGL ) because FGL is 1-D + !FGB = FGR + matmul( transpose(PhiR), FGL) + if (nL>0) then + CALL LAPACK_GEMV('t', nL , nR, 1.0_FeKi, PhiR, nL, FGL, 1, 0.0_FeKi, FGB, 1 ) + FGB = FGR + FGB + else + FGB = FGR + endif + endif + if (present(FGM)) then + !FGM = matmul( FGL, PhiL(:,1:nM) ) != matmul( transpose(PhiM), FGL ) because FGL is 1-D + if (nM>0) then + CALL LAPACK_GEMV('t', nL , nM, 1.0_FeKi, PhiL(:,1:nM), nL, FGL, 1, 0.0_FeKi, FGM, 1 ) + endif endif endif call CleanUp() @@ -547,7 +556,7 @@ SUBROUTINE CraigBamptonReduction_FromPartition( MRR, MLL, MRL, KRR, KLL, KRL, nR if(Failed()) return; endif if (nM_out Date: Thu, 24 Sep 2020 14:36:08 -0600 Subject: [PATCH 299/377] FlexSub: more lapack --- modules/subdyn/src/SubDyn.f90 | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index c20dd7c40..24db7e701 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -2301,8 +2301,9 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI__) !bjj: added this so we don't have to take the transpose 5+ times - INTEGER(IntKi) :: I + real(FEKi), allocatable :: Temp(:,:) + real(ReKi) :: TI_transpose(nDOFL_TP,p%nDOFI__) !bjj: added this so we don't have to take the transpose 5+ times + integer(IntKi) :: I integer(IntKi) :: n ! size of jacobian in AM2 calculation INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -2330,7 +2331,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, else CALL WrScr(' Using static improvement method for gravity only') endif - ! Allocations + ! Allocations - NOTE: type conversion belows from FEKi to ReKi CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); if(Failed())return CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); if(Failed())return CALL AllocAry( p%KLLm1 , p%nDOF__L, p%nDOF__L, 'p%KLLm1', ErrStat2, ErrMsg2 ); if(Failed())return @@ -2341,11 +2342,11 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, do I = 1, nM_out p%PhiLInvOmgL2(:,I) = PhiL(:,I)* (1./OmegaL(I)**2) enddo - p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t - !CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, p%PhiLInvOmgL2, p%PhiL_T, 0.0_FeKi, p%KLLm1 , ErrStat2, ErrMsg2); if(Failed()) return + ! KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t + !p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t + CALL LAPACK_gemm( 'N', 'N', 1.0_ReKi, p%PhiLInvOmgL2, p%PhiL_T, 0.0_ReKi, p%KLLm1, ErrStat2, ErrMsg2); if(Failed()) return p%FGL = FGL p%UL_st_g = MATMUL(p%KLLm1, FGL) - !CALL LAPACK_gemm( 'N', 'N', 1.0_FeKi, p%KLLm1, FGL, 0.0_FeKi, p%KLLm1 , ErrStat2, ErrMsg2); if(Failed()) return endif ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) @@ -2376,7 +2377,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !p%D1_15=-TI_transpose !this is 6x6NIN IF ( p%nDOFM > 0 ) THEN ! These values don't exist for nDOFM=0; i.e., p%nDOFM == 0 ! TODO cant use LAPACK due to type conversions FEKi->ReKi - p%MBM = MATMUL( TRANSPOSE(p%TI), MBmb ) != MBMt + p%MBM = MATMUL( TI_transpose, MBmb ) ! NOTE: type conversion !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return !p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, CBMb, 0.0_ReKi, p%CBM, ErrStat2, ErrMsg2); if (Failed()) return @@ -2385,16 +2386,12 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%MMB = TRANSPOSE( p%MBM ) != MMBt p%CMB = TRANSPOSE( p%CBM ) != CMBt - p%PhiM = PhiL(:,1:p%nDOFM) + p%PhiM = real( PhiL(:,1:p%nDOFM), ReKi) ! A_21=-Kmm (diagonal), A_22=-Cmm (approximated as diagonal) p%KMMDiag= OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array p%CMMDiag = 2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array - - ! B_23, B_24 - !p%PhiM_T = TRANSPOSE( p%PhiM ) - ! FX = matmul( transpose(PhiM), FGL ) (output of CraigBamptonReduction) p%FX = FGM @@ -2415,9 +2412,9 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%D1_13 = p%MBB - p%D1_13 ! TODO cant use LAPACK due to type conversions FEKi->ReKi - !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - p%D1_14 = MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PHiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) + !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PhiRb)) + p%D1_14 = MATMUL( TI_transpose, TRANSPOSE(PhiRb)) + !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PhiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 @@ -2433,7 +2430,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ENDDO ! D2_53, D2_63, D2_64 - p%D2_63 = MATMUL( p%PhiM, p%MMB ) + !p%D2_63 = p%PhiRb_TI - MATMUL( p%PhiM, p%MMB ) + CALL LAPACK_GEMM( 'N', 'N', 1.0_ReKi, p%PhiM, p%MMB, 0.0_ReKi, p%D2_63, ErrStat2, ErrMsg2 ); if(Failed()) return; p%D2_63 = p%PhiRb_TI - p%D2_63 !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) From 058c7e7cbd67f75a460cc2dbff2010e852ae6f13 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 28 Sep 2020 19:36:10 -0600 Subject: [PATCH 300/377] Bug fixes Fixed bug with region definition for partially submerged volume calculation Fixed bug with reordering member nodes Fixed double precision compile bug --- modules/hydrodyn/src/Morison.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index fd0a2c76b..4c15db8b2 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1380,8 +1380,8 @@ subroutine FlipMemberNodeData( member, nodes, doSwap, errStat, errMsg ) ! Loop over half the interior nodes and swap their indices do i = 1, ceiling( (numMemNodes-2.0_ReKi)/2.0_ReKi) indx = member%NodeIndx(1+i) - member%NodeIndx(1+i) = member%NodeIndx(numMemNodes-1-i) - member%NodeIndx(numMemNodes-1-i) = indx + member%NodeIndx(1+i) = member%NodeIndx(numMemNodes-i) + member%NodeIndx(numMemNodes-i) = indx end do end if @@ -1616,7 +1616,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%Vinner = member%Vinner + Vinner_l + Vinner_u member%Vouter = member%Vouter + Vouter_l + Vouter_u member%Vsubmerged = member%Vsubmerged + Vouter_l + Vouter_u - else if ((0.0 > Za) .AND. (0.0 < Zb)) then + else if ((0.0 > Za) .AND. (0.0 <= Zb)) then if (i == 1) then call SetErrStat(ErrID_Fatal, 'The lowest element of a member must not cross the free surface. This is true for MemberID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties') end if @@ -2153,7 +2153,7 @@ SUBROUTINE RodrigMat(a, R, errStat, errMsg) ! errStat = ErrID_Fatal errMsg = 'RodrigMat encountered vector of zero length' - else IF ( EqualRealNos(a(1), 0.0) .AND. EqualRealNos(a(2), 0.0) ) THEN ! return identity if vertical + else IF ( EqualRealNos(a(1), 0.0_ReKi) .AND. EqualRealNos(a(2), 0.0_ReKi) ) THEN ! return identity if vertical CALL EYE(R, errStat,errMsg) IF (a(3) < 0) THEN R = -R From f1e500b0e21c8194864dd1a0709569270091533a Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 28 Sep 2020 19:36:45 -0600 Subject: [PATCH 301/377] Add Debug_Double config --- vs-build/HydroDyn/HydroDynDriver.vfproj | 150 ++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 10 deletions(-) diff --git a/vs-build/HydroDyn/HydroDynDriver.vfproj b/vs-build/HydroDyn/HydroDynDriver.vfproj index ae00aad07..4bec1b332 100644 --- a/vs-build/HydroDyn/HydroDynDriver.vfproj +++ b/vs-build/HydroDyn/HydroDynDriver.vfproj @@ -43,6 +43,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -51,121 +71,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -185,127 +263,179 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1ffcaf353926b1cd8d69dd6781bba0b5f65e2355 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 28 Sep 2020 19:37:07 -0600 Subject: [PATCH 302/377] Add Debug_Double config --- vs-build/HydroDyn/HydroDynDriver.sln | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/vs-build/HydroDyn/HydroDynDriver.sln b/vs-build/HydroDyn/HydroDynDriver.sln index e149d6049..cc5662783 100644 --- a/vs-build/HydroDyn/HydroDynDriver.sln +++ b/vs-build/HydroDyn/HydroDynDriver.sln @@ -1,18 +1,24 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30503.244 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "HydroDynDriver", "HydroDynDriver.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_Double|Win32 = Debug_Double|Win32 + Debug_Double|x64 = Debug_Double|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.ActiveCfg = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|Win32.Build.0 = Debug_Double|Win32 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.ActiveCfg = Debug_Double|x64 + {815C302F-A93D-4C22-9329-717B085113C0}.Debug_Double|x64.Build.0 = Debug_Double|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.ActiveCfg = Debug|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|Win32.Build.0 = Debug|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Debug|x64.ActiveCfg = Debug|x64 @@ -25,4 +31,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D73C5D81-14CD-4C14-8B52-6885B380AE3E} + EndGlobalSection EndGlobal From d28dbc8bc43cb72fcbe2e2f5f80d06ed0cbde865 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 1 Oct 2020 12:46:55 -0600 Subject: [PATCH 303/377] Bug Fix: Change unwanted integer divides into desired floating divides --- modules/hydrodyn/src/Morison.f90 | 52 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 4c15db8b2..1e28566e5 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -401,11 +401,11 @@ SUBROUTINE TaperCalc(R1, R2, H, taperV, h_c) taperV = abs(pi*R1*R1*H) h_c = H/2.0 elseif ( EqualRealNos(R1,0.0_ReKi) ) then ! seperate this case out because it gives a divide by zero in general formula - taperV = abs(1./3.*pi*R2*R2*H) ! cone volume - h_c = 3./4.*H ! from base + taperV = abs(1.0/3.0*pi*R2*R2*H) ! cone volume + h_c = 3.0/4.0*H ! from base else taperV = abs(pi/3/m*(R2**3 - R1**3)) - h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) !( coneV*1./4.*coneH - coneVtip*(1./4.*(coneH-H) + H) )/ taperV ! from base + h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4.0/(R1**2 + R1*R2 + R2**2) !( coneV*1./4.*coneH - coneVtip*(1./4.*(coneH-H) + H) )/ taperV ! from base end if END SUBROUTINE TaperCalc @@ -424,17 +424,17 @@ SUBROUTINE CylInertia(R1, R2, H, rho, Il, Ir) m = (R2-R1)/H if ( EqualRealNos(R1, R2) ) then ! if just a cylinder - Ir = abs(1/12* rho*pi*R1*R1*H *(3*R1*R1 + 4*H*H)) ! radial inertia about node 1 + Ir = abs(1.0/12.0* rho*pi*R1*R1*H *(3.0*R1*R1 + 4.0*H*H)) ! radial inertia about node 1 Il = abs(0.5* rho*pi*R1*R1*H *R1*R1) ELSEIF ( EqualRealNos(R1,0.0_ReKi) ) then ! seperate this case out because it gives a divide by zero in general formula - Ir = abs(rho*pi*(1/20/m + 1/5/m**3) * R2**5) - Il = abs(1/10*rho*pi/m*R2**5) + Ir = abs(rho*pi*(1.0/20.0/m + 1.0/5.0/m**3) * R2**5) + Il = abs(1.0/10.0*rho*pi/m*R2**5) ELSE - h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) + h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4.0/(R1**2 + R1*R2 + R2**2) !l_c = R1/M + (R2-R1)/m *(R1**2 + 2*R1*R2 + 3*R2**2)/4/(R1**2 + R1*R2 + R2**2) - Ir_tip = abs(pi/20 *rho/m*(1 + 4/m**2) * (R2**5 - R1**5)) ! radial moment of inertia about tip of cone - Ir = abs(Ir_tip - rho/3/m*pi*(R2**3-R1**3) * (R1/m + 2*h_c)*R1/m ) ! radial moment of inertia about node 1 - Il = abs(1/10/m*rho*pi*(R2**5 - R1**5)) + Ir_tip = abs(pi/20.0 *rho/m*(1.0 + 4.0/m**2) * (R2**5 - R1**5)) ! radial moment of inertia about tip of cone + Ir = abs(Ir_tip - rho/3.0/m*pi*(R2**3-R1**3) * (R1/m + 2.0*h_c)*R1/m ) ! radial moment of inertia about node 1 + Il = abs(1.0/10.0/m*rho*pi*(R2**5 - R1**5)) END IF END SUBROUTINE CylInertia @@ -1653,9 +1653,9 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! force and moment magnitude constants - member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * dl *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)* member%dRdl_in(i) + member%Rin(i))*dl + 1/3* member%dRdl_in(i)*dl**2 ) - member%Cfr_fb(i) = Pi * member%FillDens * gravity * dl *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*dl +1/3 * member%dRdl_in(i)**2 *dl**2 ) - member%CM0_fb(i) = TwoPi * member%FillDens * gravity * dl *( 0.25*dl**3* member%dRdl_in(i)**4 + 0.25*dl**3* member%dRdl_in(i)**2 + dl**2* member%dRdl_in(i)**3*member%Rin(i) + 2/3*dl**2* member%dRdl_in(i)*member%Rin(i) + 1.5*dl* member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*dl*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) + member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * dl *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)* member%dRdl_in(i) + member%Rin(i))*dl + 1.0/3.0* member%dRdl_in(i)*dl**2 ) + member%Cfr_fb(i) = Pi * member%FillDens * gravity * dl *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*dl +1.0/3.0 * member%dRdl_in(i)**2 *dl**2 ) + member%CM0_fb(i) = TwoPi * member%FillDens * gravity * dl *( 0.25*dl**3* member%dRdl_in(i)**4 + 0.25*dl**3* member%dRdl_in(i)**2 + dl**2* member%dRdl_in(i)**3*member%Rin(i) + 2.0/3.0*dl**2* member%dRdl_in(i)*member%Rin(i) + 1.5*dl* member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*dl*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) ! partially filled element @@ -1686,9 +1686,9 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%alpha_fb_star(i) = (1 - member%alpha_fb(i))*( Za - member%FillFSLoc )**3 / ( ( (1-member%alpha_fb(i))*(Za - member%FillFSLoc))**3 - member%alpha_fb(i)*(Zb - member%FillFSLoc)**3 ) ! force and moment magnitude constants - member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * member%h_fill *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)*member%dRdl_in(i) + member%Rin(i))*member%h_fill + 1/3*member%dRdl_in(i)*member%h_fill**2 ) - member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1/3 *member%dRdl_in(i)**2 *member%h_fill**2 ) - member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2/3*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) & + member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * member%h_fill *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)*member%dRdl_in(i) + member%Rin(i))*member%h_fill + 1.0/3.0*member%dRdl_in(i)*member%h_fill**2 ) + member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1.0/3.0 *member%dRdl_in(i)**2 *member%h_fill**2 ) + member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2.0/3.0*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) & + 1.5*member%h_fill*member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*member%h_fill*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) & -0.25 * member%FillDens * gravity * Pi * ( member%Rin(i) + member%h_fill*member%dRdl_in(i))**4 @@ -2185,7 +2185,7 @@ FUNCTION GetAlpha(R1,R2) REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element - GetAlpha = (R1*R1 + 2*R1*R2 + 3*R2*R2)/4/(R1*R1 + R1*R2 + R2*R2) + GetAlpha = (R1*R1 + 2.0*R1*R2 + 3.0*R2*R2)/4.0/(R1*R1 + R1*R2 + R2*R2) END FUNCTION GetAlpha @@ -2706,7 +2706,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, cl = (0.75*a0b0*r1**2*cosPhi + 0.75*r1**4*C_1 + r1*C_1*C_2) / (dRdl_mg*C_1*C_2) cr = (0.75*a0b0*dRdl_mg*rh**2*sinPhi)/(C_1*C_2) cx = cr*cosPhi + cl*sinPhi - Vs = pi*(a0b0*rh*cosPhi - r1**3)/(3*dRdl_mg) + Vs = pi*(a0b0*rh*cosPhi - r1**3)/(3.0*dRdl_mg) ! End per plan equations !=================== @@ -2729,8 +2729,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, end if - pwr = 1 - alpha = (1-mem%alpha(i))*z1**pwr/(-mem%alpha(i)*z2**pwr + (1-mem%alpha(i))*z1**pwr) + pwr = 3 + alpha = (1.0-mem%alpha(i))*z1**pwr/(-mem%alpha(i)*z2**pwr + (1.0-mem%alpha(i))*z1**pwr) Fb = Vs*p%WtrDens*g !buoyant force Fr = -Fb*sinPhi !radial component of buoyant force @@ -2739,7 +2739,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! calculate (imaginary) bottom plate forces/moment to subtract from displacement-based values Fl = Fl + p%WtrDens*g*z1* Pi *r1*r1 - Moment = Moment + p%WtrDens*g* sinPhi * Pi/4*r1**4 + Moment = Moment + p%WtrDens*g* sinPhi * Pi/4.0*r1**4 ! reduce taper-based moment to remove (not double count) radial force distribution to each node @@ -2754,17 +2754,17 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, y%Mesh%Moment(:,mem%NodeIndx(i-1)) = y%Mesh%Moment(:,mem%NodeIndx(i-1)) + F_B2(4:6) else ! normal, fully submerged case - Fl = -2.0*Pi*dRdl_mg*p%WtrDens*g*dl*( z1*r1 + 0.5*(z1*dRdl_mg + r1*cosPhi)*dl + 1/3*dRdl_mg*cosPhi*dl*dl ) ! from CylinderCalculationsR1.ipynb + Fl = -2.0*Pi*dRdl_mg*p%WtrDens*g*dl*( z1*r1 + 0.5*(z1*dRdl_mg + r1*cosPhi)*dl + 1.0/3.0*(dRdl_mg*cosPhi*dl*dl) ) ! from CylinderCalculationsR1.ipynb - Fr = -Pi*p%WtrDens*g*dl*(r1*r1 + dRdl_mg*r1*dl + 1/3*dRdl_mg**2*dl**2)*sinPhi ! from CylinderCalculationsR1.ipynb - Moment = -Pi*dl*g*p%WtrDens*(3*dl**3*dRdl_mg**4 + 3*dl**3*dRdl_mg**2 + 12*dl**2*dRdl_mg**3*r1 + 8*dl**2*dRdl_mg*r1 + 18*dl*dRdl_mg**2*r1*r1 + 6*dl*r1*r1 + 12*dRdl_mg*r1**3)*sinPhi/12 ! latest from CylinderCalculationsR1.ipynb + Fr = -Pi*p%WtrDens*g*dl*(r1*r1 + dRdl_mg*r1*dl + (dRdl_mg**2*dl**2)/3.0)*sinPhi ! from CylinderCalculationsR1.ipynb + Moment = -Pi*dl*g*p%WtrDens*(3.0*dl**3*dRdl_mg**4 + 3.0*dl**3*dRdl_mg**2 + 12.0*dl**2*dRdl_mg**3*r1 + 8.0*dl**2*dRdl_mg*r1 + 18.0*dl*dRdl_mg**2*r1*r1 + 6.0*dl*r1*r1 + 12.0*dRdl_mg*r1**3)*sinPhi/12.0 ! latest from CylinderCalculationsR1.ipynb ! precomputed as mem%alpha(i) ... alpha0 = (r1*r1 + 2*r1*r2 + 3*r2**2)/4/(r1*r1 + r1*r2 + r2**2) !TODO: Review the below alpha eqn, GJH z1d = -min(0.0_ReKi,z1) z2d = -min(0.0_ReKi,z2) - pwr = 1 + pwr = 3 alpha = mem%alpha(i)*z2d**pwr/(mem%alpha(i)*z2d**pwr+(1-mem%alpha(i))*z1d**pwr) @@ -2842,7 +2842,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, lstar = dl*(i-1) end if Fl =TwoPi * mem%dRdl_in(i) * mem%FillDens * p%gravity * dl *( -( mem%Rin(i) + 0.5* mem%dRdl_in(i)*dl )*mem%z_overfill + & - ( lstar*mem%Rin(i) + 0.5*(lstar*mem%dRdl_in(i) + mem%Rin(i) )*dl + 1/3* mem%dRdl_in(i)*dl**2 )*cosphi ) + ( lstar*mem%Rin(i) + 0.5*(lstar*mem%dRdl_in(i) + mem%Rin(i) )*dl + mem%dRdl_in(i)*dl**2/3.0 )*cosphi ) ! forces and moment in tilted coordinates about node i !Fl = mem%Cfl_fb(i)*cosPhi From 3748fac955c3aebdafff261258ac7248d733da63 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Thu, 1 Oct 2020 15:05:39 -0600 Subject: [PATCH 304/377] Bug Fix: interior member nodes were not being offset using MSL2SWL --- modules/hydrodyn/src/Morison.f90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 1e28566e5..10decde6e 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -404,7 +404,7 @@ SUBROUTINE TaperCalc(R1, R2, H, taperV, h_c) taperV = abs(1.0/3.0*pi*R2*R2*H) ! cone volume h_c = 3.0/4.0*H ! from base else - taperV = abs(pi/3/m*(R2**3 - R1**3)) + taperV = abs(pi/3.0/m*(R2**3 - R1**3)) h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4.0/(R1**2 + R1*R2 + R2**2) !( coneV*1./4.*coneH - coneVtip*(1./4.*(coneH-H) + H) )/ taperV ! from base end if @@ -1017,6 +1017,7 @@ subroutine Morison_GenerateSimulationNodes( MSL2SWL, numJoints, inpJoints, numMe numNodes = numNodes + 1 s = real(j, ReKi) / real(numDiv, ReKi) nodes(numNodes)%Position = inpJoints(j1)%Position*(1-s) + inpJoints(j2)%Position*s + nodes(numNodes)%Position(3) = nodes(numNodes)%Position(3) - MSL2SWL ! Correct the Z-coordinate based on the mean sea level To still water level offset value inpMembers(i)%NodeIndx(j+1) = numNodes end do end if From 05da91ebd8a9dfaa1b1ea7fb7ca456410888df29 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 14 Oct 2020 12:49:47 -0600 Subject: [PATCH 305/377] Bug Fix: Fix matmul for Hydrodynamic Added Mass Force calc Thanks to E.B. for seeing that we should only be using the first three components of qdotdot in the matmul for computing F_A_End --- modules/hydrodyn/src/Morison.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 10decde6e..ba21f1cc1 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -3106,7 +3106,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Lumped added mass loads qdotdot = reshape((/u%Mesh%TranslationAcc(:,J),u%Mesh%RotationAcc(:,J)/),(/6/)) - m%F_A_End(:,J) = m%nodeInWater(j) * matmul( p%AM_End(:,:,J) , ( - qdotdot) ) + m%F_A_End(:,J) = m%nodeInWater(j) * matmul( p%AM_End(:,:,J) , ( - qdotdot(1:3)) ) ! TODO: The original code did not multiply by nodeInWater, but should we? GJH m%F_I_End(:,J) = (p%DP_Const_End(:,j) * m%FDynP(j) + matmul(p%AM_End(:,:,j),m%FA(:,j))) From 8906b0d5727a3bebca0ce610e6cbc6dbcde9014c Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Thu, 15 Oct 2020 09:38:48 -0600 Subject: [PATCH 306/377] Changed MoorDyn to use double-precision variables in its internal calculations: - Most floating-point variables inside the MoorDyn module, not inputs/outputs to the glue code, are now double-precision. - This eliminates strange behavior seen in a TetraSpar test case where node positions and resulting tensions were jumping by discrete steps at unpredictable and non-physically-correlated times (e.g. x and y dimensions jump independently). The case also had segment strain-rate outputs showing as proportional to the negative of segment strains, rather than leading by 90 deg phase as expected for a derivative -- this behavior, never seen before, is eliminated by this commit. - Also increased precision of MoorDyn output file data from 4 to 6 decimal places. - TO-DO: Check for proper handling of SiKi/Reki conversions throughout code, make sure things are done optimally. --- modules/moordyn/src/MoorDyn.f90 | 190 ++++---- modules/moordyn/src/MoorDyn_IO.f90 | 10 +- modules/moordyn/src/MoorDyn_Registry.txt | 88 ++-- modules/moordyn/src/MoorDyn_Types.f90 | 528 +++++++++++------------ 4 files changed, 408 insertions(+), 408 deletions(-) diff --git a/modules/moordyn/src/MoorDyn.f90 b/modules/moordyn/src/MoorDyn.f90 index b453ab6a4..ba45acad7 100644 --- a/modules/moordyn/src/MoorDyn.f90 +++ b/modules/moordyn/src/MoorDyn.f90 @@ -65,8 +65,8 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er INTEGER(IntKi) :: Converged ! flag indicating whether the dynamic relaxation has converged INTEGER(IntKi) :: N ! convenience integer for readability: number of segments in the line REAL(ReKi) :: Pos(3) ! array for setting absolute fairlead positions in mesh - REAL(ReKi) :: TransMat(3,3) ! rotation matrix for setting fairlead positions correctly if there is initial platform rotation - REAL(ReKi), ALLOCATABLE :: FairTensIC(:,:)! array of size Nfairs, 3 to store three latest fairlead tensions of each line + REAL(DbKi) :: TransMat(3,3) ! rotation matrix for setting fairlead positions correctly if there is initial platform rotation + REAL(DbKi), ALLOCATABLE :: FairTensIC(:,:)! array of size Nfairs, 3 to store three latest fairlead tensions of each line CHARACTER(20) :: TempString ! temporary string for incidental use INTEGER(IntKi) :: ErrStat2 ! Error status of the operation CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None @@ -258,9 +258,9 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er u%PtFairleadDisplacement%TranslationDisp(3,i) = InitInp%PtfmInit(3) + Transmat(1,3)*Pos(1) + Transmat(2,3)*Pos(2) + TransMat(3,3)*Pos(3) - Pos(3) ! set velocity of each node to zero - u%PtFairleadDisplacement%TranslationVel(1,i) = 0.0_ReKi - u%PtFairleadDisplacement%TranslationVel(2,i) = 0.0_ReKi - u%PtFairleadDisplacement%TranslationVel(3,i) = 0.0_ReKi + u%PtFairleadDisplacement%TranslationVel(1,i) = 0.0_DbKi + u%PtFairleadDisplacement%TranslationVel(2,i) = 0.0_DbKi + u%PtFairleadDisplacement%TranslationVel(3,i) = 0.0_DbKi !print *, 'Fairlead ', i, ' z TranslationDisp at start is ', u%PtFairleadDisplacement%TranslationDisp(3,i) !print *, 'Fairlead ', i, ' z Position at start is ', u%PtFairleadDisplacement%Position(3,i) @@ -299,16 +299,16 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er m%ConnectList(I)%r(1) = m%ConnectList(I)%conX m%ConnectList(I)%r(2) = m%ConnectList(I)%conY m%ConnectList(I)%r(3) = m%ConnectList(I)%conZ - m%ConnectList(I)%rd(1) = 0.0_ReKi - m%ConnectList(I)%rd(2) = 0.0_ReKi - m%ConnectList(I)%rd(3) = 0.0_ReKi + m%ConnectList(I)%rd(1) = 0.0_DbKi + m%ConnectList(I)%rd(2) = 0.0_DbKi + m%ConnectList(I)%rd(3) = 0.0_DbKi END DO ! then do it for fairlead types DO I = 1,p%NFairs DO J = 1, 3 m%ConnectList(m%FairIdList(I))%r(J) = u%PtFairleadDisplacement%Position(J,I) + u%PtFairleadDisplacement%TranslationDisp(J,I) - m%ConnectList(m%FairIdList(I))%rd(J) = 0.0_ReKi + m%ConnectList(m%FairIdList(I))%rd(J) = 0.0_DbKi END DO END DO @@ -350,7 +350,7 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er DO J = 1, N-1 DO K = 1, 3 x%states(m%LineStateIndList(I) + 3*N-3 + 3*J-3 + K-1 ) = m%LineList(I)%r(K,J) ! assign position - x%states(m%LineStateIndList(I) + 3*J-3 + K-1 ) = 0.0_ReKi ! assign velocities (of zero) + x%states(m%LineStateIndList(I) + 3*J-3 + K-1 ) = 0.0_DbKi ! assign velocities (of zero) END DO END DO @@ -387,7 +387,7 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er ! initialize fairlead tension memory at zero DO J = 1,p%NFairs DO I = 1, 3 - FairTensIC(J,I) = 0.0_ReKi + FairTensIC(J,I) = 0.0_DbKi END DO END DO @@ -712,11 +712,11 @@ SUBROUTINE MD_CalcContStateDeriv( t, u, p, x, xd, z, other, m, dxdt, ErrStat, Er ! clear connection force and mass values DO L = 1, p%NConnects DO J = 1,3 - m%ConnectList(L)%Ftot(J) = 0.0_ReKi - m%ConnectList(L)%Ftot(J) = 0.0_ReKi + m%ConnectList(L)%Ftot(J) = 0.0_DbKi + m%ConnectList(L)%Ftot(J) = 0.0_DbKi DO K = 1,3 - m%ConnectList(L)%Mtot(K,J) = 0.0_ReKi - m%ConnectList(L)%Mtot(K,J) = 0.0_ReKi + m%ConnectList(L)%Mtot(K,J) = 0.0_DbKi + m%ConnectList(L)%Mtot(K,J) = 0.0_DbKi END DO END DO END DO @@ -769,33 +769,33 @@ SUBROUTINE MD_CalcContStateDeriv( t, u, p, x, xd, z, other, m, dxdt, ErrStat, Er !====================================================================== SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, AnchMtot) - Real(ReKi), INTENT( IN ) :: X(:) ! state vector, provided - Real(ReKi), INTENT( INOUT ) :: Xd(:) ! derivative of state vector, returned ! cahnged to INOUT + Real(DbKi), INTENT( IN ) :: X(:) ! state vector, provided + Real(DbKi), INTENT( INOUT ) :: Xd(:) ! derivative of state vector, returned ! cahnged to INOUT Real(DbKi), INTENT (IN) :: t ! instantaneous time TYPE(MD_Line), INTENT (INOUT) :: Line ! label for the current line, for convenience TYPE(MD_LineProp), INTENT(IN) :: LineProp ! the single line property set for the line of interest - Real(ReKi), INTENT(INOUT) :: FairFtot(:) ! total force on Connect top of line is attached to - Real(ReKi), INTENT(INOUT) :: FairMtot(:,:) ! total mass of Connect top of line is attached to - Real(ReKi), INTENT(INOUT) :: AnchFtot(:) ! total force on Connect bottom of line is attached to - Real(ReKi), INTENT(INOUT) :: AnchMtot(:,:) ! total mass of Connect bottom of line is attached to + Real(DbKi), INTENT(INOUT) :: FairFtot(:) ! total force on Connect top of line is attached to + Real(DbKi), INTENT(INOUT) :: FairMtot(:,:) ! total mass of Connect top of line is attached to + Real(DbKi), INTENT(INOUT) :: AnchFtot(:) ! total force on Connect bottom of line is attached to + Real(DbKi), INTENT(INOUT) :: AnchMtot(:,:) ! total mass of Connect bottom of line is attached to INTEGER(IntKi) :: I ! index of segments or nodes along line INTEGER(IntKi) :: J ! index INTEGER(IntKi) :: K ! index INTEGER(IntKi) :: N ! number of segments in line - Real(ReKi) :: d ! line diameter - Real(ReKi) :: rho ! line material density [kg/m^3] - Real(ReKi) :: Sum1 ! for summing squares - Real(ReKi) :: m_i ! node mass - Real(ReKi) :: v_i ! node submerged volume - Real(ReKi) :: Vi(3) ! relative water velocity at a given node - Real(ReKi) :: Vp(3) ! transverse relative water velocity component at a given node - Real(ReKi) :: Vq(3) ! tangential relative water velocity component at a given node - Real(ReKi) :: SumSqVp ! - Real(ReKi) :: SumSqVq ! - Real(ReKi) :: MagVp ! - Real(ReKi) :: MagVq ! + Real(DbKi) :: d ! line diameter + Real(DbKi) :: rho ! line material density [kg/m^3] + Real(DbKi) :: Sum1 ! for summing squares + Real(DbKi) :: m_i ! node mass + Real(DbKi) :: v_i ! node submerged volume + Real(DbKi) :: Vi(3) ! relative water velocity at a given node + Real(DbKi) :: Vp(3) ! transverse relative water velocity component at a given node + Real(DbKi) :: Vq(3) ! tangential relative water velocity component at a given node + Real(DbKi) :: SumSqVp ! + Real(DbKi) :: SumSqVq ! + Real(DbKi) :: MagVp ! + Real(DbKi) :: MagVq ! N = Line%N ! for convenience @@ -822,13 +822,13 @@ SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, An ! calculate instantaneous (stretched) segment lengths and rates << should add catch here for if lstr is ever zero DO I = 1, N - Sum1 = 0.0_ReKi + Sum1 = 0.0_DbKi DO J = 1, 3 Sum1 = Sum1 + (Line%r(J,I) - Line%r(J,I-1)) * (Line%r(J,I) - Line%r(J,I-1)) END DO Line%lstr(I) = sqrt(Sum1) ! stretched segment length - Sum1 = 0.0_ReKi + Sum1 = 0.0_DbKi DO J = 1, 3 Sum1 = Sum1 + (Line%r(J,I) - Line%r(J,I-1))*(Line%rd(J,I) - Line%rd(J,I-1)) END DO @@ -887,7 +887,7 @@ SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, An END DO ELSE DO J = 1, 3 - Line%T(J,I) = 0.0_ReKi ! cable can't "push" + Line%T(J,I) = 0.0_DbKi ! cable can't "push" END DO END if @@ -917,8 +917,8 @@ SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, An END DO ! decomponse relative flow into components - SumSqVp = 0.0_ReKi ! start sums of squares at zero - SumSqVq = 0.0_ReKi + SumSqVp = 0.0_DbKi ! start sums of squares at zero + SumSqVq = 0.0_DbKi DO J = 1, 3 Vq(J) = DOT_PRODUCT( Vi , Line%q(:,I) ) * Line%q(J,I); ! tangential relative flow component Vp(J) = Vi(J) - Vq(J) ! transverse relative flow component @@ -962,7 +962,7 @@ SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, An END IF ELSE - Line%B(3,I) = 0.0_ReKi + Line%B(3,I) = 0.0_DbKi END IF ! total forces @@ -988,7 +988,7 @@ SUBROUTINE DoLineRHS (X, Xd, t, Line, LineProp, FairFtot, FairMtot, AnchFtot, An DO J=1,3 ! calculate RHS constant (premultiplying force vector by inverse of mass matrix ... i.e. rhs = S*Forces) - Sum1 = 0.0_ReKi ! reset temporary accumulator + Sum1 = 0.0_DbKi ! reset temporary accumulator DO K = 1, 3 Sum1 = Sum1 + Line%S(K,J,I) * Line%F(K,I) ! matrix-vector multiplication [S i]{Forces i} << double check indices END DO ! K @@ -1020,8 +1020,8 @@ SUBROUTINE DoConnectRHS (X, Xd, t, Connect) ! This subroutine is for the "Connect" type of Connections only. Other types don't have their own state variables. - Real(ReKi), INTENT( IN ) :: X(:) ! state vector for this connect, provided - Real(ReKi), INTENT( OUT ) :: Xd(:) ! derivative of state vector for this connect, returned + Real(DbKi), INTENT( IN ) :: X(:) ! state vector for this connect, provided + Real(DbKi), INTENT( OUT ) :: Xd(:) ! derivative of state vector for this connect, returned Real(DbKi), INTENT (IN) :: t ! instantaneous time Type(MD_Connect), INTENT (INOUT) :: Connect ! Connect number @@ -1029,7 +1029,7 @@ SUBROUTINE DoConnectRHS (X, Xd, t, Connect) !INTEGER(IntKi) :: I ! index of segments or nodes along line INTEGER(IntKi) :: J ! index INTEGER(IntKi) :: K ! index - Real(ReKi) :: Sum1 ! for adding things + Real(DbKi) :: Sum1 ! for adding things ! When this sub is called, the force and mass contributions from the attached Lines should already have been added to ! Fto and Mtot by the Line RHS function. Also, any self weight, buoyancy, or external forcing should have already been @@ -1041,7 +1041,7 @@ SUBROUTINE DoConnectRHS (X, Xd, t, Connect) DO J = 1,3 Xd(3+J) = X(J) ! velocities - these are unused in integration - Xd(J) = 0.0_ReKi ! accelerations - these are unused in integration + Xd(J) = 0.0_DbKi ! accelerations - these are unused in integration END DO ELSE ! from state values, get r and rdot values @@ -1063,7 +1063,7 @@ SUBROUTINE DoConnectRHS (X, Xd, t, Connect) DO J = 1,3 ! RHS constant - (premultiplying force vector by inverse of mass matrix ... i.e. rhs = S*Forces - Sum1 = 0.0_ReKi ! reset accumulator + Sum1 = 0.0_DbKi ! reset accumulator DO K = 1, 3 Sum1 = Sum1 + Connect%S(K,J) * Connect%Ftot(K) ! matrix multiplication [S i]{Forces i} END DO @@ -1241,7 +1241,7 @@ SUBROUTINE TimeStep ( t, dtStep, u, utimes, p, x, xd, z, other, m, ErrStat, ErrM CALL MD_Input_ExtrapInterp(u, utimes, u_interp, t + 0.5_DbKi*dtM, ErrStat, ErrMsg) ! interpolate input mesh to correct time (t+0.5*dtM) - CALL MD_CalcContStateDeriv( (t + 0.5_ReKi*dtM), u_interp, p, x2, xd, z, other, m, dxdt, ErrStat, ErrMsg ) !called with updated states x2 and time = t + dt/2.0 + CALL MD_CalcContStateDeriv( (t + 0.5_DbKi*dtM), u_interp, p, x2, xd, z, other, m, dxdt, ErrStat, ErrMsg ) !called with updated states x2 and time = t + dt/2.0 DO J = 1, Nx x%states(J) = x%states(J) + dtM*dxdt%states(J) END DO @@ -1352,8 +1352,8 @@ SUBROUTINE SetupLine (Line, LineProp, rhoW, ErrStat, ErrMsg) ! set gravity and bottom contact forces to zero initially (because the horizontal components should remain at zero) DO J = 0,N DO K = 1,3 - Line%W(K,J) = 0.0_ReKi - Line%B(K,J) = 0.0_ReKi + Line%W(K,J) = 0.0_DbKi + Line%B(K,J) = 0.0_DbKi END DO END DO @@ -1406,22 +1406,22 @@ SUBROUTINE InitializeLine (Line, LineProp, rhoW, ErrStat, ErrMsg) INTEGER, INTENT( INOUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( INOUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - REAL(ReKi) :: COSPhi ! Cosine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) - REAL(ReKi) :: SINPhi ! Sine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) - REAL(ReKi) :: XF ! Horizontal distance between anchor and fairlead of the current mooring line (meters) - REAL(ReKi) :: ZF ! Vertical distance between anchor and fairlead of the current mooring line (meters) + REAL(DbKi) :: COSPhi ! Cosine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) + REAL(DbKi) :: SINPhi ! Sine of the angle between the xi-axis of the inertia frame and the X-axis of the local coordinate system of the current mooring line (-) + REAL(DbKi) :: XF ! Horizontal distance between anchor and fairlead of the current mooring line (meters) + REAL(DbKi) :: ZF ! Vertical distance between anchor and fairlead of the current mooring line (meters) INTEGER(4) :: I ! Generic index INTEGER(4) :: J ! Generic index INTEGER(IntKi) :: ErrStat2 ! Error status of the operation CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None - REAL(ReKi) :: WetWeight - REAL(ReKi) :: SeabedCD = 0.0_ReKi - REAL(ReKi) :: TenTol = 0.0001_ReKi - REAL(ReKi), ALLOCATABLE :: LSNodes(:) - REAL(ReKi), ALLOCATABLE :: LNodesX(:) - REAL(ReKi), ALLOCATABLE :: LNodesZ(:) + REAL(DbKi) :: WetWeight + REAL(DbKi) :: SeabedCD = 0.0_DbKi + REAL(DbKi) :: TenTol = 0.0001_DbKi + REAL(DbKi), ALLOCATABLE :: LSNodes(:) + REAL(DbKi), ALLOCATABLE :: LNodesX(:) + REAL(DbKi), ALLOCATABLE :: LNodesZ(:) INTEGER(IntKi) :: N @@ -1440,8 +1440,8 @@ SUBROUTINE InitializeLine (Line, LineProp, rhoW, ErrStat, ErrMsg) ZF = Line%r(3,N) - Line%r(3,0) IF ( XF == 0.0 ) THEN ! .TRUE. if the current mooring line is exactly vertical; thus, the solution below is ill-conditioned because the orientation is undefined; so set it such that the tensions and nodal positions are only vertical - COSPhi = 0.0_ReKi - SINPhi = 0.0_ReKi + COSPhi = 0.0_DbKi + SINPhi = 0.0_DbKi ELSE ! The current mooring line must not be vertical; use simple trigonometry COSPhi = ( Line%r(1,N) - Line%r(1,0) )/XF SINPhi = ( Line%r(2,N) - Line%r(2,0) )/XF @@ -1474,7 +1474,7 @@ SUBROUTINE InitializeLine (Line, LineProp, rhoW, ErrStat, ErrMsg) END IF ! Assign node arc length locations - LSNodes(1) = 0.0_ReKi + LSNodes(1) = 0.0_DbKi DO I=2,N LSNodes(I) = LSNodes(I-1) + Line%l(I-1) ! note: l index is because line segment indices start at 1 END DO @@ -1512,9 +1512,9 @@ SUBROUTINE InitializeLine (Line, LineProp, rhoW, ErrStat, ErrMsg) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'InitializeLine') DO J = 0,Line%N ! Loop through all nodes per line where the line position and tension can be output - Line%r(1,J) = Line%r(1,0) + (Line%r(1,N) - Line%r(1,0))*REAL(J, ReKi)/REAL(N, ReKi) - Line%r(2,J) = Line%r(2,0) + (Line%r(2,N) - Line%r(2,0))*REAL(J, ReKi)/REAL(N, ReKi) - Line%r(3,J) = Line%r(3,0) + (Line%r(3,N) - Line%r(3,0))*REAL(J, ReKi)/REAL(N, ReKi) + Line%r(1,J) = Line%r(1,0) + (Line%r(1,N) - Line%r(1,0))*REAL(J, DbKi)/REAL(N, DbKi) + Line%r(2,J) = Line%r(2,0) + (Line%r(2,N) - Line%r(2,0))*REAL(J, DbKi)/REAL(N, DbKi) + Line%r(3,J) = Line%r(3,0) + (Line%r(3,N) - Line%r(3,0))*REAL(J, DbKi)/REAL(N, DbKi) ENDDO ENDIF @@ -1571,21 +1571,21 @@ SUBROUTINE Catenary ( XF_In, ZF_In, L_In , EA_In, & INTEGER(4), INTENT(IN ) :: N ! Number of nodes where the line position and tension can be output (-) - REAL(ReKi), INTENT(IN ) :: CB_In ! Coefficient of seabed static friction drag (a negative value indicates no seabed) (-) - REAL(ReKi), INTENT(IN ) :: EA_In ! Extensional stiffness of line (N) - ! REAL(ReKi), INTENT( OUT) :: HA_In ! Effective horizontal tension in line at the anchor (N) - ! REAL(ReKi), INTENT(INOUT) :: HF_In ! Effective horizontal tension in line at the fairlead (N) - REAL(ReKi), INTENT(IN ) :: L_In ! Unstretched length of line (meters) - REAL(ReKi), INTENT(IN ) :: s_In (N) ! Unstretched arc distance along line from anchor to each node where the line position and tension can be output (meters) - ! REAL(ReKi), INTENT( OUT) :: Te_In (N) ! Effective line tensions at each node (N) - REAL(ReKi), INTENT(IN ) :: Tol_In ! Convergence tolerance within Newton-Raphson iteration specified as a fraction of tension (-) - ! REAL(ReKi), INTENT( OUT) :: VA_In ! Effective vertical tension in line at the anchor (N) - ! REAL(ReKi), INTENT(INOUT) :: VF_In ! Effective vertical tension in line at the fairlead (N) - REAL(ReKi), INTENT(IN ) :: W_In ! Weight of line in fluid per unit length (N/m) - REAL(ReKi), INTENT( OUT) :: X_In (N) ! Horizontal locations of each line node relative to the anchor (meters) - REAL(ReKi), INTENT(IN ) :: XF_In ! Horizontal distance between anchor and fairlead (meters) - REAL(ReKi), INTENT( OUT) :: Z_In (N) ! Vertical locations of each line node relative to the anchor (meters) - REAL(ReKi), INTENT(IN ) :: ZF_In ! Vertical distance between anchor and fairlead (meters) + REAL(DbKi), INTENT(IN ) :: CB_In ! Coefficient of seabed static friction drag (a negative value indicates no seabed) (-) + REAL(DbKi), INTENT(IN ) :: EA_In ! Extensional stiffness of line (N) + ! REAL(DbKi), INTENT( OUT) :: HA_In ! Effective horizontal tension in line at the anchor (N) + ! REAL(DbKi), INTENT(INOUT) :: HF_In ! Effective horizontal tension in line at the fairlead (N) + REAL(DbKi), INTENT(IN ) :: L_In ! Unstretched length of line (meters) + REAL(DbKi), INTENT(IN ) :: s_In (N) ! Unstretched arc distance along line from anchor to each node where the line position and tension can be output (meters) + ! REAL(DbKi), INTENT( OUT) :: Te_In (N) ! Effective line tensions at each node (N) + REAL(DbKi), INTENT(IN ) :: Tol_In ! Convergence tolerance within Newton-Raphson iteration specified as a fraction of tension (-) + ! REAL(DbKi), INTENT( OUT) :: VA_In ! Effective vertical tension in line at the anchor (N) + ! REAL(DbKi), INTENT(INOUT) :: VF_In ! Effective vertical tension in line at the fairlead (N) + REAL(DbKi), INTENT(IN ) :: W_In ! Weight of line in fluid per unit length (N/m) + REAL(DbKi), INTENT( OUT) :: X_In (N) ! Horizontal locations of each line node relative to the anchor (meters) + REAL(DbKi), INTENT(IN ) :: XF_In ! Horizontal distance between anchor and fairlead (meters) + REAL(DbKi), INTENT( OUT) :: Z_In (N) ! Vertical locations of each line node relative to the anchor (meters) + REAL(DbKi), INTENT(IN ) :: ZF_In ! Vertical distance between anchor and fairlead (meters) INTEGER, INTENT( OUT ) :: ErrStat ! returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if ErrStat /= ErrID_None @@ -2087,13 +2087,13 @@ SUBROUTINE Catenary ( XF_In, ZF_In, L_In , EA_In, & ! convert the output arguments back into the default precision for real ! numbers: - !HA_In = REAL( HA , ReKi ) !mth: for this I only care about returning node positions - !HF_In = REAL( HF , ReKi ) - !Te_In(:) = REAL( Te(:), ReKi ) - !VA_In = REAL( VA , ReKi ) - !VF_In = REAL( VF , ReKi ) - X_In (:) = REAL( X (:), ReKi ) - Z_In (:) = REAL( Z (:), ReKi ) + !HA_In = REAL( HA , DbKi ) !mth: for this I only care about returning node positions + !HF_In = REAL( HF , DbKi ) + !Te_In(:) = REAL( Te(:), DbKi ) + !VA_In = REAL( VA , DbKi ) + !VF_In = REAL( VF , DbKi ) + X_In (:) = REAL( X (:), DbKi ) + Z_In (:) = REAL( Z (:), DbKi ) END SUBROUTINE Catenary !======================================================================= @@ -2111,16 +2111,16 @@ END SUBROUTINE InitializeLine ! return unit vector (u) in direction from r1 to r2 !======================================================================= SUBROUTINE UnitVector( u, r1, r2 ) - REAL(ReKi), INTENT(OUT) :: u(:) - REAL(ReKi), INTENT(IN) :: r1(:) - REAL(ReKi), INTENT(IN) :: r2(:) + REAL(DbKi), INTENT(OUT) :: u(:) + REAL(DbKi), INTENT(IN) :: r1(:) + REAL(DbKi), INTENT(IN) :: r2(:) - REAL(ReKi) :: Length + REAL(DbKi) :: Length u = r2 - r1 Length = TwoNorm(u) - if ( .NOT. EqualRealNos(length, 0.0_ReKi ) ) THEN + if ( .NOT. EqualRealNos(length, 0.0_DbKi ) ) THEN u = u / Length END IF @@ -2131,11 +2131,11 @@ END SUBROUTINE UnitVector !compute the inverse of a 3-by-3 matrix m !======================================================================= SUBROUTINE Inverse3by3( Minv, M ) - Real(ReKi), INTENT(OUT) :: Minv(:,:) ! returned inverse matrix - Real(ReKi), INTENT(IN) :: M(:,:) ! inputted matrix + Real(DbKi), INTENT(OUT) :: Minv(:,:) ! returned inverse matrix + Real(DbKi), INTENT(IN) :: M(:,:) ! inputted matrix - Real(ReKi) :: det ! the determinant - Real(ReKi) :: invdet ! inverse of the determinant + Real(DbKi) :: det ! the determinant + Real(DbKi) :: invdet ! inverse of the determinant det = M(1, 1) * (M(2, 2) * M(3, 3) - M(3, 2) * M(2, 3)) - & M(1, 2) * (M(2, 1) * M(3, 3) - M(2, 3) * M(3, 1)) + & diff --git a/modules/moordyn/src/MoorDyn_IO.f90 b/modules/moordyn/src/MoorDyn_IO.f90 index aca3d5755..559828e3d 100644 --- a/modules/moordyn/src/MoorDyn_IO.f90 +++ b/modules/moordyn/src/MoorDyn_IO.f90 @@ -1172,7 +1172,7 @@ SUBROUTINE MDIO_WriteOutputs( Time, p, m, y, ErrStat, ErrMsg ) CASE (FZ) y%WriteOutput(I) = m%ConnectList(p%OutParam(I)%ObjID)%Ftot(3) ! total force in z CASE DEFAULT - y%WriteOutput(I) = 0.0_ReKi + y%WriteOutput(I) = 0.0_DbKi ErrStat = ErrID_Warn ErrMsg = ' Unsupported output quantity '//TRIM(Num2Lstr(p%OutParam(I)%QType))//' requested from Connection '//TRIM(Num2Lstr(p%OutParam(I)%ObjID))//'.' END SELECT @@ -1195,13 +1195,13 @@ SUBROUTINE MDIO_WriteOutputs( Time, p, m, y, ErrStat, ErrMsg ) CASE (Ten) y%WriteOutput(I) = TwoNorm(m%LineList(p%OutParam(I)%ObjID)%T(:,p%OutParam(I)%NodeID)) ! this is actually the segment tension ( 1 < NodeID < N ) Should deal with properly! CASE DEFAULT - y%WriteOutput(I) = 0.0_ReKi + y%WriteOutput(I) = 0.0_DbKi ErrStat = ErrID_Warn ErrMsg = ' Unsupported output quantity '//TRIM(Num2Lstr(p%OutParam(I)%QType))//' requested from Line '//TRIM(Num2Lstr(p%OutParam(I)%ObjID))//'.' END SELECT ELSE ! it must be an invalid output, so write zero - y%WriteOutput(I) = 0.0_ReKi + y%WriteOutput(I) = 0.0_DbKi END IF @@ -1210,7 +1210,7 @@ SUBROUTINE MDIO_WriteOutputs( Time, p, m, y, ErrStat, ErrMsg ) ! Write the output parameters to the file - Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts))//'(A1,e10.4))' ! should evenutally use user specified format? + Frmt = '(F10.4,'//TRIM(Int2LStr(p%NumOuts))//'(A1,e12.6))' ! should evenutally use user specified format? WRITE(p%MDUnOut,Frmt) Time, ( p%Delim, y%WriteOutput(I), I=1,p%NumOuts ) @@ -1229,7 +1229,7 @@ SUBROUTINE MDIO_WriteOutputs( Time, p, m, y, ErrStat, ErrMsg ) LineNumOuts = 3*(m%LineList(I)%N + 1)*SUM(m%LineList(I)%OutFlagList(2:5)) + m%LineList(I)%N*SUM(m%LineList(I)%OutFlagList(6:9)) - Frmt = '(F10.4,'//TRIM(Int2LStr(LineNumOuts))//'(A1,e10.4))' ! should evenutally use user specified format? + Frmt = '(F10.4,'//TRIM(Int2LStr(LineNumOuts))//'(A1,e12.6))' ! should evenutally use user specified format? L = 1 ! start of index of line output file at first entry diff --git a/modules/moordyn/src/MoorDyn_Registry.txt b/modules/moordyn/src/MoorDyn_Registry.txt index 35e63e8cf..2d35146d8 100644 --- a/modules/moordyn/src/MoorDyn_Registry.txt +++ b/modules/moordyn/src/MoorDyn_Registry.txt @@ -33,14 +33,14 @@ typedef ^ ^ CHARACTER(ChanLen) OutList {: # line properties from line dictionary input typedef ^ MD_LineProp IntKi IdNum - - - "integer identifier of this set of line properties" typedef ^ ^ CHARACTER(10) name - - - "name/identifier of this set of line properties" -typedef ^ ^ ReKi d - - - "volume-equivalent diameter" "[m]" -typedef ^ ^ ReKi w - - - "per-length weight in air" "[kg/m]" -typedef ^ ^ ReKi EA - - - "stiffness" "[N]" -typedef ^ ^ ReKi BA - - - "internal damping coefficient times area" "[N-s]" -typedef ^ ^ ReKi Can - - - "transverse added mass coefficient" -typedef ^ ^ ReKi Cat - - - "tangential added mass coefficient" -typedef ^ ^ ReKi Cdn - - - "transverse drag coefficient" -typedef ^ ^ ReKi Cdt - - - "tangential drag coefficient" +typedef ^ ^ DbKi d - - - "volume-equivalent diameter" "[m]" +typedef ^ ^ DbKi w - - - "per-length weight in air" "[kg/m]" +typedef ^ ^ DbKi EA - - - "stiffness" "[N]" +typedef ^ ^ DbKi BA - - - "internal damping coefficient times area" "[N-s]" +typedef ^ ^ DbKi Can - - - "transverse added mass coefficient" +typedef ^ ^ DbKi Cat - - - "tangential added mass coefficient" +typedef ^ ^ DbKi Cdn - - - "transverse drag coefficient" +typedef ^ ^ DbKi Cdt - - - "tangential drag coefficient" # this is the Connection type, which holds data for each connection object typedef ^ MD_Connect IntKi IdNum - - - "integer identifier of this Connection" @@ -48,21 +48,21 @@ typedef ^ ^ CHARACTER(10) type - typedef ^ ^ IntKi TypeNum - - - "integer identifying the type. 0=fixed, 1=vessel, 2=connect" typedef ^ ^ IntKi AttachedFairs {:} - - "list of IdNums of connected Line tops" typedef ^ ^ IntKi AttachedAnchs {:} - - "list of IdNums of connected Line bottoms" -typedef ^ ^ ReKi conX - - - "" -typedef ^ ^ ReKi conY - - - "" -typedef ^ ^ ReKi conZ - - - "" -typedef ^ ^ ReKi conM - - - "" -typedef ^ ^ ReKi conV - - - "" -typedef ^ ^ ReKi conFX - - - "" -typedef ^ ^ ReKi conFY - - - "" -typedef ^ ^ ReKi conFZ - - - "" -typedef ^ ^ ReKi conCa - - - "added mass coefficient of connection point" "-" -typedef ^ ^ ReKi conCdA - - - "product of drag force and frontal area of connection point" "[m^2]" -typedef ^ ^ ReKi Ftot {3} - - "total force on node" -typedef ^ ^ ReKi Mtot {3}{3} - - "node mass matrix, from attached lines" -typedef ^ ^ ReKi S {3}{3} - - "inverse mass matrix" "[kg]" -typedef ^ ^ ReKi r {3} - - "position" -typedef ^ ^ ReKi rd {3} - - "velocity" +typedef ^ ^ DbKi conX - - - "" +typedef ^ ^ DbKi conY - - - "" +typedef ^ ^ DbKi conZ - - - "" +typedef ^ ^ DbKi conM - - - "" +typedef ^ ^ DbKi conV - - - "" +typedef ^ ^ DbKi conFX - - - "" +typedef ^ ^ DbKi conFY - - - "" +typedef ^ ^ DbKi conFZ - - - "" +typedef ^ ^ DbKi conCa - - - "added mass coefficient of connection point" "-" +typedef ^ ^ DbKi conCdA - - - "product of drag force and frontal area of connection point" "[m^2]" +typedef ^ ^ DbKi Ftot {3} - - "total force on node" +typedef ^ ^ DbKi Mtot {3}{3} - - "node mass matrix, from attached lines" +typedef ^ ^ DbKi S {3}{3} - - "inverse mass matrix" "[kg]" +typedef ^ ^ DbKi r {3} - - "position" +typedef ^ ^ DbKi rd {3} - - "velocity" # this is the Line type, which holds data for each line object typedef ^ MD_Line IntKi IdNum - - - "integer identifier of this Line" @@ -72,26 +72,26 @@ typedef ^ ^ IntKi FairConnect - typedef ^ ^ IntKi AnchConnect - - - "IdNum of Connection at anchor" typedef ^ ^ IntKi PropsIdNum - - - "the IdNum of the associated line properties" - typedef ^ ^ IntKi N - - - "The number of elements in the line" - -typedef ^ ^ ReKi UnstrLen - - - "unstretched length of the line" - -typedef ^ ^ ReKi BA - - - "internal damping coefficient times area for this line only" "[N-s]" -typedef ^ ^ ReKi r {:}{:} - - "node positions" - -typedef ^ ^ ReKi rd {:}{:} - - "node velocities" - -typedef ^ ^ ReKi q {:}{:} - - "node tangent vectors" - -typedef ^ ^ ReKi l {:} - - "segment unstretched length" "[m]" -typedef ^ ^ ReKi lstr {:} - - "segment stretched length" "[m]" -typedef ^ ^ ReKi lstrd {:} - - "segment change in stretched length" "[m/s]" -typedef ^ ^ ReKi V {:} - - "segment volume" "[m^3]" -typedef ^ ^ ReKi T {:}{:} - - "segment tension vectors" "[N]" -typedef ^ ^ ReKi Td {:}{:} - - "segment internal damping force vectors" "[N]" -typedef ^ ^ ReKi W {:}{:} - - "weight/buoyancy vectors" "[N]" -typedef ^ ^ ReKi Dp {:}{:} - - "node drag (transverse)" "[N]" -typedef ^ ^ ReKi Dq {:}{:} - - "node drag (axial)" "[N]" -typedef ^ ^ ReKi Ap {:}{:} - - "node added mass forcing (transverse)" "[N]" -typedef ^ ^ ReKi Aq {:}{:} - - "node added mass forcing (axial)" "[N]" -typedef ^ ^ ReKi B {:}{:} - - "node bottom contact force" "[N]" -typedef ^ ^ ReKi F {:}{:} - - "total force on node" "[N]" -typedef ^ ^ ReKi S {:}{:}{:} - - "node inverse mass matrix" "[kg]" -typedef ^ ^ ReKi M {:}{:}{:} - - "node mass matrix" "[kg]" +typedef ^ ^ DbKi UnstrLen - - - "unstretched length of the line" - +typedef ^ ^ DbKi BA - - - "internal damping coefficient times area for this line only" "[N-s]" +typedef ^ ^ DbKi r {:}{:} - - "node positions" - +typedef ^ ^ DbKi rd {:}{:} - - "node velocities" - +typedef ^ ^ DbKi q {:}{:} - - "node tangent vectors" - +typedef ^ ^ DbKi l {:} - - "segment unstretched length" "[m]" +typedef ^ ^ DbKi lstr {:} - - "segment stretched length" "[m]" +typedef ^ ^ DbKi lstrd {:} - - "segment change in stretched length" "[m/s]" +typedef ^ ^ DbKi V {:} - - "segment volume" "[m^3]" +typedef ^ ^ DbKi T {:}{:} - - "segment tension vectors" "[N]" +typedef ^ ^ DbKi Td {:}{:} - - "segment internal damping force vectors" "[N]" +typedef ^ ^ DbKi W {:}{:} - - "weight/buoyancy vectors" "[N]" +typedef ^ ^ DbKi Dp {:}{:} - - "node drag (transverse)" "[N]" +typedef ^ ^ DbKi Dq {:}{:} - - "node drag (axial)" "[N]" +typedef ^ ^ DbKi Ap {:}{:} - - "node added mass forcing (transverse)" "[N]" +typedef ^ ^ DbKi Aq {:}{:} - - "node added mass forcing (axial)" "[N]" +typedef ^ ^ DbKi B {:}{:} - - "node bottom contact force" "[N]" +typedef ^ ^ DbKi F {:}{:} - - "total force on node" "[N]" +typedef ^ ^ DbKi S {:}{:}{:} - - "node inverse mass matrix" "[kg]" +typedef ^ ^ DbKi M {:}{:}{:} - - "node mass matrix" "[kg]" typedef ^ ^ IntKi LineUnOut - - - "unit number of line output file" typedef ^ ^ ReKi LineWrOutput {:} - - "one row of output data for this line" @@ -113,7 +113,7 @@ typedef ^ ^ ProgDesc Ver - " ## ============================== Define Continuous states here: ===================================================================================================================================== -typedef ^ ContinuousStateType ReKi states {:} "" - "full list of node coordinates and velocities" "[m] or [m/s]" +typedef ^ ContinuousStateType DbKi states {:} "" - "full list of node coordinates and velocities" "[m] or [m/s]" ## ============================== Define Discrete states here: ===================================================================================================================================== diff --git a/modules/moordyn/src/MoorDyn_Types.f90 b/modules/moordyn/src/MoorDyn_Types.f90 index d9e507a62..138ab41c0 100644 --- a/modules/moordyn/src/MoorDyn_Types.f90 +++ b/modules/moordyn/src/MoorDyn_Types.f90 @@ -53,14 +53,14 @@ MODULE MoorDyn_Types TYPE, PUBLIC :: MD_LineProp INTEGER(IntKi) :: IdNum !< integer identifier of this set of line properties [-] CHARACTER(10) :: name !< name/identifier of this set of line properties [-] - REAL(ReKi) :: d !< volume-equivalent diameter [[m]] - REAL(ReKi) :: w !< per-length weight in air [[kg/m]] - REAL(ReKi) :: EA !< stiffness [[N]] - REAL(ReKi) :: BA !< internal damping coefficient times area [[N-s]] - REAL(ReKi) :: Can !< transverse added mass coefficient [-] - REAL(ReKi) :: Cat !< tangential added mass coefficient [-] - REAL(ReKi) :: Cdn !< transverse drag coefficient [-] - REAL(ReKi) :: Cdt !< tangential drag coefficient [-] + REAL(DbKi) :: d !< volume-equivalent diameter [[m]] + REAL(DbKi) :: w !< per-length weight in air [[kg/m]] + REAL(DbKi) :: EA !< stiffness [[N]] + REAL(DbKi) :: BA !< internal damping coefficient times area [[N-s]] + REAL(DbKi) :: Can !< transverse added mass coefficient [-] + REAL(DbKi) :: Cat !< tangential added mass coefficient [-] + REAL(DbKi) :: Cdn !< transverse drag coefficient [-] + REAL(DbKi) :: Cdt !< tangential drag coefficient [-] END TYPE MD_LineProp ! ======================= ! ========= MD_Connect ======= @@ -70,21 +70,21 @@ MODULE MoorDyn_Types INTEGER(IntKi) :: TypeNum !< integer identifying the type. 0=fixed, 1=vessel, 2=connect [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AttachedFairs !< list of IdNums of connected Line tops [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: AttachedAnchs !< list of IdNums of connected Line bottoms [-] - REAL(ReKi) :: conX !< [-] - REAL(ReKi) :: conY !< [-] - REAL(ReKi) :: conZ !< [-] - REAL(ReKi) :: conM !< [-] - REAL(ReKi) :: conV !< [-] - REAL(ReKi) :: conFX !< [-] - REAL(ReKi) :: conFY !< [-] - REAL(ReKi) :: conFZ !< [-] - REAL(ReKi) :: conCa !< added mass coefficient of connection point [-] - REAL(ReKi) :: conCdA !< product of drag force and frontal area of connection point [[m^2]] - REAL(ReKi) , DIMENSION(1:3) :: Ftot !< total force on node [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: Mtot !< node mass matrix, from attached lines [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: S !< inverse mass matrix [[kg]] - REAL(ReKi) , DIMENSION(1:3) :: r !< position [-] - REAL(ReKi) , DIMENSION(1:3) :: rd !< velocity [-] + REAL(DbKi) :: conX !< [-] + REAL(DbKi) :: conY !< [-] + REAL(DbKi) :: conZ !< [-] + REAL(DbKi) :: conM !< [-] + REAL(DbKi) :: conV !< [-] + REAL(DbKi) :: conFX !< [-] + REAL(DbKi) :: conFY !< [-] + REAL(DbKi) :: conFZ !< [-] + REAL(DbKi) :: conCa !< added mass coefficient of connection point [-] + REAL(DbKi) :: conCdA !< product of drag force and frontal area of connection point [[m^2]] + REAL(DbKi) , DIMENSION(1:3) :: Ftot !< total force on node [-] + REAL(DbKi) , DIMENSION(1:3,1:3) :: Mtot !< node mass matrix, from attached lines [-] + REAL(DbKi) , DIMENSION(1:3,1:3) :: S !< inverse mass matrix [[kg]] + REAL(DbKi) , DIMENSION(1:3) :: r !< position [-] + REAL(DbKi) , DIMENSION(1:3) :: rd !< velocity [-] END TYPE MD_Connect ! ======================= ! ========= MD_Line ======= @@ -96,26 +96,26 @@ MODULE MoorDyn_Types INTEGER(IntKi) :: AnchConnect !< IdNum of Connection at anchor [-] INTEGER(IntKi) :: PropsIdNum !< the IdNum of the associated line properties [-] INTEGER(IntKi) :: N !< The number of elements in the line [-] - REAL(ReKi) :: UnstrLen !< unstretched length of the line [-] - REAL(ReKi) :: BA !< internal damping coefficient times area for this line only [[N-s]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: r !< node positions [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rd !< node velocities [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: q !< node tangent vectors [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: l !< segment unstretched length [[m]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstr !< segment stretched length [[m]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstrd !< segment change in stretched length [[m/s]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V !< segment volume [[m^3]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T !< segment tension vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Td !< segment internal damping force vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: W !< weight/buoyancy vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dp !< node drag (transverse) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dq !< node drag (axial) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Ap !< node added mass forcing (transverse) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Aq !< node added mass forcing (axial) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< node bottom contact force [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F !< total force on node [[N]] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: S !< node inverse mass matrix [[kg]] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: M !< node mass matrix [[kg]] + REAL(DbKi) :: UnstrLen !< unstretched length of the line [-] + REAL(DbKi) :: BA !< internal damping coefficient times area for this line only [[N-s]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: r !< node positions [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: rd !< node velocities [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: q !< node tangent vectors [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: l !< segment unstretched length [[m]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: lstr !< segment stretched length [[m]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: lstrd !< segment change in stretched length [[m/s]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: V !< segment volume [[m^3]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: T !< segment tension vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Td !< segment internal damping force vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: W !< weight/buoyancy vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Dp !< node drag (transverse) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Dq !< node drag (axial) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Ap !< node added mass forcing (transverse) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Aq !< node added mass forcing (axial) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: B !< node bottom contact force [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: F !< total force on node [[N]] + REAL(DbKi) , DIMENSION(:,:,:), ALLOCATABLE :: S !< node inverse mass matrix [[kg]] + REAL(DbKi) , DIMENSION(:,:,:), ALLOCATABLE :: M !< node mass matrix [[kg]] INTEGER(IntKi) :: LineUnOut !< unit number of line output file [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineWrOutput !< one row of output data for this line [-] END TYPE MD_Line @@ -139,7 +139,7 @@ MODULE MoorDyn_Types ! ======================= ! ========= MD_ContinuousStateType ======= TYPE, PUBLIC :: MD_ContinuousStateType - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: states !< full list of node coordinates and velocities [[m] or [m/s]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: states !< full list of node coordinates and velocities [[m] or [m/s]] END TYPE MD_ContinuousStateType ! ======================= ! ========= MD_DiscreteStateType ======= @@ -538,14 +538,14 @@ SUBROUTINE MD_PackLineProp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! IdNum Int_BufSz = Int_BufSz + 1*LEN(InData%name) ! name - Re_BufSz = Re_BufSz + 1 ! d - Re_BufSz = Re_BufSz + 1 ! w - Re_BufSz = Re_BufSz + 1 ! EA - Re_BufSz = Re_BufSz + 1 ! BA - Re_BufSz = Re_BufSz + 1 ! Can - Re_BufSz = Re_BufSz + 1 ! Cat - Re_BufSz = Re_BufSz + 1 ! Cdn - Re_BufSz = Re_BufSz + 1 ! Cdt + Db_BufSz = Db_BufSz + 1 ! d + Db_BufSz = Db_BufSz + 1 ! w + Db_BufSz = Db_BufSz + 1 ! EA + Db_BufSz = Db_BufSz + 1 ! BA + Db_BufSz = Db_BufSz + 1 ! Can + Db_BufSz = Db_BufSz + 1 ! Cat + Db_BufSz = Db_BufSz + 1 ! Cdn + Db_BufSz = Db_BufSz + 1 ! Cdt IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -579,22 +579,22 @@ SUBROUTINE MD_PackLineProp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, IntKiBuf(Int_Xferred) = ICHAR(InData%name(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I - ReKiBuf(Re_Xferred) = InData%d - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%w - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%EA - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%BA - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Can - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cat - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cdn - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Cdt - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%d + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%w + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%EA + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%BA + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Can + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Cat + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Cdn + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Cdt + Db_Xferred = Db_Xferred + 1 END SUBROUTINE MD_PackLineProp SUBROUTINE MD_UnPackLineProp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -629,22 +629,22 @@ SUBROUTINE MD_UnPackLineProp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM OutData%name(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I - OutData%d = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%w = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%EA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%BA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Can = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Cat = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Cdn = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Cdt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%d = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%w = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%EA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%BA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Can = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Cat = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Cdn = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%Cdt = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END SUBROUTINE MD_UnPackLineProp SUBROUTINE MD_CopyConnect( SrcConnectData, DstConnectData, CtrlCode, ErrStat, ErrMsg ) @@ -772,21 +772,21 @@ SUBROUTINE MD_PackConnect( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*1 ! AttachedAnchs upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%AttachedAnchs) ! AttachedAnchs END IF - Re_BufSz = Re_BufSz + 1 ! conX - Re_BufSz = Re_BufSz + 1 ! conY - Re_BufSz = Re_BufSz + 1 ! conZ - Re_BufSz = Re_BufSz + 1 ! conM - Re_BufSz = Re_BufSz + 1 ! conV - Re_BufSz = Re_BufSz + 1 ! conFX - Re_BufSz = Re_BufSz + 1 ! conFY - Re_BufSz = Re_BufSz + 1 ! conFZ - Re_BufSz = Re_BufSz + 1 ! conCa - Re_BufSz = Re_BufSz + 1 ! conCdA - Re_BufSz = Re_BufSz + SIZE(InData%Ftot) ! Ftot - Re_BufSz = Re_BufSz + SIZE(InData%Mtot) ! Mtot - Re_BufSz = Re_BufSz + SIZE(InData%S) ! S - Re_BufSz = Re_BufSz + SIZE(InData%r) ! r - Re_BufSz = Re_BufSz + SIZE(InData%rd) ! rd + Db_BufSz = Db_BufSz + 1 ! conX + Db_BufSz = Db_BufSz + 1 ! conY + Db_BufSz = Db_BufSz + 1 ! conZ + Db_BufSz = Db_BufSz + 1 ! conM + Db_BufSz = Db_BufSz + 1 ! conV + Db_BufSz = Db_BufSz + 1 ! conFX + Db_BufSz = Db_BufSz + 1 ! conFY + Db_BufSz = Db_BufSz + 1 ! conFZ + Db_BufSz = Db_BufSz + 1 ! conCa + Db_BufSz = Db_BufSz + 1 ! conCdA + Db_BufSz = Db_BufSz + SIZE(InData%Ftot) ! Ftot + Db_BufSz = Db_BufSz + SIZE(InData%Mtot) ! Mtot + Db_BufSz = Db_BufSz + SIZE(InData%S) ! S + Db_BufSz = Db_BufSz + SIZE(InData%r) ! r + Db_BufSz = Db_BufSz + SIZE(InData%rd) ! rd IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -852,49 +852,49 @@ SUBROUTINE MD_PackConnect( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_Xferred = Int_Xferred + 1 END DO END IF - ReKiBuf(Re_Xferred) = InData%conX - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conY - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conZ - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conM - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conV - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conFX - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conFY - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conFZ - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conCa - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%conCdA - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conX + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conY + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conZ + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conM + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conV + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conFX + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conFY + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conFZ + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conCa + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%conCdA + Db_Xferred = Db_Xferred + 1 DO i1 = LBOUND(InData%Ftot,1), UBOUND(InData%Ftot,1) - ReKiBuf(Re_Xferred) = InData%Ftot(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Ftot(i1) + Db_Xferred = Db_Xferred + 1 END DO DO i2 = LBOUND(InData%Mtot,2), UBOUND(InData%Mtot,2) DO i1 = LBOUND(InData%Mtot,1), UBOUND(InData%Mtot,1) - ReKiBuf(Re_Xferred) = InData%Mtot(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Mtot(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO DO i2 = LBOUND(InData%S,2), UBOUND(InData%S,2) DO i1 = LBOUND(InData%S,1), UBOUND(InData%S,1) - ReKiBuf(Re_Xferred) = InData%S(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%S(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO DO i1 = LBOUND(InData%r,1), UBOUND(InData%r,1) - ReKiBuf(Re_Xferred) = InData%r(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%r(i1) + Db_Xferred = Db_Xferred + 1 END DO DO i1 = LBOUND(InData%rd,1), UBOUND(InData%rd,1) - ReKiBuf(Re_Xferred) = InData%rd(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%rd(i1) + Db_Xferred = Db_Xferred + 1 END DO END SUBROUTINE MD_PackConnect @@ -970,31 +970,31 @@ SUBROUTINE MD_UnPackConnect( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs Int_Xferred = Int_Xferred + 1 END DO END IF - OutData%conX = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conY = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conZ = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conM = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conV = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conFX = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conFY = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conFZ = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conCa = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%conCdA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%conX = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conY = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conZ = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conM = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conV = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conFX = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conFY = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conFZ = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conCa = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%conCdA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 i1_l = LBOUND(OutData%Ftot,1) i1_u = UBOUND(OutData%Ftot,1) DO i1 = LBOUND(OutData%Ftot,1), UBOUND(OutData%Ftot,1) - OutData%Ftot(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Ftot(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO i1_l = LBOUND(OutData%Mtot,1) i1_u = UBOUND(OutData%Mtot,1) @@ -1002,8 +1002,8 @@ SUBROUTINE MD_UnPackConnect( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs i2_u = UBOUND(OutData%Mtot,2) DO i2 = LBOUND(OutData%Mtot,2), UBOUND(OutData%Mtot,2) DO i1 = LBOUND(OutData%Mtot,1), UBOUND(OutData%Mtot,1) - OutData%Mtot(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Mtot(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO i1_l = LBOUND(OutData%S,1) @@ -1012,21 +1012,21 @@ SUBROUTINE MD_UnPackConnect( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs i2_u = UBOUND(OutData%S,2) DO i2 = LBOUND(OutData%S,2), UBOUND(OutData%S,2) DO i1 = LBOUND(OutData%S,1), UBOUND(OutData%S,1) - OutData%S(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%S(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO i1_l = LBOUND(OutData%r,1) i1_u = UBOUND(OutData%r,1) DO i1 = LBOUND(OutData%r,1), UBOUND(OutData%r,1) - OutData%r(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%r(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO i1_l = LBOUND(OutData%rd,1) i1_u = UBOUND(OutData%rd,1) DO i1 = LBOUND(OutData%rd,1), UBOUND(OutData%rd,1) - OutData%rd(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%rd(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END SUBROUTINE MD_UnPackConnect @@ -1429,97 +1429,97 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 1 ! AnchConnect Int_BufSz = Int_BufSz + 1 ! PropsIdNum Int_BufSz = Int_BufSz + 1 ! N - Re_BufSz = Re_BufSz + 1 ! UnstrLen - Re_BufSz = Re_BufSz + 1 ! BA + Db_BufSz = Db_BufSz + 1 ! UnstrLen + Db_BufSz = Db_BufSz + 1 ! BA Int_BufSz = Int_BufSz + 1 ! r allocated yes/no IF ( ALLOCATED(InData%r) ) THEN Int_BufSz = Int_BufSz + 2*2 ! r upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%r) ! r + Db_BufSz = Db_BufSz + SIZE(InData%r) ! r END IF Int_BufSz = Int_BufSz + 1 ! rd allocated yes/no IF ( ALLOCATED(InData%rd) ) THEN Int_BufSz = Int_BufSz + 2*2 ! rd upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%rd) ! rd + Db_BufSz = Db_BufSz + SIZE(InData%rd) ! rd END IF Int_BufSz = Int_BufSz + 1 ! q allocated yes/no IF ( ALLOCATED(InData%q) ) THEN Int_BufSz = Int_BufSz + 2*2 ! q upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%q) ! q + Db_BufSz = Db_BufSz + SIZE(InData%q) ! q END IF Int_BufSz = Int_BufSz + 1 ! l allocated yes/no IF ( ALLOCATED(InData%l) ) THEN Int_BufSz = Int_BufSz + 2*1 ! l upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%l) ! l + Db_BufSz = Db_BufSz + SIZE(InData%l) ! l END IF Int_BufSz = Int_BufSz + 1 ! lstr allocated yes/no IF ( ALLOCATED(InData%lstr) ) THEN Int_BufSz = Int_BufSz + 2*1 ! lstr upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%lstr) ! lstr + Db_BufSz = Db_BufSz + SIZE(InData%lstr) ! lstr END IF Int_BufSz = Int_BufSz + 1 ! lstrd allocated yes/no IF ( ALLOCATED(InData%lstrd) ) THEN Int_BufSz = Int_BufSz + 2*1 ! lstrd upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%lstrd) ! lstrd + Db_BufSz = Db_BufSz + SIZE(InData%lstrd) ! lstrd END IF Int_BufSz = Int_BufSz + 1 ! V allocated yes/no IF ( ALLOCATED(InData%V) ) THEN Int_BufSz = Int_BufSz + 2*1 ! V upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%V) ! V + Db_BufSz = Db_BufSz + SIZE(InData%V) ! V END IF Int_BufSz = Int_BufSz + 1 ! T allocated yes/no IF ( ALLOCATED(InData%T) ) THEN Int_BufSz = Int_BufSz + 2*2 ! T upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%T) ! T + Db_BufSz = Db_BufSz + SIZE(InData%T) ! T END IF Int_BufSz = Int_BufSz + 1 ! Td allocated yes/no IF ( ALLOCATED(InData%Td) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Td upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Td) ! Td + Db_BufSz = Db_BufSz + SIZE(InData%Td) ! Td END IF Int_BufSz = Int_BufSz + 1 ! W allocated yes/no IF ( ALLOCATED(InData%W) ) THEN Int_BufSz = Int_BufSz + 2*2 ! W upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%W) ! W + Db_BufSz = Db_BufSz + SIZE(InData%W) ! W END IF Int_BufSz = Int_BufSz + 1 ! Dp allocated yes/no IF ( ALLOCATED(InData%Dp) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Dp upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Dp) ! Dp + Db_BufSz = Db_BufSz + SIZE(InData%Dp) ! Dp END IF Int_BufSz = Int_BufSz + 1 ! Dq allocated yes/no IF ( ALLOCATED(InData%Dq) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Dq upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Dq) ! Dq + Db_BufSz = Db_BufSz + SIZE(InData%Dq) ! Dq END IF Int_BufSz = Int_BufSz + 1 ! Ap allocated yes/no IF ( ALLOCATED(InData%Ap) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Ap upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Ap) ! Ap + Db_BufSz = Db_BufSz + SIZE(InData%Ap) ! Ap END IF Int_BufSz = Int_BufSz + 1 ! Aq allocated yes/no IF ( ALLOCATED(InData%Aq) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Aq upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Aq) ! Aq + Db_BufSz = Db_BufSz + SIZE(InData%Aq) ! Aq END IF Int_BufSz = Int_BufSz + 1 ! B allocated yes/no IF ( ALLOCATED(InData%B) ) THEN Int_BufSz = Int_BufSz + 2*2 ! B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%B) ! B + Db_BufSz = Db_BufSz + SIZE(InData%B) ! B END IF Int_BufSz = Int_BufSz + 1 ! F allocated yes/no IF ( ALLOCATED(InData%F) ) THEN Int_BufSz = Int_BufSz + 2*2 ! F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + Db_BufSz = Db_BufSz + SIZE(InData%F) ! F END IF Int_BufSz = Int_BufSz + 1 ! S allocated yes/no IF ( ALLOCATED(InData%S) ) THEN Int_BufSz = Int_BufSz + 2*3 ! S upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%S) ! S + Db_BufSz = Db_BufSz + SIZE(InData%S) ! S END IF Int_BufSz = Int_BufSz + 1 ! M allocated yes/no IF ( ALLOCATED(InData%M) ) THEN Int_BufSz = Int_BufSz + 2*3 ! M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + Db_BufSz = Db_BufSz + SIZE(InData%M) ! M END IF Int_BufSz = Int_BufSz + 1 ! LineUnOut Int_BufSz = Int_BufSz + 1 ! LineWrOutput allocated yes/no @@ -1572,10 +1572,10 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%N Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%UnstrLen - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%BA - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%UnstrLen + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%BA + Db_Xferred = Db_Xferred + 1 IF ( .NOT. ALLOCATED(InData%r) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1591,8 +1591,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%r,2), UBOUND(InData%r,2) DO i1 = LBOUND(InData%r,1), UBOUND(InData%r,1) - ReKiBuf(Re_Xferred) = InData%r(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%r(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1611,8 +1611,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%rd,2), UBOUND(InData%rd,2) DO i1 = LBOUND(InData%rd,1), UBOUND(InData%rd,1) - ReKiBuf(Re_Xferred) = InData%rd(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%rd(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1631,8 +1631,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%q,2), UBOUND(InData%q,2) DO i1 = LBOUND(InData%q,1), UBOUND(InData%q,1) - ReKiBuf(Re_Xferred) = InData%q(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%q(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1647,8 +1647,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%l,1), UBOUND(InData%l,1) - ReKiBuf(Re_Xferred) = InData%l(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%l(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%lstr) ) THEN @@ -1662,8 +1662,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%lstr,1), UBOUND(InData%lstr,1) - ReKiBuf(Re_Xferred) = InData%lstr(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%lstr(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%lstrd) ) THEN @@ -1677,8 +1677,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%lstrd,1), UBOUND(InData%lstrd,1) - ReKiBuf(Re_Xferred) = InData%lstrd(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%lstrd(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%V) ) THEN @@ -1692,8 +1692,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%V,1), UBOUND(InData%V,1) - ReKiBuf(Re_Xferred) = InData%V(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%V(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%T) ) THEN @@ -1711,8 +1711,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%T,2), UBOUND(InData%T,2) DO i1 = LBOUND(InData%T,1), UBOUND(InData%T,1) - ReKiBuf(Re_Xferred) = InData%T(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%T(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1731,8 +1731,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Td,2), UBOUND(InData%Td,2) DO i1 = LBOUND(InData%Td,1), UBOUND(InData%Td,1) - ReKiBuf(Re_Xferred) = InData%Td(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Td(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1751,8 +1751,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%W,2), UBOUND(InData%W,2) DO i1 = LBOUND(InData%W,1), UBOUND(InData%W,1) - ReKiBuf(Re_Xferred) = InData%W(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%W(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1771,8 +1771,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Dp,2), UBOUND(InData%Dp,2) DO i1 = LBOUND(InData%Dp,1), UBOUND(InData%Dp,1) - ReKiBuf(Re_Xferred) = InData%Dp(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Dp(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1791,8 +1791,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Dq,2), UBOUND(InData%Dq,2) DO i1 = LBOUND(InData%Dq,1), UBOUND(InData%Dq,1) - ReKiBuf(Re_Xferred) = InData%Dq(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Dq(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1811,8 +1811,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Ap,2), UBOUND(InData%Ap,2) DO i1 = LBOUND(InData%Ap,1), UBOUND(InData%Ap,1) - ReKiBuf(Re_Xferred) = InData%Ap(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Ap(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1831,8 +1831,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Aq,2), UBOUND(InData%Aq,2) DO i1 = LBOUND(InData%Aq,1), UBOUND(InData%Aq,1) - ReKiBuf(Re_Xferred) = InData%Aq(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Aq(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1851,8 +1851,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%B,2), UBOUND(InData%B,2) DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) - ReKiBuf(Re_Xferred) = InData%B(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%B(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1871,8 +1871,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%F,2), UBOUND(InData%F,2) DO i1 = LBOUND(InData%F,1), UBOUND(InData%F,1) - ReKiBuf(Re_Xferred) = InData%F(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%F(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1895,8 +1895,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i3 = LBOUND(InData%S,3), UBOUND(InData%S,3) DO i2 = LBOUND(InData%S,2), UBOUND(InData%S,2) DO i1 = LBOUND(InData%S,1), UBOUND(InData%S,1) - ReKiBuf(Re_Xferred) = InData%S(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%S(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -1920,8 +1920,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i3 = LBOUND(InData%M,3), UBOUND(InData%M,3) DO i2 = LBOUND(InData%M,2), UBOUND(InData%M,2) DO i1 = LBOUND(InData%M,1), UBOUND(InData%M,1) - ReKiBuf(Re_Xferred) = InData%M(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%M(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -1994,10 +1994,10 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + 1 OutData%N = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%UnstrLen = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%BA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%UnstrLen = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%BA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2016,8 +2016,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%r,2), UBOUND(OutData%r,2) DO i1 = LBOUND(OutData%r,1), UBOUND(OutData%r,1) - OutData%r(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%r(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2039,8 +2039,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%rd,2), UBOUND(OutData%rd,2) DO i1 = LBOUND(OutData%rd,1), UBOUND(OutData%rd,1) - OutData%rd(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%rd(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2062,8 +2062,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%q,2), UBOUND(OutData%q,2) DO i1 = LBOUND(OutData%q,1), UBOUND(OutData%q,1) - OutData%q(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%q(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2081,8 +2081,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%l,1), UBOUND(OutData%l,1) - OutData%l(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%l(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstr not allocated @@ -2099,8 +2099,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%lstr,1), UBOUND(OutData%lstr,1) - OutData%lstr(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%lstr(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstrd not allocated @@ -2117,8 +2117,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%lstrd,1), UBOUND(OutData%lstrd,1) - OutData%lstrd(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%lstrd(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! V not allocated @@ -2135,8 +2135,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) - OutData%V(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%V(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T not allocated @@ -2157,8 +2157,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%T,2), UBOUND(OutData%T,2) DO i1 = LBOUND(OutData%T,1), UBOUND(OutData%T,1) - OutData%T(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%T(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2180,8 +2180,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Td,2), UBOUND(OutData%Td,2) DO i1 = LBOUND(OutData%Td,1), UBOUND(OutData%Td,1) - OutData%Td(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Td(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2203,8 +2203,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%W,2), UBOUND(OutData%W,2) DO i1 = LBOUND(OutData%W,1), UBOUND(OutData%W,1) - OutData%W(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%W(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2226,8 +2226,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Dp,2), UBOUND(OutData%Dp,2) DO i1 = LBOUND(OutData%Dp,1), UBOUND(OutData%Dp,1) - OutData%Dp(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Dp(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2249,8 +2249,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Dq,2), UBOUND(OutData%Dq,2) DO i1 = LBOUND(OutData%Dq,1), UBOUND(OutData%Dq,1) - OutData%Dq(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Dq(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2272,8 +2272,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Ap,2), UBOUND(OutData%Ap,2) DO i1 = LBOUND(OutData%Ap,1), UBOUND(OutData%Ap,1) - OutData%Ap(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Ap(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2295,8 +2295,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Aq,2), UBOUND(OutData%Aq,2) DO i1 = LBOUND(OutData%Aq,1), UBOUND(OutData%Aq,1) - OutData%Aq(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Aq(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2318,8 +2318,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%B,2), UBOUND(OutData%B,2) DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) - OutData%B(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%B(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2341,8 +2341,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%F,2), UBOUND(OutData%F,2) DO i1 = LBOUND(OutData%F,1), UBOUND(OutData%F,1) - OutData%F(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%F(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2368,8 +2368,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) DO i3 = LBOUND(OutData%S,3), UBOUND(OutData%S,3) DO i2 = LBOUND(OutData%S,2), UBOUND(OutData%S,2) DO i1 = LBOUND(OutData%S,1), UBOUND(OutData%S,1) - OutData%S(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%S(i1,i2,i3) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -2396,8 +2396,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) DO i3 = LBOUND(OutData%M,3), UBOUND(OutData%M,3) DO i2 = LBOUND(OutData%M,2), UBOUND(OutData%M,2) DO i1 = LBOUND(OutData%M,1), UBOUND(OutData%M,1) - OutData%M(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%M(i1,i2,i3) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -2993,7 +2993,7 @@ SUBROUTINE MD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 1 ! states allocated yes/no IF ( ALLOCATED(InData%states) ) THEN Int_BufSz = Int_BufSz + 2*1 ! states upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%states) ! states + Db_BufSz = Db_BufSz + SIZE(InData%states) ! states END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -3033,8 +3033,8 @@ SUBROUTINE MD_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%states,1), UBOUND(InData%states,1) - ReKiBuf(Re_Xferred) = InData%states(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%states(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF END SUBROUTINE MD_PackContState @@ -3080,8 +3080,8 @@ SUBROUTINE MD_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err RETURN END IF DO i1 = LBOUND(OutData%states,1), UBOUND(OutData%states,1) - OutData%states(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%states(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF END SUBROUTINE MD_UnPackContState From 88ad8adee68811a98904bec527135f8357274238 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 15 Oct 2020 11:41:27 -0600 Subject: [PATCH 307/377] FlexSub: starting to isolate Guyan motion --- modules/subdyn/src/SD_FEM.f90 | 20 ++++++- modules/subdyn/src/SubDyn.f90 | 72 +++++++++++++++----------- modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 2 +- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 3f6f5136b..d02fda370 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -60,8 +60,8 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 ! Types of Boundary Conditions - INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 - INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 + INTEGER(IntKi), PARAMETER :: idBC_Fixed = 11 ! Fixed BC + INTEGER(IntKi), PARAMETER :: idBC_Internal = 12 ! Free BC INTEGER(IntKi), PARAMETER :: idBC_Leader = 13 ! TODO, and maybe "BC" not appropriate here ! Types of Static Improvement Methods @@ -2013,6 +2013,22 @@ LOGICAL FUNCTION isFixedBottom(Init, p) result(bFixed) bFixed = nFixed >=1 END FUNCTION isFixedBottom +!> True if a structure is floating, no fixed BC at the bottom +logical function isFloating(Init, p) result(bFLoating) + type(SD_InitType), intent(in ):: Init + type(SD_ParameterType),intent(in ) :: p + integer(IntKi) :: i + bFloating=.True. + do i =1,size(p%Nodes_C,1) + if (all(p%Nodes_C(I,2:7)==idBC_Internal)) then + continue + else + bFloating=.False. + return + endif + enddo +end function isFloating + SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(FEKi), INTENT(OUT) :: Me(12, 12) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 24db7e701..dd173baa5 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -434,61 +434,71 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) call GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) - !________________________________________ - ! Set motion outputs on y%Y2mesh - !________________________________________ - ! Y2 = C2*x + D2*u + F2 (Eq. 17) - m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar [ Y2(1) = 0*x(1) + D2(1,1)*u(1) ] - m%UR_bar_dot = matmul( p%TI , m%udot_TP ) ! UR_bar_dot [ Y2(3) = 0*x(1) + D2(3,2)*u(2) ] - m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) ! U_R_bar_dotdot [ Y2(5) = 0*x(2) + D2(5,3)*u(3) ] - + ! -------------------------------------------------------------------------------- + ! --- Output Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) + ! -------------------------------------------------------------------------------- + m%UR_bar = 0.0_ReKi + m%UR_bar_dot = 0.0_ReKi + m%UR_bar_dotdot = 0.0_ReKi + m%UL = 0.0_ReKi + m%UL_dot = 0.0_ReKi + m%UL_dotdot = 0.0_ReKi + + ! --- CB modes contribution to motion (L-DOF only) IF ( p%nDOFM > 0) THEN - m%UL = matmul( p%PhiM, x%qm ) + matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = C2(2,1)*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiM, x%qmdot ) + matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = C2(2,2)*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & ! UL_dotdot [ Y2(6) = C2(6,1)*x(1) + C2(6,2)*x(2) ... - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & ! + D2(6,3)*u(3) + D2(6,4)*u(4) ... ! -> bjj: this line takes up a lot of time. are any matrices sparse? - + p%F2_61 ! + F2(6) ] - ELSE ! There are no states when p%nDOFM=0 (i.e., no retained modes: p%nDOFM=0), so we omit those portions of the equations - m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL [ Y2(2) = 0*x(1) + D2(2,1)*u(1) ] : IT MAY BE MODIFIED LATER IF STATIC IMPROVEMENT - m%UL_dot = matmul( p%PhiRb_TI, m%udot_TP ) ! UL_dot [ Y2(4) = 0*x(2) + D2(4,2)*u(2) ] - m%UL_dotdot = matmul( p%PhiRb_TI, m%udotdot_TP ) ! UL_dotdot [ Y2(6) = 0*x(:) + D2(6,3)*u(3) + 0*u(4) + 0] + m%UL = matmul( p%PhiM, x%qm ) + m%UL_dot = matmul( p%PhiM, x%qmdot ) + m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & + + p%F2_61 END IF - - !STATIC IMPROVEMENT METHOD ( modify UL ) + ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then if (p%SttcSolve==idSIM_Full) then FLt = MATMUL(p%PhiL_T , m%UFL + p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - ! TODO New - !ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! TODO consider using use a precomputed UL_st_g and KLLm1: ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) elseif (p%SttcSolve==idSIM_GravOnly) then FLt = MATMUL(p%PhiL_T , p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - ! TODO New - !ULS = p%UL_st_g + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! TODO consider using use a precomputed UL_st_g and KLLm1: ULS = p%UL_st_g else STOP ! Should never happen endif m%UL = m%UL + ULS if ( p%nDOFM > 0) then UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) - ! TODO new - ! <<< m%UL = m%UL - UL0M end if endif + ! --- Adding Guyan contribution to R and L DOFs + if (p%FixedBottom) then + ! Then we add the Guyan motion here + m%UR_bar = matmul( p%TI , m%u_TP ) + m%UR_bar_dot = matmul( p%TI , m%udot_TP ) + m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) + m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) + m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) + else + ! We will add it in the "Full system" later + m%UR_bar = matmul( p%TI , m%u_TP ) + m%UR_bar_dot = matmul( p%TI , m%udot_TP ) + m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) + m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) + m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) + endif ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar m%U_red (p%ID__L) = m%UL - m%U_red (p%IDC_Rb)= 0 ! TODO + m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) m%U_red (p%ID__F) = 0 m%U_red_dot (p%IDI__) = m%UR_bar_dot m%U_red_dot (p%ID__L) = m%UL_dot - m%U_red_dot (p%IDC_Rb)= 0 ! TODO + m%U_red_dot (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) m%U_red_dot (p%ID__F) = 0 m%U_red_dotdot(p%IDI__) = m%UR_bar_dotdot m%U_red_dotdot(p%ID__L) = m%UL_dotdot - m%U_red_dotdot(p%IDC_Rb)= 0 ! TODO + m%U_red_dotdot(p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) m%U_red_dotdot(p%ID__F) = 0 if (p%reduced) then @@ -2432,7 +2442,7 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! D2_53, D2_63, D2_64 !p%D2_63 = p%PhiRb_TI - MATMUL( p%PhiM, p%MMB ) CALL LAPACK_GEMM( 'N', 'N', 1.0_ReKi, p%PhiM, p%MMB, 0.0_ReKi, p%D2_63, ErrStat2, ErrMsg2 ); if(Failed()) return; - p%D2_63 = p%PhiRb_TI - p%D2_63 + p%D2_63 = - p%D2_63 ! NOTE: removed Guyan acceleration !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ); if(Failed()) return; diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 1b1120e8e..4da67a0c9 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -197,7 +197,7 @@ typedef ^ ^ IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" -typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom" +typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node)" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 72ad257e6..3f15f0546 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -233,7 +233,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] - LOGICAL :: FixedBottom !< True if Fixed bottom [-] + LOGICAL :: FixedBottom !< True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] From edd462fd91f8467c371b7c2235a808e6283c0f1f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 15 Oct 2020 12:45:46 -0600 Subject: [PATCH 308/377] FlexSub: detecting fixed/free while reading input file --- modules/subdyn/src/SD_FEM.f90 | 106 ++++++++++++------------- modules/subdyn/src/SubDyn.f90 | 40 +++++++--- modules/subdyn/src/SubDyn_Registry.txt | 5 +- modules/subdyn/src/SubDyn_Types.f90 | 54 +++++++++++++ 4 files changed, 136 insertions(+), 69 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d02fda370..31e9460b9 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -884,12 +884,6 @@ SUBROUTINE DistributeDOF(Init, p, ErrStat, ErrMsg) iPrev = iPrev + len(p%NodesDOF(iNode)) enddo ! iNode, loop on joints - ! --- Initialize boundary constraint vector - NOTE: Needs Reindexing first - CALL InitBCs(Init, p) - - ! --- Initialize interface constraint vector - NOTE: Needs Reindexing first - CALL InitIntFc(Init, p) - ! --- Safety check if (any(p%ElemsDOF<0)) then ErrStat=ErrID_Fatal @@ -917,57 +911,61 @@ LOGICAL FUNCTION Failed() Failed = ErrStat >= AbortErrLev END FUNCTION Failed - !> Sets a list of DOF indices corresponding to the BC, and the value these DOF should have - !! NOTE: need p%Nodes_C to have an updated first column that uses indices and not JointIDs - !! Note: try to remove me and merge me with ApplyConstr, but used by "SelectNonBCConstraintsDOF" and "UnReduceVRdofs" - SUBROUTINE InitBCs(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(INOUT) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_C - iNode = p%Nodes_C(I,1) ! Node index - DO J = 1, 6 - if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) - p%Nodes_C(I, J+1) = idBC_Fixed - else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF - p%Nodes_C(I, J+1) = idBC_Internal - else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF - p%Nodes_C(I, J+1) = idBC_Leader - print*,'BC 2 not allowed for now, node',iNode - STOP - else - print*,'Wrong boundary condition input for reaction node',iNode - STOP - endif - ENDDO +END SUBROUTINE DistributeDOF + + +!> Checks reaction BC, adn remap 0s and 1s +SUBROUTINE CheckBCs(p, ErrStat, ErrMsg) + TYPE(SD_ParameterType),INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: I, J, iNode + ErrMsg = "" + ErrStat = ErrID_None + DO I = 1, p%nNodes_C + iNode = p%Nodes_C(I,1) ! Node index + DO J = 1, 6 + if (p%Nodes_C(I,J+1)==1) then ! User input 1=Constrained/Fixed (should be eliminated) + p%Nodes_C(I, J+1) = idBC_Fixed + else if (p%Nodes_C(I,J+1)==0) then ! User input 0=Free, fill be part of Internal DOF + p%Nodes_C(I, J+1) = idBC_Internal + else if (p%Nodes_C(I,J+1)==2) then ! User input 2=Leader DOF + p%Nodes_C(I, J+1) = idBC_Leader + ErrStat=ErrID_Fatal + ErrMsg='BC 2 not allowed for now, node '//trim(Num2LStr(iNode)) + else + ErrStat=ErrID_Fatal + ErrMsg='Wrong boundary condition input for reaction node '//trim(Num2LStr(iNode)) + endif ENDDO - END SUBROUTINE InitBCs - - !> Sets a list of DOF indices and the value these DOF should have - !! NOTE: need Init%Interf to have been reindexed so that first column uses indices and not JointIDs - !! TODO remove me and merge me with CraigBampton - SUBROUTINE InitIntFc(Init, p) - TYPE(SD_InitType ),INTENT(INOUT) :: Init - TYPE(SD_ParameterType),INTENT(INOUT) :: p - INTEGER(IntKi) :: I, J, iNode - DO I = 1, p%nNodes_I - iNode = p%Nodes_I(I,1) ! Node index - DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss - if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF - p%Nodes_I(I,J+1) = idBC_Leader - elseif (p%Nodes_I(I,J+1)==1) then ! User input 0=Fixed DOF - p%Nodes_I(I,J+1) = idBC_Fixed - print*,'Fixed boundary condition not yet supported for interface nodes, node:',iNode - STOP - else - print*,'Wrong boundary condition input for interface node',iNode - STOP - endif - ENDDO + ENDDO +END SUBROUTINE CheckBCs + +!> Check interface inputs, and remap 0s and 1s +SUBROUTINE CheckIntf(p, ErrStat, ErrMsg) + TYPE(SD_ParameterType),INTENT(INOUT) :: p + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + INTEGER(IntKi) :: I, J, iNode + ErrMsg = "" + ErrStat = ErrID_None + DO I = 1, p%nNodes_I + iNode = p%Nodes_I(I,1) ! Node index + DO J = 1, 6 ! ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + if (p%Nodes_I(I,J+1)==1) then ! User input 1=Leader DOF + p%Nodes_I(I,J+1) = idBC_Leader + elseif (p%Nodes_I(I,J+1)==0) then ! User input 0=Fixed DOF + p%Nodes_I(I,J+1) = idBC_Fixed + ErrStat = ErrID_Fatal + ErrMsg = 'Fixed boundary condition not yet supported for interface nodes, node:'//trim(Num2LStr(iNode)) + else + ErrStat = ErrID_Fatal + ErrMsg = 'Wrong boundary condition input for interface node'//trim(Num2LStr(iNode)) + endif ENDDO - END SUBROUTINE InitIntFc + ENDDO +END SUBROUTINE CheckIntf -END SUBROUTINE DistributeDOF !------------------------------------------------------------------------------------------------------ !> Assemble stiffness and mass matrix, and gravity force vector diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index dd173baa5..edc2df3da 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -218,6 +218,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return + if (p%FixedBottom) then + call WrScr(' Fixed-bottom case detected') + else + call WrScr(' Free/floating case detected, Guyan modes will be rigid body modes') + endif ! -------------------------------------------------------------------------------- ! --- Manipulation of Init and parameters @@ -265,7 +270,6 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return if (p%ExtraMoment) then - p%FixedBottom=isFixedBottom(Init,p) if (p%FixedBottom) then call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') else @@ -515,6 +519,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) DO iSDNode = 1,p%nNodes iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! + if (.not.(p%FixedBottom)) then + ! For floating case, we add the Guyan motion contribution + ! It corresponds to a rigid body motion the the TP as origin + ! TODO + !m%U_full(DOFList(1:3)) + + endif ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) @@ -924,15 +936,17 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif ENDDO IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return +call CheckBCs(p, ErrStat2, ErrMsg2); if (Failed()) return - -! Reading SSI matrices if present +! Trigger - Reading SSI matrices if present DO I = 1, p%nNodes_C if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(:,I),Init%SSIM(:,I), ErrStat, ErrMsg, UnEc ); if(Failed()) return endif enddo +! Trigger: determine if floating/fixed based on BCs and SSI file +p%FixedBottom = isFixedBottom(Init,p) @@ -960,6 +974,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif ENDDO IF (Check( ( p%nNodes_I < 0 ) .OR. (p%nNodes_I > Init%NJoints), 'NInterf must be non-negative and less than number of joints.')) RETURN +call CheckIntf(p, ErrStat2, ErrMsg2); if (Failed()) return !----------------------------------- MEMBERS -------------------------------------- ! One day we will need to take care of COSMIDs for non-circular members @@ -2515,8 +2530,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( p%KBB, nDOFL_TP, nDOFL_TP, 'p%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%CBB, nDOFL_TP, nDOFL_TP, 'p%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2524,6 +2537,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + if (p%nDOFM > 0 ) THEN CALL AllocAry( p%MBM, nDOFL_TP, nDOFM, 'p%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2535,14 +2549,14 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_12, nDOFL_TP, nDOFL_TP , 'p%D1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 - CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 - CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 - CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L,'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 - CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_12, nDOFL_TP, nDOFL_TP , 'p%D1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 + CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L,'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 + CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if END SUBROUTINE AllocParameters diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 4da67a0c9..875421187 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -181,8 +181,9 @@ typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" -typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" -typedef ^ ^ R8Ki FG_full {:} - - "Gravity force vector (with initial cable force T0), not reduced" N +typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +typedef ^ ^ R8Ki FG_full {:} - - "Gravity force vector (with initial cable force T0), not reduced" N +typedef ^ ^ ReKi DP0 {:,:} - - "Vector from TP to a Node at t=0, used for Floating Rigid Body motion" m # --- Constraints reduction typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 3f15f0546..8500aa2af 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -222,6 +222,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG_full !< Gravity force vector (with initial cable force T0), not reduced [N] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DP0 !< Vector from TP to a Node at t=0, used for Floating Rigid Body motion [m] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red_T !< Transpose of T_red [-] @@ -6973,6 +6974,18 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF END IF DstParamData%FG_full = SrcParamData%FG_full +ENDIF +IF (ALLOCATED(SrcParamData%DP0)) THEN + i1_l = LBOUND(SrcParamData%DP0,1) + i1_u = UBOUND(SrcParamData%DP0,1) + IF (.NOT. ALLOCATED(DstParamData%DP0)) THEN + ALLOCATE(DstParamData%DP0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DP0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%DP0 = SrcParamData%DP0 ENDIF DstParamData%reduced = SrcParamData%reduced IF (ALLOCATED(SrcParamData%T_red)) THEN @@ -7858,6 +7871,9 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%FG_full)) THEN DEALLOCATE(ParamData%FG_full) ENDIF +IF (ALLOCATED(ParamData%DP0)) THEN + DEALLOCATE(ParamData%DP0) +ENDIF IF (ALLOCATED(ParamData%T_red)) THEN DEALLOCATE(ParamData%T_red) ENDIF @@ -8134,6 +8150,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF ( ALLOCATED(InData%FG_full) ) THEN Int_BufSz = Int_BufSz + 2*1 ! FG_full upper/lower bounds for each dimension Db_BufSz = Db_BufSz + SIZE(InData%FG_full) ! FG_full + END IF + Int_BufSz = Int_BufSz + 1 ! DP0 allocated yes/no + IF ( ALLOCATED(InData%DP0) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DP0 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%DP0) ! DP0 END IF Int_BufSz = Int_BufSz + 1 ! reduced Int_BufSz = Int_BufSz + 1 ! T_red allocated yes/no @@ -8697,6 +8718,21 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si DbKiBuf(Db_Xferred) = InData%FG_full(i1) Db_Xferred = Db_Xferred + 1 END DO + END IF + IF ( .NOT. ALLOCATED(InData%DP0) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP0,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP0,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%DP0,1), UBOUND(InData%DP0,1) + ReKiBuf(Re_Xferred) = InData%DP0(i1) + Re_Xferred = Re_Xferred + 1 + END DO END IF IntKiBuf(Int_Xferred) = TRANSFER(InData%reduced, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 @@ -10157,6 +10193,24 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg OutData%FG_full(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) Db_Xferred = Db_Xferred + 1 END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DP0 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DP0)) DEALLOCATE(OutData%DP0) + ALLOCATE(OutData%DP0(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP0.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DP0,1), UBOUND(OutData%DP0,1) + OutData%DP0(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END IF OutData%reduced = TRANSFER(IntKiBuf(Int_Xferred), OutData%reduced) Int_Xferred = Int_Xferred + 1 From 72939d16ca0813f53ffa3c19caa4e4485b2b828f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 15 Oct 2020 15:02:24 -0600 Subject: [PATCH 309/377] FlexSub: implemented delta r --- modules/subdyn/src/SD_FEM.f90 | 31 +++++++++++++++++++++++++ modules/subdyn/src/SubDyn.f90 | 3 +++ modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 32 ++++++++++++++++++-------- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 31e9460b9..ea211328e 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -696,6 +696,37 @@ END SUBROUTINE SetNewProp END SUBROUTINE SD_Discrt + +!> Store relative vector between nodes and TP point, to later compute Guyan rigid body motion +subroutine StoreNodesRelPos(Init, p, ErrStat, ErrMsg) + type(SD_InitType), intent(in ) :: Init + type(SD_ParameterType), intent(inout) :: p + integer(IntKi), intent(out) :: ErrStat ! Error status of the operation + character(*), intent(out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer(Intki) :: i + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + ! NOTE: using efficient memory order + call AllocAry(p%DP0, 3, size(Init%Nodes,1), 'DP0', ErrStat2, ErrMsg2); if(Failed()) return + + do i = 1, size(Init%Nodes,1) + p%DP0(1, i) = Init%Nodes(i, 2) - Init%TP_RefPoint(1) + p%DP0(2, i) = Init%Nodes(i, 3) - Init%TP_RefPoint(2) + p%DP0(3, i) = Init%Nodes(i, 4) - Init%TP_RefPoint(3) + enddo + +contains + logical function Failed() + call SetErrStat(ErrStat2, ErrMsg2, Errstat, ErrMsg, 'StoreNodesRelPos') + failed = ErrStat >= AbortErrLev + end function Failed +end subroutine StoreNodesRelPos + + + !------------------------------------------------------------------------------------------------------ !> Set Element properties p%ElemProps, different properties are set depening on element type.. SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index edc2df3da..a21c76e6a 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -230,6 +230,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Discretize the structure according to the division size ! sets p%nNodes, Init%NElm CALL SD_Discrt(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + + ! Store relative distance to TP node, for floating rigid body motion + CALL StoreNodesRelPos(Init, p, ErrStat2, ErrMsg2); if(Failed()) return ! Set element properties (p%ElemProps) CALL SetElementProperties(Init, p, ErrStat2, ErrMsg2); if(Failed()) return diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 875421187..e7ad4a613 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -183,7 +183,7 @@ typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub struc typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" typedef ^ ^ R8Ki FG_full {:} - - "Gravity force vector (with initial cable force T0), not reduced" N -typedef ^ ^ ReKi DP0 {:,:} - - "Vector from TP to a Node at t=0, used for Floating Rigid Body motion" m +typedef ^ ^ ReKi DP0 {:}{:} - - "Vector from TP to a Node at t=0, used for Floating Rigid Body motion" m # --- Constraints reduction typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 8500aa2af..8248d4557 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -222,7 +222,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG_full !< Gravity force vector (with initial cable force T0), not reduced [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DP0 !< Vector from TP to a Node at t=0, used for Floating Rigid Body motion [m] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DP0 !< Vector from TP to a Node at t=0, used for Floating Rigid Body motion [m] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red_T !< Transpose of T_red [-] @@ -6978,8 +6978,10 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ALLOCATED(SrcParamData%DP0)) THEN i1_l = LBOUND(SrcParamData%DP0,1) i1_u = UBOUND(SrcParamData%DP0,1) + i2_l = LBOUND(SrcParamData%DP0,2) + i2_u = UBOUND(SrcParamData%DP0,2) IF (.NOT. ALLOCATED(DstParamData%DP0)) THEN - ALLOCATE(DstParamData%DP0(i1_l:i1_u),STAT=ErrStat2) + ALLOCATE(DstParamData%DP0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DP0.', ErrStat, ErrMsg,RoutineName) RETURN @@ -8153,7 +8155,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF Int_BufSz = Int_BufSz + 1 ! DP0 allocated yes/no IF ( ALLOCATED(InData%DP0) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! DP0 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + 2*2 ! DP0 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%DP0) ! DP0 END IF Int_BufSz = Int_BufSz + 1 ! reduced @@ -8727,11 +8729,16 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf( Int_Xferred ) = LBOUND(InData%DP0,1) IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP0,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%DP0,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DP0,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%DP0,1), UBOUND(InData%DP0,1) - ReKiBuf(Re_Xferred) = InData%DP0(i1) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%DP0,2), UBOUND(InData%DP0,2) + DO i1 = LBOUND(InData%DP0,1), UBOUND(InData%DP0,1) + ReKiBuf(Re_Xferred) = InData%DP0(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF IntKiBuf(Int_Xferred) = TRANSFER(InData%reduced, IntKiBuf(1)) @@ -10201,15 +10208,20 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 IF (ALLOCATED(OutData%DP0)) DEALLOCATE(OutData%DP0) - ALLOCATE(OutData%DP0(i1_l:i1_u),STAT=ErrStat2) + ALLOCATE(OutData%DP0(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DP0.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%DP0,1), UBOUND(OutData%DP0,1) - OutData%DP0(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(OutData%DP0,2), UBOUND(OutData%DP0,2) + DO i1 = LBOUND(OutData%DP0,1), UBOUND(OutData%DP0,1) + OutData%DP0(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO END DO END IF OutData%reduced = TRANSFER(IntKiBuf(Int_Xferred), OutData%reduced) From 06906e98562c5cc944078f8dbe1fd10466d5f315 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 15 Oct 2020 15:58:39 -0600 Subject: [PATCH 310/377] FlexSub: small fix for SSI detection (introduced 2 commit ago) --- modules/subdyn/src/SubDyn.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index a21c76e6a..0673e4588 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -943,7 +943,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) ! Trigger - Reading SSI matrices if present DO I = 1, p%nNodes_C - if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==0))) then + if ( Init%SSIfile(I)/='' .and. (ANY(p%Nodes_C(I,2:ReactCol)==idBC_Internal))) then Init%SSIfile(I) = trim(PriPath)//trim(Init%SSIfile(I)) CALL ReadSSIfile( Init%SSIfile(I), p%Nodes_C(I,1), Init%SSIK(:,I),Init%SSIM(:,I), ErrStat, ErrMsg, UnEc ); if(Failed()) return endif From 5940f94c40364e5c2b803dcd346d2cef21bc397c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 16 Oct 2020 16:32:32 -0600 Subject: [PATCH 311/377] FlexSub: rigid guyan mode implemented but not active (ExtraMoment todo) --- modules/subdyn/src/SD_FEM.f90 | 5 +- modules/subdyn/src/SubDyn.f90 | 99 ++++++++++++++++++-------- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 7 ++ 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index ea211328e..57a03df36 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -82,6 +82,7 @@ MODULE SD_FEM LOGICAL, PARAMETER :: DEV_VERSION = .false. LOGICAL, PARAMETER :: BC_Before_CB = .true. LOGICAL, PARAMETER :: ANALYTICAL_LIN = .true. + LOGICAL, PARAMETER :: GUYAN_RIGID_FLOATING = .false. INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi @@ -2033,7 +2034,7 @@ LOGICAL FUNCTION isFixedBottom(Init, p) result(bFixed) INTEGER(IntKi) :: i, nFixed nFixed=0 do i =1,size(p%Nodes_C,1) - if (ALL(p%Nodes_C(I,2:5)==idBC_Fixed)) then + if (ALL(p%Nodes_C(I,2:7)==idBC_Fixed)) then nFixed=nFixed+1 elseif (Init%SSIfile(I)/='') then nFixed=nFixed+1 @@ -2049,7 +2050,7 @@ logical function isFloating(Init, p) result(bFLoating) integer(IntKi) :: i bFloating=.True. do i =1,size(p%Nodes_C,1) - if (all(p%Nodes_C(I,2:7)==idBC_Internal)) then + if ((all(p%Nodes_C(I,2:7)==idBC_Internal)) .and. (Init%SSIfile(i)=='')) then continue else bFloating=.False. diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 0673e4588..fb885bc79 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -218,10 +218,18 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return - if (p%FixedBottom) then - call WrScr(' Fixed-bottom case detected') + if (p%Floating) then + if (GUYAN_RIGID_FLOATING) then + call WrScr(' Floating case detected, Guyan modes will be rigid body modes') + else + call WrScr(' Floating case detected') + endif else - call WrScr(' Free/floating case detected, Guyan modes will be rigid body modes') + if (p%FixedBottom) then + call WrScr(' Fixed bottom case detected') + else + call WrScr(' Mixed free/fixed condary conditions (free/floating assumed)') + endif endif ! -------------------------------------------------------------------------------- @@ -423,14 +431,27 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: DCM(3,3) REAL(ReKi) :: F_I(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only + ! Variables for Guayn rigid body motion + real(ReKi), dimension(3) :: Om, OmD ! Omega, OmegaDot (body rotational speed and acceleration) + real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node + real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) + real(ReKi), dimension(3) :: Om_X_r ! Crossproduct of Omega and r + real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation + real(ReKi), dimension(3) :: vP ! Rigid-body velocity of node + real(ReKi), dimension(3) :: aP ! Rigid-body acceleration of node + real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" + ! --- Reference coordinate system and body motion ! Compute the small rotation angles given the input direction cosine matrix rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return + Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + Om(1:3) = u%TPMesh%RotationVel(1:3,1) + OmD(1:3) = u%TPMesh%RotationAcc(1:3,1) ! Inputs at the transition piece: m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) @@ -477,7 +498,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) end if endif ! --- Adding Guyan contribution to R and L DOFs - if (p%FixedBottom) then + if ((.not. p%Floating) .or. (.not. GUYAN_RIGID_FLOATING)) then ! Then we add the Guyan motion here m%UR_bar = matmul( p%TI , m%u_TP ) m%UR_bar_dot = matmul( p%TI , m%udot_TP ) @@ -487,12 +508,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) else ! We will add it in the "Full system" later - m%UR_bar = matmul( p%TI , m%u_TP ) - m%UR_bar_dot = matmul( p%TI , m%udot_TP ) - m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) - m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) - m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) - m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) + !m%UR_bar = matmul( p%TI , m%u_TP ) + !m%UR_bar_dot = matmul( p%TI , m%udot_TP ) + !m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) + !m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + !m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) + !m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) endif ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar @@ -523,11 +544,23 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! - if (.not.(p%FixedBottom)) then + if (p%Floating .and. GUYAN_RIGID_FLOATING) then ! For floating case, we add the Guyan motion contribution ! It corresponds to a rigid body motion the the TP as origin - ! TODO - !m%U_full(DOFList(1:3)) + ! Rigid body motion of the point + rIP0(1:3) = p%DP0(1:3, iSDNode) + rIP(1:3) = matmul(Rot, rIP0) + duP(1:3) = rIP - rIP0 + m%u_TP(1:3) + Om_X_r(1:3) = cross_product(Om, rIP) + vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r + aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) + + m%U_full (DOFList(1:3))= m%U_full (DOFList(1:3)) + duP(1:3) + m%U_full (DOFList(4:6))= m%U_full (DOFList(4:6)) + rotations(1:3) + m%U_full_dot (DOFList(1:3))= m%U_full_dot (DOFList(1:3)) + vP(1:3) + m%U_full_dot (DOFList(4:6))= m%U_full_dot (DOFList(4:6)) + Om(1:3) + m%U_full_dotdot(DOFList(1:3))= m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + m%U_full_dotdot(DOFList(4:6))= m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) endif ! TODO TODO which orientation to give for joints with more than 6 dofs? @@ -949,7 +982,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif enddo ! Trigger: determine if floating/fixed based on BCs and SSI file -p%FixedBottom = isFixedBottom(Init,p) +p%FixedBottom = isFixedBottom(Init,p) +p%Floating = isFloating(Init,p) @@ -2876,23 +2910,28 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) if (p%ExtraMoment) then - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); - m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) - m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar - m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL - m%U_red(p%IDI__) = m%UR_bar - m%U_red(p%ID__L) = m%UL - m%U_red(p%IDC_Rb)= 0 ! TODO - m%U_red(p%ID__F) = 0 - if (p%reduced) then - m%DU_full = matmul(p%T_red, m%U_red) + if (p%Floating .and. GUYAN_RIGID_FLOATING) then + print*,'TODO floating extra moment' + STOP else - m%DU_full = m%U_red - endif - if (.not.p%FixedBottom) then ! if Floating, remove u_TP translation - do iNode = 1,p%nNodes - m%DU_full(p%NodesDOF(iNode)%List(1:3)) = m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) - enddo + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar + m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL + m%U_red(p%IDI__) = m%UR_bar + m%U_red(p%ID__L) = m%UL + m%U_red(p%IDC_Rb)= 0 ! TODO + m%U_red(p%ID__F) = 0 + if (p%reduced) then + m%DU_full = matmul(p%T_red, m%U_red) + else + m%DU_full = m%U_red + endif + if (.not.p%FixedBottom) then ! if Floating, remove u_TP translation + do iNode = 1,p%nNodes + m%DU_full(p%NodesDOF(iNode)%List(1:3)) = m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) + enddo + endif endif endif diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index e7ad4a613..a1b833f31 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -199,6 +199,7 @@ typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node)" +typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 8248d4557..3817f1133 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -235,6 +235,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] LOGICAL :: FixedBottom !< True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node) [-] + LOGICAL :: Floating !< True if floating bottom (the 6 DOF are free at all reaction nodes) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -7096,6 +7097,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment DstParamData%FixedBottom = SrcParamData%FixedBottom + DstParamData%Floating = SrcParamData%Floating IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) i1_u = UBOUND(SrcParamData%KMMDiag,1) @@ -8234,6 +8236,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment Int_BufSz = Int_BufSz + 1 ! FixedBottom + Int_BufSz = Int_BufSz + 1 ! Floating Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN Int_BufSz = Int_BufSz + 2*1 ! KMMDiag upper/lower bounds for each dimension @@ -8933,6 +8936,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedBottom, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Floating, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10461,6 +10466,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%FixedBottom = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedBottom) Int_Xferred = Int_Xferred + 1 + OutData%Floating = TRANSFER(IntKiBuf(Int_Xferred), OutData%Floating) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE From f9495bebd9e1d05f6ce004bf5fc2af3ccb44a83c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 17 Oct 2020 12:20:05 -0600 Subject: [PATCH 312/377] FlexSub: rigid guyan motion for extramoment but not active --- modules/subdyn/src/SD_FEM.f90 | 2 +- modules/subdyn/src/SubDyn.f90 | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 57a03df36..26089089e 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -74,7 +74,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idGuyanDamp_None = 0 INTEGER(IntKi), PARAMETER :: idGuyanDamp_Rayleigh = 1 INTEGER(IntKi), PARAMETER :: idGuyanDamp_66 = 2 - INTEGER(IntKi) :: idGuyanDamp_Valid(3) = (/idGuyanDamp_None, idGuyanDamp_Rayleigh, idGuyanDamp_66 /) + INTEGER(IntKi) :: idGuyanDamp_Valid(3) = (/idGuyanDamp_None, idGuyanDamp_Rayleigh, idGuyanDamp_66 /) INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index fb885bc79..7ea95a20f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -554,14 +554,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Om_X_r(1:3) = cross_product(Om, rIP) vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) - m%U_full (DOFList(1:3))= m%U_full (DOFList(1:3)) + duP(1:3) m%U_full (DOFList(4:6))= m%U_full (DOFList(4:6)) + rotations(1:3) m%U_full_dot (DOFList(1:3))= m%U_full_dot (DOFList(1:3)) + vP(1:3) m%U_full_dot (DOFList(4:6))= m%U_full_dot (DOFList(4:6)) + Om(1:3) m%U_full_dotdot(DOFList(1:3))= m%U_full_dotdot(DOFList(1:3)) + aP(1:3) m%U_full_dotdot(DOFList(4:6))= m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) - endif ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles @@ -2906,15 +2904,29 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) real(ReKi) :: CableTension ! Controllable Cable force real(ReKi) :: rotations(3) real(ReKi) :: du(3), Moment(3), Force(3) + ! Variables for Guyan Rigid motion + real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node + real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) + real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation + real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) + ! real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) if (p%ExtraMoment) then + ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); if (p%Floating .and. GUYAN_RIGID_FLOATING) then - print*,'TODO floating extra moment' - STOP + ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion + Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + m%DU_full = 0.0_ReKi + do iNode = 1,p%nNodes + rIP0(1:3) = p%DP0(1:3, iNode) ! vector interface->node at t=0 + rIP(1:3) = matmul(Rot, rIP0) ! vector interface->node at t + duP(1:3) = rIP - rIP0 ! nodal rigid displacement (without u_TP) + m%DU_full(p%NodesDOF(iNode)%List(1:3)) = duP(1:3) + enddo else - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); + ! For other cases with use the computed (linear) Guyan motion m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL From 70179c51220b7e5aef3e825b5355f159c0247af4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Sat, 17 Oct 2020 15:06:46 -0600 Subject: [PATCH 313/377] FlexSub: activating rigid body Guyan modes for floating --- modules/subdyn/src/SD_FEM.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 26089089e..12ee81851 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -82,7 +82,7 @@ MODULE SD_FEM LOGICAL, PARAMETER :: DEV_VERSION = .false. LOGICAL, PARAMETER :: BC_Before_CB = .true. LOGICAL, PARAMETER :: ANALYTICAL_LIN = .true. - LOGICAL, PARAMETER :: GUYAN_RIGID_FLOATING = .false. + LOGICAL, PARAMETER :: GUYAN_RIGID_FLOATING = .true. INTERFACE FINDLOCI ! In the future, use FINDLOC from intrinsic MODULE PROCEDURE FINDLOCI_ReKi From d93ee3399706ed0a9893ff7b38bf487fa6359ce5 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 19 Oct 2020 13:38:05 -0600 Subject: [PATCH 314/377] Init_Lin now works when AD is not used E.B. reported noted that Init%OutData_AD%BladeProps(1)%NumBlNds is undefined when AD was not used. --- modules/openfast-library/src/FAST_Subs.f90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 2f1fdef2b..2b4324306 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -1208,7 +1208,11 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if ( p_FAST%Linearize ) then ! NOTE: In the following call, we use Init%OutData_AD%BladeProps(1)%NumBlNds as the number of aero nodes on EACH blade, which ! is consistent with the current AD implementation, but if AD changes this, then it must be handled here, too! - call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, Init%OutData_AD%BladeProps(1)%NumBlNds, ErrStat2, ErrMsg2) + if (p_FAST%CompAero == MODULE_AD) then + call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, Init%OutData_AD%BladeProps(1)%NumBlNds, ErrStat2, ErrMsg2) + else + call Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, Init%OutData_ED%NumBl, -1, ErrStat2, ErrMsg2) + endif call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat >= AbortErrLev) then From d6242630bb9e15b177e2ea5b1948a0a29d737be8 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 20 Oct 2020 13:13:14 -0600 Subject: [PATCH 315/377] Modify HD Driver to only input PRP motions (or PRP+ all WAMIT bodies) Removed Morison inputs section from the HD driver input file. Now the PRP motions are mapped to the Morison mesh --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 587 +++++++++---------- 1 file changed, 278 insertions(+), 309 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 774617831..9663975fb 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -39,16 +39,11 @@ PROGRAM HydroDynDriver LOGICAL :: Linearize INTEGER :: NSteps REAL(DbKi) :: TimeInterval - INTEGER :: WAMITInputsMod - CHARACTER(1024) :: WAMITInputsFile - REAL(ReKi) :: uWAMITInSteady(6) - REAL(ReKi) :: uDotWAMITInSteady(6) - REAL(ReKi) :: uDotDotWAMITInSteady(6) - INTEGER :: MorisonInputsMod - CHARACTER(1024) :: MorisonInputsFile - REAL(ReKi) :: uMorisonInSteady(6) - REAL(ReKi) :: uDotMorisonInSteady(6) - REAL(ReKi) :: uDotDotMorisonInSteady(6) + INTEGER :: PRPInputsMod + CHARACTER(1024) :: PRPInputsFile + REAL(ReKi) :: uPRPInSteady(6) + REAL(ReKi) :: uDotPRPInSteady(6) + REAL(ReKi) :: uDotDotPRPInSteady(6) LOGICAL :: WaveElevSeriesFlag !< Should we put together a wave elevation series and save it to file? REAL(ReKi) :: WaveElevdX !< Spacing in the X direction for wave elevation series (m) REAL(ReKi) :: WaveElevdY !< Spacing in the Y direction for the wave elevation series (m) @@ -92,13 +87,13 @@ PROGRAM HydroDynDriver TYPE(HydroDyn_ContinuousStateType) :: dxdt ! First time derivatives of the continuous states - INTEGER(IntKi) :: UnWAMITInp ! WAMIT Inputs file identifier + INTEGER(IntKi) :: UnPRPInp ! PRP Inputs file identifier INTEGER(IntKi) :: UnMorisonInp ! Morison Inputs file identifier INTEGER(IntKi) :: UnHD_Out ! Output file identifier - REAL(ReKi), ALLOCATABLE :: WAMITin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for WAMIT + REAL(ReKi), ALLOCATABLE :: PRPin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for PRP REAL(ReKi), ALLOCATABLE :: Morisonin(:,:) ! Variable for storing time, forces, and body velocities, in m/s or rad/s for Morison elements - INTEGER(IntKi) :: NBody ! Number of WAMIT bodies to work with if prescribing kinematics on each body (WAMITInputsMod<0) + INTEGER(IntKi) :: NBody ! Number of WAMIT bodies to work with if prescribing kinematics on each body (PRPInputsMod<0) INTEGER(IntKi) :: I ! Generic loop counter INTEGER(IntKi) :: J ! Generic loop counter @@ -119,8 +114,9 @@ PROGRAM HydroDynDriver real(DbKi) :: SttsTime ! Amount of time between screen status messages (sec) integer :: n_SttsTime ! Number of time steps between screen status messages (-) - type(MeshType) :: RefPtMesh ! 1-node Point mesh located at (0,0,0) in global system where all WAMIT-related driver inputs are set + type(MeshType) :: RefPtMesh ! 1-node Point mesh located at (0,0,0) in global system where all PRP-related driver inputs are set type(MeshMapType) :: HD_Ref_2_WB_P ! Mesh mapping between Reference pt mesh and WAMIT body(ies) mesh + type(MeshMapType) :: HD_Ref_2_M_P ! Mesh mapping between Reference pt mesh and Morison mesh real(R8Ki) :: theta(3) ! mesh creation helper data ! For testing @@ -209,58 +205,58 @@ PROGRAM HydroDynDriver !------------------------------------------------------------------------------------- - IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN + IF ( drvrInitInp%PRPInputsMod == 2 ) THEN - ! Open the WAMIT inputs data file - CALL GetNewUnit( UnWAMITInp ) - CALL OpenFInpFile ( UnWAMITInp, drvrInitInp%WAMITInputsFile, ErrStat, ErrMsg ) + ! Open the PRP inputs data file + CALL GetNewUnit( UnPRPInp ) + CALL OpenFInpFile ( UnPRPInp, drvrInitInp%PRPInputsFile, ErrStat, ErrMsg ) IF (ErrStat >=AbortErrLev) STOP - ALLOCATE ( WAMITin(drvrInitInp%NSteps, 19), STAT = ErrStat ) + ALLOCATE ( PRPin(drvrInitInp%NSteps, 19), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WAMITin array.' + ErrMsg = ' Error allocating space for PRPin array.' CALL WrScr( ErrMsg ) - CLOSE( UnWAMITInp ) + CLOSE( UnPRPInp ) STOP END IF DO n = 1,drvrInitInp%NSteps - READ (UnWAMITInp,*,IOSTAT=ErrStat) (WAMITin (n,J), J=1,19) + READ (UnPRPInp,*,IOSTAT=ErrStat) (PRPin (n,J), J=1,19) IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error reading the WAMIT input time-series file. ' + ErrMsg = ' Error reading the PRP input time-series file. ' CALL WrScr( ErrMsg ) STOP END IF END DO ! Close the inputs file - CLOSE ( UnWAMITInp ) + CLOSE ( UnPRPInp ) END IF ! multi-body kinematics driver option (time, PRP DOFs 1-6, body1 DOFs 1-6, body2 DOFs 1-6...) - IF ( drvrInitInp%WAMITInputsMod < 0 ) THEN + IF ( drvrInitInp%PRPInputsMod < 0 ) THEN - NBODY = -drvrInitInp%WAMITInputsMod + NBODY = -drvrInitInp%PRPInputsMod ! Open the WAMIT inputs data file - CALL GetNewUnit( UnWAMITInp ) - CALL OpenFInpFile ( UnWAMITInp, drvrInitInp%WAMITInputsFile, ErrStat, ErrMsg ) + CALL GetNewUnit( UnPRPInp ) + CALL OpenFInpFile ( UnPRPInp, drvrInitInp%PRPInputsFile, ErrStat, ErrMsg ) IF (ErrStat >=AbortErrLev) STOP - ALLOCATE ( WAMITin(drvrInitInp%NSteps, 7+6*NBODY), STAT = ErrStat ) + ALLOCATE ( PRPin(drvrInitInp%NSteps, 7+6*NBODY), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for WAMITin array.' + ErrMsg = ' Error allocating space for PRPin array.' CALL WrScr( ErrMsg ) - CLOSE( UnWAMITInp ) + CLOSE( UnPRPInp ) STOP END IF PRINT *, 'NBody is '//trim(Num2LStr(NBody))//' and planning to read in '//trim(Num2LStr(7+6*NBODY))//' columns from the input file' DO n = 1,drvrInitInp%NSteps - READ (UnWAMITInp,*,IOSTAT=ErrStat) (WAMITin (n,J), J=1,7+6*NBODY) + READ (UnPRPInp,*,IOSTAT=ErrStat) (PRPin (n,J), J=1,7+6*NBODY) IF ( ErrStat /= 0 ) THEN ErrMsg = ' Error reading the WAMIT input time-series file (for multiple bodies). ' @@ -270,40 +266,11 @@ PROGRAM HydroDynDriver END DO ! Close the inputs file - CLOSE ( UnWAMITInp ) + CLOSE ( UnPRPInp ) ELSE NBody = 0 END IF - IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN - - ! Open the Morison inputs data file - CALL GetNewUnit( UnMorisonInp ) - CALL OpenFInpFile ( UnMorisonInp, drvrInitInp%MorisonInputsFile, ErrStat, ErrMsg ) - IF (ErrStat >=AbortErrLev) STOP - - - ALLOCATE ( MorisonIn(drvrInitInp%NSteps, 19), STAT = ErrStat ) - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Error allocating space for MorisonIn array.' - CALL WrScr( ErrMsg ) - CLOSE( UnMorisonInp ) - STOP - END IF - - DO n = 1,drvrInitInp%NSteps - READ (UnMorisonInp,*,IOSTAT=ErrStat) (MorisonIn (n,J), J=1,19) - - IF ( ErrStat /= 0 ) THEN - ErrMsg = ' Error reading the Morison input time-series file. ' - CALL WrScr( ErrMsg ) - STOP - END IF - END DO - - ! Close the inputs file - CLOSE ( UnMorisonInp ) - END IF ! Setup the arrays for the wave elevation timeseries if requested by the driver input file @@ -363,70 +330,61 @@ PROGRAM HydroDynDriver - - IF ( u(1)%WAMITMesh%Initialized ) THEN - - - ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] - - CALL MeshMapCreate( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') - if (errStat >= AbortErrLev) then - ! Clean up and exit - call HD_DvrCleanup() - end if - - ! Set any steady-state inputs, once before the time-stepping loop + ! Set any steady-state inputs, once before the time-stepping loop - IF (( drvrInitInp%WAMITInputsMod /= 2 ) .AND. ( drvrInitInp%WAMITInputsMod >= 0 )) THEN + IF (( drvrInitInp%PRPInputsMod /= 2 ) .AND. ( drvrInitInp%PRPInputsMod >= 0 )) THEN - u(1)%PRPMesh%TranslationDisp(:,1) = drvrInitInp%uWAMITInSteady(1:3) + u(1)%PRPMesh%TranslationDisp(:,1) = drvrInitInp%uPRPInSteady(1:3) - ! Compute direction cosine matrix from the rotation angles - CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uWAMITInSteady(4), ReKi), REAL(drvrInitInp%uWAMITInSteady(5), ReKi), REAL(drvrInitInp%uWAMITInSteady(6), ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%PRPMesh%Orientation(:,:,1) = dcm + ! Compute direction cosine matrix from the rotation angles + CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uPRPInSteady(4), ReKi), REAL(drvrInitInp%uPRPInSteady(5), ReKi), REAL(drvrInitInp%uPRPInSteady(6), ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%PRPMesh%Orientation(:,:,1) = dcm - u(1)%PRPMesh%TranslationVel(:,1) = drvrInitInp%uDotWAMITInSteady(1:3) - u(1)%PRPMesh%RotationVel(:,1) = drvrInitInp%uDotWAMITInSteady(4:6) - u(1)%PRPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(1:3) - u(1)%PRPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotWAMITInSteady(4:6) + u(1)%PRPMesh%TranslationVel(:,1) = drvrInitInp%uDotPRPInSteady(1:3) + u(1)%PRPMesh%RotationVel(:,1) = drvrInitInp%uDotPRPInSteady(4:6) + u(1)%PRPMesh%TranslationAcc(:,1) = drvrInitInp%uDotDotPRPInSteady(1:3) + u(1)%PRPMesh%RotationAcc(:,1) = drvrInitInp%uDotDotPRPInSteady(4:6) + + IF ( u(1)%WAMITMesh%Initialized ) THEN - ! Map kinematics to the WAMIT mesh with 1 to NBody nodes + ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] + + CALL MeshMapCreate( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + ! Map PRP kinematics to the WAMIT mesh with 1 to NBody nodes CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() end if - END IF - END IF - - IF ( drvrInitInp%MorisonInputsMod /= 2 ) THEN - IF ( u(1)%Morison%Mesh%Initialized ) THEN - u(1)%Morison%Mesh%TranslationDisp(1,:) = drvrInitInp%uMorisonInSteady(1) - u(1)%Morison%Mesh%TranslationDisp(2,:) = drvrInitInp%uMorisonInSteady(2) - u(1)%Morison%Mesh%TranslationDisp(3,:) = drvrInitInp%uMorisonInSteady(3) - - ! Compute direction cosine matrix from the rotation angles - CALL SmllRotTrans( 'InputRotation', REAL(drvrInitInp%uMorisonInSteady(4),ReKi), REAL(drvrInitInp%uMorisonInSteady(5),ReKi), REAL(drvrInitInp%uMorisonInSteady(6),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - DO I = 1, u(1)%Morison%Mesh%nNodes - u(1)%Morison%Mesh%Orientation(:,:,I) = dcm - END DO - u(1)%Morison%Mesh%TranslationVel(1,:) = drvrInitInp%uDotMorisonInSteady(1) - u(1)%Morison%Mesh%TranslationVel(2,:) = drvrInitInp%uDotMorisonInSteady(2) - u(1)%Morison%Mesh%TranslationVel(3,:) = drvrInitInp%uDotMorisonInSteady(3) - u(1)%Morison%Mesh%RotationVel(1,:) = drvrInitInp%uDotMorisonInSteady(4) - u(1)%Morison%Mesh%RotationVel(2,:) = drvrInitInp%uDotMorisonInSteady(5) - u(1)%Morison%Mesh%RotationVel(3,:) = drvrInitInp%uDotMorisonInSteady(6) - u(1)%Morison%Mesh%TranslationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(1) - u(1)%Morison%Mesh%TranslationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(2) - u(1)%Morison%Mesh%TranslationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(3) - u(1)%Morison%Mesh%RotationAcc(1,:) = drvrInitInp%uDotDotMorisonInSteady(4) - u(1)%Morison%Mesh%RotationAcc(2,:) = drvrInitInp%uDotDotMorisonInSteady(5) - u(1)%Morison%Mesh%RotationAcc(3,:) = drvrInitInp%uDotDotMorisonInSteady(6) - END IF + END IF ! u(1)%WAMITMesh%Initialized + + if ( u(1)%Morison%Mesh%Initialized ) then + + ! Create mesh mappings between (0,0,0) reference point mesh and the Morison mesh + + CALL MeshMapCreate( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + + ! Map PRP kinematics to the Morison mesh + CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + end if ! u(1)%Morison%Mesh%Initialized + END IF + - !............................................................................................................................... ! Routines called in loose coupling -- the glue code may implement this in various ways !............................................................................................................................... @@ -440,112 +398,123 @@ PROGRAM HydroDynDriver InputTime(1) = Time ! Modify u (likely from the outputs of another module or a set of test conditions) here: - - IF ( u(1)%WAMITMesh%Initialized ) THEN - - ! WAMITInputsMod 2: Reads time series of positions, velocities, and accelerations for the platform reference point - IF ( drvrInitInp%WAMITInputsMod == 2 ) THEN + + ! PRPInputsMod 2: Reads time series of positions, velocities, and accelerations for the platform reference point + IF ( drvrInitInp%PRPInputsMod == 2 ) THEN - u(1)%PRPMesh%TranslationDisp(:,1) = WAMITin(n,2:4) + u(1)%PRPMesh%TranslationDisp(:,1) = PRPin(n,2:4) - ! Compute direction cosine matrix from the rotation angles + ! Compute direction cosine matrix from the rotation angles - IF ( abs(WAMITin(n,5)) > maxAngle ) maxAngle = abs(WAMITin(n,5)) - IF ( abs(WAMITin(n,6)) > maxAngle ) maxAngle = abs(WAMITin(n,6)) - IF ( abs(WAMITin(n,7)) > maxAngle ) maxAngle = abs(WAMITin(n,7)) + IF ( abs(PRPin(n,5)) > maxAngle ) maxAngle = abs(PRPin(n,5)) + IF ( abs(PRPin(n,6)) > maxAngle ) maxAngle = abs(PRPin(n,6)) + IF ( abs(PRPin(n,7)) > maxAngle ) maxAngle = abs(PRPin(n,7)) - CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) - u(1)%PRPMesh%Orientation(:,:,1) = dcm - u(1)%PRPMesh%TranslationVel(:,1) = WAMITin(n,8:10) - u(1)%PRPMesh%RotationVel(:,1) = WAMITin(n,11:13) - u(1)%PRPMesh%TranslationAcc(:,1) = WAMITin(n,14:16) - u(1)%PRPMesh%RotationAcc(:,1) = WAMITin(n,17:19) + CALL SmllRotTrans( 'InputRotation', REAL(PRPin(n,5),ReKi), REAL(PRPin(n,6),ReKi), REAL(PRPin(n,7),ReKi), dcm, 'Junk', ErrStat, ErrMsg ) + u(1)%PRPMesh%Orientation(:,:,1) = dcm + u(1)%PRPMesh%TranslationVel(:,1) = PRPin(n,8:10) + u(1)%PRPMesh%RotationVel(:,1) = PRPin(n,11:13) + u(1)%PRPMesh%TranslationAcc(:,1) = PRPin(n,14:16) + u(1)%PRPMesh%RotationAcc(:,1) = PRPin(n,17:19) + IF ( u(1)%WAMITMesh%Initialized ) THEN ! Map kinematics to the WAMIT mesh with 1 to NBody nodes CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then ! Clean up and exit call HD_DvrCleanup() end if - END IF - !@mhall: new kinematics input for moving bodies individually - ! WAMITInputsMod < 0: Reads time series of positions for each body individually, and uses finite differences to also get velocities and accelerations. - ! The number of bodies is the negative of WAMITInputsMod. - IF ( drvrInitInp%WAMITInputsMod < 0 ) THEN + IF ( u(1)%Morison%Mesh%Initialized ) THEN + ! Map kinematics to the WAMIT mesh with 1 to NBody nodes + CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + END IF + + end if + + !@mhall: new kinematics input for moving bodies individually + ! PRPInputsMod < 0: Reads time series of positions for each body individually, and uses finite differences to also get velocities and accelerations. + ! The number of bodies is the negative of PRPInputsMod. + IF ( drvrInitInp%PRPInputsMod < 0 ) THEN ! platform reference point (PRP), and body 1-NBody displacements - u(1)%PRPMesh%TranslationDisp(:,1) = WAMITin(n,2:4) + u(1)%PRPMesh%TranslationDisp(:,1) = PRPin(n,2:4) DO I=1,NBody - u(1)%WAMITMesh%TranslationDisp(:,I) = WAMITin(n, 6*I+2:6*I+4) + u(1)%WAMITMesh%TranslationDisp(:,I) = PRPin(n, 6*I+2:6*I+4) END DO ! PRP and body 1-NBody orientations (skipping the maxAngle stuff) - CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,5),ReKi), REAL(WAMITin(n,6),ReKi), REAL(WAMITin(n,7),ReKi), dcm, 'PRP orientation', ErrStat, ErrMsg ) + CALL SmllRotTrans( 'InputRotation', REAL(PRPin(n,5),ReKi), REAL(PRPin(n,6),ReKi), REAL(PRPin(n,7),ReKi), dcm, 'PRP orientation', ErrStat, ErrMsg ) u(1)%PRPMesh%Orientation(:,:,1) = dcm DO I=1, NBody - CALL SmllRotTrans( 'InputRotation', REAL(WAMITin(n,6*I+5),ReKi), REAL(WAMITin(n,6*I+6),ReKi), REAL(WAMITin(n,6*I+7),ReKi), dcm, 'body orientation', ErrStat, ErrMsg ) + CALL SmllRotTrans( 'InputRotation', REAL(PRPin(n,6*I+5),ReKi), REAL(PRPin(n,6*I+6),ReKi), REAL(PRPin(n,6*I+7),ReKi), dcm, 'body orientation', ErrStat, ErrMsg ) u(1)%PRPMesh%Orientation(:,:,1) = dcm END DO ! use finite differences for velocities and accelerations IF (n == 1) THEN ! use forward differences for first time step - u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n+1, 2:4) - WAMITin(n , 2:4))/drvrInitInp%TimeInterval - u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n+1, 5:7) - WAMITin(n , 5:7))/drvrInitInp%TimeInterval - u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n+2, 2:4) - 2*WAMITin(n+1, 2:4) + WAMITin(n, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n+2, 5:7) - 2*WAMITin(n+1, 5:7) + WAMITin(n, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%TranslationVel(:,1) = (PRPin(n+1, 2:4) - PRPin(n , 2:4))/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (PRPin(n+1, 5:7) - PRPin(n , 5:7))/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (PRPin(n+2, 2:4) - 2*PRPin(n+1, 2:4) + PRPin(n, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (PRPin(n+2, 5:7) - 2*PRPin(n+1, 5:7) + PRPin(n, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) DO I=1,NBody - u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - WAMITin(n , 6*I+2:6*I+4))/drvrInitInp%TimeInterval - u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - WAMITin(n , 6*I+5:6*I+7))/drvrInitInp%TimeInterval - u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n+2, 6*I+2:6*I+4) - 2*WAMITin(n+1, 6*I+2:6*I+4) + WAMITin(n, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n+2, 6*I+5:6*I+7) - 2*WAMITin(n+1, 6*I+5:6*I+7) + WAMITin(n, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%TranslationVel(:,I) = (PRPin(n+1, 6*I+2:6*I+4) - PRPin(n , 6*I+2:6*I+4))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (PRPin(n+1, 6*I+5:6*I+7) - PRPin(n , 6*I+5:6*I+7))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (PRPin(n+2, 6*I+2:6*I+4) - 2*PRPin(n+1, 6*I+2:6*I+4) + PRPin(n, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (PRPin(n+2, 6*I+5:6*I+7) - 2*PRPin(n+1, 6*I+5:6*I+7) + PRPin(n, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) END DO ELSE IF (n == drvrInitInp%NSteps) THEN ! use backward differences for last time step - u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n, 2:4) - WAMITin(n-1, 2:4))/drvrInitInp%TimeInterval - u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n, 5:7) - WAMITin(n-1, 5:7))/drvrInitInp%TimeInterval - u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n, 2:4) - 2*WAMITin(n-1, 2:4) + WAMITin(n-2, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n, 5:7) - 2*WAMITin(n-1, 5:7) + WAMITin(n-2, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%TranslationVel(:,1) = (PRPin(n, 2:4) - PRPin(n-1, 2:4))/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (PRPin(n, 5:7) - PRPin(n-1, 5:7))/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (PRPin(n, 2:4) - 2*PRPin(n-1, 2:4) + PRPin(n-2, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (PRPin(n, 5:7) - 2*PRPin(n-1, 5:7) + PRPin(n-2, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) DO I=1,NBody - u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n, 6*I+2:6*I+4) - WAMITin(n-1, 6*I+2:6*I+4))/drvrInitInp%TimeInterval - u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n, 6*I+5:6*I+7) - WAMITin(n-1, 6*I+5:6*I+7))/drvrInitInp%TimeInterval - u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n, 6*I+2:6*I+4) - 2*WAMITin(n-1, 6*I+2:6*I+4) + WAMITin(n-2, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n, 6*I+5:6*I+7) - 2*WAMITin(n-1, 6*I+5:6*I+7) + WAMITin(n-2, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%TranslationVel(:,I) = (PRPin(n, 6*I+2:6*I+4) - PRPin(n-1, 6*I+2:6*I+4))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (PRPin(n, 6*I+5:6*I+7) - PRPin(n-1, 6*I+5:6*I+7))/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (PRPin(n, 6*I+2:6*I+4) - 2*PRPin(n-1, 6*I+2:6*I+4) + PRPin(n-2, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (PRPin(n, 6*I+5:6*I+7) - 2*PRPin(n-1, 6*I+5:6*I+7) + PRPin(n-2, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) END DO ELSE ! otherwise use central differences for intermediate time steps - u(1)%PRPMesh%TranslationVel(:,1) = (WAMITin(n+1, 2:4) - WAMITin(n-1, 2:4))*0.5/drvrInitInp%TimeInterval - u(1)%PRPMesh%RotationVel( :,1) = (WAMITin(n+1, 5:7) - WAMITin(n-1, 5:7))*0.5/drvrInitInp%TimeInterval - u(1)%PRPMesh%TranslationAcc(:,1) = (WAMITin(n+1, 2:4) - 2*WAMITin(n, 2:4) + WAMITin(n-1, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%PRPMesh%RotationAcc( :,1) = (WAMITin(n+1, 5:7) - 2*WAMITin(n, 5:7) + WAMITin(n-1, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%TranslationVel(:,1) = (PRPin(n+1, 2:4) - PRPin(n-1, 2:4))*0.5/drvrInitInp%TimeInterval + u(1)%PRPMesh%RotationVel( :,1) = (PRPin(n+1, 5:7) - PRPin(n-1, 5:7))*0.5/drvrInitInp%TimeInterval + u(1)%PRPMesh%TranslationAcc(:,1) = (PRPin(n+1, 2:4) - 2*PRPin(n, 2:4) + PRPin(n-1, 2:4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%PRPMesh%RotationAcc( :,1) = (PRPin(n+1, 5:7) - 2*PRPin(n, 5:7) + PRPin(n-1, 5:7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) DO I=1,NBody - u(1)%WAMITMesh%TranslationVel(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - WAMITin(n-1, 6*I+2:6*I+4))*0.5/drvrInitInp%TimeInterval - u(1)%WAMITMesh%RotationVel( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - WAMITin(n-1, 6*I+5:6*I+7))*0.5/drvrInitInp%TimeInterval - u(1)%WAMITMesh%TranslationAcc(:,I) = (WAMITin(n+1, 6*I+2:6*I+4) - 2*WAMITin(n, 6*I+2:6*I+4) + WAMITin(n-1, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) - u(1)%WAMITMesh%RotationAcc( :,I) = (WAMITin(n+1, 6*I+5:6*I+7) - 2*WAMITin(n, 6*I+5:6*I+7) + WAMITin(n-1, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%TranslationVel(:,I) = (PRPin(n+1, 6*I+2:6*I+4) - PRPin(n-1, 6*I+2:6*I+4))*0.5/drvrInitInp%TimeInterval + u(1)%WAMITMesh%RotationVel( :,I) = (PRPin(n+1, 6*I+5:6*I+7) - PRPin(n-1, 6*I+5:6*I+7))*0.5/drvrInitInp%TimeInterval + u(1)%WAMITMesh%TranslationAcc(:,I) = (PRPin(n+1, 6*I+2:6*I+4) - 2*PRPin(n, 6*I+2:6*I+4) + PRPin(n-1, 6*I+2:6*I+4))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) + u(1)%WAMITMesh%RotationAcc( :,I) = (PRPin(n+1, 6*I+5:6*I+7) - 2*PRPin(n, 6*I+5:6*I+7) + PRPin(n-1, 6*I+5:6*I+7))/(drvrInitInp%TimeInterval*drvrInitInp%TimeInterval) END DO END IF + + IF ( u(1)%Morison%Mesh%Initialized ) THEN + ! Map kinematics to the WAMIT mesh with 1 to NBody nodes + CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + END IF END IF !@mhall: end of addition - - END IF ! ( u(1)%WAMITMesh%Initialized ) - - IF ( u(1)%Morison%Mesh%Initialized ) THEN - IF ( drvrInitInp%MorisonInputsMod == 2 ) THEN - ! Set the Morison Inputs from a time series input file - END IF - - END IF + + ! Calculate outputs at n CALL HydroDyn_CalcOutput( Time, u(1), p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) @@ -890,12 +859,12 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) !------------------------------------------------------------------------------------------------- - ! WAMIT INPUTS section + ! PRP INPUTS section !------------------------------------------------------------------------------------------------- ! Header - CALL ReadCom( UnIn, FileName, 'WAMIT INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + CALL ReadCom( UnIn, FileName, 'PRP INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Failed to read Comment line.' @@ -907,13 +876,13 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) - ! WAMITInputsMod + ! PRPInputsMod - CALL ReadVar ( UnIn, FileName, InitInp%WAMITInputsMod, 'WAMITInputsMod', & - 'Model for the WAMIT inputs', ErrStat, ErrMsg, UnEchoLocal ) + CALL ReadVar ( UnIn, FileName, InitInp%PRPInputsMod, 'PRPInputsMod', & + 'Model for the PRP (principal reference point) inputs', ErrStat, ErrMsg, UnEchoLocal ) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read WAMITInputsMod parameter.' + ErrMsg = ' Failed to read PRPInputsMod parameter.' ErrStat = ErrID_Fatal CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) CLOSE( UnIn ) @@ -921,13 +890,13 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) END IF - ! WAMITInputsFile + ! PRPInputsFile - CALL ReadVar ( UnIn, FileName, InitInp%WAMITInputsFile, 'WAMITInputsFile', & - 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + CALL ReadVar ( UnIn, FileName, InitInp%PRPInputsFile, 'PRPInputsFile', & + 'Filename for the PRP HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read WAMITInputsFile parameter.' + ErrMsg = ' Failed to read PRPInputsFile parameter.' ErrStat = ErrID_Fatal CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) CLOSE( UnIn ) @@ -936,12 +905,12 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) !------------------------------------------------------------------------------------------------- - ! WAMIT STEADY STATE INPUTS section + ! PRP STEADY STATE INPUTS section !------------------------------------------------------------------------------------------------- ! Header - CALL ReadCom( UnIn, FileName, 'WAMIT STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + CALL ReadCom( UnIn, FileName, 'PRP STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Failed to read Comment line.' @@ -953,13 +922,13 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) - ! uWAMITInSteady + ! uPRPInSteady - CALL ReadAry ( UnIn, FileName, InitInp%uWAMITInSteady, 6, 'uWAMITInSteady', & - 'WAMIT Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) + CALL ReadAry ( UnIn, FileName, InitInp%uPRPInSteady, 6, 'uPRPInSteady', & + 'PRP Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uWAMITInSteady parameter.' + ErrMsg = ' Failed to read uPRPInSteady parameter.' ErrStat = ErrID_Fatal CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) CLOSE( UnIn ) @@ -967,13 +936,13 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) END IF - ! uDotWAMITInSteady + ! uDotPRPInSteady - CALL ReadAry ( UnIn, FileName, InitInp%uDotWAMITInSteady, 6, 'uDotWAMITInSteady', & - 'WAMIT Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) + CALL ReadAry ( UnIn, FileName, InitInp%uDotPRPInSteady, 6, 'uDotPRPInSteady', & + 'PRP Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotWAMITInSteady parameter.' + ErrMsg = ' Failed to read uDotPRPInSteady parameter.' ErrStat = ErrID_Fatal CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) CLOSE( UnIn ) @@ -981,136 +950,136 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) END IF - ! uDotDotWAMITInSteady + ! uDotDotPRPInSteady - CALL ReadAry ( UnIn, FileName, InitInp%uDotDotWAMITInSteady, 6, 'uDotDotWAMITInSteady', & - 'WAMIT Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) + CALL ReadAry ( UnIn, FileName, InitInp%uDotDotPRPInSteady, 6, 'uDotDotPRPInSteady', & + 'PRP Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotDotWAMITInSteady parameter.' + ErrMsg = ' Failed to read uDotDotPRPInSteady parameter.' ErrStat = ErrID_Fatal CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) CLOSE( UnIn ) RETURN END IF - IF ( InitInp%WAMITInputsMod /= 1 ) THEN - InitInp%uWAMITInSteady = 0.0 - InitInp%uDotWAMITInSteady = 0.0 - InitInp%uDotDotWAMITInSteady = 0.0 - END IF - - - !------------------------------------------------------------------------------------------------- - ! Morison INPUTS section - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'Morison INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - - ! MorisonInputsMod - - CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsMod, 'MorisonInputsMod', & - 'Model for the Morison inputs', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read MorisonInputsMod parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! MorisonInputsFile - - CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsFile, 'MorisonInputsFile', & - 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read MorisonInputsFile parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - !------------------------------------------------------------------------------------------------- - ! Morison STEADY STATE INPUTS section - !------------------------------------------------------------------------------------------------- - - ! Header - - CALL ReadCom( UnIn, FileName, 'Morison STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read Comment line.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN + IF ( InitInp%PRPInputsMod /= 1 ) THEN + InitInp%uPRPInSteady = 0.0 + InitInp%uDotPRPInSteady = 0.0 + InitInp%uDotDotPRPInSteady = 0.0 END IF - - ! uMorisonInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uMorisonInSteady, 6, 'uMorisonInSteady', & - 'Morison Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uMorisonInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! uDotMorisonInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uDotMorisonInSteady, 6, 'uDotMorisonInSteady', & - 'Morison Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotMorisonInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - - ! uDotDotMorisonInSteady - - CALL ReadAry ( UnIn, FileName, InitInp%uDotDotMorisonInSteady, 6, 'uDotDotMorisonInSteady', & - 'Morison Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) - - IF ( ErrStat /= ErrID_None ) THEN - ErrMsg = ' Failed to read uDotDotMorisonInSteady parameter.' - ErrStat = ErrID_Fatal - CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - CLOSE( UnIn ) - RETURN - END IF - - IF ( InitInp%MorisonInputsMod /= 1 ) THEN - InitInp%uMorisonInSteady = 0.0 - InitInp%uDotMorisonInSteady = 0.0 - InitInp%uDotDotMorisonInSteady = 0.0 - END IF + !!------------------------------------------------------------------------------------------------- + !! Morison INPUTS section + !!------------------------------------------------------------------------------------------------- + ! + ! ! Header + ! + !CALL ReadCom( UnIn, FileName, 'Morison INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + ! + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read Comment line.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + !END IF + ! + ! + ! + ! ! MorisonInputsMod + ! + !CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsMod, 'MorisonInputsMod', & + ! 'Model for the Morison inputs', ErrStat, ErrMsg, UnEchoLocal ) + ! + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read MorisonInputsMod parameter.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + !END IF + ! + ! + ! ! MorisonInputsFile + ! + !CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsFile, 'MorisonInputsFile', & + ! 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) + ! + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read MorisonInputsFile parameter.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + !END IF + ! + ! + !!------------------------------------------------------------------------------------------------- + !! Morison STEADY STATE INPUTS section + !!------------------------------------------------------------------------------------------------- + ! + ! ! Header + ! + !CALL ReadCom( UnIn, FileName, 'Morison STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) + ! + !IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read Comment line.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + !END IF + ! + ! + ! + ! ! uMorisonInSteady + ! + ! CALL ReadAry ( UnIn, FileName, InitInp%uMorisonInSteady, 6, 'uMorisonInSteady', & + ! 'Morison Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) + ! + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read uMorisonInSteady parameter.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + ! END IF + ! + ! + ! ! uDotMorisonInSteady + ! + ! CALL ReadAry ( UnIn, FileName, InitInp%uDotMorisonInSteady, 6, 'uDotMorisonInSteady', & + ! 'Morison Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) + ! + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read uDotMorisonInSteady parameter.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + ! END IF + ! + ! + ! ! uDotDotMorisonInSteady + ! + ! CALL ReadAry ( UnIn, FileName, InitInp%uDotDotMorisonInSteady, 6, 'uDotDotMorisonInSteady', & + ! 'Morison Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) + ! + ! IF ( ErrStat /= ErrID_None ) THEN + ! ErrMsg = ' Failed to read uDotDotMorisonInSteady parameter.' + ! ErrStat = ErrID_Fatal + ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) + ! CLOSE( UnIn ) + ! RETURN + ! END IF + ! + !IF ( InitInp%MorisonInputsMod /= 1 ) THEN + ! InitInp%uMorisonInSteady = 0.0 + ! InitInp%uDotMorisonInSteady = 0.0 + ! InitInp%uDotDotMorisonInSteady = 0.0 + !END IF !------------------------------------------------------------------------------------------------- From b9ffc9dd78bf2829a1e0b2feb13a0ef60cd5ce8c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 20 Oct 2020 15:28:34 -0600 Subject: [PATCH 316/377] FlexSub: Bug fix: FGfull (for extra moment) didn't contain added masses --- modules/subdyn/src/SD_FEM.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 12ee81851..3e52becbf 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1048,8 +1048,6 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) ENDDO - ! Copy FG to FG_full since FG will be reduced later - p%FG_full(1:p%nDOF) = Init%FG(1:p%nDOF) ! Add concentrated mass to mass matrix DO I = 1, Init%nCMass @@ -1087,6 +1085,9 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) iGlob = p%NodesDOF(iNode)%List(3) ! uz Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO + + ! Copy FG to FG_full since FG will be reduced later + p%FG_full(1:p%nDOF) = Init%FG(1:p%nDOF) CALL CleanUp_AssembleKM() From ba75e8fdc81e93b44ecc6af56b412856f431cfb2 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 27 Oct 2020 11:15:09 -0600 Subject: [PATCH 317/377] Resolve Double Precision Compile on Windows with Intel Compiler --- modules/hydrodyn/src/SS_Excitation.f90 | 2 +- modules/hydrodyn/src/SS_Radiation.f90 | 4 ++-- modules/hydrodyn/src/WAMIT.f90 | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/SS_Excitation.f90 b/modules/hydrodyn/src/SS_Excitation.f90 index 0f440450e..5af0dd457 100644 --- a/modules/hydrodyn/src/SS_Excitation.f90 +++ b/modules/hydrodyn/src/SS_Excitation.f90 @@ -54,7 +54,7 @@ subroutine TransformStateSpaceMatrices( NBody, RotZ, C ) !.................................................................................................................................. integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) - real(SiKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(ReKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices integer(IntKi) :: i,j,indx real(R8Ki) :: R(3,3) diff --git a/modules/hydrodyn/src/SS_Radiation.f90 b/modules/hydrodyn/src/SS_Radiation.f90 index 4f0792716..d7635499d 100644 --- a/modules/hydrodyn/src/SS_Radiation.f90 +++ b/modules/hydrodyn/src/SS_Radiation.f90 @@ -54,8 +54,8 @@ subroutine TransformStateSpaceMatrices( NBody, RotZ, B, C ) !.................................................................................................................................. integer(IntKi), intent( in ) :: NBody ! Number of WAMIT bodies in this WAMIT object ( = 1 if NBodyMod > 1) real(R8Ki), intent( in ) :: RotZ(:) ! NBody heading angles (radians) - real(SiKi), intent( inout ) :: B(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices - real(SiKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(ReKi), intent( inout ) :: B(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices + real(ReKi), intent( inout ) :: C(:,:) ! Matrix data to be transformed, if NBodyMOD = 1 and NBody > 1 then we will be transforming the individual sub 6x6 matrices integer(IntKi) :: i,j,indx real(R8Ki) :: R(3,3) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 04b9be358..1a01c51b6 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -142,7 +142,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init REAL(SiKi), ALLOCATABLE :: HdroFreq (:) ! Frequency components inherent in the hydrodynamic added mass matrix, hydrodynamic daming matrix, and complex wave excitation force per unit wave amplitude vector (rad/s) REAL(SiKi), ALLOCATABLE :: HdroWvDir (:) ! Incident wave propagation heading direction components inherent in the complex wave excitation force per unit wave amplitude vector (degrees) REAL(ReKi) :: HighFreq ! The highest frequency component in the WAMIT file, not counting infinity. - REAL(ReKi) :: Omega ! Wave frequency (rad/s) + REAL(SiKi) :: Omega ! Wave frequency (rad/s) REAL(ReKi) :: PrvDir ! The value of TmpDir from the previous line (degrees) REAL(ReKi) :: PrvPer ! The value of TmpPer from the previous line (sec ) REAL(ReKi) :: SttcDim (6,6) ! Matrix used to redimensionalize WAMIT hydrostatic restoring output (kg/s^2, kg-m/s^2, kg-m^2/s^2) From e46e3b4a5a43260626c7a7cfcb9179e8a58299ae Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Tue, 27 Oct 2020 11:25:24 -0600 Subject: [PATCH 318/377] Fixed bug: External Hydro side-effects now use undisplaced configuration --- modules/hydrodyn/src/Morison.f90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index ba21f1cc1..d459acce6 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2491,7 +2491,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, real(ReKi) :: omega_s2(3) real(ReKi) :: pos1(3), pos2(3) real(ReKi) :: Imat(3,3) - real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), am(3,3), lstar, deltal + real(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), Am(3,3), lstar, deltal real(ReKi) :: C_1, C_2, a0b0, z1d, z2d, h real(ReKi) :: F_WMG(6), F_IMG(6), F_If(6), F_A(6), F_I(6), F_D(6), F_B1(6), F_B2(6) @@ -2889,8 +2889,10 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! External Hydrodynamic Side Loads + ! NOTE: All geometry-related calculations are based on the undisplaced configuration of the structure + DO i =1,N+1 ! loop through member nodes - z1 = u%Mesh%TranslationDisp(3, mem%NodeIndx(i)) + u%Mesh%Position(3, mem%NodeIndx(i)) + z1 = u%Mesh%Position(3, mem%NodeIndx(i)) if ( i > mem%i_floor .and. z1 <= 0.0 ) then ! node is above (or at? TODO: check) seabed and below or at free-surface) ! TODO: Note that for computational efficiency, we could precompute h_c and deltal for each element when we are NOT using wave stretching ! We would still need to test at time marching for nodes just below the free surface because that uses the current locations not the reference locations @@ -2905,8 +2907,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, deltal = mem%dl/2.0_ReKi - mem%h_floor ! TODO: h_floor is negative valued, should we be subrtracting it from dl/2? GJH h_c = 0.5_ReKi*(mem%dl/2.0_ReKi + mem%h_floor) else - pos1 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i)) + u%Mesh%Position(:, mem%NodeIndx(i)) - pos2 = u%Mesh%TranslationDisp(:, mem%NodeIndx(i+1)) + u%Mesh%Position(:, mem%NodeIndx(i+1)) + pos1 = u%Mesh%Position(:, mem%NodeIndx(i)) + pos2 = u%Mesh%Position(:, mem%NodeIndx(i+1)) if (pos1(3) <= 0.0 .and. 0.0 < pos2(3) ) then ! This node is just below the free surface !TODO: Needs to be augmented for wave stretching !TODO: Fix this one pos1 = u%Mesh%Position(:, mem%NodeIndx(i)) ! use reference position for following equation From dad617b47fdfed3bb0c8f77e563029c8199378ff Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 9 Nov 2020 09:31:03 -0700 Subject: [PATCH 319/377] Fixed issue where MD is used without HD Now using MD requires the use of HD, otherwise and error message is issued. --- modules/openfast-library/src/FAST_Subs.f90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 2b4324306..cbec7d903 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -1616,6 +1616,8 @@ SUBROUTINE ValidateInputData(p, m_FAST, ErrStat, ErrMsg) CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when MAP is used. Set CompHydro > 0 or CompMooring = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) ELSEIF (p%CompMooring == Module_FEAM) THEN CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when FEAMooring is used. Set CompHydro > 0 or CompMooring = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) + ELSEIF (p%CompMooring == Module_MD) THEN + CALL SetErrStat( ErrID_Fatal, 'HydroDyn must be used when MoorDyn is used. Set CompHydro > 0 or CompMooring = 0 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) END IF ELSE IF (p%CompMooring == Module_Orca) CALL SetErrStat( ErrID_Fatal, 'HydroDyn cannot be used if OrcaFlex is used. Set CompHydro = 0 or CompMooring < 4 in the FAST input file.', ErrStat, ErrMsg, RoutineName ) From ef01415e85401a62a0ba2b9ac34cd88d4770abe9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 10 Nov 2020 14:09:27 -0700 Subject: [PATCH 320/377] FlexSub: loads from CB displacements only for flating cases --- modules/subdyn/src/SubDyn.f90 | 14 +++---- modules/subdyn/src/SubDyn_Output.f90 | 4 +- modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 54 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 7ea95a20f..b7f689879 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -507,13 +507,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) else - ! We will add it in the "Full system" later - !m%UR_bar = matmul( p%TI , m%u_TP ) - !m%UR_bar_dot = matmul( p%TI , m%udot_TP ) - !m%UR_bar_dotdot = matmul( p%TI , m%udotdot_TP ) - !m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) - !m%UL_dot = m%UL_dot + matmul( p%PhiRb_TI, m%udot_TP ) - !m%UL_dotdot = m%UL_dotdot + matmul( p%PhiRb_TI, m%udotdot_TP ) + ! We know that the Guyan modes are rigid body modes. + ! We will add them in the "Full system" later endif ! --- Build original DOF vectors (DOF before the CB reduction) m%U_red (p%IDI__) = m%UR_bar @@ -538,6 +533,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_dot = m%U_red_dot m%U_full_dotdot = m%U_red_dotdot endif + + ! Storing elastic motion (full motion for fixed bottom, CB motion only for floating) + m%U_full_elast = m%U_full ! --- Place displacement/velocity/acceleration into Y2 output mesh DO iSDNode = 1,p%nNodes @@ -546,6 +544,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! if (p%Floating .and. GUYAN_RIGID_FLOATING) then ! For floating case, we add the Guyan motion contribution + ! This accounts for "rotations" effects, where the bottom node should "go up", and not just translate horizontally ! It corresponds to a rigid body motion the the TP as origin ! Rigid body motion of the point rIP0(1:3) = p%DP0(1:3, iSDNode) @@ -2620,6 +2619,7 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%UL_dotdot, p%nDOF__L, 'UL_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%DU_full, p%nDOF, 'DU_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full, p%nDOF, 'U_full', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_full_elast, p%nDOF, 'U_full_elast', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index b99b55126..fcee6c878 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -431,8 +431,8 @@ subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInput FirstOrSecond = pLst%ElmNds(iiNode,JJ) ! first or second node of the element to be considered sgn = NodeNumber_To_Sign(FirstOrSecond) ! Assign sign depending if it's the 1st or second node ElemNodes = p%Elems(iElem,2:3) ! first and second node ID associated with element iElem - X_e(1:6) = m%U_full (p%NodesDOF(ElemNodes(1))%List(1:6)) - X_e(7:12) = m%U_full (p%NodesDOF(ElemNodes(2))%List(1:6)) + X_e(1:6) = m%U_full_elast (p%NodesDOF(ElemNodes(1))%List(1:6)) + X_e(7:12) = m%U_full_elast (p%NodesDOF(ElemNodes(2))%List(1:6)) Xdd_e(1:6) = m%U_full_dotdot(p%NodesDOF(ElemNodes(1))%List(1:6)) Xdd_e(7:12) = m%U_full_dotdot(p%NodesDOF(ElemNodes(2))%List(1:6)) if (.not. bUseInputDirCos) then diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3ce6ad1af..3aec716c8 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -159,6 +159,7 @@ typedef ^ ^ ReKi DU_full {:} typedef ^ ^ ReKi U_full {:} - - typedef ^ ^ ReKi U_full_dot {:} - - typedef ^ ^ ReKi U_full_dotdot {:} - - +typedef ^ ^ ReKi U_full_elast {:} - - "Elastic displacements for computation of K ue (without rigid body mode for floating)" typedef ^ ^ ReKi U_red {:} - - typedef ^ ^ ReKi U_red_dot {:} - - typedef ^ ^ ReKi U_red_dotdot {:} - - diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 2c80e2b43..7b6c13e93 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -201,6 +201,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_elast !< Elastic displacements for computation of K ue (without rigid body mode for floating) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot @@ -5899,6 +5900,18 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%U_full_dotdot = SrcMiscData%U_full_dotdot ENDIF +IF (ALLOCATED(SrcMiscData%U_full_elast)) THEN + i1_l = LBOUND(SrcMiscData%U_full_elast,1) + i1_u = UBOUND(SrcMiscData%U_full_elast,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_elast)) THEN + ALLOCATE(DstMiscData%U_full_elast(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_elast.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_elast = SrcMiscData%U_full_elast +ENDIF IF (ALLOCATED(SrcMiscData%U_red)) THEN i1_l = LBOUND(SrcMiscData%U_red,1) i1_u = UBOUND(SrcMiscData%U_red,1) @@ -6032,6 +6045,9 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%U_full_dotdot)) THEN DEALLOCATE(MiscData%U_full_dotdot) ENDIF +IF (ALLOCATED(MiscData%U_full_elast)) THEN + DEALLOCATE(MiscData%U_full_elast) +ENDIF IF (ALLOCATED(MiscData%U_red)) THEN DEALLOCATE(MiscData%U_red) ENDIF @@ -6153,6 +6169,11 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! U_full_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%U_full_dotdot) ! U_full_dotdot END IF + Int_BufSz = Int_BufSz + 1 ! U_full_elast allocated yes/no + IF ( ALLOCATED(InData%U_full_elast) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_elast upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_elast) ! U_full_elast + END IF Int_BufSz = Int_BufSz + 1 ! U_red allocated yes/no IF ( ALLOCATED(InData%U_red) ) THEN Int_BufSz = Int_BufSz + 2*1 ! U_red upper/lower bounds for each dimension @@ -6409,6 +6430,21 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%U_full_elast) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_elast,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_elast,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%U_full_elast,1), UBOUND(InData%U_full_elast,1) + ReKiBuf(Re_Xferred) = InData%U_full_elast(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%U_red) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6781,6 +6817,24 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_elast not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_elast)) DEALLOCATE(OutData%U_full_elast) + ALLOCATE(OutData%U_full_elast(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_elast.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%U_full_elast,1), UBOUND(OutData%U_full_elast,1) + OutData%U_full_elast(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red not allocated Int_Xferred = Int_Xferred + 1 ELSE From 5bc69c826db2c7f2738e878c6189ebee0979ae16 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 10 Nov 2020 14:49:35 -0700 Subject: [PATCH 321/377] FlexSub: returning intial guess for cable DeltaL --- modules/subdyn/src/SD_FEM.f90 | 15 +++++++++++++-- modules/subdyn/src/SubDyn.f90 | 4 ++-- modules/subdyn/src/SubDyn_Registry.txt | 22 +++++++++++----------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 3e52becbf..8a80d2e5a 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1125,13 +1125,14 @@ INTEGER(IntKi) FUNCTION nDOF_Unconstrained() END SUBROUTINE AssembleKM !> Map control cable index to control channel index -subroutine ControlCableMapping(Init, p, ErrStat, ErrMsg) +subroutine ControlCableMapping(Init, uInit, p, ErrStat, ErrMsg) type(SD_InitType), intent(in ) :: Init !< init + type(SD_InputType), intent(inout) :: uInit !< init input guess type(SD_ParameterType), intent(inout) :: p !< param integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables - integer(IntKi) :: i, nCC, idCProp !< index, number of controlable cables, id of Cable Prop + integer(IntKi) :: i, nCC, idCProp, iElem !< index, number of controlable cables, id of Cable Prop integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 ErrMsg = "" @@ -1165,6 +1166,16 @@ subroutine ControlCableMapping(Init, p, ErrStat, ErrMsg) endif endif enddo + + ! --- DeltaL Guess for inputs + if (allocated(uInit%CableDeltaL)) deallocate(uInit%CableDeltaL) + call AllocAry(uInit%CableDeltaL, nCC, 'uInit%CableDeltaL', ErrStat2, ErrMsg2); if(Failed()) return; + do i = 1, nCC + iElem = p%CtrlElem2Channel(i,1) + ! DeltaL 0 = - Le T0 / (EA + T0) = - Le eps0 / (1+eps0) + uInit%CableDeltaL(i) = - p%ElemProps(iElem)%Length * p%ElemProps(iElem)%T0 / (p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area + p%ElemProps(iElem)%T0) + enddo + contains logical function Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ControlCableMapping') diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b7f689879..fd10553c9 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -248,8 +248,8 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO !Store mapping between nodes and elements CALL NodeCon(Init, p, ErrStat2, ErrMsg2); if(Failed()) return - !Store mapping between controllable elements and control channels - CALL ControlCableMapping(Init, p, ErrStat2, ErrMsg2); if(Failed()) return + !Store mapping between controllable elements and control channels, and return guess input + CALL ControlCableMapping(Init, u, p, ErrStat2, ErrMsg2); if(Failed()) return ! --- Allocate DOF indices to joints and members call DistributeDOF(Init, p ,ErrStat2, ErrMsg2); if(Failed()) return; diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3aec716c8..3af761d34 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -26,18 +26,18 @@ typedef ^ InitInputType MeshType SoilMesh - - - "Mesh f typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - # ============================== Define Initialization outputs here: ============================================================================================================================================ -typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - -typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - -typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ ^ ProgDesc Ver - - - "This module's name, version, and date" - # Linearization -typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - -typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - -typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - -typedef ^ InitOutputType LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - -typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - -typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - -typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - -typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ ^ CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ ^ LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +typedef ^ ^ LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ ^ LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ ^ IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - # ============================== Define Internal data types here: ============================================================================================================================================ typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" From 7205f72dee24714d872ab423452388f9b540c023 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Mon, 16 Nov 2020 10:51:43 -0700 Subject: [PATCH 322/377] Fixed two linearization bugs The index location for the SD LMesh was computed incorrectly The dUdy contribution from the ED Platform to the HD PRP Mesh was not being computed. --- modules/openfast-library/src/FAST_Lin.f90 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index d494c2708..30696f80f 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -3235,7 +3235,14 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapDat ErrStat = ErrID_None ErrMsg = "" - + + ! Add ED Platform mesh to HD PRP Mesh + ! use Indx_u_HD_PRP_Start + HD_Start = Indx_u_HD_PRP_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field + ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%PRPMesh, MeshMapData%ED_P_2_HD_PRP_P, HD_Start, ED_Out_Start, dUdy, .false.) + + if ( p_FAST%CompSub == Module_None ) then ! dU^{HD}/dy^{ED} !................................... @@ -3247,8 +3254,7 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapDat !!! ! while forming dUdy, too. !!!call Linearize_Point_to_Line2( y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, ErrStat2, ErrMsg2 ) - HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field + HD_Start = Indx_u_HD_Morison_Start(u_HD, y_FAST) ! start of u_HD%Morison%Mesh%TranslationDisp field call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%Morison%Mesh, MeshMapData%ED_P_2_HD_M_P, HD_Start, ED_Out_Start, dUdy, .false.) END IF @@ -3262,8 +3268,6 @@ SUBROUTINE Linear_HD_InputSolve_dy( p_FAST, y_FAST, u_HD, y_ED, y_SD, MeshMapDat !!!call Linearize_Point_to_Point( y_ED%PlatformPtMesh, u_HD%Mesh, MeshMapData%ED_P_2_HD_W_P, ErrStat2, ErrMsg2 ) HD_Start = Indx_u_HD_WAMIT_Start(u_HD, y_FAST) ! start of u_HD%Mesh%TranslationDisp field - - ED_Out_Start = Indx_y_ED_Platform_Start(y_ED, y_FAST) ! start of y_ED%PlatformPtMesh%TranslationDisp field call Assemble_dUdy_Motions(y_ED%PlatformPtMesh, u_HD%WAMITMesh, MeshMapData%ED_P_2_HD_W_P, HD_Start, ED_Out_Start, dUdy, .false.) END IF @@ -4244,7 +4248,7 @@ FUNCTION Indx_u_SD_LMesh_Start(u_SD, y_FAST) RESULT(SD_Start) INTEGER :: SD_Start !< starting index of this mesh in SubDyn inputs - SD_Start = Indx_u_SD_TPMesh_Start(u_SD, y_FAST) + u_SD%TPMesh%NNodes**18 ! 6 fields with 3 components + SD_Start = Indx_u_SD_TPMesh_Start(u_SD, y_FAST) + u_SD%TPMesh%NNodes*18 ! 6 fields with 3 components END FUNCTION Indx_u_SD_LMesh_Start !---------------------------------------------------------------------------------------------------------------------------------- From aa3b5da93805ce42fb45020af72a2eb5198c9c0f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 1 Dec 2020 14:19:31 -0700 Subject: [PATCH 323/377] Update of SubDyn documentation --- docs/Makefile | 19 + docs/conf.py | 5 +- docs/source/user/subdyn/appendixF.rst | 2 + .../subdyn/examples/OC4_Jacket_SD_Input.dat | 4 +- .../user/subdyn/figs/ElementsDefinitions.png | Bin 0 -> 331420 bytes .../user/subdyn/figs/ElementsDefinitions.svg | 1132 ++++++++++++++ docs/source/user/subdyn/figs/FEJointPin.png | Bin 0 -> 47328 bytes docs/source/user/subdyn/figs/FEJointPin.svg | 815 ++++++++++ docs/source/user/subdyn/figs/FEPreTension.png | Bin 0 -> 47130 bytes docs/source/user/subdyn/figs/FEPreTension.svg | 905 +++++++++++ docs/source/user/subdyn/input_files.rst | 187 ++- docs/source/user/subdyn/introduction.rst | 3 +- docs/source/user/subdyn/references_SD.bib | 21 + docs/source/user/subdyn/theory.rst | 1338 ++++++++++++++--- 14 files changed, 4181 insertions(+), 250 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/source/user/subdyn/figs/ElementsDefinitions.png create mode 100644 docs/source/user/subdyn/figs/ElementsDefinitions.svg create mode 100644 docs/source/user/subdyn/figs/FEJointPin.png create mode 100644 docs/source/user/subdyn/figs/FEJointPin.svg create mode 100644 docs/source/user/subdyn/figs/FEPreTension.png create mode 100644 docs/source/user/subdyn/figs/FEPreTension.svg diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..98dc07302 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ + +# You can set these variables from the command line. +ALLSPHINXOPTS = -c conf.py +SPHINXBUILD = sphinx-build +PAPER = +ALLSPHINXOPTS = -d _build/doctrees $(SPHINXOPTS) . + +BUILDDIR = _build + + +all: html + +$(BUILDDIR): + mkdir $(BUILDDIR) + +html: $(BUILDDIR) + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR) + @echo + @echo "Build finished. The HTML pages are in _build/html." diff --git a/docs/conf.py b/docs/conf.py index 35f5cd04c..63a5cf735 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -245,7 +245,10 @@ def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): ] def setup(app): - app.add_css_file('css/math_eq.css') + try: + app.add_css_file('css/math_eq.css') + except: + pass app.add_object_type( "confval", "confval", diff --git a/docs/source/user/subdyn/appendixF.rst b/docs/source/user/subdyn/appendixF.rst index dd048dfa9..c73ea8725 100644 --- a/docs/source/user/subdyn/appendixF.rst +++ b/docs/source/user/subdyn/appendixF.rst @@ -31,6 +31,8 @@ V1.04.00 (September 2020) - Inclusion of soil-structure interaction (SSI) via flexible degrees of fixity at the restrained nodes and a new input file that allows for 6x6 stiffness and mass matrices that simulate boundary conditions at those nodes. +- Controllable pretension cable elements + V1.03.00a-rrd (September 2017) ------------------------------ diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index ad619999d..391cba6d3 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -252,8 +252,8 @@ COSMID COSM11 COSM12 COSM13 COSM21 COSM22 COSM23 COSM31 (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) ------------------------ JOINT ADDITIONAL CONCENTRATED MASSES-------------------------- 0 NCmass - Number of joints with concentrated masses; Global Coordinate System -CMJointID JMass JMXX JMYY JMZZ - (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) +CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ + (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) ---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. IT can also … False OutCOSM - Output cosine matrices with the selected output member forces (flag) diff --git a/docs/source/user/subdyn/figs/ElementsDefinitions.png b/docs/source/user/subdyn/figs/ElementsDefinitions.png new file mode 100644 index 0000000000000000000000000000000000000000..5c949f4a461a4acb9a4aa1ce48cb2299e04323c0 GIT binary patch literal 331420 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/subdyn/figs/ElementsDefinitions.svg b/docs/source/user/subdyn/figs/ElementsDefinitions.svg new file mode 100644 index 000000000..1d33ad96d --- /dev/null +++ b/docs/source/user/subdyn/figs/ElementsDefinitions.svg @@ -0,0 +1,1132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Members + Elements (after subdivision) + + + Joints (from input file) Joint Axis + Joints (after subdivision) + + + + Element nodal DOFs Element frame + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rigid links + + Rigid link assembly + + diff --git a/docs/source/user/subdyn/figs/FEJointPin.png b/docs/source/user/subdyn/figs/FEJointPin.png new file mode 100644 index 0000000000000000000000000000000000000000..6ef0e6ddb1c1702309557c34e4f83b942191615c GIT binary patch literal 47328 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + xk + k + + + + + + + + + + + + + + + l + xl + p + + + + + + + + p2 + p1 + + + + diff --git a/docs/source/user/subdyn/figs/FEPreTension.png b/docs/source/user/subdyn/figs/FEPreTension.png new file mode 100644 index 0000000000000000000000000000000000000000..98fa929d77b693d5eeddb236b4adb39dc4770283 GIT binary patch literal 47130 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 YFJhKIfg^aU9Fys| + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L0 + uz + Le + ux + θ + + T0 + Td + + Ld + + ∆L0<0 + + + + + diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst index a88da7bea..a0dbfd7b8 100644 --- a/docs/source/user/subdyn/input_files.rst +++ b/docs/source/user/subdyn/input_files.rst @@ -168,17 +168,19 @@ Adams-Bashforth-Moulton 4\ :sup:`th`-order explicit predictor-corrector (ABM4); 4) Adams-Moulton implicit 2\ :sup:`nd`-order (AM2). See Section on how to properly select this and the previous parameter values. -**SttcSolve** is a flag that specifies whether SIM (see Sections 5 and -6) shall be employed. Through this method, all (higher frequency) modes +**SttcSolve** is a flag that specifies whether the static improvement method +(SIM, see :numref:`SD_SIM`) +shall be employed. Through this method, all (higher frequency) modes that are not considered by the C-B reduction are treated -quasi-statically (see Section for more details). This treatment helps +quasi-statically. This treatment helps minimize the number of retained modes needed to capture effects such as static gravity and buoyancy loads, and high-frequency loads transferred from the turbine. **ExtraMoment** is a flag to specify whether the extra moment due to -the interface lever arm is to be included in the interface reactions. +the lever arm from the deflection of the structure is to be added to the loads passed to SubDyn. +See section :numref:`SD_Loads` for details. FEA and Craig-Bampton Parameters @@ -205,23 +207,26 @@ finite-element model is retained and **Nmodes** is ignored. **Nmodes** sets the number of internal C-B modal DOFs to retain in the C-B reduction. **Nmodes** = 0 corresponds to a Guyan (static) reduction. **Nmodes** is ignored if **CBMod** is set to FALSE, -meaning the full finite-element model is retained by keeping all modes. +meaning the full finite-element model is retained by keeping all modes +(i.e. a modal analysis is still done, and all the modes are used as DOFs) . + **JDampings** specifies value(s) of damping coefficients as a percentage of critical damping for the retained C-B modes. Distinct damping coefficients for each retained mode should be listed on the same line, separated by white space. If the number of **JDampings** is less than the number of retained modes, the last value will be replicated for -all the remaining modes. +all the remaining modes. (see :numref:`SD_DampingSpecifications`) +**GuyanDampMod** Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] (see :numref:`SD_DampingSpecifications`) -**GuyanDampMod** Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] **RayleighDamp** Mass and stiffness proportional damping coefficients (:math:`(\alpha,\beta)` Rayleigh damping) [only if GuyanDampMod=1] -Guyan damping matrix (6x6) [only if GuyanDamgMod=2] +Guyan damping matrix (6x6) [only if GuyanDamgMod=2] (see :numref:`SD_DampingSpecifications`) + -**Guyan damping matrix**: The 6 lines following this input line consits of the - 6x6 coefficients of the damping matrix to be applied at the interface. +**Guyan damping matrix**: +The 6 lines following this input line consits of the 6x6 coefficients of the damping matrix to be applied at the interface. (see :numref:`SD_DampingSpecifications`) For more information on these parameters and guidelines on how to set @@ -245,6 +250,19 @@ does not consider overlap when multiple members meet at a common joint, therefore, it tends to overestimate the total substructure mass. Member overlap and node offset calculations will be considered in a future release of SubDyn. +The fifth column specifies the **JointType** (see :numref:`SD_FEM`): + +- Cantilever joints (*JointType=1*) + +- Universal joint (*JointType=2*) + +- Pin joint (*JointType=3*) + +- Ball joint (*JointType=4*) + +The three following columns specify the vector coordinates of the direction around which rotation is free for a pin joints. +The last column, **JointStiff** specify a value of additional stiffness to be added to the "free" rotational DOFs of Ball, Pin and Universal joints. + Note for HydroDyn coupling: modeling a fixed-bottom substructure embedded into the seabed (e.g., through piles or suction buckets) @@ -257,6 +275,19 @@ motion and loads across meshes in a physically relevant manner (Sprague et al. 2014), but consistency between the joints and members in HydroDyn and SubDyn is advised. + +An example of joint table is given below + +.. code:: + + 3 NJoints - Number of joints (-) + JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff + (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) + 101 0.0 0.0 50.0 1 0.0 0.0 0.0 0.0 + 111 0.0 0.0 10.0 2 0.0 1.0 0.0 100.0 + 102 0.0 0.0 -45.0 1 0.0 0.0 0.0 0.0 + + Base Reaction Joints ~~~~~~~~~~~~~~~~~~~~~ @@ -281,6 +312,22 @@ and the associated matrix elements potentially provided in the **SSIfile** will be ignored. +An example of base reaction and interface table is given below + +.. code:: + + ------------------- BASE REACTION JOINTS + 1 NReact - Number of Joints with reaction forces + RJointID RctTDXss RctTDYss RctTDZss RctRDXss RctRDYss RctRDZss SSIfile + (-) (flag) (flag) (flag) (flag) (flag) (flag) (string) + 61 1 1 1 1 1 1 "SSI.txt" + ------------------- INTERFACE JOINTS + 1 NInterf - Number of interface joints locked to the Transition Piece (TP) + IJointID ItfTDXss ItfTDYss ItfTDZss ItfRDXss ItfRDYss ItfRDZss + (-) (flag) (flag) (flag) (flag) (flag) (flag) + 24 1 1 1 1 1 1 + + Interface Joints ~~~~~~~~~~~~~~~~ @@ -317,9 +364,32 @@ specifies the ending joint, corresponding to an identifier MEMBER X-SECTION PROPERTY table (discussed next) for starting cross-section properties and **MPropSetID2** specifies the identifier for ending cross-section properties, allowing for tapered members. +The sixth column specify the member type **MType**. +A member is one of the three following types (see :numref:`SD_FEM`): + +- Beams (*MType=1*), Euler-Bernoulli (*FEMMod=1*) or Timoshenko (*FEMMod=3*) + +- Pretension cables (*MType=2*) + +- Rigid link (*MType=3*) + **COSMID** refers to the IDs of the members’ cosine matrices for noncircular members; the current release ignores this column. + +An example of member table is given below + +.. code:: + + 2 NMembers - Number of frame members + MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID + (-) (-) (-) (-) (-) (-) (-) + 10 101 102 2 2 1 + 11 102 103 2 2 1 + + + + Member Cross-Section Properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -353,6 +423,70 @@ moment of inertia (**XsecJ0**). The member cosine matrix section (see Section ) will help determine the correct orientation of the members within the assembly. + + + + +Cable Properties +~~~~~~~~~~~~~~~~ + + +Members that are specified as pretension cables (**MType=2**), +have their properties defined in the cable properties table. +The table lists for each cable property: the property ID (**PropSetID**), the cable tension stiffness (**EA**), +the material density (**MatDens**), the pretension force (**T0**), and the control channel (**CtrlChannel**). +The control channel is only used if ServoDyn provides dedicated control signal, in which case +the cable tension (given in terms of a length change :math:`\Delta l`) +is dynamically changed (see :numref:`SD_ControlCable`). +The FEM representation of pretension cable is given in :numref:`SD_PretensionCable`. + +An example of cable properties table is given below: + +.. code:: + + -------------------------- CABLE PROPERTIES ------------------------------------- + 2 NCablePropSets - Number of cable cable properties + PropSetID EA MatDens T0 CtrlChannel + (-) (N) (kg/m) (N) (-) + 11 210E7 7850.0 2E7 1 + 10 210E7 7850.0 1E7 0 + + +Rigid link Properties +~~~~~~~~~~~~~~~~~~~~~ + +Members that are specified as rigid links (**MType=3**), +have their properties defined in the rigid link properties table. +The table lists the material density (**MatDens**) for each rigid link property. +The FEM representation of rigid links is given in :numref:`SD_RigidLinks`. + +An example of rigid link properties table is given below + +.. code:: + + ----------------------- RIGID LINK PROPERTIES ------------------------------------ + 1 NRigidPropSets - Number of rigid link properties + PropSetID MatDens + (-) (kg/m) + 12 7850.0 + 3 7000.0 + + + + + + + + + + + + + + + + + Member Cosine Matrices COSM (i,j) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This table is not currently used by SubDyn, but in future releases it @@ -376,7 +510,38 @@ each joint distinguished by **CMJointID** (corresponding to an identifier, **JointID**, from the STRUCTURE JOINTS table), **JMass** specifies the lumped mass value, and **JMXX**, **JMYY**, **JMZZ** specify the mass second moments of inertia with respect to the SS -coordinate system. +coordinate system (not the element system). +Latest version of SubDyn accept 6 additional columns +(**JMXY**, **JMXZ**, **JMYZ**, **MCGX**, **MCGY**, **MCGZ**) +to specify off-diagonal terms. + +The additional mass matrix added to the node is computed in the SS system as follows: + +.. math:: + + M_\text{add}= + \begin{bmatrix} + m & 0 & 0 & 0 & z m & -y m \\ + 0 & m & 0 & -z m & 0 & x m \\ + 0 & 0 & m & y m & -x m & 0 \\ + 0 & -z m & y m & J_{xx} + m (y^2+z^2) & J_{xy} - m x y & J_{xz} - m x z \\ + z m & 0 & -x m & J_{xy} - m x y & J_{yy} + m (x^2+z^2) & J_{yz} - m y z \\ + -y m & x m & 0 & J_{xz} - m x z & J_{yz} - m y z & J_{zz} + m (x^2+y^2)\\ + \end{bmatrix} + +with :math:`m` the parameter **JMass**, and :math:`x,y,z`, the CG offsets. + + +An example of concentrated mass table is given below: + +.. code:: + + 2 NCmass - Number of joints with concentrated masses; (SS coord system) + CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ + (-) (kg) (kgm^2) (kgm^2) (kgm^2) (kgm^2) (kgm^2) (kgm^2) (m) (m) (m) + 1 4090 0 0 0 0 0 0 0 0 0 + 3 4.2e6 0 0 3.3e9 0 0 0 0 0 0 + Output: Summary and Outfile ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/user/subdyn/introduction.rst b/docs/source/user/subdyn/introduction.rst index f86691ab4..c5b8e1bf2 100644 --- a/docs/source/user/subdyn/introduction.rst +++ b/docs/source/user/subdyn/introduction.rst @@ -31,7 +31,8 @@ frame finite-element beam model (LFEB), and (2) a dynamics system reduction via the Craig-Bampton(C-B) method, together with a static-improvement method (SIM), greatly reducing the number of modes needed to obtain an accurate solution. More details can be found in -Section 6, and in :cite:`song2013`, :cite:`damiani2013`, :cite:`damiani2013omae`. +Section 6, and in :cite:`song2013`, :cite:`damiani2013`, +:cite:`damiani2013omae`, :cite:`jonkmantcf`. In SubDyn, the substructure is considered to be either clamped or supported by springs at the seabed, and rigidly connected to the diff --git a/docs/source/user/subdyn/references_SD.bib b/docs/source/user/subdyn/references_SD.bib index a4f0e90fc..7e610dbea 100644 --- a/docs/source/user/subdyn/references_SD.bib +++ b/docs/source/user/subdyn/references_SD.bib @@ -136,3 +136,24 @@ @inproceedings{damiani2013omaeB } +@techreport{felippa, + title={Introduction to finite element methods - Lecture notes (ASEN 5007)}, + author={Carlos A. Felippa}, + institution={{Department of Aerospace Engineering Sciences and Center for Aerospace Structures, University of Colorado, Boulder, CO, USA}}, + year={2004} +} + +@book{cook, + author = {Robert D. Cook }, + title = {Concepts and Applications of Finite Element Analysis}, + year = {2001}, + publisher= {John Wiley \& Sons} +} + +@techreport{jonkmantcf, + title={Implementation of Substructure Flexibility and Member-Level Load Capabilities for Floating Offshore Wind Turbines in OpenFAST}, + author={Jason Jonkman and Emmanuel Branlard and Matthew Hall and Greg Hayman and Andy Platt and Amy Robertson}, + institution={National Renewable Energy Laboratory}, + number={NREL/TP-5000-76822}, + year=2020 +} diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 47eda061f..4bfbd1765 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -10,7 +10,7 @@ Overview This section focuses on the theory behind the SubDyn module. SubDyn relies on two main engineering approaches: (1) a linear frame -finite-element beam model (LFEB), and (2) a dynamics system reduction +finite-element model (LFEM), and (2) a dynamics system reduction via the Craig-Bampton (C-B) method together with a static-improvement method (SIM), greatly reducing the number of modes needed to obtain an accurate solution. @@ -27,9 +27,9 @@ that varied in base geometry, load paths, sizes, supported towers, and turbine masses were analyzed under extreme loads using nonlinear and linear models. The results revealed that the nonlinear behavior was mainly caused by the mono-tower response and had little effect on the -multimember support structures. Therefore, an LFEB model for the +multimember support structures. Therefore, an LFEM model for the substructure is considered appropriate for wind turbine substructures. -The LFEB can accommodate different element types, including +The LFEM can accommodate different element types, including Euler-Bernoulli and Timoshenko beam elements of either constant or longitudinally tapered cross sections (Timoshenko beam elements account for shear deformation and are better suited to represent low aspect @@ -78,7 +78,7 @@ and the number of elements for each member. The following sections discuss the integration of SubDyn within the FAST framework, the main coordinate systems used in the module, and the -theory pertaining to the LFEB, the C-B reduction, and SIM. The +theory pertaining to the LFEM, the C-B reduction, and SIM. The state-space formulations to be used in the time-domain simulation are also presented. The last section discusses the calculation of the base reaction calculation. For further details, see also :cite:`song2013`. @@ -253,14 +253,117 @@ releases, the user will need to input cosine matrices to indicate the final orientation of the member principal axes with respect to the global reference frame. -Linear Finite-Element Beam Model --------------------------------- +.. _SD_FEM: + +Finite-Element Model - Elements and Constraints +----------------------------------------------- + +Definitions +~~~~~~~~~~~ + +Figure :numref:`fig:ElementsDefinitions` is used to illustrate some of the definitions used. +The model of the substructure is assumed to consists of +different members. +A member is delimited by two joints. +A joint is defined by the coordinates of a point of the +undeflected structure and a type (*JointType*). The type of a joint defines the +boundary condition or constraint of all the members that are attached to +this joint. +The following joints are supported: + +- Cantilever joints (*JointType=1*) + +- Universal joint (*JointType=2*) + +- Pin joint (*JointType=3*) + +- Ball joint (*JointType=4*) + +A member is one of the three following types: + +- Beams (*MType=1*), Euler-Bernoulli (*FEMMod=1*) or Timoshenko (*FEMMod=3*) + +- Pretension cables (*MType=2*) + +- Rigid link (*MType=3*) + +Beam members may be split into several elements to increase the accuracy of the model (using +the input parameter *NDiv*). Member of other types (rigid links and +pretension cables) are not split. In this document, the term *element* +refers to: a sub-division of a beam member or a member of another type +than beam (rigid-link or pretension cable). The term *joints* refers to +the points defining the extremities of the members. Some joints are +defined in the input file, while others arise from the subdivision of +beam members. The end points of an elements are called nodes and each +node consists of 6 degrees of freedom (DOF) for the element implemented. +In the current implementation, no geometrical offsets are assumed between a joint and the node of an +element, or between the nodes of connected elements. + +.. figure:: figs/ElementsDefinitions.png + :alt: Definitions + :name: fig:ElementsDefinitions + :width: 80.0% + + Definitions of members, element, joints, nodes and rigid assemblies. + +.. _SD_FEM_Process: + +FEM process - from elements to system matrices +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The process to obtain a FE representation of the system (performed at initialization) is as follows: + +- Elements: The mass and stiffness matrices of each element are computed and transformed to global coordinates using directional cosine matrices + +- Assembly: The element matrices are inserted into the full system matrices. The DOFs of cantilever joints are mapped to each other. The translational DOFs of the nodes linked by a joint different from a cantilever joint are mapped to each other, but the rotational DOFs of each individual nodes are retained in this system. The vector of degrees of freedom of this full system is noted :math:`\boldsymbol{x}` + +- Constraints elimination: A direct-elimination technique is used to apply the constraints introduced by the joints and the rigid links. The elimination consists in forming a matrix :math:`\boldsymbol{T}` and a reduced set of degrees of freedom :math:`\boldsymbol{\tilde{x}}` such that :math:`\boldsymbol{x}=\boldsymbol{T} \boldsymbol{\tilde{x}}`. + +- CB-reduction: The Craig-Bampton reduction technique is used to obtain a reduced set of degrees of freedom (interface DOFs and Craig-Bampton modes) + +- Boundary conditions: The displacements boundary conditions are then applied (e.g. for a fixed bottom foundation) + +The remaining of the section focuses on the element matrices, +and the account of the constraints introduced by the joints and rigid links. +The Craig-Bampton reduction is described in :numref:`GenericCBReduction`. + + +Self-Weight Loads +~~~~~~~~~~~~~~~~~ +The loads caused by self-weight are precomputed during initialization +based on the undisplaced configuration. It is therefore assumed that the +displacements will be small and that P-delta effects are small for the +substructure. +The "extra" moment may be accounted for using the flag *ExtraMoment*, +see section :numref:`SD_Loads`. +For a nontapered beam element, the lumped loads caused by +gravity to be applied at the end nodes are as follows (in the global +coordinate system): + +.. math:: :label: FG + + \left\{ F_G \right\} = \rho A_z g + \begin{bmatrix} 0 \\ + 0 \\ + -\frac{L_e}{2} \\ + -\frac{L_e^2}{12} D_{c2,3} \\ + \frac{L_e^2}{12} D_{c1,3} \\ + 0\\ + 0\\ + 0\\ + -\frac{L_e}{2}\\ + \frac{L_e^2}{12} D_{c2,3}\\ + -\frac{L_e^2}{12} D_{c1,3}\\ + 0 + \end{bmatrix} + +Note also that if lumped masses exist (selected by the user at +prescribed joints), their contribution will be included as concentrated +forces along global *Z* at the relevant nodes. -In SubDyn, the LFEB can accommodate different two-node beam element -types, including Euler-Bernoulli and Timoshenko beam elements, either of -constant or tapered cross sections. The tapered element formulation has -been derived, but has not been implemented in the current SubDyn -release. + +Beam Element Formulation +~~~~~~~~~~~~~~~~~~~~~~~~ The uniform and tapered Euler-Bernoulli beam elements are displacement-based and use third-order interpolation functions that @@ -269,10 +372,6 @@ uniform Timoshenko beam element is derived by introducing the shear deformation into the uniform Euler-Bernoulli element, so the displacements are represented by third-order interpolation functions as well. - -Element Formulation -~~~~~~~~~~~~~~~~~~~ - Following the classic Timoshenko beam theory, the generic two-node element stiffness and consistent mass matrices can be written as follows (see, for instance, :cite:`panzer2009`): @@ -392,42 +491,793 @@ system via :math:`{[ \mathbf{D_c} ]}` as shown in the following equations: where *m* and *k* are element matrices in the global coordinate system. -Self-Weight Loads -~~~~~~~~~~~~~~~~~ -The loads caused by self-weight are precomputed during initialization -based on the undisplaced configuration. It is therefore assumed that the -displacements will be small and that P-delta effects are small for the -substructure. For a nontapered beam element, the lumped loads caused by -gravity to be applied at the end nodes are as follows (in the global -coordinate system): -.. math:: :label: FG +.. _SD_PretensionCable: + +Pretension Cable Element Formulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +The master stiffness equations of FEM assumes that the forces vanish if +all displacements also vanish, that is, the relation between force and +displacement is linear, +:math:`\boldsymbol{f}=\boldsymbol{K}\boldsymbol{u}`. This assumption +does not hold if the material is subject to so-called initial strain, +initial stress of prestress. Such effects may be produced by temperature +changes and pretensions (or lack-of-fit fabrications). These effects are +for instance discussed in the notes of +Felippa :cite:`felippa`. + +Pretension cables may be modelled by assuming an initial elongation of a +truss element and considering the restoring force this initial +elongation may have in both the longitudinal and orthogonal direction. + + +Derivation +^^^^^^^^^^ + +A pretension cable oriented along the :math:`z`-direction is considered. +To simplify the derivation, the left point is assumed fixed and only the +right point deflects. The notations are illustrated in :numref:`fig:FEPreTension`. + +.. figure:: figs/FEPreTension.png + :alt: Pretension + :name: fig:FEPreTension + :width: 50.0% + + Notations used for the derivation of the pretension cable equation + + +The length of the element prior to the pretension is written +:math:`L_0`, and its axial stiffness is :math:`k=EA/L_0`. In this +equilibrium position the stress in the cable is zero. The user inputs +for this elements are selected as: the un-displaced joint locations +(while pre-tensioned) :math:`\boldsymbol{x}_1` and +:math:`\boldsymbol{x}_2`, the elongation stiffness :math:`EA`, and the +change in length :math:`\Delta L_0 = L_0-L_e` (:math:`<0`). The +pretension force :math:`T_0` is a derived input. The following +quantities are defined: + +.. math:: + + \begin{aligned} + L_e=\lVert\boldsymbol{x}_2-\boldsymbol{x}_1\rVert + ,\quad + \epsilon_0=\frac{T_0}{EA} + ,\quad + L_0=\frac{L_e}{1+\epsilon_0}\end{aligned} + +The different variables are defined as function of the inputs as +follows: + +.. math:: + + \begin{aligned} + L_0=L_e+\Delta L_0 + \qquad + T_0= - E A \frac{\Delta L_0}{L_0} + ,\qquad + \epsilon_0=\frac{T_0}{EA} = \frac{-\Delta L_0}{L_0} = \frac{-\Delta L_0}{L_e+\Delta L_0 }\end{aligned} + +The degrees of freedom for the deflections of the cable, +:math:`(u_x, u_z)`, are measured from a position which is not the +equilibrium position, but a position that is offset from the equilibrium +position, such that the pretensioned length of the element is +:math:`L_e>L_0`. The stress in the cable for :math:`u_z=0` is noted +:math:`\epsilon_0=(L_e-L_0)/L_0`, or :math:`L_e=L_0(1+\epsilon_0)`. The +initial tension in the cable is +:math:`\boldsymbol{T}_0=-k(L_e-L_0)\,\boldsymbol{e}_z=- E A \epsilon_0\, \boldsymbol{e}_z`. +In its deflected position, the length of the cable is: + +.. math:: + + \begin{aligned} + L_d =\sqrt{(L_e+u_z)^2 + u_x^2} + =L_e\sqrt{1+\frac{2u_z}{L_e} + \frac{u_z^2}{L-e^2}+\frac{u_x^2}{L_e^2}} + \approx L_e \left(1+\frac{u_z}{L_e}\right) + \label{eq:PreTensionLength}\end{aligned} + +where the deflections are assumed small compared to the element length +:math:`L_e`, :math:`u_x\ll L_e` and :math:`u_z\ll L_e`, and only the +first order terms are kept. The tension force in the deflected cable is +then :math:`\boldsymbol{T}_d=-k(L_d-L_0) \boldsymbol{e}_r` where the +radial vector is the vector along the deflected cable such that: + +.. math:: + + \begin{aligned} + \boldsymbol{e}_r=\cos\theta \boldsymbol{e}_z +\sin\theta \boldsymbol{e}_x + ,\quad\text{with}\quad + \cos\theta=\frac{L_e+u_z}{L_d} + \approx 1 + ,\quad + \sin\theta= \frac{u_x}{L_d} + \approx \frac{u_x}{L_e}(1-\frac{u_z}{L_e}) + \approx \frac{u_x}{L_e} + \label{eq:PreTensionRadial}\end{aligned} + +The components of the tension force are then: + +.. math:: + + \begin{aligned} + T_{d,z}&= -k(L_d-L_0)\cos\theta \approx -\frac{EA}{L_0}(L_e-L_0+u_z)\, 1\, + = -EA\epsilon_0-\frac{EA}{L_0}u_z + \nonumber + \\ + T_{d,x}&= -k(L_d-L_0)\sin\theta \approx -\frac{EA}{L_0}(L_e-L_0+u_z)\frac{u_x}{L_e} + \approx -EA\epsilon_0\frac{u_x}{L_e} + = -\frac{EA\epsilon_0}{L_0(1+\epsilon_0)}u_x + \label{eq:PreTensionForce}\end{aligned} + +Finite element formulation of a pretension cable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The rotational degrees of freedom are omitted for conciseness since +these degrees of freedom are not considered in this cable element. The +linear formulation from is applied to both nodes of a finite element, +interpreting the force at each node as the internal force that the +element exert on the nodes. Using this convention, the pretension cable +element can be represented with an element stiffness matrix +:math:`\boldsymbol{K}_e` and an additional nodal load vector +:math:`\boldsymbol{f}_{e,0}` such that the static equilibrium equation +of the element writes +:math:`\boldsymbol{f}_e=\boldsymbol{K}_e\boldsymbol{u}+\boldsymbol{f}_{e,0}`, +with: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + f_{x,1}\\ + f_{y,1}\\ + f_{z,1}\\ + f_{x,2}\\ + f_{y,2}\\ + f_{z,2}\\ + \end{bmatrix} + = + \frac{EA}{L_0} + \begin{bmatrix} + \frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 & -\frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 \\ + 0 & \frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 & -\frac{\epsilon_0}{1+\epsilon_0} & 0 \\ + 0 & 0 & 1 & 0 & 0 & -1\\ + -\frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 & \frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 \\ + 0 & -\frac{\epsilon_0}{1+\epsilon_0} & 0 & 0 & \frac{\epsilon_0}{1+\epsilon_0} & 0 \\ + 0 & 0 & -1 & 0 & 0 & 1 \\ + \end{bmatrix} + \begin{bmatrix} + u_{x,1}\\ + u_{y,1}\\ + u_{z,1}\\ + u_{x,2}\\ + u_{y,2}\\ + u_{z,2}\\ + \end{bmatrix} + + + EA\epsilon_0 + \begin{bmatrix} + 0\\ + 0\\ + -1\\ + 0\\ + 0\\ + 1\\ + \end{bmatrix} + \label{eq:StiffnessMatrixCable}\end{aligned} + +The relation above is expressed in the element coordinate system. The +stiffness matrix and force vector are transferred to the global system +during the assembly process. Inserting :math:`\epsilon_0=0` in the above +equations leads to the formulation of a truss element. The linear model +above is only valid for :math:`L_d-L_0>0`, that is +:math:`(L_e-L_0+u_{z,2}-u_{z,1})>0`, and the implementation should abort +if this condition is not reached at a given time. If the cable has a +positive mass density :math:`\rho`, the mass matrix of the element is +given by: + +.. math:: + + \begin{aligned} + \boldsymbol{M}_e = \rho L_e + \left[ + \begin{array}{*{12}c} + 13/35 & 0 & 0 & & & & 9/70 & 0 & 0 & & & \\ + 0 & 13/35 & 0 & & \boldsymbol{0}_3 & & 0 & 9/70 & 0 & & \boldsymbol{0}_3 & \\ + 0 & 0 & 1/3 & & & & 0 & 0 & 1/6 & & & \\ + & & & & & & & & & & & \\ + & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & \\ + & & & & & & & & & & & \\ + 9/70 & 0 & 0 & & & & 13/35 & 0 & 0 & & & \\ + 0 & 9/70 & 0 & & \boldsymbol{0}_3 & & 0 & 13/35 & 0 & & \boldsymbol{0}_3 & \\ + 0 & 0 & 1/6 & & & & 0 & 0 & 1/3 & & & \\ + & & & & & & & & & & & \\ + & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & & & \boldsymbol{0}_3 & \\ + & & & & & & & & & & & \\ + \end{array} + \right] + \label{eq:MassMatrixPreTension}\end{aligned} + +with :math:`L_e` the *undisplaced* length of the element (not +:math:`L_0`). + +.. _SD_ControlCable: + +Controlled pretension cable +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The controller updates the value of :math:`\Delta L` at each time step, +which effectively changes the pretension properties of the cable. The +quantity :math:`\Delta L` is the change in restlength if the cable had +no pretension. Since cable extension beyond the element length +(:math:`L_e`) is not allowed in SubDyn, :math:`\Delta L` is limited to +negative values. + +At a given time, the restlength of the cable is :math:`L_r(t)` (instead +of :math:`L_0`), and the pretension force is :math:`T(t)` (instead of +:math:`T_0`). The pretension force is then given as: + +.. math:: + + \begin{aligned} + T(t)= E A \frac{-\Delta L_r(t)}{L_r(t)} = E A \frac{-\Delta L_r(t)}{L_e + \Delta L(t)} + ,\quad + T(0) =T_0= E A \frac{-\Delta L_0}{L_e + \Delta L_0} + ,\quad + \Delta L(0) = \Delta L_0\end{aligned} + +The “equations of motions†for a cable element are written: + +.. math:: + + \begin{aligned} + \boldsymbol{M}_e\boldsymbol{\ddot{u}}_e&= \boldsymbol{f}_e\end{aligned} + +If the pretension force is constant, equal to :math:`T_0` then the +element force is: + +.. math:: + + \begin{aligned} + \boldsymbol{f}_e=\boldsymbol{f}_e (t,T_0) &=-\boldsymbol{K}_c(T_0) \boldsymbol{u}_e + \boldsymbol{f}_c(T_0)+ \boldsymbol{f}_g + \label{eq:CableEqMotionT0}\end{aligned} + +where :math:`\boldsymbol{f}_c(T_0)` and :math:`\boldsymbol{K}_c(T_0)` +are given in . If the pretension force is varying with time +(:math:`T=T(t)`), then the force is: + +.. math:: + + \begin{aligned} + \boldsymbol{f}_e (t) =-\boldsymbol{K}_c(T) \boldsymbol{u}_e + \boldsymbol{f}_c(T)+ \boldsymbol{f}_g + \label{eq:VaryingCableA}\end{aligned} + +where is evaluated with :math:`\epsilon=\frac{T}{EA}` and +:math:`L=\frac{L_e}{1+\epsilon}`. We seek to express , as a correction +term added to the equation of a constant pretension cable (i.e. , with +:math:`T(0)=T_0`). We add :math:`\pm\boldsymbol{f}_e(t,T_0)` to , +leading to: + +.. math:: + + \begin{aligned} + \boldsymbol{f}_e (t) &= \left [-\boldsymbol{K}_c(T_0) \boldsymbol{u}_e+ \boldsymbol{f}_c(T_0) + \boldsymbol{f}_g \right] - \left [-\boldsymbol{K}_c(T_0) \boldsymbol{u}_e + \boldsymbol{f}_c(T_0) + \boldsymbol{f}_g \right] + \left [-\boldsymbol{K}_c(T) \boldsymbol{u}_e + \boldsymbol{f}_c(T) + \boldsymbol{f}_g\right]\nonumber \\ + &= \left [-\underbrace{\boldsymbol{K}_c(T_0) \boldsymbol{u}_e}_{\text{in }CB}+ \underbrace{\boldsymbol{f}_c(T_0) + \boldsymbol{f}_g}_{\text{in } F_G} \right] +\boldsymbol{f}_{c,\text{control}}(T)\end{aligned} + +where :math:`\boldsymbol{f}_{c,\text{control}}` is the correction term +accounting for the time variation of :math:`T`: + +.. math:: + + \begin{aligned} + \boldsymbol{f}_{c,\text{control}}(T) &= \left( \boldsymbol{K}_c(T_0)-\boldsymbol{K}_c(T)\right) \boldsymbol{u}_e + \boldsymbol{f}_c(T) - \boldsymbol{f}_c(T_0)\end{aligned} + +This equation is transformed to the global system using the direction +cosine matrices of the element. The part involving +:math:`\boldsymbol{u}` introduces non-linearities, and is currently +neglected. Using , the additional control force for a given element is: + +.. math:: + + \begin{aligned} + \boldsymbol{f}_{c,\text{control}}(T) &\approx \boldsymbol{f}_c(T) - \boldsymbol{f}_c(T_0) = (T-T_0) + \begin{bmatrix} + 0\\ + 0\\ + -1\\ + 0\\ + 0\\ + 1\\ + \end{bmatrix} \end{aligned} + + + + + + + + + + + +Constraints introduced by Rotational Joints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As mentioned in :numref:`SD_FEM_Process`, the account of constraints is done via a direct elimination technique. +The technique is implemented by computing a transformation matrix :math:`\boldsymbol{T}` +which gives the relationship between the reduced set of DOF (accounting for constraints) +and the full set of DOFs. +When no constraints are present this matrix is the identity matrix. +This section describes how the :math:`\boldsymbol{T}` matrix is obtained for rotational joints. + + +**Formulation** +Joints between two nodes :math:`k` and :math:`l` are +here considered. Before accounting for the constraint introduced by the +joints, :math:`12` degrees of freedom are present: +:math:`(\boldsymbol{u}_k,\boldsymbol{\theta}_k,\boldsymbol{u}_l,\boldsymbol{\theta}_l)`. +After application of the constraints, the new set of degrees of freedom +is noted +:math:`(\boldsymbol{\tilde{u}}_{kl}, \boldsymbol{\tilde{\theta}}_{kl})`. +The degrees of freedom retained for each joint type is shown in the table below. The +meaning of the different :math:`\theta`-variable will be made explicit +in the subsequent paragraphs. + +.. table:: Nodal degrees of freedom (DOF) for different joint types. + + ============== =================================== ===================================== =================================== ===================================================================================== + **Joint type** :math:`\boldsymbol{n}_\text{c}` :math:`\boldsymbol{n}_\text{DOF}` :math:`\boldsymbol{\tilde{u}}_{kl}` :math:`\boldsymbol{\tilde{\theta}}_{kl}` + ============== =================================== ===================================== =================================== ===================================================================================== + Cantilever :math:`6` :math:`12 \to 6` :math:`u_x,u_y,u_z` :math:`\theta_x,\theta_y,\theta_k` + Pin :math:`5` :math:`12 \to 7` :math:`u_x,u_y,u_z` :math:`\theta_1,\theta_2,\theta_3,\theta_4` + Universal :math:`4` :math:`12 \to 8` :math:`u_x,u_y,u_z` :math:`\theta_1,\theta_2,\theta_3,\theta_4,\theta_5` + Ball :math:`3` :math:`12 \to 9` :math:`u_x,u_y,u_z` :math:`\theta_{x,k},\theta_{y,k},\theta_{z,k},\theta_{x,l},\theta_{y,l},\theta_{z,l}` + ============== =================================== ===================================== =================================== ===================================================================================== + +For all the joints considered, the translational DOF of the two nodes +are made equal, which may be formally expressed as: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{u}_{k} \\ + \boldsymbol{u}_{l} + \end{bmatrix} + = + \begin{bmatrix} + \boldsymbol{I}_3 \\ + \boldsymbol{I}_3 \\ + \end{bmatrix} + \boldsymbol{\tilde u}_{kl}\end{aligned} + +Since this relation is the same for all the joints, the relation between +the degrees of freedom is taken care in the assembly step. +The constraints of each joints will hence be expressed in the following form: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \boldsymbol{\theta}_{l} + \end{bmatrix} + =\boldsymbol{T}_{kl} + \boldsymbol{\tilde\theta}_{kl} + \label{eq:RotationalDOFJoint}\end{aligned} + +**Cantilever joint** For a cantilever joint between two elements, the reduction is: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \boldsymbol{\theta}_{l} + \end{bmatrix} + = + \boldsymbol{T}_{kl} + \boldsymbol{\tilde\theta}_{kl} + ,\qquad + \text{with} + \quad + \boldsymbol{\tilde\theta}_{kl} + = + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \end{bmatrix} + ,\qquad + \boldsymbol{T}_{kl}= + \begin{bmatrix} + \boldsymbol{I}_3 \\ + \boldsymbol{I}_3 \\ + \end{bmatrix}\end{aligned} + +This relationship is taken care of during the assembly process directly, and readily extended to :math:`n` elements. + +**Ball/spherical joint** For a spherical joint between two elements, the reduction is as follows: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \boldsymbol{\theta}_{l} + \end{bmatrix} + = + \boldsymbol{T}_{kl} + \boldsymbol{\tilde\theta}_{kl} + ,\qquad + \text{with} + \quad + \boldsymbol{\tilde\theta}_{kl} + = + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \boldsymbol{\theta}_{l} \\ + \end{bmatrix} + ,\qquad + \boldsymbol{T}_{kl}= + \begin{bmatrix} + \boldsymbol{I}_3 & \boldsymbol{0} \\ + \boldsymbol{0} & \boldsymbol{I}_3 \\ + \end{bmatrix}\end{aligned} + +For :math:`n` elements :math:`[e_1,\cdots, e_n]` connected by a ball +joint (constraint :math:`c`), the relationship is extended as follows: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{e_1} \\ + \cdots\\ + \boldsymbol{\theta}_{e_n} + \end{bmatrix} + = + \boldsymbol{T}^c + \boldsymbol{\tilde\theta}^c + ,\qquad + \text{with} + \quad + \boldsymbol{\tilde\theta}^c + = + \begin{bmatrix} + \boldsymbol{\theta}_{e_1} \\ + \cdots\\ + \boldsymbol{\theta}_{e_n} \\ + \end{bmatrix} + ,\qquad + \boldsymbol{T}^c = + \begin{bmatrix} + \boldsymbol{I}_3 & & \boldsymbol{0} \\ + \ & \ddots & \\ + \boldsymbol{0} & & \boldsymbol{I}_3 \\ + \end{bmatrix} + \label{eq:BallJointMulti}\end{aligned} + +**Pin/revolute joint**   A pin joint is characterized by a direction +around which no moment is transferred. The unit vector indicating this +direction is noted :math:`\boldsymbol{\hat{p}}`. Two orthogonal vectors +:math:`\boldsymbol{p}_1` and :math:`\boldsymbol{p}_2` are then defined, +forming an orthonormal base with :math:`\hat{p}`, oriented arbitrarily (see :numref:`fig:FEJointPin`). + +.. figure:: figs/FEJointPin.png + :alt: Pin joint + :name: fig:FEJointPin + :width: 40.0% + + Notations used for the derivation of the pin-joint constraint + + +The variables :math:`\tilde{\theta}_1..\tilde{\theta}_4` are then +defined as: + +.. math:: + + \begin{aligned} + \tilde{\theta}_1&= + \boldsymbol{p}_1^t\cdot\boldsymbol{\theta}_k + = + \boldsymbol{p}_1^t\cdot\boldsymbol{\theta}_l \\ + \tilde{\theta}_2&= + \boldsymbol{p}_2^t\cdot\boldsymbol{\theta}_k + = + \boldsymbol{p}_2^t\cdot\boldsymbol{\theta}_l \\ + \tilde{\theta}_3&= + \boldsymbol{\hat{p}}^t \cdot\boldsymbol{\theta}_k\\ + \tilde{\theta}_4&= + \boldsymbol{\hat{p}}^t \cdot\boldsymbol{\theta}_l\end{aligned} + +which may be written in matrix form as: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \tilde{\theta}_1 \\ + \tilde{\theta}_2 \\ + \tilde{\theta}_3 \\ + \tilde{\theta}_4 \\ + \end{bmatrix} + = + \boldsymbol{A} + \begin{bmatrix} + \boldsymbol{\theta}_k \\ + \boldsymbol{\theta}_l \\ + \end{bmatrix} + = + \begin{bmatrix} + \boldsymbol{p}_1^t/2 & \boldsymbol{p}_1^t/2 \\ + \boldsymbol{p}_2^t/2 & \boldsymbol{p}_2^t/2 \\ + \boldsymbol{\hat{p}}^t & \boldsymbol{0} \\ + \boldsymbol{0} & \boldsymbol{\hat{p}}^t \\ + \end{bmatrix} + \begin{bmatrix} + \boldsymbol{\theta}_k \\ + \boldsymbol{\theta}_l \\ + \end{bmatrix}\end{aligned} + +The relations are inverted using a pseudo inverse, defined as +:math:`\boldsymbol{A}^{-1^\ast}=\boldsymbol{A}^t(\boldsymbol{A}\boldsymbol{A}^t)^{-1}`. +Using the pseudo-inverse, this equation is rewritten in the form of as: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{k} \\ + \boldsymbol{\theta}_{l} + \end{bmatrix} + = + \boldsymbol{T}_{kl} + \boldsymbol{\tilde\theta}_{kl} + ,\qquad + \text{with} + \quad + = + \boldsymbol{\tilde\theta}_{kl} + \begin{bmatrix} + \tilde{\theta}_1 \\ + \tilde{\theta}_2 \\ + \tilde{\theta}_3 \\ + \tilde{\theta}_4 \\ + \end{bmatrix} + ,\qquad + \boldsymbol{T}_{kl}= + \begin{bmatrix} + \boldsymbol{p}_1^t/2 & \boldsymbol{p}_1^t/2 \\ + \boldsymbol{p}_2^t/2 & \boldsymbol{p}_2^t/2 \\ + \boldsymbol{\hat{p}}^t & \boldsymbol{0} \\ + \boldsymbol{0} & \boldsymbol{\hat{p}}^t \\ + \end{bmatrix}^{-1^\ast}\end{aligned} + +If :math:`n` elements :math:`[e_1,\cdots, e_n]`, are connected at a pin +joint (constraint :math:`c`), the relationship is extended as follows: + +.. math:: + + \begin{aligned} + \begin{bmatrix} + \boldsymbol{\theta}_{e_1} \\ + \cdots\\ + \boldsymbol{\theta}_{e_n} + \end{bmatrix} + = + \boldsymbol{T}^c + \boldsymbol{\tilde\theta}^c + ,\qquad + \text{with} + \quad + \boldsymbol{\tilde\theta}^c + = + \begin{bmatrix} + \tilde{\theta}_1 \\ + \tilde{\theta}_2 \\ + \tilde{\theta}_{e_1} \\ + \cdots \\ + \tilde{\theta}_{e_n} \\ + \end{bmatrix} + ,\qquad + \boldsymbol{T}^c = + \begin{bmatrix} + \boldsymbol{p}_1^t/n & \cdots &\boldsymbol{p}_1^t/n \\ + \boldsymbol{p}_2^t/n & \cdots &\boldsymbol{p}_2^t/n \\ + \boldsymbol{\hat{p}}^t & & \boldsymbol{0} \\ + & \ddots & \\ + \boldsymbol{0} & & \boldsymbol{\hat{p}}^t \\ + \end{bmatrix}^{-1^\ast} + \label{eq:PinJointMulti}\end{aligned} + +**Universal joint** A universal joint transfers the rotational moment +around two misaligned axes. Such joints are connecting only two +elements, labelled :math:`j` and :math:`k`, and the axes are taken as +the :math:`z` axis of each element. The axis vectors are expressed in +the global coordinates system and written :math:`\boldsymbol{\hat{z}}_j` +and :math:`\boldsymbol{\hat{z}}_k`. Similar notations are used for the +:math:`x` and :math:`y` axes. The DOF corresponding to the shared +rotation between the two axes is written :math:`\tilde{\theta}_1`. Each +element has two additional DOFs that are free to rotate, noted +:math:`\tilde{\theta}_x` and :math:`\tilde{\theta}_y`. The constraint +relationship between the original DOFs and the reduced DOFs is obtained +by projecting the rotational DOFs of each element against the different +axes. The relations are inverted using the pseudo-inverse, defined as +:math:`\boldsymbol{A}^{-1^\ast}=\boldsymbol{A}^t(\boldsymbol{A}\boldsymbol{A}^t)^{-1}`. +The constraints are then defined with: + +.. math:: + + \begin{aligned} + \boldsymbol{\tilde\theta}_c + = + \begin{bmatrix} + \tilde{\theta}_1 \\ + \tilde{\theta}_{x_j} \\ + \tilde{\theta}_{y_j} \\ + \tilde{\theta}_{x_k} \\ + \tilde{\theta}_{y_k} \\ + \end{bmatrix} + ,\quad + \boldsymbol{T}_c= + \begin{bmatrix} + \boldsymbol{\hat{z}}_j/2 & \boldsymbol{\hat{z}}_k/2 \\ + \boldsymbol{\hat{x}}_j & 0 \\ + \boldsymbol{\hat{y}}_j & 0 \\ + 0 & \boldsymbol{\hat{x}}_k \\ + 0 & \boldsymbol{\hat{y}}_k \\ + \end{bmatrix}^{-1^\ast}\end{aligned} + +.. math:: + + \begin{aligned} + \tilde{\theta}_c + = + \begin{Bmatrix} + \tilde{\theta}_1 \\ + \tilde{\theta}_{x,{e_1}} \\ + \tilde{\theta}_{y,{e_1}} \\ + \vdots\\ + \tilde{\theta}_{x,{e_n}} \\ + \tilde{\theta}_{y,{e_n}} \\ + \end{Bmatrix} + ,\quad + T_c= + \begin{bmatrix} + \hat{z}_{e_1}^t/2 & \cdots & \hat{z}_{e_n}^t/n \\ + \hat{x}_{e_1}^t & & 0 \\ + \hat{y}_{e_1}^t & & 0 \\ + 0 & \ddots & 0 \\ + 0 & & \hat{x}_{e_n}^t \\ + 0 & \cdots & \hat{y}_{e_n}^t \\ + \end{bmatrix}^{-1^\ast}\end{aligned} + + + + + + + + + + + + + + +.. _SD_RigidLinks: + + +Rigid-links +~~~~~~~~~~~ + +Rigid links and rigid elements impose a relationship between several +degrees of freedom, and as such, can be treated as *linear* *multipoint* +constraints. Rigid members can be used to join dissimilar elements +together or model a link of large stiffness between two elastic bodies +(see Cook :cite:`cook`). Mass properties for +rigid link may be provided in the input file, in which case the mass +matrix of a beam element is used for this rigid link. + +A rigid link between the nodes :math:`j` and :math:`k` is considered, +referred to as the element :math:`j-k`. The six degrees of freedom of a +given node, three displacements and three rotations, are noted +:math:`\boldsymbol{x}=[u_x,u_y,u_z,\theta_x,\theta_y,\theta_z]^t` in the +global system. The fact that the nodes :math:`j` and :math:`k` are rigidly connected is +formally expressed as follows: + +.. math:: :label: RigidLinkElem + + \begin{aligned} + \boldsymbol{x}_k= \boldsymbol{A}_{jk} \boldsymbol{x}_j + ,\qquad + \boldsymbol{A}_{jk}= + \begin{bmatrix} + 1 & 0 & 0 & 0 & \phantom{-} (z_k-z_j) & -(y_k-y_j) \\ + 0 & 1 & 0 & -(z_k-z_j) & 0 & \phantom{-} (x_k-x_j) \\ + 0 & 0 & 1 & \phantom{-} (y_k-y_j) & -(x_k-x_j) & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 \\ + \end{bmatrix} + ,\qquad + \begin{bmatrix} + \boldsymbol{x}_j\\ + \boldsymbol{x}_k'\\ + \end{bmatrix} + = + \boldsymbol{T} + \boldsymbol{x}_j + = + \begin{bmatrix} + \boldsymbol{I}_6\\ + \boldsymbol{A}_{jk}'\\ + \end{bmatrix} + \boldsymbol{x}_j + \end{aligned} + +where the nodal coordinates :math:`(x,y,z)` are expressed in the global +system. The matrix :math:`\boldsymbol{T}` expresses the relation between +the condensed coordinates and the original coordinates. + +In the general case, several joints may be coupled together with rigid +links. An assembly of :math:`n` joints is here assumed with the 6-DOFs +of each joints written :math:`\boldsymbol{x}_1,\cdots,\boldsymbol{x}_n`. +It is further assumed that the first joint is selected as leader. For each +joint :math:`j\in \{2,\cdots,n\}` a matrix :math:`\boldsymbol{A}_{1j}` +is formed according to :eq:`RigidLinkElem`. +The matrices are built using the global coordinates of +each joint pairs. For this given rigid assembly (or constraint +:math:`c`), the relation between the joint DOFs and the reduced leader +DOF is: + +.. math:: + + \begin{aligned} + \boldsymbol{x}^c = \boldsymbol{T}^c \boldsymbol{\tilde{x}}^c + \quad + \text{with} + \quad + \boldsymbol{x}^c= + \begin{bmatrix} + \boldsymbol{x}_1\\ + \boldsymbol{x}_2\\ + \cdots\\ + \boldsymbol{x}_n\\ + \end{bmatrix} + ,\quad + \boldsymbol{T}^c= + \begin{bmatrix} + \boldsymbol{I}_6\\ + \boldsymbol{A}_{12}\\ + \cdots\\ + \boldsymbol{A}_{1n}\\ + \end{bmatrix} + ,\quad + \boldsymbol{\tilde{x}}^c=\boldsymbol{x}_1 + \label{eq:RigidLinkGlobMulti}\end{aligned} + +SubDyn detects rigid link assemblies and selects a leader node for the assembly. +If one of the node is an interface node, it is selected as a leader node. +The following restriction apply: the follower node cannot be a boundary node. + +The constraint are applied after the full system has been assembled. + + - \left\{ F_G \right\} = \rho A_z g - \begin{bmatrix} 0 \\ - 0 \\ - -\frac{L_e}{2} \\ - -\frac{L_e^2}{12} D_{c2,3} \\ - \frac{L_e^2}{12} D_{c1,3} \\ - 0\\ - 0\\ - 0\\ - -\frac{L_e}{2}\\ - \frac{L_e^2}{12} D_{c2,3}\\ - -\frac{L_e^2}{12} D_{c1,3}\\ - 0 - \end{bmatrix} -Note also that if lumped masses exist (selected by the user at -prescribed joints), their contribution will be included as concentrated -forces along global *Z* at the relevant nodes. -.. _CBreduction: -Dynamic System of Equations and C-B Reduction ---------------------------------------------- -The main equations of motion of SubDyn are written as follows: +.. _GenericCBReduction: + +Craig-Bampton Reduction (theory) +-------------------------------- + +Full system +~~~~~~~~~~~ + + +The FEM equations of motion of SubDyn are written as follows: .. math:: :label: main @@ -459,11 +1309,8 @@ about 10 (user defined, see also Section :ref:`CBguide`). This system reduction was first introduced by :cite:`hurty1964` and later expanded by :cite:`craig1968`. -.. _GenericCBReduction: - -Craig-Bampton reduction -~~~~~~~~~~~~~~~~~~~~~~~ - +CB-reduced system +~~~~~~~~~~~~~~~~~ In this section we present the generic Craig-Bampton technique. The specific application in SubDyn is presented in following sections. In a C-B reduction, the structure nodes are separated into two @@ -658,6 +1505,12 @@ where and :math:`M_{Bm} = M_{mB}^T`, :math:`C_{Bm} =C_{mB}^T`. + + +Loads and boundary nodes +------------------------ + + .. _TP2Interface: Boundary nodes: fixed DOFs and rigid connection to TP @@ -794,7 +1647,7 @@ substructure response at each time step can then be obtained by using the state-space formulation discussed in the next section. -.. _Loads: +.. _SD_Loads: Loads ~~~~~ @@ -964,40 +1817,93 @@ For the "fixed boundary condition" case, the reference position does not corresp The output equation :math:`y_1= -F_{TP,cpl}` is then modified to include this extra contribution. +.. _SD_DampingSpecifications: +Damping specifications +~~~~~~~~~~~~~~~~~~~~~~ +There are three ways to specify the damping associated with the motion +of the interface node in SubDyn: no damping, Rayleigh damping or user defined 6x6 matrix. -.. _SSformulation: +NOTE: Damping associated with joints is not documented yet and would change the developments below. -State-Space Formulation -~~~~~~~~~~~~~~~~~~~~~~~~~~ +When **GuyanDampMod=0**, SubDyn assumes zero damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: -A state-space formulation of the substructure structural dynamics -problem was devised to integrate SubDyn within the FAST modularization -framework. The state-space formulation was developed in terms of inputs, -outputs, states, and parameters. The notations highlighted here are -consistent with those used in Jonkman (2013). Inputs (identified by *u*) -are a set of values supplied to SubDyn that, along with the states, are -needed to calculate future states and the system’s output. Outputs (*y*) -are a set of values calculated by and returned from SubDyn that depend -on the states, inputs, and/or parameters through output equations (with -functions *Y*). States are a set of internal values of SubDyn that are -influenced by the inputs and used to calculate future state values and -the output. In SubDyn, only continuous states are considered. Continuous -states (*x*) are states that are differentiable in time and -characterized by continuous time differential equations (with functions -*X*). Parameters (*p*) are a set of internal system values that are -independent of the states and inputs. Furthermore, parameters can be -fully defined at initialization and characterize the system’s state -equations and output equations. +.. math:: :label: dampingassumptions -In SubDyn, the inputs are defined as: + C_{BB} = \tilde{C}_{BB} &=0 -.. math:: :label: inputs + C_{Bm} =C_{mB} = \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 - u = \begin{bmatrix} - u_1 \\ + C_{mm} = \tilde{C}_{mm} &= 2\zeta \Omega_m + +In other words, the only damping matrix term retained is the one +associated with internal DOF damping. This assumption has implications +on the damping at the interface with the turbine system, as discussed in +Section :ref:`TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contans the modal +damping ratios corresponding to each retained internal mode. In SubDyn, +the user provides damping ratios (in percent of critical damping +coefficients) for the retained modes. + +When **GuyanDampMod=1**, SubDyn assumes Rayleigh Damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: + + +.. math:: :label: dampingRayleigh + + \tilde{C}_{BB}&=\alpha \tilde{M}_{BB} + \beta \tilde{K}_{BB} + + \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 + + \tilde{C}_{mm} &= 2\zeta \Omega_m + +where :math:`\alpha` and :math:`\beta` are the mass and stiffness proportional Rayleigh damping coefficients. The damping is directly applied to the tilde matrices, that is, the matrices related to the 6 DOF of the TP node. + +The case **GuyanDampMod=2**, is similar to the previous case, except that the user specifies the :math:`6\times6` terms of :math:`\tilde{C}_{BB}`. + + + + + + + + + + + + + + +.. _SSformulation: + +State-Space Formulation +----------------------- + +A state-space formulation of the substructure structural dynamics +problem was devised to integrate SubDyn within the FAST modularization +framework. The state-space formulation was developed in terms of inputs, +outputs, states, and parameters. The notations highlighted here are +consistent with those used in Jonkman (2013). Inputs (identified by *u*) +are a set of values supplied to SubDyn that, along with the states, are +needed to calculate future states and the system’s output. Outputs (*y*) +are a set of values calculated by and returned from SubDyn that depend +on the states, inputs, and/or parameters through output equations (with +functions *Y*). States are a set of internal values of SubDyn that are +influenced by the inputs and used to calculate future state values and +the output. In SubDyn, only continuous states are considered. Continuous +states (*x*) are states that are differentiable in time and +characterized by continuous time differential equations (with functions +*X*). Parameters (*p*) are a set of internal system values that are +independent of the states and inputs. Furthermore, parameters can be +fully defined at initialization and characterize the system’s state +equations and output equations. + +In SubDyn, the inputs are defined as: + +.. math:: :label: inputs + + u = \begin{bmatrix} + u_1 \\ u_2 \\ u_3 \\ u_4 \\ @@ -1251,166 +2157,8 @@ where The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`bigY2sim` is used instead. - - - -Member Force Calculation -~~~~~~~~~~~~~~~~~~~~~~~~ - -SubDyn can also calculate member forces by starting from the forces -computed at the nodes of the elements that are contained in the member -as: - -.. math:: :label: el_loads - - \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e - - \text{Element Static load:} ~~ F_S^e = [k] U_e - -where [*k*] and [*m*] are element stiffness and mass matrices, respectively. And -:math:`U_e` and :math:`\ddot{U}_e` are element nodal deflections and accelerations respectively, -which can be obtained from Eq. :eq:`y2`. - -There is no good way to quantify the damping forces for each element, so -the element damping forces are not calculated. - -Reaction Calculation -~~~~~~~~~~~~~~~~~~~~ - -The reactions at the base of the structure are the member forces at the -base nodes. These are usually provided in member local reference frames. -Additionally, the user may request an overall reaction -:math:`\overrightarrow{R}` (six forces and moments) lumped at the center -of the substructure (tower centerline) and mudline, i.e., at the -reference point (0,0,-**WtrDpth**) in the global reference frame, with -**WtrDpth** denoting the water depth. :math:`\overrightarrow{R}` is a -six-element array that can be calculated in matrix form as follows: - -.. math:: :label: reaction - - \overrightarrow{R} = \begin{bmatrix} - F_{X} \\ - \vdots \\ - M_{Z} \\ - \end{bmatrix} = T_{\text{React}} F_{\text{React}} - - -where :math:`F_{\text{React}}` is a (6*N\ :sub:`React`) array -containing the forces and moments at the *N\ :sub:`react`* restrained -nodes in the global coordinate frame, and :math:`T_{\text{React}}` is a -( :math:`{6×6 N_{\text{React}}}` ) matrix, as follows: - -.. math:: :label: Treact - - T_{\text{React}} = \begin{bmatrix} - 1 & 0 & 0 & 0 & 0 & 0 & \cdots & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 1 & 0 & 0 & 0 & 0 & \cdots & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & \cdots & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & -\Delta Z_1 & \Delta Y_1 & 1 & 0 & 0 & \cdots & 0 & -\Delta Z_{Nreact} & \Delta Y_{Nreact} & 1 & 0 & 0 \\ - \Delta Z_1 & 0 & -\Delta X_1 & 0 & 1 & 0 & \cdots & \Delta Z_{Nreact} & 0 & -\Delta X_{Nreact} & 0 & 1 & 0 \\ - \Delta Y_1 & \Delta X_1 & 0 & 0 & 0 & 1 & \cdots & \Delta Y_{Nreact} & \Delta X_{Nreact} & 0 & 0 & 0 & 1 - \end{bmatrix} - -where :math:`{X_i,~Y_i}`, and :math:`Z_i` (:math:`{i = 1 .. N_{\text{React}}}`) are coordinates of -the boundary nodes with respect to the reference point. For each element -with a restrained node, :math:`F_{\text{React}}` is calculated starting -from :math:`F_S^e` --- see Eq. :eq:`el_loads` --- subtracting out the contributions of gravity --- :math:`F_G`, see Eq. :eq:`FG` -and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct -element-level inertial or damping effect is therefore included in the -reaction calculation. - - - -.. _TimeIntegration: - -Time Integration -~~~~~~~~~~~~~~~~~ - -At time :math:`{t=0}`, the initial states are specified as initial conditions (all -assumed to be zero in SubDyn) and the initial inputs are supplied to -SubDyn. During each subsequent time step, the inputs and states are -known values, with the inputs :math:`u(t)` coming from ElastoDyn and HydroDyn, and -the states :math:`x(t)` known from the previous time-step integration. All of the -parameter matrices are calculated in the SubDyn initiation module. With -known :math:`u(t)` and :math:`x(t)`, :math:`{\dot{x}(t)}` can be calculated using the state equation :math:`{\dot{x}(t)=X(u,x,t)}` (see Eq. :eq:`state_eq`), and -the outputs :math:`y_1(t)` and :math:`y_2(t)` can be calculated solving Eqs. :eq:`bigY1` and :eq:`bigY2`. The element forces -can also be calculated using Eq. :eq:`el_loads`. The next time-step states :math:`{x(t + \Delta t)}` are -obtained by integration: - -.. math:: :label: integration - - \left [ u(t), \dot{x}(t), x(t) \right ] \xrightarrow[]{\text{Integrate}} x(t + \Delta t) - - -For loose coupling, SubDyn uses its own integrator, whereas for tight -coupling, the states from all the modules will be integrated -simultaneously using an integrator in the glue-code. SubDyn’s built-in -time integrator options for loose coupling are: - -- Fourth-order explicit Runge-Kutta - -- Fourth-order explicit Adams-Bashforth predictor - -- Fourth-order explicit Adams-Bashforth-Moulton predictor-corrector - -- Implicit second-order Adams-Moulton. - -For more information, consult any numerical methods reference, e.g., -:cite:`chapra2010`. - - -.. _SD_DampingSpecifications: - -Damping specifications -~~~~~~~~~~~~~~~~~~~~~~ - - -There are three ways to specify the damping associated with the motion -of the interface node in SubDyn: no damping, Rayleigh damping or user defined 6x6 matrix. - -NOTE: Damping associated with joints is not documented yet and would change the developments below. - -When **GuyanDampMod=0**, SubDyn assumes zero damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: - -.. math:: :label: dampingassumptions - - C_{BB} = \tilde{C}_{BB} &=0 - - C_{Bm} =C_{mB} = \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 - - C_{mm} = \tilde{C}_{mm} &= 2\zeta \Omega_m - -In other words, the only damping matrix term retained is the one -associated with internal DOF damping. This assumption has implications -on the damping at the interface with the turbine system, as discussed in -Section :ref:`TowerTurbineCpling`. The diagonal (*m*\ ×\ *m*) :math:`\zeta` matrix contans the modal -damping ratios corresponding to each retained internal mode. In SubDyn, -the user provides damping ratios (in percent of critical damping -coefficients) for the retained modes. - -When **GuyanDampMod=1**, SubDyn assumes Rayleigh Damping for the Guyan modes, and modal damping for the CB modes, with no cross couplings: - - -.. math:: :label: dampingRayleigh - - \tilde{C}_{BB}&=\alpha \tilde{M}_{BB} + \beta \tilde{K}_{BB} - - \tilde{C}_{Bm}=\tilde{C}_{mB}&=0 - - \tilde{C}_{mm} &= 2\zeta \Omega_m - -where :math:`\alpha` and :math:`\beta` are the mass and stiffness proportional Rayleigh damping coefficients. The damping is directly applied to the tilde matrices, that is, the matrices related to the 6 DOF of the TP node. - -The case **GuyanDampMod=2**, is similar to the previous case, except that the user specifies the :math:`6\times6` terms of :math:`\tilde{C}_{BB}`. - - - - - - - - .. _sim: +.. _SD_SIM: Static-Improvement Method ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1554,3 +2302,123 @@ derived from the parent :math:`U_{L0}` and :math:`U_{L0m}` arrays of displacemen + + +Outputs and Time Integration +---------------------------- + + + +Member Force Calculation +~~~~~~~~~~~~~~~~~~~~~~~~ + +SubDyn can also calculate member forces by starting from the forces +computed at the nodes of the elements that are contained in the member +as: + +.. math:: :label: el_loads + + \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e + + \text{Element Static load:} ~~ F_S^e = [k] U_e + +where [*k*] and [*m*] are element stiffness and mass matrices, respectively. And +:math:`U_e` and :math:`\ddot{U}_e` are element nodal deflections and accelerations respectively, +which can be obtained from Eq. :eq:`y2`. + +There is no good way to quantify the damping forces for each element, so +the element damping forces are not calculated. + +Reaction Calculation +~~~~~~~~~~~~~~~~~~~~ + +The reactions at the base of the structure are the member forces at the +base nodes. These are usually provided in member local reference frames. +Additionally, the user may request an overall reaction +:math:`\overrightarrow{R}` (six forces and moments) lumped at the center +of the substructure (tower centerline) and mudline, i.e., at the +reference point (0,0,-**WtrDpth**) in the global reference frame, with +**WtrDpth** denoting the water depth. :math:`\overrightarrow{R}` is a +six-element array that can be calculated in matrix form as follows: + +.. math:: :label: reaction + + \overrightarrow{R} = \begin{bmatrix} + F_{X} \\ + \vdots \\ + M_{Z} \\ + \end{bmatrix} = T_{\text{React}} F_{\text{React}} + + +where :math:`F_{\text{React}}` is a (6*N\ :sub:`React`) array +containing the forces and moments at the *N\ :sub:`react`* restrained +nodes in the global coordinate frame, and :math:`T_{\text{React}}` is a +( :math:`{6×6 N_{\text{React}}}` ) matrix, as follows: + +.. math:: :label: Treact + + T_{\text{React}} = \begin{bmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & \cdots & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & \cdots & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & \cdots & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & -\Delta Z_1 & \Delta Y_1 & 1 & 0 & 0 & \cdots & 0 & -\Delta Z_{Nreact} & \Delta Y_{Nreact} & 1 & 0 & 0 \\ + \Delta Z_1 & 0 & -\Delta X_1 & 0 & 1 & 0 & \cdots & \Delta Z_{Nreact} & 0 & -\Delta X_{Nreact} & 0 & 1 & 0 \\ + \Delta Y_1 & \Delta X_1 & 0 & 0 & 0 & 1 & \cdots & \Delta Y_{Nreact} & \Delta X_{Nreact} & 0 & 0 & 0 & 1 + \end{bmatrix} + +where :math:`{X_i,~Y_i}`, and :math:`Z_i` (:math:`{i = 1 .. N_{\text{React}}}`) are coordinates of +the boundary nodes with respect to the reference point. For each element +with a restrained node, :math:`F_{\text{React}}` is calculated starting +from :math:`F_S^e` --- see Eq. :eq:`el_loads` --- subtracting out the contributions of gravity --- :math:`F_G`, see Eq. :eq:`FG` +and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct +element-level inertial or damping effect is therefore included in the +reaction calculation. + + + +.. _TimeIntegration: + +Time Integration +~~~~~~~~~~~~~~~~~ + +At time :math:`{t=0}`, the initial states are specified as initial conditions (all +assumed to be zero in SubDyn) and the initial inputs are supplied to +SubDyn. During each subsequent time step, the inputs and states are +known values, with the inputs :math:`u(t)` coming from ElastoDyn and HydroDyn, and +the states :math:`x(t)` known from the previous time-step integration. All of the +parameter matrices are calculated in the SubDyn initiation module. With +known :math:`u(t)` and :math:`x(t)`, :math:`{\dot{x}(t)}` can be calculated using the state equation :math:`{\dot{x}(t)=X(u,x,t)}` (see Eq. :eq:`state_eq`), and +the outputs :math:`y_1(t)` and :math:`y_2(t)` can be calculated solving Eqs. :eq:`bigY1` and :eq:`bigY2`. The element forces +can also be calculated using Eq. :eq:`el_loads`. The next time-step states :math:`{x(t + \Delta t)}` are +obtained by integration: + +.. math:: :label: integration + + \left [ u(t), \dot{x}(t), x(t) \right ] \xrightarrow[]{\text{Integrate}} x(t + \Delta t) + + +For loose coupling, SubDyn uses its own integrator, whereas for tight +coupling, the states from all the modules will be integrated +simultaneously using an integrator in the glue-code. SubDyn’s built-in +time integrator options for loose coupling are: + +- Fourth-order explicit Runge-Kutta + +- Fourth-order explicit Adams-Bashforth predictor + +- Fourth-order explicit Adams-Bashforth-Moulton predictor-corrector + +- Implicit second-order Adams-Moulton. + +For more information, consult any numerical methods reference, e.g., +:cite:`chapra2010`. + + + + + + + + + + From 0631a9bfdbbf7729e2e68b98260b5466e96f0c17 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 4 Dec 2020 10:21:56 -0700 Subject: [PATCH 324/377] FlexSub: removing Fg/Fc from the FK outputs --- modules/subdyn/src/SubDyn_Output.f90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index fcee6c878..88b05b9be 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -251,7 +251,10 @@ SUBROUTINE ConfigOutputNode_MKF_ID(pLst, iElem, iiNode, iStore, NodeID2) CALL ElemM(p%ElemProps(iElem), pLst%Me(:,:,iiNode,iStore)) CALL ElemK(p%ElemProps(iElem), pLst%Ke(:,:,iiNode,iStore)) CALL ElemF(p%ElemProps(iElem), Init%g, pLst%Fg(:,iiNode,iStore), FCe) - pLst%Fg(:,iiNode,iStore) = pLst%Fg(:,iiNode,iStore) + FCe(1:12) ! Adding cable element force + ! NOTE: Removing this force contribution for now (maybe put Tension only?) + ! The output of subdyn will just be the "Kx" part for now + !pLst%Fg(:,iiNode,iStore) = pLst%Fg(:,iiNode,iStore) + FCe(1:12) ! Adding cable element force + pLst%Fg(:,iiNode,iStore) = 0.0_ReKi END SUBROUTINE ConfigOutputNode_MKF_ID @@ -459,7 +462,7 @@ SUBROUTINE CALC_NODE_FORCES(DIRCOS,Me,Ke,Udotdot,Y2 ,Fg, FirstOrSecond, FM_nod, FM_glb = matmul(Me,Udotdot) ! GLOBAL REFERENCE FF_glb = matmul(Ke,Y2) ! GLOBAL REFERENCE - FF_glb = FF_glb - Fg ! GLOBAL REFERENCE + FF_glb = FF_glb - Fg ! GLOBAL REFERENCE ! NOTE: Fg is now 0, only the "Kx" part in Fk DO L=1,4 ! Transforming coordinates 3 at a time FM_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FM_glb( (L-1)*3+1:L*3 ) ) FF_elm((L-1)*3+1:L*3) = matmul(DIRCOS, FF_glb( (L-1)*3+1:L*3 ) ) From f0e146f372c3dd2afc8efe34f874e216b9f46fc7 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 4 Dec 2020 10:23:07 -0700 Subject: [PATCH 325/377] FlexSub: return platform position for Moordyn that accounts for lever arm --- modules/elastodyn/src/ElastoDyn.f90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/elastodyn/src/ElastoDyn.f90 b/modules/elastodyn/src/ElastoDyn.f90 index 7b7f8d479..7bc2708c9 100644 --- a/modules/elastodyn/src/ElastoDyn.f90 +++ b/modules/elastodyn/src/ElastoDyn.f90 @@ -100,6 +100,7 @@ SUBROUTINE ED_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut INTEGER(IntKi) :: i ! loop counters LOGICAL, PARAMETER :: GetAdamsVals = .FALSE. ! Determines if we should read Adams values and create (update) an Adams model CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary Error message if ErrStat /= ErrID_None + REAL(R8Ki) :: TransMat(3,3) ! Initial rotation matrix at Platform Refz ! Initialize variables for this routine @@ -240,7 +241,14 @@ SUBROUTINE ED_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut InitOut%BladeLength = p%TipRad - p%HubRad InitOut%TowerHeight = p%TwrFlexL InitOut%TowerBaseHeight = p%TowerBsHt + + ! Platform reference point wrt to global origin (0,0,0) InitOut%PlatformPos = x%QT(1:6) + CALL SmllRotTrans('initial platform rotation', x%QT(4), x%QT(5), x%QT(6), TransMat, '', ErrStat2, ErrMsg2) + InitOut%PlatformPos(1) = InitOut%PlatformPos(1) - TransMat(3,1)*p%PtfmRefzt + InitOut%PlatformPos(2) = InitOut%PlatformPos(2) - TransMat(3,2)*p%PtfmRefzt + InitOut%PlatformPos(3) = InitOut%PlatformPos(3) - TransMat(3,3)*p%PtfmRefzt + p%PtfmRefzt + InitOut%HubHt = p%HubHt InitOut%TwrBasePos = y%TowerLn2Mesh%Position(:,p%TwrNodes + 2) InitOut%HubRad = p%HubRad From 3002c120b37bf03d753ae71b1c1e3f222e60739a Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 20:24:13 -0700 Subject: [PATCH 326/377] FlexSub: gravity is now always added to external loads --- modules/subdyn/src/SD_FEM.f90 | 20 +- modules/subdyn/src/SubDyn.f90 | 99 +- modules/subdyn/src/SubDyn_Registry.txt | 531 ++-- modules/subdyn/src/SubDyn_Types.f90 | 3714 +++++++++++------------- 4 files changed, 1982 insertions(+), 2382 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 8a80d2e5a..100328363 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -67,8 +67,7 @@ MODULE SD_FEM ! Types of Static Improvement Methods INTEGER(IntKi), PARAMETER :: idSIM_None = 0 INTEGER(IntKi), PARAMETER :: idSIM_Full = 1 - INTEGER(IntKi), PARAMETER :: idSIM_GravOnly = 2 - INTEGER(IntKi) :: idSIM_Valid(3) = (/idSIM_None, idSIM_Full, idSIM_GravOnly /) + INTEGER(IntKi) :: idSIM_Valid(2) = (/idSIM_None, idSIM_Full/) ! Types of Guyan Damping INTEGER(IntKi), PARAMETER :: idGuyanDamp_None = 0 @@ -1029,11 +1028,10 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) CALL AllocAry( Init%K, p%nDOF, p%nDOF , 'Init%K', ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, p%nDOF, p%nDOF , 'Init%M', ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG,p%nDOF, 'Init%FG', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector - CALL AllocAry( p%FG_full, p%nDOF, 'p%FG_full', ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector + CALL AllocAry( p%FG, p%nDOF, 'p%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector Init%K = 0.0_FEKi Init%M = 0.0_FEKi - Init%FG = 0.0_FEKi + p%FG = 0.0_FEKi ! loop over all elements, compute element matrices and assemble into global matrices DO i = 1, Init%NElem @@ -1044,7 +1042,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) ! --- Assembly in global unconstrained system IDOF = p%ElemsDOF(1:12, i) - Init%FG( IDOF ) = Init%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces + p%FG ( IDOF ) = p%FG( IDOF ) + FGe(1:12)+ FCe(1:12) ! Note: gravity and pretension cable forces Init%K(IDOF, IDOF) = Init%K( IDOF, IDOF) + Ke(1:12,1:12) Init%M(IDOF, IDOF) = Init%M( IDOF, IDOF) + Me(1:12,1:12) ENDDO @@ -1083,11 +1081,8 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) DO I = 1, Init%nCMass iNode = NINT(Init%CMass(I, 1)) ! Note index where concentrated mass is to be added iGlob = p%NodesDOF(iNode)%List(3) ! uz - Init%FG(iGlob) = Init%FG(iGlob) - Init%CMass(I, 2)*Init%g + p%FG(iGlob) = p%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO - - ! Copy FG to FG_full since FG will be reduced later - p%FG_full(1:p%nDOF) = Init%FG(1:p%nDOF) CALL CleanUp_AssembleKM() @@ -1588,7 +1583,6 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) type(IList), dimension(:), allocatable :: RA !< RA(a) = [e1,..,en] list of elements forming a rigid link assembly integer(IntKi), dimension(:), allocatable :: RAm1 !< RA^-1(e) = a , for a given element give the index of a rigid assembly real(FEKi), dimension(:,:), allocatable :: MM, KK - real(FEKi), dimension(:), allocatable :: FF real(FEKi), dimension(:,:), allocatable :: Temp integer(IntKi) :: nDOF, iDOF, nDOFPerNode, iNode, iiDOF, i,j ErrStat = ErrID_None @@ -1606,11 +1600,9 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) ! Temporary backup of M and K of full system call move_alloc(Init%M, MM) call move_alloc(Init%K, KK) - call move_alloc(Init%FG, FF) ! Reallocating CALL AllocAry( Init%K, nDOF, nDOF, 'Init%K' , ErrStat2, ErrMsg2); if(Failed()) return; ! system stiffness matrix CALL AllocAry( Init%M, nDOF, nDOF, 'Init%M' , ErrStat2, ErrMsg2); if(Failed()) return; ! system mass matrix - CALL AllocAry( Init%FG, nDOF, 'Init%FG' , ErrStat2, ErrMsg2); if(Failed()) return; ! system gravity force vector CALL AllocAry( Temp ,size(MM,1), nDOF, 'Temp' , ErrStat2, ErrMsg2); if(Failed()) return; CALL AllocAry( p%T_red_T,nDOF , size(MM,1), 'T_red_T' , ErrStat2, ErrMsg2); if(Failed()) return; ! --- Elimination (stack expensive) @@ -1631,7 +1623,6 @@ SUBROUTINE DirectElimination(Init, p, ErrStat, ErrMsg) !Init%K = matmul(p%T_red_T, Temp) CALL LAPACK_gemm( 'T', 'N', 1.0_FeKi, p%T_red, Temp , 0.0_FeKi, Init%K, ErrStat2, ErrMsg2); if(Failed()) return if (allocated(Temp)) deallocate(Temp) - Init%FG = matmul(p%T_red_T, FF) endif !CALL AllocAry( Init%D, nDOF, nDOF, 'Init%D' , ErrStat2, ErrMsg2); if(Failed()) return; ! system damping matrix !Init%D = 0 !< Used for additional damping @@ -1661,7 +1652,6 @@ SUBROUTINE CleanUp_DirectElimination() ! Cleaning up memory if (allocated(MM )) deallocate(MM ) if (allocated(KK )) deallocate(KK ) - if (allocated(FF )) deallocate(FF ) if (allocated(RA )) deallocate(RA ) if (allocated(RAm1)) deallocate(RAm1) if (allocated(Temp)) deallocate(Temp) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index fd10553c9..55a0fe972 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -477,20 +477,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) & - + p%F2_61 + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) END IF ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then - if (p%SttcSolve==idSIM_Full) then - FLt = MATMUL(p%PhiL_T , m%UFL + p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! TODO consider using use a precomputed UL_st_g and KLLm1: ULS = p%UL_st_g + MATMUL(p%KLLm1, m%UFL) - elseif (p%SttcSolve==idSIM_GravOnly) then - FLt = MATMUL(p%PhiL_T , p%FGL) - ULS = MATMUL(p%PhiLInvOmgL2, FLt ) ! TODO consider using use a precomputed UL_st_g and KLLm1: ULS = p%UL_st_g - else - STOP ! Should never happen - endif + FLt = MATMUL(p%PhiL_T , m%UFL) ! NOTE: Gravity in UFL + ULS = MATMUL(p%PhiLInvOmgL2, FLt ) m%UL = m%UL + ULS if ( p%nDOFM > 0) then UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) @@ -577,16 +569,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --------------------------------------------------------------------------------- !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above ! --------------------------------------------------------------------------------- - ! Eq. 15: Y1 = -(C1*x + D1*u + FY) [note the negative sign!!!!] + ! Eq. 15: Y1 = -(C1*x + D1*u ) [note the negative sign!!!!] !HydroTP = matmul(transpose(p%TI), F_I) ! (6,1) calculated below ! note: matmul( F_I, p%TI ) = matmul( transpose(p%TI), F_I) because F_I is 1-D IF ( p%nDOFM > 0) THEN Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( F_I, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + - matmul( F_I, p%TI ) ) ! + D1(1,5)*u(5) + Fy(1) ) ELSE ! No retained modes, so there are no states Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( F_I, p%TI ) + p%FY ) ! + D1(1,5)*u(5) + Fy(1) ) + - matmul( F_I, p%TI ) ) ! + D1(1,5)*u(5) + Fy(1) ) END IF ! Computing extra moments due to lever arm introduced by interface displacement ! Y1(:3) = -f_TP @@ -699,9 +691,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta dxdt%qm= x%qmdot ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D - != a(2,1) * x(1) + a(2,2) * x(2) + b(2,3) * u(3) + b(2,4) * u(4) + fx(2) - !dxdt%qmdot = -p%KMMDiag*x%qm + p%CMMDiag*x%qmdot - matmul(p%CMB,m%udotdot_TP)- matmul(p%MMB,m%udotdot_TP) + matmul(p%PhiM_T,m%UFL) + p%FX - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) + p%FX + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) END SUBROUTINE SD_CalcContStateDeriv @@ -1703,7 +1693,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array - junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM ) + p%FX) !lower portion of array + junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM )) !lower portion of array ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D !.................................................... @@ -2146,7 +2136,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables - REAL(FEKi), ALLOCATABLE :: FGR(:), FGL(:), FGB(:), FGM(:) !< Partitioned Force (R/L), and CB reduced forces(B/M) REAL(FEKi), ALLOCATABLE :: PhiRb(:, :) ! Purely to avoid loosing these modes for output ! TODO, kept for backward compatibility of Summary file REAL(ReKi) :: JDamping1 ! temporary storage for first element of JDamping array INTEGER(IntKi) :: nR !< Dimension of R DOFs (to switch between __R and R__) @@ -2195,10 +2184,6 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) nM = p%nDOFM CALL WrScr(' Performing Craig-Bampton reduction '//trim(Num2LStr(p%nDOF_red))//' DOFs -> '//trim(Num2LStr(p%nDOFM))//' modes + '//trim(Num2LStr(p%nDOF__Rb))//' DOFs') - CALL AllocAry( FGL, nL, 'array FGL', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGR, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGB, nR, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL AllocAry( FGM, nM, 'array FGR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBB, nR, nR, 'CB%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%MBM, nR, nM, 'CB%MBM', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%KBB, nR, nR, 'CB%KBB', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2206,19 +2191,18 @@ SUBROUTINE SD_Craig_Bampton(Init, p, CB, ErrStat, ErrMsg) CALL AllocAry( CB%PhiR, nL, nR, 'CB%PhiR', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL AllocAry( CB%OmegaL, nM_out, 'CB%OmegaL', ErrStat2, ErrMsg2 ); if(Failed()) return - CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2,& - Init%FG, FGR, FGL, FGB, FGM) + CALL CraigBamptonReduction(Init%M, Init%K, IDR, nR, p%ID__L, nL, nM, nM_out, CB%MBB, CB%MBM, CB%KBB, CB%PhiL, CB%PhiR, CB%OmegaL, ErrStat2, ErrMsg2) if(Failed()) return CALL AllocAry(PhiRb, nL, nR, 'PhiRb', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if(.not.BC_Before_CB) then ! We apply the BC now, removing unwanted DOFs - call applyConstr(CB, FGB, PhiRb) ! Reduces size of CB%MBB, CB%KBB, CB%MBM, FGB, NOTE: "L" unaffected + call applyConstr(CB, PhiRb) ! Reduces size of CB%MBB, CB%KBB, CB%MBM, NOTE: "L" unaffected else PhiRb=CB%PhiR ! Remove me in the future endif ! TODO, right now using PhiRb instead of CB%PhiR, keeping PhiR in harmony with OmegaL for SummaryFile - CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, FGL, FGB, FGM, ErrStat2, ErrMsg2) + CALL SetParameters(Init, p, CB%MBB, CB%MBM, CB%KBB, PhiRb, nM_out, CB%OmegaL, CB%PhiL, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'Craig_Bampton') CALL CleanUpCB() @@ -2238,33 +2222,26 @@ logical function Failed() end function Failed subroutine CleanUpCB() - IF(ALLOCATED(FGR) ) DEALLOCATE(FGR) - IF(ALLOCATED(FGL) ) DEALLOCATE(FGL) - IF(ALLOCATED(FGM) ) DEALLOCATE(FGM) - IF(ALLOCATED(FGB) ) DEALLOCATE(FGB) IF(ALLOCATED(PhiRb)) DEALLOCATE(PhiRb) end subroutine CleanUpCB !> Remove fixed DOF from system, this is in case the CB was done on an unconstrained system !! NOTE: PhiL and OmegaL are not modified - subroutine applyConstr(CBParams, FGB, PhiRb) + subroutine applyConstr(CBParams, PhiRb) TYPE(CB_MatArrays), INTENT(INOUT) :: CBparams !< NOTE: data will be reduced (andw hence reallocated) - REAL(FEKi),ALLOCATABLE,INTENT(INOUT) :: FGB(:) !< NOTE: data will be reduced (andw hence reallocated) REAL(FEKi),ALLOCATABLE,INTENT(INOUT) :: PhiRb(:,:)!< NOTE: data will be reduced (andw hence reallocated) !REAL(ReKi), ALLOCATABLE :: PhiRb(:, :) REAL(FEKi), ALLOCATABLE :: MBBb(:, :) REAL(FEKi), ALLOCATABLE :: MBMb(:, :) REAL(FEKi), ALLOCATABLE :: KBBb(:, :) - REAL(FEKi), ALLOCATABLE :: FGBb(:) ! "b" stands for "bar" CALL AllocAry( MBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix MBBb', ErrStat2, ErrMsg2 ); CALL AllocAry( MBmb, p%nDOF__Rb, p%nDOFM, 'matrix MBmb', ErrStat2, ErrMsg2 ); CALL AllocAry( KBBb, p%nDOF__Rb, p%nDOF__Rb, 'matrix KBBb', ErrStat2, ErrMsg2 ); - CALL AllocAry( FGBb, p%nDOF__Rb, 'array FGBb', ErrStat2, ErrMsg2 ); !CALL AllocAry( PhiRb, p%nDOF__L , p%nDOF__Rb, 'matrix PhiRb', ErrStat2, ErrMsg2 ); !................................ - ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , FGB to - ! MBBb, MBMb, KBBb, PHiRb, FGBb + ! Convert CBparams%MBB , CBparams%MBM , CBparams%KBB , CBparams%PhiR , to + ! MBBb, MBMb, KBBb, PHiRb, ! (throw out rows/columns of first matrices to create second matrices) !................................ ! TODO avoid this all together @@ -2273,7 +2250,6 @@ subroutine applyConstr(CBParams, FGB, PhiRb) IF (p%nDOFM > 0) THEN MBMb = CBparams%MBM(p%nDOFR__-p%nDOFI__+1:p%nDOFR__, : ) END IF - FGBb = FGB (p%nDOFR__-p%nDOFI__+1:p%nDOFR__ ) PhiRb = CBparams%PhiR( :, p%nDOFR__-p%nDOFI__+1:p%nDOFR__) deallocate(CBparams%MBB) deallocate(CBparams%KBB) @@ -2282,7 +2258,6 @@ subroutine applyConstr(CBParams, FGB, PhiRb) call move_alloc(MBBb, CBparams%MBB) call move_alloc(KBBb, CBparams%KBB) call move_alloc(MBMb, CBparams%MBM) - call move_alloc(FGBb, FGB) !call move_alloc(PhiRb, CBparams%PhiR) end subroutine applyConstr @@ -2343,7 +2318,7 @@ END SUBROUTINE SD_Guyan_RigidBodyMass !------------------------------------------------------------------------------------------------------ !> Set parameters to compute state and output equations !! NOTE: this function converst from FEKi to ReKi -SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, FGL, FGB, FGM, ErrStat, ErrMsg) +SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ErrStat, ErrMsg) use NWTC_LAPACK, only: LAPACK_GEMM, LAPACK_getrf TYPE(SD_InitType), INTENT(IN ) :: Init ! Input data for initialization routine TYPE(SD_ParameterType), INTENT(INOUT) :: p ! Parameters @@ -2354,9 +2329,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, REAL(FEKi), INTENT(IN ) :: PhiL ( p%nDOF__L, nM_out) REAL(FEKi), INTENT(IN ) :: PhiRb( p%nDOF__L, p%nDOF__Rb) REAL(FEKi), INTENT(IN ) :: OmegaL(nM_out) - REAL(FEKi), INTENT(IN ) :: FGB(p%nDOF__Rb) - REAL(FEKi), INTENT(IN ) :: FGL(p%nDOF__L) - REAL(FEKi), INTENT(IN ) :: FGM(p%nDOFM) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! local variables @@ -2394,8 +2366,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, CALL AllocAry( p%PhiL_T, p%nDOF__L, p%nDOF__L, 'p%PhiL_T', ErrStat2, ErrMsg2 ); if(Failed())return CALL AllocAry( p%PhiLInvOmgL2, p%nDOF__L, p%nDOF__L, 'p%PhiLInvOmgL2', ErrStat2, ErrMsg2 ); if(Failed())return CALL AllocAry( p%KLLm1 , p%nDOF__L, p%nDOF__L, 'p%KLLm1', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%FGL, p%nDOF__L, 'p%FGL', ErrStat2, ErrMsg2 ); if(Failed())return - CALL AllocAry( p%UL_st_g, p%nDOF__L, 'p%UL_st_g', ErrStat2, ErrMsg2 ); if(Failed())return ! TODO PhiL_T and PhiLInvOmgL2 may not be needed if KLLm1 is stored. p%PhiL_T=TRANSPOSE(PhiL) !transpose of PhiL for static improvement do I = 1, nM_out @@ -2404,8 +2374,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t !p%KLLm1 = MATMUL(p%PhiLInvOmgL2, p%PhiL_T) ! Inverse of KLL: KLL^-1 = [PhiL] x [OmegaL^2]^-1 x [PhiL]^t CALL LAPACK_gemm( 'N', 'N', 1.0_ReKi, p%PhiLInvOmgL2, p%PhiL_T, 0.0_ReKi, p%KLLm1, ErrStat2, ErrMsg2); if(Failed()) return - p%FGL = FGL - p%UL_st_g = MATMUL(p%KLLm1, FGL) endif ! block element of D2 matrix (D2_21, D2_42, & part of D2_62) @@ -2451,9 +2419,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%KMMDiag= OmegaL(1:p%nDOFM) * OmegaL(1:p%nDOFM) ! OmegaM is a one-dimensional array p%CMMDiag = 2.0_ReKi * OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) ! Init%JDampings is also a one-dimensional array - ! FX = matmul( transpose(PhiM), FGL ) (output of CraigBamptonReduction) - p%FX = FGM - ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped p%C1_11(:, I) = -p%MBM(:, I)*p%KMMDiag(I) @@ -2476,10 +2441,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PhiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 - - ! FY (with retained modes) - p%FY = MATMUL( p%MBM, p%FX ) & - - MATMUL( TI_transpose, FGB ) ! C2_21, C2_42 ! C2_61, C2_62 @@ -2495,9 +2456,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !p%D2_64 = MATMUL( p%PhiM, p%PhiM_T ) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%PhiM, p%PhiM, 0.0_ReKi, p%D2_64, ErrStat2, ErrMsg2 ); if(Failed()) return; - - ! F2_61 - p%F2_61 = MATMUL( p%D2_64, FGL ) !Now calculate a Jacobian used when AM2 is called and store in parameters IF (p%IntMethod .EQ. 4) THEN ! Allocate Jacobian if AM2 is requested & if there are states (p%nDOFM > 0) @@ -2531,15 +2489,12 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, write(Info,'(3x,A,F8.5,A,F8.5,A,F8.5)') 'SubDyn recommended dt:',dt_max, ' - Current dt:', p%SDDeltaT,' - Max frequency:', freq_max call WrScr(Info) ELSE ! no retained modes, so - ! OmegaM, JDampings, PhiM, MBM, MMB, FX , x don't exist in this case - ! p%F2_61, p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables + ! OmegaM, JDampings, PhiM, MBM, MMB, x don't exist in this case + ! p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable p%D1_12 = p%CBB ! No cross couplings p%D1_13 = p%MBB ! No cross couplings p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) - - ! FY (with 0 retained modes) - p%FY = - MATMUL( TI_transpose, FGB ) END IF CONTAINS @@ -2569,7 +2524,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FY, nDOFL_TP, 'p%FY', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2580,7 +2534,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%CMMDiag, nDOFM, 'p%CMMDiag', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%CMB, nDOFM, nDOFL_TP, 'p%CMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%CBM, nDOFL_TP, nDOFM, 'p%CBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%FX, nDOFM, 'p%FX', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2590,7 +2543,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L,'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 - CALL AllocAry( p%F2_61, p%nDOF__L, 'p%F2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if END SUBROUTINE AllocParameters @@ -2948,11 +2900,11 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) endif - ! --- Build vector of external forces (Moment done below) + ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN - DO iNode = 1,p%nNodes - ! Force - All nodes have only 3 translational DOFs - m%Fext( p%NodesDOF(iNode)%List(1:3) ) = u%LMesh%Force (:,iNode) + do iNode = 1,p%nNodes + ! Force in global for fixed bottom + m%Fext( p%NodesDOF(iNode)%List(1:3) ) = u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3)) enddo ! --- Adding controllable cable forces @@ -2974,14 +2926,13 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) endif ! --- Build vector of external moment - DO iNode = 1,p%nNodes + dO iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh - Moment(1:3) = u%LMesh%Moment(1:3,iNode) + Moment(1:3) = u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6)) nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's DOFList ! Extra moment dm = Delta u x (fe + fg) if (p%ExtraMoment) then - Force = Force + p%FG_full(p%NodesDOF(iNode)%List(1:3)) ! Adding gravity and initial cable du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) @@ -3349,8 +3300,8 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) ! --- write assembed GRAVITY FORCE FG VECTOR. gravity forces applied at each node of the full system WRITE(UnSum, '(A)') SectionDivide - WRITE(UnSum, '(A)') '#Initial gravity and cable loads applied at each node of the system (after DOF elimination with T matrix)' - call yaml_write_array(UnSum, 'FG', Init%FG, ReFmt, ErrStat2, ErrMsg2, comment='') + WRITE(UnSum, '(A)') '#Gravity and cable loads applied at each node of the system (before DOF elimination with T matrix)' + call yaml_write_array(UnSum, 'FG', p%FG, ReFmt, ErrStat2, ErrMsg2, comment='') ! --- write CB system matrices WRITE(UnSum, '(A)') SectionDivide diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3af761d34..2a4a6af3b 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -4,299 +4,282 @@ # Use ^ as a shortcut for the value in the same column from the previous line. ################################################################################################################################### # ...... Include files (definitions from NWTC Library) ............................................................................ -include Registry_NWTC_Library.txt +include Registry_NWTC_Library.txt -# -# Keyword ModuleName/ModName Derived data type Field type Variable name Dimemsion of the variable Initial value not used Description Units - -typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" +# ============================== Internal data types ============================================================================================================================================ +typedef SubDyn/SD IList INTEGER List {:} - - "List of integers" +# +typedef ^ MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" +typedef ^ MeshAuxDataType INTEGER NOutCnt - - - "Number of Nodes for the output member" +typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" +typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" +typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" +typedef ^ MeshAuxDataType R8Ki Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType R8Ki Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" +typedef ^ MeshAuxDataType R8Ki Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" -! integer, dimension(:), pointer :: data => null() -! type(IList), pointer :: next => null() +# CB_MatArrays: Matrices and arrays for CB summary +typedef ^ CB_MatArrays R8Ki MBB {:}{:} - - "FULL MBB ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki MBM {:}{:} - - "FULL MBM ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki KBB {:}{:} - - "FULL KBB ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" +typedef ^ CB_MatArrays R8Ki PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" +typedef ^ CB_MatArrays R8Ki OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" +# +typedef ^ ElemPropType IntKi eType - - - "Element Type" +typedef ^ ElemPropType ReKi Length - - - "Length of an element" +typedef ^ ElemPropType ReKi Ixx - - - "Moment of inertia of an element" +typedef ^ ElemPropType ReKi Iyy - - - "Moment of inertia of an element" +typedef ^ ElemPropType ReKi Jzz - - - "Moment of inertia of an element" +typedef ^ ElemPropType LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" +typedef ^ ElemPropType ReKi Kappa - - - "Shear coefficient" +typedef ^ ElemPropType ReKi YoungE - - - "Young's modulus" +typedef ^ ElemPropType ReKi ShearG - - - "Shear modulus" N/m^2 +# Properties common to all element types: +typedef ^ ElemPropType ReKi Area - - - "Area of an element" m^2 +typedef ^ ElemPropType ReKi Rho - - - "Density" kg/m^3 +typedef ^ ElemPropType ReKi T0 - - - "Pretension " N +typedef ^ ElemPropType R8Ki DirCos {3}{3} - - "Element direction cosine matrix" -# ============================== Define Initialization Inputs (from glue code) here: ============================================================================================================================================ -typedef SubDyn/SD InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" -typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" -typedef ^ InitInputType ReKi g - - - "Gravity acceleration" -typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" -typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" -typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" -typedef ^ InitInputType ReKi SoilStiffness ::: - - "Soil stiffness matrices from SoilDyn" '(N/m, N-m/rad)' -typedef ^ InitInputType MeshType SoilMesh - - - "Mesh for soil stiffness locations" - -typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - +# ============================== Input Initialization (from glue code) ============================================================================================================================================ +typedef ^ InitInputType CHARACTER(1024) SDInputFile - - - "Name of the input file" +typedef ^ InitInputType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ InitInputType ReKi g - - - "Gravity acceleration" +typedef ^ InitInputType ReKi WtrDpth - - - "Water Depth (positive valued)" +typedef ^ InitInputType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ InitInputType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ InitInputType ReKi SoilStiffness ::: - - "Soil stiffness matrices from SoilDyn" '(N/m, N-m/rad)' +typedef ^ InitInputType MeshType SoilMesh - - - "Mesh for soil stiffness locations" - +typedef ^ InitInputType Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." - -# ============================== Define Initialization outputs here: ============================================================================================================================================ -typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - -typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - -typedef ^ ^ ProgDesc Ver - - - "This module's name, version, and date" - +# ============================== Initialization outputs ============================================================================================================================================ +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "Names of the output-to-file channels" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputUnt {:} - - "Units of the output-to-file channels" - +typedef ^ InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - # Linearization -typedef ^ ^ CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - -typedef ^ ^ CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - -typedef ^ ^ CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - -typedef ^ ^ LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - -typedef ^ ^ LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - -typedef ^ ^ LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - -typedef ^ ^ LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - -typedef ^ ^ IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ InitOutputType LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue)" - +typedef ^ InitOutputType LOGICAL RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ InitOutputType LOGICAL IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ InitOutputType IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - -# ============================== Define Internal data types here: ============================================================================================================================================ -typedef SubDyn/SD MeshAuxDataType INTEGER MemberID - - - "Member ID for Output" -typedef ^ MeshAuxDataType INTEGER NOutCnt - - - "Number of Nodes for the output member" -typedef ^ MeshAuxDataType INTEGER NodeCnt {:} - - "Node ordinal numbers for the output member" -typedef ^ MeshAuxDataType INTEGER NodeIDs {:} - - "Node IDs associated with ordinal numbers for the output member" -typedef ^ MeshAuxDataType INTEGER ElmIDs {:}{:} - - "Element IDs connected to each NodeIDs; max 10 elements" -typedef ^ MeshAuxDataType INTEGER ElmNds {:}{:} - - "Flag to indicate 1st or 2nd node of element for each ElmIDs" -typedef ^ MeshAuxDataType R8Ki Me {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType R8Ki Ke {:}{:}{:}{:} - - "Mass matrix connected to each joint element for outAll output" -typedef ^ MeshAuxDataType R8Ki Fg {:}{:}{:} - - "Gravity load vector connected to each joint element for requested member output" -# CB_MatArrays: Matrices and arrays for CB summary -typedef ^ CB_MatArrays R8Ki MBB {:}{:} - - "FULL MBB ( no constraints applied)" -typedef ^ CB_MatArrays R8Ki MBM {:}{:} - - "FULL MBM ( no constraints applied)" -typedef ^ CB_MatArrays R8Ki KBB {:}{:} - - "FULL KBB ( no constraints applied)" -typedef ^ CB_MatArrays R8Ki PhiL {:}{:} - - "Retained CB modes, possibly allPhiL(nDOFL,nDOFL), or PhiL(nDOFL,nDOFM)" -typedef ^ CB_MatArrays R8Ki PhiR {:}{:} - - "FULL PhiR ( no constraints applied)" -typedef ^ CB_MatArrays R8Ki OmegaL {:} - - "Eigenvalues of retained CB modes, possibly all (nDOFL or nDOFM)" -# -typedef ^ ElemPropType IntKi eType - - - "Element Type" -typedef ^ ^ ReKi Length - - - "Length of an element" -typedef ^ ^ ReKi Ixx - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Iyy - - - "Moment of inertia of an element" -typedef ^ ^ ReKi Jzz - - - "Moment of inertia of an element" -typedef ^ ^ LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" -typedef ^ ^ ReKi Kappa - - - "Shear coefficient" -typedef ^ ^ ReKi YoungE - - - "Young's modulus" -typedef ^ ^ ReKi ShearG - - - "Shear modulus" N/m^2 -# Properties common to all element types: -typedef ^ ^ ReKi Area - - - "Area of an element" m^2 -typedef ^ ^ ReKi Rho - - - "Density" kg/m^3 -typedef ^ ^ ReKi T0 - - - "Pretension " N -typedef ^ ^ R8Ki DirCos {3}{3} - - "Element direction cosine matrix" # ============================== Define initialization data (not from glue code) here: ============================================================================================================================================ -#--------------------------arrays and variables from the input file --------------------------------------------------------------------------------------------------------------------------------- -typedef SubDyn/SD SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" -typedef ^ ^ ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" -typedef ^ ^ ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" -typedef ^ ^ ReKi g - - - "Gravity acceleration" -typedef ^ ^ DbKi DT - - - "Time step from Glue Code" seconds -typedef ^ ^ INTEGER NJoints - - - "Number of joints of the sub structure" -typedef ^ ^ INTEGER NPropSetsX - - - "Number of extended property sets" -typedef ^ ^ INTEGER NPropSetsB - - - "Number of property sets for beams" -typedef ^ ^ INTEGER NPropSetsC - - - "Number of property sets for cables" -typedef ^ ^ INTEGER NPropSetsR - - - "Number of property sets for rigid links" -typedef ^ ^ INTEGER NCMass - - - "Number of joints with concentrated mass" -typedef ^ ^ INTEGER NCOSMs - - - "Number of independent cosine matrices" -typedef ^ ^ INTEGER FEMMod - - - "FEM switch element model in the FEM" -typedef ^ ^ INTEGER NDiv - - - "Number of divisions for each member" -typedef ^ ^ LOGICAL CBMod - - - "Perform C-B flag" -typedef ^ ^ ReKi Joints {:}{:} - - "Joints number and coordinate values" -typedef ^ ^ ReKi PropSetsB {:}{:} - - "Property sets number and values" -typedef ^ ^ ReKi PropSetsC {:}{:} - - "Property ID and values for cables" -typedef ^ ^ ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" -typedef ^ ^ ReKi PropSetsX {:}{:} - - "Extended property sets" -typedef ^ ^ ReKi COSMs {:}{:} - - "Independent direction cosine matrices" -typedef ^ ^ ReKi CMass {:}{:} - - "Concentrated mass information" -typedef ^ ^ ReKi JDampings {:} - - "Damping coefficients for internal modes" -typedef ^ ^ IntKi GuyanDampMod - - - "Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix]" -typedef ^ ^ ReKi RayleighDamp {2} - - "Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1]" -typedef ^ ^ ReKi GuyanDampMat {6}{6} - - "Guyan Damping Matrix, see also CBB" -typedef ^ ^ INTEGER Members {:}{:} - - "Member joints connection" -typedef ^ ^ CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels" -typedef ^ ^ LOGICAL OutCOSM - - - "Output Cos-matrices Flag" -typedef ^ ^ LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag" -typedef ^ ^ R8Ki SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint" -typedef ^ ^ R8Ki SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint" -typedef ^ ^ CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" -typedef ^ ^ ReKi Soil_K {:}{:}{:} - - "Soil stiffness (at passed at Init, not in input file) 6x6xn" -typedef ^ ^ ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added" -typedef ^ ^ Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added" -#-------------------------- arrays and variables used in the module ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -typedef ^ ^ INTEGER NElem - - - "Total number of elements" -typedef ^ ^ INTEGER NPropB - - - "Total number of property sets for Beams" -typedef ^ ^ INTEGER NPropC - - - "Total number of property sets for Cable" -typedef ^ ^ INTEGER NPropR - - - "Total number of property sets for Rigid" -typedef ^ ^ ReKi Nodes {:}{:} - - "Nodes number and coordinates" -typedef ^ ^ ReKi PropsB {:}{:} - - "Property sets and values for Beams" -typedef ^ ^ ReKi PropsC {:}{:} - - "Property sets and values for Cable" -typedef ^ ^ ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" -typedef ^ ^ R8Ki K {:}{:} - - "System stiffness matrix" -typedef ^ ^ R8Ki M {:}{:} - - "System mass matrix" -typedef ^ ^ R8Ki FG {:} - - "Gravity force vector (include initial Cable force T0)" N -typedef ^ ^ ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" -typedef ^ ^ INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" -typedef ^ ^ INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node" -typedef ^ ^ INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" -typedef ^ ^ LOGICAL SSSum - - - "SubDyn Summary File Flag" +typedef ^ SD_InitType CHARACTER(1024) RootName - - - "SubDyn rootname" +typedef ^ SD_InitType ReKi TP_RefPoint {3} - - "global position of transition piece reference point (could also be defined in SubDyn itself)" +typedef ^ SD_InitType ReKi SubRotateZ - - - "Rotation angle in degrees about global Z" +typedef ^ SD_InitType ReKi g - - - "Gravity acceleration" +typedef ^ SD_InitType DbKi DT - - - "Time step from Glue Code" seconds +typedef ^ SD_InitType INTEGER NJoints - - - "Number of joints of the sub structure" +typedef ^ SD_InitType INTEGER NPropSetsX - - - "Number of extended property sets" +typedef ^ SD_InitType INTEGER NPropSetsB - - - "Number of property sets for beams" +typedef ^ SD_InitType INTEGER NPropSetsC - - - "Number of property sets for cables" +typedef ^ SD_InitType INTEGER NPropSetsR - - - "Number of property sets for rigid links" +typedef ^ SD_InitType INTEGER NCMass - - - "Number of joints with concentrated mass" +typedef ^ SD_InitType INTEGER NCOSMs - - - "Number of independent cosine matrices" +typedef ^ SD_InitType INTEGER FEMMod - - - "FEM switch element model in the FEM" +typedef ^ SD_InitType INTEGER NDiv - - - "Number of divisions for each member" +typedef ^ SD_InitType LOGICAL CBMod - - - "Perform C-B flag" +typedef ^ SD_InitType ReKi Joints {:}{:} - - "Joints number and coordinate values" +typedef ^ SD_InitType ReKi PropSetsB {:}{:} - - "Property sets number and values" +typedef ^ SD_InitType ReKi PropSetsC {:}{:} - - "Property ID and values for cables" +typedef ^ SD_InitType ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" +typedef ^ SD_InitType ReKi PropSetsX {:}{:} - - "Extended property sets" +typedef ^ SD_InitType ReKi COSMs {:}{:} - - "Independent direction cosine matrices" +typedef ^ SD_InitType ReKi CMass {:}{:} - - "Concentrated mass information" +typedef ^ SD_InitType ReKi JDampings {:} - - "Damping coefficients for internal modes" +typedef ^ SD_InitType IntKi GuyanDampMod - - - "Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix]" +typedef ^ SD_InitType ReKi RayleighDamp {2} - - "Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1]" +typedef ^ SD_InitType ReKi GuyanDampMat {6}{6} - - "Guyan Damping Matrix, see also CBB" +typedef ^ SD_InitType INTEGER Members {:}{:} - - "Member joints connection " +typedef ^ SD_InitType CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels " +typedef ^ SD_InitType LOGICAL OutCOSM - - - "Output Cos-matrices Flag " +typedef ^ SD_InitType LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag " +typedef ^ SD_InitType R8Ki SSIK {:}{:} - - "SSI stiffness packed matrix elements (21 of them), for each reaction joint " +typedef ^ SD_InitType R8Ki SSIM {:}{:} - - "SSI mass packed matrix elements (21 of them), for each reaction joint " +typedef ^ SD_InitType CHARACTER(1024) SSIfile {:} - - "Soil Structure Interaction (SSI) files to associate with each reaction node" +typedef ^ SD_InitType ReKi Soil_K {:}{:}{:} - - "Soil stiffness (at passed at Init, not in input file) 6x6xn " +typedef ^ SD_InitType ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added " +typedef ^ SD_InitType Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added " +typedef ^ SD_InitType INTEGER NElem - - - "Total number of elements" +typedef ^ SD_InitType INTEGER NPropB - - - "Total number of property sets for Beams" +typedef ^ SD_InitType INTEGER NPropC - - - "Total number of property sets for Cable" +typedef ^ SD_InitType INTEGER NPropR - - - "Total number of property sets for Rigid" +typedef ^ SD_InitType ReKi Nodes {:}{:} - - "Nodes number and coordinates " +typedef ^ SD_InitType ReKi PropsB {:}{:} - - "Property sets and values for Beams " +typedef ^ SD_InitType ReKi PropsC {:}{:} - - "Property sets and values for Cable " +typedef ^ SD_InitType ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" +typedef ^ SD_InitType R8Ki K {:}{:} - - "System stiffness matrix " +typedef ^ SD_InitType R8Ki M {:}{:} - - "System mass matrix " +typedef ^ SD_InitType ReKi ElemProps {:}{:} - - "Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) )" +typedef ^ SD_InitType INTEGER MemberNodes {:}{:} - - "Member number and list of nodes making up a member (>2 if subdivided)" +typedef ^ SD_InitType INTEGER NodesConnN {:}{:} - - "Nodes that connect to a common node " +typedef ^ SD_InitType INTEGER NodesConnE {:}{:} - - "Elements that connect to a common node" +typedef ^ SD_InitType LOGICAL SSSum - - - "SubDyn Summary File Flag " # ============================== States ============================================================================================================================================ -# Define continuous (differentiable) states here: -typedef ^ ContinuousStateType R8Ki qm {:} - - "Virtual states, Nmod elements" -typedef ^ ContinuousStateType R8Ki qmdot {:} - - "Derivative of states, Nmod elements" -# Define discrete (nondifferentiable) states here: -typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" -# Define constraint states here: -typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" +typedef ^ ContinuousStateType R8Ki qm {:} - - "Virtual states, Nmod elements" +typedef ^ ContinuousStateType R8Ki qmdot {:} - - "Derivative of states, Nmod elements" + +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" -# Define any other states, including integer or logical states here: -typedef SubDyn/SD OtherStateType SD_ContinuousStateType xdot {:} - - "previous state derivs for m-step time integrator" -typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated last" +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" +typedef ^ OtherStateType SD_ContinuousStateType xdot {:} - - "previous state derivs for m-step time integrator" +typedef ^ ^ IntKi n - - - "tracks time step for which OtherState was updated last" # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi qmdotdot {:} - - "2nd Derivative of states, used only for output-file purposes" -typedef ^ ^ ReKi u_TP 6 - - -typedef ^ ^ ReKi udot_TP 6 - - -typedef ^ ^ ReKi udotdot_TP 6 - - -typedef ^ ^ ReKi UFL {:} - - -typedef ^ ^ ReKi UR_bar {:} - - -typedef ^ ^ ReKi UR_bar_dot {:} - - -typedef ^ ^ ReKi UR_bar_dotdot {:} - - -typedef ^ ^ ReKi UL {:} - - -typedef ^ ^ ReKi UL_dot {:} - - -typedef ^ ^ ReKi UL_dotdot {:} - - -typedef ^ ^ ReKi DU_full {:} - - "Delta U used for extra moment" -typedef ^ ^ ReKi U_full {:} - - -typedef ^ ^ ReKi U_full_dot {:} - - -typedef ^ ^ ReKi U_full_dotdot {:} - - -typedef ^ ^ ReKi U_full_elast {:} - - "Elastic displacements for computation of K ue (without rigid body mode for floating)" -typedef ^ ^ ReKi U_red {:} - - -typedef ^ ^ ReKi U_red_dot {:} - - -typedef ^ ^ ReKi U_red_dotdot {:} - - -typedef ^ ^ ReKi FC_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N +typedef ^ MiscVarType ReKi qmdotdot {:} - - "2nd Derivative of states, used only for output-file purposes" +typedef ^ MiscVarType ReKi u_TP 6 - - +typedef ^ MiscVarType ReKi udot_TP 6 - - +typedef ^ MiscVarType ReKi udotdot_TP 6 - - +typedef ^ MiscVarType ReKi UFL {:} - - +typedef ^ MiscVarType ReKi UR_bar {:} - - +typedef ^ MiscVarType ReKi UR_bar_dot {:} - - +typedef ^ MiscVarType ReKi UR_bar_dotdot {:} - - +typedef ^ MiscVarType ReKi UL {:} - - +typedef ^ MiscVarType ReKi UL_dot {:} - - +typedef ^ MiscVarType ReKi UL_dotdot {:} - - +typedef ^ MiscVarType ReKi DU_full {:} - - "Delta U used for extra moment" +typedef ^ MiscVarType ReKi U_full {:} - - +typedef ^ MiscVarType ReKi U_full_dot {:} - - +typedef ^ MiscVarType ReKi U_full_dotdot {:} - - +typedef ^ MiscVarType ReKi U_full_elast {:} - - "Elastic displacements for computation of K ue (without rigid body mode for floating)" +typedef ^ MiscVarType ReKi U_red {:} - - +typedef ^ MiscVarType ReKi U_red_dot {:} - - +typedef ^ MiscVarType ReKi U_red_dotdot {:} - - +typedef ^ MiscVarType ReKi FC_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N +typedef ^ MiscVarType ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" +typedef ^ MiscVarType DbKi LastOutTime - - - "The time of the most recent stored output data" "s" +typedef ^ MiscVarType IntKi Decimat - - - "Current output decimation counter" "-" +typedef ^ MiscVarType ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" +typedef ^ MiscVarType ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" ### data for writing to an output file (this data is associated with time, but saved/written in CalcOutput so not stored as an other state) ### -typedef ^ ^ ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" -typedef ^ ^ DbKi LastOutTime - - - "The time of the most recent stored output data" "s" -typedef ^ ^ IntKi Decimat - - - "Current output decimation counter" "-" -typedef ^ ^ ReKi Fext {:} - - "External loads on unconstrained DOFs" "-" -typedef ^ ^ ReKi Fext_red {:} - - "External loads on constrained DOFs, Fext_red= T^t Fext" "-" - - # ============================== Parameters ============================================================================================================================================ -# --- Algo -typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds -typedef ^ ParameterType IntKi IntMethod - - - "INtegration Method (1/2/3)Length of y2 array" -# --- FEM -typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" -typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" -typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" -typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" -typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" -typedef ^ ^ R8Ki FG_full {:} - - "Gravity force vector (with initial cable force T0), not reduced" N -typedef ^ ^ ReKi DP0 {:}{:} - - "Vector from TP to a Node at t=0, used for Floating Rigid Body motion" m -# --- Constraints reduction -typedef ^ ^ Logical reduced - - - "True if system has been reduced to account for constraints" "-" -typedef ^ ^ R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" -typedef ^ ^ R8Ki T_red_T {:}{:} - - "Transpose of T_red" "-" -typedef ^ ^ IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" -typedef ^ ^ IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" -typedef ^ ^ IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" -typedef ^ ^ IntKi DOFred2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" -# --- Control -typedef ^ ^ IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x 2, for each CtrlCable, Elem index, and Channel Index" -# --- CB reduction -typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" -typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" -typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" -typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node)" -typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" -typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" -typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" -typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" -typedef ^ ParameterType ReKi FX {:} - - "Load components in X" -typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" -typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" -typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" -typedef ^ ParameterType ReKi FY {:} - - "Load Components in Y1" -typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" -typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R bar * TI)" -typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" -typedef ^ ParameterType ReKi F2_61 {:} - - "Load Component in Y2" -typedef ^ ParameterType ReKi MBB {:}{:} - - "Guyan Mass Matrix after C-B reduction" -typedef ^ ParameterType ReKi KBB {:}{:} - - "Guyan Stiffness Matrix after C-B reduction" -typedef ^ ParameterType ReKi CBB {:}{:} - - "Guyan Damping Matrix after C-B reduction" -typedef ^ ParameterType ReKi CMB {:}{:} - - "Cross coupling Guyan-CB damping matrix" -typedef ^ ParameterType ReKi CBM {:}{:} - - "Cross coupling Guyan-CB damping matrix" -typedef ^ ParameterType ReKi CMM {:}{:} - - "CB damping matrix" -typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" -typedef ^ ParameterType ReKi UL_st_g {:} - - "Motion of internal DOFs due to static gravitational force, for static improvement" -typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" -typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" -typedef ^ ParameterType ReKi KLLm1 {:}{:} - - "KLL^{-1}, inverse of matrix KLL, for static solve only" -typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" -typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" -typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" -typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" -# --- Partitioning I L C Y, R=[C I] -typedef ^ ParameterType IntKi nNodes - - - "Total number of nodes" -typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" -typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" -typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" -typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" -typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" -typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" -typedef ^ ParameterType IntKi nDOFI__ - - - "Size of IDI__" -typedef ^ ParameterType IntKi nDOFI_Rb - - - "Size of IDI_Rb" -typedef ^ ParameterType IntKi nDOFI_F - - - "Size of IDI_F" -typedef ^ ParameterType IntKi nDOFL_L - - - "Size of IDL_L" -typedef ^ ParameterType IntKi nDOFC__ - - - "Size of IDC__" -typedef ^ ParameterType IntKi nDOFC_Rb - - - "Size of IDC_Rb" -typedef ^ ParameterType IntKi nDOFC_L - - - "Size of IDC_L" -typedef ^ ParameterType IntKi nDOFC_F - - - "Size of IDC_F" -typedef ^ ParameterType IntKi nDOFR__ - - - "Size of IDR__" -typedef ^ ParameterType IntKi nDOF__Rb - - - "Size of ID__Rb" -typedef ^ ParameterType IntKi nDOF__L - - - "Size of ID__L" -typedef ^ ParameterType IntKi nDOF__F - - - "Size of ID__F" -typedef ^ ParameterType IntKi IDI__ {:} - - "Index of all Interface DOFs" -typedef ^ ParameterType IntKi IDI_Rb {:} - - "Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs" -typedef ^ ParameterType IntKi IDI_F {:} - - "Index array of the interface (nodes connect to TP) dofs that are fixed DOF" -typedef ^ ParameterType IntKi IDL_L {:} - - "Index array of the internal dofs coming from internal nodes" -typedef ^ ParameterType IntKi IDC__ {:} - - "Index of all bottom DOF" -typedef ^ ParameterType IntKi IDC_Rb {:} - - "Index array of the contraint dofs that are retained/master/follower DOF" -typedef ^ ParameterType IntKi IDC_L {:} - - "Index array of the contraint dofs that are follower/internal DOF" -typedef ^ ParameterType IntKi IDC_F {:} - - "Index array of the contraint dofs that are fixd DOF" -typedef ^ ParameterType IntKi IDR__ {:} - - "Index array of the interface and restraint dofs" -typedef ^ ParameterType IntKi ID__Rb {:} - - "Index array of all the retained/leader/master dofs (from any nodes of the structure)" -typedef ^ ParameterType IntKi ID__L {:} - - "Index array of all the follower/internal dofs (from any nodes of the structure)" -typedef ^ ParameterType IntKi ID__F {:} - - "Index array of the DOF that are fixed (from any nodes of the structure)" -typedef ^ ParameterType ReKi FGL {:} - - "Internal node nDOFL, gravity loads" -# --- Outputs -typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" -typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" -typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" -typedef ^ ParameterType IntKi UnJckF - - - "Unit of SD ouput file" -typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" -typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format for Output" -typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" -typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" -typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" -typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" -typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" -typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" -typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" -typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" -typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" -typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" -# --- Linearization -typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - -typedef ^ ParameterType R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" -typedef ^ ParameterType R8Ki dx {2} - - "vector that determines size of perturbation for x (continuous states)" -typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - -typedef ^ ParameterType Integer Jac_nx - - - "half the number of continuous states in jacobian matrix" - -typedef ^ ParameterType logical RotStates - - - "Orient states in rotating frame during linearization? (flag)" - +# --- Parameters - Algo +typedef ^ ParameterType DbKi SDDeltaT - - - "Time step (for integration of continuous states)" seconds +typedef ^ ParameterType IntKi IntMethod - - - "Integration Method (1/2/3)Length of y2 array" +# --- Parameters - FEM +typedef ^ ParameterType INTEGER nDOF - - - "Total degree of freedom" +typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" +typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" +typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" +typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" +typedef ^ ParameterType R8Ki FG {:} - - "Gravity force vector (with initial cable force T0), not reduced" N +typedef ^ ParameterType ReKi DP0 {:}{:} - - "Vector from TP to a Node at t=0, used for Floating Rigid Body motion" m +# --- Parameters - Constraints reduction +typedef ^ ParameterType Logical reduced - - - "True if system has been reduced to account for constraints" "-" +typedef ^ ParameterType R8Ki T_red {:}{:} - - "Transformation matrix performing the constraint reduction x = T. xtilde" "-" +typedef ^ ParameterType R8Ki T_red_T {:}{:} - - "Transpose of T_red" "-" +typedef ^ ParameterType IList NodesDOF {:} - - "DOF indices of each nodes in unconstrained assembled system " "-" +typedef ^ ParameterType IList NodesDOFred {:} - - "DOF indices of each nodes in constrained assembled system " "-" +typedef ^ ParameterType IntKi ElemsDOF {:}{:} - - "12 DOF indices of node 1 and 2 of a given member in unconstrained assembled system " "-" +typedef ^ ParameterType IntKi DOFred2Nodes {:}{:} - - "nDOFRed x 3, for each constrained DOF, col1 node index, col2 number of DOF, col3 DOF starting from 1" "-" +# --- Parameters - Control +typedef ^ ParameterType IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x 2, for each CtrlCable, Elem index, and Channel Index" +# --- Parameters - CB reduction +typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" +typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" +typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" +typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node)" +typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" +typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" +typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" +typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" +typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" +typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" +typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" +typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" +typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" +typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi PhiRb_TI {:}{:} - - "Coefficient of u in Y2 (Phi_R bar * TI)" +typedef ^ ParameterType ReKi D2_63 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 (URdotdot ULdotdot)" +typedef ^ ParameterType ReKi MBB {:}{:} - - "Guyan Mass Matrix after C-B reduction" +typedef ^ ParameterType ReKi KBB {:}{:} - - "Guyan Stiffness Matrix after C-B reduction" +typedef ^ ParameterType ReKi CBB {:}{:} - - "Guyan Damping Matrix after C-B reduction" +typedef ^ ParameterType ReKi CMB {:}{:} - - "Cross coupling Guyan-CB damping matrix" +typedef ^ ParameterType ReKi CBM {:}{:} - - "Cross coupling Guyan-CB damping matrix" +typedef ^ ParameterType ReKi CMM {:}{:} - - "CB damping matrix" +typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" +typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" +typedef ^ ParameterType ReKi PhiLInvOmgL2 {:}{:} - - "Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1)" +typedef ^ ParameterType ReKi KLLm1 {:}{:} - - "KLL^{-1}, inverse of matrix KLL, for static solve only" +typedef ^ ParameterType ReKi AM2Jac {:}{:} - - "Jacobian (factored) for Adams-Boulton 2nd order Integration" +typedef ^ ParameterType IntKi AM2JacPiv {:} - - "Pivot array for Jacobian factorization (for Adams-Boulton 2nd order Integration)" +typedef ^ ParameterType ReKi TI {:}{:} - - "Matrix to calculate TP reference point reaction at top of structure" +typedef ^ ParameterType ReKi TIreact {:}{:} - - "Matrix to calculate single point reaction at base of structure" +# --- Parameters - Partitioning I L C Y, R=[C I] +typedef ^ ParameterType IntKi nNodes - - - "Total number of nodes" +typedef ^ ParameterType IntKi nNodes_I - - - "Number of Interface nodes" +typedef ^ ParameterType IntKi nNodes_L - - - "Number of Internal nodes" +typedef ^ ParameterType IntKi nNodes_C - - - "Number of joints with reactions" +typedef ^ ParameterType IntKi Nodes_I {:}{:} - - "Interface degree of freedoms" +typedef ^ ParameterType IntKi Nodes_L {:}{:} - - "Internal nodes (not interface nor reaction)" +typedef ^ ParameterType IntKi Nodes_C {:}{:} - - "React degree of freedoms" +typedef ^ ParameterType IntKi nDOFI__ - - - "Size of IDI__" +typedef ^ ParameterType IntKi nDOFI_Rb - - - "Size of IDI_Rb" +typedef ^ ParameterType IntKi nDOFI_F - - - "Size of IDI_F" +typedef ^ ParameterType IntKi nDOFL_L - - - "Size of IDL_L" +typedef ^ ParameterType IntKi nDOFC__ - - - "Size of IDC__" +typedef ^ ParameterType IntKi nDOFC_Rb - - - "Size of IDC_Rb" +typedef ^ ParameterType IntKi nDOFC_L - - - "Size of IDC_L" +typedef ^ ParameterType IntKi nDOFC_F - - - "Size of IDC_F" +typedef ^ ParameterType IntKi nDOFR__ - - - "Size of IDR__" +typedef ^ ParameterType IntKi nDOF__Rb - - - "Size of ID__Rb" +typedef ^ ParameterType IntKi nDOF__L - - - "Size of ID__L" +typedef ^ ParameterType IntKi nDOF__F - - - "Size of ID__F" +typedef ^ ParameterType IntKi IDI__ {:} - - "Index of all Interface DOFs" +typedef ^ ParameterType IntKi IDI_Rb {:} - - "Index array of the interface (nodes connect to TP) dofs that are retained/master/follower DOFs" +typedef ^ ParameterType IntKi IDI_F {:} - - "Index array of the interface (nodes connect to TP) dofs that are fixed DOF" +typedef ^ ParameterType IntKi IDL_L {:} - - "Index array of the internal dofs coming from internal nodes" +typedef ^ ParameterType IntKi IDC__ {:} - - "Index of all bottom DOF" +typedef ^ ParameterType IntKi IDC_Rb {:} - - "Index array of the contraint dofs that are retained/master/follower DOF" +typedef ^ ParameterType IntKi IDC_L {:} - - "Index array of the contraint dofs that are follower/internal DOF" +typedef ^ ParameterType IntKi IDC_F {:} - - "Index array of the contraint dofs that are fixd DOF" +typedef ^ ParameterType IntKi IDR__ {:} - - "Index array of the interface and restraint dofs" +typedef ^ ParameterType IntKi ID__Rb {:} - - "Index array of all the retained/leader/master dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__L {:} - - "Index array of all the follower/internal dofs (from any nodes of the structure)" +typedef ^ ParameterType IntKi ID__F {:} - - "Index array of the DOF that are fixed (from any nodes of the structure)" +# --- Parameters - Outputs +typedef ^ ParameterType IntKi NMOutputs - - - "Number of members whose output is written" +typedef ^ ParameterType IntKi NumOuts - - - "Number of output channels read from input file" +typedef ^ ParameterType IntKi OutSwtch - - - "Output Requested Channels to local or global output file [1/2/3]" +typedef ^ ParameterType IntKi UnJckF - - - "Unit of SD ouput file" +typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" +typedef ^ ParameterType CHARACTER(20) OutFmt - - - "Format for Output" +typedef ^ ParameterType CHARACTER(20) OutSFmt - - - "Format for Output Headers" +typedef ^ ParameterType MeshAuxDataType MoutLst {:} - - "List of user requested members and nodes" +typedef ^ ParameterType MeshAuxDataType MoutLst2 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType MeshAuxDataType MoutLst3 {:} - - "List of all member joint nodes and elements for output" +typedef ^ ParameterType OutParmType OutParam {:} - - "An array holding names, units, and indices of all of the selected output channels. # logical" +typedef ^ ParameterType LOGICAL OutAll - - - "Flag to output or not all joint forces" +typedef ^ ParameterType LOGICAL OutReact - - - "Flag to check whether reactions are requested" +typedef ^ ParameterType IntKi OutAllInt - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutAllDims - - - "Integer version of OutAll" +typedef ^ ParameterType IntKi OutDec - - - "Output Decimation for Requested Channels" +# --- Parametesr - Linearization +typedef ^ ParameterType Integer Jac_u_indx {:}{:} - - "matrix to help fill/pack the u vector in computing the jacobian" - +typedef ^ ParameterType R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" +typedef ^ ParameterType R8Ki dx {2} - - "vector that determines size of perturbation for x (continuous states)" +typedef ^ ParameterType Integer Jac_ny - - - "number of outputs in jacobian matrix" - +typedef ^ ParameterType Integer Jac_nx - - - "half the number of continuous states in jacobian matrix" - +typedef ^ ParameterType logical RotStates - - - "Orient states in rotating frame during linearization? (flag)" - # ============================== Inputs ============================================================================================================================================ -typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" -typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" -typedef ^ InputType ReKi CableDeltaL {:} - - "Cable tension, control input" +typedef ^ InputType MeshType TPMesh - - - "Transition piece inputs on a point mesh" +typedef ^ InputType MeshType LMesh - - - "Point mesh for interior node inputs" +typedef ^ InputType ReKi CableDeltaL {:} - - "Cable tension, control input" # ============================== Outputs ============================================================================================================================================ -typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" -typedef ^ OutputType MeshType Y2Mesh - - - "Interior+Interface nodes outputs on a point mesh" -typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file" +typedef ^ OutputType MeshType Y1Mesh - - - "Transition piece outputs on a point mesh" +typedef ^ OutputType MeshType Y2Mesh - - - "Interior+Interface nodes outputs on a point mesh" +typedef ^ OutputType ReKi WriteOutput {:} - - "Data to be written to an output file" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 7b6c13e93..7b0055385 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -38,34 +38,6 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: List !< List of integers [-] END TYPE IList ! ======================= -! ========= SD_InitInputType ======= - TYPE, PUBLIC :: SD_InitInputType - CHARACTER(1024) :: SDInputFile !< Name of the input file [-] - CHARACTER(1024) :: RootName !< SubDyn rootname [-] - REAL(ReKi) :: g !< Gravity acceleration [-] - REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] - REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] - REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SoilStiffness !< Soil stiffness matrices from SoilDyn ['(N/m,] - TYPE(MeshType) :: SoilMesh !< Mesh for soil stiffness locations [-] - LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] - END TYPE SD_InitInputType -! ======================= -! ========= SD_InitOutputType ======= - TYPE, PUBLIC :: SD_InitOutputType - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] - TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] - CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] - CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states used in linearization [-] - CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] - LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame [-] - LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue) [-] - LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] - LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] - END TYPE SD_InitOutputType -! ======================= ! ========= MeshAuxDataType ======= TYPE, PUBLIC :: MeshAuxDataType INTEGER(IntKi) :: MemberID !< Member ID for Output [-] @@ -106,6 +78,34 @@ MODULE SubDyn_Types REAL(R8Ki) , DIMENSION(1:3,1:3) :: DirCos !< Element direction cosine matrix [-] END TYPE ElemPropType ! ======================= +! ========= SD_InitInputType ======= + TYPE, PUBLIC :: SD_InitInputType + CHARACTER(1024) :: SDInputFile !< Name of the input file [-] + CHARACTER(1024) :: RootName !< SubDyn rootname [-] + REAL(ReKi) :: g !< Gravity acceleration [-] + REAL(ReKi) :: WtrDpth !< Water Depth (positive valued) [-] + REAL(ReKi) , DIMENSION(1:3) :: TP_RefPoint !< global position of transition piece reference point (could also be defined in SubDyn itself) [-] + REAL(ReKi) :: SubRotateZ !< Rotation angle in degrees about global Z [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: SoilStiffness !< Soil stiffness matrices from SoilDyn ['(N/m,] + TYPE(MeshType) :: SoilMesh !< Mesh for soil stiffness locations [-] + LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-] + END TYPE SD_InitInputType +! ======================= +! ========= SD_InitOutputType ======= + TYPE, PUBLIC :: SD_InitOutputType + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of the output-to-file channels [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of the output-to-file channels [-] + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states used in linearization [-] + CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame (not used for glue) [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + END TYPE SD_InitOutputType +! ======================= ! ========= SD_InitType ======= TYPE, PUBLIC :: SD_InitType CHARACTER(1024) :: RootName !< SubDyn rootname [-] @@ -134,32 +134,31 @@ MODULE SubDyn_Types INTEGER(IntKi) :: GuyanDampMod !< Guyan damping [0=none, 1=Rayleigh Damping, 2= user specified 6x6 matrix] [-] REAL(ReKi) , DIMENSION(1:2) :: RayleighDamp !< Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] [-] REAL(ReKi) , DIMENSION(1:6,1:6) :: GuyanDampMat !< Guyan Damping Matrix, see also CBB [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] - CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] - LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] - LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] + LOGICAL :: OutCOSM !< Output Cos-matrices Flag [-] + LOGICAL :: TabDelim !< Generate a tab-delimited output file in OutJckF-Flag [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIK !< SSI stiffness packed matrix elements (21 of them), for each reaction joint [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: SSIM !< SSI mass packed matrix elements (21 of them), for each reaction joint [-] CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: SSIfile !< Soil Structure Interaction (SSI) files to associate with each reaction node [-] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Soil_K !< Soil stiffness (at passed at Init, not in input file) 6x6xn [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] + REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Soil_K !< Soil stiffness (at passed at Init, not in input file) 6x6xn [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] INTEGER(IntKi) :: NElem !< Total number of elements [-] INTEGER(IntKi) :: NPropB !< Total number of property sets for Beams [-] INTEGER(IntKi) :: NPropC !< Total number of property sets for Cable [-] INTEGER(IntKi) :: NPropR !< Total number of property sets for Rigid [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] - REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (include initial Cable force T0) [N] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: K !< System stiffness matrix [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: M !< System mass matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: ElemProps !< Element properties(A, L, Ixx, Iyy, Jzz, Shear, Kappa, E, G, Rho, DirCos(1,1), DirCos(2, 1), ....., DirCos(3, 3) ) [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: MemberNodes !< Member number and list of nodes making up a member (>2 if subdivided) [-] - INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnN !< Nodes that connect to a common node [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: NodesConnE !< Elements that connect to a common node [-] - LOGICAL :: SSSum !< SubDyn Summary File Flag [-] + LOGICAL :: SSSum !< SubDyn Summary File Flag [-] END TYPE SD_InitType ! ======================= ! ========= SD_ContinuousStateType ======= @@ -216,13 +215,13 @@ MODULE SubDyn_Types ! ========= SD_ParameterType ======= TYPE, PUBLIC :: SD_ParameterType REAL(DbKi) :: SDDeltaT !< Time step (for integration of continuous states) [seconds] - INTEGER(IntKi) :: IntMethod !< INtegration Method (1/2/3)Length of y2 array [-] + INTEGER(IntKi) :: IntMethod !< Integration Method (1/2/3)Length of y2 array [-] INTEGER(IntKi) :: nDOF !< Total degree of freedom [-] INTEGER(IntKi) :: nDOF_red !< Total degree of freedom after constraint reduction [-] INTEGER(IntKi) :: Nmembers !< Number of members of the sub structure [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] - REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG_full !< Gravity force vector (with initial cable force T0), not reduced [N] + REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector (with initial cable force T0), not reduced [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: DP0 !< Vector from TP to a Node at t=0, used for Floating Rigid Body motion [m] LOGICAL :: reduced !< True if system has been reduced to account for constraints [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: T_red !< Transformation matrix performing the constraint reduction x = T. xtilde [-] @@ -240,20 +239,17 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FX !< Load components in X [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FY !< Load Components in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiRb_TI !< Coefficient of u in Y2 (Phi_R bar * TI) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_63 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D2_64 !< Coefficient of u in Y2 (URdotdot ULdotdot) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F2_61 !< Load Component in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Guyan Mass Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Guyan Stiffness Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< Guyan Damping Matrix after C-B reduction [-] @@ -261,7 +257,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< Cross coupling Guyan-CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UL_st_g !< Motion of internal DOFs due to static gravitational force, for static improvement [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiLInvOmgL2 !< Matrix of C-B modes times the inverse of OmegaL**2 (Phi_L*(Omg**2)^-1) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KLLm1 !< KLL^{-1}, inverse of matrix KLL, for static solve only [-] @@ -300,7 +295,6 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__Rb !< Index array of all the retained/leader/master dofs (from any nodes of the structure) [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__L !< Index array of all the follower/internal dofs (from any nodes of the structure) [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: ID__F !< Index array of the DOF that are fixed (from any nodes of the structure) [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FGL !< Internal node nDOFL, gravity loads [-] INTEGER(IntKi) :: NMOutputs !< Number of members whose output is written [-] INTEGER(IntKi) :: NumOuts !< Number of output channels read from input file [-] INTEGER(IntKi) :: OutSwtch !< Output Requested Channels to local or global output file [1/2/3] [-] @@ -520,9 +514,9 @@ SUBROUTINE SD_UnPackIList( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END IF END SUBROUTINE SD_UnPackIList - SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(INOUT) :: SrcInitInputData - TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData + SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(IN) :: SrcMeshAuxDataTypeData + TYPE(MeshAuxDataType), INTENT(INOUT) :: DstMeshAuxDataTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -531,60 +525,158 @@ SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMeshAuxDataType' ! ErrStat = ErrID_None ErrMsg = "" - DstInitInputData%SDInputFile = SrcInitInputData%SDInputFile - DstInitInputData%RootName = SrcInitInputData%RootName - DstInitInputData%g = SrcInitInputData%g - DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth - DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint - DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ -IF (ALLOCATED(SrcInitInputData%SoilStiffness)) THEN - i1_l = LBOUND(SrcInitInputData%SoilStiffness,1) - i1_u = UBOUND(SrcInitInputData%SoilStiffness,1) - i2_l = LBOUND(SrcInitInputData%SoilStiffness,2) - i2_u = UBOUND(SrcInitInputData%SoilStiffness,2) - i3_l = LBOUND(SrcInitInputData%SoilStiffness,3) - i3_u = UBOUND(SrcInitInputData%SoilStiffness,3) - IF (.NOT. ALLOCATED(DstInitInputData%SoilStiffness)) THEN - ALLOCATE(DstInitInputData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + DstMeshAuxDataTypeData%MemberID = SrcMeshAuxDataTypeData%MemberID + DstMeshAuxDataTypeData%NOutCnt = SrcMeshAuxDataTypeData%NOutCnt +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeCnt)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeCnt)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeCnt.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitInputData%SoilStiffness = SrcInitInputData%SoilStiffness + DstMeshAuxDataTypeData%NodeCnt = SrcMeshAuxDataTypeData%NodeCnt ENDIF - CALL MeshCopy( SrcInitInputData%SoilMesh, DstInitInputData%SoilMesh, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - DstInitInputData%Linearize = SrcInitInputData%Linearize - END SUBROUTINE SD_CopyInitInput +IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%NodeIDs = SrcMeshAuxDataTypeData%NodeIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmIDs)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmIDs)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmIDs = SrcMeshAuxDataTypeData%ElmIDs +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmNds)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,2) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmNds)) THEN + ALLOCATE(DstMeshAuxDataTypeData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Me,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Me,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Me,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Me,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Me,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Me,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Me)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Me.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Me = SrcMeshAuxDataTypeData%Me +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Ke)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Ke,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Ke,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Ke,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Ke,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Ke,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Ke,3) + i4_l = LBOUND(SrcMeshAuxDataTypeData%Ke,4) + i4_u = UBOUND(SrcMeshAuxDataTypeData%Ke,4) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Ke)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Ke = SrcMeshAuxDataTypeData%Ke +ENDIF +IF (ALLOCATED(SrcMeshAuxDataTypeData%Fg)) THEN + i1_l = LBOUND(SrcMeshAuxDataTypeData%Fg,1) + i1_u = UBOUND(SrcMeshAuxDataTypeData%Fg,1) + i2_l = LBOUND(SrcMeshAuxDataTypeData%Fg,2) + i2_u = UBOUND(SrcMeshAuxDataTypeData%Fg,2) + i3_l = LBOUND(SrcMeshAuxDataTypeData%Fg,3) + i3_u = UBOUND(SrcMeshAuxDataTypeData%Fg,3) + IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Fg)) THEN + ALLOCATE(DstMeshAuxDataTypeData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg +ENDIF + END SUBROUTINE SD_CopyMeshAuxDataType - SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) - TYPE(SD_InitInputType), INTENT(INOUT) :: InitInputData + SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) + TYPE(MeshAuxDataType), INTENT(INOUT) :: MeshAuxDataTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMeshAuxDataType' INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(InitInputData%SoilStiffness)) THEN - DEALLOCATE(InitInputData%SoilStiffness) +IF (ALLOCATED(MeshAuxDataTypeData%NodeCnt)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeCnt) ENDIF - CALL MeshDestroy( InitInputData%SoilMesh, ErrStat, ErrMsg ) - END SUBROUTINE SD_DestroyInitInput +IF (ALLOCATED(MeshAuxDataTypeData%NodeIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%NodeIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmIDs)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmIDs) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%ElmNds)) THEN + DEALLOCATE(MeshAuxDataTypeData%ElmNds) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Me)) THEN + DEALLOCATE(MeshAuxDataTypeData%Me) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Ke)) THEN + DEALLOCATE(MeshAuxDataTypeData%Ke) +ENDIF +IF (ALLOCATED(MeshAuxDataTypeData%Fg)) THEN + DEALLOCATE(MeshAuxDataTypeData%Fg) +ENDIF + END SUBROUTINE SD_DestroyMeshAuxDataType - SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InitInputType), INTENT(IN) :: InData + TYPE(MeshAuxDataType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -599,7 +691,7 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMeshAuxDataType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -615,36 +707,43 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%SDInputFile) ! SDInputFile - Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName - Re_BufSz = Re_BufSz + 1 ! g - Re_BufSz = Re_BufSz + 1 ! WtrDpth - Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint - Re_BufSz = Re_BufSz + 1 ! SubRotateZ - Int_BufSz = Int_BufSz + 1 ! SoilStiffness allocated yes/no - IF ( ALLOCATED(InData%SoilStiffness) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! SoilStiffness upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%SoilStiffness) ! SoilStiffness + Int_BufSz = Int_BufSz + 1 ! MemberID + Int_BufSz = Int_BufSz + 1 ! NOutCnt + Int_BufSz = Int_BufSz + 1 ! NodeCnt allocated yes/no + IF ( ALLOCATED(InData%NodeCnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeCnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeCnt) ! NodeCnt + END IF + Int_BufSz = Int_BufSz + 1 ! NodeIDs allocated yes/no + IF ( ALLOCATED(InData%NodeIDs) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! NodeIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%NodeIDs) ! NodeIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmIDs allocated yes/no + IF ( ALLOCATED(InData%ElmIDs) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmIDs upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmIDs) ! ElmIDs + END IF + Int_BufSz = Int_BufSz + 1 ! ElmNds allocated yes/no + IF ( ALLOCATED(InData%ElmNds) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds + END IF + Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no + IF ( ALLOCATED(InData%Me) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Me) ! Me + END IF + Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no + IF ( ALLOCATED(InData%Ke) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Ke) ! Ke + END IF + Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no + IF ( ALLOCATED(InData%Fg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%Fg) ! Fg END IF - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! SoilMesh: size of buffers for each call to pack subtype - CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! SoilMesh - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! SoilMesh - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! SoilMesh - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 1 ! Linearize IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -672,86 +771,172 @@ SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 - DO I = 1, LEN(InData%SDInputFile) - IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(InData%RootName) - IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf(Re_Xferred) = InData%g - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%WtrDpth - Re_Xferred = Re_Xferred + 1 - DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) - ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) - Re_Xferred = Re_Xferred + 1 - END DO - ReKiBuf(Re_Xferred) = InData%SubRotateZ - Re_Xferred = Re_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%SoilStiffness) ) THEN + IntKiBuf(Int_Xferred) = InData%MemberID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NOutCnt + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%NodeCnt) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeCnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeCnt,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,2) + + DO i1 = LBOUND(InData%NodeCnt,1), UBOUND(InData%NodeCnt,1) + IntKiBuf(Int_Xferred) = InData%NodeCnt(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%NodeIDs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIDs,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,3) + + DO i1 = LBOUND(InData%NodeIDs,1), UBOUND(InData%NodeIDs,1) + IntKiBuf(Int_Xferred) = InData%NodeIDs(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElmIDs) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,2) Int_Xferred = Int_Xferred + 2 - DO i3 = LBOUND(InData%SoilStiffness,3), UBOUND(InData%SoilStiffness,3) - DO i2 = LBOUND(InData%SoilStiffness,2), UBOUND(InData%SoilStiffness,2) - DO i1 = LBOUND(InData%SoilStiffness,1), UBOUND(InData%SoilStiffness,1) - ReKiBuf(Re_Xferred) = InData%SoilStiffness(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%ElmIDs,2), UBOUND(InData%ElmIDs,2) + DO i1 = LBOUND(InData%ElmIDs,1), UBOUND(InData%ElmIDs,1) + IntKiBuf(Int_Xferred) = InData%ElmIDs(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ElmNds) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%ElmNds,2), UBOUND(InData%ElmNds,2) + DO i1 = LBOUND(InData%ElmNds,1), UBOUND(InData%ElmNds,1) + IntKiBuf(Int_Xferred) = InData%ElmNds(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Me) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Me,4), UBOUND(InData%Me,4) + DO i3 = LBOUND(InData%Me,3), UBOUND(InData%Me,3) + DO i2 = LBOUND(InData%Me,2), UBOUND(InData%Me,2) + DO i1 = LBOUND(InData%Me,1), UBOUND(InData%Me,1) + DbKiBuf(Db_Xferred) = InData%Me(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO END DO END DO END DO END IF - CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN + IF ( .NOT. ALLOCATED(InData%Ke) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) + Int_Xferred = Int_Xferred + 2 - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + DO i4 = LBOUND(InData%Ke,4), UBOUND(InData%Ke,4) + DO i3 = LBOUND(InData%Ke,3), UBOUND(InData%Ke,3) + DO i2 = LBOUND(InData%Ke,2), UBOUND(InData%Ke,2) + DO i1 = LBOUND(InData%Ke,1), UBOUND(InData%Ke,1) + DbKiBuf(Db_Xferred) = InData%Ke(i1,i2,i3,i4) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Fg) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_PackInitInput + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) + Int_Xferred = Int_Xferred + 2 - SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + DO i3 = LBOUND(InData%Fg,3), UBOUND(InData%Fg,3) + DO i2 = LBOUND(InData%Fg,2), UBOUND(InData%Fg,2) + DO i1 = LBOUND(InData%Fg,1), UBOUND(InData%Fg,1) + DbKiBuf(Db_Xferred) = InData%Fg(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE SD_PackMeshAuxDataType + + SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InitInputType), INTENT(INOUT) :: OutData + TYPE(MeshAuxDataType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -763,9 +948,10 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMeshAuxDataType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -776,27 +962,93 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - DO I = 1, LEN(OutData%SDInputFile) - OutData%SDInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - DO I = 1, LEN(OutData%RootName) - OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%g = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%WtrDpth = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%TP_RefPoint,1) - i1_u = UBOUND(OutData%TP_RefPoint,1) - DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) - OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%SubRotateZ = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SoilStiffness not allocated + OutData%MemberID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NOutCnt = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeCnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeCnt)) DEALLOCATE(OutData%NodeCnt) + ALLOCATE(OutData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeCnt.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeCnt,1), UBOUND(OutData%NodeCnt,1) + OutData%NodeCnt(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIDs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%NodeIDs)) DEALLOCATE(OutData%NodeIDs) + ALLOCATE(OutData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%NodeIDs,1), UBOUND(OutData%NodeIDs,1) + OutData%NodeIDs(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmIDs not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElmIDs)) DEALLOCATE(OutData%ElmIDs) + ALLOCATE(OutData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ElmIDs,2), UBOUND(OutData%ElmIDs,2) + DO i1 = LBOUND(OutData%ElmIDs,1), UBOUND(OutData%ElmIDs,1) + OutData%ElmIDs(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmNds not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ElmNds)) DEALLOCATE(OutData%ElmNds) + ALLOCATE(OutData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmNds.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%ElmNds,2), UBOUND(OutData%ElmNds,2) + DO i1 = LBOUND(OutData%ElmNds,1), UBOUND(OutData%ElmNds,1) + OutData%ElmNds(i1,i2) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -809,252 +1061,223 @@ SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err i3_l = IntKiBuf( Int_Xferred ) i3_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%SoilStiffness)) DEALLOCATE(OutData%SoilStiffness) - ALLOCATE(OutData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Me)) DEALLOCATE(OutData%Me) + ALLOCATE(OutData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Me.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i3 = LBOUND(OutData%SoilStiffness,3), UBOUND(OutData%SoilStiffness,3) - DO i2 = LBOUND(OutData%SoilStiffness,2), UBOUND(OutData%SoilStiffness,2) - DO i1 = LBOUND(OutData%SoilStiffness,1), UBOUND(OutData%SoilStiffness,1) - OutData%SoilStiffness(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + DO i4 = LBOUND(OutData%Me,4), UBOUND(OutData%Me,4) + DO i3 = LBOUND(OutData%Me,3), UBOUND(OutData%Me,3) + DO i2 = LBOUND(OutData%Me,2), UBOUND(OutData%Me,2) + DO i1 = LBOUND(OutData%Me,1), UBOUND(OutData%Me,1) + OutData%Me(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END DO END DO END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL MeshUnpack( OutData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! SoilMesh - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke not allocated Int_Xferred = Int_Xferred + 1 - END SUBROUTINE SD_UnPackInitInput + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Ke)) DEALLOCATE(OutData%Ke) + ALLOCATE(OutData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ke.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Ke,4), UBOUND(OutData%Ke,4) + DO i3 = LBOUND(OutData%Ke,3), UBOUND(OutData%Ke,3) + DO i2 = LBOUND(OutData%Ke,2), UBOUND(OutData%Ke,2) + DO i1 = LBOUND(OutData%Ke,1), UBOUND(OutData%Ke,1) + OutData%Ke(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Fg)) DEALLOCATE(OutData%Fg) + ALLOCATE(OutData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%Fg,3), UBOUND(OutData%Fg,3) + DO i2 = LBOUND(OutData%Fg,2), UBOUND(OutData%Fg,2) + DO i1 = LBOUND(OutData%Fg,1), UBOUND(OutData%Fg,1) + OutData%Fg(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO + END DO + END DO + END IF + END SUBROUTINE SD_UnPackMeshAuxDataType - SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SD_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(SD_InitOutputType), INTENT(INOUT) :: DstInitOutputData + SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(IN) :: SrcCB_MatArraysData + TYPE(CB_MatArrays), INTENT(INOUT) :: DstCB_MatArraysData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyCB_MatArrays' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN - ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBB)) THEN + ALLOCATE(DstCB_MatArraysData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBB.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr + DstCB_MatArraysData%MBB = SrcCB_MatArraysData%MBB ENDIF -IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN - i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) - i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) - IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN - ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt -ENDIF - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN - i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) - i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) - IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN - ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y -ENDIF -IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN - i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) - i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) - IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN - ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x -ENDIF -IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN - i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) - i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) - IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN - ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u -ENDIF -IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN - i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) - i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) - IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN - ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%MBM)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%MBM,1) + i1_u = UBOUND(SrcCB_MatArraysData%MBM,1) + i2_l = LBOUND(SrcCB_MatArraysData%MBM,2) + i2_u = UBOUND(SrcCB_MatArraysData%MBM,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBM)) THEN + ALLOCATE(DstCB_MatArraysData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBM.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y + DstCB_MatArraysData%MBM = SrcCB_MatArraysData%MBM ENDIF -IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN - i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) - i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) - IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN - ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%KBB)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%KBB,1) + i1_u = UBOUND(SrcCB_MatArraysData%KBB,1) + i2_l = LBOUND(SrcCB_MatArraysData%KBB,2) + i2_u = UBOUND(SrcCB_MatArraysData%KBB,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%KBB)) THEN + ALLOCATE(DstCB_MatArraysData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%KBB.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x + DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB ENDIF -IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN - i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) - i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) - IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN - ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiL,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiL,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiL)) THEN + ALLOCATE(DstCB_MatArraysData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiL.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u + DstCB_MatArraysData%PhiL = SrcCB_MatArraysData%PhiL ENDIF -IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN - i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) - i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) - IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN - ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%PhiR)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%PhiR,1) + i1_u = UBOUND(SrcCB_MatArraysData%PhiR,1) + i2_l = LBOUND(SrcCB_MatArraysData%PhiR,2) + i2_u = UBOUND(SrcCB_MatArraysData%PhiR,2) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiR)) THEN + ALLOCATE(DstCB_MatArraysData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiR.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u + DstCB_MatArraysData%PhiR = SrcCB_MatArraysData%PhiR ENDIF -IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN - i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) - i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) - IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN - ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcCB_MatArraysData%OmegaL)) THEN + i1_l = LBOUND(SrcCB_MatArraysData%OmegaL,1) + i1_u = UBOUND(SrcCB_MatArraysData%OmegaL,1) + IF (.NOT. ALLOCATED(DstCB_MatArraysData%OmegaL)) THEN + ALLOCATE(DstCB_MatArraysData%OmegaL(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%OmegaL.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x + DstCB_MatArraysData%OmegaL = SrcCB_MatArraysData%OmegaL ENDIF - END SUBROUTINE SD_CopyInitOutput + END SUBROUTINE SD_CopyCB_MatArrays - SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) - TYPE(SD_InitOutputType), INTENT(INOUT) :: InitOutputData + SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) + TYPE(CB_MatArrays), INTENT(INOUT) :: CB_MatArraysData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyCB_MatArrays' INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN - DEALLOCATE(InitOutputData%WriteOutputHdr) -ENDIF -IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN - DEALLOCATE(InitOutputData%WriteOutputUnt) -ENDIF - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) -IF (ALLOCATED(InitOutputData%LinNames_y)) THEN - DEALLOCATE(InitOutputData%LinNames_y) -ENDIF -IF (ALLOCATED(InitOutputData%LinNames_x)) THEN - DEALLOCATE(InitOutputData%LinNames_x) -ENDIF -IF (ALLOCATED(InitOutputData%LinNames_u)) THEN - DEALLOCATE(InitOutputData%LinNames_u) +IF (ALLOCATED(CB_MatArraysData%MBB)) THEN + DEALLOCATE(CB_MatArraysData%MBB) ENDIF -IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN - DEALLOCATE(InitOutputData%RotFrame_y) +IF (ALLOCATED(CB_MatArraysData%MBM)) THEN + DEALLOCATE(CB_MatArraysData%MBM) ENDIF -IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN - DEALLOCATE(InitOutputData%RotFrame_x) +IF (ALLOCATED(CB_MatArraysData%KBB)) THEN + DEALLOCATE(CB_MatArraysData%KBB) ENDIF -IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN - DEALLOCATE(InitOutputData%RotFrame_u) +IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN + DEALLOCATE(CB_MatArraysData%PhiL) ENDIF -IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN - DEALLOCATE(InitOutputData%IsLoad_u) +IF (ALLOCATED(CB_MatArraysData%PhiR)) THEN + DEALLOCATE(CB_MatArraysData%PhiR) ENDIF -IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN - DEALLOCATE(InitOutputData%DerivOrder_x) +IF (ALLOCATED(CB_MatArraysData%OmegaL)) THEN + DEALLOCATE(CB_MatArraysData%OmegaL) ENDIF - END SUBROUTINE SD_DestroyInitOutput + END SUBROUTINE SD_DestroyCB_MatArrays - SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SD_InitOutputType), INTENT(IN) :: InData + TYPE(CB_MatArrays), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -1069,7 +1292,7 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackCB_MatArrays' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1085,80 +1308,42 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no - IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr - END IF - Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no - IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt + Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no + IF ( ALLOCATED(InData%MBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%MBB) ! MBB END IF - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no - IF ( ALLOCATED(InData%LinNames_y) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y + Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no + IF ( ALLOCATED(InData%MBM) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%MBM) ! MBM END IF - Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no - IF ( ALLOCATED(InData%LinNames_x) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x + Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no + IF ( ALLOCATED(InData%KBB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%KBB) ! KBB END IF - Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no - IF ( ALLOCATED(InData%LinNames_u) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u + Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no + IF ( ALLOCATED(InData%PhiL) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PhiL) ! PhiL END IF - Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no - IF ( ALLOCATED(InData%RotFrame_y) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no + IF ( ALLOCATED(InData%PhiR) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%PhiR) ! PhiR END IF - Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no - IF ( ALLOCATED(InData%RotFrame_x) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no + IF ( ALLOCATED(InData%OmegaL) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%OmegaL) ! OmegaL END IF - Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no - IF ( ALLOCATED(InData%RotFrame_u) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u - END IF - Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no - IF ( ALLOCATED(InData%IsLoad_u) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u - END IF - Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no - IF ( ALLOCATED(InData%DerivOrder_x) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF END IF IF ( Db_BufSz .GT. 0 ) THEN ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) @@ -1180,201 +1365,128 @@ SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IF ( .NOT. ALLOCATED(InData%MBB) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) - DO I = 1, LEN(InData%WriteOutputHdr) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) - DO I = 1, LEN(InData%WriteOutputUnt) - IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i2 = LBOUND(InData%MBB,2), UBOUND(InData%MBB,2) + DO i1 = LBOUND(InData%MBB,1), UBOUND(InData%MBB,1) + DbKiBuf(Db_Xferred) = InData%MBB(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF ( .NOT. ALLOCATED(InData%LinNames_y) ) THEN + IF ( .NOT. ALLOCATED(InData%MBM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_y,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) - DO I = 1, LEN(InData%LinNames_y) - IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( .NOT. ALLOCATED(InData%LinNames_x) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_x,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) - DO I = 1, LEN(InData%LinNames_x) - IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i2 = LBOUND(InData%MBM,2), UBOUND(InData%MBM,2) + DO i1 = LBOUND(InData%MBM,1), UBOUND(InData%MBM,1) + DbKiBuf(Db_Xferred) = InData%MBM(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%LinNames_u) ) THEN + IF ( .NOT. ALLOCATED(InData%KBB) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_u,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) - DO I = 1, LEN(InData%LinNames_u) - IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_y,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) - IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%KBB,2), UBOUND(InData%KBB,2) + DO i1 = LBOUND(InData%KBB,1), UBOUND(InData%KBB,1) + DbKiBuf(Db_Xferred) = InData%KBB(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) THEN + IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_x,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,1) Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) - IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_u,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) - IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%PhiL,2), UBOUND(InData%PhiL,2) + DO i1 = LBOUND(InData%PhiL,1), UBOUND(InData%PhiL,1) + DbKiBuf(Db_Xferred) = InData%PhiL(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) THEN + IF ( .NOT. ALLOCATED(InData%PhiR) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%IsLoad_u,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) - IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%PhiR,2), UBOUND(InData%PhiR,2) + DO i1 = LBOUND(InData%PhiR,1), UBOUND(InData%PhiR,1) + DbKiBuf(Db_Xferred) = InData%PhiR(i1,i2) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN + IF ( .NOT. ALLOCATED(InData%OmegaL) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%OmegaL,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) - IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%OmegaL,1), UBOUND(InData%OmegaL,1) + DbKiBuf(Db_Xferred) = InData%OmegaL(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF - END SUBROUTINE SD_PackInitOutput + END SUBROUTINE SD_PackCB_MatArrays - SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SD_InitOutputType), INTENT(INOUT) :: OutData + TYPE(CB_MatArrays), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -1384,9 +1496,10 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackCB_MatArrays' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1397,241 +1510,144 @@ SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) - ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) + ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) - DO I = 1, LEN(OutData%WriteOutputHdr) - OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i2 = LBOUND(OutData%MBB,2), UBOUND(OutData%MBB,2) + DO i1 = LBOUND(OutData%MBB,1), UBOUND(OutData%MBB,1) + OutData%MBB(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) - ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) + ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) - DO I = 1, LEN(OutData%WriteOutputUnt) - OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i2 = LBOUND(OutData%MBM,2), UBOUND(OutData%MBM,2) + DO i1 = LBOUND(OutData%MBM,1), UBOUND(OutData%MBM,1) + OutData%MBM(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%LinNames_y)) DEALLOCATE(OutData%LinNames_y) - ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) - DO I = 1, LEN(OutData%LinNames_y) - OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%LinNames_x)) DEALLOCATE(OutData%LinNames_x) - ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) - DO I = 1, LEN(OutData%LinNames_x) - OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%LinNames_u)) DEALLOCATE(OutData%LinNames_u) - ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) + ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) - DO I = 1, LEN(OutData%LinNames_u) - OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I + DO i2 = LBOUND(OutData%KBB,2), UBOUND(OutData%KBB,2) + DO i1 = LBOUND(OutData%KBB,1), UBOUND(OutData%KBB,1) + OutData%KBB(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) - ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) - OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) - ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PhiL)) DEALLOCATE(OutData%PhiL) + ALLOCATE(OutData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) - OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(OutData%PhiL,2), UBOUND(OutData%PhiL,2) + DO i1 = LBOUND(OutData%PhiL,1), UBOUND(OutData%PhiL,1) + OutData%PhiL(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) - ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) - OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) - ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%PhiR)) DEALLOCATE(OutData%PhiR) + ALLOCATE(OutData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiR.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) - OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) - Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(OutData%PhiR,2), UBOUND(OutData%PhiR,2) + DO i1 = LBOUND(OutData%PhiR,1), UBOUND(OutData%PhiR,1) + OutData%PhiR(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 + END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) - ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%OmegaL)) DEALLOCATE(OutData%OmegaL) + ALLOCATE(OutData%OmegaL(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OmegaL.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) - OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(OutData%OmegaL,1), UBOUND(OutData%OmegaL,1) + OutData%OmegaL(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 END DO END IF - END SUBROUTINE SD_UnPackInitOutput + END SUBROUTINE SD_UnPackCB_MatArrays - SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(MeshAuxDataType), INTENT(IN) :: SrcMeshAuxDataTypeData - TYPE(MeshAuxDataType), INTENT(INOUT) :: DstMeshAuxDataTypeData + SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData + TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1639,159 +1655,43 @@ SUBROUTINE SD_CopyMeshAuxDataType( SrcMeshAuxDataTypeData, DstMeshAuxDataTypeDat INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyMeshAuxDataType' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyElemPropType' ! ErrStat = ErrID_None ErrMsg = "" - DstMeshAuxDataTypeData%MemberID = SrcMeshAuxDataTypeData%MemberID - DstMeshAuxDataTypeData%NOutCnt = SrcMeshAuxDataTypeData%NOutCnt -IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeCnt)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeCnt,1) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeCnt)) THEN - ALLOCATE(DstMeshAuxDataTypeData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeCnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%NodeCnt = SrcMeshAuxDataTypeData%NodeCnt -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%NodeIDs)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%NodeIDs,1) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%NodeIDs)) THEN - ALLOCATE(DstMeshAuxDataTypeData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%NodeIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%NodeIDs = SrcMeshAuxDataTypeData%NodeIDs -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmIDs)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmIDs,2) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmIDs)) THEN - ALLOCATE(DstMeshAuxDataTypeData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmIDs.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%ElmIDs = SrcMeshAuxDataTypeData%ElmIDs -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%ElmNds)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%ElmNds,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%ElmNds,2) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%ElmNds)) THEN - ALLOCATE(DstMeshAuxDataTypeData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%ElmNds.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%ElmNds = SrcMeshAuxDataTypeData%ElmNds -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Me)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Me,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Me,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Me,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Me,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Me,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Me,3) - i4_l = LBOUND(SrcMeshAuxDataTypeData%Me,4) - i4_u = UBOUND(SrcMeshAuxDataTypeData%Me,4) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Me)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Me.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Me = SrcMeshAuxDataTypeData%Me -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Ke)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Ke,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Ke,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Ke,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Ke,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Ke,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Ke,3) - i4_l = LBOUND(SrcMeshAuxDataTypeData%Ke,4) - i4_u = UBOUND(SrcMeshAuxDataTypeData%Ke,4) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Ke)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Ke.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Ke = SrcMeshAuxDataTypeData%Ke -ENDIF -IF (ALLOCATED(SrcMeshAuxDataTypeData%Fg)) THEN - i1_l = LBOUND(SrcMeshAuxDataTypeData%Fg,1) - i1_u = UBOUND(SrcMeshAuxDataTypeData%Fg,1) - i2_l = LBOUND(SrcMeshAuxDataTypeData%Fg,2) - i2_u = UBOUND(SrcMeshAuxDataTypeData%Fg,2) - i3_l = LBOUND(SrcMeshAuxDataTypeData%Fg,3) - i3_u = UBOUND(SrcMeshAuxDataTypeData%Fg,3) - IF (.NOT. ALLOCATED(DstMeshAuxDataTypeData%Fg)) THEN - ALLOCATE(DstMeshAuxDataTypeData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMeshAuxDataTypeData%Fg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMeshAuxDataTypeData%Fg = SrcMeshAuxDataTypeData%Fg -ENDIF - END SUBROUTINE SD_CopyMeshAuxDataType + DstElemPropTypeData%eType = SrcElemPropTypeData%eType + DstElemPropTypeData%Length = SrcElemPropTypeData%Length + DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx + DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy + DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz + DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear + DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa + DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE + DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG + DstElemPropTypeData%Area = SrcElemPropTypeData%Area + DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho + DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 + DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos + END SUBROUTINE SD_CopyElemPropType - SUBROUTINE SD_DestroyMeshAuxDataType( MeshAuxDataTypeData, ErrStat, ErrMsg ) - TYPE(MeshAuxDataType), INTENT(INOUT) :: MeshAuxDataTypeData + SUBROUTINE SD_DestroyElemPropType( ElemPropTypeData, ErrStat, ErrMsg ) + TYPE(ElemPropType), INTENT(INOUT) :: ElemPropTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyMeshAuxDataType' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyElemPropType' INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(MeshAuxDataTypeData%NodeCnt)) THEN - DEALLOCATE(MeshAuxDataTypeData%NodeCnt) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%NodeIDs)) THEN - DEALLOCATE(MeshAuxDataTypeData%NodeIDs) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%ElmIDs)) THEN - DEALLOCATE(MeshAuxDataTypeData%ElmIDs) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%ElmNds)) THEN - DEALLOCATE(MeshAuxDataTypeData%ElmNds) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Me)) THEN - DEALLOCATE(MeshAuxDataTypeData%Me) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Ke)) THEN - DEALLOCATE(MeshAuxDataTypeData%Ke) -ENDIF -IF (ALLOCATED(MeshAuxDataTypeData%Fg)) THEN - DEALLOCATE(MeshAuxDataTypeData%Fg) -ENDIF - END SUBROUTINE SD_DestroyMeshAuxDataType + END SUBROUTINE SD_DestroyElemPropType - SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(MeshAuxDataType), INTENT(IN) :: InData + TYPE(ElemPropType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -1806,7 +1706,7 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackMeshAuxDataType' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackElemPropType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1822,43 +1722,19 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! MemberID - Int_BufSz = Int_BufSz + 1 ! NOutCnt - Int_BufSz = Int_BufSz + 1 ! NodeCnt allocated yes/no - IF ( ALLOCATED(InData%NodeCnt) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodeCnt upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodeCnt) ! NodeCnt - END IF - Int_BufSz = Int_BufSz + 1 ! NodeIDs allocated yes/no - IF ( ALLOCATED(InData%NodeIDs) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! NodeIDs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%NodeIDs) ! NodeIDs - END IF - Int_BufSz = Int_BufSz + 1 ! ElmIDs allocated yes/no - IF ( ALLOCATED(InData%ElmIDs) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElmIDs upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElmIDs) ! ElmIDs - END IF - Int_BufSz = Int_BufSz + 1 ! ElmNds allocated yes/no - IF ( ALLOCATED(InData%ElmNds) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! ElmNds upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%ElmNds) ! ElmNds - END IF - Int_BufSz = Int_BufSz + 1 ! Me allocated yes/no - IF ( ALLOCATED(InData%Me) ) THEN - Int_BufSz = Int_BufSz + 2*4 ! Me upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%Me) ! Me - END IF - Int_BufSz = Int_BufSz + 1 ! Ke allocated yes/no - IF ( ALLOCATED(InData%Ke) ) THEN - Int_BufSz = Int_BufSz + 2*4 ! Ke upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%Ke) ! Ke - END IF - Int_BufSz = Int_BufSz + 1 ! Fg allocated yes/no - IF ( ALLOCATED(InData%Fg) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! Fg upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%Fg) ! Fg - END IF + Int_BufSz = Int_BufSz + 1 ! eType + Re_BufSz = Re_BufSz + 1 ! Length + Re_BufSz = Re_BufSz + 1 ! Ixx + Re_BufSz = Re_BufSz + 1 ! Iyy + Re_BufSz = Re_BufSz + 1 ! Jzz + Int_BufSz = Int_BufSz + 1 ! Shear + Re_BufSz = Re_BufSz + 1 ! Kappa + Re_BufSz = Re_BufSz + 1 ! YoungE + Re_BufSz = Re_BufSz + 1 ! ShearG + Re_BufSz = Re_BufSz + 1 ! Area + Re_BufSz = Re_BufSz + 1 ! Rho + Re_BufSz = Re_BufSz + 1 ! T0 + Db_BufSz = Db_BufSz + SIZE(InData%DirCos) ! DirCos IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1886,317 +1762,379 @@ SUBROUTINE SD_PackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%MemberID - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NOutCnt - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%NodeCnt) ) THEN - IntKiBuf( Int_Xferred ) = 0 + IntKiBuf(Int_Xferred) = InData%eType Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 + ReKiBuf(Re_Xferred) = InData%Length + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Ixx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Iyy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Jzz + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Shear, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeCnt,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeCnt,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%NodeCnt,1), UBOUND(InData%NodeCnt,1) - IntKiBuf(Int_Xferred) = InData%NodeCnt(i1) - Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Kappa + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YoungE + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShearG + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Area + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rho + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%T0 + Re_Xferred = Re_Xferred + 1 + DO i2 = LBOUND(InData%DirCos,2), UBOUND(InData%DirCos,2) + DO i1 = LBOUND(InData%DirCos,1), UBOUND(InData%DirCos,1) + DbKiBuf(Db_Xferred) = InData%DirCos(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO - END IF - IF ( .NOT. ALLOCATED(InData%NodeIDs) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%NodeIDs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%NodeIDs,1) - Int_Xferred = Int_Xferred + 2 + END DO + END SUBROUTINE SD_PackElemPropType - DO i1 = LBOUND(InData%NodeIDs,1), UBOUND(InData%NodeIDs,1) - IntKiBuf(Int_Xferred) = InData%NodeIDs(i1) - Int_Xferred = Int_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%ElmIDs) ) THEN - IntKiBuf( Int_Xferred ) = 0 + SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(ElemPropType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackElemPropType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%eType = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 + OutData%Length = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Ixx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Iyy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Jzz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Shear = TRANSFER(IntKiBuf(Int_Xferred), OutData%Shear) Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmIDs,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmIDs,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%ElmIDs,2), UBOUND(InData%ElmIDs,2) - DO i1 = LBOUND(InData%ElmIDs,1), UBOUND(InData%ElmIDs,1) - IntKiBuf(Int_Xferred) = InData%ElmIDs(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%ElmNds) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%ElmNds,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ElmNds,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%ElmNds,2), UBOUND(InData%ElmNds,2) - DO i1 = LBOUND(InData%ElmNds,1), UBOUND(InData%ElmNds,1) - IntKiBuf(Int_Xferred) = InData%ElmNds(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%Me) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Me,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Me,4) - Int_Xferred = Int_Xferred + 2 - - DO i4 = LBOUND(InData%Me,4), UBOUND(InData%Me,4) - DO i3 = LBOUND(InData%Me,3), UBOUND(InData%Me,3) - DO i2 = LBOUND(InData%Me,2), UBOUND(InData%Me,2) - DO i1 = LBOUND(InData%Me,1), UBOUND(InData%Me,1) - DbKiBuf(Db_Xferred) = InData%Me(i1,i2,i3,i4) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%Ke) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Ke,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Ke,4) - Int_Xferred = Int_Xferred + 2 - - DO i4 = LBOUND(InData%Ke,4), UBOUND(InData%Ke,4) - DO i3 = LBOUND(InData%Ke,3), UBOUND(InData%Ke,3) - DO i2 = LBOUND(InData%Ke,2), UBOUND(InData%Ke,2) - DO i1 = LBOUND(InData%Ke,1), UBOUND(InData%Ke,1) - DbKiBuf(Db_Xferred) = InData%Ke(i1,i2,i3,i4) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END DO + OutData%Kappa = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YoungE = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShearG = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Area = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rho = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%T0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%DirCos,1) + i1_u = UBOUND(OutData%DirCos,1) + i2_l = LBOUND(OutData%DirCos,2) + i2_u = UBOUND(OutData%DirCos,2) + DO i2 = LBOUND(OutData%DirCos,2), UBOUND(OutData%DirCos,2) + DO i1 = LBOUND(OutData%DirCos,1), UBOUND(OutData%DirCos,1) + OutData%DirCos(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 END DO - END IF - IF ( .NOT. ALLOCATED(InData%Fg) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Fg,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Fg,3) - Int_Xferred = Int_Xferred + 2 + END DO + END SUBROUTINE SD_UnPackElemPropType - DO i3 = LBOUND(InData%Fg,3), UBOUND(InData%Fg,3) - DO i2 = LBOUND(InData%Fg,2), UBOUND(InData%Fg,2) - DO i1 = LBOUND(InData%Fg,1), UBOUND(InData%Fg,1) - DbKiBuf(Db_Xferred) = InData%Fg(i1,i2,i3) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END DO + SUBROUTINE SD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(INOUT) :: SrcInitInputData + TYPE(SD_InitInputType), INTENT(INOUT) :: DstInitInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%SDInputFile = SrcInitInputData%SDInputFile + DstInitInputData%RootName = SrcInitInputData%RootName + DstInitInputData%g = SrcInitInputData%g + DstInitInputData%WtrDpth = SrcInitInputData%WtrDpth + DstInitInputData%TP_RefPoint = SrcInitInputData%TP_RefPoint + DstInitInputData%SubRotateZ = SrcInitInputData%SubRotateZ +IF (ALLOCATED(SrcInitInputData%SoilStiffness)) THEN + i1_l = LBOUND(SrcInitInputData%SoilStiffness,1) + i1_u = UBOUND(SrcInitInputData%SoilStiffness,1) + i2_l = LBOUND(SrcInitInputData%SoilStiffness,2) + i2_u = UBOUND(SrcInitInputData%SoilStiffness,2) + i3_l = LBOUND(SrcInitInputData%SoilStiffness,3) + i3_u = UBOUND(SrcInitInputData%SoilStiffness,3) + IF (.NOT. ALLOCATED(DstInitInputData%SoilStiffness)) THEN + ALLOCATE(DstInitInputData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF END IF - END SUBROUTINE SD_PackMeshAuxDataType + DstInitInputData%SoilStiffness = SrcInitInputData%SoilStiffness +ENDIF + CALL MeshCopy( SrcInitInputData%SoilMesh, DstInitInputData%SoilMesh, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%Linearize = SrcInitInputData%Linearize + END SUBROUTINE SD_CopyInitInput - SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(MeshAuxDataType), INTENT(INOUT) :: OutData + SUBROUTINE SD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) + TYPE(SD_InitInputType), INTENT(INOUT) :: InitInputData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitInput' + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(InitInputData%SoilStiffness)) THEN + DEALLOCATE(InitInputData%SoilStiffness) +ENDIF + CALL MeshDestroy( InitInputData%SoilMesh, ErrStat, ErrMsg ) + END SUBROUTINE SD_DestroyInitInput + + SUBROUTINE SD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SD_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly ! Local variables - INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_BufSz INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackMeshAuxDataType' - ! buffers to store meshes, if any + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitInput' + ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF ! ErrStat = ErrID_None ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%MemberID = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NOutCnt = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeCnt not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodeCnt)) DEALLOCATE(OutData%NodeCnt) - ALLOCATE(OutData%NodeCnt(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeCnt.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%NodeCnt,1), UBOUND(OutData%NodeCnt,1) - OutData%NodeCnt(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%SDInputFile) ! SDInputFile + Int_BufSz = Int_BufSz + 1*LEN(InData%RootName) ! RootName + Re_BufSz = Re_BufSz + 1 ! g + Re_BufSz = Re_BufSz + 1 ! WtrDpth + Re_BufSz = Re_BufSz + SIZE(InData%TP_RefPoint) ! TP_RefPoint + Re_BufSz = Re_BufSz + 1 ! SubRotateZ + Int_BufSz = Int_BufSz + 1 ! SoilStiffness allocated yes/no + IF ( ALLOCATED(InData%SoilStiffness) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! SoilStiffness upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%SoilStiffness) ! SoilStiffness END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! NodeIDs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%NodeIDs)) DEALLOCATE(OutData%NodeIDs) - ALLOCATE(OutData%NodeIDs(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%NodeIDs.', ErrStat, ErrMsg,RoutineName) + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! SoilMesh: size of buffers for each call to pack subtype + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! SoilMesh + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! SoilMesh + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! SoilMesh + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! Linearize + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) RETURN - END IF - DO i1 = LBOUND(OutData%NodeIDs,1), UBOUND(OutData%NodeIDs,1) - OutData%NodeIDs(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO + END IF END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmIDs not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElmIDs)) DEALLOCATE(OutData%ElmIDs) - ALLOCATE(OutData%ElmIDs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmIDs.', ErrStat, ErrMsg,RoutineName) + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) RETURN - END IF - DO i2 = LBOUND(OutData%ElmIDs,2), UBOUND(OutData%ElmIDs,2) - DO i1 = LBOUND(OutData%ElmIDs,1), UBOUND(OutData%ElmIDs,1) - OutData%ElmIDs(i1,i2) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END DO + END IF END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElmNds not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%ElmNds)) DEALLOCATE(OutData%ElmNds) - ALLOCATE(OutData%ElmNds(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ElmNds.', ErrStat, ErrMsg,RoutineName) + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) RETURN - END IF - DO i2 = LBOUND(OutData%ElmNds,2), UBOUND(OutData%ElmNds,2) - DO i1 = LBOUND(OutData%ElmNds,1), UBOUND(OutData%ElmNds,1) - OutData%ElmNds(i1,i2) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END DO + END IF END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Me not allocated + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%SDInputFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%SDInputFile(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(InData%RootName) + IntKiBuf(Int_Xferred) = ICHAR(InData%RootName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%g + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%WtrDpth + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%TP_RefPoint,1), UBOUND(InData%TP_RefPoint,1) + ReKiBuf(Re_Xferred) = InData%TP_RefPoint(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%SubRotateZ + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%SoilStiffness) ) THEN + IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE + IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,1) Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,2) Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%SoilStiffness,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%SoilStiffness,3) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Me)) DEALLOCATE(OutData%Me) - ALLOCATE(OutData%Me(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Me.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i4 = LBOUND(OutData%Me,4), UBOUND(OutData%Me,4) - DO i3 = LBOUND(OutData%Me,3), UBOUND(OutData%Me,3) - DO i2 = LBOUND(OutData%Me,2), UBOUND(OutData%Me,2) - DO i1 = LBOUND(OutData%Me,1), UBOUND(OutData%Me,1) - OutData%Me(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + + DO i3 = LBOUND(InData%SoilStiffness,3), UBOUND(InData%SoilStiffness,3) + DO i2 = LBOUND(InData%SoilStiffness,2), UBOUND(InData%SoilStiffness,2) + DO i1 = LBOUND(InData%SoilStiffness,1), UBOUND(InData%SoilStiffness,1) + ReKiBuf(Re_Xferred) = InData%SoilStiffness(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 END DO END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Ke not allocated + CALL MeshPack( InData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE SD_PackInitInput + + SUBROUTINE SD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SD_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitInput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%SDInputFile) + OutData%SDInputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + DO I = 1, LEN(OutData%RootName) + OutData%RootName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%g = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WtrDpth = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%TP_RefPoint,1) + i1_u = UBOUND(OutData%TP_RefPoint,1) + DO i1 = LBOUND(OutData%TP_RefPoint,1), UBOUND(OutData%TP_RefPoint,1) + OutData%TP_RefPoint(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%SubRotateZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! SoilStiffness not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -2209,190 +2147,252 @@ SUBROUTINE SD_UnPackMeshAuxDataType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta i3_l = IntKiBuf( Int_Xferred ) i3_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Ke)) DEALLOCATE(OutData%Ke) - ALLOCATE(OutData%Ke(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%SoilStiffness)) DEALLOCATE(OutData%SoilStiffness) + ALLOCATE(OutData%SoilStiffness(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Ke.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%SoilStiffness.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i4 = LBOUND(OutData%Ke,4), UBOUND(OutData%Ke,4) - DO i3 = LBOUND(OutData%Ke,3), UBOUND(OutData%Ke,3) - DO i2 = LBOUND(OutData%Ke,2), UBOUND(OutData%Ke,2) - DO i1 = LBOUND(OutData%Ke,1), UBOUND(OutData%Ke,1) - OutData%Ke(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i3 = LBOUND(OutData%SoilStiffness,3), UBOUND(OutData%SoilStiffness,3) + DO i2 = LBOUND(OutData%SoilStiffness,2), UBOUND(OutData%SoilStiffness,2) + DO i1 = LBOUND(OutData%SoilStiffness,1), UBOUND(OutData%SoilStiffness,1) + OutData%SoilStiffness(i1,i2,i3) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 END DO END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Fg not allocated - Int_Xferred = Int_Xferred + 1 - ELSE + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL MeshUnpack( OutData%SoilMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! SoilMesh + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize) Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Fg)) DEALLOCATE(OutData%Fg) - ALLOCATE(OutData%Fg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Fg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i3 = LBOUND(OutData%Fg,3), UBOUND(OutData%Fg,3) - DO i2 = LBOUND(OutData%Fg,2), UBOUND(OutData%Fg,2) - DO i1 = LBOUND(OutData%Fg,1), UBOUND(OutData%Fg,1) - OutData%Fg(i1,i2,i3) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END DO - END IF - END SUBROUTINE SD_UnPackMeshAuxDataType + END SUBROUTINE SD_UnPackInitInput - SUBROUTINE SD_CopyCB_MatArrays( SrcCB_MatArraysData, DstCB_MatArraysData, CtrlCode, ErrStat, ErrMsg ) - TYPE(CB_MatArrays), INTENT(IN) :: SrcCB_MatArraysData - TYPE(CB_MatArrays), INTENT(INOUT) :: DstCB_MatArraysData + SUBROUTINE SD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(SD_InitOutputType), INTENT(INOUT) :: DstInitOutputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyCB_MatArrays' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyInitOutput' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcCB_MatArraysData%MBB)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%MBB,1) - i1_u = UBOUND(SrcCB_MatArraysData%MBB,1) - i2_l = LBOUND(SrcCB_MatArraysData%MBB,2) - i2_u = UBOUND(SrcCB_MatArraysData%MBB,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBB)) THEN - ALLOCATE(DstCB_MatArraysData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputHdr)) THEN + ALLOCATE(DstInitOutputData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBB.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%MBB = SrcCB_MatArraysData%MBB + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%MBM)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%MBM,1) - i1_u = UBOUND(SrcCB_MatArraysData%MBM,1) - i2_l = LBOUND(SrcCB_MatArraysData%MBM,2) - i2_u = UBOUND(SrcCB_MatArraysData%MBM,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%MBM)) THEN - ALLOCATE(DstCB_MatArraysData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitOutputData%WriteOutputUnt)) THEN + i1_l = LBOUND(SrcInitOutputData%WriteOutputUnt,1) + i1_u = UBOUND(SrcInitOutputData%WriteOutputUnt,1) + IF (.NOT. ALLOCATED(DstInitOutputData%WriteOutputUnt)) THEN + ALLOCATE(DstInitOutputData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%MBM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%MBM = SrcCB_MatArraysData%MBM + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%KBB)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%KBB,1) - i1_u = UBOUND(SrcCB_MatArraysData%KBB,1) - i2_l = LBOUND(SrcCB_MatArraysData%KBB,2) - i2_u = UBOUND(SrcCB_MatArraysData%KBB,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%KBB)) THEN - ALLOCATE(DstCB_MatArraysData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_y,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_y)) THEN + ALLOCATE(DstInitOutputData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%KBB.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%KBB = SrcCB_MatArraysData%KBB + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%PhiL)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%PhiL,1) - i1_u = UBOUND(SrcCB_MatArraysData%PhiL,1) - i2_l = LBOUND(SrcCB_MatArraysData%PhiL,2) - i2_u = UBOUND(SrcCB_MatArraysData%PhiL,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiL)) THEN - ALLOCATE(DstCB_MatArraysData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitOutputData%LinNames_x)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_x,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_x)) THEN + ALLOCATE(DstInitOutputData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%LinNames_u)) THEN + i1_l = LBOUND(SrcInitOutputData%LinNames_u,1) + i1_u = UBOUND(SrcInitOutputData%LinNames_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%LinNames_u)) THEN + ALLOCATE(DstInitOutputData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_y)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_y,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_y,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_y)) THEN + ALLOCATE(DstInitOutputData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_x)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_x,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_x)) THEN + ALLOCATE(DstInitOutputData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x +ENDIF +IF (ALLOCATED(SrcInitOutputData%RotFrame_u)) THEN + i1_l = LBOUND(SrcInitOutputData%RotFrame_u,1) + i1_u = UBOUND(SrcInitOutputData%RotFrame_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%RotFrame_u)) THEN + ALLOCATE(DstInitOutputData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%PhiL = SrcCB_MatArraysData%PhiL + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%PhiR)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%PhiR,1) - i1_u = UBOUND(SrcCB_MatArraysData%PhiR,1) - i2_l = LBOUND(SrcCB_MatArraysData%PhiR,2) - i2_u = UBOUND(SrcCB_MatArraysData%PhiR,2) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%PhiR)) THEN - ALLOCATE(DstCB_MatArraysData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitOutputData%IsLoad_u)) THEN + i1_l = LBOUND(SrcInitOutputData%IsLoad_u,1) + i1_u = UBOUND(SrcInitOutputData%IsLoad_u,1) + IF (.NOT. ALLOCATED(DstInitOutputData%IsLoad_u)) THEN + ALLOCATE(DstInitOutputData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%PhiR.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%PhiR = SrcCB_MatArraysData%PhiR + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u ENDIF -IF (ALLOCATED(SrcCB_MatArraysData%OmegaL)) THEN - i1_l = LBOUND(SrcCB_MatArraysData%OmegaL,1) - i1_u = UBOUND(SrcCB_MatArraysData%OmegaL,1) - IF (.NOT. ALLOCATED(DstCB_MatArraysData%OmegaL)) THEN - ALLOCATE(DstCB_MatArraysData%OmegaL(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcInitOutputData%DerivOrder_x)) THEN + i1_l = LBOUND(SrcInitOutputData%DerivOrder_x,1) + i1_u = UBOUND(SrcInitOutputData%DerivOrder_x,1) + IF (.NOT. ALLOCATED(DstInitOutputData%DerivOrder_x)) THEN + ALLOCATE(DstInitOutputData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstCB_MatArraysData%OmegaL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstCB_MatArraysData%OmegaL = SrcCB_MatArraysData%OmegaL + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x ENDIF - END SUBROUTINE SD_CopyCB_MatArrays + END SUBROUTINE SD_CopyInitOutput - SUBROUTINE SD_DestroyCB_MatArrays( CB_MatArraysData, ErrStat, ErrMsg ) - TYPE(CB_MatArrays), INTENT(INOUT) :: CB_MatArraysData + SUBROUTINE SD_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg ) + TYPE(SD_InitOutputType), INTENT(INOUT) :: InitOutputData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyCB_MatArrays' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyInitOutput' INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(CB_MatArraysData%MBB)) THEN - DEALLOCATE(CB_MatArraysData%MBB) +IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN + DEALLOCATE(InitOutputData%WriteOutputHdr) ENDIF -IF (ALLOCATED(CB_MatArraysData%MBM)) THEN - DEALLOCATE(CB_MatArraysData%MBM) +IF (ALLOCATED(InitOutputData%WriteOutputUnt)) THEN + DEALLOCATE(InitOutputData%WriteOutputUnt) ENDIF -IF (ALLOCATED(CB_MatArraysData%KBB)) THEN - DEALLOCATE(CB_MatArraysData%KBB) + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat, ErrMsg ) +IF (ALLOCATED(InitOutputData%LinNames_y)) THEN + DEALLOCATE(InitOutputData%LinNames_y) ENDIF -IF (ALLOCATED(CB_MatArraysData%PhiL)) THEN - DEALLOCATE(CB_MatArraysData%PhiL) +IF (ALLOCATED(InitOutputData%LinNames_x)) THEN + DEALLOCATE(InitOutputData%LinNames_x) ENDIF -IF (ALLOCATED(CB_MatArraysData%PhiR)) THEN - DEALLOCATE(CB_MatArraysData%PhiR) +IF (ALLOCATED(InitOutputData%LinNames_u)) THEN + DEALLOCATE(InitOutputData%LinNames_u) ENDIF -IF (ALLOCATED(CB_MatArraysData%OmegaL)) THEN - DEALLOCATE(CB_MatArraysData%OmegaL) +IF (ALLOCATED(InitOutputData%RotFrame_y)) THEN + DEALLOCATE(InitOutputData%RotFrame_y) ENDIF - END SUBROUTINE SD_DestroyCB_MatArrays +IF (ALLOCATED(InitOutputData%RotFrame_x)) THEN + DEALLOCATE(InitOutputData%RotFrame_x) +ENDIF +IF (ALLOCATED(InitOutputData%RotFrame_u)) THEN + DEALLOCATE(InitOutputData%RotFrame_u) +ENDIF +IF (ALLOCATED(InitOutputData%IsLoad_u)) THEN + DEALLOCATE(InitOutputData%IsLoad_u) +ENDIF +IF (ALLOCATED(InitOutputData%DerivOrder_x)) THEN + DEALLOCATE(InitOutputData%DerivOrder_x) +ENDIF + END SUBROUTINE SD_DestroyInitOutput - SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE SD_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(CB_MatArrays), INTENT(IN) :: InData + TYPE(SD_InitOutputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2407,7 +2407,7 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackCB_MatArrays' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackInitOutput' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2423,35 +2423,73 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no - IF ( ALLOCATED(InData%MBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%MBB) ! MBB + Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no + IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputHdr)*LEN(InData%WriteOutputHdr) ! WriteOutputHdr END IF - Int_BufSz = Int_BufSz + 1 ! MBM allocated yes/no - IF ( ALLOCATED(InData%MBM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%MBM) ! MBM + Int_BufSz = Int_BufSz + 1 ! WriteOutputUnt allocated yes/no + IF ( ALLOCATED(InData%WriteOutputUnt) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! WriteOutputUnt upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%WriteOutputUnt)*LEN(InData%WriteOutputUnt) ! WriteOutputUnt END IF - Int_BufSz = Int_BufSz + 1 ! KBB allocated yes/no - IF ( ALLOCATED(InData%KBB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! KBB upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%KBB) ! KBB + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Ver + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Ver + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Ver + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 1 ! LinNames_y allocated yes/no + IF ( ALLOCATED(InData%LinNames_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_y)*LEN(InData%LinNames_y) ! LinNames_y END IF - Int_BufSz = Int_BufSz + 1 ! PhiL allocated yes/no - IF ( ALLOCATED(InData%PhiL) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiL upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%PhiL) ! PhiL + Int_BufSz = Int_BufSz + 1 ! LinNames_x allocated yes/no + IF ( ALLOCATED(InData%LinNames_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_x)*LEN(InData%LinNames_x) ! LinNames_x END IF - Int_BufSz = Int_BufSz + 1 ! PhiR allocated yes/no - IF ( ALLOCATED(InData%PhiR) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PhiR upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%PhiR) ! PhiR + Int_BufSz = Int_BufSz + 1 ! LinNames_u allocated yes/no + IF ( ALLOCATED(InData%LinNames_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinNames_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%LinNames_u)*LEN(InData%LinNames_u) ! LinNames_u END IF - Int_BufSz = Int_BufSz + 1 ! OmegaL allocated yes/no - IF ( ALLOCATED(InData%OmegaL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! OmegaL upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%OmegaL) ! OmegaL + Int_BufSz = Int_BufSz + 1 ! RotFrame_y allocated yes/no + IF ( ALLOCATED(InData%RotFrame_y) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_y upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_y) ! RotFrame_y + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_x allocated yes/no + IF ( ALLOCATED(InData%RotFrame_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_x) ! RotFrame_x + END IF + Int_BufSz = Int_BufSz + 1 ! RotFrame_u allocated yes/no + IF ( ALLOCATED(InData%RotFrame_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! RotFrame_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%RotFrame_u) ! RotFrame_u + END IF + Int_BufSz = Int_BufSz + 1 ! IsLoad_u allocated yes/no + IF ( ALLOCATED(InData%IsLoad_u) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! IsLoad_u upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%IsLoad_u) ! IsLoad_u + END IF + Int_BufSz = Int_BufSz + 1 ! DerivOrder_x allocated yes/no + IF ( ALLOCATED(InData%DerivOrder_x) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! DerivOrder_x upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%DerivOrder_x) ! DerivOrder_x END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) @@ -2480,128 +2518,201 @@ SUBROUTINE SD_PackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Db_Xferred = 1 Int_Xferred = 1 - IF ( .NOT. ALLOCATED(InData%MBB) ) THEN + IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputHdr,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputHdr,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputHdr,1), UBOUND(InData%WriteOutputHdr,1) + DO I = 1, LEN(InData%WriteOutputHdr) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputHdr(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%WriteOutputUnt) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WriteOutputUnt,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WriteOutputUnt,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%WriteOutputUnt,1), UBOUND(InData%WriteOutputUnt,1) + DO I = 1, LEN(InData%WriteOutputUnt) + IntKiBuf(Int_Xferred) = ICHAR(InData%WriteOutputUnt(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF ( .NOT. ALLOCATED(InData%LinNames_y) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_y,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinNames_y,1), UBOUND(InData%LinNames_y,1) + DO I = 1, LEN(InData%LinNames_y) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_y(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinNames_x) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBB,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_x,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%MBB,2), UBOUND(InData%MBB,2) - DO i1 = LBOUND(InData%MBB,1), UBOUND(InData%MBB,1) - DbKiBuf(Db_Xferred) = InData%MBB(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(InData%LinNames_x,1), UBOUND(InData%LinNames_x,1) + DO I = 1, LEN(InData%LinNames_x) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_x(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I END DO END IF - IF ( .NOT. ALLOCATED(InData%MBM) ) THEN + IF ( .NOT. ALLOCATED(InData%LinNames_u) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%MBM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBM,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinNames_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinNames_u,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%MBM,2), UBOUND(InData%MBM,2) - DO i1 = LBOUND(InData%MBM,1), UBOUND(InData%MBM,1) - DbKiBuf(Db_Xferred) = InData%MBM(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(InData%LinNames_u,1), UBOUND(InData%LinNames_u,1) + DO I = 1, LEN(InData%LinNames_u) + IntKiBuf(Int_Xferred) = ICHAR(InData%LinNames_u(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I END DO END IF - IF ( .NOT. ALLOCATED(InData%KBB) ) THEN + IF ( .NOT. ALLOCATED(InData%RotFrame_y) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%KBB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%KBB,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_y,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_y,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%KBB,2), UBOUND(InData%KBB,2) - DO i1 = LBOUND(InData%KBB,1), UBOUND(InData%KBB,1) - DbKiBuf(Db_Xferred) = InData%KBB(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(InData%RotFrame_y,1), UBOUND(InData%RotFrame_y,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_y(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%PhiL) ) THEN + IF ( .NOT. ALLOCATED(InData%RotFrame_x) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiL,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiL,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_x,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%PhiL,2), UBOUND(InData%PhiL,2) - DO i1 = LBOUND(InData%PhiL,1), UBOUND(InData%PhiL,1) - DbKiBuf(Db_Xferred) = InData%PhiL(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(InData%RotFrame_x,1), UBOUND(InData%RotFrame_x,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_x(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%PhiR) ) THEN + IF ( .NOT. ALLOCATED(InData%RotFrame_u) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%RotFrame_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%RotFrame_u,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PhiR,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PhiR,2) + + DO i1 = LBOUND(InData%RotFrame_u,1), UBOUND(InData%RotFrame_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotFrame_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%IsLoad_u) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%IsLoad_u,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%IsLoad_u,1) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%PhiR,2), UBOUND(InData%PhiR,2) - DO i1 = LBOUND(InData%PhiR,1), UBOUND(InData%PhiR,1) - DbKiBuf(Db_Xferred) = InData%PhiR(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(InData%IsLoad_u,1), UBOUND(InData%IsLoad_u,1) + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsLoad_u(i1), IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%OmegaL) ) THEN + IF ( .NOT. ALLOCATED(InData%DerivOrder_x) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OmegaL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OmegaL,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%DerivOrder_x,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DerivOrder_x,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%OmegaL,1), UBOUND(InData%OmegaL,1) - DbKiBuf(Db_Xferred) = InData%OmegaL(i1) - Db_Xferred = Db_Xferred + 1 + DO i1 = LBOUND(InData%DerivOrder_x,1), UBOUND(InData%DerivOrder_x,1) + IntKiBuf(Int_Xferred) = InData%DerivOrder_x(i1) + Int_Xferred = Int_Xferred + 1 END DO END IF - END SUBROUTINE SD_PackCB_MatArrays + END SUBROUTINE SD_PackInitOutput - SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE SD_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(CB_MatArrays), INTENT(INOUT) :: OutData + TYPE(SD_InitOutputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2611,10 +2722,9 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackCB_MatArrays' + CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackInitOutput' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2625,353 +2735,237 @@ SUBROUTINE SD_UnPackCB_MatArrays( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IF (ALLOCATED(OutData%WriteOutputHdr)) DEALLOCATE(OutData%WriteOutputHdr) + ALLOCATE(OutData%WriteOutputHdr(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputHdr.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%WriteOutputHdr,1), UBOUND(OutData%WriteOutputHdr,1) + DO I = 1, LEN(OutData%WriteOutputHdr) + OutData%WriteOutputHdr(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputUnt not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBB)) DEALLOCATE(OutData%MBB) - ALLOCATE(OutData%MBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%WriteOutputUnt)) DEALLOCATE(OutData%WriteOutputUnt) + ALLOCATE(OutData%WriteOutputUnt(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBB.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WriteOutputUnt.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%MBB,2), UBOUND(OutData%MBB,2) - DO i1 = LBOUND(OutData%MBB,1), UBOUND(OutData%MBB,1) - OutData%MBB(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(OutData%WriteOutputUnt,1), UBOUND(OutData%WriteOutputUnt,1) + DO I = 1, LEN(OutData%WriteOutputUnt) + OutData%WriteOutputUnt(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBM not allocated + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_y not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) + IF (ALLOCATED(OutData%LinNames_y)) DEALLOCATE(OutData%LinNames_y) + ALLOCATE(OutData%LinNames_y(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_y.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_y,1), UBOUND(OutData%LinNames_y,1) + DO I = 1, LEN(OutData%LinNames_y) + OutData%LinNames_y(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_x not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%MBM)) DEALLOCATE(OutData%MBM) - ALLOCATE(OutData%MBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%LinNames_x)) DEALLOCATE(OutData%LinNames_x) + ALLOCATE(OutData%LinNames_x(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBM.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%MBM,2), UBOUND(OutData%MBM,2) - DO i1 = LBOUND(OutData%MBM,1), UBOUND(OutData%MBM,1) - OutData%MBM(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(OutData%LinNames_x,1), UBOUND(OutData%LinNames_x,1) + DO I = 1, LEN(OutData%LinNames_x) + OutData%LinNames_x(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinNames_u not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinNames_u)) DEALLOCATE(OutData%LinNames_u) + ALLOCATE(OutData%LinNames_u(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinNames_u.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinNames_u,1), UBOUND(OutData%LinNames_u,1) + DO I = 1, LEN(OutData%LinNames_u) + OutData%LinNames_u(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KBB not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_y not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%KBB)) DEALLOCATE(OutData%KBB) - ALLOCATE(OutData%KBB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%RotFrame_y)) DEALLOCATE(OutData%RotFrame_y) + ALLOCATE(OutData%RotFrame_y(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%KBB.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_y.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%KBB,2), UBOUND(OutData%KBB,2) - DO i1 = LBOUND(OutData%KBB,1), UBOUND(OutData%KBB,1) - OutData%KBB(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(OutData%RotFrame_y,1), UBOUND(OutData%RotFrame_y,1) + OutData%RotFrame_y(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_y(i1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_x not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiL)) DEALLOCATE(OutData%PhiL) - ALLOCATE(OutData%PhiL(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%RotFrame_x)) DEALLOCATE(OutData%RotFrame_x) + ALLOCATE(OutData%RotFrame_x(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_x.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%PhiL,2), UBOUND(OutData%PhiL,2) - DO i1 = LBOUND(OutData%PhiL,1), UBOUND(OutData%PhiL,1) - OutData%PhiL(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(OutData%RotFrame_x,1), UBOUND(OutData%RotFrame_x,1) + OutData%RotFrame_x(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_x(i1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiR not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! RotFrame_u not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PhiR)) DEALLOCATE(OutData%PhiR) - ALLOCATE(OutData%PhiR(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%RotFrame_u)) DEALLOCATE(OutData%RotFrame_u) + ALLOCATE(OutData%RotFrame_u(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PhiR.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%RotFrame_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%PhiR,2), UBOUND(OutData%PhiR,2) - DO i1 = LBOUND(OutData%PhiR,1), UBOUND(OutData%PhiR,1) - OutData%PhiR(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO + DO i1 = LBOUND(OutData%RotFrame_u,1), UBOUND(OutData%RotFrame_u,1) + OutData%RotFrame_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotFrame_u(i1)) + Int_Xferred = Int_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OmegaL not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! IsLoad_u not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%OmegaL)) DEALLOCATE(OutData%OmegaL) - ALLOCATE(OutData%OmegaL(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%IsLoad_u)) DEALLOCATE(OutData%IsLoad_u) + ALLOCATE(OutData%IsLoad_u(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%OmegaL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%IsLoad_u.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%OmegaL,1), UBOUND(OutData%OmegaL,1) - OutData%OmegaL(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO - END IF - END SUBROUTINE SD_UnPackCB_MatArrays - - SUBROUTINE SD_CopyElemPropType( SrcElemPropTypeData, DstElemPropTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ElemPropType), INTENT(IN) :: SrcElemPropTypeData - TYPE(ElemPropType), INTENT(INOUT) :: DstElemPropTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_CopyElemPropType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstElemPropTypeData%eType = SrcElemPropTypeData%eType - DstElemPropTypeData%Length = SrcElemPropTypeData%Length - DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx - DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy - DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz - DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear - DstElemPropTypeData%Kappa = SrcElemPropTypeData%Kappa - DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE - DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG - DstElemPropTypeData%Area = SrcElemPropTypeData%Area - DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho - DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 - DstElemPropTypeData%DirCos = SrcElemPropTypeData%DirCos - END SUBROUTINE SD_CopyElemPropType - - SUBROUTINE SD_DestroyElemPropType( ElemPropTypeData, ErrStat, ErrMsg ) - TYPE(ElemPropType), INTENT(INOUT) :: ElemPropTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - CHARACTER(*), PARAMETER :: RoutineName = 'SD_DestroyElemPropType' - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 -! - ErrStat = ErrID_None - ErrMsg = "" - END SUBROUTINE SD_DestroyElemPropType - - SUBROUTINE SD_PackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ElemPropType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_PackElemPropType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! eType - Re_BufSz = Re_BufSz + 1 ! Length - Re_BufSz = Re_BufSz + 1 ! Ixx - Re_BufSz = Re_BufSz + 1 ! Iyy - Re_BufSz = Re_BufSz + 1 ! Jzz - Int_BufSz = Int_BufSz + 1 ! Shear - Re_BufSz = Re_BufSz + 1 ! Kappa - Re_BufSz = Re_BufSz + 1 ! YoungE - Re_BufSz = Re_BufSz + 1 ! ShearG - Re_BufSz = Re_BufSz + 1 ! Area - Re_BufSz = Re_BufSz + 1 ! Rho - Re_BufSz = Re_BufSz + 1 ! T0 - Db_BufSz = Db_BufSz + SIZE(InData%DirCos) ! DirCos - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%eType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Length - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Ixx - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Iyy - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Jzz - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%Shear, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Kappa - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%YoungE - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%ShearG - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Area - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Rho - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%T0 - Re_Xferred = Re_Xferred + 1 - DO i2 = LBOUND(InData%DirCos,2), UBOUND(InData%DirCos,2) - DO i1 = LBOUND(InData%DirCos,1), UBOUND(InData%DirCos,1) - DbKiBuf(Db_Xferred) = InData%DirCos(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END SUBROUTINE SD_PackElemPropType - - SUBROUTINE SD_UnPackElemPropType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ElemPropType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'SD_UnPackElemPropType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%eType = IntKiBuf(Int_Xferred) + DO i1 = LBOUND(OutData%IsLoad_u,1), UBOUND(OutData%IsLoad_u,1) + OutData%IsLoad_u(i1) = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsLoad_u(i1)) + Int_Xferred = Int_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DerivOrder_x not allocated Int_Xferred = Int_Xferred + 1 - OutData%Length = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Ixx = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Iyy = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Jzz = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Shear = TRANSFER(IntKiBuf(Int_Xferred), OutData%Shear) + ELSE Int_Xferred = Int_Xferred + 1 - OutData%Kappa = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%YoungE = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%ShearG = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Area = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Rho = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%T0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%DirCos,1) - i1_u = UBOUND(OutData%DirCos,1) - i2_l = LBOUND(OutData%DirCos,2) - i2_u = UBOUND(OutData%DirCos,2) - DO i2 = LBOUND(OutData%DirCos,2), UBOUND(OutData%DirCos,2) - DO i1 = LBOUND(OutData%DirCos,1), UBOUND(OutData%DirCos,1) - OutData%DirCos(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%DerivOrder_x)) DEALLOCATE(OutData%DerivOrder_x) + ALLOCATE(OutData%DerivOrder_x(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DerivOrder_x.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%DerivOrder_x,1), UBOUND(OutData%DerivOrder_x,1) + OutData%DerivOrder_x(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 END DO - END DO - END SUBROUTINE SD_UnPackElemPropType + END IF + END SUBROUTINE SD_UnPackInitOutput SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(SD_InitType), INTENT(IN) :: SrcInitTypeData @@ -3316,18 +3310,6 @@ SUBROUTINE SD_CopyInitType( SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, END IF DstInitTypeData%M = SrcInitTypeData%M ENDIF -IF (ALLOCATED(SrcInitTypeData%FG)) THEN - i1_l = LBOUND(SrcInitTypeData%FG,1) - i1_u = UBOUND(SrcInitTypeData%FG,1) - IF (.NOT. ALLOCATED(DstInitTypeData%FG)) THEN - ALLOCATE(DstInitTypeData%FG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%FG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInitTypeData%FG = SrcInitTypeData%FG -ENDIF IF (ALLOCATED(SrcInitTypeData%ElemProps)) THEN i1_l = LBOUND(SrcInitTypeData%ElemProps,1) i1_u = UBOUND(SrcInitTypeData%ElemProps,1) @@ -3462,9 +3444,6 @@ SUBROUTINE SD_DestroyInitType( InitTypeData, ErrStat, ErrMsg ) IF (ALLOCATED(InitTypeData%M)) THEN DEALLOCATE(InitTypeData%M) ENDIF -IF (ALLOCATED(InitTypeData%FG)) THEN - DEALLOCATE(InitTypeData%FG) -ENDIF IF (ALLOCATED(InitTypeData%ElemProps)) THEN DEALLOCATE(InitTypeData%ElemProps) ENDIF @@ -3648,11 +3627,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Int_BufSz = Int_BufSz + 2*2 ! M upper/lower bounds for each dimension Db_BufSz = Db_BufSz + SIZE(InData%M) ! M END IF - Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no - IF ( ALLOCATED(InData%FG) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%FG) ! FG - END IF Int_BufSz = Int_BufSz + 1 ! ElemProps allocated yes/no IF ( ALLOCATED(InData%ElemProps) ) THEN Int_BufSz = Int_BufSz + 2*2 ! ElemProps upper/lower bounds for each dimension @@ -4188,21 +4162,6 @@ SUBROUTINE SD_PackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%FG) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FG,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%FG,1), UBOUND(InData%FG,1) - DbKiBuf(Db_Xferred) = InData%FG(i1) - Db_Xferred = Db_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%ElemProps) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4877,24 +4836,6 @@ SUBROUTINE SD_UnPackInitType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FG)) DEALLOCATE(OutData%FG) - ALLOCATE(OutData%FG(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%FG,1), UBOUND(OutData%FG,1) - OutData%FG(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ElemProps not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7018,17 +6959,17 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) IF (ErrStat>=AbortErrLev) RETURN ENDDO ENDIF -IF (ALLOCATED(SrcParamData%FG_full)) THEN - i1_l = LBOUND(SrcParamData%FG_full,1) - i1_u = UBOUND(SrcParamData%FG_full,1) - IF (.NOT. ALLOCATED(DstParamData%FG_full)) THEN - ALLOCATE(DstParamData%FG_full(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%FG)) THEN + i1_l = LBOUND(SrcParamData%FG,1) + i1_u = UBOUND(SrcParamData%FG,1) + IF (.NOT. ALLOCATED(DstParamData%FG)) THEN + ALLOCATE(DstParamData%FG(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FG_full.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FG.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%FG_full = SrcParamData%FG_full + DstParamData%FG = SrcParamData%FG ENDIF IF (ALLOCATED(SrcParamData%DP0)) THEN i1_l = LBOUND(SrcParamData%DP0,1) @@ -7190,18 +7131,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%MMB = SrcParamData%MMB ENDIF -IF (ALLOCATED(SrcParamData%FX)) THEN - i1_l = LBOUND(SrcParamData%FX,1) - i1_u = UBOUND(SrcParamData%FX,1) - IF (.NOT. ALLOCATED(DstParamData%FX)) THEN - ALLOCATE(DstParamData%FX(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FX = SrcParamData%FX -ENDIF IF (ALLOCATED(SrcParamData%C1_11)) THEN i1_l = LBOUND(SrcParamData%C1_11,1) i1_u = UBOUND(SrcParamData%C1_11,1) @@ -7272,18 +7201,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D1_14 = SrcParamData%D1_14 ENDIF -IF (ALLOCATED(SrcParamData%FY)) THEN - i1_l = LBOUND(SrcParamData%FY,1) - i1_u = UBOUND(SrcParamData%FY,1) - IF (.NOT. ALLOCATED(DstParamData%FY)) THEN - ALLOCATE(DstParamData%FY(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FY.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FY = SrcParamData%FY -ENDIF IF (ALLOCATED(SrcParamData%PhiM)) THEN i1_l = LBOUND(SrcParamData%PhiM,1) i1_u = UBOUND(SrcParamData%PhiM,1) @@ -7368,18 +7285,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D2_64 = SrcParamData%D2_64 ENDIF -IF (ALLOCATED(SrcParamData%F2_61)) THEN - i1_l = LBOUND(SrcParamData%F2_61,1) - i1_u = UBOUND(SrcParamData%F2_61,1) - IF (.NOT. ALLOCATED(DstParamData%F2_61)) THEN - ALLOCATE(DstParamData%F2_61(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%F2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%F2_61 = SrcParamData%F2_61 -ENDIF IF (ALLOCATED(SrcParamData%MBB)) THEN i1_l = LBOUND(SrcParamData%MBB,1) i1_u = UBOUND(SrcParamData%MBB,1) @@ -7478,18 +7383,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%MBM = SrcParamData%MBM ENDIF -IF (ALLOCATED(SrcParamData%UL_st_g)) THEN - i1_l = LBOUND(SrcParamData%UL_st_g,1) - i1_u = UBOUND(SrcParamData%UL_st_g,1) - IF (.NOT. ALLOCATED(DstParamData%UL_st_g)) THEN - ALLOCATE(DstParamData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%UL_st_g.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%UL_st_g = SrcParamData%UL_st_g -ENDIF IF (ALLOCATED(SrcParamData%PhiL_T)) THEN i1_l = LBOUND(SrcParamData%PhiL_T,1) i1_u = UBOUND(SrcParamData%PhiL_T,1) @@ -7787,18 +7680,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF END IF DstParamData%ID__F = SrcParamData%ID__F -ENDIF -IF (ALLOCATED(SrcParamData%FGL)) THEN - i1_l = LBOUND(SrcParamData%FGL,1) - i1_u = UBOUND(SrcParamData%FGL,1) - IF (.NOT. ALLOCATED(DstParamData%FGL)) THEN - ALLOCATE(DstParamData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FGL = SrcParamData%FGL ENDIF DstParamData%NMOutputs = SrcParamData%NMOutputs DstParamData%NumOuts = SrcParamData%NumOuts @@ -7926,8 +7807,8 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) ENDDO DEALLOCATE(ParamData%ElemProps) ENDIF -IF (ALLOCATED(ParamData%FG_full)) THEN - DEALLOCATE(ParamData%FG_full) +IF (ALLOCATED(ParamData%FG)) THEN + DEALLOCATE(ParamData%FG) ENDIF IF (ALLOCATED(ParamData%DP0)) THEN DEALLOCATE(ParamData%DP0) @@ -7968,9 +7849,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%MMB)) THEN DEALLOCATE(ParamData%MMB) ENDIF -IF (ALLOCATED(ParamData%FX)) THEN - DEALLOCATE(ParamData%FX) -ENDIF IF (ALLOCATED(ParamData%C1_11)) THEN DEALLOCATE(ParamData%C1_11) ENDIF @@ -7986,9 +7864,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D1_14)) THEN DEALLOCATE(ParamData%D1_14) ENDIF -IF (ALLOCATED(ParamData%FY)) THEN - DEALLOCATE(ParamData%FY) -ENDIF IF (ALLOCATED(ParamData%PhiM)) THEN DEALLOCATE(ParamData%PhiM) ENDIF @@ -8007,9 +7882,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D2_64)) THEN DEALLOCATE(ParamData%D2_64) ENDIF -IF (ALLOCATED(ParamData%F2_61)) THEN - DEALLOCATE(ParamData%F2_61) -ENDIF IF (ALLOCATED(ParamData%MBB)) THEN DEALLOCATE(ParamData%MBB) ENDIF @@ -8031,9 +7903,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%MBM)) THEN DEALLOCATE(ParamData%MBM) ENDIF -IF (ALLOCATED(ParamData%UL_st_g)) THEN - DEALLOCATE(ParamData%UL_st_g) -ENDIF IF (ALLOCATED(ParamData%PhiL_T)) THEN DEALLOCATE(ParamData%PhiL_T) ENDIF @@ -8100,9 +7969,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%ID__F)) THEN DEALLOCATE(ParamData%ID__F) ENDIF -IF (ALLOCATED(ParamData%FGL)) THEN - DEALLOCATE(ParamData%FGL) -ENDIF IF (ALLOCATED(ParamData%MoutLst)) THEN DO i1 = LBOUND(ParamData%MoutLst,1), UBOUND(ParamData%MoutLst,1) CALL SD_Destroymeshauxdatatype( ParamData%MoutLst(i1), ErrStat, ErrMsg ) @@ -8204,10 +8070,10 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF END DO END IF - Int_BufSz = Int_BufSz + 1 ! FG_full allocated yes/no - IF ( ALLOCATED(InData%FG_full) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FG_full upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%FG_full) ! FG_full + Int_BufSz = Int_BufSz + 1 ! FG allocated yes/no + IF ( ALLOCATED(InData%FG) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! FG upper/lower bounds for each dimension + Db_BufSz = Db_BufSz + SIZE(InData%FG) ! FG END IF Int_BufSz = Int_BufSz + 1 ! DP0 allocated yes/no IF ( ALLOCATED(InData%DP0) ) THEN @@ -8306,11 +8172,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! MMB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%MMB) ! MMB END IF - Int_BufSz = Int_BufSz + 1 ! FX allocated yes/no - IF ( ALLOCATED(InData%FX) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FX upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FX) ! FX - END IF Int_BufSz = Int_BufSz + 1 ! C1_11 allocated yes/no IF ( ALLOCATED(InData%C1_11) ) THEN Int_BufSz = Int_BufSz + 2*2 ! C1_11 upper/lower bounds for each dimension @@ -8336,11 +8197,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 END IF - Int_BufSz = Int_BufSz + 1 ! FY allocated yes/no - IF ( ALLOCATED(InData%FY) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FY upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FY) ! FY - END IF Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no IF ( ALLOCATED(InData%PhiM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension @@ -8371,11 +8227,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D2_64 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D2_64) ! D2_64 END IF - Int_BufSz = Int_BufSz + 1 ! F2_61 allocated yes/no - IF ( ALLOCATED(InData%F2_61) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! F2_61 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F2_61) ! F2_61 - END IF Int_BufSz = Int_BufSz + 1 ! MBB allocated yes/no IF ( ALLOCATED(InData%MBB) ) THEN Int_BufSz = Int_BufSz + 2*2 ! MBB upper/lower bounds for each dimension @@ -8411,11 +8262,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! MBM upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%MBM) ! MBM END IF - Int_BufSz = Int_BufSz + 1 ! UL_st_g allocated yes/no - IF ( ALLOCATED(InData%UL_st_g) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UL_st_g upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UL_st_g) ! UL_st_g - END IF Int_BufSz = Int_BufSz + 1 ! PhiL_T allocated yes/no IF ( ALLOCATED(InData%PhiL_T) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiL_T upper/lower bounds for each dimension @@ -8541,11 +8387,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IF ( ALLOCATED(InData%ID__F) ) THEN Int_BufSz = Int_BufSz + 2*1 ! ID__F upper/lower bounds for each dimension Int_BufSz = Int_BufSz + SIZE(InData%ID__F) ! ID__F - END IF - Int_BufSz = Int_BufSz + 1 ! FGL allocated yes/no - IF ( ALLOCATED(InData%FGL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! FGL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FGL) ! FGL END IF Int_BufSz = Int_BufSz + 1 ! NMOutputs Int_BufSz = Int_BufSz + 1 ! NumOuts @@ -8763,18 +8604,18 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si ENDIF END DO END IF - IF ( .NOT. ALLOCATED(InData%FG_full) ) THEN + IF ( .NOT. ALLOCATED(InData%FG) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FG_full,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG_full,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%FG,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FG,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%FG_full,1), UBOUND(InData%FG_full,1) - DbKiBuf(Db_Xferred) = InData%FG_full(i1) + DO i1 = LBOUND(InData%FG,1), UBOUND(InData%FG,1) + DbKiBuf(Db_Xferred) = InData%FG(i1) Db_Xferred = Db_Xferred + 1 END DO END IF @@ -9042,21 +8883,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%FX) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FX,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FX,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%FX,1), UBOUND(InData%FX,1) - ReKiBuf(Re_Xferred) = InData%FX(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%C1_11) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9157,21 +8983,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%FY) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FY,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FY,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%FY,1), UBOUND(InData%FY,1) - ReKiBuf(Re_Xferred) = InData%FY(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%PhiM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9292,21 +9103,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%F2_61) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%F2_61,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F2_61,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%F2_61,1), UBOUND(InData%F2_61,1) - ReKiBuf(Re_Xferred) = InData%F2_61(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%MBB) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9447,21 +9243,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%UL_st_g) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UL_st_g,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UL_st_g,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%UL_st_g,1), UBOUND(InData%UL_st_g,1) - ReKiBuf(Re_Xferred) = InData%UL_st_g(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%PhiL_T) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9868,21 +9649,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si IntKiBuf(Int_Xferred) = InData%ID__F(i1) Int_Xferred = Int_Xferred + 1 END DO - END IF - IF ( .NOT. ALLOCATED(InData%FGL) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FGL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FGL,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%FGL,1), UBOUND(InData%FGL,1) - ReKiBuf(Re_Xferred) = InData%FGL(i1) - Re_Xferred = Re_Xferred + 1 - END DO END IF IntKiBuf(Int_Xferred) = InData%NMOutputs Int_Xferred = Int_Xferred + 1 @@ -10242,21 +10008,21 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG_full not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FG not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FG_full)) DEALLOCATE(OutData%FG_full) - ALLOCATE(OutData%FG_full(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%FG)) DEALLOCATE(OutData%FG) + ALLOCATE(OutData%FG(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG_full.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FG.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%FG_full,1), UBOUND(OutData%FG_full,1) - OutData%FG_full(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) + DO i1 = LBOUND(OutData%FG,1), UBOUND(OutData%FG,1) + OutData%FG(i1) = REAL(DbKiBuf(Db_Xferred), R8Ki) Db_Xferred = Db_Xferred + 1 END DO END IF @@ -10581,24 +10347,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FX not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FX)) DEALLOCATE(OutData%FX) - ALLOCATE(OutData%FX(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FX.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%FX,1), UBOUND(OutData%FX,1) - OutData%FX(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10714,24 +10462,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FY not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FY)) DEALLOCATE(OutData%FY) - ALLOCATE(OutData%FY(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FY.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%FY,1), UBOUND(OutData%FY,1) - OutData%FY(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10870,24 +10600,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F2_61 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%F2_61)) DEALLOCATE(OutData%F2_61) - ALLOCATE(OutData%F2_61(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F2_61.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%F2_61,1), UBOUND(OutData%F2_61,1) - OutData%F2_61(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBB not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -11049,24 +10761,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UL_st_g not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UL_st_g)) DEALLOCATE(OutData%UL_st_g) - ALLOCATE(OutData%UL_st_g(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UL_st_g.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%UL_st_g,1), UBOUND(OutData%UL_st_g,1) - OutData%UL_st_g(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiL_T not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -11539,24 +11233,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg OutData%ID__F(i1) = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FGL not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FGL)) DEALLOCATE(OutData%FGL) - ALLOCATE(OutData%FGL(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FGL.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%FGL,1), UBOUND(OutData%FGL,1) - OutData%FGL(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO END IF OutData%NMOutputs = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 From 7818376ecea28acd51110cd63d60b8141b13435c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 20:47:08 -0700 Subject: [PATCH 327/377] FlexSub: simplifying Floating/FixedBottom --- modules/subdyn/src/SD_FEM.f90 | 37 +++++----- modules/subdyn/src/SubDyn.f90 | 99 ++++++++++++++------------ modules/subdyn/src/SubDyn_Registry.txt | 1 - modules/subdyn/src/SubDyn_Types.f90 | 7 -- 4 files changed, 69 insertions(+), 75 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 100328363..d368995a4 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -2023,39 +2023,34 @@ SUBROUTINE InsertJointStiffDamp(p, Init, ErrStat, ErrMsg) END SUBROUTINE InsertJointStiffDamp !> Returns true if the substructure can be considered "fixed bottom" -!! This is relevant for the ExtraMoment calculation where different reference positions -!! are used depending if translation is fixed of free. -!! As defined in the documentation: -!! The structure is considered “fixed†at the sea bed if at least one reaction node has: -!! - the 4 degrees of freedom accounting for the x-y translation and rotation are fixed -!! OR -!! - an additional stiffness matrix via an SSI input file -LOGICAL FUNCTION isFixedBottom(Init, p) result(bFixed) +LOGICAL FUNCTION isFixedBottom(Init, p) TYPE(SD_InitType), INTENT(IN ) :: Init TYPE(SD_ParameterType),INTENT(IN ) :: p - INTEGER(IntKi) :: i, nFixed - nFixed=0 - do i =1,size(p%Nodes_C,1) - if (ALL(p%Nodes_C(I,2:7)==idBC_Fixed)) then - nFixed=nFixed+1 - elseif (Init%SSIfile(I)/='') then - nFixed=nFixed+1 - endif - enddo - bFixed = nFixed >=1 + isFixedBottom=.not.isFloating(Init,p) + !INTEGER(IntKi) :: i, nFixed + !nFixed=0 + !do i =1,size(p%Nodes_C,1) + ! if (ALL(p%Nodes_C(I,2:7)==idBC_Fixed)) then + ! nFixed=nFixed+1 + ! elseif (Init%SSIfile(I)/='') then + ! nFixed=nFixed+1 + ! endif + !enddo + !bFixed = nFixed >=1 END FUNCTION isFixedBottom !> True if a structure is floating, no fixed BC at the bottom -logical function isFloating(Init, p) result(bFLoating) +logical function isFloating(Init, p) type(SD_InitType), intent(in ):: Init type(SD_ParameterType),intent(in ) :: p integer(IntKi) :: i - bFloating=.True. + !isFloating=size(p%Nodes_C)>0 + isFloating=.True. do i =1,size(p%Nodes_C,1) if ((all(p%Nodes_C(I,2:7)==idBC_Internal)) .and. (Init%SSIfile(i)=='')) then continue else - bFloating=.False. + isFloating=.False. return endif enddo diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 55a0fe972..83e7b34db 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -219,17 +219,9 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Parse the SubDyn inputs CALL SD_Input(InitInput%SDInputFile, Init, p, ErrStat2, ErrMsg2); if(Failed()) return if (p%Floating) then - if (GUYAN_RIGID_FLOATING) then - call WrScr(' Floating case detected, Guyan modes will be rigid body modes') - else - call WrScr(' Floating case detected') - endif + call WrScr(' Floating case detected, Guyan modes will be rigid body modes') else - if (p%FixedBottom) then - call WrScr(' Fixed bottom case detected') - else - call WrScr(' Mixed free/fixed condary conditions (free/floating assumed)') - endif + call WrScr(' Fixed bottom case detected') endif ! -------------------------------------------------------------------------------- @@ -281,10 +273,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return if (p%ExtraMoment) then - if (p%FixedBottom) then - call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') - else + if (p%Floating) then + ! TODO disallow call WrScr(' Extra moment will be included in loads (free/floating case detected)') + else + call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') endif endif @@ -490,7 +483,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) end if endif ! --- Adding Guyan contribution to R and L DOFs - if ((.not. p%Floating) .or. (.not. GUYAN_RIGID_FLOATING)) then + if (.not.p%Floating) then ! Then we add the Guyan motion here m%UR_bar = matmul( p%TI , m%u_TP ) m%UR_bar_dot = matmul( p%TI , m%udot_TP ) @@ -530,15 +523,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_elast = m%U_full ! --- Place displacement/velocity/acceleration into Y2 output mesh - DO iSDNode = 1,p%nNodes - iY2Node = iSDNode - DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations - ! - if (p%Floating .and. GUYAN_RIGID_FLOATING) then + if (p%Floating) then + do iSDNode = 1,p%nNodes + iY2Node = iSDNode + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! For floating case, we add the Guyan motion contribution ! This accounts for "rotations" effects, where the bottom node should "go up", and not just translate horizontally - ! It corresponds to a rigid body motion the the TP as origin - ! Rigid body motion of the point + ! It corresponds to a rigid body motion with the TP as origin + ! --- Guyan (rigid body) motion in global coordinates rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rot, rIP0) duP(1:3) = rIP - rIP0 + m%u_TP(1:3) @@ -551,18 +543,34 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_dot (DOFList(4:6))= m%U_full_dot (DOFList(4:6)) + Om(1:3) m%U_full_dotdot(DOFList(1:3))= m%U_full_dotdot(DOFList(1:3)) + aP(1:3) m%U_full_dotdot(DOFList(4:6))= m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) - endif ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles - CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - y%Y2mesh%Orientation (:,:,iY2Node) = DCM - y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) - y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) - y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) - y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) - y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) - enddo + CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + y%Y2mesh%Orientation (:,:,iY2Node) = DCM + y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + enddo + else + ! --- Fixed bottom + do iSDNode = 1,p%nNodes + iY2Node = iSDNode + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! TODO TODO which orientation to give for joints with more than 6 dofs? + ! Construct the direction cosine matrix given the output angles + CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + y%Y2mesh%Orientation (:,:,iY2Node) = DCM + y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + enddo + endif !________________________________________ ! Set loads outputs on y%Y1Mesh !________________________________________ @@ -585,7 +593,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! MExtra = -u_TP x f_TP ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs if (p%ExtraMoment) then - if (p%FixedBottom) then ! if Fixed, transfer from non deflected TP to u_TP + if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) @@ -945,7 +953,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) Init%SSIK = 0.0_ReKi ! Important init TODO: read these matrices on the fly in SD_FEM maybe? Init%SSIM = 0.0_ReKi ! Important init ! Reading reaction lines one by one, allowing for 1, 7 or 8 columns, with col8 being a string for the SSIfile -DO I = 1, p%nNodes_C +do I = 1, p%nNodes_C READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading reaction line'; if (Failed()) return call ReadIAryFromStr(Line, p%Nodes_C(I,:), 8, nColValid, nColNumeric, Init%SSIfile(I:I)); if (nColValid==1 .and. nColNumeric==1) then @@ -954,10 +962,10 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) else if (nColNumeric==7 .and.(nColValid==7.or.nColValid==8)) then ! This is fine. else - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') + call Fatal(' Error in file "'//TRIM(SDInputFile)//'": Reaction lines must consist of 7 numerical values, followed by an optional string. Problematic line: "'//trim(Line)//'"') return endif -ENDDO +enddo IF (Check ( p%nNodes_C > Init%NJoints , 'NReact must be less than number of joints')) return call CheckBCs(p, ErrStat2, ErrMsg2); if (Failed()) return @@ -969,8 +977,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif enddo ! Trigger: determine if floating/fixed based on BCs and SSI file -p%FixedBottom = isFixedBottom(Init,p) -p%Floating = isFloating(Init,p) +p%Floating = isFloating(Init,p) +!if (p%ExtraMoment .and. p%Floating) then +! call Fatal(' Error in file "'//TRIM(SDInputFile)//'": `ExtraMoment` cannot be true in a floating case') +! return +!endif @@ -2865,9 +2876,11 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) real(ReKi), parameter :: myNaN = -9999998.989_ReKi if (p%ExtraMoment) then + ! TODO modify for floating + ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); - if (p%Floating .and. GUYAN_RIGID_FLOATING) then + if (p%Floating) then ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) m%DU_full = 0.0_ReKi @@ -2891,15 +2904,8 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) else m%DU_full = m%U_red endif - if (.not.p%FixedBottom) then ! if Floating, remove u_TP translation - do iNode = 1,p%nNodes - m%DU_full(p%NodesDOF(iNode)%List(1:3)) = m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) - enddo - endif endif endif - - ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN do iNode = 1,p%nNodes @@ -2926,8 +2932,9 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) endif ! --- Build vector of external moment - dO iNode = 1,p%nNodes + do iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh + ! Moment ext + gravity Moment(1:3) = u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6)) nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's DOFList diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 2a4a6af3b..3606b8a12 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -187,7 +187,6 @@ typedef ^ ParameterType IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" -typedef ^ ParameterType Logical FixedBottom - - - "True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node)" typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 7b0055385..081758f6c 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -234,7 +234,6 @@ MODULE SubDyn_Types INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] - LOGICAL :: FixedBottom !< True if Fixed bottom (the 4 x-y DOF fixed for at least one reaction node) [-] LOGICAL :: Floating !< True if floating bottom (the 6 DOF are free at all reaction nodes) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] @@ -7091,7 +7090,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment - DstParamData%FixedBottom = SrcParamData%FixedBottom DstParamData%Floating = SrcParamData%Floating IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) @@ -8155,7 +8153,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment - Int_BufSz = Int_BufSz + 1 ! FixedBottom Int_BufSz = Int_BufSz + 1 ! Floating Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN @@ -8829,8 +8826,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%ExtraMoment, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedBottom, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%Floating, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN @@ -10284,8 +10279,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%ExtraMoment = TRANSFER(IntKiBuf(Int_Xferred), OutData%ExtraMoment) Int_Xferred = Int_Xferred + 1 - OutData%FixedBottom = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedBottom) - Int_Xferred = Int_Xferred + 1 OutData%Floating = TRANSFER(IntKiBuf(Int_Xferred), OutData%Floating) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated From 868bcfa95e1d9b7520eff492af423b0c36b2bb4d Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 21:55:54 -0700 Subject: [PATCH 328/377] FlexSub: preparing for load-rotation and cleanup --- modules/subdyn/src/SubDyn.f90 | 197 ++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 93 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 83e7b34db..b62c6b0d0 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -438,33 +438,54 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - - ! --- Reference coordinate system and body motion + + ! --- Convert inputs to FEM DOFs and convenient 6-vector storage ! Compute the small rotation angles given the input direction cosine matrix rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); if(Failed()) return - Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) - Om(1:3) = u%TPMesh%RotationVel(1:3,1) - OmD(1:3) = u%TPMesh%RotationAcc(1:3,1) - - ! Inputs at the transition piece: m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - - ! External force on internal and interface nodes - call GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); if(Failed()) return + + ! -------------------------------------------------------------------------------- + ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) + ! -------------------------------------------------------------------------------- + ! Compute external force on internal (UFL) and interface nodes (F_I) + call GetExtForceOnInternalDOF(u, p, m, .false., m%UFL, ErrStat2, ErrMsg2); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) + ! Compute reaction/coupling force at TP + if ( p%nDOFM > 0) then + Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & + + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & + - matmul( F_I, p%TI ) ) + else ! No retained modes, so there are no states + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & + - matmul( F_I, p%TI ) ) + end if + ! Computing extra moments due to lever arm introduced by interface displacement + ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs + if (p%ExtraMoment) then + if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif + endif + ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces + y%Y1Mesh%Force (:,1) = Y1(1:3) + y%Y1Mesh%Moment(:,1) = Y1(4:6) ! -------------------------------------------------------------------------------- - ! --- Output Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) + ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- + ! External force on internal nodes (UFL) + call GetExtForceOnInternalDOF(u, p, m, .false., m%UFL, ErrStat2, ErrMsg2); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi m%UL = 0.0_ReKi m%UL_dot = 0.0_ReKi m%UL_dotdot = 0.0_ReKi - ! --- CB modes contribution to motion (L-DOF only) IF ( p%nDOFM > 0) THEN m%UL = matmul( p%PhiM, x%qm ) @@ -524,12 +545,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Place displacement/velocity/acceleration into Y2 output mesh if (p%Floating) then + ! For floating, we compute the Guyan motion directly (rigid body motion with TP as origin) + ! This introduce non-linear "rotations" effects, where the bottom node should "go up", and not just translate horizontally + Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) ! body 2 global + Om(1:3) = u%TPMesh%RotationVel(1:3,1) + OmD(1:3) = u%TPMesh%RotationAcc(1:3,1) do iSDNode = 1,p%nNodes iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations - ! For floating case, we add the Guyan motion contribution - ! This accounts for "rotations" effects, where the bottom node should "go up", and not just translate horizontally - ! It corresponds to a rigid body motion with the TP as origin ! --- Guyan (rigid body) motion in global coordinates rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rot, rIP0) @@ -537,16 +560,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Om_X_r(1:3) = cross_product(Om, rIP) vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) - m%U_full (DOFList(1:3))= m%U_full (DOFList(1:3)) + duP(1:3) - m%U_full (DOFList(4:6))= m%U_full (DOFList(4:6)) + rotations(1:3) - m%U_full_dot (DOFList(1:3))= m%U_full_dot (DOFList(1:3)) + vP(1:3) - m%U_full_dot (DOFList(4:6))= m%U_full_dot (DOFList(4:6)) + Om(1:3) - m%U_full_dotdot(DOFList(1:3))= m%U_full_dotdot(DOFList(1:3)) + aP(1:3) - m%U_full_dotdot(DOFList(4:6))= m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) - ! TODO TODO which orientation to give for joints with more than 6 dofs? - ! Construct the direction cosine matrix given the output angles - CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') + m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) + m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + ! TODO TODO which orientation to give for joints with more than 6 dofs? + ! Construct the direction cosine matrix given the output angles + call SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') y%Y2mesh%Orientation (:,:,iY2Node) = DCM y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) @@ -571,39 +594,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) enddo endif - !________________________________________ - ! Set loads outputs on y%Y1Mesh - !________________________________________ - ! --------------------------------------------------------------------------------- - !Y1= TP reaction Forces, i.e. force that the jacket exerts onto the TP and above - ! --------------------------------------------------------------------------------- - ! Eq. 15: Y1 = -(C1*x + D1*u ) [note the negative sign!!!!] - !HydroTP = matmul(transpose(p%TI), F_I) ! (6,1) calculated below - ! note: matmul( F_I, p%TI ) = matmul( transpose(p%TI), F_I) because F_I is 1-D - IF ( p%nDOFM > 0) THEN - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! -( C1(1,1)*x(1) + C1(1,2)*x(2) - + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( F_I, p%TI ) ) ! + D1(1,5)*u(5) + Fy(1) ) - ELSE ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & ! -( 0*x + D1(1,1)*u(1) + 0*u(2) + D1(1,3)*u(3) + D1(1,4)*u(4) - - matmul( F_I, p%TI ) ) ! + D1(1,5)*u(5) + Fy(1) ) - END IF - ! Computing extra moments due to lever arm introduced by interface displacement - ! Y1(:3) = -f_TP - ! MExtra = -u_TP x f_TP - ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancelling of signs - if (p%ExtraMoment) then - if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment - endif - endif - - ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces - y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE @@ -689,15 +679,14 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta IF ( p%nDOFM == 0 ) RETURN - ! form u(3) in Eq. 10: + ! 6-vectors + !m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) + ! Compute F_L, force on internal DOF + CALL GetExtForceOnInternalDOF( u, p, m, .false., m%UFL, ErrStat2, ErrMsg2 ); - ! form u(4) in Eq. 10: - CALL GetExtForceOnInternalDOF( u, p, m, m%UFL, ErrStat2, ErrMsg2 ); - - !Equation 12: X=A*x + B*u + Fx (Eq 12) + ! State equation dxdt%qm= x%qmdot - ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) @@ -1675,7 +1664,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! local variables TYPE(SD_InputType) :: u_interp ! interpolated value of inputs - REAL(ReKi) :: junk2(2*p%nDOFM) !temporary states (qm and qmdot only) + REAL(ReKi) :: xq(2*p%nDOFM) !temporary states (qm and qmdot only) REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP REAL(ReKi) :: UFL2(p%nDOF__L) ! temporary copy of UFL INTEGER(IntKi) :: ErrStat2 @@ -1691,33 +1680,31 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, m%UFL, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., m%UFL, ErrStat2, ErrMsg2); ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF( u_interp, p, m, UFL2, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., UFL2, ErrStat2, ErrMsg2); ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) - ! set junk2 = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - junk2( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array - junk2(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM )) !lower portion of array + ! set xq = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) + xq( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array + xq(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM )) !lower portion of array ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D !.................................................... - ! Solve for junk2: (equivalent to junk2= matmul(p%AM2InvJac,junk2) + ! Solve for xq: (equivalent to xq= matmul(p%AM2InvJac,xq) ! J*( x_n - x_n+1 ) = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) !.................................................... - CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=junk2, ErrStat=ErrStat2, ErrMsg=ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - !IF ( ErrStat >= AbortErrLev ) RETURN + CALL LAPACK_getrs( TRANS='N',N=SIZE(p%AM2Jac,1),A=p%AM2Jac,IPIV=p%AM2JacPiv, B=xq, ErrStat=ErrStat2, ErrMsg=ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - ! after the LAPACK solve, junk2 = ( x_n - x_n+1 ); so now we can solve for x_n+1: - x%qm = x%qm - junk2( 1: p%nDOFM) - x%qmdot = x%qmdot - junk2(p%nDOFM+1:2*p%nDOFM) + ! after the LAPACK solve, xq = ( x_n - x_n+1 ); so now we can solve for x_n+1: + x%qm = x%qm - xq( 1: p%nDOFM) + x%qmdot = x%qmdot - xq(p%nDOFM+1:2*p%nDOFM) ! clean up temporary variable(s) CALL SD_DestroyInput( u_interp, ErrStat, ErrMsg ) @@ -2852,9 +2839,10 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters + logical , intent(in ) :: rotateLoads ! If true, loads are rotated to body coordinate type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation @@ -2867,19 +2855,23 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) real(ReKi) :: CableTension ! Controllable Cable force real(ReKi) :: rotations(3) real(ReKi) :: du(3), Moment(3), Force(3) + real(ReKi) :: u_TP(6) ! Variables for Guyan Rigid motion real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) + real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates ! real(ReKi), parameter :: myNaN = -9999998.989_ReKi + ! --- Rotation matrix from body to global + if (rotateLoads) then + Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates + endif + if (p%ExtraMoment) then ! TODO modify for floating - - ! --- Compute Guyan displacement for extra moment (similar to CalcOutput, but wihtout CB) - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); if (p%Floating) then ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) @@ -2891,10 +2883,12 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) m%DU_full(p%NodesDOF(iNode)%List(1:3)) = duP(1:3) enddo else - ! For other cases with use the computed (linear) Guyan motion - m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) - m%UR_bar = matmul( p%TI , m%u_TP ) ! UR_bar - m%UL = matmul( p%PhiRb_TI, m%u_TP ) ! UL + ! --- Compute Guyan displacement for extra moment + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); + m%U_red(:) = 0.0_ReKi + u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + m%UR_bar = matmul( p%TI , u_TP ) ! UR_bar + m%UL = matmul( p%PhiRb_TI, u_TP ) ! UL m%U_red(p%IDI__) = m%UR_bar m%U_red(p%ID__L) = m%UL m%U_red(p%IDC_Rb)= 0 ! TODO @@ -2906,12 +2900,18 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) endif endif endif + ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN - do iNode = 1,p%nNodes - ! Force in global for fixed bottom - m%Fext( p%NodesDOF(iNode)%List(1:3) ) = u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3)) - enddo + if (rotateLoads) then ! Forces in body coordinates + do iNode = 1,p%nNodes + m%Fext( p%NodesDOF(iNode)%List(1:3) ) = matmul(Rg2b, u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3))) + enddo + else ! Forces in global + do iNode = 1,p%nNodes + m%Fext( p%NodesDOF(iNode)%List(1:3) ) = u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3)) + enddo + endif ! --- Adding controllable cable forces if (size(p%CtrlElem2Channel,1) > 0) then @@ -2927,7 +2927,13 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) IDOF = p%ElemsDOF(1:12, iElem) ! T(t) = - EA * DeltaL(t) /(Le + Delta L(t)) ! NOTE DeltaL<0 CableTension = -p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) - m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) + print*,'TODO, Controllable pretension cable needs thinking for moment' + STOP + !if (rotateLoads) then ! in body coordinate + ! m%Fext(IDOF) = m%Fext(IDOF) + matmul(Rg2b,m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0)) + !else ! in global + ! m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) + !endif enddo endif @@ -2935,18 +2941,23 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg ) do iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh ! Moment ext + gravity - Moment(1:3) = u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6)) - nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's DOFList + if (rotateLoads) then + ! In body coordinates + Moment(1:3) = matmul(Rg2b, u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6))) + else + Moment(1:3) = u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6)) + endif ! Extra moment dm = Delta u x (fe + fg) if (p%ExtraMoment) then - du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm + du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) Moment(3) = Moment(3) + du(1) * Force(2) - du(2) * Force(1) endif ! Moment is spread equally across all rotational DOFs if more than 3 rotational DOFs + nMembers = (size(p%NodesDOF(iNode)%List)-3)/3 ! Number of members deducted from Node's DOFList m%Fext( p%NodesDOF(iNode)%List(4::3)) = Moment(1)/nMembers m%Fext( p%NodesDOF(iNode)%List(5::3)) = Moment(2)/nMembers m%Fext( p%NodesDOF(iNode)%List(6::3)) = Moment(3)/nMembers From c8b4e991cba1f43b1ce580e56898efcde1a0946e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 22:10:44 -0700 Subject: [PATCH 329/377] FlexSub: removing unused CMB and CBM --- modules/subdyn/src/SubDyn.f90 | 21 +--- modules/subdyn/src/SubDyn_Registry.txt | 2 - modules/subdyn/src/SubDyn_Types.f90 | 132 ------------------------- 3 files changed, 5 insertions(+), 150 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b62c6b0d0..73dc7db11 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -680,7 +680,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta IF ( p%nDOFM == 0 ) RETURN ! 6-vectors - !m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing + m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Compute F_L, force on internal DOF CALL GetExtForceOnInternalDOF( u, p, m, .false., m%UFL, ErrStat2, ErrMsg2 ); @@ -688,7 +688,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta ! State equation dxdt%qm= x%qmdot ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%CMB,m%udot_TP) - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) END SUBROUTINE SD_CalcContStateDeriv @@ -2404,12 +2404,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! TODO cant use LAPACK due to type conversions FEKi->ReKi p%MBM = MATMUL( TI_transpose, MBmb ) ! NOTE: type conversion !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, MBmb, 0.0_ReKi, p%MBM, ErrStat2, ErrMsg2); if(Failed()) return - !p%CBM = MATMUL( TRANSPOSE(p%TI), CBMb ) != CBMt - !CALL LAPACK_gemm( 'T', 'N', 1.0_ReKi, p%TI, CBMb, 0.0_ReKi, p%CBM, ErrStat2, ErrMsg2); if (Failed()) return - p%CBM = 0.0_ReKi ! TODO no cross couplings p%MMB = TRANSPOSE( p%MBM ) != MMBt - p%CMB = TRANSPOSE( p%CBM ) != CMBt p%PhiM = real( PhiL(:,1:p%nDOFM), ReKi) @@ -2419,15 +2415,13 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! C1_11, C1_12 ( see eq 15 [multiply columns by diagonal matrix entries for diagonal multiply on the left]) DO I = 1, p%nDOFM ! if (p%nDOFM=p%nDOFM=nDOFM == 0), this loop is skipped - p%C1_11(:, I) = -p%MBM(:, I)*p%KMMDiag(I) - p%C1_12(:, I) = p%CBM(:,I) -p%MBM(:, I)*p%CMMDiag(I) + p%C1_11(:, I) = -p%MBM(:, I)*p%KMMDiag(I) + p%C1_12(:, I) = -p%MBM(:, I)*p%CMMDiag(I) ENDDO ! D1 Matrices ! D1_12 = CBBt - MBmt*CmBt - !CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%CBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_12 = MATMUL( p%MBM, p%CMB ) - p%D1_12 = MATMUL( p%MBM, p%CMB ) - p%D1_12 = p%CBB - p%D1_12 + p%D1_12 = p%CBB ! D1_13 = MBBt - MBmt*MmBt !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) @@ -2530,8 +2524,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%MMB, nDOFM, nDOFL_TP, 'p%MMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%KMMDiag, nDOFM, 'p%KMMDiag', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%CMMDiag, nDOFM, 'p%CMMDiag', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%CMB, nDOFM, nDOFL_TP, 'p%CMB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%CBM, nDOFL_TP, nDOFM, 'p%CBM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_11, nDOFL_TP, nDOFM, 'p%C1_11', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C1_12, nDOFL_TP, nDOFM, 'p%C1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -3327,8 +3319,6 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, ErrStat,ErrMsg) call yaml_write_array(UnSum, 'MBB ',CBparams%MBB, ReFmt, ErrStat2, ErrMsg2, comment='') call yaml_write_array(UnSum, 'MBM', CBparams%MBM, ReFmt, ErrStat2, ErrMsg2, comment='') !call yaml_write_array(UnSum, 'CBB', CBparams%CBB, ReFmt, ErrStat2, ErrMsg2, comment='') - !call yaml_write_array(UnSum, 'CBM', CBparams%CBM, ReFmt, ErrStat2, ErrMsg2, comment='') - !call yaml_write_array(UnSum, 'CBMt',p%CBM, ReFmt, ErrStat2, ErrMsg2, comment='(at TP)') !call yaml_write_array(UnSum, 'CMM', CBparams%CMM, ReFmt, ErrStat2, ErrMsg2, comment='') !call yaml_write_array(UnSum, 'CMMdiag_zeta',2.0_ReKi * CBparams%OmegaL(1:p%nDOFM) * Init%JDampings(1:p%nDOFM) , ReFmt, ErrStat2, ErrMsg2, comment='(2ZetaOmegaM)') call yaml_write_array(UnSum, 'CMMdiag',p%CMMDiag, ReFmt, ErrStat2, ErrMsg2, comment='(2 Zeta OmegaM)') @@ -3422,7 +3412,6 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) call AllocAry(BB, nX, nU, 'BB', ErrStat2, ErrMsg2 ); if(Failed()) return; BB(:,:) = 0.0_ReKi if(nCB>0) then BB(nCB+1:nX, 1 :6 ) = 0.0_ReKi - BB(nCB+1:nX, 7:12 ) = -p%CMB(1:nCB,1:6) BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) call AllocAry(dFext_dFmeshk, p%nDOF , 'dFext', ErrStat2, ErrMsg2 ); if(Failed()) return call AllocAry(dFred_dFmeshk, p%nDOF_red , 'dFred', ErrStat2, ErrMsg2 ); if(Failed()) return diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3606b8a12..7d2fa2467 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -205,8 +205,6 @@ typedef ^ ParameterType ReKi D2_64 {:}{:} - - "Coefficient of u in Y2 typedef ^ ParameterType ReKi MBB {:}{:} - - "Guyan Mass Matrix after C-B reduction" typedef ^ ParameterType ReKi KBB {:}{:} - - "Guyan Stiffness Matrix after C-B reduction" typedef ^ ParameterType ReKi CBB {:}{:} - - "Guyan Damping Matrix after C-B reduction" -typedef ^ ParameterType ReKi CMB {:}{:} - - "Cross coupling Guyan-CB damping matrix" -typedef ^ ParameterType ReKi CBM {:}{:} - - "Cross coupling Guyan-CB damping matrix" typedef ^ ParameterType ReKi CMM {:}{:} - - "CB damping matrix" typedef ^ ParameterType ReKi MBM {:}{:} - - "Matrix after C-B reduction" typedef ^ ParameterType ReKi PhiL_T {:}{:} - - "Transpose of Matrix of C-B modes" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 081758f6c..286971540 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -252,8 +252,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBB !< Guyan Mass Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KBB !< Guyan Stiffness Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBB !< Guyan Damping Matrix after C-B reduction [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMB !< Cross coupling Guyan-CB damping matrix [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CBM !< Cross coupling Guyan-CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CMM !< CB damping matrix [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBM !< Matrix after C-B reduction [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiL_T !< Transpose of Matrix of C-B modes [-] @@ -7325,34 +7323,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%CBB = SrcParamData%CBB ENDIF -IF (ALLOCATED(SrcParamData%CMB)) THEN - i1_l = LBOUND(SrcParamData%CMB,1) - i1_u = UBOUND(SrcParamData%CMB,1) - i2_l = LBOUND(SrcParamData%CMB,2) - i2_u = UBOUND(SrcParamData%CMB,2) - IF (.NOT. ALLOCATED(DstParamData%CMB)) THEN - ALLOCATE(DstParamData%CMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CMB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%CMB = SrcParamData%CMB -ENDIF -IF (ALLOCATED(SrcParamData%CBM)) THEN - i1_l = LBOUND(SrcParamData%CBM,1) - i1_u = UBOUND(SrcParamData%CBM,1) - i2_l = LBOUND(SrcParamData%CBM,2) - i2_u = UBOUND(SrcParamData%CBM,2) - IF (.NOT. ALLOCATED(DstParamData%CBM)) THEN - ALLOCATE(DstParamData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%CBM = SrcParamData%CBM -ENDIF IF (ALLOCATED(SrcParamData%CMM)) THEN i1_l = LBOUND(SrcParamData%CMM,1) i1_u = UBOUND(SrcParamData%CMM,1) @@ -7889,12 +7859,6 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%CBB)) THEN DEALLOCATE(ParamData%CBB) ENDIF -IF (ALLOCATED(ParamData%CMB)) THEN - DEALLOCATE(ParamData%CMB) -ENDIF -IF (ALLOCATED(ParamData%CBM)) THEN - DEALLOCATE(ParamData%CBM) -ENDIF IF (ALLOCATED(ParamData%CMM)) THEN DEALLOCATE(ParamData%CMM) ENDIF @@ -8239,16 +8203,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! CBB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%CBB) ! CBB END IF - Int_BufSz = Int_BufSz + 1 ! CMB allocated yes/no - IF ( ALLOCATED(InData%CMB) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CMB upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CMB) ! CMB - END IF - Int_BufSz = Int_BufSz + 1 ! CBM allocated yes/no - IF ( ALLOCATED(InData%CBM) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! CBM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%CBM) ! CBM - END IF Int_BufSz = Int_BufSz + 1 ! CMM allocated yes/no IF ( ALLOCATED(InData%CMM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! CMM upper/lower bounds for each dimension @@ -9158,46 +9112,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%CMB) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMB,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMB,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CMB,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CMB,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%CMB,2), UBOUND(InData%CMB,2) - DO i1 = LBOUND(InData%CMB,1), UBOUND(InData%CMB,1) - ReKiBuf(Re_Xferred) = InData%CMB(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%CBM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%CBM,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%CBM,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%CBM,2), UBOUND(InData%CBM,2) - DO i1 = LBOUND(InData%CBM,1), UBOUND(InData%CBM,1) - ReKiBuf(Re_Xferred) = InData%CBM(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( .NOT. ALLOCATED(InData%CMM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10662,52 +10576,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMB not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CMB)) DEALLOCATE(OutData%CMB) - ALLOCATE(OutData%CMB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CMB.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%CMB,2), UBOUND(OutData%CMB,2) - DO i1 = LBOUND(OutData%CMB,1), UBOUND(OutData%CMB,1) - OutData%CMB(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CBM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%CBM)) DEALLOCATE(OutData%CBM) - ALLOCATE(OutData%CBM(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CBM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%CBM,2), UBOUND(OutData%CBM,2) - DO i1 = LBOUND(OutData%CBM,1), UBOUND(OutData%CBM,1) - OutData%CBM(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CMM not allocated Int_Xferred = Int_Xferred + 1 ELSE From f591225d98422791d7b40c0f8d51012e5bd1bfca Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 22:16:49 -0700 Subject: [PATCH 330/377] FlexSub: renamed UFL to F_L --- modules/subdyn/src/SubDyn.f90 | 40 ++++++++++----------- modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 50 +++++++++++++------------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 73dc7db11..79615b870 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -449,16 +449,16 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! -------------------------------------------------------------------------------- ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) ! -------------------------------------------------------------------------------- - ! Compute external force on internal (UFL) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, .false., m%UFL, ErrStat2, ErrMsg2); if(Failed()) return + ! Compute external force on internal (F_L) and interface nodes (F_I) + call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP if ( p%nDOFM > 0) then Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & + + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - matmul( F_I, p%TI ) ) else ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%UFL) & + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - matmul( F_I, p%TI ) ) end if ! Computing extra moments due to lever arm introduced by interface displacement @@ -478,8 +478,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! -------------------------------------------------------------------------------- ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- - ! External force on internal nodes (UFL) - call GetExtForceOnInternalDOF(u, p, m, .false., m%UFL, ErrStat2, ErrMsg2); if(Failed()) return + ! External force on internal nodes (F_L) + call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -491,11 +491,11 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%UFL ) + + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%F_L ) END IF ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then - FLt = MATMUL(p%PhiL_T , m%UFL) ! NOTE: Gravity in UFL + FLt = MATMUL(p%PhiL_T , m%F_L) ! NOTE: Gravity in F_L ULS = MATMUL(p%PhiLInvOmgL2, FLt ) m%UL = m%UL + ULS if ( p%nDOFM > 0) then @@ -607,7 +607,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! call CalcContStateDeriv one more time to store these qmdotdot for debugging purposes in the output file !find xdot at t IF ( p%nDOFM > 0 ) THEN - ! note that this re-sets m%udotdot_TP and m%UFL, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() + ! note that this re-sets m%udotdot_TP and m%F_L, but they are the same values as earlier in this routine so it doesn't change results in SDOut_MapOutputs() CALL SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat2, ErrMsg2 ); if(Failed()) return !Assign the acceleration to the x variable since it will be used for output file purposes for SSqmdd01-99, and dxdt will disappear m%qmdotdot=dxdt%qmdot @@ -653,7 +653,7 @@ END SUBROUTINE SD_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for computing derivatives of continuous states -!! note that this also sets m%UFL and m%udotdot_TP +!! note that this also sets m%F_L and m%udotdot_TP SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t @@ -683,12 +683,12 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF( u, p, m, .false., m%UFL, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF( u, p, m, .false., m%F_L, ErrStat2, ErrMsg2 ); ! State equation dxdt%qm= x%qmdot - ! NOTE: matmul( TRANSPOSE(p%PhiM), m%UFL ) = matmul( m%UFL, p%PhiM ) because UFL is 1-D - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%UFL, p%PhiM) + ! NOTE: matmul( TRANSPOSE(p%PhiM), m%F_L ) = matmul( m%F_L, p%PhiM ) because F_L is 1-D + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%F_L, p%PhiM) END SUBROUTINE SD_CalcContStateDeriv @@ -1666,7 +1666,7 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg TYPE(SD_InputType) :: u_interp ! interpolated value of inputs REAL(ReKi) :: xq(2*p%nDOFM) !temporary states (qm and qmdot only) REAL(ReKi) :: udotdot_TP2(6) ! temporary copy of udotdot_TP - REAL(ReKi) :: UFL2(p%nDOF__L) ! temporary copy of UFL + REAL(ReKi) :: F_L2(p%nDOF__L) ! temporary copy of F_L INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -1680,21 +1680,21 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., m%UFL, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., m%F_L, ErrStat2, ErrMsg2); ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., UFL2, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., F_L2, ErrStat2, ErrMsg2); ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) - UFL2 = 0.5_ReKi * ( UFL2 + m%UFL ) + F_L2 = 0.5_ReKi * ( F_L2 + m%F_L ) ! set xq = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) xq( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array - xq(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(UFL2,p%PhiM )) !lower portion of array - ! note: matmul(UFL2,p%PhiM ) = matmul(p%PhiM_T,UFL2) because UFL2 is 1-D + xq(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(F_L2,p%PhiM )) !lower portion of array + ! note: matmul(F_L2,p%PhiM ) = matmul(p%PhiM_T,F_L2) because F_L2 is 1-D !.................................................... ! Solve for xq: (equivalent to xq= matmul(p%AM2InvJac,xq) @@ -2552,7 +2552,7 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) ErrMsg = "" ! for readability, we're going to keep track of the max ErrStat through SetErrStat() and not return until the end of this routine. - CALL AllocAry( Misc%UFL, p%nDOF__L, 'UFL', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%F_L, p%nDOF__L, 'F_L', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%UR_bar, p%nDOFI__, 'UR_bar', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb CALL AllocAry( Misc%UR_bar_dot, p%nDOFI__, 'UR_bar_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb CALL AllocAry( Misc%UR_bar_dotdot,p%nDOFI__, 'UR_bar_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') !TODO Rb diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 7d2fa2467..5e686c602 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -138,7 +138,7 @@ typedef ^ MiscVarType ReKi qmdotdot {:} - - "2nd Deriva typedef ^ MiscVarType ReKi u_TP 6 - - typedef ^ MiscVarType ReKi udot_TP 6 - - typedef ^ MiscVarType ReKi udotdot_TP 6 - - -typedef ^ MiscVarType ReKi UFL {:} - - +typedef ^ MiscVarType ReKi F_L {:} - - typedef ^ MiscVarType ReKi UR_bar {:} - - typedef ^ MiscVarType ReKi UR_bar_dot {:} - - typedef ^ MiscVarType ReKi UR_bar_dotdot {:} - - diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 286971540..4262c2c8f 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -189,7 +189,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(1:6) :: u_TP REAL(ReKi) , DIMENSION(1:6) :: udot_TP REAL(ReKi) , DIMENSION(1:6) :: udotdot_TP - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UFL + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: F_L REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: UR_bar_dotdot @@ -5706,17 +5706,17 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) DstMiscData%u_TP = SrcMiscData%u_TP DstMiscData%udot_TP = SrcMiscData%udot_TP DstMiscData%udotdot_TP = SrcMiscData%udotdot_TP -IF (ALLOCATED(SrcMiscData%UFL)) THEN - i1_l = LBOUND(SrcMiscData%UFL,1) - i1_u = UBOUND(SrcMiscData%UFL,1) - IF (.NOT. ALLOCATED(DstMiscData%UFL)) THEN - ALLOCATE(DstMiscData%UFL(i1_l:i1_u),STAT=ErrStat2) +IF (ALLOCATED(SrcMiscData%F_L)) THEN + i1_l = LBOUND(SrcMiscData%F_L,1) + i1_u = UBOUND(SrcMiscData%F_L,1) + IF (.NOT. ALLOCATED(DstMiscData%F_L)) THEN + ALLOCATE(DstMiscData%F_L(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%UFL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstMiscData%UFL = SrcMiscData%UFL + DstMiscData%F_L = SrcMiscData%F_L ENDIF IF (ALLOCATED(SrcMiscData%UR_bar)) THEN i1_l = LBOUND(SrcMiscData%UR_bar,1) @@ -5950,8 +5950,8 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%qmdotdot)) THEN DEALLOCATE(MiscData%qmdotdot) ENDIF -IF (ALLOCATED(MiscData%UFL)) THEN - DEALLOCATE(MiscData%UFL) +IF (ALLOCATED(MiscData%F_L)) THEN + DEALLOCATE(MiscData%F_L) ENDIF IF (ALLOCATED(MiscData%UR_bar)) THEN DEALLOCATE(MiscData%UR_bar) @@ -6052,10 +6052,10 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_BufSz = Re_BufSz + SIZE(InData%u_TP) ! u_TP Re_BufSz = Re_BufSz + SIZE(InData%udot_TP) ! udot_TP Re_BufSz = Re_BufSz + SIZE(InData%udotdot_TP) ! udotdot_TP - Int_BufSz = Int_BufSz + 1 ! UFL allocated yes/no - IF ( ALLOCATED(InData%UFL) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! UFL upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%UFL) ! UFL + Int_BufSz = Int_BufSz + 1 ! F_L allocated yes/no + IF ( ALLOCATED(InData%F_L) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! F_L upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%F_L) ! F_L END IF Int_BufSz = Int_BufSz + 1 ! UR_bar allocated yes/no IF ( ALLOCATED(InData%UR_bar) ) THEN @@ -6203,18 +6203,18 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz ReKiBuf(Re_Xferred) = InData%udotdot_TP(i1) Re_Xferred = Re_Xferred + 1 END DO - IF ( .NOT. ALLOCATED(InData%UFL) ) THEN + IF ( .NOT. ALLOCATED(InData%F_L) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%UFL,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%UFL,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%F_L,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F_L,1) Int_Xferred = Int_Xferred + 2 - DO i1 = LBOUND(InData%UFL,1), UBOUND(InData%UFL,1) - ReKiBuf(Re_Xferred) = InData%UFL(i1) + DO i1 = LBOUND(InData%F_L,1), UBOUND(InData%F_L,1) + ReKiBuf(Re_Xferred) = InData%F_L(i1) Re_Xferred = Re_Xferred + 1 END DO END IF @@ -6557,21 +6557,21 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) OutData%udotdot_TP(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! UFL not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F_L not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 i1_l = IntKiBuf( Int_Xferred ) i1_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%UFL)) DEALLOCATE(OutData%UFL) - ALLOCATE(OutData%UFL(i1_l:i1_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%F_L)) DEALLOCATE(OutData%F_L) + ALLOCATE(OutData%F_L(i1_l:i1_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%UFL.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F_L.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i1 = LBOUND(OutData%UFL,1), UBOUND(OutData%UFL,1) - OutData%UFL(i1) = ReKiBuf(Re_Xferred) + DO i1 = LBOUND(OutData%F_L,1), UBOUND(OutData%F_L,1) + OutData%F_L(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END IF From e2c47939a213db474a0900e34e7938b451e3f8aa Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 15 Dec 2020 22:56:46 -0700 Subject: [PATCH 331/377] FlexSub: Option to rotate loads (in OutCosm) --- modules/subdyn/src/SubDyn.f90 | 24 ++++++++++++++++++------ modules/subdyn/src/SubDyn_Registry.txt | 1 + modules/subdyn/src/SubDyn_Types.f90 | 7 +++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 79615b870..b5230cced 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -280,6 +280,16 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') endif endif + if (p%RotateLoads) then + if (p%Floating) then + call WrScr(' >>> Loads will be rotated (floating and OutCosM=True))') + else + call WrScr(' >>> Loads will not be rotated (fixed bottom)') + p%RotateLoads=.false. + endif + else + call WrScr(' >>> Loads will not be rotated (OutCosM=False)') + endif ! --- Craig-Bampton reduction (sets many parameters) CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -479,7 +489,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- ! External force on internal nodes (F_L) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -683,7 +693,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF( u, p, m, .false., m%F_L, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF( u, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2 ); ! State equation dxdt%qm= x%qmdot @@ -1122,6 +1132,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +! TEMPORARY HACK +p%RotateLoads=Init%OutCOSM !Store an integer version of it p%OutAllInt= 1 IF ( .NOT. p%OutAll ) p%OutAllInt= 0 @@ -1680,12 +1692,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., m%F_L, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2); ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., F_L2, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, p%RotateLoads, F_L2, ErrStat2, ErrMsg2); ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2863,11 +2875,11 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg endif if (p%ExtraMoment) then - ! TODO modify for floating if (p%Floating) then + ! TODO deactivate for floating ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion - Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) m%DU_full = 0.0_ReKi + Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) do iNode = 1,p%nNodes rIP0(1:3) = p%DP0(1:3, iNode) ! vector interface->node at t=0 rIP(1:3) = matmul(Rot, rIP0) ! vector interface->node at t diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 5e686c602..3af5e8215 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -188,6 +188,7 @@ typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of fr typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" +typedef ^ ParameterType Logical RotateLoads - - - "Temporary, rotate loads" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4262c2c8f..9945f91e8 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -235,6 +235,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] LOGICAL :: Floating !< True if floating bottom (the 6 DOF are free at all reaction nodes) [-] + LOGICAL :: RotateLoads !< Temporary, rotate loads [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -7089,6 +7090,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment DstParamData%Floating = SrcParamData%Floating + DstParamData%RotateLoads = SrcParamData%RotateLoads IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) i1_u = UBOUND(SrcParamData%KMMDiag,1) @@ -8118,6 +8120,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment Int_BufSz = Int_BufSz + 1 ! Floating + Int_BufSz = Int_BufSz + 1 ! RotateLoads Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN Int_BufSz = Int_BufSz + 2*1 ! KMMDiag upper/lower bounds for each dimension @@ -8782,6 +8785,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%Floating, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateLoads, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10195,6 +10200,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%Floating = TRANSFER(IntKiBuf(Int_Xferred), OutData%Floating) Int_Xferred = Int_Xferred + 1 + OutData%RotateLoads = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateLoads) + Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE From 957d504036e7f912962c988fe13b2de7ce905203 Mon Sep 17 00:00:00 2001 From: Greg Hayman Date: Wed, 16 Dec 2020 13:22:11 -0700 Subject: [PATCH 332/377] Fixed indexing bug when setting InitOut data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit n the modified code lines, the data on the left side of the equal sign is allocated from 0:NStepWave because the NStepWave element is the ‘wrapped’ value (it ends up being set to the 0th element value) further down in the code. The data on the right side of the equal sign is allocated from 0:NStepWave-1 because it is intermediate data and does not require the ‘wrapped’ element. --- modules/hydrodyn/src/Waves.f90 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/hydrodyn/src/Waves.f90 b/modules/hydrodyn/src/Waves.f90 index 462874179..de6958b00 100644 --- a/modules/hydrodyn/src/Waves.f90 +++ b/modules/hydrodyn/src/Waves.f90 @@ -1939,13 +1939,14 @@ SUBROUTINE VariousWaves_Init ( InitInp, InitOut, ErrStat, ErrMsg ) ELSE ! The elevation of the point defined by WaveKinzi(J) must lie between the seabed and the mean sea level (inclusive) - InitOut%WaveDynP(:,J ) = WaveDynP0B(:,K) - InitOut%WaveVel (:,J,1) = WaveVel0Hxi(:,K) - InitOut%WaveVel (:,J,2) = WaveVel0Hyi(:,K) - InitOut%WaveVel (:,J,3) = WaveVel0V(:,K) - InitOut%WaveAcc (:,J,1) = WaveAcc0Hxi(:,K) - InitOut%WaveAcc (:,J,2) = WaveAcc0Hyi(:,K) - InitOut%WaveAcc (:,J,3) = WaveAcc0V(:,K) + InitOut%WaveDynP(0:InitOut%NStepWave-1,J ) = WaveDynP0B(:,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,1) = WaveVel0Hxi(:,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,2) = WaveVel0Hyi(:,K) + InitOut%WaveVel (0:InitOut%NStepWave-1,J,3) = WaveVel0V(:,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,1) = WaveAcc0Hxi(:,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,2) = WaveAcc0Hyi(:,K) + InitOut%WaveAcc (0:InitOut%NStepWave-1,J,3) = WaveAcc0V(:,K) + K = K + 1 END IF From 4c0657286bf78218d7546d62d1db94286ddba965 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 16 Dec 2020 18:38:07 -0700 Subject: [PATCH 333/377] Temporary new Y1 --- modules/subdyn/src/SD_FEM.f90 | 53 +++++- modules/subdyn/src/SubDyn.f90 | 165 ++++++++++++---- modules/subdyn/src/SubDyn_Registry.txt | 4 + modules/subdyn/src/SubDyn_Types.f90 | 252 +++++++++++++++++++++++++ 4 files changed, 440 insertions(+), 34 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index d368995a4..2475f9498 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1006,7 +1006,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K + INTEGER :: I, J, K, ie INTEGER :: iGlob REAL(FEKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector REAL(FEKi) :: FCe(12) ! Pretension force from cable element @@ -1083,6 +1083,57 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) iGlob = p%NodesDOF(iNode)%List(3) ! uz p%FG(iGlob) = p%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO + + ! --- Compute Stiffness matrix of interface nodes + ! TODO TODO for now only one node + if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then + CALL AllocAry( p%K_I2, 6, 6 , 'p%K_I2' , ErrStat2, ErrMsg2); if(Failed()) return; + CALL AllocAry( p%Nodes_I2, 1, 'p%Nodes_I2' , ErrStat2, ErrMsg2); if(Failed()) return; + !DO I = 1, p%nNodes_I + i=1 + print*,'---------------------------------------------------' + if (size(p%Nodes_I,1)>1) then + print*,'>>> Cannot have more than one interface node for now' + STOP + endif + print*,'Interface Node',p%Nodes_I(1,1) + iNode = INT(p%Nodes_I(i, 1)) + if ( Init%NodesConnE(iNode, 1)>1 ) then + print*,'>>> Cannot have more than one member connected to interface node' + STOP + endif + print*,'Elements connected to interface Node',Init%NodesConnE(iNode, 2:4) + ie = Init%NodesConnE(iNode, 2) + print*,'Interface Element ',ie + print*,'Interface Element Nodes',p%Elems(ie,2:3) + CALL ElemK(p%ElemProps(ie), Ke) + + if (p%Elems(ie, 2)==iNode) then + p%Nodes_I2(1) = p%Elems(ie, 3) + p%K_I2 = Ke(7:12,7:12) + + else if (p%Elems(ie, 3)==iNode) then + p%Nodes_I2(1) = p%Elems(ie, 2) + p%K_I2 = Ke(1:6,1:6) + else + print*,'>>> One of the two nodes should be ',iNode + STOP + endif + print*,'Interface Node ',iNode + print*,'Interface Second Node ',p%Nodes_I2(1) + print*,'Interface elemprop',p%ElemProps(ie)%rho, p%ElemProps(ie)%Length + print*,'Stiffness matrix for second interface node (first element) ' + print*,'K ',p%K_I2(1,:) + print*,'K ',p%K_I2(2,:) + print*,'K ',p%K_I2(3,:) + print*,'K ',p%K_I2(4,:) + print*,'K ',p%K_I2(5,:) + print*,'K ',p%K_I2(6,:) + print*,'---------------------------------------------------' + + endif + + CALL CleanUp_AssembleKM() diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index b5230cced..58188bbdc 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -427,7 +427,13 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method + REAL(ReKi) :: ULS_I2(6) ! TODO 6*nDOFI REAL(ReKi) :: Y1(6) + REAL(ReKi) :: Y1_CB(6) + REAL(ReKi) :: Y1_CB_L(6) + REAL(ReKi) :: Y1_Guy_R(6) + REAL(ReKi) :: Y1_Guy_L(6) + REAL(ReKi) :: Y1_Utp(6) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF @@ -443,6 +449,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) real(ReKi), dimension(3) :: vP ! Rigid-body velocity of node real(ReKi), dimension(3) :: aP ! Rigid-body acceleration of node real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) + real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates + real(R8Ki), dimension(3,3) :: Rb2g ! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None ! Initialize ErrStat @@ -455,35 +463,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - - ! -------------------------------------------------------------------------------- - ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) - ! -------------------------------------------------------------------------------- - ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return - call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) - ! Compute reaction/coupling force at TP - if ( p%nDOFM > 0) then - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - - matmul( F_I, p%TI ) ) - else ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - - matmul( F_I, p%TI ) ) - end if - ! Computing extra moments due to lever arm introduced by interface displacement - ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs - if (p%ExtraMoment) then - if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment - endif - endif - ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces - y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) + Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates + Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) ! -------------------------------------------------------------------------------- ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) @@ -497,21 +478,21 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dot = 0.0_ReKi m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) - IF ( p%nDOFM > 0) THEN + if ( p%nDOFM > 0) then m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%F_L ) - END IF + end if ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then FLt = MATMUL(p%PhiL_T , m%F_L) ! NOTE: Gravity in F_L ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - m%UL = m%UL + ULS if ( p%nDOFM > 0) then UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) - m%UL = m%UL - UL0M + ULS = ULS-UL0M end if + m%UL = m%UL + ULS endif ! --- Adding Guyan contribution to R and L DOFs if (.not.p%Floating) then @@ -604,6 +585,115 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) enddo endif + + + ! -------------------------------------------------------------------------------- + ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) + ! -------------------------------------------------------------------------------- + ! Compute external force on internal (F_L) and interface nodes (F_I) + call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return + call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) + ! Compute reaction/coupling force at TP + if ( p%nDOFM > 0) then + Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & + + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + else ! No retained modes, so there are no states + Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + end if + print*,'-----------------------' + print*,'UTP ',m%u_TP + print*,'-----------------------' + print*,'Y1 old2 ',Y1 + + Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) ) + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) + if ( p%nDOFM > 0) then + Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) + else + Y1_CB = 0.0_ReKi + endif + Y1_Guy_R = matmul( F_I, p%TI ) + Y1_Guy_L = - matmul(p%D1_142, m%F_L) + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R + print*,'-----------------------' + print*,'Split terms (old)' + print*,'Y1 UtP ',Y1_Utp + print*,'Y1 GR ',Y1_Guy_R + print*,'Y1 CB ',Y1_CB + print*,'Y1 CBL ',Y1_CB_L + print*,'Y1 GL old',Y1_Guy_L + print*,'Y1 old ',Y1 + + if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then + m%U_red(:) = 0.0_ReKi + m%U_red(p%ID__L) = ULS + + iSDNode = p%Nodes_I2(1) ! Second node of interface element + DOFList => p%NodesDOF(iSDNode)%List + ULS_I2 = m%U_red(p%ID__L) + + + Y1_Guy_L = matmul( p%K_I2 , ULS_I2) + print*,'ULS ',ULS_I2 + print*,'-----------------------' + print*,'Split terms (new)' + print*,'Y1 UtP ',Y1_Utp + print*,'Y1 GR ',Y1_Guy_R + print*,'Y1 CB ',Y1_CB + print*,'Y1 CBL ',Y1_CB_L + print*,'Y1 GL new ',Y1_Guy_L + Y1_Guy_L(1:3) = matmul(Rb2g,Y1_Guy_L(1:3)) + Y1_Guy_L(4:6) = matmul(Rb2g,Y1_Guy_L(4:6)) + + Y1_CB(1:3) = matmul(Rb2g,Y1_CB(1:3)) + Y1_CB(4:6) = matmul(Rb2g,Y1_CB(4:6)) + Y1_CB_L(1:3) = matmul(Rb2g,Y1_CB_L(1:3)) + Y1_CB_L(4:6) = matmul(Rb2g,Y1_CB_L(4:6)) + print*,'Y1 GL rot ',Y1_Guy_L + print*,'Y1 CB rot',Y1_CB + print*,'Y1 CBLrot',Y1_CB_L + + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R + print*,'Y1 new',Y1 + else + + Y1_Guy_L = - matmul(p%D1_142, m%F_L) + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R + !if ( p%nDOFM > 0) then + ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & + ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !else ! No retained modes, so there are no states + ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !end if + endif + print*,'' + !if ( p%nDOFM > 0) then + ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & + ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !else ! No retained modes, so there are no states + ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !end if + + ! Computing extra moments due to lever arm introduced by interface displacement + ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs + if (p%ExtraMoment) then + if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif + endif + ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces + y%Y1Mesh%Force (:,1) = Y1(1:3) + y%Y1Mesh%Moment(:,1) = Y1(4:6) + !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE @@ -2445,6 +2535,11 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PhiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 + ! --- Intermediates D1_14 = D1_141 + D1_142 + p%D1_141 = MATMUL(p%MBM, TRANSPOSE(p%PhiM)) + !CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, 0.0_ReKi, p%D1_141, ErrStat2, ErrMsg2 ); if(Failed()) return + p%D1_142 =- MATMUL(TI_transpose, TRANSPOSE(PhiRb)) + ! C2_21, C2_42 ! C2_61, C2_62 @@ -2499,6 +2594,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, p%D1_12 = p%CBB ! No cross couplings p%D1_13 = p%MBB ! No cross couplings p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + p%D1_141 = 0.0_ReKi + p%D1_142 = - MATMUL(TI_transpose, TRANSPOSE(PhiRb)) END IF CONTAINS @@ -2528,6 +2625,8 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_141, nDOFL_TP, p%nDOF__L,'p%D1_141', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_142, nDOFL_TP, p%nDOF__L,'p%D1_142', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 3af5e8215..ac7aade24 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -197,6 +197,10 @@ typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1 typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" +typedef ^ ParameterType ReKi D1_141 {:}{:} - - "MBm PhiM^T" +typedef ^ ParameterType ReKi D1_142 {:}{:} - - "TI^T PhiR^T" +typedef ^ ParameterType ReKi K_I2 {:}{:} - - "Stiffness matrix of I2 nodes" +typedef ^ ParameterType IntKi Nodes_I2 {:} - - "I2 node indices" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 9945f91e8..b2ad03183 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -244,6 +244,10 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_141 !< MBm PhiM^T [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_142 !< TI^T PhiR^T [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K_I2 !< Stiffness matrix of I2 nodes [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Nodes_I2 !< I2 node indices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] @@ -7199,6 +7203,60 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D1_14 = SrcParamData%D1_14 ENDIF +IF (ALLOCATED(SrcParamData%D1_141)) THEN + i1_l = LBOUND(SrcParamData%D1_141,1) + i1_u = UBOUND(SrcParamData%D1_141,1) + i2_l = LBOUND(SrcParamData%D1_141,2) + i2_u = UBOUND(SrcParamData%D1_141,2) + IF (.NOT. ALLOCATED(DstParamData%D1_141)) THEN + ALLOCATE(DstParamData%D1_141(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_141.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_141 = SrcParamData%D1_141 +ENDIF +IF (ALLOCATED(SrcParamData%D1_142)) THEN + i1_l = LBOUND(SrcParamData%D1_142,1) + i1_u = UBOUND(SrcParamData%D1_142,1) + i2_l = LBOUND(SrcParamData%D1_142,2) + i2_u = UBOUND(SrcParamData%D1_142,2) + IF (.NOT. ALLOCATED(DstParamData%D1_142)) THEN + ALLOCATE(DstParamData%D1_142(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_142.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_142 = SrcParamData%D1_142 +ENDIF +IF (ALLOCATED(SrcParamData%K_I2)) THEN + i1_l = LBOUND(SrcParamData%K_I2,1) + i1_u = UBOUND(SrcParamData%K_I2,1) + i2_l = LBOUND(SrcParamData%K_I2,2) + i2_u = UBOUND(SrcParamData%K_I2,2) + IF (.NOT. ALLOCATED(DstParamData%K_I2)) THEN + ALLOCATE(DstParamData%K_I2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%K_I2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%K_I2 = SrcParamData%K_I2 +ENDIF +IF (ALLOCATED(SrcParamData%Nodes_I2)) THEN + i1_l = LBOUND(SrcParamData%Nodes_I2,1) + i1_u = UBOUND(SrcParamData%Nodes_I2,1) + IF (.NOT. ALLOCATED(DstParamData%Nodes_I2)) THEN + ALLOCATE(DstParamData%Nodes_I2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_I2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%Nodes_I2 = SrcParamData%Nodes_I2 +ENDIF IF (ALLOCATED(SrcParamData%PhiM)) THEN i1_l = LBOUND(SrcParamData%PhiM,1) i1_u = UBOUND(SrcParamData%PhiM,1) @@ -7834,6 +7892,18 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D1_14)) THEN DEALLOCATE(ParamData%D1_14) ENDIF +IF (ALLOCATED(ParamData%D1_141)) THEN + DEALLOCATE(ParamData%D1_141) +ENDIF +IF (ALLOCATED(ParamData%D1_142)) THEN + DEALLOCATE(ParamData%D1_142) +ENDIF +IF (ALLOCATED(ParamData%K_I2)) THEN + DEALLOCATE(ParamData%K_I2) +ENDIF +IF (ALLOCATED(ParamData%Nodes_I2)) THEN + DEALLOCATE(ParamData%Nodes_I2) +ENDIF IF (ALLOCATED(ParamData%PhiM)) THEN DEALLOCATE(ParamData%PhiM) ENDIF @@ -8161,6 +8231,26 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 END IF + Int_BufSz = Int_BufSz + 1 ! D1_141 allocated yes/no + IF ( ALLOCATED(InData%D1_141) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_141 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_141) ! D1_141 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_142 allocated yes/no + IF ( ALLOCATED(InData%D1_142) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_142 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_142) ! D1_142 + END IF + Int_BufSz = Int_BufSz + 1 ! K_I2 allocated yes/no + IF ( ALLOCATED(InData%K_I2) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! K_I2 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%K_I2) ! K_I2 + END IF + Int_BufSz = Int_BufSz + 1 ! Nodes_I2 allocated yes/no + IF ( ALLOCATED(InData%Nodes_I2) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Nodes_I2 upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%Nodes_I2) ! Nodes_I2 + END IF Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no IF ( ALLOCATED(InData%PhiM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension @@ -8937,6 +9027,81 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF + IF ( .NOT. ALLOCATED(InData%D1_141) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_141,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_141,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_141,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_141,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D1_141,2), UBOUND(InData%D1_141,2) + DO i1 = LBOUND(InData%D1_141,1), UBOUND(InData%D1_141,1) + ReKiBuf(Re_Xferred) = InData%D1_141(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D1_142) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_142,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_142,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_142,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_142,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D1_142,2), UBOUND(InData%D1_142,2) + DO i1 = LBOUND(InData%D1_142,1), UBOUND(InData%D1_142,1) + ReKiBuf(Re_Xferred) = InData%D1_142(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%K_I2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K_I2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K_I2,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%K_I2,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K_I2,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%K_I2,2), UBOUND(InData%K_I2,2) + DO i1 = LBOUND(InData%K_I2,1), UBOUND(InData%K_I2,1) + ReKiBuf(Re_Xferred) = InData%K_I2(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Nodes_I2) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I2,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I2,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Nodes_I2,1), UBOUND(InData%Nodes_I2,1) + IntKiBuf(Int_Xferred) = InData%Nodes_I2(i1) + Int_Xferred = Int_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%PhiM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10376,6 +10541,93 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_141 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_141)) DEALLOCATE(OutData%D1_141) + ALLOCATE(OutData%D1_141(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_141.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D1_141,2), UBOUND(OutData%D1_141,2) + DO i1 = LBOUND(OutData%D1_141,1), UBOUND(OutData%D1_141,1) + OutData%D1_141(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_142 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_142)) DEALLOCATE(OutData%D1_142) + ALLOCATE(OutData%D1_142(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_142.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D1_142,2), UBOUND(OutData%D1_142,2) + DO i1 = LBOUND(OutData%D1_142,1), UBOUND(OutData%D1_142,1) + OutData%D1_142(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K_I2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%K_I2)) DEALLOCATE(OutData%K_I2) + ALLOCATE(OutData%K_I2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K_I2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%K_I2,2), UBOUND(OutData%K_I2,2) + DO i1 = LBOUND(OutData%K_I2,1), UBOUND(OutData%K_I2,1) + OutData%K_I2(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I2 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Nodes_I2)) DEALLOCATE(OutData%Nodes_I2) + ALLOCATE(OutData%Nodes_I2(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I2.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Nodes_I2,1), UBOUND(OutData%Nodes_I2,1) + OutData%Nodes_I2(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM not allocated Int_Xferred = Int_Xferred + 1 ELSE From b14e412c4bff6500238ca30f50114d9591d35b9f Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 17 Dec 2020 14:02:42 -0700 Subject: [PATCH 334/377] Using proper submatrix and displacements --- modules/subdyn/src/SD_FEM.f90 | 6 +- modules/subdyn/src/SubDyn.f90 | 54 +++++++---- modules/subdyn/src/SubDyn_Output.f90 | 37 ++++++-- modules/subdyn/src/SubDyn_Registry.txt | 4 +- modules/subdyn/src/SubDyn_Types.f90 | 120 +++++++++++++++++++++++-- 5 files changed, 187 insertions(+), 34 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 2475f9498..1ab5fcead 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1110,11 +1110,11 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) if (p%Elems(ie, 2)==iNode) then p%Nodes_I2(1) = p%Elems(ie, 3) - p%K_I2 = Ke(7:12,7:12) + p%K_I2 = Ke(1:6,7:12) else if (p%Elems(ie, 3)==iNode) then p%Nodes_I2(1) = p%Elems(ie, 2) - p%K_I2 = Ke(1:6,1:6) + p%K_I2 = Ke(7:12,1:6) else print*,'>>> One of the two nodes should be ',iNode STOP @@ -1133,8 +1133,6 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) endif - - CALL CleanUp_AssembleKM() CONTAINS diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 58188bbdc..c9775f239 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -603,6 +603,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) end if print*,'-----------------------' + print*,'t ',t print*,'UTP ',m%u_TP print*,'-----------------------' print*,'Y1 old2 ',Y1 @@ -627,36 +628,49 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) print*,'Y1 old ',Y1 if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then - m%U_red(:) = 0.0_ReKi - m%U_red(p%ID__L) = ULS - + ! --- Going from flatten DOFs to reduced DOFs, to full DOFs... + ! NOTE: this is only needed for the few DOFs below the interface + ! so this could be greatly optimized with the mapping computed at init only.. + ! TODO... + m%U_red_SIM(:) = 0.0_ReKi + m%U_red_SIM(p%ID__L) = ULS ! Only the static contribution + if (p%reduced) then + m%U_full_SIM = matmul(p%T_red, m%U_red_SIM) + else + m%U_full_SIM = m%U_red_SIM + endif iSDNode = p%Nodes_I2(1) ! Second node of interface element DOFList => p%NodesDOF(iSDNode)%List - ULS_I2 = m%U_red(p%ID__L) - - - Y1_Guy_L = matmul( p%K_I2 , ULS_I2) - print*,'ULS ',ULS_I2 + ULS_I2 = m%U_full_SIM(DOFList(1:6)) + !print*,'NODE',iSDNode + !print*,'DOFLIST',DOFLIST + !print*,'DOFLIST', p%NodesDOF(p%Elems(1,2))%List(1:6) + !print*,'DOFLIST', p%NodesDOF(p%Elems(1,3))%List(1:6) + Y1_Guy_L = - matmul( p%K_I2 , ULS_I2) + print*,'ULs ',ULS_I2 + print*,'ULe ',m%U_full_elast(DOFList) + if (any(ULS_I2>2)) then + STOP + endif print*,'-----------------------' print*,'Split terms (new)' print*,'Y1 UtP ',Y1_Utp print*,'Y1 GR ',Y1_Guy_R print*,'Y1 CB ',Y1_CB print*,'Y1 CBL ',Y1_CB_L - print*,'Y1 GL new ',Y1_Guy_L + print*,'Y1 GL new',Y1_Guy_L Y1_Guy_L(1:3) = matmul(Rb2g,Y1_Guy_L(1:3)) Y1_Guy_L(4:6) = matmul(Rb2g,Y1_Guy_L(4:6)) - Y1_CB(1:3) = matmul(Rb2g,Y1_CB(1:3)) Y1_CB(4:6) = matmul(Rb2g,Y1_CB(4:6)) Y1_CB_L(1:3) = matmul(Rb2g,Y1_CB_L(1:3)) Y1_CB_L(4:6) = matmul(Rb2g,Y1_CB_L(4:6)) - print*,'Y1 GL rot ',Y1_Guy_L + print*,'Y1 GL rot',Y1_Guy_L print*,'Y1 CB rot',Y1_CB print*,'Y1 CBLrot',Y1_CB_L Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R - print*,'Y1 new',Y1 + print*,'Y1 new',Y1 else Y1_Guy_L = - matmul(p%D1_142, m%F_L) @@ -670,7 +684,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) !end if endif - print*,'' + print*,'-----------------------' + print*,'FileOutputs' !if ( p%nDOFM > 0) then ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & @@ -737,7 +752,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END DO m%LastOutTime = t ENDIF - + print*,'' CONTAINS LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') @@ -2675,9 +2690,14 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%U_full_elast, p%nDOF, 'U_full_elast', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red, p%nDOF_red, 'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dot, p%nDOF_red, 'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red, 'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + +if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then + CALL AllocAry( Misc%U_full_SIM, p%nDOF, 'U_full_SIM', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_SIM, p%nDOF_red, 'U_red_SIM', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') +endif CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 88b05b9be..077aba9d4 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -277,7 +277,7 @@ SUBROUTINE SDOut_MapOutputs(u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) !locals integer(IntKi) :: iMemberOutput, iiNode, iSDNode, iMeshNode, I, J, L, L2 ! Counters integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM - real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments + real(ReKi), dimension (6) :: FM_elm, FK_elm, FK_elm1, FK_elm3, Fext !output static and dynamic forces and moments real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments real(FEKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions @@ -300,18 +300,28 @@ SUBROUTINE SDOut_MapOutputs(u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member ! --- Forces (potentially averaged on 2 elements) - call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) + FK_elm1=0 + FK_elm2=0 + FK_elm3=0 + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm1, sgn, DIRCOS, .false.) FM_elm2=sgn*FM_elm - FK_elm2=sgn*FK_elm + FK_elm1=sgn*FK_elm1 IF (pLst%ElmIDs(iiNode,2) .NE. 0) THEN ! Second element exist ! NOTE: forces are computed in the coordinate system of the first element for averaging - call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above + call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm2, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average - FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average + FK_elm3=0.5*( FK_elm1 + sgn*FK_elm2) ! Now Average + else + FK_elm3=FK_elm1 ENDIF ! Static (elastic) component of reaction forces and moments at MαNβ along local member coordinate system ! "MαNβFKxe, MαNβFKye, MαNβFKze, MαNβMKxe, MαNβMKye, MαNβMKze" - AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref + AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm3 !static forces and moments (6) Local Ref + if (pLst%ElmIDs(iiNode,1)==1) then + print*,'CalcO FK1',FK_elm1 + print*,'CalcO FK2',FK_elm2 + print*,'CalcO FK3',FK_elm3 + endif ! Dynamic (inertial) component of reaction forces and moments at MαNβ along local member coordinate system ! "MαNβFMxe, MαNβFMye, MαNβFMze, MαNβMMxe, MαNβMMye, MαNβMMze" AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref @@ -442,6 +452,21 @@ subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInput DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local endif CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,JJ),pLst%Ke(:,:,iiNode,JJ), Xdd_e, X_e, pLst%Fg(:,iiNode,JJ), FirstOrSecond, FM_elm, FK_elm) + if (iElem==1) then + ! print*,'K',pLst%Ke(1,7:12,iiNode,JJ) + ! print*,'K',pLst%Ke(2,7:12,iiNode,JJ) + ! print*,'K',pLst%Ke(3,7:12,iiNode,JJ) + ! print*,'K',pLst%Ke(4,7:12,iiNode,JJ) + ! print*,'K',pLst%Ke(5,7:12,iiNode,JJ) + ! print*,'K',pLst%Ke(6,7:12,iiNode,JJ) + print*,'CalcODC1',DIRCOS(1,:) + print*,'CalcODC2',DIRCOS(2,:) + print*,'CalcODC3',DIRCOS(3,:) + print*,'First ?', FirstOrSecond,sgn + print*,'CalcO U ',X_e(1:6) + print*,'CalcO U ',X_e(7:12) + print*,'ClacO FK',FK_elm + endif end subroutine ElementForce !==================================================================================================== diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index ac7aade24..fc35b484b 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -153,6 +153,8 @@ typedef ^ MiscVarType ReKi U_full_elast {:} - - "Elastic di typedef ^ MiscVarType ReKi U_red {:} - - typedef ^ MiscVarType ReKi U_red_dot {:} - - typedef ^ MiscVarType ReKi U_red_dotdot {:} - - +typedef ^ MiscVarType ReKi U_red_SIM {:} - - "Static Solve contribution to U, reduced system" +typedef ^ MiscVarType ReKi U_full_SIM {:} - - "Static Solve contribution to U, full system" typedef ^ MiscVarType ReKi FC_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N typedef ^ MiscVarType ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ MiscVarType DbKi LastOutTime - - - "The time of the most recent stored output data" "s" @@ -199,7 +201,7 @@ typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotd typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" typedef ^ ParameterType ReKi D1_141 {:}{:} - - "MBm PhiM^T" typedef ^ ParameterType ReKi D1_142 {:}{:} - - "TI^T PhiR^T" -typedef ^ ParameterType ReKi K_I2 {:}{:} - - "Stiffness matrix of I2 nodes" +typedef ^ ParameterType R8Ki K_I2 {:}{:} - - "Stiffness matrix of I2 nodes" typedef ^ ParameterType IntKi Nodes_I2 {:} - - "I2 node indices" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index b2ad03183..70fd93b6f 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -204,6 +204,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_SIM !< Static Solve contribution to U, reduced system [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_SIM !< Static Solve contribution to U, full system [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_unit !< Cable Force vector (for varying cable load, of unit cable load) [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] @@ -246,7 +248,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_141 !< MBm PhiM^T [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_142 !< TI^T PhiR^T [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: K_I2 !< Stiffness matrix of I2 nodes [-] + REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: K_I2 !< Stiffness matrix of I2 nodes [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Nodes_I2 !< I2 node indices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] @@ -5891,6 +5893,30 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot ENDIF +IF (ALLOCATED(SrcMiscData%U_red_SIM)) THEN + i1_l = LBOUND(SrcMiscData%U_red_SIM,1) + i1_u = UBOUND(SrcMiscData%U_red_SIM,1) + IF (.NOT. ALLOCATED(DstMiscData%U_red_SIM)) THEN + ALLOCATE(DstMiscData%U_red_SIM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_SIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_red_SIM = SrcMiscData%U_red_SIM +ENDIF +IF (ALLOCATED(SrcMiscData%U_full_SIM)) THEN + i1_l = LBOUND(SrcMiscData%U_full_SIM,1) + i1_u = UBOUND(SrcMiscData%U_full_SIM,1) + IF (.NOT. ALLOCATED(DstMiscData%U_full_SIM)) THEN + ALLOCATE(DstMiscData%U_full_SIM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_SIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%U_full_SIM = SrcMiscData%U_full_SIM +ENDIF IF (ALLOCATED(SrcMiscData%FC_unit)) THEN i1_l = LBOUND(SrcMiscData%FC_unit,1) i1_u = UBOUND(SrcMiscData%FC_unit,1) @@ -6000,6 +6026,12 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%U_red_dotdot)) THEN DEALLOCATE(MiscData%U_red_dotdot) ENDIF +IF (ALLOCATED(MiscData%U_red_SIM)) THEN + DEALLOCATE(MiscData%U_red_SIM) +ENDIF +IF (ALLOCATED(MiscData%U_full_SIM)) THEN + DEALLOCATE(MiscData%U_full_SIM) +ENDIF IF (ALLOCATED(MiscData%FC_unit)) THEN DEALLOCATE(MiscData%FC_unit) ENDIF @@ -6132,6 +6164,16 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot END IF + Int_BufSz = Int_BufSz + 1 ! U_red_SIM allocated yes/no + IF ( ALLOCATED(InData%U_red_SIM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_red_SIM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_red_SIM) ! U_red_SIM + END IF + Int_BufSz = Int_BufSz + 1 ! U_full_SIM allocated yes/no + IF ( ALLOCATED(InData%U_full_SIM) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! U_full_SIM upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%U_full_SIM) ! U_full_SIM + END IF Int_BufSz = Int_BufSz + 1 ! FC_unit allocated yes/no IF ( ALLOCATED(InData%FC_unit) ) THEN Int_BufSz = Int_BufSz + 2*1 ! FC_unit upper/lower bounds for each dimension @@ -6433,6 +6475,36 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%U_red_SIM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_SIM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_SIM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%U_red_SIM,1), UBOUND(InData%U_red_SIM,1) + ReKiBuf(Re_Xferred) = InData%U_red_SIM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%U_full_SIM) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_SIM,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_SIM,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%U_full_SIM,1), UBOUND(InData%U_full_SIM,1) + ReKiBuf(Re_Xferred) = InData%U_full_SIM(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%FC_unit) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6832,6 +6904,42 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_SIM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_red_SIM)) DEALLOCATE(OutData%U_red_SIM) + ALLOCATE(OutData%U_red_SIM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_SIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%U_red_SIM,1), UBOUND(OutData%U_red_SIM,1) + OutData%U_red_SIM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_SIM not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%U_full_SIM)) DEALLOCATE(OutData%U_full_SIM) + ALLOCATE(OutData%U_full_SIM(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_SIM.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%U_full_SIM,1), UBOUND(OutData%U_full_SIM,1) + OutData%U_full_SIM(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_unit not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -8244,7 +8352,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! K_I2 allocated yes/no IF ( ALLOCATED(InData%K_I2) ) THEN Int_BufSz = Int_BufSz + 2*2 ! K_I2 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%K_I2) ! K_I2 + Db_BufSz = Db_BufSz + SIZE(InData%K_I2) ! K_I2 END IF Int_BufSz = Int_BufSz + 1 ! Nodes_I2 allocated yes/no IF ( ALLOCATED(InData%Nodes_I2) ) THEN @@ -9082,8 +9190,8 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si DO i2 = LBOUND(InData%K_I2,2), UBOUND(InData%K_I2,2) DO i1 = LBOUND(InData%K_I2,1), UBOUND(InData%K_I2,1) - ReKiBuf(Re_Xferred) = InData%K_I2(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%K_I2(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -10605,8 +10713,8 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END IF DO i2 = LBOUND(OutData%K_I2,2), UBOUND(OutData%K_I2,2) DO i1 = LBOUND(OutData%K_I2,1), UBOUND(OutData%K_I2,1) - OutData%K_I2(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%K_I2(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF From 1e776ed7eac273a16e48fe6b7e193218c596b5db Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 17 Dec 2020 17:48:51 -0700 Subject: [PATCH 335/377] Rotatedload version working --- modules/subdyn/src/SubDyn.f90 | 89 ++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index c9775f239..41fa208a6 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -590,8 +590,11 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! -------------------------------------------------------------------------------- ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) ! -------------------------------------------------------------------------------- + + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) + ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2, DoExtraMoment=.True.); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP if ( p%nDOFM > 0) then @@ -602,21 +605,19 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) end if - print*,'-----------------------' print*,'t ',t print*,'UTP ',m%u_TP print*,'-----------------------' print*,'Y1 old2 ',Y1 Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) ) - Y1_CB_L = - (matmul(p%D1_141, m%F_L)) + Y1_Guy_L = - matmul(p%D1_142, m%F_L) if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) else Y1_CB = 0.0_ReKi endif Y1_Guy_R = matmul( F_I, p%TI ) - Y1_Guy_L = - matmul(p%D1_142, m%F_L) Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R print*,'-----------------------' print*,'Split terms (old)' @@ -632,42 +633,43 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! NOTE: this is only needed for the few DOFs below the interface ! so this could be greatly optimized with the mapping computed at init only.. ! TODO... - m%U_red_SIM(:) = 0.0_ReKi - m%U_red_SIM(p%ID__L) = ULS ! Only the static contribution - if (p%reduced) then - m%U_full_SIM = matmul(p%T_red, m%U_red_SIM) - else - m%U_full_SIM = m%U_red_SIM - endif - iSDNode = p%Nodes_I2(1) ! Second node of interface element - DOFList => p%NodesDOF(iSDNode)%List - ULS_I2 = m%U_full_SIM(DOFList(1:6)) - !print*,'NODE',iSDNode - !print*,'DOFLIST',DOFLIST - !print*,'DOFLIST', p%NodesDOF(p%Elems(1,2))%List(1:6) - !print*,'DOFLIST', p%NodesDOF(p%Elems(1,3))%List(1:6) - Y1_Guy_L = - matmul( p%K_I2 , ULS_I2) - print*,'ULs ',ULS_I2 - print*,'ULe ',m%U_full_elast(DOFList) - if (any(ULS_I2>2)) then - STOP - endif - print*,'-----------------------' - print*,'Split terms (new)' - print*,'Y1 UtP ',Y1_Utp - print*,'Y1 GR ',Y1_Guy_R - print*,'Y1 CB ',Y1_CB - print*,'Y1 CBL ',Y1_CB_L - print*,'Y1 GL new',Y1_Guy_L - Y1_Guy_L(1:3) = matmul(Rb2g,Y1_Guy_L(1:3)) - Y1_Guy_L(4:6) = matmul(Rb2g,Y1_Guy_L(4:6)) - Y1_CB(1:3) = matmul(Rb2g,Y1_CB(1:3)) - Y1_CB(4:6) = matmul(Rb2g,Y1_CB(4:6)) - Y1_CB_L(1:3) = matmul(Rb2g,Y1_CB_L(1:3)) - Y1_CB_L(4:6) = matmul(Rb2g,Y1_CB_L(4:6)) - print*,'Y1 GL rot',Y1_Guy_L - print*,'Y1 CB rot',Y1_CB - print*,'Y1 CBLrot',Y1_CB_L +! m%U_red_SIM(:) = 0.0_ReKi +! m%U_red_SIM(p%ID__L) = ULS ! Only the static contribution +! !m%U_red_SIM(p%ID__L) = m%UL ! Only the static contribution +! if (p%reduced) then +! m%U_full_SIM = matmul(p%T_red, m%U_red_SIM) +! else +! m%U_full_SIM = m%U_red_SIM +! endif +! iSDNode = p%Nodes_I2(1) ! Second node of interface element +! DOFList => p%NodesDOF(iSDNode)%List +! ULS_I2 = m%U_full_SIM(DOFList(1:6)) +! !print*,'NODE',iSDNode +! !print*,'DOFLIST',DOFLIST +! !print*,'DOFLIST', p%NodesDOF(p%Elems(1,2))%List(1:6) +! !print*,'DOFLIST', p%NodesDOF(p%Elems(1,3))%List(1:6) +! Y1_Guy_L = - matmul( p%K_I2 , ULS_I2) +! print*,'ULs ',ULS_I2 +! print*,'ULe ',m%U_full_elast(DOFList) +! if (any(ULS_I2>2)) then +! STOP +! endif +! print*,'-----------------------' +! print*,'Split terms (new)' +! print*,'Y1 UtP ',Y1_Utp +! print*,'Y1 GR ',Y1_Guy_R +! print*,'Y1 CB ',Y1_CB +! print*,'Y1 CBL ',Y1_CB_L +! print*,'Y1 GL new',Y1_Guy_L +! Y1_Guy_L(1:3) = matmul(Rb2g,Y1_Guy_L(1:3)) +! Y1_Guy_L(4:6) = matmul(Rb2g,Y1_Guy_L(4:6)) +! Y1_CB(1:3) = matmul(Rb2g,Y1_CB(1:3)) +! Y1_CB(4:6) = matmul(Rb2g,Y1_CB(4:6)) +! Y1_CB_L(1:3) = matmul(Rb2g,Y1_CB_L(1:3)) +! Y1_CB_L(4:6) = matmul(Rb2g,Y1_CB_L(4:6)) +! print*,'Y1 GL rot',Y1_Guy_L +! print*,'Y1 CB rot',Y1_CB +! print*,'Y1 CBLrot',Y1_CB_L Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R print*,'Y1 new',Y1 @@ -2962,7 +2964,7 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, DoExtraMoment ) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters logical , intent(in ) :: rotateLoads ! If true, loads are rotated to body coordinate @@ -2970,6 +2972,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + logical, intent(in ) ,optional :: DoExtraMoment integer :: iNode ! indices of u-mesh nodes and SD nodes integer :: nMembers integer :: startDOF, I @@ -2993,7 +2996,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates endif - if (p%ExtraMoment) then + if (p%ExtraMoment .or. present(DoExtraMoment)) then if (p%Floating) then ! TODO deactivate for floating ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion @@ -3072,7 +3075,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg endif ! Extra moment dm = Delta u x (fe + fg) - if (p%ExtraMoment) then + if (p%ExtraMoment .or. present(DoExtraMoment)) then du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) From 1ce8396b5ec7cec57a4b48ef9b87e296f4c30ec4 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 17 Dec 2020 18:50:18 -0700 Subject: [PATCH 336/377] FlexSub: rotating CB loads for floating with ExtraMom Guyan --- modules/subdyn/src/SubDyn.f90 | 155 ++++++++++++++----------- modules/subdyn/src/SubDyn_Registry.txt | 3 +- modules/subdyn/src/SubDyn_Types.f90 | 128 +++++++++++++++----- 3 files changed, 189 insertions(+), 97 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 79615b870..f5fef5569 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -274,8 +274,7 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return if (p%ExtraMoment) then if (p%Floating) then - ! TODO disallow - call WrScr(' Extra moment will be included in loads (free/floating case detected)') + call WrScr(' Extra moment for Guyan loads and rotated CB-frame will be used (floating case detected)') else call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') endif @@ -418,6 +417,11 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method REAL(ReKi) :: Y1(6) + REAL(ReKi) :: Y1_CB(6) + REAL(ReKi) :: Y1_CB_L(6) + REAL(ReKi) :: Y1_Guy_R(6) + REAL(ReKi) :: Y1_Guy_L(6) + REAL(ReKi) :: Y1_Utp(6) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF @@ -433,6 +437,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) real(ReKi), dimension(3) :: vP ! Rigid-body velocity of node real(ReKi), dimension(3) :: aP ! Rigid-body acceleration of node real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) + real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates + real(R8Ki), dimension(3,3) :: Rb2g ! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None ! Initialize ErrStat @@ -445,41 +451,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) m%udot_TP = (/u%TPMesh%TranslationVel( :,1), u%TPMesh%RotationVel(:,1)/) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - - ! -------------------------------------------------------------------------------- - ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) - ! -------------------------------------------------------------------------------- - ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return - call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) - ! Compute reaction/coupling force at TP - if ( p%nDOFM > 0) then - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - - matmul( F_I, p%TI ) ) - else ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) + matmul(p%D1_14, m%F_L) & - - matmul( F_I, p%TI ) ) - end if - ! Computing extra moments due to lever arm introduced by interface displacement - ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs - if (p%ExtraMoment) then - if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment - endif - endif - ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces - y%Y1Mesh%Force (:,1) = Y1(1:3) - y%Y1Mesh%Moment(:,1) = Y1(4:6) - + Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates + Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + ! -------------------------------------------------------------------------------- ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- ! External force on internal nodes (F_L) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -487,21 +466,21 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dot = 0.0_ReKi m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) - IF ( p%nDOFM > 0) THEN + if ( p%nDOFM > 0) then m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%F_L ) - END IF + end if ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then FLt = MATMUL(p%PhiL_T , m%F_L) ! NOTE: Gravity in F_L ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - m%UL = m%UL + ULS if ( p%nDOFM > 0) then UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) - m%UL = m%UL - UL0M + ULS = ULS-UL0M end if + m%UL = m%UL + ULS endif ! --- Adding Guyan contribution to R and L DOFs if (.not.p%Floating) then @@ -594,7 +573,56 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) enddo endif - + + ! -------------------------------------------------------------------------------- + ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) + ! -------------------------------------------------------------------------------- + ! --- Special case for floating with extramoment + if (p%ExtraMoment.and.p%Floating) then + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses rotated loads + endif + + ! Compute external force on internal (F_L) and interface nodes (F_I) + call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return + call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) + + ! Compute reaction/coupling force at TP + Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) ) + if ( p%nDOFM > 0) then + Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) + else + Y1_CB = 0.0_ReKi + endif + Y1_Guy_R = matmul( F_I, p%TI ) + Y1_Guy_L = - matmul(p%D1_142, m%F_L) + if (.not.(p%ExtraMoment.and.p%Floating)) then + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads + endif + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R + ! KEEP ME + !if ( p%nDOFM > 0) then + ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & + ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !else ! No retained modes, so there are no states + ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) + !end if + + ! Computing extra moments due to lever arm introduced by interface displacement + ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs + if (p%ExtraMoment) then + if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP + Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + endif + endif + ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces + y%Y1Mesh%Force (:,1) = Y1(1:3) + y%Y1Mesh%Moment(:,1) = Y1(4:6) + !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE !________________________________________ @@ -683,7 +711,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF( u, p, m, .false., m%F_L, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF( u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! State equation dxdt%qm= x%qmdot @@ -967,11 +995,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) enddo ! Trigger: determine if floating/fixed based on BCs and SSI file p%Floating = isFloating(Init,p) -!if (p%ExtraMoment .and. p%Floating) then -! call Fatal(' Error in file "'//TRIM(SDInputFile)//'": `ExtraMoment` cannot be true in a floating case') -! return -!endif - !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- @@ -1680,12 +1703,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., m%F_L, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, .false., F_L2, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2427,11 +2450,11 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) p%D1_13 = p%MBB - p%D1_13 - ! TODO cant use LAPACK due to type conversions FEKi->ReKi - !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PhiRb)) - p%D1_14 = MATMUL( TI_transpose, TRANSPOSE(PhiRb)) - !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PhiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 + ! --- Intermediates D1_14 = D1_141 + D1_142 + !p%D1_141 = MATMUL(p%MBM, TRANSPOSE(p%PhiM)) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, 0.0_ReKi, p%D1_141, ErrStat2, ErrMsg2 ); if(Failed()) return + ! NOTE: cant use LAPACK due to type conversions FEKi->ReKi + p%D1_142 =- MATMUL(TI_transpose, TRANSPOSE(PhiRb)) ! C2_21, C2_42 @@ -2486,7 +2509,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable p%D1_12 = p%CBB ! No cross couplings p%D1_13 = p%MBB ! No cross couplings - p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) + p%D1_141 = 0.0_ReKi + p%D1_142 = - MATMUL(TI_transpose, TRANSPOSE(PhiRb)) END IF CONTAINS @@ -2515,7 +2539,8 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%CBB, nDOFL_TP, nDOFL_TP, 'p%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_141, nDOFL_TP, p%nDOF__L,'p%D1_141', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') + CALL AllocAry( p%D1_142, nDOFL_TP, p%nDOF__L,'p%D1_142', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2564,9 +2589,9 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%U_full_elast, p%nDOF, 'U_full_elast', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dot, p%nDOF, 'U_full_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_full_dotdot,p%nDOF, 'U_full_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red, p%nDOF_red,'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dot, p%nDOF_red,'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red,'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red, p%nDOF_red, 'U_red', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dot, p%nDOF_red, 'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') + CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red, 'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') @@ -2831,10 +2856,11 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters - logical , intent(in ) :: rotateLoads ! If true, loads are rotated to body coordinate + logical , intent(in ) :: ExtraMoment ! If true add extra moment + logical , intent(in ) :: RotateLoads ! If true, loads are rotated to body coordinate type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation @@ -2858,12 +2884,11 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg real(ReKi), parameter :: myNaN = -9999998.989_ReKi ! --- Rotation matrix from body to global - if (rotateLoads) then + if (RotateLoads) then Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates endif - if (p%ExtraMoment) then - ! TODO modify for floating + if (ExtraMoment) then if (p%Floating) then ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) @@ -2895,7 +2920,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN - if (rotateLoads) then ! Forces in body coordinates + if (RotateLoads) then ! Forces in body coordinates do iNode = 1,p%nNodes m%Fext( p%NodesDOF(iNode)%List(1:3) ) = matmul(Rg2b, u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3))) enddo @@ -2921,7 +2946,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg CableTension = -p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) print*,'TODO, Controllable pretension cable needs thinking for moment' STOP - !if (rotateLoads) then ! in body coordinate + !if (RotateLoads) then ! in body coordinate ! m%Fext(IDOF) = m%Fext(IDOF) + matmul(Rg2b,m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0)) !else ! in global ! m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) @@ -2933,7 +2958,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg do iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh ! Moment ext + gravity - if (rotateLoads) then + if (RotateLoads) then ! In body coordinates Moment(1:3) = matmul(Rg2b, u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6))) else @@ -2941,7 +2966,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg endif ! Extra moment dm = Delta u x (fe + fg) - if (p%ExtraMoment) then + if (ExtraMoment) then du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 5e686c602..d2b1dab80 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -195,7 +195,8 @@ typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1 typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" -typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" +typedef ^ ParameterType ReKi D1_141 {:}{:} - - "MBm PhiM^T" +typedef ^ ParameterType ReKi D1_142 {:}{:} - - "TI^T PhiR^T" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 4262c2c8f..958493c71 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -242,7 +242,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_141 !< MBm PhiM^T [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_142 !< TI^T PhiR^T [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] @@ -7183,19 +7184,33 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D1_13 = SrcParamData%D1_13 ENDIF -IF (ALLOCATED(SrcParamData%D1_14)) THEN - i1_l = LBOUND(SrcParamData%D1_14,1) - i1_u = UBOUND(SrcParamData%D1_14,1) - i2_l = LBOUND(SrcParamData%D1_14,2) - i2_u = UBOUND(SrcParamData%D1_14,2) - IF (.NOT. ALLOCATED(DstParamData%D1_14)) THEN - ALLOCATE(DstParamData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcParamData%D1_141)) THEN + i1_l = LBOUND(SrcParamData%D1_141,1) + i1_u = UBOUND(SrcParamData%D1_141,1) + i2_l = LBOUND(SrcParamData%D1_141,2) + i2_u = UBOUND(SrcParamData%D1_141,2) + IF (.NOT. ALLOCATED(DstParamData%D1_141)) THEN + ALLOCATE(DstParamData%D1_141(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_14.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_141.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstParamData%D1_14 = SrcParamData%D1_14 + DstParamData%D1_141 = SrcParamData%D1_141 +ENDIF +IF (ALLOCATED(SrcParamData%D1_142)) THEN + i1_l = LBOUND(SrcParamData%D1_142,1) + i1_u = UBOUND(SrcParamData%D1_142,1) + i2_l = LBOUND(SrcParamData%D1_142,2) + i2_u = UBOUND(SrcParamData%D1_142,2) + IF (.NOT. ALLOCATED(DstParamData%D1_142)) THEN + ALLOCATE(DstParamData%D1_142(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_142.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%D1_142 = SrcParamData%D1_142 ENDIF IF (ALLOCATED(SrcParamData%PhiM)) THEN i1_l = LBOUND(SrcParamData%PhiM,1) @@ -7829,8 +7844,11 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D1_13)) THEN DEALLOCATE(ParamData%D1_13) ENDIF -IF (ALLOCATED(ParamData%D1_14)) THEN - DEALLOCATE(ParamData%D1_14) +IF (ALLOCATED(ParamData%D1_141)) THEN + DEALLOCATE(ParamData%D1_141) +ENDIF +IF (ALLOCATED(ParamData%D1_142)) THEN + DEALLOCATE(ParamData%D1_142) ENDIF IF (ALLOCATED(ParamData%PhiM)) THEN DEALLOCATE(ParamData%PhiM) @@ -8153,10 +8171,15 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 END IF - Int_BufSz = Int_BufSz + 1 ! D1_14 allocated yes/no - IF ( ALLOCATED(InData%D1_14) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 + Int_BufSz = Int_BufSz + 1 ! D1_141 allocated yes/no + IF ( ALLOCATED(InData%D1_141) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_141 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_141) ! D1_141 + END IF + Int_BufSz = Int_BufSz + 1 ! D1_142 allocated yes/no + IF ( ALLOCATED(InData%D1_142) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! D1_142 upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%D1_142) ! D1_142 END IF Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no IF ( ALLOCATED(InData%PhiM) ) THEN @@ -8912,22 +8935,42 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%D1_14) ) THEN + IF ( .NOT. ALLOCATED(InData%D1_141) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 ELSE IntKiBuf( Int_Xferred ) = 1 Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,1) + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_141,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_141,1) Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,2) + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_141,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_141,2) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%D1_14,2), UBOUND(InData%D1_14,2) - DO i1 = LBOUND(InData%D1_14,1), UBOUND(InData%D1_14,1) - ReKiBuf(Re_Xferred) = InData%D1_14(i1,i2) + DO i2 = LBOUND(InData%D1_141,2), UBOUND(InData%D1_141,2) + DO i1 = LBOUND(InData%D1_141,1), UBOUND(InData%D1_141,1) + ReKiBuf(Re_Xferred) = InData%D1_141(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%D1_142) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_142,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_142,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_142,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_142,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%D1_142,2), UBOUND(InData%D1_142,2) + DO i1 = LBOUND(InData%D1_142,1), UBOUND(InData%D1_142,1) + ReKiBuf(Re_Xferred) = InData%D1_142(i1,i2) Re_Xferred = Re_Xferred + 1 END DO END DO @@ -10346,7 +10389,30 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_14 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_141 not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%D1_141)) DEALLOCATE(OutData%D1_141) + ALLOCATE(OutData%D1_141(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_141.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%D1_141,2), UBOUND(OutData%D1_141,2) + DO i1 = LBOUND(OutData%D1_141,1), UBOUND(OutData%D1_141,1) + OutData%D1_141(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_142 not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -10356,15 +10422,15 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_14)) DEALLOCATE(OutData%D1_14) - ALLOCATE(OutData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%D1_142)) DEALLOCATE(OutData%D1_142) + ALLOCATE(OutData%D1_142(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_14.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_142.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D1_14,2), UBOUND(OutData%D1_14,2) - DO i1 = LBOUND(OutData%D1_14,1), UBOUND(OutData%D1_14,1) - OutData%D1_14(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%D1_142,2), UBOUND(OutData%D1_142,2) + DO i1 = LBOUND(OutData%D1_142,1), UBOUND(OutData%D1_142,1) + OutData%D1_142(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO From 3592bc75517699a57ec74ed14beb97c819fa103e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 17 Dec 2020 18:43:08 -0700 Subject: [PATCH 337/377] Rotated loads cleaned up --- modules/subdyn/src/SD_FEM.f90 | 51 +---- modules/subdyn/src/SubDyn.f90 | 169 +++----------- modules/subdyn/src/SubDyn_Output.f90 | 37 +-- modules/subdyn/src/SubDyn_Registry.txt | 6 - modules/subdyn/src/SubDyn_Types.f90 | 301 ------------------------- 5 files changed, 37 insertions(+), 527 deletions(-) diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 1ab5fcead..c705e6aea 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -1006,7 +1006,7 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None ! Local variables - INTEGER :: I, J, K, ie + INTEGER :: I, J, K INTEGER :: iGlob REAL(FEKi) :: Ke(12,12), Me(12, 12), FGe(12) ! element stiffness and mass matrices gravity force vector REAL(FEKi) :: FCe(12) ! Pretension force from cable element @@ -1084,55 +1084,6 @@ SUBROUTINE AssembleKM(Init, p, ErrStat, ErrMsg) p%FG(iGlob) = p%FG(iGlob) - Init%CMass(I, 2)*Init%g ENDDO - ! --- Compute Stiffness matrix of interface nodes - ! TODO TODO for now only one node - if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then - CALL AllocAry( p%K_I2, 6, 6 , 'p%K_I2' , ErrStat2, ErrMsg2); if(Failed()) return; - CALL AllocAry( p%Nodes_I2, 1, 'p%Nodes_I2' , ErrStat2, ErrMsg2); if(Failed()) return; - !DO I = 1, p%nNodes_I - i=1 - print*,'---------------------------------------------------' - if (size(p%Nodes_I,1)>1) then - print*,'>>> Cannot have more than one interface node for now' - STOP - endif - print*,'Interface Node',p%Nodes_I(1,1) - iNode = INT(p%Nodes_I(i, 1)) - if ( Init%NodesConnE(iNode, 1)>1 ) then - print*,'>>> Cannot have more than one member connected to interface node' - STOP - endif - print*,'Elements connected to interface Node',Init%NodesConnE(iNode, 2:4) - ie = Init%NodesConnE(iNode, 2) - print*,'Interface Element ',ie - print*,'Interface Element Nodes',p%Elems(ie,2:3) - CALL ElemK(p%ElemProps(ie), Ke) - - if (p%Elems(ie, 2)==iNode) then - p%Nodes_I2(1) = p%Elems(ie, 3) - p%K_I2 = Ke(1:6,7:12) - - else if (p%Elems(ie, 3)==iNode) then - p%Nodes_I2(1) = p%Elems(ie, 2) - p%K_I2 = Ke(7:12,1:6) - else - print*,'>>> One of the two nodes should be ',iNode - STOP - endif - print*,'Interface Node ',iNode - print*,'Interface Second Node ',p%Nodes_I2(1) - print*,'Interface elemprop',p%ElemProps(ie)%rho, p%ElemProps(ie)%Length - print*,'Stiffness matrix for second interface node (first element) ' - print*,'K ',p%K_I2(1,:) - print*,'K ',p%K_I2(2,:) - print*,'K ',p%K_I2(3,:) - print*,'K ',p%K_I2(4,:) - print*,'K ',p%K_I2(5,:) - print*,'K ',p%K_I2(6,:) - print*,'---------------------------------------------------' - - endif - CALL CleanUp_AssembleKM() CONTAINS diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 41fa208a6..32b079529 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -274,22 +274,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return if (p%ExtraMoment) then if (p%Floating) then - ! TODO disallow - call WrScr(' Extra moment will be included in loads (free/floating case detected)') + call WrScr(' Extra moment for Guyan loads and rotated CB-frame will be used (floating case detected)') else call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') endif endif - if (p%RotateLoads) then - if (p%Floating) then - call WrScr(' >>> Loads will be rotated (floating and OutCosM=True))') - else - call WrScr(' >>> Loads will not be rotated (fixed bottom)') - p%RotateLoads=.false. - endif - else - call WrScr(' >>> Loads will not be rotated (OutCosM=False)') - endif ! --- Craig-Bampton reduction (sets many parameters) CALL SD_Craig_Bampton(Init, p, CBparams, ErrStat2, ErrMsg2); if(Failed()) return @@ -427,7 +416,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method - REAL(ReKi) :: ULS_I2(6) ! TODO 6*nDOFI REAL(ReKi) :: Y1(6) REAL(ReKi) :: Y1_CB(6) REAL(ReKi) :: Y1_CB_L(6) @@ -470,7 +458,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- ! External force on internal nodes (F_L) - call GetExtForceOnInternalDOF(u, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -585,109 +573,33 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) enddo endif - ! -------------------------------------------------------------------------------- ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) ! -------------------------------------------------------------------------------- - - Y1_CB_L = - (matmul(p%D1_141, m%F_L)) + ! --- Special case for floating with extramoment + if (p%ExtraMoment.and.p%Floating) then + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses rotated loads + endif ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, .false., m%F_L, ErrStat2, ErrMsg2, DoExtraMoment=.True.); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) - ! Compute reaction/coupling force at TP - if ( p%nDOFM > 0) then - Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & - + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) - else ! No retained modes, so there are no states - Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & - + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) - end if - print*,'t ',t - print*,'UTP ',m%u_TP - print*,'-----------------------' - print*,'Y1 old2 ',Y1 + ! Compute reaction/coupling force at TP Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) ) - Y1_Guy_L = - matmul(p%D1_142, m%F_L) if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) else Y1_CB = 0.0_ReKi endif Y1_Guy_R = matmul( F_I, p%TI ) - Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R - print*,'-----------------------' - print*,'Split terms (old)' - print*,'Y1 UtP ',Y1_Utp - print*,'Y1 GR ',Y1_Guy_R - print*,'Y1 CB ',Y1_CB - print*,'Y1 CBL ',Y1_CB_L - print*,'Y1 GL old',Y1_Guy_L - print*,'Y1 old ',Y1 - - if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then - ! --- Going from flatten DOFs to reduced DOFs, to full DOFs... - ! NOTE: this is only needed for the few DOFs below the interface - ! so this could be greatly optimized with the mapping computed at init only.. - ! TODO... -! m%U_red_SIM(:) = 0.0_ReKi -! m%U_red_SIM(p%ID__L) = ULS ! Only the static contribution -! !m%U_red_SIM(p%ID__L) = m%UL ! Only the static contribution -! if (p%reduced) then -! m%U_full_SIM = matmul(p%T_red, m%U_red_SIM) -! else -! m%U_full_SIM = m%U_red_SIM -! endif -! iSDNode = p%Nodes_I2(1) ! Second node of interface element -! DOFList => p%NodesDOF(iSDNode)%List -! ULS_I2 = m%U_full_SIM(DOFList(1:6)) -! !print*,'NODE',iSDNode -! !print*,'DOFLIST',DOFLIST -! !print*,'DOFLIST', p%NodesDOF(p%Elems(1,2))%List(1:6) -! !print*,'DOFLIST', p%NodesDOF(p%Elems(1,3))%List(1:6) -! Y1_Guy_L = - matmul( p%K_I2 , ULS_I2) -! print*,'ULs ',ULS_I2 -! print*,'ULe ',m%U_full_elast(DOFList) -! if (any(ULS_I2>2)) then -! STOP -! endif -! print*,'-----------------------' -! print*,'Split terms (new)' -! print*,'Y1 UtP ',Y1_Utp -! print*,'Y1 GR ',Y1_Guy_R -! print*,'Y1 CB ',Y1_CB -! print*,'Y1 CBL ',Y1_CB_L -! print*,'Y1 GL new',Y1_Guy_L -! Y1_Guy_L(1:3) = matmul(Rb2g,Y1_Guy_L(1:3)) -! Y1_Guy_L(4:6) = matmul(Rb2g,Y1_Guy_L(4:6)) -! Y1_CB(1:3) = matmul(Rb2g,Y1_CB(1:3)) -! Y1_CB(4:6) = matmul(Rb2g,Y1_CB(4:6)) -! Y1_CB_L(1:3) = matmul(Rb2g,Y1_CB_L(1:3)) -! Y1_CB_L(4:6) = matmul(Rb2g,Y1_CB_L(4:6)) -! print*,'Y1 GL rot',Y1_Guy_L -! print*,'Y1 CB rot',Y1_CB -! print*,'Y1 CBLrot',Y1_CB_L - - Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R - print*,'Y1 new',Y1 - else - - Y1_Guy_L = - matmul(p%D1_142, m%F_L) - Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R - !if ( p%nDOFM > 0) then - ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & - ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) - !else ! No retained modes, so there are no states - ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & - ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) - !end if + Y1_Guy_L = - matmul(p%D1_142, m%F_L) + if (.not.(p%ExtraMoment.and.p%Floating)) then + Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif - print*,'-----------------------' - print*,'FileOutputs' + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R + ! KEEP ME !if ( p%nDOFM > 0) then ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & @@ -710,7 +622,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces y%Y1Mesh%Force (:,1) = Y1(1:3) y%Y1Mesh%Moment(:,1) = Y1(4:6) - !________________________________________ ! CALCULATE OUTPUT TO BE WRITTEN TO FILE @@ -754,7 +665,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) END DO m%LastOutTime = t ENDIF - print*,'' + CONTAINS LOGICAL FUNCTION Failed() call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') @@ -800,7 +711,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF( u, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2 ); + CALL GetExtForceOnInternalDOF( u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! State equation dxdt%qm= x%qmdot @@ -1084,11 +995,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) enddo ! Trigger: determine if floating/fixed based on BCs and SSI file p%Floating = isFloating(Init,p) -!if (p%ExtraMoment .and. p%Floating) then -! call Fatal(' Error in file "'//TRIM(SDInputFile)//'": `ExtraMoment` cannot be true in a floating case') -! return -!endif - !------- INTERFACE JOINTS: T/F for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) --------- @@ -1239,8 +1145,6 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadLVar(UnIn, SDInputFile, Init%SSSum , 'SSSum' , 'Summary File Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadLVar(UnIn, SDInputFile, Init%OutCOSM, 'OutCOSM', 'Cosine Matrix Logic Variable' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return !bjj: TODO: OutCOSM isn't used anywhere else. CALL ReadLVar(UnIn, SDInputFile, p%OutAll , 'OutAll' , 'Output all Member Forces Logic Variable',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -! TEMPORARY HACK -p%RotateLoads=Init%OutCOSM !Store an integer version of it p%OutAllInt= 1 IF ( .NOT. p%OutAll ) p%OutAllInt= 0 @@ -1799,12 +1703,12 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, p%RotateLoads, m%F_L, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - CALL GetExtForceOnInternalDOF(u_interp, p, m, p%RotateLoads, F_L2, ErrStat2, ErrMsg2); + CALL GetExtForceOnInternalDOF(u_interp, p, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2546,15 +2450,10 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) p%D1_13 = p%MBB - p%D1_13 - ! TODO cant use LAPACK due to type conversions FEKi->ReKi - !p%D1_14 = MATMUL( p%MBM, p%PhiM_T ) - MATMUL( TI_transpose, TRANSPOSE(PhiRb)) - p%D1_14 = MATMUL( TI_transpose, TRANSPOSE(PhiRb)) - !CALL LAPACK_GEMM( 'T', 'T', 1.0_ReKi, p%TI, PhiRb, 0.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( TRANSPOSE(TI), TRANSPOSE(PHiRb)) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, -1.0_ReKi, p%D1_14, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_14 = MATMUL( p%MBM, TRANSPOSE(p%PhiM) ) - p%D1_14 - ! --- Intermediates D1_14 = D1_141 + D1_142 - p%D1_141 = MATMUL(p%MBM, TRANSPOSE(p%PhiM)) - !CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, 0.0_ReKi, p%D1_141, ErrStat2, ErrMsg2 ); if(Failed()) return + !p%D1_141 = MATMUL(p%MBM, TRANSPOSE(p%PhiM)) + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%PhiM, 0.0_ReKi, p%D1_141, ErrStat2, ErrMsg2 ); if(Failed()) return + ! NOTE: cant use LAPACK due to type conversions FEKi->ReKi p%D1_142 =- MATMUL(TI_transpose, TRANSPOSE(PhiRb)) @@ -2610,7 +2509,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable p%D1_12 = p%CBB ! No cross couplings p%D1_13 = p%MBB ! No cross couplings - p%D1_14 = - MATMUL( TI_transpose, TRANSPOSE(PHiRb)) p%D1_141 = 0.0_ReKi p%D1_142 = - MATMUL(TI_transpose, TRANSPOSE(PhiRb)) END IF @@ -2641,7 +2539,6 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%CBB, nDOFL_TP, nDOFL_TP, 'p%CBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%MBB, nDOFL_TP, nDOFL_TP, 'p%MBB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%TI, p%nDOFI__, 6, 'p%TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_14, nDOFL_TP, p%nDOF__L,'p%D1_14', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_141, nDOFL_TP, p%nDOF__L,'p%D1_141', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%D1_142, nDOFL_TP, p%nDOF__L,'p%D1_142', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%PhiRb_TI, p%nDOF__L, nDOFL_TP,'p%PhiRb_TI', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') @@ -2696,11 +2593,6 @@ SUBROUTINE AllocMiscVars(p, Misc, ErrStat, ErrMsg) CALL AllocAry( Misc%U_red_dot, p%nDOF_red, 'U_red_dot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%U_red_dotdot, p%nDOF_red, 'U_red_dotdot', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') -if (p%RotateLoads.and.p%SttcSolve/=idSIM_None) then - CALL AllocAry( Misc%U_full_SIM, p%nDOF, 'U_full_SIM', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') - CALL AllocAry( Misc%U_red_SIM, p%nDOF_red, 'U_red_SIM', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') -endif - CALL AllocAry( Misc%Fext, p%nDOF , 'm%Fext ', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') CALL AllocAry( Misc%Fext_red, p%nDOF_red , 'm%Fext_red', ErrStat2, ErrMsg2 );CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocMiscVars') @@ -2964,15 +2856,15 @@ END SUBROUTINE PartitionDOFNodes !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, DoExtraMoment ) +SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters - logical , intent(in ) :: rotateLoads ! If true, loads are rotated to body coordinate + logical , intent(in ) :: ExtraMoment ! If true add extra moment + logical , intent(in ) :: RotateLoads ! If true, loads are rotated to body coordinate type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - logical, intent(in ) ,optional :: DoExtraMoment integer :: iNode ! indices of u-mesh nodes and SD nodes integer :: nMembers integer :: startDOF, I @@ -2992,16 +2884,15 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, real(ReKi), parameter :: myNaN = -9999998.989_ReKi ! --- Rotation matrix from body to global - if (rotateLoads) then + if (RotateLoads) then Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates endif - if (p%ExtraMoment .or. present(DoExtraMoment)) then + if (ExtraMoment) then if (p%Floating) then - ! TODO deactivate for floating ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion - m%DU_full = 0.0_ReKi Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + m%DU_full = 0.0_ReKi do iNode = 1,p%nNodes rIP0(1:3) = p%DP0(1:3, iNode) ! vector interface->node at t=0 rIP(1:3) = matmul(Rot, rIP0) ! vector interface->node at t @@ -3029,7 +2920,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN - if (rotateLoads) then ! Forces in body coordinates + if (RotateLoads) then ! Forces in body coordinates do iNode = 1,p%nNodes m%Fext( p%NodesDOF(iNode)%List(1:3) ) = matmul(Rg2b, u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3))) enddo @@ -3055,7 +2946,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, CableTension = -p%ElemProps(iElem)%YoungE*p%ElemProps(iElem)%Area * u%CableDeltaL(iChannel) / (p%ElemProps(iElem)%Length + u%CableDeltaL(iChannel)) print*,'TODO, Controllable pretension cable needs thinking for moment' STOP - !if (rotateLoads) then ! in body coordinate + !if (RotateLoads) then ! in body coordinate ! m%Fext(IDOF) = m%Fext(IDOF) + matmul(Rg2b,m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0)) !else ! in global ! m%Fext(IDOF) = m%Fext(IDOF) + m%FC_unit( IDOF ) * (CableTension - p%ElemProps(iElem)%T0) @@ -3067,7 +2958,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, do iNode = 1,p%nNodes Force(1:3) = m%Fext(p%NodesDOF(iNode)%List(1:3) ) ! Controllable cable + External Forces on LMesh ! Moment ext + gravity - if (rotateLoads) then + if (RotateLoads) then ! In body coordinates Moment(1:3) = matmul(Rg2b, u%LMesh%Moment(1:3,iNode) + p%FG(p%NodesDOF(iNode)%List(4:6))) else @@ -3075,7 +2966,7 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, rotateLoads, F_L, ErrStat, ErrMsg, endif ! Extra moment dm = Delta u x (fe + fg) - if (p%ExtraMoment .or. present(DoExtraMoment)) then + if (ExtraMoment) then du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) diff --git a/modules/subdyn/src/SubDyn_Output.f90 b/modules/subdyn/src/SubDyn_Output.f90 index 077aba9d4..88b05b9be 100644 --- a/modules/subdyn/src/SubDyn_Output.f90 +++ b/modules/subdyn/src/SubDyn_Output.f90 @@ -277,7 +277,7 @@ SUBROUTINE SDOut_MapOutputs(u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) !locals integer(IntKi) :: iMemberOutput, iiNode, iSDNode, iMeshNode, I, J, L, L2 ! Counters integer(IntKi) :: maxOutModes ! maximum modes to output, the minimum of 99 or p%nDOFM - real(ReKi), dimension (6) :: FM_elm, FK_elm, FK_elm1, FK_elm3, Fext !output static and dynamic forces and moments + real(ReKi), dimension (6) :: FM_elm, FK_elm, Fext !output static and dynamic forces and moments real(ReKi), dimension (6) :: FM_elm2, FK_elm2 !output static and dynamic forces and moments real(FEKi), dimension (3,3) :: DIRCOS !direction cosice matrix (global to local) (3x3) real(ReKi), allocatable :: ReactNs(:) !6*Nreact reactions @@ -300,28 +300,18 @@ SUBROUTINE SDOut_MapOutputs(u,p,x, y, m, AllOuts, ErrStat, ErrMsg ) pLst=>p%MOutLst(iMemberOutput) ! List for a given member-output DO iiNode=1,pLst%NOutCnt !Iterate on requested nodes for that member ! --- Forces (potentially averaged on 2 elements) - FK_elm1=0 - FK_elm2=0 - FK_elm3=0 - call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm1, sgn, DIRCOS, .false.) + call ElementForce(pLst, iiNode, 1, FM_elm, FK_elm, sgn, DIRCOS, .false.) FM_elm2=sgn*FM_elm - FK_elm1=sgn*FK_elm1 + FK_elm2=sgn*FK_elm IF (pLst%ElmIDs(iiNode,2) .NE. 0) THEN ! Second element exist ! NOTE: forces are computed in the coordinate system of the first element for averaging - call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm2, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above + call ElementForce(pLst, iiNode, 2, FM_elm, FK_elm, sgn, DIRCOS, .true.) ! True= we use DIRCOS from element above FM_elm2=0.5*( FM_elm2 + sgn*FM_elm ) ! Now Average - FK_elm3=0.5*( FK_elm1 + sgn*FK_elm2) ! Now Average - else - FK_elm3=FK_elm1 + FK_elm2=0.5*( FK_elm2 + sgn*FK_elm) ! Now Average ENDIF ! Static (elastic) component of reaction forces and moments at MαNβ along local member coordinate system ! "MαNβFKxe, MαNβFKye, MαNβFKze, MαNβMKxe, MαNβMKye, MαNβMKze" - AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm3 !static forces and moments (6) Local Ref - if (pLst%ElmIDs(iiNode,1)==1) then - print*,'CalcO FK1',FK_elm1 - print*,'CalcO FK2',FK_elm2 - print*,'CalcO FK3',FK_elm3 - endif + AllOuts(MNfmKe (:,iiNode,iMemberOutput)) = FK_elm2 !static forces and moments (6) Local Ref ! Dynamic (inertial) component of reaction forces and moments at MαNβ along local member coordinate system ! "MαNβFMxe, MαNβFMye, MαNβFMze, MαNβMMxe, MαNβMMye, MαNβMMze" AllOuts(MNfmMe (:,iiNode,iMemberOutput)) = FM_elm2 !dynamic forces and moments (6) Local Ref @@ -452,21 +442,6 @@ subroutine ElementForce(pLst, iiNode, JJ, FM_elm, FK_elm, sgn, DIRCOS, bUseInput DIRCOS=transpose(p%ElemProps(iElem)%DirCos)! global to local endif CALL CALC_NODE_FORCES( DIRCOS, pLst%Me(:,:,iiNode,JJ),pLst%Ke(:,:,iiNode,JJ), Xdd_e, X_e, pLst%Fg(:,iiNode,JJ), FirstOrSecond, FM_elm, FK_elm) - if (iElem==1) then - ! print*,'K',pLst%Ke(1,7:12,iiNode,JJ) - ! print*,'K',pLst%Ke(2,7:12,iiNode,JJ) - ! print*,'K',pLst%Ke(3,7:12,iiNode,JJ) - ! print*,'K',pLst%Ke(4,7:12,iiNode,JJ) - ! print*,'K',pLst%Ke(5,7:12,iiNode,JJ) - ! print*,'K',pLst%Ke(6,7:12,iiNode,JJ) - print*,'CalcODC1',DIRCOS(1,:) - print*,'CalcODC2',DIRCOS(2,:) - print*,'CalcODC3',DIRCOS(3,:) - print*,'First ?', FirstOrSecond,sgn - print*,'CalcO U ',X_e(1:6) - print*,'CalcO U ',X_e(7:12) - print*,'ClacO FK',FK_elm - endif end subroutine ElementForce !==================================================================================================== diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index fc35b484b..d2b1dab80 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -153,8 +153,6 @@ typedef ^ MiscVarType ReKi U_full_elast {:} - - "Elastic di typedef ^ MiscVarType ReKi U_red {:} - - typedef ^ MiscVarType ReKi U_red_dot {:} - - typedef ^ MiscVarType ReKi U_red_dotdot {:} - - -typedef ^ MiscVarType ReKi U_red_SIM {:} - - "Static Solve contribution to U, reduced system" -typedef ^ MiscVarType ReKi U_full_SIM {:} - - "Static Solve contribution to U, full system" typedef ^ MiscVarType ReKi FC_unit {:} - - "Cable Force vector (for varying cable load, of unit cable load)" N typedef ^ MiscVarType ReKi SDWrOutput {:} - - "Data from previous step to be written to a SubDyn output file" typedef ^ MiscVarType DbKi LastOutTime - - - "The time of the most recent stored output data" "s" @@ -190,7 +188,6 @@ typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of fr typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" -typedef ^ ParameterType Logical RotateLoads - - - "Temporary, rotate loads" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" @@ -198,11 +195,8 @@ typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1 typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" -typedef ^ ParameterType ReKi D1_14 {:}{:} - - "Coefficient of Fle in Y1" typedef ^ ParameterType ReKi D1_141 {:}{:} - - "MBm PhiM^T" typedef ^ ParameterType ReKi D1_142 {:}{:} - - "TI^T PhiR^T" -typedef ^ ParameterType R8Ki K_I2 {:}{:} - - "Stiffness matrix of I2 nodes" -typedef ^ ParameterType IntKi Nodes_I2 {:} - - "I2 node indices" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" typedef ^ ParameterType ReKi C2_61 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" typedef ^ ParameterType ReKi C2_62 {:}{:} - - "Coefficient of x in Y2 (URdotdot ULdotdot)" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 70fd93b6f..958493c71 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -204,8 +204,6 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dot REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_dotdot - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_red_SIM !< Static Solve contribution to U, reduced system [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: U_full_SIM !< Static Solve contribution to U, full system [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: FC_unit !< Cable Force vector (for varying cable load, of unit cable load) [N] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SDWrOutput !< Data from previous step to be written to a SubDyn output file [-] REAL(DbKi) :: LastOutTime !< The time of the most recent stored output data [s] @@ -237,7 +235,6 @@ MODULE SubDyn_Types INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] LOGICAL :: Floating !< True if floating bottom (the 6 DOF are free at all reaction nodes) [-] - LOGICAL :: RotateLoads !< Temporary, rotate loads [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] @@ -245,11 +242,8 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_14 !< Coefficient of Fle in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_141 !< MBm PhiM^T [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_142 !< TI^T PhiR^T [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: K_I2 !< Stiffness matrix of I2 nodes [-] - INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Nodes_I2 !< I2 node indices [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_61 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C2_62 !< Coefficient of x in Y2 (URdotdot ULdotdot) [-] @@ -5893,30 +5887,6 @@ SUBROUTINE SD_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) END IF DstMiscData%U_red_dotdot = SrcMiscData%U_red_dotdot ENDIF -IF (ALLOCATED(SrcMiscData%U_red_SIM)) THEN - i1_l = LBOUND(SrcMiscData%U_red_SIM,1) - i1_u = UBOUND(SrcMiscData%U_red_SIM,1) - IF (.NOT. ALLOCATED(DstMiscData%U_red_SIM)) THEN - ALLOCATE(DstMiscData%U_red_SIM(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_red_SIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_red_SIM = SrcMiscData%U_red_SIM -ENDIF -IF (ALLOCATED(SrcMiscData%U_full_SIM)) THEN - i1_l = LBOUND(SrcMiscData%U_full_SIM,1) - i1_u = UBOUND(SrcMiscData%U_full_SIM,1) - IF (.NOT. ALLOCATED(DstMiscData%U_full_SIM)) THEN - ALLOCATE(DstMiscData%U_full_SIM(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%U_full_SIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%U_full_SIM = SrcMiscData%U_full_SIM -ENDIF IF (ALLOCATED(SrcMiscData%FC_unit)) THEN i1_l = LBOUND(SrcMiscData%FC_unit,1) i1_u = UBOUND(SrcMiscData%FC_unit,1) @@ -6026,12 +5996,6 @@ SUBROUTINE SD_DestroyMisc( MiscData, ErrStat, ErrMsg ) IF (ALLOCATED(MiscData%U_red_dotdot)) THEN DEALLOCATE(MiscData%U_red_dotdot) ENDIF -IF (ALLOCATED(MiscData%U_red_SIM)) THEN - DEALLOCATE(MiscData%U_red_SIM) -ENDIF -IF (ALLOCATED(MiscData%U_full_SIM)) THEN - DEALLOCATE(MiscData%U_full_SIM) -ENDIF IF (ALLOCATED(MiscData%FC_unit)) THEN DEALLOCATE(MiscData%FC_unit) ENDIF @@ -6164,16 +6128,6 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 2*1 ! U_red_dotdot upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%U_red_dotdot) ! U_red_dotdot END IF - Int_BufSz = Int_BufSz + 1 ! U_red_SIM allocated yes/no - IF ( ALLOCATED(InData%U_red_SIM) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_red_SIM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_red_SIM) ! U_red_SIM - END IF - Int_BufSz = Int_BufSz + 1 ! U_full_SIM allocated yes/no - IF ( ALLOCATED(InData%U_full_SIM) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! U_full_SIM upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%U_full_SIM) ! U_full_SIM - END IF Int_BufSz = Int_BufSz + 1 ! FC_unit allocated yes/no IF ( ALLOCATED(InData%FC_unit) ) THEN Int_BufSz = Int_BufSz + 2*1 ! FC_unit upper/lower bounds for each dimension @@ -6475,36 +6429,6 @@ SUBROUTINE SD_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( .NOT. ALLOCATED(InData%U_red_SIM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_red_SIM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_red_SIM,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%U_red_SIM,1), UBOUND(InData%U_red_SIM,1) - ReKiBuf(Re_Xferred) = InData%U_red_SIM(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%U_full_SIM) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%U_full_SIM,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%U_full_SIM,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%U_full_SIM,1), UBOUND(InData%U_full_SIM,1) - ReKiBuf(Re_Xferred) = InData%U_full_SIM(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%FC_unit) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -6904,42 +6828,6 @@ SUBROUTINE SD_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Re_Xferred = Re_Xferred + 1 END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_red_SIM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_red_SIM)) DEALLOCATE(OutData%U_red_SIM) - ALLOCATE(OutData%U_red_SIM(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_red_SIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%U_red_SIM,1), UBOUND(OutData%U_red_SIM,1) - OutData%U_red_SIM(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! U_full_SIM not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%U_full_SIM)) DEALLOCATE(OutData%U_full_SIM) - ALLOCATE(OutData%U_full_SIM(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%U_full_SIM.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%U_full_SIM,1), UBOUND(OutData%U_full_SIM,1) - OutData%U_full_SIM(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FC_unit not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -7202,7 +7090,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) DstParamData%SttcSolve = SrcParamData%SttcSolve DstParamData%ExtraMoment = SrcParamData%ExtraMoment DstParamData%Floating = SrcParamData%Floating - DstParamData%RotateLoads = SrcParamData%RotateLoads IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) i1_u = UBOUND(SrcParamData%KMMDiag,1) @@ -7297,20 +7184,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D1_13 = SrcParamData%D1_13 ENDIF -IF (ALLOCATED(SrcParamData%D1_14)) THEN - i1_l = LBOUND(SrcParamData%D1_14,1) - i1_u = UBOUND(SrcParamData%D1_14,1) - i2_l = LBOUND(SrcParamData%D1_14,2) - i2_u = UBOUND(SrcParamData%D1_14,2) - IF (.NOT. ALLOCATED(DstParamData%D1_14)) THEN - ALLOCATE(DstParamData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_14.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D1_14 = SrcParamData%D1_14 -ENDIF IF (ALLOCATED(SrcParamData%D1_141)) THEN i1_l = LBOUND(SrcParamData%D1_141,1) i1_u = UBOUND(SrcParamData%D1_141,1) @@ -7339,32 +7212,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%D1_142 = SrcParamData%D1_142 ENDIF -IF (ALLOCATED(SrcParamData%K_I2)) THEN - i1_l = LBOUND(SrcParamData%K_I2,1) - i1_u = UBOUND(SrcParamData%K_I2,1) - i2_l = LBOUND(SrcParamData%K_I2,2) - i2_u = UBOUND(SrcParamData%K_I2,2) - IF (.NOT. ALLOCATED(DstParamData%K_I2)) THEN - ALLOCATE(DstParamData%K_I2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%K_I2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%K_I2 = SrcParamData%K_I2 -ENDIF -IF (ALLOCATED(SrcParamData%Nodes_I2)) THEN - i1_l = LBOUND(SrcParamData%Nodes_I2,1) - i1_u = UBOUND(SrcParamData%Nodes_I2,1) - IF (.NOT. ALLOCATED(DstParamData%Nodes_I2)) THEN - ALLOCATE(DstParamData%Nodes_I2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Nodes_I2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Nodes_I2 = SrcParamData%Nodes_I2 -ENDIF IF (ALLOCATED(SrcParamData%PhiM)) THEN i1_l = LBOUND(SrcParamData%PhiM,1) i1_u = UBOUND(SrcParamData%PhiM,1) @@ -7997,21 +7844,12 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%D1_13)) THEN DEALLOCATE(ParamData%D1_13) ENDIF -IF (ALLOCATED(ParamData%D1_14)) THEN - DEALLOCATE(ParamData%D1_14) -ENDIF IF (ALLOCATED(ParamData%D1_141)) THEN DEALLOCATE(ParamData%D1_141) ENDIF IF (ALLOCATED(ParamData%D1_142)) THEN DEALLOCATE(ParamData%D1_142) ENDIF -IF (ALLOCATED(ParamData%K_I2)) THEN - DEALLOCATE(ParamData%K_I2) -ENDIF -IF (ALLOCATED(ParamData%Nodes_I2)) THEN - DEALLOCATE(ParamData%Nodes_I2) -ENDIF IF (ALLOCATED(ParamData%PhiM)) THEN DEALLOCATE(ParamData%PhiM) ENDIF @@ -8298,7 +8136,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 1 ! SttcSolve Int_BufSz = Int_BufSz + 1 ! ExtraMoment Int_BufSz = Int_BufSz + 1 ! Floating - Int_BufSz = Int_BufSz + 1 ! RotateLoads Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN Int_BufSz = Int_BufSz + 2*1 ! KMMDiag upper/lower bounds for each dimension @@ -8334,11 +8171,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 END IF - Int_BufSz = Int_BufSz + 1 ! D1_14 allocated yes/no - IF ( ALLOCATED(InData%D1_14) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_14 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_14) ! D1_14 - END IF Int_BufSz = Int_BufSz + 1 ! D1_141 allocated yes/no IF ( ALLOCATED(InData%D1_141) ) THEN Int_BufSz = Int_BufSz + 2*2 ! D1_141 upper/lower bounds for each dimension @@ -8349,16 +8181,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! D1_142 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%D1_142) ! D1_142 END IF - Int_BufSz = Int_BufSz + 1 ! K_I2 allocated yes/no - IF ( ALLOCATED(InData%K_I2) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! K_I2 upper/lower bounds for each dimension - Db_BufSz = Db_BufSz + SIZE(InData%K_I2) ! K_I2 - END IF - Int_BufSz = Int_BufSz + 1 ! Nodes_I2 allocated yes/no - IF ( ALLOCATED(InData%Nodes_I2) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Nodes_I2 upper/lower bounds for each dimension - Int_BufSz = Int_BufSz + SIZE(InData%Nodes_I2) ! Nodes_I2 - END IF Int_BufSz = Int_BufSz + 1 ! PhiM allocated yes/no IF ( ALLOCATED(InData%PhiM) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PhiM upper/lower bounds for each dimension @@ -8983,8 +8805,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%Floating, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateLoads, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%KMMDiag) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9115,26 +8935,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%D1_14) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_14,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_14,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%D1_14,2), UBOUND(InData%D1_14,2) - DO i1 = LBOUND(InData%D1_14,1), UBOUND(InData%D1_14,1) - ReKiBuf(Re_Xferred) = InData%D1_14(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( .NOT. ALLOCATED(InData%D1_141) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -9175,41 +8975,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%K_I2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%K_I2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K_I2,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%K_I2,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%K_I2,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%K_I2,2), UBOUND(InData%K_I2,2) - DO i1 = LBOUND(InData%K_I2,1), UBOUND(InData%K_I2,1) - DbKiBuf(Db_Xferred) = InData%K_I2(i1,i2) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%Nodes_I2) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Nodes_I2,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Nodes_I2,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%Nodes_I2,1), UBOUND(InData%Nodes_I2,1) - IntKiBuf(Int_Xferred) = InData%Nodes_I2(i1) - Int_Xferred = Int_Xferred + 1 - END DO - END IF IF ( .NOT. ALLOCATED(InData%PhiM) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10473,8 +10238,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%Floating = TRANSFER(IntKiBuf(Int_Xferred), OutData%Floating) Int_Xferred = Int_Xferred + 1 - OutData%RotateLoads = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateLoads) - Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! KMMDiag not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10626,29 +10389,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_14 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_14)) DEALLOCATE(OutData%D1_14) - ALLOCATE(OutData%D1_14(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_14.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%D1_14,2), UBOUND(OutData%D1_14,2) - DO i1 = LBOUND(OutData%D1_14,1), UBOUND(OutData%D1_14,1) - OutData%D1_14(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_141 not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -10695,47 +10435,6 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! K_I2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%K_I2)) DEALLOCATE(OutData%K_I2) - ALLOCATE(OutData%K_I2(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%K_I2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%K_I2,2), UBOUND(OutData%K_I2,2) - DO i1 = LBOUND(OutData%K_I2,1), UBOUND(OutData%K_I2,1) - OutData%K_I2(i1,i2) = REAL(DbKiBuf(Db_Xferred), R8Ki) - Db_Xferred = Db_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Nodes_I2 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Nodes_I2)) DEALLOCATE(OutData%Nodes_I2) - ALLOCATE(OutData%Nodes_I2(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Nodes_I2.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%Nodes_I2,1), UBOUND(OutData%Nodes_I2,1) - OutData%Nodes_I2(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PhiM not allocated Int_Xferred = Int_Xferred + 1 ELSE From 61dd97f75f68b72091bb7f07c8eef163fa39d974 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 17 Dec 2020 23:23:54 -0700 Subject: [PATCH 338/377] TCF-mods2: fix type conversion in MD registry Values from the MD_Line derived type were stored as ReKi, but passed into subroutines that expected to receive DbKi. This fixes compilation issues in debug with gcc. --- modules/moordyn/src/MoorDyn_Registry.txt | 42 ++-- modules/moordyn/src/MoorDyn_Types.f90 | 252 +++++++++++------------ 2 files changed, 147 insertions(+), 147 deletions(-) diff --git a/modules/moordyn/src/MoorDyn_Registry.txt b/modules/moordyn/src/MoorDyn_Registry.txt index 477a772d4..6fb1e729d 100644 --- a/modules/moordyn/src/MoorDyn_Registry.txt +++ b/modules/moordyn/src/MoorDyn_Registry.txt @@ -73,27 +73,27 @@ typedef ^ ^ IntKi FairConnect - typedef ^ ^ IntKi AnchConnect - - - "IdNum of Connection at anchor" typedef ^ ^ IntKi PropsIdNum - - - "the IdNum of the associated line properties" - typedef ^ ^ IntKi N - - - "The number of elements in the line" - -typedef ^ ^ ReKi UnstrLen - - - "unstretched length of the line" - -typedef ^ ^ ReKi BA - - - "internal damping coefficient times area for this line only" "[N-s]" -typedef ^ ^ ReKi r {:}{:} - - "node positions" - -typedef ^ ^ ReKi rd {:}{:} - - "node velocities" - -typedef ^ ^ ReKi q {:}{:} - - "node tangent vectors" - -typedef ^ ^ ReKi l {:} - - "segment unstretched length" "[m]" -typedef ^ ^ ReKi ld {:} - - "segment unstretched length rate of change (used in active tensioning)" "[m]" -typedef ^ ^ ReKi lstr {:} - - "segment stretched length" "[m]" -typedef ^ ^ ReKi lstrd {:} - - "segment change in stretched length" "[m/s]" -typedef ^ ^ ReKi V {:} - - "segment volume" "[m^3]" -typedef ^ ^ ReKi T {:}{:} - - "segment tension vectors" "[N]" -typedef ^ ^ ReKi Td {:}{:} - - "segment internal damping force vectors" "[N]" -typedef ^ ^ ReKi W {:}{:} - - "weight/buoyancy vectors" "[N]" -typedef ^ ^ ReKi Dp {:}{:} - - "node drag (transverse)" "[N]" -typedef ^ ^ ReKi Dq {:}{:} - - "node drag (axial)" "[N]" -typedef ^ ^ ReKi Ap {:}{:} - - "node added mass forcing (transverse)" "[N]" -typedef ^ ^ ReKi Aq {:}{:} - - "node added mass forcing (axial)" "[N]" -typedef ^ ^ ReKi B {:}{:} - - "node bottom contact force" "[N]" -typedef ^ ^ ReKi F {:}{:} - - "total force on node" "[N]" -typedef ^ ^ ReKi S {:}{:}{:} - - "node inverse mass matrix" "[kg]" -typedef ^ ^ ReKi M {:}{:}{:} - - "node mass matrix" "[kg]" +typedef ^ ^ DbKi UnstrLen - - - "unstretched length of the line" - +typedef ^ ^ DbKi BA - - - "internal damping coefficient times area for this line only" "[N-s]" +typedef ^ ^ DbKi r {:}{:} - - "node positions" - +typedef ^ ^ DbKi rd {:}{:} - - "node velocities" - +typedef ^ ^ DbKi q {:}{:} - - "node tangent vectors" - +typedef ^ ^ DbKi l {:} - - "segment unstretched length" "[m]" +typedef ^ ^ DbKi ld {:} - - "segment unstretched length rate of change (used in active tensioning)" "[m]" +typedef ^ ^ DbKi lstr {:} - - "segment stretched length" "[m]" +typedef ^ ^ DbKi lstrd {:} - - "segment change in stretched length" "[m/s]" +typedef ^ ^ DbKi V {:} - - "segment volume" "[m^3]" +typedef ^ ^ DbKi T {:}{:} - - "segment tension vectors" "[N]" +typedef ^ ^ DbKi Td {:}{:} - - "segment internal damping force vectors" "[N]" +typedef ^ ^ DbKi W {:}{:} - - "weight/buoyancy vectors" "[N]" +typedef ^ ^ DbKi Dp {:}{:} - - "node drag (transverse)" "[N]" +typedef ^ ^ DbKi Dq {:}{:} - - "node drag (axial)" "[N]" +typedef ^ ^ DbKi Ap {:}{:} - - "node added mass forcing (transverse)" "[N]" +typedef ^ ^ DbKi Aq {:}{:} - - "node added mass forcing (axial)" "[N]" +typedef ^ ^ DbKi B {:}{:} - - "node bottom contact force" "[N]" +typedef ^ ^ DbKi F {:}{:} - - "total force on node" "[N]" +typedef ^ ^ DbKi S {:}{:}{:} - - "node inverse mass matrix" "[kg]" +typedef ^ ^ DbKi M {:}{:}{:} - - "node mass matrix" "[kg]" typedef ^ ^ IntKi LineUnOut - - - "unit number of line output file" typedef ^ ^ ReKi LineWrOutput {:} - - "one row of output data for this line" diff --git a/modules/moordyn/src/MoorDyn_Types.f90 b/modules/moordyn/src/MoorDyn_Types.f90 index 4d149b3d0..dc9c2bff1 100644 --- a/modules/moordyn/src/MoorDyn_Types.f90 +++ b/modules/moordyn/src/MoorDyn_Types.f90 @@ -97,27 +97,27 @@ MODULE MoorDyn_Types INTEGER(IntKi) :: AnchConnect !< IdNum of Connection at anchor [-] INTEGER(IntKi) :: PropsIdNum !< the IdNum of the associated line properties [-] INTEGER(IntKi) :: N !< The number of elements in the line [-] - REAL(ReKi) :: UnstrLen !< unstretched length of the line [-] - REAL(ReKi) :: BA !< internal damping coefficient times area for this line only [[N-s]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: r !< node positions [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rd !< node velocities [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: q !< node tangent vectors [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: l !< segment unstretched length [[m]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ld !< segment unstretched length rate of change (used in active tensioning) [[m]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstr !< segment stretched length [[m]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: lstrd !< segment change in stretched length [[m/s]] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V !< segment volume [[m^3]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: T !< segment tension vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Td !< segment internal damping force vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: W !< weight/buoyancy vectors [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dp !< node drag (transverse) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Dq !< node drag (axial) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Ap !< node added mass forcing (transverse) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Aq !< node added mass forcing (axial) [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: B !< node bottom contact force [[N]] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F !< total force on node [[N]] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: S !< node inverse mass matrix [[kg]] - REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: M !< node mass matrix [[kg]] + REAL(DbKi) :: UnstrLen !< unstretched length of the line [-] + REAL(DbKi) :: BA !< internal damping coefficient times area for this line only [[N-s]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: r !< node positions [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: rd !< node velocities [-] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: q !< node tangent vectors [-] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: l !< segment unstretched length [[m]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: ld !< segment unstretched length rate of change (used in active tensioning) [[m]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: lstr !< segment stretched length [[m]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: lstrd !< segment change in stretched length [[m/s]] + REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: V !< segment volume [[m^3]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: T !< segment tension vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Td !< segment internal damping force vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: W !< weight/buoyancy vectors [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Dp !< node drag (transverse) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Dq !< node drag (axial) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Ap !< node added mass forcing (transverse) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: Aq !< node added mass forcing (axial) [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: B !< node bottom contact force [[N]] + REAL(DbKi) , DIMENSION(:,:), ALLOCATABLE :: F !< total force on node [[N]] + REAL(DbKi) , DIMENSION(:,:,:), ALLOCATABLE :: S !< node inverse mass matrix [[kg]] + REAL(DbKi) , DIMENSION(:,:,:), ALLOCATABLE :: M !< node mass matrix [[kg]] INTEGER(IntKi) :: LineUnOut !< unit number of line output file [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LineWrOutput !< one row of output data for this line [-] END TYPE MD_Line @@ -1450,102 +1450,102 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_BufSz = Int_BufSz + 1 ! AnchConnect Int_BufSz = Int_BufSz + 1 ! PropsIdNum Int_BufSz = Int_BufSz + 1 ! N - Re_BufSz = Re_BufSz + 1 ! UnstrLen - Re_BufSz = Re_BufSz + 1 ! BA + Db_BufSz = Db_BufSz + 1 ! UnstrLen + Db_BufSz = Db_BufSz + 1 ! BA Int_BufSz = Int_BufSz + 1 ! r allocated yes/no IF ( ALLOCATED(InData%r) ) THEN Int_BufSz = Int_BufSz + 2*2 ! r upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%r) ! r + Db_BufSz = Db_BufSz + SIZE(InData%r) ! r END IF Int_BufSz = Int_BufSz + 1 ! rd allocated yes/no IF ( ALLOCATED(InData%rd) ) THEN Int_BufSz = Int_BufSz + 2*2 ! rd upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%rd) ! rd + Db_BufSz = Db_BufSz + SIZE(InData%rd) ! rd END IF Int_BufSz = Int_BufSz + 1 ! q allocated yes/no IF ( ALLOCATED(InData%q) ) THEN Int_BufSz = Int_BufSz + 2*2 ! q upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%q) ! q + Db_BufSz = Db_BufSz + SIZE(InData%q) ! q END IF Int_BufSz = Int_BufSz + 1 ! l allocated yes/no IF ( ALLOCATED(InData%l) ) THEN Int_BufSz = Int_BufSz + 2*1 ! l upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%l) ! l + Db_BufSz = Db_BufSz + SIZE(InData%l) ! l END IF Int_BufSz = Int_BufSz + 1 ! ld allocated yes/no IF ( ALLOCATED(InData%ld) ) THEN Int_BufSz = Int_BufSz + 2*1 ! ld upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%ld) ! ld + Db_BufSz = Db_BufSz + SIZE(InData%ld) ! ld END IF Int_BufSz = Int_BufSz + 1 ! lstr allocated yes/no IF ( ALLOCATED(InData%lstr) ) THEN Int_BufSz = Int_BufSz + 2*1 ! lstr upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%lstr) ! lstr + Db_BufSz = Db_BufSz + SIZE(InData%lstr) ! lstr END IF Int_BufSz = Int_BufSz + 1 ! lstrd allocated yes/no IF ( ALLOCATED(InData%lstrd) ) THEN Int_BufSz = Int_BufSz + 2*1 ! lstrd upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%lstrd) ! lstrd + Db_BufSz = Db_BufSz + SIZE(InData%lstrd) ! lstrd END IF Int_BufSz = Int_BufSz + 1 ! V allocated yes/no IF ( ALLOCATED(InData%V) ) THEN Int_BufSz = Int_BufSz + 2*1 ! V upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%V) ! V + Db_BufSz = Db_BufSz + SIZE(InData%V) ! V END IF Int_BufSz = Int_BufSz + 1 ! T allocated yes/no IF ( ALLOCATED(InData%T) ) THEN Int_BufSz = Int_BufSz + 2*2 ! T upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%T) ! T + Db_BufSz = Db_BufSz + SIZE(InData%T) ! T END IF Int_BufSz = Int_BufSz + 1 ! Td allocated yes/no IF ( ALLOCATED(InData%Td) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Td upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Td) ! Td + Db_BufSz = Db_BufSz + SIZE(InData%Td) ! Td END IF Int_BufSz = Int_BufSz + 1 ! W allocated yes/no IF ( ALLOCATED(InData%W) ) THEN Int_BufSz = Int_BufSz + 2*2 ! W upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%W) ! W + Db_BufSz = Db_BufSz + SIZE(InData%W) ! W END IF Int_BufSz = Int_BufSz + 1 ! Dp allocated yes/no IF ( ALLOCATED(InData%Dp) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Dp upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Dp) ! Dp + Db_BufSz = Db_BufSz + SIZE(InData%Dp) ! Dp END IF Int_BufSz = Int_BufSz + 1 ! Dq allocated yes/no IF ( ALLOCATED(InData%Dq) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Dq upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Dq) ! Dq + Db_BufSz = Db_BufSz + SIZE(InData%Dq) ! Dq END IF Int_BufSz = Int_BufSz + 1 ! Ap allocated yes/no IF ( ALLOCATED(InData%Ap) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Ap upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Ap) ! Ap + Db_BufSz = Db_BufSz + SIZE(InData%Ap) ! Ap END IF Int_BufSz = Int_BufSz + 1 ! Aq allocated yes/no IF ( ALLOCATED(InData%Aq) ) THEN Int_BufSz = Int_BufSz + 2*2 ! Aq upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Aq) ! Aq + Db_BufSz = Db_BufSz + SIZE(InData%Aq) ! Aq END IF Int_BufSz = Int_BufSz + 1 ! B allocated yes/no IF ( ALLOCATED(InData%B) ) THEN Int_BufSz = Int_BufSz + 2*2 ! B upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%B) ! B + Db_BufSz = Db_BufSz + SIZE(InData%B) ! B END IF Int_BufSz = Int_BufSz + 1 ! F allocated yes/no IF ( ALLOCATED(InData%F) ) THEN Int_BufSz = Int_BufSz + 2*2 ! F upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%F) ! F + Db_BufSz = Db_BufSz + SIZE(InData%F) ! F END IF Int_BufSz = Int_BufSz + 1 ! S allocated yes/no IF ( ALLOCATED(InData%S) ) THEN Int_BufSz = Int_BufSz + 2*3 ! S upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%S) ! S + Db_BufSz = Db_BufSz + SIZE(InData%S) ! S END IF Int_BufSz = Int_BufSz + 1 ! M allocated yes/no IF ( ALLOCATED(InData%M) ) THEN Int_BufSz = Int_BufSz + 2*3 ! M upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%M) ! M + Db_BufSz = Db_BufSz + SIZE(InData%M) ! M END IF Int_BufSz = Int_BufSz + 1 ! LineUnOut Int_BufSz = Int_BufSz + 1 ! LineWrOutput allocated yes/no @@ -1600,10 +1600,10 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%N Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%UnstrLen - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%BA - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%UnstrLen + Db_Xferred = Db_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%BA + Db_Xferred = Db_Xferred + 1 IF ( .NOT. ALLOCATED(InData%r) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1619,8 +1619,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%r,2), UBOUND(InData%r,2) DO i1 = LBOUND(InData%r,1), UBOUND(InData%r,1) - ReKiBuf(Re_Xferred) = InData%r(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%r(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1639,8 +1639,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%rd,2), UBOUND(InData%rd,2) DO i1 = LBOUND(InData%rd,1), UBOUND(InData%rd,1) - ReKiBuf(Re_Xferred) = InData%rd(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%rd(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1659,8 +1659,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%q,2), UBOUND(InData%q,2) DO i1 = LBOUND(InData%q,1), UBOUND(InData%q,1) - ReKiBuf(Re_Xferred) = InData%q(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%q(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1675,8 +1675,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%l,1), UBOUND(InData%l,1) - ReKiBuf(Re_Xferred) = InData%l(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%l(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%ld) ) THEN @@ -1690,8 +1690,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%ld,1), UBOUND(InData%ld,1) - ReKiBuf(Re_Xferred) = InData%ld(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%ld(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%lstr) ) THEN @@ -1705,8 +1705,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%lstr,1), UBOUND(InData%lstr,1) - ReKiBuf(Re_Xferred) = InData%lstr(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%lstr(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%lstrd) ) THEN @@ -1720,8 +1720,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%lstrd,1), UBOUND(InData%lstrd,1) - ReKiBuf(Re_Xferred) = InData%lstrd(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%lstrd(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%V) ) THEN @@ -1735,8 +1735,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz Int_Xferred = Int_Xferred + 2 DO i1 = LBOUND(InData%V,1), UBOUND(InData%V,1) - ReKiBuf(Re_Xferred) = InData%V(i1) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%V(i1) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( .NOT. ALLOCATED(InData%T) ) THEN @@ -1754,8 +1754,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%T,2), UBOUND(InData%T,2) DO i1 = LBOUND(InData%T,1), UBOUND(InData%T,1) - ReKiBuf(Re_Xferred) = InData%T(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%T(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1774,8 +1774,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Td,2), UBOUND(InData%Td,2) DO i1 = LBOUND(InData%Td,1), UBOUND(InData%Td,1) - ReKiBuf(Re_Xferred) = InData%Td(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Td(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1794,8 +1794,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%W,2), UBOUND(InData%W,2) DO i1 = LBOUND(InData%W,1), UBOUND(InData%W,1) - ReKiBuf(Re_Xferred) = InData%W(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%W(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1814,8 +1814,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Dp,2), UBOUND(InData%Dp,2) DO i1 = LBOUND(InData%Dp,1), UBOUND(InData%Dp,1) - ReKiBuf(Re_Xferred) = InData%Dp(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Dp(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1834,8 +1834,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Dq,2), UBOUND(InData%Dq,2) DO i1 = LBOUND(InData%Dq,1), UBOUND(InData%Dq,1) - ReKiBuf(Re_Xferred) = InData%Dq(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Dq(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1854,8 +1854,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Ap,2), UBOUND(InData%Ap,2) DO i1 = LBOUND(InData%Ap,1), UBOUND(InData%Ap,1) - ReKiBuf(Re_Xferred) = InData%Ap(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Ap(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1874,8 +1874,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%Aq,2), UBOUND(InData%Aq,2) DO i1 = LBOUND(InData%Aq,1), UBOUND(InData%Aq,1) - ReKiBuf(Re_Xferred) = InData%Aq(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%Aq(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1894,8 +1894,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%B,2), UBOUND(InData%B,2) DO i1 = LBOUND(InData%B,1), UBOUND(InData%B,1) - ReKiBuf(Re_Xferred) = InData%B(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%B(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1914,8 +1914,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i2 = LBOUND(InData%F,2), UBOUND(InData%F,2) DO i1 = LBOUND(InData%F,1), UBOUND(InData%F,1) - ReKiBuf(Re_Xferred) = InData%F(i1,i2) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%F(i1,i2) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -1938,8 +1938,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i3 = LBOUND(InData%S,3), UBOUND(InData%S,3) DO i2 = LBOUND(InData%S,2), UBOUND(InData%S,2) DO i1 = LBOUND(InData%S,1), UBOUND(InData%S,1) - ReKiBuf(Re_Xferred) = InData%S(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%S(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -1963,8 +1963,8 @@ SUBROUTINE MD_PackLine( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Siz DO i3 = LBOUND(InData%M,3), UBOUND(InData%M,3) DO i2 = LBOUND(InData%M,2), UBOUND(InData%M,2) DO i1 = LBOUND(InData%M,1), UBOUND(InData%M,1) - ReKiBuf(Re_Xferred) = InData%M(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%M(i1,i2,i3) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -2039,10 +2039,10 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) Int_Xferred = Int_Xferred + 1 OutData%N = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%UnstrLen = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%BA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%UnstrLen = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%BA = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! r not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2061,8 +2061,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%r,2), UBOUND(OutData%r,2) DO i1 = LBOUND(OutData%r,1), UBOUND(OutData%r,1) - OutData%r(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%r(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2084,8 +2084,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%rd,2), UBOUND(OutData%rd,2) DO i1 = LBOUND(OutData%rd,1), UBOUND(OutData%rd,1) - OutData%rd(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%rd(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2107,8 +2107,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%q,2), UBOUND(OutData%q,2) DO i1 = LBOUND(OutData%q,1), UBOUND(OutData%q,1) - OutData%q(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%q(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2126,8 +2126,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%l,1), UBOUND(OutData%l,1) - OutData%l(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%l(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ld not allocated @@ -2144,8 +2144,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%ld,1), UBOUND(OutData%ld,1) - OutData%ld(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%ld(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstr not allocated @@ -2162,8 +2162,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%lstr,1), UBOUND(OutData%lstr,1) - OutData%lstr(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%lstr(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! lstrd not allocated @@ -2180,8 +2180,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%lstrd,1), UBOUND(OutData%lstrd,1) - OutData%lstrd(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%lstrd(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! V not allocated @@ -2198,8 +2198,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) RETURN END IF DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) - OutData%V(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%V(i1) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! T not allocated @@ -2220,8 +2220,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%T,2), UBOUND(OutData%T,2) DO i1 = LBOUND(OutData%T,1), UBOUND(OutData%T,1) - OutData%T(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%T(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2243,8 +2243,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Td,2), UBOUND(OutData%Td,2) DO i1 = LBOUND(OutData%Td,1), UBOUND(OutData%Td,1) - OutData%Td(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Td(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2266,8 +2266,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%W,2), UBOUND(OutData%W,2) DO i1 = LBOUND(OutData%W,1), UBOUND(OutData%W,1) - OutData%W(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%W(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2289,8 +2289,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Dp,2), UBOUND(OutData%Dp,2) DO i1 = LBOUND(OutData%Dp,1), UBOUND(OutData%Dp,1) - OutData%Dp(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Dp(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2312,8 +2312,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Dq,2), UBOUND(OutData%Dq,2) DO i1 = LBOUND(OutData%Dq,1), UBOUND(OutData%Dq,1) - OutData%Dq(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Dq(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2335,8 +2335,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Ap,2), UBOUND(OutData%Ap,2) DO i1 = LBOUND(OutData%Ap,1), UBOUND(OutData%Ap,1) - OutData%Ap(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Ap(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2358,8 +2358,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%Aq,2), UBOUND(OutData%Aq,2) DO i1 = LBOUND(OutData%Aq,1), UBOUND(OutData%Aq,1) - OutData%Aq(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%Aq(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2381,8 +2381,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%B,2), UBOUND(OutData%B,2) DO i1 = LBOUND(OutData%B,1), UBOUND(OutData%B,1) - OutData%B(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%B(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2404,8 +2404,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) END IF DO i2 = LBOUND(OutData%F,2), UBOUND(OutData%F,2) DO i1 = LBOUND(OutData%F,1), UBOUND(OutData%F,1) - OutData%F(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%F(i1,i2) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END IF @@ -2431,8 +2431,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) DO i3 = LBOUND(OutData%S,3), UBOUND(OutData%S,3) DO i2 = LBOUND(OutData%S,2), UBOUND(OutData%S,2) DO i1 = LBOUND(OutData%S,1), UBOUND(OutData%S,1) - OutData%S(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%S(i1,i2,i3) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO @@ -2459,8 +2459,8 @@ SUBROUTINE MD_UnPackLine( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) DO i3 = LBOUND(OutData%M,3), UBOUND(OutData%M,3) DO i2 = LBOUND(OutData%M,2), UBOUND(OutData%M,2) DO i1 = LBOUND(OutData%M,1), UBOUND(OutData%M,1) - OutData%M(i1,i2,i3) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + OutData%M(i1,i2,i3) = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 END DO END DO END DO From b806b2d6e072f2d263722aaf0bbd51fde3ef6e50 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 17 Dec 2020 23:34:09 -0700 Subject: [PATCH 339/377] TCF-mods2: update r-test pointer to updated r-test branch --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index c22e86fd4..cbcb3165b 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit c22e86fd4a7130d411df0d80ebada228c38febd2 +Subproject commit cbcb3165bfe1a5debd7fc7fd065534f079fd7b98 From 8520e40dd23ab45b5ba13be27196df95c1aca092 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 18 Dec 2020 15:21:56 -0700 Subject: [PATCH 340/377] TCF_mods2: move HD related Outlists to OutListParameters.xlsx in docs --- docs/OtherSupporting/OutListParameters.xlsx | Bin 224114 -> 252669 bytes .../src/HydroDynOutListParameters.xlsx | Bin 154011 -> 0 bytes .../src/MorisonOutListParameters.xlsx | Bin 113539 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 modules/hydrodyn/src/HydroDynOutListParameters.xlsx delete mode 100644 modules/hydrodyn/src/MorisonOutListParameters.xlsx diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx index 461e96fa46db44ec5bec6a681b68f62382f38769..c0e7f544ef491c655a5ea647f8c33c10e8019785 100644 GIT binary patch delta 185623 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 delta 156912 zcmagGcOaK--v>-a_9lB1A-l+)Nk6hj*-5q#NjPPXMD`Z4Wwc}qWkh6zkeQ5(LN@Pl zov^8{egC=d9KZ88j_)3y?{VJ;uStJ@A*R*3iiJ&ufs28Mfq}t>adD#Z`Fl(Z zj0BQOT8>lDJ9`FUvXIr_hL#+MU!CfsVghDAV&1e}h}poTvinK>MO{(!%5v3eX>76% zBLk(9$H*w2aqW<4#MrjX zBcH{4^6U4n(8mek@)awS*Ly0DWm4Ugm!Fz?&3&6OmsK@(UTkH(>8rA>_V}f`#5cp{ zU)dCoqZ96=gMSrKJdRYCkTq=1&VTJc5L;NBsHXqgy11B2PhX&@*gjle|7uzB5p`*+ z#>I9wU*7<#6f7p%z7JTLHKYPLq3I7Y-hCshTK^b_wJ-PF*T2QqrObOJ<(d!Pjd9;Y z=^2wB$uVt(L~U5oJ^V8(SFG6DXDy^&|6Dw*dMq7SUt>iZDoyAaTE(yQeV;V$9SL<3 z!)Gj#mz3CNun1l;HQ9Ls<-Q<#DR!C{6H1z}Zx*8ZuzLDIXzX4}zWt!(rq#{Kf`3UA?_>-)0=nSwesA;x4qS=YKZe- zqCvXLc)D&N&oL?_fT^i+bMer5hv50f6qn(}`m2i6%LE1wCgj{!^oTR=a`Xq1@JZc- zq!wCw4eFBY1^Fh8Q|HDG%ikH?7LU^~7OLfKIUH4D@oX>~{plGMa64D_Qtx3i&Hl&X z`VveZo^wt(4Hj*@ZJ`M}JUll0FKC6i4LCj>KX=%2OgfeJd_J*`WIRb)Jbj;vdZ! z&F&YXB*i&CbrVHtsAfzPB`6VJetNfXY7%mEvoCS$D&~I`>Qz;_9(v(b+>HLdlxnV` z1{S4~6Y=7sFz@m4-m}3?!>I76)SRMh1CBeA+N7Ta4Dxs~R8ZwU+rI<*pD>5`c;(zr zA^UMFfIOUF78jx^lo_za?&OaA%ADXhs4KwWtKQ|hNJ=2L*Kc$HyzJ-*3j_ALxGoX` zXz<+b#3D8Z1`7!W1}XT_%Te&2i<^U$i;Kf~FDJ)R!)2EoHQFP;jssH01;Zc(WwzH0 z+9RoswHl*NaeG#(v`f|xr$Q8*F6=d~iWW*Ju6|lBvwN3v|J#qPIuvEOMfq63DMClmOty2Gdb94`yTSEobW?~Ju53;$gXrbf8FeSzjX(m1@FlvfzOjh}X|2UGGja>sZ`ocu?y;%P}3Ln46L~l&`!cazf z`J9weZ0Vdv{yXm@=H4q@r_bOx|9;;gg@OF4J6YvZeCqN9Ez_$U(4Sc0$7k^0)~m=s zP9LXwf+6d7EwZ)&xrxQ`s_E2@yq8$Nj?s<(W-;bgJj*ux=H{JD&bC==jqglf3|zM| z460xAZ}AWrH}Vr>zB*UBO;&eLeQEH`$nN0xSngT7)275fb_6uPYjD*hPAZ~qo>P+^ z*sHK+a2vaGH!A7ARv)$|`3thX?h^V>_e`M34vM63FKkwpR;=vh;WvD|n6$adWSN!< zANVQ#Tk6dlBdXQ^c)iD%`YN+i@GM>43bUcf&}+KAEpnP9GQr@tbzz!0!JTidl1=8x z6iy6X;pB1RSB%WQw_QG0_A!_@&J|x+m{HV5+tQDQubHJ&`nHLDP8vbHtCWl1sV<3F zh+KqCS?Z$aMB3CTm$wkc&x}cWpDYd8hYv};hz;@NF-1#=vO1&|KfMgwvpp1`y>HNX z=Ie*yHy>1mT=PHJ_Oa0ZY4;rSBPCY6y}^_|RmLK05;4fkq_d%Q&)bD@d~$gT+t}~Q zOfKC-=|Nk}>W7&-e@rj&FHKT%rA>!%R1ZLJdc-0}Yzi3)Cm8&1l(!N0JYh(Sm`wR# zB|hNP zJD$5>$VKN^{_VO!-e-P3Y(WLW0sVOloyt1GdEBw2)NTH<->To~$UkwHYX#W5G4Pi! zKu&bU7w3Oe@rRV<-07f_v0b=OeJY?oga%JdV|Aa<_Xc58_S~X)b^ePGvATykI-+`c z@*ep%wtNAXuCH&VMc9l`EXK74(?2Y07O{QdGe=HB`65H%*VI);@&w9Vo#$N+Zn9(z z&JsA^uT|@mbhsYSSDn|7YAN$Be)!fho#q8ZKFBklS!nxi^8Q`X2YRLwn8r(od~R#M z@kFj|KJ_^2(b6SIXebGwh;YD4*y6n9K;aOgD(XaPH_t<6uX0wW<iX`e{bVzjo>jMn;f|MA5lO z6m&-|f;#FZd#J)eG47`MnOwqIbDug|uRnQ3?S574cV-1tYJV0DX1`1Mx+2lty8k3X zIWac>S~15Y?k=&SDc7abxjhsITXm}%wU$E*-EC!3DN>0SGftcJW<4++ReaZkA804E z>iFf>4=+QFEWaDuejn1$wY#)!LqG3xh@6XnFv>BS@j?W5ic=dx`D=^Kt@&iBrxz){ z32kZFx+%Dj8JYH6NGA&p36%bbcWOx3JFa4MDYwJxE8%xqRw#M<2CwVRr~B>}24mQf z6gI+=A^HyHvMmSB_0?leKVL3e+y7oY`=aY-^-<&+=3He^`V~gmj4Kii_4n(FR9{|X z5+Y)IBUH@9?!@djYI^YU9f@ldp|jdGPcM873>*oJxG56aIQcgFalC2lJ292}#MX~VPyua6pbuYM87Ty!wVJrFZomZ~; z;}oh9%CzMsLwp_`F#qTojJny^L~tC#)##;oy{F1gOL{Ijl-4T5$8Yk z0gbZzgf(`v9wPnO!}_;OWyRfN>TD%-H~Up;+CA$zi;s-0>h5TNhg^b(!Tf+M4rLa}$drM}mD>lC5XS46Q#(7;lvoNkf_H0FiR=ETE zv^jVaQ;Ppps{T%YXZ5f1tGP|aCgxYLc1zkPmfrPB40 z7?;Im$FyOhJpDOKfW{HTkr$DrFq@MkxnCXEm~dhLhWLZ_#r?9eBU9-Mf|LA{e9=3) ze`;Jd-dks4H!ye|zBu~5_4^>H&dblv0?#CY#(ih|X2y_|kfp_?Eu2u(>QMZtqmgW~ zGCZ1OUvtR{(pCEg3z8O=-!&sNiix75^ZX?O4E`but7qt|nxPgVKd!_CaRC|adg@BR!1Krt7F8+h=*zu%*7 z_u)EzyUrjSVjCz?dV{PFS70wBK%U{*@5Gc(&xnHv9h_Qeb2Nf{8gba1UdeS@yvk<% z(3iY``WiND>tN?3t>PEQ>U16K+X4G%uinfTwc|Kvbp!0GyGZ`{lz?riMo=yWj&R}! za20pPQvnyb#!pH-lfmhePfg567ipeRV`RG`&Q&1_Xsdi_)#1}_s= zvYCpfS~nA{7|+mB-S(o{e0VWWJ|?h2@clFB)OYouJ&P0R_AX6Fuw9{bP0efa zTnM~u%^GrBThvQ80#_2RBtB-XDS;RtpVV<&o~S41&RV`6i5r=Ac+lxGPc=0!i^$WE zl^4xmpj@7JOkkM0gf!29MA%sgX(1l&K{wIV=70S_rGp=O8u$IP>oCK*#iz4Mm?;>U zsQ|YvSbI>1K_cp96Mv7?}}v2Ll~nd}WTCWp(u8B_SmU)@z=6 zsNfoM`?D2U2Bf&u63nQq$3FG2g!zv9?ObbO>K}mAp2=%P%s>qk_@pMAF|lh+2BZ>z zBzj*v_037qYUwLL4#lDIfMM^ZqQtb%g?;gh?{2$GmN8S=&t5IM+KhEWW>W8CkL~=X zW)ZW`g`~K(COuO0I$6uhLgrI?GCsqFiO{5L!KJ9A_IT$9@o(igy$A0tc0PTeQRdj5 zAn?Rpu1;jd^%^hjsjtpzH~S`Z3bUVMM!c%NVeC4QH6hZc6jy?+8-XQh%h>Br`-U%A zaih|7v(WkDn@4v=eNFMUlgQ|MYTwKEi}befazEW7#R%r>WzJi;!FeEGMZ`bfPes%U z-MRE6$B^W@Z@Q*;e7?(*Nvw=Xf%*Qsgd47lF**3Y>6eh@F070$upD@wK8`t_DrzB) zSueV8L*VhjL(MUo4ZCUF-Bu4fbzCafagw|R(OVCNf6sF|DP(cmv8tLR<(tcs4=rn@ zHoSM0?ZqDnkkyEmfAsde#%q7}GH5hg%r|nDVR80>tgj?q+W~EDnPLpwmVWup{ zIPI2FhKInsyK&M+=rh}&HP7S*a>ab-XaYL^AV2hT+^0V~Ya`+`j}ppq0 zFDuqV>HHG+um`ohqx7@Yey}BtVMq6cbNj7vY;XbF?y$!Lm|YL3h1b}Sq`BWb(rs7NaPLl&pt4kxZB8GX41HH4JIFqC! z=bG-XbzINxU4)O=SiE699wUhxx!!#FcH0ffuu@r9)ALKQhmo=3Ccdd22YFNB&$;@A zj^Z02MrCkoiI(kV< zNnh?I?(?4GTyY+heM$@3sj>;q`8{Iwas@rsmhj>5OWe~~(Q@MvVIU+ll_91Uq^ zb<~7Mn%=wO;uH9565;aPI4aA|1_D1xg40}0zjnb&l#0*4mY2358nx83APSD*D7$*2 z&n_VA)j0q0PfMkIEKD@MnaJ-!(&M$(FPx{R0;(_D?dsK}$l9w_^^AR$DXw+w=k!YV zn-_nd=~JK;=y$gI1)Uk)rbv=*YL^>XP3@EE;Yx!-OUOHb9!K(b$Yr+6-+qfeX7Q*y z^K?qlu7IJ4QKLFo;52!{la?}S`%;lVnZ%LJl@1?!!t`jKKJ3Ig!&oAncazDr;KuY- z;L;x&T5}3JS+WXlJvcH8qc1L{95wpRYq}C9MgD+?w~U&g=n-+6igtpWY#?6(rkLJ{ zmVI-r93`_&_?+fv=1+z?8*h~;^1(m&BZ~KbRht$`lX%Pe$v65k75NU%#>@O@v>9}F zExo+a5UWp=(;@O${Q zao&8g_K+nBvj>a%Y;i^s0@snOKd%dofD{4QEg zyXtDjIpX0Io8mjvZ*Gh+NUBLWT0f(887S|}Rk1Pxq2&aCm!**{X=#(mIyrnojv3L=Myf-}d-Rq=$$gxi&`Wly1kp7|ec`2o)f)}es!?YT z_Aghnb#=~c1)0k)L>!u^S%2Hk=}TFU`!x1}?wVnP&(+5c>y5#e->i84kP-SbFFPDB zBeQ)tvtoHTd*Axq{{0HV!;2S7Zk{qs&PsUFR`7a9E%CvntkL|}#^DsZXT#+pzT6Hp zoMroHwnJ(TJ-i|>K+F&pvCnal#FAX@RuU9<^L|KQXs6tVg0*EG_1uf=jP_DNpVC;4 zx@7$#*cQ!<9hnXTV(Bz zP(+yX%6NC;HPgAPIj*%nuWzdSGaaqjoMT4V<}HwS^IA*s`GUf{9~DFwOQiRNo?5c4 zz89GNeK~P5*)X_8Dzqf{I<*#wPX~wj%L|w|lcxv{d~cSQZgqD?*tZ&7Cfn}Ek;QiUb#!br%JzT zox7f(ggt0pt4v25n55+|?q^6nr+#m=Pozms!K><-PD7b3xr!GSws?~qq#}yXovO@$ z3bX(7Mlgjv4eU1`)W9B`Q1ksHdHB-n>m0HK{px3O& zgc?_IZ8}-A+i}y6*9P>>XHY2@_U{LLmFOCxzkC^DQ^+aXrN7;&mea0g)zBv~ip#Z% zQ{wUbiQdg;w+f6;b@wzlEqH#3f1>>4NvqH18*GKwy5o6SB91&FY{})~ZyqleWQnNq zNhm2oBdOOe@SZpc_e8V9DyH{A9&ug5AoIqqC#_XC#ScF=q{g|!1F`xNbBzeeRPf_S-ZNx@GkmFR)Km} zZZ7V2-k+$+wpT9M_TaCtGugVnDEo=%1so%2upzkE7q2+WOnm~+8?{Rlu_5zPYEia6 z@B_Px@*Y;~bqRJ>6ycd-8WAR(@2uM6OTsFIbos%A`h?^I7)MmX*2%Qz^@NqR4))6g zzV{k8|H!sn)5{*Rak!bE=E+gl3Z+HghzrHa&V<>FkLQzsB zCs(z`btuzi9_wIfG9Bl&e7ZBya202n&gc9~28iyhKM~^#3bWPm#*8T@FCrI?pL8bs zx`_!}f?6vE>ju8-OmV-ks0eo`$)veBF)>mC2$F=|Pthf%(PH95jF)5cR?iIIWAzfO zWS906!HEb=a4kfn>})JQgROt=6ck3w?aEnA74gSH8$2WHtp%GL!bIy9U40{ z2pSy5y?-MIMVclq&0IY4+Uu{nb~GVUiqQh*Ei*JPUrTz zyX%%G>i3VXnM)rnILS08H7<6vjb=6a?j|jyu_UFvkn{aBeP1g0uxE5sPL}C#^=y{h z{+|gK=y3mFx%S?fot^!Sj_;fYOQEDtqwP`s;qSDM*C4q#7HCkj@95XB4s&y;=HRfU z_Gs@8BUG^!cy z;RI(+3xeBy^g)AB(su&;U(w|bm+RZ_oe(}*6WG=nf@Q7 ztL2(2eo(`awT#&E*(JGhIZ5Aor;pv9!ka^**Rss(>%H#p&JwCDve~ID%B@DEH#|Pt zaNFwN%rYdrI^DJ;Xx~_OxPB=3_GmN^YW6hDJ6td8^plWy$G&I!WVff5ed(?Qk$Ktg zQkH&C#d@EEoz2J}EOPt5o?UP=-MiLU-{8ZqIWYirCh6vyTw46iE0RgSnf`Xa-Tb`V z`f`79@$|LVn0}D!`u@o3rjM_C!L}x~?m>BI&T4I8+0U$7#WsFC-r+gFwKlLK5<_zg z7wxu9poj1$n%0|x&E#*A_=)J8phsXYZbW3NXk%W`+oAikpfsb z_iEzeV&Hl<^IpZfNKdi1q@k;%b^auIaH`dY{k|up5!8K8LGig z)7F5Q;N7ZowqLTJ?5Vl*Ck^RTY2x~I0zHctp@S{aGjVo_yiW`!#4D2-M{&U7j~NTW#017sTs@1}>A6|@vvC)b2r(Cygh+6UvNo;9T3SA+0 zP5clZ)E$&(GBehu(Zu<_)tLS)g#=}yNR%ivarV;;cbeDFmGxnXr+x0R>P{E)UFY^% z@sop+hn+vP+HtY$rDK1t8BhL@vPyZ@g2KwGmX4ty!DoOI-am0xvx&2{)l>9>Cf`os z75-cFw;Qgd`(FtQU%rDsD(G^(T?*5oD-zz{sxza8~B}7AOKWO{JdB4u5?9JJ6g&uvO0S zZ+7WiaS|HRp7-d$6)z@$!o)@qEJ;ZJF` zvl5oPKvLMm$@OWPdD5EVc6PGSEV<@99Z4c0i(rb|PhiO;UN;5Q-Og?`1{M(B0u=uL z_ZM{X=~#acYP$5U<%`bsYx)b9$r8V!W=g@$)4$x^7|^o1EgJRG22lHc_L$hv+ef4; z7Vua9&}Tz`yPH#!GP0x6RUU_%*YyG{A!G30u)HjIt2`{=pQHICoteFG&KW^h2+GG{ z0UM~No6?_+l`!e#{FHhn9hiUoKe|q!xSfRjB@*@W7NFo37Z6WECh(PI#$j0XxmQLc zG0q8H37_#Kar_TG9b%sn!ErQkH)s3_P&(7;sF{C%0C7DYm8^izeE$q_uK43WFUP%b z$Iz>YjhDC`CvgKY2z6k)p;xOvbZ~xB9g;x*j5f^+>Ws+!;d!X(pYZjPW8gY<4V|J( zX-%VATfh!~S-2%-U;!P+NYsKWZX-83E<*!Cm|$ry$}U|7*apx$FzMu=))5!f404jN zBsZ*h&QE?burW!Q%>0CJwun`)&cJ#A=<+f_^A5bL7QJGG`WK}n!j&ICVQRfohrKYR zb%c%E^MurybdhkVzt!z6xHBQORmb^96EAF^sp)OC_J}neul%(}SE)E(Js`Iv-@f`mp-lz_k~0N$cSiwe-R9T`9DH@7|l0BuThF{=88aCS2_P zumt2<75k($Tc@OU^Ij)xH&=G>BF6M{b(U5_fS++Ffd#`U`Z$2+)#{wkGCI;0p0G$bi3ZYr>RO2s{VZC z%LGCIqPJ2`lbKRrE@$SIy=onS55PwOANb^KJI_risjC~QLDzIDWw+I8X+&de+}i54 zJ!CI@X^y0$o#*lP+oIYu)CNjJK=syjB5UjT%!Rk3{{0%F3g5mE2)7<=Bd zz)h)O3ch*uoZ6R%BX`5GZJZ?CSwwhX(CTg%TkI3r%;!8@{ZoGi0=si`1Mym;`ff6gc#THNHsr*k-gD_<;e#ca znwB@;mLgQ&G-$L64M$wfr)sre-)NGBnmf#%5Ru5Z5y5Ni7VP^?vcKDkwYwQbBHU%q zr|1X;;!EIcCKj8B2H(Loa&*VKqDx@gJ2+ES(4rex>n;`~)?}5&pq{Fu6<9`->())x zOm9)yP0TIsWwU+ZieaSo74D}ry^`u3uZC^ZO-0FLEt0yYb@5!}i#^=2)ODd;@*ug( z;dd%nGB2Cq^*3Gu|bqXRrlU{m=`#8WBj=--hCl9*>}VO z8ocughS4n7Y8CqxhfrZ!cLJ|Mx&%JGgI0QFDHt*Gq0B!5#)j&s_AS_V-<`)I;pE7b zV3=)~6DL!6yM%uOoR)0{XtY_zr^9nT+cIE*?V5YH`_;#BX;#MGi0MZ$d#OYI$lBfH z&9`N?JSj23lb&KIVs)~M>O&}k4D3EwS8=0*LgGRSW3bksg$)lCrH&vJcGXKubp`So z?|rXJ9q##LG?)cfF^l{Y1R zkw6*yy0$uZ)t;q2M&Mgm73}D04PH<6}o>nG! zAw*6;#rf!V?7Ik^%JCI{wTCp^>;mZ|EWY>n=oJMlD#wYhYVZy#8h(^KcW+(sEe`*i zQ9$WrvvO;2|CH!1Oj(Xq?KtL>fb%G2Qwe;TH0!&M`#cF?F_SBY4mHMTUfi6K`@8FA^SQHxyi{{3%QyW#GC3{`-!W#8&v=lst z?d`3Dx3fb(rpG;6-O7pPrp#vf*)%vXPk@-#Y7KJM6btmTcQ8KS!re`;$DhD)j>pHn zwPbf|Sy;>4cUDoF$K{_pU9Phh5zUK;Zqh9 zV`6!%Bp@|#r6|&#=6^FX`j|JSMVT|S-!gY=lM$FQ_2^GPYL_KDcFPqr0|k*w8?PX& zW)ibJe-cVdT1~~ftaNnm?{in_bKrO+g;2JE3_3w(t}ong4al%6|c6r?Pcothlb;k7PK%Q)s~U6F;^tB)Tt{l zbLU8>&t`CO2D-;bIQ@BZlVC%Ld|~P?M5_t{#k?~!^?INo?{JH9SV&x*MX>d&oL3in zzImcBS-9C{(@AtG(Xxj>nr~4a2#u>F4gnv$3Hm?!}U^Ewn@+DUU49YvB|-7EBU*d+mP?wCx+}Hv}8tIBxc>b zxXOl+pMNXZ`|%HLzn6=VGFDc=PlCZ}C(18Xsv39V)3C<25a zu{TS9Ed$ga{}D^I4G`>eo~Y#-CNi{5{!c-6iX&?Oi8l2UvpBiq*peWc6HNd`;A@fh zqVVGHNU{D)o$VlD1M9nt+bRgKHt%Y>tscAk2Xkpzhnv6u^rwxQFE!Tfc>C>6-+%Dw z!1Rb$SekR-V@auB#n7p&#pt6$D;fOohs6T9iL2uZN=#`_70~s`uAA2yxTki);6k6_!~@o&cyS1)&XagSHGJ&ewX?DY~C3mILu>Oz7B38{EN3^^RqcQCB+ z=e?(|{bwJ9XR7UO{Io^s`0#2sOj_*cJlH82{i)!rGUi8_!7!=n<#*7hr|^*8W)lWs zQAcE?HlEkIb!-4m1gspOV)%3Z76F|w<@YImPFzrkt8<5jB8MbW12>?>rsc8@IzASb ze%Pa!=(Etj>FEf9`RK4-)ya<`7u9C|q-e!T$K>sk5m$RPMNzdY=#d0r_(N-JD)S$+ z&O3lD_?zF0cj2PH^T!-ol5OsKYD940JDmN)_^)&5^4fHq(el4;0Ca6ZW=++W1v!eE zPP6Tk1@n;pxKfq^gvN4h!>F^K6;TxYVG(FE0;zHInIN~SeYAL&?#EgyS_hT#P``A) z?oL4W8OeoVkF;`Mb&O4AA1l;Elubl2N=Kynubx273BCb@#qtI}N)G>hCvz4`#kU?n zZC^S&ib_ec>1qlnR12_tZuSJEo$WYKk&9SyceWTK41spw*nFffBRYwgxdsaK_OO4c zr233CqR5XC>LTFw8fLwctbTPi4jV<)ba;=E_PMzqui!l~bV|9oVjQZ#IHLL>UzzDV5Vbc6qzmQ+Ck zun6V*|5!vSEY$zp)X&A-d`~^>_Z=FF7NUQ#`7e4Qw2c2>34Sa$VxtcFI_6L6Rv4f< z_;t1)#Ra@>@mK1?+G5`!ahA0`6{yrTOP;}ArrK6}AJ`sH)oJA`z|%n&d2d}!6_jfr zkj5eo%~YO(EHD{#~8Wmb72ha|2SmJISzKgY9=!H3(!Q% z-UbO7kQaxL_pgN{6bKubG_BsUCUaw4l0HZ|6fl5KnV&@nDK`yQT96G>U z;Z{~Hgp2$WdbnV}P-RQ;+zKc~Gm!w>KRvh(n5{$pDgLmpDA=K4)YfT-&^aAgf>Lz3JIF|is#F#V1NG)7$IZfO z@$j#uXf0#Xt@4kkUb>|#JbAaJZcqT{b)rxU0ABsyYK z)2g)5VQS|e{;M}@7Q`59svju`b2vt19x8}JLo;JLzCoTSKx+kSF<=MQI;aY|(K^t} zo%tpm`!2h{>JQos?Ikb6``GvhiU&!|5FNiSLf;sH!y3s!hg;>>8O{3RQAg&RG^$ox| z86h2s(u~=lRAI5vEdNnxLqeDL0|m@_qZ@?U@dtDYO8}@TVLNi z6VcZ>q_@_7VFNV7t1uRn)JVyvhYj};!1HjGG2begqK_&xGX1+VZcRo!5%ROq8~#Nlq3&Lz`>*j_${D1I=*< zr~tJp2ag4X^kYPL=M181Y}5fCO-zf~NpR6#Xe7Rv3h}=8=fSvF2sdr$kIL_(r6zuS zP6Uews8i*s{H65J#Xoh4s;P*0vC{SoKAKR1_DQTPQ1vp@A)1Re6(qs~0Tt~m`Kph| zz&=o)+`ZTXntDKi5Gzc-;b5K*?U#wA=1YJC&kLaz{&x~0QU2)+^B`H*#8G#T)N=0TILh& zYUA-(!f^?>2y@yMS~Ad%1zUe*@_qw50jygLYK6a!jafO4hn3?G!n<_bIOb>2aJcIU zx})tjhfK@ro?!cR_@qQ7IWy5GD8qO?sKi&{3)*j(;y{xLTmU74a2EMl7*3SHD8>5! z^+Eg`+{^rH;s4rUB8nCc++o6bf7Vl;A8~5*nMi+zJ_16gV{nV7Z;0kAF{>b2gpPR6 zsM^uTCjv!0vBY=g_+CT_u=&==zV|o6Sg9CiWG3Dmf6N)EMEbs1`%E@3ZtJN#q4r2e z^3-au5SF_Yhy*8=VLveDX+mGdw(ASMD*4WcK5y85!s|6GRT+9}T~Upr89DMW+M%EuZUG`wh zR}7AH4l+;1BJyMZ2AfL%VtS8m;QIXjPKev#hGx=|rPVJdgQb6k40BEpDq%e!?h5nU z)%eREiP<$~aC7}{4S?u(95aC&rC4d86GnhUlmw8pgF{QUiFGR-)KeZZ4OvLW`s?O| zm|UQrL>L@K!Fa%Po@M`vDkjj_0xiLb6^>#6u1bVagj?WmfHd%_6NN2TeE%^8pk=_e zBS;8;137dOrB5RJzmk)dupHVT{uM&4?cav1iBp0gijK4V*zv<8wNxQCon4{=P5$V( zvgnO&?*AjEwxBU_-P}v9r1c?J!~wns{1%`a(5ts_!2P$m`mG_t^Zp5g2Sf%SnE*KE zUnx+pi_{G5q5rV)|3&qQG~OTE(EhOiE$&j_VnZE;OTP}#`5s7cllu`2)+oGRjHs~& z*@DJO{#eWiumu+Ur3OHGgrpBsZO}LX#fM=E!vID_j#eqj>$ePKfE`7mFgR9mYp5hSqb7ED1@By2T1S`vWcT-6 zjvE@G&>6!qnQB6i4TtTIt){K~ejI{!=#?JZKXSZ+h{T50|5!n4NjUcdtB*r6cDSbX zJ$VpBz=?ot7`@zs>%M<4z$EI4h+DM|Z#MfwM(At?*JXgMZnukqt^P*x-;YBPfDML@ z!^Jof3lO1UcTDywRbJ`=wfR5d|C@3Cxf-bov8>o|TRD$2G7LG%^B?mgqP~uT(8;a* zSf=>GtZMqF8U7>X=K$11nlOYVeh|Eh79+mGUD-bi#oD8&mTz_DvW8s_2V>jp&VFn( ztzs`&&CG6XJ{>I1%53mD+>3Ogpuo~kYwJFci?x4#@2D%Yg$feM$xNaqmg9DQ!gnU- zA%Il|N(^pq#BxuO;)61qI^lsm$ibjj*kXI4sLCJo2+XEoI7G0!!u>ixKNQ=;t{~m{ z|Nf-h9gUa-$B@S%{o8_vCejWYrF#F|RmuDV+Y7V}Ya<4eFsDILzRUzDV~WB-#O`>|=lj-smlM4nd&43Qeu(lpS}q z=*AOZ6xBA@8OGW6CDnoMAT^@;`5DlklSDrbaTiNKAsVg-cw_*&K`;ya-~?t$7Ju?v z{5~|0TH?@xTddvg@eaWPh7&iqmlh`>3oR=c)$)JD3b+6NWeGIuXRQCj02rJtFNKGICkBa&m@H!NKQJo_y(>&)E53d{_Od!T^ku(WWj+d+jzZsQmqGs346X3Df2Hx+&O$N=22>~92{ z-wBqeVjVP!S&6nkP=wNfA`}f-Rh}Zuxe&)m3B&-*wXTzvERm9G*29ah>1T<@HSxA`j$Enm% zv@%jS26^D4K-YEu6E<*JfY8~veEXLIX#v?F)c~af3PR0d@gY$10yGl_1dSfzXv6&m z;*KVw0Epm2_vL81VQAzZx&gBnba7u+0oDS3sd_UZE{mKzkWpX5aSsi*!RS@z&+d|5 zFA=x{f$4#ZMPMiZpYxDQ-j{)_sbV`or#2l)`5?X4d%GzMffflmUcs|XYvu8$@-Ug! z7V$CUo|+|A7e)Di+koBm^SS2hPm{Cyi=#VrRK-z?Z9wL%9EhG_@dP^RqXXxPgENiF;GI? z5^u^+k}%bKz$1Us13I1m&D^WSr+)S-Qx9HF=4_I6X*QKibs$-$u@^uwsDt8P&E?i)TM?I|`mdIF?&jLOoAtGN}N4LVO? zW#MV;sDUB3&k>yoguoJ`fid7JBg2G{E;5&n%9Rt9+ z2T39-$%VJco&!AZI0ArO2H?78C3vg}2M*q5WnT}*(!w=34Imb@2+gsObK6X@m9jNs z7wzx8vQN4tdpTT4n2_|u?6>Tm1Hv`A!ATsar}PDP-va&+7z(T?S{1&0>UOSQQaw6v zZ12^V4-r5)rdEi)d|;PHOksjv%~TNBpAkH@0OtWsn}L6V-SdzNi>WrxpI{hS&T04- z10(Zb6a``cjQhbc0FC$`+YBFovXSWnkU3n%kc(IWY?lDh$_l)rQ1DUE@c`geLeIB6 z$Gf3kL;c-yY{I2*WCrkL8gBv$IG@lN`CPET^09KM=yxo;XYa&m!_$H20PwiV=&j z%NIZ*!RKFgq`)~J%cWR1ZOSYHRwa{c_xiOW~?S?+(e>EzV)?Ktxs&hen8v<6vqb6lf{I?o~B z1CmG&$Dll8ktbpku<3&9VH6n--kTarcR{K}ll{cL3MLV52;o$PBpt*)AoxiJT-3*{5Qy0x2hr;;vb5EjWBz&2|EIr9w+x%`v!^`R z3OYx*_w76;qJulkw?TagWa0BTkpUSVfG!<^(RRn6M?CPT6AVa|nM8&8K*4ab1mnoC z8@J-}hk5sa$4(%jf;0%8vA_%|S3jw}4@(tp#eyFJscIwb2^cW|^BzJW=ME!VNG6(D zocTd12ebvqLI${?D1{Jn0Z$*{`+*a_09ZzQ7_kxACT0*~F9--#WNq({4@1caKIzsi z#?H|Y7BP%RtqsGNLIm#@lVcD}hXYrc9AH(2~ICVZaGIUAgfOJ_$lR z(mq1|!(o`nDR3`~6emPs>_lP2C(?zxZEcdO$QAI;3oPp;@Xj^Nfqs@jm^A|Kc=^<& zSYdHsSvf3LrW~WH$Uy^P6P*NK4tg{&m zJ2VJ+C0NNjw)*pg8W(|gSaT^)lOcsKi7>FA4p;XP{_a$I2{S+7&iDVOT%gsTRo@i! zqaeV+(rCp+p1~lUFMROvE0Pz1h5$%wfYL4_{KC5i&)}AWUjBJeTiF>PL=bZ`LH+~) z9644F?B}{byE4g4LAK$VAnSRz1Q2-yUeDOkW z#Y5gw9AnS_lV(Wy@Adjjw_d{2C4jYC$~(eg8a={j#k~`n`soE0JB*|q;uzlm_;6e} zayuvjds3bn1^)u=IC$HMm4k<61=@c#{isx%ukd3JW)3|-W50X6-e93!z6>&WxdfnJ z5WJ-0?DA{OAyHwkLHIpU+GWsH*M0!8>3@B-d&++xqFGv(99LOz*JvoNIQF>{$eng) z(Z+_z>4GkI%A%j~_?8~YYWdHJ%#-1T&FR)}VdOKC=MVs*#s(ydMT2pWprlwyCOF{t zeM7;{)6pG3A1)$j^0W7H{J`@ zV7I~T#s*j}2rLk;a)y-uYA$%F2VMuS%xPC1gT7c}*_puL5ziHDM=MkAGK}fMa||T) zBgQ-oUVZ5dQon{L9l+itO(ftaveLRtgik0N=)tl&z={VJZos0jI;}5m57%GloeHWy zcp#0h%y0IkhZCz2v37I*Mc%l zh=I@X)Ed0^^K02P7;ys9`vZn>z@7onhXAo)co$4dCRMo4Q2qx-ecPhJOQ{&5Puf=U z!xzn#k-5XMCH#wI&{e_EG;}f@I5v*?-hSyg1mcDb4~Z3s8zP`P;+a1YTX2X*P`zVy zs`4ENPe60$&=WMxJK%ESRx-JbjdXy80#^kuqA@GKjy?uwT`Z0cS%e9PV9FP@B9RHj zF%6T9T)4`znmIWoyQZ{N=n%A0{|4^DL)JzUE;QC5{1FB2^KA| z6p+Sg$s&*C=7DNQayWo;E#-f*K>*D=9x4D#1Gg1~ei;x76HczG@q_cpJY(K{Fi)X*u_rN5kjN|#h~-!dBr;Tc&6D~d_fTS4p^JfI?B28Kf}U2* zUwl9G4X_mGSYAjE1JuA!#x}Nz2p*1a6_^pemTSd8?V#v6(S_W>r4_$&0k3*gBFTsItZ z1~AWYX#~3eXA4pQuFL@qAB(nFa{~PD9LBpj{wm-&tAlU@TtH0~esz(3dkYB^F5Arz z@}|^*yA~@4dEN;;^w_$;pDx#gW5>q`_z`SBH5c%SOMsfckBq=*BMwynAM}16{j~O5 z4;XZ&!vj{D+!=8gZmrJ(xS0gJ3q4eX?KH*u5}2O9TB-$r@GA6*3xES#$BSbC{6e0Q z{+xcS=eM>vP)OpMOV7QzX)rThXSU&*8w1`OFUs*qRm~1RnGIXXyU03i?C+T0&G}mO zMhetna}W{9^E+UTvSTgl&~}~SF87nQ&eBJ5q3`|GUhgktfyYs~ax$Bu`e#{5A~B!X z3-3Z>aGx72u6y_O?{@($R`SoTgDK%_c%bfFcZnZYxfmWBMS{|-*){=1gEh^H+Y0CM zcUjC4gHeWUahSh)jv_H53w*-TdLS;2J+;C{*;~T3xr;}KzkW;{Zr=8p+1%sp%D7vs z+IWUZq*2@pTH=!Cw^lCBYK)Gdg+QUO5Oe?a)%zxQL;oMjzC51FE$aUmBT`g`G#DzX zgHm*xOl4@+K%ImJN0Z19WqMF<%G_|IiAs~9a+G;!AaW83k?E#H#>_LnwfFNJx%YkF zKYoARkA0tKKWneO_IIuIUF+<6PlSbt$An0;8-t&jD@(3hTEF=X5fdkWiKT@*VQ1R&W-aNnE{yP{cGzO$Cr?-__u|vcs z0sD&M^+Q9u;y0f~k7yf`DfrbbrKrW5jtWnr=V_vQKV?LHk*c2Hh%r^=O$ zrmFDBOp*IJeMc_%1{mR<7HR&q_aUDcdLbqv13S0)eTkldar{vtdf^q{fWL%f;xp%m z@5_TekG^AbB-Is43&jzg+PFO!eVdWzcMgk))P3TKLs+q%!EB^g0##EkeOYDl-b!9k z3>Z!_4_W`yB%;jTUiK^EDou<;8Qr5mhGIt#PVD5`ls|gFMw{j5Mg6D#%20wrH zzDUllbJlOO%=~a2K?7l#9lfMXopY~Q9hX;pym!S_>VpLN#X#jmZIgLjbgOLLJfZmC zQz1))&E~F*s(?Ic`n(z&P9c|_j}~E5+NkYCdj?yyD*RUOqw%%Ik36}xrR;{V^3=R;0bVU3L~ni>xX=|=b_i|S!?uua`_h=Kj=i=%C?4m z6f*`9bM;*sWqsSjHRYFCeVS+4Ph&l%7IGFSevqJ0dBHCI=yho45SIMw_-!K8UxtY9 zj?I*#^mcg*viz8FD?jlNX~Or@#3h`2&!5vo?tD{&AJ;h6^1vQ~1>2AoT%F#@e;y8o zmw@<+$s6%3TzwAzViw@Tle)c`Ah(PBtjPV+8v=~6Hi+H2Th-eBnKqH_^ut|-7>Az%j_Z=_zEC36oe|Y4jHG-Pwa=qjp{a&|g ze-fkn6`&2+@=eTik+$3iqyiWcX)$Vft6`JeWeoE>NvhY$S!HuA`OFD7_>b4{wr~nq2gPI{>fy?A}j;z2T!1BpD7nkna ziiEYmKWzg~GO`8y0qwccGP$-&{dSTdj-K^w+r(LOGIoJS67`$@kJu0~N4a~|y*Mi$ zgk%i@hmI;ij;DE0$Ldo%-*&>a<;Y^CE7!KrT>Qkrb1akFW}M?^dgc8gom*Zfg&;jv z0b)z!K6kc*l$bEpBNXv`fCf!TScdPX<0}i{oiH#GMA-m-yg7>3zmX92+lq4zu$yfQ zmq2Q7f59T7_CBVc(T2lvRS4**MNORhmYW3b!81#PB^S-fQ;rJ<7laqLZ1IVQF^$3R z`J+=in$jPOwF*HtwNTWLKA3>sqZFwQ^eU1$MwV2`G6MWKB9)Te9}iwX0t*E83uT>K z7Al(}^ASbSMz=G4U}UZU>T30T2uLWHy>Wur3$EmN{iOyTpyem70sN5>Y3%Xd>NBS; zc3fRUit4vpYT;5(?S0j{d9INhUBoIlx%X4I9x5^9C z87DrJ^O!(CbZUegaPfAXz1So=UT-0d?NiB4@Ke~lv9Ct$sVgn8J$60{)4)M#)4Q0@ zIA+bawLn4Y_}_nGSn|7M3_Ia}^DO4I*d7^8Ak+cLBFI)nuwQTiU@F;O<+yk8e++B_ z3l|mwljlu5Sj&BcG{EOmzyJ~73Fk7-9z9Ye&kd##mPt>0!eXeA`wjX>e@haS5sw=L zWe@!iQ*WSfn?HH|TJ9rUQ5Es&iv_metZo@LPy=Rx)65Zj`$^G*KCzTSP$IkHp40L4 zx^>hUF8jCX;V%)uXHug4IZo$cL$63rOGEimp>j>(ZjZUJYY1jMSl9~6BRlf{C`lTa zmaE*I8DB6tD+zN)Hvp>P^~@K{R>f2xKG~;v2}ly*JKKQRZaESy=>kh0f28Ti;-on$ z*x1dvXVhbE#;GZ-&+H&i6XC0~0TyCr^~!oH_D9G8>pX9@Wn7pFi2_Wu5S{scdp;)r3<}4AcM4i z)5$F*QF>(d4&2uT2)Zgf7CkXCzrJC4bolylH9CnxPYR+O)EV!A3{KA97jXP%QN-M#@JsJkc<)g=6L|J%6>z0779W#sycoIc9h8FM`UQuN3At#&DE6ACl5O71e!vz{0|eca^L zQ{%8~=z}VZw49Arx<1|VAn&%{`Vlc&g12dJ9X@T_y=|$8#St{dEcDNT>{4L&pGBvaw)b5_`Z|6(~~Pr~g5d#>krK30EC z_uH`h5r3t|>wVI~bg5w7Pr@<|YOnp~i${o`wpz3KS>JYo&=NG^+mn~UpY}uj^@`Uz zhQfmE!QR-V%?qT(7xY$!-A#Gu5q2_t%5&}LTL&a}9~zX4&Q{$mT=FSTFGae-!H03+ z;?leR52g2ReJ;6=ms2{$T)t02^tt#!Q;;m|%vg5=f6R?ky|x9?I`Vak`bT)WyTS$L zXbG09nRsq^Avc}qNc%La<$-Y7n=J=Y8uen7u7@4iaHHG~ZdMDlQF|S^|9YI#^&~;Q zfDLN}K`B)m0_btCqZd8{?HOcW9C;utxZ2(N*c4OHi8bh?DO&_xHtL=NhM{6)71T2J>9?4<%HTt_ws8O}~0TFH&dDjR)r0 zW+`@-^Yl&BUenaX?f76>f7gwCju1BeX15+z5vuGgzayP9I{ZPwzfO7j2cI41g*Pp| zyCYI;9^Y5}Slil5(H1`9p@*`jBpt4(l6(gIiH@fEa zKI>m@OYfS1%(EwF$DA>Fq;apQo&Q95ss655snf)iGCfnUzQaD(Ryz3(_o*J@&=*`c zUQ)x9RrFuCx85*YHu)Ztl{qQxHviC;=aQ)ko=WBV?$uAbJl&g8UoY8beN3tYmi2AP z8+y+nlSeDbPoDlXqcC=%^s7aU=R}v$ElP!hmJT6Nybr~TI)&Av0%c1!((7_W9`AC3gmU~HKu7jrWYTaogcSU5t*I!1pL z_Stw`{x10PXdrz-`I8gRCCd~()ZN}yFIBMexju(JzkJ<1?b-yD7y8#9h}AV=lMyVx zRNhfyo-J8}_B2@6x0IMN(5|ufgq8ejxR_OgongK~?qEqE^I&h^tQNzBu@2VQNN|7i zNNw#{f35cDaAnqLK&Z$3a-zm*thb@|spUUenWMF%xea4OBBQm$+p(cZB|{PIW9{}XmO5|7npx3J%bJBdzh{p0-&eQbRyCE=XINsW|TI-xg zkjhexB9+FbJ8AtLHLJvF*4f>qc|3E{9=z>O@)*p0@uGZI2S-<@MqAx8Fb+-YVbVUf z&nxiMX5mHuOfHExJ5ET)tn^aJH%RuJsQS>Cz3VvX9-9uGOy@r+o^{Q7 zewr_{=63dwyKP3`CSKbr?GPd`?rCkgN^kJBB}YY4#SaTMr-!|w8|T_C;@A#37RL7^ zE*8${NWINJHmlN_rJK<>Pi1@E-u^)8<@xN538GGG6R$FRG@s}ELtNMLdK#Z)%eh?` zFEA%nz`Xi_ly(hAUB~9US%G>{yqOJs$&qmV?|zm+>@CVtj}IqZWtQq6+fg?3ZpzYG z_Rn>tj3d#Q$!Ck?o}hKSn-!~?HtNB9Ez6fAeDHD1Rx@nQV65cP&9(jY&v(Otlm7aR zLP^h=XD3CwXH37rAOw5rR;RkM&eo>#cq!iDHxKg;%4LZKl~lf#j8S~YDr3HRr2`86 zJk;a)T%bir>ME1>4H~$w*z@;u{nqPRLX{m7vjm%pR7zro2Jgj&F|*sw6x?8fROLRV zAJzS9#j|EJ!%r;(<;Zgct34#M755jVZuv(V*5X7X*flc}jplyyDP!v8!Mr)DFVs1z zod#LVpfhvTUPF`N&s0&To~kNuIWCO~W%rwgv2iJu7Ue!)$DI4hbwB2ZEyK!Y> zpZ~|Tg(}SOH=690!a|i_O*bnaHoo~?wUf2zq$0-|{(Ef>VP989IBsrM&pByT5oES6 ztlIUTtgPvEPS+Y>sb^&wiQi%WnT3|_OWIN%tTPa>MUUmP&7So-+Qgk^xNnuns)Bzm zoV+n5xs(otw6q6w5OK@g#q;ay zO#634q0@yvb=Ws*e^ow+gA8Kr(6Y17LtxfbtG2Ip@_!L>sc5#Hy`8zii;ythzt}d4 zb0TXZg->;!l3zpw#Yy~SluPR3`dSP0>02XmaD>ozh%IxMq7NmAddas)rj(Z*?)Gdo&jUmFCmCuFFqfw%+2>H@P|5!XeDl zOaA$xyMCu?A*`!Nr(ET9?6o7>3xj7}cCe3O2s(*7`>UL&r*}P*f1RxgxymVTN)_!_XpziRi>c&MnmYS(=OZ(weMnHX9;>>rOUs$H)*)}hkC3o8 zuoBxRC*#oi8_|2mSv-f%SMOw*eBtDLEvY;_-#KryJ;)d;X8bJkuxgbnSn$-di-IYe zTjzbnaO%dCwZf^Ye6B*;!dD5T+g}%_9!o5&&zfEtY&^7N)LF*#U{jgaqurv>xmj~H zqfDy8f9ZL4YYU2>`f=K9p{FNPV72q+3;oS1yMzBy=h( zyJ~dcF@HcPQ}(k&)0D3b4`m&#MrA@ScQ$mzS&0^Rlpk8ZZ@{}>aL%z5;(=QEjKF0) zPUov(a23b4B$Q<~=(Dv#`m;%5*L>sk`!al8-v+&?DweXDoO|6%>CIvPDaYz3)ycX< z)w3iWHsxNYDZjCemyg@;T=Pm%C8=BBX5F%da+jW)*%-wf3GWlA6j&VU;-ea#^wmY+QBLXgYPxURf#vW*pzo&=fdI5zeD3{^fF!>?z8>&JkNf; zk%#9tTE9?Q&fhN_Sk;a2l~a3v7#qCf-wWFc($Les!K3n=AhRod2oSs`}xrw{tX)z5bJI)OW_;Q;zk}yTtsb zDgQ9;e#Z|RWBD8wG*{V*_qpLxo6|R+2~WQ3+7o!DGaRYl`G`x76*k=~398Sbc! zh$VEX`P^-1X6UYVm!Pecu;tLZbmXUd>jhQL^tL=)`9b~h%H-L0ojUT1!s1K6OVMV0 zi+}J|p+~Ywzq_%$6uz81QlI%QF`Q{^cWPaYQ>eBmoY_k?dF((s-|xIg4_o}Il5Q58 zHxi7lJOn%koYlyX^`8jY>5b(ono-vnKfU!9^7_uc1XzNOW@W>|sWUD+oRwI?xe+-n zdgajw3>y(x%-LqNOXn*)r{AA6Ib3LlgR<*6rxt|m|DNQn0+U>v>UJM%#`GC_J%X){ zS0-Vkxqp7Eu~4b(3!-rATxA3RUzjx7HzjW|t(qH?=2?nbZV2}5l)ySI;r9)(Ez(+f zHWDAyxr#LXGd7Dj`MoLc`4A>G?a-rvx#hDv+3Dm697-C0wSsb#Z3L-EF?~BY%R3!= z;^KZS%$m81UhC@eiM$b`{!g*Gc?!x$cn!u4w}05f*BH?+t9ZgH_Dm6IAfAvgU3?QI?Gk!(9Trgo!R6s zh2^83kV*g}_Zthx3G2Y)dKKOjT; zF)+3!hBdRo-CjRCt_9737a4n+9Es&1n3hK{?FLrkZ^j4<6|0s|j>_C@H&Is2C<5#5 z16Ow#O~7Wl7QjiP^Fcg@AP3YxaM_=XM~@qU*ZM%(Y(mT8A#((4<15bZV{*lBp8Z{v z7P9yHQI>|T{BE@yBTbB-%!-_up?G5Ct}C=wY7@Hh1-&W5E{BH1j}rnV3U8athN|v% zi;&2FO-($QuFfZHrG3>?ceT@ItI)kJl6@%!a~bpN3$tEt4l~dZJ(%R=msO>AdmS5j z)_3ns5!87B5>Vw#t-8` zfnWV84`8h#r_pO+O1j^FEUr8&@f_j0t5s-toC@B9$A!`2wQG?cs;@pwhS`d?Dq z)!NBV$_}~COkHvOvc7duj)yJy+B}8jq55JEEJMU{S$PUQt&RzXk{bscS&K$|xNs3l z=>OcTYOBEk?*N8?*7U&fKtlih0zjEzU={kk=z(}6 z!ht66f^>CQL~@3Gjmjhts9V4cRO@CHdX+=}Oh0j1|8Whd!}GHKyFU9zfESvzvdR*b zBJdCX%rzsh<%coJv$0ZFKFU8{?95X)&ghis@Xoif7$fy|2mi~Fl2l&#b%8_?o4=is47*9Yj4q;4gIkiyt(A9&#bRt7`eS+|`tE%{QE_>qC&Q&A|otE*| z+oo^#0kG~@-A3gj1f^;u;&n0bU!=-L-6b%V!Fgn&<0tcK?$8sA#$52-5*gxHJn@9e z(BzgSQXrbvi4Gg}smSl~57rNZE5dt`uq8p1CWpKgJTga;;Gr3zXbiMrU8IkJ@~r|G z!_16j$QWc_6c(Vf-Z{T9Rn$vic)qdY>9drGPB9?RUGRk2<*c-M0H=b_b3L)DAwbp| zLL1BLdkgzhE{cTf$T!3?1XrV|g=#cg-c z5vccwVK`qq*|LoA!P0Wnv8t}$jGR{NTZs{un)gDXN{L8Py^_KImnwtBI2eG5g&PCW z0rjms&QjTKY?R=kI#%7q_x8%`jy+X_1NIt5?k6JFtUT6n&$YWT#Ma;Z{XO}U9SB@& zHw9UOdWz*o9Yl!JXh%5j!Cldve>m2tE;hIJb~g;Pad;b1cMQ1qw6*IfXw z80VWngJ4MPJUy#W$1fOsEs|9dKEN|Nq7~c083aY}!x_dSVf*h8q*u*ngXc+^CfCY5 zf-+Oa6*>fqNrfs>yxFHj3QEDi*ftGQ$XJ`*GG%f~Qcf!jN)~lo(Yc_XuTqi&0mtyb zd=!Z`vT&4Mhmn{>Ua7*9IN;%VZn##M#0c3ct)w%NAq39h5X>RynfMMwyk@GMhGSD8 zPVRD^QD6P^7D@{qqj8i#Gi}CE9siBQ#xX94Js#4|_|^wpMyt-(zJ;ar3a6zZJ1qo^ zfNby%1gwCNLo24XG5w zD$w-HRpz+U?YJXPIaG#-!d5noW~FVHW)pGZ0y;eU1U47rJYHJJshDQ$@!Qe%+{;iK1-fWSNDhdOu<%q8|zOvQrE=PH0&uY-(P^AO?8Z6;8-Mi$+P`o;7Q?o-^Ta#1Dk-@ zf>5GyeY;5Go0DfzN`kddo)kdeZKL{4OFI zq>w((Qu!zq1Bsv*h&tmC6{Q)?8R=8;TK5K@MK)x{CW+)}?4+D5)^U{BVF(;&WB@@z zM7$H8(HULnxj#zmEga5fNDDWk{0Cw;q+==&aj%7lsz|Gk-`A04nU6By|H*xQT!Nbg{dzNIpj-AJA6?!Vho|p8PyCEzU$W!=c z3c)lALWq3kBST4s7hS?uV;dO+2OJNkvuO;7wr+WG^BUV00YCX~reOv+2u|yy-r|>7 z5?-57*L9)=L$B;ka9(c}bVP-da3C%T90vGO_@WVPdYD1v+Xe{4&8oE;LiHu({1L-W z09BsPb`>c_04*sD=L;W!(?hqoQlZei17|^$u=mR`}AERTb;C31{>Zxi40{SBOG6E==zy z|7@y`9SmSJ9-QwVU>C7@z){|1&7I!STRN*i`j zdnL&=nUVC5p?GYBaHkQH^R$Tn;|_(Q zyJq~pRZG2s5p%YL3jlgO_cY>xvOuecl$P{*FLL+Z8QDwaVKM~rR#ZO6;F%!-OqC3r z-PUE95LRhK#nC2@p9yfE*vux7S)^^?&>ZKO6V)7v= z$qud-)d`wcB#3_Xh&Fd$F(omz zDMP9l;h;rSkSDR4R{mXM5kw@K#Skn2yNT8~DqXn|vViYSul|04Sw4pF4E5@^#G&EL zf0^O`Wd{(t{mX1WtuR6PDT9Y5k@F{NQoCn3MxgNO*Lo!5`*~v{b{Y^};RIo05zcN< z=05SvfHRs4tRs?V5tTAh#-p8UiW8TsOzuWO8ZJni<^)j{q#YL2j&ozQI5K1>#%`B; zp8sn3`B57XFHwkiAw(fQ#mK$MDs&^JIDlcP(d)@mSQ4tg5QVTPU6LsUu3`Z@58ffU z3hilt?bq@Yt`w^Q3_%7myt+uyKURnL;zQzChXR0(Y_Y9nwN|DnxQQhpkmPwXONsgZ zm?vn0kbcztbM>1h$74>{PSV%tqBxV{bT;B}7)*i;y&vpAf4@12<7|-eSQ&Q&g4}VL zzOCVDnu5+J@Iv()i^xarO?mP`9o&lq!z#79|M$Q);wYj=AbtP`fFeH9!$8^_hd8F~ zNt?2uyaH_U0&g2wKaNW=aDyuMpdYE0l90x=HU5hz|OfcyEg$Cz2h=h|D3*R4xm zeE0*&j8NcHe>;*465!A@10!zN559V5w*l*9EL5S;(ok-&DiM87JIQHp6nHM9Iq%B# z)_;v^Bm!R|vi7mZM?T+J{>kAeaG7n!>)X;J89hM+){Pj<0kQGah~{KgoUHHezx59m zJX`BYx*g=M(JPN5#(4=)=_ugL<#I0EnQ^sZqW!iI=n)rf$mk~@2>udh)43-o#Zlry-MYtKuyvKHmetZD!*(C*$XHUrG7}bN%~0a?V$3+NQ97)rkm9ffiJmGxID(_A)C> zTRm+^57jHZk>WxNFwksbh2n$KbJ3ps?jNs5PKw+Wff8t(?@yu0d2fb{5z|tnsEC85 zC=RiZlmGF95be__ zrju|<8!CdN22tWI%Me5n2Dz0QoTpGj2B(kEv_go)KonZcf4XOJTmHZ0JW9&V_01C$ zFhR#qI;4CGocWXBt;Pl*eg53K>3m;BFun4Ok`7lu)x(so|0A#{I~L*^u15A$e7r(y zWiH5(FD}YMOf(<;nMQVjv+TX0XSJMI7|ug-&p>mD6Vw+eB~(rNnu6 zd%tu)8LH88IerU5#BRr=@@uhLf)FpK^wpzA5h(m6xFR6HMpR& zS@x;tZoXwdG?t7U0#eur$h9y(qEA3}+IooC0b|+Ts#Pq@-DmKG34r1k?19CIL;DXH zItEPN{tYG%90_o`n!$8b znXV+XYGPX@FS+fh(uM59q z*)}l0%2sV~SX6NJmPrc!Hh^8g&}T`c;1UKd=G}|Pca`wsmjD6+$d$|5qeHdFi?pO} z6LasFt$Qqu1NPA2j=IF*?0yKlD;w(aRt0Fk{m z?@W^hsA{8sdrdmz`8Js3?9A1!O=1r1Z&|U|7GelDKLjO4qy3L6E7$hdte82}0(6SH zzMWOYyCX|!mp1U?s!q1%K{oCY>^DGhzb5x0-zWK&16#qEi z;fL0aj0VSML>$9ofU^}kkiw|;-b#;uK;H!(1v*nSqkv4~u>F^G?*Bzk%@tbhiCq01 zX4ac0S%e4#dg++Wjn`Fbzs^OafIrmGzo6oN?_AaPrn(B&6$a3NMTs)dH3fN;jw@cc zY|U;V>Mr?_8%UM_Rr$D~d!Aq_yu@=m;SRXN515T;fV7~V!coNi3+afvOX!e34+OC0 zZZTKaQq^g80EjN`Z%kVbRBGz)9J{A9eF9=E))jjW9Je^ zxL|tkiVNvY-B9@v!kyJ;`>?O1I%z6euaEStdsmGe8@CB&gHk)1czY66GhY+4?%jw2 z@xrBb+zrbXM{f^En~-;+q@ZPjIK+(@PQpC$3Ch{IUm)R~ht_!m?fPu9$5c_q88#y6 z+WVmo5)gn`RW#qn$re-x#tp315l^-D52jOVA5Q|%5=giBy+M*qCu|KCr7m}-vQ7w> z(a{Dk-z)7x^Gg3&Ijg7ncBD)WvhjUkcrKL4;RFK+RI<2Qpic9GfKPe;*LBeiWqiIZ zP>WE~{X#zVqA=&lv=b1BQ~ch1Vz@7>6ry^h-!LUYcU-c+-gbJ}+-!9mXwU9dEE&C_ zb-EU6UttKD^|W2UjiQR4Hn9W+;ExtmhnU*leJ4JrUH8$}_v;Z1L;i54sJS<#nj6XP zsc2t4*KBpRrS09e|DZK~rb_QtH!-UiDkv)Vzbg8-Y>*6}8aTb^+Z7$FP;g*l#B0WAU;le6dlBUe8Jum~ z{-~f)DF7qJjEs0(9ivP@`%Wc#@w*Za1hbGi8RvPvM-dey(jKohF&2YOoK=}eT8_Wc zU9RCK6Mq6We7Gj?r(C1tmQu0I$WcL@jSFK;8Q@8|0s=>iUf^=lf{MmQHbN%g%_Bob zpmvY?I#Jd(a1p5G7FfbU^Dsm;5NfFR2VBD%;J|UrPDaY4b^b9<^5p-?ohi#F6Opg@ z)2Pu5%X-QTRn8>#j5X?ZVTCdTAzQ-*h)J}(6FV@R0Yi=?CXmQiB5{w$ zD~GaT+(hDe2)Hrs&I0p7I--eB5IB;CLcT{@(_BR`SnS`S)fP?rt_J0+kXd;`ar-@Y z`B%gs07pBFzRfrtEbi1lUrsp+SA3lzalmF&{U+6>2qn6J+4O(afT=a%Zs1l&0@yNY zzv9jE*n6;#L-vWw-$P?pZ<`0vSFvs-DU|S@@6I}vT4X-;jeg&1!R1}iVYVxxs++Ga zSE&5lx?JsR+RV?Y{!y!B*3OgXI1_z}e7@;ITy2RI+pw6CAySl)S0B>75y51z#FYuO z%oEdq@V@Y+!9qqkiql>ze6x)ss4HJ$k#d@0y2PHX)=YA(vxKAElp`va8ykf|wb8r^(FQMS=ZdEoM2zY2mNxbrUHK9%YF zm&_8Q`@M7X8+rri#VB643Zd(@uDe>;D#M84T-{`j%oMLN6X2J@U% z=x76Te)8pWuC_{!n`KkXlML{fovldxud>Pj`c6BuBBP@5PYd*a9As%aT&ig#3dBCB z(=M&OS~&BKhNFmDlnM+M1SLP1SKcCi{Pjn5ScH^V(~*oh{J!1VYTwHW*^MUQhk9Nm zpM>v5PCJejq$6+cxxI$7^0P~=7)qo;-_dVY$O@w_M63Y1Q38YItrvaE-@u17u9~;a zjwaWp6Fn+4o!$q>SW|rT1|zZx)y=f_^zB&=Ukz*jRG5svO1Lx!8-vxEi{A^4WM~Ra z#=FquQXFfCsyLr+&bba%!LyWU*6vw~GWRU$LTxq0*LRj#M~1+WSbQIvrG(25`3QXvM{2gl`>>J{5XSa*?^w1;5pr< zQd5DqtB_MZ|Mk!Ls1Ab_{Vy-nJGu!@{?&Q2(geBM9zxPf0c>GtW0Q2IP8k?zp)?N- z`f23~tSdHl3st?zv@z*^rzJF5-n=KSItFKWKqryf3n&vSdViE|Z6+tOj~Qa?8VkMbGlnxC8KR1aiisA7+QzuMhrf)D zA2N>oxRFC2{;c_kjE~-MHBuDdHQBBu8CBtdR=9nD@W4F-(9`~*b|i27C5RPtZxpa6 zzSGKSX@-63mae^v=P|JBZSXq?I=9Y}UXI;PkHgskM@=#4hmV}*zpV!0Bx*pzhGKH# z=yq*&<2*51$ZDmMKgL6F7e8?&ooSSoC8GuytX2-d_+rXXT?pX4E7k&IAmCC z1OSW|FC(0)_8*g^Y}Vlf77)HX*s9a_ZxwnFF+(VNPhMc0w|-zhs017=*~2us_&-XU zxo0SC-o%f?p-!Na(G;1T3LMkqz#757BI8DRRHl2I*yL55hS6l6zTvVr+pTjV%lce|mop}01yGG=VS*l@GmSbu9@)^KwlxFZbNeG9f@3VwIU&tT*2 z{CWLlet8Np#cIw_xC8+zKL*g*(-~GKxQ)fUE(sk-Kz8Q*#xfy4`9`RB-qhABz+tl~ zrtbCn2dJrwlTtMZUS8oe-`{X;`@1AZsd^TH z!cyHEH<>Dm{!S^e!obZcCPlfO@p#IFuS3Ty@^YIQ*1^VR*u#)DPwwBHX_afb>+GgO zIw(HxYru;D zf5A2Du!vV}w)g9rfX`gq`w4X+KA@)!vz%OH%_Wa1?fIcabuS7W>-As8=evUDwHrPF zTaD-cia;Bj7E2+YGUc-^V{cZb?`k^b#GO0B&DHqB}qw z3d>I5GO@801Dw+)69-X%;a-1oD}XONRtlrI13^meM|JDGgX*ImBD9djPsaMBYSM1q z2Nl+daFyzIm1M5+A!xwXS^KV)te1d&4q;=Y?Sw`{)Ne^blMyub^*%rYpoVtO7oszW z;(B#xDM3~SKDUr9^iMgBwo?&m#dyg$YKDz(-3$Y$DjxPMs?znQw;q^&G=vXWR~RRY z;Wg6m7jeh|Ky6f_Y>~tP9G~xtU7nWHaaa%1c(RyB0-&>)P-U)l0$ zPm~!LIf}@YLXdo=aoK1N_}!DZ`_-2o^JS}OWI8hRFvde{vm%V26Sg>Vnv)2M$hn6D znK>ZNZDdJ2G$P7694G2CqXrPV!%);xvs5+I`tGx04Zu0l*|=7*gx-3ZnCYWjWHEQ4 zV12OtYm}{?yFVRs>C5@{@t=MT4=3&X2F(YS#%{xfZ+%u|`E9rw3+>xm$-3%AqITY0 zYpYNgIr;ZrpNvrqV=Wa5vAQ3fjrzn9fRFa1utN1y_rFVeCmaIhdhp(G9ku@oV7gIx zk`k0{1dRU<*`DiD!8E~nA#^_WXjn@E#mvY6K;^Ql;2nQk^jjp@Z3O7Vu?>;0micz29C$C|98sRnh5<@UM#39B^5p~L_6X$P)>dy+*hZUhRFxDd@ibptV&@{;) zay_IE6$qkh9bpHt}FS-=B|)HzJ&dOtAtjujK`g;ur+ig&^hWL z?xmWeIJC1)XxSz?aHVq<@1^lEh{0G)z?;m4%C6{afIMVcX9a9EL<1pDEqW8A^2kk0 zM5ne2DHug}$7sFEt|`_88MY#SgDeQ4o{o5nS<$*{g)jiD-J!?L%W83GOFaV~5r?0f z!}LMNFcE60H$gwSg@g^s%d4$?(vMq9aU}COn zh@l-jQP^BnP7py(@e$Q7F#t45jM+QDk4jMHO6v1dX3JkG3U#LVnME9%fvQmKXK;P9 zILB~kaN+=Uw0_7L8?76)AKL~$G}JftQ;EQ`kuf(JazlRZG*C^D$^>C>=wy#8kw8N* z!>LzLZxD`xe{(;B!ge&pmj-J62{w?ww_Y}S=4Q(rUk*S34PznP7yVJN?) z5~Ddv1B$0&h90{<+JQQ6u;uk35ux@n4k!dd6fv-ntrX%8)BQcw){q#C*HxPQ5-)gd5a51#+j7Yr{XaCjE?vvz)`sAY9}pxzYz(YvDI{hF^J8mYb9laS zp7T+(BVt7+wS#aRfs{PH6;f?}-`SB%lJKsA1P)w~CZsxyp~;3A00piq1a+pj}MCKOLj=W`Sd)LOmP20*Jlv)}U6- zk*(76{bxs34mUd*qWCwQIZNrBmH6>zRiNsVKVYU*cL~qFxVf60Mz4HUKz128J5=A| zify3adxc4j(RL$r4qMbueyF*VXQ(>qa8Bu@7kg|^vH+m@jO6M~lL#P6U^)xLPk&LKKFT|w)wC7)XKjTH2r_a=lRH8|QTleX$rK%9 zw%?CC>6dE$(jh3=p+k~~ww4D%6RCNSTHq7rpd#LHg=lnh_in?-E12KbUf#gC8!)JGTfTvt!F`Uj(-N8)=Nd$uc5dTd`{FQy01?q(7|-N2wwOOSU5_} zpW3N-^u<}v;3k{sxNgSj99|3yekuhP_gxx!mrd!zpkJuwqSc{%{+iiP&UJjC(@~@| z7Z{*KchbC1aEYH?D9>C)qp`E#5n^=v4;BSW+cU6aqSGo4KbQq%a<~!MI#>KS=CnxyzpB0Pmj!a)R`hW z!{JuvkWq4Xj!W%v102>(Jg3OnhZWuiUH3pKQca&A^+vi|?nxbjkP%#IC9u#)CO!xe zK1zFFwP7nk{YST#Wm39-#)<8>m@Y`Do$Cdy4A1n|t8rkwZe#qty3wp;pflz2n0?;L z)P?EwE=fK$IuI^N6@Q?|SdW!U3)r3}=Dp0a=sVHTZavnmzM{!}VE_9oQpGh6zbc1b zo++`f1$P$CEVb!$=rL2ZZ9fu#uYYK3Gt{`L^Q^|f-c4^ra`qN1%nHk>uj}>f z<2#M^aG1WC9lO6MvxR-5uSXIOeaMWxv9*_Jm(txj(l!Y$Bw-TaX+t{-7BYHS{`iaW zW~&c7xoH1<1`B18P6_o#Ca2BoX#hRa@usjE za#YpvUX*SHdh0z0A8->5?fcTQ2r`Sqk<)CRRo##^T~Nq|rrdhd1j0siM(1dkc5aed z#FDctNWRGDLi!@4k|1JaK=A*iKBs0onl2xTuAYky_IJEH{2mEo)C07iwDOOUh6g0j z;3;9oo$zCHh!gN$bh@!x$uAd%6<%A*0XN&CrfZjeb55T6(Ly4u&?KQEv*l{-kZF-@ zyR~5z6}1ti|D;l^Rdcc%0a zN}DTGN<2N9qeaFBzSNF(RJIcXU)nXC-0p(+jpE}@H1On>>#o3{Qq*$e;X?hoKp6xl{SGQJT-YUoClVI=fT z><% z9leyNU^k$0*X6Edq*yhtHxvR)Ks7wetZIEdJ8Yc~ROz{8x<9>9py{B)yC})^!=%-1 zhsC}yhlmyb4_-*{XO8k@yJt7np zfY0mgWs{MrsRf|(Y9)o?Z>H$iu6oB(n?yCp&Q#!h?Pqjc-K%w$Lo`dYQQI>?Z2@OAdzG~TBHucNYV?n z>D__|sKed`i*2{!pSE2y8Vh(qO+&%uijo0@!WxdCvpdF<+%k?UllhHJ6D^n_=HrOAPwxLoU^ z4PlZzDp}NPu0Gu2U_aFUtife9$yro}ZB-gLd?usS!Jgpe!k#RBhUV@4;^ePtaB}?c zPkIdqI%oCSJ8h96uRBvlYpYMz%FNEHX&viHnpf|bR;>1T-Ef0As-bR03Ta3O$`c?jWasf`hs+WpQZ;zt+Oga4JNP^5Y+w(LgyY~IQO-8`m`>N= zcQGHQbEwONIZt%)1!h!|_m8m)acHkwO}_Khu?mG@=r zmj5IN+tM)?l|m=wvj^vTCUzsRVPwy}yA9iwqAmpM>y!8=cho!XBAIL`@xTQssq{LF zh?|edO~pUHgUui?KMQxwI8RIw;c^kHJzRE$qw@eWZvhceCSZ$9+Orw1;zAdzASX&d4hz?x zJl+}w#PbFCec&NWN=D2N(-1ujHso*<1?W+W@aGolxWO(v$eO#iK(%q*;n|3AAV+W! z{zw2Bo)6=yU~9mFRV*eoKJAZZ4&h{7j)VC5eakyj&|K@$c^qA*>N40+-DgaVaryyGUy{?yYWdnU_68sfNse~hg~|}AObTEP?ZI6$=>MX` zhHedz5^B#Be+@PO`bPXU)jTpT_4rPzD(dz@EE&PcM-q z9`)My%m?%?7gPeJzD+u60%tk!p~Jj5kHG08+(Wbio8wLv!>RKssu*Q1q`STof?xAM zZPiR`B_b;))`Ll?JZ;Hs4xpf`PFtZ*#{SPsN#g@dtRf*wP^ z)r5@#XU?^gs-{fLOF<6_-dwV-(q@*L-QMo`=N)tcp(OzlQaD_&nE=O6tIxK~|F|=m{a`ZtOR3MwJpy=S$R`-*SiEdXQ$ zzn-{1iJ~kVF0MLIrrw3H&p}<=Dtt9=D;NV2n^DfJYSu1E#^Fz?77O+|FK{~ z+1B6rdZ1aso#>vSzS#b`NzoK1bd{MyI|nyI5h#~OtfaG&|5|84(!BunOK)^nQ8t7z zr+Ysc0ihcRKPuNXHX7^F{&F2?-{|tCaF-*-p;xXVzz#M~c8eBU#2p*Qrjq(&vy${2 z6y^kzP7qP^FU(PV2Yx1jpS=peihxuB7wAsm|)x}_*`+Sp*#EyR%<_*hp|w1AMQu7xD@!7VLr2H&^T z!P|799vPDm>q68l0=Ks~uVN0}I_FIU4Uv|O_y`To3e?fEoa8M(O5-bt4$lRqtqt1H zJ|f>a6pb(Wnk!6|aX{-1`)LQb)E+o^QlS);4a70RHT2NaSl~(9l1@RdVm3sMl->yv z%uGIA#jwH$w=*CFL>Vp|Nn|l_BiwaBQPh)wMW8^Rt8+wykoK7;nu^#K@Mds13c6Md zGcphp$tVIN2zUPAGmDE)NFaPwha}v81xW&kxP8EbwH4QXcke&RY4}NoDSz5k(CTqN zfHJtXAvWh&{>ck>@D)2CAQ@dfD=bj@ba>bbJP!QY)-{3e$oHZeuBCt}LSx!^`2tC> z1^S5yMC1*YVf5#rvEkMQImnQqkEGtw5rQXR^2kfpP%2LvPLRll&IA`4+#hM|2Ox#z zf+92aJkcvYp(Y4)X%2cV*^UeOU~oa`hbK7xl{!qC)(M|c3j)8FIMTV*WpfRL7wr!O`k5bB7D*g(y_mUOtMjKKXsh{|-H2S2=ZMVH6$`NZM z1E(Lgi>tLHGJAXa+Iyceoo}M$qY!y)`HF2`^f$J@B(iX?&GKpMo5s8?7Vu-2E?X)y z;ZiS%o91Pc1M$$JLy+;sZs@gvJH{?>iFGxFim5g_qE8xBqq0v3Lf#CKGOE1(L^X77 zLDw14_|#h$Y@sv9Ty#NOw@47`0OulLb{1J6Vw52jC0D z(8V_t=``{RD$+0oQZnB9@w?2Zq96|RL0s!Ubx#HV*_*PikZY5i< zHfrjoS)h!n$>S13Jb)zbWD{VtF6_LB7C)eSpoj~u$;}7#IKZQkA#ev0STbtK!J5Uu zMc(OGJkP_tr_i(xmJo5_mm7xbHF=&)JIVUZ`7 zTTvz7;%2R=RU-+4B-GjT4t{#$Pav`N8Hwl;%UemAU-%&}zz^N}5&UgtEc9sB2cX}x zBJc0dwvp#v%9zgllCA7%uenK+V>q)=|$56|ZCNh_D}M{oUmuf;(a?Bg|0xz-@+tSd;7~KsTGh{Uwl1 zP)`6^O*QyI?UYnUzKI@{(m_^4r>qi1>u!CA$5jsvRpcqaw-q7NhWZyyXt-*o!ho8Q zy;KbvhanT4(O%qhGht^$q4A09Lto8pg<6#e*fDUCx{j4ysH$~ajHZ(xH*Apz*Qr1Q zR@yvdvz-x&cVQ2S+XZ4RKriXB z77bISWaCptgtp}ad#KRAI3_mNkIbm*t7 z+vVRxz$-Y{7FSnKgPD(qy)k$>31PH{64&!V#<$UqA2vj75Lo`%Ot!0XmZs5iou z`-8r4bcqntBGYOg*;xb-5|~%Z{F(3h*9D4ssEQ#l+`7yifu|+fpv6)9)q_auTyf?z zX}j^7tyKpDNzFuwji7<^#R||w(dzBRIP6d=gaCRJ&RZHv-q9d%0jCMqE;iQ&%{I43 z3cp&&%dw}S6bOP7TiIefi@dZ7b0*8-M?e~|u$J^ry$vn35TX(A-;$|)42i>-L|0Jy z8G!1#L{BU*uEC2yM?&PPz}s=|6t#hDAmMV6r671|PRFaigqLbC8OJ2$JS-UW6-y9N zau{EnQjvHRE7*BUx-lar3biOzql*Wb2bnVe$J>;Z*^--T3#|b=mmwKpi&|%$BK?!Y zV<}Lb@J3$WGUy|!VGKtkcT!rLTe1Tq*y`}*p3Luueiav%UeKg3`n>a3QF2$Q=cvAy zZS)U;5z5PE@NdfK3*XFCa0FXwZfHV)?Rg_=e)#g1j9uUZ39EHAfp<3m^U~rr@l`6} zqRqf>YS=AX;R8qK5eAhtbXJ*T;SL8FN(r8^N5k48s^!5`E=(ORIO zudRa;g=vV&E`NOVWlt834;=~oYKdxZo)&%Q47bF@wX{d5#Bi)Y2RJ$_WSQ^9dO_H) zAols0+kfouTS6tfbnsvaAo`Qh+>p+>C-|}YHcZaOf_CEdRWGTN1ow7^f>?;t#%{e= z8389K@yF+bIVq*X-sPp9=*^ew&{^WbQ9j3)2197p-^4y+fh{qyX$T-?mHuZ+ReDGk zBCex?oef8K7xNz3UIzjce`?T#g3Xw)Td!kUQ5~l|y#Rv!tMAWswK?Zm2UAi#R?<~T zH(7rD;Jvpw0Nf;G1vR@4n!>6;P>b1{Bp2T&W!(4Zq3^QoWGYAR$-7wT?S$f=_$?*! zM^qd3t7?pFTr+T}Hb1>%bt6Ws-n35)O%714NJsST!0%uDlxBIbOX z2-rzXOtSh*5nc@`ZmJ8mLZKTEMFYiZ;nVg4GcIY9CPhjzzng`|qSAnwdlFs2bW&kU z3564)G2yH7tMMZvo-lD-Dp51FhUSR^qDdZZqV5c7vTj_ z@gZKo(g?ibxXPCT{q-R!#_-qL(;&IFYtPD$TP|cI@-0a%7cdY?D2_STt#z?u5?HZ0 z3E}yC?4l*_A{s3MVZ7vaTS9TRt?y$xQ*H=f6) zf1O2$IJUYhv+Y`}l|0QTRSHq0Kx$ko)e#!7R~#Wtk~CrG$mFKnv!=9 zals^-PYP`LLph88-VtDKaQ9yKKe9tuy9r;*`hIi*@-Jl`tUcm!M9vds*p{fVrwY_; zjM=PuVcD(C(2tWWD#taq! zLrm;6X(`mU37Zk{82BDYzlvP@L;N!F^?$TAvIICEJ_;H`lR;NEU)zgZgPn^}s)_cW zl;*Ocv=DU6W+#rF3yVBDx$h?J5$ORo;AA% za#WNMU@@WgYYa|vyy=a&Z1)1ldgOaWrJ=A17Di1F{RaN>tgF-lg`=uDE{%r6QnZ>q z2NxCtuc3I6Zgmz_@x#FrW&+XMm)ZrWlscORMCD|I_Xe9PdDjTH#Ab4q+LTNdN;m0s zD1a%H<3r^5=xt`}j1W1VT}oB>1A9Wagfl^s+m5wVlDnE$=S)B@EkQ>5q$(^+SN zT8Fsjw?E$?b>LAMb;zc|zdU8#wt1r!bOn(xmT80l3}@j63;;bcz+XbHmqslFx^xw@ zM<%5MO9y+EUrUh(LXiZDTClM^jyN|)oNt)IlAu~+9dedy^&KkLc8coKvLGyyz>gUD zS=I~&cuPcKK`UChi1p13JKQvq)}hDvT^8Q zdh}Y8R&-GDXk6xxYe#}9&Ay4$1-TlF@@9=gV-eqJLU!_^OOHPBQ4@R$n&q1=gJWE| z<2_h(i}hA5nLS+OuOn4T5rbSrl`zoIU$dKxso_fQ?8@;vS;$E9sc9(`%Lux5JGG$! zZ2F|Wax?ezh1wJ60h2RKk5qM>QtN2&GJJ{QyA4BD+&?kfQY$-Xee#nq|4MbE{O%c? zzsp67UelB}^-w5ybZC6Em{{MEl+n3)d8=r~r-9yb(jYzJ`UOIyr#PSpUo;V3vKpp$tEoz(<(L%>29O)B4JOMvA+hI5s9 zk`ht}{HuN^qLfScl|hcOSUPLsAi@y_0$~pL2EHMd2U&u7hK_A>ge5R>fq4hxRfiNv z<)Uu=^&4c*{ALr{=k&MAyN7%z%8lm~04tfHp6C>0w;9P@tVAdvi&3aUhSMn zi3E;nR*%$G$2}y}AfV4^4E7`HD#kp5PKBs*EYJZ8G#V`iJ0M%RvLJG~$9mLu3%4DZ z8~jP&0cpIyG&+5tVN~ipcQuB}nmGMb@=5P=-?l~NIV`n(%~K|^>2N32JuhmRTXr0WV{bz z0yei_`>p-}l*?P~t_*~97|0lOZ4sB)QyKUt`v@HC9$G1dQL6oHs7R(dC>pn4Lxn~( zLlf&HrkhL^EBT-roNphbNr;RJh7b5cB08SW&_EDF@R*cj13EBa`n=K!Ez9OBeFTv+ zxut7~A>r)n#4#EZ9{L8-ZXgfMb?b*(_HuntQv|T*idFBQctXV4!l2395u6o|_A|SF zWlp#amF%D^5&(4mVglHYsLzRjSTSU8H{FDrURuc*5ApX2qJWzj?1w9zKxM;V=Sn~$ZFw?iT@IMjA9@=`W>fguIX+_7oq|(mVf{UattE)5(w)c zDqqO82pb0b#qOOGW$FlW322$r zJjXn7hVyt>dBnvm?Z9Tu?K>5uZ(EcAXrVsmGQk=*PsLgg&e@|xX{~Q{{=M;tfdw3o zQIDo3zM2PbNt^-t4qPZLyz;8d@EJpv7r^b&3`LEv-BRSfKmSm~-`4WG7XTJUGnCb0 zmPUovA{frkgQHUMdN@%GUy$@h)-jLG0P4IboolC+#@(AgoAvQd(&dE`0pz2vOlXy5 zoN0<4{2hRl&v@)_q^9X0VZbdu%5FN0;cbl+b8i^_qv2xb0VMg;BZGX~cg{oGZjT)@ z`&DK3AIgZ(-!T=kye;t*HJ#bcN#dw4RnQ47uLY@8^<;iBZhGn=?%jB`N0dTX0KSo{ zvORG0{|xnRm|s7jo#-O}jTRq;5q&9PesQBE*Y>hGgUPiEU?hZUs(|4 z{u2mSfTjEG-y0VE_>0FSqH4CMX8oFvjH{itXxWcjE0f85Sf&k8+IB~ME88zz4duMq z@qHTQPsTqVStf8jLx)_)xo$oOK_tjEPw!AXywtI1e$)DOCcu;S1M?_&m3I3AY`d7@ z4u4TrK|P_k*9>Ljn`&&B0HI;}0KY50b-9X2shEtJ8e`;;q3uG5?>Zbq?JiW_Mfk*O z9($@t_Se6+u5aqtKA15+GT>NAh(Nv=k?}SO(pDn%j?=FrTVI`8zBUUoB*_7pFC11- zbO78n%qfcv?AAPL{nU}%`s=1`kZ4?4X3-TLFR0enaG76<1{Lx%5Ok1D%Uz<;Um=OY zpy**xis@rMbOmV{Cp@P-$J1Vz4Z+MIDa`mcRPP=b)c6Ng;@B@|NKuAlMUqjug{^`> z2nha-)8AJ6z`llZJ9G=%!_0>P#eGIwDe1QI_lz6w#pyS=Ypo%V^LUhMJr7N|$RrJY zvy{kwd3iBRjPW?9$|BVZL~3C=3T4@52;@900^pE;bsX(BlB3|i+Ve3Z9)zx&>3dMO z@m<>?+oy?shSJqB6NtZ#=agb~!O41PGK%LHUTgR!F}pcqlUqj#_$;IG;F;8DDJC3vP)SEp*c z)bGEj_VG4Zt-3sloA*xGj8R{dj1*Vx>sJN^hm zCj)|^z~LaZj8c_tM3@vLZ5OaIXf$&Q+dECw z%~S7ZbsQH{`MkULxfxxug1Q_Q!KrSZ8rHvlXjE#`v@K2M&J%ztS=L*# zN9I1SS#pziNoY7<;skcS^30|2ce<4a>2~Rh@^z}^0P_DZ5KS!*m9IlevI{Rvn|x&X zig%`?qEcsD9Wi4azi<3_m`i_F1CNK~-!RBoVevx4fuwc)<++5R(5eTHdu*P-K@ouS z64UFXfC?U!#sXU&nwb~2)xPa5@=V?i^*%$s=vfl)zdOFZ)U(I*Uva~t3_e1N5Gd$J zKK9SP(ceR6^d}VoAo!i2!0Sw6o;m|9#QO^zA#>(-_G`)jtWbT*tE4g)J%80Lo@yWb zU_z!UDWklfVj*;<8G&P0r6WZ^DJH+3l#@C2M z$oy}@W(1?`5OE_1_!}fKn;O;-H5`#JYCDGxDuq=lI<$gs)OPcOMLY;HG1)Q9&C^m? zG5al?pgz)D6Hl0kKa2cCwA1O7eT0yqdcLn>xjnyWqWZ~S}r9qP^Va+xb-|7H19C`NE< z*XP7OQ7E0b9G+`1m15ywY%rT(|9f9PNWFR8_}CzRHoI*v0*T}V5Sh694wtDxrWMj&8ZYAX5AAnE$|^@w-WJy{XZR7@elwLYc+JM}s-8H4}>PL6$E- zdHF9WI4?8-ezcgR;DppA*uuYAdy*$moEXRdq=i`qXs_y^5|oKqQsOiXUF)1*w;*tA z*#voqO&OTF>ZyWdeI5Ea#hB^w+Z$l9UEtKboAvPLpNY%KxfS*mM%n6oi#{J|VDHP< zTmwwj{f0zmJ@`bP0YHC|f6itPmvPgi1Q+oJ^JV<&}9J*F4Te#rwQ!$o|5p<*o>a|xb)UBE&| zrz~yxuz%7=_fW9#W}x#_iMJs`TRty005NzVJ`n$wB_Dp-_H8N_YEDur&u>7!ga*(Z zC>iiiS}+Z3;Nbqux_1~aQa*6lOsrbaB`65+W9H6EE()DqbBpCK%$8F$n<|MYht&~y zGw)i48#W>|6Fk8 zI*M=`c(T4&NK4fVPDC_C3(9!X!MG+3e(Zy}eaNPSC0aP#wGX1QLcHi{)KT3D_KP5! zqHJGNGzPZfO*O;<>7W4QmMRVNNpX~ye=M(A@Jp9dEJT}q;}a>EC!o7(l`9A&kuqXI zqW^W|EM@RN22RA`>`+dPVfgSk`_<)#wSjer~l^^IFj)oL}Nm3%`yOM69Xb5 zCFvRz-;mK6)U?;cqj}Uv39l|M;q%&u%+eW1*ZW>GHFFT*=)=PR-1OS8?5|nfuZm=j z&MibsEpbULupbt` zX0WkfOS4!p#Bss9;ac^tkp50!s<1C{B?>{T9DdEH503>0nNG(~T6prlkR5|?Rfz1Y zbtc?coUYi2#6Iezad;%^SDL$EJ=7W35pBFc7jw*7p{u=)i;fyeXrV{6tBrAh8LxF% zR+e$jd|}QYU%x~K(%T4)ch7tGY$2Ti(_WjO^ye}{)sxehGs0?|^cFmus_C8ASQ%%k_#`21FZI)T}6=X02GD{r;1^vJn zPcFLu10t1;aiR@zZOG?B(#YX>kniw!9&_VgU%gvj4w70G4SP3W4FD zyL#%K0;qkG+XoMgNgfe-@j)0C1GVQSR)6Kvy01Z`p`GN=ZhOJ^*R9#IhY5J%e*Px# z`R0xSe~E?6Q~tIwpkm`GNAjZ?F*hRhkwnbhFcgfEUpn2KB^L*JLd&qt8AL3FBlQJA zYqfOnf}2J6R3;%f+*pP^g6>`iysk-v7J@mYC?eEr_Z*RZ0Gc{$by@0cAze#BKsP z%HBy>?;M4fyolp8Dz(ESKd2_g90;AGp4`882DiH>v6DaUFy)-}*6ejG7oj$IFQcX= zhDzM29pgW&fI9}YPzo`f<_+l43PLH+w(+d|EDTg!(Y)9C~k z7#R~*a^DgmmlhlR>ird-n)Gqpxh-ZmxN2yNflecPfCqN}j8xH0fyOx}fX+7ELSZ>D zPVG;!4Z2H$V>|2Q0M$q?8Dv^%;a|UVC0`Gw_6JfNPpuALu+s#woik3CHXnZc=Z~Fi zuPwXOPBk)VA$sCrYCXpiQoM*~yoKoYKGw3?ozMlvqJ!j(uY^m>7q1Eg&q%_dL4aIO z=6P~AI`7icUibKq=6Ok}I9>U5OBe?=`ruigK?-8F!r&nde`kr;yV)|N2k`N^kY_!5 z+%lf2^mB*cRN;Vei45kD1z#yo6$iT25uJg+FVHEmk6{h!a+Kn8ym2Uqk(L0d=o~@| zvB$8fw6r?3q}775DjM75;!>T`zRZ3}Fb60OfNJLDioiF7tszJQirO5p=FbAxLg1kT ztRj$`h$IF~KmfNHFg$i(Bh=n&|EK=!OOm+TWS(llgxmt&qQPh(Vn!c=F`|9JKDs1U zm!iyZsLF4_t0%t>3wzjC{azk;czRJ7gA+u^c4dC|P+;sMn0x2!(^U+LQEVQR{WTsL z4?!}4Zx1o{U;esoJ{LgHFsSf3W8zBg!2Fq@Mi`>y@ySU{rfpg5K&5q<6!Z?o+#`5*Hj;>DI{zzM3#@;&{A#VfGmW0`9KSC2&Huz`Tq z9Pxn85@ov(^9Ia%@oqT2AeXyJ$Q&?5Dw-A(r-&Va@WMqL z2gJoQk#%qN&p4=>ov3P*YTC3T?_9d-^ntPZFft#@Tc#=mKFTR|Y}R(0pru;Zly{(X z*44(ki27H+j!U=G4oCbQOeA*aXPOkbzKmJfWSkxp4(Jt5u>l)(L`jYxAs`hk)B}JC zcp&zFA5mXcS-c<($5-1|CWNI~%ViEkz36W15Etv7ED21GJ$WVJ7D_Lwg7d`<8d6dk zH`YF#4wrIzL#Et@V@~^h9pZdS9c}giQ34d%*+n7Yj=#!BbMd_ywhkzF(lyp8a`I~9 z!V3{0;HfZjUH~C=k`)tg{y!SQ}B;WvC9%&yW9T#Y=+XW;q zx58)1ZAY1QbKNG>h5>!HsDrag2KBgz%KQo9;v+s3>HW0sO9WeMO?*`Wv{Zl~nYXG; zW`1CG=?T=61OF#Ck`kpO3t>F6cqMJ1? zSufrrCT<;I0)ky0{Ds+LUsTNl;`mk{&ogK#DY7V5>#Zf`qo;UhO|nN7*j00=0}fzhx9F^vIHPs}QEfXgsSJIV)Y;SiJ|%D_Av`tLJb5!m`Bw=mnsc zZ2|c(Bjhi1kdlCIHZtzCUP8bi7&#K)KA_>sO{GsJ6c`3-wp3xRT2?owPQl zi%zghwYv}AktD0T&rtl^8rw9JwY&5R0F5)8A;^%E_e|VtkMvWGX%4~cRIpJXYBkMa zPxf0yk2m@o*YK;knBfCWrA+JElQf}Y*4_;2cKots$Ve0=kRQa21b9wXvWNH^I7uPl zf%HiMoutNSe7~sPLUbL%5f2YWoIt{BNvY$)w`ozPO$`f{vyL1TNI*r1dp*)Q{MK3l z!j0y0!~CPR{1yjaApcwel96@)^wIp|V^YwhpFVwdQp(b?2Z@e6j3Zx^y|d@;m(MgL zyxy$Sp@j}stzX_ONPpzK*aYAp)Ak@mrJ!u#ku$EhHCx4;4v{57Sx8c!(MARhh3kD6 z0xOB>_!k<|NOWR5H@r8k^{{utr(2eX(NPi~Y`2`SQ`4PHGHJ{_QInewQl|Ck-q~Bs zu>2uYA{cHMGQs96do8CY%BZb3tKQ{a*O)WmRu|ZBLfq5wbsp`>ns=7dSH!7d@fMzq z`e7MZ`sY2}_V|4Oea#2x&AME|j)PY=N52G&_GT&9AuHF1Z$ci>lQ(LaBQ<} z%hQ7+mjkLpyPzR!QfsX?&8W{Y{d2+nXRo@)4rcc}n#;JRLawPCRZ(^R&6dax_sx_u z8M^YN-hyxP_|S;F_e>25j~R(r{Niu&Wl?8mb%K)_xL;pRQhw|58MvvC;yrc43cM7K z=)VYLy<70!xrKH|^w&IFujuk^f<=pv9sPM{AB_coZ%cDNXNpxs!cM{n9 z>fM1{2b>p;obXq{>_fx6?Z>0OS(_wyZ8)O;0Pti2XxjJDOQ18<)-PVfCdo5##2eR^{nObR990rzIEwK^%gby91HUyfPWlI^WJR|!A)}bo5sApI8pp2soDqUM-e_m~3 z?Za&{Bhs{&4le`3CYR(q_#>jMi^myu%hZ%;*9T@5O zi3rS98QL*_M^L#UIp)!~y1b$XkOxZ=>a8`+TwvmcT^)+@g|nY1fUtl?Zl>sxo5_A< zsgi=!5m|dsAz;tNmZyj?;ifC>GxQj=i!E6TFS$*SsStl}>q=3x>or(%<^H-Q@SlY_ zqiU2-2P5#fPhU>l>kMD>;FOh;UXX6G7VSfb0Z}@lr7!|FbzxTSoL{$_Du%J5I8a$&GS>lM;U%QaBaaOP& zTKg|ia@f5-Cz`&WD4ZP$=2c{=b#~C`Yi3Ed)fCh3<>F7dV5*TKisZc3T$Ed z0vzYLNrA`L>4^525L9Fwmi&^U{(_=6$~}IU=RnX3!?KLIK|xFQv+WcTAZlgWE-Z6G zUi**d-rzt+Kj`P~DSoq{q%^mj=4fVMUU*AY$Pba6XX7tG3yFXX9sOzDLQkNyu17rlW)0!M7iq_-MTUf zc8lu#sLsU&a*-No_P6)t%k|6H3;dq|s^FpAIcUjIJwz}KEKvr#?xE5QxxRCfsN%aYL+m?H{#lmuzKfc&Ah)6T{$c zPZEQ)M0kNdDh1GmW>E5$;M02i23hCzQyI$B#&Q5><;$~Mx4#e&hy0Y-X_gY*2?244 zGz|{U=+9T3F8$h zVEi#cP9?i&>0dErkdJz(n>t)iWd%3v%Rh}`FBiICr>{6}Ej$B7NF+KH+;q}iJfVOc zuJ4aM&K|t?HdF^cJW*P;_I=Pcp9mb$c48XIFL`3|aol`HPl+B*Q2-s%kODR69wVo< zHN;2VQfOWfBFXI8M7SX&^w`t|4sXqNEMi?c=K4f5)QX~S2={3vAJh$3q-q zhQ1ibuNkN~odX-M(PTh9`=4>wTz0b}(L&>f>q;>w98I>aB2I46{|ORc!~;X|2nv7k zi`J_7a}ib7raU$w;cT;|1cMpp?61=$W>a+`u*ap^qhknp%GoVx2$$lG_In``lknEIlXPgR?dvACr{alF1n%kUW`jqNEElZgwR|J%>~t; ze4R5Qiu^u=aUzCta+o^->vY~KkN9jKRR3pLQNxY(O^nOd!!9o#b@uN%H$h;B2VWRippN6ig7DIt zGc;9^p2nD1;eF<$c56BxMiVPS#hF5cUu>7CXf`TU>XG03x$h=%#BOUot{$gghFh{b$Iy3g5|DQS?|l)k{~PaD-+WSA^9mfV;Xo}G=?zw&k4=J;@qrnQ_mDUnxZ_@&Qu@Rb z^tST%u=0`fpriStr)3zNa4LWtAY2loKp3-JP=r87nks;SZ^9f-rfx6<4rAa=5Hd5{ zzMiEmTaF=%XVZahsO8ZmDTl}iQ2BYVXJE6FO^Jyvr>Zf;m7qjP9pQlV7FBLAxq%23 zvIM|7e=6jyg89P^l8{4Xrc9ePWC@6tH53`aEu#}M+QOPL(Z*7qZGQo;K8YN0 z5;U!-7nE^%NgT4K~P4 zPZoNjig8-Ds?AZK>sNMVTie(qnlejh*FYgH-wAWNjly$6;v|MoJ!KJtD#z;iZFw*5 zg$LpDPG2!TZ9=O`MARPEI5JAqC?i;-xB$8RLD?9_*(I}+ETbH%n$4TXtV#)A1k_)= z4?CIgf}cjAhO%@x*T>LvZF=n9GmWWHI?cvEI8m=e|D9SQeTPcbDXZ_WS@;L@`eyxf zL@_|W3lT@hss^6Dz;Yb(VUFgysb~e`%TL*^jm-=Y#3;#3dXP>KE5izsNR5hjSF=BG z;NR~_|JtL17Wl6NDToge^lVgH0J`4?U&JK3Jdv5$YX6kxzF*`Bx)PQNLTn!j<*$)J zFANzAqb8TdIxI~2r$JhpC z@05_~e7L!BTl_>jlH=*saW8Goz>KbRvADT!MUG!I>PwC_54g7}Z0-dxmyqNK&!IZ_PwK@WFto)@s`}pQ%=Bxq-ZM?La zq(@>$quC-V6@*#T9YY!DO{Qy4&XUXGvjS92#6A#4^W`kI)=+PbZg~-mkh+a?kkW^Bc(JBNp2n1H(&@p%Ly_{{XS(QcAOd&j(>)+$rpP^?NX!C>nV?t+6+iIRcSb$$f524;?ox7e}#?C8&J^S{P7p; zKhYdoLPKekrJlfvd97sNB|4N4_80>jv8jI-U3}zsgrkIOj38UA7b!DQUX>o)Ru56F zd$ND9o97sGbIwN_GNPWLBrHW%HLi%x>3`OcBXA?K_^^n7s8I*m7*+(pd;Dw(DPSZv z!V~*J^aTZfhSe3?2@xsj?@U`J4;iDhRB4Vuo$RE`nI;zk#0f29yXw;lLQ^jw17gw zkg3iIVqTBDv_#QtSQZ}Y{EvkGQz%C_A2BKNL4;BJq6D1FBZHLXuQ8qveq?_XbP~BC z6WHL}X`s#wC= zdE{izi}urZ(jj+6w+LAkXoQxX!Ma~Jx2`N(SoH12urh&CydKQ%9v|BWr-oBj8daKf zSULXNM?~2Y2|aiDVak;6hsG-o)QX`nMJfMn-&#}5HGAEG1-ZNnz^Z_l!^_z1dAKAN zd%D{uR=L{D8TPny8&yhmsHKKR2DjYRnqAh^_uP=g75vz;Hxoi#akE}kP0*};HEGpx zAIV;BGL9Oj#L}r~{rt(|Aj1~$^}pYDZ~MbHp|U$ntr0I~zX6mDG{X|odZ?j<*K^39 zS*{<7ocT%_g2kt%q(w298zj3S$HX)-(4uqae}9Gv@EB6$9+Xv0Q?Gl{IS-YXZAJOr z7E#WMNaMWX`8V@6GrA&}jPA51wW{jX(W(Sy+@s(t+Q@}Q)Rz+(*DXWj7_uY%)TLr?cop38hJl(wL1!c^8T#F=?{srV8V2 zo#LN9FuR$CYcoS~$=Lm^f{sZMRIdX>j%&L}={Ko^{?}PBzWp!raR`}JzhAe-0j9#E zi6{pROL8#t4w+a@CN$Ojqu@>xz++?!2eAq?dpcPy-G}HkyN>>0nl{No~?BaIG-`ynr3`T~|nOWX&YTvJClNM~y zJ{D#Cge&Pjqq1~(ocs%|`dN#jH}p^N8lK+H;Cff}5mu>>BdVj^-`_f1B)99fje54M z*6#!#Pd)RW@#=Fs0(4D!L6GUaU_ZscxXg7vPl9{&i@bYQ+p^MAPfki|`zwk`9N(#Y zalTvDxo@jiN{U@f81S~v_mA}xf~0GQM94J7>1y0E&*~^Eqt1uqKRJ5K_tN-Wu++^& zW5k|h>0fb=rKS3!ggrsEZ!f*V4mCLi9lW~KW=6~ek9rwOP>XH8zrOoSTFPVupbaii zYd}wf(|^7Hrl~~6<%Iv<@-q#Cwhl~l3PV#YN2m@J4m!Bh!BgvlHy(~oKS`U4yU)Zk zXdaV)TvhmM1aT`RKcpR(8JYTS-JXf|=L4S`^6M@i zQ|B|L&D!9x{CD^tBguEfK=r06sGHHqOT%9xSC(t`_hA&%1^3u1M!~h7g`@4)>w-j zY78lspR0j*GzOD4sC0GgrF}?*ZJ4n2`qhh4qQnY-d7~8{(cIkE$razeb1kb zKIb=~)Y{z0V3(L*HMeDXeu9UR?vzBCUwa^ADm?Y1BzA6%X*pu-{a@z1G!N(^b-p}4 zJ8Rvk|KG#eHg2cAjAWAhf1aRj??8J$T(ZXqnNPwxkYqvsBScHf`2Md)5Q~U#?*F$% zX^~V;F|WQ$4!Z2U(E4;%>R2L6SYoVZ0dYo;b%R>GVJ#$PxCF36yzHlk;Z?PHqw4PLK52o zrv)4AY}qavok1P*ChcwU!IlS|X^tsbnzx&T@>iFWy_G` zv0~98{dE42R{hzxVahH~J^P8J*1?4;?RMSHicw%2ATI4Tzn0oDOjt{G@XE0lw#}wG z{)>JEPH@|yw^1&FGT}tpMDkahXz4n(8~h`{HLD@JyZVTWx?%=*KRQ{k-8W_2c+tlF z*{Y_Rj#Tf~pdOM}s5EaNw!x%#2BRB@Ta zr#UZKAPb_GBlTEp==mg~no5|aD%yDjZYM2ozi(S=$~k$+pau13W-9-g)iu{?Zo<3^ z6O(V8yzBGnyUo@uc@k$o4lj=@&oevyVf^mGw8rzA`HnIA*^)#3eyQ))E(p@m`#41R zciP}Na&ZIA^AgOad>EQFx}D8yiKs-qD7AqGU5bZshS{?rm{QPj&q+IzE)4ZaX@;Yi~-hm$VF7fco%p#l^f~TCj(8SGoM)X zWKIOMRzcfADbt4zPv8yMOoC`3O8{B-8BX- zI65a)GrAibvo@x^2L00T;rw`{PFKoa4ScR}-t~!6V~zguHF7wrRz3TvKPZC0hDMo4 z>f^=eVcyT^FhlZl7LgJnmEsz>{fUw_VA8PFNgB^r__^(gQbO!~r!W@Czi~tbC}!qS z2GB#<<0}hNG$Gf;ZC>}j5U9Fnu;j&$<8Tgtz*Z}ct~jOo`=X{%aO(UE6QvNO5hsJD z#2N>h-;5V`s!d{oo13mSewso>>BHgG-N>LTxe~Bq<3A8x#u&sy6`Z`Uf)0pu3}d-k zv1RWbJ~0k7yC~l)=qz5B z_{g7Es9WKrxtnNkF!j8DO~yepGNQp6q`adkwH2W6M^{DFLjR7qsP21p_8V}B zi`aqMHLhWjPuBVT1AEMvl+_nCf3#D^%NW3<%xu+G(6`PtpFiac4CT#CSL$S`;-VhT zZ3r_B3(V9)uJCChDP3*3ljpRTB`__*G;Hz1l!xA5OLA5yXuqY~c=hd`m7iIf8ByhP zQ(;usDrf(7KG30W(z>ZnkF<}Fw{=SIeI)LU6>|nYUnp4aDy6ZF! zHZV^+H&^#Vub>jQ!5itse}smFom^g+&edbRzLVwa#N_NGI^3Te-BZ3k2c77tYC+I; zb1+jI|F5*vHImu$TTJN0B<%llV?6SbY&{%1S2EgLZ1yvvWol8^>l=n{1(4 zm2vfdmI?3IQhoIya2hn^#>(VA)eSKPC9qgWYA^dU!}p=n=|@G$oU;E8n++B}yML4n zx|4kb(7X|Uaj8IYS& zvj@A|-#NPzeyE|rX}O+|^LiwM`Mav(&boIogS1u*RGCKVU{7+1eUZz_KQ}uM^UfLH z7&6>n-$0($lWvL2Bvo*}oVM~4CHS8r`3^rOG*FfNPo@`0EeQX|j>I$JkHWks|C79r zlF>u`w#K}+y8_8O(&Y1XCZD(IeYi~`yf?f8v)2UT0Ee_%Lo{4c8JN_#&CGQe}~oiUYUz1zvQkNTBgI3Os@O~Sw?`-)>P{zxVPL(P?P0hlSIj{Z(W?^IJ}MK+9$q zwxA2lAh$)cJkIJ)Q{)DQa?*=jcU(T%Me16wUKvR{PDzYqkF&OSvWV_}y13h$G>{JC zfpexQx{%x9+^G-g)7A^jGhKtYgX_2{KL&PFP}jL`3R?!&jmt^-UWdbd18SsG z+-o?!2p7YR;d~K#7$q7|S=J$?DJptXr ziNUY_eC}>(uXvyt%Vf#DFG}A)n!4m%!|K=$v2`9h&zQfHw0!Sl`rUe8KgW(E-)YsN z=X!R-pZTs?eI^vbFo$8xdH&2a?VJ#=kf^-vbaqanZ9`2(-l+RUOIrsXA?xC_N^~s2o7BK*C|szhjm%>|&hSV80h?_s1qb z3>@Zr%8%Sp@g4R|b6hvg3OsVS2%2`m1^;Ed$2^tN%a;~gU(WLgcMF-77`V_VHNi%3 z4~o0F$4%be{*Ej7x2CH(s+7TzcbuzGZrHM@E#lfq_3;X2cp;{IcqQ}xHpI?IG<%%P z{&Ioz|G#9Wxn`d;i-A+U&i;0;8o9d8-nt(u)$sL~N=cb$i`3+m^a!T@j|cPNCJsv< z);8`|V!tlEk1&N6E&kUXkc5BBgPI)I&QjZJ-Sc)P?~`j)BJtV9i9dSu`u(O0JH8eR$bLzv?6Twq`zFd}eeW^b@*Z17KlRGac2R?jv&Ud4D zfeM}=88=e)wn?nb<2{uJQ}-+zqi7q#jozm|J8$iS&=dQ@54@RY^!OhB8h&8?@WZ|A zB4-%JkDf8T^5n~dl9<65_X(>#M_s-wAMV$s=gCPPz5)MC>s@hKWohRf`{xa?ST_{E zeiOXA_wPYUvMG@%GQ+Q~+2HYS{1xpp%bxE#uz3FiN7-H>H`c5ED}{%Z-^kq~8G7Or zH{pif1U;*Qgf+PyL3rNc=@Lu#PsQ_m6AVrSkN=u)bZFM&Jwtcn_3ft8>y?^SBznyl ze(&Jyxb|uJ_YcRMe0gWR)q}7TJ!D@7+`T?#n*7OMqlUk1{A+@3C=q60u3A z<81Tmqsxt5awm*>+4QnX<)@v0!T`?(PTlR};*PondY7fb&eTcu729<{_Cs@yL~xDW z!iF6k%<$wJGk&PgIUX78J#Sm@0Nn=t)#bgn9+8ZEAY+jFONlsjsWrkc-&g6^ey3kL%%5XW7xKOm%djVg8$K*!$HIQD9n4l0 zNcibQo{;cU*VoaNpr4<(zd7d8w~qbjZEM7nKhFQQaU{LspyXEPiRb&T=l}iEsrBEg z_;+tv{(dFgzoiHN@7kRC-%bx;_s{-R5whtgy?fc1U5o8GZ;cq0Z{o7b^J=$09y)LP z!eh>C(kEspsLx5g&L-_2T%ezR#)4njn-9EyhpT*3k~M!kRASr0c}}>!V9}T)hyF=A z!`yy1_;=3xGUt4?U18YIdv;5jD$Z-#_jlNL`e&5g)OLvn?iRaEOH91HG~996{fYlz z;kW{4`Ag%M6*#w-HTN1ez~xm%I+ii18xT;{$>LmG?GSgqm zj}M7uemOX-x}Z8#Q+{FxafSGbu{VpC?NR2m$8YZX>TbR9GW+{iIvUCvzPEWGVZ8kQ zA2Gv2^u5<-SicT@%zyjAufFUoojS;IH~ZvMhI(Xejg*d$J5ai3t9HV0c;HSGvr3Mt zX{?S|9W(GpFWE&o2J$CwjQRm@c#U3l{6+71%X>RtX#ZaR%WL|>+Z)*nmT^z#rJ4ug zD{Xw2^lEdl_n^=7@M-Rp^?#hvb!;_ae@yKmRR9I80t;<7?WBZI}nEv+Zo6l5^O7Ul-(#2DWL>e-S$A%$Jr3i}omCd6ajyP^x<9}C}a=jMJ|2ceX z`>u2ty_KV{jR=ZTyfrRD_R1|k*|CsEwa2=iycCB+D>Y00kHtRw;A!%WQ*Z=T7tv8W zd8rl;m0f;u=`q7BKa*3ZA$x8ZknFJv_(~@=MchSp1%#3r&WnWHwbL)Z4Az)iK_ZI3 zjk5~4Jbb~r8tq8gN2nqq69nr0lQDSNUm7EH@uxac*(n{x=LFMg-}_e|v`ui-+$t8HJyx zsy<&=z!_}Uu61fCPfUn1X#Bk+`&qLdui3B zn+BC?AFAJe`+&6cpmPB#pED*VMt*v|y)bOR)9Eg*7Ot8(qvhXq(i>HgrmPn_Vt-Um z#olqhq{amsHfsABcAuzsQAyt1>$2r)?~oDw$1FM`9XW%0y*cvB)8I;#z`@s2AJ>OY za56JGwDf`XkU68aKR$dx=!n9op2~QxT(rcT-d-yw zh+k5Y&wU!u`C7=aw2tw=CKimgYiF}Te@x(^mseJ)O|7;WQhjYikzV|IwFN21waX?- z==APjHo-F}B<@%4Lat}yl4D!5_In&$xvjfIXKvKNc-uWX`fB%-#UJVPwl zX(t|h@PS(Yc1A~}%T9{*G}5;TJk! z>AYc&2lT&PMvbc0PVFLTh#QoT;BQNu&X>I2M6VdJL`Qv*nb$zF;^A;w4f1x=?f64lLn||I~G56OJoub)A-Lx+p{Q4s7&J4pUf9p419uB=PK@x=Zu53L+L4 zzke7a@vLL~OIjrFQ3vna21}c5yW<~wHKdE^vd<_^>R%kpmD{Y|%(PnaYI>Z3eEcu- z+Si+R>1Unly7jztq_a$a<6hUZbaDOdHHlfhFKtBK3oXQwB@6GZZEyDNf$5cu%{%mK zPaWEHCD?b{z1K5Se)R5OYaoxAYD#V!rTf0euU^mb?*rRLxn6xU^U>nZ55mswnc7=R zb;FR)oXyXW?ayBOStKo7n!0!EzfP|fq`cNLvw#`t=cHV$C%?4Rc7|5($9P_R?3)(@ zZscN*yqkV95kjou@b4b0s_SNtI`qy`GB?R(auR2A#qx_x(ll53OY@%fss8O`|M@}a zokP0ULX5f;KZv{W_SzwXYavUz&~qc~_RQ)1m|KGf-`HT6{VKHNY{W|8FPf&q)T~_Q z$ESMDnmaz^(!rx+E=rp%FL~3k&k~h`$$n~E^D|czTnddEb7BJvXcDUDR+8~F+P4+(X6I_`37ah#m40)W~MH|2P+-AHguH2>-{IO+wb@XUvuri zS$f=?=!qZUZyQ2KIltDGH>ZEwhK_Q7YN!%7_Rv3}IL8|gTnK&oY+M070w7$&R@8Q!m%-kLCWU^0`xvAKn>y@I~d=p;NK85(`4pyPxtLIj?yR-OOzYP65j-8JF-Z;A8Oz5KVXBA?udk-|wSSfa3 z#qrSM8#juuzKal>>THATpKuZB|f6* z6&ZQs<6Lo>RpmLUmD^S>8KM?Csu>EX_-u;)_=1qo-|DnmN|tc!--lwaew$c;JxzZ| zP%YIzI_Mi~aepqosx_kL(tj^)=r^zj+mD+U8ecm#Q+Wp4 zsd!1~vHUA(#vhHZYlYC zZ`gVjGxnm>_?9iP%^>+q=ba;y?hdCF*4X=8MbiaPWS7Za=TK#FPG)*5_@k+C8UHSd7}hubUS>*X+0< zRXxvY*%u1~UQDQkiZ|;O>2@%5a@qMLR;_a2;=I`<_3{{}=6$Q!;17}w-YNQb2CmXr zX;gY|i+W?WskiqE?G-EEgf+N2Ng3~s=V~*vzPxa2SQZx>+wn^XB-@)8+EWs|WkNeT zotIvB_QR}BgOcdRmtKoC>%ZNfYKga0uJXf{bp5U;zo7KTg_8Q(rq88y zKl{{<6r%E4nu-T`z4+yjQ$H^Qm!-`~dZ>rL-}Z=3B%|7bS3kZnRRyHG%I|-zs^d z_GiQB%?rbRsYgESN2+q=n^6sOUGjH~&HMskqqd=U(-)`ZmjB0JxHdm>h~IHL_Uf`) zYp+Z*UZrs}G) zdY!86O}>$NiSCVgDM^i0ML|s^MHWfTrb)KVzpF}OQj#hi4Lxd#-dQxeHBSy|R`4%x z-%H9seck9m5@KSXdj$UDDBdsdm$i6DZh7|MunE1~Bj0ek_x5=!&XXB7`Kk4ZbNl8P zXQthnenz6}sy%0)_=GmO#XKK+X6Hwe&r_c^C_QV4ZmPZV<&a$2553M4cPd({R6N+8c*9Q4 z%;4ZjPT%q9zskxhE}nRpU0{3b-r$-MhI3^5PhPO<%A^<1j;>zllOKF#@qi;*hpvx& zvTgPvKMBYEL1qPKGHq?f?NxjHxPE-ljB(F*74%RZ(|q*e!z{YC)CF^$DiGkpXL!I={_#2=5Cf%k>R@h0rPi1 zf7ASKrMmB!CCgVHU+DMxX-=&7#BpOws}@aoX)z}5=G}LDzooRlR93LNEV!`q)ri&8 zvwV|!C$}3Lb>T@~`4Nj?uKawN@8>;{k`D6g-aeatxG2P?BEPJ%TKYh`e77t2L&KX2 zYVIhjdOAxOOG|#-KfK3)hKU({lBKqsEHK=DFVi)kf6aoySG(^i|3}W}a!<3qS8N6@ z(KkM-+ijTSfd5C?I{;Y{bm4++PusR_+qP|E+PrOh+P1A}+s3rrJ#E|F+w=dsvF}B^ zeH$+#>sID>&UdnIMb$}GCQV{G+ox?0H%_c8)a3$^e-<2YEM3I%U(3HCU}&(oG$}hL zk^p^bcusX(s2H;PiPO=g6_eQIiNGzmH2zV6iTZ11ci_Q-(Hu-rrdR8P{Pw-17)}Xv z^j^63N0STM3xwm&GGSZSU|4~;JU!^ZPIgv*p}0I>icxQ{F1NsU3B|IJBFipUv5QVt zR`#N*F`U20{0>1c$eNO8n<4V0-N;)l5P%3NWUZ}a*nlj^`Z^5^{lyT)1CI_Jk8pfr zESwK@Lk;ptMHTXJ{c^#wAfMpF&2rF+xjm4|2pU&dSH&LArgclFfW^UNdiZ}S*{}bm zxL{r52{slF^A8y}3x~kf(Vo_Rjzj$TR%!JpXm3ovhV$E$U)QwnOi z+G0-`y5FLgrRq`ui|5>mpszD4+3N@HIj8P;WxyX6xC*@6Cl|Ha`jFOnpEGGW>jz#r zr(XX=OHZ>P$6;?hfQjeJOOu1=4!r4Q@88ZkXE^!W2fmUI{8HtUfZB_W>bIELs|JCh zwcH}y$~f(>H-Im+`Vm6;=W@X56<|eR@smfmXR>FR*X82x3C-OnQ`KM-O)WNgl{%?{ zCknm0*+HRu?95*c-K_m+ENHGVI@BgrrOSF;SbgV=sF=klyp?lB`1QiqP4I3x!fV!J z%^e#GY0nSw^Y@G^iltN|Oki}F2^}gp3s4{+G1&k34FD^>hn;Pf`g&|8BjW$oU%=?~g^%l$P<& zYtS2K#2fRl0Y1aML>6{H(4faH14<8Z4i6X3?@GrK8Z^2GG%uglv|3UJris` z5*r0%^gB}0TCrdo4b@XJp-Kf=x08>!6iv>eFpb8Tjr6#za#GP6tXoH|h-lCQSjdP1 z+X;!etGBJNda)~K-RDEB3<1U>%*0!$R`Of&!X7C2l9cHoP_^47dd zUR!AHokxL(N0QcG<0$Gvp8Xz=E_59C*@_U&eY&Ee!^YTG@q&+N(9vvTv!|CA%Ug_o zykPMvM79B{nz-ZDjje;$djm_8uCpdi$Dh-C$dwTW%-U1BkT3awlh{nQu*=JDirr1# z;@<>#FIxKTp_-QTr!{LcqWTOEo4atAZyu*l2S+8yggqa}o^T_r&4ikRbxN~&1S|fF zy5a@gZLda$jO)1uk4r?$GmWv1vLnerId>t^Q5E+f9&8Ob-N6`Nyah3uBWmuI+jV=S z5rz}(@nn*+Q+I;&6zui+FQ;{Ma7af8?X=W6GY|p*+kf7?R6U1NPQ=hFjkPbtmmHr& zRzhJl$&-^I>B_~IR`x#sMbcPX6>Yo=z_t@E$Y5Q(x}Dx6Pc6YrbOev*JLS)_?C<5` z(g|nW62!)%t1a84X5+4+graGQoZ9-iXru!9BLw3X1isSFu>dGK!bRZl#gen?XbjDMnQkZ1A!z+YA+gKn8XPY060&)C6Tdh}omwk#<&+B;Wof&9 zsaUe>D7xywzUtA-dKyN+x>`^)8k#1pmHdH)U1Sw8PLI9x@C|dAFTg`2ON#)v+xHn7 ze&WyFur&A-CyFhdoueCTW7|gp%TLE8Zb155&%`hecUGs0T5n9cIa zw^7+vVs19Zhfxce2t$>Nm}VV%ED}`Sq*yKwwHZ1(W=t|*6YED?ZJ`k_A>0Mw^=9u` zAET|Vp{;IUZ|qw;kn0r4e!$QfUw=E6RZ&pM=z-}trmyu9xwm75Y!;vTuhbAJR3yv~!o1z>(#t{5u#ze4p-EMbYghUV z8zj@FX5bhAy);8)p!3|F*xa>l6Jt8JO_y$g8-X?sr1H|?4>v%@@2{y;z&ttBTI;4I zW@z@11!MwuB=v+dAJQVEv|Q0<#L?wo!P(7EW+!n3THi{36(;CF6PNZVc`{|XKyhv~ zR~jSkm$~|&X+fj5tvu>spdUQG#bO+Sa;24dv%_6NYSF;hu7b_S5M?JWXsGb+4vJ_d z{`d&uo3-WWn?P*YHGzRDfd7EQ+0oW>KNJ^EsLR?dAK#&}%P~P+{s1o);N+DosLjq{ z2&&0q-2bgRowxaa)c)MdTj81Jx#4qL6}IsJ`Y>HONK4co`}G_LPTHr566Q8+jd&?n}BfzrS z%O2xFaBybYlbsIuYHr6$7uO1Tb4@#Z^DyroDSom0JY!f`?)0E`chbe`tz)n_tf_!U znE+51>Scu-5DE->KhKaeG}Hyg4J}b4h~d_VmC`oju0K}O%08BurlF=f{>_v_9-83w zn%?szlZxd0K~vYWK^E3vG*KXP+)(G?#lIoy=>`-zLMm6`E@X|Z#rjgec_j9n*5A3E zh9f?#11tdl4xecx%7aBEQ$WmcC&vb4E`z-$TPn~ptd7|%>+*>)$GA+rmm17dSNN0P zJaxw!1Owm-sxZ8LjnBwYS{x^jqm5 zYKHTZ~k8>1v`invm6~GXO9k5q*ma7vfGL;}I!j8sf0`LM`#L zv(NE(MdT1@!bDfSGFT-;{9aexb7@7zSql9+)-b?gs^8XrEo4&&Z!Wv?du!3IEvVn- z-zf7>$Vqp*ugG-&xqeiSCDI!AA=&qK9^SLdt=^vb;Pnj9oEVv`$|K;jqBKZe9Fdjc z6o4kPxTq!l0Cko^)cd0U15jWdZ?KQ68A>bh)T| zcs26;nVG#pHHKt(nfQhhSWqgAwj?5FWifDcVPJ~(tRgtLc6?=^`X6%ErLJk~x0d31 z!7+7tM1(PDXu-d{R3xQo>9f_@J!dfq;sE6RsNjP&1}BkO8$~!UeN)1}OJVQ6Bjx7g zE?01_bu45M{oP@G-9>3Pm_{IxH=)_EqVLsZ-(8E!AswZd?2kN!Xyu0HxesKeioPdI zsKu}mCojkxU|kSHf};trzFhpjI^46QABux6lH%9t4>LlifA2HR^WSjTel5savyL?1-Ur;^XZuQdUiwemh+y!=l@myj8`f5!+GV`rX?-O4I-HlIinh4 zT$jl6541#94*EVOoh)woq&9Q;JN3sds(bW*+@NA07g~qh>ng)ph6nMZNu{J|dSFoTqqX^XRj-fJFEmga^ zl61O%BqbdlP$4EKyL||MY(243ZVN@7S3o?FtP|0cLHuP(+C|_dUq5pLF~c%xa^p?O zqz}Haf;LMiCM}hq7J*hKiB%0n1#3^7SBxTVCTflp&yE**=oZ)fvEXC`=*f#TZHm6f z%-Ak~cz9%-N50oleKOFO&Y2;UyEr7Cp?{9RnXk$fX`(fKq|=XF_v=Cl@r|k+!FDB& zs3|AFq9YXObcd!_&1)OXZcsdj{nJFLG9soew>3l44s=FKc+d>tVhr8g>1TFys^P~M z2&;*qQO8zRi%_jV&rMAAGORj%@&S$y{=5LDULl-zgkzFc~cIogCIifBE zv(bLNVG$mA&AV_{CWry=`jyJrzqu^y%c5|+usAneR87@vv3mDvd8&?qF<(XH|B{`_ z>Gqp$b5f$HbIw04CJv<%yI2+vPv14ZuvDXU%oZkVrn0bHRZo>in|9Fu^tP(J#JA!3 zc>DxO`%Q!GMaq?)I{DzDsuP4Kc>VdQZiW19UUJtw)u1de3f6O<`ZJWrU~Zg&{|@F- zI#Yq?Ifp1T6T=%wr=NVL@({EK*uJMN?d!kpIPYU;D&o8C!VdS}whPC<8dOz^j>8%w zX6O~gg@9-`g#0M{IgTaUMbA}ZHfY4jV1+m$#q`-ot^q)v zx65~0`RL#Jq;X0+ucJhs{p_sUL&tBw)vh48g!g=cR8oFnb|D7XTM!7yDntuJ@Da@e z3)34nr8cB_P_uSo?30T1kKaTX23RFR8F!Z%SKMS! z8VtvXNZMEt<&|lP{OU_X$}F{h{-7UtKT*6#PC@h6Tu2(n_#q~rB8%_NweOML-V&q8ii19OAXo0gZubl#92n*XI82ZeEEo+Ay_S+Hg;$x zBnpBBm(ZRcNn}Lj0%bu_XiX*zvS*=}BMX?z6RM4fr>O`Zm4X*;sDh~w#e$m54;9oB z9=2BuaVG;Uk!Q)H#S+?%DVU7|VH>5P`bY#ZW63%LWCkfi0-K?UUVjO}$-pF$neFHk z43ydaFk9t@t94yqX{=nZ4Is;r}-^p35`GuE0=6jhrY3D~KIV+u8Ty?_;zCxoGpY2R9i*n%E8Q`#t#-{}_c|QuwDKSENFHuXklhd#H}M~j!1PhO5n!X-C(^3y z|B#n&-OPM~{Hrp7ukW61i>ErdgOCH_GR6P(MSl5v7~nuK)@eH=>802eH$`Un@iww= ziPguzo@-QmK5fCWZ?v)O3m1^Kw1x3lgnAz`GHMWPx#^sd)t(k?Fxa^tuBdk#B%c|7 zwKjb{^L2&WR@ygwaIdGl`B?QFHGk~Bju6!7Pn_C(Bpt4?C(>*7ZUstYu?=Hd3j3D%a$=zjU7@ zs=lz>_yayvaZgoRHmzmb_0)ZR`E{$tH-VLTQP&GR9e%AX*}J~n?RQr-gwfrT5d@&W*vNJ3$ay{|Ib^K+bO6L0Ep@iXe?FNd z+ua$|L+qBF3A#Q>2w23ul%99_*fTEA#}b8$eJG|F+>Fi$E&=1ac28+&>Z?N#FnBHt zBR>;H_vlzZ<9SSZ8{fZ0n6AO>I-BvCy87wZe^D<@q5N#9cI_U^`90;xm?4(q$g2V7 zd;RKIH$LbfI-J&LHcs3 z-{=`R9b=(gb}~obLo7xA(am7IZVn)!T7;{mdfcEkC3l9_;yI;att_v zKORfw3!*-o{S6ka)o+j<^#VWG#4Y0QmUk7pGWO$seh%q8r(B{jAIBj_xSAwnl_H8@ z0zY{4BHj;J1tPft@p;aU7_u16WY$zLHQ5~qT{zY%B00b}&L|W^{ts6%0HNfb2c|*5 zUWzXq)3iHWdOzDV+hE5Xx3$ zwIYdK<;H3?NL_@X`@KBbzu$iueB1Z%X3cPgRkxzK1mmJ|7)rC$6~WCsnc-lup!Ws1 z?K#IC(##;k)<^^^9qPs_>yBjQIGFSIkvnV@f-@iLCP5WWrc*_*Qu0pG}rs|@OT z&i_!@p-;P4rlOZjkfDeC4TN&4dge@&ig8G4g8uU@d5;*Ao17(c&&-3NHdd>QQnGuE zNJTNy%InbFTm^1okz2itQnaNio{AJO#7fe{)0)`JbAGqBxTai2Dfn2dsMJe&LV-$ocM-$W_z8AG}#1!LIo3#N3M)Ys1+T7RnruUfBQA5UAISsqyf|) z&Q4MTq=$`^mO>V!7EM^z92pKPG^&o|L}ZvnvnlK77>oqg9E<402epbsTmuP+j-%kj z9DoYcHVJQ~4esQOY^7!Ni`{XelV}{ww@51<+94p}&U-*;0J6!HXS6UVbUJ2nEmq#( zl-XZMxH+ABm6&wNG?X8YKGTlOO#ku8WIWmQiA2+0@(E-zyjLE-#5;^-5ea~*1`OJY zOCgGzXQc^HCF~tCW$qCOpAi6(B3!1d{^=;0jvH_ zV*X1aur2_r6UJz!tEe@76?OmGWta%JM(&%e3#_aQwKsO#SV5H%pumv4F7E*}ovSXD zLWD~XEX%UtmQgOp1gl_y-oJ}2h>6Em159&(5#)@7DRK>VL_?E2gSrFHHU`U?h5`djXA?$8XH<>~GJ~)*Q_1g~WC^xL z!jV!S))0f9Af={bH-h-Y>3$9>($DYjEdT4Q~Wc;X`?Mu@WCTyrBfo!Cz|_ z^VYZsE<~>d*xP9QhCTv%8}=Kk7%?``(OGc{^{zEUu56#ux^Q2KTEYi+_n^dC(Qtiz z0DB{FUfJ87%v+VyVlO4Adjh@l8_PTjQd0*%Ke7JJN`E1u#imB6&RRDE84I8xs*{5U zzmyyB&6ES?*@*3NLeTD^yL%P*)d!FE+ma8|2NF;x9~EHpJ+jG&0R;2|2nfi-mciM@ z)7H%SUv2+f)6Qm}6YwpRp3sH1a0CR(q({uyen9#OITqwP?G#)ZkB1 zF2F!U_fYbu(d(PTFKK(K?yeC{YoNXg(Vo5JNi zNgAhxi5anG;N}rf3p&A0>3AT@#5Z+XI9LqJl8I#bqV_nndNhqUrD*#gbX1Dfb_izL zc98vZ)^o5{<~_eu5@oL=F@A!zk~6?0?gFk(hRtmYY~#R2ONmyyt+*5(^`lS{cvW^J z3MNYxD8MZm=9#;VnCE;6D^wZ%4Bug87HR4ne_L~xe=g!9g<$D$l>UlVp=X6I0i9xF zflF@HW0FXs1y`DYQAKXIE5&1*)9ldEK%VW&U`2~dnR01Rt*jxfObq1Rv4J^fM+cPK z<;s{SG(Wig8OB9h2~zx?8>YwwA}dSb7)^>!8xpX@w{5q)0|6)RV>4~OiJ)E!wzd`v zc!oqPCDou+zstW90!tKqsWpnhWr!V^RRf3K!a9d_IiPdQ!vc;upJKlYOdvVq~CC47tak zwVguCBJDmfHbHyM)8=)O;lHSI43|TO+0C@a6?RH?mZ+&8<92d4O`?|JQ30Qb)kFBb z-1Lt8_!^Z_+5V~BEde`sRc;10mR%(}$x`jOPCzIU%b`5)=&+>JRp>7yWHjn~=ziP* zO$+d90mM=z4QQApT$ip+@%S6=$?)s|v#X=+3viceUnEQ4u(Peb!#Ao=Rced+ezV}p zEN`hNfbSWFlz=qSPP|1F6+ps7kGdr5Sb+k+h$Z&~u7Jiq>i&sqYy`#Q?uAdk$X#*G z-_}KgP!Pi<}yvlMJtW$|ZPGXt7@pgWxsJ>iEI z3#%C&YD19qi&S-Ir5Bs)w%omd+IqM!WFd`i^FgR$YYLwV1*p0H6@bP8f!Y-F=^`w8 zKrBH`FREX8h(who?Z6JDFx@hfz_?lVo;BtOowX#?F51Ci>`lhBfH1;BUeN1o7O{OzvXy zf_)Zz)}1r>6wC7>J0Ots6~NKRsJ~GZi=@>!daZkoQ!k){+0Btlhi+xdweT>Z0PViSZslwd5DF4A)1s=GniYacI)`J)NA zY4p$lV1Vv#&Owb5!cl6mn^vDG`A0)dE22t+-|uy%Bi+K+y?^w_d#?Lq?nj*o*C%OO z`{%<9Pfu*z)7H7BlI@$yI;_vpQFbxP#rsjm*GG?EWWkECmcXkg;D|i-NPr)JFK3^X zj>iXk7>h8jhB$qW2?$-DDfB#ESvVec+Dm`(xgS8N&6%-X-mWL_>yHC$Vd1@BqodLJ zJk5mM5qUm7PJKpYy9)G_q*cjPi2oUeUGmkz?ZP)%ux1q_iPSqJ|Bj#H~sUY;q1!e zKG!;abn!L+Ha=YaKOsr}_q6CQ$zG&qUi4?UzP)v-Yph%H&f4Ec=bZOjVHBQDJg|Y! z&zC<9Joo{~IRw`;6d=>0z3JDSGWmQHGWZsrR69@?S}+${KQAKUF!J5Yo;3KD$qVn= zdH~NMMwa5UUhzmx^rT>+7+6C7#;plSt;?$!NML2&+4ZV>qNjvNnv}$Kc)TyfF7Z$x zNwa;w7=$4s2nBEOaHUAfpm39j9r3^duJVYX6ny}YN`e202}2em{YPy39TA20149$? zN9LxCACV`^t4q_-mQU#0Ei0o~K0sD`=JqbjzXZUYEnTsNJAI3i#;D5y{{@?Oa|39*; z{oiM&@xP=2x`S%}_t`D~FL~WT4*&b?IR3wA|8s5tA^-pRuKfOA@=AhC)*n_#{G;=- zfurN}zGgGGElb-(pB+)xmR}aY#Gd!`txEMG9lfgX=1OO-IP*xpSfgD)yx)U@4Ai+7 zjxsQdX4w2HkD@J0W;}7l85iFs>xyUCvNi$b&efZ0=a(mOpU-jt_636MwYA13>zWCP zNiGEa5tEt$kIBGmTOQ-V>^iOza3*gi=I#&F1*0T-HE1D$Nm-fW(y&PX+Vrsg-&9B* zl-%@2GPC93qKJ7#>T^t>2q80BWV1;AqC5GP+taD>+G08u)I_~7y4x14+5Y$ zvL%Q&X^>{EqMpoBf*k2teXb;&;kzrGoz@n5%})}nTdm1rM@F)`z^p?xFsy)#O(#%& z8d=CcQCmz#314~-jSgiMxd}T7%BRv&X!u_qQDiM(biSk@+tk{%*JR%pk|;#oClqp3 zXi}qep9NZQ1Tr1r?@YXtbYJVIzB! z{eg$6bhw}}xOZs{;e?O#&3_0ZupK0@E1h0I>kyeJf#7P}H*gYO^MM4MBxr}-7J8H# z0LUGjCl*+$IGc6!I^}1$jPj1Kr>%I~xcJ(ZGk+nm7De|8>P-zx1p4+R7?wJcu3&`E zkl}Xe55f2mIFj3f9Ru2y7+jHN94UQkm?(Xx_p+ccUOlGwcDUk5bO&>xFm62Po5Fg+ z1&l}&UPF$Ay}@vIg};KkW+A(KEqIS!oEfkovaE6J()RIA*X*K4O5gWk51qUY^9oHM zM_F_D4N5M?Og<|Qm8QWky{31wW=btux>L9XOfZO^?VH^fsR5>wm>ZNJP0$7)+wovz zDTYg?m+wIsuT>eUVDbZ0fx~dkpv#NVUR5?I51Ja}$9KD3b%ZE6xpgxNtECvP3r{(G zu2sIU1;*K6OmOPWtE}D!GK}?nXFm3C^O*+Q-f8;TqputcpOwW^*qNp=&EH2~=3fj? z;C0d-TJj!h0C^8Rc@GtN&(tpzh}cP9d@XZ)3PVWqx*%jj1B}KeeP(U!o?nsjda|4I z9>0{Gg_W?8uWiBu{jz*a42Fz_y!SkEO!`Juy}&E$2sa8%wCe5ps!=Xug4!N7`Yp`5 z+|Lmom-o(QTSGj?Mx&wCY@eQ66yG^U+n*icU2nDt0cU$XLQ6w{psJ`Z2rZ1S9}V=M zIHq#%3Vb}|9j?Fp^3w^JVSl-Og02~090xv$r$Afn^Uw%#GZNeRn9|Od4i$sT00@PQ zUoNvN<92!Bjk+8Xz;0^$%C?~Ggo!#8E+3}0UN)Rc)Rl9peJ^;%_<>E=#`poR6Q6 zlWWaC7cz@AR4aDM?E8Y+!43Y2j9#E$_Kix+ZzVZ+-J~^FC z!8IzvKk&9AeIv%`H3#p+Y~}22x7|C#t$Fx)32fG3n|AWezc>G8fTCAHdDbcac{UjXRKTT*>PWYZZ;{NW070wgS4(YZDMOo z1*9N6{HQHKta94NS>&6EK!bGW_v2fuccUm`))n~qJ{q%m6&vblSYZx4Y{0#wW9?|E zfXazla3q@0Ec3(hBjPuq1dZC)^jK_2`N&#&+b8kb+^LGb+!C$W=2t*aF;kR%V2A{= z;7)9FV@ILO^)$*mN3aE28Ujc4yJpv{H^8|?P(|(6&;4u~8GSzV?$5i#;-xm*7>Eb_4u3!hET;t?fL4g0&OT{g&`v(^ zipU?PuaBW8Hz`Kw)!Ol_y2jJrD^%X@8pPvPV?|B&DxZFtEh=4lW{>Orf2>B~?XgPis@Z-nNcW?mjMR~`YWDZ8o(O{c zPzMTptKGXITyOwOJ?7Zu*#sz1j09Kri~GYv)qUMrNmMU6ti3uqJ1hN=)g)T9(W>11 z1K*PAqQV2=08)aN!2!GwyOQZ|1$isiJGfpcy5CIPw0c{ImR}7?4rRy3C}epS04=P8 zAd9%>Wf(ZS1d0;ef}cj%1Zije4=DLoqklj3$@~`Cq!Tth^a8;CN9qYiaYQn1HdEJA z$?2iqhpeAeYQYItEFeZEc+*pm;w+#R@1*F_C3VHuY~{4HA00uq!pP*{mr-RdjLt7D zT`6i4O4?tB{DP2HFFD_Py{52tILZ*QIxpR~x!I?rspV|#{v`i+`6Dcuw@TbSww$fI z09b=Yk{BM+)zisY8#}$GH|CI%YKEdrZr<6W+Jvfn(=kE$^FvNlqw7V3#d{9zJU@`H zXyD*y-Pwc!gkJg_`SJZP0LdA8`qHffA!X_*=hiF)%hwpv*cPvjn*%*zxp3>`-_vaK_Jx5m^YZswvKwMCjwu60XrgWM_!NCAJAYRRX~ZR z%m!hK#dBA#eezKi^Pnp!E?thcl#h_5Ft0yaIfuwW&(9Qr|xYE_4k=i@0t5IN~{7)Nz|nT#-E76K+`ialxb$bz4?a`lbikMK(o;C zo$#$Rlu|S}ZKg_vC&UW$o-@mBC4jeQBrTn;G=0Qj)$aR)Oww)!7kwXtHrCK4UJ@;pSLfn9bcN6;oxtK2hyQD2Z05NR_WB^gG6Jk zrGF!<;4FZrTo3zH{Rv8!wRKQ;S2AIrcnYUvuCRRw`fQol`pZcKAxtu)L0G+7Noy7p z#6eU|d5F?b%>JE~RFj~2GSd(Kpc7Wpr2|D!Ov$m$3b6n)YtpC!kn`ARg0Mkc4B3$L z3MQ;{;hlN9W&I=ROQRy0cgvVN!qz|raYy?}(6L7y<2v>>gT`sP^ZXQN)nwH*RAe`; z$J5K1&nuU3#<*SYE*A$`2gEufutN7rA$dulgfSw&*!B1*dLF7 z@gL?)bh5F@=jCS#v1S!kMn9`eE9maUH@yBvGn}E-a&ehMP_t1;Ofl+?RBIXsZqQmj){M)ctm~VV zatGnv@?X59^uOoHEA2E~8m#^0T-*uOh5o;qW79or=PBt0iyK_#LpJiUS~uT{tHU_w zgx?7>90$g%DlV>+gUJ`^h4)BNtCo?&FGmsz zxIi#SA0$S`>i#ew&?JY^5_+0IWjIwr=DSHO5UdWZH{4m$kJ~5@LNJc|)L~t+5rZjm zx}e)zq$d^?ViGS$BAIC?)y{rprW+!rZr-Y*NT-A10xf$v$q;@)!^|yOF6dM`^75@D zgIG*=srjJI zF4kF-Z?^vp6EN;piC854yNS+m(;f{Z`9hsYGTGj$W4(Qo8jO0qS~#A1bG~KD^_!#G zq7y=>)?R!Oe)i2Nv;7StRN*4CZoT}?QCzi;0B8(Lr78!V9-Te@L4B&B97PuvBPUu# zBz8Kee4BiYevXm|qc~Ea!yuwX!efo7hOQM81$qfjOF+F#)m5VCgA?MQ>NYM4Y{d&! zsS=+@B(m~Xc5zUs#(Y%e(fA9sZaR|7SthTxN1|Jzsf6u!U+(I?PYl!=Q;isysg2aa z56DSgp%u7Cna+k1#@;R>pVE$5VinY?a4=U9oV7?ScW&_5_^{YHhl(x!63)`Ac2Kh% z#wO-2DU4Rtwbz3R$hN&lih02Autr-*0$DPa;|)^Dj?@amyYG)Gv{e@Gl>3qX}MU+w}^2O4Z4I~aZg5=mPFiK>;TIrtHF zENW$ZX23A;!v~T5dF2twr=?v|vouG92R~e3=s<0I6qE)jmE$EbsBIn+3M@+$Lfw7> zp)cqcP&euXyOGXqF=a7gL@r7b5);vCjO;9&hfUvIZ-g-h0WoR-wkj)mt@@!nC&2x9 zL%dC5Zv`SugVF;Hf~D9kNdk-)w{f3c+1t{6zRC9(jv^vC3!bUW;|W>5`FG{sN%}C$ z+3)iMT&N-TZa7MPvSH^7RMLfn7j_FK)sv(MD|@%lM0~^=?MGRHT(i1S;?K}&mw?zx zXWlHvJ=v?D<=9E~U>D^bin>trPJrMf7i^;l3{()ci(l%x7!X!T_T*t>q*1DC^QO$w zpjq(0#;74|ZL;w0$AhrnDHdrUgY=bRU8@{p4=g7|5b z?_@S?wLWGVBo}SZbzrpHnKvw<9n3iU4L3b*8*5U8_Sx^ zKGMcpYO6HVwK^MWr0I6m4h^&%iW)9x&UDn!YpVv7WIU2zG?q%sY~RMcB$J0&Jn+=i z{mm{qalXHoJntmy9N)Kb1g@CuX`mPT@nB{5iM8RkHb2w6uCc^amd{_k+1=1B@GZD_ z#Cmt8j&sn;O$~k3at^dA11Q+s&Fq+|qyx-0xp7Xtr~b6&^Dj=e==9sj2rS#@Vh)lX z-L5MBi}u|W(S7K4_?r2uV4ohXU9ddIH8uOyeA~t+|F7*%!8Pq~O#>}~gp_-$yNA1S zn6#RPz0I{<)HW`sWFL`7^h(n}YWK2c>66q?D$>L%e?aPC%*6Hcxf9y;{5vZaJ{Q*b zYR1xK9Bjcb#TL3#;^8Lh7spovS7O71zisru8`;qu64^;Za!fU94PHvuSn@erO*caj zk6CS|Ufq$dsLN4&0St%nFL%9(!;$$snK39n-Ej(f8fs{(E#jl%oDTM=taIWYZMP+9 zeKo-F$N*{}d^5Hd_JTfbE!(lc`w}%G@a6=EPOKJ2O!GpB#!<9&xg~gc%>I?a71e#1 zKE9y!;}O=x#}URRzZQP*U58Ipd%f=w)IR>Mr(XnDBBULWH<^LUd!?Bf08_R22#9pc z{A$?nVCg@y{4%3t*tEn5T!p_Jq>4$%Z4k#5LjWtUmuMT_Nk?c|>Ps=(vp!&;u||!| z`$2Iv60i`cMv2uD#(xqqJBwV&Tks>4kj&QAFM@v{+dmP;)P?F$orMd3s!+09>zh~I z!O6C{BCb4?R~RntvsSanrWuAhH(!@UwKT8=?8?b5IUgexkBcj<+$zwe6&jlNCW9ZK z2?FkoAfe3-WB)$)?O|ipg0AGmJE;xwNeN`VOOsX;*O4Q0r3>*+TO}{&* zN>m(}jGa{ktqNAwC(&{Dx2~-s%;-IqcG`(Bmo|P(9viWuABCOBptSDRNDP~A&kaRS zYOB;n(TLlsSa%fHszn2?>p0yDT34~BlmS$rONkD4D{@|iuDsW=f*kzaLCpP%Gx^zIdj4x7&LrrqRad=0*Z4%$wvK64&He$*?q8U2)Cql+-&GYBl%I>^3L zkf}-z)s$1%JAo(mWv+K(VkFC*QG+K#W2fz3wOqZ|!#Q!6{?l~hcK}$stw)S{ZSwm4 zlkUYMPOQ0Vt6FnHd#eI|gd)|Ta{mU4&ygco7py|rY@2L{;Os-4l67c#t$wZ|l?aE$8j>;k?ts}A!E2438bqmb7yx^*a z5Y>k7QKM%Xqd`XEjtyulavZ-qO6;ezd;$A~`-F;V#KD%Fz8{%UAQ=6agav8ebkXMg z+i$gc6p~8IMi7bO&3a&$PdIqcWnIom$Y>@pv{Ta9fgF%9$Uj&*YJc8{NI;Dm)UGKZ zxm3?1pk-{A@!2_|&~6z<8Jk>Yy?h|i+WkbemKzpMs2+|94+U7Rvk7aY=wg!+s|~If zoQGd`zT)Ult=jHeI99OeMc&P;@v7s_d!`^P%4&1j(}5J?^i!-_DW$AJ zLD*I5=22ixm?dtJ-~3)$wpT_IbOE7CiXJp=WUj(uVTC$o$6H`ulrN%EGQp7oIGSi9 zLWanTCip^b{}@n{j9wuH0}-8zpivenEEJ__8_>Bg3;?O>nH&JoWc@Ubcc27!qKUJbLfB_ zeI3&=??} zq|)Iz!SGlN0mYRv$EqjW#QgU;X9h~Pc`gcSh|yZ*EdAadkWwe5_*K2EY+r~~?hm(J zk>Oe3Y=wYlF;fTeCFAn^)l<1Ns~1y?5@Wtn823aqGG?>lxy8x7HYgQc#y|VfshLA1 zb!;>mwkIShOM~OYY68WA$JDp+&0jwE1Y!0b!7m2_^u2F@Xi7>H+M{EHhI<<)+1m|6 z;_=!QFADfx5z~9L%v^p^q>-VXhG}&Xf3glY3 z)gYGu8z;>>AC*2;pV+Kc)j&`8TKI?Mdh3oW+J?IU=n4>t>>={^Dk;7h+p0cYy`@7A z+-IA#^iTGd%PAHqcv^C{fz-@l5<1;KJc8zbAWcGlY8jnX%21LU_8NY>qGv>>ki`w_|e7 z4T)lpW3K!A!&fVXggmq?V)IpiS+lVK{8(A|y%dJ#Hg_<<2kZ4pAuWcE1yaY;R&=$# zJ^^3Z$YIAx{|0{F4=$BqFLM#&19{_;5#w32h@wd;5k0;`87MRi82)!S4FLlOLHG_2 z%7GvOVc)@vOemmN^U}-mzw9oI7vU2BNhthvg)ZdDui&7y{U#PkoG%DJ6!u~%>r$r%q zuc~Y`s%FtJz7@YvB5f2FlN6JgsPD_=g(++J)b51ThRbFFrQEA|t&gg55NcT8reW+l zXpX~$vl6+52RsUMZSiOpC`Y*KO=h~ArWfJE*xOw!eGm#qUE$~?^`uR;Z`VjIR7vl^04w`czxz9Q5| zP5A<)%r*pw{i(dMF2b4ux12t;fABSTSt6iPpws@!{j){{vR9J;cYlO+wt?x(&ExUm zZn@{f^26(M?)Bg-b-Q}sV7hAGpvPyG=j+4g{brE+^ZDlZV>j&UwbJ$V&r6RhyM$3dvgs{``03<2jJZUsKQIyJqh>q z>g{<;5LvOv#lOD7w{dQ@27S8s_jZqNmGat-?RP2@_{enjs1@Mjf#>@;N%M__<-A-J z3H`Bu=X`l`L$tuwIl;@lpwXbzuYpuO!&wbCZXXaifVl_z zGjeT3oF3wRHMK8~SCwfUT%YdR>$HXGAG$K1Pobe+Y^H0{v;C~S+n~-Xc>D+3X*MJ- zh;;ShmjCsYB4%a@D>XaPl^0_jR}x8l&hvR}#9v%K^zYtRoc-P@^G8;7+@-eANb5s> zkiXSUGBQm`kEeZB)ZGh`w%wFR)6N zgUwxiU(Zga&+b1$yq_CakdxL^s$5|7j5V$zsn#$t&j%rq6d{P4mI&v4&fG{!;7gcW zu-RN6O5n@BR5G^etjgWJmdEOtD6TycZxm{;q0~tmbBjRu%3-|RgF8TUQT1dE3cc>} zyYP-03MAC@%gbux|7tc7nQ$c4NL{fOt@xaJ6$c}CYKF2UI#K86BJ~=6X}xL6#nn*2 zY~r`I?RLz)azUAv1)di#L4XHI#KzoINp&pX$^+(iWH_oO|wfj zO=x>w0^gL2Z|m1`?XRETe$)9l#&~f$qE$Tdll?S**M)kXbjgJpjLd}^P0_F+l2rqI z*|15g8Z;KF#Wo!3wlU;l@6?NJ6h}*_xyKnVVn?)#qaQJpYGc@bD}+?Uzu0Zzlsa{t z1gg$`*Pis%FLodkM@yAxS%QMOyvjZil5Nm11@}lqHqd^|>Kt%E9Nb7wr2XxVblteX zR~r9bx2VkVcejP(iq4nI&1@+o-IcKXO4_nn!olom*)2x{v zzs}E-+Rs;}P{A_D&&!9l5|riN#$y*8ws%555a$D;-g`X~E$LoLlYZ%4$i&M(G`f0y zqOK9>ZGEXemd_NtIQG4KirSEsiKU?8*R62NZ!@LH88S&S*vDR$Uym&t!qc9kTgZ^@ zOfzshx^&Vv$#8)kai(qrH^VF;vFGT` z4E(#YFn9a3a^Neec8gSOhFrp<@sZo35L_M}CZr=RPrmM7@~(ps#A;Lmr|0|Ho$`1w zM?C+W(_{AwA9=DqjNN|`xOymW!lLsCwlTB{l=KYyvA{dy+?6Q|1>^Y)<+sM}!*U`5 zTTy?kP@?~|u>Zq4-A_J|%Kus}Y?`>*f0+f1j;N)6*D?b-v(17xQ>2CE!liZ1H=KH7 zu%fESDTw8(U~a&R2~pJ-Qt}8OV+)d)mkR}$VkRM~ytsS7OxEkK7aI4kGSHQ!F-M5N zF!T_q|C;bvdE$5P;mO6VTa^>T=GqBS9|T&3Wn;cL=0ObHg=SUh(0$e|F|lXsO2LE< zO;gbcwCJTjN6)B|lK8nMmmU)$8%H|p)bHJ)$R3`ei6FxfCU&E_RWVRbP z>SrcsP*It_7c%OXQ1`y#k2IO{xZO;wPpfoF-qOEdEL6nhuSkVTGKr=$xQFS3wiDmM|BpJN@!B*NF?tLixKgfFUGU3bfozz@eu5nnVw1{%OHHE zMdyG=tiVknX^DZG5m{_785gTgUen?%Rsa=>u^{mZ)m0ZfIi65vnq*bnMbYLt$j$zp-%CB4t9gUyF`@m zL>;=wKRP=hLdBiIr#CKcFGAIbV-^Nq6C!vX8~O>;mFjb;ime(Y6}A2KXKxF>#~kZV zwHJ`-my+aVlHVJASj0X1lH`%(b9iH4TRGKLhl*nMxV8|7JGy{OVlp_5V~l2M{i5AR zp@X+HNI`Mq^SJs|F~1sHSNdf4-Lm9@@N+oYazo+{2?6ZC;`Hs3oxtdu6M^2kW z>__&$HooaIU%xxFeIMS|r1-Fi#~{w86&05H;KPW9Qq9RaxCd-14b6{Yyu| zq=TuC?*xs=Tl+|v%v`D`w=@Mxo)Tqc&h1<;&0jgNkW7f84zo-8%j5)HUOaNB2cHNT zrjSH%SpSD1hYi1hpCuNKn)C_zo<~l?S4xnjAC4+2VAH}S*>Ng~fVaBY41IC`Sf|Ea zHxOGpJkj~Op*y&u-48b;zE1D_bds5tlv|@`e}_|R&d$#|_2e*?)9niROI6asv~g?w z3i7-#=PI-D`KcO*HGgZ>z?T|cKYIm7GRLK(FDW}h1+Di%;<>DAe5_NIj{ay9|7fTG zXpio-(5V{VA91I14?&~5Lw^H1G5f)HE~~J*gReMAU6;ff0f%DEy~C0s4n7Y&#yWi0 ze6YI)#Ll1Tz*V@K&CXRv5%q*-v>`tn%!m(Bb<^nIry)x9Twpk8v09fOY(pSJ8h31& zs3^=IOyTeT&4CeVel=B^VBrSuH?Hdx6%uz>`iK^SZ2f4zuI#c@hzqIp^LyG1#6CCU zCzW1FTDpHj6)qa;ugJf~M;Bus`jp(87%khbACdZ8nc^?gR-R#vSmHVS9|4y1e&GwC zMe?B*lxH9yQStBQrv-1YqJL}nBHOv;zw75OLIrVf_>c-%(LszhZ}JQXGg^A$M_?YT zZ#}YCfMPYIEKW_gY=|!Y&g%uDD6nHnJaH5drKv4+sTIs{q#uJ#FVOkDDUV2`Dixjf zt_42bhdkr2D0I`!RD2Vjqt5E$6e>E(_IGNJ$`f4WIwxTAeVIIkN~XY(uz=^?G^GBM zRJG83F;T}38ZgCh4L75Z(M2oZ8JV%a_b?kEZhL}5pQ~KZ-<0=6-HLGP5`_DMBtP?e zv;y2R*wY{2peU645(r+{wUFK)POH8LBtA){aP4WYaFRF(;XEMBkUHzyp{Sh|v5su* z2-1ml4@x#`q=*`>>vM*T0=92ivoHKQL$DE>=3>%6Zt{1&kZE@f_?nu=QDo?DDe1$9+EpSBd;hWPze|kaLN&v{JN<0UDK+pg zgADR7&=nAo8h73DpWm+zuQh=`PS2=+I#agX@}p%08Er5@QoQ@Ma$k+I19fGqeR3Ql zsIHskNzBAXC~04|P<{;*cUl0grf5xp$Cc+Y(R+p>ABFpDdw32eAFkt&Gz%=30hS%1 z5_KD}npNuwscg#Dcgx@x19iZKWrl@0_ zjE5@aa-yn59Idq+&_bcyC`kbv7OGyuoE!o*drq=)Vb}D2f&?x-CrT1=r#mTTlPQ?6 zh4TXi1EszOlp{yF7z22vh7#daTT3l6;@$R-x6b$7u19JcY-xF&DAap@6q*>h#&4f= zZHzRwnR$*cCHjjqRI#||yH=fYfD1fs%^|{UF+5fpFYHWSn1&Q}833A(Oc7D34#foL>*=E0?2j9dHb`^#>Bwr#DMDH#$5a~y&VSZxhnw?NvQvDc$I zB4#F6+nbe2D3+3By$FD2XM1sifYr%@(BRp=hmPjE0Pu{*`3ZuTV?qyCDlt9%jFy)(7xnv1@LQ&$jO1Jw9Oh z^xu{1(%9PF!l4xvMbf^(&f}0##1+4~$ggcAN^2w7t9z(^yaPl zR_;xld$VLVx%jkqveYO@GJdYPJ~$Y&X*%6pr{%a80cTaAm?Nj1 z`|Rqn=RE%8q00_>yN2^-i=*C_@g(?y+}nw-4b#i*r|um=1zH?l_TY1;Un2QqcPKhN ztvjTiX3)A-d*5)Oy~3=+J$+w7?GvHLB|(%qg8SyJhm?aa$4lSi$A*DO3%5PkI4$FG z^b9`wtZ&~vX4THgLuaXzg%l{R?c+1DTL@GzKQlekir|Xr{?a_I&Hw|e^Znf`m`0PY zk8j+D;E7pq#uAGw-tB*E%p-3_p#JVNI1XYr#?mt!SI7>*yW@yw$QF8$gMI)MpV1b$asKoZuYh?D-`(pjCkR_$QI%+DRd95_Q zA(jNsm-56;)$GRTK0TF@xU#OvK(=lp62=y~M7exF(w<{eEFopY){--`j1Gp1){-NO zzwY;}?(fB-OMl`(gjLggKiZgo^`7QlFKl=!U5?(^6{pl5EU&_Fy3)YDipKQf8CW1R zUwGYxagMoL{q{-G5f5riu1u0-9hSwESdyxUlE*KbZ|yfKhg9cN`6! zN3P#2kDw~+H(ms&MMrI-PGl)F1MzEg;n3x13LmKxDwJz&j@!F#_C~j9lS{7q2H$GI z`AZXjBi7UiEpie!>I(rLyt(XKwXGXhvMI;};Yh7@kOa}>Hm*2m(skg^$LnLrP`0dA zZvvj4fZfb~;@fe#^VvyfWB222I@Hiuk4A(wCr{VLqscof*WHoJ@T3b3vKM&%*G0+N z&vm~;mNPF+! z#$d#{jwa)r0W*6t#8;bAtv%~2-aY$_rt0K)?nOR>{;AV~*rwd?LTi%Aa{l@Y#|~PF z#jQI_&sv8q!H=0W2%%B<1V{@kd|#>$6eBz4p{?h%zTzfar_<1#RzAD4+fU)UWa#Fs z$-FqVu&wh)UI%04vhBFeaa8e}y6Bd|VNUZ~yxQ2yz*SSi#p`Q#zS|?1e16L8`y0zf z&kMJQC;U0{6%|{;_9;S2#sM2ogPkvTrjKgY76-TnJ5au6p!~>Y$hE1!P!5zS@F;}T zT`^hr-M=fWU9)o1HX`PX4TxxT6^{E%r>2mrp~QEPZr~e+Jg2m4?k2H3E0V8GF(Y+EZVyT@!M{y zPGKYClm@=zMD#*;Ecj4G$ecMbWK>o_k|3>S-BG42$gzHv!7?}QOIpz?WSQ)x%(%Xa zjFFzm>EkVI;!iPkiHxi;*hfJ5g4g&l!c7K=pNSd9-;pwaKy{96;-b990gq>sD2R{q z9q=I}mOlH`}OBx+G zN7&3_WVXA%DX~a#fA64nKpba?n^;lK*NikX36t5bEmC4BH7`-Fp&A_|jhkrG&ewd8 zXH;k>^(|e9rIhi9a?Q`8G4++mcVe!Z@8f(6?LKR@RCH5+^*gQpS%jmpf>~E&9wVcO zvSa&M>v?52wL>Y0pG7zYEn(JutABoMa)7Lv3`Zl;p7T)!h4|LytBdP7XZ$ALwZf~9 z#J8|%0;o;4MWL;Gy!lJ})89Aw3Wyi`_qbU7opOqd-fW~;VKDF#A8;k~zs>h5!BoZZ z!D;$NUa+kMrw3Qe@R;$VlBjA#K2l4!h7!8+ME`LRzVQaa9JbysJg8izR@K*j3VET` zR*+bTz8;RE#{5%9pf1caWkRCgrCyT{!eWNtoeHXXe&|zIJtSrPiL$TiEZk+@k40n^ z_mwWuXt&H)O^R9L3r-I(2$+CT4U7#2U}OWMh8`G^`ZuUfH#X=LFgfY&$u3VKY!PS7 z^?$B@U3asIA~8^9z7@G}Lgn&m7Y<_*nQN+^j43PGePpz4OF})iL7C|& z)r;ahzXP!*KQYP~z!dRC{421_uVCv|K`1(BLFyK1eauw+4UIIgheT;tIpN4Q^^~?@ z<2%fL6{h3#LnrNhqweCTrZls@6o}>|&?8*Y(JE_e_cN(QkjL!r?}?9bMOhQavE;ch6v{ja<0W?FbGkGB_8WU|-5$Bxpo) z=&fFthW^73$`UQGJpS+1{P*YvrUx6J(4Y5b?_uc^LQH=@;^G`9|A(2wIa zCFvBPszcJhKO)K?)-&kQdyZ2vQSS%(WW#EQl|=u@$B4yrVs26N+O&Ng!9BawOO;1z zOe1>2$BFo@BVI~gs9zSij46=+v9qb?H4J z6?~BN(hDTj0!huEfTV`aijRsJRi%F`!O4JJ)DlCl{+Z)%f&NPwGNBnE|9=(sQk|2o zjrB2SnB16of}D&HNXiHYk|zHENijiE?nhucUVzfZ5tyj+NaKiK68)Q@{-)y` zzKH=17oJsMw;xMAyh6g0V$tZ;7IXCMnteiX(|-reV6UQRIiUcNwl`g$?>M=%{Q`Hu zu;#x)5Wo(#RB>-CVLW!aJ6*&VFuOpbe&1x=H=FkjM>l9(?wc0Sn6g;l?sH8 zA83N@H}C&gV?8|d&!Mc;m2BIWpqy6(iEd%|=Dz?F zjO>~cy&u+g|5M_B9j9LFr}^c7Ghfhu$M#xw?Y!S!2d-E`{Iz}Mxv8bd6O9;X9TEbW z6-!5nLpE-zoP?ooj9#@Ku=kqq3ELB(bRaNgF0f_)@|YPVV>B(CMG74V7jHfAi~w#D zOq31@(Ts)j83`_8vcmwsB`lI58_B#Ww53b;0;sS;qxm3b)P!#?oe-sCS|M}6Y0s34 z*qSTEZ%HeA$fn+xix5@n~Kr$k31eL)8abT9#%9I*KT`#m~>Zx%T!5~3(EcBH3+e1$mZKvK_v_7fi+ z@~y2r{`pcG+j@tn-j6Wv7F{v~Ur*sh`r2C7U- zbIDgPA4LQQYElwb#3}=z6#!)bsDDa;Lodm}P!<6cG(e#M6h-2hV;pe+UXCZ&vLz}waE6uu$5b99$^Qug)FN@%yJmb+=Ky z^H4^1$k`aGynmq2pgvl%6oeil7Xc))()&lrBr6Ngd_J5p+)LB!@S^NvKE*0TR}nWDye6uAc*CqqiQ{T z&;;gZDZjpz{_3x(||m&|9jU1jTJfg2?kG&AIfUc4=bg!kxP_>4L=n| zGQe2Gs8Q?k4l@EnA8^Hc9%vY90PYIlI>!NSBjCbAMxS=BLhE=mThtyoJjLVup^O;+ zu(G=w_{@wx6&`W|c@~h%_C3(ZHiw^R-0MV4@UC-=(tGV?&YvJx7Idr2kD~QJ`h~bh ztWQ7z6Cy^9DkddI36=P=mQ+AzWh8opJ~hSVQ%x)8pce%zZvmD8FhObxN_`-LQlfnV zw&@Tt_!WRE9jHVU0xAkJOHm=1{<4J69U9vm~d_Mv2=9(g@CA-4TwC{NP)lT08s=Ge@bCv8_NQo z65#Pif`Flbr@YLdxsm)X05I>ZUttSG{V+pCg3xb_B>2 z05k!>H%kZy^MOs;(!eUji=u`bseKU$eL$pR%MdTUDgaCazytt3?yj6oefjKTIHz&E z_Ra@Z2bUxWzNI{{t^JZny?hHQxUGZ*;QC0cENhxsl2CPV3fB_|A( zdd@|REac3pn0NwHnj{=71UissZ2%0Hi3tu4gnTQC+fxG@J=svN_zQUwSQfzs;;V2{gs# zPxO5J60*XT7;+VLt%TfB+H6#$@7+xdH5;)Q0!cTJ#Gq8}2_`SyQ~^T8aLE>b9EiaRV(0>(4Je|3g15Zc zDAdS%=Sq%u(ouOSk$>8~&vzfUz7I9ECXqz=h*!{U)yCnxcWHY+zGrfQGqt=GI&(LF z>(+ys>Z~Q;Ayie~YV2X`KR`SHfD{s8dm*531&RxxIGbF!x}|pPAv(7fx|11)dG9OS_1H~**Q~`yt2K>tLqB9t|{r$+TL4gZk935cfabTdrV4z7* z|NnC6oM$o}#cL3V@em9WVG7K}O6Ze`1x~W>t;TXD{sZ-3GHTLEgb!OYYwaV;-BM;{ zU-eidyn*+*2fuL@m?R?UE$$Kr|2dciLcx^MB&0g5&zEJsMCme%!pA;+S8kBx%^BKsS;+{s)yPho_X6!J{bHE?64GNJLpo zhzjcqU8l?65CHr;2^O5%o4>_4_OH#d3H|ReF%e~p4~`9qgV=w(WYGT<Ix{j;{l#?*h7{`G8oNyRw`dW;_7^WR}&6Mlz{XS zzFIN_)5iQF0&u7RAPs;xWSa<1g5Q+396w&38hi@E?tT!5CF+>YD<^K`yS>l<(!hV< zf>O|JSxv&>JV~mob?tj3iSXJN;93B#$=naum+zthk_`b!%FsW|t?x&Zne`3F&o#|h ztvj3dJ*e|%tTh!aB@o|AOcCUM3!WlTdLS41m^Br z!|dXEW8V&L1o4nE{E@f@K`)M_A)C(knC7H=;1vK!EDg_ZX{&VbuMq4di3Fid=d42H z)yPVYFK?#0b>&PMz2ja2O%>2w4=cml%W8l(&E3oduROE|xGlHy8kk!rP*;;G9oY5& zW#$(M`v!y+1sb%9n1!pfnJimuw?)oKfABm+sAx65HT55u`2|*aE_fcuf#*RYSi{^q z`|fv<(>%z~b$*I|&X$hrmS6g9FZ0f^u{Pi*4Wp)BWC6Yu;70&H#jk^{i%c+T2C(>f zL1bgF>KnnT*BkQMm&x`A=q-;bLJ0FL*Ax(6hQ2u_}X z(XBB+08RyP66hUC10FK~ngBq2KQdXs)4Vrc0}nr#IpOut$cb*|Ff4ErqeR{b2t^3uR+@6i=6PxenCm-*4;#kwyS}jt-u6l+nQ{0JP`%PL3r=Y&- zxw2T=J<)X$f)eGHU2}>V_$Fsh&g2lX~KsmpK-O zvYL9!+iu>+yCN7$pX^4B)Qyi`*?+#HN4$H>d@CxPN_uhQ%A?htJG@#HSKj!JVD8Q3 zc%~>%%Blb4s|)(jA*#9_zf5Og)zF+Mv+-N!r3pp>EeLn<`W6Y>QRnII!|A>J=i6^W zCK@VdkM~h#{X7_O_9}LwS%3F644Y3g>ipQMHC(zB5$LwQcJL#;GGOY#rE|vEp_xay)8UG~&g}>154>lAM;;4^lW2=nPb@y{ z@g^XR(H28aw_0NZEI+4XclCRZt|?R3qCCq>IG!5fWeUb$Et~sU4JSNN=V_q3^$=?K zXgP3ndqP$org9-pIN#e2E~DmsX1psCFnLie(u=1f6Es8_b$1BO1Y2F%%?{i7UhG~~ z85UYB&1erSgIsotM{oiyp2q04()x3w!~J*l z`aF_c3i8@6zqH2I4gNYKMYw*IKdbQ`=n~L#y+qJKDsPwVN$B`f{5> z)L%7R%oI9sc?Tnd2&6pSc$2U0+}KIxnN||>-vp-%)9SxZV`*ZfY3(^U)^u^F5-K6? z(qTzjxHV|U%H|QQl{#*^J8Hru03VTll+y#9t&pR~u$gsAFD5&R&e{4S)xE2J={x`*>!`qaWQI+M|2$uN`NqQx+i`C@W(bF0Sr_;a-Xe|n(5TrKWFh* z!elX3R`I>0l#_9Mt0sAl&+N)ocuk*`#0RJ?Ih9K^%w=kay-PP8n0l=4lM#7QukT_RD`^M5xHaxWL2 zqsDQN@@)VP$mnKCNKr5B-2@2CZnhnTbd}bEx0zADLTo)O(;sK_)k23taxSs#S1Uwe zmwkIRXuDQ5RKvl0DG)@ORvzuuKRf?wt=nL8i^=6vzao-=^$m}Jijj_v@es_1Sj9o- zt9!QA)qk)Bn?m|yE@sEojvpjvV}F=~ZY)0(!NUG0eGkwvMctBLq7AA^i>}>(;L@E3 zA901A8`Hxj^U|-KQ0IK_*+b447F@9P$F%Ku|FA9j4%#*geQlzGu(KJd)uAXI@d%?5 zT~yk1?v;s3wM9gK4zMf?`6#6TlERkqcaFc65bCf-z`00$Egs)%)k&CJ^B^lsn49?1cKvB<|Frpk z+9c2t&WG@r8a618zngk#etJ0U^}R>6#%R|UTrskysMM|x7C8osJKz%m<9Kh2d=2wE zt7+h7@az6eDBczvW4@}NHv^$ERGAlOa?*>fh@(&%ws&)La=x=di<#zCE{ab{x6AOG zw?`|eK59|IBuxmhS27y5oE0$ z_40u7@mNlkIQvD0`Wx2J&G&N zS5H*1S-qZLdzc^enHSS(!+M_gVW~d!5ZH;X6I1UKtfpUvb@crnN5*#WI}|;7-jY>B zceQzkoDRxwxc>AN;mj-Tdgt^IW|eg2vDcyFR1ex0Hygai-G7Lu&CGyU42T;DXHeSp z%{>t!o4NKpm&U^{6os0KRo~#g>w%wk&K0B zcSI?R=$woU{i}G%M5SaR)f5pp_Vdm{;Z&Be`4b&OYA7*WiGL9DGvo_>m18oywnJY@l zNqY^mS4QPWC~n-MyPT@pUD`1(cX#FRjlr+AeHeTp*Y>)YEMeE(3tzG2vO|Cesu8V!f zJrxnge$Uid*(~+qCRGFf8*|6ZiFUQU!D1#~=x$@afiv0gfFky;cNDsHY;sBOeiNVO zF6`gz&ZZG#FR?GcpWs(UjvlxxL9ThD<(h^+F^arx2H)Kvn1I~&qsT~Cg;Tz<$%~`A zOOLI8B@ZgAdmw65$h+I^WpT7MiZ~o{)L18>D?q=RGD@Id)2~lq{5rd%OKSufR&N&8U$ICznH;aYo7NSm!PlCL<~+(5 zG2)O2WU(4{`=S?Qj?-wu%6amEqjBJ}eA3N@x7GpT?MYhmz765B+w2^w@g!bwIC7)m zTtutX`C= zG|Kt_EkAmaA2IB_@ihA_@=s#{#ah3o*;m67(r5f((afz8WhcWD-DCEo^wWM%4X?7p zqIcGwDLNoaboa}U(F+bZXKfRPM$g6xD>|eeNltPS)4Q^|XKf3uMU+|dDW2+FN=`zd zPgjl*;Cf#L8kp*wO4^d_BXe4(im)5;DQY{dLWTC%Oq|yF5%1%iqdq3Z3FkiR>76#q znlPL*(Axv~jN_d(La^(46AO+Tk0TEMgS$oCwBMV!^~t!`WQW7L3~xDmfPR4Es50U0 zHt6!N|6RF_>$>rDMa^hV7BWtgd!Zjl_Jbt?wN_vA z;5Ypv6@MGc5shF!7>9FgeATFAX-|C@h7TBSis7myw<5?j8<*m24}{M5LR9*OWB&V0 z%J%nNxx$9Ol^mrX4CdxKtiQf1*Ava-u(5AlxCpvB_SU|UpglZ6o5mcRY#z|Oeu9(A zF!du>cTq{eFh&l|EoK=DCoSTX9Z4yBaG*)R*2A$zQNB?BoBB}&S6%|$!*3s7E15Uu z!z*D?Kd)eZJDR{+B04ILC~rCau3}ZgQl4Ak(YtAOrNWDEMDJclKNxkmr{DcW7lQ8j zZGZ9S0YA|W@V#<0ksei4Efe+DVPh?4xFtF6oS3J$DKw#Oj#rEqJHx-a5ywjKya)Xh znwUqdr?s0_Yw%C7UYoE~0{@FwHxBYmTCO(<#)czrxYE@of&VMP$+Xzb>AfgbL1gIX zUX%CG^?OKwum?voYQ=3c;@p4QtnBueS$tjDR;>tuiwY}F)pX~IM&YKT_g2$hj}|*` zRK!f*sE&ahO5ctNUDaCWC=cUj8OMsanKHWw5@IW9q&w>%HxG`~{`&mlx!|_b%!BFI z^L~e-60UF1Qm)kA)Q51BS*K8Op1XMXeM6k( z%#J6n>Jjsb^7qA7_cXNqkhX-#^(swdP?D5vSlx*y4uI!W0W^hhlnmW^`;6W;#A}SG# z2h5}waSV3Uooy73OfIdNBt^W$c6Qczom~x(XQx)s-2O!D7K(q;3=so>$q!>+T3aaj z7yccp1khV+zUAdP`G_c2meQt&|Fv*IEaG`-|!!JqzVvi~s$p!`iMt6Q17 z+RO4rl0K1n8fNRnm7AeNE2q~vyYM?^Hz8Yh>uz=XzuXc#l26w?hOLgOr%Brfu&qd~ zEBp^UC^yP>PT59|1b6i6O&F)PEBy~zqJL}y*Q%rEq&3>o>tO3;S6Ov5WJg8j8i^)6 z8ydTEmO{fjzE;LE-U|zMp3uO~6Qkq{ajS5j0Avb84Cfb^lx4nPYYG``O%X4mZ=H() zAOHZE0H6a36`-gCiqHt30NJOA7#FXI-;-5+$R3L;TP()CPL(5b^A`2v`R1_RC zHEz>QCu3;uJEdUJ?IRzP=TKri?|n}B>5G&21NQlV2k#Rw9{${>d=wz{k|<4`1$3}M zCteH|9n0@A`6?pDb6GUN#sO>sz(yT}&*M3kcwqZ8?7`x5vWGtpgdPR7y1=4K96csS zUBq}!4AnjTRR54Zmqq(3m!)60f56Dt|CS&u^@?o1cSH2xZ!$;#cL57tF%TwMeldZYMv#Tc|7fS;JJ+!&jG&;h;LWwL?t?bG5k=`%85Bdf@ zPdoH4o}ad2ByW9n-L{N$W_##R8%J}F#)XAzR{%*dx$fLvH}vjTK_b_fw=jLdx3iMN z;!P(5`wP}l3tBO#a}BXi&C3T6vX|FlSqtWS2UJ`;tyivodk-l#S~d0_-v0h3S*t8c zeCS@WKZkVj7Uv=g@o>RpXoN_?ouc}+J4Vp-2o`(w-heRI$JY1!O$423;p|t(EzxPs z6px^U%cpA3-*#jnp4%k2(mu~#S5~aAa&{hh&)(Cfzv;HT?_sA%(y6FSERa~J9Jcj9 zu7SiO_u|GtfRv@opXtai>8zeKq{9l;Ln&Xj_?uL*%?^i}*49SZ(>Wp*gtiYfZ>->V za!^bcQ9?Lt;3RMdW??5u4}R|^L+7UvE^QB?La>2KKP|A;`z-N+oKm@biTA3~^U`9~6b30YY*^;f5{jrHGP(!H1?ZjJy|3(D<`~4o+ zNqY+8c25%ddm`VallrxtK^d8IB9aDM2d0isB4i7*;r0$Mp3z+7)4H;33M^R8>M}wD z+ihtsiK5Sh5LA9$l=!CfnC(3ybkRAs`0TQLgCr8{gBA1XF1Pvp*>z!_=?OJG~;FUuQ<=N)zd2pISa$RJ6;eA+!_L17DlSJD+=_=laoE}QxcRM!om?ROO~!#^t1EH(ajR%aCaC| zr4JoVL(VI05+a|P?znY)_fYt6G&Ijj!#O&dFPmx$1CDBv;2l`EmA*HTTx+pRR~O*c zadgxg;I$4DFe_j0{FoJF@|+`)kAU^`c~bLQ4D2wtd?TB^k#D=U%T*#U_1T;YURkqK ziFxLd-FsN)1s7-Jl)kw>2O|t!F5{eR{uJ?v=DQHm@fe7MKCD?Hedd@KfMTQjr zRl9Xd?fP}C>QGmoSms^4p6ko7$&P$C$`#)7(%vU8&cjgWQr)%sML6KVl{RX3WbRm1 z25zrJ?#v_DFWWmY_Mwk#Q|9S!DRrF0&O!))#M@A*x+m zicX?Os7JGB)?}5_mP!7%ixD@}O-}j{j))Ugp^T@`dMX1{0;~oq*Vb@Dtq8s}K zUf#tT((F5%y@x68=dgy3w=3;ryXo6l(H9XfhJ9|uZy(a^sC(-Tqn2G_7YM`UzY#fC zmeCLqId85~pSmm;P-V8eN#Xl6C;YEB_?leuGwkIQFHO^}vxl8R4;h@<5_`%DCdPy^9Ion6D$FTV8i1LHE zW^vC7V&-Un2*3H{K{|FEuR-{wj`3U8-PG9(#TV%DD%seVJ5}!hIX)jbzGXSSlg|Fu zAEu*-b8Ink`{CJG*JX1g(W28S^QS#fulq1-%@EqJMuT%+KX9>=m27cIYZFqEWY@Pa z2-i(B1Gz!XA5Je4>IB2?9)ID@h4q@n`oc>9=jBex2I1Oox->;$x6~=fvI^C6o($yj z_Vn%*Xv-Q4H6LHevQ3{&V#zjb!T#D4$gLm$C?{~dMsD-TU1XPa`LQ@nF-chqbXc(=W8}QZ) z*)|{hWj6*Hgi%JKA&Nj=Bk5jD?{JiP2clt?I^LinAgqMYmus1ZmT;E?ci*3!W^-h0a zIf!o`qjR!Q`e9-d;)S3B7yN2G;2$>?aaL~B;(&fLVn_$WeT?r%+LnvN;77&vkI9j$ zEaUTY1D8<+9n&Ic9-m0WMpd{b4c99jI#Kqm9x}ULmqtm{FvKx^c=Bd+%>QZC@QQ-}>$LDO+&I<;ySuN&_Okbw zQ1*dJ0cEnw8#huz(`H20PR5L2yR-D0bgBz=c4mL> z%5W54qJfwJ%xGHmgiYHxlC^V!gU5H6nI0ixY^LI&S%Z!4UvJbp!GAD?6+~7f;taXo zh!j(0-3e1~b~ITZ^=eRk{zh|r?Odfof`jyd-`N8??NQRCFaCA7;?!hVtggtoc2qD= z)p7OOMZ`@Y7EV+OruI$=J3ofsewvnShs(8^p}=f9V%%RZmZ``I(v8% z*pQ!f_F=maRXX*Wd+)05TlV!$MrwJmMl0S)h5 zR=d>$6PWel-F!)*`ITAd-IVGY9b!|L{Ii30Q`m1lMa4?=*djv(_)Agp2&Y=@|SALLo07&L;#XBBzSD@Oyt-GLki zN|U?Vk=x8f{pE7;-S0`;WVdDXlQP}a!cnH*-tI*9ucgSB)@x(a#j^;}(Y{#Kg_z<# zlk`xl>(=;?GsRW=tza^hYEs%%B+awC)YQrBR(voN?hpKWrDKS&QgOVcyTBZGww$B> zTLEt=F~XpW)P0@wJw$J!a0vgIc9Qqb;qrAQ1=$N5BnykiOK&&S=Zjqx+x6FqJ+92r zSC*nM3%D5P=$LISMFhe>&70>rS|J1uit}ls^B*5zp$=p+lP|yb5*A=2u&;$U-N;M4 znymfMwrgp5R}g;pbQYbf&<-{&%V~4E9kSMF%p<2>%dpJyw$g%~iR)%ZmD%}*zRKtpnO?~g1Q_Z_uhws zfipT^);U~xbRY2|%acI(Vq7^K>gvopA6HI;Ea5Ix@c)8*f$IO(MYxE&w!^ubLOm{q zcF6CLK=vur!(ukK!{Yx_H<|n{GNtf*TrLgTf&Hrv_L6-kOU9CAEMxnf^98QBo^hKA`$;+WyaAb`6>m$fi6SrhoATd@zv$Nvg|x{Ly;h6L)SD?X zIZ+`bYHWR?f^Q}jtbG~M;i|F!WD!5+P_6S|F#CaUld_}!3Y%rjNnt&|jL*CATt02W zZ|;|w2VID|2E^VZL1m9mL$QP%@ngphK`~EyDCUd-V&ew85%^KVX_3dNeMH%@gR~DU zc2wI9~fQ?_BCm4XBq<9dpQGtW5gdPM-y9xK&f`YDzzUco5Id?Y}wV4MojY4bJ zzILZzeJ&pvcNh~A?i%dl7VaA8lNIiYGvQP|Wy`6Yx&!c_jw26DfTzBflLH5{k1}Q$ z>?i|KuMPcyJ-`d>l^pu&e2p#O&mpjcT@ zD=(x~dy&SFy;Y!Mqe=ZBno$#!?nG(*t2UPFIXh||SzpxWs(EzjG^9dOkZu*#)Vq6x zGv?%bOCM0c_bT@w<-H5(s<*|3hXW=jR5-rph`->y&<6$R%~JvgKRSr4SxfeFus)%p zy*Ec3dBIDTR_G8qbc0 zTIB6zvdt8JU}BFC$jWvN3vkJH#Rtq~yGHsO?4U0gFn9)Zx?u-^V15#`+NA}=K}AD( zCld7^AcG(C1VAdj89W2dPo-3%H7|w|AOw^b@&N~3w17c?5hws6r?UQ{7@+1T6aWcB zS%1|l{NOGW0D1n!2UITtfp|O-0_hjzP%(Ki{MA32`RRXtYwl71G6UhRzCLT=uHHUy z)!&B`063lbA7B+(+Xw#@SpN^ODhv#rTW}D4!F$*U77(e#gSqKDh)pKL(h zYfp)}27{jWpV`_rklDYs@gdKqgx+}S9qztd>GEt!_Khb`72k-!0QZ}hV~>lHzMAD7 zm=Pei3U4N!$7Nn95oyBDCp}FwV7c>*Vuk-;{6?;w@3Kxpo%1q3xo3}`W=D?C59S>`u0Bz0B_)g#)>m%ja59}CCRol>=~V=+dSNMFKAXl zRNW-ENl{e&6-xV1x?ei$VSS3M`j)3XDH(wN02JBs6hnZ6-|B=8lv{!?H2Eqmg#fKZ z=@*nXIWldYZKEqw*gU7p1n4|U7f?#+P<%y%_WFp>-u^;JO;GwuKI`ER0G7`*$_J4&E~+KFB3|)qLkT=Y2OBDFM0#Cv5y|oXh@45@Az>nO<__o zZMJCVA3`th%!3c+pC3P>w#>{IE#F1|13o$1-vYXC@Z+IV&W`p0$LjCp-iWGT@V^5n z2cQV`V~yVD_{-w|4{ON((x7MI5uXdj#SFCyo;`hg`tgicoRaG~+e;Z)x#rjR>(^bWy6w9?Mu$vY#kqTIbI}ZMeQz^nJ#6{J{90rF&IeVm zz2Ssxum%>6T4qt4!W{qhjD+qD0H&D)`X(LXpwq8PPIAK2O# zI9{qA@*ySsI>_`hmR{E6!bJy@Zwj_9---e; zk`6s*FuPCM?Z*V|mfVg}+4gkDNju*4!OKnFybP)viXPE{e?+9?=YXFUsAr|I`=;Rc zh)!aCP~^9+P2J=lRU;VeHoI~E6&1gLh+;}~P@XG4M-d%b1X`e}Z zxoGSnNYdLeLpemCAH8&mW~k^GZ@w_5Sa)WAgG;p8e$Tt)xDL78y!z=kv^~NzXGaz5 zl;<}L343q*Bs}ApfXQZ(W$k6_^xflUFxqt1#w5=2EWamCtn^eB zkz$t$;v%^buhfM|dC3Cz$*Ga|M0d*YNL5Tbp)M#Qvf1(Ow1{D6gsi-~7jCNYGalO< zM-J~tyxefkjv8gtRnL<|s)$5cLLr-EK_cOxe4$K^taPp$&e3C55m}7m=?eZ$arsod z{1&oG^or!y;M2>SNjG*yuUw7~OFF?@9hP(e5G08WUT(NIJ-``llkz^`sBMb7?r(!N zT3Nr9Y6 zx&-#{nNSJrW=OuD2ILdnP!+dgr~Zv?KzLv)AU7Zx*n+$ixv|N~@!3%yH^*nfkQ{+T zz>auv-`5(g2&g>-k|03D0#{Hy5AA zaUe~k*Tw~^j7>FKVH-gV7F7zs1M3| z{+0X#|Nk93R%E4cz8J|`UUjxywXs?5-&*|^Y33Q;+PqY%j-`APTXhk_WE*^T!FUzBb1O8FFrbpcKIZs^cBjKq-v zgZvA>e!7*k;_xtXViU%wVyGA70knZxV!o#^>W|KlA+DEq$v^#0JtEPAXVs| zEcxXF4U$QOdqYoIW5CMXovukE%opilGfec#-mg5rQ)1MS-6IvzD?a37 z-iZ3@A#l!SVZcE-!T}G;PFi@>)Ae|Q3n$0MZkpdgSN(-Pqp>5dY}pHh@-U^~bY(?P z*L5LTIw&OM4Q?Zj{Yfyjcp9JFoJwfrS0ZVIZ2S$}UC^N>|0F%0I~Bkd+5+49FT{KL z1_s=7{Gu3|5cMwA+t@v~v&dj4#zyx6%{xOC&|dE*H*ddQ5Cp)x;VOam56TV<$?4`h zL$i&f!9))Xxc6{khT4&F8auBomi!{1q?Dg*zBmafw`*T}}6Q{lNj$t}7cF-9YXrFH)ZF+Ag$cM)E z>@f&7J{W|(vB*7qCus6pAe`tx|1ZZJmEQ;&`N&}mxSp3<$u9@+tAh;i5-uXSUA^F4r#(^dYdznijConJ0oqsX0ncM*r{RNOCfgxV4@Rgq394OW1p3m_Pzy{?Lu=@P zPNdZky1sQI6g2^t`UR5typthjTjWy=dp3TulJcxnUL8#PeE(VCN{v|zvmh7lmMQqy zmBeW^^CmD*&bDQfcM>OfNNZ#Qk830JEMVd1060Ou>xap9zw=>)9z4=f2gT5g@qSE- z;a()wy;ymDbaXogD-sITolQ1;_j9nWJ7$vqfVK!Q7hDkuxc)*}fn`Gr^4&l?b_1aL z2rF>O=Y|Qe_wHh{;og64<$jhl(lv$YuV`fIz+EjcjzL6QhD$-bChyRA%Z%3pwUy(- zb^XmFsxQBW4x^>@Yh(fsi6itsLr0@k0ImdrJp36t8tg+vr@)vOB;wD|(P;mz?#X#p zR+=BKOMZSBSDBR$XD~8*5Jgn~`~jL2!yj)-q@W=k2AE7zk5zEda!}S%pbxn(Mf}3> zO4VqHT}&o>_T{>;j(8-H-sUSSzl4S59WHY9xxm&Fy~<<4b}@V6asWE}eISZdAyB7% zSkgR7z?+Fhet@C@PPqeVz9sM(xb;jg1RR$yOImPAAb9dsWrVnY195MIUdE}Lh-*UJ zU+@L$#I>M0J@iuh5F#oq2mzW^0sxvP2mx9MFQtz>4He=50BybA3-D>p0r6=LFW+*U zuQp@?uQx_Bp$RW0Xe}FFMlkW+Z14pr%QS!{`k{$TLvYzFvdz|YNkdI#yjsML?&k8{ zK*R8s;r>cxkwV03#{NbO-bkF1{VLU~7|dAB_>}@g7D9X)fwDA*1p$IIcFVMWWQZE-0B#sB2$Vtv z6X5Im;9omLRToeyy=V1n|0C&Xrj9#T3yov2{2;3LpOaX*aQdyo1NcC>6!T=Gcb}_7 zxNv;{%*_BE$ht3R9P0z%7F<#zs30S)xU`5e;y3-kLmq4y5D6Pd9Lut z&j+g*zSM8Vp5w+j;mC3Agy5Ci&MS@06HCnJCUMn9fx}z1`%j&hxfrODFexb(q|xuk zRWNbaHmgu;|B3N9Wy~m!v-b_H@kHJx#1GT5C>%PBGdWjhPayEy}& zGm!7%3^Aa7lXt0e|EH=%k?la02p>*zdbYbxrB}7*3|FD&8n? z>TvkJH9Yz=!&5&w)0SbnN@X5(af`da62iJHpvvXQ7K3gPt6Nsq$DhS!G zjCS{O2D@hhJ8b0s5SL{TiY9kH_`}{!9Y9>BLMZC&O*Mh7n>v8~>j>Bzf*fa)bpW>3 z1_1MG+E@fRtbPvuRE_+1x+5Q)6a{fVIJqy?#NIWaUx@jP*K010?8f(o#mYQt;_j_C zVuJa(3P#_5u6Pn?==@oSU>u{iL%dB892Xv?FboOko<}LzX^dc}xx?@Z?)o8^Y(p3l zLBXT|ZZ+xv#)pM_U+^JN1ol3402Gke;WlPG&;%8)4M4W2>i(vCUE9A?jrIZQ3NE%WM%sM^>NmzBqc2(>{rgdm$jIcazM*}i}@(yFuL%+k`}K-s77t)89b zjrazc#p$tD^1!FE6*~RZ+1feD8Sp%F&Rk~inCDKHvoh!XDiZ8p?o#V8=j>&kxX&ML zkI0MB8t0vLO~AAWvjEr|`1mMc<+w+19()^d_yMR{LnFjX=yW7F-K#(<ZB6MPKevgWdyxqLIm`d*-1rB%9hRBC3ia-=e- zWlk2b{n7*ai(cxtV=6k@>o2^uKDu45IAbfUV`ee9_i7e@sMBuD>v`9b3*Zkd(Dt-# z1kqU2`DJVcy^cD#2cQkuG5YNaCcxO*0BMK44rs)zX;~itY_F+1&?F9e-G8sU|3_>^ zo{U+JWqXg%bHfL%!!gy$BIRh1oTlQGLusD_M0Z(&sBe8x#vuB?IDpzbn`{kGGIY*= z+o!gTMgnM5K5A>hP(zkfY8LGY88g6>mf=Dm%slNg!LySZlqvHViM#JqHkAdN^$yq+zs3i0Dof`_ z-U4qf;O?V3fZ9}eMHDWJgwxdE!2R>ii=d)_ANl73Ccpx4|4)xmA0O(}!JCm^97fZ7 zpy~Mkz!wvlevf6|YjIc+Vm#q2;?}h~-#kWM;3U|PR=uVdK5@$&Iq7+PaqeJp^S&De zO?*ux@ArmDEF>q%s|2ylf591)Mr`V67Iei5h$P z+yQUGgaHpP6IhC;1xv5I7bZ6VgCUTG7rrFh1eWG$2344W=8rUh#R4wvfSTz;c?5yx z{tbX-2V9baOIwY-uJ`=7xgo+jUu0)b_#@pD;M=TE?#L(bUhe2sk)6f`+YXZW=;DL7 zyfftA48DqMht@mv!TY4aCg{U4?}Z!!c$qbr0!MRf;Pq2Z4Ai{E*vp0=yo92RYk3iQ z={&i?R|9k}=iDTL#3Py}@QuM17z`ay_YuC#%wFU(t2NF zh-Wo{ru4X0>ZJBnsx zQD0m?r4E1LeieBEaagd+kvED=(LW>8DG9`$y5`DrgQ2=iC(&c3D(T6P#QmnFnY7c^ zatqUL2F8&_k)9dd^)5RW&!(EqUBwlRoYv+^rGz$`YDd0vpZIPjC3{tf(cl6k=O9sm zL@ClMHtliat9rhtfY3v-@X_M(a38WT^Q2T`d~|Ao!OY0Z&Dq^!rYtF`nI9iVn9jNH z8Satz_e{>PMtCH0(AUXo1>7BqNK`6zRBL?IlQXyZ?=x{gf5+mIM}&t+3MEX%zPEu% zCa-RUPMhaF<&VaSW z$}JV!5~sLvi)Go}D_3h42CzI{ZuU;({FUI+Jgl00vE`iB<$>HIiTZ^B0?odc2PoE> zIl_Sg%@Z+|PWGN7Nimgy{Uk^PUjt(K8UZxvn}*RrEt}m&haeGvofULw`i|{-mu}w`rgzG;4-m1V-jfVr} zz31Wy0Up|FdXqv9)8Bu{e7oKMF3vO;D`cpT_K-Q&FPs=!GrDZQzgd7*-?kV0|{Y)H!GwDWQ|T;2S; z3-Y7y+weW+Ak{j8n$cK;cZ~bUY+2c-=`@M^@(YoXtAnL=6r}lM8R=e@*CgWAIWa#| zQ!Y|hnBSSvGc0ZUh9~P~_)9O`Z8!4LXm?Pph?%`DThL-LfPe9Wc++{c>ds?`!RTI2C}W`b3SEixNmXyJ^Ao%FC2MfcKGf6o*!f* zFI)e@m4{i}gQby^b9$kxJ$rH8_|+LVNj*8-_FZbo+#>U8vk0>Cl)u}S8DT~|yzFvU zXP0`KhbbeoBa~tAT4LZT&XAM8S;eT3(iflTbg=oHy}Of>f!V;PvDRWY@T1ZsWNv0@ zY9XnCQdL_L$#dF^z_J{$r`oprGkZ;PXk!8^rG6* z(}@GNgq!$s+QuBo*YdKI##VCGmCWgtH-&PE(F=j{QVUfJNt{_mJo(R7aZ^i?u3X@^ zexI&1d?HVW74keUEDVlB=FTpSA+q_dzH>*h5l^slT{0I}9i|DkAvSeJFL8G6TAYuc zC8gMwYmhr62-yC8_ zWGHw7A*F8B!O6|TVUj>DZX)H+FDBK7Wy|Fz;I_ssyJR;YC)HTCxl#~r-0f!h0p8S( zLQStAI{?k2^_snqQce$N9*`H4j(phS<6glqY^TFIJLQy2cHgx_ZZE`F<=H zbQZ`FOWVgRzb|^^c|_yxXSH(<%*{E^`7dv?%_59Lb#GR=yT%J5jl7%=*=prWN>lnq zXVuKi@G8g-hNXUiHVLG2R3AA`ejoD8{g2kwPF>{_3#YG-SF9w2CSqMMp`T^ zrXq((jORd(Zg%?GC>eO$j6StTb=XK6e`lLl!FT&xx$KF3l`- zR&*0_Zj_Pnfq;tcF0ZA9PFrMob^uvgEHw(ji^w5v)9rP(UC7edWIG;N^#q;5h`2~t z9SD<`_oB298S(HG=0Du&wYW4^1%ASQVVQ&_$Q3S=CriWXjBrcKlM)Leg`P_@y)~Q* zg^??ik?D!ZJ>5&m_vG>sv5w9ff?U4aTzeI1ixJ{qJvoUt>MFo_E>Dhi%ge0H4oH29 ztC+JTZd$D?BrYybBMnwOUCObGKL#7RS5_8{fWJTTE>1S&%}o%OH284~eWmS$)iFXL zZfRyPZqA`|RWi`Fi#T7wztFuG0jJ>Sy6<6f`5uek`-g&ov*&MmISo|f5jQ6{^5B>p zs}W-UqG5idp`T}>iRXt~Vz2o5xLc8yt`W%{lCAk_naB%LLo8lEhTxsrKtjIFjGhnGIV&u6nzlb19169ny;4d0V)dKXtxHqrNO!jv-6|WwAC%y2h zPRe{4c_m?6n7`ORd8>$WLqu-1d#pW+;FW>Qxpd2{F0z9E^|5`mB92qOU}0&#v|?^` zsI$(nA;KvwJJSM$BPr?gt*R=!V8@W{(NYKzTP-JkjSoHm#BYc-?r!ATp#1>DM1ozwQ@*LSBsiKI+_ifs2BA`HfT zzw7v*efQK5Yh3U6bIlT3=0>g2J>v?a7)v^R-32Na4X9-xy2F0kj>2=G0B#Wox!68`y|Swz8N)( zb`#m2ddpXFuT;3Wbmvn}+q7hH^(_ka9Vo2bcJhL+Vpv=OfFU7LUH|OV?pgvMAu;0E~~oyCbs_8SEsbLh5ID_T)u=} zqju);F$QL}?sVaPry!mrW^dxd)WXGF9w!k~?&+~Av%B3!@;dmj6{c-2__C#H>{qwK zlx8)aqWFM?bKLdcYdg%C)gDBc?Go8IZCbYL$lfYB>pMx;?keY-a=$-xoD7 zJVWSJT?TFPT~0O8sy%S$h}XGC-xS`Qyj<#G%uUCU?PV-v%rVT2)x2>hj=6~TW?5I> zUducD%CbzF$;Gru47IxJY)7AK*(qspxKc1jjKzIDIIj!+_z-V)$6riGVRk8#MoC`(@-zAfISf;1r&50x{Z%Fz(UGfBCR;glA{E}x6-jM8Vz*qRTQquW zjWJ%x?ii=b#2s^fPm`}{3LqT2oMKwij(0_5I#U{l1uXuQ2A#rh8&$Qgzr&dbU6Ux= zs;$>2g@2?$w~ud^ZDUAFpVX$us{DB;ZRjj7=rioP&@yJv)138z^=%5Dz__`e9==(F zZa)nRo}xj=Lt}&ArAeniqleeiq}xLif_H}>didv>bV^{sExNr( z$PUM-9gd41bWGBv2R9}O^%l779t+9|Ch6^GF>UJj%#!sX^o3eUV{dsV?^r0Csf|YT z#Ex4PTgpPE-;T?D_7}acXQ(-{H{FNJG$`Hl%7dIsH;$Z=zImv;Ux@>Zh+b6`% zwEB_rMSsz(ga>@)ROu8xUD3gPb{8Hb+^c7?d2sSe&^ggTaduskSKPgS|9|L5N$esnhW?t+H^uRZ}HmNAOiR+vtWr2|4f^1FNh~o8$`#4Z-J96_&IGl zZh0Zm*lmgzvPB0kN*^o>ZPzsSJ3bZ~y~8oCG2@J2`4JGC)FvSinpvCZ;qs2yV|`+=+57IptY53Bh~~?cnWm`( z%RaJrz0TdrhJvi{+iIif?ji9x_a;JZ{6w98(=7=U6>+ZU*r+}EVdWh6VMKp4==-Y{ zmPd1;VlL?)ghU6=Oo(QwjmlngsRr082@thTt6G*z;kr7Oo;!CYX^&$rU-{Qlu4>s6 zR6R{0b|x2ZWr=N-S4ztuQ{@8z(4lyU@4znkUJ zju&k<4*VCG~K3U^ev;n zj7x{GjopT=*t7f})mbb{S&%{xj} zqdgkmF3ose(2u+KBe7s|u4e~Ptk%}Gmi$PRkR3L$J8Tv|jNbgJkybpC{H&KA<%em_23CZmhbQaO z@gjOA$GLq9Gq}Po8&!+HBU*@v#}Id*u^T!Giig?y)!hEg5H2&XEenc^$E?L{k~S@r z`h45nq%Jv87fEuS)w_|zIkl0N2NVO;WtT=VHJ#=m)C6{{{AO7>8gux|9|{FRC&pnB zkP&SwXCj|?!ztHB8!Khp5j1F^L1#TFEu)?ntYSe@I$M%kTCBKqj50XGF4r-x7d0&W zPal!WwGdX=eug03%@X!~Z~llS+jZyTBTB6sn?M0>ehpCU-{Z{KxLvEgubsy-B0H>; zB`iE??s7B!pg!mzA$Vo*fnGS6CZhf&9eOFe`a~&Bh_-4m6bA7+?ixkcC+ed zc1SNMXT)`!8W;JUti)USFZ~3UbJ{>i%S8aLywsg!A1gXi(yYnxkCA0aB zO`OfTGn^COY^pLAVTo=MtIQ5G8>O8f#ZsAf$hI&S&8PnAa!Hc2>G6@?mW>ECSEcLg z1rmBTR6s0tJ)npIc`c8LnwwlYV zuN6yf%RgJLD-(Z*Ks-vfxBT2fHNt2`Qrs6mxC)ODT8taDCL+Ir)M4wP2NQ{w5j_Nv zKdXi}S*w}|{m-fy{1U=Js*5|xmr!{S!Ni&gLL1K38Ocm-g-%Ws>?EHZ?N7A4PCpW^ zU7%~_QW7lYmOo~@xkXrO?`>T1dz=YJp0)G*wR?@RKWH<{Dw8JqDY34v8YPqj{qs6l z$^ZfdI}X{1)`iGh(OGJ^UVb@tIJ>)od})#`oqXvt#YLAYvci)oeS14VyfI2^A+)qr;mcQ ztp!$L#UyrZgCL={!tU6Uxi91X5V(C(;>^`7vXgj*?T$Rsnc**}T!F~5|Eycq7`bVu$Mw+BW~alP~YcIHl4%BQWrTTK%6pY)7a z9&4m?xTI?LLB4_Yi2Egp4{}q|InhBvrFcsgecUByBi9$hKU~}yO-$yxwmu5ff5Q2Z zO;25<`9SuNr9h^fffx8kr6;}O;+j=bEpzvsd1N_dxQ|_Lmq_ylmkT*DPYg2sz;6WK z>p@DB2O=Vi7Pfa(f#C%Ks;Mb{_?{ql$ zVa~zusX$ck6P;APUIIJTh;?jxap|6y4SRlf-W|=qUsHEr*_4<$&00@tk+RMCCR81- zn&M7Lmdf*&&m9Wh6Co$CcGcWi4iAkw@3S+g z4%t`yBg4u|_6d`U1lv2Owvz1#o8CjA-P}CggY%<(yt@sWZITjwd2^lheR}C7^{8iK&m27#2*1~6$h#s7q=_qqc_KOa#d^)*6m+OcRS%PzAsU*Z@V*|B3X znH^V#d5fY^6RJ)Pl+2ki(rAN!()R`rK{~tP=Hs`A{v^k6g?_-0Defv}aR^ z_Eq`QAM$P9EO56<8W1e2j`+$+Y3Y4BG!vXJjA?5k_~g>f7|4#Bkob%uwe_8*TONP# zVCo5DxCtC{>%273)+LjE8>@dQvg0e~^Ku3){;m!n3C&e)f!PRKb4Dt>J6|v za$EWoQlUo(Kk5<4pP>uumCUB0Hvy`R9A7ps^Aec6w?XA!gN1NYxq>M~w~wS<-f1u@ zzWCj(ZXIR@dM^AD%s@%o!6sCb(KRCKUvV^cg;k@)iYTuEabHaffI zd^Rj~r%YzcXczvTDcyA%V%D%JT@(#6x3TAQuv_POr(=rU(DDR(70jao~#%Hf-i#-MkzlQ4IqsxaK^tM@8?`ftk;wHVfWpUHir_83Sh((S)6rA8<0DDgWH0=tlKPQ; zDbL)m`4H!lr5(f?r7SN+<_puxP(%rOpMFyw&NIX(B{W^Nq_7?3EsEip&V3eP>_a3u z<-D*6&p=+)HEM49Fgq+}#~(HO?v%P9 z0Wk3Wc-rl^H(%)RKnwed(!7ok^b!)3k|ze7R0O>a0u1QlQa$KEA^}hXIHD)qsp+DY zP6ciyT-qjF^Lm(Qfl|#nk@N9K6uKLExj;3_8fR{O-(M8X>^=MCEn5YebHU$cDe1Mk z4g7=vs^?#>ZKtF(4_G8RHNB8?GuYrdV``Z71rt#35=pJ-dO`D31WbJIZNx@c{+U5E zc3nLf`x+*Y{M(>6RM%h4Jxm}mnu0v}R_gFlL#!qx9@JVIw1*)_vox8j5sC8qsA)aL z9*0J#IFJOuf+o-4S&DxHT7c*;jplWs93&oD&??*}s!rzR9jKiAQt;}#5SNz5;S}B6 zS>s_3I%5)V)M-S1I$2QVhr7t;gcs-S#c(92t-!)mu0y76C5ZElg+O>ltZhLGjqA*5 zLl^Zs@xuj(QhS)$D+_@#*@npY7nK+p%07bN(B`=030ab==A}2F{BN7ZK(;=TDtn6$ zQzDwf<6oQy$kiiQV)iVz3Au#Wl#{lly!(2lQ4;|@6(HKR^Z{t8W?e_CCd+GUk3ahT zDcD^3x0$DMB~Rb?I!F+VJK`||J!Hov#va2=3~qKaI4OD3X~M(M1-Jryth+E*MC#jO zO~RU}(-27h3YRo5@x>`N(@b9v?kbP~;5`a7Rg&a3OPxxWyDau>H&Y-eH$uhfvs#T0 zYmTbMDO1vK2mZ#!uGqJQn?z6}TqBUqLv>r1}J)9048lmu*WO2=_}n+{jtW5}OKx|0HesdwSw72$+E zceu+f9(iG*@IApVJz+~xj+-&sKAbWV4kpI#Qg^pNy#zZdCGnDPK}ymkF_5;GgWDvS zZ)xoGhI>lOT7a4av8b7^XWBq&Krc7Y3PXXYrSU0Y${c5yt5OI0)le5ag2I5#M4C5o zz`!v~9q5oql7)sn+zyEeXE->M)nIzzdGJ)cG0MDc4wn2``+jSXEx5DKhgsO6-dzD_ zWPZwaLZA1^*h^yZZJP6g_UOVF&}Y+c2d5|4{XYBU(k+dx{)1r^;>(9YqpHhQY14#o zswCyMX|if*Y&|3^hJcW0Bh;E_5ih8_Ak~Z-c_gSBn$&d-hpiJ&eNLZN7kk#1=<%!GEaD=P3@T4|UhUHB zOEj(re@wv;MJR_Y)J?u(0!<5@WBe z&zaM(4b}SO|GmLd;A<=h)8c5KR&6cobS@gw#YnvHYis_**e`yR3lf7)8f}{QUirzv z7L)4+bCT}?FoMoLCyq61ftpQGYp~d*Mh)`=(x?flU@zAANc@>sgAID{-qd<;LTdP; z^gZFbqT$@xFbfR0uNm2z2BNnYV+Xn7bZ?UV61xinj(hheEj~fZ<>yHW0I!16MsQD<0DAJ(RPxwD1c<%H1s>jr)k{%Op2pY`(O{t8 zQH&j|+`bs;W!-FDmY%Q?VtFpY$qd{8SSLPL{nkJjYgmV8u3PpC#y4>{Q(~pQ#D1~$ zA6-NZh=Oe&e@U$2qz4@>$iQrJ81PjeNdM`hz;diN8EhWU2_&yg^EhblGheOh-sJHF zr6>GW-zACWY+*3kduK+%O`zK^_W~z+k7%Ivem^`#zi0p}T4U=&Qkgqg>ifNdOz;{VQA~ScT zvL`gUVET1>0R_k0Y@qZKp#F#NII{5Ci2g8!IF|d%YsnUD0=WSc}YimRr)+dJrhO;`fB-s+0yl@KhuU8uEELjnYv79<(}+ zPA6vCIU~VWfdssk9o<(NEMCB#u8M{oKWk4Xcv>lqJoW|bhi+}OkhCpEtxwvle`eDo?XuQaN_y-^H09}A8dbg@JV0dSey2CzcG{Vl~2E2vFF2cJl4OW zUsEgjgkeLvi)rIo#?|*JufCLsDa6O8>nQPE8#y4@`%gppoI`_S+ye#ZQV z=e}duu?*(DmF!<>bd$F|1b+KJtyZ(Y;l&|*@znFkGLG0yd7*@}3G-~&GPB-XR<`d~ ztvdZswzF#XO70xOf~U4dl=;s_5bir6bcYJ^BX92wA7JFF%pF_<+#G-kg~+g zO?eLqJ2YM$!JZf^*Hn(m7En%ob%c3iJ>`aq)@8r8asQjnnaSGrV$vGhMMf2gCKt~o z>VK}TB|g^z!2LQw756`kO~2t1jqEP$i)b~l3NmW(^(+fzIg|71dAQI^4Zx|{P33gw z$DT+_YaI4ZYHgKB+gNYNzSBrF*Wn=N`69uTn-xj>zX>Wg^7s+1PUQ3{TJT9()&yad zK4Kpn7JV%E!t3h!NWl~nvxXsuZfM}kE?|J0z-UL$8OF`&EQ%OCdd#wuy=K&0E9&XT zvh#kRRuy&ZrsofT17UmUmP>JxgzG$xEUd~Eu@c2IgxUZabR5|zE^8whW zmu>Xy*`+J3xfH?-26Ieq-;fc0+ODl%6XaPYb@>~NKnS^>j$otHIBM!c@xavU)XH?AO%xSwemSp!S{i9-bL=O!y|h7hqB&g zzu;C#qjZWnX1} z0L&ZfQ9<;&-#^J3WF2hxFWX}Tx$S}DeHPHw=fKq|_C(%O5f6a+VW~ehi7ha0NN;`P z=_|Md;+xIx69Bnt#{fJMOB$VkK@UV9;ADz@6Y&3&_=6Oy(x3jf{w|*PlwhZ|6XbHw z<=ed=Ryy;v3k!@`cs;gVi4!b{d!tNZ?2rko5B{KOUH!9*Q2iMtACR`KQ8mH?g8JyS zisl)xfch{IrC*HP1M4bmGV61|uj8noEL>O<%()A$E7-Ab8L2g{#AaJ;07wXq;@j)K z{7vw;`s;WWt{n!ccK{zdwmry`-hV3^cM>0r`wv}Ozzxv>B(Kmw$wTb0;56w7%udn< zYIYKhLe^7l6SE3yBu+8vaJ}?zHNV%KerR-n2vr{tN>~kxCpB zZOp-$`49r*@=9CdaRv|bW;}9tM}YPnbAUe zst(_P*qXgR#fn72z+?f@T6F7M#^H9DSxh<(2025?9H_d5Kvyvzu^%Xz6`I|%>@|f) z&MP%tXa0WYv^Cdw0t*3W-;I#qT8WXe_#^Gy&_e+`c& z0XV+qHzul7n7pl$)E*)dhoWS!5smjYc%*|`2OW=fQLhhy#lZ}}yHId%3XSUWU77|)Vi~< z&Lv#&n3&O3nSLugHno1IF+k1M2BwCDhJ4lh_U5Eyx>Jt|30CTOs#sK=&Kg3|6rEbGTb2{mZ z`4`pEc@dKNViG|A-2)1qb|TU+@RKNs4RU z;@VkZmqgEo!%pM#?AF+_q8#hd_C08$goU$_p5XqffCE3LHT{A+-WJV^l$fW(VkW}~ zdJl_Lis!TifXg1!t}7`#LSX#CPB)Zkifh*xsh$95#v?)zaqJG-XU_q%nbTd!sjZ-6 z)8$kFQ!-!j3SwS+`nG4us&~(BU~qsv+ttM7i2*nQppjZ@)9zVl|8h^K+1ea5oN@Cc z?B&o!&+Z&tJFuB*>(SHU432>F;oz8Scrnl+K5NbVvONgEGhrG%AnVv$vSbnJ>GYaaCQ!!uo*9`$4+=!l6oktUQc5OsP|VSEstff4!BnPtx4 z2B>=$rsZK?4LCQ>=jGoj1ZOiUOf@nQ1v~M2QmOuNKXrD4-So#c3*gb7kLW(=a%;cw z|CDtVU`@4ee=tfKC8PyZ6eOh^Bz#2?6+|h66dXgk2TDv35D}(yNQiW7bV?{vBDpa@ zC6pEk$?rKs-}ryL*QM{d&;8u-yYq0(9dN~yBL?#srP8qL$|j)A1 zI2qYYiag0kP}VaD2$x|T$|5z!XMhoWP>Hk}Eq9X|ZZQeYe~fPiTQW$_K%(Yk5P`H- zB|{BhDGh8TP-iwQ;vz(XB_uY31ku5?2dY5xpP^lLoFJ1%s8 zocOq{KDqn7Hez5eRxbR7A0_MIv5}iL{`d$7yb99y3PSkeQ$JaAPJ(dx-G8`X-B;)FGv0e2GIu#3;M=@|V16qqt+-^BUK&(SY z!@TjBStUE$)Ik#GDwbmf5lzSD(P3J@kh2DHl#!HfVkKPvR!TCa3FrS9b2=I>j1heb zr^BGY|0zRu&HcxSbjM%V-?B+oOdJ^hhe@!0!H#5V0cJ89F2eO6<4Njc#kfat^O}?x zr)cnzKiTp1vMIb;W~NW=AHNci+an1$e_c@}#T8BLeV*6Mbs5w60IVP0t~}$&Z-j>Y z@I8aI3ujIH-o3m@a{ONuKGtn4#{kw5*y2cB=MV;IgqAQWr9C3q-#g`x27NcN!s35I3$lW; zx&lILita-B0?WqLXpTOt;zTLa$mkD5YG1f`p{Oq5$znxI;C}xf^*KTO6J585lI!Z-k1jR)i;#9sgJ6)e@jR)g#;YQAPMMm zue@7PkDw1^cl+AfB59}DZdt4E##?x!0J$wNx{gkCxL%H6tSlUfNBUOOFNE3SQ9@3- z!p1Cqc#|rSWhQg@Hl9f@J8z=g$+b3RZW6raAO=U@iq3Z6B5zhcbYeWect1ikAIW{z zm2&KU=iV|i!uN!g=flEQwn5x3xR~oqbjdU2Y1%$)dr0o&oNg4Y62xbcfJ;{Kgd%~sNX_Qy3OJo@5zecF=!voB%nr%Mt_Tby@cc7!l3tfkPAc}zEzUYThK7O~i zGSU*^he@GDT)f44Akcc=ptk~5*$l!!eWh2*1c-fB@>@q6g{Efv9I#|)w06N=p`;T6 zfeAQZoFj1xB*3wE2R@uzJnl)djwFmEOV{8)*5EXvsK6T(Q2sk@Jl})9=HNbq0s?sW7c#z(_0Xk8gDZuUOArfxwAtJM;kf|?ZPt3j$)y7*ou40EK--^42 zfP-qWX_A5IL#h9*I~?0ZHuO8A zK)h5x+qyNgRe0kaq2^G~lk5z70mMp&Vk4evd2CS#O1O>Z*(RZcl&Ge_e@0;s-m#`L z&y-21D~pcGQ6KNI&@Tej3G!Byblw$I+@G|w8JDBde=Cs-0!Av>wQdLFtZ=|X=a3}u%vP~IvoDm(qoR$Q>Je_pXykLq5Lx8*lk09jC|m0h zKlM1=Wa~0yp~^%2yn-S0Rg)KdKv7y;!aD&qApXhkDR~P-d(W8n4*U!Uofg2^*KF3y zVv@#-OM7zc(K;$#K!rRVQG_5=aR(N~XVP&qOQc zOUb)&yrH(NK=srdUbn>pywu!q)?0Me!MyK)(R385SkU+n@~q(sfccUYDC`giJc#$4 z^WCAoD%Ddz5l|K9A%;LvfN<;0tf%#E8i7JVAc*TqNyF}L?NMIB-#klbU7U#s4bvfW)>43z zra>Bm1hv-@o}&ecZHzDcMQRIYU!v9!nf);;p0$vxfDI&6RCl2$X?g=Q5|F-#U*KR> z8RR@r;n78^Ohr%7>x~eJAoD9a2Ls9jVjF>jadkA8-b$GlD>=`61JuK2mQMj(t zJ21!w@!1U>U>T`TfwDj_IY2FDzFG?^x=dMg+M93x=K4n|Z?c66C^vKWt@>;K7`v$X z8VdYR|EJ1kW+wEYYa~yBg#6<;5rp8ZDbe$vzJ&R{GWdITWA#vkC*t4Pc%G)s<%`OJ z6!#2Vj+6%7Dn=9<(l<@+58@bn>(Yek$Qd^b*}iDqnjS$Yl)N#1pxdrY2d{zVw940q zg>TvLP^K#u1`e6`_VKaK6Cs)zsoPcc=cTEhI+{mm@fV&L3Yx5PJKM6p{^I$f!2TPk z-njKN?Bv_ROjmQVoDxXh#ioDBy8$(0|GFy^@oa7<>h6LW-DB^)2o038O0UB~ct{i- zVW{gUs97yK)Gq-0Iz0!suywAzExsl764pgE^?WFK41d(Wd7uMk7LY`5zyfw2 z)TC7SEHJtN+Oa~w#NvB!B=#}Xi*GH0x`w2^5~>oC;PaDyR`U#7#~|$S3vu5cU))4< zF!6fW^Pp;T%Bs_uo45dH(DjA_o(%<&pr&G~xkHbDpTdLP)7eGHEk9 z?|^M(^B~G4!4J+sV0`D!0<9A`%JZ7zHyUgyHDG}Pq@;l8Sx}nr*%Di@)&9$eepg{I zugujwK_S}u;}x33sz`IzJlDm}%-0ZXCTBmAfJ7}sQn?6M&Dle)eqk;BJ)yPY2o-~1 zpQ;NdImJ^EmzTSs`Nw$$PtgN$Z+>BM@nFQnC$NqG+3wD#)UcZjd*c-tL=KpQpyjLr z+NF|k2dfVflqRVJT-*gKusq$LIqrMh1=Bx1d?Q`=k@wDFQS}> z5~W2Xv=DZIRaZCrYt&EL`4fN8NybGMXdRgK0_TtVMIcQt?iwGc9-t90o+Bp1b*;MM z31qOBh|_8#;=ba$f~*i7@}del8(}9a{l7}vMd^%jBUQD0thBz+HHs@?{v*nksZ@GJ~IGUv2@hj12-d1QM`>s6G1nHc?1ksv& zqs?IP(twkP3&0@%j-KeXHaLYP_i+5|;;Beg|gaRU)HH zpqD6=RXFx&=uYIAPqlm>V565PNgPD%yxY+*A8XWR{D_qi8ODPYED7a(Ul#$ZFRSw9AOo`_5%1#pMQ+qiLcB$fkfeH= z!NXH{1mfzfi=e3Q|FpnVbAE#7sSUsy zX;K7u+;mK%A(RP=Y@!n<-%+z&o;FCS1E~_RAug?OA+9VZ>xy;c+$vFru08STSM=0*) za+&b_zJ!kqTP_mpR{&sct~v}efm4dAd~S!WkRx?H_BYRmbE$o{^)lsJH5CdP`r-S? z0dLa1I3y-e@sx@VwIEi46d1Nmg;SoEFa#a8RgE{WTKHBtlDKN+2=ujRJ|?2kvc< z+*>;B`{&r;9;B{p7nqR*m-Ye?+XE0e=c_6BHgg@=T^yl*56u--!PL_K@daEO1u-!$ z1Ew=kG^Bt*0Pv0hIZ;`hEwL3;l)!4fNo$18nI#D^+}@YklpGY>Kzk zKv@c!Ao;j4gB{1FxcG81Ii&t*_R7<`sY?USF5W^Kz}rg8P@LbyHu^e%KbDCH)DKGG z7}P%PDB6oUrFYQ21*PLg3^{?;bh%R$zN{cu zk^R#a>Hud$;GmC`g}!Jm$+{jqbT<+;DS(k+H*R^yR$u#?tGmAze5WXYgRZ^E@t&k( zE>|~p84Rmi3LZarz?A_OIl(b_`<55fl%3&qD|1)5tm*Xvi>a7?lA69^3q+FX<0gaR zZRFI+6@@VHbTwuWp4s@3?Vw=RLYh0?BsS|^-9S{nY&dbbZi+!YbE-ANLBYEPc#-M# z11megjW1uHb|6_{`7_iC&!K)p?bX-X$@5W=2YHh^$W3CxoWE`-ghBo|6b6XIH4lD| ztRlu>%dip}P3OP&`GVycF{FZA)mWJ@ahXNlf9W+BB(J}AbzTvPQdmrWPIYNf7x)mp zULUZ;fb*=9Ns{Mj5YN&aL{iW=ver#*JNphz-W)XiM~#Bqu9^G>I{qVx7ATy5knm~Q7(_3fHJv=<_;iibodP1`<$1QEMHxVtwivvwa*^Ep;jins{z|3;P?`Zn zfg-0nqV*qOi*@_B>v3&!8vXyyar_NIP@L6m1`EG zg*Ly%n{u^Q=sJGfSgf7gbpHdRv6`M)X1##eXyTi!rhEY+=z5212N~m5LnV-Tp|NY+ zWToC_0D{i@s=j*VMum_!R4QVTT#ke^54mN3T9d$)*zfd7@!W#wF!UUTj$D~8>hdJ5 z6pForQ{mi`uPlOB(Y#xY?vdk6o>J`ZAR5JCh!z7Mau;RVag{uh8YF?1XK6pDOTB#e+Dt4rtI9(|zf{LtptSYW;dW?K zaTR%$nm$#J2i-2#SJc}&OrvP7iC0w6?v3)*D0nKuX4{WewX@uLpY>k6McQ)gZtJbD z*U!lJed=larJLyTx>Uc@I_j2OK-1L8>Mc$M@Q;&KwO>trwBneNp?+IAP6<06OVBoF zV&QxnKf=Qw8gHR}OC3IQ#-R$ux;ss>_zTa?Pc8y_ih||l;VG^f^Cc0k$?(8Zx~lgq z=~GvKCd2Onw^seC9uEdsdRF%dV#ClsZ_XE3ByIBmG&(GzXlyVU`#dOpzy{}qJ-6t1 z2)SVF!HNB`^#)(nOV;?D4iP%0?WO0EH~%p~DQeEtgJl7=OP`dg1M%H^*|*XO3`42I zh0%hIVd!#mpZU*JPbK6Zyn@5ZBGAhMf{%u!v&M-@qP&pGcz`ZP%DEIj3GB%jc*Zw7 za+s<3yh_94qbSSotC>%2OF(#%8PV^>tuN~Z$J6P&BE{i5h=cc6du*eXme#F~``J;Lc9- z%ynd(=6Gi2B=`}2H_jrIp{~2Hy8@&{4mGUw89_UjiRB(Uh-SVjJyyUih z);TnHUQ2CVCITdh!TQw6QPpG8HE1t>P$Yojq=r>rda+~SmA$S?@JJvGdRqqJN| zOT7)E;5l6jJz%}jQXU24+8ynYg@qQTv0V>P7BwC$cH5i^aS`ZW0)kz4FMB>%1k!!f zV3IZHwBOPhJvC&en&$;G)Q$lxY+M@Z6fw%j9IA>Vc5RLPQ`}Q(tIhhm$@)qo6vlcW zkKXvAJDh$N7Y#MICE^d3wdz6o(BJ+AOd&;=StT^U; z8n}&9EfzdW>VzW7TBW)mzEy}1TR+~q#fToL(C^%dnyaqp9LwFhk803AySaKbD=WZ} zU8!(xcnV@{9Jk@x@_xK2Ht*c}aIb zV(artVvxmND1jflyk94#zVi)-+G|)+-`mNF-fvW|-`(2l@*Lm$W}?2km^hBw>iK-< zg&l$Y*B+Zf+1QUKoTn?Jf{2Jwa`CiV5uDARUbz`-|?NvW=1nY_b}Wz|HpfTCJ%6O}j$Q%na7q7J zrwhECd#p!cVMX;qE#*z|Fh(9@%6X%toRPOa^51~))~1s?6wbHvMQ(fYp%yqdK1I=^ zXpc8K?%1nJU+m0uZ0w7_MR9-k*X1(m4LW7>L;*!OCsvg*#ddo~74`J&{rCp(jmt_cB~==1 z#WvNIiP7{8I3b$AxNntX8swXEFS^%xy%NUuHyU9#UPf^<9}k4YKKD^+nMAl-4@+B^ zFMQ#gj;A;@QDmhgkK+q;mtR+vvW|up^$u&`X0mm=6xRN{C zkW41I7O*)jKkm=H{w7yci>xA35%u%(;cF*1bTnqtC4<=0>=RwIcv-r4u4~L*cOFIa zH(ZX+^Z3lf;%X_>{IZvpCb`7ecje2*w?Im+4SU9W1@T{E@ak;t^5OD6E*+M`bSG$Ll3T$6wb2BA&zIfT({|BhkmgsVx zG%AK=Uv)@&7@5MS)pD9?VKn-}OHMcoiN^F3qHX$LJAKybShLXuROGc~ha~}-q=)13 zani1|f)}%TN2j(F=iUEm9CMA!2xHTo_{sDA4rSDNhpM6DlhX;ukDW6;{fV56#q>1c zxWKzR!(p8bJiY79Q-<8kPa02$jRpn^mGWStzK@wl1c$A!=oQWw(+HMdJtcT7b$ntY?pm%Ux#06_rvy9iL|-#UQS8*ee*RL5`Ho0d z$LYFt8u=lM7ojY4oCdN{Xkw${YE-)GSFwj>fFQULP=m)QlkwGCY=tPNf3aXk<78r z3F4MNcb<7&p><6QvgX6-QG3`}zQa;WA3kkwYQj`Nh4?dA(Z{9_7rD+kfu1Mn4u%D1 zUwv_{ybCspU~`3VpgF+79z#~Xore;bU(?h$BGG=@N6U-C;1;7aC#;5}tTdG{Wyu|! z==dm*2Lvq^u6-)UnLBvSbkSW?10#hwr<$%rp2Oo1K^E2F0tuy0^v^xGC!s z)j_gS1Ey8L`rSE@W{Pz&=qX_eIL!{6o?>+XwB4=G>>%1GKx70&$ep~t%qg=KM1TJ^ zb9iu=0bOHFu%ZqmEd|1Bk6I%)No$vhIsMix)))bRt0O896istdMjfRSVQ&H|8uiMm zMZg!QRmZ@b9@jj^bU0Yd_j{MDdgGE~7Ee$=x0y2C6Mf_L+rD*7z2QC1w5X^v9ZDfe z+$zr2$5PlhF(M?v{s%cpMaoI)cNU8vh<+qmJrxw1Zfa7VwoyZdmm35T@;$36HwNZ> z18qas6=mYIlE`Cju&{$9TZeVA@@g%dmL$JbL7#k?g5uPv?qnTrJzpRFNm6eZn_ zvaXzJTEk}#t-y9gEEpqoFYnUx8HRsV{2E0v@yQ;|igxcMJBqZDlg8nFv!?}X zI#mt4kvAHbtaw=hyAx4Q3>8DnxQ>HddG8zcFtFF?0$MWe>euIeR%v@`e#pO=1ICSL zUBS_+dz#N$h)Pp+)MP?3T&iowyl(HCi9!V*p&=BuNWgG11roDBukwOLb%PU<9iou7w(bw;D2aWNVWh}x1bNQL1J}X72T9!n@Jys1~1;9F;h>ryX-`z#R=j-4w z^@wTI#9?$`^zOvzISdC(pb_xpYyV7Ur_(JBm$MEF7p1;D*Bn*ANCqHk-T(xoJRe~iacP6eb+!D z#*-gBv}kFQgQt?g!G^>y`da5t7KO?PiP+p4=Q&Hwrdm{ zwWIvNUVjMK#!*8Eh#1<$q_hf|`&mp=9PwVpj3wQsCEa>{ETKRW*2{3&WlX5~d1r0$ zU$>MbJWgxM_}+n~@mqZ@(+fV05vjR&edn-tnKK!9FmM?JjQVjFs8Gedo$unBGBtp6 z?%I!!2jr7A{*)Owe4^FGCMRT+R0w*`}3$ap0Uel2Mw{ zwN9~vRq!yHq|~6pMqc>k!y00e^&j(0ed`q8v(B$gpSp%Ve{6ktO0re7=0(}XCe$rt zw{!@a0_^%8o#NAy{Vba|+irNczBo-n!R6@8CH6Rrhb_b;TS(T>=u||{=Z4!7yVe-* zxG2WqAfT2ry+;Z2|ESA@hD9QcMg}5H|Gpc{}M(wSJUU;2E zzdeC8To+(c6MXJ}>T}CaPE=ze+pNjBrdMbfQr3-y1K~qa|J<(p{NtKTfzK}E^t(Tl z6R+BN?IhH``6xwxtJN)98MK|~Fpt5->N0l0Y?-%baPexhy~w-;HRJbQ_Zz6SzVEn1 zo4#F<52pFn%`W(?A-zJbnVxK0KDems3o^~W!k3V!ycf!RXOD`Q=!;T~T2U)!zkKvu z8Va7`@oSzxXtiHFbywi-Rz@U^nX>EAN4Lv(h(3Dp_w=djK2`BWp9!Ohonl_`nR~0A zQQ;YOg?2HzccGOCPfzMmf_6v)5Mj!18eJIm<^TwAD2yR6=FC{ZS z*wrgv-)}s=9?hHpbfJ=IZ2Wgv%C*Wo9}1@Q4_@_4GF1*fWw@=^A?-@hjnd9d_!6Ba zo3tx*O7NGEPvjxVqb++ZKR`d5Q5W>1orqQtmpziqE~jUW(vFU>SR(&w#4o&f@wUPG zUHT3`5w@;kwT6b~7U^o1=QeT|H;RkA{BPv)AKRlDi9L!*_@RPY*w96*o^&6hi}xj* zX;V(|IdZI-V85kQzc(9p>I?D_vxc2Utf$1L@!@ZU=BqOW%{V08-D#l@~iLt*kx+i zSsugf?@Si)@9&0T2-R@T@A{s_gH#=+!#xuEBQVggOD!0r5>h1bLJQVIa9OhIqt8!(Gl<$==5cJx-R=Po+aBH+@6wQBZaaMD z`(u8{5hY-K= z^h{z!MUTx5sg^4Zx~_)VnsJ56HL+)Wow81y=z3l3a{u0npPh{86{_5?r#ReSid*qZ zNUI=A-){yzHLvkUk5#Hpr*#c{H~vZ0Y@}_zXNo$@A}6<;cS_{};Zleu8(GB{kA%?o zrWx-GOJ97QbPuw!Kdj?jAD{8FL|rtTY_D^WWydI z@=H1dcCY6LEB)mKFYt*#y4tAk=_x*soZ#s3SZf~XxJCcV@Z@QHZI~u~T8<8J@-B5?$ndhcsD^-pnJ+v(E~cwVq{F zlz4Jj=icogE@%6fDXAw)KbMvlm)KAa&P-%zNJn)#1g#TIc&vms(n1m`!VZ1LmYZ&( zmhX919{zF6Bal-7bK?=m1+O5p+vbtlGRNY0Vg?e$lmed}rR}|4+v29Rf*E==u-K!K zlceCjm?(0e>w8LR+oIIb=dzuqcFWc{@NWFje ztsZERGTLwHJPcb`K7N-Ey(H z?<#>wAA+-Sm-9B>^8xou>0vM~*uQ^-Fvvc*825n4*7$b{7>u7024nj7eb^WV*9TW2 z|H+66`Uq#k(0+tVkmt)CTo{52vPeweN4O68(}n{Y0dVm+oxkkibqEHdRDi*b{zsf) z+X0(kKajK6b8uk~U5E~lE@CAHs4&JK;mkan-+7s2s9>-Jei)4NKSHwc2j|xM;p{xW zjxej7I8Fw8`H=R1*jPRvu&I24v-6&puoL409)4y1Uug&`atzr8;M=kdIVI-tCpa^2 zr`c(GJAk1M-TyK-)Ba}e`~+v?rFNz=eF6AV8UB~=Hsf!;!vlbib3u9rO$meT0WkjS zip1gHd^aJ!wB3oW$3UJOh|_=h7C8?1$mB6sKEhdf@so4ox->8t{`CJMT*yrx8`Qvx zNd*Ei_Ns7ZVB4P`k>lhTgF*Olo??TDAV+|PBnJ%kuls;6TNKkf0O#kKH6`*br@~X$UR@FCPAVwE$g}j*#r&#HbE~`2GE2 zi*xY*$vtl+B;etG*W(Er91(=R3|GE!@MHpZfhT*E@ zC$3=5jKEdkt5@Kdm`=D5CTavO0Ux~f`%2<1oDwrT0vCZB-TX~b7zGSwW~8fAm}jHl j-lFBfJ#H!SyZ4+7^(jHx!(b=De{X1Eu#(##C1C#tn@#2! diff --git a/modules/hydrodyn/src/HydroDynOutListParameters.xlsx b/modules/hydrodyn/src/HydroDynOutListParameters.xlsx deleted file mode 100644 index c9c2501e403038abb1c6af586b1b910f72dfbf36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154011 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

ld_t3r#{em1=rvefhW`vVk=g_ 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�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 From c57092b0cdb46c093195194e366dd7d10d8f4372 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 18 Dec 2020 17:25:01 -0700 Subject: [PATCH 341/377] TCF_mods2: update r-test cases hd driver cases still broken --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index cbcb3165b..9487f7b10 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit cbcb3165bfe1a5debd7fc7fd065534f079fd7b98 +Subproject commit 9487f7b10ebdcf04955e3189ffb55f52ac47f588 From 813603774b11710a694f7ef8faf6fbf4f7aa95d2 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 18 Dec 2020 18:09:32 -0700 Subject: [PATCH 342/377] TCF_mods2: update r-test input files: Driver segfaults --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 112 ------------------- reg_tests/r-test | 2 +- 2 files changed, 1 insertion(+), 113 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 03ee8d90f..2a4463c4a 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -962,118 +962,6 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) END IF - !!------------------------------------------------------------------------------------------------- - !! Morison INPUTS section - !!------------------------------------------------------------------------------------------------- - ! - ! ! Header - ! - !CALL ReadCom( UnIn, FileName, 'Morison INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - ! - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read Comment line.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - !END IF - ! - ! - ! - ! ! MorisonInputsMod - ! - !CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsMod, 'MorisonInputsMod', & - ! 'Model for the Morison inputs', ErrStat, ErrMsg, UnEchoLocal ) - ! - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read MorisonInputsMod parameter.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - !END IF - ! - ! - ! ! MorisonInputsFile - ! - !CALL ReadVar ( UnIn, FileName, InitInp%MorisonInputsFile, 'MorisonInputsFile', & - ! 'Filename for the HydroDyn inputs', ErrStat, ErrMsg, UnEchoLocal ) - ! - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read MorisonInputsFile parameter.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - !END IF - ! - ! - !!------------------------------------------------------------------------------------------------- - !! Morison STEADY STATE INPUTS section - !!------------------------------------------------------------------------------------------------- - ! - ! ! Header - ! - !CALL ReadCom( UnIn, FileName, 'Morison STEADY STATE INPUTS header', ErrStat, ErrMsg, UnEchoLocal ) - ! - !IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read Comment line.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - !END IF - ! - ! - ! - ! ! uMorisonInSteady - ! - ! CALL ReadAry ( UnIn, FileName, InitInp%uMorisonInSteady, 6, 'uMorisonInSteady', & - ! 'Morison Steady-state displacements and rotations.', ErrStat, ErrMsg, UnEchoLocal) - ! - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read uMorisonInSteady parameter.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - ! END IF - ! - ! - ! ! uDotMorisonInSteady - ! - ! CALL ReadAry ( UnIn, FileName, InitInp%uDotMorisonInSteady, 6, 'uDotMorisonInSteady', & - ! 'Morison Steady-state translational and rotational velocities.', ErrStat, ErrMsg, UnEchoLocal) - ! - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read uDotMorisonInSteady parameter.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - ! END IF - ! - ! - ! ! uDotDotMorisonInSteady - ! - ! CALL ReadAry ( UnIn, FileName, InitInp%uDotDotMorisonInSteady, 6, 'uDotDotMorisonInSteady', & - ! 'Morison Steady-state translational and rotational accelerations.', ErrStat, ErrMsg, UnEchoLocal) - ! - ! IF ( ErrStat /= ErrID_None ) THEN - ! ErrMsg = ' Failed to read uDotDotMorisonInSteady parameter.' - ! ErrStat = ErrID_Fatal - ! CALL CleanupEchoFile( InitInp%Echo, UnEchoLocal ) - ! CLOSE( UnIn ) - ! RETURN - ! END IF - ! - !IF ( InitInp%MorisonInputsMod /= 1 ) THEN - ! InitInp%uMorisonInSteady = 0.0 - ! InitInp%uDotMorisonInSteady = 0.0 - ! InitInp%uDotDotMorisonInSteady = 0.0 - !END IF - - !------------------------------------------------------------------------------------------------- !> ### Waves elevation series section !------------------------------------------------------------------------------------------------- diff --git a/reg_tests/r-test b/reg_tests/r-test index 9487f7b10..cde96f06a 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 9487f7b10ebdcf04955e3189ffb55f52ac47f588 +Subproject commit cde96f06a8130178cd63c5212b90a537ecf87714 From 9eb4469be310c10e60a07263c9260b6eb8772c0a Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 21 Dec 2020 14:53:05 -0700 Subject: [PATCH 343/377] TCF_Mods: fix segfault in HD driver with existing test cases --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 36 +++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index 2a4463c4a..d413d3b2f 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -198,6 +198,7 @@ PROGRAM HydroDynDriver ! Begin Simulation Setup !------------------------------------------------------------------------------------- +print*,'PRP inputs file' IF ( drvrInitInp%PRPInputsMod == 2 ) THEN @@ -320,6 +321,25 @@ PROGRAM HydroDynDriver CALL HydroDyn_DestroyInitInput( InitInData, ErrStat, ErrMsg ) CALL HydroDyn_DestroyInitOutput( InitOutData, ErrStat, ErrMsg ) + + ! Create Mesh mappings + if ( u(1)%WAMITMesh%Initialized ) then + ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] + CALL MeshMapCreate( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + endif + if ( u(1)%Morison%Mesh%Initialized ) then + ! Create mesh mappings between (0,0,0) reference point mesh and the Morison mesh + CALL MeshMapCreate( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') + if (errStat >= AbortErrLev) then + ! Clean up and exit + call HD_DvrCleanup() + end if + endif + ! Set any steady-state inputs, once before the time-stepping loop @@ -339,14 +359,6 @@ PROGRAM HydroDynDriver IF ( u(1)%WAMITMesh%Initialized ) THEN - ! Create mesh mappings between (0,0,0) reference point mesh and the WAMIT body(ies) mesh [ 1 node per body ] - - CALL MeshMapCreate( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') - if (errStat >= AbortErrLev) then - ! Clean up and exit - call HD_DvrCleanup() - end if - ! Map PRP kinematics to the WAMIT mesh with 1 to NBody nodes CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%WAMITMesh, HD_Ref_2_WB_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then @@ -358,14 +370,6 @@ PROGRAM HydroDynDriver if ( u(1)%Morison%Mesh%Initialized ) then - ! Create mesh mappings between (0,0,0) reference point mesh and the Morison mesh - - CALL MeshMapCreate( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') - if (errStat >= AbortErrLev) then - ! Clean up and exit - call HD_DvrCleanup() - end if - ! Map PRP kinematics to the Morison mesh CALL Transfer_Point_to_Point( u(1)%PRPMesh, u(1)%Morison%Mesh, HD_Ref_2_M_P, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'HydroDynDriver') if (errStat >= AbortErrLev) then From bf0161a82e1cb0e753c8eba7e7ca11b59e3c6fbb Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 22 Dec 2020 11:40:16 -0700 Subject: [PATCH 344/377] TCF_mods: update r-test pointer with hd driver case updates --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index cde96f06a..c3f583792 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit cde96f06a8130178cd63c5212b90a537ecf87714 +Subproject commit c3f5837920bbe491f3dc69713aff972d5bf8ad79 From 54aa449111b4ff29521688836acd4245131dcde9 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 23 Dec 2020 14:17:30 -0700 Subject: [PATCH 345/377] TCF_mods2: bugfix in WAMIT.f90 Complex variables were cast into reals, so the phase information was lost. Corrected the intermediate variables in the calculation --- modules/hydrodyn/src/WAMIT.f90 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/hydrodyn/src/WAMIT.f90 b/modules/hydrodyn/src/WAMIT.f90 index 1a01c51b6..7097067ab 100644 --- a/modules/hydrodyn/src/WAMIT.f90 +++ b/modules/hydrodyn/src/WAMIT.f90 @@ -195,7 +195,7 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init ! Error handling CHARACTER(ErrMsgLen) :: ErrMsg2 ! Temporary error message for calls INTEGER(IntKi) :: ErrStat2 ! Temporary error status for calls - real(SiKi) :: tmp1, tmp2, tmp4, tmp5 ! Temporary transformation terms + COMPLEX(SiKi) :: Ctmp1, Ctmp2, Ctmp4, Ctmp5 ! Temporary COMPLEX transformation terms ! Initialize data @@ -1046,16 +1046,15 @@ SUBROUTINE WAMIT_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init do J = 1, NInpWvDir do I = 1, NInpFreq - tmp1 = ( HdroExctn(I,J,1)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn(I,J,2)*sin(InitInp%PtfmRefztRot(1)) ) - tmp2 = ( HdroExctn(I,J,1)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn(I,J,2)*cos(InitInp%PtfmRefztRot(1)) ) - tmp4 = ( HdroExctn(I,J,4)*cos(InitInp%PtfmRefztRot(1)) - HdroExctn(I,J,5)*sin(InitInp%PtfmRefztRot(1)) ) - tmp5 = ( HdroExctn(I,J,4)*sin(InitInp%PtfmRefztRot(1)) + HdroExctn(I,J,5)*cos(InitInp%PtfmRefztRot(1)) ) - - HdroExctn(I,J,1) = tmp1 - HdroExctn(I,J,2) = tmp2 - HdroExctn(I,J,4) = tmp4 - HdroExctn(I,J,5) = tmp5 + Ctmp1 = ( HdroExctn(I,J,1)*cos(InitInp%PtfmRefztRot(1)) ) - ( HdroExctn(I,J,2)*sin(InitInp%PtfmRefztRot(1)) ) + Ctmp2 = ( HdroExctn(I,J,1)*sin(InitInp%PtfmRefztRot(1)) ) + ( HdroExctn(I,J,2)*cos(InitInp%PtfmRefztRot(1)) ) + Ctmp4 = ( HdroExctn(I,J,4)*cos(InitInp%PtfmRefztRot(1)) ) - ( HdroExctn(I,J,5)*sin(InitInp%PtfmRefztRot(1)) ) + Ctmp5 = ( HdroExctn(I,J,4)*sin(InitInp%PtfmRefztRot(1)) ) + ( HdroExctn(I,J,5)*cos(InitInp%PtfmRefztRot(1)) ) + HdroExctn(I,J,1) = Ctmp1 + HdroExctn(I,J,2) = Ctmp2 + HdroExctn(I,J,4) = Ctmp4 + HdroExctn(I,J,5) = Ctmp5 end do end do From e73184af54901288d667ed1d99705f2fe9a65553 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 23 Dec 2020 15:01:52 -0700 Subject: [PATCH 346/377] TCF-mods2: remove file removed in PR 610 Not sure how the .travis.yml file is still in this branch --- .travis.yml | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e1d5c8b70..000000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Travis CI configuration - -language: c - -os: linux -dist: bionic -env: FC=/usr/bin/gfortran-8 ; CXX=/usr/bin/g++-8 ; CC=/usr/bin/gcc-8 -packages: g++-8 -sudo: true - -before_install: - # linux configuration - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install gfortran libblas-dev liblapack-dev; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CPP_API" == "ON" ]]; then sudo apt-get install libopenmpi-dev libyaml-cpp-dev libhdf5-dev libxml2-dev; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pyenv shell 3.7.1; fi - - apt-cache policy libblas-dev - - apt-cache policy liblapack-dev - - ls -la /usr/lib/x86_64-linux-gnu/liblapa* - - ldd /usr/lib/x86_64-linux-gnu/liblapack.so - - # common configuration - - pip install numpy - -install: - - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DDOUBLE_PRECISION=OFF - - make -j4 - - cd .. - - git clone https://github.com/ebranlard/weio - - python --version - - pip install -r weio/requirements.txt - - pip install -e weio - - git clone https://github.com/ebranlard/tcf-test - - cp build/glue-codes/openfast/openfast tcf-test - - cd tcf-test - -script: - - ls - - make From 6699b6b9a798df1e587bc95d1b612e9621b72e9e Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 28 Dec 2020 17:57:08 -0700 Subject: [PATCH 347/377] FlexSub: preparing to rotate MBm and MmB --- modules/subdyn/src/SubDyn.f90 | 76 +++++++--- modules/subdyn/src/SubDyn_Registry.txt | 3 +- modules/subdyn/src/SubDyn_Types.f90 | 194 ++++++++----------------- 3 files changed, 119 insertions(+), 154 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index f5fef5569..5bfdbd60c 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -438,7 +438,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) real(ReKi), dimension(3) :: aP ! Rigid-body acceleration of node real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates - real(R8Ki), dimension(3,3) :: Rb2g ! + real(R8Ki), dimension(3,3) :: Rb2g ! Rotation matrix body 2 global coordinates + real(R8Ki), dimension(6,6) :: RRb2g ! Rotation matrix global 2 body coordinates, acts on a 6-vector INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None ! Initialize ErrStat @@ -453,6 +454,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + RRb2g(:,:) = 0.0_ReKi + RRb2g(1:3,1:3) = Rb2g + RRb2g(4:6,4:6) = Rb2g ! -------------------------------------------------------------------------------- ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) @@ -580,6 +584,8 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Special case for floating with extramoment if (p%ExtraMoment.and.p%Floating) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses rotated loads + ! + !Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New endif ! Compute external force on internal (F_L) and interface nodes (F_I) @@ -587,9 +593,21 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP - Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) ) + !Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) + Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) + if (p%nDOFM>0) then + Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) + endif + !if (p%Floating) then + !Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) !>>> New + !else + ! ! + !endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) + if (p%Floating) then + !Y1_CB = matmul(RRb2g, Y1_CB) !>>> New + endif else Y1_CB = 0.0_ReKi endif @@ -602,10 +620,10 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! KEEP ME !if ( p%nDOFM > 0) then ! Y1 = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot) & - ! + matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! + matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB - p%MBmmB, m%udotdot_TP) & ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) !else ! No retained modes, so there are no states - ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%D1_12, m%udot_TP) + matmul(p%D1_13, m%udotdot_TP) & + ! Y1 = -( matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB - p%MBmmB, m%udotdot_TP) & ! + matmul(p%D1_141, m%F_L) + matmul(p%D1_142, m%F_L) - matmul( F_I, p%TI ) ) !end if @@ -642,6 +660,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Destroy dxdt because it is not necessary for the rest of the subroutine CALL SD_DestroyContState( dxdt, ErrStat2, ErrMsg2); if(Failed()) return END IF + ! 6-vectors (making sure they are up to date for outputs + m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) + m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) ! Write the previous output data into the output file IF ( ( p%OutSwtch == 1 .OR. p%OutSwtch == 3 ) .AND. ( t > m%LastOutTime ) ) THEN @@ -694,6 +715,7 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta TYPE(SD_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at t INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(ReKi) :: udotdot_TP(6) INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ! Initialize ErrStat @@ -704,19 +726,22 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta CALL AllocAry(dxdt%qm, p%nDOFM, 'dxdt%qm', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) CALL AllocAry(dxdt%qmdot, p%nDOFM, 'dxdt%qmdot', ErrStat2, ErrMsg2 ); CALL SetErrStat ( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcContStateDeriv' ) IF ( ErrStat >= AbortErrLev ) RETURN - IF ( p%nDOFM == 0 ) RETURN - - ! 6-vectors - m%udot_TP = (/u%TPMesh%TranslationVel( :,1),u%TPMesh%RotationVel(:,1)/) ! TODO TODO TODO missing - m%udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) + ! Compute F_L, force on internal DOF CALL GetExtForceOnInternalDOF( u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + + udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) + if (p%Floating) then + ! >>> New udotdot_TP to body coordinates + !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + endif ! State equation dxdt%qm= x%qmdot ! NOTE: matmul( TRANSPOSE(p%PhiM), m%F_L ) = matmul( m%F_L, p%PhiM ) because F_L is 1-D - dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB,m%udotdot_TP) + matmul(m%F_L, p%PhiM) + dxdt%qmdot = -p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB,udotdot_TP) + matmul(m%F_L, p%PhiM) END SUBROUTINE SD_CalcContStateDeriv @@ -1713,6 +1738,11 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) F_L2 = 0.5_ReKi * ( F_L2 + m%F_L ) + if (p%Floating) then + ! >>> New udotdot_TP to body coordinates + !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + endif ! set xq = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) xq( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array @@ -2443,12 +2473,8 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ENDDO ! D1 Matrices - ! D1_12 = CBBt - MBmt*CmBt - p%D1_12 = p%CBB - ! D1_13 = MBBt - MBmt*MmBt - !p%D1_13 = p%MBB - MATMUL( p%MBM, p%MMB ) - CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%D1_13, ErrStat2, ErrMsg2 ); if(Failed()) return ! p%D1_13 = MATMUL( p%MBM, p%MMB ) - p%D1_13 = p%MBB - p%D1_13 + ! MBmt*MmBt + CALL LAPACK_GEMM( 'N', 'T', 1.0_ReKi, p%MBM, p%MBM, 0.0_ReKi, p%MBmmB, ErrStat2, ErrMsg2 ); if(Failed()) return ! MATMUL( p%MBM, p%MMB ) ! --- Intermediates D1_14 = D1_141 + D1_142 !p%D1_141 = MATMUL(p%MBM, TRANSPOSE(p%PhiM)) @@ -2507,8 +2533,6 @@ SUBROUTINE SetParameters(Init, p, MBBb, MBmb, KBBb, PhiRb, nM_out, OmegaL, PhiL, ! OmegaM, JDampings, PhiM, MBM, MMB, x don't exist in this case ! p%D2_64 are zero in this case so we simplify the equations in the code, omitting these variables ! p%D2_63 = p%PhiRb_TI in this case so we simplify the equations in the code, omitting storage of this variable - p%D1_12 = p%CBB ! No cross couplings - p%D1_13 = p%MBB ! No cross couplings p%D1_141 = 0.0_ReKi p%D1_142 = - MATMUL(TI_transpose, TRANSPOSE(PhiRb)) END IF @@ -2554,8 +2578,7 @@ SUBROUTINE AllocParameters(p, nDOFM, ErrStat, ErrMsg) CALL AllocAry( p%PhiM, p%nDOF__L, nDOFM, 'p%PhiM', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_61, p%nDOF__L, nDOFM, 'p%C2_61', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') CALL AllocAry( p%C2_62, p%nDOF__L, nDOFM, 'p%C2_62', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') - CALL AllocAry( p%D1_12, nDOFL_TP, nDOFL_TP , 'p%D1_12', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 - CALL AllocAry( p%D1_13, nDOFL_TP, nDOFL_TP , 'p%D1_13', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 + CALL AllocAry( p%MBmmB, nDOFL_TP, nDOFL_TP , 'p%MBmmB', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%MBB when p%nDOFM == 0 CALL AllocAry( p%D2_63, p%nDOF__L, nDOFL_TP, 'p%D2_63', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is p%PhiRb_TI when p%nDOFM == 0 CALL AllocAry( p%D2_64, p%nDOF__L, p%nDOF__L,'p%D2_64', ErrStat2, ErrMsg2 ); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'AllocParameters') ! is zero when p%nDOFM == 0 end if @@ -3482,6 +3505,11 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) if (nCB>0) then CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 + ! TODO rotate + if (p%Floating) then + !CC(1:3,:) = matmul(Rb2g, CC(1:3,:) !>>> New + !CC(4:6,:) = matmul(Rb2g, CC(1:3,:) !>>> New + endif endif endif @@ -3491,8 +3519,12 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) if(allocated(DD)) deallocate(DD) call AllocAry(DD, nY, nU, 'DD', ErrStat2, ErrMsg2 ); if(Failed()) return; DD(:,:) = 0.0_ReKi DD(1:nY,1:6 ) = - p%KBB - DD(1:nY,7:12 ) = - p%D1_12 - DD(1:nY,13:18 ) = - p%D1_13 + DD(1:nY,7:12 ) = - p%CBB + DD(1:nY,13:18 ) = - p%MBB + if (p%nDOFM>0) then + DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB + ! TODO TODO rotate it A MBmmB A^t + endif endif call CleanUp() diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index d2b1dab80..49c3a201d 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -191,10 +191,9 @@ typedef ^ ParameterType Logical Floating - - - "True if floating botto typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" typedef ^ ParameterType ReKi MMB {:}{:} - - "Matrix after C-B reduction (transpose of MBM" +typedef ^ ParameterType ReKi MBmmB {:}{:} - - "MBm * MmB, used for Y1" typedef ^ ParameterType ReKi C1_11 {:}{:} - - "Coefficient of x in Y1" typedef ^ ParameterType ReKi C1_12 {:}{:} - - "Coefficient of x in Y1" -typedef ^ ParameterType ReKi D1_12 {:}{:} - - "Coefficient of uTPdot in Y1" -typedef ^ ParameterType ReKi D1_13 {:}{:} - - "Coefficient of uTPdotdot in Y1" typedef ^ ParameterType ReKi D1_141 {:}{:} - - "MBm PhiM^T" typedef ^ ParameterType ReKi D1_142 {:}{:} - - "TI^T PhiR^T" typedef ^ ParameterType ReKi PhiM {:}{:} - - "Coefficient of x in Y2" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 958493c71..a7162c816 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -238,10 +238,9 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MMB !< Matrix after C-B reduction (transpose of MBM [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MBmmB !< MBm * MmB, used for Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_11 !< Coefficient of x in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: C1_12 !< Coefficient of x in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_12 !< Coefficient of uTPdot in Y1 [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_13 !< Coefficient of uTPdotdot in Y1 [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_141 !< MBm PhiM^T [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: D1_142 !< TI^T PhiR^T [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PhiM !< Coefficient of x in Y2 [-] @@ -7128,6 +7127,20 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%MMB = SrcParamData%MMB ENDIF +IF (ALLOCATED(SrcParamData%MBmmB)) THEN + i1_l = LBOUND(SrcParamData%MBmmB,1) + i1_u = UBOUND(SrcParamData%MBmmB,1) + i2_l = LBOUND(SrcParamData%MBmmB,2) + i2_u = UBOUND(SrcParamData%MBmmB,2) + IF (.NOT. ALLOCATED(DstParamData%MBmmB)) THEN + ALLOCATE(DstParamData%MBmmB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MBmmB.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%MBmmB = SrcParamData%MBmmB +ENDIF IF (ALLOCATED(SrcParamData%C1_11)) THEN i1_l = LBOUND(SrcParamData%C1_11,1) i1_u = UBOUND(SrcParamData%C1_11,1) @@ -7156,34 +7169,6 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) END IF DstParamData%C1_12 = SrcParamData%C1_12 ENDIF -IF (ALLOCATED(SrcParamData%D1_12)) THEN - i1_l = LBOUND(SrcParamData%D1_12,1) - i1_u = UBOUND(SrcParamData%D1_12,1) - i2_l = LBOUND(SrcParamData%D1_12,2) - i2_u = UBOUND(SrcParamData%D1_12,2) - IF (.NOT. ALLOCATED(DstParamData%D1_12)) THEN - ALLOCATE(DstParamData%D1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_12.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D1_12 = SrcParamData%D1_12 -ENDIF -IF (ALLOCATED(SrcParamData%D1_13)) THEN - i1_l = LBOUND(SrcParamData%D1_13,1) - i1_u = UBOUND(SrcParamData%D1_13,1) - i2_l = LBOUND(SrcParamData%D1_13,2) - i2_u = UBOUND(SrcParamData%D1_13,2) - IF (.NOT. ALLOCATED(DstParamData%D1_13)) THEN - ALLOCATE(DstParamData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%D1_13.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%D1_13 = SrcParamData%D1_13 -ENDIF IF (ALLOCATED(SrcParamData%D1_141)) THEN i1_l = LBOUND(SrcParamData%D1_141,1) i1_u = UBOUND(SrcParamData%D1_141,1) @@ -7832,18 +7817,15 @@ SUBROUTINE SD_DestroyParam( ParamData, ErrStat, ErrMsg ) IF (ALLOCATED(ParamData%MMB)) THEN DEALLOCATE(ParamData%MMB) ENDIF +IF (ALLOCATED(ParamData%MBmmB)) THEN + DEALLOCATE(ParamData%MBmmB) +ENDIF IF (ALLOCATED(ParamData%C1_11)) THEN DEALLOCATE(ParamData%C1_11) ENDIF IF (ALLOCATED(ParamData%C1_12)) THEN DEALLOCATE(ParamData%C1_12) ENDIF -IF (ALLOCATED(ParamData%D1_12)) THEN - DEALLOCATE(ParamData%D1_12) -ENDIF -IF (ALLOCATED(ParamData%D1_13)) THEN - DEALLOCATE(ParamData%D1_13) -ENDIF IF (ALLOCATED(ParamData%D1_141)) THEN DEALLOCATE(ParamData%D1_141) ENDIF @@ -8151,6 +8133,11 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! MMB upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%MMB) ! MMB END IF + Int_BufSz = Int_BufSz + 1 ! MBmmB allocated yes/no + IF ( ALLOCATED(InData%MBmmB) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! MBmmB upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%MBmmB) ! MBmmB + END IF Int_BufSz = Int_BufSz + 1 ! C1_11 allocated yes/no IF ( ALLOCATED(InData%C1_11) ) THEN Int_BufSz = Int_BufSz + 2*2 ! C1_11 upper/lower bounds for each dimension @@ -8161,16 +8148,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_BufSz = Int_BufSz + 2*2 ! C1_12 upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%C1_12) ! C1_12 END IF - Int_BufSz = Int_BufSz + 1 ! D1_12 allocated yes/no - IF ( ALLOCATED(InData%D1_12) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_12 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_12) ! D1_12 - END IF - Int_BufSz = Int_BufSz + 1 ! D1_13 allocated yes/no - IF ( ALLOCATED(InData%D1_13) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! D1_13 upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%D1_13) ! D1_13 - END IF Int_BufSz = Int_BufSz + 1 ! D1_141 allocated yes/no IF ( ALLOCATED(InData%D1_141) ) THEN Int_BufSz = Int_BufSz + 2*2 ! D1_141 upper/lower bounds for each dimension @@ -8855,6 +8832,26 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF + IF ( .NOT. ALLOCATED(InData%MBmmB) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBmmB,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBmmB,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%MBmmB,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MBmmB,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%MBmmB,2), UBOUND(InData%MBmmB,2) + DO i1 = LBOUND(InData%MBmmB,1), UBOUND(InData%MBmmB,1) + ReKiBuf(Re_Xferred) = InData%MBmmB(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF IF ( .NOT. ALLOCATED(InData%C1_11) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -8895,46 +8892,6 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END DO END DO END IF - IF ( .NOT. ALLOCATED(InData%D1_12) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_12,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_12,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_12,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_12,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%D1_12,2), UBOUND(InData%D1_12,2) - DO i1 = LBOUND(InData%D1_12,1), UBOUND(InData%D1_12,1) - ReKiBuf(Re_Xferred) = InData%D1_12(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%D1_13) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%D1_13,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%D1_13,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%D1_13,2), UBOUND(InData%D1_13,2) - DO i1 = LBOUND(InData%D1_13,1), UBOUND(InData%D1_13,1) - ReKiBuf(Re_Xferred) = InData%D1_13(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF IF ( .NOT. ALLOCATED(InData%D1_141) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -10297,30 +10254,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C1_11)) DEALLOCATE(OutData%C1_11) - ALLOCATE(OutData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_11.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%C1_11,2), UBOUND(OutData%C1_11,2) - DO i1 = LBOUND(OutData%C1_11,1), UBOUND(OutData%C1_11,1) - OutData%C1_11(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_12 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MBmmB not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -10330,20 +10264,20 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%C1_12)) DEALLOCATE(OutData%C1_12) - ALLOCATE(OutData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%MBmmB)) DEALLOCATE(OutData%MBmmB) + ALLOCATE(OutData%MBmmB(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_12.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MBmmB.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%C1_12,2), UBOUND(OutData%C1_12,2) - DO i1 = LBOUND(OutData%C1_12,1), UBOUND(OutData%C1_12,1) - OutData%C1_12(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%MBmmB,2), UBOUND(OutData%MBmmB,2) + DO i1 = LBOUND(OutData%MBmmB,1), UBOUND(OutData%MBmmB,1) + OutData%MBmmB(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_12 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_11 not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -10353,20 +10287,20 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_12)) DEALLOCATE(OutData%D1_12) - ALLOCATE(OutData%D1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%C1_11)) DEALLOCATE(OutData%C1_11) + ALLOCATE(OutData%C1_11(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_12.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_11.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D1_12,2), UBOUND(OutData%D1_12,2) - DO i1 = LBOUND(OutData%D1_12,1), UBOUND(OutData%D1_12,1) - OutData%D1_12(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%C1_11,2), UBOUND(OutData%C1_11,2) + DO i1 = LBOUND(OutData%C1_11,1), UBOUND(OutData%C1_11,1) + OutData%C1_11(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! D1_13 not allocated + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! C1_12 not allocated Int_Xferred = Int_Xferred + 1 ELSE Int_Xferred = Int_Xferred + 1 @@ -10376,15 +10310,15 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%D1_13)) DEALLOCATE(OutData%D1_13) - ALLOCATE(OutData%D1_13(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ALLOCATED(OutData%C1_12)) DEALLOCATE(OutData%C1_12) + ALLOCATE(OutData%C1_12(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%D1_13.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%C1_12.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%D1_13,2), UBOUND(OutData%D1_13,2) - DO i1 = LBOUND(OutData%D1_13,1), UBOUND(OutData%D1_13,1) - OutData%D1_13(i1,i2) = ReKiBuf(Re_Xferred) + DO i2 = LBOUND(OutData%C1_12,2), UBOUND(OutData%C1_12,2) + DO i1 = LBOUND(OutData%C1_12,1), UBOUND(OutData%C1_12,1) + OutData%C1_12(i1,i2) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO END DO From e5d4f8215caa05e239705dd29f3e4d7d5273b4f9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 28 Dec 2020 18:55:36 -0700 Subject: [PATCH 348/377] FlexSub: rotating MBm and MmB --- modules/subdyn/src/SubDyn.f90 | 80 ++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 5bfdbd60c..5a5e59c35 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -422,6 +422,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: Y1_Guy_R(6) REAL(ReKi) :: Y1_Guy_L(6) REAL(ReKi) :: Y1_Utp(6) + REAL(ReKi) :: udotdot_TP(6) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement INTEGER(IntKi), pointer :: DOFList(:) INTEGER(IntKi) :: startDOF @@ -471,10 +472,15 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then + if (p%Floating) then + udotdot_TP = matmul(transpose(RRb2g), (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/)) + else + udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + endif m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & - + matmul( p%D2_63, m%udotdot_TP ) + matmul( p%D2_64, m%F_L ) + + matmul( p%D2_63, udotdot_TP ) + matmul( p%D2_64, m%F_L ) end if ! Static improvement (modify UL) if (p%SttcSolve/=idSIM_None) then @@ -549,6 +555,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + !m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) + !m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) + !m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) + !m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) + !m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) + !m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles call SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) @@ -584,8 +596,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Special case for floating with extramoment if (p%ExtraMoment.and.p%Floating) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses rotated loads - ! - !Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New endif ! Compute external force on internal (F_L) and interface nodes (F_I) @@ -593,20 +603,18 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP - !Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) if (p%nDOFM>0) then - Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) + if (p%Floating) then + Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) !>>> New + else + Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) + endif endif - !if (p%Floating) then - !Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) !>>> New - !else - ! ! - !endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) if (p%Floating) then - !Y1_CB = matmul(RRb2g, Y1_CB) !>>> New + Y1_CB = matmul(RRb2g, Y1_CB) !>>> New endif else Y1_CB = 0.0_ReKi @@ -616,6 +624,10 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) if (.not.(p%ExtraMoment.and.p%Floating)) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif + if (p%Floating) then + Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New + endif + Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R ! KEEP ME !if ( p%nDOFM > 0) then @@ -734,8 +746,8 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) endif ! State equation @@ -1727,25 +1739,30 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg !Start by getting u_n and u_n+1 ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) CALL GetExtForceOnInternalDOF(u_interp, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + if (p%Floating) then + ! >>> New udotdot_TP to body coordinates + m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) + m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) + endif ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) CALL GetExtForceOnInternalDOF(u_interp, p, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) + if (p%Floating) then + ! >>> New udotdot_TP to body coordinates + udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) + udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) + endif ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) F_L2 = 0.5_ReKi * ( F_L2 + m%F_L ) - if (p%Floating) then - ! >>> New udotdot_TP to body coordinates - !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) - endif ! set xq = dt * ( A*x_n + B *(u_n + u_n+1)/2 + Fx) - xq( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array + xq( 1: p%nDOFM)=p%SDDeltaT * x%qmdot !upper portion of array xq(1+p%nDOFM:2*p%nDOFM)=p%SDDeltaT * (-p%KMMDiag*x%qm - p%CMMDiag*x%qmdot - matmul(p%MMB, udotdot_TP2) + matmul(F_L2,p%PhiM )) !lower portion of array ! note: matmul(F_L2,p%PhiM ) = matmul(p%PhiM_T,F_L2) because F_L2 is 1-D @@ -3416,7 +3433,7 @@ SUBROUTINE CleanUp() END SUBROUTINE CleanUp END SUBROUTINE OutSummary -SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) +SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) type(SD_ParameterType), intent(in) :: p !< Parameters integer(IntKi), intent(out) :: ErrStat !< Error status of the operation character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -3424,6 +3441,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) real(R8Ki), dimension(:,:), allocatable, optional :: BB !< real(R8Ki), dimension(:,:), allocatable, optional :: CC !< real(R8Ki), dimension(:,:), allocatable, optional :: DD !< + type(SD_InputType), intent(in), optional :: u !< Inputs integer(IntKi) :: nU, nX, nY, nCB, i, j, iNode, iOff, k, nMembers, iField real(R8Ki), dimension(:), allocatable :: dFext_dFmeshk real(R8Ki), dimension(:), allocatable :: dFred_dFmeshk @@ -3460,7 +3478,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) call AllocAry(BB, nX, nU, 'BB', ErrStat2, ErrMsg2 ); if(Failed()) return; BB(:,:) = 0.0_ReKi if(nCB>0) then BB(nCB+1:nX, 1 :6 ) = 0.0_ReKi - BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) + BB(nCB+1:nX, 13:18 ) = -p%MMB(1:nCB,1:6) ! TODO rotate call AllocAry(dFext_dFmeshk, p%nDOF , 'dFext', ErrStat2, ErrMsg2 ); if(Failed()) return call AllocAry(dFred_dFmeshk, p%nDOF_red , 'dFred', ErrStat2, ErrMsg2 ); if(Failed()) return call AllocAry(dFL_dFmeshk , p%nDOF__L , 'dFl' , ErrStat2, ErrMsg2 ); if(Failed()) return @@ -3505,10 +3523,9 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) if (nCB>0) then CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 - ! TODO rotate - if (p%Floating) then - !CC(1:3,:) = matmul(Rb2g, CC(1:3,:) !>>> New - !CC(4:6,:) = matmul(Rb2g, CC(1:3,:) !>>> New + if (p%Floating .and. present(u)) then + CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) !>>> New + CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) !>>> New endif endif endif @@ -3522,8 +3539,13 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD) DD(1:nY,7:12 ) = - p%CBB DD(1:nY,13:18 ) = - p%MBB if (p%nDOFM>0) then - DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB - ! TODO TODO rotate it A MBmmB A^t + if (p%Floating .and. present(u)) then + ! TODO TODO rotate it A MBmmB A^t + !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) !>>> New + DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB + else + DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB + endif endif endif From 5b2bfbe9e1f82ab18008e4fb289468a4e8410cc8 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 29 Dec 2020 14:03:02 -0700 Subject: [PATCH 349/377] FlexSub: rolling back some rotations --- modules/subdyn/src/SubDyn.f90 | 258 +++++++++++++++++++++------------- 1 file changed, 163 insertions(+), 95 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 5a5e59c35..08eca252f 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -412,7 +412,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None !locals INTEGER(IntKi) :: I ! Counters - INTEGER(IntKi) :: iSDNode, iY2Node + INTEGER(IntKi) :: iSDNode REAL(ReKi) :: AllOuts(0:MaxOutPts+p%OutAllInt*p%OutAllDims) REAL(ReKi) :: rotations(3) REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method @@ -422,10 +422,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: Y1_Guy_R(6) REAL(ReKi) :: Y1_Guy_L(6) REAL(ReKi) :: Y1_Utp(6) - REAL(ReKi) :: udotdot_TP(6) REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement + REAL(ReKi) :: udotdot_TP(6) INTEGER(IntKi), pointer :: DOFList(:) - INTEGER(IntKi) :: startDOF REAL(ReKi) :: DCM(3,3) REAL(ReKi) :: F_I(6*p%nNodes_I) ! !Forces from all interface nodes listed in one big array ( those translated to TP ref point HydroTP(6) are implicitly calculated in the equations) TYPE(SD_ContinuousStateType) :: dxdt ! Continuous state derivatives at t- for output file qmdotdot purposes only @@ -437,7 +436,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation real(ReKi), dimension(3) :: vP ! Rigid-body velocity of node real(ReKi), dimension(3) :: aP ! Rigid-body acceleration of node - real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates real(R8Ki), dimension(3,3) :: Rb2g ! Rotation matrix body 2 global coordinates real(R8Ki), dimension(6,6) :: RRb2g ! Rotation matrix global 2 body coordinates, acts on a 6-vector @@ -463,7 +461,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- ! External force on internal nodes (F_L) - call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -472,14 +470,15 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then - if (p%Floating) then - udotdot_TP = matmul(transpose(RRb2g), (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/)) - else + !if (p%Floating) then ! >>> New + ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + !else udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - endif + !endif m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) - m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & + m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & + matmul( p%D2_63, udotdot_TP ) + matmul( p%D2_64, m%F_L ) end if ! Static improvement (modify UL) @@ -536,57 +535,66 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) if (p%Floating) then ! For floating, we compute the Guyan motion directly (rigid body motion with TP as origin) ! This introduce non-linear "rotations" effects, where the bottom node should "go up", and not just translate horizontally - Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) ! body 2 global Om(1:3) = u%TPMesh%RotationVel(1:3,1) OmD(1:3) = u%TPMesh%RotationAcc(1:3,1) do iSDNode = 1,p%nNodes - iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! --- Guyan (rigid body) motion in global coordinates rIP0(1:3) = p%DP0(1:3, iSDNode) - rIP(1:3) = matmul(Rot, rIP0) + rIP(1:3) = matmul(Rb2g, rIP0) duP(1:3) = rIP - rIP0 + m%u_TP(1:3) Om_X_r(1:3) = cross_product(Om, rIP) vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) - m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) - m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) - m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) - m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) - m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) - m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) - !m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) - !m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) - !m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) - !m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) - !m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) - !m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + + !m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) + !m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) + !m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) + !m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) + !m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + !m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + + ! >>> New + m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) + m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + + + !m%U_full (DOFList(1:3)) = duP(1:3) + !m%U_full (DOFList(4:6)) = rotations(1:3) + !m%U_full_dot (DOFList(1:3)) = vP(1:3) + !m%U_full_dot (DOFList(4:6)) = Om(1:3) + !m%U_full_dotdot(DOFList(1:3)) = aP(1:3) + !m%U_full_dotdot(DOFList(4:6)) = OmD(1:3) + ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles call SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - y%Y2mesh%Orientation (:,:,iY2Node) = DCM - y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) - y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) - y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) - y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) - y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + y%Y2mesh%Orientation (:,:,iSDNode) = DCM + y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iSDNode) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iSDNode) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(4:6)) enddo else ! --- Fixed bottom do iSDNode = 1,p%nNodes - iY2Node = iSDNode DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations ! TODO TODO which orientation to give for joints with more than 6 dofs? ! Construct the direction cosine matrix given the output angles CALL SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') - y%Y2mesh%Orientation (:,:,iY2Node) = DCM - y%Y2mesh%TranslationDisp (:,iY2Node) = m%U_full (DOFList(1:3)) - y%Y2mesh%TranslationVel (:,iY2Node) = m%U_full_dot (DOFList(1:3)) - y%Y2mesh%TranslationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(1:3)) - y%Y2mesh%RotationVel (:,iY2Node) = m%U_full_dot (DOFList(4:6)) - y%Y2mesh%RotationAcc (:,iY2Node) = m%U_full_dotdot (DOFList(4:6)) + y%Y2mesh%Orientation (:,:,iSDNode) = DCM + y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3)) + y%Y2mesh%TranslationVel (:,iSDNode) = m%U_full_dot (DOFList(1:3)) + y%Y2mesh%TranslationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(1:3)) + y%Y2mesh%RotationVel (:,iSDNode) = m%U_full_dot (DOFList(4:6)) + y%Y2mesh%RotationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(4:6)) enddo endif @@ -599,33 +607,34 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP - Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) + Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) if (p%nDOFM>0) then - if (p%Floating) then - Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) !>>> New - else + !>>> New + !if (p%Floating) then + ! Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) + !else Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) - endif + !endif endif if ( p%nDOFM > 0) then - Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12,x%qmdot)) - if (p%Floating) then - Y1_CB = matmul(RRb2g, Y1_CB) !>>> New - endif + Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) + !if (p%Floating) then + ! Y1_CB = matmul(RRb2g, Y1_CB) !>>> New + !endif else Y1_CB = 0.0_ReKi endif Y1_Guy_R = matmul( F_I, p%TI ) - Y1_Guy_L = - matmul(p%D1_142, m%F_L) + Y1_Guy_L = - matmul(p%D1_142, m%F_L) ! non rotated loads if (.not.(p%ExtraMoment.and.p%Floating)) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif if (p%Floating) then - Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New + !Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New endif Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R @@ -741,13 +750,13 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta IF ( p%nDOFM == 0 ) RETURN ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF( u, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) endif ! State equation @@ -1739,22 +1748,22 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg !Start by getting u_n and u_n+1 ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - CALL GetExtForceOnInternalDOF(u_interp, p, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u_interp, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) - m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) + !m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) + !m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) endif ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - CALL GetExtForceOnInternalDOF(u_interp, p, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u_interp, p, x, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) - udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) + !udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) + !udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) endif ! calculate (u_n + u_n+1)/2 @@ -2892,22 +2901,105 @@ END SUBROUTINE CleanUp END SUBROUTINE PartitionDOFNodes +!> Compute displacements of all nodes in global system (Guyan + Rotated CB) +!! +SUBROUTINE Displacements(u, p, x, m, U_full, bGuyan, bElastic) + TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t + TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters + TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t + TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + LOGICAL, INTENT(IN ) :: bGuyan !< include Guyan Contribution + LOGICAL, INTENT(IN ) :: bElastic !< include Elastic contribution + REAL(ReKi), DIMENSION(:), INTENT( OUT) :: U_full !< Displacements in full system + !locals + INTEGER(IntKi) :: iSDNode + REAL(ReKi) :: rotations(3) + !REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method + INTEGER(IntKi), pointer :: DOFList(:) + ! Variables for Guayn rigid body motion + real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node + real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) + real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation + real(R8Ki), dimension(3,3) :: Rb2g ! Rotation matrix body 2 global coordinates + INTEGER(IntKi) :: ErrStat2 ! Error status of the operation (occurs after initial error) + CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None + ! --- Convert inputs to FEM DOFs and convenient 6-vector storage + ! Compute the small rotation angles given the input direction cosine matrix + rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + + m%UR_bar = 0.0_ReKi + m%UL = 0.0_ReKi + ! --- CB modes contribution to motion (L-DOF only) + if (bElastic .and. p%nDOFM > 0) then + m%UL = matmul( p%PhiM, x%qm ) + end if + ! Static improvement (modify UL) + ! TODO + !if (p%SttcSolve/=idSIM_None) then + ! ! External force on internal nodes (F_L) + ! call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return + ! FLt = MATMUL(p%PhiL_T , m%F_L) ! NOTE: Gravity in F_L + ! ULS = MATMUL(p%PhiLInvOmgL2, FLt ) + ! if ( p%nDOFM > 0) then + ! UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) + ! ULS = ULS-UL0M + ! end if + ! m%UL = m%UL + ULS + !endif + ! --- Adding Guyan contribution to R and L DOFs + if (bGuyan .and. .not.p%Floating) then + m%UR_bar = matmul( p%TI , m%u_TP ) + m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + else + ! Guyan modes are rigid body modes, we will add them in the "Full system" later + endif + ! --- Build original DOF vectors (DOF before the CB reduction) + m%U_red (p%IDI__) = m%UR_bar + m%U_red (p%ID__L) = m%UL + m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) + m%U_red (p%ID__F) = 0 + if (p%reduced) then + U_full = matmul(p%T_red, m%U_red) + else + U_full = m%U_red + endif + ! --- Adding Guyan contribution for rigid body + if (bGuyan .and. p%Floating) then + ! For floating, we compute the Guyan motion directly (rigid body motion with TP as origin) + ! This introduce non-linear "rotations" effects, where the bottom node should "go up", and not just translate horizontally + Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + do iSDNode = 1,p%nNodes + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! --- Guyan (rigid body) motion in global coordinates + rIP0(1:3) = p%DP0(1:3, iSDNode) + rIP(1:3) = matmul(Rb2g, rIP0) + duP(1:3) = rIP - rIP0 + m%u_TP(1:3) + !U_full(DOFList(1:3)) = U_full(DOFList(1:3)) + duP(1:3) + ! >>> New + U_full(DOFList(1:3)) = matmul(Rb2g, U_full(DOFList(1:3))) + duP(1:3) + U_full(DOFList(4:6)) = matmul(Rb2g, U_full(DOFList(4:6))) + rotations(1:3) + enddo + endif +END SUBROUTINE Displacements + !------------------------------------------------------------------------------------------------------ !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads) +SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters + type(SD_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red logical , intent(in ) :: ExtraMoment ! If true add extra moment logical , intent(in ) :: RotateLoads ! If true, loads are rotated to body coordinate - type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None integer :: iNode ! indices of u-mesh nodes and SD nodes integer :: nMembers - integer :: startDOF, I + integer :: I integer :: iCC, iElem, iChannel !< Index on control cables, element, Channel integer(IntKi), dimension(12) :: IDOF ! 12 DOF indices in global unconstrained system real(ReKi) :: CableTension ! Controllable Cable force @@ -2918,49 +3010,25 @@ SUBROUTINE GetExtForceOnInternalDOF( u, p, m, F_L, ErrStat, ErrMsg, ExtraMoment, real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation - real(R8Ki), dimension(3,3) :: Rot ! Rotation matrix (DCM^t) and delta Rot (DCM^t-I) + real(R8Ki), dimension(3,3) :: Rb2g ! Rotation matrix body 2 global real(R8Ki), dimension(3,3) :: Rg2b ! Rotation matrix global 2 body coordinates ! real(ReKi), parameter :: myNaN = -9999998.989_ReKi - ! --- Rotation matrix from body to global - if (RotateLoads) then - Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates - endif - if (ExtraMoment) then - if (p%Floating) then - ! For fully floating case, we prescribe the Guyan motion as a "rigid" (non-linear) motion - Rot(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) - m%DU_full = 0.0_ReKi + ! Compute node displacements for lever arm + call Displacements(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False.) + if (p%Floating) then ! remove u_TP do iNode = 1,p%nNodes - rIP0(1:3) = p%DP0(1:3, iNode) ! vector interface->node at t=0 - rIP(1:3) = matmul(Rot, rIP0) ! vector interface->node at t - duP(1:3) = rIP - rIP0 ! nodal rigid displacement (without u_TP) - m%DU_full(p%NodesDOF(iNode)%List(1:3)) = duP(1:3) + m%DU_full(p%NodesDOF(iNode)%List(1:3)) =m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) enddo - else - ! --- Compute Guyan displacement for extra moment - rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat, Errmsg); - m%U_red(:) = 0.0_ReKi - u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) - m%UR_bar = matmul( p%TI , u_TP ) ! UR_bar - m%UL = matmul( p%PhiRb_TI, u_TP ) ! UL - m%U_red(p%IDI__) = m%UR_bar - m%U_red(p%ID__L) = m%UL - m%U_red(p%IDC_Rb)= 0 ! TODO - m%U_red(p%ID__F) = 0 - if (p%reduced) then - m%DU_full = matmul(p%T_red, m%U_red) - else - m%DU_full = m%U_red - endif endif endif ! --- Build vector of external forces (including gravity) (Moment done below) m%Fext= myNaN if (RotateLoads) then ! Forces in body coordinates + Rg2b(1:3,1:3) = u%TPMesh%Orientation(:,:,1) ! global 2 body coordinates do iNode = 1,p%nNodes m%Fext( p%NodesDOF(iNode)%List(1:3) ) = matmul(Rg2b, u%LMesh%Force(:,iNode) + p%FG(p%NodesDOF(iNode)%List(1:3))) enddo @@ -3524,8 +3592,8 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 if (p%Floating .and. present(u)) then - CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) !>>> New - CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) !>>> New + CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> New + CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> New endif endif endif @@ -3541,7 +3609,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) if (p%nDOFM>0) then if (p%Floating .and. present(u)) then ! TODO TODO rotate it A MBmmB A^t - !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) !>>> New + !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) ! >>> New DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB else DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB From fc3e6c13bf12f8045763ddd3e11b27c1f6b435b2 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 29 Dec 2020 16:51:40 -0700 Subject: [PATCH 350/377] FlexSub: elastic displ. in lever arm, and all rotated terms except MBmmB --- modules/subdyn/src/SubDyn.f90 | 59 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 08eca252f..41e17fd96 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -470,12 +470,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then - !if (p%Floating) then ! >>> New - ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) - ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) - !else + if (p%Floating) then ! >>> New + udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + else udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - !endif + endif m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & @@ -562,7 +562,6 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) - !m%U_full (DOFList(1:3)) = duP(1:3) !m%U_full (DOFList(4:6)) = rotations(1:3) !m%U_full_dot (DOFList(1:3)) = vP(1:3) @@ -614,17 +613,20 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) if (p%nDOFM>0) then !>>> New + ! NOTE: this introduces some hysteresis !if (p%Floating) then - ! Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, matmul(transpose(RRb2g), m%udotdot_TP))) + ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + ! Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, udotdot_TP)) !else Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) !endif endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) - !if (p%Floating) then - ! Y1_CB = matmul(RRb2g, Y1_CB) !>>> New - !endif + if (p%Floating) then + Y1_CB = matmul(RRb2g, Y1_CB) !>>> New + endif else Y1_CB = 0.0_ReKi endif @@ -634,7 +636,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif if (p%Floating) then - !Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New + Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New endif Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R @@ -755,8 +757,8 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - !udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - !udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) endif ! State equation @@ -1752,8 +1754,8 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - !m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) - !m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) + m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) + m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) endif ! extrapolate u to find u_interp = u(t + dt)=u_n+1 @@ -1762,8 +1764,8 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) if (p%Floating) then ! >>> New udotdot_TP to body coordinates - !udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) - !udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) + udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) + udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) endif ! calculate (u_n + u_n+1)/2 @@ -2903,14 +2905,14 @@ END SUBROUTINE PartitionDOFNodes !> Compute displacements of all nodes in global system (Guyan + Rotated CB) !! -SUBROUTINE Displacements(u, p, x, m, U_full, bGuyan, bElastic) +SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic) TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables LOGICAL, INTENT(IN ) :: bGuyan !< include Guyan Contribution LOGICAL, INTENT(IN ) :: bElastic !< include Elastic contribution - REAL(ReKi), DIMENSION(:), INTENT( OUT) :: U_full !< Displacements in full system + REAL(ReKi), DIMENSION(:), INTENT( OUT) :: DU_full !< LeverArm in full system !locals INTEGER(IntKi) :: iSDNode REAL(ReKi) :: rotations(3) @@ -2960,9 +2962,9 @@ SUBROUTINE Displacements(u, p, x, m, U_full, bGuyan, bElastic) m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) m%U_red (p%ID__F) = 0 if (p%reduced) then - U_full = matmul(p%T_red, m%U_red) + DU_full = matmul(p%T_red, m%U_red) else - U_full = m%U_red + DU_full = m%U_red endif ! --- Adding Guyan contribution for rigid body if (bGuyan .and. p%Floating) then @@ -2974,14 +2976,14 @@ SUBROUTINE Displacements(u, p, x, m, U_full, bGuyan, bElastic) ! --- Guyan (rigid body) motion in global coordinates rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rb2g, rIP0) - duP(1:3) = rIP - rIP0 + m%u_TP(1:3) + duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) !U_full(DOFList(1:3)) = U_full(DOFList(1:3)) + duP(1:3) ! >>> New - U_full(DOFList(1:3)) = matmul(Rb2g, U_full(DOFList(1:3))) + duP(1:3) - U_full(DOFList(4:6)) = matmul(Rb2g, U_full(DOFList(4:6))) + rotations(1:3) + DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) + DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) enddo endif -END SUBROUTINE Displacements +END SUBROUTINE LeverArm !------------------------------------------------------------------------------------------------------ !> Construct force vector on internal DOF (L) from the values on the input mesh @@ -3017,12 +3019,7 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen if (ExtraMoment) then ! Compute node displacements for lever arm - call Displacements(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False.) - if (p%Floating) then ! remove u_TP - do iNode = 1,p%nNodes - m%DU_full(p%NodesDOF(iNode)%List(1:3)) =m%DU_full(p%NodesDOF(iNode)%List(1:3)) - m%u_TP(1:3) - enddo - endif + call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.True.) endif ! --- Build vector of external forces (including gravity) (Moment done below) From e54f37acd00a6dd63e6a600d0df4d463b107c348 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 31 Dec 2020 11:34:11 -0700 Subject: [PATCH 351/377] FlexSub: adding rotation of MBmmB term --- modules/subdyn/src/SubDyn.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 41e17fd96..0eefed4b8 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -614,13 +614,13 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) if (p%nDOFM>0) then !>>> New ! NOTE: this introduces some hysteresis - !if (p%Floating) then - ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) - ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) - ! Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, udotdot_TP)) - !else + if (p%Floating) then + udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, udotdot_TP)) + else Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) - !endif + endif endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) From 4b886d487dac2595687fcaffa0a7861f02b03d02 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 4 Jan 2021 10:54:05 -0700 Subject: [PATCH 352/377] FlexSub: using full displacement vector (with static solve) for lever arm --- modules/subdyn/src/SubDyn.f90 | 120 +++++++++++++++++----------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 0eefed4b8..f8a020979 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -606,7 +606,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False., U_full=m%U_full); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP @@ -2905,7 +2905,7 @@ END SUBROUTINE PartitionDOFNodes !> Compute displacements of all nodes in global system (Guyan + Rotated CB) !! -SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic) +SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) TYPE(SD_InputType), INTENT(IN ) :: u !< Inputs at t TYPE(SD_ParameterType),target,INTENT(IN ) :: p !< Parameters TYPE(SD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t @@ -2913,10 +2913,10 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic) LOGICAL, INTENT(IN ) :: bGuyan !< include Guyan Contribution LOGICAL, INTENT(IN ) :: bElastic !< include Elastic contribution REAL(ReKi), DIMENSION(:), INTENT( OUT) :: DU_full !< LeverArm in full system + REAL(ReKi), DIMENSION(:), OPTIONAL, INTENT(IN ) :: U_full !< Displacements in full system !locals INTEGER(IntKi) :: iSDNode REAL(ReKi) :: rotations(3) - !REAL(ReKi) :: ULS(p%nDOF__L), UL0m(p%nDOF__L), FLt(p%nDOF__L) ! Temporary values in static improvement method INTEGER(IntKi), pointer :: DOFList(:) ! Variables for Guayn rigid body motion real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node @@ -2928,74 +2928,74 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic) ! --- Convert inputs to FEM DOFs and convenient 6-vector storage ! Compute the small rotation angles given the input direction cosine matrix rotations = GetSmllRotAngs(u%TPMesh%Orientation(:,:,1), ErrStat2, Errmsg2); - m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) - - m%UR_bar = 0.0_ReKi - m%UL = 0.0_ReKi - ! --- CB modes contribution to motion (L-DOF only) - if (bElastic .and. p%nDOFM > 0) then - m%UL = matmul( p%PhiM, x%qm ) - end if - ! Static improvement (modify UL) - ! TODO - !if (p%SttcSolve/=idSIM_None) then - ! ! External force on internal nodes (F_L) - ! call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return - ! FLt = MATMUL(p%PhiL_T , m%F_L) ! NOTE: Gravity in F_L - ! ULS = MATMUL(p%PhiLInvOmgL2, FLt ) - ! if ( p%nDOFM > 0) then - ! UL0M = MATMUL(p%PhiLInvOmgL2(:,1:p%nDOFM), FLt(1:p%nDOFM) ) - ! ULS = ULS-UL0M - ! end if - ! m%UL = m%UL + ULS - !endif - ! --- Adding Guyan contribution to R and L DOFs - if (bGuyan .and. .not.p%Floating) then - m%UR_bar = matmul( p%TI , m%u_TP ) - m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) - else - ! Guyan modes are rigid body modes, we will add them in the "Full system" later - endif - ! --- Build original DOF vectors (DOF before the CB reduction) - m%U_red (p%IDI__) = m%UR_bar - m%U_red (p%ID__L) = m%UL - m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) - m%U_red (p%ID__F) = 0 - if (p%reduced) then - DU_full = matmul(p%T_red, m%U_red) + m%u_TP = (/REAL(u%TPMesh%TranslationDisp(:,1),ReKi), rotations/) + + if (present(U_full)) then + ! Then we use it directly, U_full may contain Static improvement + DU_full=U_full + ! We remove u_TP for floating + if (p%Floating) then + do iSDNode = 1,p%nNodes + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) - m%u_TP(1:3) + enddo + endif else - DU_full = m%U_red - endif - ! --- Adding Guyan contribution for rigid body - if (bGuyan .and. p%Floating) then - ! For floating, we compute the Guyan motion directly (rigid body motion with TP as origin) - ! This introduce non-linear "rotations" effects, where the bottom node should "go up", and not just translate horizontally - Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) - do iSDNode = 1,p%nNodes - DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations - ! --- Guyan (rigid body) motion in global coordinates - rIP0(1:3) = p%DP0(1:3, iSDNode) - rIP(1:3) = matmul(Rb2g, rIP0) - duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) - !U_full(DOFList(1:3)) = U_full(DOFList(1:3)) + duP(1:3) - ! >>> New - DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) - DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) - enddo - endif + m%UR_bar = 0.0_ReKi + m%UL = 0.0_ReKi + ! --- CB modes contribution to motion (L-DOF only), NO STATIC IMPROVEMENT + if (bElastic .and. p%nDOFM > 0) then + m%UL = matmul( p%PhiM, x%qm ) + end if + ! --- Adding Guyan contribution to R and L DOFs + if (bGuyan .and. .not.p%Floating) then + m%UR_bar = matmul( p%TI , m%u_TP ) + m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + else + ! Guyan modes are rigid body modes, we will add them in the "Full system" later + endif + ! --- Build original DOF vectors (DOF before the CB reduction) + m%U_red (p%IDI__) = m%UR_bar + m%U_red (p%ID__L) = m%UL + m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) + m%U_red (p%ID__F) = 0 + if (p%reduced) then + DU_full = matmul(p%T_red, m%U_red) + else + DU_full = m%U_red + endif + ! --- Adding Guyan contribution for rigid body + if (bGuyan .and. p%Floating) then + ! For floating, we compute the Guyan motion directly (rigid body motion with TP as origin) + ! This introduce non-linear "rotations" effects, where the bottom node should "go up", and not just translate horizontally + Rb2g(1:3,1:3) = transpose(u%TPMesh%Orientation(:,:,1)) + do iSDNode = 1,p%nNodes + DOFList => p%NodesDOF(iSDNode)%List ! Alias to shorten notations + ! --- Guyan (rigid body) motion in global coordinates + rIP0(1:3) = p%DP0(1:3, iSDNode) + rIP(1:3) = matmul(Rb2g, rIP0) + duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) + !U_full(DOFList(1:3)) = U_full(DOFList(1:3)) + duP(1:3) + ! >>> New + DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) + DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) + enddo + endif + endif ! U_full no provided END SUBROUTINE LeverArm !------------------------------------------------------------------------------------------------------ !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads) +SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads, U_full) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_ContinuousStateType), intent(in ) :: x !< Continuous states at t type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red logical , intent(in ) :: ExtraMoment ! If true add extra moment logical , intent(in ) :: RotateLoads ! If true, loads are rotated to body coordinate + real(Reki), optional, intent(in ) :: U_full(:) ! DOF displacements (Guyan + CB) real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -3018,8 +3018,8 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen real(ReKi), parameter :: myNaN = -9999998.989_ReKi if (ExtraMoment) then - ! Compute node displacements for lever arm - call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.True.) + ! Compute node displacements "DU_full" for lever arm + call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.True., U_full=U_full) endif ! --- Build vector of external forces (including gravity) (Moment done below) From d43ed857e3b500dd6f43bc985def1333ad4dc52b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 5 Jan 2021 06:20:11 -0700 Subject: [PATCH 353/377] TCF_Mods: add the vtk outputs for morrison mesh Not sure why this was missing before. --- modules/openfast-library/src/FAST_Subs.f90 | 36 ++++++++++++---------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index cbec7d903..7b59d0e63 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -5171,18 +5171,20 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, H IF ( p_FAST%CompHydro == Module_HD .and. allocated(HD%Input)) THEN !TODO: Fix for Visualizaton GJH 4/23/20 !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) - !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%LumpedMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonLumped_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) - !call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2 ) - - if (p_FAST%CompSub == Module_NONE) then -!TODO call MeshWrVTK(p_FAST%TurbinePos, HD%y%AllHdroOrigin, trim(p_FAST%VTK_OutFileRoot)//'.HD_AllHdroOrigin', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Mesh ) - outputFields = .false. - else - call MeshWrVTK(p_FAST%TurbinePos, HD%y%WamitMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh ) - outputFields = p_FAST%VTK_fields - end if - call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, outputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh ) - + call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison_Motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth ) + + if (HD%y%WamitMesh%Committed) then +! if (p_FAST%CompSub == Module_NONE) then +!TODO call MeshWrVTK(p_FAST%TurbinePos, HD%y%WamitMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh ) +! outputFields = .false. +! else + call MeshWrVTK(p_FAST%TurbinePos, HD%y%WamitMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Mesh', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh ) +! outputFields = p_FAST%VTK_fields +! end if + endif + if (HD%y%Morison%Mesh%Committed) then + call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh ) + endif END IF ! SubDyn @@ -5331,8 +5333,8 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, OutputFields = p_FAST%VTK_fields end if !TODO: Fix for Visualization GJH 4/23/20 - ! call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonDistrib', & - ! y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=HD%y%Morison%DistribMesh ) + call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', & + y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, Sib=HD%y%Morison%Mesh ) END IF @@ -5443,16 +5445,16 @@ SUBROUTINE WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW ! END IF !TODO: Fix below section for new Morison GJH 4/23/20 ! - !IF ( HD%Input(1)%Morison%DistribMesh%Committed ) THEN + !IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN ! !if ( p_FAST%CompSub == Module_NONE ) then ! floating ! ! OutputFields = .false. ! !else ! ! OutputFields = p_FAST%VTK_fields ! !end if ! - ! call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%DistribMesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', & + ! call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', & ! y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, & - ! p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%DistribMesh ) + ! p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%Mesh ) !END IF From d600d44ecff3a1cf059c37b577b6d81026facc50 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 5 Jan 2021 06:20:39 -0700 Subject: [PATCH 354/377] TCF_mods2: Add outputs to HD for PRP motion This is mostly for diagnostic purposes when troubleshooting an input motion to the driver when WAMIT is not used --- docs/OtherSupporting/OutListParameters.xlsx | Bin 252669 -> 253353 bytes modules/hydrodyn/src/HydroDyn.f90 | 2 +- modules/hydrodyn/src/HydroDyn.txt | 2 +- modules/hydrodyn/src/HydroDyn_Output.f90 | 1517 ++++++++++--------- modules/hydrodyn/src/HydroDyn_Types.f90 | 2 +- 5 files changed, 769 insertions(+), 754 deletions(-) diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx index c0e7f544ef491c655a5ea647f8c33c10e8019785..18d640a05281200a4b41dce0852ac3739b64d07d 100644 GIT binary patch delta 61185 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%0A{b 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 Po1hmwL-Or_zykjQT>QgH delta 60319 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 Date: Tue, 5 Jan 2021 11:16:22 -0700 Subject: [PATCH 355/377] FlexSub: documentation sign for DCM condition was flipped --- docs/source/user/subdyn/theory.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 4bfbd1765..5859d4d33 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -216,7 +216,7 @@ are the start and end joints of the member (or nodes of the element of interest) If :math:`{X_E = X_S}` and :math:`{Z_E = Z_S}`, the :math:`{[ \mathbf{D_c} ]}` matrix can be found as follows: -if :math:`{Z_E < Z_S}` then +if :math:`{Z_E >= Z_S}` then .. math:: :label: Dc_spec1 From 564fc331b1bae86b330b2f104f4a70eb151da9c7 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 5 Jan 2021 11:24:59 -0700 Subject: [PATCH 356/377] FlexSub: Guyan only for displacements and lever arm --- modules/subdyn/src/SubDyn.f90 | 56 ++++++++++++++--------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ab37b9bbf..79be5eed7 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -547,14 +547,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) - !m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) - !m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) - !m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) - !m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) - !m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) - !m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) - - ! >>> New + ! Full displacements CB-rotated + Guyan (KEEP ME) m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) @@ -562,19 +555,14 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) - !m%U_full (DOFList(1:3)) = duP(1:3) - !m%U_full (DOFList(4:6)) = rotations(1:3) - !m%U_full_dot (DOFList(1:3)) = vP(1:3) - !m%U_full_dot (DOFList(4:6)) = Om(1:3) - !m%U_full_dotdot(DOFList(1:3)) = aP(1:3) - !m%U_full_dotdot(DOFList(4:6)) = OmD(1:3) - - ! TODO TODO which orientation to give for joints with more than 6 dofs? + ! NOTE: For now, displacements passed to HydroDyn are Guyan only! ! Construct the direction cosine matrix given the output angles - call SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + !call SmllRotTrans( 'UR_bar input angles', m%U_full(DOFList(4)), m%U_full(DOFList(5)), m%U_full(DOFList(6)), DCM, '', ErrStat2, ErrMsg2) + call SmllRotTrans( 'UR_bar input angles', rotations(1), rotations(2), rotations(3), DCM, '', ErrStat2, ErrMsg2) ! NOTE: using only Guyan rotations call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') y%Y2mesh%Orientation (:,:,iSDNode) = DCM - y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3)) + !y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3) + y%Y2mesh%TranslationDisp (:,iSDNode) = duP(1:3) ! NOTE: using only the Guyan Displacements y%Y2mesh%TranslationVel (:,iSDNode) = m%U_full_dot (DOFList(1:3)) y%Y2mesh%TranslationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(1:3)) y%Y2mesh%RotationVel (:,iSDNode) = m%U_full_dot (DOFList(4:6)) @@ -606,7 +594,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False., U_full=m%U_full); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP @@ -2912,13 +2900,13 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) TYPE(SD_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables LOGICAL, INTENT(IN ) :: bGuyan !< include Guyan Contribution LOGICAL, INTENT(IN ) :: bElastic !< include Elastic contribution - REAL(ReKi), DIMENSION(:), INTENT( OUT) :: DU_full !< LeverArm in full system + REAL(ReKi), DIMENSION(:), INTENT( OUT) :: DU_full !< LeverArm in full system REAL(ReKi), DIMENSION(:), OPTIONAL, INTENT(IN ) :: U_full !< Displacements in full system !locals INTEGER(IntKi) :: iSDNode REAL(ReKi) :: rotations(3) INTEGER(IntKi), pointer :: DOFList(:) - ! Variables for Guayn rigid body motion + ! Variables for Guyan rigid body motion real(ReKi), dimension(3) :: rIP ! Vector from TP to rotated Node real(ReKi), dimension(3) :: rIP0 ! Vector from TP to Node (undeflected) real(ReKi), dimension(3) :: duP ! Displacement of node due to rigid rotation @@ -2941,28 +2929,29 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) enddo endif else - m%UR_bar = 0.0_ReKi - m%UL = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only), NO STATIC IMPROVEMENT if (bElastic .and. p%nDOFM > 0) then m%UL = matmul( p%PhiM, x%qm ) + else + m%UL = 0.0_ReKi end if ! --- Adding Guyan contribution to R and L DOFs if (bGuyan .and. .not.p%Floating) then - m%UR_bar = matmul( p%TI , m%u_TP ) - m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) + m%UR_bar = matmul( p%TI , m%u_TP ) + m%UL = m%UL + matmul( p%PhiRb_TI, m%u_TP ) else ! Guyan modes are rigid body modes, we will add them in the "Full system" later + m%UR_bar = 0.0_ReKi endif ! --- Build original DOF vectors (DOF before the CB reduction) - m%U_red (p%IDI__) = m%UR_bar - m%U_red (p%ID__L) = m%UL - m%U_red (p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) - m%U_red (p%ID__F) = 0 + m%U_red(p%IDI__) = m%UR_bar + m%U_red(p%ID__L) = m%UL + m%U_red(p%IDC_Rb)= 0 ! NOTE: for now we don't have leader DOF at "C" (bottom) + m%U_red(p%ID__F) = 0 if (p%reduced) then - DU_full = matmul(p%T_red, m%U_red) + DU_full = matmul(p%T_red, m%U_red) else - DU_full = m%U_red + DU_full = m%U_red endif ! --- Adding Guyan contribution for rigid body if (bGuyan .and. p%Floating) then @@ -2975,8 +2964,7 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rb2g, rIP0) duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) - !U_full(DOFList(1:3)) = U_full(DOFList(1:3)) + duP(1:3) - ! >>> New + ! Full diplacements Guyan + rotated CB (if asked) DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) enddo @@ -3019,7 +3007,7 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen if (ExtraMoment) then ! Compute node displacements "DU_full" for lever arm - call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.True., U_full=U_full) + call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False.)!, U_full=U_full) endif ! --- Build vector of external forces (including gravity) (Moment done below) From e35aa079c0d77e6f3dcc7b979536d3ea3255474c Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Jan 2021 15:08:34 -0700 Subject: [PATCH 357/377] FlexSub: rolling back rotation of CB, MBmmB is the most problematic term --- modules/subdyn/src/SubDyn.f90 | 80 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 79be5eed7..45969f739 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -470,12 +470,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then - if (p%Floating) then ! >>> New - udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) - udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) - else - udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - endif + !if (p%Floating) then ! >>> Rotate All + ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + !else + udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + !endif m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & @@ -600,21 +600,21 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Compute reaction/coupling force at TP Y1_Utp = - (matmul(p%KBB, m%u_TP) + matmul(p%CBB, m%udot_TP) + matmul(p%MBB, m%udotdot_TP) ) if (p%nDOFM>0) then - !>>> New + !>>> Rotate All ! NOTE: this introduces some hysteresis - if (p%Floating) then - udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) - udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) - Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, udotdot_TP)) - else - Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) - endif + !if (p%Floating) then + ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + ! Y1_Utp = Y1_Utp + matmul(RRb2g, matmul(p%MBmmB, udotdot_TP)) + !else + Y1_Utp = Y1_Utp + matmul(p%MBmmB, m%udotdot_TP) + !endif endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) - if (p%Floating) then - Y1_CB = matmul(RRb2g, Y1_CB) !>>> New - endif + !if (p%Floating) then + ! Y1_CB = matmul(RRb2g, Y1_CB) !>>> Rotate All + !endif else Y1_CB = 0.0_ReKi endif @@ -623,9 +623,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) if (.not.(p%ExtraMoment.and.p%Floating)) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif - if (p%Floating) then - Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> New - endif + !if (p%Floating) then + ! Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> Rotate All + !endif Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R ! KEEP ME @@ -743,11 +743,11 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta CALL GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then - ! >>> New udotdot_TP to body coordinates - udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) - endif + !if (p%Floating) then + ! ! >>> Rotate All - udotdot_TP to body coordinates + ! udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + ! udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + !endif ! State equation dxdt%qm= x%qmdot @@ -1740,21 +1740,21 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') CALL GetExtForceOnInternalDOF(u_interp, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then - ! >>> New udotdot_TP to body coordinates - m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) - m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) - endif + !if (p%Floating) then + ! ! >>> Rotate All - udotdot_TP to body coordinates + ! m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) + ! m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) + !endif ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') CALL GetExtForceOnInternalDOF(u_interp, p, x, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then - ! >>> New udotdot_TP to body coordinates - udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) - udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) - endif + !if (p%Floating) then + ! ! >>> Rotate All - udotdot_TP to body coordinates + ! udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) + ! udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) + !endif ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -3576,10 +3576,10 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) if (nCB>0) then CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 - if (p%Floating .and. present(u)) then - CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> New - CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> New - endif + !if (p%Floating .and. present(u)) then + ! CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> Rotate All + ! CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> Rotate All + !endif endif endif @@ -3594,7 +3594,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) if (p%nDOFM>0) then if (p%Floating .and. present(u)) then ! TODO TODO rotate it A MBmmB A^t - !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) ! >>> New + !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) ! >>> Rotate All DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB else DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB From 26944e8d001819c1ecb576a25cafcda7333baa5e Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 6 Jan 2021 17:10:50 -0700 Subject: [PATCH 358/377] TCF_mods2: BugFix for inertial mass of filled members The filled members and partially filled members were incorrectly calculated. The entire member was considered filled and FillFSLoc value was ignored. For full members, it was not an issue, but was an issue for partially filled ones. This was evident in the OC4Semi case. --- modules/hydrodyn/src/HydroDyn_DriverCode.f90 | 16 +++-- modules/hydrodyn/src/Morison.f90 | 71 +++++++++++++++----- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 index d413d3b2f..59fb89cc4 100644 --- a/modules/hydrodyn/src/HydroDyn_DriverCode.f90 +++ b/modules/hydrodyn/src/HydroDyn_DriverCode.f90 @@ -198,14 +198,16 @@ PROGRAM HydroDynDriver ! Begin Simulation Setup !------------------------------------------------------------------------------------- -print*,'PRP inputs file' IF ( drvrInitInp%PRPInputsMod == 2 ) THEN ! Open the PRP inputs data file CALL GetNewUnit( UnPRPInp ) CALL OpenFInpFile ( UnPRPInp, drvrInitInp%PRPInputsFile, ErrStat, ErrMsg ) - IF (ErrStat >=AbortErrLev) STOP + IF (ErrStat >=AbortErrLev) THEN + call WrScr( ErrMsg ) + STOP + ENDIF ALLOCATE ( PRPin(drvrInitInp%NSteps, 19), STAT = ErrStat ) @@ -237,7 +239,10 @@ PROGRAM HydroDynDriver ! Open the WAMIT inputs data file CALL GetNewUnit( UnPRPInp ) CALL OpenFInpFile ( UnPRPInp, drvrInitInp%PRPInputsFile, ErrStat, ErrMsg ) - IF (ErrStat >=AbortErrLev) STOP + IF (ErrStat >=AbortErrLev) THEN + call WrScr( ErrMsg ) + STOP + ENDIF ALLOCATE ( PRPin(drvrInitInp%NSteps, 7+6*NBODY), STAT = ErrStat ) @@ -647,7 +652,10 @@ SUBROUTINE ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) CALL GetNewUnit( UnIn ) CALL OpenFInpFile ( UnIn, FileName, ErrStat, ErrMsg ) - IF (ErrStat >=AbortErrLev) RETURN + IF (ErrStat >=AbortErrLev) THEN + call WrScr( ErrMsg ) + STOP + ENDIF CALL WrScr( 'Opening HydroDyn Driver input file: '//FileName ) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index d459acce6..f43799631 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -787,12 +787,12 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no WRITE( UnSum, '(//)' ) WRITE( UnSum, '(A14,I4,A44)' ) 'Nodes (first [',numJoints,'] are joints, remainder are internal nodes)' WRITE( UnSum, '(/)' ) - WRITE( UnSum, '(1X,A5,19(2X,A10))' ) ' i ', ' MbrIndx ', ' Nxi ', ' Nyi ', ' Nzi ', ' R ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', ' Cd ', ' Ca ', ' Cp ', ' AxCd ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ' - WRITE( UnSum, '(1X,A5,19(2X,A10))' ) ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' + WRITE( UnSum, '(1X,A5,20(2X,A10))' ) ' i ', ' MbrIndx ', ' Nxi ', ' Nyi ', ' Nzi ', ' R ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', 'FilledMass', ' Cd ', ' Ca ', ' Cp ', ' AxCd ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ' + WRITE( UnSum, '(1X,A5,20(2X,A10))' ) ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' ! Write the node data do I = 1,numJoints - write( UnSum, '(1X,I5,(2X,A10),3(2X,F10.4),2(2X,A10),2(2X,ES10.3),8(2X,A10),3(2X,ES10.3))' ) i,' - ', nodes(i)%Position, ' - ', ' - ', nodes(i)%tMG, nodes(i)%MGdensity, ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', nodes(i)%JAxCd, nodes(i)%JAxCa, nodes(i)%JAxCp + write( UnSum, '(1X,I5,(2X,A10),3(2X,F10.4),2(2X,A10),2(2X,ES10.3),9(2X,A10),3(2X,ES10.3))' ) i,' - ', nodes(i)%Position, ' - ', ' - ', nodes(i)%tMG, nodes(i)%MGdensity, ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', nodes(i)%JAxCd, nodes(i)%JAxCa, nodes(i)%JAxCp end do c = numJoints do j= 1, numMembers @@ -803,7 +803,7 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no else fillFlag = .false. end if - write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),4(2X,ES10.3),2(6X,L6),6(2X,ES10.3),3(7x,A5))' ) c, members(j)%MemberID, nodes(c)%Position, members(j)%R(i), members(j)%R(i)-members(j)%Rin(i), members(j)%tMG(i), members(j)%MGdensity(i), members(j)%PropPot, fillFlag, members(j)%Cd(i), members(j)%Ca(i), members(j)%Cp(i), members(j)%AxCd(i), members(j)%AxCa(i), members(j)%AxCp(i), ' - ', ' - ', ' - ' + write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),4(2X,ES10.3),2(6X,L6),7(2X,ES10.3),3(7x,A5))' ) c, members(j)%MemberID, nodes(c)%Position, members(j)%R(i), members(j)%R(i)-members(j)%Rin(i), members(j)%tMG(i), members(j)%MGdensity(i), members(j)%PropPot, fillFlag, members(j)%m_fb_u(i)+members(j)%m_fb_l(i), members(j)%Cd(i), members(j)%Ca(i), members(j)%Cp(i), members(j)%AxCd(i), members(j)%AxCa(i), members(j)%AxCp(i), ' - ', ' - ', ' - ' end do end do @@ -1569,42 +1569,75 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF Za = InitInp%Nodes(member%NodeIndx( i))%Position(3) ! z location of node i Zb = InitInp%Nodes(member%NodeIndx(i+1))%Position(3) ! z location of node i+1 - ! ------------------ marine growth weight and inertia, and flooded ballast inertia-------------------- + ! ------------------ marine growth weight and inertia ------------------------------------------------ Vinner_l = 0.0 Vouter_l = 0.0 Vinner_U = 0.0 Vouter_U = 0.0 - Vballast_l = 0.0 - Vballast_U = 0.0 if (i > member%i_floor) then ! full marine growth: get the properties for each half-element lumped to the appropriate node Rmid = 0.5*(member%R( i)+member%R( i+1)) ! radius at middle of segment, where division occurs RmidMG = 0.5*(member%RMG(i)+member%RMG(i+1)) ! radius with marine growth at middle of segment, where division occurs - Rmidin = 0.5*(member%Rin(i)+member%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment - CALL MarineGrowthPartSegment(member%R(i ), Rmid, member%RMG(i ),RmidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_rmg_l(i)) ! get precomupted quantities for lower half-segment - CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomupted quantities for upper half-segment - CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomupted quantities for lower half-segment - CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomupted quantities for upper half-segment - + CALL MarineGrowthPartSegment(member%R(i ), Rmid, member%RMG(i ),RmidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_rmg_l(i)) ! get precomputed quantities for lower half-segment + CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment else if (i == member%i_floor) then ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node Rmid = (-member%h_floor*member%R( i) +(dl+member%h_floor)*member%R( i+1))/dl RmidMG = (-member%h_floor*member%RMG(i) +(dl+member%h_floor)*member%RMG(i+1))/dl - Rmidin = (-member%h_floor*member%Rin(i) +(dl+member%h_floor)*member%Rin(i+1))/dl Lmid = -member%h_floor - CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG, -Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomupted quantities for upper half-segment - CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomupted quantities for upper half-segment + CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG, -Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment Vinner_l = 0.0 Vouter_l = 0.0 - Vballast_l = 0.0 end if + + ! ------------------ flooded ballast inertia --------------------------------------------------------- + Vballast_l = 0.0 + Vballast_U = 0.0 + if (member%memfloodstatus > 0 .and. (member%FillFSLoc > Za)) then + ! Fully filled element, so split in middle + if ((i > member%i_floor) .and. (member%FillFSLoc >= Zb)) then + + ! get the properties for each half-element lumped to the appropriate node + Rmidin = 0.5*(member%Rin(i)+member%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs + Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment + CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + + ! partially filled element, so split at FillFSLoc + else if ((i > member%i_floor) .AND. (member%FillFSLoc < Zb)) then + + ! get the properties for each partial-element lumped to the appropriate node + Lmid = member%FillFSLoc - Za + Rmidin = member%Rin(i)+(Lmid/(Zb-Za))*(member%Rin(i+1)-member%Rin(i)) ! radius of member interior at middle of segment, where division occurs + CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, 0.0, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + + else if (i == member%i_floor) then ! Hopefully we don't have a partially filled element crossing the seabed. + + ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node + RmidMG = (-member%h_floor*member%RMG(i) +(dl+member%h_floor)*member%RMG(i+1))/dl + Rmidin = (-member%h_floor*member%Rin(i) +(dl+member%h_floor)*member%Rin(i+1))/dl + Lmid = -member%h_floor + CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + Vballast_l = 0.0 + + end if + else ! Either no ballast flooding in member, or this particular element isn't flooded at all + Vballast_u = 0.0 + Vballast_l = 0.0 + member%m_fb_u(i) = 0.0 + member%h_cfb_u(i) = 0.0 + member%I_lfb_u(i) = 0.0 + member%I_rfb_u(i) = 0.0 + endif + ! Determine volumes to add to Non-WAMIT modeled members, etc. if (.not. member%PropPot) then @@ -1638,6 +1671,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF end if ! ------------------ flooded ballast weight (done) -------------------- + ! NOTE: this section of code is somewhat redundant with "flooded ballast inertia" section above li = dl*(i-1) ! fully buried element @@ -1680,7 +1714,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF !Since this element is only partially flooded/ballasted, compute the Volume fraction which is filled call TaperCalc( member%Rin(i), member%Rin(i)+member%h_fill*member%dRdl_in(i), member%h_fill, Vballast_l, h_c) Vballast_u = 0.0 - member%Vballast = member%Vballast + Vballast_l + Vballast_u ! TODO: Determine how to add only fraction of volume + member%Vballast = member%Vballast + Vballast_l + Vballast_u ! Note: Vballast_l will match calculations above ! depth-adjusted force distribution constant @@ -2788,6 +2822,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! ------------------ flooded ballast inertia: sides: Section 6.1.1 : Always compute regardless of PropPot setting --------------------- +!FIXME: these calculations use the mass of the fully filled volume and do not account for FillFSLoc... yet ! lower node Ioffset = mem%h_cfb_l(i)*mem%h_cfb_l(i)*mem%m_fb_l(i) Imat(1,1) = mem%I_rfb_l(i) - Ioffset From fbd7494e4438ca20d383f6eb6afe640438b6ca1c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 6 Jan 2021 18:10:39 -0700 Subject: [PATCH 359/377] HD 2nd order: add warning about 2nd order potential flow when PotMod/=1 --- modules/hydrodyn/src/HydroDyn_Input.f90 | 38 +++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 120fe9163..b4eb4cba5 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -3166,6 +3166,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) RETURN END IF + if ( InitInp%NBody > 1 .and. InitInp%WAMIT2%MnDrift == 8 ) then call SetErrStat( ErrID_Fatal,'MnDrift cannot equal 8 when NBody > 1.',ErrStat,ErrMsg,RoutineName) return @@ -3176,6 +3177,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) return end if + ! Check MnDrift and set the flag indicating WAMIT2 should perform the mean drift calculation. ! Also make sure we have a valid input value for the file extension @@ -3183,7 +3185,12 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%WAMIT2%MnDriftF = .FALSE. ELSE IF ( InitInp%WAMIT2%MnDrift == 7 .OR. InitInp%WAMIT2%MnDrift == 8 .OR. InitInp%WAMIT2%MnDrift == 9 .OR. & InitInp%WAMIT2%MnDrift == 10 .OR. InitInp%WAMIT2%MnDrift == 11 .OR. InitInp%WAMIT2%MnDrift == 12 ) THEN ! Valid values for MnDrift - InitInp%WAMIT2%MnDriftF = .TRUE. + IF ( InitInp%PotMod /= 1 ) THEN + CALL SetErrStat( ErrID_warn,'MnDrift can only be used with PotMod==1. Turning off',ErrStat,ErrMsg,RoutineName) + InitInp%WAMIT2%MnDriftF = .FALSE. + ELSE + InitInp%WAMIT2%MnDriftF = .TRUE. + ENDIF ELSE ! Must have received an invalid value CALL SetErrStat( ErrID_Fatal,'MnDrift can only have values of 0, 7, 8, 9, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3197,7 +3204,12 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) InitInp%WAMIT2%NewmanAppF = .FALSE. ELSE IF ( InitInp%WAMIT2%NewmanApp == 7 .OR. InitInp%WAMIT2%NewmanApp == 8 .OR. InitInp%WAMIT2%NewmanApp == 9 .OR. & InitInp%WAMIT2%NewmanApp == 10 .OR. InitInp%WAMIT2%NewmanApp == 11 .OR. InitInp%WAMIT2%NewmanApp == 12 ) THEN ! Valid values for NewmanApp - InitInp%WAMIT2%NewmanAppF = .TRUE. + IF ( InitInp%PotMod /= 1 ) THEN + CALL SetErrStat( ErrID_warn,'NewmanApp can only be used with PotMod==1. Turning off',ErrStat,ErrMsg,RoutineName) + InitInp%WAMIT2%NewmanAppF = .FALSE. + ELSE + InitInp%WAMIT2%NewmanAppF = .TRUE. + ENDIF ELSE ! Must have received an invalid value CALL SetErrStat( ErrID_Fatal,'NewmanApp can only have values of 0, 7, 8, 9, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3210,7 +3222,12 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) IF ( InitInp%WAMIT2%DiffQTF == 0 ) THEN ! not using DiffQTF method InitInp%WAMIT2%DiffQTFF = .FALSE. ELSE IF ( InitInp%WAMIT2%DiffQTF == 10 .OR. InitInp%WAMIT2%DiffQTF == 11 .OR. InitInp%WAMIT2%DiffQTF == 12 ) THEN ! Valid values for DiffQTF - InitInp%WAMIT2%DiffQTFF = .TRUE. + IF ( InitInp%PotMod /= 1 ) THEN + CALL SetErrStat( ErrID_warn,'DiffQTF can only be used with PotMod==1. Turning off',ErrStat,ErrMsg,RoutineName) + InitInp%WAMIT2%DiffQTFF = .FALSE. + ELSE + InitInp%WAMIT2%DiffQTFF = .TRUE. + ENDIF ELSE CALL SetErrStat( ErrID_Fatal,'DiffQTF can only have values of 0, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3223,7 +3240,12 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) IF ( InitInp%WAMIT2%SumQTF == 0 ) THEN ! not using SumQTF method InitInp%WAMIT2%SumQTFF = .FALSE. ELSE IF ( InitInp%WAMIT2%SumQTF == 10 .OR. InitInp%WAMIT2%SumQTF == 11 .OR. InitInp%WAMIT2%SumQTF == 12 ) THEN ! Valid values for SumQTF - InitInp%WAMIT2%SumQTFF = .TRUE. + IF ( InitInp%PotMod /= 1 ) THEN + CALL SetErrStat( ErrID_warn,'SumQTF can only be used with PotMod==1. Turning off',ErrStat,ErrMsg,RoutineName) + InitInp%WAMIT2%SumQTFF = .FALSE. + ELSE + InitInp%WAMIT2%SumQTFF = .TRUE. + ENDIF ELSE CALL SetErrStat( ErrID_Fatal,'SumQTF can only have values of 0, 10, 11, or 12.',ErrStat,ErrMsg,RoutineName) RETURN @@ -3256,7 +3278,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) ! now that it has been established that the input parameters for second order are good, we check to make sure that the WAMIT files actually exist. ! Check MnDrift file - IF ( InitInp%WAMIT2%MnDrift /= 0) THEN + IF ( InitInp%WAMIT2%MnDriftF ) THEN ! Check if using QTF file types (10d, 11d, 12d) or not (7,8,9) IF ( InitInp%WAMIT2%MnDrift <= 9 ) THEN TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%MnDrift)) @@ -3273,7 +3295,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF ! Check existence of NewmanApp file - IF ( InitInp%WAMIT2%NewmanApp /= 0) THEN + IF ( InitInp%WAMIT2%NewmanAppF ) THEN ! Check if using QTF file types (10d, 11d, 12d) or not (7,8,9) IF ( InitInp%WAMIT2%NewmanApp <= 9 ) THEN TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%NewmanApp)) @@ -3289,7 +3311,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF END IF - IF ( InitInp%WAMIT2%DiffQTF /= 0) THEN + IF ( InitInp%WAMIT2%DiffQTFF ) THEN TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%DiffQTF))//'d' INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) IF ( .not. TmpFileExist ) THEN @@ -3299,7 +3321,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, ErrStat, ErrMsg ) END IF END IF - IF ( InitInp%WAMIT2%SumQTF /= 0) THEN + IF ( InitInp%WAMIT2%SumQTFF ) THEN TmpExtension = TRIM(Num2LStr(InitInp%WAMIT2%SumQTF))//'s' INQUIRE( file=TRIM(InitInp%WAMIT2%WAMITFile)//'.'//TRIM(TmpExtension), exist=TmpFileExist ) IF ( .not. TmpFileExist ) THEN From 96046ffa7baff94aec5a742747932fefc4c0f3bf Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Wed, 6 Jan 2021 19:49:21 -0700 Subject: [PATCH 360/377] FlexSub: documentation of rigid body rotations and more floating cases --- docs/source/user/api_change.rst | 32 +-- docs/source/user/subdyn/input_files.rst | 3 + docs/source/user/subdyn/theory.rst | 356 +++++++++++++++++++----- modules/subdyn/src/SubDyn.f90 | 28 +- 4 files changed, 329 insertions(+), 90 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index f8fded7ca..04d60d91c 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -22,25 +22,25 @@ Added in OpenFAST dev --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Module Line Flag Name Example Value ============================================= ==== =============== ======================================================================================================================================================================================================== -IfW driver 6 [separator line] ===================== File Conversion Options ================================= +IfW driver 6 [sep. line] ===================== File Conversion Options ================================= IfW driver 7 WrHAWC false WrHAWC - Convert all data to HAWC2 format? (flag) IfW driver 8 WrBladed false WrBladed - Convert all data to Bladed format? (flag) IfW driver 9 WrVTK false WrVTK - Convert all data to VTK format? (flag) -InflowWind 7 VFlowAng 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) -SubDyn 8 ExtraMom False ExtraMoment - Include extra moment from lever arm at interface in interface reactions. -SubDyn 15 GuyanDampMod 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} -SubDyn 16 RayleighDamp 0.001, 0.003 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] -SubDyn 17 GuyanDampSize 6 GuyanDampSize - Guyan damping matrix size (square, 6x6) [only if GuyanDampMod=2] -SubDyn 18 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 -SubDyn -23 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 -SubDyn na CablesSection -------------------------- CABLE PROPERTIES ------------------------------------- -SubDyn na CablesSection 0 NCablePropSets - Number of cable cable properties -SubDyn na CablesSection PropSetID EA MatDens T0 -SubDyn na CablesSection (-) (N) (kg/m) (N) -SubDyn na RigidSection ---------------------- RIGID LINK PROPERTIES ------------------------------------ -SubDyn na RigidSection 0 NRigidPropSets - Number of rigid link properties -SubDyn na RigidSection PropSetID MatDens -SubDyn na RigidSection (-) (kg/m) +InflowWind 7 VFlowAng 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) +SubDyn 8 ExtraMom False ExtraMoment - Include extra moment from lever arm at interface in interface reactions. +SubDyn 15 GuyanDampMod 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} +SubDyn 16 RayleighDamp 0.001, 0.003 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] +SubDyn 17 GuyanDampSize 6 GuyanDampSize - Guyan damping matrix size (square, 6x6) [only if GuyanDampMod=2] +SubDyn 18 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 +SubDyn -23 GuyanDampMat 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 +SubDyn na CablesSection -------------------------- CABLE PROPERTIES ------------------------------------- +SubDyn na CablesSection 0 NCablePropSets - Number of cable cable properties +SubDyn na CablesSection PropSetID EA MatDens T0 +SubDyn na CablesSection (-) (N) (kg/m) (N) +SubDyn na RigidSection ---------------------- RIGID LINK PROPERTIES ------------------------------------ +SubDyn na RigidSection 0 NRigidPropSets - Number of rigid link properties +SubDyn na RigidSection PropSetID MatDens +SubDyn na RigidSection (-) (kg/m) ============================================= ==== =============== ======================================================================================================================================================================================================== diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst index a0dbfd7b8..cdac52e42 100644 --- a/docs/source/user/subdyn/input_files.rst +++ b/docs/source/user/subdyn/input_files.rst @@ -593,6 +593,9 @@ to align properly, the width specification should match. For example: | "ES11.4" OutFmt | "A11" OutSFmt. + +.. _SD_Member_Output: + Member Output List ~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 5859d4d33..8f3e1981f 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -1305,7 +1305,7 @@ DOFs). For this reason, a C-B methodology was used to recharacterize the substructure finite-element model into a reduced DOF model that maintains the fundamental low-frequency response modes of the structure. With the C-B method, the DOFs of the substructure can be reduced to -about 10 (user defined, see also Section :ref:`CBguide`). This system reduction method +about 10 (user defined, see also Section :numref:`CBguide`). This system reduction method was first introduced by :cite:`hurty1964` and later expanded by :cite:`craig1968`. @@ -1647,6 +1647,17 @@ substructure response at each time step can then be obtained by using the state-space formulation discussed in the next section. +Floating or fixed-bottom structure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Different formulations are used in SubDyn depending if the structure is "fixed-bottom" or "floating". + +The structure is considered to be "floating" if there is no reaction nodes. + +The structure is considered to be "fixed-bottom" in any other case. + + + .. _SD_Loads: Loads @@ -1694,6 +1705,16 @@ The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given +.. _SD_Rotated Loads: + +Rotation of loads for floating +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the floating case, the loads acting on the FEM degrees of freedom need to be rotated to the body frame. In the current implementation, this is done when evaluating :math:`F_{L}` for the time evolution of the CB degrees of freedom, and the determination of the static improvement displacements. +More details on this special case is found in section :numref:`SD_summary`. + + + .. _SD_ExtraMoment: Extra moment from deflection @@ -1714,7 +1735,6 @@ First, a reference undeflected position of the structure is defined, with two po Illustration for the additional moment occurring due to the distance between the deflected position of the structure and the reference position used for the finite element representation. For simplicity, the loads are assumed to act at the Guyan position instead of the true deflected position. -The structure is considered "fixed" at the sea bed if at least one reaction node satisfies one of these two conditions: the 4 degrees of freedom accounting for the x-y translation and rotation are fixed at the sea bed, or, an additional stiffness matrix is given via an SSI input file (see :numref:`sd_ssi_inputfile`). Second, the external loads are assumed to be applied on the "Guyan" deflected structure, instead of the fully deflected structure. The Craig-Bampton displacements are omitted to avoid the non-linear dependency between the input loads and the Craig-Bampton states. With this assumption, the external loads at the Guyan position are mapped to the reference position. @@ -2001,20 +2021,6 @@ By examining Eq. :eq:`main4` and Eq. :eq:`FTPtilde`, the force is extracted from Inserting the expression of :math:`\ddot{q}_m` into :math:`F_{TP}` leads to: -.. F_{TP} =& \tilde{M}_{BB}\ddot{U}_{TP} - + \tilde{M}_{Bm} \left[ - \Phi_m^T(F_L + F_{L,g}) - - \tilde{M}_{mB} \ddot{U}_{TP} - - \tilde{C}_{mB} \dot{U}_{TP} - - \tilde{C}_{mm} \dot{q}_m - - \tilde{K}_{mm} q_m - \right] - \nonumber\\ - &+ \tilde{C}_{BB}\dot{U}_{TP} + \tilde{C}_{Bm} \dot{q}_m - + \tilde{K}_{BB} U_{TP} - - T_I^T \left(\bar{F}_{HDR} + \bar{F}_{Rg} + \bar{\Phi}_R(F_{L,e} + F_{L,g}) \right) - \nonumber\\ - .. math:: :label: FTP3 :nowrap: @@ -2102,7 +2108,7 @@ From the CB coordinate transformation (Eq. :eq:`CB3`), and the link between boun ,\qquad \ddot{\bar{U}}_L = \bar{\Phi}_R \ddot{\bar{U}}_R + \Phi_m \ddot{q}_m -Using the expression of :math:`\ddot{q}m` from Eq. :eq:`ddotqm`, the internal accelerations are: +Using the expression of :math:`\ddot{q}_m` from Eq. :eq:`ddotqm`, the internal accelerations are: .. math:: :label: y2internalacc @@ -2114,6 +2120,7 @@ Using the expression of :math:`\ddot{q}m` from Eq. :eq:`ddotqm`, the internal ac - \tilde{K}_{mm} q_m \right] +In the floating case, the Guyan part of the motion are replaced by the analytical rigid body motion (se details in section :numref:`SD_summary`). The output equation for :math:`y_2`: can then be written as: @@ -2157,6 +2164,7 @@ where The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`bigY2sim` is used instead. + .. _sim: .. _SD_SIM: @@ -2186,7 +2194,7 @@ with C-B modes (:math:`U_{L0m}`), as cast in :eq:`SIM` : .. math:: :label: SIM - U_L = \hat{U}_L + U_{L0} - U_{L0m} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} + U_L = \hat{U}_L + U_{L,\text{SIM}} =\hat{U}+ \underbrace{U_{L0} - U_{L0m}}_{U_{L,\text{SIM}}} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} .. where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. @@ -2234,12 +2242,13 @@ Similarly: with :math:`\tilde{F}_m =\Phi_m^T(F_{L,e} + F_{L,g})`. Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. +In the floating case the loads :math:`F_L` is rotated to the body coordinate system when "ExtraMoment" is True (see :numref:`SD_summary` for more details). + The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R \end{bmatrix} }` is calculated following the usual procedure described in :numref:`SSformulation` to :numref:`TimeIntegration`. For example, states are still calculated and integrated as in Eq. :eq:`state_eq`, and the output to ElastoDyn, i.e., the reaction provided by the substructure at the TP interface, is also calculated as it was done previously in Eqs. :eq:`smally1` and :eq:`bigY1`. - However, the state-space formulation is slightly modified (simply adding the contribution :math:`U_{L0}-U_{L0m}` to :math:`F_{Y2}` when computing the outputs to HydroDyn as: @@ -2255,7 +2264,7 @@ when computing the outputs to HydroDyn as: \ddot{U}_L \\ \end{bmatrix} = \begin{bmatrix} \bar{U}_R \\ - \hat{U}_L + \boldsymbol{U_{L0} - U_{L0m}} \\ + \hat{U}_L + \boldsymbol{U_{L,\text{SIM}}} \\ \dot{\bar{U}}_R \\ \dot{U}_L \\ \ddot{\bar{U}}_R \\ @@ -2268,7 +2277,7 @@ The array :math:`F_{Y2}` from Eq. :eq:`bigY2` is now defined as follows: F_{Y2} &= \begin{bmatrix} 0 \\ - \boldsymbol{U_{L0} - U_{L0m}} \\ + \boldsymbol{U_{L,\text{SIM}}} \\ 0 \\ 0 \\ 0 \\ @@ -2276,70 +2285,89 @@ The array :math:`F_{Y2}` from Eq. :eq:`bigY2` is now defined as follows: \end{bmatrix} -Finally, the element forces can be calculated as: -.. math:: :label: el_loads_sim - \text{Element Inertia load:} ~~ F_I^e &= [m] \ddot{U}_e - - \text{Element Static load:} ~~ F_S^e &= [k] U_e = [k] \left[ \hat{U}_e + U_{L0,e} - U_{L0m,e} \right] - -with the element node DOFs expressed as: +Outputs and Time Integration +---------------------------- + + + +.. _SD_MemberForce: -.. math:: :label: Uesim +Nodal Loads Calculation +~~~~~~~~~~~~~~~~~~~~~~~~ - U_e = \hat{U}_e + U_{L0,e} - U_{L0m,e} +We start by introducing how element loads are computed, before detailling how nodal loads are obtained. -where the SIM decomposition is still used with :math:`\hat{U}_e` denoting the -time-varying components of the elements nodes' displacements, and :math:`U_{L0,e}` and :math:`U_{L0m,e}` are -derived from the parent :math:`U_{L0}` and :math:`U_{L0m}` arrays of displacements, respectively. +**Element Loads**: +SubDyn calculates 12-vector element loads in the element coordinate system using the global motion of the element: +.. math:: :label: el_loads + \text{Element Inertia load:} ~~ F_{I,12}^e &= [D_{c,12}]^T [m] \ddot{U}_{e,12} + + \text{Element Stiffness load:} ~~ F_{S,12}^e &= [D_{c,12}]^T [k] \left[ \hat{U}_e + U_{L,\text{SIM}} \right]_{12} + +where [*k*] and [*m*] are element stiffness and mass matrices expressed in the global frame, +:math:`D_{c,12}` is a 12x12 matrix of DCM for a given element, +the subscript 12 indicates that the 12 degrees of freedom of the element are considered, +and :math:`U_e` and :math:`\ddot{U}_e` are element nodal deflections and accelerations respectively, +which can be obtained from Eq. :eq:`y2` and may contain the static displacement contribution :math:`U_{L,\text{SIM}}`. There is no good way to quantify the damping forces for each element, so +the element damping forces are not calculated. +**Nodal loads** +For a given element node, the loads are the 6-vector with index 1-6 or 7-12 for the first or second node respectively. By convention, the 6-vector is multiplied by -1 for the first node and +1 for the second node of the element: +.. math:: :label: nd_loads + F_{6}^{n_1} = - F_{12}^e(1:6) + ,\quad + F_{6}^{n_2} = + F_{12}^e(7:12) +The above applies for the inertial and stiffness loads. + +**Member nodal loads requested by the user** -Outputs and Time Integration ----------------------------- +The user can output nodal loads for a set of members (see :numref:`SD_Member_Output`). +For the user requested member nodal outputs, the loads are either: 1) the appropriate 6-vector at the member end nodes, or, 2) the average of the 6-vectors from the two elements surrounding a node for the nodes in the middle of a member. When averaging is done, the 12-vectors of both surrounding elements are expressed using the DCM of the member where outputs are requested. -Member Force Calculation -~~~~~~~~~~~~~~~~~~~~~~~~ +**"AllOuts" nodal loads** -SubDyn can also calculate member forces by starting from the forces -computed at the nodes of the elements that are contained in the member -as: +For "AllOuts" nodal outputs, the loads are not averaged and the 6-vector (with the appropriate signs) are directly written to file. + +**Reaction nodal loads** +(See :numref:`SD_Reaction`) -.. math:: :label: el_loads - \text{Element Inertia load:} ~~ F_I^e = [m] \ddot{U}_e - - \text{Element Static load:} ~~ F_S^e = [k] U_e - -where [*k*] and [*m*] are element stiffness and mass matrices, respectively. And -:math:`U_e` and :math:`\ddot{U}_e` are element nodal deflections and accelerations respectively, -which can be obtained from Eq. :eq:`y2`. -There is no good way to quantify the damping forces for each element, so -the element damping forces are not calculated. + +.. _SD_Reaction: Reaction Calculation ~~~~~~~~~~~~~~~~~~~~ -The reactions at the base of the structure are the member forces at the -base nodes. These are usually provided in member local reference frames. +The reactions at the base of the structure are the nodal loads at the +base nodes. + + + + Additionally, the user may request an overall reaction :math:`\overrightarrow{R}` (six forces and moments) lumped at the center of the substructure (tower centerline) and mudline, i.e., at the reference point (0,0,-**WtrDpth**) in the global reference frame, with -**WtrDpth** denoting the water depth. :math:`\overrightarrow{R}` is a -six-element array that can be calculated in matrix form as follows: +**WtrDpth** denoting the water depth. + +To obtain this overall reaction, the forces and moments at the :math:`N_\text{React}` restrained +nodes are expressed in the global coordinate frame and gathered into the vector :math:`F_{\text{React}}`, which is a (6*N\ :sub:`React`) array. +For a given reaction node, the 6-vector of loads is obtained by summing the nodal load contributions from all the elements connected to that node expressed in the global frame (no account of the sign is done here), and subtracting the external loads (:math:`F_{HDR}`) applied on this node. +The loads from all nodes, :math:`F_{\text{React}}`, are then rigidly-transferred to :math:`(0,0,-\text{WtrDpth})` to obtain the overall six-element array :math:`\overrightarrow{R}`: .. math:: :label: reaction @@ -2349,10 +2377,7 @@ six-element array that can be calculated in matrix form as follows: M_{Z} \\ \end{bmatrix} = T_{\text{React}} F_{\text{React}} - -where :math:`F_{\text{React}}` is a (6*N\ :sub:`React`) array -containing the forces and moments at the *N\ :sub:`react`* restrained -nodes in the global coordinate frame, and :math:`T_{\text{React}}` is a +where :math:`T_{\text{React}}` is a ( :math:`{6×6 N_{\text{React}}}` ) matrix, as follows: .. math:: :label: Treact @@ -2367,12 +2392,7 @@ nodes in the global coordinate frame, and :math:`T_{\text{React}}` is a \end{bmatrix} where :math:`{X_i,~Y_i}`, and :math:`Z_i` (:math:`{i = 1 .. N_{\text{React}}}`) are coordinates of -the boundary nodes with respect to the reference point. For each element -with a restrained node, :math:`F_{\text{React}}` is calculated starting -from :math:`F_S^e` --- see Eq. :eq:`el_loads` --- subtracting out the contributions of gravity --- :math:`F_G`, see Eq. :eq:`FG` -and hydrodynamic loads (:math:`F_{HDR}`) at the restrained node. No direct -element-level inertial or damping effect is therefore included in the -reaction calculation. +the boundary nodes with respect to the reference point. @@ -2417,8 +2437,216 @@ For more information, consult any numerical methods reference, e.g., +.. _SD_summary: + +Summary of the formulation implemented +-------------------------------------- + +This section summarizes the equations currently implemented in SubDyn. + +State equation +~~~~~~~~~~~~~~ + +**Fixed-bottom case** + +.. math:: + :nowrap: + + \begin{align} + \ddot{q}_m = \Phi_m^T F_L + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \end{align} + +Note: :math:`F_L` contains the "extra moment" if user-requested. + +**Floating case without "Extra Moment"** + +.. math:: + :nowrap: + + \begin{align} + \ddot{q}_m = \Phi_m^T F_L + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \end{align} + +Notes: :math:`F_L` *does not* contain the "extra moment". + + +**Floating case with "Extra Moment"** + +.. math:: + :nowrap: + + \begin{align} + \ddot{q}_m = \Phi_m^T R_{g2b} F_L + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m + \end{align} + +Notes: :math:`F_L` *does not* contain the "extra moment". The (external + gravity) loads are rotated to the body coordinate system using the matrix :math:`R_{g2b}` (global to body). + + +Output: interface reaction +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Fixed bottom case** + +.. math:: + :nowrap: + + \begin{align} + -Y_1 =F_{TP,cpl} = + \begin{Bmatrix} + f_{TP,cpl} \\ + m_{TP,cpl} \\ + \end{Bmatrix} + & = + \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + +\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + \\ + &+\left[\tilde{K}_{BB} \right] U_{TP} + +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} + +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} + \nonumber \\ + &+\left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} + +\left[ -T_I^T \right] \bar{F}_R + \nonumber + \end{align} + +Note: :math:`F_L` and :math:`\bar{F}_R` contains the "extra moment" if user-requested. +If this is the case, the following additional term is added to the moment part of :math:`Y_1`, +:math:`m_{Y_1,\text{extra}}=u_{TP} \times f_{TP,cpl}`. + + + +**Floating case without "Extra moment"** + +.. math:: + :nowrap: + + \begin{align} + -Y_1 =F_{TP,cpl} =& + \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + +\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + \\ + &+\left[\tilde{K}_{BB} \right] U_{TP} + +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} + +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} + \nonumber \\ + &+\left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} + +\left[-T_I^T \right] \bar{F}_R + \nonumber + \end{align} + +Note: :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment". + +**Floating case with "Extra moment"** + +.. math:: + :nowrap: + + \begin{align} + -Y_1 =F_{TP,cpl} =& + \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + +\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + \\ + &+\left[\tilde{K}_{BB} \right] U_{TP} + +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} + +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} + \nonumber \\ + &+\left[\tilde{M}_{Bm}\Phi_m^T\right] R_{b2g} F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L,\text{extra}} + +\left[-T_I^T \right] \bar{F}_{R,\text{extra}} + \nonumber + \end{align} + + +Note: :math:`F_{L,\text{extra}}` and :math:`F_{R,\text{extra}}` contain the "extra moment" in the Guyan contribution. For the Craig-Bampton contribution, the loads are rotated to the body coordinate system using the matrix :math:`R_{g2b}` (global to body). + + +Output: nodal motions +~~~~~~~~~~~~~~~~~~~~~ + +**Fixed-bottom case** + +.. math:: :label: + + \bar{U}_R &= T_I U_{TP} + ,\qquad + \bar{U}_L = \bar{\Phi}_R \bar{U}_R + \Phi_m q_m + U_{L,\text{SIM}} + + \dot{\bar{U}}_R &= T_I \dot{U}_{TP} + ,\qquad + \dot{\bar{U}}_L = \bar{\Phi}_R \dot{\bar{U}}_R + \Phi_m \dot{q}_m + + \ddot{\bar{U}}_R &= T_I \ddot{U}_{TP} + ,\qquad + \ddot{\bar{U}}_L = \bar{\Phi}_R \ddot{\bar{U}}_R + \Phi_m\left[\Phi_m^T F_L + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m \right] + + +Note: :math:`F_L` contains the "extra moment" if user-requested. + + + + +**Floating case** + +.. math:: :label: + + \bar{U}_R &= U_{R,\text{rigid}} + ,\qquad + \bar{U}_L = U_{L,\text{rigid}} + 0\cdot \Phi_m q_m + 0\cdot U_{L,\text{SIM}} + + \dot{\bar{U}}_R &= \dot{U}_{R,\text{rigid}} + ,\qquad + \dot{\bar{U}}_L = \dot{U}_{L,\text{rigid}} + \Phi_m \dot{q}_m + + \ddot{\bar{U}}_R &= \ddot{U}_{R,\text{rigid}} + ,\qquad + \ddot{\bar{U}}_L = \ddot{U}_{L,\text{rigid}} + \Phi_m\left[\Phi_m^T R_{g2b} F_L + - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{C}_{mm} \dot{q}_m + - \tilde{K}_{mm} q_m \right] + +where: 1) :math:`F_L` does not contain the extra moment, 2) the matrix :math:`R_{g2b}` is only used if ExtraMoment is True, 3) the elastic displacements were set to 0 for stability purposes (assuming that these are small) 4) the Guyan motion is computed using the exact rigid body motions. For a given node :math:`P`, located at the position :math:`r_{IP,0}` from the interface in the undisplaced configuration, the position (from the interface point), displacement, translational velocity and acceleration due to the rigid body motion are: + + +.. math:: + r_{IP} &= R_{b2g} r_{IP,0} + ,\quad + u_P = r_{IP} - r_{IP,0} + u_{TP} + ,\quad + + \dot{u}_P &= \dot{u}_{TP} + \omega_{TP} \times r_{IP} + ,\quad + \ddot{u}_P= \ddot{u}_{TP} + \dot{\omega}_{TP} \times r_{IP} + \omega_{TP} \times (\omega_{TP} \times r_{IP}) + +where :math:`\omega_{TP}` is the angular velocity at the transition piece. The small angle rotations, angular velocities and accelerations of each nodes, due to the rigid body rotation, are the same as the interface values, :math:`\theta_{TP}`, :math:`\omega_{TP}` and :math:`\dot{\omega}_{TP}`, so that: + +.. math:: + U_{P,\text{rigid}} = \{u_P \ ; \theta_{TP}\}^T + ,\quad + \dot{U}_{P,\text{rigid}} = \{\dot{u}_P \ ; \omega_{TP}\}^T + ,\quad + \ddot{U}_{P,\text{rigid}} = \{\ddot{u}_P \ ; \dot{\omega}_{TP}\}^T + +where :math:`P` is a point belonging to the R- or L-set of nodes. + + +Outputs to file: +~~~~~~~~~~~~~~~~ +**Motions**: nodal motions written to file are in global coordinates, and for the floating case they contain the elastic motion :math:`\bar{U}_L = U_{L,\text{rigid}} + \Phi_m q_m + U_{L,\text{SIM}}` (whereas these elastic motions are not returned to the glue code) +**Loads**: +Nodal loads are written to file in the element coordinate system. The procedure are the same for fixed-bottom and floating cases. diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 45969f739..799ba7432 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -547,13 +547,19 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) vP(1:3) = u%TPMesh%TranslationVel(1:3,1) + Om_X_r aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) - ! Full displacements CB-rotated + Guyan (KEEP ME) - m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) - m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) - m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) - m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) - m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) - m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + ! Full displacements CB-rotated + Guyan (KEEP ME) >>> Rotate All + !m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) + !m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) + !m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) + !m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) + !m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) + !m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) + m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) ! NOTE: For now, displacements passed to HydroDyn are Guyan only! ! Construct the direction cosine matrix given the output angles @@ -2964,9 +2970,11 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rb2g, rIP0) duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) - ! Full diplacements Guyan + rotated CB (if asked) - DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) - DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) + DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) + duP(1:3) + DU_full(DOFList(4:6)) = DU_full(DOFList(4:6)) + rotations(1:3) + ! Full diplacements Guyan + rotated CB (if asked) >>> Rotate All + !DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) + !DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) enddo endif endif ! U_full no provided From 116f4b8140076e2f90b46791ffb1a84cc39e0524 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Fri, 8 Jan 2021 10:11:17 -0700 Subject: [PATCH 361/377] FlexSub: rotate all but MBmmB and only Guyan disp --- modules/subdyn/src/SubDyn.f90 | 102 ++++++++++++++++------------------ 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 799ba7432..ccb434472 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -33,10 +33,6 @@ Module SubDyn PRIVATE - !............................ - ! NOTE: for debugging, add preprocessor definition SD_SUMMARY_DEBUG - ! this will add additional matrices to the SubDyn summary file. - !............................ TYPE(ProgDesc), PARAMETER :: SD_ProgDesc = ProgDesc( 'SubDyn', '', '' ) ! ..... Public Subroutines ................................................................................................... @@ -470,12 +466,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then - !if (p%Floating) then ! >>> Rotate All - ! udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) - ! udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) - !else - udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) - !endif + if (p%Floating) then ! >>> Rotate All + udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) + udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) + else + udotdot_TP = (/u%TPMesh%TranslationAcc( :,1), u%TPMesh%RotationAcc(:,1)/) + endif m%UL = matmul( p%PhiM, x%qm ) m%UL_dot = matmul( p%PhiM, x%qmdot ) m%UL_dotdot = matmul( p%C2_61, x%qm ) + matmul( p%C2_62 , x%qmdot ) & @@ -548,18 +544,18 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) ! Full displacements CB-rotated + Guyan (KEEP ME) >>> Rotate All - !m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) - !m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) - !m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) - !m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) - !m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) - !m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) - m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) - m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) - m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) - m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) - m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) - m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) + m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + !m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) + !m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) + !m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) + !m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) + !m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + !m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) ! NOTE: For now, displacements passed to HydroDyn are Guyan only! ! Construct the direction cosine matrix given the output angles @@ -567,7 +563,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) call SmllRotTrans( 'UR_bar input angles', rotations(1), rotations(2), rotations(3), DCM, '', ErrStat2, ErrMsg2) ! NOTE: using only Guyan rotations call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'SD_CalcOutput') y%Y2mesh%Orientation (:,:,iSDNode) = DCM - !y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3) + !y%Y2mesh%TranslationDisp (:,iSDNode) = m%U_full (DOFList(1:3)) y%Y2mesh%TranslationDisp (:,iSDNode) = duP(1:3) ! NOTE: using only the Guyan Displacements y%Y2mesh%TranslationVel (:,iSDNode) = m%U_full_dot (DOFList(1:3)) y%Y2mesh%TranslationAcc (:,iSDNode) = m%U_full_dotdot (DOFList(1:3)) @@ -618,9 +614,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) - !if (p%Floating) then - ! Y1_CB = matmul(RRb2g, Y1_CB) !>>> Rotate All - !endif + if (p%Floating) then + Y1_CB = matmul(RRb2g, Y1_CB) !>>> Rotate All + endif else Y1_CB = 0.0_ReKi endif @@ -629,9 +625,9 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) if (.not.(p%ExtraMoment.and.p%Floating)) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif - !if (p%Floating) then - ! Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> Rotate All - !endif + if (p%Floating) then + Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> Rotate All + endif Y1 = Y1_CB + Y1_Utp + Y1_CB_L+ Y1_Guy_L + Y1_Guy_R ! KEEP ME @@ -749,11 +745,11 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta CALL GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) - !if (p%Floating) then - ! ! >>> Rotate All - udotdot_TP to body coordinates - ! udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) - ! udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) - !endif + if (p%Floating) then + ! >>> Rotate All - udotdot_TP to body coordinates + udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) + udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) + endif ! State equation dxdt%qm= x%qmdot @@ -1746,21 +1742,21 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') CALL GetExtForceOnInternalDOF(u_interp, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - !if (p%Floating) then - ! ! >>> Rotate All - udotdot_TP to body coordinates - ! m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) - ! m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) - !endif + if (p%Floating) then + ! >>> Rotate All - udotdot_TP to body coordinates + m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) + m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) + endif ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') CALL GetExtForceOnInternalDOF(u_interp, p, x, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - !if (p%Floating) then - ! ! >>> Rotate All - udotdot_TP to body coordinates - ! udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) - ! udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) - !endif + if (p%Floating) then + ! >>> Rotate All - udotdot_TP to body coordinates + udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) + udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) + endif ! calculate (u_n + u_n+1)/2 udotdot_TP2 = 0.5_ReKi * ( udotdot_TP2 + m%udotdot_TP ) @@ -2970,11 +2966,11 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rb2g, rIP0) duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) - DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) + duP(1:3) - DU_full(DOFList(4:6)) = DU_full(DOFList(4:6)) + rotations(1:3) + !DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) + duP(1:3) + !DU_full(DOFList(4:6)) = DU_full(DOFList(4:6)) + rotations(1:3) ! Full diplacements Guyan + rotated CB (if asked) >>> Rotate All - !DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) - !DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) + DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) + DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) enddo endif endif ! U_full no provided @@ -3015,7 +3011,7 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen if (ExtraMoment) then ! Compute node displacements "DU_full" for lever arm - call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False.)!, U_full=U_full) + call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False., U_full=U_full) endif ! --- Build vector of external forces (including gravity) (Moment done below) @@ -3584,10 +3580,10 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) if (nCB>0) then CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 - !if (p%Floating .and. present(u)) then - ! CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> Rotate All - ! CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> Rotate All - !endif + if (p%Floating .and. present(u)) then + CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> Rotate All + CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> Rotate All + endif endif endif From c73de8f11cf7257cd5f59c6e15f04b133d881c91 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 11 Jan 2021 14:21:45 -0700 Subject: [PATCH 362/377] FlexSub: update of documentation to include rotated matrices --- docs/source/user/subdyn/theory.rst | 38 ++++++++++++++++-------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 8f3e1981f..2096c50ac 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -2442,7 +2442,9 @@ For more information, consult any numerical methods reference, e.g., Summary of the formulation implemented -------------------------------------- -This section summarizes the equations currently implemented in SubDyn. +This section summarizes the equations currently implemented in SubDyn, with the distinction between floating and fixed bottom cases. +We introduce the operators :math:`R_{g2b}` (rotation global to body) and :math:`R_{b2g}` (rotation body to global), which act on the array on the right of the operator. The operators rotate the individual 3-vectors present in an array. When applied to load vectors (e.g. :math:`F_L`), the rotations actually is applied to the loads on the full system, before the loads are transferred to the reduced system by use of the :math:`\boldsymbol{T}` matrix. + State equation ~~~~~~~~~~~~~~ @@ -2468,7 +2470,7 @@ Note: :math:`F_L` contains the "extra moment" if user-requested. \begin{align} \ddot{q}_m = \Phi_m^T F_L - - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{M}_{mB} R_{g2b} \ddot{U}_{TP} - \tilde{C}_{mm} \dot{q}_m - \tilde{K}_{mm} q_m \end{align} @@ -2483,12 +2485,12 @@ Notes: :math:`F_L` *does not* contain the "extra moment". \begin{align} \ddot{q}_m = \Phi_m^T R_{g2b} F_L - - \tilde{M}_{mB} \ddot{U}_{TP} + - \tilde{M}_{mB} R_{g2b} \ddot{U}_{TP} - \tilde{C}_{mm} \dot{q}_m - \tilde{K}_{mm} q_m \end{align} -Notes: :math:`F_L` *does not* contain the "extra moment". The (external + gravity) loads are rotated to the body coordinate system using the matrix :math:`R_{g2b}` (global to body). +Notes: :math:`F_L` *does not* contain the "extra moment". The (external + gravity) loads and the acceleration of the TP are rotated to the body coordinate system. Output: interface reaction @@ -2531,19 +2533,20 @@ If this is the case, the following additional term is added to the moment part o \begin{align} -Y_1 =F_{TP,cpl} =& - \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m - +\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + R_{b2g}\left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + + R_{b2g}\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m \\ &+\left[\tilde{K}_{BB} \right] U_{TP} +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} \nonumber \\ - &+\left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} + &+ R_{b2g}\left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} +\left[-T_I^T \right] \bar{F}_R \nonumber \end{align} -Note: :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment". +Notes: 1) :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment"; +2) The rotation :math:`R_{b2g}\tilde{M}_{Bm} \tilde{M}_{mB}R_{g2b}` is not carried out since it introduced stability issues. **Floating case with "Extra moment"** @@ -2552,21 +2555,20 @@ Note: :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment". \begin{align} -Y_1 =F_{TP,cpl} =& - \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m - +\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + R_{b2g}\left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + + R_{b2g}\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m \\ &+\left[\tilde{K}_{BB} \right] U_{TP} +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} \nonumber \\ - &+\left[\tilde{M}_{Bm}\Phi_m^T\right] R_{b2g} F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L,\text{extra}} + &+ R_{b2g}\left[\tilde{M}_{Bm}\Phi_m^T\right] R_{b2g} F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L,\text{extra}} +\left[-T_I^T \right] \bar{F}_{R,\text{extra}} \nonumber \end{align} -Note: :math:`F_{L,\text{extra}}` and :math:`F_{R,\text{extra}}` contain the "extra moment" in the Guyan contribution. For the Craig-Bampton contribution, the loads are rotated to the body coordinate system using the matrix :math:`R_{g2b}` (global to body). - +Notes: 1) :math:`F_{L,\text{extra}}` and :math:`F_{R,\text{extra}}` contain the "extra moment" in the Guyan contribution; 2) For the Craig-Bampton contribution, the loads are rotated to the body coordinate system using the operator :math:`R_{g2b}` (global to body); 3) The rotation :math:`R_{b2g}\tilde{M}_{Bm} \tilde{M}_{mB}R_{g2b}` is not carried out since it introduced stability issues. Output: nodal motions ~~~~~~~~~~~~~~~~~~~~~ @@ -2602,20 +2604,20 @@ Note: :math:`F_L` contains the "extra moment" if user-requested. \bar{U}_R &= U_{R,\text{rigid}} ,\qquad - \bar{U}_L = U_{L,\text{rigid}} + 0\cdot \Phi_m q_m + 0\cdot U_{L,\text{SIM}} + \bar{U}_L = U_{L,\text{rigid}} + 0\cdot R_{b2g} \left(\Phi_m q_m + U_{L,\text{SIM}}\right) \dot{\bar{U}}_R &= \dot{U}_{R,\text{rigid}} ,\qquad - \dot{\bar{U}}_L = \dot{U}_{L,\text{rigid}} + \Phi_m \dot{q}_m + \dot{\bar{U}}_L = \dot{U}_{L,\text{rigid}} + R_{b2g} \Phi_m \dot{q}_m \ddot{\bar{U}}_R &= \ddot{U}_{R,\text{rigid}} ,\qquad - \ddot{\bar{U}}_L = \ddot{U}_{L,\text{rigid}} + \Phi_m\left[\Phi_m^T R_{g2b} F_L - - \tilde{M}_{mB} \ddot{U}_{TP} + \ddot{\bar{U}}_L = \ddot{U}_{L,\text{rigid}} + R_{b2g}\Phi_m\left[\Phi_m^T R_{g2b} F_L + - \tilde{M}_{mB} R_{g2b}\ddot{U}_{TP} - \tilde{C}_{mm} \dot{q}_m - \tilde{K}_{mm} q_m \right] -where: 1) :math:`F_L` does not contain the extra moment, 2) the matrix :math:`R_{g2b}` is only used if ExtraMoment is True, 3) the elastic displacements were set to 0 for stability purposes (assuming that these are small) 4) the Guyan motion is computed using the exact rigid body motions. For a given node :math:`P`, located at the position :math:`r_{IP,0}` from the interface in the undisplaced configuration, the position (from the interface point), displacement, translational velocity and acceleration due to the rigid body motion are: +where: 1) :math:`F_L` does not contain the extra moment, 2) the operator :math:`R_{g2b}` is only used on :math:`F_L` if ExtraMoment is True, 3) the elastic displacements were set to 0 for stability purposes (assuming that these are small) 4) the Guyan motion is computed using the exact rigid body motions. For a given node :math:`P`, located at the position :math:`r_{IP,0}` from the interface in the undisplaced configuration, the position (from the interface point), displacement, translational velocity and acceleration due to the rigid body motion are: .. math:: From 1f8b044f8247e1f015fc70c1e62a5f328f476ae9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Mon, 11 Jan 2021 14:33:12 -0700 Subject: [PATCH 363/377] FlexSub: update of documentation, small fix --- docs/source/user/subdyn/theory.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 2096c50ac..1d69ec2c8 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -2562,7 +2562,7 @@ Notes: 1) :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment"; +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} \nonumber \\ - &+ R_{b2g}\left[\tilde{M}_{Bm}\Phi_m^T\right] R_{b2g} F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L,\text{extra}} + &+ R_{b2g}\left[\tilde{M}_{Bm}\Phi_m^T\right] R_{g2b} F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L,\text{extra}} +\left[-T_I^T \right] \bar{F}_{R,\text{extra}} \nonumber \end{align} From 62ac61d4cdebc40d28215da740b5e9cf5cae53f9 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Tue, 12 Jan 2021 12:14:30 -0700 Subject: [PATCH 364/377] FlexSub: introducing GuyanLoadCorrection instead of ExtraMoment --- docs/source/user/api_change.rst | 2 +- .../subdyn/examples/OC4_Jacket_SD_Input.dat | 2 +- docs/source/user/subdyn/input_files.rst | 10 +- docs/source/user/subdyn/theory.rst | 270 ++++++++---------- modules/subdyn/src/SubDyn.f90 | 102 +++---- modules/subdyn/src/SubDyn_Registry.txt | 2 +- modules/subdyn/src/SubDyn_Types.f90 | 10 +- 7 files changed, 184 insertions(+), 214 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index 04d60d91c..c6814bd7d 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -27,7 +27,7 @@ IfW driver 7 WrHAWC false IfW driver 8 WrBladed false WrBladed - Convert all data to Bladed format? (flag) IfW driver 9 WrVTK false WrVTK - Convert all data to VTK format? (flag) InflowWind 7 VFlowAng 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) -SubDyn 8 ExtraMom False ExtraMoment - Include extra moment from lever arm at interface in interface reactions. +SubDyn 8 GuyanLoadCorr. False GuyanLoadCorection - Include extra moment from lever arm at interface and rotate FEM for floating SubDyn 15 GuyanDampMod 0 GuyanDampMod - Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix} SubDyn 16 RayleighDamp 0.001, 0.003 RayleighDamp - Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] SubDyn 17 GuyanDampSize 6 GuyanDampSize - Guyan damping matrix size (square, 6x6) [only if GuyanDampMod=2] diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index 391cba6d3..84126f2a9 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -5,7 +5,7 @@ False Echo - Echo input data to ".SD.ech" (flag) "DEFAULT" SDdeltaT - Local Integration Step. If "default", the glue-code integration step will be used. 3 IntMethod - Integration Method [1/2/3/4 = RK4/AB4/ABM4/AM2]. True SttcSolve - Solve dynamics about static equilibrium point -True ExtraMoment - Include extra moment from lever arm at interface in interface reactions. +True GuyanLoadCorrection - Include extra moment from lever arm at interface and rotate FEM for floating. -------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- 3 FEMMod - FEM switch: element model in the FEM. [1= Euler-Bernoulli(E-B) ; 2=Tapered E-B (unavailable); 3= 2-node Timoshenko; 4= 2-node tapered Timoshenko (unavailable)] 2 NDiv - Number of sub-elements per member diff --git a/docs/source/user/subdyn/input_files.rst b/docs/source/user/subdyn/input_files.rst index cdac52e42..e1cf61113 100644 --- a/docs/source/user/subdyn/input_files.rst +++ b/docs/source/user/subdyn/input_files.rst @@ -175,12 +175,14 @@ that are not considered by the C-B reduction are treated quasi-statically. This treatment helps minimize the number of retained modes needed to capture effects such as static gravity and buoyancy loads, and high-frequency loads transferred -from the turbine. +from the turbine. Recommended to set to True. -**ExtraMoment** is a flag to specify whether the extra moment due to -the lever arm from the deflection of the structure is to be added to the loads passed to SubDyn. -See section :numref:`SD_Loads` for details. +**GuyanLoadCorrection** is a flag to specify whether the extra moment due to +the lever arm from the Guyan deflection of the structure is to be added to the loads +passed to SubDyn, and, whether the FEM representation should be expressed in the rotating +frame in the floating case (the rotation is induced by the rigid body Guyan modes). +See section :numref:`SD_Loads` for details. Recommended to set to True. FEA and Craig-Bampton Parameters diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 1d69ec2c8..3e965c15f 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -334,8 +334,8 @@ The loads caused by self-weight are precomputed during initialization based on the undisplaced configuration. It is therefore assumed that the displacements will be small and that P-delta effects are small for the substructure. -The "extra" moment may be accounted for using the flag *ExtraMoment*, -see section :numref:`SD_Loads`. +The "extra" moment may be accounted for using the flag **GuyanLoadCorrection**, +see section :numref:`SD_ExtraMoment`. For a nontapered beam element, the lumped loads caused by gravity to be applied at the end nodes are as follows (in the global coordinate system): @@ -1506,9 +1506,8 @@ and :math:`M_{Bm} = M_{mB}^T`, :math:`C_{Bm} =C_{mB}^T`. - -Loads and boundary nodes ------------------------- +FEM formulation in SubDyn +------------------------- .. _TP2Interface: @@ -1705,27 +1704,35 @@ The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given + + + + .. _SD_Rotated Loads: +.. _SD_ExtraMoment: -Rotation of loads for floating -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Corrections to the baseline formulation ("GuyanLoadCorrection") +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In the floating case, the loads acting on the FEM degrees of freedom need to be rotated to the body frame. In the current implementation, this is done when evaluating :math:`F_{L}` for the time evolution of the CB degrees of freedom, and the determination of the static improvement displacements. -More details on this special case is found in section :numref:`SD_summary`. +The baseline FEM implementation needs to be corrected to account for the fact that loads are provided to SubDyn at the displaced positions, and to account for the rigid body motions in the floating case. +The corrections are activated by setting the parameter **GuyanLoadCorrection** to True. -.. _SD_ExtraMoment: +**Rotation of coordinate system for floating** + +In the floating case, the FEM formulation needs to be rotated to the body frame. This is done when **GuyanLoadCorrection** is set to True. The CB and static modes are solved in a rotating frame of reference, that follows the rigid-body rotation of the Guyan modes. More details on this special case is found in section :numref:`SD_summary`. + -Extra moment from deflection -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Additional lever arm from external loads** The external loads that are applied on the substructure are computed at the location of the deflected stucture. On the other hand, the finite element formulation expect loads to be provided relative to the undeflected position of the structure, or, if rigid body motions are present, relative to a reference undeflected position (see Figure :numref:`sd_fig_extramoment`). Nodal forces at a displaced node can be directly applied to the reference nodal position, but the mapping introduces a moment at the reference nodal position. -The parameter **ExtraMom** in the input file is used to account for this extra nodal moment occurring due to the fact that the finite element loads are expected to be expressed at a reference position and not at the displaced position. -The mapping of nodal forces is done as follows when the parameter **ExtraMom** is set to True. +The parameter **GuyanLoadCorrection** in the input file is used to account for this extra nodal moment occurring due to the fact that the finite element loads are expected to be expressed at a reference position and not at the displaced position. + +The mapping of nodal forces is done as follows when the parameter **GuyanLoadCorrection** is set to True. First, a reference undeflected position of the structure is defined, with two possible configurations whether the structure is "fixed" at the sea bed, or not. The two configurations are illustrated in Figure :numref:`sd_fig_extramoment`. .. _sd_fig_extramoment: @@ -1771,7 +1778,7 @@ where :math:`j \in [x,y,z]` and the subscript :math:`ij` in :math:`[\bar{\Phi}_R Boundary DOFs that are fixed have no displacements and thus no extra moment contribution. Boundary DOFs that are free are part of the internal DOF *L* in the implementation. The gravitational and cable forces at each node (that were computed at the initialization and stored in the constant vector :math:`F_G`) are used to obtain :math:`f_{i,g}`. It is noted that the *g*-contribution to the moment , :math:`\Delta m_i`, is not a constant and needs to be computed at each time step. -To avoid adding more notations, all the load vectors used in this document will have the additional moment implicitely included when **ExtraMom=True**. +To avoid adding more notations, all the load vectors used in this document will have the additional moment implicitely included when **GuyanLoadCorrection=True**. This applies e.g.: to :math:`F_{R,e}, F_{L,e}, F_{R,g}, F_{L,g}`, where the following replacement is implied: .. math:: @@ -1802,7 +1809,7 @@ This applies e.g.: to :math:`F_{R,e}, F_{L,e}, F_{R,g}, F_{L,g}`, where the foll \vdots\\ \end{Bmatrix} \ - \text{(ExtraMom=True)} + \text{(GuyanLoadCorrection=True)} @@ -1832,7 +1839,7 @@ For the "fixed boundary condition" case, the reference position does not corresp m_{TP,cpl} -u_{TP} \times f_{TP,cpl} \\ \end{Bmatrix} \ - \text{(ExtraMom=True and Fixed BC)} + \text{(GuyanLoadCorrection=True and Fixed BC)} The output equation :math:`y_1= -F_{TP,cpl}` is then modified to include this extra contribution. @@ -1883,9 +1890,84 @@ The case **GuyanDampMod=2**, is similar to the previous case, except that the us +.. _sim: +.. _SD_SIM: + +Static-Improvement Method +~~~~~~~~~~~~~~~~~~~~~~~~~ +To account for the effects of static gravity (member self-weight) and +buoyancy forces, one would have to include all of the structural axial +modes in the C-B reduction. This inclusion often translates into +hundreds of modes to be retained for practical problems. An alternative +method is thus promoted to reduce this limitation and speed up SubDyn. +This method is denoted as SIM, and computes two static solutions at each +time step: one based on the full system stiffness matrix and one based +on the reduced stiffness matrix. The dynamic solution then proceeds as +described in the previous sections, and at each time step the +time-varying dynamic solution is superimposed on the difference between +the two static solutions, which amounts to quasi-statically accounting +for the contribution of those modes not directly included within the +dynamic solution. + +The SIM formulation provides a correction for the displacements of the +internal nodes. The uncorrected displacements are now noted :math:`{\hat{U}}_{L}`, while +the corrected displacements are noted :math:`U_L`. The SIM correction +consists in an additional term :math:`U_L` obtained by adding the total +static deflection of all the internal +DOFs (:math:`U_{L0}`), and subtracting the static deflection associated +with C-B modes (:math:`U_{L0m}`), as cast in :eq:`SIM` : + +.. math:: :label: SIM + + U_L = \hat{U}_L + U_{L,\text{SIM}} =\hat{U}_L+ \underbrace{U_{L0} - U_{L0m}}_{U_{L,\text{SIM}}} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} + + +.. where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. + will be derived in the next paragraph. Eq. :eq:`SIM` can be rewritten as: + \begin{bmatrix} + U_R \\ + U_L + \end{bmatrix} = + \begin{bmatrix} + I & 0 & 0 & 0 \\ + \Phi_R & \Phi_m & \Phi_L & -\Phi_m + \end{bmatrix} + \begin{bmatrix} + U_R \\ + q_m \\ + q_{L0} \\ + q_{m0} + \end{bmatrix} + with: + U_{L0} = \Phi_L q_{L0}, \qquad U_{L0m} = \Phi_m q_{m0} + +where :math:`{q_{m0}}` and :math:`{q_{L0}}` are the *m* and *L* modal coefficients that are assumed to be +operating in a static fashion. These coefficients are +calculated under the C-B hypothesis that the boundary nodes are fixed. +The static displacement vectors can be calculated as follows: + + +.. math:: :label: SIM3 + + K_{LL} U_{L0} = F_{L,e} + F_{L,g} + +By pre-multiplying both sides times , Eq. :eq:`SIM3` can be +rewritten as: :math:`{\Phi_L^T K_{LL} \Phi_L q_{L0} = \Phi_L^T \left( F_{L,e} + F_{L,g} \right) = \tilde{F}_L }` or, recalling that :math:`{\Phi_L^T K_{LL} \Phi_L = \Omega_L^2}`, as: :math:`{\Omega_L^2 q_{L0} =\tilde{F}_L }`, or equivalently in terms of :math:`U_{L0}`: + +.. math:: :label: UL02 + + U_{L0} = \Phi_L \left[ \Omega_L^2 \right]^{-1} \tilde{F}_L +Similarly: + +.. math:: :label: UL0m2 + + K_{LL} U_{L0m} = F_{L,e} + F_{L,g} \quad\rightarrow \quad U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m +with :math:`\tilde{F}_m =\Phi_m^T(F_{L,e} + F_{L,g})`. +Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. +In the floating case the loads :math:`F_L` is rotated to the body coordinate system when "GuyanLoadCorrection" is True (see :numref:`SD_ExtraMoment` for more details and :numref:`SD_summary` for the final equations used). @@ -2098,7 +2180,7 @@ From the CB coordinate transformation (Eq. :eq:`CB3`), and the link between boun \bar{U}_R &= T_I U_{TP} ,\qquad - \bar{U}_L = \bar{\Phi}_R \bar{U}_R + \Phi_m q_m + \bar{U}_L = \bar{\Phi}_R \bar{U}_R + \Phi_m q_m + \boldsymbol{U_{L,SIM}} \dot{\bar{U}}_R &= T_I \dot{U}_{TP} ,\qquad @@ -2108,6 +2190,7 @@ From the CB coordinate transformation (Eq. :eq:`CB3`), and the link between boun ,\qquad \ddot{\bar{U}}_L = \bar{\Phi}_R \ddot{\bar{U}}_R + \Phi_m \ddot{q}_m +The expression for :math:`y2motions` contains the optional SIM contribution (see :numref:`SD_SIM`). Using the expression of :math:`\ddot{q}_m` from Eq. :eq:`ddotqm`, the internal accelerations are: @@ -2120,7 +2203,7 @@ Using the expression of :math:`\ddot{q}_m` from Eq. :eq:`ddotqm`, the internal a - \tilde{K}_{mm} q_m \right] -In the floating case, the Guyan part of the motion are replaced by the analytical rigid body motion (se details in section :numref:`SD_summary`). +In the floating case, the Guyan part of the motion are replaced by the analytical rigid body motion (see details in section :numref:`SD_summary`). The output equation for :math:`y_2`: can then be written as: @@ -2154,6 +2237,7 @@ where F_{Y2}& = \begin{bmatrix} 0 \\ + \boldsymbol{U_{L,\text{SIM}}} \\ 0 \\ 0 \\ 0 \\ @@ -2161,128 +2245,7 @@ where \Phi_m \Phi_m^T F_{L,g} \end{bmatrix} -The expression for :math:`F_{Y2}` will be modified by the SIM method and Eq. :eq:`bigY2sim` is used instead. - - - -.. _sim: -.. _SD_SIM: - -Static-Improvement Method -~~~~~~~~~~~~~~~~~~~~~~~~~ -To account for the effects of static gravity (member self-weight) and -buoyancy forces, one would have to include all of the structural axial -modes in the C-B reduction. This inclusion often translates into -hundreds of modes to be retained for practical problems. An alternative -method is thus promoted to reduce this limitation and speed up SubDyn. -This method is denoted as SIM, and computes two static solutions at each -time step: one based on the full system stiffness matrix and one based -on the reduced stiffness matrix. The dynamic solution then proceeds as -described in the previous sections, and at each time step the -time-varying dynamic solution is superimposed on the difference between -the two static solutions, which amounts to quasi-statically accounting -for the contribution of those modes not directly included within the -dynamic solution. - -The SIM formulation provides a correction for the displacements of the -internal nodes. The uncorrected displacements, as obtained from the -previous C-B formulation , are now noted :math:`{\hat{U}}_{L}`, while -the corrected displacements are noted :math:`_{}`. The SIM correction -consists in and adding the total static deflection of all the internal -DOFs (:math:`U_{L0}`), and subtracting the static deflection associated -with C-B modes (:math:`U_{L0m}`), as cast in :eq:`SIM` : - -.. math:: :label: SIM - - U_L = \hat{U}_L + U_{L,\text{SIM}} =\hat{U}+ \underbrace{U_{L0} - U_{L0m}}_{U_{L,\text{SIM}}} = \underbrace{\Phi_R U_R + \Phi_m q_m}_{\hat{U}_L} + \underbrace{\Phi_L q_{L0}}_{U_{L0}} - \underbrace{\Phi_m q_{m0}}_{U_{L0m}} - - -.. where the expression for :math:`U_{L0}` and :math:`U_{L0m}` will be derived in the next paragraph. - will be derived in the next paragraph. Eq. :eq:`SIM` can be rewritten as: - \begin{bmatrix} - U_R \\ - U_L - \end{bmatrix} = - \begin{bmatrix} - I & 0 & 0 & 0 \\ - \Phi_R & \Phi_m & \Phi_L & -\Phi_m - \end{bmatrix} - \begin{bmatrix} - U_R \\ - q_m \\ - q_{L0} \\ - q_{m0} - \end{bmatrix} - with: - U_{L0} = \Phi_L q_{L0}, \qquad U_{L0m} = \Phi_m q_{m0} - -where :math:`{q_{m0}}` and :math:`{q_{L0}}` are the *m* and *L* modal coefficients that are assumed to be -operating in a static fashion. These coefficients are -calculated under the C-B hypothesis that the boundary nodes are fixed. -The static displacement vectors can be calculated as follows: - - -.. math:: :label: SIM3 - - K_{LL} U_{L0} = F_{L,e} + F_{L,g} - -By pre-multiplying both sides times , Eq. :eq:`SIM3` can be -rewritten as: :math:`{\Phi_L^T K_{LL} \Phi_L q_{L0} = \Phi_L^T \left( F_{L,e} + F_{L,g} \right) = \tilde{F}_L }` or, recalling that :math:`{\Phi_L^T K_{LL} \Phi_L = \Omega_L^2}`, as: :math:`{\Omega_L^2 q_{L0} =\tilde{F}_L }`, or equivalently in terms of :math:`U_{L0}`: - -.. math:: :label: UL02 - - U_{L0} = \Phi_L \left[ \Omega_L^2 \right]^{-1} \tilde{F}_L - -Similarly: - -.. math:: :label: UL0m2 - - K_{LL} U_{L0m} = F_{L,e} + F_{L,g} \quad\rightarrow \quad U_{L0m} = \Phi_m \left[ \Omega_m^2 \right]^{-1} \tilde{F}_m - -with :math:`\tilde{F}_m =\Phi_m^T(F_{L,e} + F_{L,g})`. -Note that: :math:`{ \dot{U}_{L0} = \dot{q}_{L0} = \dot{U}_{L0m} = \dot{q}_{m0} =0 }` and :math:`{ \ddot{U}_{L0} = \ddot{q}_{L0} = \ddot{U}_{L0m} = \ddot{q}_{m0} =0 }`. - -In the floating case the loads :math:`F_L` is rotated to the body coordinate system when "ExtraMoment" is True (see :numref:`SD_summary` for more details). - -The dynamic component :math:`{ \hat{U} = \begin{bmatrix} \hat{U}_R \\ \hat{U}_R \end{bmatrix} }` is calculated following the usual procedure -described in :numref:`SSformulation` to :numref:`TimeIntegration`. For example, states are still -calculated and integrated as in Eq. :eq:`state_eq`, and the output to ElastoDyn, i.e., -the reaction provided by the substructure at the TP interface, is also -calculated as it was done previously in Eqs. :eq:`smally1` and :eq:`bigY1`. -However, the state-space formulation is slightly modified -(simply adding the contribution :math:`U_{L0}-U_{L0m}` to :math:`F_{Y2}` -when computing the outputs to HydroDyn as: - -.. math:: :label: y2sim - - y_2= \begin{bmatrix} - \bar{U}_R \\ - U_L \\ - \dot{\bar{U}}_R \\ - \dot{U}_L \\ - \ddot{\bar{U}}_R \\ - \ddot{U}_L \\ - \end{bmatrix} = \begin{bmatrix} - \bar{U}_R \\ - \hat{U}_L + \boldsymbol{U_{L,\text{SIM}}} \\ - \dot{\bar{U}}_R \\ - \dot{U}_L \\ - \ddot{\bar{U}}_R \\ - \ddot{U}_L \\ - \end{bmatrix} - -The array :math:`F_{Y2}` from Eq. :eq:`bigY2` is now defined as follows: - -.. math:: :label: bigY2sim - F_{Y2} &= \begin{bmatrix} - 0 \\ - \boldsymbol{U_{L,\text{SIM}}} \\ - 0 \\ - 0 \\ - 0 \\ - \Phi_m \Phi_m^T F_{L,g} - \end{bmatrix} @@ -2461,16 +2424,16 @@ State equation - \tilde{K}_{mm} q_m \end{align} -Note: :math:`F_L` contains the "extra moment" if user-requested. +Note: :math:`F_L` contains the "extra moment" if user-requested with **GuyanLoadCorrection**. -**Floating case without "Extra Moment"** +**Floating case without "GuyanLoadCorrection"** .. math:: :nowrap: \begin{align} \ddot{q}_m = \Phi_m^T F_L - - \tilde{M}_{mB} R_{g2b} \ddot{U}_{TP} + - \tilde{M}_{mB} \ddot{U}_{TP} - \tilde{C}_{mm} \dot{q}_m - \tilde{K}_{mm} q_m \end{align} @@ -2478,7 +2441,7 @@ Note: :math:`F_L` contains the "extra moment" if user-requested. Notes: :math:`F_L` *does not* contain the "extra moment". -**Floating case with "Extra Moment"** +**Floating case with "GuyanLoadCorrection"** .. math:: :nowrap: @@ -2526,29 +2489,29 @@ If this is the case, the following additional term is added to the moment part o -**Floating case without "Extra moment"** +**Floating case without "GuyanLoadCorrection"** .. math:: :nowrap: \begin{align} -Y_1 =F_{TP,cpl} =& - R_{b2g}\left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m - + R_{b2g}\left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m + \left[ - \tilde{M}_{Bm}\tilde{K}_{mm} \right] q_m + + \left[- \tilde{M}_{Bm}\tilde{C}_{mm} \right] \dot{q}_m \\ &+\left[\tilde{K}_{BB} \right] U_{TP} +\left[\tilde{C}_{BB} \right] \dot{U}_{TP} +\left[\tilde{M}_{BB} -\tilde{M}_{Bm} \tilde{M}_{mB} \right] \ddot{U}_{TP} \nonumber \\ - &+ R_{b2g}\left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} + &+ \left[\tilde{M}_{Bm}\Phi_m^T\right] F_L +\left[- T_I^T \bar{\Phi}_R^T \right] F_{L} +\left[-T_I^T \right] \bar{F}_R \nonumber \end{align} -Notes: 1) :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment"; -2) The rotation :math:`R_{b2g}\tilde{M}_{Bm} \tilde{M}_{mB}R_{g2b}` is not carried out since it introduced stability issues. +Note: :math:`F_L` and :math:`\bar{F}_R` *do not* contain the "extra moment". -**Floating case with "Extra moment"** + +**Floating case with "GuyanLoadCorrection"** .. math:: :nowrap: @@ -2593,8 +2556,7 @@ Output: nodal motions - \tilde{K}_{mm} q_m \right] -Note: :math:`F_L` contains the "extra moment" if user-requested. - +Note: :math:`F_L` contains the "extra moment" if user-requested with **GuyanLoadCorrection**. @@ -2617,7 +2579,7 @@ Note: :math:`F_L` contains the "extra moment" if user-requested. - \tilde{C}_{mm} \dot{q}_m - \tilde{K}_{mm} q_m \right] -where: 1) :math:`F_L` does not contain the extra moment, 2) the operator :math:`R_{g2b}` is only used on :math:`F_L` if ExtraMoment is True, 3) the elastic displacements were set to 0 for stability purposes (assuming that these are small) 4) the Guyan motion is computed using the exact rigid body motions. For a given node :math:`P`, located at the position :math:`r_{IP,0}` from the interface in the undisplaced configuration, the position (from the interface point), displacement, translational velocity and acceleration due to the rigid body motion are: +where: 1) :math:`F_L` does not contain the extra moment, 2) the operators :math:`R_{g2b}` and :math:`R_{b2g}` are when GuyanLoadCorrection is True, 3) the elastic displacements were set to 0 for stability purposes (assuming that these are small) 4) the Guyan motion is computed using the exact rigid body motions. For a given node :math:`P`, located at the position :math:`r_{IP,0}` from the interface in the undisplaced configuration, the position (from the interface point), displacement, translational velocity and acceleration due to the rigid body motion are: .. math:: diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index ccb434472..1c545885b 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -268,11 +268,11 @@ SUBROUTINE SD_Init( InitInput, u, p, x, xd, z, OtherState, y, m, Interval, InitO ! Nodes into (I,C,L,R): I=Interface ,C=Boundary (bottom), R=(I+C), L=Interior ! DOFs into (B,F,L): B=Leader (i.e. Rbar) ,F=Fixed, L=Interior call PartitionDOFNodes(Init, m, p, ErrStat2, ErrMsg2) ; if(Failed()) return - if (p%ExtraMoment) then + if (p%GuyanLoadCorrection) then if (p%Floating) then - call WrScr(' Extra moment and rotated CB-frame will be used (floating case detected)') + call WrScr(' Guyan extra moment and rotated CB-frame will be used (floating case detected)') else - call WrScr(' Extra moment will be included in loads (fixed-bottom case detected)') + call WrScr(' Guyan extra moment will be included in loads (fixed-bottom case detected)') endif endif @@ -418,7 +418,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) REAL(ReKi) :: Y1_Guy_R(6) REAL(ReKi) :: Y1_Guy_L(6) REAL(ReKi) :: Y1_Utp(6) - REAL(ReKi) :: Y1_ExtraMoment(3) ! Lever arm moment contributions due to interface displacement + REAL(ReKi) :: Y1_GuyanLoadCorrection(3) ! Lever arm moment contributions due to interface displacement REAL(ReKi) :: udotdot_TP(6) INTEGER(IntKi), pointer :: DOFList(:) REAL(ReKi) :: DCM(3,3) @@ -457,7 +457,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Output 2, Y2Mesh: motions on all FEM nodes (R, and L DOFs, then full DOF vector) ! -------------------------------------------------------------------------------- ! External force on internal nodes (F_L) - call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, GuyanLoadCorrection=(p%GuyanLoadCorrection.and..not.p%Floating), RotateLoads=(p%GuyanLoadCorrection.and.p%Floating)); if(Failed()) return m%UR_bar = 0.0_ReKi m%UR_bar_dot = 0.0_ReKi m%UR_bar_dotdot = 0.0_ReKi @@ -466,7 +466,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%UL_dotdot = 0.0_ReKi ! --- CB modes contribution to motion (L-DOF only) if ( p%nDOFM > 0) then - if (p%Floating) then ! >>> Rotate All + if (p%GuyanLoadCorrection.and.p%Floating) then ! >>> Rotate All udotdot_TP(1:3) = matmul(Rg2b, u%TPMesh%TranslationAcc( :,1)) udotdot_TP(4:6) = matmul(Rg2b, u%TPMesh%RotationAcc(:,1) ) else @@ -544,18 +544,21 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) aP(1:3) = u%TPMesh%TranslationAcc(1:3,1) + cross_product(OmD, rIP) + cross_product(Om, Om_X_r) ! Full displacements CB-rotated + Guyan (KEEP ME) >>> Rotate All - m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) - m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) - m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) - m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) - m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) - m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) - !m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) - !m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) - !m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) - !m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) - !m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) - !m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + if (p%GuyanLoadCorrection) then + m%U_full (DOFList(1:3)) = matmul(Rb2g, m%U_full (DOFList(1:3))) + duP(1:3) + m%U_full (DOFList(4:6)) = matmul(Rb2g, m%U_full (DOFList(4:6))) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = matmul(Rb2g, m%U_full_dot (DOFList(1:3))) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = matmul(Rb2g, m%U_full_dot (DOFList(4:6))) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = matmul(Rb2g, m%U_full_dotdot(DOFList(1:3))) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = matmul(Rb2g, m%U_full_dotdot(DOFList(4:6))) + OmD(1:3) + else + m%U_full (DOFList(1:3)) = m%U_full (DOFList(1:3)) + duP(1:3) + m%U_full (DOFList(4:6)) = m%U_full (DOFList(4:6)) + rotations(1:3) + m%U_full_dot (DOFList(1:3)) = m%U_full_dot (DOFList(1:3)) + vP(1:3) + m%U_full_dot (DOFList(4:6)) = m%U_full_dot (DOFList(4:6)) + Om(1:3) + m%U_full_dotdot(DOFList(1:3)) = m%U_full_dotdot(DOFList(1:3)) + aP(1:3) + m%U_full_dotdot(DOFList(4:6)) = m%U_full_dotdot(DOFList(4:6)) + OmD(1:3) + endif ! NOTE: For now, displacements passed to HydroDyn are Guyan only! ! Construct the direction cosine matrix given the output angles @@ -591,12 +594,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! --- Outputs 1, Y1=-F_TP, reaction force from SubDyn to ElastoDyn (stored in y%Y1Mesh) ! -------------------------------------------------------------------------------- ! --- Special case for floating with extramoment - if (p%ExtraMoment.and.p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses rotated loads endif ! Compute external force on internal (F_L) and interface nodes (F_I) - call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment), RotateLoads=.False.); if(Failed()) return + call GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, GuyanLoadCorrection=(p%GuyanLoadCorrection), RotateLoads=.False.); if(Failed()) return call GetExtForceOnInterfaceDOF(p, m%Fext, F_I) ! Compute reaction/coupling force at TP @@ -614,7 +617,7 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif if ( p%nDOFM > 0) then Y1_CB = -( matmul(p%C1_11, x%qm) + matmul(p%C1_12, x%qmdot) ) - if (p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then Y1_CB = matmul(RRb2g, Y1_CB) !>>> Rotate All endif else @@ -622,10 +625,10 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) endif Y1_Guy_R = matmul( F_I, p%TI ) Y1_Guy_L = - matmul(p%D1_142, m%F_L) ! non rotated loads - if (.not.(p%ExtraMoment.and.p%Floating)) then + if (.not.(p%GuyanLoadCorrection.and.p%Floating)) then Y1_CB_L = - (matmul(p%D1_141, m%F_L)) ! Uses non rotated loads endif - if (p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then Y1_CB_L = matmul(RRb2g, Y1_CB_L) !>>> Rotate All endif @@ -642,12 +645,12 @@ SUBROUTINE SD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Computing extra moments due to lever arm introduced by interface displacement ! Y1_MExtra = - MExtra = -u_TP x Y1(1:3) ! NOTE: double cancellation of signs - if (p%ExtraMoment) then + if (p%GuyanLoadCorrection) then if (.not.p%floating) then ! if Fixed, transfer from non deflected TP to u_TP - Y1_ExtraMoment(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) - Y1_ExtraMoment(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) - Y1_ExtraMoment(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) - Y1(4:6) = Y1(4:6) + Y1_ExtraMoment + Y1_GuyanLoadCorrection(1) = - m%u_TP(2) * Y1(3) + m%u_TP(3) * Y1(2) + Y1_GuyanLoadCorrection(2) = - m%u_TP(3) * Y1(1) + m%u_TP(1) * Y1(3) + Y1_GuyanLoadCorrection(3) = - m%u_TP(1) * Y1(2) + m%u_TP(2) * Y1(1) + Y1(4:6) = Y1(4:6) + Y1_GuyanLoadCorrection endif endif ! values on the interface mesh are Y1 (SubDyn forces) + Hydrodynamic forces @@ -742,10 +745,10 @@ SUBROUTINE SD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta IF ( p%nDOFM == 0 ) RETURN ! Compute F_L, force on internal DOF - CALL GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u, p, x, m, m%F_L, ErrStat2, ErrMsg2, GuyanLoadCorrection=(p%GuyanLoadCorrection.and..not.p%Floating), RotateLoads=(p%GuyanLoadCorrection.and.p%Floating)) udotdot_TP = (/u%TPMesh%TranslationAcc(:,1), u%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then ! >>> Rotate All - udotdot_TP to body coordinates udotdot_TP(1:3) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(1:3) ) udotdot_TP(4:6) = matmul( u%TPMesh%Orientation(:,:,1), udotdot_TP(4:6) ) @@ -854,15 +857,15 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif IF (Check(.not.(any(idSIM_Valid==p%SttcSolve)), 'Invalid value entered for SttcSolve')) return -! ExtraMoment - For legacy, allowing this line to be a comment -CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'ExtraMoment', 'Add extra lever arm contribution to interface loads', ErrStat2, ErrMsg2, UnEc); if(Failed()) return +! GuyanLoadCorrection - For legacy, allowing this line to be a comment +CALL ReadVar (UnIn, SDInputFile, Dummy_Str, 'GuyanLoadCorrection', 'Add extra lever arm contribution to interface loads', ErrStat2, ErrMsg2, UnEc); if(Failed()) return if (is_logical(Dummy_Str, Dummy_Bool)) then ! the parameter was present - p%ExtraMoment=Dummy_Bool + p%GuyanLoadCorrection=Dummy_Bool ! We still need to read the comment on the next line CALL ReadCom ( UnIn, SDInputFile, ' FEA and CRAIG-BAMPTON PARAMETERS ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return else ! we have a actually read a comment line, we do nothing. call LegacyWarning('ExtraMom line missing from input file. Assuming no extra moment.') - p%ExtraMoment=.False. ! For Legacy, ExtraMoment is False + p%GuyanLoadCorrection=.False. ! For Legacy, GuyanLoadCorrection is False endif !-------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- @@ -1740,9 +1743,9 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg !Start by getting u_n and u_n+1 ! interpolate u to find u_interp = u(t) = u_n CALL SD_Input_ExtrapInterp( u, utimes, u_interp, t, ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - CALL GetExtForceOnInternalDOF(u_interp, p, x, m, m%F_L, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u_interp, p, x, m, m%F_L, ErrStat2, ErrMsg2, GuyanLoadCorrection=(p%GuyanLoadCorrection.and..not.p%Floating), RotateLoads=(p%GuyanLoadCorrection.and.p%Floating)) m%udotdot_TP = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then ! >>> Rotate All - udotdot_TP to body coordinates m%udotdot_TP(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(1:3)) m%udotdot_TP(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), m%udotdot_TP(4:6)) @@ -1750,9 +1753,9 @@ SUBROUTINE SD_AM2( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ! extrapolate u to find u_interp = u(t + dt)=u_n+1 CALL SD_Input_ExtrapInterp(u, utimes, u_interp, t+p%SDDeltaT, ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,'SD_AM2') - CALL GetExtForceOnInternalDOF(u_interp, p, x, m, F_L2, ErrStat2, ErrMsg2, ExtraMoment=(p%ExtraMoment.and..not.p%Floating), RotateLoads=(p%ExtraMoment.and.p%Floating)) + CALL GetExtForceOnInternalDOF(u_interp, p, x, m, F_L2, ErrStat2, ErrMsg2, GuyanLoadCorrection=(p%GuyanLoadCorrection.and..not.p%Floating), RotateLoads=(p%GuyanLoadCorrection.and.p%Floating)) udotdot_TP2 = (/u_interp%TPMesh%TranslationAcc(:,1), u_interp%TPMesh%RotationAcc(:,1)/) - if (p%Floating) then + if (p%GuyanLoadCorrection.and.p%Floating) then ! >>> Rotate All - udotdot_TP to body coordinates udotdot_TP2(1:3) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(1:3)) udotdot_TP2(4:6) = matmul(u_interp%TPMesh%Orientation(:,:,1), udotdot_TP2(4:6)) @@ -2966,11 +2969,14 @@ SUBROUTINE LeverArm(u, p, x, m, DU_full, bGuyan, bElastic, U_full) rIP0(1:3) = p%DP0(1:3, iSDNode) rIP(1:3) = matmul(Rb2g, rIP0) duP(1:3) = rIP - rIP0 ! NOTE: without m%u_TP(1:3) - !DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) + duP(1:3) - !DU_full(DOFList(4:6)) = DU_full(DOFList(4:6)) + rotations(1:3) ! Full diplacements Guyan + rotated CB (if asked) >>> Rotate All - DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) - DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) + if (p%GuyanLoadCorrection) then + DU_full(DOFList(1:3)) = matmul(Rb2g, DU_full(DOFList(1:3))) + duP(1:3) + DU_full(DOFList(4:6)) = matmul(Rb2g, DU_full(DOFList(4:6))) + rotations(1:3) + else + DU_full(DOFList(1:3)) = DU_full(DOFList(1:3)) + duP(1:3) + DU_full(DOFList(4:6)) = DU_full(DOFList(4:6)) + rotations(1:3) + endif enddo endif endif ! U_full no provided @@ -2980,12 +2986,12 @@ END SUBROUTINE LeverArm !> Construct force vector on internal DOF (L) from the values on the input mesh !! First, the full vector of external forces is built on the non-reduced DOF !! Then, the vector is reduced using the Tred matrix -SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMoment, RotateLoads, U_full) +SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, GuyanLoadCorrection, RotateLoads, U_full) type(SD_InputType), intent(in ) :: u ! Inputs type(SD_ParameterType), intent(in ) :: p ! Parameters type(SD_ContinuousStateType), intent(in ) :: x !< Continuous states at t type(SD_MiscVarType), intent(inout) :: m ! Misc, for storage optimization of Fext and Fext_red - logical , intent(in ) :: ExtraMoment ! If true add extra moment + logical , intent(in ) :: GuyanLoadCorrection ! If true add extra moment logical , intent(in ) :: RotateLoads ! If true, loads are rotated to body coordinate real(Reki), optional, intent(in ) :: U_full(:) ! DOF displacements (Guyan + CB) real(ReKi) , intent(out) :: F_L(p%nDOF__L) !< External force on internal nodes "L" @@ -3009,7 +3015,7 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen ! real(ReKi), parameter :: myNaN = -9999998.989_ReKi - if (ExtraMoment) then + if (GuyanLoadCorrection) then ! Compute node displacements "DU_full" for lever arm call LeverArm(u, p, x, m, m%DU_full, bGuyan=.True., bElastic=.False., U_full=U_full) endif @@ -3063,7 +3069,7 @@ SUBROUTINE GetExtForceOnInternalDOF(u, p, x, m, F_L, ErrStat, ErrMsg, ExtraMomen endif ! Extra moment dm = Delta u x (fe + fg) - if (ExtraMoment) then + if (GuyanLoadCorrection) then du = m%DU_full(p%NodesDOF(iNode)%List(1:3)) ! Lever arm Moment(1) = Moment(1) + du(2) * Force(3) - du(3) * Force(2) Moment(2) = Moment(2) + du(3) * Force(1) - du(1) * Force(3) @@ -3580,7 +3586,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) if (nCB>0) then CC(1:nY,1:nCB ) = - p%C1_11 CC(1:nY,nCB+1:nX) = - p%C1_12 - if (p%Floating .and. present(u)) then + if (p%GuyanLoadCorrection .and. p%Floating .and. present(u)) then CC(1:3,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(1:3,:)) ! >>> Rotate All CC(4:6,:) = matmul(transpose(u%TPMesh%Orientation(:,:,1)), CC(4:6,:)) ! >>> Rotate All endif @@ -3596,7 +3602,7 @@ SUBROUTINE StateMatrices(p, ErrStat, ErrMsg, AA, BB, CC, DD, u) DD(1:nY,7:12 ) = - p%CBB DD(1:nY,13:18 ) = - p%MBB if (p%nDOFM>0) then - if (p%Floating .and. present(u)) then + if (p%GuyanLoadCorrection .and. p%Floating .and. present(u)) then ! TODO TODO rotate it A MBmmB A^t !DD(1:3,:) = DD(1:3,:) + matmul(transpose(u%TPMesh%Orientation(:,:,1)), p%MBmmB(1:3,:) ! >>> Rotate All DD(1:nY,13:18 ) = DD(1:nY,13:18 )+ p%MBmmB diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 49c3a201d..d8d458ca5 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -186,7 +186,7 @@ typedef ^ ParameterType IntKi CtrlElem2Channel {:}{:} - - "nCtrlCable x # --- Parameters - CB reduction typedef ^ ParameterType IntKi nDOFM - - - "retained degrees of freedom (modes)" typedef ^ ParameterType IntKi SttcSolve - - - "Solve dynamics about static equilibrium point (flag)" -typedef ^ ParameterType Logical ExtraMoment - - - "Add Extra lever arm contribution to interface reaction outputs" +typedef ^ ParameterType Logical GuyanLoadCorrection - - - "Add Extra lever arm contribution to interface reaction outputs" typedef ^ ParameterType Logical Floating - - - "True if floating bottom (the 6 DOF are free at all reaction nodes)" typedef ^ ParameterType ReKi KMMDiag {:} - - "Diagonal coefficients of Kmm (OmegaM squared)" typedef ^ ParameterType ReKi CMMDiag {:} - - "Diagonal coefficients of Cmm (~2 Zeta OmegaM))" diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index a7162c816..6a0d60bda 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -233,7 +233,7 @@ MODULE SubDyn_Types INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: CtrlElem2Channel !< nCtrlCable x 2, for each CtrlCable, Elem index, and Channel Index [-] INTEGER(IntKi) :: nDOFM !< retained degrees of freedom (modes) [-] INTEGER(IntKi) :: SttcSolve !< Solve dynamics about static equilibrium point (flag) [-] - LOGICAL :: ExtraMoment !< Add Extra lever arm contribution to interface reaction outputs [-] + LOGICAL :: GuyanLoadCorrection !< Add Extra lever arm contribution to interface reaction outputs [-] LOGICAL :: Floating !< True if floating bottom (the 6 DOF are free at all reaction nodes) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: KMMDiag !< Diagonal coefficients of Kmm (OmegaM squared) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CMMDiag !< Diagonal coefficients of Cmm (~2 Zeta OmegaM)) [-] @@ -7087,7 +7087,7 @@ SUBROUTINE SD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) ENDIF DstParamData%nDOFM = SrcParamData%nDOFM DstParamData%SttcSolve = SrcParamData%SttcSolve - DstParamData%ExtraMoment = SrcParamData%ExtraMoment + DstParamData%GuyanLoadCorrection = SrcParamData%GuyanLoadCorrection DstParamData%Floating = SrcParamData%Floating IF (ALLOCATED(SrcParamData%KMMDiag)) THEN i1_l = LBOUND(SrcParamData%KMMDiag,1) @@ -8116,7 +8116,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si END IF Int_BufSz = Int_BufSz + 1 ! nDOFM Int_BufSz = Int_BufSz + 1 ! SttcSolve - Int_BufSz = Int_BufSz + 1 ! ExtraMoment + Int_BufSz = Int_BufSz + 1 ! GuyanLoadCorrection Int_BufSz = Int_BufSz + 1 ! Floating Int_BufSz = Int_BufSz + 1 ! KMMDiag allocated yes/no IF ( ALLOCATED(InData%KMMDiag) ) THEN @@ -8778,7 +8778,7 @@ SUBROUTINE SD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%SttcSolve Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%ExtraMoment, IntKiBuf(1)) + IntKiBuf(Int_Xferred) = TRANSFER(InData%GuyanLoadCorrection, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%Floating, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 @@ -10191,7 +10191,7 @@ SUBROUTINE SD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg Int_Xferred = Int_Xferred + 1 OutData%SttcSolve = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%ExtraMoment = TRANSFER(IntKiBuf(Int_Xferred), OutData%ExtraMoment) + OutData%GuyanLoadCorrection = TRANSFER(IntKiBuf(Int_Xferred), OutData%GuyanLoadCorrection) Int_Xferred = Int_Xferred + 1 OutData%Floating = TRANSFER(IntKiBuf(Int_Xferred), OutData%Floating) Int_Xferred = Int_Xferred + 1 From fdb92d72b3496d64a95c1c3762e1a5f012bbd7fb Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 12 Jan 2021 19:15:26 -0700 Subject: [PATCH 365/377] [BugFix] TCF_mods: end nodes of Morison members were double counted. The length used for the force loads using the LumpDistrHydroLoads routine was incorrect for the end elements. This should have been calculated according to the table in the implementation plan (page 18), but the wrong variable was passed. The correct value was calculated, just not passed. This can be confirmed by comparing the HydroFxi term for a simple cylinder undergoing surge translational acceleration (only this DOF) with the driver. Increasing the discretization of the members would converge towards the correct answer (well, what we expect from v2.4 with commit 22f41618 to enable the driver to run this case). --- modules/hydrodyn/src/Morison.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index f43799631..3adc3172d 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2973,8 +2973,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) f_hydro = mem%Cd(i)*p%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & 0.5*mem%AxCd(i)*p%WtrDens*pi*mem%RMG(i)*dRdl_p * matmul( dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )*mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) -! call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_D(:, mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_D(:, i) ) +! call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%F_D(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_D(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(4:6, i) @@ -2982,8 +2982,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ Am = mem%Ca(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) - !call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_A(:, mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_A(:, i) ) + !call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%F_A(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_A(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(4:6, i) @@ -2991,8 +2991,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & 2.0*mem%AxCa(i)*p%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k - !call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%F_I(:, mem%NodeIndx(i)) ) - call LumpDistrHydroLoads( f_hydro, mem%k, mem%dl, h_c, m%memberLoads(im)%F_I(:, i) ) + !call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%F_I(:, mem%NodeIndx(i)) ) + call LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_I(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(4:6, i) end if From b080f68e268a70d49eeeb52be2bd52c63b1f541a Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 13 Jan 2021 16:47:26 -0700 Subject: [PATCH 366/377] Update r-test pointer (minor HD input file updates) --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index c3f583792..1703d4634 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit c3f5837920bbe491f3dc69713aff972d5bf8ad79 +Subproject commit 1703d4634d530198168e4b3938c264e4e1bf46f0 From 7b3107e5b2472120955df3888b806511fe6e4562 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 15 Jan 2021 18:13:40 -0700 Subject: [PATCH 367/377] [BugFix] Normal to ends of members that had joints swapped was incorrect --- modules/hydrodyn/src/Morison.f90 | 15 ++++++++++----- modules/hydrodyn/src/Morison.txt | 1 + modules/hydrodyn/src/Morison_Types.f90 | 7 +++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 3adc3172d..ba38e93f9 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -850,10 +850,10 @@ SUBROUTINE WriteSummaryFile( UnSum, g, MSL2SWL, WtrDpth, numJoints, numNodes, no AxCp2 = members(i)%AxCp(N+1) JAxCd1 = nodes(members(i)%NodeIndx(1 ))%JAxCd - JAxCd2 = nodes(members(i)%NodeIndx(1+N))%JAxCa - JAxCa1 = nodes(members(i)%NodeIndx(1 ))%JAxCp - JAxCa2 = nodes(members(i)%NodeIndx(1+N))%JAxCd - JAxCp1 = nodes(members(i)%NodeIndx(1 ))%JAxCa + JAxCd2 = nodes(members(i)%NodeIndx(1+N))%JAxCd + JAxCa1 = nodes(members(i)%NodeIndx(1 ))%JAxCa + JAxCa2 = nodes(members(i)%NodeIndx(1+N))%JAxCa + JAxCp1 = nodes(members(i)%NodeIndx(1 ))%JAxCp JAxCp2 = nodes(members(i)%NodeIndx(1+N))%JAxCp @@ -1374,6 +1374,8 @@ subroutine FlipMemberNodeData( member, nodes, doSwap, errStat, errMsg ) doSwap = .TRUE. ! Z1 > Z2 END IF + ! If we swap the the nodes, we need know this later when calculating the normal vector to the ends + member%Flipped = doSwap IF ( doSwap ) THEN member%NodeIndx(1) = j2 member%NodeIndx(numMemNodes) = j1 @@ -2049,7 +2051,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In MemberEndIndx = 1 ELSE ! set up for end node N+1 - !TODO: I am not sure about the negative sign, is %ConnectionList(J) ever negative valued? + ! NOTE: %ConnectionList(J) is negative valued if InitInp%Morison%InpMembers(I)%MJointID2 == InitInp%Morison%InpJoints(J)%JointID. See HydroDynInput_ProcessInitData, members section member = p%Members(-InitInp%InpJoints(I)%ConnectionList(J)) MemberEndIndx = member%NElements + 1 END IF @@ -2062,6 +2064,9 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ELSE sgn = 1.0 ! Local coord sys points out of member at ending node, so leave sign of local z vector END IF + + ! Account for reordering of what the original node for the end was -- This affects the sign of the An term which can pose a problem for members crossing the waterline + if (member%Flipped) sgn = -1.0 * sgn ! Compute the signed quantities for this member end (for drag regardless of PropPot value), and add them to the joint values An_drag = An_drag + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 1f717cdc7..2837ece0b 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -145,6 +145,7 @@ typedef ^ ^ INTEGER typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - +typedef ^ ^ LOGICAL Flipped - - - "Was the member flipped in a reordering event? Need to know this to get the correct normal vector to the ends" - # typedef ^ Morison_MemberLoads ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index dd5fc4259..57addb8d5 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -190,6 +190,7 @@ MODULE Morison_Types REAL(ReKi) :: FillFSLoc !< Z-location of the filled free-surface [m] REAL(ReKi) :: FillDens !< Filled fluid density [kg/m^3] LOGICAL :: PropPot !< Is this element/member modeled with potential flow theory T/F [-] + LOGICAL :: Flipped !< Was the member flipped in a reordering event? Need to know this to get the correct normal vector to the ends [-] END TYPE Morison_MemberType ! ======================= ! ========= Morison_MemberLoads ======= @@ -2238,6 +2239,7 @@ SUBROUTINE Morison_CopyMemberType( SrcMemberTypeData, DstMemberTypeData, CtrlCod DstMemberTypeData%FillFSLoc = SrcMemberTypeData%FillFSLoc DstMemberTypeData%FillDens = SrcMemberTypeData%FillDens DstMemberTypeData%PropPot = SrcMemberTypeData%PropPot + DstMemberTypeData%Flipped = SrcMemberTypeData%Flipped END SUBROUTINE Morison_CopyMemberType SUBROUTINE Morison_DestroyMemberType( MemberTypeData, ErrStat, ErrMsg ) @@ -2609,6 +2611,7 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_BufSz = Re_BufSz + 1 ! FillFSLoc Re_BufSz = Re_BufSz + 1 ! FillDens Int_BufSz = Int_BufSz + 1 ! PropPot + Int_BufSz = Int_BufSz + 1 ! Flipped IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -3255,6 +3258,8 @@ SUBROUTINE Morison_PackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Re_Xferred = Re_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%PropPot, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Flipped, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_PackMemberType SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -4025,6 +4030,8 @@ SUBROUTINE Morison_UnPackMemberType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Re_Xferred = Re_Xferred + 1 OutData%PropPot = TRANSFER(IntKiBuf(Int_Xferred), OutData%PropPot) Int_Xferred = Int_Xferred + 1 + OutData%Flipped = TRANSFER(IntKiBuf(Int_Xferred), OutData%Flipped) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE Morison_UnPackMemberType SUBROUTINE Morison_CopyMemberLoads( SrcMemberLoadsData, DstMemberLoadsData, CtrlCode, ErrStat, ErrMsg ) From 0f47d820b5a615b7b05a798d886e5e943489af2c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 22 Jan 2021 13:52:20 -0700 Subject: [PATCH 368/377] TCF_mods2: docs format issue in SD/theory --- docs/source/user/subdyn/theory.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 3e965c15f..9ce6b69c1 100644 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -1,11 +1,11 @@ .. _subdyn-theory: SubDyn Theory -============== +============= Overview ------------------- +-------- This section focuses on the theory behind the SubDyn module. @@ -1712,7 +1712,7 @@ The Guyan TP force, :math:`\tilde{F}_{TP}`, and the CB force, :math:`F_m`, given .. _SD_ExtraMoment: Corrections to the baseline formulation ("GuyanLoadCorrection") -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The baseline FEM implementation needs to be corrected to account for the fact that loads are provided to SubDyn at the displaced positions, and to account for the rigid body motions in the floating case. The corrections are activated by setting the parameter **GuyanLoadCorrection** to True. From 3f63be78a135b728cfa615a358eefda799e473f7 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 26 Jan 2021 08:36:29 -0700 Subject: [PATCH 369/377] Merge dev into TCF_mods2: manual merge of commit 0336f3faa HD Morison: update interpolation routine for better performance --- modules/hydrodyn/src/Morison.f90 | 92 ++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index ba38e93f9..b98fec719 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -2440,7 +2440,79 @@ SUBROUTINE Morison_UpdateStates( Time, u, p, x, xd, z, OtherState, m, errStat, e END SUBROUTINE Morison_UpdateStates +!> This routine is similar to InterpWrappedStpReal, except it returns only the slope for the interpolation. +!! By returning the slope based on Time, we don't have to calculate this for every variable (Yary) we want to interpolate. +!! NOTE: p%WaveTime (and most arrays here) start with index of 0 instead of 1, so we will subtract 1 from "normal" interpolation +!! schemes. +FUNCTION GetInterpolationSlope(Time, p, m, IntWrapIndx) RESULT( InterpSlope ) + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(Morison_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(Morison_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables + INTEGER, OPTIONAL, INTENT( OUT) :: IntWrapIndx + + REAL(SiKi) :: Time_SiKi + REAL(SiKi) :: TimeMod + REAL(ReKi) :: InterpSlope + + Time_SiKi = REAL(Time, SiKi) + TimeMod = MOD(Time_SiKi, p%WaveTime(p%NStepWave)) !p%WaveTime starts at index 0, so it has p%NStepWave+1 elements + IF ( TimeMod <= p%WaveTime(1) ) THEN !second element + m%LastIndWave = 0 + END IF + + IF ( TimeMod <= p%WaveTime(0) ) THEN + m%LastIndWave = 0 + InterpSlope = 0.0_ReKi ! returns values at m%LastIndWave + IF(PRESENT(IntWrapIndx)) IntWrapIndx = 0 + ELSE IF ( TimeMod >= p%WaveTime(p%NStepWave) ) THEN + m%LastIndWave = p%NStepWave-1 + InterpSlope = 1.0_ReKi ! returns values at p%NStepWave + IF(PRESENT(IntWrapIndx)) IntWrapIndx = p%NStepWave + ELSE + m%LastIndWave = MAX( MIN( m%LastIndWave, p%NStepWave-1 ), 0 ) + + DO + + IF ( TimeMod < p%WaveTime(m%LastIndWave) ) THEN + + m%LastIndWave = m%LastIndWave - 1 + + ELSE IF ( TimeMod >= p%WaveTime(m%LastIndWave+1) ) THEN + + m%LastIndWave = m%LastIndWave + 1 + + ELSE + IF(PRESENT(IntWrapIndx)) IntWrapIndx = m%LastIndWave + + InterpSlope = ( TimeMod - p%WaveTime(m%LastIndWave) )/( p%WaveTime(m%LastIndWave+1) - p%WaveTime(m%LastIndWave) ) + RETURN ! stop checking DO loop + END IF + + END DO + + END IF + +END FUNCTION GetInterpolationSlope +!> Use in conjunction with GetInterpolationSlope, to replace InterpWrappedStpReal here. +FUNCTION InterpolateWithSlope(InterpSlope, Ind, YAry) + REAL(ReKi), INTENT(IN) :: InterpSlope + INTEGER(IntKi), INTENT(IN ) :: Ind !< Misc/optimization variables + REAL(SiKi), INTENT(IN) :: YAry(0:) + REAL(ReKi) :: InterpolateWithSlope + InterpolateWithSlope = ( YAry(Ind+1) - YAry(Ind) )*InterpSlope + YAry(Ind) + +END FUNCTION InterpolateWithSlope +!> Use in conjunction with GetInterpolationSlope, to replace InterpWrappedStpReal here. +FUNCTION InterpolateWithSlopeR(InterpSlope, Ind, YAry) + REAL(ReKi), INTENT(IN) :: InterpSlope + INTEGER(IntKi), INTENT(IN ) :: Ind !< Misc/optimization variables + REAL(ReKi), INTENT(IN) :: YAry(0:) + REAL(ReKi) :: InterpolateWithSlopeR + + InterpolateWithSlopeR = ( YAry(Ind+1) - YAry(Ind) )*InterpSlope + YAry(Ind) + +END FUNCTION InterpolateWithSlopeR !---------------------------------------------------------------------------------------------------------------------------------- !> Routine for computing outputs, used in both loose and tight coupling. SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) @@ -2465,7 +2537,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, CHARACTER(errMsgLen) :: errMsg2 ! Error message if errStat2 /= ErrID_None REAL(ReKi) :: F_DP(6), kvec(3), v(3), vf(3), vrel(3), vmag - INTEGER :: I, J, K, nodeIndx + INTEGER :: I, J, K, nodeIndx, IntWrapIndx REAL(ReKi) :: AllOuts(MaxMrsnOutputs) REAL(ReKi) :: qdotdot(6) ,qdotdot2(3) ! The structural acceleration of a mesh node !REAL(ReKi) :: accel_fluid(6) ! Acceleration of fluid at the mesh node @@ -2476,7 +2548,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, REAL(ReKi) :: D_AM_M(6,6) REAL(ReKi) :: nodeInWater REAL(ReKi) :: D_dragConst ! The distributed drag factor - + REAL(ReKi) :: InterpolationSlope + + TYPE(Morison_MemberType) :: mem ! the current member INTEGER :: N ! Number of elements within a given member @@ -2541,22 +2615,21 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, Imat = 0.0_ReKi g = p%Gravity + InterpolationSlope = GetInterpolationSlope(Time, p, m, IntWrapIndx) + !=============================================================================================== ! Calculate the fluid kinematics at all mesh nodes and store for use in the equations below do j = 1, p%NNodes - m%nodeInWater(j) = REAL( InterpWrappedStpInt( REAL(Time, SiKi), p%WaveTime(:), p%nodeInWater(:,j), m%LastIndWave, p%NStepWave + 1 ), ReKi ) + m%nodeInWater(j) = REAL( p%nodeInWater(IntWrapIndx,j), ReKi ) ! Determine the dynamic pressure at the node - m%FDynP(j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveDynP(:,j), & - m%LastIndWave, p%NStepWave + 1 ) + m%FDynP(j) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveDynP(:,j)) do i=1,3 ! Determine the fluid acceleration and velocity and relative structural velocity at the node - m%FA(i,j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveAcc(:,j,i), & - m%LastIndWave, p%NStepWave + 1 ) + m%FA(i,j) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveAcc(:,j,i)) - m%FV(i,j) = InterpWrappedStpReal ( REAL(Time, SiKi), p%WaveTime(:), p%WaveVel(:,j,i), & - m%LastIndWave, p%NStepWave + 1 ) + m%FV(i,j) = InterpolateWithSlope(InterpolationSlope, m%LastIndWave, p%WaveVel(:,j,i)) m%vrel(i,j) = m%FV(i,j) - u%Mesh%TranslationVel(i,j) end do end do @@ -2827,7 +2900,6 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! ------------------ flooded ballast inertia: sides: Section 6.1.1 : Always compute regardless of PropPot setting --------------------- -!FIXME: these calculations use the mass of the fully filled volume and do not account for FillFSLoc... yet ! lower node Ioffset = mem%h_cfb_l(i)*mem%h_cfb_l(i)*mem%m_fb_l(i) Imat(1,1) = mem%I_rfb_l(i) - Ioffset From b9070f393bdc40f1dcee87db30b33032c6cd18e9 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 26 Jan 2021 09:51:43 -0700 Subject: [PATCH 370/377] TCF mods: missing continuous states info for linearization I'm not sure if a copy is the right way to handle this or not. I'm just blindly assuming it will work and get all the nested derived type sizing correct. --- modules/hydrodyn/src/HydroDyn.f90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 31b9f3315..ca4cf13dd 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -1846,7 +1846,7 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt ! Local variables INTEGER :: I, iWAMIT, iBody ! Generic loop counters - TYPE(HydroDyn_ContinuousStateType) :: dxdt ! Continuous state derivatives at t +! TYPE(HydroDyn_ContinuousStateType) :: dxdt ! Continuous state derivatives at t TYPE(HydroDyn_DiscreteStateType) :: xd_t ! Discrete states at t (copy) TYPE(HydroDyn_ConstraintStateType) :: z_Residual ! Residual of the constraint state functions (Z) TYPE(HydroDyn_InputType) :: u ! Instantaneous inputs @@ -2308,6 +2308,8 @@ SUBROUTINE HydroDyn_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxd ! Compute the first time derivatives of the continuous states here: if ( .not. m%u_WAMIT(1)%Mesh%Committed ) return ! Make sure we are using WAMIT / there is a valid mesh + call HydroDyn_CopyContState( x, dxdt, MESH_NEWCOPY, ErrStat, ErrMsg) + if ( ErrStat >= AbortErrLev ) return if ( p%NBodyMod == 1 .or. p%NBody == 1 ) then ! Copy the inputs from the HD mesh into the WAMIT mesh From 9e4c40be46d58dc951ea9ef01f7487d48b75ce37 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 26 Jan 2021 17:24:44 -0700 Subject: [PATCH 371/377] SD: minor typos in example input file. --- .../user/subdyn/examples/OC4_Jacket_SD_Input.dat | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index 84126f2a9..995e22121 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -7,7 +7,7 @@ False Echo - Echo input data to ".SD.ech" (flag) True SttcSolve - Solve dynamics about static equilibrium point True GuyanLoadCorrection - Include extra moment from lever arm at interface and rotate FEM for floating. -------------------- FEA and CRAIG-BAMPTON PARAMETERS--------------------------- - 3 FEMMod - FEM switch: element model in the FEM. [1= Euler-Bernoulli(E-B) ; 2=Tapered E-B (unavailable); 3= 2-node Timoshenko; 4= 2-node tapered Timoshenko (unavailable)] + 3 FEMMod - FEM switch: element model in the FEM. [1= Euler-Bernoulli(E-B); 2=Tapered E-B (unavailable); 3= 2-node Timoshenko; 4= 2-node tapered Timoshenko (unavailable)] 2 NDiv - Number of sub-elements per member True CBMod - [T/F] If True perform C-B reduction, else full FEM dofs will be retained. If True, select Nmodes to retain in C-B reduced system. 8 Nmodes - Number of internal modes to retain (ignored if CBMod=False). If Nmodes=0 --> Guyan Reduction. @@ -235,7 +235,8 @@ PropSetID YoungE ShearG MatDens XsecD X 4 2.10000e+11 8.07690e+10 7850.00 1.200000 0.040000 5 2.10000e+11 8.07690e+10 3339.12 2.082000 0.491000 6 2.10000e+11 8.07690e+10 7850.00 2.082000 0.060000 ------------------- MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below]- 0 NXPropSets - Number of structurally unique non-circular x-sections (if 0 the following table is ignored) +------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below] ------------------------ + 0 NXPropSets - Number of structurally unique non-circular x-sections (if 0 the following table is ignored) PropSetID YoungE ShearG MatDens XsecA XsecAsx XsecAsy XsecJxx XsecJyy XsecJ0 (-) (N/m2) (N/m2) (kg/m3) (m2) (m2) (m2) (m4) (m4) (m4) -------------------------- CABLE PROPERTIES ------------------------------------- @@ -255,7 +256,7 @@ COSMID COSM11 COSM12 COSM13 COSM21 COSM22 COSM23 COSM31 CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) ---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ -True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. IT can also … +True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. False OutCOSM - Output cosine matrices with the selected output member forces (flag) False OutAll - [T/F] Output all members' end forces and additional summary file info 1 OutSwtch - [1/2/3] Output requested channels to: 1=.SD.out 2=.out (generated by FAST) 3=both files. @@ -265,7 +266,7 @@ True TabDelim - Generate a tab-delimited output in the "A11" OutSFmt - Output format for header strings in the .SD.out file ------------------------- MEMBER OUTPUT LIST ------------------------------------------ 8 NMOutputs - Number of members whose forces/displacements/velocities/accelerations will be output (-) [Must be <= 9]. -MemberID NOutCnt NodeCnt [NOutCnt=how many nodes to get output for [< 10]; NodeCnt are local ordinal numbers from the start of the member, and must be >=1 and … +MemberID NOutCnt NodeCnt [NOutCnt=how many nodes to get output for [< 10]; NodeCnt are local ordinal numbers from the start of the member, and must be >=1 and <= NDiv+1] If NMOutputs=0 leave blank as well. (-) (-) (-) 22 1 3 30 1 3 @@ -279,6 +280,7 @@ MemberID NOutCnt NodeCnt [NOutCnt=how many nodes to get output for [< 10]; "M1N1FKZe, M2N1FKZe" - Axial force in leg 2 at K1L2 and in leg 4 at K1L4 "M3N1TDXss, M3N1TDYss, M3N1TDZss, M4N1TDXss, M4N1TDYss, M4N1TDZss" - Deflections at X2S2, X2S3: use cosdir matrix to get Out-of-plane (OOP) deflection "M5N2TDXss, M5N2TDYss, M5N2TDZss, M6N2TDXss, M6N2TDYss, M6N2TDZss" - Deflections at X4S2, X4S3: use cosdir matrix to get OOP deflection -"M5N1FKXe,M5N1FKYe,M5N1FKZe,M6N1FKXe,M6N1FKYe,M6N1FKZe" - Forces OOP and Axial at mid brace points x,y, z >> *we will need to do some post-processing "M7N1FKZe, M8N1FKZe" - Axial force in leg 2 and leg 4 at mudbrace level: MudbraceL2, MudbraceL4 -"-ReactFXss, -ReactFYss, -ReactMXss, -ReactMYss, -ReactMZss, -ReactFZss" - Base reactions: fore-aft shear, side-to-side shear, side-to-side moment, fore-aft moment, … -END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line) +"M5N1FKXe,M5N1FKYe,M5N1FKZe,M6N1FKXe,M6N1FKYe,M6N1FKZe" - Forces OOP and Axial at mid brace points x,y, z >> *we will need to do some post-processing using the direction cosine matrices to get OOP forces +"M7N1FKZe, M8N1FKZe" - Axial force in leg 2 and leg 4 at mudbrace level: MudbraceL2, MudbraceL4 +"-ReactFXss, -ReactFYss, -ReactMXss, -ReactMYss, -ReactMZss, -ReactFZss" - Base reactions: fore-aft shear, side-to-side shear, side-to-side moment, fore-aft moment, yaw moment, vertical force +END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line) From ea579c1a35b7e75d3452d24a822170952d98185c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 26 Jan 2021 18:23:16 -0700 Subject: [PATCH 372/377] TCF: update SubDyn input files to new format --- docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat | 6 +++--- reg_tests/r-test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat index 995e22121..56c91f40a 100644 --- a/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat +++ b/docs/source/user/subdyn/examples/OC4_Jacket_SD_Input.dat @@ -256,10 +256,10 @@ COSMID COSM11 COSM12 COSM13 COSM21 COSM22 COSM23 COSM31 CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) ---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------ -True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. +True SumPrint - Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. It can also contain COSMs if requested. False OutCOSM - Output cosine matrices with the selected output member forces (flag) -False OutAll - [T/F] Output all members' end forces and additional summary file info - 1 OutSwtch - [1/2/3] Output requested channels to: 1=.SD.out 2=.out (generated by FAST) 3=both files. +False OutAll - [T/F] Output all members' end forces + 1 OutSwtch - [1/2/3] Output requested channels to: 1=.SD.out; 2=.out (generated by FAST); 3=both files. True TabDelim - Generate a tab-delimited output in the .SD.out file 1 OutDec - Decimation of output in the .SD.out file "ES11.4e2" OutFmt - Output format for numerical results in the .SD.out file diff --git a/reg_tests/r-test b/reg_tests/r-test index d61262284..a350141bc 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit d612622841aabc0afb55d8010b75c9b2147bb698 +Subproject commit a350141bc5cde25a4d30e7f51e55c94827b1dd14 From dcc38d2e5385d06ea34c4484427e363afabb97b4 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 27 Jan 2021 16:14:13 -0700 Subject: [PATCH 373/377] TCF: minor corrections in regression test input files --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index a350141bc..6a13a64eb 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit a350141bc5cde25a4d30e7f51e55c94827b1dd14 +Subproject commit 6a13a64ebbac6c2407c0a229634c8e36ca81bb7a From a2ee342d19a89944c7e9a0772b5c9a39e2bdbbb5 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 27 Jan 2021 17:14:37 -0700 Subject: [PATCH 374/377] TCF: update api_change.rst for HD --- docs/source/user/api_change.rst | 61 ++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index 99d15e27a..27710d8d4 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -37,24 +37,69 @@ SubDyn na RigidSection --------- SubDyn na RigidSection 0 NRigidPropSets - Number of rigid link properties SubDyn na RigidSection PropSetID MatDens SubDyn na RigidSection (-) (kg/m) +HydroDyn 52 NBody 1 NBody - Number of WAMIT bodies to be used (-) [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6] +HydroDyn 53 NBodyMod 1 NBodyMod - Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1] + ============================================= ==== =============== ======================================================================================================================================================================================================== +============================================= ====== =============== ====================================================================================================================================================================================================== +Modified in OpenFAST dev +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Module Line Flag Name Example Value +============================================= ====== =============== ====================================================================================================================================================================================================== +AeroDyn 15 9 TwrShadow 0 TwrShadow - Calculate tower influence on wind based on downstream tower shadow (switch) {0=none, 1=Powles model, 2=Eames model} +SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff +SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) +SubDyn na Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID +SubDyn na Members (-) (-) (-) (-) (-) (-) (-) +SubDyn na ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ +SubDyn na ConcentratedM (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) +HydroDyn 48 ExtnMod 1 ExctnMod - Wave-excitation model {0: no wave-excitation calculation, 1: DFT, 2: state-space} (switch) [only used when PotMod=1; STATE-SPACE REQUIRES \*.ssexctn INPUT FILE] +HydroDyn 49 RdtnMod 2 RdtnMod - Radiation memory-effect model {0: no memory-effect calculation, 1: convolution, 2: state-space} (switch) [only used when PotMod=1; STATE-SPACE REQUIRES \*.ss INPUT FILE] +HydroDyn 50 RdtnTMax 60 RdtnTMax - Analysis time for wave radiation kernel calculations (sec) [only used when PotMod=1 and RdtnMod>0; determines RdtnDOmega=Pi/RdtnTMax in the cosine transform; MAKE SURE THIS IS LONG ENOUGH FOR THE RADIATION IMPULSE RESPONSE FUNCTIONS TO DECAY TO NEAR-ZERO FOR THE GIVEN PLATFORM!] +HydroDyn 51 RdtnDT 0.0125 RdtnDT - Time step for wave radiation kernel calculations (sec) [only used when PotMod=1 and ExctnMod>0 or RdtnMod>0; DT<=RdtnDT<=0.1 recommended; determines RdtnOmegaMax=Pi/RdtnDT in the cosine transform] +HydroDyn 54 PotFile "Barge" PotFile - Root name of potential-flow model data; WAMIT output files containing the linear, nondimensionalized, hydrostatic restoring matrix (.hst), frequency-dependent hydrodynamic added mass matrix and damping matrix (.1), and frequency- and direction-dependent wave excitation force vector per unit wave amplitude (.3) (quoted string) [1 to NBody if NBodyMod>1] [MAKE SURE THE FREQUENCIES INHERENT IN THESE WAMIT FILES SPAN THE PHYSICALLY-SIGNIFICANT RANGE OF FREQUENCIES FOR THE GIVEN PLATFORM; THEY MUST CONTAIN THE ZERO- AND INFINITE-FREQUENCY LIMITS!] +HydroDyn 55 WAMITULEN 1 WAMITULEN - Characteristic body length scale used to redimensionalize WAMIT output (meters) [1 to NBody if NBodyMod>1] [only used when PotMod=1] +HydroDyn 56 PtfmRefxt 0.0 PtfmRefxt - The xt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1] +HydroDyn 57 PtfmRefyt 0.0 PtfmRefyt - The yt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1] +HydroDyn 58 PtfmRefzt 0.0 PtfmRefzt - The zt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1. If NBodyMod=2,PtfmRefzt=0.0] +HydroDyn 59 PtfmRefztRot 0.0 PtfmRefztRot - The rotation about zt of the body reference frame(s) from xt/yt (degrees) [1 to NBody] [only used when PotMod=1] +HydroDyn 60 PtfmVol0 6000 PtfmVol0 - Displaced volume of water when the body is in its undisplaced position (m^3) [1 to NBody] [only used when PotMod=1; USE THE SAME VALUE COMPUTED BY WAMIT AS OUTPUT IN THE .OUT FILE!] +HydroDyn 61 PtfmCOBxt 0.0 PtfmCOBxt - The xt offset of the center of buoyancy (COB) from (0,0) (meters) [1 to NBody] [only used when PotMod=1] +HydroDyn 62 PtfmCOByt 0.0 PtfmCOByt - The yt offset of the center of buoyancy (COB) from (0,0) (meters) [1 to NBody] [only used when PotMod=1] +HydroDyn 69-74 AddF0 0 AddF0 - Additional preload (N, N-m) [If NBodyMod=1, one size 6*NBody x 1 vector; if NBodyMod>1, NBody size 6 x 1 vectors] +HydroDyn 75-80 AddCLin 0 0 0 0 0 0 AddCLin - Additional linear stiffness (N/m, N/rad, N-m/m, N-m/rad) [If NBodyMod=1, one size 6*NBody x 6*NBody matrix; if NBodyMod>1, NBody size 6 x 6 matrices] +HydroDyn 81-86 AddBLin 0 0 0 0 0 0 AddBLin - Additional linear damping(N/(m/s), N/(rad/s), N-m/(m/s), N-m/(rad/s)) [If NBodyMod=1, one size 6*NBody x 6*NBody matrix; if NBodyMod>1, NBody size 6 x 6 matrices] +HydroDyn 87-92 AddBQuad 0 0 0 0 0 0 AddBQuad - Additional quadratic drag(N/(m/s)^2, N/(rad/s)^2, N-m(m/s)^2, N-m/(rad/s)^2) [If NBodyMod=1, one size 6*NBody x 6*NBody matrix; if NBodyMod>1, NBody size 6 x 6 matrices] +HydroDyn na Simple Coef Tab SimplCd SimplCdMG SimplCa SimplCaMG SimplCp SimplCpMG SimplAxCa SimplAxCaMG SimplAxCa SimplAxCaMG SimplAxCp SimplAxCpMG +HydroDyn na (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) +HydroDyn na Depth Coef Tab Dpth DpthCd DpthCdMG DpthCa DpthCaMG DpthCp DpthCpMG DpthAxCa DpthAxCaMG DpthAxCa DpthAxCaMG DpthAxCp DpthAxCpMG +HydroDyn na (m) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) +HydroDyn na Member Coef Tab MemberID MemberCd1 MemberCd2 MemberCdMG1 MemberCdMG2 MemberCa1 MemberCa2 MemberCaMG1 MemberCaMG2 MemberCp1 MemberCp2 MemberCpMG1 MemberCpMG2 MemberAxCd1 MemberAxCd2 MemberAxCdMG1 MemberAxCdMG2 MemberAxCa1 MemberAxCa2 MemberAxCaMG1 MemberAxCaMG2 MemberAxCp1 MemberAxCp2 MemberAxCpMG1 MemberAxCpMG2 +HydroDyn na (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) (-) +HydroDyn na OutList names *see OutlistParameters.xlsx for new and revised output channel names* +============================================= ====== =============== ====================================================================================================================================================================================================== + + + ============================================= ==== =============== ======================================================================================================================================================================================================== -Changed in OpenFAST dev +Removed in OpenFAST dev --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Module Line Flag Name Example Value ============================================= ==== =============== ======================================================================================================================================================================================================== -AeroDyn 15 9 TwrShadow 0 TwrShadow - Calculate tower influence on wind based on downstream tower shadow (switch) {0=none, 1=Powles model, 2=Eames model} -SubDyn 26 Joints JointID JointXss JointYss JointZss JointType JointDirX JointDirY JointDirZ JointStiff -SubDyn 27 Joints (-) (m) (m) (m) (-) (-) (-) (-) (Nm/rad) -SubDyn na Members MemberID MJointID1 MJointID2 MPropSetID1 MPropSetID2 MType COSMID -SubDyn na Members (-) (-) (-) (-) (-) (-) (-) -SubDyn na ConcentratedM CMJointID JMass JMXX JMYY JMZZ JMXY JMXZ JMYZ MCGX MCGY MCGZ -SubDyn na ConcentratedM (-) (kg) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (kg*m^2) (m) (m) (m) +HydroDyn 68 na ---------------------- FLOATING PLATFORM FORCE FLAGS -------------------------- [unused with WaveMod=6] +HydroDyn 69 PtfmSgF True PtfmSgF - Platform horizontal surge translation force (flag) or DEFAULT +HydroDyn 70 PtfmSwF True PtfmSwF - Platform horizontal sway translation force (flag) or DEFAULT +HydroDyn 71 PtfmHvF True PtfmHvF - Platform vertical heave translation force (flag) or DEFAULT +HydroDyn 72 PtfmRF True PtfmRF - Platform roll tilt rotation force (flag) or DEFAULT +HydroDyn 73 PtfmPF True PtfmPF - Platform pitch tilt rotation force (flag) or DEFAULT +HydroDyn 74 PtfmYF True PtfmYF - Platform yaw rotation force (flag) or DEFAULT ============================================= ==== =============== ======================================================================================================================================================================================================== + + OpenFAST v2.4.0 to OpenFAST v2.5.0 ---------------------------------- From 1082ba1628662a3ccf9738cd3f1e38217a0b86ec Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 27 Jan 2021 17:29:37 -0700 Subject: [PATCH 375/377] TCF: remove temporary matlab files --- compareResults_OpenFAST_HD.m | 116 ----------------------------- copyOpenFAST_Results_To_HD_input.m | 44 ----------- reg_tests/r-test | 2 +- 3 files changed, 1 insertion(+), 161 deletions(-) delete mode 100644 compareResults_OpenFAST_HD.m delete mode 100644 copyOpenFAST_Results_To_HD_input.m diff --git a/compareResults_OpenFAST_HD.m b/compareResults_OpenFAST_HD.m deleted file mode 100644 index d9038c081..000000000 --- a/compareResults_OpenFAST_HD.m +++ /dev/null @@ -1,116 +0,0 @@ - addpath('_MATLAB_scripts/'); - -CaseList={ '5MW_OC4Semi_WSt_WavesWN', ... - '5MW_OC3Spar_DLL_WTurb_WavesIrr',... - '5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti', ... - '5MW_ITIBarge_DLL_WTurb_WavesIrr'}; -% RegTestMainDir='OpenFAST_reg-test/'; -% HDTestDir='HD_reg-test/'; -RegTestMainDir='build-DP-gcc7/reg_tests/glue-codes/openfast/'; -HDTestDir='reg_tests/r-test/modules/hydrodyn/'; -HDTestDir='build-DP-gcc7/reg_tests/modules/hydrodyn/'; -OutFileName='OpenFAST_DisplacementTimeseries.dat'; - -DiffTable.ChanNames={... - 'Wave1Elev',... - 'HydroFxi' ,... - 'HydroFyi' ,... - 'HydroFzi' ,... - 'HydroMxi' ,... - 'HydroMyi' ,... - 'HydroMzi' ,... - 'WRPSurge' ,... - 'WRPSway' ,... - 'WRPHeave' ,... - 'WRPRoll' ,... - 'WRPPitch' ,... - 'WRPYaw' ,... - 'WRPTVxi' ,... - 'WRPTVyi' ,... - 'WRPTVzi' ,... - 'WRPRVxi' ,... - 'WRPRVyi' ,... - 'WRPRVzi' ,... - 'WRPTAxi' ,... - 'WRPTAyi' ,... - 'WRPTAzi' ,... - 'WRPRAxi' ,... - 'WRPRAyi' ,... - 'WRPRAzi' ,... - 'WavesFxi' ,... - 'WavesFyi' ,... - 'WavesFzi' ,... - 'WavesMxi' ,... - 'WavesMyi' ,... - 'WavesMzi' ,... - 'HdrStcFxi',... - 'HdrStcFyi',... - 'HdrStcFzi',... - 'HdrStcMxi',... - 'HdrStcMyi',... - 'HdrStcMzi',... - 'RdtnFxi' ,... - 'RdtnFyi' ,... - 'RdtnFzi' ,... - 'RdtnMxi' ,... - 'RdtnMyi' ,... - 'RdtnMzi' }; - -%% Data difference table -DiffTable.Diff=zeros(size(CaseList,2),size(DiffTable.ChanNames,2)); -DiffTable.Percent=DiffTable.Diff; -DiffTable.Range=DiffTable.Diff; -DiffTable.CaseList=CaseList'; -for i=1:size(CaseList,2) - LoadFASTOut([RegTestMainDir CaseList{i} '/' CaseList{i} '.out'],[HDTestDir 'hd_' CaseList{i} '/driver.HD.out']); - for j=1:size(DiffTable.ChanNames,2) - Ref=FASTDataSet(1).FASTData(:,GetChanNum(DiffTable.ChanNames{j},1)); - Test=FASTDataSet(2).FASTData(:,GetChanNum(DiffTable.ChanNames{j},2)); - DiffTable.Range(i,j)=max(Ref)-min(Ref); - DiffTable.Diff(i,j)=max(abs(Test-Ref)); - DiffTable.Percent(i,j)=DiffTable.Diff(i,j)/DiffTable.Range(i,j); - end -end -% Now to generate a nice table -disp('Difference'); - % header line -txt=''; -for i=1:size(DiffTable.CaseList,1) - txt=[txt char(9) DiffTable.CaseList{i} char(9)]; -end -disp(txt); - % diff sub header line -txt=''; -for i=1:size(DiffTable.CaseList,1) - txt=[txt char(9) 'Abs diff' char(9) '% diff']; -end -disp(txt); - % table itself -for j=1:size(DiffTable.ChanNames,2) - txt=DiffTable.ChanNames{j}; - for i=1:size(DiffTable.CaseList,1) - txt=[txt char(9) num2str(DiffTable.Diff(i,j)) char(9) num2str(DiffTable.Percent(i,j)*100)]; - end - disp(txt); -end - - -%% -i=4; -LoadFASTOut([RegTestMainDir CaseList{i} '/' CaseList{i} '.out'],[HDTestDir 'hd_' CaseList{i} '/driver.HD.out']); -for i=3:size(FASTDataSet(2).HeadNames) - Chan=FASTDataSet(2).HeadNames{i}; - PlotFAST('Time',Chan); - legend({'OpenFAST coupled simulation','HdyroDyn\_driver'}); -end - - - -%% -figure; -Chan='HydroMxi'; -plot(FASTDataSet(2).FASTData(:,1),FASTDataSet(2).FASTData(:,GetChanNum(Chan,2))-FASTDataSet(1).FASTData(:,GetChanNum(Chan,1))); -xlabel('Time (sec)'); -ylabel(['Difference: ' FASTDataSet(2).HeadUnits{GetChanNum(Chan,2)}]); -% ylabel('Difference: (kN)'); -title('HydroDyn\_driver - OpenFAST'); diff --git a/copyOpenFAST_Results_To_HD_input.m b/copyOpenFAST_Results_To_HD_input.m deleted file mode 100644 index e51140c30..000000000 --- a/copyOpenFAST_Results_To_HD_input.m +++ /dev/null @@ -1,44 +0,0 @@ -% addpath('_MATLAB_scripts/'); - -CaseList={ '5MW_OC4Semi_WSt_WavesWN', ... - '5MW_OC3Spar_DLL_WTurb_WavesIrr',... - '5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti', ... - '5MW_ITIBarge_DLL_WTurb_WavesIrr'}; -% RegTestMainDir='OpenFAST_reg-test/'; -% HDTestDir='HD_reg-test/'; -RegTestMainDir='build-DP-gcc7/reg_tests/glue-codes/openfast/'; -HDTestDir='reg_tests/r-test/modules/hydrodyn/'; -OutFileName='OpenFAST_DisplacementTimeseries.dat'; - -DispChanSet={... - 'Time',... - 'WRPSurge',... - 'WRPSway',... - 'WRPHeave',... - 'WRPRoll',... - 'WRPPitch',... - 'WRPYaw',... - 'WRPTVxi',... - 'WRPTVyi',... - 'WRPTVzi',... - 'WRPRVxi',... - 'WRPRVyi',... - 'WRPRVzi',... - 'WRPTAxi',... - 'WRPTAyi',... - 'WRPTAzi',... - 'WRPRAxi',... - 'WRPRAyi',... - 'WRPRAzi'}; - -%% Write the new data for HD Input - -for i=1:size(CaseList,2) - LoadFASTOut([RegTestMainDir CaseList{i} '/' CaseList{i} '.out']); - DatSet=[]; - for j=1:size(DispChanSet,2) - DatSet(:,j)=FASTDataSet(1).FASTData(:,GetChanNum(DispChanSet{j},1)); - end - writematrix(DatSet,[HDTestDir 'hd_' CaseList{i} '/' OutFileName]); -end - diff --git a/reg_tests/r-test b/reg_tests/r-test index 6a13a64eb..2af2b0872 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 6a13a64ebbac6c2407c0a229634c8e36ca81bb7a +Subproject commit 2af2b0872be3b71dea19ee4622ffc3208e5f0809 From e0fe096f3b577424518731ecf454d1fe9a0892f4 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 28 Jan 2021 17:20:15 -0700 Subject: [PATCH 376/377] TCF: add SD regression tests and results --- reg_tests/CMakeLists.txt | 5 +- reg_tests/CTestList.cmake | 15 +++ reg_tests/executeSubdynRegressionCase.py | 141 +++++++++++++++++++++++ reg_tests/lib/openfastDrivers.py | 5 + reg_tests/r-test | 2 +- 5 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 reg_tests/executeSubdynRegressionCase.py diff --git a/reg_tests/CMakeLists.txt b/reg_tests/CMakeLists.txt index 71350e798..7f1beb912 100644 --- a/reg_tests/CMakeLists.txt +++ b/reg_tests/CMakeLists.txt @@ -46,6 +46,9 @@ set(CTEST_BEAMDYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/beamdyn/beamdyn_driver # Set the HydroDyn executable configuration option and default set(CTEST_HYDRODYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/hydrodyn/hydrodyn_driver" CACHE FILEPATH "Specify the HydroDyn driver executable to use in testing.") +# Set the SubDyn executable configuration option and default +set(CTEST_SUBDYN_EXECUTABLE "${CMAKE_BINARY_DIR}/modules/subdyn/subdyn_driver" CACHE FILEPATH "Specify the SubDyn driver executable to use in testing.") + # Set the python executable configuration option and default if(NOT EXISTS ${PYTHON_EXECUTABLE}) find_program(PYTHON_EXECUTABLE NAMES python3 python py) @@ -67,7 +70,7 @@ add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/r-test") # build and seed the test directories with the data they need to run the tests file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}) -foreach(regTest glue-codes/openfast modules/aerodyn modules/beamdyn modules/hydrodyn) +foreach(regTest glue-codes/openfast modules/aerodyn modules/beamdyn modules/hydrodyn modules/subdyn) file(MAKE_DIRECTORY ${CTEST_BINARY_DIR}/${regTest}) endforeach() diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index 6c0209050..d9fd1a471 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -111,6 +111,15 @@ function(hd_regression TESTNAME LABEL) regression(${TEST_SCRIPT} ${HYDRODYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") endfunction(hd_regression) +# subdyn +function(sd_regression TESTNAME LABEL) + set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeSubdynRegressionCase.py") + set(SUBDYN_EXECUTABLE "${CTEST_SUBDYN_EXECUTABLE}") + set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") + set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/modules/subdyn") + regression(${TEST_SCRIPT} ${SUBDYN_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} ${TESTNAME} "${LABEL}") +endfunction(sd_regression) + #=============================================================================== # Regression tests #=============================================================================== @@ -173,3 +182,9 @@ hd_regression("hd_5MW_ITIBarge_DLL_WTurb_WavesIrr" "hydrodyn;offshore") hd_regression("hd_5MW_OC3Spar_DLL_WTurb_WavesIrr" "hydrodyn;offshore") hd_regression("hd_5MW_OC4Semi_WSt_WavesWN" "hydrodyn;offshore") hd_regression("hd_5MW_TLP_DLL_WTurb_WavesIrr_WavesMulti" "hydrodyn;offshore") + +# SubDyn regression tests +sd_regression("SD_Cable_5Joints" "subdyn;offshore") +sd_regression("SD_PendulumDamp" "subdyn;offshore") +sd_regression("SD_Rigid" "subdyn;offshore") +sd_regression("SD_SparHanging" "subdyn;offshore") diff --git a/reg_tests/executeSubdynRegressionCase.py b/reg_tests/executeSubdynRegressionCase.py new file mode 100644 index 000000000..151049fa4 --- /dev/null +++ b/reg_tests/executeSubdynRegressionCase.py @@ -0,0 +1,141 @@ +# +# Copyright 2017 National Renewable Energy Laboratory +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" + This program executes SubDyn and a regression test for a single test case. + The test data is contained in a git submodule, r-test, which must be initialized + prior to running. See the r-test README or OpenFAST documentation for more info. + + Get usage with: `executeSubdynRegressionCase.py -h` +""" + +import os +import sys +basepath = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1]) if os.path.sep in sys.argv[0] else "." +sys.path.insert(0, os.path.sep.join([basepath, "lib"])) +import argparse +import shutil +import glob +import subprocess +import rtestlib as rtl +import openfastDrivers +import pass_fail +from errorPlotting import exportCaseSummary + +##### Main program + +### Store the python executable for future python calls +pythonCommand = sys.executable + +### Verify input arguments +parser = argparse.ArgumentParser(description="Executes SubDyn and a regression test for a single test case.") +parser.add_argument("caseName", metavar="Case-Name", type=str, nargs=1, help="The name of the test case.") +parser.add_argument("executable", metavar="SubDyn-Driver", type=str, nargs=1, help="The path to the SubDyn driver executable.") +parser.add_argument("sourceDirectory", metavar="path/to/openfast_repo", type=str, nargs=1, help="The path to the OpenFAST repository.") +parser.add_argument("buildDirectory", metavar="path/to/openfast_repo/build", type=str, nargs=1, help="The path to the OpenFAST repository build directory.") +parser.add_argument("tolerance", metavar="Test-Tolerance", type=float, nargs=1, help="Tolerance defining pass or failure in the regression test.") +parser.add_argument("systemName", metavar="System-Name", type=str, nargs=1, help="The current system\'s name: [Darwin,Linux,Windows]") +parser.add_argument("compilerId", metavar="Compiler-Id", type=str, nargs=1, help="The compiler\'s id: [Intel,GNU]") +parser.add_argument("-p", "-plot", dest="plot", default=False, metavar="Plotting-Flag", type=bool, nargs="?", help="bool to include matplotlib plots in failed cases") +parser.add_argument("-n", "-no-exec", dest="noExec", default=False, metavar="No-Execution", type=bool, nargs="?", help="bool to prevent execution of the test cases") +parser.add_argument("-v", "-verbose", dest="verbose", default=False, metavar="Verbose-Flag", type=bool, nargs="?", help="bool to include verbose system output") + +args = parser.parse_args() + +caseName = args.caseName[0] +executable = args.executable[0] +sourceDirectory = args.sourceDirectory[0] +buildDirectory = args.buildDirectory[0] +tolerance = args.tolerance[0] +plotError = args.plot if args.plot is False else True +noExec = args.noExec if args.noExec is False else True +verbose = args.verbose if args.verbose is False else True + +# validate inputs +rtl.validateExeOrExit(executable) +rtl.validateDirOrExit(sourceDirectory) +if not os.path.isdir(buildDirectory): + os.makedirs(buildDirectory) + +### Build the filesystem navigation variables for running the test case +regtests = os.path.join(sourceDirectory, "reg_tests") +lib = os.path.join(regtests, "lib") +rtest = os.path.join(regtests, "r-test") +moduleDirectory = os.path.join(rtest, "modules", "subdyn") +inputsDirectory = os.path.join(moduleDirectory, caseName) +targetOutputDirectory = os.path.join(inputsDirectory) +testBuildDirectory = os.path.join(buildDirectory, caseName) + +# verify all the required directories exist +if not os.path.isdir(rtest): + rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest)) +if not os.path.isdir(targetOutputDirectory): + rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory)) +if not os.path.isdir(inputsDirectory): + rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory)) + +# create the local output directory if it does not already exist +# and initialize it with input files for all test cases +if not os.path.isdir(testBuildDirectory): + os.makedirs(testBuildDirectory) + for file in glob.glob(os.path.join(inputsDirectory,caseName+".dvr")): + filename = file.split(os.path.sep)[-1] + shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) + for file in glob.glob(os.path.join(inputsDirectory,"*dat")): + filename = file.split(os.path.sep)[-1] + shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) + +### Run SubDyn on the test case +if not noExec: + caseInputFile = os.path.join(testBuildDirectory, caseName+".dvr") + returnCode = openfastDrivers.runSubdynDriverCase(caseInputFile, executable) + if returnCode != 0: + rtl.exitWithError("") + +### Build the filesystem navigation variables for running the regression test +localOutFile = os.path.join(testBuildDirectory, caseName+".SD.out") +baselineOutFile = os.path.join(targetOutputDirectory, caseName+".SD.out") +rtl.validateFileOrExit(localOutFile) +rtl.validateFileOrExit(baselineOutFile) + +testData, testInfo, testPack = pass_fail.readFASTOut(localOutFile) +baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +performance = pass_fail.calculateNorms(testData, baselineData) +normalizedNorm = performance[:, 1] + +# export all case summaries +results = list(zip(testInfo["attribute_names"], [*performance])) +results_max = performance.max(axis=0) +exportCaseSummary(testBuildDirectory, caseName, results, results_max, tolerance) + +# failing case +if not pass_fail.passRegressionTest(normalizedNorm, tolerance): + if plotError: + from errorPlotting import finalizePlotDirectory, plotOpenfastError + ixFailChannels = [i for i in range(len(testInfo["attribute_names"])) if normalizedNorm[i] > tolerance] + failChannels = [channel for i, channel in enumerate(testInfo["attribute_names"]) if i in ixFailChannels] + failResults = [res for i, res in enumerate(results) if i in ixFailChannels] + for channel in failChannels: + try: + plotOpenfastError(localOutFile, baselineOutFile, channel) + except: + error = sys.exc_info()[1] + print("Error generating plots: {}".format(error.msg)) + finalizePlotDirectory(localOutFile, failChannels, caseName) + sys.exit(1) + +# passing case +sys.exit(0) diff --git a/reg_tests/lib/openfastDrivers.py b/reg_tests/lib/openfastDrivers.py index b06fd7621..550171f39 100644 --- a/reg_tests/lib/openfastDrivers.py +++ b/reg_tests/lib/openfastDrivers.py @@ -64,3 +64,8 @@ def runHydrodynDriverCase(inputFile, executable, verbose=False): caseDirectory = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) os.chdir(caseDirectory) return _runGenericCase(inputFile, executable, verbose) + +def runSubdynDriverCase(inputFile, executable, verbose=False): + caseDirectory = os.path.sep.join(inputFile.split(os.path.sep)[:-1]) + os.chdir(caseDirectory) + return _runGenericCase(inputFile, executable, verbose) diff --git a/reg_tests/r-test b/reg_tests/r-test index 2af2b0872..d8e464244 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 2af2b0872be3b71dea19ee4622ffc3208e5f0809 +Subproject commit d8e46424489f587f75f85bd093e350c0c4e98b1f From a25195fbd89de8defa6e54cba7f81486b53afbca Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 29 Jan 2021 08:08:39 -0700 Subject: [PATCH 377/377] TCF: final updates of all regression tests This is now ready for merging!!! --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index d8e464244..adffb7e3b 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit d8e46424489f587f75f85bd093e350c0c4e98b1f +Subproject commit adffb7e3baa3ef4b8b2ea4b777ba6b23b8048069

;c8^yZ!L|sTvS#^{Cvvl>Jtm=5uK+ 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⁣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%0Agb=jbt~R|QQ#JkN5v&3Du5muzySw5$PJNH=fG9K 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